File indexing completed on 2024-05-12 05:55:12
0001 /* floatconvert.c: radix conversion, based on floatnum. */ 0002 /* 0003 Copyright (C) 2007 - 2009 Wolf Lammen. 0004 0005 This program is free software; you can redistribute it and/or modify 0006 it under the terms of the GNU General Public License as published by 0007 the Free Software Foundation; either version 2 of the License , or 0008 (at your option) any later version. 0009 0010 This program is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 GNU General Public License for more details. 0014 0015 You should have received a copy of the GNU General Public License 0016 along with this program; see the file COPYING. If not, write to: 0017 0018 The Free Software Foundation, Inc. 0019 59 Temple Place, Suite 330 0020 Boston, MA 02111-1307 USA. 0021 0022 0023 You may contact the author by: 0024 e-mail: ookami1 <at> gmx <dot> de 0025 mail: Wolf Lammen 0026 Oertzweg 45 0027 22307 Hamburg 0028 Germany 0029 0030 *************************************************************************/ 0031 0032 #include "floatconvert.h" 0033 #include "floatcommon.h" 0034 #include "floatconst.h" 0035 #include "floatipower.h" 0036 #include <stdlib.h> 0037 0038 typedef struct{ 0039 t_number_desc n; 0040 t_longint l; 0041 floatnum f; 0042 int bitlength; 0043 int trailing0; 0044 int lgbase; 0045 }t_ext_number; 0046 typedef t_ext_number* p_ext_number; 0047 0048 /************************ conversion to/from longint *******************/ 0049 0050 static unsigned 0051 _digitblock( 0052 floatnum f, 0053 int ofs, 0054 int count) 0055 { 0056 unsigned result; 0057 0058 result = 0; 0059 for (; --count >= 0;) 0060 result = 10 * result + float_getdigit(f, ofs++); 0061 return result; 0062 } 0063 0064 Error 0065 _floatnum2longint( 0066 t_longint* longint, 0067 floatnum f) 0068 { 0069 int digits; 0070 int i; 0071 unsigned factor; 0072 0073 longint->length = 0; 0074 digits = float_getexponent(f) + 1; 0075 i = digits % 9; 0076 _longintadd(longint, _digitblock(f, 0, i)); 0077 factor = 1000000000; 0078 while (i < digits) 0079 { 0080 if (_longintmul(longint, factor) 0081 || _longintadd(longint, _digitblock(f, i, 9))) 0082 return IOConversionOverflow; 0083 i += 9; 0084 } 0085 /* extra element for floatlong operations */ 0086 *(longint->value+longint->length) = 0; 0087 return Success; 0088 } 0089 0090 static void 0091 _setunsigned( 0092 floatnum f, 0093 unsigned value) 0094 { 0095 float_setinteger(f, value); 0096 if ((int)value < 0) 0097 float_add(f, f, &cUnsignedBound, EXACT); 0098 } 0099 0100 void 0101 _longint2floatnum( 0102 floatnum f, 0103 t_longint* longint) 0104 { 0105 floatstruct tmp; 0106 int idx; 0107 0108 float_setzero(f); 0109 if(longint->length == 0) 0110 return; 0111 float_create(&tmp); 0112 idx = longint->length - 1; 0113 for (; idx >= 0; --idx) 0114 { 0115 _setunsigned(&tmp, longint->value[idx]); 0116 float_mul(f, f, &cUnsignedBound, EXACT); 0117 float_add(f, f, &tmp, EXACT); 0118 } 0119 float_free(&tmp); 0120 } 0121 0122 /************************** io routines **************************/ 0123 0124 static int 0125 _max( 0126 int a, 0127 int b) 0128 { 0129 return a > b? a : b; 0130 } 0131 0132 static char 0133 _validmode( 0134 char mode) 0135 { 0136 return mode >= IO_MODE_SCIENTIFIC && mode <= IO_MODE_COMPLEMENT; 0137 } 0138 0139 static int 0140 lgbase( 0141 signed char base) 0142 { 0143 switch(base) 0144 { 0145 case 2: 0146 return 1; 0147 case 8: 0148 return 3; 0149 case 16: 0150 return 4; 0151 } 0152 return 0; 0153 } 0154 0155 static char 0156 _getfnintdigit( 0157 int ofs, 0158 p_seq_desc n) 0159 { 0160 if (ofs <= n->digits) 0161 return float_getdigit((floatnum)(n->param), ofs); 0162 return 0; 0163 } 0164 0165 static char 0166 _getfnfracdigit( 0167 int ofs, 0168 p_seq_desc n) 0169 { 0170 floatnum x; 0171 int exp; 0172 0173 x = (floatnum)(n->param); 0174 exp = float_getexponent(x); 0175 if (ofs >= 0) 0176 return float_getdigit(x, ofs + exp + 1); 0177 return 0; 0178 } 0179 0180 static void 0181 _setfndesc( 0182 p_number_desc n, 0183 floatnum x) 0184 { 0185 int digits; 0186 0187 n->intpart.seq.base = 10; 0188 digits = _max(float_getexponent(x) + 1, 0); 0189 n->intpart.seq.digits = digits; 0190 n->intpart.seq.trailing0 = _max(digits - float_getlength(x), 0); 0191 n->intpart.seq.param = x; 0192 n->intpart.getdigit = _getfnintdigit; 0193 n->fracpart.seq.base = 10; 0194 n->fracpart.seq.leadingSignDigits = _max(-float_getexponent(x) - 1, 0); 0195 n->fracpart.seq.digits = float_getlength(x) - digits 0196 + n->fracpart.seq.leadingSignDigits; 0197 n->fracpart.seq.param = x; 0198 n->fracpart.getdigit = _getfnfracdigit; 0199 } 0200 0201 static Error 0202 _pack2longint( 0203 t_longint* l, 0204 p_ext_seq_desc n) 0205 { 0206 int bitofs; 0207 int ofs; 0208 int logbase; 0209 0210 logbase = lgbase(n->seq.base); 0211 ofs = n->seq.leadingSignDigits; 0212 if (_significantdigits(&n->seq) == 0) 0213 /* can be true in complement case: 0xFF00 */ 0214 --ofs; 0215 bitofs = (n->seq.digits - ofs) * logbase; 0216 if (!_longintsetsize(l, bitofs)) 0217 return IOBufferOverflow; 0218 for (; bitofs > 0;) 0219 { 0220 bitofs -= logbase; 0221 _orsubstr(l->value, bitofs, n->getdigit(ofs++, &n->seq)); 0222 } 0223 return Success; 0224 } 0225 0226 static char 0227 _getlongintdigit( 0228 int ofs, 0229 p_seq_desc n) 0230 { 0231 if (ofs < 0 || ofs >= n->digits) 0232 return 0; 0233 return _bitsubstr(((t_longint*)(n->param))->value, 0234 (n->digits - ofs - 1) * lgbase(n->base)) 0235 & (n->base - 1); 0236 } 0237 0238 static char 0239 _getlongintofsdigit( 0240 int ofs, 0241 p_seq_desc n) 0242 { 0243 p_number_desc nmb; 0244 int digits; 0245 0246 nmb = (p_number_desc)(n->param); 0247 digits = n->digits; 0248 if (ofs < 0 || ofs >= digits) 0249 return 0; 0250 digits += nmb->fracpart.seq.digits; 0251 return _bitsubstr(((t_longint*)(nmb->fracpart.seq.param))->value, 0252 (digits - ofs - 1) * lgbase(n->base)) 0253 & (n->base - 1); 0254 } 0255 0256 static void 0257 _setlongintdesc( 0258 p_ext_seq_desc n, 0259 t_longint* l, 0260 signed char base) 0261 { 0262 int lg; 0263 0264 n->seq.base = base; 0265 lg = lgbase(base); 0266 n->seq.digits = (_bitlength(l) + lg - 1) / lg; 0267 n->seq.leadingSignDigits = 0; 0268 n->seq.trailing0 = _lastnonzerobit(l) / lg; 0269 n->seq.param = l; 0270 n->getdigit = _getlongintdigit; 0271 } 0272 0273 static Error 0274 _packdec2int( 0275 floatnum x, 0276 p_ext_seq_desc n) 0277 { 0278 int ofs; 0279 int exp; 0280 int bufsz; 0281 int i; 0282 char buf[DECPRECISION]; 0283 0284 float_setnan(x); 0285 ofs = n->seq.leadingSignDigits; 0286 exp = n->seq.trailing0; 0287 bufsz = n->seq.digits - ofs - exp; 0288 if (bufsz > DECPRECISION) 0289 return IOBufferOverflow; 0290 if (bufsz == 0) 0291 float_setzero(x); 0292 else 0293 for (i = -1; ++i < bufsz;) 0294 buf[i] = n->getdigit(ofs++, &n->seq) + '0'; 0295 float_setsignificand(x, NULL, buf, bufsz); 0296 float_setexponent(x, exp + bufsz - 1); 0297 return Success; 0298 } 0299 0300 static Error 0301 _packbin2int( 0302 floatnum x, 0303 p_ext_seq_desc n) 0304 { 0305 t_longint l; 0306 Error result; 0307 0308 float_setnan(x); 0309 if ((result = _pack2longint(&l, n)) != Success) 0310 return result; 0311 _longint2floatnum(x, &l); 0312 return Success; 0313 } 0314 0315 static Error 0316 _pack2int( 0317 floatnum x, 0318 p_ext_seq_desc n) 0319 { 0320 switch(n->seq.base) 0321 { 0322 case IO_BASE_NAN: 0323 float_setnan(x); 0324 break; 0325 case IO_BASE_ZERO: 0326 float_setzero(x); 0327 break; 0328 case 10: 0329 return _packdec2int(x, n); 0330 default: 0331 return _packbin2int(x, n); 0332 } 0333 return Success; 0334 } 0335 0336 static Error 0337 _pack2frac( 0338 floatnum x, 0339 p_ext_seq_desc n, 0340 int digits) 0341 { 0342 floatstruct tmp; 0343 int exp; 0344 Error result; 0345 0346 n->seq.digits -= n->seq.trailing0; 0347 n->seq.trailing0 = 0; 0348 switch(n->seq.base) 0349 { 0350 case IO_BASE_NAN: 0351 float_setnan(x); 0352 break; 0353 case IO_BASE_ZERO: 0354 float_setzero(x); 0355 break; 0356 default: 0357 if ((result = _pack2int(x, n)) != Success) 0358 return result; 0359 float_create(&tmp); 0360 float_setinteger(&tmp, n->seq.base); 0361 _raiseposi(&tmp, &exp, n->seq.digits, digits+2); 0362 float_div(x, x, &tmp, digits + 2); 0363 float_setexponent(x, float_getexponent(x) - exp); 0364 float_free(&tmp); 0365 } 0366 n->seq.digits += n->seq.trailing0; 0367 return Success; 0368 } 0369 0370 Error 0371 pack2floatnum( 0372 floatnum x, 0373 p_number_desc n) 0374 { 0375 floatstruct tmp; 0376 int digits; 0377 int saveerr; 0378 int saverange; 0379 Error result; 0380 signed char base; 0381 0382 if ((result = _pack2int(x, &n->intpart)) != Success) 0383 return result; 0384 if (float_isnan(x)) 0385 return Success; 0386 saveerr = float_geterror(); 0387 saverange = float_setrange(MAXEXP); 0388 float_create(&tmp); 0389 float_move(&tmp, x); 0390 float_setzero(x); 0391 digits = DECPRECISION - float_getexponent(&tmp); 0392 if (digits <= 0 0393 || (result = _pack2frac(x, &n->fracpart, digits)) == Success) 0394 float_add(x, x, &tmp, DECPRECISION); 0395 if (result != Success) 0396 return result; 0397 if ((!float_getlength(x)) == 0) /* no zero, no NaN? */ 0398 { 0399 base = n->prefix.base; 0400 float_setinteger(&tmp, base); 0401 if (n->exp >= 0) 0402 { 0403 _raiseposi_(&tmp, n->exp, DECPRECISION + 2); 0404 float_mul(x, x, &tmp, DECPRECISION + 2); 0405 } 0406 else 0407 { 0408 _raiseposi_(&tmp, -n->exp, DECPRECISION + 2); 0409 float_div(x, x, &tmp, DECPRECISION + 2); 0410 } 0411 } 0412 float_free(&tmp); 0413 float_setsign(x, n->prefix.sign == IO_SIGN_COMPLEMENT? -1 : n->prefix.sign); 0414 float_geterror(); 0415 float_seterror(saveerr); 0416 float_setrange(saverange); 0417 if (!float_isvalidexp(float_getexponent(x))) 0418 float_setnan(x); 0419 return float_isnan(x)? IOExpOverflow : Success; 0420 } 0421 0422 static Error 0423 _outscidec( 0424 p_otokens tokens, 0425 floatnum x, 0426 p_number_desc n, 0427 int scale) 0428 { 0429 float_checkedround(x, scale + 1); 0430 n->exp = float_getexponent(x); 0431 float_setexponent(x, 0); 0432 _setfndesc(n, x); 0433 return desc2str(tokens, n, scale); 0434 } 0435 0436 static int 0437 _checkbounds( 0438 floatnum x, 0439 int digits, 0440 signed char base) 0441 { 0442 if (float_getexponent(x) < 0) 0443 { 0444 float_muli(x, x, base, digits); 0445 return -1; 0446 } 0447 else if (float_asinteger(x) >= base) 0448 { 0449 float_divi(x, x, base, digits); 0450 return 1; 0451 } 0452 return 0; 0453 } 0454 0455 static void 0456 _scale2int( 0457 floatnum x, 0458 int scale, 0459 signed char base) 0460 { 0461 floatstruct pwr; 0462 int pwrexp; 0463 0464 (void)scale; 0465 0466 if (scale != 0) 0467 { 0468 float_create(&pwr); 0469 float_setinteger(&pwr, base); 0470 _raiseposi(&pwr, &pwrexp, scale, DECPRECISION+4); 0471 float_mul(x, x, &pwr, DECPRECISION+4); 0472 float_addexp(x, pwrexp); 0473 float_free(&pwr); 0474 } 0475 float_roundtoint(x, TONEAREST); 0476 } 0477 0478 static Error 0479 _fixp2longint( 0480 p_number_desc n, 0481 t_longint* l, 0482 floatnum x, 0483 int scale) 0484 { 0485 Error result; 0486 _scale2int(x, scale, n->prefix.base); 0487 result = _floatnum2longint(l, x); 0488 if (result != Success) 0489 return result; 0490 _setlongintdesc(&n->fracpart, l, n->prefix.base); 0491 return Success; 0492 } 0493 0494 static int 0495 _extractexp( 0496 floatnum x, 0497 int scale, 0498 signed char base) 0499 { 0500 floatstruct pwr; 0501 floatstruct fbase; 0502 int decprec; 0503 int pwrexp; 0504 int exp; 0505 int logbase; 0506 0507 (void)scale; 0508 0509 logbase = lgbase(base); 0510 decprec = DECPRECISION + 3; 0511 exp = (int)(aprxlog10fn(x) * 3.321928095f); 0512 if (float_getexponent(x) < 0) 0513 exp -= 3; 0514 exp /= logbase; 0515 if (exp != 0) 0516 { 0517 float_create(&fbase); 0518 float_setinteger(&fbase, base); 0519 float_create(&pwr); 0520 float_copy(&pwr, &fbase, EXACT); 0521 _raiseposi(&pwr, &pwrexp, exp < 0? -exp : exp, decprec); 0522 if (float_getexponent(x) < 0) 0523 { 0524 float_addexp(x, pwrexp); 0525 float_mul(x, x, &pwr, decprec); 0526 } 0527 else 0528 { 0529 float_addexp(x, -pwrexp); 0530 float_div(x, x, &pwr, decprec); 0531 } 0532 float_free(&pwr); 0533 float_free(&fbase); 0534 } 0535 exp += _checkbounds(x, decprec, base); 0536 return exp; 0537 } 0538 0539 static void 0540 _setscale( 0541 p_number_desc n, 0542 t_longint* l, 0543 int scale) 0544 { 0545 (void)l; 0546 0547 n->intpart.seq.leadingSignDigits = 0; 0548 n->intpart.seq.trailing0 = n->fracpart.seq.trailing0 - scale; 0549 if (n->intpart.seq.trailing0 < 0) 0550 n->intpart.seq.trailing0 = 0; 0551 n->intpart.seq.base = n->fracpart.seq.base; 0552 n->intpart.seq.digits = n->fracpart.seq.digits - scale; 0553 n->intpart.getdigit = _getlongintofsdigit; 0554 n->intpart.seq.param = n; 0555 0556 n->fracpart.seq.digits = scale; 0557 if (n->fracpart.seq.trailing0 >= scale) 0558 { 0559 n->fracpart.seq.base = IO_BASE_ZERO; 0560 n->fracpart.seq.trailing0 = scale; 0561 } 0562 } 0563 0564 static Error 0565 _outscihex( 0566 p_otokens tokens, 0567 floatnum x, 0568 p_number_desc n, 0569 int scale) 0570 { 0571 t_longint l; 0572 Error result; 0573 0574 n->exp = _extractexp(x, scale, n->prefix.base); 0575 result = _fixp2longint(n, &l, x, scale); 0576 if (result != Success) 0577 return result; 0578 /* rounding in _fixp2longint may have increased the exponent */ 0579 n->exp += n->fracpart.seq.digits - 1 - scale; 0580 _setscale(n, &l, n->fracpart.seq.digits - 1); 0581 return desc2str(tokens, n, scale); 0582 } 0583 0584 static char 0585 _isvalidbase( 0586 signed char base) 0587 { 0588 return base == 10 || lgbase(base) != 0; 0589 } 0590 0591 static Error 0592 _outsci( 0593 p_otokens tokens, 0594 floatnum x, 0595 p_number_desc n, 0596 int scale) 0597 { 0598 if (n->prefix.base == 10) 0599 return _outscidec(tokens, x, n, scale); 0600 return _outscihex(tokens, x, n, scale); 0601 } 0602 0603 static Error 0604 _outfixpdec( 0605 p_otokens tokens, 0606 floatnum x, 0607 p_number_desc n, 0608 int scale) 0609 { 0610 int digits; 0611 0612 digits = float_getexponent(x) + scale + 1; 0613 if (digits <= 0) 0614 /* underflow */ 0615 return IOConversionUnderflow; 0616 if (float_round(x, x, digits, TONEAREST) != TRUE) 0617 /* float_round() can err if the number contains too many digits */ 0618 return float_geterror(); 0619 _setfndesc(n, x); 0620 return desc2str(tokens, n, scale); 0621 } 0622 0623 static Error 0624 _outfixphex( 0625 p_otokens tokens, 0626 floatnum x, 0627 p_number_desc n, 0628 int scale) 0629 { 0630 t_longint l; 0631 Error result; 0632 0633 float_copy(x, x, DECPRECISION+1); 0634 result = _fixp2longint(n, &l, x, scale); 0635 if (result != Success) 0636 return result; 0637 if (l.length == 0) { 0638 result = float_geterror(); 0639 return result != Success ? result : IOConversionUnderflow; 0640 } 0641 _setscale(n, &l, scale); 0642 return desc2str(tokens, n, scale); 0643 } 0644 0645 static Error 0646 _outfixp( 0647 p_otokens tokens, 0648 floatnum x, 0649 p_number_desc n, 0650 int scale) 0651 { 0652 if (n->prefix.base == 10) 0653 return _outfixpdec(tokens, x, n, scale); 0654 return _outfixphex(tokens, x, n, scale); 0655 } 0656 0657 static Error 0658 _outengdec( 0659 p_otokens tokens, 0660 floatnum x, 0661 p_number_desc n, 0662 int scale) 0663 { 0664 int shift; 0665 0666 float_checkedround(x, scale + 1); 0667 n->exp = float_getexponent(x); 0668 if (n->exp < 0) 0669 shift = 2 - (-n->exp-1) % 3; 0670 else 0671 shift = n->exp % 3; 0672 float_setexponent(x, shift); 0673 n->exp -= shift; 0674 _setfndesc(n, x); 0675 return desc2str(tokens, n, scale - shift); 0676 } 0677 0678 static Error 0679 _outeng( 0680 p_otokens tokens, 0681 floatnum x, 0682 p_number_desc n, 0683 int scale) 0684 { 0685 if (n->prefix.base != 10 || scale < 2) 0686 return InvalidParam; 0687 return _outengdec(tokens, x, n, scale); 0688 } 0689 0690 static Error 0691 _outcompl( 0692 p_otokens tokens, 0693 floatnum x, 0694 p_number_desc n, 0695 int scale) 0696 { 0697 (void)scale; 0698 0699 if (!float_isinteger(x)) 0700 return IOInvalidComplement; 0701 if (n->prefix.sign == IO_SIGN_MINUS) 0702 n->prefix.sign = IO_SIGN_COMPLEMENT; 0703 else 0704 n->prefix.sign = IO_SIGN_NONE; 0705 return _outfixphex(tokens, x, n, 0); 0706 } 0707 0708 static void 0709 _emptybuffer( 0710 p_buffer token) 0711 { 0712 if (token->sz > 0) 0713 *(token->buf) = '\0'; 0714 else 0715 token->buf = NULL; 0716 } 0717 0718 static void 0719 _emptytokens( 0720 p_otokens tokens) 0721 { 0722 _emptybuffer(&tokens->intpart); 0723 _emptybuffer(&tokens->fracpart); 0724 tokens->sign = IO_SIGN_NONE; 0725 tokens->base = IO_BASE_NAN; 0726 tokens->exp = 0; 0727 } 0728 0729 Error float_out( 0730 p_otokens tokens, 0731 floatnum x, 0732 int scale, 0733 signed char base, 0734 char outmode) 0735 { 0736 t_number_desc n; 0737 0738 _emptytokens(tokens); 0739 /* do some sanity checks first */ 0740 if (!_validmode(outmode) || scale < 0 || !_isvalidbase(base)) 0741 return InvalidParam; 0742 _clearnumber(&n); 0743 if (float_iszero(x)) 0744 n.prefix.base = IO_BASE_ZERO; 0745 else if (!float_isnan(x)) 0746 n.prefix.base = base; 0747 if (!_isvalidbase(n.prefix.base)) 0748 /* NaN and 0 are handled here */ 0749 return desc2str(tokens, &n, 0); 0750 n.prefix.sign = float_getsign(x); 0751 float_abs(x); 0752 switch (outmode) 0753 { 0754 case IO_MODE_FIXPOINT: 0755 return _outfixp(tokens, x, &n, scale); 0756 case IO_MODE_ENG: 0757 return _outeng(tokens, x, &n, scale); 0758 case IO_MODE_COMPLEMENT: 0759 return _outcompl(tokens, x, &n, 0); 0760 default: 0761 return _outsci(tokens, x, &n, scale); 0762 } 0763 } 0764 0765 Error 0766 float_in( 0767 floatnum x, 0768 p_itokens tokens) 0769 { 0770 t_number_desc n; 0771 Error result; 0772 0773 if ((result = str2desc(&n, tokens)) == Success) 0774 result = pack2floatnum(x, &n); 0775 if (result != Success) 0776 { 0777 _seterror(x, BadLiteral); 0778 float_setnan(x); 0779 } 0780 return result; 0781 }