1 /* 2 * ***************************************************************************** 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * Copyright (c) 2018-2021 Gavin D. Howard and contributors. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are met: 10 * 11 * * Redistributions of source code must retain the above copyright notice, this 12 * list of conditions and the following disclaimer. 13 * 14 * * Redistributions in binary form must reproduce the above copyright notice, 15 * this list of conditions and the following disclaimer in the documentation 16 * and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 * 30 * ***************************************************************************** 31 * 32 * Code for the number type. 33 * 34 */ 35 36 #include <assert.h> 37 #include <ctype.h> 38 #include <stdbool.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <setjmp.h> 42 #include <limits.h> 43 44 #include <num.h> 45 #include <rand.h> 46 #include <vm.h> 47 48 static void bc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); 49 50 static inline ssize_t bc_num_neg(size_t n, bool neg) { 51 return (((ssize_t) n) ^ -((ssize_t) neg)) + neg; 52 } 53 54 ssize_t bc_num_cmpZero(const BcNum *n) { 55 return bc_num_neg((n)->len != 0, BC_NUM_NEG(n)); 56 } 57 58 static inline size_t bc_num_int(const BcNum *n) { 59 return n->len ? n->len - BC_NUM_RDX_VAL(n) : 0; 60 } 61 62 static void bc_num_expand(BcNum *restrict n, size_t req) { 63 64 assert(n != NULL); 65 66 req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE; 67 68 if (req > n->cap) { 69 70 BC_SIG_LOCK; 71 72 n->num = bc_vm_realloc(n->num, BC_NUM_SIZE(req)); 73 n->cap = req; 74 75 BC_SIG_UNLOCK; 76 } 77 } 78 79 static void bc_num_setToZero(BcNum *restrict n, size_t scale) { 80 assert(n != NULL); 81 n->scale = scale; 82 n->len = n->rdx = 0; 83 } 84 85 void bc_num_zero(BcNum *restrict n) { 86 bc_num_setToZero(n, 0); 87 } 88 89 void bc_num_one(BcNum *restrict n) { 90 bc_num_zero(n); 91 n->len = 1; 92 n->num[0] = 1; 93 } 94 95 static void bc_num_clean(BcNum *restrict n) { 96 97 while (BC_NUM_NONZERO(n) && !n->num[n->len - 1]) n->len -= 1; 98 99 if (BC_NUM_ZERO(n)) n->rdx = 0; 100 else { 101 size_t rdx = BC_NUM_RDX_VAL(n); 102 if (n->len < rdx) n->len = rdx; 103 } 104 } 105 106 static size_t bc_num_log10(size_t i) { 107 size_t len; 108 for (len = 1; i; i /= BC_BASE, ++len); 109 assert(len - 1 <= BC_BASE_DIGS + 1); 110 return len - 1; 111 } 112 113 static inline size_t bc_num_zeroDigits(const BcDig *n) { 114 assert(*n >= 0); 115 assert(((size_t) *n) < BC_BASE_POW); 116 return BC_BASE_DIGS - bc_num_log10((size_t) *n); 117 } 118 119 static size_t bc_num_intDigits(const BcNum *n) { 120 size_t digits = bc_num_int(n) * BC_BASE_DIGS; 121 if (digits > 0) digits -= bc_num_zeroDigits(n->num + n->len - 1); 122 return digits; 123 } 124 125 static size_t bc_num_nonzeroLen(const BcNum *restrict n) { 126 size_t i, len = n->len; 127 assert(len == BC_NUM_RDX_VAL(n)); 128 for (i = len - 1; i < len && !n->num[i]; --i); 129 assert(i + 1 > 0); 130 return i + 1; 131 } 132 133 static BcDig bc_num_addDigits(BcDig a, BcDig b, bool *carry) { 134 135 assert(((BcBigDig) BC_BASE_POW) * 2 == ((BcDig) BC_BASE_POW) * 2); 136 assert(a < BC_BASE_POW); 137 assert(b < BC_BASE_POW); 138 139 a += b + *carry; 140 *carry = (a >= BC_BASE_POW); 141 if (*carry) a -= BC_BASE_POW; 142 143 assert(a >= 0); 144 assert(a < BC_BASE_POW); 145 146 return a; 147 } 148 149 static BcDig bc_num_subDigits(BcDig a, BcDig b, bool *carry) { 150 151 assert(a < BC_BASE_POW); 152 assert(b < BC_BASE_POW); 153 154 b += *carry; 155 *carry = (a < b); 156 if (*carry) a += BC_BASE_POW; 157 158 assert(a - b >= 0); 159 assert(a - b < BC_BASE_POW); 160 161 return a - b; 162 } 163 164 static void bc_num_addArrays(BcDig *restrict a, const BcDig *restrict b, 165 size_t len) 166 { 167 size_t i; 168 bool carry = false; 169 170 for (i = 0; i < len; ++i) a[i] = bc_num_addDigits(a[i], b[i], &carry); 171 172 for (; carry; ++i) a[i] = bc_num_addDigits(a[i], 0, &carry); 173 } 174 175 static void bc_num_subArrays(BcDig *restrict a, const BcDig *restrict b, 176 size_t len) 177 { 178 size_t i; 179 bool carry = false; 180 181 for (i = 0; i < len; ++i) a[i] = bc_num_subDigits(a[i], b[i], &carry); 182 183 for (; carry; ++i) a[i] = bc_num_subDigits(a[i], 0, &carry); 184 } 185 186 static void bc_num_mulArray(const BcNum *restrict a, BcBigDig b, 187 BcNum *restrict c) 188 { 189 size_t i; 190 BcBigDig carry = 0; 191 192 assert(b <= BC_BASE_POW); 193 194 if (a->len + 1 > c->cap) bc_num_expand(c, a->len + 1); 195 196 memset(c->num, 0, BC_NUM_SIZE(c->cap)); 197 198 for (i = 0; i < a->len; ++i) { 199 BcBigDig in = ((BcBigDig) a->num[i]) * b + carry; 200 c->num[i] = in % BC_BASE_POW; 201 carry = in / BC_BASE_POW; 202 } 203 204 assert(carry < BC_BASE_POW); 205 c->num[i] = (BcDig) carry; 206 c->len = a->len; 207 c->len += (carry != 0); 208 209 bc_num_clean(c); 210 211 assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c)); 212 assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len); 213 assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len); 214 } 215 216 static void bc_num_divArray(const BcNum *restrict a, BcBigDig b, 217 BcNum *restrict c, BcBigDig *rem) 218 { 219 size_t i; 220 BcBigDig carry = 0; 221 222 assert(c->cap >= a->len); 223 224 for (i = a->len - 1; i < a->len; --i) { 225 BcBigDig in = ((BcBigDig) a->num[i]) + carry * BC_BASE_POW; 226 assert(in / b < BC_BASE_POW); 227 c->num[i] = (BcDig) (in / b); 228 carry = in % b; 229 } 230 231 c->len = a->len; 232 bc_num_clean(c); 233 *rem = carry; 234 235 assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c)); 236 assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len); 237 assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len); 238 } 239 240 static ssize_t bc_num_compare(const BcDig *restrict a, const BcDig *restrict b, 241 size_t len) 242 { 243 size_t i; 244 BcDig c = 0; 245 for (i = len - 1; i < len && !(c = a[i] - b[i]); --i); 246 return bc_num_neg(i + 1, c < 0); 247 } 248 249 ssize_t bc_num_cmp(const BcNum *a, const BcNum *b) { 250 251 size_t i, min, a_int, b_int, diff, ardx, brdx; 252 BcDig *max_num, *min_num; 253 bool a_max, neg = false; 254 ssize_t cmp; 255 256 assert(a != NULL && b != NULL); 257 258 if (a == b) return 0; 259 if (BC_NUM_ZERO(a)) return bc_num_neg(b->len != 0, !BC_NUM_NEG(b)); 260 if (BC_NUM_ZERO(b)) return bc_num_cmpZero(a); 261 if (BC_NUM_NEG(a)) { 262 if (BC_NUM_NEG(b)) neg = true; 263 else return -1; 264 } 265 else if (BC_NUM_NEG(b)) return 1; 266 267 a_int = bc_num_int(a); 268 b_int = bc_num_int(b); 269 a_int -= b_int; 270 271 if (a_int) return neg ? -((ssize_t) a_int) : (ssize_t) a_int; 272 273 ardx = BC_NUM_RDX_VAL(a); 274 brdx = BC_NUM_RDX_VAL(b); 275 a_max = (ardx > brdx); 276 277 if (a_max) { 278 min = brdx; 279 diff = ardx - brdx; 280 max_num = a->num + diff; 281 min_num = b->num; 282 } 283 else { 284 min = ardx; 285 diff = brdx - ardx; 286 max_num = b->num + diff; 287 min_num = a->num; 288 } 289 290 cmp = bc_num_compare(max_num, min_num, b_int + min); 291 292 if (cmp) return bc_num_neg((size_t) cmp, !a_max == !neg); 293 294 for (max_num -= diff, i = diff - 1; i < diff; --i) { 295 if (max_num[i]) return bc_num_neg(1, !a_max == !neg); 296 } 297 298 return 0; 299 } 300 301 void bc_num_truncate(BcNum *restrict n, size_t places) { 302 303 size_t nrdx, places_rdx; 304 305 if (!places) return; 306 307 nrdx = BC_NUM_RDX_VAL(n); 308 places_rdx = nrdx ? nrdx - BC_NUM_RDX(n->scale - places) : 0; 309 assert(places <= n->scale && (BC_NUM_ZERO(n) || places_rdx <= n->len)); 310 311 n->scale -= places; 312 BC_NUM_RDX_SET(n, nrdx - places_rdx); 313 314 if (BC_NUM_NONZERO(n)) { 315 316 size_t pow; 317 318 pow = n->scale % BC_BASE_DIGS; 319 pow = pow ? BC_BASE_DIGS - pow : 0; 320 pow = bc_num_pow10[pow]; 321 322 n->len -= places_rdx; 323 memmove(n->num, n->num + places_rdx, BC_NUM_SIZE(n->len)); 324 325 // Clear the lower part of the last digit. 326 if (BC_NUM_NONZERO(n)) n->num[0] -= n->num[0] % (BcDig) pow; 327 328 bc_num_clean(n); 329 } 330 } 331 332 void bc_num_extend(BcNum *restrict n, size_t places) { 333 334 size_t nrdx, places_rdx; 335 336 if (!places) return; 337 if (BC_NUM_ZERO(n)) { 338 n->scale += places; 339 return; 340 } 341 342 nrdx = BC_NUM_RDX_VAL(n); 343 places_rdx = BC_NUM_RDX(places + n->scale) - nrdx; 344 345 if (places_rdx) { 346 bc_num_expand(n, bc_vm_growSize(n->len, places_rdx)); 347 memmove(n->num + places_rdx, n->num, BC_NUM_SIZE(n->len)); 348 memset(n->num, 0, BC_NUM_SIZE(places_rdx)); 349 } 350 351 BC_NUM_RDX_SET(n, nrdx + places_rdx); 352 n->scale += places; 353 n->len += places_rdx; 354 355 assert(BC_NUM_RDX_VAL(n) == BC_NUM_RDX(n->scale)); 356 } 357 358 static void bc_num_retireMul(BcNum *restrict n, size_t scale, 359 bool neg1, bool neg2) 360 { 361 if (n->scale < scale) bc_num_extend(n, scale - n->scale); 362 else bc_num_truncate(n, n->scale - scale); 363 364 bc_num_clean(n); 365 if (BC_NUM_NONZERO(n)) n->rdx = BC_NUM_NEG_VAL(n, !neg1 != !neg2); 366 } 367 368 static void bc_num_split(const BcNum *restrict n, size_t idx, 369 BcNum *restrict a, BcNum *restrict b) 370 { 371 assert(BC_NUM_ZERO(a)); 372 assert(BC_NUM_ZERO(b)); 373 374 if (idx < n->len) { 375 376 b->len = n->len - idx; 377 a->len = idx; 378 a->scale = b->scale = 0; 379 BC_NUM_RDX_SET(a, 0); 380 BC_NUM_RDX_SET(b, 0); 381 382 assert(a->cap >= a->len); 383 assert(b->cap >= b->len); 384 385 memcpy(b->num, n->num + idx, BC_NUM_SIZE(b->len)); 386 memcpy(a->num, n->num, BC_NUM_SIZE(idx)); 387 388 bc_num_clean(b); 389 } 390 else bc_num_copy(a, n); 391 392 bc_num_clean(a); 393 } 394 395 static size_t bc_num_shiftZero(BcNum *restrict n) { 396 397 size_t i; 398 399 assert(!BC_NUM_RDX_VAL(n) || BC_NUM_ZERO(n)); 400 401 for (i = 0; i < n->len && !n->num[i]; ++i); 402 403 n->len -= i; 404 n->num += i; 405 406 return i; 407 } 408 409 static void bc_num_unshiftZero(BcNum *restrict n, size_t places_rdx) { 410 n->len += places_rdx; 411 n->num -= places_rdx; 412 } 413 414 static void bc_num_shift(BcNum *restrict n, BcBigDig dig) { 415 416 size_t i, len = n->len; 417 BcBigDig carry = 0, pow; 418 BcDig *ptr = n->num; 419 420 assert(dig < BC_BASE_DIGS); 421 422 pow = bc_num_pow10[dig]; 423 dig = bc_num_pow10[BC_BASE_DIGS - dig]; 424 425 for (i = len - 1; i < len; --i) { 426 BcBigDig in, temp; 427 in = ((BcBigDig) ptr[i]); 428 temp = carry * dig; 429 carry = in % pow; 430 ptr[i] = ((BcDig) (in / pow)) + (BcDig) temp; 431 } 432 433 assert(!carry); 434 } 435 436 static void bc_num_shiftLeft(BcNum *restrict n, size_t places) { 437 438 BcBigDig dig; 439 size_t places_rdx; 440 bool shift; 441 442 if (!places) return; 443 if (places > n->scale) { 444 size_t size = bc_vm_growSize(BC_NUM_RDX(places - n->scale), n->len); 445 if (size > SIZE_MAX - 1) bc_vm_err(BC_ERR_MATH_OVERFLOW); 446 } 447 if (BC_NUM_ZERO(n)) { 448 if (n->scale >= places) n->scale -= places; 449 else n->scale = 0; 450 return; 451 } 452 453 dig = (BcBigDig) (places % BC_BASE_DIGS); 454 shift = (dig != 0); 455 places_rdx = BC_NUM_RDX(places); 456 457 if (n->scale) { 458 459 size_t nrdx = BC_NUM_RDX_VAL(n); 460 461 if (nrdx >= places_rdx) { 462 463 size_t mod = n->scale % BC_BASE_DIGS, revdig; 464 465 mod = mod ? mod : BC_BASE_DIGS; 466 revdig = dig ? BC_BASE_DIGS - dig : 0; 467 468 if (mod + revdig > BC_BASE_DIGS) places_rdx = 1; 469 else places_rdx = 0; 470 } 471 else places_rdx -= nrdx; 472 } 473 474 if (places_rdx) { 475 bc_num_expand(n, bc_vm_growSize(n->len, places_rdx)); 476 memmove(n->num + places_rdx, n->num, BC_NUM_SIZE(n->len)); 477 memset(n->num, 0, BC_NUM_SIZE(places_rdx)); 478 n->len += places_rdx; 479 } 480 481 if (places > n->scale) { 482 n->scale = 0; 483 BC_NUM_RDX_SET(n, 0); 484 } 485 else { 486 n->scale -= places; 487 BC_NUM_RDX_SET(n, BC_NUM_RDX(n->scale)); 488 } 489 490 if (shift) bc_num_shift(n, BC_BASE_DIGS - dig); 491 492 bc_num_clean(n); 493 } 494 495 void bc_num_shiftRight(BcNum *restrict n, size_t places) { 496 497 BcBigDig dig; 498 size_t places_rdx, scale, scale_mod, int_len, expand; 499 bool shift; 500 501 if (!places) return; 502 if (BC_NUM_ZERO(n)) { 503 n->scale += places; 504 bc_num_expand(n, BC_NUM_RDX(n->scale)); 505 return; 506 } 507 508 dig = (BcBigDig) (places % BC_BASE_DIGS); 509 shift = (dig != 0); 510 scale = n->scale; 511 scale_mod = scale % BC_BASE_DIGS; 512 scale_mod = scale_mod ? scale_mod : BC_BASE_DIGS; 513 int_len = bc_num_int(n); 514 places_rdx = BC_NUM_RDX(places); 515 516 if (scale_mod + dig > BC_BASE_DIGS) { 517 expand = places_rdx - 1; 518 places_rdx = 1; 519 } 520 else { 521 expand = places_rdx; 522 places_rdx = 0; 523 } 524 525 if (expand > int_len) expand -= int_len; 526 else expand = 0; 527 528 bc_num_extend(n, places_rdx * BC_BASE_DIGS); 529 bc_num_expand(n, bc_vm_growSize(expand, n->len)); 530 memset(n->num + n->len, 0, BC_NUM_SIZE(expand)); 531 n->len += expand; 532 n->scale = 0; 533 BC_NUM_RDX_SET(n, 0); 534 535 if (shift) bc_num_shift(n, dig); 536 537 n->scale = scale + places; 538 BC_NUM_RDX_SET(n, BC_NUM_RDX(n->scale)); 539 540 bc_num_clean(n); 541 542 assert(BC_NUM_RDX_VAL(n) <= n->len && n->len <= n->cap); 543 assert(BC_NUM_RDX_VAL(n) == BC_NUM_RDX(n->scale)); 544 } 545 546 static void bc_num_inv(BcNum *a, BcNum *b, size_t scale) { 547 548 BcNum one; 549 BcDig num[2]; 550 551 assert(BC_NUM_NONZERO(a)); 552 553 bc_num_setup(&one, num, sizeof(num) / sizeof(BcDig)); 554 bc_num_one(&one); 555 556 bc_num_div(&one, a, b, scale); 557 } 558 559 #if BC_ENABLE_EXTRA_MATH 560 static void bc_num_intop(const BcNum *a, const BcNum *b, BcNum *restrict c, 561 BcBigDig *v) 562 { 563 if (BC_ERR(BC_NUM_RDX_VAL(b))) bc_vm_err(BC_ERR_MATH_NON_INTEGER); 564 bc_num_copy(c, a); 565 bc_num_bigdig(b, v); 566 } 567 #endif // BC_ENABLE_EXTRA_MATH 568 569 static void bc_num_as(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) { 570 571 BcDig *ptr_c, *ptr_l, *ptr_r; 572 size_t i, min_rdx, max_rdx, diff, a_int, b_int, min_len, max_len, max_int; 573 size_t len_l, len_r, ardx, brdx; 574 bool b_neg, do_sub, do_rev_sub, carry, c_neg; 575 576 // Because this function doesn't need to use scale (per the bc spec), 577 // I am hijacking it to say whether it's doing an add or a subtract. 578 // Convert substraction to addition of negative second operand. 579 580 if (BC_NUM_ZERO(b)) { 581 bc_num_copy(c, a); 582 return; 583 } 584 if (BC_NUM_ZERO(a)) { 585 bc_num_copy(c, b); 586 c->rdx = BC_NUM_NEG_VAL(c, BC_NUM_NEG(b) != sub); 587 return; 588 } 589 590 // Invert sign of b if it is to be subtracted. This operation must 591 // preced the tests for any of the operands being zero. 592 b_neg = (BC_NUM_NEG(b) != sub); 593 594 // Actually add the numbers if their signs are equal, else subtract. 595 do_sub = (BC_NUM_NEG(a) != b_neg); 596 597 a_int = bc_num_int(a); 598 b_int = bc_num_int(b); 599 max_int = BC_MAX(a_int, b_int); 600 601 ardx = BC_NUM_RDX_VAL(a); 602 brdx = BC_NUM_RDX_VAL(b); 603 min_rdx = BC_MIN(ardx, brdx); 604 max_rdx = BC_MAX(ardx, brdx); 605 diff = max_rdx - min_rdx; 606 607 max_len = max_int + max_rdx; 608 609 if (do_sub) { 610 611 // Check whether b has to be subtracted from a or a from b. 612 if (a_int != b_int) do_rev_sub = (a_int < b_int); 613 else if (ardx > brdx) 614 do_rev_sub = (bc_num_compare(a->num + diff, b->num, b->len) < 0); 615 else 616 do_rev_sub = (bc_num_compare(a->num, b->num + diff, a->len) <= 0); 617 } 618 else { 619 620 // The result array of the addition might come out one element 621 // longer than the bigger of the operand arrays. 622 max_len += 1; 623 do_rev_sub = (a_int < b_int); 624 } 625 626 assert(max_len <= c->cap); 627 628 if (do_rev_sub) { 629 ptr_l = b->num; 630 ptr_r = a->num; 631 len_l = b->len; 632 len_r = a->len; 633 } 634 else { 635 ptr_l = a->num; 636 ptr_r = b->num; 637 len_l = a->len; 638 len_r = b->len; 639 } 640 641 ptr_c = c->num; 642 carry = false; 643 644 if (diff) { 645 646 // If the rdx values of the operands do not match, the result will 647 // have low end elements that are the positive or negative trailing 648 // elements of the operand with higher rdx value. 649 if ((ardx > brdx) != do_rev_sub) { 650 651 // !do_rev_sub && ardx > brdx || do_rev_sub && brdx > ardx 652 // The left operand has BcDig values that need to be copied, 653 // either from a or from b (in case of a reversed subtraction). 654 memcpy(ptr_c, ptr_l, BC_NUM_SIZE(diff)); 655 ptr_l += diff; 656 len_l -= diff; 657 } 658 else { 659 660 // The right operand has BcDig values that need to be copied 661 // or subtracted from zero (in case of a subtraction). 662 if (do_sub) { 663 664 // do_sub (do_rev_sub && ardx > brdx || 665 // !do_rev_sub && brdx > ardx) 666 for (i = 0; i < diff; i++) 667 ptr_c[i] = bc_num_subDigits(0, ptr_r[i], &carry); 668 } 669 else { 670 671 // !do_sub && brdx > ardx 672 memcpy(ptr_c, ptr_r, BC_NUM_SIZE(diff)); 673 } 674 675 ptr_r += diff; 676 len_r -= diff; 677 } 678 679 ptr_c += diff; 680 } 681 682 min_len = BC_MIN(len_l, len_r); 683 684 // After dealing with possible low array elements that depend on only one 685 // operand, the actual add or subtract can be performed as if the rdx of 686 // both operands was the same. 687 // Inlining takes care of eliminating constant zero arguments to 688 // addDigit/subDigit (checked in disassembly of resulting bc binary 689 // compiled with gcc and clang). 690 if (do_sub) { 691 for (i = 0; i < min_len; ++i) 692 ptr_c[i] = bc_num_subDigits(ptr_l[i], ptr_r[i], &carry); 693 for (; i < len_l; ++i) ptr_c[i] = bc_num_subDigits(ptr_l[i], 0, &carry); 694 } 695 else { 696 for (i = 0; i < min_len; ++i) 697 ptr_c[i] = bc_num_addDigits(ptr_l[i], ptr_r[i], &carry); 698 for (; i < len_l; ++i) ptr_c[i] = bc_num_addDigits(ptr_l[i], 0, &carry); 699 ptr_c[i] = bc_num_addDigits(0, 0, &carry); 700 } 701 702 assert(carry == false); 703 704 // The result has the same sign as a, unless the operation was a 705 // reverse subtraction (b - a). 706 c_neg = BC_NUM_NEG(a) != (do_sub && do_rev_sub); 707 BC_NUM_RDX_SET_NEG(c, max_rdx, c_neg); 708 c->len = max_len; 709 c->scale = BC_MAX(a->scale, b->scale); 710 711 bc_num_clean(c); 712 } 713 714 static void bc_num_m_simp(const BcNum *a, const BcNum *b, BcNum *restrict c) 715 { 716 size_t i, alen = a->len, blen = b->len, clen; 717 BcDig *ptr_a = a->num, *ptr_b = b->num, *ptr_c; 718 BcBigDig sum = 0, carry = 0; 719 720 assert(sizeof(sum) >= sizeof(BcDig) * 2); 721 assert(!BC_NUM_RDX_VAL(a) && !BC_NUM_RDX_VAL(b)); 722 723 clen = bc_vm_growSize(alen, blen); 724 bc_num_expand(c, bc_vm_growSize(clen, 1)); 725 726 ptr_c = c->num; 727 memset(ptr_c, 0, BC_NUM_SIZE(c->cap)); 728 729 for (i = 0; i < clen; ++i) { 730 731 ssize_t sidx = (ssize_t) (i - blen + 1); 732 size_t j = (size_t) BC_MAX(0, sidx), k = BC_MIN(i, blen - 1); 733 734 for (; j < alen && k < blen; ++j, --k) { 735 736 sum += ((BcBigDig) ptr_a[j]) * ((BcBigDig) ptr_b[k]); 737 738 if (sum >= ((BcBigDig) BC_BASE_POW) * BC_BASE_POW) { 739 carry += sum / BC_BASE_POW; 740 sum %= BC_BASE_POW; 741 } 742 } 743 744 if (sum >= BC_BASE_POW) { 745 carry += sum / BC_BASE_POW; 746 sum %= BC_BASE_POW; 747 } 748 749 ptr_c[i] = (BcDig) sum; 750 assert(ptr_c[i] < BC_BASE_POW); 751 sum = carry; 752 carry = 0; 753 } 754 755 // This should always be true because there should be no carry on the last 756 // digit; multiplication never goes above the sum of both lengths. 757 assert(!sum); 758 759 c->len = clen; 760 } 761 762 static void bc_num_shiftAddSub(BcNum *restrict n, const BcNum *restrict a, 763 size_t shift, BcNumShiftAddOp op) 764 { 765 assert(n->len >= shift + a->len); 766 assert(!BC_NUM_RDX_VAL(n) && !BC_NUM_RDX_VAL(a)); 767 op(n->num + shift, a->num, a->len); 768 } 769 770 static void bc_num_k(BcNum *a, BcNum *b, BcNum *restrict c) { 771 772 size_t max, max2, total; 773 BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp; 774 BcDig *digs, *dig_ptr; 775 BcNumShiftAddOp op; 776 bool aone = BC_NUM_ONE(a); 777 778 assert(BC_NUM_ZERO(c)); 779 780 if (BC_NUM_ZERO(a) || BC_NUM_ZERO(b)) return; 781 if (aone || BC_NUM_ONE(b)) { 782 bc_num_copy(c, aone ? b : a); 783 if ((aone && BC_NUM_NEG(a)) || BC_NUM_NEG(b)) BC_NUM_NEG_TGL(c); 784 return; 785 } 786 if (a->len < BC_NUM_KARATSUBA_LEN || b->len < BC_NUM_KARATSUBA_LEN) { 787 bc_num_m_simp(a, b, c); 788 return; 789 } 790 791 max = BC_MAX(a->len, b->len); 792 max = BC_MAX(max, BC_NUM_DEF_SIZE); 793 max2 = (max + 1) / 2; 794 795 total = bc_vm_arraySize(BC_NUM_KARATSUBA_ALLOCS, max); 796 797 BC_SIG_LOCK; 798 799 digs = dig_ptr = bc_vm_malloc(BC_NUM_SIZE(total)); 800 801 bc_num_setup(&l1, dig_ptr, max); 802 dig_ptr += max; 803 bc_num_setup(&h1, dig_ptr, max); 804 dig_ptr += max; 805 bc_num_setup(&l2, dig_ptr, max); 806 dig_ptr += max; 807 bc_num_setup(&h2, dig_ptr, max); 808 dig_ptr += max; 809 bc_num_setup(&m1, dig_ptr, max); 810 dig_ptr += max; 811 bc_num_setup(&m2, dig_ptr, max); 812 max = bc_vm_growSize(max, 1); 813 bc_num_init(&z0, max); 814 bc_num_init(&z1, max); 815 bc_num_init(&z2, max); 816 max = bc_vm_growSize(max, max) + 1; 817 bc_num_init(&temp, max); 818 819 BC_SETJMP_LOCKED(err); 820 821 BC_SIG_UNLOCK; 822 823 bc_num_split(a, max2, &l1, &h1); 824 bc_num_split(b, max2, &l2, &h2); 825 826 bc_num_expand(c, max); 827 c->len = max; 828 memset(c->num, 0, BC_NUM_SIZE(c->len)); 829 830 bc_num_sub(&h1, &l1, &m1, 0); 831 bc_num_sub(&l2, &h2, &m2, 0); 832 833 if (BC_NUM_NONZERO(&h1) && BC_NUM_NONZERO(&h2)) { 834 835 assert(BC_NUM_RDX_VALID_NP(h1)); 836 assert(BC_NUM_RDX_VALID_NP(h2)); 837 838 bc_num_m(&h1, &h2, &z2, 0); 839 bc_num_clean(&z2); 840 841 bc_num_shiftAddSub(c, &z2, max2 * 2, bc_num_addArrays); 842 bc_num_shiftAddSub(c, &z2, max2, bc_num_addArrays); 843 } 844 845 if (BC_NUM_NONZERO(&l1) && BC_NUM_NONZERO(&l2)) { 846 847 assert(BC_NUM_RDX_VALID_NP(l1)); 848 assert(BC_NUM_RDX_VALID_NP(l2)); 849 850 bc_num_m(&l1, &l2, &z0, 0); 851 bc_num_clean(&z0); 852 853 bc_num_shiftAddSub(c, &z0, max2, bc_num_addArrays); 854 bc_num_shiftAddSub(c, &z0, 0, bc_num_addArrays); 855 } 856 857 if (BC_NUM_NONZERO(&m1) && BC_NUM_NONZERO(&m2)) { 858 859 assert(BC_NUM_RDX_VALID_NP(m1)); 860 assert(BC_NUM_RDX_VALID_NP(m1)); 861 862 bc_num_m(&m1, &m2, &z1, 0); 863 bc_num_clean(&z1); 864 865 op = (BC_NUM_NEG_NP(m1) != BC_NUM_NEG_NP(m2)) ? 866 bc_num_subArrays : bc_num_addArrays; 867 bc_num_shiftAddSub(c, &z1, max2, op); 868 } 869 870 err: 871 BC_SIG_MAYLOCK; 872 free(digs); 873 bc_num_free(&temp); 874 bc_num_free(&z2); 875 bc_num_free(&z1); 876 bc_num_free(&z0); 877 BC_LONGJMP_CONT; 878 } 879 880 static void bc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { 881 882 BcNum cpa, cpb; 883 size_t ascale, bscale, ardx, brdx, azero = 0, bzero = 0, zero, len, rscale; 884 885 assert(BC_NUM_RDX_VALID(a)); 886 assert(BC_NUM_RDX_VALID(b)); 887 888 bc_num_zero(c); 889 ascale = a->scale; 890 bscale = b->scale; 891 scale = BC_MAX(scale, ascale); 892 scale = BC_MAX(scale, bscale); 893 894 rscale = ascale + bscale; 895 scale = BC_MIN(rscale, scale); 896 897 if ((a->len == 1 || b->len == 1) && !a->rdx && !b->rdx) { 898 899 BcNum *operand; 900 BcBigDig dig; 901 902 if (a->len == 1) { 903 dig = (BcBigDig) a->num[0]; 904 operand = b; 905 } 906 else { 907 dig = (BcBigDig) b->num[0]; 908 operand = a; 909 } 910 911 bc_num_mulArray(operand, dig, c); 912 913 if (BC_NUM_NONZERO(c)) 914 c->rdx = BC_NUM_NEG_VAL(c, BC_NUM_NEG(a) != BC_NUM_NEG(b)); 915 916 return; 917 } 918 919 assert(BC_NUM_RDX_VALID(a)); 920 assert(BC_NUM_RDX_VALID(b)); 921 922 BC_SIG_LOCK; 923 924 bc_num_init(&cpa, a->len + BC_NUM_RDX_VAL(a)); 925 bc_num_init(&cpb, b->len + BC_NUM_RDX_VAL(b)); 926 927 BC_SETJMP_LOCKED(err); 928 929 BC_SIG_UNLOCK; 930 931 bc_num_copy(&cpa, a); 932 bc_num_copy(&cpb, b); 933 934 assert(BC_NUM_RDX_VALID_NP(cpa)); 935 assert(BC_NUM_RDX_VALID_NP(cpb)); 936 937 BC_NUM_NEG_CLR_NP(cpa); 938 BC_NUM_NEG_CLR_NP(cpb); 939 940 assert(BC_NUM_RDX_VALID_NP(cpa)); 941 assert(BC_NUM_RDX_VALID_NP(cpb)); 942 943 ardx = BC_NUM_RDX_VAL_NP(cpa) * BC_BASE_DIGS; 944 bc_num_shiftLeft(&cpa, ardx); 945 946 brdx = BC_NUM_RDX_VAL_NP(cpb) * BC_BASE_DIGS; 947 bc_num_shiftLeft(&cpb, brdx); 948 949 // We need to reset the jump here because azero and bzero are used in the 950 // cleanup, and local variables are not guaranteed to be the same after a 951 // jump. 952 BC_SIG_LOCK; 953 954 BC_UNSETJMP; 955 956 azero = bc_num_shiftZero(&cpa); 957 bzero = bc_num_shiftZero(&cpb); 958 959 BC_SETJMP_LOCKED(err); 960 961 BC_SIG_UNLOCK; 962 963 bc_num_clean(&cpa); 964 bc_num_clean(&cpb); 965 966 bc_num_k(&cpa, &cpb, c); 967 968 zero = bc_vm_growSize(azero, bzero); 969 len = bc_vm_growSize(c->len, zero); 970 971 bc_num_expand(c, len); 972 bc_num_shiftLeft(c, (len - c->len) * BC_BASE_DIGS); 973 bc_num_shiftRight(c, ardx + brdx); 974 975 bc_num_retireMul(c, scale, BC_NUM_NEG(a), BC_NUM_NEG(b)); 976 977 err: 978 BC_SIG_MAYLOCK; 979 bc_num_unshiftZero(&cpb, bzero); 980 bc_num_free(&cpb); 981 bc_num_unshiftZero(&cpa, azero); 982 bc_num_free(&cpa); 983 BC_LONGJMP_CONT; 984 } 985 986 static bool bc_num_nonZeroDig(BcDig *restrict a, size_t len) { 987 size_t i; 988 bool nonzero = false; 989 for (i = len - 1; !nonzero && i < len; --i) nonzero = (a[i] != 0); 990 return nonzero; 991 } 992 993 static ssize_t bc_num_divCmp(const BcDig *a, const BcNum *b, size_t len) { 994 995 ssize_t cmp; 996 997 if (b->len > len && a[len]) cmp = bc_num_compare(a, b->num, len + 1); 998 else if (b->len <= len) { 999 if (a[len]) cmp = 1; 1000 else cmp = bc_num_compare(a, b->num, len); 1001 } 1002 else cmp = -1; 1003 1004 return cmp; 1005 } 1006 1007 static void bc_num_divExtend(BcNum *restrict a, BcNum *restrict b, 1008 BcBigDig divisor) 1009 { 1010 size_t pow; 1011 1012 assert(divisor < BC_BASE_POW); 1013 1014 pow = BC_BASE_DIGS - bc_num_log10((size_t) divisor); 1015 1016 bc_num_shiftLeft(a, pow); 1017 bc_num_shiftLeft(b, pow); 1018 } 1019 1020 static void bc_num_d_long(BcNum *restrict a, BcNum *restrict b, 1021 BcNum *restrict c, size_t scale) 1022 { 1023 BcBigDig divisor; 1024 size_t len, end, i, rdx; 1025 BcNum cpb; 1026 bool nonzero = false; 1027 1028 assert(b->len < a->len); 1029 len = b->len; 1030 end = a->len - len; 1031 assert(len >= 1); 1032 1033 bc_num_expand(c, a->len); 1034 memset(c->num, 0, c->cap * sizeof(BcDig)); 1035 1036 BC_NUM_RDX_SET(c, BC_NUM_RDX_VAL(a)); 1037 c->scale = a->scale; 1038 c->len = a->len; 1039 1040 divisor = (BcBigDig) b->num[len - 1]; 1041 1042 if (len > 1 && bc_num_nonZeroDig(b->num, len - 1)) { 1043 1044 nonzero = (divisor > 1 << ((10 * BC_BASE_DIGS) / 6 + 1)); 1045 1046 if (!nonzero) { 1047 1048 bc_num_divExtend(a, b, divisor); 1049 1050 len = BC_MAX(a->len, b->len); 1051 bc_num_expand(a, len + 1); 1052 1053 if (len + 1 > a->len) a->len = len + 1; 1054 1055 len = b->len; 1056 end = a->len - len; 1057 divisor = (BcBigDig) b->num[len - 1]; 1058 1059 nonzero = bc_num_nonZeroDig(b->num, len - 1); 1060 } 1061 } 1062 1063 divisor += nonzero; 1064 1065 bc_num_expand(c, a->len); 1066 memset(c->num, 0, BC_NUM_SIZE(c->cap)); 1067 1068 assert(c->scale >= scale); 1069 rdx = BC_NUM_RDX_VAL(c) - BC_NUM_RDX(scale); 1070 1071 BC_SIG_LOCK; 1072 1073 bc_num_init(&cpb, len + 1); 1074 1075 BC_SETJMP_LOCKED(err); 1076 1077 BC_SIG_UNLOCK; 1078 1079 i = end - 1; 1080 1081 for (; i < end && i >= rdx && BC_NUM_NONZERO(a); --i) { 1082 1083 ssize_t cmp; 1084 BcDig *n; 1085 BcBigDig result; 1086 1087 n = a->num + i; 1088 assert(n >= a->num); 1089 result = 0; 1090 1091 cmp = bc_num_divCmp(n, b, len); 1092 1093 while (cmp >= 0) { 1094 1095 BcBigDig n1, dividend, q; 1096 1097 n1 = (BcBigDig) n[len]; 1098 dividend = n1 * BC_BASE_POW + (BcBigDig) n[len - 1]; 1099 q = (dividend / divisor); 1100 1101 if (q <= 1) { 1102 q = 1; 1103 bc_num_subArrays(n, b->num, len); 1104 } 1105 else { 1106 1107 assert(q <= BC_BASE_POW); 1108 1109 bc_num_mulArray(b, (BcBigDig) q, &cpb); 1110 bc_num_subArrays(n, cpb.num, cpb.len); 1111 } 1112 1113 result += q; 1114 assert(result <= BC_BASE_POW); 1115 1116 if (nonzero) cmp = bc_num_divCmp(n, b, len); 1117 else cmp = -1; 1118 } 1119 1120 assert(result < BC_BASE_POW); 1121 1122 c->num[i] = (BcDig) result; 1123 } 1124 1125 err: 1126 BC_SIG_MAYLOCK; 1127 bc_num_free(&cpb); 1128 BC_LONGJMP_CONT; 1129 } 1130 1131 static void bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { 1132 1133 size_t len, cpardx; 1134 BcNum cpa, cpb; 1135 1136 if (BC_NUM_ZERO(b)) bc_vm_err(BC_ERR_MATH_DIVIDE_BY_ZERO); 1137 if (BC_NUM_ZERO(a)) { 1138 bc_num_setToZero(c, scale); 1139 return; 1140 } 1141 if (BC_NUM_ONE(b)) { 1142 bc_num_copy(c, a); 1143 bc_num_retireMul(c, scale, BC_NUM_NEG(a), BC_NUM_NEG(b)); 1144 return; 1145 } 1146 if (!BC_NUM_RDX_VAL(a) && !BC_NUM_RDX_VAL(b) && b->len == 1 && !scale) { 1147 BcBigDig rem; 1148 bc_num_divArray(a, (BcBigDig) b->num[0], c, &rem); 1149 bc_num_retireMul(c, scale, BC_NUM_NEG(a), BC_NUM_NEG(b)); 1150 return; 1151 } 1152 1153 len = bc_num_divReq(a, b, scale); 1154 1155 BC_SIG_LOCK; 1156 1157 bc_num_init(&cpa, len); 1158 bc_num_copy(&cpa, a); 1159 bc_num_createCopy(&cpb, b); 1160 1161 BC_SETJMP_LOCKED(err); 1162 1163 BC_SIG_UNLOCK; 1164 1165 len = b->len; 1166 1167 if (len > cpa.len) { 1168 bc_num_expand(&cpa, bc_vm_growSize(len, 2)); 1169 bc_num_extend(&cpa, (len - cpa.len) * BC_BASE_DIGS); 1170 } 1171 1172 cpardx = BC_NUM_RDX_VAL_NP(cpa); 1173 cpa.scale = cpardx * BC_BASE_DIGS; 1174 1175 bc_num_extend(&cpa, b->scale); 1176 cpardx = BC_NUM_RDX_VAL_NP(cpa) - BC_NUM_RDX(b->scale); 1177 BC_NUM_RDX_SET_NP(cpa, cpardx); 1178 cpa.scale = cpardx * BC_BASE_DIGS; 1179 1180 if (scale > cpa.scale) { 1181 bc_num_extend(&cpa, scale); 1182 cpardx = BC_NUM_RDX_VAL_NP(cpa); 1183 cpa.scale = cpardx * BC_BASE_DIGS; 1184 } 1185 1186 if (cpa.cap == cpa.len) bc_num_expand(&cpa, bc_vm_growSize(cpa.len, 1)); 1187 1188 // We want an extra zero in front to make things simpler. 1189 cpa.num[cpa.len++] = 0; 1190 1191 if (cpardx == cpa.len) cpa.len = bc_num_nonzeroLen(&cpa); 1192 if (BC_NUM_RDX_VAL_NP(cpb) == cpb.len) cpb.len = bc_num_nonzeroLen(&cpb); 1193 cpb.scale = 0; 1194 BC_NUM_RDX_SET_NP(cpb, 0); 1195 1196 bc_num_d_long(&cpa, &cpb, c, scale); 1197 1198 bc_num_retireMul(c, scale, BC_NUM_NEG(a), BC_NUM_NEG(b)); 1199 1200 err: 1201 BC_SIG_MAYLOCK; 1202 bc_num_free(&cpb); 1203 bc_num_free(&cpa); 1204 BC_LONGJMP_CONT; 1205 } 1206 1207 static void bc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, 1208 BcNum *restrict d, size_t scale, size_t ts) 1209 { 1210 BcNum temp; 1211 bool neg; 1212 1213 if (BC_NUM_ZERO(b)) bc_vm_err(BC_ERR_MATH_DIVIDE_BY_ZERO); 1214 if (BC_NUM_ZERO(a)) { 1215 bc_num_setToZero(c, ts); 1216 bc_num_setToZero(d, ts); 1217 return; 1218 } 1219 1220 BC_SIG_LOCK; 1221 1222 bc_num_init(&temp, d->cap); 1223 1224 BC_SETJMP_LOCKED(err); 1225 1226 BC_SIG_UNLOCK; 1227 1228 bc_num_d(a, b, c, scale); 1229 1230 if (scale) scale = ts + 1; 1231 1232 assert(BC_NUM_RDX_VALID(c)); 1233 assert(BC_NUM_RDX_VALID(b)); 1234 1235 bc_num_m(c, b, &temp, scale); 1236 bc_num_sub(a, &temp, d, scale); 1237 1238 if (ts > d->scale && BC_NUM_NONZERO(d)) bc_num_extend(d, ts - d->scale); 1239 1240 neg = BC_NUM_NEG(d); 1241 bc_num_retireMul(d, ts, BC_NUM_NEG(a), BC_NUM_NEG(b)); 1242 d->rdx = BC_NUM_NEG_VAL(d, BC_NUM_NONZERO(d) ? neg : false); 1243 1244 err: 1245 BC_SIG_MAYLOCK; 1246 bc_num_free(&temp); 1247 BC_LONGJMP_CONT; 1248 } 1249 1250 static void bc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { 1251 1252 BcNum c1; 1253 size_t ts; 1254 1255 ts = bc_vm_growSize(scale, b->scale); 1256 ts = BC_MAX(ts, a->scale); 1257 1258 BC_SIG_LOCK; 1259 1260 bc_num_init(&c1, bc_num_mulReq(a, b, ts)); 1261 1262 BC_SETJMP_LOCKED(err); 1263 1264 BC_SIG_UNLOCK; 1265 1266 bc_num_r(a, b, &c1, c, scale, ts); 1267 1268 err: 1269 BC_SIG_MAYLOCK; 1270 bc_num_free(&c1); 1271 BC_LONGJMP_CONT; 1272 } 1273 1274 static void bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { 1275 1276 BcNum copy; 1277 BcBigDig pow = 0; 1278 size_t i, powrdx, resrdx; 1279 bool neg, zero; 1280 1281 if (BC_ERR(BC_NUM_RDX_VAL(b))) bc_vm_err(BC_ERR_MATH_NON_INTEGER); 1282 1283 if (BC_NUM_ZERO(b)) { 1284 bc_num_one(c); 1285 return; 1286 } 1287 if (BC_NUM_ZERO(a)) { 1288 if (BC_NUM_NEG(b)) bc_vm_err(BC_ERR_MATH_DIVIDE_BY_ZERO); 1289 bc_num_setToZero(c, scale); 1290 return; 1291 } 1292 if (BC_NUM_ONE(b)) { 1293 if (!BC_NUM_NEG(b)) bc_num_copy(c, a); 1294 else bc_num_inv(a, c, scale); 1295 return; 1296 } 1297 1298 BC_SIG_LOCK; 1299 1300 neg = BC_NUM_NEG(b); 1301 BC_NUM_NEG_CLR(b); 1302 bc_num_bigdig(b, &pow); 1303 b->rdx = BC_NUM_NEG_VAL(b, neg); 1304 1305 bc_num_createCopy(©, a); 1306 1307 BC_SETJMP_LOCKED(err); 1308 1309 BC_SIG_UNLOCK; 1310 1311 if (!neg) { 1312 size_t max = BC_MAX(scale, a->scale), scalepow = a->scale * pow; 1313 scale = BC_MIN(scalepow, max); 1314 } 1315 1316 for (powrdx = a->scale; !(pow & 1); pow >>= 1) { 1317 powrdx <<= 1; 1318 assert(BC_NUM_RDX_VALID_NP(copy)); 1319 bc_num_mul(©, ©, ©, powrdx); 1320 } 1321 1322 bc_num_copy(c, ©); 1323 resrdx = powrdx; 1324 1325 while (pow >>= 1) { 1326 1327 powrdx <<= 1; 1328 assert(BC_NUM_RDX_VALID_NP(copy)); 1329 bc_num_mul(©, ©, ©, powrdx); 1330 1331 if (pow & 1) { 1332 resrdx += powrdx; 1333 assert(BC_NUM_RDX_VALID(c)); 1334 assert(BC_NUM_RDX_VALID_NP(copy)); 1335 bc_num_mul(c, ©, c, resrdx); 1336 } 1337 } 1338 1339 if (neg) bc_num_inv(c, c, scale); 1340 1341 if (c->scale > scale) bc_num_truncate(c, c->scale - scale); 1342 1343 // We can't use bc_num_clean() here. 1344 for (zero = true, i = 0; zero && i < c->len; ++i) zero = !c->num[i]; 1345 if (zero) bc_num_setToZero(c, scale); 1346 1347 err: 1348 BC_SIG_MAYLOCK; 1349 bc_num_free(©); 1350 BC_LONGJMP_CONT; 1351 } 1352 1353 #if BC_ENABLE_EXTRA_MATH 1354 static void bc_num_place(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { 1355 1356 BcBigDig val = 0; 1357 1358 BC_UNUSED(scale); 1359 1360 bc_num_intop(a, b, c, &val); 1361 1362 if (val < c->scale) bc_num_truncate(c, c->scale - val); 1363 else if (val > c->scale) bc_num_extend(c, val - c->scale); 1364 } 1365 1366 static void bc_num_left(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { 1367 1368 BcBigDig val = 0; 1369 1370 BC_UNUSED(scale); 1371 1372 bc_num_intop(a, b, c, &val); 1373 1374 bc_num_shiftLeft(c, (size_t) val); 1375 } 1376 1377 static void bc_num_right(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { 1378 1379 BcBigDig val = 0; 1380 1381 BC_UNUSED(scale); 1382 1383 bc_num_intop(a, b, c, &val); 1384 1385 if (BC_NUM_ZERO(c)) return; 1386 1387 bc_num_shiftRight(c, (size_t) val); 1388 } 1389 #endif // BC_ENABLE_EXTRA_MATH 1390 1391 static void bc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, 1392 BcNumBinaryOp op, size_t req) 1393 { 1394 BcNum *ptr_a, *ptr_b, num2; 1395 bool init = false; 1396 1397 assert(a != NULL && b != NULL && c != NULL && op != NULL); 1398 1399 assert(BC_NUM_RDX_VALID(a)); 1400 assert(BC_NUM_RDX_VALID(b)); 1401 1402 BC_SIG_LOCK; 1403 1404 if (c == a) { 1405 1406 ptr_a = &num2; 1407 1408 memcpy(ptr_a, c, sizeof(BcNum)); 1409 init = true; 1410 } 1411 else { 1412 ptr_a = a; 1413 } 1414 1415 if (c == b) { 1416 1417 ptr_b = &num2; 1418 1419 if (c != a) { 1420 memcpy(ptr_b, c, sizeof(BcNum)); 1421 init = true; 1422 } 1423 } 1424 else { 1425 ptr_b = b; 1426 } 1427 1428 if (init) { 1429 1430 bc_num_init(c, req); 1431 1432 BC_SETJMP_LOCKED(err); 1433 BC_SIG_UNLOCK; 1434 } 1435 else { 1436 BC_SIG_UNLOCK; 1437 bc_num_expand(c, req); 1438 } 1439 1440 op(ptr_a, ptr_b, c, scale); 1441 1442 assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c)); 1443 assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len); 1444 assert(BC_NUM_RDX_VALID(c)); 1445 assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len); 1446 1447 err: 1448 if (init) { 1449 BC_SIG_MAYLOCK; 1450 bc_num_free(&num2); 1451 BC_LONGJMP_CONT; 1452 } 1453 } 1454 1455 #if !defined(NDEBUG) || BC_ENABLE_LIBRARY 1456 bool bc_num_strValid(const char *restrict val) { 1457 1458 bool radix = false; 1459 size_t i, len = strlen(val); 1460 1461 if (!len) return true; 1462 1463 for (i = 0; i < len; ++i) { 1464 1465 BcDig c = val[i]; 1466 1467 if (c == '.') { 1468 1469 if (radix) return false; 1470 1471 radix = true; 1472 continue; 1473 } 1474 1475 if (!(isdigit(c) || isupper(c))) return false; 1476 } 1477 1478 return true; 1479 } 1480 #endif // !defined(NDEBUG) || BC_ENABLE_LIBRARY 1481 1482 static BcBigDig bc_num_parseChar(char c, size_t base_t) { 1483 1484 if (isupper(c)) { 1485 c = BC_NUM_NUM_LETTER(c); 1486 c = ((size_t) c) >= base_t ? (char) base_t - 1 : c; 1487 } 1488 else c -= '0'; 1489 1490 return (BcBigDig) (uchar) c; 1491 } 1492 1493 static void bc_num_parseDecimal(BcNum *restrict n, const char *restrict val) { 1494 1495 size_t len, i, temp, mod; 1496 const char *ptr; 1497 bool zero = true, rdx; 1498 1499 for (i = 0; val[i] == '0'; ++i); 1500 1501 val += i; 1502 assert(!val[0] || isalnum(val[0]) || val[0] == '.'); 1503 1504 // All 0's. We can just return, since this 1505 // procedure expects a virgin (already 0) BcNum. 1506 if (!val[0]) return; 1507 1508 len = strlen(val); 1509 1510 ptr = strchr(val, '.'); 1511 rdx = (ptr != NULL); 1512 1513 for (i = 0; i < len && (zero = (val[i] == '0' || val[i] == '.')); ++i); 1514 1515 n->scale = (size_t) (rdx * (((uintptr_t) (val + len)) - 1516 (((uintptr_t) ptr) + 1))); 1517 1518 BC_NUM_RDX_SET(n, BC_NUM_RDX(n->scale)); 1519 i = len - (ptr == val ? 0 : i) - rdx; 1520 temp = BC_NUM_ROUND_POW(i); 1521 mod = n->scale % BC_BASE_DIGS; 1522 i = mod ? BC_BASE_DIGS - mod : 0; 1523 n->len = ((temp + i) / BC_BASE_DIGS); 1524 1525 bc_num_expand(n, n->len); 1526 memset(n->num, 0, BC_NUM_SIZE(n->len)); 1527 1528 if (zero) { 1529 // I think I can set rdx directly to zero here because n should be a 1530 // new number with sign set to false. 1531 n->len = n->rdx = 0; 1532 } 1533 else { 1534 1535 BcBigDig exp, pow; 1536 1537 assert(i <= BC_NUM_BIGDIG_MAX); 1538 1539 exp = (BcBigDig) i; 1540 pow = bc_num_pow10[exp]; 1541 1542 for (i = len - 1; i < len; --i, ++exp) { 1543 1544 char c = val[i]; 1545 1546 if (c == '.') exp -= 1; 1547 else { 1548 1549 size_t idx = exp / BC_BASE_DIGS; 1550 1551 if (isupper(c)) c = '9'; 1552 n->num[idx] += (((BcBigDig) c) - '0') * pow; 1553 1554 if ((exp + 1) % BC_BASE_DIGS == 0) pow = 1; 1555 else pow *= BC_BASE; 1556 } 1557 } 1558 } 1559 } 1560 1561 static void bc_num_parseBase(BcNum *restrict n, const char *restrict val, 1562 BcBigDig base) 1563 { 1564 BcNum temp, mult1, mult2, result1, result2, *m1, *m2, *ptr; 1565 char c = 0; 1566 bool zero = true; 1567 BcBigDig v; 1568 size_t i, digs, len = strlen(val); 1569 1570 for (i = 0; zero && i < len; ++i) zero = (val[i] == '.' || val[i] == '0'); 1571 if (zero) return; 1572 1573 BC_SIG_LOCK; 1574 1575 bc_num_init(&temp, BC_NUM_BIGDIG_LOG10); 1576 bc_num_init(&mult1, BC_NUM_BIGDIG_LOG10); 1577 1578 BC_SETJMP_LOCKED(int_err); 1579 1580 BC_SIG_UNLOCK; 1581 1582 for (i = 0; i < len && (c = val[i]) && c != '.'; ++i) { 1583 1584 v = bc_num_parseChar(c, base); 1585 1586 bc_num_mulArray(n, base, &mult1); 1587 bc_num_bigdig2num(&temp, v); 1588 bc_num_add(&mult1, &temp, n, 0); 1589 } 1590 1591 if (i == len && !val[i]) goto int_err; 1592 1593 assert(val[i] == '.'); 1594 1595 BC_SIG_LOCK; 1596 1597 BC_UNSETJMP; 1598 1599 bc_num_init(&mult2, BC_NUM_BIGDIG_LOG10); 1600 bc_num_init(&result1, BC_NUM_DEF_SIZE); 1601 bc_num_init(&result2, BC_NUM_DEF_SIZE); 1602 bc_num_one(&mult1); 1603 1604 BC_SETJMP_LOCKED(err); 1605 1606 BC_SIG_UNLOCK; 1607 1608 m1 = &mult1; 1609 m2 = &mult2; 1610 1611 for (i += 1, digs = 0; i < len && (c = val[i]); ++i, ++digs) { 1612 1613 size_t rdx; 1614 1615 v = bc_num_parseChar(c, base); 1616 1617 bc_num_mulArray(&result1, base, &result2); 1618 1619 bc_num_bigdig2num(&temp, v); 1620 bc_num_add(&result2, &temp, &result1, 0); 1621 bc_num_mulArray(m1, base, m2); 1622 1623 rdx = BC_NUM_RDX_VAL(m2); 1624 1625 if (m2->len < rdx) m2->len = rdx; 1626 1627 ptr = m1; 1628 m1 = m2; 1629 m2 = ptr; 1630 } 1631 1632 // This one cannot be a divide by 0 because mult starts out at 1, then is 1633 // multiplied by base, and base cannot be 0, so mult cannot be 0. 1634 bc_num_div(&result1, m1, &result2, digs * 2); 1635 bc_num_truncate(&result2, digs); 1636 bc_num_add(n, &result2, n, digs); 1637 1638 if (BC_NUM_NONZERO(n)) { 1639 if (n->scale < digs) bc_num_extend(n, digs - n->scale); 1640 } 1641 else bc_num_zero(n); 1642 1643 err: 1644 BC_SIG_MAYLOCK; 1645 bc_num_free(&result2); 1646 bc_num_free(&result1); 1647 bc_num_free(&mult2); 1648 int_err: 1649 BC_SIG_MAYLOCK; 1650 bc_num_free(&mult1); 1651 bc_num_free(&temp); 1652 BC_LONGJMP_CONT; 1653 } 1654 1655 static inline void bc_num_printNewline(void) { 1656 #if !BC_ENABLE_LIBRARY 1657 if (vm.nchars >= vm.line_len - 1) { 1658 bc_vm_putchar('\\'); 1659 bc_vm_putchar('\n'); 1660 } 1661 #endif // !BC_ENABLE_LIBRARY 1662 } 1663 1664 static void bc_num_putchar(int c) { 1665 if (c != '\n') bc_num_printNewline(); 1666 bc_vm_putchar(c); 1667 } 1668 1669 #if DC_ENABLED && !BC_ENABLE_LIBRARY 1670 static void bc_num_printChar(size_t n, size_t len, bool rdx) { 1671 BC_UNUSED(rdx); 1672 BC_UNUSED(len); 1673 assert(len == 1); 1674 bc_vm_putchar((uchar) n); 1675 } 1676 #endif // DC_ENABLED && !BC_ENABLE_LIBRARY 1677 1678 static void bc_num_printDigits(size_t n, size_t len, bool rdx) { 1679 1680 size_t exp, pow; 1681 1682 bc_num_putchar(rdx ? '.' : ' '); 1683 1684 for (exp = 0, pow = 1; exp < len - 1; ++exp, pow *= BC_BASE); 1685 1686 for (exp = 0; exp < len; pow /= BC_BASE, ++exp) { 1687 size_t dig = n / pow; 1688 n -= dig * pow; 1689 bc_num_putchar(((uchar) dig) + '0'); 1690 } 1691 } 1692 1693 static void bc_num_printHex(size_t n, size_t len, bool rdx) { 1694 1695 BC_UNUSED(len); 1696 1697 assert(len == 1); 1698 1699 if (rdx) bc_num_putchar('.'); 1700 1701 bc_num_putchar(bc_num_hex_digits[n]); 1702 } 1703 1704 static void bc_num_printDecimal(const BcNum *restrict n) { 1705 1706 size_t i, j, rdx = BC_NUM_RDX_VAL(n); 1707 bool zero = true; 1708 size_t buffer[BC_BASE_DIGS]; 1709 1710 if (BC_NUM_NEG(n)) bc_num_putchar('-'); 1711 1712 for (i = n->len - 1; i < n->len; --i) { 1713 1714 BcDig n9 = n->num[i]; 1715 size_t temp; 1716 bool irdx = (i == rdx - 1); 1717 1718 zero = (zero & !irdx); 1719 temp = n->scale % BC_BASE_DIGS; 1720 temp = i || !temp ? 0 : BC_BASE_DIGS - temp; 1721 1722 memset(buffer, 0, BC_BASE_DIGS * sizeof(size_t)); 1723 1724 for (j = 0; n9 && j < BC_BASE_DIGS; ++j) { 1725 buffer[j] = ((size_t) n9) % BC_BASE; 1726 n9 /= BC_BASE; 1727 } 1728 1729 for (j = BC_BASE_DIGS - 1; j < BC_BASE_DIGS && j >= temp; --j) { 1730 bool print_rdx = (irdx & (j == BC_BASE_DIGS - 1)); 1731 zero = (zero && buffer[j] == 0); 1732 if (!zero) bc_num_printHex(buffer[j], 1, print_rdx); 1733 } 1734 } 1735 } 1736 1737 #if BC_ENABLE_EXTRA_MATH 1738 static void bc_num_printExponent(const BcNum *restrict n, bool eng) { 1739 1740 size_t places, mod, nrdx = BC_NUM_RDX_VAL(n); 1741 bool neg = (n->len <= nrdx); 1742 BcNum temp, exp; 1743 BcDig digs[BC_NUM_BIGDIG_LOG10]; 1744 1745 BC_SIG_LOCK; 1746 1747 bc_num_createCopy(&temp, n); 1748 1749 BC_SETJMP_LOCKED(exit); 1750 1751 BC_SIG_UNLOCK; 1752 1753 if (neg) { 1754 1755 size_t i, idx = bc_num_nonzeroLen(n) - 1; 1756 1757 places = 1; 1758 1759 for (i = BC_BASE_DIGS - 1; i < BC_BASE_DIGS; --i) { 1760 if (bc_num_pow10[i] > (BcBigDig) n->num[idx]) places += 1; 1761 else break; 1762 } 1763 1764 places += (nrdx - (idx + 1)) * BC_BASE_DIGS; 1765 mod = places % 3; 1766 1767 if (eng && mod != 0) places += 3 - mod; 1768 bc_num_shiftLeft(&temp, places); 1769 } 1770 else { 1771 places = bc_num_intDigits(n) - 1; 1772 mod = places % 3; 1773 if (eng && mod != 0) places -= 3 - (3 - mod); 1774 bc_num_shiftRight(&temp, places); 1775 } 1776 1777 bc_num_printDecimal(&temp); 1778 bc_num_putchar('e'); 1779 1780 if (!places) { 1781 bc_num_printHex(0, 1, false); 1782 goto exit; 1783 } 1784 1785 if (neg) bc_num_putchar('-'); 1786 1787 bc_num_setup(&exp, digs, BC_NUM_BIGDIG_LOG10); 1788 bc_num_bigdig2num(&exp, (BcBigDig) places); 1789 1790 bc_num_printDecimal(&exp); 1791 1792 exit: 1793 BC_SIG_MAYLOCK; 1794 bc_num_free(&temp); 1795 BC_LONGJMP_CONT; 1796 } 1797 #endif // BC_ENABLE_EXTRA_MATH 1798 1799 static void bc_num_printFixup(BcNum *restrict n, BcBigDig rem, 1800 BcBigDig pow, size_t idx) 1801 { 1802 size_t i, len = n->len - idx; 1803 BcBigDig acc; 1804 BcDig *a = n->num + idx; 1805 1806 if (len < 2) return; 1807 1808 for (i = len - 1; i > 0; --i) { 1809 1810 acc = ((BcBigDig) a[i]) * rem + ((BcBigDig) a[i - 1]); 1811 a[i - 1] = (BcDig) (acc % pow); 1812 acc /= pow; 1813 acc += (BcBigDig) a[i]; 1814 1815 if (acc >= BC_BASE_POW) { 1816 1817 if (i == len - 1) { 1818 len = bc_vm_growSize(len, 1); 1819 bc_num_expand(n, bc_vm_growSize(len, idx)); 1820 a = n->num + idx; 1821 a[len - 1] = 0; 1822 } 1823 1824 a[i + 1] += acc / BC_BASE_POW; 1825 acc %= BC_BASE_POW; 1826 } 1827 1828 assert(acc < BC_BASE_POW); 1829 a[i] = (BcDig) acc; 1830 } 1831 1832 n->len = len + idx; 1833 } 1834 1835 static void bc_num_printPrepare(BcNum *restrict n, BcBigDig rem, 1836 BcBigDig pow) 1837 { 1838 size_t i; 1839 1840 for (i = 0; i < n->len; ++i) bc_num_printFixup(n, rem, pow, i); 1841 1842 for (i = 0; i < n->len; ++i) { 1843 1844 assert(pow == ((BcBigDig) ((BcDig) pow))); 1845 1846 if (n->num[i] >= (BcDig) pow) { 1847 1848 if (i + 1 == n->len) { 1849 n->len = bc_vm_growSize(n->len, 1); 1850 bc_num_expand(n, n->len); 1851 n->num[i + 1] = 0; 1852 } 1853 1854 assert(pow < BC_BASE_POW); 1855 n->num[i + 1] += n->num[i] / ((BcDig) pow); 1856 n->num[i] %= (BcDig) pow; 1857 } 1858 } 1859 } 1860 1861 static void bc_num_printNum(BcNum *restrict n, BcBigDig base, 1862 size_t len, BcNumDigitOp print) 1863 { 1864 BcVec stack; 1865 BcNum intp, fracp1, fracp2, digit, flen1, flen2, *n1, *n2, *temp; 1866 BcBigDig dig = 0, *ptr, acc, exp; 1867 size_t i, j, nrdx; 1868 bool radix; 1869 BcDig digit_digs[BC_NUM_BIGDIG_LOG10 + 1]; 1870 1871 assert(base > 1); 1872 1873 if (BC_NUM_ZERO(n)) { 1874 print(0, len, false); 1875 return; 1876 } 1877 1878 // This function uses an algorithm that Stefan Esser <se@freebsd.org> came 1879 // up with to print the integer part of a number. What it does is convert 1880 // intp into a number of the specified base, but it does it directly, 1881 // instead of just doing a series of divisions and printing the remainders 1882 // in reverse order. 1883 // 1884 // Let me explain in a bit more detail: 1885 // 1886 // The algorithm takes the current least significant digit (after intp has 1887 // been converted to an integer) and the next to least significant digit, 1888 // and it converts the least significant digit into one of the specified 1889 // base, putting any overflow into the next to least significant digit. It 1890 // iterates through the whole number, from least significant to most 1891 // significant, doing this conversion. At the end of that iteration, the 1892 // least significant digit is converted, but the others are not, so it 1893 // iterates again, starting at the next to least significant digit. It keeps 1894 // doing that conversion, skipping one more digit than the last time, until 1895 // all digits have been converted. Then it prints them in reverse order. 1896 // 1897 // That is the gist of the algorithm. It leaves out several things, such as 1898 // the fact that digits are not always converted into the specified base, 1899 // but into something close, basically a power of the specified base. In 1900 // Stefan's words, "You could consider BcDigs to be of base 10^BC_BASE_DIGS 1901 // in the normal case and obase^N for the largest value of N that satisfies 1902 // obase^N <= 10^BC_BASE_DIGS. [This means that] the result is not in base 1903 // "obase", but in base "obase^N", which happens to be printable as a number 1904 // of base "obase" without consideration for neighbouring BcDigs." This fact 1905 // is what necessitates the existence of the loop later in this function. 1906 // 1907 // The conversion happens in bc_num_printPrepare() where the outer loop 1908 // happens and bc_num_printFixup() where the inner loop, or actual 1909 // conversion, happens. 1910 1911 nrdx = BC_NUM_RDX_VAL(n); 1912 1913 BC_SIG_LOCK; 1914 1915 bc_vec_init(&stack, sizeof(BcBigDig), NULL); 1916 bc_num_init(&fracp1, nrdx); 1917 1918 bc_num_createCopy(&intp, n); 1919 1920 BC_SETJMP_LOCKED(err); 1921 1922 BC_SIG_UNLOCK; 1923 1924 bc_num_truncate(&intp, intp.scale); 1925 1926 bc_num_sub(n, &intp, &fracp1, 0); 1927 1928 if (base != vm.last_base) { 1929 1930 vm.last_pow = 1; 1931 vm.last_exp = 0; 1932 1933 while (vm.last_pow * base <= BC_BASE_POW) { 1934 vm.last_pow *= base; 1935 vm.last_exp += 1; 1936 } 1937 1938 vm.last_rem = BC_BASE_POW - vm.last_pow; 1939 vm.last_base = base; 1940 } 1941 1942 exp = vm.last_exp; 1943 1944 if (vm.last_rem != 0) bc_num_printPrepare(&intp, vm.last_rem, vm.last_pow); 1945 1946 for (i = 0; i < intp.len; ++i) { 1947 1948 acc = (BcBigDig) intp.num[i]; 1949 1950 for (j = 0; j < exp && (i < intp.len - 1 || acc != 0); ++j) 1951 { 1952 if (j != exp - 1) { 1953 dig = acc % base; 1954 acc /= base; 1955 } 1956 else { 1957 dig = acc; 1958 acc = 0; 1959 } 1960 1961 assert(dig < base); 1962 1963 bc_vec_push(&stack, &dig); 1964 } 1965 1966 assert(acc == 0); 1967 } 1968 1969 for (i = 0; i < stack.len; ++i) { 1970 ptr = bc_vec_item_rev(&stack, i); 1971 assert(ptr != NULL); 1972 print(*ptr, len, false); 1973 } 1974 1975 if (!n->scale) goto err; 1976 1977 BC_SIG_LOCK; 1978 1979 BC_UNSETJMP; 1980 1981 bc_num_init(&fracp2, nrdx); 1982 bc_num_setup(&digit, digit_digs, sizeof(digit_digs) / sizeof(BcDig)); 1983 bc_num_init(&flen1, BC_NUM_BIGDIG_LOG10); 1984 bc_num_init(&flen2, BC_NUM_BIGDIG_LOG10); 1985 1986 BC_SETJMP_LOCKED(frac_err); 1987 1988 BC_SIG_UNLOCK; 1989 1990 bc_num_one(&flen1); 1991 1992 radix = true; 1993 n1 = &flen1; 1994 n2 = &flen2; 1995 1996 fracp2.scale = n->scale; 1997 BC_NUM_RDX_SET_NP(fracp2, BC_NUM_RDX(fracp2.scale)); 1998 1999 while (bc_num_intDigits(n1) < n->scale + 1) { 2000 2001 bc_num_expand(&fracp2, fracp1.len + 1); 2002 bc_num_mulArray(&fracp1, base, &fracp2); 2003 2004 nrdx = BC_NUM_RDX_VAL_NP(fracp2); 2005 2006 if (fracp2.len < nrdx) fracp2.len = nrdx; 2007 2008 // fracp is guaranteed to be non-negative and small enough. 2009 bc_num_bigdig2(&fracp2, &dig); 2010 2011 bc_num_bigdig2num(&digit, dig); 2012 bc_num_sub(&fracp2, &digit, &fracp1, 0); 2013 2014 print(dig, len, radix); 2015 bc_num_mulArray(n1, base, n2); 2016 2017 radix = false; 2018 temp = n1; 2019 n1 = n2; 2020 n2 = temp; 2021 } 2022 2023 frac_err: 2024 BC_SIG_MAYLOCK; 2025 bc_num_free(&flen2); 2026 bc_num_free(&flen1); 2027 bc_num_free(&fracp2); 2028 err: 2029 BC_SIG_MAYLOCK; 2030 bc_num_free(&fracp1); 2031 bc_num_free(&intp); 2032 bc_vec_free(&stack); 2033 BC_LONGJMP_CONT; 2034 } 2035 2036 static void bc_num_printBase(BcNum *restrict n, BcBigDig base) { 2037 2038 size_t width; 2039 BcNumDigitOp print; 2040 bool neg = BC_NUM_NEG(n); 2041 2042 if (neg) bc_num_putchar('-'); 2043 2044 BC_NUM_NEG_CLR(n); 2045 2046 if (base <= BC_NUM_MAX_POSIX_IBASE) { 2047 width = 1; 2048 print = bc_num_printHex; 2049 } 2050 else { 2051 assert(base <= BC_BASE_POW); 2052 width = bc_num_log10(base - 1); 2053 print = bc_num_printDigits; 2054 } 2055 2056 bc_num_printNum(n, base, width, print); 2057 n->rdx = BC_NUM_NEG_VAL(n, neg); 2058 } 2059 2060 #if DC_ENABLED && !BC_ENABLE_LIBRARY 2061 void bc_num_stream(BcNum *restrict n, BcBigDig base) { 2062 bc_num_printNum(n, base, 1, bc_num_printChar); 2063 } 2064 #endif // DC_ENABLED && !BC_ENABLE_LIBRARY 2065 2066 void bc_num_setup(BcNum *restrict n, BcDig *restrict num, size_t cap) { 2067 assert(n != NULL); 2068 n->num = num; 2069 n->cap = cap; 2070 bc_num_zero(n); 2071 } 2072 2073 void bc_num_init(BcNum *restrict n, size_t req) { 2074 2075 BcDig *num; 2076 2077 BC_SIG_ASSERT_LOCKED; 2078 2079 assert(n != NULL); 2080 2081 req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE; 2082 2083 if (req == BC_NUM_DEF_SIZE && vm.temps.len) { 2084 BcNum *nptr = bc_vec_top(&vm.temps); 2085 num = nptr->num; 2086 bc_vec_pop(&vm.temps); 2087 } 2088 else num = bc_vm_malloc(BC_NUM_SIZE(req)); 2089 2090 bc_num_setup(n, num, req); 2091 } 2092 2093 void bc_num_clear(BcNum *restrict n) { 2094 n->num = NULL; 2095 n->cap = 0; 2096 } 2097 2098 void bc_num_free(void *num) { 2099 2100 BcNum *n = (BcNum*) num; 2101 2102 BC_SIG_ASSERT_LOCKED; 2103 2104 assert(n != NULL); 2105 2106 if (n->cap == BC_NUM_DEF_SIZE) bc_vec_push(&vm.temps, n); 2107 else free(n->num); 2108 } 2109 2110 void bc_num_copy(BcNum *d, const BcNum *s) { 2111 assert(d != NULL && s != NULL); 2112 if (d == s) return; 2113 bc_num_expand(d, s->len); 2114 d->len = s->len; 2115 // I can just copy directly here. 2116 d->rdx = s->rdx; 2117 d->scale = s->scale; 2118 memcpy(d->num, s->num, BC_NUM_SIZE(d->len)); 2119 } 2120 2121 void bc_num_createCopy(BcNum *d, const BcNum *s) { 2122 BC_SIG_ASSERT_LOCKED; 2123 bc_num_init(d, s->len); 2124 bc_num_copy(d, s); 2125 } 2126 2127 void bc_num_createFromBigdig(BcNum *n, BcBigDig val) { 2128 BC_SIG_ASSERT_LOCKED; 2129 bc_num_init(n, BC_NUM_BIGDIG_LOG10); 2130 bc_num_bigdig2num(n, val); 2131 } 2132 2133 size_t bc_num_scale(const BcNum *restrict n) { 2134 return n->scale; 2135 } 2136 2137 size_t bc_num_len(const BcNum *restrict n) { 2138 2139 size_t len = n->len; 2140 2141 if (BC_NUM_ZERO(n)) return n->scale ? n->scale : 1; 2142 2143 if (BC_NUM_RDX_VAL(n) == len) { 2144 2145 size_t zero, scale; 2146 2147 len = bc_num_nonzeroLen(n); 2148 2149 scale = n->scale % BC_BASE_DIGS; 2150 scale = scale ? scale : BC_BASE_DIGS; 2151 2152 zero = bc_num_zeroDigits(n->num + len - 1); 2153 2154 len = len * BC_BASE_DIGS - zero - (BC_BASE_DIGS - scale); 2155 } 2156 else len = bc_num_intDigits(n) + n->scale; 2157 2158 return len; 2159 } 2160 2161 void bc_num_parse(BcNum *restrict n, const char *restrict val, BcBigDig base) { 2162 2163 assert(n != NULL && val != NULL && base); 2164 assert(base >= BC_NUM_MIN_BASE && base <= vm.maxes[BC_PROG_GLOBALS_IBASE]); 2165 assert(bc_num_strValid(val)); 2166 2167 if (!val[1]) { 2168 BcBigDig dig = bc_num_parseChar(val[0], BC_NUM_MAX_LBASE); 2169 bc_num_bigdig2num(n, dig); 2170 } 2171 else if (base == BC_BASE) bc_num_parseDecimal(n, val); 2172 else bc_num_parseBase(n, val, base); 2173 2174 assert(BC_NUM_RDX_VALID(n)); 2175 } 2176 2177 void bc_num_print(BcNum *restrict n, BcBigDig base, bool newline) { 2178 2179 assert(n != NULL); 2180 assert(BC_ENABLE_EXTRA_MATH || base >= BC_NUM_MIN_BASE); 2181 2182 bc_num_printNewline(); 2183 2184 if (BC_NUM_ZERO(n)) bc_num_printHex(0, 1, false); 2185 else if (base == BC_BASE) bc_num_printDecimal(n); 2186 #if BC_ENABLE_EXTRA_MATH 2187 else if (base == 0 || base == 1) bc_num_printExponent(n, base != 0); 2188 #endif // BC_ENABLE_EXTRA_MATH 2189 else bc_num_printBase(n, base); 2190 2191 if (newline) bc_num_putchar('\n'); 2192 } 2193 2194 void bc_num_bigdig2(const BcNum *restrict n, BcBigDig *result) { 2195 2196 // This function returns no errors because it's guaranteed to succeed if 2197 // its preconditions are met. Those preconditions include both parameters 2198 // being non-NULL, n being non-negative, and n being less than vm.max. If 2199 // all of that is true, then we can just convert without worrying about 2200 // negative errors or overflow. 2201 2202 BcBigDig r = 0; 2203 size_t nrdx = BC_NUM_RDX_VAL(n); 2204 2205 assert(n != NULL && result != NULL); 2206 assert(!BC_NUM_NEG(n)); 2207 assert(bc_num_cmp(n, &vm.max) < 0); 2208 assert(n->len - nrdx <= 3); 2209 2210 // There is a small speed win from unrolling the loop here, and since it 2211 // only adds 53 bytes, I decided that it was worth it. 2212 switch (n->len - nrdx) { 2213 2214 case 3: 2215 { 2216 r = (BcBigDig) n->num[nrdx + 2]; 2217 } 2218 // Fallthrough. 2219 BC_FALLTHROUGH 2220 2221 case 2: 2222 { 2223 r = r * BC_BASE_POW + (BcBigDig) n->num[nrdx + 1]; 2224 } 2225 // Fallthrough. 2226 BC_FALLTHROUGH 2227 2228 case 1: 2229 { 2230 r = r * BC_BASE_POW + (BcBigDig) n->num[nrdx]; 2231 } 2232 } 2233 2234 *result = r; 2235 } 2236 2237 void bc_num_bigdig(const BcNum *restrict n, BcBigDig *result) { 2238 2239 assert(n != NULL && result != NULL); 2240 2241 if (BC_ERR(BC_NUM_NEG(n))) bc_vm_err(BC_ERR_MATH_NEGATIVE); 2242 if (BC_ERR(bc_num_cmp(n, &vm.max) >= 0)) 2243 bc_vm_err(BC_ERR_MATH_OVERFLOW); 2244 2245 bc_num_bigdig2(n, result); 2246 } 2247 2248 void bc_num_bigdig2num(BcNum *restrict n, BcBigDig val) { 2249 2250 BcDig *ptr; 2251 size_t i; 2252 2253 assert(n != NULL); 2254 2255 bc_num_zero(n); 2256 2257 if (!val) return; 2258 2259 bc_num_expand(n, BC_NUM_BIGDIG_LOG10); 2260 2261 for (ptr = n->num, i = 0; val; ++i, val /= BC_BASE_POW) 2262 ptr[i] = val % BC_BASE_POW; 2263 2264 n->len = i; 2265 } 2266 2267 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 2268 void bc_num_rng(const BcNum *restrict n, BcRNG *rng) { 2269 2270 BcNum temp, temp2, intn, frac; 2271 BcRand state1, state2, inc1, inc2; 2272 size_t nrdx = BC_NUM_RDX_VAL(n); 2273 2274 BC_SIG_LOCK; 2275 2276 bc_num_init(&temp, n->len); 2277 bc_num_init(&temp2, n->len); 2278 bc_num_init(&frac, nrdx); 2279 bc_num_init(&intn, bc_num_int(n)); 2280 2281 BC_SETJMP_LOCKED(err); 2282 2283 BC_SIG_UNLOCK; 2284 2285 assert(BC_NUM_RDX_VALID_NP(vm.max)); 2286 2287 memcpy(frac.num, n->num, BC_NUM_SIZE(nrdx)); 2288 frac.len = nrdx; 2289 BC_NUM_RDX_SET_NP(frac, nrdx); 2290 frac.scale = n->scale; 2291 2292 assert(BC_NUM_RDX_VALID_NP(frac)); 2293 assert(BC_NUM_RDX_VALID_NP(vm.max2)); 2294 2295 bc_num_mul(&frac, &vm.max2, &temp, 0); 2296 2297 bc_num_truncate(&temp, temp.scale); 2298 bc_num_copy(&frac, &temp); 2299 2300 memcpy(intn.num, n->num + nrdx, BC_NUM_SIZE(bc_num_int(n))); 2301 intn.len = bc_num_int(n); 2302 2303 // This assert is here because it has to be true. It is also here to justify 2304 // the use of BC_ERR_SIGNAL_ONLY() on each of the divmod's and mod's below. 2305 assert(BC_NUM_NONZERO(&vm.max)); 2306 2307 if (BC_NUM_NONZERO(&frac)) { 2308 2309 bc_num_divmod(&frac, &vm.max, &temp, &temp2, 0); 2310 2311 // frac is guaranteed to be smaller than vm.max * vm.max (pow). 2312 // This means that when dividing frac by vm.max, as above, the 2313 // quotient and remainder are both guaranteed to be less than vm.max, 2314 // which means we can use bc_num_bigdig2() here and not worry about 2315 // overflow. 2316 bc_num_bigdig2(&temp2, (BcBigDig*) &state1); 2317 bc_num_bigdig2(&temp, (BcBigDig*) &state2); 2318 } 2319 else state1 = state2 = 0; 2320 2321 if (BC_NUM_NONZERO(&intn)) { 2322 2323 bc_num_divmod(&intn, &vm.max, &temp, &temp2, 0); 2324 2325 // Because temp2 is the mod of vm.max, from above, it is guaranteed 2326 // to be small enough to use bc_num_bigdig2(). 2327 bc_num_bigdig2(&temp2, (BcBigDig*) &inc1); 2328 2329 if (bc_num_cmp(&temp, &vm.max) >= 0) { 2330 bc_num_copy(&temp2, &temp); 2331 bc_num_mod(&temp2, &vm.max, &temp, 0); 2332 } 2333 2334 // The if statement above ensures that temp is less than vm.max, which 2335 // means that we can use bc_num_bigdig2() here. 2336 bc_num_bigdig2(&temp, (BcBigDig*) &inc2); 2337 } 2338 else inc1 = inc2 = 0; 2339 2340 bc_rand_seed(rng, state1, state2, inc1, inc2); 2341 2342 err: 2343 BC_SIG_MAYLOCK; 2344 bc_num_free(&intn); 2345 bc_num_free(&frac); 2346 bc_num_free(&temp2); 2347 bc_num_free(&temp); 2348 BC_LONGJMP_CONT; 2349 } 2350 2351 void bc_num_createFromRNG(BcNum *restrict n, BcRNG *rng) { 2352 2353 BcRand s1, s2, i1, i2; 2354 BcNum conv, temp1, temp2, temp3; 2355 BcDig temp1_num[BC_RAND_NUM_SIZE], temp2_num[BC_RAND_NUM_SIZE]; 2356 BcDig conv_num[BC_NUM_BIGDIG_LOG10]; 2357 2358 BC_SIG_LOCK; 2359 2360 bc_num_init(&temp3, 2 * BC_RAND_NUM_SIZE); 2361 2362 BC_SETJMP_LOCKED(err); 2363 2364 BC_SIG_UNLOCK; 2365 2366 bc_num_setup(&temp1, temp1_num, sizeof(temp1_num) / sizeof(BcDig)); 2367 bc_num_setup(&temp2, temp2_num, sizeof(temp2_num) / sizeof(BcDig)); 2368 bc_num_setup(&conv, conv_num, sizeof(conv_num) / sizeof(BcDig)); 2369 2370 // This assert is here because it has to be true. It is also here to justify 2371 // the assumption that vm.max2 is not zero. 2372 assert(BC_NUM_NONZERO(&vm.max)); 2373 2374 // Because this is true, we can just use BC_ERR_SIGNAL_ONLY() below when 2375 // dividing by vm.max2. 2376 assert(BC_NUM_NONZERO(&vm.max2)); 2377 2378 bc_rand_getRands(rng, &s1, &s2, &i1, &i2); 2379 2380 bc_num_bigdig2num(&conv, (BcBigDig) s2); 2381 2382 assert(BC_NUM_RDX_VALID_NP(conv)); 2383 2384 bc_num_mul(&conv, &vm.max, &temp1, 0); 2385 2386 bc_num_bigdig2num(&conv, (BcBigDig) s1); 2387 2388 bc_num_add(&conv, &temp1, &temp2, 0); 2389 2390 bc_num_div(&temp2, &vm.max2, &temp3, BC_RAND_STATE_BITS); 2391 2392 bc_num_bigdig2num(&conv, (BcBigDig) i2); 2393 2394 assert(BC_NUM_RDX_VALID_NP(conv)); 2395 2396 bc_num_mul(&conv, &vm.max, &temp1, 0); 2397 2398 bc_num_bigdig2num(&conv, (BcBigDig) i1); 2399 2400 bc_num_add(&conv, &temp1, &temp2, 0); 2401 2402 bc_num_add(&temp2, &temp3, n, 0); 2403 2404 assert(BC_NUM_RDX_VALID(n)); 2405 2406 err: 2407 BC_SIG_MAYLOCK; 2408 bc_num_free(&temp3); 2409 BC_LONGJMP_CONT; 2410 } 2411 2412 void bc_num_irand(const BcNum *restrict a, BcNum *restrict b, 2413 BcRNG *restrict rng) 2414 { 2415 BcRand r; 2416 BcBigDig modl; 2417 BcNum pow, pow2, cp, cp2, mod, temp1, temp2, rand; 2418 BcNum *p1, *p2, *t1, *t2, *c1, *c2, *tmp; 2419 BcDig rand_num[BC_NUM_BIGDIG_LOG10]; 2420 bool carry; 2421 ssize_t cmp; 2422 2423 assert(a != b); 2424 2425 if (BC_ERR(BC_NUM_NEG(a))) bc_vm_err(BC_ERR_MATH_NEGATIVE); 2426 if (BC_ERR(BC_NUM_RDX_VAL(a))) bc_vm_err(BC_ERR_MATH_NON_INTEGER); 2427 if (BC_NUM_ZERO(a) || BC_NUM_ONE(a)) return; 2428 2429 cmp = bc_num_cmp(a, &vm.max); 2430 2431 if (cmp <= 0) { 2432 2433 BcRand bits = 0; 2434 2435 if (cmp < 0) bc_num_bigdig2(a, (BcBigDig*) &bits); 2436 2437 // This condition means that bits is a power of 2. In that case, we 2438 // can just grab a full-size int and mask out the unneeded bits. 2439 // Also, this condition says that 0 is a power of 2, which works for 2440 // us, since a value of 0 means a == rng->max. The bitmask will mask 2441 // nothing in that case as well. 2442 if (!(bits & (bits - 1))) r = bc_rand_int(rng) & (bits - 1); 2443 else r = bc_rand_bounded(rng, bits); 2444 2445 // We made sure that r is less than vm.max, 2446 // so we can use bc_num_bigdig2() here. 2447 bc_num_bigdig2num(b, r); 2448 2449 return; 2450 } 2451 2452 // In the case where a is less than rng->max, we have to make sure we have 2453 // an exclusive bound. This ensures that it happens. (See below.) 2454 carry = (cmp < 0); 2455 2456 BC_SIG_LOCK; 2457 2458 bc_num_createCopy(&cp, a); 2459 2460 bc_num_init(&cp2, cp.len); 2461 bc_num_init(&mod, BC_NUM_BIGDIG_LOG10); 2462 bc_num_init(&temp1, BC_NUM_DEF_SIZE); 2463 bc_num_init(&temp2, BC_NUM_DEF_SIZE); 2464 bc_num_init(&pow2, BC_NUM_DEF_SIZE); 2465 bc_num_init(&pow, BC_NUM_DEF_SIZE); 2466 bc_num_one(&pow); 2467 bc_num_setup(&rand, rand_num, sizeof(rand_num) / sizeof(BcDig)); 2468 2469 BC_SETJMP_LOCKED(err); 2470 2471 BC_SIG_UNLOCK; 2472 2473 p1 = &pow; 2474 p2 = &pow2; 2475 t1 = &temp1; 2476 t2 = &temp2; 2477 c1 = &cp; 2478 c2 = &cp2; 2479 2480 // This assert is here because it has to be true. It is also here to justify 2481 // the use of BC_ERR_SIGNAL_ONLY() on each of the divmod's and mod's below. 2482 assert(BC_NUM_NONZERO(&vm.max)); 2483 2484 while (BC_NUM_NONZERO(c1)) { 2485 2486 bc_num_divmod(c1, &vm.max, c2, &mod, 0); 2487 2488 // Because mod is the mod of vm.max, it is guaranteed to be smaller, 2489 // which means we can use bc_num_bigdig2() here. 2490 bc_num_bigdig(&mod, &modl); 2491 2492 if (bc_num_cmp(c1, &vm.max) < 0) { 2493 2494 // In this case, if there is no carry, then we know we can generate 2495 // an integer *equal* to modl. Thus, we add one if there is no 2496 // carry. Otherwise, we add zero, and we are still bounded properly. 2497 // Since the last portion is guaranteed to be greater than 1, we 2498 // know modl isn't 0 unless there is no carry. 2499 modl += !carry; 2500 2501 if (modl == 1) r = 0; 2502 else if (!modl) r = bc_rand_int(rng); 2503 else r = bc_rand_bounded(rng, (BcRand) modl); 2504 } 2505 else { 2506 if (modl) modl -= carry; 2507 r = bc_rand_int(rng); 2508 carry = (r >= (BcRand) modl); 2509 } 2510 2511 bc_num_bigdig2num(&rand, r); 2512 2513 assert(BC_NUM_RDX_VALID_NP(rand)); 2514 assert(BC_NUM_RDX_VALID(p1)); 2515 2516 bc_num_mul(&rand, p1, p2, 0); 2517 bc_num_add(p2, t1, t2, 0); 2518 2519 if (BC_NUM_NONZERO(c2)) { 2520 2521 assert(BC_NUM_RDX_VALID_NP(vm.max)); 2522 assert(BC_NUM_RDX_VALID(p1)); 2523 2524 bc_num_mul(&vm.max, p1, p2, 0); 2525 2526 tmp = p1; 2527 p1 = p2; 2528 p2 = tmp; 2529 2530 tmp = c1; 2531 c1 = c2; 2532 c2 = tmp; 2533 } 2534 else c1 = c2; 2535 2536 tmp = t1; 2537 t1 = t2; 2538 t2 = tmp; 2539 } 2540 2541 bc_num_copy(b, t1); 2542 bc_num_clean(b); 2543 2544 assert(BC_NUM_RDX_VALID(b)); 2545 2546 err: 2547 BC_SIG_MAYLOCK; 2548 bc_num_free(&pow); 2549 bc_num_free(&pow2); 2550 bc_num_free(&temp2); 2551 bc_num_free(&temp1); 2552 bc_num_free(&mod); 2553 bc_num_free(&cp2); 2554 bc_num_free(&cp); 2555 BC_LONGJMP_CONT; 2556 } 2557 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 2558 2559 size_t bc_num_addReq(const BcNum *a, const BcNum *b, size_t scale) { 2560 2561 size_t aint, bint, ardx, brdx; 2562 2563 BC_UNUSED(scale); 2564 2565 ardx = BC_NUM_RDX_VAL(a); 2566 aint = bc_num_int(a); 2567 assert(aint <= a->len && ardx <= a->len); 2568 2569 brdx = BC_NUM_RDX_VAL(b); 2570 bint = bc_num_int(b); 2571 assert(bint <= b->len && brdx <= b->len); 2572 2573 ardx = BC_MAX(ardx, brdx); 2574 aint = BC_MAX(aint, bint); 2575 2576 return bc_vm_growSize(bc_vm_growSize(ardx, aint), 1); 2577 } 2578 2579 size_t bc_num_mulReq(const BcNum *a, const BcNum *b, size_t scale) { 2580 size_t max, rdx; 2581 rdx = bc_vm_growSize(BC_NUM_RDX_VAL(a), BC_NUM_RDX_VAL(b)); 2582 max = BC_NUM_RDX(scale); 2583 max = bc_vm_growSize(BC_MAX(max, rdx), 1); 2584 rdx = bc_vm_growSize(bc_vm_growSize(bc_num_int(a), bc_num_int(b)), max); 2585 return rdx; 2586 } 2587 2588 size_t bc_num_divReq(const BcNum *a, const BcNum *b, size_t scale) { 2589 size_t max, rdx; 2590 rdx = bc_vm_growSize(BC_NUM_RDX_VAL(a), BC_NUM_RDX_VAL(b)); 2591 max = BC_NUM_RDX(scale); 2592 max = bc_vm_growSize(BC_MAX(max, rdx), 1); 2593 rdx = bc_vm_growSize(bc_num_int(a), max); 2594 return rdx; 2595 } 2596 2597 size_t bc_num_powReq(const BcNum *a, const BcNum *b, size_t scale) { 2598 BC_UNUSED(scale); 2599 return bc_vm_growSize(bc_vm_growSize(a->len, b->len), 1); 2600 } 2601 2602 #if BC_ENABLE_EXTRA_MATH 2603 size_t bc_num_placesReq(const BcNum *a, const BcNum *b, size_t scale) { 2604 BC_UNUSED(scale); 2605 return a->len + b->len - BC_NUM_RDX_VAL(a) - BC_NUM_RDX_VAL(b); 2606 } 2607 #endif // BC_ENABLE_EXTRA_MATH 2608 2609 void bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) { 2610 assert(BC_NUM_RDX_VALID(a)); 2611 assert(BC_NUM_RDX_VALID(b)); 2612 bc_num_binary(a, b, c, false, bc_num_as, bc_num_addReq(a, b, scale)); 2613 } 2614 2615 void bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) { 2616 assert(BC_NUM_RDX_VALID(a)); 2617 assert(BC_NUM_RDX_VALID(b)); 2618 bc_num_binary(a, b, c, true, bc_num_as, bc_num_addReq(a, b, scale)); 2619 } 2620 2621 void bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) { 2622 assert(BC_NUM_RDX_VALID(a)); 2623 assert(BC_NUM_RDX_VALID(b)); 2624 bc_num_binary(a, b, c, scale, bc_num_m, bc_num_mulReq(a, b, scale)); 2625 } 2626 2627 void bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) { 2628 assert(BC_NUM_RDX_VALID(a)); 2629 assert(BC_NUM_RDX_VALID(b)); 2630 bc_num_binary(a, b, c, scale, bc_num_d, bc_num_divReq(a, b, scale)); 2631 } 2632 2633 void bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) { 2634 assert(BC_NUM_RDX_VALID(a)); 2635 assert(BC_NUM_RDX_VALID(b)); 2636 bc_num_binary(a, b, c, scale, bc_num_rem, bc_num_divReq(a, b, scale)); 2637 } 2638 2639 void bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) { 2640 assert(BC_NUM_RDX_VALID(a)); 2641 assert(BC_NUM_RDX_VALID(b)); 2642 bc_num_binary(a, b, c, scale, bc_num_p, bc_num_powReq(a, b, scale)); 2643 } 2644 2645 #if BC_ENABLE_EXTRA_MATH 2646 void bc_num_places(BcNum *a, BcNum *b, BcNum *c, size_t scale) { 2647 assert(BC_NUM_RDX_VALID(a)); 2648 assert(BC_NUM_RDX_VALID(b)); 2649 bc_num_binary(a, b, c, scale, bc_num_place, bc_num_placesReq(a, b, scale)); 2650 } 2651 2652 void bc_num_lshift(BcNum *a, BcNum *b, BcNum *c, size_t scale) { 2653 assert(BC_NUM_RDX_VALID(a)); 2654 assert(BC_NUM_RDX_VALID(b)); 2655 bc_num_binary(a, b, c, scale, bc_num_left, bc_num_placesReq(a, b, scale)); 2656 } 2657 2658 void bc_num_rshift(BcNum *a, BcNum *b, BcNum *c, size_t scale) { 2659 assert(BC_NUM_RDX_VALID(a)); 2660 assert(BC_NUM_RDX_VALID(b)); 2661 bc_num_binary(a, b, c, scale, bc_num_right, bc_num_placesReq(a, b, scale)); 2662 } 2663 #endif // BC_ENABLE_EXTRA_MATH 2664 2665 void bc_num_sqrt(BcNum *restrict a, BcNum *restrict b, size_t scale) { 2666 2667 BcNum num1, num2, half, f, fprime, *x0, *x1, *temp; 2668 size_t pow, len, rdx, req, resscale; 2669 BcDig half_digs[1]; 2670 2671 assert(a != NULL && b != NULL && a != b); 2672 2673 if (BC_ERR(BC_NUM_NEG(a))) bc_vm_err(BC_ERR_MATH_NEGATIVE); 2674 2675 if (a->scale > scale) scale = a->scale; 2676 2677 len = bc_vm_growSize(bc_num_intDigits(a), 1); 2678 rdx = BC_NUM_RDX(scale); 2679 req = bc_vm_growSize(BC_MAX(rdx, BC_NUM_RDX_VAL(a)), len >> 1); 2680 2681 BC_SIG_LOCK; 2682 2683 bc_num_init(b, bc_vm_growSize(req, 1)); 2684 2685 BC_SIG_UNLOCK; 2686 2687 assert(a != NULL && b != NULL && a != b); 2688 assert(a->num != NULL && b->num != NULL); 2689 2690 if (BC_NUM_ZERO(a)) { 2691 bc_num_setToZero(b, scale); 2692 return; 2693 } 2694 if (BC_NUM_ONE(a)) { 2695 bc_num_one(b); 2696 bc_num_extend(b, scale); 2697 return; 2698 } 2699 2700 rdx = BC_NUM_RDX(scale); 2701 rdx = BC_MAX(rdx, BC_NUM_RDX_VAL(a)); 2702 len = bc_vm_growSize(a->len, rdx); 2703 2704 BC_SIG_LOCK; 2705 2706 bc_num_init(&num1, len); 2707 bc_num_init(&num2, len); 2708 bc_num_setup(&half, half_digs, sizeof(half_digs) / sizeof(BcDig)); 2709 2710 bc_num_one(&half); 2711 half.num[0] = BC_BASE_POW / 2; 2712 half.len = 1; 2713 BC_NUM_RDX_SET_NP(half, 1); 2714 half.scale = 1; 2715 2716 bc_num_init(&f, len); 2717 bc_num_init(&fprime, len); 2718 2719 BC_SETJMP_LOCKED(err); 2720 2721 BC_SIG_UNLOCK; 2722 2723 x0 = &num1; 2724 x1 = &num2; 2725 2726 bc_num_one(x0); 2727 pow = bc_num_intDigits(a); 2728 2729 if (pow) { 2730 2731 if (pow & 1) x0->num[0] = 2; 2732 else x0->num[0] = 6; 2733 2734 pow -= 2 - (pow & 1); 2735 bc_num_shiftLeft(x0, pow / 2); 2736 } 2737 2738 // I can set the rdx here directly because neg should be false. 2739 x0->scale = x0->rdx = 0; 2740 resscale = (scale + BC_BASE_DIGS) + 2; 2741 2742 while (bc_num_cmp(x1, x0)) { 2743 2744 assert(BC_NUM_NONZERO(x0)); 2745 2746 bc_num_div(a, x0, &f, resscale); 2747 bc_num_add(x0, &f, &fprime, resscale); 2748 2749 assert(BC_NUM_RDX_VALID_NP(fprime)); 2750 assert(BC_NUM_RDX_VALID_NP(half)); 2751 2752 bc_num_mul(&fprime, &half, x1, resscale); 2753 2754 temp = x0; 2755 x0 = x1; 2756 x1 = temp; 2757 } 2758 2759 bc_num_copy(b, x0); 2760 if (b->scale > scale) bc_num_truncate(b, b->scale - scale); 2761 2762 assert(!BC_NUM_NEG(b) || BC_NUM_NONZERO(b)); 2763 assert(BC_NUM_RDX_VALID(b)); 2764 assert(BC_NUM_RDX_VAL(b) <= b->len || !b->len); 2765 assert(!b->len || b->num[b->len - 1] || BC_NUM_RDX_VAL(b) == b->len); 2766 2767 err: 2768 BC_SIG_MAYLOCK; 2769 bc_num_free(&fprime); 2770 bc_num_free(&f); 2771 bc_num_free(&num2); 2772 bc_num_free(&num1); 2773 BC_LONGJMP_CONT; 2774 } 2775 2776 void bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, size_t scale) { 2777 2778 size_t ts, len; 2779 BcNum *ptr_a, num2; 2780 bool init = false; 2781 2782 ts = BC_MAX(scale + b->scale, a->scale); 2783 len = bc_num_mulReq(a, b, ts); 2784 2785 assert(a != NULL && b != NULL && c != NULL && d != NULL); 2786 assert(c != d && a != d && b != d && b != c); 2787 2788 if (c == a) { 2789 2790 memcpy(&num2, c, sizeof(BcNum)); 2791 ptr_a = &num2; 2792 2793 BC_SIG_LOCK; 2794 2795 bc_num_init(c, len); 2796 2797 init = true; 2798 2799 BC_SETJMP_LOCKED(err); 2800 2801 BC_SIG_UNLOCK; 2802 } 2803 else { 2804 ptr_a = a; 2805 bc_num_expand(c, len); 2806 } 2807 2808 if (BC_NUM_NONZERO(a) && !BC_NUM_RDX_VAL(a) && 2809 !BC_NUM_RDX_VAL(b) && b->len == 1 && !scale) 2810 { 2811 BcBigDig rem; 2812 2813 bc_num_divArray(ptr_a, (BcBigDig) b->num[0], c, &rem); 2814 2815 assert(rem < BC_BASE_POW); 2816 2817 d->num[0] = (BcDig) rem; 2818 d->len = (rem != 0); 2819 } 2820 else bc_num_r(ptr_a, b, c, d, scale, ts); 2821 2822 assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c)); 2823 assert(BC_NUM_RDX_VALID(c)); 2824 assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len); 2825 assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len); 2826 assert(!BC_NUM_NEG(d) || BC_NUM_NONZERO(d)); 2827 assert(BC_NUM_RDX_VALID(d)); 2828 assert(BC_NUM_RDX_VAL(d) <= d->len || !d->len); 2829 assert(!d->len || d->num[d->len - 1] || BC_NUM_RDX_VAL(d) == d->len); 2830 2831 err: 2832 if (init) { 2833 BC_SIG_MAYLOCK; 2834 bc_num_free(&num2); 2835 BC_LONGJMP_CONT; 2836 } 2837 } 2838 2839 #if DC_ENABLED 2840 void bc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) { 2841 2842 BcNum base, exp, two, temp; 2843 BcDig two_digs[2]; 2844 2845 assert(a != NULL && b != NULL && c != NULL && d != NULL); 2846 assert(a != d && b != d && c != d); 2847 2848 if (BC_ERR(BC_NUM_ZERO(c))) bc_vm_err(BC_ERR_MATH_DIVIDE_BY_ZERO); 2849 if (BC_ERR(BC_NUM_NEG(b))) bc_vm_err(BC_ERR_MATH_NEGATIVE); 2850 if (BC_ERR(BC_NUM_RDX_VAL(a) || BC_NUM_RDX_VAL(b) || BC_NUM_RDX_VAL(c))) 2851 bc_vm_err(BC_ERR_MATH_NON_INTEGER); 2852 2853 bc_num_expand(d, c->len); 2854 2855 BC_SIG_LOCK; 2856 2857 bc_num_init(&base, c->len); 2858 bc_num_setup(&two, two_digs, sizeof(two_digs) / sizeof(BcDig)); 2859 bc_num_init(&temp, b->len + 1); 2860 bc_num_createCopy(&exp, b); 2861 2862 BC_SETJMP_LOCKED(err); 2863 2864 BC_SIG_UNLOCK; 2865 2866 bc_num_one(&two); 2867 two.num[0] = 2; 2868 bc_num_one(d); 2869 2870 // We already checked for 0. 2871 bc_num_rem(a, c, &base, 0); 2872 2873 while (BC_NUM_NONZERO(&exp)) { 2874 2875 // Num two cannot be 0, so no errors. 2876 bc_num_divmod(&exp, &two, &exp, &temp, 0); 2877 2878 if (BC_NUM_ONE(&temp) && !BC_NUM_NEG_NP(temp)) { 2879 2880 assert(BC_NUM_RDX_VALID(d)); 2881 assert(BC_NUM_RDX_VALID_NP(base)); 2882 2883 bc_num_mul(d, &base, &temp, 0); 2884 2885 // We already checked for 0. 2886 bc_num_rem(&temp, c, d, 0); 2887 } 2888 2889 assert(BC_NUM_RDX_VALID_NP(base)); 2890 2891 bc_num_mul(&base, &base, &temp, 0); 2892 2893 // We already checked for 0. 2894 bc_num_rem(&temp, c, &base, 0); 2895 } 2896 2897 err: 2898 BC_SIG_MAYLOCK; 2899 bc_num_free(&exp); 2900 bc_num_free(&temp); 2901 bc_num_free(&base); 2902 BC_LONGJMP_CONT; 2903 assert(!BC_NUM_NEG(d) || d->len); 2904 assert(BC_NUM_RDX_VALID(d)); 2905 assert(!d->len || d->num[d->len - 1] || BC_NUM_RDX_VAL(d) == d->len); 2906 } 2907 #endif // DC_ENABLED 2908 2909 #if BC_DEBUG_CODE 2910 void bc_num_printDebug(const BcNum *n, const char *name, bool emptyline) { 2911 bc_file_puts(&vm.fout, name); 2912 bc_file_puts(&vm.fout, ": "); 2913 bc_num_printDecimal(n); 2914 bc_file_putchar(&vm.fout, '\n'); 2915 if (emptyline) bc_file_putchar(&vm.fout, '\n'); 2916 vm.nchars = 0; 2917 } 2918 2919 void bc_num_printDigs(const BcDig *n, size_t len, bool emptyline) { 2920 2921 size_t i; 2922 2923 for (i = len - 1; i < len; --i) 2924 bc_file_printf(&vm.fout, " %lu", (unsigned long) n[i]); 2925 2926 bc_file_putchar(&vm.fout, '\n'); 2927 if (emptyline) bc_file_putchar(&vm.fout, '\n'); 2928 vm.nchars = 0; 2929 } 2930 2931 void bc_num_printWithDigs(const BcNum *n, const char *name, bool emptyline) { 2932 bc_file_puts(&vm.fout, name); 2933 bc_file_printf(&vm.fout, " len: %zu, rdx: %zu, scale: %zu\n", 2934 name, n->len, BC_NUM_RDX_VAL(n), n->scale); 2935 bc_num_printDigs(n->num, n->len, emptyline); 2936 } 2937 2938 void bc_num_dump(const char *varname, const BcNum *n) { 2939 2940 ulong i, scale = n->scale; 2941 2942 bc_file_printf(&vm.ferr, "\n%s = %s", varname, 2943 n->len ? (BC_NUM_NEG(n) ? "-" : "+") : "0 "); 2944 2945 for (i = n->len - 1; i < n->len; --i) { 2946 2947 if (i + 1 == BC_NUM_RDX_VAL(n)) bc_file_puts(&vm.ferr, ". "); 2948 2949 if (scale / BC_BASE_DIGS != BC_NUM_RDX_VAL(n) - i - 1) 2950 bc_file_printf(&vm.ferr, "%lu ", (unsigned long) n->num[i]); 2951 else { 2952 2953 int mod = scale % BC_BASE_DIGS; 2954 int d = BC_BASE_DIGS - mod; 2955 BcDig div; 2956 2957 if (mod != 0) { 2958 div = n->num[i] / ((BcDig) bc_num_pow10[(ulong) d]); 2959 bc_file_printf(&vm.ferr, "%lu", (unsigned long) div); 2960 } 2961 2962 div = n->num[i] % ((BcDig) bc_num_pow10[(ulong) d]); 2963 bc_file_printf(&vm.ferr, " ' %lu ", (unsigned long) div); 2964 } 2965 } 2966 2967 bc_file_printf(&vm.ferr, "(%zu | %zu.%zu / %zu) %lu\n", 2968 n->scale, n->len, BC_NUM_RDX_VAL(n), n->cap, 2969 (unsigned long) (void*) n->num); 2970 } 2971 #endif // BC_DEBUG_CODE 2972