mirror of
https://github.com/GnoConsortium/gno.git
synced 2025-03-29 08:32:41 +00:00
Added _isnan(), _isinf(), __dtoa(), fcvt(), and ecvt() routines. The
first three are required by stdio.
This commit is contained in:
parent
123ac5dd20
commit
05cc2bfd4c
@ -1,11 +1,18 @@
|
||||
#
|
||||
# $Id: Makefile,v 1.1 1997/02/28 05:12:49 gdr Exp $
|
||||
# gno/lib/libc/stdlib/Makefile
|
||||
#
|
||||
# Devin Reade, 1997
|
||||
#
|
||||
# $Id: Makefile,v 1.2 1997/09/05 06:31:58 gdr Exp $
|
||||
#
|
||||
|
||||
.INCLUDE: ../../../paths.mk
|
||||
.INCLUDE: ../../const.mk
|
||||
|
||||
OBJS = environ.o getopt.o getsubopt.o
|
||||
OBJS = cvt.o environ.o fpspecnum.o getopt.o getsubopt.o
|
||||
|
||||
default: $(OBJS)
|
||||
|
||||
.INCLUDE: ../rules.mk
|
||||
|
||||
fpspecnum.o:: fpspecnum.mac
|
||||
|
136
lib/libc/stdlib/cvt.c
Normal file
136
lib/libc/stdlib/cvt.c
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Floating point conversion routines.
|
||||
* Devin Reade, 1997.
|
||||
*
|
||||
* $Id: cvt.c,v 1.1 1997/09/05 06:31:59 gdr Exp $
|
||||
*
|
||||
* This file is formatted with tab stops every 8 columns.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sane.h>
|
||||
#include <math.h>
|
||||
|
||||
char *
|
||||
ecvt (double number, size_t ndigits, int *decpt, int *sign)
|
||||
{
|
||||
static DecForm convert;
|
||||
static Decimal d;
|
||||
|
||||
convert.style = FLOATDECIMAL;
|
||||
if (ndigits > SIGDIGLEN) {
|
||||
ndigits = SIGDIGLEN;
|
||||
}
|
||||
convert.digits = ndigits;
|
||||
s_num2dec(&convert, number, &d);
|
||||
*decpt = (int)d.sig.length + d.exp;
|
||||
*sign = d.sgn;
|
||||
*(d.sig.text + (int)d.sig.length) = '\0'; /* depends on d.sig.unused */
|
||||
return d.sig.text;
|
||||
}
|
||||
|
||||
char *
|
||||
fcvt (double number, size_t ndigits, int *decpt, int *sign)
|
||||
{
|
||||
static DecForm convert;
|
||||
static Decimal d;
|
||||
|
||||
convert.style = FIXEDDECIMAL;
|
||||
if (ndigits > SIGDIGLEN) {
|
||||
ndigits = SIGDIGLEN;
|
||||
}
|
||||
convert.digits = ndigits;
|
||||
s_num2dec(&convert, number, &d);
|
||||
*decpt = (int)d.sig.length + d.exp;
|
||||
*sign = d.sgn;
|
||||
*(d.sig.text + (int)d.sig.length) = '\0'; /* depends on d.sig.unused */
|
||||
return d.sig.text;
|
||||
}
|
||||
|
||||
/* __dtoa: These are the comments from the BSD implementation of
|
||||
this routine. Whether or not we have achieved compatibility
|
||||
remains to be seen.
|
||||
|
||||
Arguments ndigits, decpt, sign are similar to those
|
||||
of ecvt and fcvt; trailing zeros are suppressed from
|
||||
the returned string. If not null, *rve is set to point
|
||||
to the end of the return value. If d is +-Infinity or NaN,
|
||||
then *decpt is set to 9999.
|
||||
|
||||
mode:
|
||||
0 ==> shortest string that yields d when read in
|
||||
and rounded to nearest.
|
||||
1 ==> like 0, but with Steele & White stopping rule;
|
||||
e.g. with IEEE P754 arithmetic , mode 0 gives
|
||||
1e23 whereas mode 1 gives 9.999999999999999e22.
|
||||
2 ==> max(1,ndigits) significant digits. This gives a
|
||||
return value similar to that of ecvt, except
|
||||
that trailing zeros are suppressed.
|
||||
3 ==> through ndigits past the decimal point. This
|
||||
gives a return value similar to that from fcvt,
|
||||
except that trailing zeros are suppressed, and
|
||||
ndigits can be negative.
|
||||
4-9 should give the same return values as 2-3, i.e.,
|
||||
4 <= mode <= 9 ==> same return as mode
|
||||
2 + (mode & 1). These modes are mainly for
|
||||
debugging; often they run slower but sometimes
|
||||
faster than modes 2-3.
|
||||
4,5,8,9 ==> left-to-right digit generation.
|
||||
6-9 ==> don't try fast floating-point estimate
|
||||
(if applicable).
|
||||
|
||||
Values of mode other than 0-9 are treated as mode 0.
|
||||
|
||||
Sufficient space is allocated to the return value
|
||||
to hold the suppressed trailing zeros.
|
||||
*/
|
||||
|
||||
#undef MAX
|
||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
char *
|
||||
__dtoa (double number, int mode, int ndigits, int *decpt, int *sign,
|
||||
char **rve)
|
||||
{
|
||||
char *result, *p;
|
||||
|
||||
switch(mode) {
|
||||
case 2:
|
||||
case 4:
|
||||
case 6:
|
||||
case 8:
|
||||
mode0: /* this label doesn't belong here */
|
||||
result = ecvt(number, MAX(1, ndigits), decpt, sign);
|
||||
break;
|
||||
case 3:
|
||||
case 5:
|
||||
case 7:
|
||||
case 9:
|
||||
result = fcvt(number, ndigits, decpt, sign);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
case 1:
|
||||
default:
|
||||
goto mode0; /* TEMP KLUDGE */
|
||||
}
|
||||
|
||||
/* truncate trailing zeros */
|
||||
p = result;
|
||||
while (*p) p++;
|
||||
p--;
|
||||
while ((p > result) && (*p == '0')) {
|
||||
*p-- = '\0';
|
||||
}
|
||||
if (rve != NULL) {
|
||||
*rve = p + 1;
|
||||
}
|
||||
|
||||
/* set decimal point for NaNs and Infinities */
|
||||
if (isnan(number) || isinf(number)) {
|
||||
*decpt = 9999;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
107
lib/libc/stdlib/fpspecnum.asm
Normal file
107
lib/libc/stdlib/fpspecnum.asm
Normal file
@ -0,0 +1,107 @@
|
||||
*
|
||||
* Test an extended to see whether it is NaN or INF
|
||||
*
|
||||
* $Id: fpspecnum.asm,v 1.1 1997/09/05 06:31:59 gdr Exp $
|
||||
*
|
||||
* Soenke Behrens, August 1997
|
||||
*
|
||||
case on
|
||||
mcopy fpspecnum.mac
|
||||
|
||||
*
|
||||
* Dummy function to take care of fpspecnum.root, which
|
||||
* can then be discarded.
|
||||
*
|
||||
|
||||
dummy start
|
||||
copy :lib:ainclude:e16.sane ; Apple-supplied SANE EQUs
|
||||
end
|
||||
|
||||
****************************************************************
|
||||
*
|
||||
* int _isnan (extended x);
|
||||
*
|
||||
* Check whether x is NaN, if so, return 1, otherwise, return 0.
|
||||
*
|
||||
****************************************************************
|
||||
*
|
||||
|
||||
_isnan start libc_stdlib
|
||||
result equ 1
|
||||
space equ result+2
|
||||
|
||||
csub (10:x),space
|
||||
|
||||
short m clear the specific NaN code
|
||||
stz x+6
|
||||
long m
|
||||
|
||||
lda x and do the compare
|
||||
cmp nan_x
|
||||
bne diff
|
||||
lda x+2
|
||||
cmp nan_x+2
|
||||
bne diff
|
||||
lda x+4
|
||||
cmp nan_x+4
|
||||
bne diff
|
||||
lda x+6
|
||||
cmp nan_x+6
|
||||
bne diff
|
||||
lda x+8
|
||||
cmp nan_x+8
|
||||
bne diff
|
||||
lda #1
|
||||
sta result
|
||||
bra bye
|
||||
diff stz result
|
||||
|
||||
bye ret (2:result)
|
||||
|
||||
nan_x dc h'0000000000000040FF7F' ; Hex encoding of a NaN
|
||||
end
|
||||
|
||||
****************************************************************
|
||||
*
|
||||
* int _isinf (extended x);
|
||||
*
|
||||
* Check whether x is INF, if so, return 1, otherwise, return 0.
|
||||
*
|
||||
****************************************************************
|
||||
*
|
||||
|
||||
_isinf start libc_stdlib
|
||||
result equ 1
|
||||
space equ result+2
|
||||
|
||||
csub (10:x),space
|
||||
short m
|
||||
lda x+9 get rid of sign bit
|
||||
and #%01111111
|
||||
sta x+9
|
||||
long m
|
||||
|
||||
lda x and do the compare
|
||||
cmp inf_x
|
||||
bne diff
|
||||
lda x+2
|
||||
cmp inf_x+2
|
||||
bne diff
|
||||
lda x+4
|
||||
cmp inf_x+4
|
||||
bne diff
|
||||
lda x+6
|
||||
cmp inf_x+6
|
||||
bne diff
|
||||
lda x+8
|
||||
cmp inf_x+8
|
||||
bne diff
|
||||
lda #1
|
||||
sta result
|
||||
bra bye
|
||||
diff stz result
|
||||
|
||||
bye ret (2:result)
|
||||
|
||||
inf_x dc h'0000000000000000FF7F' ; Hex encoding of +INF
|
||||
end
|
133
lib/libc/stdlib/fpspecnum.mac
Normal file
133
lib/libc/stdlib/fpspecnum.mac
Normal file
@ -0,0 +1,133 @@
|
||||
macro
|
||||
&l csub &parms,&work
|
||||
&l anop
|
||||
aif c:&work,.a
|
||||
lclc &work
|
||||
&work setc 0
|
||||
.a
|
||||
gbla &totallen
|
||||
gbla &worklen
|
||||
&worklen seta &work
|
||||
&totallen seta 0
|
||||
aif c:&parms=0,.e
|
||||
lclc &len
|
||||
lclc &p
|
||||
lcla &i
|
||||
&i seta 1
|
||||
.b
|
||||
&p setc &parms(&i)
|
||||
&len amid &p,2,1
|
||||
aif "&len"=":",.c
|
||||
&len amid &p,1,2
|
||||
&p amid &p,4,l:&p-3
|
||||
ago .d
|
||||
.c
|
||||
&len amid &p,1,1
|
||||
&p amid &p,3,l:&p-2
|
||||
.d
|
||||
&p equ &totallen+4+&work
|
||||
&totallen seta &totallen+&len
|
||||
&i seta &i+1
|
||||
aif &i<=c:&parms,^b
|
||||
.e
|
||||
tsc
|
||||
aif &work=0,.f
|
||||
sec
|
||||
sbc #&work
|
||||
tcs
|
||||
.f
|
||||
phd
|
||||
tcd
|
||||
mend
|
||||
macro
|
||||
&l ret &r
|
||||
&l anop
|
||||
lclc &len
|
||||
aif c:&r,.a
|
||||
lclc &r
|
||||
&r setc 0
|
||||
&len setc 0
|
||||
ago .h
|
||||
.a
|
||||
&len amid &r,2,1
|
||||
aif "&len"=":",.b
|
||||
&len amid &r,1,2
|
||||
&r amid &r,4,l:&r-3
|
||||
ago .c
|
||||
.b
|
||||
&len amid &r,1,1
|
||||
&r amid &r,3,l:&r-2
|
||||
.c
|
||||
aif &len<>2,.d
|
||||
ldy &r
|
||||
ago .h
|
||||
.d
|
||||
aif &len<>4,.e
|
||||
ldx &r+2
|
||||
ldy &r
|
||||
ago .h
|
||||
.e
|
||||
aif &len<>10,.g
|
||||
ldy #&r
|
||||
ldx #^&r
|
||||
ago .h
|
||||
.g
|
||||
mnote 'Not a valid return length',16
|
||||
mexit
|
||||
.h
|
||||
aif &totallen=0,.i
|
||||
lda &worklen+2
|
||||
sta &worklen+&totallen+2
|
||||
lda &worklen+1
|
||||
sta &worklen+&totallen+1
|
||||
.i
|
||||
pld
|
||||
tsc
|
||||
clc
|
||||
adc #&worklen+&totallen
|
||||
tcs
|
||||
aif &len=0,.j
|
||||
tya
|
||||
.j
|
||||
rtl
|
||||
mend
|
||||
macro
|
||||
&l long &a,&b
|
||||
lclb &i
|
||||
lclb &m
|
||||
&a amid &a,1,1
|
||||
&m setb ("&a"="M").or.("&a"="m")
|
||||
&i setb ("&a"="I").or.("&a"="i")
|
||||
aif c:&b=0,.a
|
||||
&b amid &b,1,1
|
||||
&m setb ("&b"="M").or.("&b"="m").or.&m
|
||||
&i setb ("&b"="I").or.("&b"="i").or.&i
|
||||
.a
|
||||
&l rep #&m*32+&i*16
|
||||
aif .not.&m,.b
|
||||
longa on
|
||||
.b
|
||||
aif .not.&i,.c
|
||||
longi on
|
||||
.c
|
||||
mend
|
||||
macro
|
||||
&l short &a,&b
|
||||
lclb &i
|
||||
lclb &m
|
||||
&a amid &a,1,1
|
||||
&m setb ("&a"="M").or.("&a"="m")
|
||||
&i setb ("&a"="I").or.("&a"="i")
|
||||
aif c:&b=0,.a
|
||||
&b amid &b,1,1
|
||||
&m setb ("&b"="M").or.("&b"="m").or.&m
|
||||
&i setb ("&b"="I").or.("&b"="i").or.&i
|
||||
.a
|
||||
&l sep #&m*32+&i*16
|
||||
aif .not.&m,.b
|
||||
longa off
|
||||
.b
|
||||
aif .not.&i,.c
|
||||
longi off
|
||||
.c
|
||||
mend
|
Loading…
x
Reference in New Issue
Block a user