exp(x)
ZXNet echo conference «code.zx»
From Stanislav Yudin → To All 7 December 2002
Hello everyone!
Hey, who's the smartest here? :) It is necessary to implement it in assembler Z80 subject
function. Or maybe someone has a ready-made solution?
If possible, you can complicate the task by ensuring that the program does not
used RAM and worked only in ROM.
Stanislav
From Kirill Frolov → To Stanislav Yudin 8 December 2002
Press RESET immediately, Stanislav!
07 Dec 02 22:55, Stanislav Yudin wrote to All:
SY> Hey, who's the smartest here? :) Need to be implemented in assembly language Z80
SY> subject function. Or maybe someone has a ready-made solution?
SY> If possible, you can complicate the task by ensuring that
SY> the program did not use RAM and worked only in ROM.
=== Cut ===
; These functions allow the mantissa and exponent of floating
; numbers to be manipulated separately.
psect text
global _frexp, _ldexp
; double frexp(value, eptr)
; double value;
; int * eptr;
_frexp:
push ix
ld ix,0
add ix,sp
ld a,(ix+7) ;get old exponent
ld b,a ;save sign bit
and 80h ;mask it out
add a,64 ;add in bias
ld d,a ;store new exponent back
ld a,b ;now get exponent
and 7Fh ;clea sign bit
sub 64 ;remove bias
ld l,(ix+8) ;get pointer
ld h,(ix+9)
ld(hl),a
inc hl
rla
sbc a,a
ld (hl),a ;store upper byte
ld l,(ix+4) ;now get value to return
ld h,(ix+5)
ld e,(ix+6)
ex de,hl ;already have sign in d
pop ix
ret
_ldexp:
push ix
ld ix,0
add ix,sp
ld a,(ix+8)
and 7Fh ld c,a
ld a,(ix+7)
ld h,a
and 80h
ld b,a
ld a,h
add a,c
and 7Fh
or b
ld h,a
ld l,(ix+6)
ld d,(ix+5)
ld e,(ix+4)
pop ix
ret
=== Cut ===
double
eval_poly(x, d, n)
double x, d[];
int n;
{
int i;
double res;
res = d[i = n];
while(i)
res = x * res + d[--i];
return res;
}
double log(x)
double x;
{
int exp;
static double coeff[] =
{
0.0000000000, /* a0 */
0.9999964239, /* a1 */
-0.4998741238, /* a2 */
0.3317990258, /* a3 */
-0.2407338084, /* a4 */
0.1676540711, /* a5 */
-0.0953293897, /* a6 */
0.0360884937, /* a7 */
-0.0064535442, /* a8 */
};
/* zero or -ve arguments are not defined */
if(x <= 0.0)
return 0.0;
x = frexp(x, &exp) * 2.0 - 1.0;
exp--;
x = eval_poly(x, coeff, sizeof coeff/sizeof coeff[0] - 1);
return x + 0.69314718055995 * exp;
}
double
log10(x)
double x;
{
return log(x) * 0.4342944819;
}
double exp(x)
double x;
{
int exp;
char sign;
static double coeff[] =
{
1.0000000000e+00,
6.9314718056e-01,
2.4022650695e-01,
5.5504108945e-02,
9.6181261779e-03,
1.3333710529e-03,
1.5399104432e-04,
1.5327675257e-05,
1.2485143336e-06,
1.3908092221e-07,
};
if(x == 0.0)
return 1.0;
sign = x < 0.0;
if(sign)
x = -x;
x *= 1.4426950409; /* convert to log2 */
exp = (int)floor(x);
x -= (double)exp;
x = ldexp(eval_poly(x, coeff, sizeof coeff/sizeof coeff[0] - 1), exp);
if(sign)
return 1.0/x;
return x;
}
double pow(x, y)
double x, y;
{
if(y == 0.0)
return 1.0;
if(x < 0.0)
return 0.0;
if(x == 0.0)
return 0.0;
x = exp(log(x) * y);
return x;
}