This source file includes following definitions.
- _one_mult
- bc_divide
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 #include <config.h>
33 #include <stdio.h>
34 #include <assert.h>
35 #include <stdlib.h>
36 #include <ctype.h>
37 #include <stdarg.h>
38 #include "bcmath.h"
39 #include "private.h"
40
41
42
43
44
45
46
47 static void
48 _one_mult (num, size, digit, result)
49 unsigned char *num;
50 int size, digit;
51 unsigned char *result;
52 {
53 int carry, value;
54 unsigned char *nptr, *rptr;
55
56 if (digit == 0)
57 memset (result, 0, size);
58 else
59 {
60 if (digit == 1)
61 memcpy (result, num, size);
62 else
63 {
64
65 nptr = (unsigned char *) (num+size-1);
66 rptr = (unsigned char *) (result+size-1);
67 carry = 0;
68
69 while (size-- > 0)
70 {
71 value = *nptr-- * digit + carry;
72 *rptr-- = value % BASE;
73 carry = value / BASE;
74 }
75
76 if (carry != 0) *rptr = carry;
77 }
78 }
79 }
80
81
82
83
84
85
86
87 int
88 bc_divide (bc_num n1, bc_num n2, bc_num *quot, int scale)
89 {
90 bc_num qval;
91 unsigned char *num1, *num2;
92 unsigned char *ptr1, *ptr2, *n2ptr, *qptr;
93 int scale1, val;
94 unsigned int len1, len2, scale2, qdigits, extra, count;
95 unsigned int qdig, qguess, borrow, carry;
96 unsigned char *mval;
97 char zero;
98 unsigned int norm;
99
100
101 if (bc_is_zero (n2)) return -1;
102
103
104 if (n2->n_scale == 0)
105 {
106 if (n2->n_len == 1 && *n2->n_value == 1)
107 {
108 qval = bc_new_num (n1->n_len, scale);
109 qval->n_sign = (n1->n_sign == n2->n_sign ? PLUS : MINUS);
110 memset (&qval->n_value[n1->n_len],0,scale);
111 memcpy (qval->n_value, n1->n_value,
112 n1->n_len + MIN(n1->n_scale,scale));
113 bc_free_num (quot);
114 *quot = qval;
115 }
116 }
117
118
119
120 scale2 = n2->n_scale;
121 n2ptr = (unsigned char *) n2->n_value+n2->n_len+scale2-1;
122 while ((scale2 > 0) && (*n2ptr-- == 0)) scale2--;
123
124 len1 = n1->n_len + scale2;
125 scale1 = n1->n_scale - scale2;
126 if (scale1 < scale)
127 extra = scale - scale1;
128 else
129 extra = 0;
130 num1 = (unsigned char *) safe_emalloc (1, n1->n_len+n1->n_scale, extra+2);
131 if (num1 == NULL) bc_out_of_memory();
132 memset (num1, 0, n1->n_len+n1->n_scale+extra+2);
133 memcpy (num1+1, n1->n_value, n1->n_len+n1->n_scale);
134
135 len2 = n2->n_len + scale2;
136 num2 = (unsigned char *) safe_emalloc (1, len2, 1);
137 if (num2 == NULL) bc_out_of_memory();
138 memcpy (num2, n2->n_value, len2);
139 *(num2+len2) = 0;
140 n2ptr = num2;
141 while (*n2ptr == 0)
142 {
143 n2ptr++;
144 len2--;
145 }
146
147
148 if (len2 > len1+scale)
149 {
150 qdigits = scale+1;
151 zero = TRUE;
152 }
153 else
154 {
155 zero = FALSE;
156 if (len2>len1)
157 qdigits = scale+1;
158 else
159 qdigits = len1-len2+scale+1;
160 }
161
162
163 qval = bc_new_num (qdigits-scale,scale);
164 memset (qval->n_value, 0, qdigits);
165
166
167 mval = (unsigned char *) safe_emalloc (1, len2, 1);
168 if (mval == NULL) bc_out_of_memory ();
169
170
171 if (!zero)
172 {
173
174 norm = 10 / ((int)*n2ptr + 1);
175 if (norm != 1)
176 {
177 _one_mult (num1, len1+scale1+extra+1, norm, num1);
178 _one_mult (n2ptr, len2, norm, n2ptr);
179 }
180
181
182 qdig = 0;
183 if (len2 > len1)
184 qptr = (unsigned char *) qval->n_value+len2-len1;
185 else
186 qptr = (unsigned char *) qval->n_value;
187
188
189 while (qdig <= len1+scale-len2)
190 {
191
192 if (*n2ptr == num1[qdig])
193 qguess = 9;
194 else
195 qguess = (num1[qdig]*10 + num1[qdig+1]) / *n2ptr;
196
197
198 if (n2ptr[1]*qguess >
199 (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10
200 + num1[qdig+2])
201 {
202 qguess--;
203
204 if (n2ptr[1]*qguess >
205 (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10
206 + num1[qdig+2])
207 qguess--;
208 }
209
210
211 borrow = 0;
212 if (qguess != 0)
213 {
214 *mval = 0;
215 _one_mult (n2ptr, len2, qguess, mval+1);
216 ptr1 = (unsigned char *) num1+qdig+len2;
217 ptr2 = (unsigned char *) mval+len2;
218 for (count = 0; count < len2+1; count++)
219 {
220 val = (int) *ptr1 - (int) *ptr2-- - borrow;
221 if (val < 0)
222 {
223 val += 10;
224 borrow = 1;
225 }
226 else
227 borrow = 0;
228 *ptr1-- = val;
229 }
230 }
231
232
233 if (borrow == 1)
234 {
235 qguess--;
236 ptr1 = (unsigned char *) num1+qdig+len2;
237 ptr2 = (unsigned char *) n2ptr+len2-1;
238 carry = 0;
239 for (count = 0; count < len2; count++)
240 {
241 val = (int) *ptr1 + (int) *ptr2-- + carry;
242 if (val > 9)
243 {
244 val -= 10;
245 carry = 1;
246 }
247 else
248 carry = 0;
249 *ptr1-- = val;
250 }
251 if (carry == 1) *ptr1 = (*ptr1 + 1) % 10;
252 }
253
254
255 *qptr++ = qguess;
256 qdig++;
257 }
258 }
259
260
261 qval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS );
262 if (bc_is_zero (qval)) qval->n_sign = PLUS;
263 _bc_rm_leading_zeros (qval);
264 bc_free_num (quot);
265 *quot = qval;
266
267
268 efree (mval);
269 efree (num1);
270 efree (num2);
271
272 return 0;
273 }
274