1 /* number.c: Implements arbitrary precision numbers. */
3 /* This file is part of bc written for MINIX.
4 Copyright (C) 1991, 1992 Free Software Foundation, Inc.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License , or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20 You may contact the author by:
21 e-mail: phil@cs.wwu.edu
22 us-mail: Philip A. Nelson
23 Computer Science Department, 9062
24 Western Washington University
25 Bellingham, WA 98226-9062
27 *************************************************************************/
32 /* Storage used for special numbers. */
38 /* "Frees" a bc_num NUM. Actually decreases reference count and only
39 frees the storage if reference count is zero. */
45 if (*num == NULL) return;
47 if ((*num)->n_refs == 0) free(*num);
52 /* new_num allocates a number and sets fields to known values. */
55 new_num (length, scale)
60 temp = (bc_num) malloc (sizeof(bc_struct)+length+scale);
61 if (temp == NULL) out_of_memory ();
64 temp->n_scale = scale;
71 /* Intitialize the number package! */
76 _zero_ = new_num (1,0);
77 _one_ = new_num (1,0);
78 _one_->n_value[0] = 1;
79 _two_ = new_num (1,0);
80 _two_->n_value[0] = 2;
84 /* Make a copy of a number! Just increments the reference count! */
95 /* Initialize a number NUM by making it a copy of zero. */
101 *num = copy_num (_zero_);
105 /* Convert an integer VAL to a bc number NUM. */
124 /* Get things going. */
129 /* Extract remaining digits. */
134 ix++; /* Count the digits. */
137 /* Make the number. */
139 *num = new_num (ix, 0);
140 if (neg) (*num)->n_sign = MINUS;
142 /* Assign the digits. */
143 vptr = (*num)->n_value;
149 /* Convert a number NUM to a long. The function returns only the integer
150 part of the number. For numbers that are too large to represent as
151 a long, this function returns a zero. This can be detected by checking
152 the NUM for zero after having a zero returned. */
162 /* Extract the int value, ignore the fraction. */
165 for (index=num->n_len; (index>0) && (val<=(LONG_MAX/10)); index--)
166 val = val*10 + *nptr++;
168 /* Check for overflow. If overflow, return zero. */
169 if (index>0) val = 0;
170 if (val < 0) val = 0;
172 /* Return the value. */
173 if (num->n_sign == PLUS)
180 /* The following are some math routines for numbers. */
181 _PROTOTYPE(static int _do_compare, (bc_num n1, bc_num n2, int use_sign,
183 _PROTOTYPE(static void _rm_leading_zeros, (bc_num num));
184 _PROTOTYPE(static bc_num _do_add, (bc_num n1, bc_num n2));
185 _PROTOTYPE(static bc_num _do_sub, (bc_num n1, bc_num n2));
186 _PROTOTYPE(static void _one_mult, (unsigned char *num, int size, int digit,
187 unsigned char *result));
191 /* Compare two bc numbers. Return value is 0 if equal, -1 if N1 is less
192 than N2 and +1 if N1 is greater than N2. If USE_SIGN is false, just
193 compare the magnitudes. */
196 _do_compare (n1, n2, use_sign, ignore_last)
204 /* First, compare signs. */
205 if (use_sign && n1->n_sign != n2->n_sign)
207 if (n1->n_sign == PLUS)
208 return (1); /* Positive N1 > Negative N2 */
210 return (-1); /* Negative N1 < Positive N1 */
213 /* Now compare the magnitude. */
214 if (n1->n_len != n2->n_len)
216 if (n1->n_len > n2->n_len)
218 /* Magnitude of n1 > n2. */
219 if (!use_sign || n1->n_sign == PLUS)
226 /* Magnitude of n1 < n2. */
227 if (!use_sign || n1->n_sign == PLUS)
234 /* If we get here, they have the same number of integer digits.
235 check the integer part and the equal length part of the fraction. */
236 count = n1->n_len + MIN (n1->n_scale, n2->n_scale);
240 while ((count > 0) && (*n1ptr == *n2ptr))
246 if (ignore_last && count == 1 && n1->n_scale == n2->n_scale)
252 /* Magnitude of n1 > n2. */
253 if (!use_sign || n1->n_sign == PLUS)
260 /* Magnitude of n1 < n2. */
261 if (!use_sign || n1->n_sign == PLUS)
268 /* They are equal up to the last part of the equal part of the fraction. */
269 if (n1->n_scale != n2->n_scale)
270 if (n1->n_scale > n2->n_scale)
272 for (count = n1->n_scale-n2->n_scale; count>0; count--)
275 /* Magnitude of n1 > n2. */
276 if (!use_sign || n1->n_sign == PLUS)
284 for (count = n2->n_scale-n1->n_scale; count>0; count--)
287 /* Magnitude of n1 < n2. */
288 if (!use_sign || n1->n_sign == PLUS)
295 /* They must be equal! */
300 /* This is the "user callable" routine to compare numbers N1 and N2. */
306 return _do_compare (n1, n2, TRUE, FALSE);
310 /* In some places we need to check if the number NUM is zero. */
320 if (num == _zero_) return TRUE;
323 count = num->n_len + num->n_scale;
327 while ((count > 0) && (*nptr++ == 0)) count--;
336 /* In some places we need to check if the number is negative. */
342 return num->n_sign == MINUS;
346 /* For many things, we may have leading zeros in a number NUM.
347 _rm_leading_zeros just moves the data to the correct
348 place and adjusts the length. */
351 _rm_leading_zeros (num)
357 /* Do a quick check to see if we need to do it. */
358 if (*num->n_value != 0) return;
360 /* The first digit is 0, find the first non-zero digit in the 10's or
364 while (bytes > 1 && *src == 0) src++, bytes--;
366 bytes += num->n_scale;
368 while (bytes-- > 0) *dst++ = *src++;
373 /* Perform addition: N1 is added to N2 and the value is
374 returned. The signs of N1 and N2 are ignored. */
381 int sum_scale, sum_digits;
382 char *n1ptr, *n2ptr, *sumptr;
383 int carry, n1bytes, n2bytes;
386 sum_scale = MAX (n1->n_scale, n2->n_scale);
387 sum_digits = MAX (n1->n_len, n2->n_len) + 1;
388 sum = new_num (sum_digits,sum_scale);
390 /* Start with the fraction part. Initialize the pointers. */
391 n1bytes = n1->n_scale;
392 n2bytes = n2->n_scale;
393 n1ptr = (char *) (n1->n_value + n1->n_len + n1bytes - 1);
394 n2ptr = (char *) (n2->n_value + n2->n_len + n2bytes - 1);
395 sumptr = (char *) (sum->n_value + sum_scale + sum_digits - 1);
397 /* Add the fraction part. First copy the longer fraction.*/
398 if (n1bytes != n2bytes)
400 if (n1bytes > n2bytes)
401 while (n1bytes>n2bytes)
402 { *sumptr-- = *n1ptr--; n1bytes--;}
404 while (n2bytes>n1bytes)
405 { *sumptr-- = *n2ptr--; n2bytes--;}
408 /* Now add the remaining fraction part and equal size integer parts. */
409 n1bytes += n1->n_len;
410 n2bytes += n2->n_len;
412 while ((n1bytes > 0) && (n2bytes > 0))
414 *sumptr = *n1ptr-- + *n2ptr-- + carry;
427 /* Now add carry the longer integer part. */
429 { n1bytes = n2bytes; n1ptr = n2ptr; }
430 while (n1bytes-- > 0)
432 *sumptr = *n1ptr-- + carry;
443 /* Set final carry. */
447 /* Adjust sum and return. */
448 _rm_leading_zeros (sum);
453 /* Perform subtraction: N2 is subtracted from N1 and the value is
454 returned. The signs of N1 and N2 are ignored. Also, N1 is
455 assumed to be larger than N2. */
462 int diff_scale, diff_len;
463 int min_scale, min_len;
464 char *n1ptr, *n2ptr, *diffptr;
465 int borrow, count, val;
467 /* Allocate temporary storage. */
468 diff_len = MAX (n1->n_len, n2->n_len);
469 diff_scale = MAX (n1->n_scale, n2->n_scale);
470 min_len = MIN (n1->n_len, n2->n_len);
471 min_scale = MIN (n1->n_scale, n2->n_scale);
472 diff = new_num (diff_len, diff_scale);
474 /* Initialize the subtract. */
475 n1ptr = (char *) (n1->n_value + n1->n_len + n1->n_scale -1);
476 n2ptr = (char *) (n2->n_value + n2->n_len + n2->n_scale -1);
477 diffptr = (char *) (diff->n_value + diff_len + diff_scale -1);
479 /* Subtract the numbers. */
482 /* Take care of the longer scaled number. */
483 if (n1->n_scale != min_scale)
485 /* n1 has the longer scale */
486 for (count = n1->n_scale - min_scale; count > 0; count--)
487 *diffptr-- = *n1ptr--;
491 /* n2 has the longer scale */
492 for (count = n2->n_scale - min_scale; count > 0; count--)
494 val = - *n2ptr-- - borrow;
506 /* Now do the equal length scale and integer parts. */
508 for (count = 0; count < min_len + min_scale; count++)
510 val = *n1ptr-- - *n2ptr-- - borrow;
521 /* If n1 has more digits then n2, we now do that subtract. */
522 if (diff_len != min_len)
524 for (count = diff_len - min_len; count > 0; count--)
526 val = *n1ptr-- - borrow;
538 /* Clean up and return. */
539 _rm_leading_zeros (diff);
544 /* Here is the full add routine that takes care of negative numbers.
545 N1 is added to N2 and the result placed into RESULT. */
548 bc_add ( n1, n2, result)
549 bc_num n1, n2, *result;
554 if (n1->n_sign == n2->n_sign)
556 sum = _do_add (n1, n2);
557 sum->n_sign = n1->n_sign;
561 /* subtraction must be done. */
562 cmp_res = _do_compare (n1, n2, FALSE, FALSE); /* Compare magnitudes. */
566 /* n1 is less than n2, subtract n1 from n2. */
567 sum = _do_sub (n2, n1);
568 sum->n_sign = n2->n_sign;
571 /* They are equal! return zero! */
572 sum = copy_num (_zero_);
575 /* n2 is less than n1, subtract n2 from n1. */
576 sum = _do_sub (n1, n2);
577 sum->n_sign = n1->n_sign;
581 /* Clean up and return. */
587 /* Here is the full subtract routine that takes care of negative numbers.
588 N2 is subtracted from N1 and the result placed in RESULT. */
591 bc_sub ( n1, n2, result)
592 bc_num n1, n2, *result;
597 if (n1->n_sign != n2->n_sign)
599 diff = _do_add (n1, n2);
600 diff->n_sign = n1->n_sign;
604 /* subtraction must be done. */
605 cmp_res = _do_compare (n1, n2, FALSE, FALSE); /* Compare magnitudes. */
609 /* n1 is less than n2, subtract n1 from n2. */
610 diff = _do_sub (n2, n1);
611 diff->n_sign = (n2->n_sign == PLUS ? MINUS : PLUS);
614 /* They are equal! return zero! */
615 diff = copy_num (_zero_);
618 /* n2 is less than n1, subtract n2 from n1. */
619 diff = _do_sub (n1, n2);
620 diff->n_sign = n1->n_sign;
625 /* Clean up and return. */
631 /* The multiply routine. N2 time N1 is put int PROD with the scale of
632 the result being MIN(N2 scale+N1 scale, MAX (SCALE, N2 scale, N1 scale)).
636 bc_multiply (n1, n2, prod, scale)
637 bc_num n1, n2, *prod;
640 bc_num pval; /* For the working storage. */
641 char *n1ptr, *n2ptr, *pvptr; /* Work pointers. */
642 char *n1end, *n2end; /* To the end of n1 and n2. */
645 int len1, len2, total_digits;
647 int full_scale, prod_scale;
650 /* Initialize things. */
651 len1 = n1->n_len + n1->n_scale;
652 len2 = n2->n_len + n2->n_scale;
653 total_digits = len1 + len2;
654 full_scale = n1->n_scale + n2->n_scale;
655 prod_scale = MIN(full_scale,MAX(scale,MAX(n1->n_scale,n2->n_scale)));
656 toss = full_scale - prod_scale;
657 pval = new_num (total_digits-full_scale, prod_scale);
658 pval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS );
659 n1end = (char *) (n1->n_value + len1 - 1);
660 n2end = (char *) (n2->n_value + len2 - 1);
661 pvptr = (char *) (pval->n_value + total_digits - toss - 1);
664 /* Here are the loops... */
665 for (indx = 0; indx < toss; indx++)
667 n1ptr = (char *) (n1end - MAX(0, indx-len2+1));
668 n2ptr = (char *) (n2end - MIN(indx, len2-1));
669 while ((n1ptr >= n1->n_value) && (n2ptr <= n2end))
670 sum += *n1ptr-- * *n2ptr++;
673 for ( ; indx < total_digits-1; indx++)
675 n1ptr = (char *) (n1end - MAX(0, indx-len2+1));
676 n2ptr = (char *) (n2end - MIN(indx, len2-1));
677 while ((n1ptr >= n1->n_value) && (n2ptr <= n2end))
678 sum += *n1ptr-- * *n2ptr++;
684 /* Assign to prod and clean up the number. */
687 _rm_leading_zeros (*prod);
689 (*prod)->n_sign = PLUS;
693 /* Some utility routines for the divide: First a one digit multiply.
694 NUM (with SIZE digits) is multiplied by DIGIT and the result is
695 placed into RESULT. It is written so that NUM and RESULT can be
696 the same pointers. */
699 _one_mult (num, size, digit, result)
702 unsigned char *result;
705 unsigned char *nptr, *rptr;
708 memset (result, 0, size);
712 memcpy (result, num, size);
716 nptr = (unsigned char *) (num+size-1);
717 rptr = (unsigned char *) (result+size-1);
722 value = *nptr-- * digit + carry;
723 *rptr-- = value % 10;
727 if (carry != 0) *rptr = carry;
733 /* The full division routine. This computes N1 / N2. It returns
734 0 if the division is ok and the result is in QUOT. The number of
735 digits after the decimal point is SCALE. It returns -1 if division
736 by zero is tried. The algorithm is found in Knuth Vol 2. p237. */
739 bc_divide (n1, n2, quot, scale)
740 bc_num n1, n2, *quot;
744 unsigned char *num1, *num2;
745 unsigned char *ptr1, *ptr2, *n2ptr, *qptr;
747 unsigned int len1, len2, scale2, qdigits, extra, count;
748 unsigned int qdig, qguess, borrow, carry;
753 /* Test for divide by zero. */
754 if (is_zero (n2)) return -1;
756 /* Test for divide by 1. If it is we must truncate. */
757 if (n2->n_scale == 0)
759 if (n2->n_len == 1 && *n2->n_value == 1)
761 qval = new_num (n1->n_len, scale);
762 qval->n_sign = (n1->n_sign == n2->n_sign ? PLUS : MINUS);
763 memset (&qval->n_value[n1->n_len],0,scale);
764 memcpy (qval->n_value, n1->n_value,
765 n1->n_len + MIN(n1->n_scale,scale));
771 /* Set up the divide. Move the decimal point on n1 by n2's scale.
772 Remember, zeros on the end of num2 are wasted effort for dividing. */
773 scale2 = n2->n_scale;
774 n2ptr = (unsigned char *) n2->n_value+n2->n_len+scale2-1;
775 while ((scale2 > 0) && (*n2ptr-- == 0)) scale2--;
777 len1 = n1->n_len + scale2;
778 scale1 = n1->n_scale - scale2;
780 extra = scale - scale1;
783 num1 = (unsigned char *) malloc (n1->n_len+n1->n_scale+extra+2);
784 if (num1 == NULL) out_of_memory();
785 memset (num1, 0, n1->n_len+n1->n_scale+extra+2);
786 memcpy (num1+1, n1->n_value, n1->n_len+n1->n_scale);
788 len2 = n2->n_len + scale2;
789 num2 = (unsigned char *) malloc (len2+1);
790 if (num2 == NULL) out_of_memory();
791 memcpy (num2, n2->n_value, len2);
800 /* Calculate the number of quotient digits. */
801 if (len2 > len1+scale)
810 qdigits = scale+1; /* One for the zero integer part. */
812 qdigits = len1-len2+scale+1;
815 /* Allocate and zero the storage for the quotient. */
816 qval = new_num (qdigits-scale,scale);
817 memset (qval->n_value, 0, qdigits);
819 /* Allocate storage for the temporary storage mval. */
820 mval = (unsigned char *) malloc (len2+1);
821 if (mval == NULL) out_of_memory ();
823 /* Now for the full divide algorithm. */
827 norm = 10 / ((int)*n2ptr + 1);
830 _one_mult (num1, len1+scale1+extra+1, norm, num1);
831 _one_mult (n2ptr, len2, norm, n2ptr);
834 /* Initialize divide loop. */
837 qptr = (unsigned char *) qval->n_value+len2-len1;
839 qptr = (unsigned char *) qval->n_value;
842 while (qdig <= len1+scale-len2)
844 /* Calculate the quotient digit guess. */
845 if (*n2ptr == num1[qdig])
848 qguess = (num1[qdig]*10 + num1[qdig+1]) / *n2ptr;
851 if (n2ptr[1]*qguess >
852 (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10
857 if (n2ptr[1]*qguess >
858 (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10
863 /* Multiply and subtract. */
868 _one_mult (n2ptr, len2, qguess, mval+1);
869 ptr1 = (unsigned char *) num1+qdig+len2;
870 ptr2 = (unsigned char *) mval+len2;
871 for (count = 0; count < len2+1; count++)
873 val = (int) *ptr1 - (int) *ptr2-- - borrow;
885 /* Test for negative result. */
889 ptr1 = (unsigned char *) num1+qdig+len2;
890 ptr2 = (unsigned char *) n2ptr+len2-1;
892 for (count = 0; count < len2; count++)
894 val = (int) *ptr1 + (int) *ptr2-- + carry;
904 if (carry == 1) *ptr1 = (*ptr1 + 1) % 10;
907 /* We now know the quotient digit. */
913 /* Clean up and return the number. */
914 qval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS );
915 if (is_zero (qval)) qval->n_sign = PLUS;
916 _rm_leading_zeros (qval);
920 /* Clean up temporary storage. */
925 return 0; /* Everything is OK. */
929 /* Modulo for numbers. This computes NUM1 % NUM2 and puts the
933 bc_modulo (num1, num2, result, scale)
934 bc_num num1, num2, *result;
940 /* Check for correct numbers. */
941 if (is_zero (num2)) return -1;
943 /* Calculate final scale. */
944 rscale = MAX (num1->n_scale, num2->n_scale+scale);
948 bc_divide (num1, num2, &temp, scale);
949 bc_multiply (temp, num2, &temp, rscale);
950 bc_sub (num1, temp, result);
953 return 0; /* Everything is OK. */
957 /* Raise NUM1 to the NUM2 power. The result is placed in RESULT.
958 Maximum exponent is LONG_MAX. If a NUM2 is not an integer,
959 only the integer part is used. */
962 bc_raise (num1, num2, result, scale)
963 bc_num num1, num2, *result;
971 /* Check the exponent for scale digits and convert to a long. */
972 if (num2->n_scale != 0)
973 rt_warn ("non-zero scale in exponent");
974 exponent = num2long (num2);
975 if (exponent == 0 && (num2->n_len > 1 || num2->n_value[0] != 0))
976 rt_error ("exponent too large in raise");
978 /* Special case if exponent is a zero. */
982 *result = copy_num (_one_);
986 /* Other initializations. */
990 exponent = -exponent;
996 rscale = MIN (num1->n_scale*exponent, MAX(scale, num1->n_scale));
998 temp = copy_num (_one_);
999 power = copy_num (num1);
1001 /* Do the calculation. */
1002 while (exponent != 0)
1004 if (exponent & 1 != 0)
1005 bc_multiply (temp, power, &temp, rscale);
1006 bc_multiply (power, power, &power, rscale);
1007 exponent = exponent >> 1;
1010 /* Assign the value. */
1013 bc_divide (_one_, temp, result, rscale);
1025 /* Take the square root NUM and return it in NUM with SCALE digits
1026 after the decimal place. */
1029 bc_sqrt (num, scale)
1033 int rscale, cmp_res, done;
1035 bc_num guess, guess1, point5;
1037 /* Initial checks. */
1038 cmp_res = bc_compare (*num, _zero_);
1040 return 0; /* error */
1046 *num = copy_num (_zero_);
1050 cmp_res = bc_compare (*num, _one_);
1054 *num = copy_num (_one_);
1058 /* Initialize the variables. */
1059 rscale = MAX (scale, (*num)->n_scale);
1060 cscale = rscale + 2;
1063 point5 = new_num (1,1);
1064 point5->n_value[1] = 5;
1067 /* Calculate the initial guess. */
1069 /* The number is between 0 and 1. Guess should start at 1. */
1070 guess = copy_num (_one_);
1073 /* The number is greater than 1. Guess should start at 10^(exp/2). */
1074 int2num (&guess,10);
1075 int2num (&guess1,(*num)->n_len);
1076 bc_multiply (guess1, point5, &guess1, rscale);
1077 guess1->n_scale = 0;
1078 bc_raise (guess, guess1, &guess, rscale);
1082 /* Find the square root using Newton's algorithm. */
1087 guess1 = copy_num (guess);
1088 bc_divide (*num,guess,&guess,cscale);
1089 bc_add (guess,guess1,&guess);
1090 bc_multiply (guess,point5,&guess,cscale);
1091 cmp_res = _do_compare (guess,guess1,FALSE,TRUE);
1092 if (cmp_res == 0) done = TRUE;
1095 /* Assign the number and clean up. */
1097 bc_divide (guess,_one_,num,rscale);
1105 /* The following routines provide output for bcd numbers package
1106 using the rules of POSIX bc for output. */
1108 /* This structure is used for saving digits in the conversion process. */
1109 typedef struct stk_rec {
1111 struct stk_rec *next;
1114 /* The reference string for digits. */
1115 char ref_str[] = "0123456789ABCDEF";
1118 /* A special output routine for "multi-character digits." Exactly
1119 SIZE characters must be output for the value VAL. If SPACE is
1120 non-zero, we must output one space before the number. OUT_CHAR
1121 is the actual routine for writing the characters. */
1124 out_long (val, size, space, out_char)
1128 void (*out_char)(int);
1136 if (space) (*out_char) (' ');
1137 sprintf (digits, "%ld", val);
1138 len = strlen (digits);
1144 for (ix=0; ix < len; ix++)
1145 (*out_char) (digits[ix]);
1148 /* Output of a bcd number. NUM is written in base O_BASE using OUT_CHAR
1149 as the routine to do the actual output of the characters. */
1152 out_num (num, o_base, out_char)
1156 void (*out_char)(int);
1162 int index, fdigit, pre_space;
1163 stk_rec *digits, *temp;
1164 bc_num int_part, frac_part, base, cur_dig, t_num, max_o_digit;
1166 /* The negative sign if needed. */
1167 if (num->n_sign == MINUS) (*out_char) ('-');
1169 /* Output the number. */
1175 /* The number is in base 10, do it the fast way. */
1176 nptr = num->n_value;
1177 if (num->n_len > 1 || *nptr != 0)
1178 for (index=num->n_len; index>0; index--)
1179 (*out_char) (BCD_CHAR(*nptr++));
1183 /* Now the fraction. */
1184 if (num->n_scale > 0)
1187 for (index=0; index<num->n_scale; index++)
1188 (*out_char) (BCD_CHAR(*nptr++));
1193 /* The number is some other base. */
1195 init_num (&int_part);
1196 bc_divide (num, _one_, &int_part, 0);
1197 init_num (&frac_part);
1198 init_num (&cur_dig);
1200 bc_sub (num, int_part, &frac_part);
1201 int2num (&base, o_base);
1202 init_num (&max_o_digit);
1203 int2num (&max_o_digit, o_base-1);
1206 /* Get the digits of the integer part and push them on a stack. */
1207 while (!is_zero (int_part))
1209 bc_modulo (int_part, base, &cur_dig, 0);
1210 temp = (stk_rec *) malloc (sizeof(stk_rec));
1211 if (temp == NULL) out_of_memory();
1212 temp->digit = num2long (cur_dig);
1213 temp->next = digits;
1215 bc_divide (int_part, base, &int_part, 0);
1218 /* Print the digits on the stack. */
1221 /* Output the digits. */
1222 while (digits != NULL)
1225 digits = digits->next;
1227 (*out_char) (ref_str[ (int) temp->digit]);
1229 out_long (temp->digit, max_o_digit->n_len, 1, out_char);
1234 /* Get and print the digits of the fraction part. */
1235 if (num->n_scale > 0)
1239 t_num = copy_num (_one_);
1240 while (t_num->n_len <= num->n_scale) {
1241 bc_multiply (frac_part, base, &frac_part, num->n_scale);
1242 fdigit = num2long (frac_part);
1243 int2num (&int_part, fdigit);
1244 bc_sub (frac_part, int_part, &frac_part);
1246 (*out_char) (ref_str[fdigit]);
1248 out_long (fdigit, max_o_digit->n_len, pre_space, out_char);
1251 bc_multiply (t_num, base, &t_num, 0);
1256 free_num (&int_part);
1257 free_num (&frac_part);
1259 free_num (&cur_dig);
1266 /* Debugging procedures. Some are just so one can call them from the
1269 /* p_n prints the number NUM in base 10. */
1275 out_num (num, 10, out_char);
1280 /* p_b prints a character array as if it was a string of bcd digits. */
1282 p_v (name, num, len)
1288 printf ("%s=", name);
1289 for (i=0; i<len; i++) printf ("%c",BCD_CHAR(num[i]));
1294 /* Convert strings to bc numbers. Base 10 only.*/
1297 str2num (num, str, scale)
1302 int digits, strscale;
1309 /* Check for valid number and count digits. */
1314 if ( (*ptr == '+') || (*ptr == '-')) ptr++; /* Sign */
1315 while (*ptr == '0') ptr++; /* Skip leading zeros. */
1316 while (isdigit(*ptr)) ptr++, digits++; /* digits */
1317 if (*ptr == '.') ptr++; /* decimal point */
1318 while (isdigit(*ptr)) ptr++, strscale++; /* digits */
1319 if ((*ptr != '\0') || (digits+strscale == 0))
1321 *num = copy_num (_zero_);
1325 /* Adjust numbers and allocate storage and initialize fields. */
1326 strscale = MIN(strscale, scale);
1332 *num = new_num (digits, strscale);
1334 /* Build the whole number. */
1338 (*num)->n_sign = MINUS;
1343 (*num)->n_sign = PLUS;
1344 if (*ptr == '+') ptr++;
1346 while (*ptr == '0') ptr++; /* Skip leading zeros. */
1347 nptr = (*num)->n_value;
1353 for (;digits > 0; digits--)
1354 *nptr++ = CH_VAL(*ptr++);
1357 /* Build the fractional part. */
1360 ptr++; /* skip the decimal point! */
1361 for (;strscale > 0; strscale--)
1362 *nptr++ = CH_VAL(*ptr++);
1366 /* Convert a numbers to a string. Base 10 only.*/
1376 /* Allocate the string memory. */
1377 signch = ( num->n_sign == PLUS ? 0 : 1 ); /* Number of sign chars. */
1378 if (num->n_scale > 0)
1379 str = (char *) malloc (num->n_len + num->n_scale + 2 + signch);
1381 str = (char *) malloc (num->n_len + 1 + signch);
1382 if (str == NULL) out_of_memory();
1384 /* The negative sign if needed. */
1386 if (signch) *sptr++ = '-';
1388 /* Load the whole number. */
1389 nptr = num->n_value;
1390 for (index=num->n_len; index>0; index--)
1391 *sptr++ = BCD_CHAR(*nptr++);
1393 /* Now the fraction. */
1394 if (num->n_scale > 0)
1397 for (index=0; index<num->n_scale; index++)
1398 *sptr++ = BCD_CHAR(*nptr++);
1401 /* Terminate the string and return it! */