zsub.c (1941B)
1 /* See LICENSE file for copyright and license details. */ 2 #include "internals.h" 3 4 5 static inline void 6 zsub_impl(z_t a, z_t b, size_t n) 7 { 8 zahl_char_t carry = 0, tcarry; 9 size_t i; 10 11 for (i = 0; i < n; i++) { 12 tcarry = carry ? (a->chars[i] <= b->chars[i]) : (a->chars[i] < b->chars[i]); 13 a->chars[i] -= b->chars[i]; 14 a->chars[i] -= carry; 15 carry = tcarry; 16 } 17 18 if (carry) { 19 while (!a->chars[i]) 20 a->chars[i++] = ZAHL_CHAR_MAX; 21 if (a->chars[i] == 1) 22 a->used--; 23 else 24 a->chars[i] -= 1; 25 } 26 } 27 28 static inline void 29 libzahl_zsub_unsigned(z_t a, z_t b, z_t c) 30 { 31 int magcmp; 32 size_t n; 33 34 if (unlikely(zzero(b))) { 35 zabs(a, c); 36 zneg(a, a); 37 return; 38 } else if (unlikely(zzero(c))) { 39 zabs(a, b); 40 return; 41 } 42 43 magcmp = zcmpmag(b, c); 44 if (unlikely(magcmp <= 0)) { 45 if (unlikely(magcmp == 0)) { 46 SET_SIGNUM(a, 0); 47 return; 48 } 49 n = b->used; 50 if (a == b) { 51 zset(libzahl_tmp_sub, b); 52 SET(a, c); 53 zsub_impl(a, libzahl_tmp_sub, n); 54 } else { 55 SET(a, c); 56 zsub_impl(a, b, n); 57 } 58 } else { 59 n = c->used; 60 if (unlikely(a == c)) { 61 zset(libzahl_tmp_sub, c); 62 SET(a, b); 63 zsub_impl(a, libzahl_tmp_sub, n); 64 } else { 65 SET(a, b); 66 zsub_impl(a, c, n); 67 } 68 } 69 70 SET_SIGNUM(a, magcmp); 71 } 72 73 void 74 zsub_unsigned(z_t a, z_t b, z_t c) 75 { 76 libzahl_zsub_unsigned(a, b, c); 77 } 78 79 void 80 zsub_nonnegative_assign(z_t a, z_t b) 81 { 82 if (unlikely(zzero(b))) 83 zabs(a, a); 84 else if (unlikely(!zcmpmag(a, b))) 85 SET_SIGNUM(a, 0); 86 else 87 zsub_impl(a, b, b->used); 88 } 89 90 void 91 zsub_positive_assign(z_t a, z_t b) 92 { 93 zsub_impl(a, b, b->used); 94 } 95 96 void 97 zsub(z_t a, z_t b, z_t c) 98 { 99 if (unlikely(zzero(b))) { 100 zneg(a, c); 101 } else if (unlikely(zzero(c))) { 102 SET(a, b); 103 } else if (unlikely(znegative(b))) { 104 if (znegative(c)) { 105 libzahl_zsub_unsigned(a, c, b); 106 } else { 107 zadd_unsigned(a, b, c); 108 SET_SIGNUM(a, -zsignum(a)); 109 } 110 } else if (znegative(c)) { 111 zadd_unsigned(a, b, c); 112 } else { 113 libzahl_zsub_unsigned(a, b, c); 114 } 115 }