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