1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2025-01-09 13:33:26 +00:00

Much better floating point string conversion

This commit is contained in:
Dave Schmenk 2023-02-23 17:57:11 -08:00
parent 1713c71505
commit 7a3debfd0c
3 changed files with 92 additions and 76 deletions

View File

@ -6,6 +6,7 @@ const FPSTR_FIXED = 1 // Fixed count of fractional digits
const FPSTR_FLOAT = 0 // Floating count of fractional digits
const FPSTR_STRIP = 2 // Strip trailing fractional zeros
const FPSTR_EXP = 4 // Force exponential format
const FPSTR_FLEX = 8 // Flexible switch to EXP format if over/underflow
//
// Parse string into decrecord, return SANE conversion output
//

View File

@ -3,6 +3,7 @@
//
include "inc/cmdsys.plh"
include "inc/sane.plh"
include "inc/fpstr.plh"
//
// Structures for DEC2BIN, BIN2DEC
//
@ -136,14 +137,15 @@ end
// Convert extended FP to string using , return string
//
export def ext2str(ext, str, intdigits, fracdigits, format)
byte d, i, sigdigits, numdigits
word dp, tens
byte d, numdigits
word istr, dp, tens
byte decform[t_decformat]
byte decrec[t_decrecord]
numdigits = intdigits + fracdigits
decform:style = format & $01
numdigits = intdigits + fracdigits
decform:style = format & FPSTR_FIXED
decform:digits = decform:style ?? fracdigits :: numdigits
decrec:exp = 0
sane:saveZP()
sane:restoreZP(sane:op3FP(FFEXT|FOB2D, @decrec, ext, @decform))
^(str+1) = decrec.sgn ?? '-' :: ' '
@ -162,94 +164,109 @@ export def ext2str(ext, str, intdigits, fracdigits, format)
return str
fin
dp = decrec.sig + decrec:exp
if decrec.sig.1 == '0'
//
// Zero with significant fractional digits
//
while decrec.sig <= fracdigits
decrec.sig++
decrec.sig[decrec.sig] = '0'
loop
decrec:exp = 0
dp = 1
fin
sigdigits = decrec.sig
if decrec:exp < 0 and format & $02
//
// Strip off trailing fractional zeros
//
while sigdigits > dp and decrec.sig[sigdigits] == '0'
sigdigits--
decrec:exp++
loop
fin
if -decrec:exp > numdigits or sigdigits + decrec:exp >= (decform:style ?? intdigits :: numdigits) or format & $04
//
// Convert to exponential format
//
^(str+2) = decrec.sig.1
^(str+3) = '.'
i = 3
fracdigits = fracdigits - 5 // Replace last four fracdigits with exponent notation
for d = 0 to fracdigits
i++
^(str+i) = decrec.sig.2[d]
next
if format & FPSTR_EXP
if format & FPSTR_STRIP
//
// Strip off trailing fractional zeros
//
while decrec.sig > 1 and decrec.sig[decrec.sig] == '0'
decrec.sig--
decrec:exp++
loop
fin
//
// Copy over all significant digits
//
if ^(str+i) == '.'; i--; fin
i++
^(str+i) = 'E'
i++
^(str+2) = decrec.sig.1
^(str+3) = '.'
istr = str + 3
for d = 2 to decrec.sig
istr++
^istr = decrec.sig[d]
next
if ^istr == '.'; istr--; fin
//
// Print exponent as 4 digits with leading zeros
//
istr++
^istr = 'E'
istr++
dp--
if dp < 0
^(str+i) = '-'
^istr = '-'
dp = -dp
else
^(str+i) = '+'
fin
//
// Pretty output the exponent (preceding zero for values less than 10)
//
if dp < 100
tens = 10
else
tens = 10000
while !(dp / tens)
tens = tens / 10
loop
^istr = '+'
fin
tens = 1000
while tens
i++
^(str+i) = (dp / tens) + '0'
istr++
^istr = (dp / tens) + '0'
dp = dp % tens
tens = tens / 10
loop
else
if format & FPSTR_STRIP and decrec:exp < 0
//
// Strip off trailing fractional zeros
//
while decrec.sig > dp and decrec.sig[decrec.sig] == '0'
decrec.sig--
decrec:exp++
loop
fin
if decrec:sig == 1 | '0'<<8
//
// Case of zero or underflow
//
if decrec:exp == 0
//
// Zero
//
if format & FPSTR_FIXED
//
// Add trailing fractional zeros
//
dp = 1 - fracdigits
fin
elsif format & FPSTR_FLEX
//
// Underflow
//
dp = -fracdigits
fin
fin
if format & FPSTR_FLEX and (dp <= -fracdigits or dp >= (format & FPSTR_FIXED ?? intdigits :: numdigits))
//
// Print as exponent if over/underflow fixed digits
//
if numdigits < 8; numdigits = 8; fin
return ext2str(ext, str, 1, numdigits - 8, FPSTR_EXP | (format & FPSTR_STRIP))
fin
//
// Convert as floating point
//
i = 1
if dp <= 0
*(str+2) = '0'|('.'<<8)
i = 3
istr = str + 3
while dp < 0
dp++
i++
^(str+i) = '0'
istr++
^istr = '0'
loop
else
istr = str + 1
fin
for d = 1 to sigdigits
i++
^(str+i) = decrec.sig[d]
for d = 1 to decrec.sig
istr++
^istr = decrec.sig[d]
if d == dp
i++
^(str+i) = '.'
istr++
^istr = '.'
fin
next
if ^(str+i) == '.'; i--; fin
if ^istr == '.'; istr--; fin
fin
^str = i
^str = istr - str
return str
end

View File

@ -37,7 +37,7 @@ byte inputStr[32] = ""
// Display format state
//
byte displayFix = 6
byte displayInt = displayWidth - 7 // - displayFix - 1
byte displayInt = displayWidth - 8
//
// Store/load memory
//
@ -81,8 +81,6 @@ byte[t_keypad] = '0', 3, 16, "[0]"
word = @digitKey
byte[t_keypad] = '.', 7, 16, "[.]"
word = @pointKey
byte[t_keypad] = 'E', 3, 16, "[0]"
word = @digitKey
byte[t_keypad] = 'X', 11, 16, "[X]"
word = @dropKey
byte[t_keypad] = '+', 15, 16, "[+]"
@ -109,7 +107,7 @@ byte[t_keypad] = '^', 30, 14, "[X(^)Y]"
word = @elemsKey
byte[t_keypad] = 'L', 30, 16, "[(L)G2]"
word = @elemsKey
byte[t_keypad] = 'E', 30, 18, "[(P)^X]"
byte[t_keypad] = 'E', 30, 18, "[(E)^X]"
word = @elemsKey
byte[t_keypad] = 'N', 30, 20, "[L(N)X]"
word = @elemsKey
@ -154,7 +152,7 @@ def showStack#0
byte strFP[displayWidth+1]
for s = 0 to 3
fpu:storStr(@strFP, displayInt, displayFix, FPSTR_FIXED, s)
fpu:storStr(@strFP, displayInt, displayFix, FPSTR_FIXED|FPSTR_FLEX, s)
conio:gotoxy(4, 5 - s)
repc(displayWidth - strFP - 1, ' ')
puts(@strFP)
@ -165,7 +163,7 @@ def showMem#0
byte strFP[displayWidth+1]
for m = 0 to 9
ext2str(@memory[m*t_fpureg], @strFP, displayInt, displayFix, FPSTR_FIXED)
ext2str(@memory[m*t_fpureg], @strFP, displayInt, displayFix, FPSTR_FIXED|FPSTR_FLEX)
conio:gotoxy(23, 2 + m)
repc(displayWidth - strFP - 1, ' ')
puts(@strFP)
@ -254,7 +252,7 @@ def delKey(pkey)#0
showInput
end
def dropKey(pkey)#0
fpu:pullStr(@inputStr, displayInt, displayFix, FPSTR_STRIP|FPSTR_FLOAT)
fpu:pullStr(@inputStr, displayInt, displayFix, FPSTR_STRIP|FPSTR_FLOAT|FPSTR_FLEX)
if inputStr.1 == ' '
inputStr--
memcpy(@inputStr.1, @inputStr.2, inputStr)
@ -263,7 +261,7 @@ def dropKey(pkey)#0
showStack
end
def copyKey(pkey)#0
fpu:storStr(@inputStr, displayInt, displayFix, FPSTR_STRIP|FPSTR_FLOAT, X_REG)
fpu:storStr(@inputStr, displayInt, displayFix, FPSTR_STRIP|FPSTR_FLOAT|FPSTR_FLEX, X_REG)
if inputStr.1 == ' '
inputStr--
memcpy(@inputStr.1, @inputStr.2, inputStr)
@ -452,7 +450,7 @@ initInput
showStack
showMem
showInput
showStatus("Version 0.6")
showStatus("Version 0.7")
inputKey
conio:gotoxy(0, 22)
done