turns printfs back on
[freebsd-src/fkvm-freebsd.git] / contrib / bc / lib / number.c
blob1f913d5350d6ed20e9b519bfcdd7cf985995ee3e
1 /* number.c: Implements arbitrary precision numbers. */
2 /*
3 Copyright (C) 1991, 1992, 1993, 1994, 1997, 2000 Free Software Foundation, Inc.
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.
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.
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:
18 The Free Software Foundation, Inc.
19 59 Temple Place, Suite 330
20 Boston, MA 02111-1307 USA.
23 You may contact the author by:
24 e-mail: philnelson@acm.org
25 us-mail: Philip A. Nelson
26 Computer Science Department, 9062
27 Western Washington University
28 Bellingham, WA 98226-9062
30 *************************************************************************/
32 #include <stdio.h>
33 #include <config.h>
34 #include <number.h>
35 #include <assert.h>
36 #include <stdlib.h>
37 #include <ctype.h>/* Prototypes needed for external utility routines. */
39 #define bc_rt_warn rt_warn
40 #define bc_rt_error rt_error
41 #define bc_out_of_memory out_of_memory
43 _PROTOTYPE(void rt_warn, (char *mesg ,...));
44 _PROTOTYPE(void rt_error, (char *mesg ,...));
45 _PROTOTYPE(void out_of_memory, (void));
47 /* Storage used for special numbers. */
48 bc_num _zero_;
49 bc_num _one_;
50 bc_num _two_;
52 static bc_num _bc_Free_list = NULL;
54 /* new_num allocates a number and sets fields to known values. */
56 bc_num
57 bc_new_num (length, scale)
58 int length, scale;
60 bc_num temp;
62 if (_bc_Free_list != NULL) {
63 temp = _bc_Free_list;
64 _bc_Free_list = temp->n_next;
65 } else {
66 temp = (bc_num) malloc (sizeof(bc_struct));
67 if (temp == NULL) bc_out_of_memory ();
69 temp->n_sign = PLUS;
70 temp->n_len = length;
71 temp->n_scale = scale;
72 temp->n_refs = 1;
73 temp->n_ptr = (char *) malloc (length+scale);
74 if (temp->n_ptr == NULL) bc_out_of_memory();
75 temp->n_value = temp->n_ptr;
76 memset (temp->n_ptr, 0, length+scale);
77 return temp;
80 /* "Frees" a bc_num NUM. Actually decreases reference count and only
81 frees the storage if reference count is zero. */
83 void
84 bc_free_num (num)
85 bc_num *num;
87 if (*num == NULL) return;
88 (*num)->n_refs--;
89 if ((*num)->n_refs == 0) {
90 if ((*num)->n_ptr)
91 free ((*num)->n_ptr);
92 (*num)->n_next = _bc_Free_list;
93 _bc_Free_list = *num;
95 *num = NULL;
99 /* Intitialize the number package! */
101 void
102 bc_init_numbers ()
104 _zero_ = bc_new_num (1,0);
105 _one_ = bc_new_num (1,0);
106 _one_->n_value[0] = 1;
107 _two_ = bc_new_num (1,0);
108 _two_->n_value[0] = 2;
112 /* Make a copy of a number! Just increments the reference count! */
114 bc_num
115 bc_copy_num (num)
116 bc_num num;
118 num->n_refs++;
119 return num;
123 /* Initialize a number NUM by making it a copy of zero. */
125 void
126 bc_init_num (num)
127 bc_num *num;
129 *num = bc_copy_num (_zero_);
132 /* For many things, we may have leading zeros in a number NUM.
133 _bc_rm_leading_zeros just moves the data "value" pointer to the
134 correct place and adjusts the length. */
136 static void
137 _bc_rm_leading_zeros (num)
138 bc_num num;
140 /* We can move n_value to point to the first non zero digit! */
141 while (*num->n_value == 0 && num->n_len > 1) {
142 num->n_value++;
143 num->n_len--;
148 /* Compare two bc numbers. Return value is 0 if equal, -1 if N1 is less
149 than N2 and +1 if N1 is greater than N2. If USE_SIGN is false, just
150 compare the magnitudes. */
152 static int
153 _bc_do_compare (n1, n2, use_sign, ignore_last)
154 bc_num n1, n2;
155 int use_sign;
156 int ignore_last;
158 char *n1ptr, *n2ptr;
159 int count;
161 /* First, compare signs. */
162 if (use_sign && n1->n_sign != n2->n_sign)
164 if (n1->n_sign == PLUS)
165 return (1); /* Positive N1 > Negative N2 */
166 else
167 return (-1); /* Negative N1 < Positive N1 */
170 /* Now compare the magnitude. */
171 if (n1->n_len != n2->n_len)
173 if (n1->n_len > n2->n_len)
175 /* Magnitude of n1 > n2. */
176 if (!use_sign || n1->n_sign == PLUS)
177 return (1);
178 else
179 return (-1);
181 else
183 /* Magnitude of n1 < n2. */
184 if (!use_sign || n1->n_sign == PLUS)
185 return (-1);
186 else
187 return (1);
191 /* If we get here, they have the same number of integer digits.
192 check the integer part and the equal length part of the fraction. */
193 count = n1->n_len + MIN (n1->n_scale, n2->n_scale);
194 n1ptr = n1->n_value;
195 n2ptr = n2->n_value;
197 while ((count > 0) && (*n1ptr == *n2ptr))
199 n1ptr++;
200 n2ptr++;
201 count--;
203 if (ignore_last && count == 1 && n1->n_scale == n2->n_scale)
204 return (0);
205 if (count != 0)
207 if (*n1ptr > *n2ptr)
209 /* Magnitude of n1 > n2. */
210 if (!use_sign || n1->n_sign == PLUS)
211 return (1);
212 else
213 return (-1);
215 else
217 /* Magnitude of n1 < n2. */
218 if (!use_sign || n1->n_sign == PLUS)
219 return (-1);
220 else
221 return (1);
225 /* They are equal up to the last part of the equal part of the fraction. */
226 if (n1->n_scale != n2->n_scale)
228 if (n1->n_scale > n2->n_scale)
230 for (count = n1->n_scale-n2->n_scale; count>0; count--)
231 if (*n1ptr++ != 0)
233 /* Magnitude of n1 > n2. */
234 if (!use_sign || n1->n_sign == PLUS)
235 return (1);
236 else
237 return (-1);
240 else
242 for (count = n2->n_scale-n1->n_scale; count>0; count--)
243 if (*n2ptr++ != 0)
245 /* Magnitude of n1 < n2. */
246 if (!use_sign || n1->n_sign == PLUS)
247 return (-1);
248 else
249 return (1);
254 /* They must be equal! */
255 return (0);
259 /* This is the "user callable" routine to compare numbers N1 and N2. */
262 bc_compare (n1, n2)
263 bc_num n1, n2;
265 return _bc_do_compare (n1, n2, TRUE, FALSE);
268 /* In some places we need to check if the number is negative. */
270 char
271 bc_is_neg (num)
272 bc_num num;
274 return num->n_sign == MINUS;
277 /* In some places we need to check if the number NUM is zero. */
279 char
280 bc_is_zero (num)
281 bc_num num;
283 int count;
284 char *nptr;
286 /* Quick check. */
287 if (num == _zero_) return TRUE;
289 /* Initialize */
290 count = num->n_len + num->n_scale;
291 nptr = num->n_value;
293 /* The check */
294 while ((count > 0) && (*nptr++ == 0)) count--;
296 if (count != 0)
297 return FALSE;
298 else
299 return TRUE;
302 /* In some places we need to check if the number NUM is almost zero.
303 Specifically, all but the last digit is 0 and the last digit is 1.
304 Last digit is defined by scale. */
306 char
307 bc_is_near_zero (num, scale)
308 bc_num num;
309 int scale;
311 int count;
312 char *nptr;
314 /* Error checking */
315 if (scale > num->n_scale)
316 scale = num->n_scale;
318 /* Initialize */
319 count = num->n_len + scale;
320 nptr = num->n_value;
322 /* The check */
323 while ((count > 0) && (*nptr++ == 0)) count--;
325 if (count != 0 && (count != 1 || *--nptr != 1))
326 return FALSE;
327 else
328 return TRUE;
332 /* Perform addition: N1 is added to N2 and the value is
333 returned. The signs of N1 and N2 are ignored.
334 SCALE_MIN is to set the minimum scale of the result. */
336 static bc_num
337 _bc_do_add (n1, n2, scale_min)
338 bc_num n1, n2;
339 int scale_min;
341 bc_num sum;
342 int sum_scale, sum_digits;
343 char *n1ptr, *n2ptr, *sumptr;
344 int carry, n1bytes, n2bytes;
345 int count;
347 /* Prepare sum. */
348 sum_scale = MAX (n1->n_scale, n2->n_scale);
349 sum_digits = MAX (n1->n_len, n2->n_len) + 1;
350 sum = bc_new_num (sum_digits, MAX(sum_scale, scale_min));
352 /* Zero extra digits made by scale_min. */
353 if (scale_min > sum_scale)
355 sumptr = (char *) (sum->n_value + sum_scale + sum_digits);
356 for (count = scale_min - sum_scale; count > 0; count--)
357 *sumptr++ = 0;
360 /* Start with the fraction part. Initialize the pointers. */
361 n1bytes = n1->n_scale;
362 n2bytes = n2->n_scale;
363 n1ptr = (char *) (n1->n_value + n1->n_len + n1bytes - 1);
364 n2ptr = (char *) (n2->n_value + n2->n_len + n2bytes - 1);
365 sumptr = (char *) (sum->n_value + sum_scale + sum_digits - 1);
367 /* Add the fraction part. First copy the longer fraction.*/
368 if (n1bytes != n2bytes)
370 if (n1bytes > n2bytes)
371 while (n1bytes>n2bytes)
372 { *sumptr-- = *n1ptr--; n1bytes--;}
373 else
374 while (n2bytes>n1bytes)
375 { *sumptr-- = *n2ptr--; n2bytes--;}
378 /* Now add the remaining fraction part and equal size integer parts. */
379 n1bytes += n1->n_len;
380 n2bytes += n2->n_len;
381 carry = 0;
382 while ((n1bytes > 0) && (n2bytes > 0))
384 *sumptr = *n1ptr-- + *n2ptr-- + carry;
385 if (*sumptr > (BASE-1))
387 carry = 1;
388 *sumptr -= BASE;
390 else
391 carry = 0;
392 sumptr--;
393 n1bytes--;
394 n2bytes--;
397 /* Now add carry the longer integer part. */
398 if (n1bytes == 0)
399 { n1bytes = n2bytes; n1ptr = n2ptr; }
400 while (n1bytes-- > 0)
402 *sumptr = *n1ptr-- + carry;
403 if (*sumptr > (BASE-1))
405 carry = 1;
406 *sumptr -= BASE;
408 else
409 carry = 0;
410 sumptr--;
413 /* Set final carry. */
414 if (carry == 1)
415 *sumptr += 1;
417 /* Adjust sum and return. */
418 _bc_rm_leading_zeros (sum);
419 return sum;
423 /* Perform subtraction: N2 is subtracted from N1 and the value is
424 returned. The signs of N1 and N2 are ignored. Also, N1 is
425 assumed to be larger than N2. SCALE_MIN is the minimum scale
426 of the result. */
428 static bc_num
429 _bc_do_sub (n1, n2, scale_min)
430 bc_num n1, n2;
431 int scale_min;
433 bc_num diff;
434 int diff_scale, diff_len;
435 int min_scale, min_len;
436 char *n1ptr, *n2ptr, *diffptr;
437 int borrow, count, val;
439 /* Allocate temporary storage. */
440 diff_len = MAX (n1->n_len, n2->n_len);
441 diff_scale = MAX (n1->n_scale, n2->n_scale);
442 min_len = MIN (n1->n_len, n2->n_len);
443 min_scale = MIN (n1->n_scale, n2->n_scale);
444 diff = bc_new_num (diff_len, MAX(diff_scale, scale_min));
446 /* Zero extra digits made by scale_min. */
447 if (scale_min > diff_scale)
449 diffptr = (char *) (diff->n_value + diff_len + diff_scale);
450 for (count = scale_min - diff_scale; count > 0; count--)
451 *diffptr++ = 0;
454 /* Initialize the subtract. */
455 n1ptr = (char *) (n1->n_value + n1->n_len + n1->n_scale -1);
456 n2ptr = (char *) (n2->n_value + n2->n_len + n2->n_scale -1);
457 diffptr = (char *) (diff->n_value + diff_len + diff_scale -1);
459 /* Subtract the numbers. */
460 borrow = 0;
462 /* Take care of the longer scaled number. */
463 if (n1->n_scale != min_scale)
465 /* n1 has the longer scale */
466 for (count = n1->n_scale - min_scale; count > 0; count--)
467 *diffptr-- = *n1ptr--;
469 else
471 /* n2 has the longer scale */
472 for (count = n2->n_scale - min_scale; count > 0; count--)
474 val = - *n2ptr-- - borrow;
475 if (val < 0)
477 val += BASE;
478 borrow = 1;
480 else
481 borrow = 0;
482 *diffptr-- = val;
486 /* Now do the equal length scale and integer parts. */
488 for (count = 0; count < min_len + min_scale; count++)
490 val = *n1ptr-- - *n2ptr-- - borrow;
491 if (val < 0)
493 val += BASE;
494 borrow = 1;
496 else
497 borrow = 0;
498 *diffptr-- = val;
501 /* If n1 has more digits then n2, we now do that subtract. */
502 if (diff_len != min_len)
504 for (count = diff_len - min_len; count > 0; count--)
506 val = *n1ptr-- - borrow;
507 if (val < 0)
509 val += BASE;
510 borrow = 1;
512 else
513 borrow = 0;
514 *diffptr-- = val;
518 /* Clean up and return. */
519 _bc_rm_leading_zeros (diff);
520 return diff;
524 /* Here is the full subtract routine that takes care of negative numbers.
525 N2 is subtracted from N1 and the result placed in RESULT. SCALE_MIN
526 is the minimum scale for the result. */
528 void
529 bc_sub (n1, n2, result, scale_min)
530 bc_num n1, n2, *result;
531 int scale_min;
533 bc_num diff = NULL;
534 int cmp_res;
535 int res_scale;
537 if (n1->n_sign != n2->n_sign)
539 diff = _bc_do_add (n1, n2, scale_min);
540 diff->n_sign = n1->n_sign;
542 else
544 /* subtraction must be done. */
545 /* Compare magnitudes. */
546 cmp_res = _bc_do_compare (n1, n2, FALSE, FALSE);
547 switch (cmp_res)
549 case -1:
550 /* n1 is less than n2, subtract n1 from n2. */
551 diff = _bc_do_sub (n2, n1, scale_min);
552 diff->n_sign = (n2->n_sign == PLUS ? MINUS : PLUS);
553 break;
554 case 0:
555 /* They are equal! return zero! */
556 res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale));
557 diff = bc_new_num (1, res_scale);
558 memset (diff->n_value, 0, res_scale+1);
559 break;
560 case 1:
561 /* n2 is less than n1, subtract n2 from n1. */
562 diff = _bc_do_sub (n1, n2, scale_min);
563 diff->n_sign = n1->n_sign;
564 break;
568 /* Clean up and return. */
569 bc_free_num (result);
570 *result = diff;
574 /* Here is the full add routine that takes care of negative numbers.
575 N1 is added to N2 and the result placed into RESULT. SCALE_MIN
576 is the minimum scale for the result. */
578 void
579 bc_add (n1, n2, result, scale_min)
580 bc_num n1, n2, *result;
581 int scale_min;
583 bc_num sum = NULL;
584 int cmp_res;
585 int res_scale;
587 if (n1->n_sign == n2->n_sign)
589 sum = _bc_do_add (n1, n2, scale_min);
590 sum->n_sign = n1->n_sign;
592 else
594 /* subtraction must be done. */
595 cmp_res = _bc_do_compare (n1, n2, FALSE, FALSE); /* Compare magnitudes. */
596 switch (cmp_res)
598 case -1:
599 /* n1 is less than n2, subtract n1 from n2. */
600 sum = _bc_do_sub (n2, n1, scale_min);
601 sum->n_sign = n2->n_sign;
602 break;
603 case 0:
604 /* They are equal! return zero with the correct scale! */
605 res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale));
606 sum = bc_new_num (1, res_scale);
607 memset (sum->n_value, 0, res_scale+1);
608 break;
609 case 1:
610 /* n2 is less than n1, subtract n2 from n1. */
611 sum = _bc_do_sub (n1, n2, scale_min);
612 sum->n_sign = n1->n_sign;
616 /* Clean up and return. */
617 bc_free_num (result);
618 *result = sum;
621 /* Recursive vs non-recursive multiply crossover ranges. */
622 #if defined(MULDIGITS)
623 #include "muldigits.h"
624 #else
625 #define MUL_BASE_DIGITS 80
626 #endif
628 int mul_base_digits = MUL_BASE_DIGITS;
629 #define MUL_SMALL_DIGITS mul_base_digits/4
631 /* Multiply utility routines */
633 static bc_num
634 new_sub_num (length, scale, value)
635 int length, scale;
636 char *value;
638 bc_num temp;
640 if (_bc_Free_list != NULL) {
641 temp = _bc_Free_list;
642 _bc_Free_list = temp->n_next;
643 } else {
644 temp = (bc_num) malloc (sizeof(bc_struct));
645 if (temp == NULL) bc_out_of_memory ();
647 temp->n_sign = PLUS;
648 temp->n_len = length;
649 temp->n_scale = scale;
650 temp->n_refs = 1;
651 temp->n_ptr = NULL;
652 temp->n_value = value;
653 return temp;
656 static void
657 _bc_simp_mul (bc_num n1, int n1len, bc_num n2, int n2len, bc_num *prod,
658 int full_scale)
660 char *n1ptr, *n2ptr, *pvptr;
661 char *n1end, *n2end; /* To the end of n1 and n2. */
662 int indx, sum, prodlen;
664 prodlen = n1len+n2len+1;
666 *prod = bc_new_num (prodlen, 0);
668 n1end = (char *) (n1->n_value + n1len - 1);
669 n2end = (char *) (n2->n_value + n2len - 1);
670 pvptr = (char *) ((*prod)->n_value + prodlen - 1);
671 sum = 0;
673 /* Here is the loop... */
674 for (indx = 0; indx < prodlen-1; indx++)
676 n1ptr = (char *) (n1end - MAX(0, indx-n2len+1));
677 n2ptr = (char *) (n2end - MIN(indx, n2len-1));
678 while ((n1ptr >= n1->n_value) && (n2ptr <= n2end))
679 sum += *n1ptr-- * *n2ptr++;
680 *pvptr-- = sum % BASE;
681 sum = sum / BASE;
683 *pvptr = sum;
687 /* A special adder/subtractor for the recursive divide and conquer
688 multiply algorithm. Note: if sub is called, accum must
689 be larger that what is being subtracted. Also, accum and val
690 must have n_scale = 0. (e.g. they must look like integers. *) */
691 static void
692 _bc_shift_addsub (bc_num accum, bc_num val, int shift, int sub)
694 signed char *accp, *valp;
695 int count, carry;
697 count = val->n_len;
698 if (val->n_value[0] == 0)
699 count--;
700 assert (accum->n_len+accum->n_scale >= shift+count);
702 /* Set up pointers and others */
703 accp = (signed char *)(accum->n_value +
704 accum->n_len + accum->n_scale - shift - 1);
705 valp = (signed char *)(val->n_value + val->n_len - 1);
706 carry = 0;
708 if (sub) {
709 /* Subtraction, carry is really borrow. */
710 while (count--) {
711 *accp -= *valp-- + carry;
712 if (*accp < 0) {
713 carry = 1;
714 *accp-- += BASE;
715 } else {
716 carry = 0;
717 accp--;
720 while (carry) {
721 *accp -= carry;
722 if (*accp < 0)
723 *accp-- += BASE;
724 else
725 carry = 0;
727 } else {
728 /* Addition */
729 while (count--) {
730 *accp += *valp-- + carry;
731 if (*accp > (BASE-1)) {
732 carry = 1;
733 *accp-- -= BASE;
734 } else {
735 carry = 0;
736 accp--;
739 while (carry) {
740 *accp += carry;
741 if (*accp > (BASE-1))
742 *accp-- -= BASE;
743 else
744 carry = 0;
749 /* Recursive divide and conquer multiply algorithm.
750 Based on
751 Let u = u0 + u1*(b^n)
752 Let v = v0 + v1*(b^n)
753 Then uv = (B^2n+B^n)*u1*v1 + B^n*(u1-u0)*(v0-v1) + (B^n+1)*u0*v0
755 B is the base of storage, number of digits in u1,u0 close to equal.
757 static void
758 _bc_rec_mul (bc_num u, int ulen, bc_num v, int vlen, bc_num *prod,
759 int full_scale)
761 bc_num u0, u1, v0, v1;
762 int u0len, v0len;
763 bc_num m1, m2, m3, d1, d2;
764 int n, prodlen, m1zero;
765 int d1len, d2len;
767 /* Base case? */
768 if ((ulen+vlen) < mul_base_digits
769 || ulen < MUL_SMALL_DIGITS
770 || vlen < MUL_SMALL_DIGITS ) {
771 _bc_simp_mul (u, ulen, v, vlen, prod, full_scale);
772 return;
775 /* Calculate n -- the u and v split point in digits. */
776 n = (MAX(ulen, vlen)+1) / 2;
778 /* Split u and v. */
779 if (ulen < n) {
780 u1 = bc_copy_num (_zero_);
781 u0 = new_sub_num (ulen,0, u->n_value);
782 } else {
783 u1 = new_sub_num (ulen-n, 0, u->n_value);
784 u0 = new_sub_num (n, 0, u->n_value+ulen-n);
786 if (vlen < n) {
787 v1 = bc_copy_num (_zero_);
788 v0 = new_sub_num (vlen,0, v->n_value);
789 } else {
790 v1 = new_sub_num (vlen-n, 0, v->n_value);
791 v0 = new_sub_num (n, 0, v->n_value+vlen-n);
793 _bc_rm_leading_zeros (u1);
794 _bc_rm_leading_zeros (u0);
795 u0len = u0->n_len;
796 _bc_rm_leading_zeros (v1);
797 _bc_rm_leading_zeros (v0);
798 v0len = v0->n_len;
800 m1zero = bc_is_zero(u1) || bc_is_zero(v1);
802 /* Calculate sub results ... */
804 bc_init_num(&d1);
805 bc_init_num(&d2);
806 bc_sub (u1, u0, &d1, 0);
807 d1len = d1->n_len;
808 bc_sub (v0, v1, &d2, 0);
809 d2len = d2->n_len;
812 /* Do recursive multiplies and shifted adds. */
813 if (m1zero)
814 m1 = bc_copy_num (_zero_);
815 else
816 _bc_rec_mul (u1, u1->n_len, v1, v1->n_len, &m1, 0);
818 if (bc_is_zero(d1) || bc_is_zero(d2))
819 m2 = bc_copy_num (_zero_);
820 else
821 _bc_rec_mul (d1, d1len, d2, d2len, &m2, 0);
823 if (bc_is_zero(u0) || bc_is_zero(v0))
824 m3 = bc_copy_num (_zero_);
825 else
826 _bc_rec_mul (u0, u0->n_len, v0, v0->n_len, &m3, 0);
828 /* Initialize product */
829 prodlen = ulen+vlen+1;
830 *prod = bc_new_num(prodlen, 0);
832 if (!m1zero) {
833 _bc_shift_addsub (*prod, m1, 2*n, 0);
834 _bc_shift_addsub (*prod, m1, n, 0);
836 _bc_shift_addsub (*prod, m3, n, 0);
837 _bc_shift_addsub (*prod, m3, 0, 0);
838 _bc_shift_addsub (*prod, m2, n, d1->n_sign != d2->n_sign);
840 /* Now clean up! */
841 bc_free_num (&u1);
842 bc_free_num (&u0);
843 bc_free_num (&v1);
844 bc_free_num (&m1);
845 bc_free_num (&v0);
846 bc_free_num (&m2);
847 bc_free_num (&m3);
848 bc_free_num (&d1);
849 bc_free_num (&d2);
852 /* The multiply routine. N2 times N1 is put int PROD with the scale of
853 the result being MIN(N2 scale+N1 scale, MAX (SCALE, N2 scale, N1 scale)).
856 void
857 bc_multiply (n1, n2, prod, scale)
858 bc_num n1, n2, *prod;
859 int scale;
861 bc_num pval;
862 int len1, len2;
863 int full_scale, prod_scale;
865 /* Initialize things. */
866 len1 = n1->n_len + n1->n_scale;
867 len2 = n2->n_len + n2->n_scale;
868 full_scale = n1->n_scale + n2->n_scale;
869 prod_scale = MIN(full_scale,MAX(scale,MAX(n1->n_scale,n2->n_scale)));
871 /* Do the multiply */
872 _bc_rec_mul (n1, len1, n2, len2, &pval, full_scale);
874 /* Assign to prod and clean up the number. */
875 pval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS );
876 pval->n_value = pval->n_ptr;
877 pval->n_len = len2 + len1 + 1 - full_scale;
878 pval->n_scale = prod_scale;
879 _bc_rm_leading_zeros (pval);
880 if (bc_is_zero (pval))
881 pval->n_sign = PLUS;
882 bc_free_num (prod);
883 *prod = pval;
886 /* Some utility routines for the divide: First a one digit multiply.
887 NUM (with SIZE digits) is multiplied by DIGIT and the result is
888 placed into RESULT. It is written so that NUM and RESULT can be
889 the same pointers. */
891 static void
892 _one_mult (num, size, digit, result)
893 unsigned char *num;
894 int size, digit;
895 unsigned char *result;
897 int carry, value;
898 unsigned char *nptr, *rptr;
900 if (digit == 0)
901 memset (result, 0, size);
902 else
904 if (digit == 1)
905 memcpy (result, num, size);
906 else
908 /* Initialize */
909 nptr = (unsigned char *) (num+size-1);
910 rptr = (unsigned char *) (result+size-1);
911 carry = 0;
913 while (size-- > 0)
915 value = *nptr-- * digit + carry;
916 *rptr-- = value % BASE;
917 carry = value / BASE;
920 if (carry != 0) *rptr = carry;
926 /* The full division routine. This computes N1 / N2. It returns
927 0 if the division is ok and the result is in QUOT. The number of
928 digits after the decimal point is SCALE. It returns -1 if division
929 by zero is tried. The algorithm is found in Knuth Vol 2. p237. */
932 bc_divide (n1, n2, quot, scale)
933 bc_num n1, n2, *quot;
934 int scale;
936 bc_num qval;
937 unsigned char *num1, *num2;
938 unsigned char *ptr1, *ptr2, *n2ptr, *qptr;
939 int scale1, val;
940 unsigned int len1, len2, scale2, qdigits, extra, count;
941 unsigned int qdig, qguess, borrow, carry;
942 unsigned char *mval;
943 char zero;
944 unsigned int norm;
946 /* Test for divide by zero. */
947 if (bc_is_zero (n2)) return -1;
949 /* Test for divide by 1. If it is we must truncate. */
950 if (n2->n_scale == 0)
952 if (n2->n_len == 1 && *n2->n_value == 1)
954 qval = bc_new_num (n1->n_len, scale);
955 qval->n_sign = (n1->n_sign == n2->n_sign ? PLUS : MINUS);
956 memset (&qval->n_value[n1->n_len],0,scale);
957 memcpy (qval->n_value, n1->n_value,
958 n1->n_len + MIN(n1->n_scale,scale));
959 bc_free_num (quot);
960 *quot = qval;
964 /* Set up the divide. Move the decimal point on n1 by n2's scale.
965 Remember, zeros on the end of num2 are wasted effort for dividing. */
966 scale2 = n2->n_scale;
967 n2ptr = (unsigned char *) n2->n_value+n2->n_len+scale2-1;
968 while ((scale2 > 0) && (*n2ptr-- == 0)) scale2--;
970 len1 = n1->n_len + scale2;
971 scale1 = n1->n_scale - scale2;
972 if (scale1 < scale)
973 extra = scale - scale1;
974 else
975 extra = 0;
976 num1 = (unsigned char *) malloc (n1->n_len+n1->n_scale+extra+2);
977 if (num1 == NULL) bc_out_of_memory();
978 memset (num1, 0, n1->n_len+n1->n_scale+extra+2);
979 memcpy (num1+1, n1->n_value, n1->n_len+n1->n_scale);
981 len2 = n2->n_len + scale2;
982 num2 = (unsigned char *) malloc (len2+1);
983 if (num2 == NULL) bc_out_of_memory();
984 memcpy (num2, n2->n_value, len2);
985 *(num2+len2) = 0;
986 n2ptr = num2;
987 while (*n2ptr == 0)
989 n2ptr++;
990 len2--;
993 /* Calculate the number of quotient digits. */
994 if (len2 > len1+scale)
996 qdigits = scale+1;
997 zero = TRUE;
999 else
1001 zero = FALSE;
1002 if (len2>len1)
1003 qdigits = scale+1; /* One for the zero integer part. */
1004 else
1005 qdigits = len1-len2+scale+1;
1008 /* Allocate and zero the storage for the quotient. */
1009 qval = bc_new_num (qdigits-scale,scale);
1010 memset (qval->n_value, 0, qdigits);
1012 /* Allocate storage for the temporary storage mval. */
1013 mval = (unsigned char *) malloc (len2+1);
1014 if (mval == NULL) bc_out_of_memory ();
1016 /* Now for the full divide algorithm. */
1017 if (!zero)
1019 /* Normalize */
1020 norm = 10 / ((int)*n2ptr + 1);
1021 if (norm != 1)
1023 _one_mult (num1, len1+scale1+extra+1, norm, num1);
1024 _one_mult (n2ptr, len2, norm, n2ptr);
1027 /* Initialize divide loop. */
1028 qdig = 0;
1029 if (len2 > len1)
1030 qptr = (unsigned char *) qval->n_value+len2-len1;
1031 else
1032 qptr = (unsigned char *) qval->n_value;
1034 /* Loop */
1035 while (qdig <= len1+scale-len2)
1037 /* Calculate the quotient digit guess. */
1038 if (*n2ptr == num1[qdig])
1039 qguess = 9;
1040 else
1041 qguess = (num1[qdig]*10 + num1[qdig+1]) / *n2ptr;
1043 /* Test qguess. */
1044 if (n2ptr[1]*qguess >
1045 (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10
1046 + num1[qdig+2])
1048 qguess--;
1049 /* And again. */
1050 if (n2ptr[1]*qguess >
1051 (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10
1052 + num1[qdig+2])
1053 qguess--;
1056 /* Multiply and subtract. */
1057 borrow = 0;
1058 if (qguess != 0)
1060 *mval = 0;
1061 _one_mult (n2ptr, len2, qguess, mval+1);
1062 ptr1 = (unsigned char *) num1+qdig+len2;
1063 ptr2 = (unsigned char *) mval+len2;
1064 for (count = 0; count < len2+1; count++)
1066 val = (int) *ptr1 - (int) *ptr2-- - borrow;
1067 if (val < 0)
1069 val += 10;
1070 borrow = 1;
1072 else
1073 borrow = 0;
1074 *ptr1-- = val;
1078 /* Test for negative result. */
1079 if (borrow == 1)
1081 qguess--;
1082 ptr1 = (unsigned char *) num1+qdig+len2;
1083 ptr2 = (unsigned char *) n2ptr+len2-1;
1084 carry = 0;
1085 for (count = 0; count < len2; count++)
1087 val = (int) *ptr1 + (int) *ptr2-- + carry;
1088 if (val > 9)
1090 val -= 10;
1091 carry = 1;
1093 else
1094 carry = 0;
1095 *ptr1-- = val;
1097 if (carry == 1) *ptr1 = (*ptr1 + 1) % 10;
1100 /* We now know the quotient digit. */
1101 *qptr++ = qguess;
1102 qdig++;
1106 /* Clean up and return the number. */
1107 qval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS );
1108 if (bc_is_zero (qval)) qval->n_sign = PLUS;
1109 _bc_rm_leading_zeros (qval);
1110 bc_free_num (quot);
1111 *quot = qval;
1113 /* Clean up temporary storage. */
1114 free (mval);
1115 free (num1);
1116 free (num2);
1118 return 0; /* Everything is OK. */
1122 /* Division *and* modulo for numbers. This computes both NUM1 / NUM2 and
1123 NUM1 % NUM2 and puts the results in QUOT and REM, except that if QUOT
1124 is NULL then that store will be omitted.
1128 bc_divmod (num1, num2, quot, rem, scale)
1129 bc_num num1, num2, *quot, *rem;
1130 int scale;
1132 bc_num quotient = NULL;
1133 bc_num temp;
1134 int rscale;
1136 /* Check for correct numbers. */
1137 if (bc_is_zero (num2)) return -1;
1139 /* Calculate final scale. */
1140 rscale = MAX (num1->n_scale, num2->n_scale+scale);
1141 bc_init_num(&temp);
1143 /* Calculate it. */
1144 bc_divide (num1, num2, &temp, scale);
1145 if (quot)
1146 quotient = bc_copy_num (temp);
1147 bc_multiply (temp, num2, &temp, rscale);
1148 bc_sub (num1, temp, rem, rscale);
1149 bc_free_num (&temp);
1151 if (quot)
1153 bc_free_num (quot);
1154 *quot = quotient;
1157 return 0; /* Everything is OK. */
1161 /* Modulo for numbers. This computes NUM1 % NUM2 and puts the
1162 result in RESULT. */
1165 bc_modulo (num1, num2, result, scale)
1166 bc_num num1, num2, *result;
1167 int scale;
1169 return bc_divmod (num1, num2, NULL, result, scale);
1172 /* Raise BASE to the EXPO power, reduced modulo MOD. The result is
1173 placed in RESULT. If a EXPO is not an integer,
1174 only the integer part is used. */
1177 bc_raisemod (base, expo, mod, result, scale)
1178 bc_num base, expo, mod, *result;
1179 int scale;
1181 bc_num power, exponent, parity, temp;
1182 int rscale;
1184 /* Check for correct numbers. */
1185 if (bc_is_zero(mod)) return -1;
1186 if (bc_is_neg(expo)) return -1;
1188 /* Set initial values. */
1189 power = bc_copy_num (base);
1190 exponent = bc_copy_num (expo);
1191 temp = bc_copy_num (_one_);
1192 bc_init_num(&parity);
1194 /* Check the base for scale digits. */
1195 if (base->n_scale != 0)
1196 bc_rt_warn ("non-zero scale in base");
1198 /* Check the exponent for scale digits. */
1199 if (exponent->n_scale != 0)
1201 bc_rt_warn ("non-zero scale in exponent");
1202 bc_divide (exponent, _one_, &exponent, 0); /*truncate */
1205 /* Check the modulus for scale digits. */
1206 if (mod->n_scale != 0)
1207 bc_rt_warn ("non-zero scale in modulus");
1209 /* Do the calculation. */
1210 rscale = MAX(scale, base->n_scale);
1211 while ( !bc_is_zero(exponent) )
1213 (void) bc_divmod (exponent, _two_, &exponent, &parity, 0);
1214 if ( !bc_is_zero(parity) )
1216 bc_multiply (temp, power, &temp, rscale);
1217 (void) bc_modulo (temp, mod, &temp, scale);
1220 bc_multiply (power, power, &power, rscale);
1221 (void) bc_modulo (power, mod, &power, scale);
1224 /* Assign the value. */
1225 bc_free_num (&power);
1226 bc_free_num (&exponent);
1227 bc_free_num (result);
1228 *result = temp;
1229 return 0; /* Everything is OK. */
1232 /* Raise NUM1 to the NUM2 power. The result is placed in RESULT.
1233 Maximum exponent is LONG_MAX. If a NUM2 is not an integer,
1234 only the integer part is used. */
1236 void
1237 bc_raise (num1, num2, result, scale)
1238 bc_num num1, num2, *result;
1239 int scale;
1241 bc_num temp, power;
1242 long exponent;
1243 int rscale;
1244 int pwrscale;
1245 int calcscale;
1246 char neg;
1248 /* Check the exponent for scale digits and convert to a long. */
1249 if (num2->n_scale != 0)
1250 bc_rt_warn ("non-zero scale in exponent");
1251 exponent = bc_num2long (num2);
1252 if (exponent == 0 && (num2->n_len > 1 || num2->n_value[0] != 0))
1253 bc_rt_error ("exponent too large in raise");
1255 /* Special case if exponent is a zero. */
1256 if (exponent == 0)
1258 bc_free_num (result);
1259 *result = bc_copy_num (_one_);
1260 return;
1263 /* Other initializations. */
1264 if (exponent < 0)
1266 neg = TRUE;
1267 exponent = -exponent;
1268 rscale = scale;
1270 else
1272 neg = FALSE;
1273 rscale = MIN (num1->n_scale*exponent, MAX(scale, num1->n_scale));
1276 /* Set initial value of temp. */
1277 power = bc_copy_num (num1);
1278 pwrscale = num1->n_scale;
1279 while ((exponent & 1) == 0)
1281 pwrscale = 2*pwrscale;
1282 bc_multiply (power, power, &power, pwrscale);
1283 exponent = exponent >> 1;
1285 temp = bc_copy_num (power);
1286 calcscale = pwrscale;
1287 exponent = exponent >> 1;
1289 /* Do the calculation. */
1290 while (exponent > 0)
1292 pwrscale = 2*pwrscale;
1293 bc_multiply (power, power, &power, pwrscale);
1294 if ((exponent & 1) == 1) {
1295 calcscale = pwrscale + calcscale;
1296 bc_multiply (temp, power, &temp, calcscale);
1298 exponent = exponent >> 1;
1301 /* Assign the value. */
1302 if (neg)
1304 bc_divide (_one_, temp, result, rscale);
1305 bc_free_num (&temp);
1307 else
1309 bc_free_num (result);
1310 *result = temp;
1311 if ((*result)->n_scale > rscale)
1312 (*result)->n_scale = rscale;
1314 bc_free_num (&power);
1317 /* Take the square root NUM and return it in NUM with SCALE digits
1318 after the decimal place. */
1321 bc_sqrt (num, scale)
1322 bc_num *num;
1323 int scale;
1325 int rscale, cmp_res, done;
1326 int cscale;
1327 bc_num guess, guess1, point5, diff;
1329 /* Initial checks. */
1330 cmp_res = bc_compare (*num, _zero_);
1331 if (cmp_res < 0)
1332 return 0; /* error */
1333 else
1335 if (cmp_res == 0)
1337 bc_free_num (num);
1338 *num = bc_copy_num (_zero_);
1339 return 1;
1342 cmp_res = bc_compare (*num, _one_);
1343 if (cmp_res == 0)
1345 bc_free_num (num);
1346 *num = bc_copy_num (_one_);
1347 return 1;
1350 /* Initialize the variables. */
1351 rscale = MAX (scale, (*num)->n_scale);
1352 bc_init_num(&guess);
1353 bc_init_num(&guess1);
1354 bc_init_num(&diff);
1355 point5 = bc_new_num (1,1);
1356 point5->n_value[1] = 5;
1359 /* Calculate the initial guess. */
1360 if (cmp_res < 0)
1362 /* The number is between 0 and 1. Guess should start at 1. */
1363 guess = bc_copy_num (_one_);
1364 cscale = (*num)->n_scale;
1366 else
1368 /* The number is greater than 1. Guess should start at 10^(exp/2). */
1369 bc_int2num (&guess,10);
1371 bc_int2num (&guess1,(*num)->n_len);
1372 bc_multiply (guess1, point5, &guess1, 0);
1373 guess1->n_scale = 0;
1374 bc_raise (guess, guess1, &guess, 0);
1375 bc_free_num (&guess1);
1376 cscale = 3;
1379 /* Find the square root using Newton's algorithm. */
1380 done = FALSE;
1381 while (!done)
1383 bc_free_num (&guess1);
1384 guess1 = bc_copy_num (guess);
1385 bc_divide (*num, guess, &guess, cscale);
1386 bc_add (guess, guess1, &guess, 0);
1387 bc_multiply (guess, point5, &guess, cscale);
1388 bc_sub (guess, guess1, &diff, cscale+1);
1389 if (bc_is_near_zero (diff, cscale))
1391 if (cscale < rscale+1)
1392 cscale = MIN (cscale*3, rscale+1);
1393 else
1394 done = TRUE;
1398 /* Assign the number and clean up. */
1399 bc_free_num (num);
1400 bc_divide (guess,_one_,num,rscale);
1401 bc_free_num (&guess);
1402 bc_free_num (&guess1);
1403 bc_free_num (&point5);
1404 bc_free_num (&diff);
1405 return 1;
1409 /* The following routines provide output for bcd numbers package
1410 using the rules of POSIX bc for output. */
1412 /* This structure is used for saving digits in the conversion process. */
1413 typedef struct stk_rec {
1414 long digit;
1415 struct stk_rec *next;
1416 } stk_rec;
1418 /* The reference string for digits. */
1419 static char ref_str[] = "0123456789ABCDEF";
1422 /* A special output routine for "multi-character digits." Exactly
1423 SIZE characters must be output for the value VAL. If SPACE is
1424 non-zero, we must output one space before the number. OUT_CHAR
1425 is the actual routine for writing the characters. */
1427 void
1428 bc_out_long (val, size, space, out_char)
1429 long val;
1430 int size, space;
1431 #ifdef __STDC__
1432 void (*out_char)(int);
1433 #else
1434 void (*out_char)();
1435 #endif
1437 char digits[40];
1438 int len, ix;
1440 if (space) (*out_char) (' ');
1441 sprintf (digits, "%ld", val);
1442 len = strlen (digits);
1443 while (size > len)
1445 (*out_char) ('0');
1446 size--;
1448 for (ix=0; ix < len; ix++)
1449 (*out_char) (digits[ix]);
1452 /* Output of a bcd number. NUM is written in base O_BASE using OUT_CHAR
1453 as the routine to do the actual output of the characters. */
1455 void
1456 bc_out_num (num, o_base, out_char, leading_zero)
1457 bc_num num;
1458 int o_base;
1459 #ifdef __STDC__
1460 void (*out_char)(int);
1461 #else
1462 void (*out_char)();
1463 #endif
1464 int leading_zero;
1466 char *nptr;
1467 int index, fdigit, pre_space;
1468 stk_rec *digits, *temp;
1469 bc_num int_part, frac_part, base, cur_dig, t_num, max_o_digit;
1471 /* The negative sign if needed. */
1472 if (num->n_sign == MINUS) (*out_char) ('-');
1474 /* Output the number. */
1475 if (bc_is_zero (num))
1476 (*out_char) ('0');
1477 else
1478 if (o_base == 10)
1480 /* The number is in base 10, do it the fast way. */
1481 nptr = num->n_value;
1482 if (num->n_len > 1 || *nptr != 0)
1483 for (index=num->n_len; index>0; index--)
1484 (*out_char) (BCD_CHAR(*nptr++));
1485 else
1486 nptr++;
1488 if (leading_zero && bc_is_zero (num))
1489 (*out_char) ('0');
1491 /* Now the fraction. */
1492 if (num->n_scale > 0)
1494 (*out_char) ('.');
1495 for (index=0; index<num->n_scale; index++)
1496 (*out_char) (BCD_CHAR(*nptr++));
1499 else
1501 /* special case ... */
1502 if (leading_zero && bc_is_zero (num))
1503 (*out_char) ('0');
1505 /* The number is some other base. */
1506 digits = NULL;
1507 bc_init_num (&int_part);
1508 bc_divide (num, _one_, &int_part, 0);
1509 bc_init_num (&frac_part);
1510 bc_init_num (&cur_dig);
1511 bc_init_num (&base);
1512 bc_sub (num, int_part, &frac_part, 0);
1513 /* Make the INT_PART and FRAC_PART positive. */
1514 int_part->n_sign = PLUS;
1515 frac_part->n_sign = PLUS;
1516 bc_int2num (&base, o_base);
1517 bc_init_num (&max_o_digit);
1518 bc_int2num (&max_o_digit, o_base-1);
1521 /* Get the digits of the integer part and push them on a stack. */
1522 while (!bc_is_zero (int_part))
1524 bc_modulo (int_part, base, &cur_dig, 0);
1525 temp = (stk_rec *) malloc (sizeof(stk_rec));
1526 if (temp == NULL) bc_out_of_memory();
1527 temp->digit = bc_num2long (cur_dig);
1528 temp->next = digits;
1529 digits = temp;
1530 bc_divide (int_part, base, &int_part, 0);
1533 /* Print the digits on the stack. */
1534 if (digits != NULL)
1536 /* Output the digits. */
1537 while (digits != NULL)
1539 temp = digits;
1540 digits = digits->next;
1541 if (o_base <= 16)
1542 (*out_char) (ref_str[ (int) temp->digit]);
1543 else
1544 bc_out_long (temp->digit, max_o_digit->n_len, 1, out_char);
1545 free (temp);
1549 /* Get and print the digits of the fraction part. */
1550 if (num->n_scale > 0)
1552 (*out_char) ('.');
1553 pre_space = 0;
1554 t_num = bc_copy_num (_one_);
1555 while (t_num->n_len <= num->n_scale) {
1556 bc_multiply (frac_part, base, &frac_part, num->n_scale);
1557 fdigit = bc_num2long (frac_part);
1558 bc_int2num (&int_part, fdigit);
1559 bc_sub (frac_part, int_part, &frac_part, 0);
1560 if (o_base <= 16)
1561 (*out_char) (ref_str[fdigit]);
1562 else {
1563 bc_out_long (fdigit, max_o_digit->n_len, pre_space, out_char);
1564 pre_space = 1;
1566 bc_multiply (t_num, base, &t_num, 0);
1568 bc_free_num (&t_num);
1571 /* Clean up. */
1572 bc_free_num (&int_part);
1573 bc_free_num (&frac_part);
1574 bc_free_num (&base);
1575 bc_free_num (&cur_dig);
1576 bc_free_num (&max_o_digit);
1579 /* Convert a number NUM to a long. The function returns only the integer
1580 part of the number. For numbers that are too large to represent as
1581 a long, this function returns a zero. This can be detected by checking
1582 the NUM for zero after having a zero returned. */
1584 long
1585 bc_num2long (num)
1586 bc_num num;
1588 long val;
1589 char *nptr;
1590 int index;
1592 /* Extract the int value, ignore the fraction. */
1593 val = 0;
1594 nptr = num->n_value;
1595 for (index=num->n_len; (index>0) && (val<=(LONG_MAX/BASE)); index--)
1596 val = val*BASE + *nptr++;
1598 /* Check for overflow. If overflow, return zero. */
1599 if (index>0) val = 0;
1600 if (val < 0) val = 0;
1602 /* Return the value. */
1603 if (num->n_sign == PLUS)
1604 return (val);
1605 else
1606 return (-val);
1610 /* Convert an integer VAL to a bc number NUM. */
1612 void
1613 bc_int2num (num, val)
1614 bc_num *num;
1615 int val;
1617 char buffer[30];
1618 char *bptr, *vptr;
1619 int ix = 1;
1620 char neg = 0;
1622 /* Sign. */
1623 if (val < 0)
1625 neg = 1;
1626 val = -val;
1629 /* Get things going. */
1630 bptr = buffer;
1631 *bptr++ = val % BASE;
1632 val = val / BASE;
1634 /* Extract remaining digits. */
1635 while (val != 0)
1637 *bptr++ = val % BASE;
1638 val = val / BASE;
1639 ix++; /* Count the digits. */
1642 /* Make the number. */
1643 bc_free_num (num);
1644 *num = bc_new_num (ix, 0);
1645 if (neg) (*num)->n_sign = MINUS;
1647 /* Assign the digits. */
1648 vptr = (*num)->n_value;
1649 while (ix-- > 0)
1650 *vptr++ = *--bptr;
1653 /* Convert a numbers to a string. Base 10 only.*/
1655 char
1656 *num2str (num)
1657 bc_num num;
1659 char *str, *sptr;
1660 char *nptr;
1661 int index, signch;
1663 /* Allocate the string memory. */
1664 signch = ( num->n_sign == PLUS ? 0 : 1 ); /* Number of sign chars. */
1665 if (num->n_scale > 0)
1666 str = (char *) malloc (num->n_len + num->n_scale + 2 + signch);
1667 else
1668 str = (char *) malloc (num->n_len + 1 + signch);
1669 if (str == NULL) bc_out_of_memory();
1671 /* The negative sign if needed. */
1672 sptr = str;
1673 if (signch) *sptr++ = '-';
1675 /* Load the whole number. */
1676 nptr = num->n_value;
1677 for (index=num->n_len; index>0; index--)
1678 *sptr++ = BCD_CHAR(*nptr++);
1680 /* Now the fraction. */
1681 if (num->n_scale > 0)
1683 *sptr++ = '.';
1684 for (index=0; index<num->n_scale; index++)
1685 *sptr++ = BCD_CHAR(*nptr++);
1688 /* Terminate the string and return it! */
1689 *sptr = '\0';
1690 return (str);
1692 /* Convert strings to bc numbers. Base 10 only.*/
1694 void
1695 bc_str2num (num, str, scale)
1696 bc_num *num;
1697 char *str;
1698 int scale;
1700 int digits, strscale;
1701 char *ptr, *nptr;
1702 char zero_int;
1704 /* Prepare num. */
1705 bc_free_num (num);
1707 /* Check for valid number and count digits. */
1708 ptr = str;
1709 digits = 0;
1710 strscale = 0;
1711 zero_int = FALSE;
1712 if ( (*ptr == '+') || (*ptr == '-')) ptr++; /* Sign */
1713 while (*ptr == '0') ptr++; /* Skip leading zeros. */
1714 while (isdigit((int)*ptr)) ptr++, digits++; /* digits */
1715 if (*ptr == '.') ptr++; /* decimal point */
1716 while (isdigit((int)*ptr)) ptr++, strscale++; /* digits */
1717 if ((*ptr != '\0') || (digits+strscale == 0))
1719 *num = bc_copy_num (_zero_);
1720 return;
1723 /* Adjust numbers and allocate storage and initialize fields. */
1724 strscale = MIN(strscale, scale);
1725 if (digits == 0)
1727 zero_int = TRUE;
1728 digits = 1;
1730 *num = bc_new_num (digits, strscale);
1732 /* Build the whole number. */
1733 ptr = str;
1734 if (*ptr == '-')
1736 (*num)->n_sign = MINUS;
1737 ptr++;
1739 else
1741 (*num)->n_sign = PLUS;
1742 if (*ptr == '+') ptr++;
1744 while (*ptr == '0') ptr++; /* Skip leading zeros. */
1745 nptr = (*num)->n_value;
1746 if (zero_int)
1748 *nptr++ = 0;
1749 digits = 0;
1751 for (;digits > 0; digits--)
1752 *nptr++ = CH_VAL(*ptr++);
1755 /* Build the fractional part. */
1756 if (strscale > 0)
1758 ptr++; /* skip the decimal point! */
1759 for (;strscale > 0; strscale--)
1760 *nptr++ = CH_VAL(*ptr++);
1764 /* pn prints the number NUM in base 10. */
1766 static void
1767 out_char (int c)
1769 putchar(c);
1773 void
1774 pn (num)
1775 bc_num num;
1777 bc_out_num (num, 10, out_char, 0);
1778 out_char ('\n');
1782 /* pv prints a character array as if it was a string of bcd digits. */
1783 void
1784 pv (name, num, len)
1785 char *name;
1786 unsigned char *num;
1787 int len;
1789 int i;
1790 printf ("%s=", name);
1791 for (i=0; i<len; i++) printf ("%c",BCD_CHAR(num[i]));
1792 printf ("\n");