Files
RomWBW/Source/Images/d_aztecc/u0/MATHSRC.ARC
2023-06-14 12:45:41 -04:00

2829 lines
40 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
sin.c
#include "math.h"
#include "errno.h"
double cos(x)
double x;
{
double sincos();
return sincos(x, fabs(x) + 1.57079632679489661923, 0);
}
double sin(x)
double x;
{
double sincos();
if (x < 0.0)
return sincos(x,-x,1);
else
return sincos(x,x,0);
}
#define R1 -0.16666666666666665052e+00
#define R2 +0.83333333333331650314e-02
#define R3 -0.19841269841201840457e-03
#define R4 +0.27557319210152756119e-05
#define R5 -0.25052106798274584544e-07
#define R6 +0.16058936490371589114e-09
#define R7 -0.76429178068910467734e-12
#define R8 +0.27204790957888846175e-14
#define YMAX 6.7465e09
static double sincos(x,y,sgn)
double x,y;
{
double f, xn, r, g;
extern int errno;
if (y >= YMAX) {
errno = ERANGE;
return 0.0;
}
if (modf(y * 0.31830988618379067154, &xn) >= 0.5)
++xn;
if ((int)xn & 1)
sgn = !sgn;
if (fabs(x) != y)
xn -= 0.5;
g = modf(fabs(x), &x); /* break into fraction and integer parts */
f = ((x - xn*3.1416015625) + g) + xn*8.9089102067615373566e-6;
if (fabs(f) > 2.3283e-10) {
g = f*f;
r = (((((((R8*g R7)*g R6)*g R5)*g
R4)*g R3)*g R2)*g R1)*g;
f += f*r;
}
if (sgn)
f = -f;
return f;
}
tan.c
#include "math.h"
#include "errno.h"
extern int errno;
static double tansub();
double cotan(x)
double x;
{
double y;
y = fabs(x);
if (y < 1.91e-152) {
errno = ERANGE;
if (x < 0.0)
return -HUGE;
else
return HUGE;
}
return tansub(x,y,2);
}
double tan(x)
double x;
{
return tansub(x, fabs(x), 0);
}
#define P1 -0.13338350006421960681e+0
#define P2 +0.34248878235890589960e-2
#define P3 -0.17861707342254426711e-4
#define Q0 +1.0
#define Q1 -0.46671683339755294240e+0
#define Q2 +0.25663832289440112864e-1
#define Q3 -0.31181531907010027307e-3
#define Q4 +0.49819433993786512270e-6
#define P(f,g) (((P3*g P2)*g P1)*g*f + f)
#define Q(g) ((((Q4*g Q3)*g Q2)*g Q1)*g Q0)
#define YMAX 6.74652e09
static double tansub(x, y, flag)
double x,y;
{
double f, g, xn;
double xnum, xden;
if (y > YMAX) {
errno = ERANGE;
return 0.0;
}
if (modf(x*0.63661977236758134308, &xn) >= 0.5)
xn += (x < 0.0) ? -1.0 : 1.0;
f = (x - xn*1.57080078125) + xn*4.454455103380768678308e-6;
if (fabs(f) < 2.33e-10) {
xnum = f;
xden = 1.0;
} else {
g = f*f;
xnum = P(f,g);
xden = Q(g);
}
flag |= ((int)xn & 1);
switch (flag) {
case 1: /* A: tan, xn odd */
xnum = -xnum;
case 2: /* B: cotan, xn even */
return xden/xnum;
case 3: /* C: cotan, xn odd */
xnum = -xnum;
case 0: /* D: tan, xn even */
return xnum/xden;
}
return 0.0;
}
asin.c
#include "math.h"
#include "errno.h"
double arcsine();
double asin(x)
double x;
{
return arcsine(x,0);
}
double acos(x)
double x;
{
return arcsine(x,1);
}
#define P1 -0.27368494524164255994e+2
#define P2 +0.57208227877891731407e+2
#define P3 -0.39688862997504877339e+2
#define P4 +0.10152522233806463645e+2
#define P5 -0.69674573447350646411
#define Q0 -0.16421096714498560795e+3
#define Q1 +0.41714430248260412556e+3
#define Q2 -0.38186303361750149284e+3
#define Q3 +0.15095270841030604719e+3
#define Q4 -0.23823859153670238830e+2
#define P(g) ((((P5*g P4)*g P3)*g P2)*g P1)
#define Q(g) (((((g Q4)*g Q3)*g Q2)*g Q1)*g Q0)
double arcsine(x,flg)
double x;
{
double y, g, r;
register int i;
extern int errno;
static double a[2] = { 0.0, 0.78539816339744830962 };
static double b[2] = { 1.57079632679489661923, 0.78539816339744830962 };
y = fabs(x);
i = flg;
if (y < 2.3e-10)
r = y;
else {
if (y > 0.5) {
i = 1-i;
if (y > 1.0) {
errno = EDOM;
return 0.0;
}
g = (0.5-y)+0.5;
g = ldexp(g,-1);
y = sqrt(g);
y = -(y+y);
} else
g = y*y;
r = y + y*
((P(g)*g)
/Q(g));
}
if (flg) {
if (x < 0.0)
r = (b[i] + r) + b[i];
else
r = (a[i] - r) + a[i];
} else {
r = (a[i] + r) + a[i];
if (x < 0.0)
r = -r;
}
return r;
}
atan.c
#include "libc.h"
#include "math.h"
#include "errno.h"
static int nopper() {;}
#define PI 3.14159265358979323846
#define PIov2 1.57079632679489661923
double atan2(v,u)
double u,v;
{
double f;
int (*save)();
extern int flterr;
extern int errno;
if (u == 0.0) {
if (v == 0.0) {
errno = EDOM;
return 0.0;
}
return PIov2;
}
save = Sysvec[FLT_FAULT];
Sysvec[FLT_FAULT] = nopper;
flterr = 0;
f = v/u;
Sysvec[FLT_FAULT] = save;
if (flterr == 2) /* overflow */
f = PIov2;
else {
if (flterr == 1) /* underflow */
f = 0.0;
else
f = atan(fabs(f));
if (u < 0.0)
f = PI - f;
}
if (v < 0.0)
f = -f;
return f;
}
#define P0 -0.13688768894191926929e+2
#define P1 -0.20505855195861651981e+2
#define P2 -0.84946240351320683534e+1
#define P3 -0.83758299368150059274e+0
#define Q0 +0.41066306682575781263e+2
#define Q1 +0.86157349597130242515e+2
#define Q2 +0.59578436142597344465e+2
#define Q3 +0.15024001160028576121e+2
#define P(g) (((P3*g P2)*g P1)*g P0)
#define Q(g) ((((g Q3)*g Q2)*g Q1)*g Q0)
double atan(x)
double x;
{
double f, r, g;
int n;
static double Avals[4] = {
0.0,
0.52359877559829887308,
1.57079632679489661923,
1.04719755119659774615
};
n = 0;
f = fabs(x);
if (f > 1.0) {
f = 1.0/f;
n = 2;
}
if (f > 0.26794919243112270647) {
f = (((0.73205080756887729353*f - 0.5) - 0.5) + f) /
(1.73205080756887729353 + f);
++n;
}
if (fabs(f) < 2.3e-10)
r = f;
else {
g = f*f;
r = f + f *
((P(g)*g)
/Q(g));
}
if (n > 1)
r = -r;
r += Avals[n];
if (x < 0.0)
r = -r;
return r;
}
sinh.c
#include "math.h"
#include "errno.h"
extern int errno;
#define P0 -0.35181283430177117881e+6
#define P1 -0.11563521196851768270e+5
#define P2 -0.16375798202630751372e+3
#define P3 -0.78966127417357099479e+0
#define Q0 -0.21108770058106271242e+7
#define Q1 +0.36162723109421836460e+5
#define Q2 -0.27773523119650701667e+3
#define PS(x) (((P3*x P2)*x P1)*x P0)
#define QS(x) (((x Q2)*x Q1)*x Q0)
double sinh(x)
double x;
{
double y, w, z;
int sign;
y = x;
sign = 0;
if (x < 0.0) {
y = -x;
sign = 1;
}
if (y > 1.0) {
w = y - 0.6931610107421875000;
if (w > 349.3) {
errno = ERANGE;
z = HUGE;
} else {
z = exp(w);
if (w < 19.95)
z -= 0.24999308500451499336 / z;
z += 0.13830277879601902638e-4 * z;
}
if (sign)
z = -z;
} else if (y < 2.3e-10)
z = x;
else {
z = x*x;
z = x + x *
(z*(PS(z)
/QS(z)));
}
return z;
}
double cosh(x)
double x;
{
double y, w, z;
y = fabs(x);
if (y > 1.0) {
w = y - 0.6931610107421875000;
if (w > 349.3) {
errno = ERANGE;
return HUGE;
}
z = exp(w);
if (w < 19.95)
z += 0.24999308500451499336 / z;
z += 0.13830277879601902638e-4 * z;
} else {
z = exp(y);
z = z*0.5 + 0.5/z;
}
return z;
}
tanh.c
#include "math.h"
#define P0 -0.16134119023996228053e+4
#define P1 -0.99225929672236083313e+2
#define P2 -0.96437492777225469787e+0
#define Q0 +0.48402357071988688686e+4
#define Q1 +0.22337720718962312926e+4
#define Q2 +0.11274474380534949335e+3
#define gP(g) (((P2*g P1)*g P0)*g)
#define Q(g) (((g Q2)*g Q1)*g Q0)
double tanh(x)
double x;
{
double f,g,r;
f = fabs(x);
if (f > 25.3)
r = 1.0;
else if (f > 0.54930614433405484570) {
r = 0.5 - 1.0/(exp(f+f)+1.0);
r += r;
} else if (f < 2.3e-10)
r = f;
else {
g = f*f;
r = f + f*
(gP(g)
/Q(g));
}
if (x < 0.0)
r = -r;
return r;
}
pow.c
#include "math.h"
#include "errno.h"
double pow(a,b)
double a,b;
{
double loga;
extern int errno;
if (a<=0.0) {
if (a<0.0 || a==0.0 && b<=0.0) {
errno = EDOM;
return -HUGE;
}
else return 0.0;
}
loga = log(a);
loga *= b;
if (loga > LOGHUGE) {
errno = ERANGE;
return HUGE;
}
if (loga < LOGTINY) {
errno = ERANGE;
return 0.0;
}
return exp(loga);
}
sqrt.c
#include "math.h"
#include "errno.h"
double sqrt(x)
double x;
{
double f, y;
int n;
extern int errno;
if (x == 0.0)
return x;
if (x < 0.0) {
errno = EDOM;
return 0.0;
}
f = frexp(x, &n);
y = 0.41731 + 0.59016 * f;
y = (y + f/y);
y = 0.25*y + f/y; /* fast calculation of y2 */
y = 0.5 * (y + f/y);
y = y + 0.5 * (f/y - y);
if (n&1) {
y *= 0.70710678118654752440;
++n;
}
return ldexp(y,n/2);
}
log.c
#include "math.h"
#include "errno.h"
double log10(x)
double x;
{
return log(x)*0.43429448190325182765;
}
#define A0 -0.64124943423745581147e+2
#define A1 +0.16383943563021534222e+2
#define A2 -0.78956112887491257267e+0
#define A(w) ((A2*w A1)*w A0)
#define B0 -0.76949932108494879777e+3
#define B1 +0.31203222091924532844e+3
#define B2 -0.35667977739034646171e+2
#define B(w) (((w B2)*w B1)*w B0)
#define C0 0.70710678118654752440
#define C1 0.693359375
#define C2 -2.121944400546905827679e-4
double log(x)
double x;
{
double Rz, f, z, w, znum, zden, xn;
int n;
extern int errno;
if (x <= 0.0) {
errno = EDOM;
return -HUGE;
}
f = frexp(x, &n);
if (f > C0) {
znum = (f-0.5)-0.5;
zden = f*0.5 + 0.5;
} else {
--n;
znum = f - 0.5;
zden = znum*0.5 + 0.5;
}
z = znum/zden;
w = z*z;
/* the lines below are split up to allow expansion of A(w) and B(w) */
Rz = z + z * (w *
A(w)
/B(w));
xn = n;
return (xn*C2 + Rz) + xn*C1;
}
random.c
/*
* Random number generator -
* adapted from the FORTRAN version
* in "Software Manual for the Elementary Functions"
* by W.J. Cody, Jr and William Waite.
*/
double ran()
{
static long int iy = 100001;
iy *= 125;
iy -= (iy/2796203) * 2796203;
return (double) iy/ 2796203.0;
}
double randl(x)
double x;
{
double exp();
return exp(x*ran());
}
exp.c
#include "math.h"
#include "errno.h"
#define P0 0.249999999999999993e+0
#define P1 0.694360001511792852e-2
#define P2 0.165203300268279130e-4
#define Q0 0.500000000000000000e+0
#define Q1 0.555538666969001188e-1
#define Q2 0.495862884905441294e-3
#define P(z) ((P2*z + P1)*z + P0)
#define Q(z) ((Q2*z + Q1)*z + Q0)
#define EPS 2.710505e-20
double
exp(x)
double x;
{
int n;
double xn, g, r, z;
extern int errno;
if (x > LOGHUGE) {
errno = ERANGE;
return HUGE;
}
if (x < LOGTINY) {
errno = ERANGE;
return 0.0;
}
if (fabs(x) < EPS)
return 1.0;
z = modf(x * 1.4426950408889634074, &xn);
if (z >= 0.5)
++xn;
n = xn;
z = modf(x, &x); /* break x up into fraction and integer part */
g = ((x - xn*0.693359375) + z) + xn*2.1219444005469058277e-4;
z = g*g;
r = P(z)*g;
r = 0.5 + r/(Q(z)-r);
return ldexp(r,n+1);
}
floor.c
#include "math.h"
double floor(d)
double d;
{
if (d < 0.0)
return -ceil(-d);
modf(d, &d);
return d;
}
double ceil(d)
double d;
{
if (d < 0.0)
return -floor(-d);
if (modf(d, &d) > 0.0)
++d;
return d;
}
atof.asm
; Copyright (C) 1983 by Manx Software Systems
; :ts=8
extrn .dml10, .utod, .dswap, .dad
extrn .dlis, .ddv, .dng
dseg
msign: ds 1
esign: ds 1
dpflg: ds 1
dexp: ds 2
cseg
public atof_
atof_:
push b
xra a
sta msign ;clear mantissa sign
sta esign ;clear exponent sign
sta dpflg ;have not seen decimal point yet
lxi h,0
shld dexp ;clear exponent to zero
call .utod ;clear floating point accumulator
;
lxi h,4
dad sp
mov c,m ;get address of string to convert
inx h
mov b,m
skipbl:
ldax b
cpi ' '
jz blank
cpi 9
jnz notblank
blank:
inx b
jmp skipbl
notblank:
cpi '-'
jnz notneg ;not minus sign
sta msign ;set negative for later
jmp skpsign
notneg:
cpi '+' ;check for plus sign
jnz getnumb
skpsign:
inx b ;skip over sign character
getnumb:
ldax b
cpi '0'
jc notdigit
cpi '9'+1
jnc notdigit
push psw
call .dml10
call .dswap
pop psw
sui '0'
mov l,a
mvi h,0
call .utod
call .dad
lda dpflg
ora a
jz skpsign
lhld dexp
dcx h
shld dexp
jmp skpsign
notdigit:
cpi '.'
jnz nomore
lxi h,dpflg
mvi m,1 ;set dec. pt. seen
jmp skpsign
;
nomore:
lxi h,0 ;clear exponent
ori 20H ;force to lower case
cpi 'e'
jnz scaleit
inx b
ldax b
cpi '-'
jnz exppos
sta esign ;set exponent negative
jmp nxtchr
exppos:
cpi '+'
jnz getexp
nxtchr:
inx b
getexp:
ldax b
cpi '0'
jc expdone
cpi '9'+1
jnc expdone
sui '0'
dad h ; exp *= 2
mov d,h
mov e,l
dad h ;exp *= 4
dad h ;exp *= 8
dad d ;exp *= 10
mov e,a
mvi d,0
dad d ;exp = exp*10 + char - '0'
jmp nxtchr
;
expdone:
lda esign ;check sign of exponent
ora a
jz addexp
mov a,h ;negate if sign was minus
cma
mov h,a
mov a,l
cma
mov l,a
inx h
addexp:
xchg
lhld dexp ;get digit count
dad d ;add in exponent value
shld dexp ;save for scaling later
;
scaleit: ;scale number to correct value
lhld dexp
mov a,h
ora a
jp movup
;negative exponent
cpi 0ffH ;test if exponent too large
jnz rngerr
mov a,l
cma
inr a
mov c,a ;save for loop later
cpi 166
jnc rngerr
cpi 150
jc sizeok
call .dlis ;divide by 1e16 since smallest will overflow
db 47H,23H,86H,0f2H,6fH,0c1H,0,0
call .ddv
mov a,c ;get exponent value back
sui 16
mov c,a
sizeok:
call .dswap
lxi h,1
call .utod
sclp1:
call .dml10 ;compute number to divide by
dcr c
jnz sclp1
call .dswap ;get everybody back in place
call .ddv ;move into range
jmp dosign
;
movup: ;positive exponent scale number up
jnz rngerr
mov a,l ;get loop count
ora a
jz dosign
mov c,a
sclp2:
call .dml10
dcr c
jnz sclp2
;
dosign:
lda msign ;check sign of number
ora a
jz return
call .dng ;negate accumulator
return:
pop b
ret
;
rngerr:
pop b
ret
end
ftoa.asm
; Copyright (C) 1982, 1983 by Manx Software Systems
; :ts=8
extrn .dldp, .dlds, .utod, .dlis, .dswap, .dtst
extrn .dng, .dlt, .dge, .dad, .ddv, .dml10
extrn flprm
dseg
chrptr: ds 2
maxdig: ds 1
ndig: ds 2
exp: ds 2
count: ds 1
fflag: ds 1
cseg
rounding:
; 0.5,
DB 040H,080H,00H,00H,00H,00H,00H,00H
; 0.05,
DB 040H,0CH,0CCH,0CCH,0CCH,0CCH,0CCH,0CDH
; 0.005,
DB 040H,01H,047H,0AEH,014H,07AH,0E1H,048H
; 0.0005,
DB 03FH,020H,0C4H,09BH,0A5H,0E3H,054H,00H
; 0.00005,
DB 03FH,03H,046H,0DCH,05DH,063H,088H,066H
; 0.000005,
DB 03EH,053H,0E2H,0D6H,023H,08DH,0A3H,0CDH
; 0.0000005,
DB 03EH,08H,063H,07BH,0D0H,05AH,0F6H,0C8H
; 0.00000005,
DB 03DH,0D6H,0BFH,094H,0D5H,0E5H,07AH,066H
; 0.000000005,
DB 03DH,015H,079H,08EH,0E2H,030H,08CH,03DH
; 0.0000000005,
DB 03DH,02H,025H,0C1H,07DH,04H,0DAH,0D3H
; 0.00000000005,
DB 03CH,036H,0F9H,0BFH,0B3H,0AFH,07BH,080H
; 0.000000000005,
DB 03CH,05H,07FH,05FH,0F8H,05EH,059H,026H
; 0.0000000000005,
DB 03BH,08CH,0BCH,0CCH,09H,06FH,050H,09AH
; 0.00000000000005,
DB 03BH,0EH,012H,0E1H,034H,024H,0BBH,043H
; 0.000000000000005,
DB 03BH,01H,068H,049H,0B8H,06AH,012H,0BAH
;
;
public ftoa_
ftoa_:
push b
lxi h,12
dad sp
mov e,m
inx h
mov d,m
xchg
shld chrptr ;buffer for converted data
lxi h,16
dad sp
mov a,m
sta fflag ;e/f/g format flag
;
lxi h,4
dad sp
call .dldp ;fetch number to convert
lxi h,14
dad sp
mov a,m ;fetch precision
sta maxdig
inr a
mov l,a
mvi h,0
shld ndig
;
lhld flprm
mov a,m
ora a
jp notneg
call .dng
lhld chrptr
mvi m,'-'
inx h
shld chrptr
notneg:
lxi b,0 ;clear integer exponent
call .dtst
jz numbok
call .dlis
db 041H,0aH,0,0,0,0,0,0
adjust:
lhld flprm
inx h
mov a,m
cpi 1
jm toosml
jz tentest
cpi 2
jnz bignum
inx h
inx h
mov a,m
cpi 27H ;number < 10000, just do divides
jc quick
bignum:
call inverse
call .dlis
db 40H,19H,99H,99H,99H,99H,99H,9aH
bignlp:
call .dml10
inx b
call .dlt
jnz bignlp
call inverse
lhld flprm
inx h
inx h
inx h
mov a,m
cpi 10
jc numbok
dcx b
call .dml10
jmp numbok
qcklp:
lhld flprm
inx h
mov a,m
cpi 1
jnz quick
tentest:
inx h
inx h
mov a,m
cpi 10
jc numbok
quick:
call .ddv ;divide by ten till 1 <= number < 10
inx b ;count for exponent
jmp qcklp
sml.lp:
lhld flprm
inx h
mov a,m
cpi 1
jp numbok
toosml:
call .dml10 ;multiply by ten till 1 <= number < 10
dcx b ;count for exponent
jmp sml.lp
;
numbok:
lda fflag ;check conversion format
ora a
jz eformat
cpi 1
jz fformat
lda maxdig ;if %g then precision is # sig. digits
mov l,a
mvi h,0
shld ndig
mov a,b ;select %f if maxdig > exp > -4, else use %e
ora a
jm chkm4
mov a,c
cmp l
jnc eformat
mvi a,1 ;exp < maxdig, so use %f
jmp setformat
;
chkm4:
mov a,c
cpi -4
jc eformat ;exp < -4, so use %e
fformat:
lhld ndig
dad b
shld ndig
mvi a,1
jmp setformat
eformat:
xra a
setformat:
sta fflag
; now round number according to the number of digits
lhld ndig
dcx h
mov a,h
ora a
jp L1
lxi h,0
jmp L5
L1:
jnz toomany
mov a,l
cpi 14
jc L5
toomany:
lxi h,14
L5:
dad h ;*2
dad h ;*4
dad h ;*8
lxi d,rounding
dad d
call .dlds
call .dad ;add in rounding counstant
;
call .dlis
db 041H,0aH,0,0,0,0,0,0
call .dge ;check for rounding overflow
jz rndok
lxi h,1
call .utod ;and repair if necessary
inx b
lda fflag
ora a
jz rndok
lhld ndig
inx h
shld ndig
rndok:
mov h,b
mov l,c
shld exp
lda fflag
ora a
jz unpack
mov a,b
ora a
mov a,c ;move for unpack
jp unpack
; F format and negative exponent
; put out leading zeros
lhld chrptr
mvi m,'0'
inx h
mvi m,'.'
inx h
lda ndig+1
ora a
jm under
mov a,c
cma
jmp L2
under:
lda maxdig
L2:
ora a
jz zdone
zdiglp:
mvi m,'0'
inx h
dcr a
jnz zdiglp
zdone:
shld chrptr
mvi a,0ffH ;mark decpt already output
;
unpack: ;when we get here A has the position for the
;decimal point
mov c,a ;save decimal point position
lxi h,ndig+1 ;check if ndigits is <= zero
mov a,m
ora a
jm unpdone ;if so just quit now
dcx h
ora m
jz unpdone ;if so just quit now
lhld flprm
lxi d,10
dad d
mvi m,0 ;zap guard bytes
inx h
mvi m,0
mvi b,0
unplp:
mov a,b
cpi 15
mvi a,'0'
jnc zerodigit
lhld flprm
inx h ;skip sign byte
mov a,m
cpi 1
mvi a,'0'
jnz zerodigit
inx h ;skip exponent
inx h ;skip overflow
add m
mvi m,0 ;subtract integer portion (virtual)
zerodigit:
lhld chrptr
mov m,a
inx h
shld chrptr
lxi h,ndig
dcr m
jz unpdone
mov a,b
cmp c
jnz mul10
lhld chrptr
mvi m,'.'
inx h
shld chrptr
mul10:
call .dml10 ;multiply by 10 and re-normalize
inr b
jmp unplp
;
unpdone:
lda fflag
ora a
jnz alldone
;
lhld chrptr
mvi m,'e'
inx h
mvi m,'+'
lda exp+1
ora a
lda exp
jp posexp
mvi m,'-'
cma
inr a
posexp:
inx h
cpi 100
jc lt100
mvi m,'1'
inx h
sui 100
lt100:
mvi b,0
tens:
cpi 10
jc lt10
inr b
sui 10
jmp tens
lt10:
adi '0' ;ascii of last digit
mov e,a ;save last digit
mvi a,'0'
add b ;compute second digit
mov m,a
inx h
mov m,e
inx h
shld chrptr
;
alldone:
lhld chrptr
mvi m,0
pop b
ret
;
inverse:
call .dswap
lxi h,1
call .utod
jmp .ddv ;implied return
;
end
frexp.asm
; Copyright (C) 1982, 1983, 1984 by Manx Software Systems
; :ts=8
extrn flprm
extrn .dldp, .utod
public frexp_, ldexp_, modf_
;
frexp_: ;return mantissa and exponent
push b
lxi h,4
dad sp
call calcexp ;calculate power of two exponent
jnz retexp
lxi b,0
retexp:
lxi h,12 ;address second argument
dad sp
mov e,m
inx h
mov d,m
xchg
mov m,c ;return base 2 exponent
inx h
mov m,b
popret:
pop b
ret
;
ldexp_: ;load new exponent value (actualy add to exponent)
push b
lxi h,4
dad sp
call calcexp
jz popret ;do nothing if number is zero or unnormalized
lxi h,12 ;fetch number to add to exponent
dad sp
mov e,m
inx h
mov d,m
xchg
dad b ;add exponents
mov a,h
ora a ;check sign of exponent
jp posexp
cma ;make positive for div and modulo below
mov h,a
mov a,l
cma
mov l,a
inx h
mov a,l
ani 7
mov c,a ;save amount to shift
call rsexp ;make power of 256
mov a,l
cma
inr a ;fix sign back
mov l,a
jmp ldrs
posexp:
ora l ;check if zero
jz popret ;no adjustment needed
mov c,l ;save to compute left shift
call rsexp ;make power of 256
mov a,c
ani 7
jz ldrsx
inr l ;bump exponent to make right shift
cma
adi 9 ;compensate for +1 (c = -(x-8))
ldrsx:
mov c,a ;save for loop below
ldrs:
xchg
lhld flprm
inx h
mov m,e ;save exponent
rsloop:
dcr c
jm popret
lhld flprm
inx h
inx h
mvi b,7
ora a ;clear carry
rslp:
inx h
mov a,m
rar
mov m,a
dcr b
jnz rslp
jmp rsloop
;
rsexp:
ora a
mvi b,3
rselp:
mov a,h
rar
mov h,a
mov a,l
rar
mov l,a
dcr b
jnz rselp
ret
;
calcexp:
call .dldp ;load into floating accumulator
lhld flprm
inx h
mov a,m ;get exponent value
cpi -64
rz
mvi m,0 ;make exponent zero for return
mov l,a ;get low byte of exponent
rlc ;sign extend value
sbb a
mov h,a ;save high byte of exponent
dad h
dad h
dad h ; exp*8 to make power of two
mov b,h ; bc = exponent
mov c,l
lhld flprm
inx h
inx h
inx h ;hl = first byte of mantissa
mov a,m
ora a
rz ;unnormalized number? give up
lshft:
mov a,m
ani 80H ;test high bit of mantissa
rnz ;mantissa >= 0.5 ? yes return
;otherwise, shift number to the left one place
dcx b ;and adjust exponent
lxi d,7
dad d ;address of end of fraction
lsloop:
dcx h
mov a,m
ral
mov m,a
dcr e
jnz lsloop
jmp lshft
;
modf_: ;split into integral and fraction parts
push b
lxi h,12 ;pick up address to store integral part
dad sp
mov c,m
inx h
mov b,m
mov l,c
mov h,b
mvi e,8 ;clear out integer
xra a
mdclr:
mov m,a
inx h
dcr e
jnz mdclr
;
lxi h,4
dad sp
call .dldp
lhld flprm
inx h
mov a,m
ora a
jm popret
jz popret
adi 64
ani 7fH
mov e,a
dcx h
mov a,m ;get sign of number
ani 80H ;isolate
ora e ;combine with exponent
stax b ;store away
inx b
inx h
mov a,m ;refetch exponent
inx h ;skip over exponent
inx h ;skip over overflow byte
cpi 7
jc expok ;limit move loop to 7 bytes
mvi a,7
expok:
mov e,a ;save count for loop
cma
adi 8 ; 7 - loop count
mov d,a ;save # bytes in fraction
intmov: ;copy integer part into given area
mov a,m
stax b
inx h
inx b
dcr e
jnz intmov
;
fnorm: ;note: E is zero at start of this loop
dcr d
jm zfrac ;fraction is zero
mov a,m ;look for non-zero byte
inx h
dcr e ;count for exponent of fraction
ora a
jz fnorm
;
dcx h ;back up to good byte
inr e ;fix exponent
mov b,h ;save position in accumulator
mov c,l
lhld flprm
inx h
mov m,e ;store exponent
inx h ;skip overflow byte
mvi e,7 ;count of # that must be cleared
frcmov:
inx h
ldax b
mov m,a
inx b
dcr e
dcr d
jp frcmov
xra a
frcclr: ;clear out rest of register
inx h
mov m,a
dcr e
jnz frcclr
pop b
ret
zfrac: ;fraction is zero
lxi h,0
call .utod
pop b
ret
fsubs.asm
; Copyright (C) 1982, 1983, 1984 by Manx Software Systems
; :ts=8
extrn Sysvec_
extrn lnprm
extrn puterr_
dseg
public flprm,flsec
flprm: dw acc1
flsec: dw acc2
public flterr_
flterr_: dw 0
retsave:ds 2
YU: ds 2
VEE: ds 2
expdiff:ds 1
acc1: ds 18
acc2: ds 18
;work area for divide and multiply routines
lcnt: ds 1 ;iterations left
tmpa: ds 8 ;quotient
tmpb: ds 8 ;remainder work area
tmpc: ds 8 ;temp for divisor
cseg
public .flds ;load single float into secondary accum
.flds:
xchg
lhld flsec
jmp fload
;
public .fldp ;load single float into primary accum
.fldp:
xchg
lhld flprm
fload:
push b
ldax d ;get first byte of number
mov m,a ;save sign
inx h
ani 7fH ;isolate exponent
sui 64 ;adjust from excess 64 notation
mov m,a ;and save
inx h
mvi m,0 ;extra byte for carry
mvi b,3 ;copy 3 byte fraction
ldloop:
inx h
inx d
ldax d
mov m,a
dcr b
jnz ldloop
mvi b,5 ;clear rest to zeros
xra a
clloop:
inx h
mov m,a
dcr b
jnz clloop
pop b
ret
;
public .fst ;store single at addr in HL
.fst:
push b
xchg
lhld flprm
mov a,m ;get sign
ani 80H ;and isolate
mov b,a ;save
inx h
mov a,m ;get exponent
adi 64 ;put into excess 64 notation
ani 7fH ;clear sign bit
ora b ;merge exponent and sign
stax d
inx h ;skip overflow byte
mvi b,3 ;copy 3 bytes of fraction
fstlp:
inx d
inx h
mov a,m
stax d
dcr b
jnz fstlp
pop b
ret
;
public .dlis ;load double immediate secondary
.dlis:
pop d ;get return addr
lxi h,8 ;size of double
dad d
push h ;put back correct return addr
xchg
;fall through into .dlds
;
public .dlds ;load double float into secondary accum
.dlds:
xchg
lhld flsec
jmp dload
;
public .dlip ;load double immediate primary
.dlip:
pop d ;get return addr
lxi h,8 ;size of double
dad d
push h ;put back correct return addr
xchg
;fall through into .dldp
;
public .dldp ;load double float into primary accum
.dldp:
xchg
lhld flprm
dload:
push b
ldax d ;get first byte of number
mov m,a ;save sign
inx h
ani 7fH ;isolate exponent
sui 64 ;adjust from excess 64 notation
mov m,a ;and save
inx h
mvi m,0 ;extra byte for carry
mvi b,7 ;copy 7 byte fraction
dloop:
inx h
inx d
ldax d
mov m,a
dcr b
jnz dloop
inx h
mvi m,0 ;clear guard byte
pop b
ret
;
public .dst ;store double at addr in HL
.dst:
push b
push h ;save address
call dornd ;round fraction to 7 bytes
pop d ;restore address
lhld flprm
mov a,m ;get sign
ani 80H ;and isolate
mov b,a ;save
inx h
mov a,m ;get exponent
adi 64 ;put into excess 64 notation
ani 7fH ;clear sign bit
ora b ;merge exponent and sign
stax d
inx h ;skip overflow byte
mvi b,7 ;copy 7 bytes of fraction
dstlp:
inx d
inx h
mov a,m
stax d
dcr b
jnz dstlp
pop b
ret
;
public .dpsh ;push double float onto the stack
.dpsh: ;from the primary accumulator
pop h ;get return address
shld retsave ;and save for later
call dornd
lhld flprm
lxi d,9
dad d
mov d,m ;bytes 6 and 7
dcx h
mov e,m
dcx h
push d
mov d,m ;bytes 4 and 5
dcx h
mov e,m
dcx h
push d
mov d,m ;bytes 2 and 3
dcx h
mov e,m
dcx h
push d
mov d,m ;byte 1
dcx h
dcx h ;skip over carry byte
mov a,m ;get exponent
adi 64 ;and restore to excess 64 notation
ani 7fH
mov e,a
dcx h
mov a,m
ani 80H ;isolate sign bit
ora e ;combine exponent and sign
mov e,a
push d
lhld retsave
pchl
;
public .dpop ;pop double float into secondary accum
.dpop:
pop h ;get return address
shld retsave ;and save
lhld flsec
pop d ;exponent/sign and first fraction
mov m,e ;save sign
inx h
mov a,e
ani 7fH ;isolate exponent
sui 64 ;adjust for excess 64 notation
mov m,a
inx h
mvi m,0 ;extra byte for carry
inx h
mov m,d
inx h
pop d ;bytes 2 and 3 of fraction
mov m,e
inx h
mov m,d
inx h
pop d ;bytes 4 and 5 of fraction
mov m,e
inx h
mov m,d
inx h
pop d ;bytes 6 and 7 of fraction
mov m,e
inx h
mov m,d
inx h
mvi m,0 ;clear guard byte
lhld retsave
pchl
;
public .dswap ;exchange primary and secondary
.dswap:
lhld flsec
xchg
lhld flprm
shld flsec
xchg
shld flprm
ret
;
public .dng ;negate primary
.dng:
lhld flprm
mov a,m
xri 80H ;flip sign
mov m,a
ret
;
public .dtst ;test if primary is zero
.dtst:
lhld flprm
; mov a,m
; ora a
; jnz true
inx h
mov a,m
cpi -64
jnz true
; inx h
; inx h
; mov a,m
; ora a
; jnz true
jmp false
;
public .dcmp ;compare primary and secondary
;
;return 0 if p == s
p.lt.s: ;return < 0 if p < s
xra a
dcr a
pop b
ret
;
p.gt.s: ; > 0 if p > s
xra a
inr a
pop b
ret
;
.dcmp:
push b
lhld flprm
xchg
lhld flsec
ldax d
ora a
jm dcneg
; primary is positive
xra m ;check if signs the same
jm p.gt.s ;differ then p > s
jmp docomp
dcneg:
;primary is negative
xra m ;check if signs the same
jm p.lt.s ;differ the p < s
xchg ;both negative reverse sense of test
docomp:
inx h
inx d
ldax d
cmp m ;compare exponents
jm p.lt.s ;sign test ok since -64 < exp < 64
jnz p.gt.s
mvi b,9 ;test overflow byte + 8 bytes of fraction
cmploop:
inx h
inx d
ldax d
cmp m
jc p.lt.s
jnz p.gt.s
dcr b
jnz cmploop
;return 0 if p == s
xra a
pop b
ret
;
public .dsb ;subtract secondary from primary
.dsb:
lhld flsec
mov a,m
xri 80H ;flip sign of secondary
mov m,a
;fall thru into add routine
;
public .dad ;add secondary to primary
.dad:
;DE is used as primary address
;and HL is used as secondary address
push b
;clear extra bytes at end of accumulators
lhld flprm
lxi d,11 ;leave guard byte alone
dad d
mvi b,7
xra a
clp1:
mov m,a
inx h
dcr b
jnz clp1
lhld flsec
lxi d,11 ;leave guard byte alone
dad d
mvi b,7
clp2:
mov m,a
inx h
dcr b
jnz clp2
lhld flprm
xchg
lhld flsec
inx h
inx d
ldax d ;primary exponent
sub m ;compute difference
jp ordok
xchg ;swap so primary is larger
cma
inr a
ordok:
dcx d
dcx h
shld flsec ;fix primary and secondary
xchg
shld flprm
cpi 9 ;check for exp diff too large
jnc normalize
mov c,a ;save exponent difference
push h
push d
adi 9 ;adjust for offset
mov e,a
mvi d,0
dad d ;adjust address for exponent difference
shld YU
pop d
lxi h,9
dad d
shld VEE
pop h
xchg ;get prm in DE and scnd in HL
ldax d ;sign of primary
xra m ;check if signs same
jp doadd
ldax d
ora a ;test which one is negative
jm UfromV ;jump if primary is negative
;subtract V from U
mvi b,7
lhld YU
xchg
lhld VEE
sublpa: ;carry is already cleared
ldax d
sbb m
stax d
dcx d
dcx h
dcr b
jnz sublpa
brlpa:
ldax d
sbi 0
stax d
dcx d
dcr c
jp brlpa
xchg ;get destination into HL
jmp subchk ;check for negative result
;
UfromV:
;subtract U from V
mvi b,7
lhld VEE
xchg
lhld YU
sublpb: ;carry is already cleared
ldax d
sbb m
mov m,a
dcx d
dcx h
dcr b
jnz sublpb
brlpb:
mvi a,0
sbb m
mov m,a
dcx h
dcr c
jp brlpb
subchk: ;check for negative result
inx h
mov a,m ;check carry byte
ora a ;test sign
mvi a,1
jp makpos
lxi d,15
dad d ;point to end of number
neglp:
mvi a,0
sbb m
mov m,a
dcx h
dcr e
jp neglp
mvi a,81H ;make number negative
makpos:
lhld flprm
mov m,a ;set sign of number
jmp normalize
;
doadd:
;add V to U
mvi b,7
lhld YU
xchg
lhld VEE
addlp: ;carry is already cleared
ldax d
adc m
stax d
dcx d
dcx h
dcr b
jnz addlp
crylp:
ldax d
aci 0
stax d
dcx d
dcr c
jp crylp
jmp normalize
;
public .ddv
.ddv: ;double floating divide (primary = primary/secondary)
push b
lhld flprm
xchg
lhld flsec
ldax d
xra m ;compute sign of result
stax d ;and store
inx h
inx d
ldax d ;primary exponent
sub m ;eu-ev
mov c,a ;save exponent
push d
push h
mov a,m
cpi -64
jnz d.ok
pop h
pop h ;throw away
mvi a,3 ;flag divide by zero error
sta flterr_
jmp setbig ;set to biggest possible number
d.ok:
inx d
inx h
mvi b,8
cmloop:
inx d
inx h
ldax d
cmp m
jnz differ
dcr b
jnz cmloop
;numbers are the same give 1 as the answer
pop h ;throw away
pop h ;get destination addr
inr c ;adjust exponent
mov m,c ;save exponent
inx h
mvi m,0 ;clear extra byte
inx h
mvi m,1 ;set result
mvi b,8
xra a
sta flterr_
jmp zclr
;
differ: ;check carry to find out smaller number
pop d ;restore divisor address
pop h ;restore dividend address
mov m,c ;store exponent
jc uok
inr c ;bump exponent
mov m,c
dcx h ;and shift dividend right (logically)
uok:
push d ;save for later
lxi d,9
dad d ;compute end address
mvi b,8
lxi d,tmpb ;copy dividend into work area
remsav:
mov a,m
stax d
dcx h
inx d
dcr b
jnz remsav
pop h ;restore divisor addr
lxi d,9
dad d ;move backwards
mvi b,8
lxi d,tmpc ;copy divisor into work area
divsav:
mov a,m
stax d
dcx h
inx d
dcr b
jnz divsav
mvi b,8
lxi h,tmpa ;clear quotient buffer
xra a
quinit:
mov m,a
inx h
dcr b
jnz quinit
mvi a,64
sta lcnt ;initialize loop counter
divloop:
lxi h,tmpa
mvi b,16
ora a ;clear carry
shlp:
mov a,m
adc a ;shift one bit to the left
mov m,a
inx h
dcr b
jnz shlp
sbb a
ani 1
mov c,a
mvi b,8
lxi d,tmpb
lxi h,tmpc
ora a ;clear carry
sublp:
ldax d
sbb m
stax d
inx d
inx h
dcr b
jnz sublp
mov a,c
sbi 0
jnz zerobit
onebit:
lxi h,tmpa
inr m
lxi h,lcnt
dcr m
jnz divloop
jmp divdone
;
zerobit:
lxi h,lcnt
dcr m
jz divdone
lxi h,tmpa
mvi b,16
ora a ;clear carry
zshlp:
mov a,m
adc a ;shift one bit to the left
mov m,a
inx h
dcr b
jnz zshlp
sbb a
mov c,a
mvi b,8
lxi d,tmpb
lxi h,tmpc
ora a ;clear carry
daddlp:
ldax d
adc m
stax d
inx d
inx h
dcr b
jnz daddlp
mov a,c
aci 0
jnz zerobit
jmp onebit
;
divdone:
lhld flprm
lxi d,12
dad d
mvi m,0
dcx h
mvi m,0
lxi d,tmpa
mvi b,8
qusav:
dcx h
ldax d
mov m,a
inx d
dcr b
jnz qusav
jmp normalize
;
public .dml
.dml: ;double floating multiply (primary = primary * secondary)
push b
lhld flprm
xchg
lhld flsec
ldax d
xra m ;compute sign of result
stax d ;and store
inx h
inx d
ldax d ;primary exponent
cpi -64
jz zresult
add m ;eu+ev
stax d ;save exponent
mov a,m ;check for mult by zero
cpi -64
jz zresult
push d ;save for later
lxi d,9
dad d ;compute end address
mvi b,8
lxi d,tmpc ;copy muliplicand into work area
msav1:
mov a,m
stax d
dcx h
inx d
dcr b
jnz msav1
pop h ;restore multiplier addr
lxi d,9
dad d ;move backwards
mvi b,8
lxi d,tmpb ;copy multiplier into work area
msav2:
mov a,m
stax d
dcx h
inx d
dcr b
jnz msav2
mvi b,8
lxi h,tmpa ;clear buffer
xra a
clrmul:
mov m,a
inx h
dcr b
jnz clrmul
mvi a,64
sta lcnt ;initialize loop counter
muloop:
lxi h,tmpa
mvi b,16
ora a ;clear carry
mshlp:
mov a,m
adc a ;shift one bit to the left
mov m,a
inx h
dcr b
jnz mshlp
jnc mnext
mvi b,8
lxi d,tmpa
lxi h,tmpc
ora a ;clear carry
maddlp:
ldax d
adc m
stax d
inx d
inx h
dcr b
jnz maddlp
;
mvi b,8
madclp:
ldax d
aci 0
stax d
jnc mnext
inx d
dcr b
jnz madclp
;
mnext:
lxi h,lcnt
dcr m
jnz muloop
lhld flprm
lxi d,12
dad d
lxi d,tmpb-2
mvi b,10
msav:
ldax d
mov m,a
inx d
dcx h
dcr b
jnz msav
jmp normalize
;
;
public .deq
.deq:
call .dcmp
jz true
false:
lxi h,0
xra a
ret
;
public .dne
.dne:
call .dcmp
jz false
true:
lxi h,1
xra a
inr a
ret
;
public .dlt
.dlt:
call .dcmp
jm true
jmp false
;
public .dle
.dle:
call .dcmp
jm true
jz true
jmp false
;
public .dge
.dge:
call .dcmp
jm false
jmp true
;
public .dgt
.dgt:
call .dcmp
jm false
jz false
jmp true
;
public .utod
.utod:
push b
mov a,h
ora l
jz zresult
xchg
mvi b,0
jmp posconv
;
public .itod
.itod:
push b
mov a,h
ora l
jz zresult
xchg
mvi b,0
mov a,d
ora a
jp posconv
cma
mov d,a
mov a,e
cma
mov e,a
inx d
mvi b,80H
posconv:
lhld flprm
mov m,b ;store sign
inx h
mov a,d
ora a
jnz longcvt
mvi m,1 ;set up exponent
inx h
mvi m,0 ;clear extra byte
inx h
mov m,e ;move number into accumulator
mvi b,7
xra a
jmp cnvlp
;
longcvt:
mvi m,2 ;setup exponent
inx h
mvi m,0 ;clear extra byte
inx h
mov m,d ;move number into accumulator
inx h
mov m,e
mvi b,6
xra a
cnvlp:
inx h
mov m,a
dcr b
jnz cnvlp
jmp goodexit
;
dornd: ; round the number in the primary accumulator
lhld flprm
lxi d,10 ;offset of guard byte
dad d
mov a,m
cpi 128
rc ; < 128 do nothing
jnz rndit
dcx h ; == 128 make number odd
mov a,m
ori 1
mov m,a
ret
;
rndit: ; > 128 add one to fraction
push b
lxi b,0800H ;b = 8, and c = 0
stc ; make loop add 1
rndlp:
dcx h
mov a,m
adc c
mov m,a
dcr b
jnz rndlp
ora a ;check for fraction overflow
jnz normalize ;re-normalize number if so.
pop b
ret ;return if none
;
normalize:
lhld flprm ;get address of accum
inx h
mov a,m ;fetch exponent
mov d,h ;save address for later
mov e,l
inx h
mov c,a
xra a
cmp m ;check extra byte
jnz movrgt ;non-zero move number right
mvi b,8 ;search up to 8 bytes
nloop:
inx h
cmp m
jnz movleft
dcr c ;adjust exponent
dcr b ;count times thru
jnz nloop
;zero answer
zresult:
xra a
sta flterr_
under0:
lhld flprm
mvi b,10
mov m,a
inx h
mvi m,-64 ;so exponent will be zero after store
zclr:
inx h
mov m,a
dcr b
jnz zclr
pop b
ret
;
movleft:
mvi a,8
sub b
mov b,a
jz chkexp ;no change in counter, no move needed
dcx h ;back up to zero
mov a,c
stax d ;save new exponent
push d ;save for rounding
inx d
mvi a,15
sub b ;compute # of bytes to move
mov c,a ;save for loop
lmovlp:
mov a,m
stax d
inx d
inx h
dcr c
jnz lmovlp
xra a
lclrlp:
stax d ;pad with zeros
inx d
dcr b
jnz lclrlp
pop d ;restore accum address
;
chkexp: ;check for over/under flow
ldax d ;get exponent
ora a
jm chkunder
cpi 64
jc goodexit
jmp overflow
;
chkunder:
cpi -63
jc underflow
goodexit:
mvi a,0
sta flterr_
pop b
ret
;
movrgt: ;fraction overflow
inr c ;bump exponent
mov a,c
stax d ;save in accum
mvi b,15
push d ;save for check at end
lxi h,16
dad d ;end address for backwards move
mov d,h
mov e,l
rmovlp:
dcx d
ldax d
mov m,a
dcx h
dcr b
jnz rmovlp
mvi m,0 ;zap overflow byte back to zero
pop d ;restore exponent addr
jmp chkexp
;
underflow:
mvi a,1
sta flterr_
call userrtn ;check for user routine to handle errors
xra a
lhld flprm
inx h ;leave sign alone
mvi m,-63 ;set to smallest non-zero value
inx h
mov m,a
inx h
mvi m,1
mvi b,8
jmp zclr ;clear rest to zero
;
overflow:
mvi a,2
sta flterr_
setbig:
call userrtn ;check for user routine to handle errors
lhld flprm
inx h ;leave sign alone
mvi m,63 ;set exponent at max
inx h
mvi m,0 ;clear overflow byte
mvi a,0ffH ;and set fraction to max
mvi b,7
oclr:
inx h
mov m,a
dcr b
jnz oclr
inx h
mvi m,0
pop b
ret
;
userrtn: ;handle messages
lhld Sysvec_ ;any routine supplied?
mov a,h
ora l
jz myway
xchg
lxi h,4
dad sp
mov c,m
inx h
mov b,m
push b
lhld flterr_
push h
xchg
call apchl
pop h
pop h ;clean up arguments
ret
apchl:
pchl
;
myway:
call pmsg
db 'Floating point ',0
lda flterr_
cpi 1
jnz notund
call pmsg
db 'underflow',0
jmp mycontinue
notund: cpi 2
jnz notovr
call pmsg
db 'overflow',0
jmp mycontinue
notovr: call pmsg
db 'divide by zero',0
mycontinue:
call pmsg
db ' at location 0x',0
lxi h,5
dad sp
mov a,m
push h
push psw
call phex2
pop psw
call phex
pop h
dcx h
mov a,m
push psw
call phex2
pop psw
call phex
lxi h,10 ;newline
push h
call puterr_
pop h
ret
;
phex2:
rar
rar
rar
rar
phex:
ani 15
adi '0'
cpi '9'+1
jc hexok
adi 'A'-'0'-10
hexok:
mov l,a
mvi h,0
push h
call puterr_
pop h
ret
;
pmsg:
pop b ;get address of message
pmloop:
ldax b
inx b
ora a
jz pmsgdone
mov l,a
mvi h,0
push h
call puterr_
pop h
jmp pmloop
pmsgdone:
push b
ret
;
public .xtod
.xtod:
push b
lhld flprm
mvi m,0 ;clear sign
inx h
mvi m,3 ;set up exponent
lxi d,4
dad d
mov e,l
mov d,h
mvi b,5
xra a
xtodclr:
inx h
mov m,a
dcr b
jnz xtodclr
;
mvi b,4
lxi h,lnprm
lda lnprm+3
ora a
jp lngok
;
lngloop:
mvi a,0
sbb m
stax d
inx h
dcx d
dcr b
jnz lngloop
dcx d ;back up to sign field
mvi a,080H ;mark as negative
stax d
jmp normalize
;
lngok:
mov a,m
stax d
inx h
dcx d
dcr b
jnz lngok
jmp normalize
;
public .dtox
.dtox:
push b
lxi h,0
shld lnprm
shld lnprm+2
lxi d,lnprm
;
lhld flprm
mov c,m ;get sign
inx h
mov a,m ;get exponent
ora a
jz goodexit ; |x| < 1.0 so return zero
jm goodexit
;
cpi 5 ;check for too big
jnc ltoobig
;
mov b,a ;save byte count
inx h ;skip overflow byte
add l
mov l,a
jnc lxx
inr h
lxx:
mov a,m
stax d
inx d
dcx h
dcr b
jnz lxx
;
mov a,c ;now check sign
ora a
jp goodexit
mvi b,4
lxi h,lnprm
d2xneg:
mvi a,0
sbb m
mov m,a
inx h
dcr b
jnz d2xneg
jmp goodexit
;
ltoobig:
xchg
mov a,c
ora a
jm bigneg
mvi m,07fH
inx h
mvi m,0ffH
inx h
mvi m,0ffH
inx h
mvi m,0ffH
jmp oflow
bigneg:
mvi m,080H
inx h
mvi m,0
inx h
mvi m,0
inx h
mvi m,0
jmp oflow
;
;
public .dtou
.dtou:
push b
mvi c,0 ;flag as dtou
jmp ifix
;
public .dtoi
.dtoi:
push b
mvi c,1 ;flag as dtoi
ifix:
lhld flprm
mov b,m ;get sign
inx h
mov a,m ;get exponent
ora a
jz zeroint
jp nonzero
zeroint:
lxi h,0 ; |x| < 1.0 so return zero
jmp goodexit
;
nonzero:
cpi 3 ;check for too big
jnc toobig
;
inx h ;skip overflow byte
add l
mov l,a
jnc xx
inr h
xx: mov e,m
dcx h
mov d,m
xchg
mov a,c
ora a
jz goodexit
mov a,b
ora a
jp goodexit
mov a,h
cma
mov h,a
mov a,l
cma
mov l,a
inx h
jmp goodexit
;
toobig:
mov a,c
ora a
jnz bigsigned
lxi h,0ffffH ;return largest unsigned #
jmp oflow
;
bigsigned:
mov a,b
ora a
jm negover
lxi h,7fffH ;return largest positive #
jmp oflow
;
negover:
lxi h,8000H ;return largest negative #
oflow:
mvi a,2
sta flterr_
pop b
ret
;
public fabs_
fabs_:
lhld flprm
mvi m,0 ;force to positive sign
ret
;
public .dml10
.dml10:
push b
lhld flprm
inx h
inr m ;adjust exponent
lxi d,9
dad d
xra a
mvi b,8
ml10lp:
push b
mov e,m
xchg
mvi h,0
dad h ;num*2
mov b,h
mov c,l ;save
dad h ;num*4
dad h ;num*8
dad b ;num*10
xchg
add e
inx h
mov m,a
mov a,d
aci 0
dcx h
dcx h
pop b
dcr b
jnz ml10lp
inx h
mov m,a ;save last byte of result
ora a
jz normalize
dcx h
dcx h ;back up to exponent
mov a,m ;check to be sure no overflow
ora a
jm m10ok
cpi 64
jnc overflow
m10ok:
pop b
ret
end