// // 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 sane:saveZP() return sane:restoreZP(sane:op2FP(FFEXT|FOD2B, ext, @decrec)) 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 decform[t_decformat] byte decrec[t_decrecord] numdigits = intdigits + fracdigits decform:style = format & $01 decform:digits = decform:style ?? fracdigits :: numdigits sane:saveZP() sane:restoreZP(sane:op3FP(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' while decrec.sig < fracdigits decrec.sig++ decrec.sig[decrec.sig] = '0' loop decrec:exp = -decrec.sig fin dp = decrec.sig + decrec:exp 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 for d = 0 to fracdigits i++ ^(str+i) = decrec.sig.2[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