1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2024-06-28 19:29:43 +00:00

FP <-> string library

This commit is contained in:
David Schmenk 2017-11-19 18:09:54 -08:00
parent f9447602b6
commit 129f2bf601
2 changed files with 249 additions and 0 deletions

10
src/inc/fpstr.plh Normal file
View File

@ -0,0 +1,10 @@
import fpstr
//
// Parse string into decrecord, return SANE conversion output
//
predef str2ext(str, ext)#1
//
// Convert extended FP to string using , return string
//
predef ext2str(ext, str, numdigits, expformat)#1
end

239
src/libsrc/fpstr.pla Normal file
View File

@ -0,0 +1,239 @@
//
// SANE Extended FP to String conversion library
//
include "inc/cmdsys.plh"
include "inc/sane.plh"
//
// Structures for DEC2BIN, BIN2DEC
//
struc t_decrecord
word sgn
word exp
byte sig[29]
end
struc t_decformat
word style
word digits
end
//
// Parse string into decrecord, return SANE conversion output
//
export def str2ext(str, ext)
byte i, s, d
byte decrec[t_decrecord]
word sgnadj, expadj
decrec:sgn = 0
decrec:exp = 0
decrec.sig = 0
s = 1
i = 1
//
// Skip whitespace
//
while ^(str+i) <= ' ' and i <= ^str; i++; loop
//
// Check for sign
//
if ^(str+i) == '-'
decrec:sgn = 1
i++
elsif ^(str+i) == '+'
i++
fin
//
// Skip leading zeros
//
while i <= ^str and ^(str+i) == '0'
i++
loop
//
// Parse number
//
while i <= ^str
d = toupper(^(str+i))
if d >= '0' and d <= '9'
//
// Parse digit
//
decrec.sig[s] = ^(str+i)
decrec:sig++
s++
elsif d == '.'
//
// Parse decimal point
//
i++
while i <= ^str
d = toupper(^(str+i))
if d >= '0' and d <= '9'
decrec.sig[s] = ^(str+i)
decrec.sig++
decrec:exp--
s++
elsif d == 'E'
i--
break
else
i = ^str
fin
i++
loop
elsif d == 'E'
//
// Parse exponent
//
i++
expadj = 0
sgnadj = 1
if ^(str+i) == '-'
sgnadj = -1
i++
elsif ^(str+i) == '+'
i++
fin
while i <= ^str
d = ^(str+i)
i++
if d >= '0' and d <= '9'
expadj = expadj * 10 + (d - '0')
else
i = ^str
fin
loop
decrec:exp = decrec:exp + (sgnadj * expadj)
else
i = ^str
fin
i++
loop
//
// Strip leading zeros from sig
//
while decrec.sig > 1 and decrec.sig.1 == '0'
decrec.sig--
if decrec:exp < 0
decrec:exp--
fin
memcpy(@decrec.sig.1, @decrec.sig.2, decrec.sig)
loop
//
// Check for zero
//
if !decrec.sig
decrec.sig = 1
decrec.sig.1 = '0'
fin
return sane:fpOp2(FFEXT|FOD2B, ext, @decrec)
end
//
// Convert extended FP to string using , return string
//
export def ext2str(ext, str, numdigits, expformat)
byte d, i, sigdigits
word dp, tens
byte decform[t_decformat]
byte decrec[t_decrecord]
decform:style = 0
decform:digits = numdigits
sane:fpOp3(FFEXT|FOB2D, @decrec, ext, @decform)
^(str+1) = decrec.sgn ?? '-' :: ' '
if decrec.sig.1 == 'I'
^(str+2) = 'I'
^(str+3) = 'n'
^(str+4) = 'f'
^str = 4
return str
fin
if decrec.sig.1 == 'N'
^(str+2) = 'N'
^(str+3) = 'a'
^(str+4) = 'N'
^str = 4
return str
fin
if decrec.sig.1 == '0'
decrec:exp = -decrec.sig
fin
dp = decrec.sig + decrec:exp
sigdigits = decrec.sig
if decrec:exp < 0
//
// Strip off trailing fractional zeros
//
while sigdigits > dp and decrec.sig[sigdigits] == '0'
sigdigits--
loop
fin
if (decrec:exp + (decrec.sig - sigdigits)) < -numdigits or decrec:exp > 0 or expformat
//
// Convert to exponential format
//
^(str+2) = decrec.sig.1
^(str+3) = '.'
i = 3
for d = 2 to decrec.sig
i++
^(str+i) = decrec.sig[d]
next
//
// Copy over all significant digits
//
if ^(str+i) == '.'; i--; fin
i++
^(str+i) = 'E'
i++
dp--
if dp < 0
^(str+i) = '-'
dp = -dp
else
^(str+i) = '+'
if dp == 0
i++
^(str+i) = '0'
fin
fin
//
// Pretty output the exponent (preceding zero for values less than 10)
d = 0
tens = 10000
while dp
d = d or tens <= 10
if dp >= tens or d
d = 1
i++
^(str+i) = (dp / tens) + '0'
fin
dp = dp % tens
tens = tens / 10
if !tens; break; fin
loop
else
//
// Convert as floating point
//
i = 1
if dp <= 0
*(str+2) = '0'|('.'<<8)
i = 3
while dp < 0
dp++
i++
^(str+i) = '0'
loop
fin
for d = 1 to sigdigits
i++
^(str+i) = decrec.sig[d]
if d == dp
i++
^(str+i) = '.'
fin
next
if ^(str+i) == '.'; i--; fin
fin
^str = i
return str
end