1 /* floatnum.c: Arbitrary precision floating point numbers, based on bc. */
2 /*
3 Copyright (C) 2007, 2008 Wolf Lammen.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License , or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING. If not, write to:
17
18 The Free Software Foundation, Inc.
19 59 Temple Place, Suite 330
20 Boston, MA 02111-1307 USA.
21
22
23 You may contact the author by:
24 e-mail: ookami1 <at> gmx <dot> de
25 mail: Wolf Lammen
26 Oertzweg 45
27 22307 Hamburg
28 Germany
29
30 *************************************************************************/
31
32 /* a floating point engine based on bc's decimal
33 fix point arithmetic. The speed is not overwhelming,
34 but sufficient for calculators with limited demands.
35 As bc's number.c is a portable engine, this should be
36 portable as well.
37 */
38
39 #include "floatnum.h"
40 #include "floatlong.h"
41 #include <stdio.h>
42 #include <string.h>
43
44 #define NOSPECIALVALUE 1
45
46 int maxdigits = MAXDIGITS;
47
48 Error float_error;
49 int expmax = EXPMAX;
50 int expmin = EXPMIN;
51
52 /* general helper routines */
53
54 static int
_max(int x,int y)55 _max(int x, int y)
56 {
57 return x > y? x : y;
58 }
59
60 static int
_min(int x,int y)61 _min(int x, int y)
62 {
63 return x < y? x : y;
64 }
65
66 /* the return value points to the first character different
67 from accept. */
68 const char*
_memskip(const char * buf,const char * end,char accept)69 _memskip(
70 const char* buf,
71 const char* end,
72 char accept)
73 {
74 for(--buf; ++buf != end && *buf == accept;);
75 return buf;
76 }
77
78 /* scans a value in a bc-num (or part of it) for the first
79 occurence of a digit *different* from <digit>. The scan
80 is limited to <count> bytes. Returns the offset of the
81 matching byte, or <count>, if none was found */
82 static int
_scan_digit(const char * p,int count,char digit)83 _scan_digit(
84 const char*p,
85 int count,
86 char digit)
87 {
88 const char* ps;
89
90 ps = p;
91 for (; count-- > 0 && *p == digit; ++p);
92 return p - ps;
93 }
94
95 /* bc_num primitives */
96
97 #define _scaleof(f) (f->significand->n_scale)
98 #define _lenof(f) (f->significand->n_len)
99 #define _valueof(f) (f->significand->n_value)
100 #define _digit(f, offset) (*(_valueof(f) + offset))
101 #define _setscale(f, value) (_scaleof(f) = value)
102
103 /* converts floatnum's sign encodings (+1, -1) to bc_num
104 sign encoding (PLUS, MINUS) */
105 static void
_setsign(floatnum f,signed char value)106 _setsign(
107 floatnum f,
108 signed char value)
109 {
110 f->significand->n_sign = value < 0? MINUS : PLUS;
111 #ifdef FLOATDEBUG
112 f->value[0] = value < 0? '-' : '+';
113 #endif
114 }
115
116 /* modifies a bc_num significand such that the last <count>
117 (existing) digits of its value are not visible
118 to bc_num operations any more.
119 A negative <count> reverts this operation (unhide).
120 pre: <count> <= n_scale*/
121 static void
_hidelast(floatnum f,int count)122 _hidelast(
123 floatnum f,
124 int count)
125 {
126 f->significand->n_scale -= count;
127 }
128
129 /* modifies a bc_num significand such that the first <count>
130 (existing) digits of its value are not visible
131 to bc_num operations any more.
132 A negative <count> reverts this operation (unhide).
133 pre: <count> <= n_scale*/
134 static void
_hidefirst(floatnum f,int count)135 _hidefirst(
136 floatnum f,
137 int count)
138 {
139 f->significand->n_value += count;
140 f->significand->n_scale -= count;
141 }
142
143 /* Usually, significands are normalized, which means they
144 fulfill 1 <= x < 10. This operation moves the decimal
145 point <count> places to the right, effectively multiplying
146 the significand by a power of 10. A negative <count>
147 reverts such an operation.
148 pre: <count> < n_scale */
149 static void
_movepoint(floatnum f,int digits)150 _movepoint(
151 floatnum f,
152 int digits)
153 {
154 f->significand->n_len += digits;
155 f->significand->n_scale -= digits;
156 }
157
158 /* floatstruct primitives */
159
160 /* a quick check for NaN and 0 */
161 static char
_is_special(cfloatnum f)162 _is_special(
163 cfloatnum f)
164 {
165 return f->significand == NULL;
166 }
167
168 /* creates a shallow working copy of <source> in <dest>,
169 using b as a container for the significand.
170 On return, <dest> is equal in value to <source>.
171 <dest> may then be modified freely in the course
172 of an operation, without effecting source,
173 *except* that the digits in *(dest->significand->n_value)
174 have to be retained (or restored).
175 <dest> must *never* be the destination of a
176 float_xxx operation, in particiular, it must not be
177 freed. Neither must b be modified (or freed) in a bc_num
178 operation */
179 static void
_copyfn(floatnum dest,cfloatnum source,bc_num b)180 _copyfn(
181 floatnum dest,
182 cfloatnum source,
183 bc_num b)
184 {
185 *dest = *source;
186 if (!_is_special(source))
187 {
188 *b = *(source->significand);
189 b->n_ptr = 0;
190 dest->significand = b;
191 }
192 }
193
194 /* If you want to execute a bc_num operation to a limited scale,
195 it is a waste of computation time to pass operands
196 with a longer scale, because bc lets the operand's
197 scale override your limit. This function hides superfluous
198 digits from bc, returning the original scale for restoring
199 purposes */
200 static int
_limit_scale(floatnum f,int newscale)201 _limit_scale(
202 floatnum f,
203 int newscale)
204 {
205 int oldscale;
206 oldscale = _scaleof(f);
207 _setscale(f, _min(oldscale, newscale));
208 return oldscale;
209 }
210
211 /*============================ floatnum routines ===================*/
212
213 int
float_getrange()214 float_getrange()
215 {
216 return expmax;
217 }
218
219 int
float_getprecision()220 float_getprecision()
221 {
222 return maxdigits;
223 }
224
225 int
float_setrange(int maxexp)226 float_setrange(
227 int maxexp)
228 {
229 int result;
230
231 result = expmax;
232 expmax = _max(_min(maxexp, MAXEXP), 1);
233 expmin = -expmax - 1;
234 return result;
235 }
236
237 int
float_setprecision(int digits)238 float_setprecision(
239 int digits)
240 {
241 int result;
242
243 result = maxdigits;
244 maxdigits = _max(_min(digits, MAXDIGITS), 1);
245 return result;
246 }
247
248 /* checking the limits on exponents */
249 char
float_isvalidexp(int exp)250 float_isvalidexp(
251 int exp)
252 {
253 return exp >= expmin && exp <= expmax;
254 }
255
256 /* clears the error state as well */
257 Error
float_geterror()258 float_geterror()
259 {
260 Error tmp;
261
262 tmp = float_error;
263 float_error = Success;
264 return tmp;
265 }
266
267 /* the first error blocks all others as it may be the source
268 of a cascade of dependent errors */
269 void
float_seterror(Error code)270 float_seterror(
271 Error code)
272 {
273 if (float_error == Success)
274 float_error = code;
275 }
276
277 void
floatnum_init()278 floatnum_init()
279 {
280 bc_init_numbers();
281 float_geterror();
282 }
283
284 void
float_create(floatnum f)285 float_create(
286 floatnum f)
287 {
288 f->significand = NULL;
289 f->exponent = EXPNAN;
290 #ifdef FLOATDEBUG
291 memcpy(f->value, "NaN", 4);
292 #endif
293 }
294
295 void
float_setnan(floatnum f)296 float_setnan (
297 floatnum f)
298 {
299 bc_free_num(&(f->significand));
300 float_create(f);
301 }
302
303 char
_setnan(floatnum result)304 _setnan(
305 floatnum result)
306 {
307 float_setnan(result);
308 return FALSE;
309 }
310
311 char
_seterror(floatnum result,Error code)312 _seterror(
313 floatnum result,
314 Error code)
315 {
316 float_seterror(code);
317 return _setnan(result);
318 }
319
320 void
float_setzero(floatnum f)321 float_setzero (
322 floatnum f)
323 {
324 bc_free_num(&(f->significand));
325 f->exponent = EXPZERO;
326 #ifdef FLOATDEBUG
327 f->value[0] ='0';
328 f->value[1] = 0;
329 #endif
330 }
331
332 char
_setzero(floatnum result)333 _setzero(
334 floatnum result)
335 {
336 float_setzero(result);
337 return TRUE;
338 }
339
340 char
float_isnan(cfloatnum f)341 float_isnan(
342 cfloatnum f)
343 {
344 return _is_special(f) && f->exponent != EXPZERO;
345 }
346
347 char
float_iszero(cfloatnum f)348 float_iszero(
349 cfloatnum f)
350 {
351 return _is_special(f) && f->exponent == EXPZERO;
352 }
353
354 int
float_getlength(cfloatnum f)355 float_getlength(
356 cfloatnum f)
357 {
358 return _is_special(f)? 0 : _scaleof(f) + 1;
359 }
360
361 char
float_getdigit(cfloatnum f,int ofs)362 float_getdigit(
363 cfloatnum f,
364 int ofs)
365 {
366 if (ofs >= float_getlength(f) || ofs < 0)
367 return 0;
368 return _digit(f, ofs);
369 }
370
371 /* checks whether f is a NaN and sets the float_error
372 variable accordingly. Used in parameter checks when
373 float_xxx calls are executed.
374 FALSE is returned if a NaN is encountered. */
375 char
_checknan(cfloatnum f)376 _checknan(
377 cfloatnum f)
378 {
379 if (!float_isnan(f))
380 return TRUE;
381 float_seterror(NoOperand);
382 return FALSE;
383 }
384
385 /* checks whether <digits> is positive and
386 sets the float_error variable accordingly. Used in
387 parameter checks when float_xxx calls are executed.
388 Some operations accept a special value like EXACT,
389 that has to pass this check, even though its numerical
390 encoding violates the boundaries.
391 If a function does not accept a special value,
392 use NOSPECIALVALUE as a parameter for <specialval>.
393 TRUE is returned if the check is passed.
394 The check for the limit MAXDIGITS is not executed
395 here, because some intermediate operations have to succeed
396 on more than MAXDIGITS digits */
397 static char
_checkdigits(int digits,int specialval)398 _checkdigits(
399 int digits,
400 int specialval)
401 {
402 if ((digits > 0 && digits <= maxdigits) || digits == specialval)
403 return TRUE;
404 float_seterror(InvalidPrecision);
405 return FALSE;
406 }
407
408 /* backward-scans the significand in <f>. Returns the number of
409 digits equal to <digit> beginning with the <scale>+1-th digit of
410 f->significand->n_value. */
411 static int
_bscandigit(cfloatnum f,int scale,char digit)412 _bscandigit(
413 cfloatnum f,
414 int scale,
415 char digit)
416 {
417 char* p;
418 char* ps;
419
420 ps = _valueof(f);
421 for (p = ps + scale + 1; p-- != ps && *p == digit;);
422 return scale - (p - ps);
423 }
424
425 /* scans two significands for the first occurence
426 of a pair of differnt digits. Returns the number
427 of equal digits at the beginning */
428 static int
_scan_equal(floatnum v1,floatnum v2)429 _scan_equal(
430 floatnum v1,
431 floatnum v2)
432 {
433 int count, i;
434 char* p1;
435 char* p2;
436
437 count = _min(_scaleof(v1), _scaleof(v2));
438 p1 = _valueof(v1);
439 p2 = _valueof(v2);
440 i = 0;
441 for (; *(p1++) == *(p2++) && ++i <= count;);
442 return i;
443 }
444
445 /* scans two significands until it finds a digit different
446 from 0 in the first significand, or a digit different from
447 9 in the second operand. The scan is limited by <count>
448 compares and starts with the *second* digit in the
449 significands. Returns the number of found (0,9) pairs. */
450 static int
_scan_09pairs(floatnum f1,floatnum f2,int count)451 _scan_09pairs(
452 floatnum f1,
453 floatnum f2,
454 int count)
455 {
456 char* p;
457 char* p1;
458 char* p2;
459
460 p1 = _valueof(f1) + 1;
461 p2 = _valueof(f2) + 1;
462 p = p1;
463 for (; count-- > 0 && *p1 == 0 && *(p2++) == 9; ++p1);
464 return p1 - p;
465 }
466
467 signed char
float_getsign(cfloatnum f)468 float_getsign(
469 cfloatnum f)
470 {
471 if(_is_special(f))
472 return 0;
473 return f->significand->n_sign == PLUS? 1 : -1;
474 }
475
476 void
float_setsign(floatnum f,signed char s)477 float_setsign(
478 floatnum f,
479 signed char s)
480 {
481 if (s == 1 || s == -1)
482 {
483 if(!_is_special(f))
484 _setsign(f, s);
485 }
486 else if (s != 0)
487 float_setnan(f);
488 }
489
490 char
float_neg(floatnum f)491 float_neg(
492 floatnum f)
493 {
494 float_setsign(f, -float_getsign(f));
495 return _checknan(f);
496 }
497
498 char
float_abs(floatnum f)499 float_abs(
500 floatnum f)
501 {
502 if(float_getsign(f) == -1)
503 float_neg(f);
504 return _checknan(f);
505 }
506
507 signed char
float_cmp(cfloatnum val1,cfloatnum val2)508 float_cmp(
509 cfloatnum val1,
510 cfloatnum val2)
511 {
512 signed char sgn1;
513
514 if (!_checknan(val1) || !_checknan(val2))
515 return UNORDERED;
516 sgn1 = float_getsign(val1);
517 if (float_getsign(val2) != sgn1)
518 {
519 if (sgn1 != 0)
520 return sgn1;
521 return -float_getsign(val2);
522 }
523 if (val1->exponent > val2->exponent)
524 return sgn1;
525 if (val1->exponent < val2->exponent)
526 return -sgn1;
527 if (_is_special(val1))
528 return 0;
529 return (bc_compare(val1->significand, val2->significand));
530 }
531
532 /* normalizing process:
533 hides leading zeros in a significand and corrects the
534 exponent accordingly */
535 static void
_corr_lead_zero(floatnum f)536 _corr_lead_zero(
537 floatnum f)
538 {
539 int count;
540
541 count = _scan_digit(_valueof(f), float_getlength(f), 0);
542 _hidefirst(f, count);
543 f->exponent-=count;
544 }
545
546 /* normalizing process:
547 if the significand is > 10 in magnitude, this function
548 corrects this */
549 static void
_corr_overflow(floatnum f)550 _corr_overflow(
551 floatnum f)
552 {
553 int shift;
554
555 shift = _lenof(f) - 1;
556 _movepoint(f, -shift);
557 f->exponent += shift;
558 }
559
560 /* cuts off trailing zeros at the end of a significand */
561 static void
_corr_trailing_zeros(floatnum f)562 _corr_trailing_zeros(
563 floatnum f)
564 {
565 _hidelast(f, _bscandigit(f, _scaleof(f), 0));
566 }
567
568 static char hexdigits[] = "0123456789ABCDEF";
569
570 int
float_getsignificand(char * buf,int bufsz,cfloatnum f)571 float_getsignificand(
572 char* buf,
573 int bufsz,
574 cfloatnum f)
575 {
576 int idx, lg;
577
578 if (bufsz <= 0)
579 return 0;
580 if (float_isnan(f))
581 {
582 *buf = 'N';
583 return 1;
584 }
585 if (float_iszero(f))
586 {
587 *buf = '0';
588 return 1;
589 }
590 idx = -1;
591 lg = _min(bufsz, float_getlength(f));
592 for(; ++idx < lg;)
593 *(buf++) = hexdigits[(int)float_getdigit(f, idx)];
594 return lg;
595 }
596
597 int
float_getexponent(cfloatnum f)598 float_getexponent(
599 cfloatnum f)
600 {
601 if (_is_special(f))
602 return 0;
603 return f->exponent;
604 }
605
float_getscientific(char * buf,int bufsz,cfloatnum f)606 int float_getscientific(
607 char* buf,
608 int bufsz,
609 cfloatnum f)
610 {
611 char b[42]; /* supports exponents encoded in up to 128 bits */
612 int sgnlg, explg, mlg;
613
614 /* handle special cases */
615 if(float_isnan(f))
616 {
617 if (bufsz < 4)
618 return -1;
619 memcpy(buf, "NaN\0", 4);
620 return 3;
621 }
622 if(float_iszero(f))
623 {
624 if (bufsz < 2)
625 return -1;
626 *buf = '0';
627 *(buf+1) = '\0';
628 return 1;
629 }
630
631 /* set one byte aside for sign? */
632 sgnlg = 0;
633 if(float_getsign(f) < 0)
634 sgnlg = 1;
635
636 /* convert the exponent */
637 sprintf(b, "%d", float_getexponent(f));
638 explg = strlen(b);
639
640 /* 3 extra bytes for dot, exp char and terminating \0 */
641 bufsz -= explg + sgnlg + 3; /* rest is for significand */
642 if (bufsz <= 0)
643 /* buffer too small */
644 return-1;
645
646 if(sgnlg > 0)
647 *(buf++) = '-';
648
649 /* get the digit sequence of the significand, trailing zeros cut off */
650 mlg = float_getsignificand(++buf, bufsz, f) - 1;
651
652 /* move the first digit one byte to the front and fill
653 the gap with a dot */
654 *(buf-1) = *buf;
655 *(buf++) = '.';
656
657 /* append the exponent */
658 *(buf+mlg) = 'e';
659 memcpy(buf+mlg+1, b, explg);
660
661 /* the trailing \0 */
662 *(buf+mlg+explg+1) = '\0';
663 return sgnlg + mlg + explg + 3;
664 }
665
666 #ifdef FLOATDEBUG
_setvalue_(floatnum f)667 void _setvalue_(floatnum f)
668 {
669 f->value[float_getsignificand(f->value+2, sizeof(f->value)-3, f)+2] = 0;
670 f->value[1] = f->value[2];
671 f->value[2] = '.';
672 f->value[0] = float_getsign(f) < 0? '-' : '+';
673 }
674 #endif
675
676 int
float_setsignificand(floatnum f,int * leadingzeros,const char * buf,int bufsz)677 float_setsignificand(
678 floatnum f,
679 int* leadingzeros,
680 const char* buf,
681 int bufsz)
682 {
683 const char* p;
684 const char* dot;
685 const char* last;
686 const char* b;
687 char* bcp;
688 int zeros;
689 int lg;
690 char c;
691
692 float_setnan(f);
693 if (bufsz == NULLTERMINATED)
694 bufsz = strlen(buf);
695
696 /* initialize the output parameters for all
697 early out branches */
698 if (leadingzeros != NULL)
699 *leadingzeros = 0;
700
701 if (bufsz <= 0)
702 return -1;
703
704 dot = memchr(buf, '.', bufsz);
705 /* do not accept more than 1 dots */
706 if (dot != NULL && memchr(dot + 1, '.', bufsz - (dot - buf)) != NULL)
707 return -1;
708
709 last = buf + bufsz; /* points behind the input buffer */
710
711 /* skip all leading zeros */
712 b = _memskip(buf, last, '0');
713
714 /* is the first non-zero character found a dot? */
715 if (b == dot)
716 /* then skip all zeros following the dot */
717 b = _memskip(b+1, last, '0');
718
719 /* the 'leading zeros' */
720 zeros = b - buf - (dot == NULL || dot >= b? 0:1);
721
722 /* only zeros found? */
723 if (b == last)
724 {
725 /* indicate no dot, no leading zeros, because
726 this does not matter in case of zero */
727 if (bufsz > (dot == NULL? 0:1))
728 float_setzero(f);
729 /* do not accept a dot without any zero */
730 return -1;
731 }
732
733 /* size of the rest buffer without leading zeros */
734 bufsz -= b - buf;
735
736 /* does the rest buffer contain a dot? */
737 lg = dot >= b && dot - b < maxdigits? 1 : 0;
738
739 /* points behind the last significant digit */
740 p = b + _min(maxdigits + lg, bufsz);
741
742 /* digits, limited by MAXDIGITS */
743 lg = _min(maxdigits, bufsz - lg);
744
745 /* reduce lg by the number of trailing zeros */
746 for (; *--p == '0'; --lg);
747 if (*(p--) == '.')
748 for (; *(p--) == '0'; --lg);
749
750 /* get a bc_num of sufficient size */
751 f->significand = bc_new_num(1, lg - 1);
752 if (f->significand == NULL)
753 return -1;
754
755 /* exponent is forced to 0 */
756 f->exponent = 0;
757
758 /* copy lg digits into bc_num buffer,
759 scan the rest for invalid characters */
760 bcp = _valueof(f);
761 for(; --bufsz >= 0;)
762 {
763 c = *(b++);
764 if (c != '.') /* ignore a dot */
765 {
766 if (c < '0' || c > '9')
767 {
768 /* invalid character */
769 float_setnan(f);
770 return -1;
771 }
772 if (--lg >= 0)
773 *(bcp++) = c - '0';
774 }
775 }
776
777 if (leadingzeros != NULL)
778 *leadingzeros = zeros;
779 #ifdef FLOATDEBUG
780 _setvalue_(f);
781 #endif
782 return dot == NULL? -1 : dot - buf;
783 }
784
785 void
float_setexponent(floatnum f,int exponent)786 float_setexponent(
787 floatnum f,
788 int exponent)
789 {
790 if (!_is_special(f))
791 {
792 if (!float_isvalidexp(exponent))
793 float_setnan(f);
794 else
795 f->exponent = exponent;
796 }
797 }
798
799 void
float_setscientific(floatnum f,const char * buf,int bufsz)800 float_setscientific(
801 floatnum f,
802 const char* buf,
803 int bufsz)
804 {
805 int exppos;
806 int zeros;
807 int dotpos;
808 unsigned exp, ovfl;
809 signed char expsign, msign;
810 const char* expptr;
811 const char* last;
812 char c;
813
814 float_setnan(f);
815
816 if (bufsz == NULLTERMINATED)
817 bufsz = strlen(buf);
818
819 /* find the offset of the exponent character,
820 or -1, if not found */
821 for(exppos = bufsz; --exppos >= 0;)
822 if ((c = *(buf+exppos)) == 'E' || c == 'e')
823 break;
824
825 /* marks the end of the exponent string */
826 last = buf + bufsz;
827
828 /* pre-set exponent to +0, which is the right value,
829 if there is no exponent. */
830 exp = 0;
831 expsign = 1;
832 ovfl = 0;
833 if (exppos >= 0)
834 {
835 /* points behind the exponent character */
836 expptr = buf + (exppos + 1);
837 if (expptr == last)
838 /* do not accept an exponent char without an integer */
839 return;
840
841 /* get the exponent sign */
842 switch(*expptr)
843 {
844 case '-':
845 expsign = -1; /* and fall through */
846 case '+':
847 ++expptr;
848 }
849 if (expptr == last)
850 /* do not accept a sign without a digit following */
851 return;
852
853 /* encode the sequence of digits into an unsignedeger */
854 for (;expptr != last ;)
855 {
856 if (*expptr < '0' || *expptr > '9')
857 /* invalid char encountered */
858 return;
859 ovfl = 10;
860 if (_longmul(&exp, &ovfl))
861 {
862 ovfl = *(expptr++) - '0';
863 _longadd(&exp, &ovfl);
864 }
865 if (ovfl != 0 || exp > EXPMAX+1)
866 {
867 /* do not return immediately, because the
868 significand can be zero */
869 ovfl = 1;
870 break;
871 }
872 }
873 /* move the last pointer to the exponent char.*/
874 last = buf + exppos;
875 }
876 /* last points behind the significand part.
877 exp is at most -EXPMIN */
878
879 /* get the sign of the significand */
880 msign = 1;
881 if (buf != last)
882 switch(*buf)
883 {
884 case '-':
885 msign = -1; /* fall through */
886 case '+':
887 ++buf;
888 }
889
890 /* let setsignificand convert the sequence of digits
891 into a significand. If a dot is found, its position
892 is given in dotpos, -1 otherwise.
893 zeros are the count of leading '0' digits before
894 the first non_zero digit. */
895 dotpos = float_setsignificand(f, &zeros, buf, last-buf);
896 if (_is_special(f))
897 /* setsignificand either found a zero or encountered
898 invalid characters */
899 return;
900
901 /* if we did not find a dot, we assume an integer,
902 and put the dot after last digit */
903 if (dotpos == -1)
904 dotpos = last - buf;
905
906 /* leading zeros shift the dot to the left.
907 dotpos is now the exponent that results
908 from the position of the dot in the significand. */
909 dotpos -= zeros+1;
910
911 /* combine the dot position with the explicit exponent */
912 if (ovfl != 0 || !_checkadd(&dotpos, expsign * (int)exp))
913 /* exponent overflow */
914 float_setnan(f);
915
916 float_setexponent(f, dotpos);
917 float_setsign(f, msign);
918 }
919
920 /* normalizes a significand such that 1 <= x < 10.
921 If the exponent overflows during this operation
922 this is notified. */
923 static char
_normalize(floatnum f)924 _normalize(
925 floatnum f)
926 {
927 _corr_lead_zero(f);
928 if (f->significand != NULL && _lenof(f) > 1)
929 _corr_overflow(f);
930 if (f->significand != NULL)
931 _corr_trailing_zeros(f);
932 if (f->significand != NULL && !float_isvalidexp(f->exponent))
933 {
934 float_seterror(Underflow);
935 if (f->exponent > 0)
936 float_seterror(Overflow);
937 float_setnan(f);
938 }
939 #ifdef FLOATDEBUG
940 if (f->significand != NULL)
941 _setvalue_(f);
942 #endif
943 return f->significand != NULL;
944 }
945
946 void
float_setinteger(floatnum dest,int value)947 float_setinteger(floatnum dest, int value)
948 {
949 char buf[BITS_IN_UNSIGNED/3 + 3];
950
951 sprintf(buf, "%d", value);
952 float_setscientific(dest, buf, NULLTERMINATED);
953 }
954
955 void
float_move(floatnum dest,floatnum source)956 float_move(
957 floatnum dest,
958 floatnum source)
959 {
960 if (dest != source)
961 {
962 float_setnan(dest);
963 *dest = *source;
964 float_create(source);
965 }
966 }
967
968 /* creates a copy of <source> and assigns it to
969 <dest>. The significand is guaranteed to have
970 <scale>+1 digits. The <dest> significand is
971 truncated, or padded with zeros to the right,
972 to achieve the desired length.
973 <scale> may assume the special value EXACT, in
974 which case a true copy is generated.
975 This function allows an in-place copy
976 (dest == source). */
977 static void
_scaled_clone(floatnum dest,cfloatnum source,int scale)978 _scaled_clone(
979 floatnum dest,
980 cfloatnum source,
981 int scale)
982 {
983 /* dest == source allowed! */
984
985 bc_num mant;
986 unsigned exp;
987 signed char sign;
988
989 mant = NULL;
990 if(scale == EXACT)
991 scale = _scaleof(source);
992 if (dest == source && scale <= _scaleof(source))
993 {
994 _setscale(dest, scale);
995 return;
996 }
997 mant = bc_new_num(1, scale);
998 scale = _min(scale, _scaleof(source));
999 memcpy(mant->n_value, _valueof(source), scale+1);
1000 sign = float_getsign(source);
1001 exp = source->exponent;
1002 float_setnan(dest);
1003 dest->exponent = exp;
1004 dest->significand = mant;
1005 #ifdef FLOATDEBUG
1006 _setvalue_(dest);
1007 #endif
1008 float_setsign(dest, sign);
1009 }
1010
1011 char
float_copy(floatnum dest,cfloatnum source,int digits)1012 float_copy(
1013 floatnum dest,
1014 cfloatnum source,
1015 int digits)
1016 {
1017 int scale, save;
1018
1019 if (digits == EXACT)
1020 digits = _max(1, float_getlength(source));
1021 if (!_checkdigits(digits, NOSPECIALVALUE))
1022 return _seterror(dest, InvalidPrecision);
1023 if (_is_special(source))
1024 {
1025 if (dest != source)
1026 float_free(dest);
1027 *dest = *source;
1028 }
1029 else
1030 {
1031 // invariant: source has to be restored, if it is != dest
1032 scale = _min(digits - 1, _scaleof(source));
1033 save = _limit_scale((floatnum)source, scale);
1034 _corr_trailing_zeros((floatnum)source);
1035 _scaled_clone(dest, source, EXACT);
1036 if (dest != source)
1037 _setscale(source, save);
1038 }
1039 return TRUE;
1040 }
1041
1042 /* rounding a value towards zero */
1043 static void
_trunc(floatnum dest,cfloatnum x,int scale)1044 _trunc(
1045 floatnum dest,
1046 cfloatnum x,
1047 int scale)
1048 {
1049 scale -= _bscandigit(x, scale, 0);
1050 _scaled_clone(dest, x, scale);
1051 #ifdef FLOATDEBUG
1052 _setvalue_(dest);
1053 #endif
1054 }
1055
1056 /* rounding a value towards infinity */
1057 static char
_roundup(floatnum dest,cfloatnum x,int scale)1058 _roundup(
1059 floatnum dest,
1060 cfloatnum x,
1061 int scale)
1062 {
1063 scale -= _bscandigit(x, scale, 9);
1064 _scaled_clone(dest, x, _max(0, scale));
1065 if (scale < 0)
1066 {
1067 *_valueof(dest) = 1;
1068 if (!float_isvalidexp(++dest->exponent))
1069 return FALSE;
1070 }
1071 else
1072 {
1073 ++*(_valueof(dest) + scale);
1074 }
1075 #ifdef FLOATDEBUG
1076 _setvalue_(dest);
1077 #endif
1078 return TRUE;
1079 }
1080
1081 char
float_round(floatnum dest,cfloatnum src,int digits,roundmode mode)1082 float_round(
1083 floatnum dest,
1084 cfloatnum src,
1085 int digits,
1086 roundmode mode)
1087 {
1088 int scalediff, scale;
1089 char digit;
1090 signed char sign, updown;
1091
1092 if (mode > TOMINUSINFINITY)
1093 return _seterror(dest, InvalidParam);
1094 if (!_checkdigits(digits, NOSPECIALVALUE))
1095 return _setnan(dest);
1096 if (float_isnan(src))
1097 return _seterror(dest, NoOperand);
1098 updown = 0;
1099 scale = digits - 1;
1100 if (float_getlength(src) > digits)
1101 {
1102 sign = float_getsign(src);
1103 switch(mode)
1104 {
1105 case TONEAREST:
1106 scalediff = _scaleof(src) - scale;
1107 if (scalediff > 0)
1108 {
1109 digit = _digit(src, digits);
1110 if (digit < 5
1111 || (digit == 5
1112 && scalediff == 1
1113 && (_digit(src, scale) & 1) == 0))
1114 updown = -1;
1115 else
1116 updown = 1;
1117 }
1118 break;
1119 case TOZERO:
1120 updown = -1;
1121 break;
1122 case TOINFINITY:
1123 updown = 1;
1124 break;
1125 case TOPLUSINFINITY:
1126 updown = sign;
1127 break;
1128 case TOMINUSINFINITY:
1129 updown = -sign;
1130 break;
1131 }
1132 }
1133 switch (updown)
1134 {
1135 case 1:
1136 if (!_roundup(dest, src, scale))
1137 return _seterror(dest, Overflow);
1138 break;
1139 case 0:
1140 float_copy(dest, src, digits);
1141 break;
1142 case -1:
1143 _trunc(dest, src, scale);
1144 break;
1145 }
1146 return TRUE;
1147 }
1148
1149 char
float_int(floatnum f)1150 float_int(
1151 floatnum f)
1152 {
1153 if (!_checknan(f))
1154 return FALSE;
1155 if (f->exponent < 0)
1156 float_setzero(f);
1157 else if (!float_iszero(f))
1158 float_round(f, f, f->exponent+1, TOZERO);
1159 return TRUE;
1160 }
1161
1162 char
float_frac(floatnum f)1163 float_frac(
1164 floatnum f)
1165 {
1166 if (!_checknan(f) || float_iszero(f) || f->exponent < 0)
1167 return !float_isnan(f);
1168 if (_scaleof(f) <= f->exponent)
1169 float_setzero(f);
1170 else
1171 {
1172 int leadingzeros = 0;
1173 _hidefirst(f, f->exponent + 1);
1174 leadingzeros = _scan_digit(_valueof(f), float_getlength(f), 0);
1175 _hidefirst(f, leadingzeros);
1176 f->exponent = -leadingzeros - 1;
1177 #ifdef FLOATDEBUG
1178 _setvalue_(f);
1179 #endif
1180 }
1181 return TRUE;
1182 }
1183
1184 /* the general purpose add/subtract routine that deals with
1185 the ordinary case. */
1186 static char
_addsub_normal(floatnum dest,floatnum summand1,floatnum summand2,int digits)1187 _addsub_normal(
1188 floatnum dest,
1189 floatnum summand1,
1190 floatnum summand2,
1191 int digits)
1192 {
1193 floatstruct tmp;
1194 int expdiff;
1195 int scale;
1196 int fulllength;
1197 int extradigit;
1198
1199 /* the operands are ordered by their exponent */
1200
1201 expdiff = (unsigned)(summand1->exponent - summand2->exponent);
1202
1203 /* the full length of the sum (without carry) */
1204 fulllength = _max(expdiff + _scaleof(summand2), _scaleof(summand1)) + 1;
1205
1206 extradigit = 0;
1207 if (digits == EXACT || digits > fulllength)
1208 digits = fulllength;
1209 else
1210 {
1211 if (float_getsign(summand1) + float_getsign(summand2) == 0)
1212 extradigit = 1; /* a true subtraction needs no space for a carry */
1213 if (expdiff > digits + extradigit)
1214 /* second operand underflows due to exponent diff */
1215 return float_copy(dest, summand1, digits+extradigit);
1216 }
1217
1218 if (digits > maxdigits)
1219 return _seterror(dest, InvalidPrecision);
1220
1221 /* we cannot add the operands directly
1222 because of possibly different exponents.
1223 So we assume the second operand "to be OK"
1224 and shift the decimal point of the first
1225 appropriately to the right.
1226 There is a cheap way to do this:
1227 increment len by expdiff and decrement
1228 scale by the same amount.
1229 But: Check the operand is long enough
1230 to do this. */
1231
1232 float_create(&tmp);
1233 if (_scaleof(summand1) < expdiff)
1234 {
1235 _scaled_clone(&tmp, summand1, expdiff);
1236 summand1 = &tmp;
1237 }
1238 scale = digits + extradigit - (int)expdiff - 1;
1239 _movepoint(summand1, expdiff);
1240
1241 /* truncate overly long operands */
1242 _limit_scale(summand1, scale);
1243 _limit_scale(summand2, scale);
1244
1245 /* add */
1246 dest->exponent = summand2->exponent;
1247 bc_add(summand1->significand,
1248 summand2->significand,
1249 &(dest->significand),
1250 scale);
1251
1252 float_free(&tmp);
1253
1254 return _normalize(dest);
1255 }
1256
1257 static char
_sub_checkborrow(floatnum dest,floatnum summand1,floatnum summand2,int digits)1258 _sub_checkborrow(
1259 floatnum dest,
1260 floatnum summand1,
1261 floatnum summand2,
1262 int digits)
1263 {
1264 /* the operands have opposite signs, the same exponent,
1265 but their first digit of the significand differ.
1266 The operands are ordered by this digit. */
1267 int result;
1268 int borrow;
1269 int scale1, scale2;
1270 char save;
1271 char* v1;
1272 char* v2;
1273
1274 /* Cancellation occurs, when the operands are of type
1275 p.000...yyy - q.999...xxx, p-q == 1, because a borrow
1276 propagates from the difference ..0yyy.. - ..9xxx..,
1277 leaving zeros in the first part. We check for this here. */
1278
1279 borrow = 0;
1280 if (_digit(summand1, 0) - _digit(summand2, 0) == 1)
1281 {
1282 scale1 = _scaleof(summand1);
1283 scale2 = _scaleof(summand2);
1284 if (scale1 == 0)
1285 /* the special case of a one-digit first operand
1286 p. - q.999..xxx */
1287 borrow = _scan_digit(_valueof(summand2) + 1, scale2, 9);
1288 else if (scale2 > 0)
1289 /* count the 0 - 9 pairs after the first digit, the area
1290 where a borrow can propagate */
1291 borrow = _scan_09pairs(summand1, summand2, _min(scale1, scale2));
1292
1293 /* In case of a one-digit second operand (p.yyy.. - q. == 1.yyy..),
1294 nothing is cancelled out. Borrow is already set to 0, and this is
1295 the correct value for this case, so nothing has to be done here */
1296
1297 if (borrow > 0)
1298 {
1299 /* we have cancellation here. We skip all digits, that
1300 cancel out due to a propagating borrow. These
1301 include the first digit and all following
1302 (0,9) digit pairs, except the last one. The last
1303 pair may be subject to cancellation or not, we do not
1304 care, because the following digit pair either yields a
1305 non-zero difference, or creates no borrow. Our standard
1306 adder is good enough to deal with such a limited
1307 cancelling effect. We will replace the last (0,9)
1308 digit pair with a (9,8) pair. This prevents the
1309 creation of a borrow, and yet, will yield the correct
1310 result */
1311
1312 /* hide all digits until the last found 0 - 9 pair */
1313 summand2->exponent -= borrow;
1314 summand1->exponent -= borrow;
1315 /* in case of a one-digit significand, there is nothing to hide */
1316 if (scale1 > 0)
1317 _hidefirst(summand1, borrow);
1318 _hidefirst(summand2, borrow);
1319
1320 /* we replace the last found 0 - 9 pair by a 9 - 8 pair,
1321 avoiding a carry, yet yielding the correct result */
1322 save = *(v1 = _valueof(summand1));
1323 *v1 = 9;
1324 *(v2 = _valueof(summand2)) = 8;
1325 }
1326 }
1327 result = _addsub_normal(dest, summand1, summand2, digits);
1328
1329 /* restore the modified digits */
1330 if (borrow > 0)
1331 {
1332 if (summand1 != dest)
1333 *v1 = save;
1334 if (summand2 != dest)
1335 *v2 = 9;
1336 }
1337 return result;
1338 }
1339
1340 static char
_sub_expdiff0(floatnum dest,floatnum summand1,floatnum summand2,int digits)1341 _sub_expdiff0(
1342 floatnum dest,
1343 floatnum summand1,
1344 floatnum summand2,
1345 int digits)
1346 {
1347 int eq;
1348 int result;
1349
1350 /* the operands are ordered by their significand length,
1351 and have the same exponent, and different sign */
1352
1353 /* One type of cancellation is when both significands set out
1354 with the same digits. Since these digits cancel out
1355 during subtraction, we look out for the first pair
1356 of different digits. eq receives the number of
1357 equal digits, which may be 0 */
1358 eq = _scan_equal(summand1, summand2);
1359 if (float_getlength(summand2) == eq)
1360 {
1361 /* the complete second operand is cancelled out */
1362 if (float_getlength(summand1) == eq)
1363 /* op1 == -op2 */
1364 return _setzero(dest);
1365 /* If xxx.. denotes the second operand, the (longer)
1366 first one is of form xxx..yyy.., since it has
1367 the same digits in the beginning. During
1368 subtraction the xxx... part is cancelled out, and
1369 this leaves yyy... as the subtraction result.
1370 By copying the yyy... to the result, we can shortcut the
1371 subtraction.
1372 But before doing so, we have to check yyy... for
1373 leading zeros, because the cancellation continues in
1374 this case. */
1375 eq += _scan_digit(_valueof(summand1) + eq,
1376 float_getlength(summand1) - eq, 0);
1377 _hidefirst(summand1, eq);
1378 result = float_copy(dest, summand1, digits);
1379 dest->exponent -= eq;
1380 return result != 0 && _normalize(dest);
1381 }
1382 /* hide the identical digits, and do the
1383 subtraction without them. */
1384 summand1->exponent -= eq;
1385 summand2->exponent -= eq;
1386 _hidefirst(summand1, eq);
1387 _hidefirst(summand2, eq);
1388
1389 /* order the operands by their first digit */
1390 if (_digit(summand1, 0) >= _digit(summand2, 0))
1391 return _sub_checkborrow(dest, summand1, summand2, digits);
1392 return _sub_checkborrow(dest, summand2, summand1, digits);
1393 }
1394
1395 static char
_sub_expdiff1(floatnum dest,floatnum summand1,floatnum summand2,int digits)1396 _sub_expdiff1(
1397 floatnum dest,
1398 floatnum summand1,
1399 floatnum summand2,
1400 int digits)
1401 {
1402 /* Cancellation occurs when subtracting 0.9xxx from
1403 1.0yyy */
1404
1405 int result;
1406 char singledigit;
1407 char* v1;
1408 char* v2;
1409
1410 /* the operands have different sign, are ordered by their
1411 exponent, and the difference of the exponents is 1 */
1412
1413 /* 1.0yyy may be given as a single digit 1 or as a string of
1414 digits starting with 1.0 */
1415 singledigit = _scaleof(summand1) == 0;
1416 if (_digit(summand1, 0) != 1
1417 || _digit(summand2, 0) != 9
1418 || (!singledigit && _digit(summand1, 1) != 0))
1419 return _addsub_normal(dest, summand1, summand2, digits);
1420
1421 /* we have cancellation here. We transform this
1422 case into that of equal exponents. */
1423
1424 /* we align both operands by hiding the first digit (1) of the
1425 greater operand. This leaves .0yyy which matches the
1426 second operand .9xxx. Unfortunately, if the first operand
1427 has only one digit, we cannot hide it, so we have to
1428 work around this then. */
1429 if (!singledigit)
1430 _hidefirst(summand1, 1);
1431 /* we change the leading digits into a '9' and a '8' resp.
1432 So we finally subtract .8xxx from .9yyy, yielding
1433 the correct result. */
1434 v1 = _valueof(summand1);
1435 v2 = _valueof(summand2);
1436 *v1 = 9;
1437 *v2 = 8;
1438 summand1->exponent--;
1439 result = _sub_checkborrow(dest, summand1, summand2, digits);
1440
1441 /* restore the original digits */
1442 if (summand1 != dest)
1443 *v1 = singledigit? 1 : 0;
1444 if (summand2 != dest)
1445 *v2 = 9;
1446 return result;
1447 }
1448
1449 static char
_sub_ordered(floatnum dest,floatnum summand1,floatnum summand2,int digits)1450 _sub_ordered(
1451 floatnum dest,
1452 floatnum summand1,
1453 floatnum summand2,
1454 int digits)
1455 {
1456 /* we have to check for cancellation when subtracting.
1457 Cancellation occurs when the operands are almost
1458 equal in magnitude. E.g. in 1.234 - 1.226 = 0.008,
1459 the result is on quite a different scale than the
1460 operands. Actually, this is a big problem, because
1461 it means that the (true) subtraction is numerically not
1462 stable. There is no way to get around this; you always
1463 have to take this into account, when subtracting.
1464 We make the best out of it, and check for cancellation
1465 in advance, so the result is at least valid to all digits,
1466 if the operands are known to be exact.
1467 Cancellation occurs only, if the difference between the
1468 exponents is 1 at most. We prepare the critical cases in
1469 specialized routines, and let the standard routine do the
1470 rest. */
1471
1472 /* the operands are ordered by their exponent */
1473
1474 unsigned expdiff;
1475
1476 expdiff = (unsigned)(summand1->exponent - summand2->exponent);
1477 switch (expdiff)
1478 {
1479 case 0:
1480 /* order the operands by their length of the significands */
1481 if (float_getlength(summand1) >= float_getlength(summand2))
1482 return _sub_expdiff0(dest, summand1, summand2, digits);
1483 return _sub_expdiff0(dest, summand2, summand1, digits);
1484 case 1:
1485 return _sub_expdiff1(dest, summand1, summand2, digits);
1486 }
1487 return _addsub_normal(dest, summand1, summand2, digits);
1488 }
1489
1490 static char
_addsub_ordered(floatnum dest,floatnum summand1,floatnum summand2,int digits)1491 _addsub_ordered(
1492 floatnum dest,
1493 floatnum summand1,
1494 floatnum summand2,
1495 int digits)
1496 {
1497 /* operands are ordered by their exponent */
1498
1499 /* handle a bunch of special cases */
1500 if (!_checkdigits(digits, EXACT) || !_checknan(summand1))
1501 return _setnan(dest);
1502 if (float_iszero(summand2))
1503 return float_copy(dest, summand1, digits);
1504
1505 /* separate true addition from true subtraction */
1506 if (float_getsign(summand1) == float_getsign(summand2))
1507 return _addsub_normal(dest, summand1, summand2, digits);
1508 return _sub_ordered(dest, summand1, summand2, digits);
1509 }
1510
1511 char
float_add(floatnum dest,cfloatnum summand1,cfloatnum summand2,int digits)1512 float_add(
1513 floatnum dest,
1514 cfloatnum summand1,
1515 cfloatnum summand2,
1516 int digits)
1517 {
1518 bc_struct bc1, bc2;
1519 floatstruct tmp1, tmp2;
1520 floatnum s1, s2;
1521
1522 /* the adder may occasionally adjust operands to
1523 his needs. Hence we work on temporary structures */
1524 s1 = dest;
1525 s2 = dest;
1526 if (dest != summand1)
1527 {
1528 _copyfn(&tmp1, summand1, &bc1);
1529 s1 = &tmp1;
1530 }
1531 if (dest != summand2)
1532 {
1533 _copyfn(&tmp2, summand2, &bc2);
1534 s2 = &tmp2;
1535 }
1536
1537 /* order the operands by their exponent. This should
1538 bring a NaN always to the front, and keeps zeros after any
1539 other number. */
1540 if (s1->exponent >= s2->exponent)
1541 return _addsub_ordered(dest, s1, s2, digits);
1542 return _addsub_ordered(dest, s2, s1, digits);
1543 }
1544
1545 char
float_sub(floatnum dest,cfloatnum minuend,cfloatnum subtrahend,int scale)1546 float_sub(
1547 floatnum dest,
1548 cfloatnum minuend,
1549 cfloatnum subtrahend,
1550 int scale)
1551 {
1552 int result;
1553 if (minuend == subtrahend)
1554 {
1555 /* changing the sign of one operand would change that of
1556 the other as well. So this is a special case */
1557 if(!_checknan(minuend))
1558 return FALSE;
1559 _setzero(dest);
1560 }
1561 /* do not use float_neg, because it may change float_error */
1562 float_setsign((floatnum)subtrahend, -float_getsign(subtrahend));
1563 result = float_add(dest, minuend, subtrahend, scale);
1564 if (dest != subtrahend)
1565 float_setsign((floatnum)subtrahend, -float_getsign(subtrahend));
1566 return result;
1567 }
1568
1569 char
float_mul(floatnum dest,cfloatnum factor1,cfloatnum factor2,int digits)1570 float_mul(
1571 floatnum dest,
1572 cfloatnum factor1,
1573 cfloatnum factor2,
1574 int digits)
1575 {
1576 int result;
1577 int fullscale;
1578 int savescale1, savescale2;
1579 int scale;
1580
1581 /* handle a bunch of special cases */
1582 if (!_checkdigits(digits, EXACT)
1583 || !_checknan(factor1)
1584 || !_checknan(factor2))
1585 /* invalid scale value or NaN operand */
1586 return _setnan(dest);
1587 if (float_iszero(factor1) || float_iszero(factor2))
1588 return _setzero(dest);
1589
1590 scale = digits - 1;
1591 fullscale = _scaleof(factor1) + _scaleof(factor2);
1592 if (digits == EXACT || scale > fullscale)
1593 scale = fullscale;
1594
1595 if (scale >= maxdigits)
1596 /* scale too large */
1597 return _seterror(dest, InvalidPrecision);
1598
1599 /* limit the scale of the operands to sane sizes */
1600 savescale1 = _limit_scale((floatnum)factor1, scale);
1601 savescale2 = _limit_scale((floatnum)factor2, scale);
1602
1603 /* multiply */
1604 dest->exponent = factor1->exponent + factor2->exponent;
1605 bc_multiply(factor1->significand, factor2->significand, &(dest->significand), scale);
1606 result = _normalize(dest);
1607
1608 /* reverse order is necessary in case factor1 == factor2 */
1609 if (dest != factor2)
1610 _setscale(factor2, savescale2);
1611 if (dest != factor1)
1612 _setscale(factor1, savescale1);
1613 return result;
1614 }
1615
1616 char
float_div(floatnum dest,cfloatnum dividend,cfloatnum divisor,int digits)1617 float_div(
1618 floatnum dest,
1619 cfloatnum dividend,
1620 cfloatnum divisor,
1621 int digits)
1622 {
1623 int result;
1624 int savescale1, savescale2;
1625 int exp;
1626
1627 /* handle a bunch of special cases */
1628 if (!_checkdigits(digits, INTQUOT) || !_checknan(dividend)
1629 || !_checknan(divisor))
1630 return _setnan(dest);
1631 if (float_iszero(divisor))
1632 return _seterror(dest, ZeroDivide);
1633 if (float_iszero(dividend))
1634 /* 0/x == 0 */
1635 return _setzero(dest);
1636
1637 exp = dividend->exponent - divisor->exponent;
1638
1639 /* check for integer quotient */
1640 if(digits == INTQUOT)
1641 {
1642 if (exp < 0)
1643 return _setzero(dest);
1644 digits = exp;
1645 }
1646
1647 /* scale OK? */
1648 if(digits > maxdigits)
1649 return _seterror(dest, InvalidPrecision);
1650
1651 /* limit the scale of the operands to sane sizes */
1652 savescale1 = _limit_scale((floatnum)dividend, digits);
1653 savescale2 = _limit_scale((floatnum)divisor, digits);
1654
1655 /* divide */
1656 result = TRUE;
1657 dest->exponent = exp;
1658 bc_divide(dividend->significand,
1659 divisor->significand,
1660 &(dest->significand),
1661 digits);
1662 if (bc_is_zero(dest->significand))
1663 float_setzero(dest);
1664 else
1665 result = _normalize(dest);
1666
1667 /* reverse order is necessary in case divisor == dividend */
1668 if (dest != divisor)
1669 _setscale(divisor, savescale2);
1670 if (dest != dividend)
1671 _setscale(dividend, savescale1);
1672 return result;
1673 }
1674
1675 char
float_divmod(floatnum quotient,floatnum remainder,cfloatnum dividend,cfloatnum divisor,int digits)1676 float_divmod(
1677 floatnum quotient,
1678 floatnum remainder,
1679 cfloatnum dividend,
1680 cfloatnum divisor,
1681 int digits)
1682 {
1683 int exp, exp1;
1684
1685 if (!_checkdigits(digits, INTQUOT) || !_checknan(dividend)
1686 || !_checknan(divisor) || quotient == remainder
1687 || float_iszero(divisor) || float_getlength(divisor) > maxdigits)
1688 {
1689 if (quotient == remainder)
1690 float_seterror(InvalidParam);
1691 if (float_getlength(divisor) > maxdigits)
1692 float_seterror(TooExpensive);
1693 if (float_iszero(divisor))
1694 float_seterror(ZeroDivide);
1695 float_setnan(quotient);
1696 return _setnan(remainder);
1697 }
1698 if (float_iszero(dividend))
1699 {
1700 float_setzero(quotient);
1701 return _setzero(remainder);
1702 }
1703 exp1 = dividend->exponent;
1704 exp = exp1 - divisor->exponent;
1705 if(digits-- == INTQUOT)
1706 {
1707 if (exp < 0)
1708 {
1709 if (float_copy(remainder, dividend, EXACT))
1710 return _setzero(quotient);
1711 return _setnan(quotient);
1712 }
1713 digits = exp;
1714 }
1715 if (digits > maxdigits)
1716 {
1717 float_setnan(quotient);
1718 return _seterror(remainder, TooExpensive);
1719 }
1720
1721 /* divide */
1722 quotient->exponent = exp;
1723 remainder->exponent = exp1;
1724 bc_divmod(dividend->significand,
1725 divisor->significand,
1726 &(quotient->significand),
1727 &(remainder->significand),
1728 digits);
1729
1730 /* if something goes wrong (one of the results overflows
1731 or underflows), always set both quotient and remainder
1732 to NaN */
1733 if (bc_is_zero(remainder->significand))
1734 float_setzero(remainder);
1735 else if (!_normalize(remainder))
1736 return _setnan(quotient);
1737 if (bc_is_zero(quotient->significand))
1738 float_setzero(quotient);
1739 else if (!_normalize(quotient))
1740 return _setnan(remainder);
1741 return TRUE;
1742 }
1743
1744 char
float_sqrt(floatnum value,int digits)1745 float_sqrt(floatnum value, int digits)
1746 {
1747 if (!_checkdigits(digits, NOSPECIALVALUE) || !_checknan(value))
1748 return _setnan(value);
1749 switch (float_getsign(value))
1750 {
1751 case -1:
1752 return _seterror(value, OutOfDomain);
1753 case 0:
1754 return TRUE;
1755 }
1756 if ((value->exponent & 1) != 0)
1757 {
1758 if (float_getlength(value) == 1)
1759 _scaled_clone(value, value, 1);
1760 _movepoint(value, 1);
1761 }
1762 bc_sqrt(&value->significand, digits - 1);
1763 #ifdef FLOATDEBUG
1764 _setvalue_(value);
1765 #endif
1766 if (value->exponent >= 0)
1767 value->exponent >>= 1;
1768 else
1769 value->exponent = -((1-value->exponent) >> 1);
1770 return TRUE;
1771 }
1772