41 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000
49static inline void bc_fast_div(
52 size_t numerator_top_index = numerator_arr_size - 1;
53 size_t quot_top_index = quot_arr_size - 1;
54 for (
size_t i = 0; i < quot_arr_size - 1; i++) {
55 if (numerator_vectors[numerator_top_index - i] < divisor_vector) {
56 quot_vectors[quot_top_index - i] = 0;
58 numerator_vectors[numerator_top_index - i - 1] += numerator_vectors[numerator_top_index - i] *
BC_VECTOR_BOUNDARY_NUM;
61 quot_vectors[quot_top_index - i] = numerator_vectors[numerator_top_index - i] / divisor_vector;
62 numerator_vectors[numerator_top_index - i] -= divisor_vector * quot_vectors[quot_top_index - i];
63 numerator_vectors[numerator_top_index - i - 1] += numerator_vectors[numerator_top_index - i] *
BC_VECTOR_BOUNDARY_NUM;
64 numerator_vectors[numerator_top_index - i] = 0;
67 quot_vectors[0] = numerator_vectors[0] / divisor_vector;
75static inline void bc_standard_div(
76 BC_VECTOR *numerator_vectors,
size_t numerator_arr_size,
77 BC_VECTOR *divisor_vectors,
size_t divisor_arr_size,
size_t divisor_len,
78 BC_VECTOR *quot_vectors,
size_t quot_arr_size
80 size_t numerator_top_index = numerator_arr_size - 1;
81 size_t divisor_top_index = divisor_arr_size - 1;
82 size_t quot_top_index = quot_arr_size - 1;
173 if (divisor_top_digits == 0) {
177 size_t high_part_shift = POW_10_LUT[
BC_VECTOR_SIZE - divisor_top_digits + 1];
178 size_t low_part_shift = POW_10_LUT[divisor_top_digits - 1];
179 BC_VECTOR divisor_high_part = divisor_vectors[divisor_top_index] * high_part_shift + divisor_vectors[divisor_top_index - 1] / low_part_shift;
180 for (
size_t i = 0; i < quot_arr_size; i++) {
181 BC_VECTOR numerator_high_part = numerator_vectors[numerator_top_index - i] * high_part_shift + numerator_vectors[numerator_top_index - i - 1] / low_part_shift;
193 if (numerator_high_part < divisor_high_part) {
194 quot_vectors[quot_top_index - i] = 0;
195 div_carry = numerator_vectors[numerator_top_index - i];
196 numerator_vectors[numerator_top_index - i] = 0;
200 BC_VECTOR quot_guess = numerator_high_part / divisor_high_part;
209 if (quot_guess == 0) {
210 quot_vectors[quot_top_index - i] = 0;
211 div_carry = numerator_vectors[numerator_top_index - i];
212 numerator_vectors[numerator_top_index - i] = 0;
219 BC_VECTOR *numerator_calc_bottom = numerator_vectors + numerator_arr_size - divisor_arr_size - i;
221 for (
j = 0;
j < divisor_arr_size - 1;
j++) {
222 sub = divisor_vectors[
j] * quot_guess + borrow;
226 if (numerator_calc_bottom[
j] >= sub_low) {
227 numerator_calc_bottom[
j] -= sub_low;
234 sub = divisor_vectors[
j] * quot_guess + borrow;
235 bool neg_remainder = numerator_calc_bottom[
j] < sub;
236 numerator_calc_bottom[
j] -= sub;
242 for (
j = 0;
j < divisor_arr_size - 1;
j++) {
243 numerator_calc_bottom[
j] += divisor_vectors[
j] + carry;
248 numerator_calc_bottom[
j] += divisor_vectors[
j] + carry;
251 quot_vectors[quot_top_index - i] = quot_guess;
252 div_carry = numerator_vectors[numerator_top_index - i];
253 numerator_vectors[numerator_top_index - i] = 0;
257static void bc_do_div(
258 const char *numerator,
size_t numerator_readable_len,
size_t numerator_bottom_extension,
259 const char *divisor,
size_t divisor_len,
bc_num *quot,
size_t quot_len
263 size_t quot_arr_size = numerator_arr_size - divisor_arr_size + 1;
267 BC_VECTOR *divisor_vectors = numerator_vectors + numerator_arr_size;
268 BC_VECTOR *quot_vectors = divisor_vectors + divisor_arr_size;
271 size_t numerator_vector_count = 0;
273 numerator_vectors[numerator_vector_count] = 0;
275 numerator_vector_count++;
278 size_t numerator_bottom_read_len =
BC_VECTOR_SIZE - numerator_bottom_extension;
281 size_t numerator_read = 0;
283 numerator_read =
MIN(numerator_bottom_read_len, numerator_readable_len);
284 base = POW_10_LUT[numerator_bottom_extension];
285 numerator_vectors[numerator_vector_count] = 0;
286 for (
size_t i = 0; i < numerator_read; i++) {
287 numerator_vectors[numerator_vector_count] += *numerator * base;
291 numerator_vector_count++;
295 if (numerator_readable_len > numerator_read) {
296 bc_convert_to_vector(numerator_vectors + numerator_vector_count, numerator, numerator_readable_len - numerator_read);
298 bc_convert_to_vector(divisor_vectors, divisor, divisor_len);
301 if (divisor_arr_size == 1) {
302 bc_fast_div(numerator_vectors, numerator_arr_size, divisor_vectors[0], quot_vectors, quot_arr_size);
304 bc_standard_div(numerator_vectors, numerator_arr_size, divisor_vectors, divisor_arr_size, divisor_len, quot_vectors, quot_arr_size);
308 char *qptr = (*quot)->n_value;
309 char *qend = qptr + quot_len - 1;
312 for (i = 0; i < quot_real_arr_size - 1; i++) {
313#if BC_VECTOR_SIZE == 4
323 while (qend >= qptr) {
324 *qend-- = quot_vectors[i] %
BASE;
325 quot_vectors[i] /=
BASE;
328 efree(numerator_vectors);
348 size_t quot_scale =
MIN(numerator->
n_scale, scale);
350 char *qptr = (*quot)->n_value;
357 char *numeratorptr = numerator->
n_value;
358 char *numeratorend = numeratorptr + numerator->
n_len + numerator->
n_scale - 1;
359 size_t numerator_len = numerator->
n_len;
360 size_t numerator_scale = numerator->
n_scale;
362 char *divisorptr = divisor->
n_value;
363 char *divisorend = divisorptr + divisor->
n_len + divisor->
n_scale - 1;
364 size_t divisor_len = divisor->
n_len;
365 size_t divisor_scale = divisor->
n_scale;
366 size_t divisor_int_right_zeros = 0;
369 while (*divisorend == 0 && divisor_scale > 0) {
373 while (*divisorend == 0) {
375 divisor_int_right_zeros++;
378 if (*numeratorptr == 0 && numerator_len == 1) {
383 size_t numerator_top_extension = 0;
384 size_t numerator_bottom_extension = 0;
385 if (divisor_scale > 0) {
393 numerator_len += divisor_scale;
394 numerator_bottom_extension = numerator_scale < divisor_scale ? divisor_scale - numerator_scale : 0;
395 numerator_scale = numerator_scale > divisor_scale ? numerator_scale - divisor_scale : 0;
396 divisor_len += divisor_scale;
398 }
else if (divisor_int_right_zeros > 0) {
406 numerator_top_extension = numerator_len < divisor_int_right_zeros ? divisor_int_right_zeros - numerator_len : 0;
407 numerator_len = numerator_len > divisor_int_right_zeros ? numerator_len - divisor_int_right_zeros : 0;
408 numerator_scale += divisor_int_right_zeros;
409 divisor_len -= divisor_int_right_zeros;
414 while (*numeratorptr == 0 && numerator_len > 0) {
419 while (*divisorptr == 0) {
425 if (divisor_len > numerator_len + scale) {
431 size_t numerator_readable_len = numeratorend - numeratorptr + 1;
434 if (numerator_scale > scale) {
435 size_t scale_diff = numerator_scale - scale;
436 if (numerator_bottom_extension > scale_diff) {
437 numerator_bottom_extension -= scale_diff;
439 numerator_bottom_extension = 0;
440 if (
EXPECTED(numerator_readable_len > scale_diff)) {
441 numerator_readable_len -= scale_diff;
442 numeratorend -= scale_diff;
444 numerator_readable_len = 0;
445 numeratorend = numeratorptr;
448 numerator_top_extension =
MIN(numerator_top_extension, scale);
450 numerator_bottom_extension += scale - numerator_scale;
452 numerator_scale = scale;
454 if (divisor_len > numerator_readable_len + numerator_bottom_extension) {
460 if (divisor_len == 1 && *divisorptr == 1) {
461 if (numerator_len == 0) {
463 numerator_top_extension++;
465 size_t quot_scale = numerator_scale > numerator_bottom_extension ? numerator_scale - numerator_bottom_extension : 0;
466 numerator_bottom_extension = numerator_scale < numerator_bottom_extension ? numerator_bottom_extension - numerator_scale : 0;
469 char *qptr = (*quot)->n_value;
470 for (
size_t i = 0; i < numerator_top_extension; i++) {
473 memcpy(qptr, numeratorptr, numerator_readable_len);
474 qptr += numerator_readable_len;
475 for (
size_t i = 0; i < numerator_bottom_extension; i++) {
482 size_t quot_full_len;
483 if (divisor_len > numerator_len) {
485 quot_full_len = 1 + scale;
488 quot_full_len = numerator_len - divisor_len + 1 + scale;
492 bc_do_div(numeratorend, numerator_readable_len, numerator_bottom_extension, divisorend, divisor_len, quot, quot_full_len);
495 (*quot)->n_sign =
PLUS;
bool bc_is_zero(bc_num num)
struct bc_struct * bc_num
#define bc_new_num_nonzeroed(length, scale)
bcmath_compare_result _bc_do_compare(bc_num n1, bc_num n2, size_t scale, bool use_sign)
void bc_write_bcd_representation(uint32_t value, char *str)
bool bc_divide(bc_num numerator, bc_num divisor, bc_num *quot, size_t scale)
void _bc_rm_leading_zeros(bc_num num)
#define BC_VECTOR_BOUNDARY_NUM
#define safe_emalloc(nmemb, size, offset)
#define EXPECTED(condition)