| File: | subcmd/unitools/bigint.c |
| Warning: | line 2242, column 20 The result of left shift is undefined because the right operand is >= 32, not smaller than 32, the capacity of 'BIntS' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /***************************************************************************** | |||
| 2 | * | |||
| 3 | * bigint.c: Big integer arithmetic. | |||
| 4 | * | |||
| 5 | * Copyright (c) 1990-2007 Aldor Software Organization Ltd (Aldor.org). | |||
| 6 | * | |||
| 7 | ****************************************************************************/ | |||
| 8 | ||||
| 9 | /* | |||
| 10 | * Operations of the form "bintAaaa" do not modify their arguments, | |||
| 11 | * and always allocate new values as their results. E.g., the statement | |||
| 12 | * | |||
| 13 | * b1 = bintShift(b0, i); | |||
| 14 | * | |||
| 15 | * causes the BInt value b0 to be shifted by i bits, creating | |||
| 16 | * a new BInt value b1. | |||
| 17 | * These operations work on normalized numbers. | |||
| 18 | * I.e. When a number is small enough, it is represented immediately. | |||
| 19 | * Otherwise it is stored and Placec(b) > 0 && Placev(b)[Placec(b)-1] != 0. | |||
| 20 | * | |||
| 21 | * Operations of the form "xintAaaa" can modify their arguments or, | |||
| 22 | * if necessary, reallocate and free their input. | |||
| 23 | * | |||
| 24 | * Operations of the form "iintAaaa" do no storage allocation whatsoever | |||
| 25 | * and perform the big integer arithmetic algorithms. | |||
| 26 | */ | |||
| 27 | ||||
| 28 | #include "axlgen.h" | |||
| 29 | #include "bigint.h" | |||
| 30 | #include "debug.h" | |||
| 31 | #include "store.h" | |||
| 32 | #include "util.h" | |||
| 33 | #include "compopt.h" | |||
| 34 | ||||
| 35 | /* | |||
| 36 | * The following symbols are used to conditionalize code in this file: | |||
| 37 | * | |||
| 38 | * BIGINT_DO_DEBUG -- Turns on DEBUG(bint) blocks. | |||
| 39 | * BIGINT_DEBUG_IMMED -- Turns on (bad) code for generalized ImmedIfCan. | |||
| 40 | * BIGINT_SHORT_IMMED -- Defines IInt as "short" rather than "int". | |||
| 41 | * BIGINT_USE_WHOLE_WORDS -- Turns on (incomplete) code for long bint digits. | |||
| 42 | * BIGINT_SHHH -- Turns off all debugging code. | |||
| 43 | * | |||
| 44 | */ | |||
| 45 | ||||
| 46 | ||||
| 47 | /* | |||
| 48 | * Define BIGINT_DO_DEBUG to display debug info. | |||
| 49 | */ | |||
| 50 | #ifdef BIGINT_DO_DEBUG | |||
| 51 | # define bintDebug((int) 0) true1 | |||
| 52 | #else | |||
| 53 | # define bintDebug((int) 0) false((int) 0) | |||
| 54 | #endif | |||
| 55 | ||||
| 56 | #define bintDEBUGif (!((int) 0)) { } else fprintf DEBUG_IF(bint)if (!((int) 0)) { } else fprintf | |||
| 57 | ||||
| 58 | #ifdef FOAM_RTS | |||
| 59 | # define dbOut stdoutstdout | |||
| 60 | #endif | |||
| 61 | ||||
| 62 | /***************************************************************************** | |||
| 63 | * | |||
| 64 | * :: Remove linkage to String (and hence format.c etc) | |||
| 65 | * | |||
| 66 | ****************************************************************************/ | |||
| 67 | ||||
| 68 | localstatic String | |||
| 69 | localStrAlloc(Length n) | |||
| 70 | { | |||
| 71 | String s; | |||
| 72 | s = (String) stoAlloc((unsigned) OB_String7, n + 1); | |||
| 73 | s[0] = 0; | |||
| 74 | s[n] = 0; | |||
| 75 | return s; | |||
| 76 | } | |||
| 77 | ||||
| 78 | localstatic void | |||
| 79 | localStrFree(String s) | |||
| 80 | { | |||
| 81 | stoFree((Pointer) s); | |||
| 82 | } | |||
| 83 | ||||
| 84 | /***************************************************************************** | |||
| 85 | * | |||
| 86 | * :: Integer range defintitions | |||
| 87 | * | |||
| 88 | * Should work for 2's complement n-bit ints, for even n >= 4. | |||
| 89 | * | |||
| 90 | *****************************************************************************/ | |||
| 91 | ||||
| 92 | ||||
| 93 | #ifdef BIGINT_SHORT_IMMED | |||
| 94 | typedef short IInt; | |||
| 95 | typedef UShort UIInt; | |||
| 96 | #else | |||
| 97 | typedef long IInt; | |||
| 98 | typedef unsigned long UIInt; | |||
| 99 | #endif | |||
| 100 | ||||
| 101 | ||||
| 102 | /* | |||
| 103 | * Conversion between ints and immediate BInts. | |||
| 104 | */ | |||
| 105 | #define IsImmed(b)((long)(b) & 1) ((long)(b) & 1) | |||
| 106 | #define MkImmed(n)((((long)(n)) << 1) | 1) ((((long)(n)) << 1) | 1) | |||
| 107 | #define UnImmed(n)((n) >> 1) ((n) >> 1) | |||
| 108 | ||||
| 109 | #define BIntToInt(b)((IInt) ((((long) (b))) >> 1)) ((IInt) UnImmed(ptrToLong(b))((((long) (b))) >> 1)) | |||
| 110 | #define IntToBInt(n)((BInt) ((Pointer)(((((long)(n)) << 1) | 1)))) ((BInt) ptrFrLong(MkImmed(n))((Pointer)(((((long)(n)) << 1) | 1)))) | |||
| 111 | #define BIntZero((BInt) ((((long)(0)) << 1) | 1)) ((BInt) MkImmed(0)((((long)(0)) << 1) | 1)) | |||
| 112 | #define BIntOne((BInt) ((((long)(1)) << 1) | 1)) ((BInt) MkImmed(1)((((long)(1)) << 1) | 1)) | |||
| 113 | ||||
| 114 | /* | |||
| 115 | * Fields of stored BInts. | |||
| 116 | */ | |||
| 117 | #define Beq(a,b)((a) == (b)) ((a) == (b)) | |||
| 118 | #define IsNeg(b)((b)->isNeg) ((b)->isNeg) | |||
| 119 | #define Placec(b)((b)->placec) ((b)->placec) | |||
| 120 | #define Placea(b)((b)->placea) ((b)->placea) | |||
| 121 | #define Placev(b)((b)->placev) ((b)->placev) | |||
| 122 | ||||
| 123 | /* | |||
| 124 | * The minimum and maximum values of type int. | |||
| 125 | */ | |||
| 126 | #ifndef INT_MIN(-2147483647 -1) | |||
| 127 | # define INT_MIN(-2147483647 -1) ((IInt) ((-1)<<(bitsizeof(IInt)(8 * sizeof(IInt))-1))) | |||
| 128 | # define INT_MAX2147483647 (- (INT_MIN(-2147483647 -1) + 1)) /* 2's complement */ | |||
| 129 | #endif | |||
| 130 | ||||
| 131 | /* | |||
| 132 | * These are the min + max int values which are represented as immediate BInts. | |||
| 133 | * These must satisfy BIntToInt(IntToBInt(n)) == n, | |||
| 134 | * hence the "-2" in INT_MIN_IMMED. | |||
| 135 | */ | |||
| 136 | #define INT_LG_IMMED((8 * sizeof(IInt))-2) (bitsizeof(IInt)(8 * sizeof(IInt))-2) | |||
| 137 | #define INT_MIN_IMMED((((IInt) 3) << ((8 * sizeof(IInt))-2)) + 1) ((((IInt) 3) << INT_LG_IMMED((8 * sizeof(IInt))-2)) + 1) | |||
| 138 | #define INT_MAX_IMMED(- (long) ((((IInt) 3) << ((8 * sizeof(IInt))-2)) + 1)) (- (long) INT_MIN_IMMED((((IInt) 3) << ((8 * sizeof(IInt))-2)) + 1)) | |||
| 139 | #define INT_IS_IMMED(n)(((((IInt) 3) << ((8 * sizeof(IInt))-2)) + 1)<= (long )(n) && (long)(n)<= (- (long) ((((IInt) 3) << ((8 * sizeof(IInt))-2)) + 1))) (INT_MIN_IMMED((((IInt) 3) << ((8 * sizeof(IInt))-2)) + 1)<= (long)(n) && (long)(n)<= INT_MAX_IMMED(- (long) ((((IInt) 3) << ((8 * sizeof(IInt))-2)) + 1))) | |||
| 140 | ||||
| 141 | #define INT_LG_HALF(((8 * sizeof(IInt))-2)/2) ((bitsizeof(IInt)(8 * sizeof(IInt))-2)/2) | |||
| 142 | #define INT_MAX_HALF((((IInt) 1)<<((((8 * sizeof(IInt))-2)/2))) -1) ((((IInt) 1)<<(INT_LG_HALF(((8 * sizeof(IInt))-2)/2))) -1) | |||
| 143 | #define INT_MIN_HALF(-((((IInt) 1)<<((((8 * sizeof(IInt))-2)/2))) -1)) (-INT_MAX_HALF((((IInt) 1)<<((((8 * sizeof(IInt))-2)/2))) -1)) | |||
| 144 | #define INT_IS_HALF(n)((-((((IInt) 1)<<((((8 * sizeof(IInt))-2)/2))) -1)) <= (long)(n) && (long)(n)<= ((((IInt) 1)<<(((( 8 * sizeof(IInt))-2)/2))) -1)) (INT_MIN_HALF(-((((IInt) 1)<<((((8 * sizeof(IInt))-2)/2))) -1)) <= (long)(n) && (long)(n)<= INT_MAX_HALF((((IInt) 1)<<((((8 * sizeof(IInt))-2)/2))) -1)) | |||
| 145 | ||||
| 146 | /* | |||
| 147 | * Calculation radix. | |||
| 148 | * Must be possible to detect overflow on addition and implement double word | |||
| 149 | * multiply and divide. | |||
| 150 | */ | |||
| 151 | ||||
| 152 | #ifdef BIGINT_DO_DEBUG | |||
| 153 | # define BINT_LG_RADIX((8 * sizeof(BIntS))) 7 | |||
| 154 | #else | |||
| 155 | # define BINT_LG_RADIX((8 * sizeof(BIntS))) (bitsizeof(BIntS)(8 * sizeof(BIntS))) | |||
| 156 | #endif | |||
| 157 | #define BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS)))) (((unsigned long) 1) << BINT_LG_RADIX((8 * sizeof(BIntS)))) | |||
| 158 | /* Might not be representable! */ | |||
| 159 | #define BINT_RADIX_MASK((((unsigned long) 1) << ((8 * sizeof(BIntS)))) - 1) (BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS)))) - 1) | |||
| 160 | #define BINT_RADIX_MINUS_1((((unsigned long) 1) << ((8 * sizeof(BIntS)))) - 1) (BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS)))) - 1) | |||
| 161 | ||||
| 162 | /***************************************************************************** | |||
| 163 | * | |||
| 164 | * :: Double precision arithmetic macros | |||
| 165 | * | |||
| 166 | *****************************************************************************/ | |||
| 167 | ||||
| 168 | typedef ULong BIntD; /* To contain two BInt digits. */ | |||
| 169 | ||||
| 170 | #define TestGTDouble(b, h1, l1, h2, l2){ BIntS h1_ = (h1), h2_ = (h2); (b) = (h1_ > h2_) || (h1_ == h2_ && (l1)>(l2)); } { \ | |||
| 171 | BIntS h1_ = (h1), h2_ = (h2); \ | |||
| 172 | (b) = (h1_ > h2_) || (h1_ == h2_ && (l1)>(l2)); \ | |||
| 173 | } | |||
| 174 | ||||
| 175 | #define TimesDouble(h, l, a, b){ BIntD t_ = (BIntD)(a)*(BIntD)(b); (h) = t_ / (((unsigned long ) 1) << ((8 * sizeof(BIntS)))); (l) = t_ % (((unsigned long ) 1) << ((8 * sizeof(BIntS)))); } { \ | |||
| 176 | BIntD t_ = (BIntD)(a)*(BIntD)(b); \ | |||
| 177 | (h) = t_ / BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS)))); \ | |||
| 178 | (l) = t_ % BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS)))); \ | |||
| 179 | } | |||
| 180 | ||||
| 181 | #define DivideDouble(q, r, nh, nl, d){ BIntD n_ = (BIntD)(nh)*(BIntD)(((unsigned long) 1) << ((8 * sizeof(BIntS)))) + (nl); BIntD d_ = (d); (q) = n_ / d_ ; (r) = n_ % d_; } { \ | |||
| 182 | BIntD n_ = (BIntD)(nh)*(BIntD)BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS)))) + (nl);\ | |||
| 183 | BIntD d_ = (d); \ | |||
| 184 | (q) = n_ / d_; \ | |||
| 185 | (r) = n_ % d_; \ | |||
| 186 | } | |||
| 187 | ||||
| 188 | #define PlusStep(kout, r, a, b, kin){ BIntD r_ = (BIntD)(a)+(BIntD)(b)+(BIntD)(kin); BIntS k_ = ( r_ >= (BIntD) (((unsigned long) 1) << ((8 * sizeof(BIntS ))))); if (k_) r_ -= (((unsigned long) 1) << ((8 * sizeof (BIntS)))); (r) = r_; (kout) = k_; } { \ | |||
| 189 | BIntD r_ = (BIntD)(a)+(BIntD)(b)+(BIntD)(kin);\ | |||
| 190 | BIntS k_ = (r_ >= (BIntD) BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS))))); \ | |||
| 191 | if (k_) r_ -= BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS)))); \ | |||
| 192 | (r) = r_; \ | |||
| 193 | (kout) = k_; \ | |||
| 194 | } | |||
| 195 | ||||
| 196 | #define MinusStep(kp1out, r, a, b, kp1in){ BIntD r_ = (BIntD)(a)+(BIntD)((((((unsigned long) 1) << ((8 * sizeof(BIntS)))) - 1) - (b)))+(BIntD)(kp1in); BIntS k_ = (r_ >= (BIntD) (((unsigned long) 1) << ((8 * sizeof (BIntS))))); if (k_) r_ -= (((unsigned long) 1) << ((8 * sizeof(BIntS)))); (r) = r_; (kp1out) = k_; } \ | |||
| 197 | PlusStep(kp1out, r, a, (BINT_RADIX_MINUS_1 - (b)), kp1in){ BIntD r_ = (BIntD)(a)+(BIntD)((((((unsigned long) 1) << ((8 * sizeof(BIntS)))) - 1) - (b)))+(BIntD)(kp1in); BIntS k_ = (r_ >= (BIntD) (((unsigned long) 1) << ((8 * sizeof (BIntS))))); if (k_) r_ -= (((unsigned long) 1) << ((8 * sizeof(BIntS)))); (r) = r_; (kp1out) = k_; } | |||
| 198 | ||||
| 199 | #define TimesStep(kout, r, a, b, c, kin){ BIntD t_ = (BIntD)(a)*(BIntD)(b)+(BIntD)(c)+(BIntD)(kin); ( r) = t_ % (((unsigned long) 1) << ((8 * sizeof(BIntS))) ); (kout) = t_ / (((unsigned long) 1) << ((8 * sizeof(BIntS )))); } { \ | |||
| 200 | BIntD t_ = (BIntD)(a)*(BIntD)(b)+(BIntD)(c)+(BIntD)(kin); \ | |||
| 201 | (r) = t_ % BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS)))); \ | |||
| 202 | (kout) = t_ / BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS)))); \ | |||
| 203 | } | |||
| 204 | ||||
| 205 | ||||
| 206 | ||||
| 207 | /***************************************************************************** | |||
| 208 | * | |||
| 209 | * :: Related machine integer operations | |||
| 210 | * | |||
| 211 | *****************************************************************************/ | |||
| 212 | ||||
| 213 | /* | |||
| 214 | * The length of n, in bits. I.e. cieling(lg(abs(n))). | |||
| 215 | * Define the bit length of zero to be one bit. | |||
| 216 | */ | |||
| 217 | Length | |||
| 218 | uintLength(unsigned long u) | |||
| 219 | { | |||
| 220 | register Length i; | |||
| 221 | register UIInt p; | |||
| 222 | ||||
| 223 | /* Eventually the unsigned quantity p is bigger than u = abs(n). */ | |||
| 224 | /* At each stage of the loop, any u < p can fit in i bits. */ | |||
| 225 | for (i = 1, p = 2; ; i += 1, p <<= 1) | |||
| 226 | if (!p || u < p) break; | |||
| 227 | return i; | |||
| 228 | } | |||
| 229 | ||||
| 230 | Length | |||
| 231 | intLength(long n) | |||
| 232 | { | |||
| 233 | return uintLength((n < 0) ? -n : n); | |||
| 234 | } | |||
| 235 | ||||
| 236 | ||||
| 237 | Bool | |||
| 238 | uintBit(unsigned long si, Length ix) | |||
| 239 | { | |||
| 240 | return (ix < bitsizeof(UIInt)(8 * sizeof(UIInt))) && ( ((ULong)si) & (1L<<ix)) != 0; | |||
| 241 | } | |||
| 242 | ||||
| 243 | Bool | |||
| 244 | intBit(long si, Length ix) | |||
| 245 | { | |||
| 246 | return uintBit((si < 0) ? -si : si, ix); | |||
| 247 | } | |||
| 248 | ||||
| 249 | /**************************************************************************** | |||
| 250 | * | |||
| 251 | * :: Input/output | |||
| 252 | * | |||
| 253 | ****************************************************************************/ | |||
| 254 | ||||
| 255 | int | |||
| 256 | bintPrint(FILE *fout, BInt b) | |||
| 257 | { | |||
| 258 | int cc; | |||
| 259 | String s; | |||
| 260 | ||||
| 261 | if (IsImmed(b)((long)(b) & 1)) return fprintf(fout, "%ld", BIntToInt(b)((IInt) ((((long) (b))) >> 1))); | |||
| 262 | ||||
| 263 | s = bintToString(b); | |||
| 264 | cc = fprintf(fout, "%s", s); | |||
| 265 | localStrFree(s); | |||
| 266 | ||||
| 267 | return cc; | |||
| 268 | } | |||
| 269 | ||||
| 270 | void | |||
| 271 | bintPrintDb(BInt b) | |||
| 272 | { | |||
| 273 | bintPrint(dbOut, b); | |||
| 274 | fprintf(dbOut, "\n"); | |||
| 275 | } | |||
| 276 | ||||
| 277 | int | |||
| 278 | bintPrint16(FILE *fout, BInt b) | |||
| 279 | { | |||
| 280 | int i, cc; | |||
| 281 | ||||
| 282 | if (IsImmed(b)((long)(b) & 1)) return fprintf(fout, "0x%lx", BIntToInt(b)((IInt) ((((long) (b))) >> 1))); | |||
| 283 | ||||
| 284 | cc = fprintf(fout, IsNeg(b)((b)->isNeg) ? "-" : "+"); | |||
| 285 | cc += fprintf(fout, "0x"); | |||
| 286 | ||||
| 287 | for (i = Placec(b)((b)->placec) - 1; i >= 0; i--) | |||
| 288 | cc += fprintf(fout, "%0*x.", | |||
| 289 | (int) QUO_ROUND_UP(BINT_LG_RADIX,4)((((8 * sizeof(BIntS)))) % (4) ? (((8 * sizeof(BIntS))))/(4) + 1 : (((8 * sizeof(BIntS))))/(4)), | |||
| 290 | Placev(b)((b)->placev)[i]); | |||
| 291 | ||||
| 292 | return cc; | |||
| 293 | } | |||
| 294 | ||||
| 295 | /* | |||
| 296 | * +0b[3/4]10,10100,00110. | |||
| 297 | * | |||
| 298 | * [3/4] -- 3 of 4 allocated places are used | |||
| 299 | */ | |||
| 300 | ||||
| 301 | int | |||
| 302 | bintPrint2(FILE *fout, BInt b) | |||
| 303 | { | |||
| 304 | int i, n, cc = 0; | |||
| 305 | ||||
| 306 | if (bintIsNeg(b)) cc += fprintf(fout, "-"); | |||
| 307 | ||||
| 308 | cc += fprintf(fout, "0b"); | |||
| 309 | ||||
| 310 | if (IsImmed(b)((long)(b) & 1)) | |||
| 311 | cc += fprintf(fout, "[0/0]"); | |||
| 312 | else | |||
| 313 | cc += fprintf(fout, "[%d/%d]", (int) Placec(b)((b)->placec), (int) Placea(b)((b)->placea)); | |||
| 314 | ||||
| 315 | n = bintLength(b); | |||
| 316 | ||||
| 317 | for (i = n-1; i >= 0; i--) | |||
| 318 | cc += fprintf(fout, bintBit(b, i) ? "1" : "0"); | |||
| 319 | ||||
| 320 | return cc; | |||
| 321 | } | |||
| 322 | ||||
| 323 | /* | |||
| 324 | * Overestimate the size of a base 10 string representation for b, | |||
| 325 | * by dividing by 3 (not log(10)/log(2) > 3.32). | |||
| 326 | * +3 for signs, \0, etc. | |||
| 327 | * +dio for temp leading zeros. | |||
| 328 | */ | |||
| 329 | ||||
| 330 | int | |||
| 331 | bintStringSize(BInt b) | |||
| 332 | { | |||
| 333 | IInt dio; | |||
| 334 | ULong rio; | |||
| 335 | ||||
| 336 | if (IsImmed(b)((long)(b) & 1)) return INT_LG_IMMED((8 * sizeof(IInt))-2); | |||
| 337 | ||||
| 338 | /* | |||
| 339 | * Determine power of output radix for divisions. | |||
| 340 | * This is the largest power of 10 < BINT_RADIX. | |||
| 341 | */ | |||
| 342 | for (rio = 10, dio = 1; 10*rio <= BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS)))); rio *= 10, dio++) | |||
| 343 | ; | |||
| 344 | return bintLength(b)/3+3+dio; | |||
| 345 | } | |||
| 346 | ||||
| 347 | ||||
| 348 | /* | |||
| 349 | * Compute a base 10 string representation of b. | |||
| 350 | * The string representation includes a terminating \0 character. | |||
| 351 | */ | |||
| 352 | String | |||
| 353 | bintIntoString(String s, BInt b) | |||
| 354 | { | |||
| 355 | Bool isNeg; | |||
| 356 | IInt digEst, i, j, dio; | |||
| 357 | ULong rio; | |||
| 358 | BIntS r; | |||
| 359 | ||||
| 360 | if (IsImmed(b)((long)(b) & 1)) { | |||
| 361 | sprintf(s, "%ld", BIntToInt(b)((IInt) ((((long) (b))) >> 1))); | |||
| 362 | return s; | |||
| 363 | } | |||
| 364 | ||||
| 365 | /* | |||
| 366 | * Determine power of output radix for divisions. | |||
| 367 | * This is the largest power of 10 < BINT_RADIX. | |||
| 368 | */ | |||
| 369 | for (rio = 10, dio = 1; 10*rio <= BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS)))); rio *= 10, dio++) | |||
| 370 | ; | |||
| 371 | ||||
| 372 | /* | |||
| 373 | * Make copy for in-place divisions. | |||
| 374 | */ | |||
| 375 | b = bintCopy(b); | |||
| 376 | isNeg = IsNeg(b)((b)->isNeg); | |||
| 377 | ||||
| 378 | digEst = bintStringSize(b); | |||
| 379 | i = digEst; | |||
| 380 | s[--i] = 0; | |||
| 381 | ||||
| 382 | while (Placec(b)((b)->placec) > 0) { | |||
| 383 | iintDivideS(b, &r, b, (BIntS) rio); | |||
| 384 | for (j = 0; j < dio; j++) { | |||
| 385 | s[--i] = '0' + r % 10; | |||
| 386 | r /= 10; | |||
| 387 | } | |||
| 388 | } | |||
| 389 | ||||
| 390 | while (s[i] == '0') i++; /* Cd have leading zeros. */ | |||
| 391 | if (s[i] == 0) s[--i] = '0'; /* Ensure at least one digit. */ | |||
| 392 | if (isNeg) s[--i] = '-'; /* Put on sign. */ | |||
| 393 | ||||
| 394 | /* | |||
| 395 | * Move text to the beginning of the string. | |||
| 396 | */ | |||
| 397 | assert(i >= 0)do { if (!(i >= 0)) _do_assert(("i >= 0"),"bigint.c",397 ); } while (0); | |||
| 398 | if (i > 0) for (j = 0; i < digEst; i++, j++) s[j] = s[i]; | |||
| 399 | ||||
| 400 | bintFree(b); | |||
| 401 | ||||
| 402 | return s; | |||
| 403 | } | |||
| 404 | ||||
| 405 | ||||
| 406 | /* | |||
| 407 | * Compute a base 10 string representation of b. | |||
| 408 | * The string representation includes a terminating \0 character. | |||
| 409 | */ | |||
| 410 | String | |||
| 411 | bintToString(BInt b) | |||
| 412 | { | |||
| 413 | IInt digEst = bintStringSize(b); | |||
| 414 | String s = localStrAlloc(digEst); | |||
| 415 | ||||
| 416 | bintIntoString(s, b); | |||
| 417 | ||||
| 418 | return s; | |||
| 419 | } | |||
| 420 | ||||
| 421 | /* | |||
| 422 | * Convert from the textual representation of an Aldor number into a big | |||
| 423 | * integer. This function may be invoked (indirectly) by convert()$Machine | |||
| 424 | * and cannot assume base 10. | |||
| 425 | * | |||
| 426 | * General Aldor integer format is RRrWW | |||
| 427 | * | |||
| 428 | * RR is the radix part (2-36) | |||
| 429 | * 'r' is the radix character. | |||
| 430 | * WW is the whole part ([0-9A-Z]+). | |||
| 431 | */ | |||
| 432 | BInt | |||
| 433 | bintFrString(String s) | |||
| 434 | { | |||
| 435 | return bintRadixScanFrString(s, NULL((void*)0)); | |||
| 436 | } | |||
| 437 | ||||
| 438 | #define fiRadixChar('r') ('r') | |||
| 439 | #define fiPlusChar('+') ('+') | |||
| 440 | #define fiMinusChar('-') ('-') | |||
| 441 | ||||
| 442 | /* Scan a big integer with possible radix specification */ | |||
| 443 | BInt | |||
| 444 | bintRadixScanFrString(String num, String *pEnd) | |||
| 445 | { | |||
| 446 | Bool isNeg = false((int) 0); | |||
| 447 | String rpos = (String)NULL((void*)0); | |||
| 448 | String end; | |||
| 449 | long radix = 10; | |||
| 450 | BInt retval; | |||
| 451 | Length rlen, ndigs, bpd; | |||
| 452 | IInt dim, dio; | |||
| 453 | UIInt ires; | |||
| 454 | IInt l, l0, n; | |||
| 455 | ULong rim, rio, nbits; | |||
| 456 | ULong maxi; | |||
| 457 | ||||
| 458 | ||||
| 459 | /* Skip over leading whitespace */ | |||
| 460 | while (isspace(*num)((*__ctype_b_loc ())[(int) ((*num))] & (unsigned short int ) _ISspace)) | |||
| 461 | num++; | |||
| 462 | ||||
| 463 | ||||
| 464 | /* Deal with the sign (if any) */ | |||
| 465 | if ((*num == fiPlusChar('+')) || (*num == fiMinusChar('-'))) | |||
| 466 | { | |||
| 467 | isNeg = (*num == fiMinusChar('-')) ? true1 : false((int) 0); | |||
| 468 | num++; | |||
| 469 | } | |||
| 470 | ||||
| 471 | ||||
| 472 | /* | |||
| 473 | * Locate the end of the string: start by skipping over | |||
| 474 | * the leading part (which must be in base 10). This | |||
| 475 | * might be the radix or it might be the whole part. | |||
| 476 | */ | |||
| 477 | for (end = num; isdigit(*end)((*__ctype_b_loc ())[(int) ((*end))] & (unsigned short int ) _ISdigit); end++); | |||
| 478 | ||||
| 479 | ||||
| 480 | /* Is there a radix marker? */ | |||
| 481 | if (*end == fiRadixChar('r')) | |||
| 482 | { | |||
| 483 | /* Yes - note its position */ | |||
| 484 | rpos = end; | |||
| 485 | end++; | |||
| 486 | ||||
| 487 | ||||
| 488 | /* Skip past the whole part */ | |||
| 489 | for (;isdigit(*end)((*__ctype_b_loc ())[(int) ((*end))] & (unsigned short int ) _ISdigit) || isupper(*end)((*__ctype_b_loc ())[(int) ((*end))] & (unsigned short int ) _ISupper);end++); | |||
| 490 | } | |||
| 491 | else | |||
| 492 | { | |||
| 493 | /* NOOOOOOOOOOOOOOO!!!!!!!!!!!!!! */ | |||
| 494 | /* Skip past the decimal whole part */ | |||
| 495 | for (;isdigit(*end)((*__ctype_b_loc ())[(int) ((*end))] & (unsigned short int ) _ISdigit);end++); | |||
| 496 | } | |||
| 497 | ||||
| 498 | ||||
| 499 | /* Did the caller want to know where the number ends? */ | |||
| 500 | if (pEnd) *pEnd = end; | |||
| 501 | ||||
| 502 | ||||
| 503 | /* There must be something before the radix marker */ | |||
| 504 | if (rpos == num) | |||
| 505 | return IntToBInt((long) 0)((BInt) ((Pointer)(((((long)((long) 0)) << 1) | 1)))); /* Bad number */ | |||
| 506 | ||||
| 507 | ||||
| 508 | /* Extract the radix (if any) */ | |||
| 509 | if (rpos) | |||
| 510 | { | |||
| 511 | /* Extract the radix as a (small) decimal integer */ | |||
| 512 | rlen = rpos - num; | |||
| 513 | radix = ulongSmallIntFrString(num, rlen, 10); | |||
| 514 | ||||
| 515 | ||||
| 516 | /* Valid radix: 2-36 inclusive */ | |||
| 517 | if (errno(*__errno_location ()) || (radix < 2) || (radix > 36)) | |||
| 518 | return IntToBInt((long) 0)((BInt) ((Pointer)(((((long)((long) 0)) << 1) | 1)))); | |||
| 519 | ||||
| 520 | ||||
| 521 | /* Move to the start of the whole part */ | |||
| 522 | num = rpos + 1; | |||
| 523 | } | |||
| 524 | ||||
| 525 | ||||
| 526 | /* | |||
| 527 | * Determine the largest power `rim' of the input radix that | |||
| 528 | * can be used for immediate representation. We want `rim' such | |||
| 529 | * that (INT_MAX_IMMED/radix < rim <= INT_MAX_IMMED). We can | |||
| 530 | * not check whether (radix*rim <= INT_MAX_IMMED) because the | |||
| 531 | * LHS may overflow for large `radix'. Instead we `rim' such | |||
| 532 | * that (INT_MAX_IMMED/(radix^2) < rim <= INT_MAX_IMMED/radix). | |||
| 533 | * This means that for all radix, (radix*rim <= INT_MAX_IMMED). | |||
| 534 | */ | |||
| 535 | maxi = INT_MAX_IMMED(- (long) ((((IInt) 3) << ((8 * sizeof(IInt))-2)) + 1)) / radix; | |||
| 536 | for ( | |||
| 537 | rim = radix, dim = 1; | |||
| 538 | radix*rim <= maxi; | |||
| 539 | rim *= radix, dim++ | |||
| 540 | ); | |||
| 541 | ||||
| 542 | ||||
| 543 | /* Now satisfy (INT_MAX_IMMED/radix < rim <= INT_MAX_IMMED) */ | |||
| 544 | rim *= radix, dim++; | |||
| 545 | ||||
| 546 | ||||
| 547 | /* | |||
| 548 | * Determine the largest power `rio' of input radix for | |||
| 549 | * multiplications s.t. (BINT_RADIX/radix <= rio < BINT_RADIX). | |||
| 550 | */ | |||
| 551 | maxi = BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS)))) / radix; | |||
| 552 | for ( | |||
| 553 | rio = radix, dio = 1; | |||
| 554 | radix*rio < maxi; | |||
| 555 | rio *= radix, dio++ | |||
| 556 | ); | |||
| 557 | ||||
| 558 | ||||
| 559 | /* Now satisfy (BINT_RADIX/radix <= rio < BINT_RADIX) */ | |||
| 560 | rio *= radix, dio++; | |||
| 561 | ||||
| 562 | ||||
| 563 | /* | |||
| 564 | * Convert the whole part using the specified base. First we | |||
| 565 | * need to estimate the number of bits needed for the result. | |||
| 566 | */ | |||
| 567 | bpd = (ULong)(log((double)radix)/log(2.0)) + 1; | |||
| 568 | ndigs = (Length)(end - num); | |||
| 569 | nbits = ndigs*bpd; | |||
| 570 | ||||
| 571 | ||||
| 572 | /* If safe, compute as a C integer. */ | |||
| 573 | if (nbits <= INT_LG_IMMED((8 * sizeof(IInt))-2)) | |||
| 574 | { | |||
| 575 | /* Scan the small immediate integer */ | |||
| 576 | ires = ulongSmallIntFrString(num, ndigs, radix); | |||
| 577 | ||||
| 578 | ||||
| 579 | /* | |||
| 580 | * Return the immediate result. If the number | |||
| 581 | * contained invalid characters then the result | |||
| 582 | * will be invalid. Check errno if required. | |||
| 583 | */ | |||
| 584 | if (isNeg) ires = -ires; | |||
| 585 | return IntToBInt(ires)((BInt) ((Pointer)(((((long)(ires)) << 1) | 1)))); | |||
| 586 | } | |||
| 587 | ||||
| 588 | ||||
| 589 | /* Allocate enough store for the result */ | |||
| 590 | retval = bintAlloc(nbits); | |||
| 591 | ||||
| 592 | ||||
| 593 | /* | |||
| 594 | * Convert radix by interpreting string as a poly in radix | |||
| 595 | * `rio' and evaluating using Horner's rule. This means that | |||
| 596 | * we convert the number in chunks that will fit into an | |||
| 597 | * immediate integer. Start with a chunk big enough to ensure | |||
| 598 | * that the remaining chunks are all `dio' digits long. | |||
| 599 | */ | |||
| 600 | l0 = ndigs % dio; | |||
| 601 | for (n = 0, l = l0; l > 0; l--) | |||
| 602 | { | |||
| 603 | IInt dig; | |||
| 604 | ||||
| 605 | dig = (*num <= '9') ? (*num - '0') : (*num - 'A') + 10; | |||
| 606 | n = radix*n + dig; | |||
| 607 | num++; | |||
| 608 | } | |||
| 609 | retval = xintCopyInI(retval, n); | |||
| 610 | ||||
| 611 | ||||
| 612 | /* Now deal with the other chunks */ | |||
| 613 | for (ndigs -= l0; ndigs > 0; ndigs -= dio) | |||
| 614 | { | |||
| 615 | for (n = 0, l = dio; l > 0; l--) | |||
| 616 | { | |||
| 617 | IInt dig; | |||
| 618 | ||||
| 619 | dig = (*num <= '9') ? (*num - '0') : (*num - 'A') + 10; | |||
| 620 | n = radix*n + dig; | |||
| 621 | num++; | |||
| 622 | } | |||
| 623 | iintTimesPlusS(retval, retval, (BIntS) rio, (BIntS) n); | |||
| 624 | } | |||
| 625 | ||||
| 626 | ||||
| 627 | /* Deal with any negation */ | |||
| 628 | IsNeg(retval)((retval)->isNeg) = isNeg; | |||
| 629 | ||||
| 630 | ||||
| 631 | /* Try to make it an immediate integer is possible */ | |||
| 632 | return xintImmedIfCan(retval); | |||
| 633 | } | |||
| 634 | ||||
| 635 | ||||
| 636 | /* Convert a base 10 string representation to a big integer. */ | |||
| 637 | BInt | |||
| 638 | bintScanFrString(String s, String *end) | |||
| 639 | { | |||
| 640 | String t; | |||
| 641 | BInt b; | |||
| 642 | Bool isNeg = false((int) 0); | |||
| 643 | Length ndig; | |||
| 644 | IInt dim, dio; | |||
| 645 | ULong rim, rio; | |||
| 646 | IInt l, l0, n; | |||
| 647 | ||||
| 648 | /* | |||
| 649 | * Determine rim: power of input radix for immediate representation. | |||
| 650 | * This is the largest power of 10 <= INT_MAX_IMMED. | |||
| 651 | * Determine rio: power of input radix for multiplications. | |||
| 652 | * This is the largest power of 10 < BINT_RADIX. | |||
| 653 | */ | |||
| 654 | for (rim = 10, dim = 1; 10*rim <= INT_MAX_IMMED(- (long) ((((IInt) 3) << ((8 * sizeof(IInt))-2)) + 1)); rim *= 10, dim++) | |||
| 655 | ; | |||
| 656 | /* | |||
| 657 | * BUG -------------------------+ | |||
| 658 | * V | |||
| 659 | */ | |||
| 660 | for (rio = 10, dio = 1; 10*rio <= BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS)))); rio *= 10, dio++) | |||
| 661 | ; | |||
| 662 | ||||
| 663 | /* | |||
| 664 | * Find beginning and end of number. | |||
| 665 | * Don't use strlen, since there may be trailing text. | |||
| 666 | */ | |||
| 667 | while (isspace(*s)((*__ctype_b_loc ())[(int) ((*s))] & (unsigned short int) _ISspace)) | |||
| 668 | s++; | |||
| 669 | if (*s == '-') { | |||
| 670 | isNeg = true1; | |||
| 671 | s++; | |||
| 672 | } | |||
| 673 | while (*s == '0') | |||
| 674 | s++; | |||
| 675 | for (t = s; isdigit(*t)((*__ctype_b_loc ())[(int) ((*t))] & (unsigned short int) _ISdigit); t++) | |||
| 676 | ; | |||
| 677 | ndig = t-s; | |||
| 678 | ||||
| 679 | if (end) *end = t; | |||
| 680 | /* | |||
| 681 | * If safe, compute as a C integer. | |||
| 682 | */ | |||
| 683 | if (ndig <= dim) { | |||
| 684 | for (n = 0; s != t; s++) n = 10*n + *s - '0'; | |||
| 685 | if (isNeg) n = -n; | |||
| 686 | return IntToBInt(n)((BInt) ((Pointer)(((((long)(n)) << 1) | 1)))); | |||
| 687 | } | |||
| 688 | ||||
| 689 | /* | |||
| 690 | * Over-estimate number of bits by multiplying by 4, rather than | |||
| 691 | * log(10)/log(2) < 3.322. | |||
| 692 | */ | |||
| 693 | b = bintAlloc(4*ndig); | |||
| 694 | ||||
| 695 | /* | |||
| 696 | * Convert radix by interpreting string as a poly in radix "rio" | |||
| 697 | * and evaluating using Horner's rule. | |||
| 698 | */ | |||
| 699 | l0 = ndig % dio; | |||
| 700 | for (n = 0, l = l0; l > 0; l--) n = 10*n + *s++ - '0'; | |||
| 701 | b = xintCopyInI(b, n); | |||
| 702 | ||||
| 703 | for (ndig -= l0; ndig > 0; ndig -= dio) { | |||
| 704 | for (n = 0, l = dio; l > 0; l--) n = 10*n + *s++ - '0'; | |||
| 705 | iintTimesPlusS(b, b, (BIntS) rio, (BIntS) n); | |||
| 706 | } | |||
| 707 | ||||
| 708 | IsNeg(b)((b)->isNeg) = isNeg; | |||
| 709 | ||||
| 710 | b = xintImmedIfCan(b); | |||
| 711 | ||||
| 712 | return b; | |||
| 713 | } | |||
| 714 | ||||
| 715 | ||||
| 716 | /**************************************************************************** | |||
| 717 | * | |||
| 718 | * :: Basic Allocation | |||
| 719 | * | |||
| 720 | ****************************************************************************/ | |||
| 721 | ||||
| 722 | BInt | |||
| 723 | bintAllocPlaces(Length placea) | |||
| 724 | { | |||
| 725 | BInt b; | |||
| 726 | b = (BInt) stoAlloc(OB_BInt2, fullsizeof(*b, placea, Placev(b)[0])(sizeof(*b) + (placea) * sizeof(((b)->placev)[0]) - 10 * sizeof (((b)->placev)[0]))); | |||
| 727 | Placea(b)((b)->placea) = placea; | |||
| 728 | Placec(b)((b)->placec) = placea; | |||
| 729 | IsNeg(b)((b)->isNeg) = false((int) 0); | |||
| 730 | ||||
| 731 | return b; | |||
| 732 | } | |||
| 733 | ||||
| 734 | BInt | |||
| 735 | bintAlloc(Length bitc) | |||
| 736 | { | |||
| 737 | return bintAllocPlaces(QUO_ROUND_UP(bitc, BINT_LG_RADIX)((bitc) % (((8 * sizeof(BIntS)))) ? (bitc)/(((8 * sizeof(BIntS )))) + 1 : (bitc)/(((8 * sizeof(BIntS)))))); | |||
| 738 | } | |||
| 739 | ||||
| 740 | void | |||
| 741 | bintFree(BInt b) | |||
| 742 | { | |||
| 743 | if (IsImmed(b)((long)(b) & 1)) return; | |||
| 744 | ||||
| 745 | stoFree((Pointer) b); | |||
| 746 | } | |||
| 747 | ||||
| 748 | BInt | |||
| 749 | bintNew(long n) | |||
| 750 | { | |||
| 751 | if (INT_IS_IMMED(n)(((((IInt) 3) << ((8 * sizeof(IInt))-2)) + 1)<= (long )(n) && (long)(n)<= (- (long) ((((IInt) 3) << ((8 * sizeof(IInt))-2)) + 1)))) return IntToBInt(n)((BInt) ((Pointer)(((((long)(n)) << 1) | 1)))); | |||
| 752 | ||||
| 753 | return xintStoreI(n); | |||
| 754 | } | |||
| 755 | ||||
| 756 | BInt | |||
| 757 | bintCopy(BInt bo) | |||
| 758 | { | |||
| 759 | BInt bn; | |||
| 760 | Length i, c; | |||
| 761 | ||||
| 762 | if (IsImmed(bo)((long)(bo) & 1)) return bo; | |||
| 763 | ||||
| 764 | c = Placec(bo)((bo)->placec); | |||
| 765 | bn = bintAllocPlaces(c); | |||
| 766 | ||||
| 767 | for (i = 0; i < c; i++) Placev(bn)((bn)->placev)[i] = Placev(bo)((bo)->placev)[i]; | |||
| 768 | IsNeg(bn)((bn)->isNeg) = IsNeg(bo)((bo)->isNeg); | |||
| 769 | ||||
| 770 | return bn; | |||
| 771 | } | |||
| 772 | ||||
| 773 | BInt | |||
| 774 | bintFrPlacev(Bool isNeg, Length placec, BIntS *data) | |||
| 775 | { | |||
| 776 | BInt bint; | |||
| 777 | int i; | |||
| 778 | ||||
| 779 | bint = bintAllocPlaces(placec); | |||
| 780 | IsNeg(bint)((bint)->isNeg) = isNeg; | |||
| 781 | ||||
| 782 | for (i = placec - 1; i >= 0 && data[i] == 0; i--) ; | |||
| 783 | ||||
| 784 | Placec(bint)((bint)->placec) = i+1; | |||
| 785 | ||||
| 786 | for (; i >= 0; i--) | |||
| 787 | Placev(bint)((bint)->placev)[i] = data[i]; | |||
| 788 | return xintImmedIfCan(bint); | |||
| 789 | } | |||
| 790 | ||||
| 791 | #if (U16sPerUNotAsLong2 == 1) | |||
| 792 | BInt | |||
| 793 | bintFrPlacevS(Bool isNeg, Length placec, U16 *data) | |||
| 794 | { | |||
| 795 | return bintFrPlacev(isNeg, placec, (BIntS*) data); | |||
| 796 | } | |||
| 797 | ||||
| 798 | void | |||
| 799 | bintToPlacevS(BInt b, int *psize, U16 **pdata) | |||
| 800 | { | |||
| 801 | *psize = b->placec; | |||
| 802 | *pdata = b->placev; | |||
| 803 | } | |||
| 804 | ||||
| 805 | void | |||
| 806 | bintReleasePlacevS(U16 *pdata) | |||
| 807 | { | |||
| 808 | } | |||
| 809 | #endif | |||
| 810 | ||||
| 811 | #if (U16sPerUNotAsLong2 == 2) | |||
| 812 | BInt | |||
| 813 | bintFrPlacevS(Bool isNeg, Length placec, U16 *data) | |||
| 814 | { | |||
| 815 | BInt bint; | |||
| 816 | BIntS *bint_data; | |||
| 817 | int newc, i; | |||
| 818 | ||||
| 819 | if (placec & 1) | |||
| 820 | bint_data = (BIntS*) data; | |||
| 821 | else | |||
| 822 | bint_data = (BIntS*) stoAlloc(OB_Other0, sizeof(BIntS) * (placec + 1)); | |||
| 823 | newc = (placec+1)/2; | |||
| 824 | for (i = 0; i < newc-1; i++) | |||
| 825 | bint_data[i] = data[2*i] + (data[2*i+1] << bitsizeof(U16)(8 * sizeof(U16))); | |||
| 826 | bint_data[i] = (placec & 1) ? | |||
| 827 | data[2*i] : | |||
| 828 | data[2*i] + (data[2*i+1] << bitsizeof(U16)(8 * sizeof(U16))); | |||
| 829 | ||||
| 830 | bint = bintFrPlacev(isNeg, newc, bint_data); | |||
| 831 | ||||
| 832 | if (!(placec & 1)) | |||
| 833 | stoFree(bint_data); | |||
| 834 | return bint; | |||
| 835 | } | |||
| 836 | ||||
| 837 | void | |||
| 838 | bintToPlacevS(BInt b, int *psize, U16 **pdata) | |||
| 839 | { | |||
| 840 | BInt oldb; | |||
| 841 | U16 *data; | |||
| 842 | int placec; | |||
| 843 | int i; | |||
| 844 | ||||
| 845 | oldb = b; | |||
| 846 | b = xintStore(b); | |||
| 847 | placec = b->placec; | |||
| 848 | ||||
| 849 | data = (U16*) stoAlloc(OB_Other0, 2*placec*sizeof(U16)); | |||
| 850 | ||||
| 851 | for (i=0; i < placec; i++) { | |||
| 852 | data[2*i] = b->placev[i] & 0x0000FFFF; | |||
| 853 | data[2*i+1] = (b->placev[i] & 0xFFFF0000) >> 16; | |||
| 854 | } | |||
| 855 | ||||
| 856 | if (data[2*placec - 1] == 0) | |||
| 857 | *psize = 2*placec - 1; | |||
| 858 | else | |||
| 859 | *psize = 2*placec; | |||
| 860 | *pdata = data; | |||
| 861 | ||||
| 862 | if (oldb != b) | |||
| 863 | bintFree(b); | |||
| 864 | } | |||
| 865 | ||||
| 866 | void | |||
| 867 | bintReleasePlacevS(U16 *data) | |||
| 868 | { | |||
| 869 | stoFree(data); | |||
| 870 | } | |||
| 871 | #endif | |||
| 872 | ||||
| 873 | /**************************************************************************** | |||
| 874 | * | |||
| 875 | * :: Small integers | |||
| 876 | * | |||
| 877 | ****************************************************************************/ | |||
| 878 | ||||
| 879 | Bool | |||
| 880 | bintIsSmall(BInt b) | |||
| 881 | { | |||
| 882 | return IsImmed(b)((long)(b) & 1); | |||
| 883 | } | |||
| 884 | ||||
| 885 | long | |||
| 886 | bintSmall(BInt b) | |||
| 887 | { | |||
| 888 | return BIntToInt(b)((IInt) ((((long) (b))) >> 1)); | |||
| 889 | } | |||
| 890 | ||||
| 891 | ||||
| 892 | /**************************************************************************** | |||
| 893 | * | |||
| 894 | * :: General arithmetic | |||
| 895 | * | |||
| 896 | ****************************************************************************/ | |||
| 897 | localstatic BInt bintModi (BInt, unsigned long); | |||
| 898 | localstatic ULong bintToULong (BInt); | |||
| 899 | ||||
| 900 | /* | |||
| 901 | * Special values | |||
| 902 | */ | |||
| 903 | BInt bint0 = BIntZero((BInt) ((((long)(0)) << 1) | 1)); | |||
| 904 | BInt bint1 = BIntOne((BInt) ((((long)(1)) << 1) | 1)); | |||
| 905 | ||||
| 906 | /* | |||
| 907 | * b < 0 ? | |||
| 908 | */ | |||
| 909 | Bool | |||
| 910 | bintIsNeg(BInt b) | |||
| 911 | { | |||
| 912 | if (IsImmed(b)((long)(b) & 1)) return BIntToInt(b)((IInt) ((((long) (b))) >> 1)) < 0; | |||
| 913 | ||||
| 914 | return IsNeg(b)((b)->isNeg); | |||
| 915 | } | |||
| 916 | ||||
| 917 | /* | |||
| 918 | * b == 0 ? | |||
| 919 | */ | |||
| 920 | Bool | |||
| 921 | bintIsZero(BInt b) | |||
| 922 | { | |||
| 923 | return IsImmed(b)((long)(b) & 1) && BIntToInt(b)((IInt) ((((long) (b))) >> 1)) == 0; | |||
| 924 | } | |||
| 925 | ||||
| 926 | /* | |||
| 927 | * b > 0 ? | |||
| 928 | */ | |||
| 929 | Bool | |||
| 930 | bintIsPos(BInt b) | |||
| 931 | { | |||
| 932 | if (IsImmed(b)((long)(b) & 1)) return BIntToInt(b)((IInt) ((((long) (b))) >> 1)) > 0; | |||
| 933 | ||||
| 934 | return Placec(b)((b)->placec) > 0 && !IsNeg(b)((b)->isNeg); | |||
| 935 | } | |||
| 936 | ||||
| 937 | /* | |||
| 938 | * a == b ? | |||
| 939 | */ | |||
| 940 | Bool | |||
| 941 | bintEQ(BInt a, BInt b) | |||
| 942 | { | |||
| 943 | Bool aImmed, bImmed; | |||
| 944 | IInt i, c; | |||
| 945 | ||||
| 946 | if (Beq(a,b)((a) == (b))) return true1; | |||
| 947 | ||||
| 948 | aImmed = IsImmed(a)((long)(a) & 1); | |||
| 949 | bImmed = IsImmed(b)((long)(b) & 1); | |||
| 950 | ||||
| 951 | if (aImmed && bImmed) return BIntToInt(a)((IInt) ((((long) (a))) >> 1)) == BIntToInt(b)((IInt) ((((long) (b))) >> 1)); | |||
| 952 | if (aImmed != bImmed) return false((int) 0); | |||
| 953 | if (IsNeg(a)((a)->isNeg) != IsNeg(b)((b)->isNeg)) return false((int) 0); | |||
| 954 | if (Placec(a)((a)->placec) != Placec(b)((b)->placec)) return false((int) 0); | |||
| 955 | ||||
| 956 | c = Placec(a)((a)->placec); | |||
| 957 | ||||
| 958 | for (i = 0; i < c; i++) | |||
| 959 | if (Placev(a)((a)->placev)[i] != Placev(b)((b)->placev)[i]) return false((int) 0); | |||
| 960 | return true1; | |||
| 961 | } | |||
| 962 | ||||
| 963 | /* | |||
| 964 | * a < b ? | |||
| 965 | */ | |||
| 966 | Bool | |||
| 967 | bintLT(BInt a, BInt b) | |||
| 968 | { | |||
| 969 | Bool aImmed, bImmed; | |||
| 970 | IInt i, c; | |||
| 971 | ||||
| 972 | if (Beq(a,b)((a) == (b))) return false((int) 0); | |||
| 973 | ||||
| 974 | aImmed = IsImmed(a)((long)(a) & 1); | |||
| 975 | bImmed = IsImmed(b)((long)(b) & 1); | |||
| 976 | ||||
| 977 | if (aImmed && bImmed) return BIntToInt(a)((IInt) ((((long) (a))) >> 1)) < BIntToInt(b)((IInt) ((((long) (b))) >> 1)); | |||
| 978 | if (aImmed) return !IsNeg(b)((b)->isNeg); | |||
| 979 | if (bImmed) return IsNeg(a)((a)->isNeg); | |||
| 980 | if (IsNeg(a)((a)->isNeg) != IsNeg(b)((b)->isNeg)) return IsNeg(a)((a)->isNeg) && !IsNeg(b)((b)->isNeg); | |||
| 981 | ||||
| 982 | if (IsNeg(a)((a)->isNeg)) { | |||
| 983 | if (Placec(a)((a)->placec)!= Placec(b)((b)->placec)) return Placec(a)((a)->placec) > Placec(b)((b)->placec); | |||
| 984 | c = Placec(a)((a)->placec); | |||
| 985 | for (i = c-1; i >= 0; i--) { | |||
| 986 | if (Placev(a)((a)->placev)[i] == Placev(b)((b)->placev)[i]) continue; | |||
| 987 | return Placev(a)((a)->placev)[i] > Placev(b)((b)->placev)[i]; | |||
| 988 | } | |||
| 989 | return false((int) 0); | |||
| 990 | } | |||
| 991 | else { | |||
| 992 | if (Placec(a)((a)->placec)!= Placec(b)((b)->placec)) return Placec(a)((a)->placec) < Placec(b)((b)->placec); | |||
| 993 | c = Placec(a)((a)->placec); | |||
| 994 | for (i = c-1; i >= 0; i--) { | |||
| 995 | if (Placev(a)((a)->placev)[i] == Placev(b)((b)->placev)[i]) continue; | |||
| 996 | return Placev(a)((a)->placev)[i] < Placev(b)((b)->placev)[i]; | |||
| 997 | } | |||
| 998 | return false((int) 0); | |||
| 999 | } | |||
| 1000 | } | |||
| 1001 | ||||
| 1002 | /* | |||
| 1003 | * a > b ? | |||
| 1004 | */ | |||
| 1005 | Bool | |||
| 1006 | bintGT(BInt a, BInt b) | |||
| 1007 | { | |||
| 1008 | Bool aImmed, bImmed; | |||
| 1009 | IInt i, c; | |||
| 1010 | ||||
| 1011 | if (Beq(a,b)((a) == (b))) return false((int) 0); | |||
| 1012 | ||||
| 1013 | aImmed = IsImmed(a)((long)(a) & 1); | |||
| 1014 | bImmed = IsImmed(b)((long)(b) & 1); | |||
| 1015 | ||||
| 1016 | if (aImmed && bImmed) return BIntToInt(a)((IInt) ((((long) (a))) >> 1)) > BIntToInt(b)((IInt) ((((long) (b))) >> 1)); | |||
| 1017 | if (aImmed) return IsNeg(b)((b)->isNeg); | |||
| 1018 | if (bImmed) return !IsNeg(a)((a)->isNeg); | |||
| 1019 | if (IsNeg(a)((a)->isNeg) != IsNeg(b)((b)->isNeg)) return !IsNeg(a)((a)->isNeg) && IsNeg(b)((b)->isNeg); | |||
| 1020 | ||||
| 1021 | if (IsNeg(a)((a)->isNeg)) { | |||
| 1022 | if (Placec(a)((a)->placec)!= Placec(b)((b)->placec)) return Placec(a)((a)->placec) < Placec(b)((b)->placec); | |||
| 1023 | c = Placec(a)((a)->placec); | |||
| 1024 | for (i = c-1; i >= 0; i--) { | |||
| 1025 | if (Placev(a)((a)->placev)[i] == Placev(b)((b)->placev)[i]) continue; | |||
| 1026 | return Placev(a)((a)->placev)[i] < Placev(b)((b)->placev)[i]; | |||
| 1027 | } | |||
| 1028 | return false((int) 0); | |||
| 1029 | } | |||
| 1030 | else { | |||
| 1031 | if (Placec(a)((a)->placec)!= Placec(b)((b)->placec)) return Placec(a)((a)->placec) > Placec(b)((b)->placec); | |||
| 1032 | c = Placec(a)((a)->placec); | |||
| 1033 | for (i = c-1; i >= 0; i--) { | |||
| 1034 | if (Placev(a)((a)->placev)[i] == Placev(b)((b)->placev)[i]) continue; | |||
| 1035 | return Placev(a)((a)->placev)[i] > Placev(b)((b)->placev)[i]; | |||
| 1036 | } | |||
| 1037 | return false((int) 0); | |||
| 1038 | } | |||
| 1039 | } | |||
| 1040 | ||||
| 1041 | /* | |||
| 1042 | * Form a new value equal to the absolute value of a. | |||
| 1043 | */ | |||
| 1044 | BInt | |||
| 1045 | bintAbs(BInt a) | |||
| 1046 | { | |||
| 1047 | BInt r; | |||
| 1048 | ||||
| 1049 | if (IsImmed(a)((long)(a) & 1)) { | |||
| 1050 | r = (BIntToInt(a)((IInt) ((((long) (a))) >> 1)) < 0) ? bintNew(-BIntToInt(a)((IInt) ((((long) (a))) >> 1))) : a; | |||
| 1051 | } | |||
| 1052 | else { | |||
| 1053 | r = bintCopy(a); | |||
| 1054 | IsNeg(r)((r)->isNeg) = false((int) 0); | |||
| 1055 | } | |||
| 1056 | return r; | |||
| 1057 | } | |||
| 1058 | ||||
| 1059 | /* | |||
| 1060 | * Form a new value equal to -a. | |||
| 1061 | */ | |||
| 1062 | BInt | |||
| 1063 | bintNegate(BInt a) | |||
| 1064 | { | |||
| 1065 | BInt r; | |||
| 1066 | ||||
| 1067 | if (IsImmed(a)((long)(a) & 1)) return IntToBInt(-BIntToInt(a))((BInt) ((Pointer)(((((long)(-((IInt) ((((long) (a))) >> 1)))) << 1) | 1)))); | |||
| 1068 | ||||
| 1069 | r = bintCopy(a); | |||
| 1070 | IsNeg(r)((r)->isNeg) = !IsNeg(r)((r)->isNeg); | |||
| 1071 | return r; | |||
| 1072 | } | |||
| 1073 | ||||
| 1074 | #define BINT_NEGATE(r){ if (((long)(r) & 1)) (r) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (r))) >> 1)))) << 1) | 1)))); else ((r)->isNeg) = !((r)->isNeg); } \ | |||
| 1075 | { if (IsImmed(r)((long)(r) & 1)) (r) = IntToBInt(-BIntToInt(r))((BInt) ((Pointer)(((((long)(-((IInt) ((((long) (r))) >> 1)))) << 1) | 1)))); else IsNeg(r)((r)->isNeg) = !IsNeg(r)((r)->isNeg); } | |||
| 1076 | ||||
| 1077 | /* | |||
| 1078 | * Add a and b to produce a newly allocated result. | |||
| 1079 | */ | |||
| 1080 | BInt | |||
| 1081 | bintPlus(BInt a, BInt b) | |||
| 1082 | { | |||
| 1083 | BInt r; | |||
| 1084 | Bool aImmed, bImmed, rImmed, aNeg, bNeg; | |||
| 1085 | IInt abitc, bbitc, rbitc; | |||
| 1086 | ||||
| 1087 | /* Small integer case. */ | |||
| 1088 | aImmed = IsImmed(a)((long)(a) & 1); | |||
| 1089 | bImmed = IsImmed(b)((long)(b) & 1); | |||
| 1090 | ||||
| 1091 | if (aImmed && bImmed) { | |||
| 1092 | IInt ai = BIntToInt(a)((IInt) ((((long) (a))) >> 1)); | |||
| 1093 | IInt bi = BIntToInt(b)((IInt) ((((long) (b))) >> 1)); | |||
| 1094 | IInt ki, ri; | |||
| 1095 | PlusStep(ki,ri, ai, bi, int0){ BIntD r_ = (BIntD)(ai)+(BIntD)(bi)+(BIntD)(((int) 0)); BIntS k_ = (r_ >= (BIntD) (((unsigned long) 1) << ((8 * sizeof (BIntS))))); if (k_) r_ -= (((unsigned long) 1) << ((8 * sizeof(BIntS)))); (ri) = r_; (ki) = k_; }; | |||
| 1096 | if (ki == 0 && INT_IS_IMMED(ri)(((((IInt) 3) << ((8 * sizeof(IInt))-2)) + 1)<= (long )(ri) && (long)(ri)<= (- (long) ((((IInt) 3) << ((8 * sizeof(IInt))-2)) + 1)))) return IntToBInt(ri)((BInt) ((Pointer)(((((long)(ri)) << 1) | 1)))); | |||
| 1097 | } | |||
| 1098 | ||||
| 1099 | if (aImmed) a = xintStore(a); | |||
| 1100 | if (bImmed) b = xintStore(b); | |||
| 1101 | ||||
| 1102 | aNeg = bintIsNeg(a); | |||
| 1103 | bNeg = bintIsNeg(b); | |||
| 1104 | ||||
| 1105 | if (aNeg && bNeg) { | |||
| 1106 | BINT_NEGATE(a){ if (((long)(a) & 1)) (a) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (a))) >> 1)))) << 1) | 1)))); else ((a)->isNeg) = !((a)->isNeg); }; if (!Beq(a,b)((a) == (b))) BINT_NEGATE(b){ if (((long)(b) & 1)) (b) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (b))) >> 1)))) << 1) | 1)))); else ((b)->isNeg) = !((b)->isNeg); }; | |||
| 1107 | r = bintPlus(a, b); | |||
| 1108 | BINT_NEGATE(a){ if (((long)(a) & 1)) (a) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (a))) >> 1)))) << 1) | 1)))); else ((a)->isNeg) = !((a)->isNeg); }; if (!Beq(a,b)((a) == (b))) BINT_NEGATE(b){ if (((long)(b) & 1)) (b) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (b))) >> 1)))) << 1) | 1)))); else ((b)->isNeg) = !((b)->isNeg); }; | |||
| 1109 | BINT_NEGATE(r){ if (((long)(r) & 1)) (r) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (r))) >> 1)))) << 1) | 1)))); else ((r)->isNeg) = !((r)->isNeg); }; | |||
| 1110 | } | |||
| 1111 | else if (aNeg) { | |||
| 1112 | BINT_NEGATE(a){ if (((long)(a) & 1)) (a) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (a))) >> 1)))) << 1) | 1)))); else ((a)->isNeg) = !((a)->isNeg); }; | |||
| 1113 | r = bintMinus(b, a); | |||
| 1114 | BINT_NEGATE(a){ if (((long)(a) & 1)) (a) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (a))) >> 1)))) << 1) | 1)))); else ((a)->isNeg) = !((a)->isNeg); }; | |||
| 1115 | } | |||
| 1116 | else if (bNeg) { | |||
| 1117 | BINT_NEGATE(b){ if (((long)(b) & 1)) (b) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (b))) >> 1)))) << 1) | 1)))); else ((b)->isNeg) = !((b)->isNeg); }; | |||
| 1118 | r = bintMinus(a, b); | |||
| 1119 | BINT_NEGATE(b){ if (((long)(b) & 1)) (b) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (b))) >> 1)))) << 1) | 1)))); else ((b)->isNeg) = !((b)->isNeg); }; | |||
| 1120 | } | |||
| 1121 | else { | |||
| 1122 | /* General case. */ | |||
| 1123 | abitc = bintLength(a); | |||
| 1124 | bbitc = bintLength(b); | |||
| 1125 | ||||
| 1126 | if (abitc < bbitc) { | |||
| 1127 | r = a; rbitc = abitc; rImmed = aImmed; | |||
| 1128 | a = b; abitc = bbitc; aImmed = bImmed; | |||
| 1129 | b = r; bbitc = rbitc; bImmed = rImmed; | |||
| 1130 | } | |||
| 1131 | ||||
| 1132 | rbitc = abitc + 1; /* +1 for potential carry */ | |||
| 1133 | ||||
| 1134 | r = bintAlloc(rbitc); | |||
| 1135 | ||||
| 1136 | iintPlus(r, a, b); | |||
| 1137 | ||||
| 1138 | r = xintImmedIfCan(r); | |||
| 1139 | } | |||
| 1140 | ||||
| 1141 | if (aImmed) bintFree(a); | |||
| 1142 | if (bImmed) bintFree(b); | |||
| 1143 | return r; | |||
| 1144 | } | |||
| 1145 | ||||
| 1146 | /* | |||
| 1147 | * Subtract b from a to produce a newly allocated result. | |||
| 1148 | */ | |||
| 1149 | BInt | |||
| 1150 | bintMinus(BInt a, BInt b) | |||
| 1151 | { | |||
| 1152 | BInt r; | |||
| 1153 | Bool aImmed, bImmed, rImmed, aNeg, bNeg, rNeg; | |||
| 1154 | ||||
| 1155 | /* Small integer case. */ | |||
| 1156 | aImmed = IsImmed(a)((long)(a) & 1); | |||
| 1157 | bImmed = IsImmed(b)((long)(b) & 1); | |||
| 1158 | ||||
| 1159 | if (aImmed && bImmed) { | |||
| 1160 | IInt ai = BIntToInt(a)((IInt) ((((long) (a))) >> 1)); | |||
| 1161 | IInt bi = BIntToInt(b)((IInt) ((((long) (b))) >> 1)); | |||
| 1162 | IInt ri = ai - bi; | |||
| 1163 | if (INT_IS_IMMED(ri)(((((IInt) 3) << ((8 * sizeof(IInt))-2)) + 1)<= (long )(ri) && (long)(ri)<= (- (long) ((((IInt) 3) << ((8 * sizeof(IInt))-2)) + 1)))) return IntToBInt(ri)((BInt) ((Pointer)(((((long)(ri)) << 1) | 1)))); | |||
| 1164 | } | |||
| 1165 | ||||
| 1166 | if (aImmed) a = xintStore(a); | |||
| 1167 | if (bImmed) b = xintStore(b); | |||
| 1168 | ||||
| 1169 | aNeg = bintIsNeg(a); | |||
| 1170 | bNeg = bintIsNeg(b); | |||
| 1171 | ||||
| 1172 | if (aNeg && bNeg) { | |||
| 1173 | BINT_NEGATE(a){ if (((long)(a) & 1)) (a) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (a))) >> 1)))) << 1) | 1)))); else ((a)->isNeg) = !((a)->isNeg); }; if (!Beq(a,b)((a) == (b))) BINT_NEGATE(b){ if (((long)(b) & 1)) (b) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (b))) >> 1)))) << 1) | 1)))); else ((b)->isNeg) = !((b)->isNeg); }; | |||
| 1174 | r = bintMinus(b, a); | |||
| 1175 | BINT_NEGATE(a){ if (((long)(a) & 1)) (a) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (a))) >> 1)))) << 1) | 1)))); else ((a)->isNeg) = !((a)->isNeg); }; if (!Beq(a,b)((a) == (b))) BINT_NEGATE(b){ if (((long)(b) & 1)) (b) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (b))) >> 1)))) << 1) | 1)))); else ((b)->isNeg) = !((b)->isNeg); }; | |||
| 1176 | } | |||
| 1177 | else if (aNeg) { | |||
| 1178 | BINT_NEGATE(a){ if (((long)(a) & 1)) (a) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (a))) >> 1)))) << 1) | 1)))); else ((a)->isNeg) = !((a)->isNeg); }; | |||
| 1179 | r = bintPlus(a, b); | |||
| 1180 | BINT_NEGATE(a){ if (((long)(a) & 1)) (a) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (a))) >> 1)))) << 1) | 1)))); else ((a)->isNeg) = !((a)->isNeg); }; | |||
| 1181 | BINT_NEGATE(r){ if (((long)(r) & 1)) (r) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (r))) >> 1)))) << 1) | 1)))); else ((r)->isNeg) = !((r)->isNeg); }; | |||
| 1182 | } | |||
| 1183 | else if (bNeg) { | |||
| 1184 | BINT_NEGATE(b){ if (((long)(b) & 1)) (b) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (b))) >> 1)))) << 1) | 1)))); else ((b)->isNeg) = !((b)->isNeg); }; | |||
| 1185 | r = bintPlus(a, b); | |||
| 1186 | BINT_NEGATE(b){ if (((long)(b) & 1)) (b) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (b))) >> 1)))) << 1) | 1)))); else ((b)->isNeg) = !((b)->isNeg); }; | |||
| 1187 | } | |||
| 1188 | else { | |||
| 1189 | /* General case. */ | |||
| 1190 | ||||
| 1191 | /* If a < b, compute -(b-a). */ | |||
| 1192 | rNeg = bintLT(a, b); | |||
| 1193 | if (rNeg) { | |||
| 1194 | r = a; rImmed = aImmed; | |||
| 1195 | a = b; aImmed = bImmed; | |||
| 1196 | b = r; bImmed = rImmed; | |||
| 1197 | } | |||
| 1198 | ||||
| 1199 | r = bintAllocPlaces(Placec(a)((a)->placec)); | |||
| 1200 | ||||
| 1201 | iintMinus(r, a, b); | |||
| 1202 | IsNeg(r)((r)->isNeg) = rNeg; | |||
| 1203 | ||||
| 1204 | r = xintImmedIfCan(r); | |||
| 1205 | } | |||
| 1206 | ||||
| 1207 | if (aImmed) bintFree(a); | |||
| 1208 | if (bImmed) bintFree(b); | |||
| 1209 | ||||
| 1210 | return r; | |||
| 1211 | } | |||
| 1212 | ||||
| 1213 | /* | |||
| 1214 | * Multiply a and b to produce a newly allocated result. | |||
| 1215 | */ | |||
| 1216 | BInt | |||
| 1217 | bintTimes(BInt a, BInt b) | |||
| 1218 | { | |||
| 1219 | BInt r; | |||
| 1220 | Bool aImmed, bImmed, aNeg, bNeg; | |||
| 1221 | IInt ac, bc, rc; | |||
| 1222 | ||||
| 1223 | /* Small integer case. */ | |||
| 1224 | aImmed = IsImmed(a)((long)(a) & 1); | |||
| 1225 | bImmed = IsImmed(b)((long)(b) & 1); | |||
| 1226 | ||||
| 1227 | if (aImmed && bImmed) { | |||
| 1228 | IInt ai = BIntToInt(a)((IInt) ((((long) (a))) >> 1)); | |||
| 1229 | IInt bi = BIntToInt(b)((IInt) ((((long) (b))) >> 1)); | |||
| 1230 | if (INT_IS_HALF(ai)((-((((IInt) 1)<<((((8 * sizeof(IInt))-2)/2))) -1)) <= (long)(ai) && (long)(ai)<= ((((IInt) 1)<<(( ((8 * sizeof(IInt))-2)/2))) -1)) && INT_IS_HALF(bi)((-((((IInt) 1)<<((((8 * sizeof(IInt))-2)/2))) -1)) <= (long)(bi) && (long)(bi)<= ((((IInt) 1)<<(( ((8 * sizeof(IInt))-2)/2))) -1))) return bintNew(ai*bi); | |||
| 1231 | } | |||
| 1232 | if (aImmed) { | |||
| 1233 | IInt ai = BIntToInt(a)((IInt) ((((long) (a))) >> 1)); | |||
| 1234 | if (ai == 0) return IntToBInt(int0)((BInt) ((Pointer)(((((long)(((int) 0))) << 1) | 1)))); | |||
| 1235 | if (ai == 1) return bintCopy(b); | |||
| 1236 | if (ai ==-1) return bintNegate(b); | |||
| 1237 | } | |||
| 1238 | if (bImmed) { | |||
| 1239 | IInt bi = BIntToInt(b)((IInt) ((((long) (b))) >> 1)); | |||
| 1240 | if (bi == 0) return IntToBInt(int0)((BInt) ((Pointer)(((((long)(((int) 0))) << 1) | 1)))); | |||
| 1241 | if (bi == 1) return bintCopy(a); | |||
| 1242 | if (bi ==-1) return bintNegate(a); | |||
| 1243 | } | |||
| 1244 | ||||
| 1245 | if (aImmed) a = xintStore(a); | |||
| 1246 | if (bImmed) b = xintStore(b); | |||
| 1247 | ||||
| 1248 | aNeg = bintIsNeg(a); | |||
| 1249 | bNeg = bintIsNeg(b); | |||
| 1250 | ||||
| 1251 | if (aNeg && bNeg) { | |||
| 1252 | BINT_NEGATE(a){ if (((long)(a) & 1)) (a) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (a))) >> 1)))) << 1) | 1)))); else ((a)->isNeg) = !((a)->isNeg); }; if (!Beq(a,b)((a) == (b))) BINT_NEGATE(b){ if (((long)(b) & 1)) (b) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (b))) >> 1)))) << 1) | 1)))); else ((b)->isNeg) = !((b)->isNeg); }; | |||
| 1253 | r = bintTimes(a, b); | |||
| 1254 | BINT_NEGATE(a){ if (((long)(a) & 1)) (a) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (a))) >> 1)))) << 1) | 1)))); else ((a)->isNeg) = !((a)->isNeg); }; if (!Beq(a,b)((a) == (b))) BINT_NEGATE(b){ if (((long)(b) & 1)) (b) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (b))) >> 1)))) << 1) | 1)))); else ((b)->isNeg) = !((b)->isNeg); }; | |||
| 1255 | } | |||
| 1256 | else if (aNeg) { | |||
| 1257 | BINT_NEGATE(a){ if (((long)(a) & 1)) (a) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (a))) >> 1)))) << 1) | 1)))); else ((a)->isNeg) = !((a)->isNeg); }; | |||
| 1258 | r = bintTimes(a, b); | |||
| 1259 | BINT_NEGATE(a){ if (((long)(a) & 1)) (a) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (a))) >> 1)))) << 1) | 1)))); else ((a)->isNeg) = !((a)->isNeg); }; | |||
| 1260 | BINT_NEGATE(r){ if (((long)(r) & 1)) (r) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (r))) >> 1)))) << 1) | 1)))); else ((r)->isNeg) = !((r)->isNeg); }; | |||
| 1261 | } | |||
| 1262 | else if (bNeg) { | |||
| 1263 | BINT_NEGATE(b){ if (((long)(b) & 1)) (b) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (b))) >> 1)))) << 1) | 1)))); else ((b)->isNeg) = !((b)->isNeg); }; | |||
| 1264 | r = bintTimes(a, b); | |||
| 1265 | BINT_NEGATE(b){ if (((long)(b) & 1)) (b) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (b))) >> 1)))) << 1) | 1)))); else ((b)->isNeg) = !((b)->isNeg); }; | |||
| 1266 | BINT_NEGATE(r){ if (((long)(r) & 1)) (r) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (r))) >> 1)))) << 1) | 1)))); else ((r)->isNeg) = !((r)->isNeg); }; | |||
| 1267 | } | |||
| 1268 | else { | |||
| 1269 | /* General case. */ | |||
| 1270 | ||||
| 1271 | ac = Placec(a)((a)->placec); | |||
| 1272 | bc = Placec(b)((b)->placec); | |||
| 1273 | rc = ac + bc; | |||
| 1274 | ||||
| 1275 | r = bintAllocPlaces(rc); | |||
| 1276 | ||||
| 1277 | iintTimes(r, a, b); | |||
| 1278 | ||||
| 1279 | r = xintImmedIfCan(r); | |||
| 1280 | } | |||
| 1281 | ||||
| 1282 | if (aImmed) bintFree(a); | |||
| 1283 | if (bImmed) bintFree(b); | |||
| 1284 | ||||
| 1285 | return r; | |||
| 1286 | } | |||
| 1287 | ||||
| 1288 | ||||
| 1289 | /* | |||
| 1290 | * Divide a by b to produce a newly allocated quotient as the result. | |||
| 1291 | * If the pointer pr != 0, then a newly allocated remainder is returned via it. | |||
| 1292 | */ | |||
| 1293 | BInt | |||
| 1294 | bintDivide(BInt *pr, BInt a, BInt b) | |||
| 1295 | { | |||
| 1296 | BInt q, r; | |||
| 1297 | Bool aImmed, bImmed, aNeg, bNeg; | |||
| 1298 | IInt n, m; | |||
| 1299 | ||||
| 1300 | /* Small integer case not yet handled. */ | |||
| 1301 | aImmed = IsImmed(a)((long)(a) & 1); | |||
| 1302 | bImmed = IsImmed(b)((long)(b) & 1); | |||
| 1303 | ||||
| 1304 | if (aImmed) a = xintStore(a); | |||
| 1305 | if (bImmed) b = xintStore(b); | |||
| 1306 | ||||
| 1307 | aNeg = bintIsNeg(a); | |||
| 1308 | bNeg = bintIsNeg(b); | |||
| 1309 | ||||
| 1310 | if (aNeg && bNeg) { | |||
| 1311 | /* (q,r) = divide(-a,-b); if (r != 0) {q++; r = b-r;} */ | |||
| 1312 | BINT_NEGATE(a){ if (((long)(a) & 1)) (a) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (a))) >> 1)))) << 1) | 1)))); else ((a)->isNeg) = !((a)->isNeg); }; if (!Beq(a,b)((a) == (b))) BINT_NEGATE(b){ if (((long)(b) & 1)) (b) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (b))) >> 1)))) << 1) | 1)))); else ((b)->isNeg) = !((b)->isNeg); }; | |||
| 1313 | q = bintDivide(&r, a, b); | |||
| 1314 | BINT_NEGATE(a){ if (((long)(a) & 1)) (a) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (a))) >> 1)))) << 1) | 1)))); else ((a)->isNeg) = !((a)->isNeg); }; if (!Beq(a,b)((a) == (b))) BINT_NEGATE(b){ if (((long)(b) & 1)) (b) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (b))) >> 1)))) << 1) | 1)))); else ((b)->isNeg) = !((b)->isNeg); }; | |||
| 1315 | ||||
| 1316 | BINT_NEGATE(r){ if (((long)(r) & 1)) (r) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (r))) >> 1)))) << 1) | 1)))); else ((r)->isNeg) = !((r)->isNeg); }; | |||
| 1317 | } | |||
| 1318 | else if (aNeg) { | |||
| 1319 | /* (q,r) = divide(-a,b); q = -q-1; r = b-r; */ | |||
| 1320 | BINT_NEGATE(a){ if (((long)(a) & 1)) (a) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (a))) >> 1)))) << 1) | 1)))); else ((a)->isNeg) = !((a)->isNeg); }; | |||
| 1321 | q = bintDivide(&r, a, b); | |||
| 1322 | BINT_NEGATE(a){ if (((long)(a) & 1)) (a) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (a))) >> 1)))) << 1) | 1)))); else ((a)->isNeg) = !((a)->isNeg); }; | |||
| 1323 | ||||
| 1324 | BINT_NEGATE(q){ if (((long)(q) & 1)) (q) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (q))) >> 1)))) << 1) | 1)))); else ((q)->isNeg) = !((q)->isNeg); }; | |||
| 1325 | BINT_NEGATE(r){ if (((long)(r) & 1)) (r) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (r))) >> 1)))) << 1) | 1)))); else ((r)->isNeg) = !((r)->isNeg); }; | |||
| 1326 | } | |||
| 1327 | else if (bNeg) { | |||
| 1328 | /* (q,r) = divide(a,-b); q = -q; */ | |||
| 1329 | BINT_NEGATE(b){ if (((long)(b) & 1)) (b) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (b))) >> 1)))) << 1) | 1)))); else ((b)->isNeg) = !((b)->isNeg); }; | |||
| 1330 | q = bintDivide(&r, a, b); | |||
| 1331 | BINT_NEGATE(b){ if (((long)(b) & 1)) (b) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (b))) >> 1)))) << 1) | 1)))); else ((b)->isNeg) = !((b)->isNeg); }; | |||
| 1332 | ||||
| 1333 | BINT_NEGATE(q){ if (((long)(q) & 1)) (q) = ((BInt) ((Pointer)(((((long) (-((IInt) ((((long) (q))) >> 1)))) << 1) | 1)))); else ((q)->isNeg) = !((q)->isNeg); }; | |||
| 1334 | } | |||
| 1335 | else { | |||
| 1336 | /* General case. */ | |||
| 1337 | ||||
| 1338 | n = Placec(b)((b)->placec); | |||
| 1339 | m = Placec(a)((a)->placec) - n; if (m < 0) m = 0; | |||
| 1340 | ||||
| 1341 | q = bintAllocPlaces(m+1); | |||
| 1342 | r = bintAllocPlaces(n+m+1); | |||
| 1343 | ||||
| 1344 | iintDivide(q, r, a, b); /*!! Should shrink r here. */ | |||
| 1345 | ||||
| 1346 | q = xintImmedIfCan(q); | |||
| 1347 | r = xintImmedIfCan(r); | |||
| 1348 | } | |||
| 1349 | ||||
| 1350 | if (aImmed) bintFree(a); | |||
| 1351 | if (bImmed) bintFree(b); | |||
| 1352 | ||||
| 1353 | if (pr) *pr = r; else bintFree(r); | |||
| 1354 | return q; | |||
| 1355 | } | |||
| 1356 | ||||
| 1357 | BInt | |||
| 1358 | bintMod(BInt a, BInt b) | |||
| 1359 | { | |||
| 1360 | BInt r, q; | |||
| 1361 | Bool neg; | |||
| 1362 | /* | |||
| 1363 | * Compute a mod b via horner's rule if b fits into a single word, | |||
| 1364 | * use bintDivide o/wise. | |||
| 1365 | */ | |||
| 1366 | neg = bintIsNeg(a); | |||
| 1367 | if (neg) | |||
| 1368 | a = bintNegate(a); | |||
| 1369 | ||||
| 1370 | if (bintIsNeg(b)) | |||
| 1371 | b = bintNegate(b); | |||
| 1372 | ||||
| 1373 | if (IsImmed(b)((long)(b) & 1)) { | |||
| 1374 | r = bintModi(a, (ULong) BIntToInt(b)((IInt) ((((long) (b))) >> 1))); | |||
| 1375 | } | |||
| 1376 | else if (bintLength(b) < bitsizeof(ULong)(8 * sizeof(ULong))) { | |||
| 1377 | /* Can't handle 32 bit divisors as yet! */ | |||
| 1378 | r = bintModi(a, bintToULong(b)); | |||
| 1379 | } | |||
| 1380 | else { | |||
| 1381 | q = bintDivide(&r, (BInt) a, (BInt) b); | |||
| 1382 | bintFree(q); | |||
| 1383 | } | |||
| 1384 | if (neg) | |||
| 1385 | r = xintNegate(r); | |||
| 1386 | ||||
| 1387 | return r; | |||
| 1388 | } | |||
| 1389 | ||||
| 1390 | localstatic BInt | |||
| 1391 | bintModi(BInt a, ULong b) | |||
| 1392 | { | |||
| 1393 | ULong d = 1L << bitsizeof(BIntS)(8 * sizeof(BIntS)); | |||
| 1394 | ULong r; | |||
| 1395 | ULong acc; | |||
| 1396 | int i; | |||
| 1397 | ||||
| 1398 | assert(!bintIsNeg(a))do { if (!(!bintIsNeg(a))) _do_assert(("!bintIsNeg(a)"),"bigint.c" ,1398); } while (0); | |||
| 1399 | ||||
| 1400 | if (IsImmed(a)((long)(a) & 1)) { | |||
| 1401 | return bintNew(BIntToInt(a)((IInt) ((((long) (a))) >> 1)) % b); | |||
| 1402 | } | |||
| 1403 | ||||
| 1404 | if (b < d) { | |||
| 1405 | d = d % b; | |||
| 1406 | i = Placec(a)((a)->placec) - 1; | |||
| 1407 | acc = Placev(a)((a)->placev)[i] % b; | |||
| 1408 | i--; | |||
| 1409 | while (i>=0) { | |||
| 1410 | long tmp; | |||
| 1411 | /* acc = acc mod* d mod+ a[i] */ | |||
| 1412 | acc = (acc * d) % b; | |||
| 1413 | tmp = acc - b + Placev(a)((a)->placev)[i] % b; | |||
| 1414 | if (tmp < 0) tmp += b; | |||
| 1415 | acc = tmp; | |||
| 1416 | i--; | |||
| 1417 | } | |||
| 1418 | } | |||
| 1419 | else { | |||
| 1420 | /* b larger than 1 halfword */ | |||
| 1421 | i = Placec(a)((a)->placec) - 1; | |||
| 1422 | acc = Placev(a)((a)->placev)[i]; | |||
| 1423 | i--; | |||
| 1424 | while (i>=0) { | |||
| 1425 | /* acc = acc mod* d mod+ a[i] */ | |||
| 1426 | ULong hi, lo, rem; | |||
| 1427 | long tmp; | |||
| 1428 | /*xxTimesDouble(&hi, &lo, acc, d);*/ | |||
| 1429 | hi = acc >> bitsizeof(BIntS)(8 * sizeof(BIntS)); | |||
| 1430 | lo = acc << bitsizeof(BIntS)(8 * sizeof(BIntS)); | |||
| 1431 | rem = xxModDouble(hi, lo, b); | |||
| 1432 | tmp = (rem - (long) b) + Placev(a)((a)->placev)[i]; | |||
| 1433 | if (tmp < 0) | |||
| 1434 | tmp += b; | |||
| 1435 | acc = tmp; | |||
| 1436 | i--; | |||
| 1437 | } | |||
| 1438 | } | |||
| 1439 | r = acc; | |||
| 1440 | return bintNew(r); | |||
| 1441 | } | |||
| 1442 | ||||
| 1443 | localstatic ULong | |||
| 1444 | bintToULong(BInt b) | |||
| 1445 | { | |||
| 1446 | ULong res; | |||
| 1447 | if (bintIsSmall(b)) | |||
| 1448 | return bintSmall(b); | |||
| 1449 | ||||
| 1450 | res = (ULong) Placev(b)((b)->placev)[0] + ( ((ULong) Placev(b)((b)->placev)[1]) << bitsizeof(BIntS)(8 * sizeof(BIntS))); | |||
| 1451 | ||||
| 1452 | return res; | |||
| 1453 | } | |||
| 1454 | ||||
| 1455 | /* | |||
| 1456 | * The length of b, in bits. I.e. cieling(lg(abs(b))). | |||
| 1457 | * Define the bit length of zero to be one bit. | |||
| 1458 | */ | |||
| 1459 | Length | |||
| 1460 | bintLength(BInt b) | |||
| 1461 | { | |||
| 1462 | Length res; | |||
| 1463 | if (IsImmed(b)((long)(b) & 1)) return intLength(BIntToInt(b)((IInt) ((((long) (b))) >> 1))); | |||
| 1464 | res = BINT_LG_RADIX((8 * sizeof(BIntS)))*(Placec(b)((b)->placec)-1) + uintLength(Placev(b)((b)->placev)[Placec(b)((b)->placec)-1]); | |||
| 1465 | return res; | |||
| 1466 | } | |||
| 1467 | ||||
| 1468 | ||||
| 1469 | /* | |||
| 1470 | * Extract the ix-th bit of b. I.e. the coef of 2**ix. | |||
| 1471 | * !! This should handle negative numbers. | |||
| 1472 | */ | |||
| 1473 | Bool | |||
| 1474 | bintBit(BInt b, Length ix) | |||
| 1475 | { | |||
| 1476 | Length cq, cr; | |||
| 1477 | ||||
| 1478 | if (IsImmed(b)((long)(b) & 1)) return intBit(BIntToInt(b)((IInt) ((((long) (b))) >> 1)), ix); | |||
| 1479 | ||||
| 1480 | cq = ix / BINT_LG_RADIX((8 * sizeof(BIntS))); | |||
| 1481 | cr = ix % BINT_LG_RADIX((8 * sizeof(BIntS))); | |||
| 1482 | ||||
| 1483 | return (cq < Placec(b)((b)->placec)) && (Placev(b)((b)->placev)[cq] & (1<<cr)) != 0; | |||
| 1484 | } | |||
| 1485 | ||||
| 1486 | /* | |||
| 1487 | * Shift b by n bits. I.e. compute b*2**n. | |||
| 1488 | */ | |||
| 1489 | BInt | |||
| 1490 | bintShift(BInt b, int n) | |||
| 1491 | { | |||
| 1492 | BInt r; | |||
| 1493 | IInt bbitc, rbitc; | |||
| 1494 | Bool bImmed; | |||
| 1495 | ||||
| 1496 | bImmed = IsImmed(b)((long)(b) & 1); | |||
| 1497 | bbitc = bintLength(b); | |||
| 1498 | rbitc = bbitc + n; | |||
| 1499 | ||||
| 1500 | if (b == bint0) return bint0; | |||
| 1501 | if (bbitc == 0 || rbitc <= 0) | |||
| 1502 | return IntToBInt(int0)((BInt) ((Pointer)(((((long)(((int) 0))) << 1) | 1)))); | |||
| 1503 | if (bImmed && rbitc <= INT_LG_IMMED((8 * sizeof(IInt))-2)) { | |||
| 1504 | IInt i = BIntToInt(b)((IInt) ((((long) (b))) >> 1)); | |||
| 1505 | UIInt u = (i > 0) ? i : -i; | |||
| 1506 | u = (n > 0) ? u << n : u >> -n; | |||
| 1507 | return IntToBInt((i > 0) ? u : -(IInt)u)((BInt) ((Pointer)(((((long)((i > 0) ? u : -(IInt)u)) << 1) | 1)))); | |||
| 1508 | } | |||
| 1509 | if (bImmed
| |||
| 1510 | r = bintAlloc(rbitc); | |||
| 1511 | ||||
| 1512 | iintShift(r, b, n); | |||
| 1513 | ||||
| 1514 | if (bImmed) bintFree(b); | |||
| 1515 | if (rbitc <= INT_LG_IMMED((8 * sizeof(IInt))-2)) r = xintImmedIfCan(r); | |||
| 1516 | ||||
| 1517 | return r; | |||
| 1518 | } | |||
| 1519 | ||||
| 1520 | BInt | |||
| 1521 | bintShiftRem(BInt b, int n) | |||
| 1522 | { | |||
| 1523 | BInt r; | |||
| 1524 | int i, top; | |||
| 1525 | /* Returns lowest `n' bits from b. */ | |||
| 1526 | ||||
| 1527 | if (IsImmed(b)((long)(b) & 1)) { | |||
| 1528 | IInt x = BIntToInt(b)((IInt) ((((long) (b))) >> 1)); | |||
| 1529 | return IntToBInt(x & ((1 << n) - 1))((BInt) ((Pointer)(((((long)(x & ((1 << n) - 1))) << 1) | 1)))); | |||
| 1530 | } | |||
| 1531 | ||||
| 1532 | r = bintAlloc(n); | |||
| 1533 | ||||
| 1534 | for (i=0; i<Placea(r)((r)->placea) - 1; i++) Placev(r)((r)->placev)[i] = Placev(b)((b)->placev)[i]; | |||
| 1535 | top = n - BINT_LG_RADIX((8 * sizeof(BIntS)))*(Placec(r)((r)->placec) - 1); | |||
| 1536 | Placev(r)((r)->placev)[i] = Placev(b)((b)->placev)[i] & ((1<< top) - 1); | |||
| 1537 | ||||
| 1538 | return xintImmedIfCan(r); | |||
| 1539 | } | |||
| 1540 | ||||
| 1541 | /**************************************************************************** | |||
| 1542 | * | |||
| 1543 | * :: Low-level, fine control allocation | |||
| 1544 | * | |||
| 1545 | ****************************************************************************/ | |||
| 1546 | ||||
| 1547 | /* | |||
| 1548 | * Allocate a new, stored integer value. | |||
| 1549 | */ | |||
| 1550 | BInt | |||
| 1551 | xintStoreI(long n) | |||
| 1552 | { | |||
| 1553 | BInt b; | |||
| 1554 | ULong u; | |||
| 1555 | IInt a; | |||
| 1556 | ||||
| 1557 | u = (n < 0) ? -n : n; | |||
| 1558 | for (a = 1; ; a += 1, u >>= BINT_LG_RADIX((8 * sizeof(BIntS)))) | |||
| 1559 | if( u < BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS)))) ) break; | |||
| 1560 | b = bintAllocPlaces(a); | |||
| 1561 | return xintCopyInI(b, n); | |||
| 1562 | } | |||
| 1563 | ||||
| 1564 | /* | |||
| 1565 | * Convert b to a stored representation. | |||
| 1566 | */ | |||
| 1567 | BInt | |||
| 1568 | xintStore(BInt b) | |||
| 1569 | { | |||
| 1570 | if (IsImmed(b)((long)(b) & 1)) return xintStoreI(BIntToInt(b)((IInt) ((((long) (b))) >> 1))); | |||
| 1571 | ||||
| 1572 | return b; | |||
| 1573 | } | |||
| 1574 | ||||
| 1575 | /* | |||
| 1576 | * Convert b to an immeditate (non-stored) representation, if possible. | |||
| 1577 | */ | |||
| 1578 | BInt | |||
| 1579 | xintImmedIfCan(BInt b) | |||
| 1580 | { | |||
| 1581 | Length pb; | |||
| 1582 | ULong u = 0; | |||
| 1583 | ||||
| 1584 | if (IsImmed(b)((long)(b) & 1)) return b; | |||
| 1585 | ||||
| 1586 | pb = Placec(b)((b)->placec); | |||
| 1587 | ||||
| 1588 | /* Special case all 32-bit cases */ | |||
| 1589 | if (pb == 0) | |||
| 1590 | return IntToBInt(int0)((BInt) ((Pointer)(((((long)(((int) 0))) << 1) | 1)))); | |||
| 1591 | if (pb == 1 || pb == 2) { | |||
| 1592 | if (pb == 1) | |||
| 1593 | u = Placev(b)((b)->placev)[0]; | |||
| 1594 | else | |||
| 1595 | u = ((BIntD)(Placev(b)((b)->placev)[1]) << BINT_LG_RADIX((8 * sizeof(BIntS)))) | |||
| 1596 | + Placev(b)((b)->placev)[0]; | |||
| 1597 | if (IsNeg(b)((b)->isNeg)) | |||
| 1598 | return u > -(long)INT_MIN_IMMED((((IInt) 3) << ((8 * sizeof(IInt))-2)) + 1) | |||
| 1599 | ? b : (BInt) ptrFrLong(MkImmed(-(IInt)u))((Pointer)(((((long)(-(IInt)u)) << 1) | 1))); | |||
| 1600 | else | |||
| 1601 | return u > INT_MAX_IMMED(- (long) ((((IInt) 3) << ((8 * sizeof(IInt))-2)) + 1)) | |||
| 1602 | ? b : (BInt) ptrFrLong(MkImmed(u))((Pointer)(((((long)(u)) << 1) | 1))); | |||
| 1603 | } | |||
| 1604 | ||||
| 1605 | ||||
| 1606 | /* For cases where 2*sizeof(BIntS) < sizeof(BInt) */ | |||
| 1607 | if (pb*BINT_LG_RADIX((8 * sizeof(BIntS))) <= bitsizeof(IInt)(8 * sizeof(IInt))) { | |||
| 1608 | int i; | |||
| 1609 | for (i = pb - 1; i>= 0; i--) | |||
| 1610 | u = (u << BINT_LG_RADIX((8 * sizeof(BIntS)))) + Placev(b)((b)->placev)[i]; | |||
| 1611 | if (IsNeg(b)((b)->isNeg)) | |||
| 1612 | return (u > -INT_MIN_IMMED((((IInt) 3) << ((8 * sizeof(IInt))-2)) + 1)) ? b | |||
| 1613 | : (BInt) ptrFrLong(MkImmed(-u))((Pointer)(((((long)(-u)) << 1) | 1))); | |||
| 1614 | else | |||
| 1615 | return (u > INT_MAX_IMMED(- (long) ((((IInt) 3) << ((8 * sizeof(IInt))-2)) + 1))) ? b | |||
| 1616 | : (BInt) ptrFrLong(MkImmed(u))((Pointer)(((((long)(u)) << 1) | 1))); | |||
| 1617 | } | |||
| 1618 | ||||
| 1619 | return b; | |||
| 1620 | } | |||
| 1621 | ||||
| 1622 | /* | |||
| 1623 | * Place integer value n into stored BInt b. | |||
| 1624 | * If b is not big enough, then it is reallocated. | |||
| 1625 | */ | |||
| 1626 | BInt | |||
| 1627 | xintCopyInI(BInt b, long n) | |||
| 1628 | { | |||
| 1629 | ULong u, ut; | |||
| 1630 | IInt i, c, a; | |||
| 1631 | assert(!IsImmed(b))do { if (!(!((long)(b) & 1))) _do_assert(("!IsImmed(b)"), "bigint.c",1631); } while (0); | |||
| 1632 | ||||
| 1633 | u = (n<0)? -n : n; | |||
| 1634 | c = Placea(b)((b)->placea); | |||
| 1635 | ||||
| 1636 | /* Quick test for usual case. */ | |||
| 1637 | if (u < BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS)))) && c > 0) { | |||
| 1638 | Placev(b)((b)->placev)[0] = u; | |||
| 1639 | Placec(b)((b)->placec) = 1; | |||
| 1640 | IsNeg(b)((b)->isNeg) = (n < 0); | |||
| 1641 | return b; | |||
| 1642 | } | |||
| 1643 | ||||
| 1644 | /* Multi-word case */ | |||
| 1645 | ut = u; for (a = 0; ut != 0; a++) ut /= BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS)))); | |||
| 1646 | ||||
| 1647 | if (a > c) { | |||
| 1648 | bintFree(b); | |||
| 1649 | b = bintAllocPlaces(a); | |||
| 1650 | c = a; | |||
| 1651 | } | |||
| 1652 | for (i = 0; u != 0 && i < c; i++) { | |||
| 1653 | Placev(b)((b)->placev)[i] = u % BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS)))); | |||
| 1654 | u = u / BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS)))); | |||
| 1655 | } | |||
| 1656 | Placec(b)((b)->placec) = i; | |||
| 1657 | ||||
| 1658 | IsNeg(b)((b)->isNeg) = (n < 0); | |||
| 1659 | return b; | |||
| 1660 | } | |||
| 1661 | ||||
| 1662 | ||||
| 1663 | /* | |||
| 1664 | * Ensure b can contain at least bitc bits. | |||
| 1665 | */ | |||
| 1666 | BInt | |||
| 1667 | xintNeeds(BInt b, Length bitc) | |||
| 1668 | { | |||
| 1669 | BInt bn; | |||
| 1670 | Length i, c; | |||
| 1671 | ||||
| 1672 | if (IsImmed(b)((long)(b) & 1)) { | |||
| 1673 | if (bitc <= INT_LG_IMMED((8 * sizeof(IInt))-2)) | |||
| 1674 | return b; | |||
| 1675 | else | |||
| 1676 | return xintCopyInI(bintAlloc(bitc), BIntToInt(b)((IInt) ((((long) (b))) >> 1))); | |||
| 1677 | } | |||
| 1678 | ||||
| 1679 | if (Placea(b)((b)->placea)*BINT_LG_RADIX((8 * sizeof(BIntS))) >= bitc) return b; | |||
| 1680 | ||||
| 1681 | bn = bintAlloc(bitc); | |||
| 1682 | c = Placec(b)((b)->placec); | |||
| 1683 | for (i = 0; i < c; i++) Placev(bn)((bn)->placev)[i] = Placev(b)((b)->placev)[i]; | |||
| 1684 | Placec(bn)((bn)->placec) = Placec(b)((b)->placec); | |||
| 1685 | IsNeg(bn)((bn)->isNeg) = IsNeg(b)((b)->isNeg); | |||
| 1686 | bintFree(b); | |||
| 1687 | ||||
| 1688 | return bn; | |||
| 1689 | } | |||
| 1690 | ||||
| 1691 | ||||
| 1692 | /* | |||
| 1693 | * Operations which free their operands. | |||
| 1694 | */ | |||
| 1695 | int | |||
| 1696 | xintPrint(FILE *fout, BInt a) | |||
| 1697 | { | |||
| 1698 | int cc = bintPrint(fout, a); | |||
| 1699 | bintFree(a); | |||
| 1700 | return cc; | |||
| 1701 | } | |||
| 1702 | ||||
| 1703 | int | |||
| 1704 | xintPrint2(FILE *fout, BInt a) | |||
| 1705 | { | |||
| 1706 | int cc = bintPrint2(fout, a); | |||
| 1707 | bintFree(a); | |||
| 1708 | return cc; | |||
| 1709 | } | |||
| 1710 | ||||
| 1711 | int | |||
| 1712 | xintPrint16(FILE *fout, BInt a) | |||
| 1713 | { | |||
| 1714 | int cc = bintPrint16(fout, a); | |||
| 1715 | bintFree(a); | |||
| 1716 | return cc; | |||
| 1717 | } | |||
| 1718 | ||||
| 1719 | BInt | |||
| 1720 | xintNegate(BInt a) | |||
| 1721 | { | |||
| 1722 | BInt r = bintNegate(a); | |||
| 1723 | bintFree(a); | |||
| 1724 | return r; | |||
| 1725 | } | |||
| 1726 | ||||
| 1727 | BInt | |||
| 1728 | xintPlus(BInt a, BInt b) | |||
| 1729 | { | |||
| 1730 | BInt r = bintPlus(a, b); | |||
| 1731 | bintFree(a); | |||
| 1732 | bintFree(b); | |||
| 1733 | return r; | |||
| 1734 | } | |||
| 1735 | ||||
| 1736 | BInt | |||
| 1737 | xintMinus(BInt a, BInt b) | |||
| 1738 | { | |||
| 1739 | BInt r = bintMinus(a, b); | |||
| 1740 | bintFree(a); | |||
| 1741 | bintFree(b); | |||
| 1742 | return r; | |||
| 1743 | } | |||
| 1744 | ||||
| 1745 | BInt | |||
| 1746 | xintTimes(BInt a, BInt b) | |||
| 1747 | { | |||
| 1748 | BInt r = bintTimes(a, b); | |||
| 1749 | bintFree(a); | |||
| 1750 | bintFree(b); | |||
| 1751 | return r; | |||
| 1752 | } | |||
| 1753 | ||||
| 1754 | BInt | |||
| 1755 | xintDivide(BInt *pr, BInt a, BInt b) | |||
| 1756 | { | |||
| 1757 | BInt q = bintDivide(pr, a, b); | |||
| 1758 | bintFree(a); | |||
| 1759 | bintFree(b); | |||
| 1760 | return q; | |||
| 1761 | } | |||
| 1762 | ||||
| 1763 | BInt | |||
| 1764 | xintShift(BInt a, int n) | |||
| 1765 | { | |||
| 1766 | BInt r = bintShift(a, n); | |||
| ||||
| 1767 | bintFree(a); | |||
| 1768 | return r; | |||
| 1769 | } | |||
| 1770 | ||||
| 1771 | /***************************************************************************** | |||
| 1772 | * | |||
| 1773 | * :: Low-level, non-allocating operations | |||
| 1774 | * | |||
| 1775 | * Arithmetic is done with the macros PlusStep, TimesDouble, etc. | |||
| 1776 | * | |||
| 1777 | ****************************************************************************/ | |||
| 1778 | ||||
| 1779 | /* | |||
| 1780 | * Place the value abs(a) in r. | |||
| 1781 | */ | |||
| 1782 | void | |||
| 1783 | iintAbs(BInt r, BInt a) | |||
| 1784 | { | |||
| 1785 | IInt i, c; | |||
| 1786 | ||||
| 1787 | assert(!IsImmed(r) && !IsImmed(a) && Placea(r)>=Placec(a))do { if (!(!((long)(r) & 1) && !((long)(a) & 1 ) && ((r)->placea)>=((a)->placec))) _do_assert (("!IsImmed(r) && !IsImmed(a) && Placea(r)>=Placec(a)" ),"bigint.c",1787); } while (0); | |||
| 1788 | ||||
| 1789 | IsNeg(r)((r)->isNeg) = false((int) 0); | |||
| 1790 | ||||
| 1791 | if (Beq(r,a)((r) == (a))) return; | |||
| 1792 | ||||
| 1793 | c = Placec(a)((a)->placec); | |||
| 1794 | ||||
| 1795 | for (i = 0; i < c; i++) Placev(r)((r)->placev)[i] = Placev(a)((a)->placev)[i]; | |||
| 1796 | Placec(r)((r)->placec) = Placec(a)((a)->placec); | |||
| 1797 | } | |||
| 1798 | ||||
| 1799 | /* | |||
| 1800 | * Place the value -a in r. | |||
| 1801 | */ | |||
| 1802 | void | |||
| 1803 | iintNegate(BInt r, BInt a) | |||
| 1804 | { | |||
| 1805 | IInt i, c; | |||
| 1806 | ||||
| 1807 | assert(!IsImmed(r) && !IsImmed(a) && Placea(r)>=Placec(a))do { if (!(!((long)(r) & 1) && !((long)(a) & 1 ) && ((r)->placea)>=((a)->placec))) _do_assert (("!IsImmed(r) && !IsImmed(a) && Placea(r)>=Placec(a)" ),"bigint.c",1807); } while (0); | |||
| 1808 | ||||
| 1809 | IsNeg(r)((r)->isNeg) = !IsNeg(a)((a)->isNeg); | |||
| 1810 | ||||
| 1811 | if (Beq(r,a)((r) == (a))) return; | |||
| 1812 | ||||
| 1813 | c = Placec(a)((a)->placec); | |||
| 1814 | ||||
| 1815 | for (i = 0; i < c; i++) Placev(r)((r)->placev)[i] = Placev(a)((a)->placev)[i]; | |||
| 1816 | Placec(r)((r)->placec) = Placec(a)((a)->placec); | |||
| 1817 | } | |||
| 1818 | ||||
| 1819 | /* | |||
| 1820 | * Add non-negative integers a and b and place result in preallocated r. | |||
| 1821 | * It is assumed that a is greater than b. | |||
| 1822 | * The result r, can be an alias for a or b. | |||
| 1823 | */ | |||
| 1824 | void | |||
| 1825 | iintPlus(BInt r, BInt a, BInt b) | |||
| 1826 | { | |||
| 1827 | BIntS s, k; /* k = 0 or 1 */ | |||
| 1828 | IInt i, ac, bc; | |||
| 1829 | ||||
| 1830 | assert(!IsImmed(a) && !IsImmed(b))do { if (!(!((long)(a) & 1) && !((long)(b) & 1 ))) _do_assert(("!IsImmed(a) && !IsImmed(b)"),"bigint.c" ,1830); } while (0); | |||
| 1831 | assert(!IsNeg(a) && !IsNeg(b))do { if (!(!((a)->isNeg) && !((b)->isNeg))) _do_assert (("!IsNeg(a) && !IsNeg(b)"),"bigint.c",1831); } while (0); | |||
| 1832 | assert(Placec(a) >= Placec(b))do { if (!(((a)->placec) >= ((b)->placec))) _do_assert (("Placec(a) >= Placec(b)"),"bigint.c",1832); } while (0); | |||
| 1833 | assert(!IsImmed(r) && Placea(r) >= Placec(a))do { if (!(!((long)(r) & 1) && ((r)->placea) >= ((a)->placec))) _do_assert(("!IsImmed(r) && Placea(r) >= Placec(a)" ),"bigint.c",1833); } while (0); | |||
| 1834 | ||||
| 1835 | ac = Placec(a)((a)->placec); | |||
| 1836 | bc = Placec(b)((b)->placec); | |||
| 1837 | ||||
| 1838 | k = 0; | |||
| 1839 | ||||
| 1840 | for (i = 0; i < bc; i++) { | |||
| 1841 | PlusStep(k, s, Placev(a)[i], Placev(b)[i], k){ BIntD r_ = (BIntD)(((a)->placev)[i])+(BIntD)(((b)->placev )[i])+(BIntD)(k); BIntS k_ = (r_ >= (BIntD) (((unsigned long ) 1) << ((8 * sizeof(BIntS))))); if (k_) r_ -= (((unsigned long) 1) << ((8 * sizeof(BIntS)))); (s) = r_; (k) = k_ ; }; | |||
| 1842 | Placev(r)((r)->placev)[i] = s; | |||
| 1843 | } | |||
| 1844 | ||||
| 1845 | for ( ; i < ac && k; i++) { | |||
| 1846 | PlusStep(k, s, Placev(a)[i], int0, k){ BIntD r_ = (BIntD)(((a)->placev)[i])+(BIntD)(((int) 0))+ (BIntD)(k); BIntS k_ = (r_ >= (BIntD) (((unsigned long) 1) << ((8 * sizeof(BIntS))))); if (k_) r_ -= (((unsigned long ) 1) << ((8 * sizeof(BIntS)))); (s) = r_; (k) = k_; }; | |||
| 1847 | Placev(r)((r)->placev)[i] = s; | |||
| 1848 | } | |||
| 1849 | ||||
| 1850 | if (!k && Beq(r,a)((r) == (a))) return; | |||
| 1851 | ||||
| 1852 | for ( ; i < ac; i++) { | |||
| 1853 | Placev(r)((r)->placev)[i] = Placev(a)((a)->placev)[i]; | |||
| 1854 | } | |||
| 1855 | ||||
| 1856 | if (k) | |||
| 1857 | Placev(r)((r)->placev)[i++] = k; | |||
| 1858 | ||||
| 1859 | Placec(r)((r)->placec) = i; | |||
| 1860 | } | |||
| 1861 | ||||
| 1862 | /* | |||
| 1863 | * Subtract non-negative integers a and b and place result in preallocated r. | |||
| 1864 | * It is assumed that a >= b >= 0. | |||
| 1865 | * The result r, can be an alias for a or b. | |||
| 1866 | * | |||
| 1867 | * This is Algorithm S of Knuth Volume 2, Section 4.3.1. | |||
| 1868 | */ | |||
| 1869 | void | |||
| 1870 | iintMinus(BInt r, BInt a, BInt b) | |||
| 1871 | { | |||
| 1872 | BIntS s, kp1; /* kp1 = k+1. k = 0 or -1 */ | |||
| 1873 | IInt i, ac, bc; | |||
| 1874 | ||||
| 1875 | assert(!IsImmed(a) && !IsImmed(b))do { if (!(!((long)(a) & 1) && !((long)(b) & 1 ))) _do_assert(("!IsImmed(a) && !IsImmed(b)"),"bigint.c" ,1875); } while (0); | |||
| 1876 | assert(!IsNeg(a) && !IsNeg(b))do { if (!(!((a)->isNeg) && !((b)->isNeg))) _do_assert (("!IsNeg(a) && !IsNeg(b)"),"bigint.c",1876); } while (0); | |||
| 1877 | assert(Placec(a) >= Placec(b))do { if (!(((a)->placec) >= ((b)->placec))) _do_assert (("Placec(a) >= Placec(b)"),"bigint.c",1877); } while (0); | |||
| 1878 | assert(!IsImmed(r) && Placea(r) >= Placec(a))do { if (!(!((long)(r) & 1) && ((r)->placea) >= ((a)->placec))) _do_assert(("!IsImmed(r) && Placea(r) >= Placec(a)" ),"bigint.c",1878); } while (0); | |||
| 1879 | ||||
| 1880 | ac = Placec(a)((a)->placec); | |||
| 1881 | bc = Placec(b)((b)->placec); | |||
| 1882 | ||||
| 1883 | kp1 = 1; | |||
| 1884 | ||||
| 1885 | for (i = 0; i < bc; i++) { | |||
| 1886 | MinusStep(kp1, s, Placev(a)[i], Placev(b)[i], kp1){ BIntD r_ = (BIntD)(((a)->placev)[i])+(BIntD)((((((unsigned long) 1) << ((8 * sizeof(BIntS)))) - 1) - (((b)->placev )[i])))+(BIntD)(kp1); BIntS k_ = (r_ >= (BIntD) (((unsigned long) 1) << ((8 * sizeof(BIntS))))); if (k_) r_ -= ((( unsigned long) 1) << ((8 * sizeof(BIntS)))); (s) = r_; ( kp1) = k_; }; | |||
| 1887 | Placev(r)((r)->placev)[i] = s; | |||
| 1888 | } | |||
| 1889 | ||||
| 1890 | for ( ; i < ac && kp1 == 0; i++) { | |||
| 1891 | MinusStep(kp1, s, Placev(a)[i], int0, kp1){ BIntD r_ = (BIntD)(((a)->placev)[i])+(BIntD)((((((unsigned long) 1) << ((8 * sizeof(BIntS)))) - 1) - (((int) 0))) )+(BIntD)(kp1); BIntS k_ = (r_ >= (BIntD) (((unsigned long ) 1) << ((8 * sizeof(BIntS))))); if (k_) r_ -= (((unsigned long) 1) << ((8 * sizeof(BIntS)))); (s) = r_; (kp1) = k_ ; }; | |||
| 1892 | Placev(r)((r)->placev)[i] = s; | |||
| 1893 | } | |||
| 1894 | ||||
| 1895 | if (kp1 == 1 && Beq(r,a)((r) == (a))) goto normalize; | |||
| 1896 | ||||
| 1897 | for ( ; i < ac; i++) { | |||
| 1898 | Placev(r)((r)->placev)[i] = Placev(a)((a)->placev)[i]; | |||
| 1899 | } | |||
| 1900 | ||||
| 1901 | assert(kp1 == 1)do { if (!(kp1 == 1)) _do_assert(("kp1 == 1"),"bigint.c",1901 ); } while (0); | |||
| 1902 | ||||
| 1903 | normalize: | |||
| 1904 | for (i = Placec(a)((a)->placec) - 1; i >= 0; i--) | |||
| 1905 | if (Placev(r)((r)->placev)[i] != 0) break; | |||
| 1906 | Placec(r)((r)->placec) = i+1; | |||
| 1907 | } | |||
| 1908 | ||||
| 1909 | /* | |||
| 1910 | * Multiply non-negative integers a and b and place result in preallocated r. | |||
| 1911 | * The result r, cannot be an alias for a or b. | |||
| 1912 | */ | |||
| 1913 | void | |||
| 1914 | iintTimes(BInt r, BInt a, BInt b) | |||
| 1915 | { | |||
| 1916 | IInt i, j, ac, bc; | |||
| 1917 | BIntS k, ai, bj; | |||
| 1918 | ||||
| 1919 | assert(!IsImmed(a) && !IsImmed(b))do { if (!(!((long)(a) & 1) && !((long)(b) & 1 ))) _do_assert(("!IsImmed(a) && !IsImmed(b)"),"bigint.c" ,1919); } while (0); | |||
| 1920 | assert(!IsNeg(a) && !IsNeg(b))do { if (!(!((a)->isNeg) && !((b)->isNeg))) _do_assert (("!IsNeg(a) && !IsNeg(b)"),"bigint.c",1920); } while (0); | |||
| 1921 | assert(!IsImmed(r) && Placea(r) >= Placec(a)+Placec(b))do { if (!(!((long)(r) & 1) && ((r)->placea) >= ((a)->placec)+((b)->placec))) _do_assert(("!IsImmed(r) && Placea(r) >= Placec(a)+Placec(b)" ),"bigint.c",1921); } while (0); | |||
| 1922 | ||||
| 1923 | ac = Placec(a)((a)->placec); | |||
| 1924 | bc = Placec(b)((b)->placec); | |||
| 1925 | ||||
| 1926 | /* Make a be the longer number to minimize loop cost. */ | |||
| 1927 | if (ac < bc) { | |||
| 1928 | BInt x; | |||
| 1929 | IInt xc; | |||
| 1930 | x = a; xc = ac; | |||
| 1931 | a = b; ac = bc; | |||
| 1932 | b = x; bc = xc; | |||
| 1933 | } | |||
| 1934 | ||||
| 1935 | for (i = 0; i < ac; i++) Placev(r)((r)->placev)[i] = 0; | |||
| 1936 | ||||
| 1937 | for (j = 0; j < bc; j++) { | |||
| 1938 | bj = Placev(b)((b)->placev)[j]; | |||
| 1939 | k = 0; | |||
| 1940 | if (bj != 0) { | |||
| 1941 | for (i = 0; i < ac; i++) { | |||
| 1942 | ai = Placev(a)((a)->placev)[i]; | |||
| 1943 | TimesStep(k, Placev(r)[i+j],{ BIntD t_ = (BIntD)(ai)*(BIntD)(bj)+(BIntD)(((r)->placev) [i+j])+(BIntD)(k); (((r)->placev)[i+j]) = t_ % (((unsigned long) 1) << ((8 * sizeof(BIntS)))); (k) = t_ / (((unsigned long) 1) << ((8 * sizeof(BIntS)))); } | |||
| 1944 | ai, bj, Placev(r)[i+j], k){ BIntD t_ = (BIntD)(ai)*(BIntD)(bj)+(BIntD)(((r)->placev) [i+j])+(BIntD)(k); (((r)->placev)[i+j]) = t_ % (((unsigned long) 1) << ((8 * sizeof(BIntS)))); (k) = t_ / (((unsigned long) 1) << ((8 * sizeof(BIntS)))); }; | |||
| 1945 | } | |||
| 1946 | } | |||
| 1947 | Placev(r)((r)->placev)[ac+j] = k; | |||
| 1948 | } | |||
| 1949 | while (Placec(r)((r)->placec) > 0 && Placev(r)((r)->placev)[Placec(r)((r)->placec)-1] == 0) Placec(r)((r)->placec)--; | |||
| 1950 | } | |||
| 1951 | ||||
| 1952 | ||||
| 1953 | /* | |||
| 1954 | * Divide the non-negative numbers a and b and place the quotient and | |||
| 1955 | * remainder in the preallocated structures q and r. | |||
| 1956 | * | |||
| 1957 | * The output structure, q, must have space for m+1 digits. | |||
| 1958 | * The output structure, r, must have space for n+m+1 digits | |||
| 1959 | * (unless n = 1 or a < b), even though at most n will be used for output. | |||
| 1960 | * | |||
| 1961 | * The output q may not be an alias for an input. | |||
| 1962 | * The output r can be an alias for the input a. | |||
| 1963 | * | |||
| 1964 | * This is Algorithm D of Knuth Vol 2, Section 4.3.1. | |||
| 1965 | * Note: we index the digits n-1..0 rather than 1..n. | |||
| 1966 | */ | |||
| 1967 | ||||
| 1968 | /* | |||
| 1969 | * Convert to Knuth's notation. | |||
| 1970 | */ | |||
| 1971 | #define KtoI(ki)(n - (ki)) (n - (ki)) | |||
| 1972 | #define KtoJu(kj)(nm - (kj)) (nm - (kj)) | |||
| 1973 | #define KtoJq(kj)(m - (kj)) (m - (kj)) | |||
| 1974 | #define DB /*Debug*/ | |||
| 1975 | ||||
| 1976 | void | |||
| 1977 | iintDivide(BInt q, BInt r, BInt u, BInt v) | |||
| 1978 | { | |||
| 1979 | IInt n, m, nm; | |||
| 1980 | IInt i; | |||
| 1981 | IInt ki, kj, kjj; /* Knuths i + j. */ | |||
| 1982 | BIntS d, qhat, rhat; | |||
| 1983 | BIntS v1, v2, uj0, uj1, uj2; /* Knuth's v1,v2, uj,uj+1,uj+2 */ | |||
| 1984 | BIntS k, kk, vi, ujj, uh, ul; | |||
| 1985 | ||||
| 1986 | assert(!IsImmed(u) && !IsImmed(v))do { if (!(!((long)(u) & 1) && !((long)(v) & 1 ))) _do_assert(("!IsImmed(u) && !IsImmed(v)"),"bigint.c" ,1986); } while (0); | |||
| 1987 | assert(!IsImmed(q) && !IsImmed(r))do { if (!(!((long)(q) & 1) && !((long)(r) & 1 ))) _do_assert(("!IsImmed(q) && !IsImmed(r)"),"bigint.c" ,1987); } while (0); | |||
| 1988 | assert(Placea(r) > Placec(u))do { if (!(((r)->placea) > ((u)->placec))) _do_assert (("Placea(r) > Placec(u)"),"bigint.c",1988); } while (0); | |||
| 1989 | assert(Placev(v)[Placec(v)-1] != 0)do { if (!(((v)->placev)[((v)->placec)-1] != 0)) _do_assert (("Placev(v)[Placec(v)-1] != 0"),"bigint.c",1989); } while (0 ); | |||
| 1990 | assert(q != r && q != u && q != v && r != v)do { if (!(q != r && q != u && q != v && r != v)) _do_assert(("q != r && q != u && q != v && r != v" ),"bigint.c",1990); } while (0); | |||
| 1991 | ||||
| 1992 | n = Placec(v)((v)->placec); | |||
| 1993 | m = Placec(u)((u)->placec) - n; | |||
| 1994 | nm = n + m; | |||
| 1995 | ||||
| 1996 | /* Copy u into r as an in-place work area. */ | |||
| 1997 | if (r != u) { | |||
| 1998 | for (i = 0; i < nm; i++) Placev(r)((r)->placev)[i] = Placev(u)((u)->placev)[i]; | |||
| 1999 | Placec(r)((r)->placec) = nm; | |||
| 2000 | u = r; | |||
| 2001 | } | |||
| 2002 | ||||
| 2003 | /* Trivial case: v has 1 digit. */ | |||
| 2004 | if (n == 1) { | |||
| 2005 | iintDivideS(q, &rhat, u, Placev(v)((v)->placev)[0]); | |||
| 2006 | Placev(u)((u)->placev)[0] = rhat; | |||
| 2007 | Placec(u)((u)->placec) = 1; | |||
| 2008 | return; | |||
| 2009 | } | |||
| 2010 | ||||
| 2011 | /* Trivial case: u < v => q = 0, r = u. */ | |||
| 2012 | if (bintLT(u,v)) { | |||
| 2013 | Placec(q)((q)->placec) = 0; | |||
| 2014 | return; | |||
| 2015 | } | |||
| 2016 | ||||
| 2017 | /* | |||
| 2018 | * D1. Normalize: choose d which results in v[n-1] >= BINT_RADIX/2. | |||
| 2019 | */ | |||
| 2020 | v1= Placev(v)((v)->placev)[KtoI(1)(n - (1))]; | |||
| 2021 | if (v1 >= BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS))))/2) { | |||
| 2022 | bintDEBUGif (!((int) 0)) { } else fprintf(dbOut, "**** d = 1 ****\n"); | |||
| 2023 | d = 1; | |||
| 2024 | } | |||
| 2025 | else { | |||
| 2026 | d = BINT_RADIX(((unsigned long) 1) << ((8 * sizeof(BIntS))))/(v1 + 1); | |||
| 2027 | iintTimesS(u, u, d); | |||
| 2028 | iintTimesS(v, v, d); /* Guaranteed ptr u != v */ | |||
| 2029 | } | |||
| 2030 | v1= Placev(v)((v)->placev)[KtoI(1)(n - (1))]; | |||
| 2031 | v2= Placev(v)((v)->placev)[KtoI(2)(n - (2))]; | |||
| 2032 | if (Placec(u)((u)->placec) == nm) { | |||
| 2033 | Placev(u)((u)->placev)[Placec(u)((u)->placec)++] = 0; | |||
| 2034 | } | |||
| 2035 | assert(Placec(u) == nm+1)do { if (!(((u)->placec) == nm+1)) _do_assert(("Placec(u) == nm+1" ),"bigint.c",2035); } while (0); | |||
| 2036 | assert(Placec(v) == n)do { if (!(((v)->placec) == n)) _do_assert(("Placec(v) == n" ),"bigint.c",2036); } while (0); | |||
| 2037 | ||||
| 2038 | /* | |||
| 2039 | * D2-D7. Each iter, divide u[kj..kj+n] by v[1..n] to get a digit of q. | |||
| 2040 | */ | |||
| 2041 | for (kj = 0; kj <= m; kj++) { | |||
| 2042 | /* | |||
| 2043 | * D3. Compute qhat. | |||
| 2044 | */ | |||
| 2045 | uj0 = Placev(u)((u)->placev)[KtoJu(kj)(nm - (kj))]; | |||
| 2046 | uj1 = Placev(u)((u)->placev)[KtoJu(kj+1)(nm - (kj+1))]; | |||
| 2047 | uj2 = Placev(u)((u)->placev)[KtoJu(kj+2)(nm - (kj+2))]; | |||
| 2048 | ||||
| 2049 | if (uj0 == v1) { | |||
| 2050 | bintDEBUGif (!((int) 0)) { } else fprintf(dbOut, "**** uj0 == v1 ****\n"); | |||
| 2051 | qhat = BINT_RADIX_MINUS_1((((unsigned long) 1) << ((8 * sizeof(BIntS)))) - 1); | |||
| 2052 | rhat = uj1; | |||
| 2053 | PlusStep(k, rhat, rhat, v1, int0){ BIntD r_ = (BIntD)(rhat)+(BIntD)(v1)+(BIntD)(((int) 0)); BIntS k_ = (r_ >= (BIntD) (((unsigned long) 1) << ((8 * sizeof (BIntS))))); if (k_) r_ -= (((unsigned long) 1) << ((8 * sizeof(BIntS)))); (rhat) = r_; (k) = k_; }; | |||
| 2054 | ||||
| 2055 | } | |||
| 2056 | else { | |||
| 2057 | DivideDouble(qhat, rhat, uj0, uj1, v1){ BIntD n_ = (BIntD)(uj0)*(BIntD)(((unsigned long) 1) << ((8 * sizeof(BIntS)))) + (uj1); BIntD d_ = (v1); (qhat) = n_ / d_; (rhat) = n_ % d_; }; | |||
| 2058 | k = 0; | |||
| 2059 | } | |||
| 2060 | if (!k) { | |||
| 2061 | BIntS v2qhh, v2qhl; | |||
| 2062 | Bool isGT; | |||
| 2063 | for (i = 1; ; i++) { | |||
| 2064 | /* Loop shd be evaluated no more than twice. */ | |||
| 2065 | if (DEBUG(bint)((int) 0)) { | |||
| 2066 | if (i == 2) | |||
| 2067 | fprintf(dbOut, "**** 2 ****\n"); | |||
| 2068 | } | |||
| 2069 | assert(i <= 2)do { if (!(i <= 2)) _do_assert(("i <= 2"),"bigint.c",2069 ); } while (0); | |||
| 2070 | /* | |||
| 2071 | * This test could be speeded up by doing | |||
| 2072 | * unsigned long arithmetic and a comparison | |||
| 2073 | * when BINT_LG_RADIX <= bitsizeof(long). | |||
| 2074 | * However by writing it this way, this code | |||
| 2075 | * could handle a long-sized radix. | |||
| 2076 | */ | |||
| 2077 | TimesDouble (v2qhh,v2qhl, v2, qhat){ BIntD t_ = (BIntD)(v2)*(BIntD)(qhat); (v2qhh) = t_ / (((unsigned long) 1) << ((8 * sizeof(BIntS)))); (v2qhl) = t_ % ((( unsigned long) 1) << ((8 * sizeof(BIntS)))); }; | |||
| 2078 | TestGTDouble(isGT, v2qhh,v2qhl, rhat,uj2){ BIntS h1_ = (v2qhh), h2_ = (rhat); (isGT) = (h1_ > h2_) || (h1_ == h2_ && (v2qhl)>(uj2)); }; | |||
| 2079 | ||||
| 2080 | if (!isGT) break; | |||
| 2081 | ||||
| 2082 | qhat--; | |||
| 2083 | PlusStep(k, rhat, rhat, v1, int0){ BIntD r_ = (BIntD)(rhat)+(BIntD)(v1)+(BIntD)(((int) 0)); BIntS k_ = (r_ >= (BIntD) (((unsigned long) 1) << ((8 * sizeof (BIntS))))); if (k_) r_ -= (((unsigned long) 1) << ((8 * sizeof(BIntS)))); (rhat) = r_; (k) = k_; }; | |||
| 2084 | if (k) break; | |||
| 2085 | } | |||
| 2086 | } | |||
| 2087 | if (DEBUG(bint)((int) 0)) { | |||
| 2088 | if (k) | |||
| 2089 | fprintf(dbOut, "**** rhat ov ****\n"); | |||
| 2090 | } | |||
| 2091 | ||||
| 2092 | /* | |||
| 2093 | * D4. Multiply and subtract: u[kj..kj+n] -= qhat * (0,v[1..n]) | |||
| 2094 | */ | |||
| 2095 | ||||
| 2096 | k = 0; | |||
| 2097 | ||||
| 2098 | for (ki = n, kjj = kj+n; ki >= 0; ki--, kjj--) { | |||
| 2099 | vi = (ki == 0) ? 0 : Placev(v)((v)->placev)[KtoI(ki)(n - (ki))]; | |||
| 2100 | ujj = Placev(u)((u)->placev)[KtoJu(kjj)(nm - (kjj))]; | |||
| 2101 | ||||
| 2102 | TimesDouble(uh, ul, qhat, vi){ BIntD t_ = (BIntD)(qhat)*(BIntD)(vi); (uh) = t_ / (((unsigned long) 1) << ((8 * sizeof(BIntS)))); (ul) = t_ % (((unsigned long) 1) << ((8 * sizeof(BIntS)))); }; | |||
| 2103 | ||||
| 2104 | MinusStep(kk, ujj, ujj, ul, 1){ BIntD r_ = (BIntD)(ujj)+(BIntD)((((((unsigned long) 1) << ((8 * sizeof(BIntS)))) - 1) - (ul)))+(BIntD)(1); BIntS k_ = ( r_ >= (BIntD) (((unsigned long) 1) << ((8 * sizeof(BIntS ))))); if (k_) r_ -= (((unsigned long) 1) << ((8 * sizeof (BIntS)))); (ujj) = r_; (kk) = k_; }; | |||
| 2105 | uh += !kk; | |||
| 2106 | ||||
| 2107 | MinusStep(kk, ujj, ujj, k, 1){ BIntD r_ = (BIntD)(ujj)+(BIntD)((((((unsigned long) 1) << ((8 * sizeof(BIntS)))) - 1) - (k)))+(BIntD)(1); BIntS k_ = ( r_ >= (BIntD) (((unsigned long) 1) << ((8 * sizeof(BIntS ))))); if (k_) r_ -= (((unsigned long) 1) << ((8 * sizeof (BIntS)))); (ujj) = r_; (kk) = k_; }; | |||
| 2108 | uh += !kk; | |||
| 2109 | ||||
| 2110 | Placev(u)((u)->placev)[KtoJu(kjj)(nm - (kjj))] = ujj; | |||
| 2111 | k = uh; | |||
| 2112 | } | |||
| 2113 | ||||
| 2114 | /* | |||
| 2115 | * D5. Set quotient digit and test remainder. | |||
| 2116 | */ | |||
| 2117 | Placev(q)((q)->placev)[KtoJq(kj)(m - (kj))] = qhat; /* I.e. Knuth's q[j] */ | |||
| 2118 | ||||
| 2119 | if (k != 0) { | |||
| 2120 | /* | |||
| 2121 | * D6. Add back: u[kj..kj+n] += (0,v[1..n]) | |||
| 2122 | */ | |||
| 2123 | bintDEBUGif (!((int) 0)) { } else fprintf(dbOut, "**** Add Back %d ****\n", k); | |||
| 2124 | Placev(q)((q)->placev)[KtoJq(kj)(m - (kj))]--; | |||
| 2125 | k = 0; | |||
| 2126 | ||||
| 2127 | for (ki = n, kjj = kj+n; ki >= 0; ki--, kjj--) { | |||
| 2128 | vi = (ki == 0) ? 0 : Placev(v)((v)->placev)[KtoI(ki)(n - (ki))]; | |||
| 2129 | ||||
| 2130 | PlusStep(k, Placev(u)[KtoJu(kjj)],{ BIntD r_ = (BIntD)(vi)+(BIntD)(((u)->placev)[(nm - (kjj) )])+(BIntD)(k); BIntS k_ = (r_ >= (BIntD) (((unsigned long ) 1) << ((8 * sizeof(BIntS))))); if (k_) r_ -= (((unsigned long) 1) << ((8 * sizeof(BIntS)))); (((u)->placev)[ (nm - (kjj))]) = r_; (k) = k_; } | |||
| 2131 | vi, Placev(u)[KtoJu(kjj)], k){ BIntD r_ = (BIntD)(vi)+(BIntD)(((u)->placev)[(nm - (kjj) )])+(BIntD)(k); BIntS k_ = (r_ >= (BIntD) (((unsigned long ) 1) << ((8 * sizeof(BIntS))))); if (k_) r_ -= (((unsigned long) 1) << ((8 * sizeof(BIntS)))); (((u)->placev)[ (nm - (kjj))]) = r_; (k) = k_; }; | |||
| 2132 | } | |||
| 2133 | } | |||
| 2134 | } | |||
| 2135 | ||||
| 2136 | /* | |||
| 2137 | * D8. Unnormalize: u /= d | |||
| 2138 | */ | |||
| 2139 | Placec(u)((u)->placec) = n; | |||
| 2140 | iintDivideS(u, NULL((void*)0), u, d); | |||
| 2141 | iintDivideS(v, NULL((void*)0), v, d); /* Return v to original state. */ | |||
| 2142 | ||||
| 2143 | /* Set place counts to not see leading zeros. */ | |||
| 2144 | for (i = Placec(q)((q)->placec)-1; i >= 0; i--) | |||
| 2145 | if (Placev(q)((q)->placev)[i] != 0) break; | |||
| 2146 | Placec(q)((q)->placec) = i+1; | |||
| 2147 | ||||
| 2148 | for (i = Placec(u)((u)->placec)-1; i >= 0; i--) | |||
| 2149 | if (Placev(u)((u)->placev)[i] != 0) break; | |||
| 2150 | Placec(u)((u)->placec) = i+1; | |||
| 2151 | } | |||
| 2152 | ||||
| 2153 | /* | |||
| 2154 | * iintShift(r, b, n) | |||
| 2155 | * Shift b by n bits into r; | |||
| 2156 | * The result, r, can be an alias for the argument b. | |||
| 2157 | * | |||
| 2158 | * Examples: | |||
| 2159 | * BINT_LG_RADIX = 4 | |||
| 2160 | * n -- number of bits shifted by | |||
| 2161 | * bitc -- bit count of result | |||
| 2162 | * c -- number of places | |||
| 2163 | * z -- number of zero bits in leading place | |||
| 2164 | * up -- whether position of bits in first place is further up | |||
| 2165 | * q -- upward rel offset of first place (not including chopped zeros) | |||
| 2166 | * q0 -- upward rel offset of first place (including phantom chopped zeros) | |||
| 2167 | * h -- upward rel offset of bits from previous place | |||
| 2168 | * k -- downard rel offset of bits within place | |||
| 2169 | * | |||
| 2170 | * n bitc c z up q q0 h k | |||
| 2171 | * .ooaa.bbbb.0000.0000. 8 14 4 2 n 2 2 4 0 | |||
| 2172 | * .0ooa.abbb.b000.0000. 7 13 4 3 n 2 2 3 1 | |||
| 2173 | * .aabb.bb00.0000. 6 12 3 0 y 1 2 2 2 | |||
| 2174 | * .oaab.bbb0.0000. 5 11 3 1 y 1 2 1 3 | |||
| 2175 | * .ooaa.bbbb.0000. 4 10 3 2 n 1 1 4 0 | |||
| 2176 | * .0ooa.abbb.b000. 3 9 3 3 n 1 1 3 1 | |||
| 2177 | * .aabb.bb00. 2 8 2 0 y 0 1 2 2 | |||
| 2178 | * .oaab.bbb0. 1 7 2 1 y 0 1 1 3 | |||
| 2179 | * .ooaa.bbbb. 0 6 2 2 n 0 0 4 0 | |||
| 2180 | * .0ooa.abbb. -1 5 2 3 n 0 0 3 1 | |||
| 2181 | * .aabb. -2 4 1 0 y -1 0 1 2 | |||
| 2182 | * .oaab. -3 3 1 1 y -1 0 3 1 | |||
| 2183 | * .ooaa. -4 2 1 2 n -1 -1 4 0 | |||
| 2184 | * .0ooa. -5 1 1 3 n -1 -1 3 1 | |||
| 2185 | * . -6 0 0 0 y -2 -1 2 2 | |||
| 2186 | */ | |||
| 2187 | ||||
| 2188 | void | |||
| 2189 | iintShift(BInt r, BInt b, int n) | |||
| 2190 | { | |||
| 2191 | IInt q, q0, h, k; | |||
| 2192 | IInt rbitc, rc, rz; | |||
| 2193 | IInt bbitc, bc, bz; | |||
| 2194 | Bool up; | |||
| 2195 | IInt i, j, x0, x1; | |||
| 2196 | BIntS *rp, *bp; | |||
| 2197 | ||||
| 2198 | assert(!IsImmed(r) && !IsImmed(b))do { if (!(!((long)(r) & 1) && !((long)(b) & 1 ))) _do_assert(("!IsImmed(r) && !IsImmed(b)"),"bigint.c" ,2198); } while (0); | |||
| 2199 | ||||
| 2200 | bbitc = bintLength(b); | |||
| 2201 | bc = Placec(b)((b)->placec); | |||
| 2202 | bz = bc * BINT_LG_RADIX((8 * sizeof(BIntS))) - bbitc; | |||
| 2203 | bp = Placev(b)((b)->placev); | |||
| 2204 | ||||
| 2205 | rbitc = bbitc + n; | |||
| 2206 | rc = QUO_ROUND_UP(rbitc, BINT_LG_RADIX)((rbitc) % (((8 * sizeof(BIntS)))) ? (rbitc)/(((8 * sizeof(BIntS )))) + 1 : (rbitc)/(((8 * sizeof(BIntS))))); | |||
| 2207 | rz = rc * BINT_LG_RADIX((8 * sizeof(BIntS))) - rbitc; | |||
| 2208 | rp = Placev(r)((r)->placev); | |||
| 2209 | ||||
| 2210 | assert(Placea(r) >= rc)do { if (!(((r)->placea) >= rc)) _do_assert(("Placea(r) >= rc" ),"bigint.c",2210); } while (0); | |||
| 2211 | Placec(r)((r)->placec) = rc; | |||
| 2212 | IsNeg(r)((r)->isNeg) = IsNeg(b)((b)->isNeg); | |||
| 2213 | ||||
| 2214 | up = (rz <= bz); | |||
| 2215 | q = rc - bc; | |||
| 2216 | q0 = q + up; | |||
| 2217 | h = q0 * BINT_LG_RADIX((8 * sizeof(BIntS))) - n; | |||
| 2218 | k = BINT_LG_RADIX((8 * sizeof(BIntS))) - h; | |||
| 2219 | x0 = 0; /* for lint */ | |||
| 2220 | ||||
| 2221 | /* | |||
| 2222 | * Copy in the direction which allows in-place operation. | |||
| 2223 | * | |||
| 2224 | * Each place's value is temporarily held in x0 until | |||
| 2225 | * it is certain that the original value of that place | |||
| 2226 | * will not be needed. | |||
| 2227 | */ | |||
| 2228 | ||||
| 2229 | /* | |||
| 2230 | * Would you believe that some compiler have trouble with x<<32 | |||
| 2231 | * MIPS cc on IRIX64 with -64 | |||
| 2232 | */ | |||
| 2233 | if (h == BINT_LG_RADIX((8 * sizeof(BIntS)))) h=0; | |||
| 2234 | if (n < 0) { | |||
| 2235 | /* Copy from lo to hi. */ | |||
| 2236 | bp -= q0; | |||
| 2237 | i = 0; | |||
| 2238 | j = 0; | |||
| 2239 | ||||
| 2240 | if (rc > 1) { | |||
| 2241 | x0 = h ? bp[i] >> h : 0; | |||
| 2242 | x0 |= bp[++i] << k; | |||
| ||||
| 2243 | } | |||
| 2244 | while (i < rc-1) { | |||
| 2245 | x1 = x0; | |||
| 2246 | x0 = h ? bp[i] >> h : 0 ; | |||
| 2247 | x0 |= bp[++i] << k; | |||
| 2248 | ||||
| 2249 | rp[j++] = x1 & BINT_RADIX_MASK((((unsigned long) 1) << ((8 * sizeof(BIntS)))) - 1); | |||
| 2250 | } | |||
| 2251 | if (rc > 1) | |||
| 2252 | rp[j++] = x0 & BINT_RADIX_MASK((((unsigned long) 1) << ((8 * sizeof(BIntS)))) - 1); | |||
| 2253 | if (up) { | |||
| 2254 | x0 = h ? bp[i] >> h : 0; | |||
| 2255 | x0 |= bp[++i] << k; | |||
| 2256 | } | |||
| 2257 | else { | |||
| 2258 | x0 = h ? bp[i] >> h : 0; | |||
| 2259 | } | |||
| 2260 | rp[j++] = x0 & BINT_RADIX_MASK((((unsigned long) 1) << ((8 * sizeof(BIntS)))) - 1); | |||
| 2261 | } | |||
| 2262 | else if (n > 0) { | |||
| 2263 | /* Copy from hi to lo. */ | |||
| 2264 | i = bc - 1; | |||
| 2265 | j = rc - 1; | |||
| 2266 | ||||
| 2267 | if (up) { | |||
| 2268 | x0 = bp[i--] << k; | |||
| 2269 | x0 |= h ? bp[i] >> h : 0; | |||
| 2270 | } | |||
| 2271 | else { | |||
| 2272 | x0 = h ? bp[i] >> h : 0; | |||
| 2273 | } | |||
| 2274 | while (i > 0) { | |||
| 2275 | x1 = x0; | |||
| 2276 | x0 = bp[i--] << k; | |||
| 2277 | x0 |= h ? bp[i] >> h : 0; | |||
| 2278 | ||||
| 2279 | rp[j--] = x1 & BINT_RADIX_MASK((((unsigned long) 1) << ((8 * sizeof(BIntS)))) - 1); | |||
| 2280 | } | |||
| 2281 | if (i == 0) { | |||
| 2282 | x1 = x0; | |||
| 2283 | x0 = bp[0] << k; | |||
| 2284 | rp[j--] = x1 & BINT_RADIX_MASK((((unsigned long) 1) << ((8 * sizeof(BIntS)))) - 1); | |||
| 2285 | } | |||
| 2286 | rp[j--] = x0 & BINT_RADIX_MASK((((unsigned long) 1) << ((8 * sizeof(BIntS)))) - 1); | |||
| 2287 | ||||
| 2288 | while (j >= 0) rp[j--] = 0; | |||
| 2289 | } | |||
| 2290 | else /* n == 0 */ { | |||
| 2291 | for (i = 0; i < rc; i++) rp[i] = bp[i]; | |||
| 2292 | } | |||
| 2293 | } | |||
| 2294 | ||||
| 2295 | /* | |||
| 2296 | * iintTimesS(r, a, b) | |||
| 2297 | * | |||
| 2298 | * Place the value a*b into r. | |||
| 2299 | * The result, r, can be an alias for the input a. | |||
| 2300 | */ | |||
| 2301 | void | |||
| 2302 | iintTimesS(BInt r, BInt a, BIntS b) | |||
| 2303 | { | |||
| 2304 | IInt n, j; | |||
| 2305 | BIntS c; | |||
| 2306 | ||||
| 2307 | assert(!IsImmed(r) && !IsImmed(a))do { if (!(!((long)(r) & 1) && !((long)(a) & 1 ))) _do_assert(("!IsImmed(r) && !IsImmed(a)"),"bigint.c" ,2307); } while (0); | |||
| 2308 | assert(Placea(r) >= Placea(a))do { if (!(((r)->placea) >= ((a)->placea))) _do_assert (("Placea(r) >= Placea(a)"),"bigint.c",2308); } while (0); | |||
| 2309 | ||||
| 2310 | /* !!! xintCopyInI may reallocate */ | |||
| 2311 | if (b == 0) { xintCopyInI(r, int0((int) 0)); return; } | |||
| 2312 | ||||
| 2313 | n = Placec(a)((a)->placec); | |||
| 2314 | c = 0; | |||
| 2315 | ||||
| 2316 | for (j = 0; j < n; j++) | |||
| 2317 | TimesStep(c, Placev(r)[j], Placev(a)[j], b, c, int0){ BIntD t_ = (BIntD)(((a)->placev)[j])*(BIntD)(b)+(BIntD)( c)+(BIntD)(((int) 0)); (((r)->placev)[j]) = t_ % (((unsigned long) 1) << ((8 * sizeof(BIntS)))); (c) = t_ / (((unsigned long) 1) << ((8 * sizeof(BIntS)))); }; | |||
| 2318 | ||||
| 2319 | if (c) Placev(r)((r)->placev)[j++] = c; | |||
| 2320 | Placec(r)((r)->placec) = j; | |||
| 2321 | } | |||
| 2322 | ||||
| 2323 | /* | |||
| 2324 | * iintTimesPlusS(r, a, b, c) | |||
| 2325 | * | |||
| 2326 | * Place the value a*b + c into r. | |||
| 2327 | * The result, r, can be an alias for the input a. | |||
| 2328 | */ | |||
| 2329 | void | |||
| 2330 | iintTimesPlusS(BInt r, BInt a, BIntS b, BIntS c) | |||
| 2331 | { | |||
| 2332 | IInt n, j; | |||
| 2333 | ||||
| 2334 | assert(!IsImmed(r) && !IsImmed(a))do { if (!(!((long)(r) & 1) && !((long)(a) & 1 ))) _do_assert(("!IsImmed(r) && !IsImmed(a)"),"bigint.c" ,2334); } while (0); | |||
| 2335 | assert(Placea(r) >= Placea(a))do { if (!(((r)->placea) >= ((a)->placea))) _do_assert (("Placea(r) >= Placea(a)"),"bigint.c",2335); } while (0); | |||
| 2336 | ||||
| 2337 | /* !!! xintCopyInI may reallocate */ | |||
| 2338 | if (b == 0) { xintCopyInI(r, c); return; } | |||
| 2339 | ||||
| 2340 | n = Placec(a)((a)->placec); | |||
| 2341 | ||||
| 2342 | for (j = 0; j < n; j++) | |||
| 2343 | TimesStep(c, Placev(r)[j], Placev(a)[j], b, c, int0){ BIntD t_ = (BIntD)(((a)->placev)[j])*(BIntD)(b)+(BIntD)( c)+(BIntD)(((int) 0)); (((r)->placev)[j]) = t_ % (((unsigned long) 1) << ((8 * sizeof(BIntS)))); (c) = t_ / (((unsigned long) 1) << ((8 * sizeof(BIntS)))); }; | |||
| 2344 | ||||
| 2345 | if (c) Placev(r)((r)->placev)[j++] = c; | |||
| 2346 | Placec(r)((r)->placec) = j; | |||
| 2347 | } | |||
| 2348 | ||||
| 2349 | /* | |||
| 2350 | * iintDivideS(q, &r, a, b) | |||
| 2351 | * | |||
| 2352 | * This divides the positive multiprecision number a by the half precision | |||
| 2353 | * number b, 0 < b < BINT_RADIX. | |||
| 2354 | * | |||
| 2355 | * The quotient is placed in q and the remainder in r. | |||
| 2356 | * If q == u, then the operation is done in-place. | |||
| 2357 | * | |||
| 2358 | * The result, q, can be an alias for a. | |||
| 2359 | */ | |||
| 2360 | void | |||
| 2361 | iintDivideS(BInt q, BIntS *pr, BInt a, BIntS b) | |||
| 2362 | { | |||
| 2363 | IInt n, j; | |||
| 2364 | BIntS r; | |||
| 2365 | ||||
| 2366 | assert(!IsImmed(q) && !IsImmed(a))do { if (!(!((long)(q) & 1) && !((long)(a) & 1 ))) _do_assert(("!IsImmed(q) && !IsImmed(a)"),"bigint.c" ,2366); } while (0); | |||
| 2367 | #ifndef BIGINT_SHHHH | |||
| 2368 | if (Placea(q)((q)->placea) < Placec(a)((a)->placec)) | |||
| 2369 | printf("This is it guys.\n"); | |||
| 2370 | #endif | |||
| 2371 | assert(Placea(q) >= Placec(a))do { if (!(((q)->placea) >= ((a)->placec))) _do_assert (("Placea(q) >= Placec(a)"),"bigint.c",2371); } while (0); | |||
| 2372 | ||||
| 2373 | n = Placec(a)((a)->placec); | |||
| 2374 | r = 0; | |||
| 2375 | for (j = n-1; j >= 0; j--) | |||
| 2376 | DivideDouble(Placev(q)[j], r, r, Placev(a)[j], b){ BIntD n_ = (BIntD)(r)*(BIntD)(((unsigned long) 1) << ( (8 * sizeof(BIntS)))) + (((a)->placev)[j]); BIntD d_ = (b) ; (((q)->placev)[j]) = n_ / d_; (r) = n_ % d_; }; | |||
| 2377 | ||||
| 2378 | Placec(q)((q)->placec) = (Placev(q)((q)->placev)[n-1] == 0) ? n-1 : n; | |||
| 2379 | if (pr) *pr = r; | |||
| 2380 | } | |||
| 2381 |