diff --git a/src/inc/fpstr.plh b/src/inc/fpstr.plh new file mode 100644 index 0000000..48465ca --- /dev/null +++ b/src/inc/fpstr.plh @@ -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 diff --git a/src/libsrc/fpstr.pla b/src/libsrc/fpstr.pla new file mode 100644 index 0000000..461d6ca --- /dev/null +++ b/src/libsrc/fpstr.pla @@ -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