mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2829 lines
40 KiB
2829 lines
40 KiB
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
|
|
|