| zsqr.c - libzahl - big integer library | |
| git clone git://git.suckless.org/libzahl | |
| Log | |
| Files | |
| Refs | |
| README | |
| LICENSE | |
| --- | |
| zsqr.c (1377B) | |
| --- | |
| 1 /* See LICENSE file for copyright and license details. */ | |
| 2 #include "internals.h" | |
| 3 | |
| 4 | |
| 5 static inline void | |
| 6 zsqr_ll_single_char(z_t a, z_t b) | |
| 7 { | |
| 8 ENSURE_SIZE(a, 1); | |
| 9 a->used = 1; | |
| 10 a->chars[0] = b->chars[0] * b->chars[0]; | |
| 11 SET_SIGNUM(a, 1); | |
| 12 } | |
| 13 | |
| 14 void | |
| 15 zsqr_ll(z_t a, z_t b) | |
| 16 { | |
| 17 /* | |
| 18 * Karatsuba algorithm, optimised for equal factors. | |
| 19 */ | |
| 20 | |
| 21 #define z2 a | |
| 22 z_t z0, z1, high, low; | |
| 23 zahl_char_t auxchars[3 * ZAHL_FLUFF]; | |
| 24 size_t bits; | |
| 25 | |
| 26 bits = zbits(b); | |
| 27 | |
| 28 if (bits <= BITS_PER_CHAR / 2) { | |
| 29 zsqr_ll_single_char(a, b); | |
| 30 return; | |
| 31 } | |
| 32 | |
| 33 bits >>= 1; | |
| 34 | |
| 35 /* Try to split only at a character level rather than a bit leve… | |
| 36 * Such splits are faster, even if bit-level is required, and do | |
| 37 * not require auxiliary memory except for the bit-level split | |
| 38 * which require constant auxiliary memory. */ | |
| 39 if (bits < BITS_PER_CHAR) { | |
| 40 low->chars = auxchars; | |
| 41 high->chars = auxchars + ZAHL_FLUFF; | |
| 42 zsplit_unsigned_fast_small_auto(high, low, b, bits); | |
| 43 } else { | |
| 44 bits = TRUNCATE_TO_CHAR(bits); | |
| 45 zsplit_unsigned_fast_large_taint(high, low, b, bits); | |
| 46 } | |
| 47 | |
| 48 | |
| 49 if (unlikely(zzero(low))) { | |
| 50 zsqr_ll(z2, high); | |
| 51 zlsh(a, z2, bits << 1); | |
| 52 } else { | |
| 53 zinit_temp(z0); | |
| 54 zinit_temp(z1); | |
| 55 | |
| 56 zsqr_ll(z0, low); | |
| 57 | |
| 58 zmul_ll(z1, low, high); | |
| 59 zlsh(z1, z1, bits + 1); | |
| 60 | |
| 61 zsqr_ll(z2, high); | |
| 62 zlsh(a, z2, bits << 1); | |
| 63 | |
| 64 zadd_unsigned_assign(a, z1); | |
| 65 zadd_unsigned_assign(a, z0); | |
| 66 | |
| 67 zfree_temp(z1); | |
| 68 zfree_temp(z0); | |
| 69 } | |
| 70 } |