Added _isnan(), _isinf(), __dtoa(), fcvt(), and ecvt() routines. The

first three are required by stdio.
This commit is contained in:
gdr 1997-09-05 06:31:59 +00:00
parent 123ac5dd20
commit 05cc2bfd4c
4 changed files with 385 additions and 2 deletions

View File

@ -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
View 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;
}

View 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

View 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