1 /// Multiple precision integers (Z). 2 module gmp.z; 3 4 import core.lifetime : move; 5 import std.traits : Unsigned, Unqual; // used by expression templates 6 7 /// Call version(gmp_test) unittests taking long to execute. 8 // version = version(gmp_test) unittestLong; 9 10 /// Is `true` if type `T` can be evaluated to a `MpZ` value. 11 enum isMpZExpr(T) = (is(Unqual!(typeof(T.eval())) == MpZ) || 12 is(Unqual!(typeof(T.eval())) == CopyableMpZ)); // which returns an `MpZ` 13 /// Is `true` if type `T` is lazy (not yet evaluated) `MpZ`-expression. 14 enum isLazyMpZExpr(T) = (!is(Unqual!T == MpZ) && // exclude direct value 15 isMpZExpr!T); 16 17 /** WordEndianess of serialization in `MpZ.serialize` and 18 unserialization-construction from integer array. 19 */ 20 enum WordEndianess { 21 host, 22 bigEndian, 23 littleEndian, 24 } 25 26 /** Word-order of serialization in `MpZ.serialize` and 27 unserialization-construction from integer array. 28 */ 29 enum WordOrder { 30 mostSignificantWordFirst, 31 leastSignificantWordFirst, 32 } 33 34 /** Rounding used in division variants `cdiv`, `fdiv` and `tdiv`. 35 36 TODO: Make use of. 37 */ 38 enum Rounding { 39 ceiling, ///< Used by functions named `..._cdiv_...` 40 floor, ///< Used by functions named `..._fdiv_...` 41 truncate ///< Used by functions named `..._tdiv_...` 42 } 43 44 // TODO: use these imports instead of the ones below 45 // import deimos.gmp.gmp; 46 // import deimos.gmp.integer; 47 48 /** Arbitrary (multi) precision signed integer (Z). 49 50 Wrapper for GNU MP (GMP)'s type `mpz_t` and functions `__gmpz_.*`. 51 52 If `cow` is `false` copying (via assignment and parameter passing by value) 53 is only possible explicitly via `.dup` (Rust-style) otherwise copying is 54 automatic and does copy-on-write (CoW) of the internal data via reference 55 counting (ARC) (Swift-style). 56 */ 57 private struct _Z(bool cow) { 58 /// Put `string` to sink in base `base`. 59 void toString(scope void delegate(scope const(char)[]) @safe sink, 60 in uint base = defaultBase, 61 in bool upperCaseDigits = false) const @trusted 62 in(((-2 <= base) && (base <= -36)) || 63 ((+2 <= base) && (base <= +62))) { 64 import core.memory : pureMalloc; 65 if (isZero) { return sink(`0`); } 66 if (isOne) { return sink(`1`); } 67 const size = sizeInBase(base); // NOTE: one too much for some values 68 scope char[] str = (cast(char*)pureMalloc(size + 1))[0 .. size + 1]; // one extra for minus sign 69 scope(exit) qualifiedFree(str.ptr); 70 sink(fillChars(str, base, upperCaseDigits)); 71 } 72 73 pure: 74 /** Needed below because `mpz_init_set_str` is currently the only way to 75 * construct from an array of characters. 76 */ 77 private enum smallBufSize = 1024; 78 79 /** Construct from `value` in base `base`. 80 81 If `base` is 0 it's guessed from contents of `value`. 82 */ 83 this(scope const(char)[] value, uint base = 0) @trusted // TODO: Use Optional/Nullable when value is nan, or inf 84 in(base == 0 || 85 (+2 <= base && base <= +62)) { 86 if (value.length >= 2 && 87 value[0] == '0' && 88 ((base == 16 && 89 (value[1] == 'x' || 90 value[1] == 'X')) || 91 (base == 2 && 92 (value[1] == 'b' || 93 value[1] == 'B')) || 94 (base == 8 && 95 (value[1] == 'o' || 96 value[1] == 'O')))) { 97 value = value[2 .. $]; // __gmpz_init_set_str doesn’t allow `"0x"` prefix if `base` given 98 } 99 char[smallBufSize] buf; 100 char* stringz; 101 import std.algorithm.searching : canFind; 102 if (value.length + 1 <= smallBufSize && 103 value[0] != '-' && // TODO: support minus sign 104 !value.canFind('_')) // TODO: support underscore 105 { 106 buf[0 .. value.length] = value; 107 buf[value.length] = '\0'; // null terminator 108 stringz = buf.ptr; 109 } else { 110 stringz = _allocStringzCopyOf(value); // TODO: append inline trailing zero if possible otherwise make this stack allocated 111 } 112 scope(exit) { 113 if (stringz != buf.ptr) 114 qualifiedFree(stringz); 115 } 116 immutable int status = __gmpz_init_set_str(_ptr, stringz, base); 117 import std.exception : enforce; 118 enforce(status == 0, "Parameter `value` does not contain an integer"); 119 } 120 121 static typeof(this) fromBinaryString(scope const(char)[] value) pure @safe { 122 return typeof(return)(value, 2); 123 } 124 125 static typeof(this) fromHexString(scope const(char)[] value) pure @safe { 126 return typeof(return)(value, 16); 127 } 128 129 nothrow: 130 131 /// Convert to `string` in base `base`. 132 string toString(in uint base = defaultBase, 133 in bool upperCaseDigits = false) scope const @trusted 134 in(((-2 <= base) && (base <= -36)) || 135 ((+2 <= base) && (base <= +62))) { 136 if (isZero) { return `0`; } 137 if (isOne) { return `1`; } 138 const size = sizeInBase(base); // NOTE: one too much for some values 139 char[] str = new char[](size + 1); // one extra for minus sign 140 __gmpz_get_str(str.ptr, base, _ptr); // fill it 141 return fillChars(str, base, upperCaseDigits); 142 } 143 144 /** Convert in base `base` into `chars` of length `length`. 145 146 Returns: char[] which must be freed manually with `pureFree` thereby 147 making this `@system`. 148 */ 149 char[] toChars(in uint base = defaultBase, 150 in bool upperCaseDigits = false) scope const @system @nogc 151 in(((-2 <= base) && (base <= -36)) || 152 ((+2 <= base) && (base <= +62))) { 153 import core.memory : pureMalloc; 154 if (isZero || isOne) { 155 char[] chars = (cast(char*)pureMalloc(1))[0 .. 1]; 156 if (isZero) 157 chars[0] = '0'; 158 else if (isOne) 159 chars[0] = '1'; 160 return chars; 161 } 162 const size = sizeInBase(base); // NOTE: one too much for some values 163 char[] chars = (cast(char*)pureMalloc(size + 1))[0 .. size + 1]; // one extra for minus sign 164 return fillChars(chars, base, upperCaseDigits); 165 } 166 167 private char[] fillChars(char[] chars, 168 in uint base = defaultBase, 169 in bool upperCaseDigits = false) const @system @nogc 170 in(((-2 <= base) && (base <= -36)) || 171 ((+2 <= base) && (base <= +62))) { 172 __gmpz_get_str(chars.ptr, base, _ptr); // fill it 173 import std.ascii : isAlphaNum, isLower, toUpper; 174 while (chars.length && 175 !chars[$ - 1].isAlphaNum) 176 chars = chars[0 .. $ - 1]; // skip trailing garbage 177 if (upperCaseDigits) 178 foreach (ref e; chars) 179 if (e.isLower) 180 e = e.toUpper; 181 return chars; 182 } 183 184 void toString(Writer)(ref Writer writer, // `mir.appender` compliant 185 in uint base = defaultBase, 186 in bool upperCaseDigits = false) const @nogc @trusted 187 if (is(typeof(writer.put((const(char)[]).init)))) { 188 import core.memory : pureFree; 189 if (isZero) { return writer.put("0"); } 190 if (isOne) { return writer.put("1"); } 191 auto chars = toChars(base, upperCaseDigits); 192 scope(exit) pureFree(chars.ptr); 193 writer.put(chars); 194 } 195 196 /// Get the unique hash of the `_Z` value suitable for use in a hash table. 197 size_t toHash() const @trusted { 198 import core.internal.hash : hashOf; 199 typeof(return) hash = limbCount; 200 foreach (immutable i; 0 .. limbCount) 201 hash ^= _limbs[i].hashOf; 202 return hash; 203 } 204 205 /** Serialize `this` into a new GC-allocated slice of words, each word of 206 type `Word`. 207 208 It's format defined by: 209 - `order`: the most significant word `first` or `last` for least significant first 210 - `endian` can be `bigEndian`, `littleEndian` or `host` default 211 - the most significant `nails` bits of each word are unused and set to zero, this can be 0 to produce full words 212 213 Returns: a new GC-allocated slice containing the words produced. 214 */ 215 Word[] serialize(Word)(WordOrder order, WordEndianess endian, size_t nails) const @trusted if (__traits(isUnsigned, Word)) { 216 const numb = 8 * Word.sizeof - nails; 217 size_t count = (__gmpz_sizeinbase(_ptr, 2) + numb-1) / numb; 218 return serialize(new Word[count], order, Word.sizeof, endian, nails); 219 } 220 221 @nogc: 222 223 /** No default construction for now, because `mpz_init` initialize 224 `__mpz_struct`-fields to non-zero values. 225 226 TODO: Allow default construction by delaying call to initialize(). 227 */ 228 // @disable this(); 229 230 /// Construct empty (undefined) from explicit `null`. 231 this(typeof(null)) @trusted { 232 pragma(inline, true); 233 initialize(); // TODO: is there a faster way? 234 assert(this == _Z.init); // if this is same as default 235 } 236 237 /// Construct from expression `expr`. 238 this(Expr)(Expr expr) if (isLazyMpZExpr!Expr) { 239 version(LDC) pragma(inline, true); 240 // TODO: ok to just assume zero-initialized contents at `_z` before... 241 this = expr; // ...calling this.opAssign ?x 242 } 243 244 /** Construct from `value`. */ 245 this(T)(T value) @trusted if (__traits(isArithmetic, T)) { 246 // TODO: add support for static initialization 247 // if (!__ctfe) 248 // { 249 pragma(inline, true); 250 251 static if (__traits(isUnsigned, T)) __gmpz_init_set_ui(_ptr, value); 252 else static if (__traits(isFloating, T)) __gmpz_init_set_d(_ptr, value); 253 else __gmpz_init_set_si(_ptr, value); // isSigned integral 254 // } 255 // else 256 // { 257 // if (value == 0) 258 // { 259 // reinterpret_to_size_if_sizeof_and_zero(); 260 // } 261 // else 262 // { 263 // assert(0, "Cannot set non-zero value at ctfe"); 264 // } 265 // } 266 } 267 268 /** Constucts number from serialized binary array. 269 270 Arguments: 271 - `rop` : array of unsinged values 272 - `order`: the most significant word `first` or `last` for least significant first 273 - `size` in bytes of each word 274 - `endian` can be `bigEndian`, `littleEndian` or `host` default 275 - the most significant `nails` bits of each word are unused and set to zero, this can be 0 to produce full words 276 */ 277 this(T)(const T[] rop, WordOrder order, size_t size, WordEndianess endian, size_t nails) if (__traits(isUnsigned, T)) { 278 int realOrder; 279 final switch(order) { 280 case WordOrder.mostSignificantWordFirst: realOrder = 1; break; 281 case WordOrder.leastSignificantWordFirst: realOrder = -1; break; 282 } 283 int realEndian; 284 final switch(endian) { 285 case WordEndianess.littleEndian: realEndian = -1; break; 286 case WordEndianess.bigEndian: realEndian = 1; break; 287 case WordEndianess.host: realEndian = 0; break; 288 } 289 __gmpz_init(_ptr); 290 __gmpz_import(_ptr, rop.length, realOrder, size, realEndian, nails, rop.ptr); 291 } 292 293 /// Mersenne prime, M(p) = 2 ^^ p - 1 294 static _Z mersennePrime(Integral)(Integral p) if (__traits(isIntegral, Integral)) { 295 version(LDC) pragma(inline, true); 296 return typeof(this).pow(2UL, p) - 1; 297 } 298 299 /** 300 * Checks if the number is probably a prime using a probabilistic primality test. 301 * 302 * It performs a specified number of Miller-Rabin probabilistic tests to determine the 303 * primality of the `MpZ` instance. 304 * 305 * Params: 306 * - repetitionCount: The number of Miller-Rabin tests to perform. A higher value 307 * increases the certainty of the result for a composite number. 308 * 309 * Returns: An integer representing the test result: 310 * - **0**: The number is definitely composite. 311 * - **1**: The number is probably prime. 312 * - **2**: The number is definitely prime. 313 * 314 * See Also: `mpz_probab_prime_p`. 315 */ 316 @property int isProbablyPrime(in int repetitionCount = 25) @trusted { 317 version(LDC) pragma(inline, true); 318 return __gmpz_probab_prime_p(_ptr, repetitionCount); 319 } 320 321 /** Checks if the number is definitely a prime using a probabilistic primality test. 322 Returns: `true` if `this` is a prime, `false` if computation could determine. 323 */ 324 @property bool isDefinitelyPrime(in int repetitionCount = 25) @trusted { 325 return isProbablyPrime(repetitionCount) == 2; 326 } 327 328 // /// Construct copy of `value`. 329 // this(ref const _Z value) @trusted 330 // { 331 // __gmpz_init_set(_ptr, value._ptr); 332 // } 333 334 // /// Construct copy of `value`. 335 // this(_Z value) @trusted 336 // { 337 // import core.lifetime : moveEmplace; 338 // moveEmplace(value, this); // fast 339 // } 340 341 static if (cow) { 342 void selfdupIfAliased() scope pure nothrow @nogc @safe { 343 pragma(inline, true); 344 if (_refCountCopies >= 1) 345 this = this.dup(); 346 } 347 this(this) scope pure nothrow @nogc @safe { 348 pragma(inline, true); 349 _refCountCopies += 1; 350 } 351 } else { 352 @disable this(this); 353 } 354 355 /// Swap content of `this` with `rhs`. 356 void swap()(ref _Z rhs) pure nothrow @nogc @safe { 357 pragma(inline, true); 358 import std.algorithm.mutation : swap; 359 swap(this, rhs); // faster than __gmpz_swap(_ptr, rhs._ptr); 360 } 361 362 /// (Duplicate) Copy `this`. 363 _Z dup() scope const pure nothrow @trusted { 364 version(LDC) pragma(inline, true); 365 typeof(return) y = void; 366 __gmpz_init_set(y._ptr, _ptr); 367 static if (cow) { y._refCountCopies = 0; } 368 return y; 369 } 370 371 /// Assign from `rhs`. 372 ref _Z opAssign()(auto ref scope const _Z rhs) scope return @trusted { 373 version(LDC) pragma(inline, true); 374 static if (cow) { selfdupIfAliased(); } 375 __gmpz_set(_ptr, rhs._ptr); 376 return this; 377 } 378 /// ditto 379 ref _Z opAssign(Expr)(auto ref Expr rhs) scope return @trusted if (isLazyMpZExpr!Expr) { 380 version(LDC) pragma(inline, true); 381 rhs.evalTo(this); 382 return this; 383 } 384 /// ditto 385 ref _Z opAssign(T)(T rhs) scope return @trusted if (__traits(isArithmetic, T)) { 386 version(LDC) pragma(inline, true); 387 assertInitialized(); 388 static if (cow) { selfdupIfAliased(); } 389 static if (__traits(isUnsigned, T)) __gmpz_set_ui(_ptr, rhs); 390 else static if (__traits(isFloating, T)) __gmpz_set_d(_ptr, rhs); 391 else static if (__traits(isArithmetic, T) && !__traits(isUnsigned, T)) __gmpz_set_si(_ptr, rhs); 392 else static assert(0); 393 return this; 394 } 395 396 /** Assign `this` from `string` `rhs` interpreted in base `base`. 397 If `base` is 0 it's guessed from contents of `value`. 398 */ 399 ref _Z fromString(scope const(char)[] rhs, uint base = 0) scope return @trusted { 400 assert(base == 0 || (base >= 2 && base <= 62)); 401 static if (cow) { selfdupIfAliased(); } 402 char* stringz = _allocStringzCopyOf(rhs); 403 immutable int status = __gmpz_set_str(_ptr, stringz, base); 404 qualifiedFree(stringz); 405 assert(status == 0, "Parameter `rhs` does not contain an integer"); 406 return this; 407 } 408 409 /// Destruct `this`. 410 ~this() scope @nogc @trusted { 411 version(LDC) pragma(inline, true); 412 if (_z._mp_d) { 413 static if (cow) { 414 if (_refCountCopies >= 1) { 415 _z._mp_d = null; // prevent GC from scanning this memory 416 return; 417 } 418 } 419 __gmpz_clear(_ptr); 420 _z._mp_d = null; // prevent GC from scanning this memory 421 } 422 } 423 424 /// Returns: `true` iff `this` equals `rhs`. 425 bool opEquals()(auto ref scope const _Z rhs) const @trusted { 426 version(LDC) pragma(inline, true); 427 if (_ptr == rhs._ptr) // fast equality 428 return true; // fast bailout 429 return __gmpz_cmp(_ptr, rhs._ptr) == 0; 430 } 431 /// ditto 432 bool opEquals(Rhs)(Rhs rhs) const @trusted if (__traits(isArithmetic, Rhs)) { 433 version(LDC) pragma(inline, true); 434 if (rhs == 0) 435 return isZero; // optimization 436 if (rhs == 1) 437 return isOne; // optimization 438 static if (__traits(isUnsigned, Rhs)) return __gmpz_cmp_ui(_ptr, cast(ulong)rhs) == 0; 439 else static if (__traits(isFloating, Rhs)) return __gmpz_cmp_d(_ptr, cast(double)rhs) == 0; // TODO: correct to do this cast here? 440 else return __gmpz_cmp_si(_ptr, cast(long)rhs) == 0; // isSigned integral 441 } 442 443 /// Compare `this` to `rhs`. 444 int opCmp()(auto ref scope const _Z rhs) const @trusted { 445 version(LDC) pragma(inline, true); 446 if (rhs == 0) 447 return sgn(); // optimization 448 return __gmpz_cmp(_ptr, rhs._ptr); 449 } 450 /// ditto 451 int opCmp(T)(T rhs) const @trusted if (__traits(isArithmetic, T)) { 452 pragma(inline, true); 453 if (rhs == 0) 454 return sgn(); // optimization 455 static if (__traits(isUnsigned, T)) return __gmpz_cmp_ui(_ptr, rhs); 456 else static if (__traits(isFloating, T)) return __gmpz_cmp_d(_ptr, rhs); 457 else return __gmpz_cmp_si(_ptr, rhs); // isSigned integral 458 } 459 460 /// Cast to `bool`. 461 bool opCast(T : bool)() scope const { 462 pragma(inline, true); 463 return !isZero; 464 } 465 466 /// Cast to arithmetic type `T`. 467 T opCast(T)() scope const @trusted if (__traits(isArithmetic, T)) { 468 pragma(inline, true); 469 static if (__traits(isUnsigned, T)) return cast(T)__gmpz_get_ui(_ptr); 470 else static if (__traits(isFloating, T)) return cast(T)__gmpz_get_d(_ptr); 471 else return cast(T)__gmpz_get_si(_ptr); // isSigned integral 472 } 473 474 /** Get the value of this as a `long`, or +/- `long.max` if outside the 475 representable range. */ 476 long toLong() scope const @trusted { 477 version(LDC) pragma(inline, true); 478 // TODO: can probably be optimized 479 if (this <= long.min) 480 return long.min; 481 else if (this >= long.max) 482 return long.max; 483 else 484 return cast(long)__gmpz_get_si(_ptr); 485 } 486 487 /** Get the value of this as a `int`, or +/- `int.max` if outside the 488 representable range. 489 */ 490 int toInt() const @trusted { 491 version(LDC) pragma(inline, true); 492 // TODO: can probably be optimized 493 if (this <= int.min) 494 return int.min; 495 else if (this >= int.max) 496 return int.max; 497 else 498 return cast(int)__gmpz_get_si(_ptr); 499 } 500 501 /** Get `this` `s` `rhs`. */ 502 _Z opBinary(string s)(auto ref scope const _Z rhs) const @trusted // direct value 503 if ((s == "+" || s == "-" || 504 s == "*" || s == "/" || s == "%" || 505 s == "&" || s == "|" || s == "^" || 506 s == "<<" || s == ">>")) { 507 version(LDC) pragma(inline, true); 508 static if (!__traits(isRef, rhs)) // r-value `rhs` 509 { 510 _Z* mut_rhs = (cast(_Z*)(&rhs)); // @trusted because `_Z` has no aliased indirections 511 static if (s == "+") __gmpz_add(mut_rhs._ptr, _ptr, rhs._ptr); 512 else static if (s == "-") __gmpz_sub(mut_rhs._ptr, _ptr, rhs._ptr); 513 else static if (s == "*") __gmpz_mul(mut_rhs._ptr, _ptr, rhs._ptr); 514 else static if (s == "/") 515 { 516 assert(rhs != 0, "Divison by zero"); 517 __gmpz_tdiv_q(mut_rhs._ptr, _ptr, rhs._ptr); 518 } 519 else static if (s == "%") 520 { 521 assert(rhs != 0, "Divison by zero"); 522 const neg = rhs.isNegative; 523 __gmpz_mod(mut_rhs._ptr, _ptr, rhs._ptr); 524 if (neg) 525 mut_rhs.negate(); 526 } 527 else static if (s == "&") __gmpz_and(mut_rhs._ptr, _ptr, rhs._ptr); 528 else static if (s == "|") __gmpz_ior(mut_rhs._ptr, _ptr, rhs._ptr); 529 else static if (s == "^") __gmpz_xor(mut_rhs._ptr, _ptr, rhs._ptr); 530 else static if (s == "<<") 531 { 532 if (rhs.isPositive()) 533 __gmpz_mul_2exp(mut_rhs._ptr, _ptr, cast(mp_bitcnt_t)rhs); 534 else 535 __gmpz_tdiv_q_2exp(mut_rhs._ptr, _ptr, cast(mp_bitcnt_t)-rhs); // `z << -1` becomes `z >> 1` 536 } 537 else static if (s == ">>") 538 { 539 if (rhs.isPositive()) 540 __gmpz_tdiv_q_2exp(mut_rhs._ptr, _ptr, cast(mp_bitcnt_t)rhs); 541 else 542 __gmpz_mul_2exp(mut_rhs._ptr, _ptr, cast(mp_bitcnt_t)-rhs); // `z >> -1` becomes `z << 1` 543 } 544 else static assert(0); 545 return move(*mut_rhs); // TODO: shouldn't have to call `move` here 546 } else { 547 typeof(return) y = null; 548 static if (s == "+") __gmpz_add(y._ptr, _ptr, rhs._ptr); 549 else static if (s == "-") __gmpz_sub(y._ptr, _ptr, rhs._ptr); 550 else static if (s == "*") __gmpz_mul(y._ptr, _ptr, rhs._ptr); 551 else static if (s == "/") { 552 assert(rhs != 0, "Divison by zero"); 553 __gmpz_tdiv_q(y._ptr, _ptr, rhs._ptr); 554 } else static if (s == "%") { 555 assert(rhs != 0, "Divison by zero"); 556 const neg = rhs.isNegative; 557 __gmpz_mod(y._ptr, _ptr, rhs._ptr); 558 if (neg) 559 y.negate(); 560 } 561 else static if (s == "&") __gmpz_and(y._ptr, _ptr, rhs._ptr); 562 else static if (s == "|") __gmpz_ior(y._ptr, _ptr, rhs._ptr); 563 else static if (s == "^") __gmpz_xor(y._ptr, _ptr, rhs._ptr); 564 else static if (s == "<<") { 565 if (rhs.isPositive()) 566 __gmpz_mul_2exp(y._ptr, _ptr, cast(mp_bitcnt_t)rhs); 567 else 568 __gmpz_tdiv_q_2exp(y._ptr, _ptr, cast(mp_bitcnt_t)-rhs); // `z << -1` becomes `z >> 1` 569 } else static if (s == ">>") { 570 if (rhs.isPositive()) 571 __gmpz_tdiv_q_2exp(y._ptr, _ptr, cast(mp_bitcnt_t)rhs); 572 else 573 __gmpz_mul_2exp(y._ptr, _ptr, cast(mp_bitcnt_t)-rhs); // `z >> -1` becomes `z << 1` 574 } 575 else static assert(0); 576 return y; 577 } 578 } 579 580 /// ditto 581 _Z opBinary(string s, Rhs)(auto ref const Rhs rhs) const if (isLazyMpZExpr!Rhs && // lazy value 582 (s == "+" || s == "-" || s == "*" || s == "/" || s == "%")) { 583 pragma(inline, true); 584 static assert(false, "TODO"); 585 } 586 587 /// ditto 588 _Z opBinary(string s, Rhs)(Rhs rhs) const @trusted 589 if ((s == "+" || s == "-" || s == "*" || s == "/" /* || s == "%"*/ || s == "^^" || s == "<<" || s == ">>") && __traits(isUnsigned, Rhs)) { 590 version(LDC) pragma(inline, true); 591 typeof(return) y = null; 592 static if (s == "+") __gmpz_add_ui(y._ptr, _ptr, rhs); 593 else static if (s == "-") __gmpz_sub_ui(y._ptr, _ptr, rhs); 594 else static if (s == "*") __gmpz_mul_ui(y._ptr, _ptr, rhs); 595 else static if (s == "/") { 596 assert(rhs != 0, "Divison by zero"); 597 __gmpz_tdiv_q_ui(y._ptr, _ptr, rhs); 598 } 599 // NOTE: handled by call to `mpz_tdiv_r_ui` below 600 // else static if (s == "%") 601 // { 602 // assert(rhs != 0, "Divison by zero"); 603 // __gmpz_mod_ui(y._ptr, _ptr, rhs); 604 // } 605 else static if (s == "^^") __gmpz_pow_ui(y._ptr, _ptr, rhs); 606 else static if (s == "<<") __gmpz_mul_2exp(y._ptr, _ptr, rhs); 607 else static if (s == ">>") __gmpz_tdiv_q_2exp(y._ptr, _ptr, rhs); 608 else static assert(0); 609 return y; 610 } 611 612 /// ditto 613 _Z opBinary(string s, Rhs)(Rhs rhs) const @trusted 614 if ((s == "+" || s == "-" || s == "*" || s == "/" || s == "^^" || s == "<<" || s == ">>") && 615 __traits(isArithmetic, Rhs) && !__traits(isUnsigned, Rhs)) { 616 version(LDC) pragma(inline, true); 617 typeof(return) y = null; 618 static if (s == "+") { 619 if (rhs < 0) // TODO: handle `rhs == rhs.min` 620 { 621 immutable ulong pos_rhs = -rhs; // make it positive 622 __gmpz_sub_ui(y._ptr, _ptr, pos_rhs); 623 } 624 else 625 __gmpz_add_ui(y._ptr, _ptr, rhs); 626 } else static if (s == "-") { 627 if (rhs < 0) // TODO: handle `rhs == rhs.min` 628 __gmpz_add_ui(y._ptr, _ptr, -rhs); // x - (-y) == x + y 629 else 630 __gmpz_sub_ui(y._ptr, _ptr, rhs); // rhs is positive 631 } else static if (s == "*") { 632 __gmpz_mul_si(y._ptr, _ptr, rhs); 633 } else static if (s == "/") { 634 assert(rhs != 0, "Divison by zero"); 635 if (rhs < 0) // TODO: handle `rhs == rhs.min` 636 { 637 immutable ulong pos_rhs = -rhs; // make it positive 638 __gmpz_tdiv_q_ui(y._ptr, _ptr, pos_rhs); 639 y.negate(); // negate result 640 } else 641 __gmpz_tdiv_q_ui(y._ptr, _ptr, rhs); 642 } else static if (s == "^^") { 643 assert(rhs >= 0, "TODO: Negative power exponent needs MpQ return"); 644 __gmpz_pow_ui(y._ptr, _ptr, rhs); 645 } else static if (s == "<<") { 646 if (rhs >= 0) 647 __gmpz_mul_2exp(y._ptr, _ptr, rhs); 648 else 649 __gmpz_tdiv_q_2exp(y._ptr, _ptr, -rhs); // `z << -1` becomes `z >> 1` 650 } else static if (s == ">>") { 651 if (rhs >= 0) 652 __gmpz_tdiv_q_2exp(y._ptr, _ptr, rhs); 653 else 654 __gmpz_mul_2exp(y._ptr, _ptr, -rhs); // `z >> -1` becomes `z << 1` 655 } 656 else static assert(0); 657 return y; 658 } 659 660 /// Remainer propagates modulus type. 661 Unqual!Rhs opBinary(string s, Rhs)(Rhs rhs) const @trusted 662 if ((s == "%") && __traits(isIntegral, Rhs)) { 663 version(LDC) pragma(inline, true); 664 assert(rhs != 0, "Divison by zero"); 665 _Z y = null; 666 static if (__traits(isArithmetic, Rhs) && !__traits(isUnsigned, Rhs)) { 667 if (rhs < 0) // TODO: handle `rhs == rhs.min` 668 { 669 immutable ulong pos_rhs = -cast(int)rhs; // make it positive 670 return cast(typeof(return))-__gmpz_tdiv_r_ui(y._ptr, _ptr, pos_rhs); 671 } 672 else 673 return cast(typeof(return))__gmpz_tdiv_r_ui(y._ptr, _ptr, rhs); 674 } else static if (__traits(isUnsigned, Rhs)) 675 return cast(typeof(return))__gmpz_tdiv_r_ui(y._ptr, _ptr, rhs); 676 else 677 static assert(0); 678 } 679 680 /// Get an unsigned type `lhs` divided by `this`. 681 _Z opBinaryRight(string s, Lhs)(Lhs lhs) const @trusted 682 if ((s == "+" || s == "-" || s == "*" || s == "%") && __traits(isUnsigned, Lhs)) { 683 version(LDC) pragma(inline, true); 684 typeof(return) y = null; 685 static if (s == "+") 686 __gmpz_add_ui(y._ptr, _ptr, lhs); // commutative 687 else static if (s == "-") 688 __gmpz_ui_sub(y._ptr, lhs, _ptr); 689 else static if (s == "*") 690 __gmpz_mul_ui(y._ptr, _ptr, lhs); // commutative 691 else static if (s == "%") { 692 assert(this != 0, "Divison by zero"); 693 __gmpz_tdiv_r(y._ptr, _Z(lhs)._ptr, _ptr); // convert `lhs` to _Z 694 } else 695 static assert(0); 696 return y; 697 } 698 699 /// Get a signed type `lhs` divided by `this`. 700 _Z opBinaryRight(string s, Lhs)(Lhs lhs) const @trusted 701 if ((s == "+" || s == "-" || s == "*" || s == "%") && 702 __traits(isArithmetic, Lhs) && !__traits(isUnsigned, Lhs)) { 703 version(LDC) pragma(inline, true); 704 static if (s == "+" || s == "*") { 705 return opBinary!s(lhs); // commutative reuse 706 } else static if (s == "-") { 707 typeof(return) y = null; 708 if (lhs < 0) // TODO: handle `lhs == lhs.min` 709 { 710 immutable ulong pos_rhs = -lhs; // make it positive 711 __gmpz_add_ui(y._ptr, _ptr, pos_rhs); 712 } else 713 __gmpz_sub_ui(y._ptr, _ptr, lhs); 714 y.negate(); 715 return y; 716 } else static if (s == "%") { 717 typeof(return) y = null; 718 assert(this != 0, "Divison by zero"); 719 __gmpz_tdiv_r(y._ptr, _Z(lhs)._ptr, _ptr); // convert `lhs` to _Z 720 return y; 721 } else 722 static assert(0); 723 } 724 725 /// Dividend propagates quotient type to signed. 726 Unqual!Lhs opBinaryRight(string s, Lhs)(Lhs lhs) const @trusted 727 if ((s == "/") && __traits(isIntegral, Lhs)) { 728 version(LDC) pragma(inline, true); 729 _Z y = null; // TODO: avoid if !__traits(isRef, this) 730 assert(this != 0, "Divison by zero"); 731 __gmpz_tdiv_q(y._ptr, _Z(lhs)._ptr, _ptr); 732 static if (__traits(isArithmetic, Lhs) && !__traits(isUnsigned, Lhs)) 733 return cast(typeof(return))y; 734 else static if (__traits(isUnsigned, Lhs)) { 735 import std.traits : Signed; 736 return cast(Signed!(typeof(return)))y; 737 } else 738 static assert(0); 739 } 740 741 /// Exponentation. 742 _Z opBinaryRight(string s, Base)(Base base) const 743 if ((s == "^^") && __traits(isIntegral, Base)) { 744 pragma(inline, true); 745 static assert(false, "Convert `this _Z` exponent to `ulong` and calculate power via static method `pow()`"); 746 // _Z exp = null; 747 // __gmpz_pow(); 748 // return exp; 749 } 750 751 /// Operate-assign to `this` from `rhs`. 752 ref _Z opOpAssign(string s)(auto ref scope const _Z rhs) scope return @trusted 753 if ((s == "+" || s == "-" || 754 s == "*" || s == "/" || s == "%" || 755 s == "&" || s == "|" || s == "^" || 756 s == "<<" || s == ">>")) 757 { 758 version(LDC) pragma(inline, true); 759 static if (s == "+") 760 __gmpz_add(_ptr, _ptr, rhs._ptr); 761 else static if (s == "-") 762 __gmpz_sub(_ptr, _ptr, rhs._ptr); 763 else static if (s == "*") { 764 if (rhs == -1) 765 negate(); 766 else 767 __gmpz_mul(_ptr, _ptr, rhs._ptr); 768 } else static if (s == "/") { 769 assert(rhs != 0, "Divison by zero"); 770 if (rhs == -1) 771 negate(); 772 else 773 __gmpz_tdiv_q(_ptr, _ptr, rhs._ptr); 774 } else static if (s == "%") { 775 assert(rhs != 0, "Divison by zero"); 776 __gmpz_tdiv_r(_ptr, _ptr, rhs._ptr); 777 } else static if (s == "&") 778 __gmpz_and(_ptr, _ptr, rhs._ptr); 779 else static if (s == "|") 780 __gmpz_ior(_ptr, _ptr, rhs._ptr); 781 else static if (s == "^") 782 __gmpz_xor(_ptr, _ptr, rhs._ptr); 783 else static if (s == "<<") { 784 if (rhs.isPositive()) 785 __gmpz_mul_2exp(_ptr, _ptr, cast(mp_bitcnt_t)rhs); 786 else 787 __gmpz_tdiv_q_2exp(_ptr, _ptr, cast(mp_bitcnt_t)rhs); // `z << -1` becomes `z >> 1` 788 } else static if (s == ">>") { 789 if (rhs.isPositive()) 790 __gmpz_tdiv_q_2exp(_ptr, _ptr, cast(mp_bitcnt_t)rhs); 791 else 792 __gmpz_mul_2exp(_ptr, _ptr, cast(mp_bitcnt_t)rhs); // `z >> -1` becomes `z << 1` 793 } else 794 static assert(0); 795 return this; 796 } 797 798 /// ditto 799 ref _Z opOpAssign(string s, Rhs)(Rhs rhs) scope return @trusted 800 if ((s == "+" || s == "-" || s == "*" || s == "/" || s == "%" || s == "^^" || s == "<<" || s == ">>") && __traits(isUnsigned, Rhs)) { 801 version(LDC) pragma(inline, true); 802 static if (s == "+") 803 __gmpz_add_ui(_ptr, _ptr, rhs); 804 else static if (s == "-") 805 __gmpz_sub_ui(_ptr, _ptr, rhs); 806 else static if (s == "*") 807 __gmpz_mul_ui(_ptr, _ptr, rhs); 808 else static if (s == "/") { 809 assert(rhs != 0, "Divison by zero"); 810 __gmpz_tdiv_q_ui(_ptr, _ptr, rhs); 811 } else static if (s == "%") { 812 assert(rhs != 0, "Divison by zero"); 813 const _ = __gmpz_tdiv_r_ui(_ptr, _ptr, rhs); 814 } else static if (s == "^^") 815 __gmpz_pow_ui(_ptr, _ptr, rhs); 816 else static if (s == "<<") 817 __gmpz_mul_2exp(_ptr, _ptr, rhs); 818 else static if (s == ">>") 819 __gmpz_tdiv_q_2exp(_ptr, _ptr, rhs); 820 else 821 static assert(0); 822 return this; 823 } 824 825 /// ditto 826 ref _Z opOpAssign(string s, Rhs)(Rhs rhs) scope return @trusted 827 if ((s == "+" || s == "-" || s == "*" || s == "/" || s == "%" || s == "^^" || s == "<<" || s == ">>") && 828 __traits(isArithmetic, Rhs) && !__traits(isUnsigned, Rhs)) 829 { 830 version(LDC) pragma(inline, true); 831 static if (s == "+") { 832 if (rhs < 0) // TODO: handle `rhs == rhs.min` 833 { 834 assert(rhs != rhs.min); 835 immutable ulong pos_rhs = -rhs; // make it positive 836 __gmpz_sub_ui(_ptr, _ptr, pos_rhs); 837 } 838 else 839 __gmpz_add_ui(_ptr, _ptr, rhs); 840 } else static if (s == "-") { 841 if (rhs < 0) // TODO: handle `rhs == rhs.min` 842 { 843 assert(rhs != rhs.min); 844 immutable ulong pos_rhs = -rhs; // make it positive 845 __gmpz_add_ui(_ptr, _ptr, pos_rhs); 846 } else 847 __gmpz_sub_ui(_ptr, _ptr, rhs); 848 } else static if (s == "*") { 849 if (rhs == -1) 850 negate(); // optimization 851 else 852 __gmpz_mul_si(_ptr, _ptr, rhs); 853 } else static if (s == "/") { 854 assert(rhs != 0, "Divison by zero"); 855 if (rhs < 0) // TODO: handle `rhs == rhs.min` 856 { 857 immutable ulong pos_rhs = -rhs; // make it positive 858 __gmpz_tdiv_q_ui(_ptr, _ptr, pos_rhs); 859 negate(); 860 } else 861 __gmpz_tdiv_q_ui(_ptr, _ptr, rhs); 862 } else static if (s == "%") { 863 assert(rhs != 0, "Divison by zero"); 864 __gmpz_tdiv_r_ui(_ptr, _ptr, rhs); 865 } else static if (s == "^^") { 866 assert(rhs >= 0, "Negative exponent"); 867 __gmpz_pow_ui(_ptr, _ptr, rhs); 868 } else static if (s == "<<") { 869 if (rhs >= 0) 870 __gmpz_mul_2exp(_ptr, _ptr, rhs); 871 else 872 __gmpz_tdiv_q_2exp(_ptr, _ptr, -rhs); // `z << -1` becomes `z >> 1` 873 } else static if (s == ">>") { 874 if (rhs >= 0) 875 __gmpz_tdiv_q_2exp(_ptr, _ptr, rhs); 876 else 877 __gmpz_mul_2exp(_ptr, _ptr, -rhs); // `z >> -1` becomes `z << 1` 878 } else 879 static assert(0); 880 881 return this; 882 } 883 884 /// Returns: `this`. 885 ref inout(_Z) opUnary(string s)() inout scope return if (s == "+") { 886 pragma(inline, true); 887 return this; 888 } 889 890 /// Negation of `this`. 891 _Z opUnary(string s)() const if (s == "-") { 892 version(LDC) pragma(inline, true); 893 typeof(return) y = this.dup; 894 y.negate(); 895 return y; 896 } 897 898 /// Negation of `this`. 899 _Z unaryMinus() const @safe { 900 version(LDC) pragma(inline, true); 901 // pragma(msg, "memberFun:", __traits(isRef, this) ? "ref" : "non-ref", " this"); 902 typeof(return) y = this.dup; 903 y.negate(); 904 return y; 905 } 906 907 /** Negate `this` in-place. 908 Returns: `void` to make it obvious that `this` is mutated. 909 */ 910 void negate() @safe { 911 static if (cow) { selfdupIfAliased(); } 912 pragma(inline, true); 913 _z._mp_size = -_z._mp_size; // fast C macro `mpz_neg` in gmp.h 914 } 915 916 /** Make `this` the absolute value of itself in-place. 917 918 Returns: `void` to make it obvious that `this` is mutated. 919 */ 920 void absolute() @trusted { 921 version(LDC) pragma(inline, true); 922 if (isZero) { return; } // `__gmpz_abs` cannot handle default-constructed `this` 923 if (isOne) { return; } // `__gmpz_abs` cannot handle default-constructed `this` 924 static if (cow) { selfdupIfAliased(); } 925 __gmpz_abs(_ptr, _ptr); 926 } 927 alias absSelf = absolute; 928 929 /** Make `this` the one's complement value of itself in-place. 930 931 Returns: `void` to make it obvious that `this` is mutated. 932 */ 933 void onesComplementSelf() @trusted { 934 version(LDC) pragma(inline, true); 935 if (isZero) { return; } // `__gmpz_com` cannot handle default-constructed `this` 936 static if (cow) { selfdupIfAliased(); } 937 __gmpz_com(_ptr, _ptr); 938 } 939 940 /** Make `this` the square root of itself in-place. 941 942 Returns: `void` to make it obvious that `this` is mutated. 943 */ 944 void sqrtSelf() @trusted { 945 version(LDC) pragma(inline, true); 946 if (isZero) { return; } // `__gmpz_co` cannot handle default-constructed `this` 947 if (isOne) { return; } // `__gmpz_co` cannot handle default-constructed `this` 948 static if (cow) { selfdupIfAliased(); } 949 __gmpz_sqrt(_ptr, _ptr); 950 } 951 952 /** Make `this` the `n`:th root of itself in-place. 953 954 Returns: `true` if computation was exact. 955 */ 956 bool rootSelf(ulong n) @trusted { 957 version(LDC) pragma(inline, true); 958 if (isZero) { return true; } // `__gmpz_co` cannot handle default-constructed `this` 959 if (isOne) { return true; } // `__gmpz_co` cannot handle default-constructed `this` 960 static if (cow) { selfdupIfAliased(); } 961 const status = __gmpz_root(_ptr, _ptr, n); 962 return status != 0; 963 } 964 965 /** Make `this` the `n`:th root of itself in-place along with its remainder returned. 966 967 Returns: `rem` to the remainder, u-root ^^ `n`. 968 */ 969 _Z rootremSelf(ulong n) @trusted { 970 version(LDC) pragma(inline, true); 971 if (isZero) { return typeof(return).init; } // `__gmpz_co` cannot handle default-constructed `this` 972 if (isOne) { return typeof(return).init; } // `__gmpz_co` cannot handle default-constructed `this` 973 static if (cow) { selfdupIfAliased(); } 974 _Z rem; 975 __gmpz_rootrem(_ptr, rem._ptr, _ptr, n); 976 return move(rem); 977 } 978 979 /** Make `this` the square root of itself in-place along with its remainder 980 returned. 981 982 Returns: `rem` to the remainder. 983 */ 984 _Z sqrtremSelf() @trusted { 985 version(LDC) pragma(inline, true); 986 if (isZero) { return typeof(return).init; } // `__gmpz_co` cannot handle default-constructed `this` 987 if (isOne) { return typeof(return).init; } // `__gmpz_co` cannot handle default-constructed `this` 988 static if (cow) { selfdupIfAliased(); } 989 _Z rem; 990 __gmpz_sqrtrem(_ptr, rem._ptr, _ptr); 991 return move(rem); 992 } 993 994 /// Increase `this` by one. 995 ref _Z opUnary(string s)() scope return @trusted if (s == "++") 996 { 997 version(LDC) pragma(inline, true); 998 static if (cow) { selfdupIfAliased(); } 999 if (isDefaultConstructed) // `__gmpz_add_ui` cannot handle default-constructed `this` 1000 __gmpz_init_set_si(_ptr, 1); 1001 else 1002 __gmpz_add_ui(_ptr, _ptr, 1); 1003 return this; 1004 } 1005 1006 /// Decrease `this` by one. 1007 ref _Z opUnary(string s)() scope return @trusted if (s == "--") 1008 { 1009 version(LDC) pragma(inline, true); 1010 static if (cow) { selfdupIfAliased(); } 1011 if (isDefaultConstructed) // `__gmpz_sub_ui` cannot handle default-constructed `this` 1012 __gmpz_init_set_si(_ptr, -1); 1013 else 1014 __gmpz_sub_ui(_ptr, _ptr, 1); 1015 return this; 1016 } 1017 1018 /// Get `base` raised to the power of `exp`. 1019 static typeof(this) pow(Base, Exp)(Base base, Exp exp) @trusted if (__traits(isIntegral, Base) && __traits(isIntegral, Exp)) 1020 { 1021 version(LDC) pragma(inline, true); 1022 1023 static if (__traits(isArithmetic, Base) && !__traits(isUnsigned, Base)) { 1024 immutable bool negate = base < 0; 1025 immutable ubase = cast(ulong)(negate ? -base : base); 1026 } else { 1027 immutable bool negate = false; 1028 immutable ubase = base; 1029 } 1030 1031 static if (__traits(isArithmetic, Exp) && !__traits(isUnsigned, Exp)) { 1032 assert(exp >= 0, "Negative exponent"); // TODO: return mpq? 1033 immutable uexp = cast(ulong)exp; 1034 } else 1035 immutable uexp = exp; 1036 1037 typeof(return) y = null; 1038 __gmpz_ui_pow_ui(y._ptr, ubase, uexp); 1039 if (negate && 1040 exp & 1) // if negative odd exponent 1041 y.negate(); 1042 1043 return y; 1044 } 1045 1046 /// Get number of digits in base `base`. 1047 size_t sizeInBase(uint base) const @trusted { 1048 pragma(inline, true); 1049 if (isZero || isOne) 1050 return 1; 1051 else 1052 return __gmpz_sizeinbase(_ptr, base); 1053 } 1054 1055 /** Serialize `this` into an existing pre-allocated slice of words `words`, 1056 each word of type `Word`. 1057 1058 It's format defined by: 1059 - `order`: the most significant word `first` or `last` for least significant first 1060 - `size` in bytes of each word 1061 - `endian` can be `bigEndian`, `littleEndian` or `host` default 1062 - the most significant `nails` bits of each word are unused and set to zero, this can be 0 to produce full words 1063 1064 Returns: a (sub-)slice of `words` containing only the words produced. 1065 */ 1066 Word[] serialize(Word)(return scope Word[] words, 1067 WordOrder order, size_t size, WordEndianess endian, size_t nails) const @trusted 1068 if (__traits(isUnsigned, Word)) { 1069 assert(words, "Words is empty"); 1070 1071 size_t count; 1072 debug { 1073 const numb = 8 * size - nails; 1074 const items = (__gmpz_sizeinbase(_ptr, 2) + numb-1) / numb; 1075 assert(Word.sizeof * words.length >= items * size , 1076 "Words has not enough space pre-allocated"); 1077 } 1078 1079 int realOrder; 1080 final switch(order) { 1081 case WordOrder.mostSignificantWordFirst: realOrder = 1; break; 1082 case WordOrder.leastSignificantWordFirst: realOrder = -1; break; 1083 } 1084 1085 int realEndian; 1086 final switch(endian) { 1087 case WordEndianess.littleEndian: realEndian = -1; break; 1088 case WordEndianess.bigEndian: realEndian = 1; break; 1089 case WordEndianess.host: realEndian = 0; break; 1090 } 1091 1092 __gmpz_export(words.ptr, &count, realOrder, size, realEndian, nails, _ptr); 1093 return words[0 .. count]; 1094 } 1095 1096 1097 /// Returns: `true` iff `this` fits in a `T`. 1098 bool fitsIn(T)() const @trusted if (__traits(isIntegral, T)) { 1099 pragma(inline, true); 1100 if (isZero || 1101 isOne) { return true; } // default-constructed `this` 1102 static if (is(T == ulong)) { return __gmpz_fits_ulong_p(_ptr) != 0; } 1103 else static if (is(T == long)) { return __gmpz_fits_slong_p(_ptr) != 0; } 1104 else static if (is(T == uint)) { return __gmpz_fits_uint_p(_ptr) != 0; } 1105 else static if (is(T == int)) { return __gmpz_fits_sint_p(_ptr) != 0; } 1106 else static if (is(T == ushort)) { return __gmpz_fits_ushort_p(_ptr) != 0; } 1107 else static if (is(T == short)) { return __gmpz_fits_sshort_p(_ptr) != 0; } 1108 else { static assert(false, "Unsupported type " ~ T.stringof); } 1109 } 1110 1111 /** Get population count of `this`. 1112 1113 If 1114 - `this` >= 0, number of 1 bits in the binary representation 1115 - otherwise, ??? 1116 */ 1117 @property mp_bitcnt_t populationCount() const @trusted { 1118 version(LDC) pragma(inline, true); 1119 if (isZero) { return 0; } // default-constructed `this` 1120 if (isOne) { return 1; } // default-constructed `this` 1121 return __gmpz_popcount(this._ptr); // TODO: use core.bitop `popcnt` inline here instead? 1122 } 1123 alias countOnes = populationCount; 1124 1125 /// Set bit at 0-offset index `bitIndex` (to one). 1126 void setBit(mp_bitcnt_t bitIndex) @trusted { 1127 pragma(inline, true); 1128 static if (cow) { selfdupIfAliased(); } 1129 __gmpz_setbit(_ptr, bitIndex); 1130 } 1131 1132 /// Clear bit at 0-offset index `bitIndex` (to zero). 1133 void clearBit(mp_bitcnt_t bitIndex) @trusted { 1134 pragma(inline, true); 1135 static if (cow) { selfdupIfAliased(); } 1136 __gmpz_clrbit(_ptr, bitIndex); 1137 } 1138 1139 /// Complement bit at 0-offset index `bitIndex` (to zero). 1140 void complementBit(mp_bitcnt_t bitIndex) @trusted { 1141 pragma(inline, true); 1142 static if (cow) { selfdupIfAliased(); } 1143 __gmpz_combit(_ptr, bitIndex); 1144 } 1145 1146 /// Test/Get bit at 0-offset index `bitIndex`. 1147 bool testBit(mp_bitcnt_t bitIndex) const @trusted { 1148 pragma(inline, true); 1149 return __gmpz_tstbit(_ptr, bitIndex) != 0; 1150 } 1151 alias getBit = testBit; 1152 1153 /** Check if `this` is default-constructed (in constrast to having been 1154 initialized via `__gmpz_...`-operations). 1155 1156 Used to specially prepare avoid some `__gmpz_`-functions that cannot 1157 handle the case when the membere `_mp_alloc` is zero and, in turn, 1158 `_mp_d` is `null`. 1159 */ 1160 @property bool isDefaultConstructed() const @safe { 1161 pragma(inline, true); 1162 return _z._mp_alloc == 0; // fast, actually enough to just test this 1163 } 1164 1165 /// Check if `this` is zero (either via default-construction or `__gmpz_...`-operations). 1166 @property bool isZero() const @safe { 1167 pragma(inline, true); 1168 return _z._mp_size == 0; // fast 1169 } 1170 1171 /// Check if `this` is one. 1172 @property bool isOne() const @safe { 1173 pragma(inline, true); 1174 /* NOTE: cannot use _z._mp_d !is null && _z._mp_d[0] == 1 because that’s 1175 true for -1 because sign is stored in `_z._mp_size` 1176 */ 1177 return _z._mp_size == 1 && _z._mp_d[0] == 1; // fast 1178 } 1179 1180 /// Check if `this` is odd. 1181 @property bool isOdd() const @safe { 1182 pragma(inline, true); 1183 return ((_z._mp_alloc != 0) && // this is needed for default (zero) initialized `__mpz_structs` 1184 ((_z._mp_size != 0) & cast(int)(_z._mp_d[0]))); // fast C macro `mpz_odd_p` in gmp.h 1185 } 1186 1187 /// Check if `this` is odd. 1188 @property bool isEven() const @safe { 1189 pragma(inline, true); 1190 return !isOdd; // fast C macro `mpz_even_p` in gmp.h 1191 } 1192 1193 /// Check if `this` is negative. 1194 @property bool isNegative() const @safe { 1195 pragma(inline, true); 1196 return _z._mp_size < 0; // fast 1197 } 1198 1199 /// Check if `this` is positive. 1200 @property bool isPositive() const @safe { 1201 pragma(inline, true); 1202 return _z._mp_size >= 0; // fast 1203 } 1204 1205 /** Check if `this` is a perfect power, i.e., if there exist integers A and 1206 * B, with B>1, such that `this` equals A raised to the power B. 1207 */ 1208 @property bool isPerfectPower() const @trusted { 1209 pragma(inline, true); 1210 return __gmpz_perfect_power_p(_ptr) != 0; 1211 } 1212 1213 /** Return non-zero if `this` is a perfect square, i.e., if the square root 1214 * of op is an integer. Under this definition both 0 and 1 are considered to 1215 * be perfect squares. 1216 */ 1217 @property bool isPerfectSquare() const @trusted { 1218 pragma(inline, true); 1219 return __gmpz_perfect_square_p(_ptr) != 0; 1220 } 1221 1222 /// Returns: `true` iff `this` is exactly divisible by `rhs`. 1223 @property bool isDivisibleBy()(auto ref scope const _Z rhs) const @trusted { 1224 version(LDC) pragma(inline, true); 1225 if (rhs.isOne) { return true; } 1226 return __gmpz_divisible_p(_ptr, rhs._ptr) != 0; 1227 } 1228 /// ditto 1229 @property bool isDivisibleBy(Rhs)(auto ref scope const Rhs rhs) const @trusted if (__traits(isUnsigned, Rhs)) { 1230 version(LDC) pragma(inline, true); 1231 if (rhs == 1) { return true; } 1232 return __gmpz_divisible_ui_p(_ptr, rhs) != 0; 1233 } 1234 1235 /** Returns: sign as either 1236 1237 - -1 (`this` < 0), 1238 - 0 (`this` == 0), or 1239 - +1 (`this` > 0). 1240 */ 1241 @property int sgn() const @safe { 1242 pragma(inline, true); 1243 return _z._mp_size < 0 ? -1 : _z._mp_size > 0; // fast C macro `mpz_sgn` in gmp.h 1244 } 1245 1246 /// Number of significant `uint`s used for storing `this`. 1247 @property size_t uintLength() const { 1248 pragma(inline, true); 1249 assert(false, "TODO: use mpz_size"); 1250 } 1251 1252 /// Number of significant `ulong`s used for storing `this`. 1253 @property size_t uintLong() const { 1254 pragma(inline, true); 1255 assert(false, "TODO: use mpz_size"); 1256 } 1257 1258 /// Get number of limbs in internal representation. 1259 @property uint limbCount() const @safe { 1260 pragma(inline, true); 1261 return _integralAbs(_z._mp_size); 1262 } 1263 1264 private: 1265 1266 /** Initialize internal struct. */ 1267 void initialize() @system // cannot be called `init` as that will override builtin type property 1268 { 1269 pragma(inline, true); 1270 __gmpz_init(_ptr); 1271 } 1272 1273 /** Initialize internal struct if needed. */ 1274 void assertInitialized() @system { 1275 pragma(inline, true); 1276 if (isDefaultConstructed) 1277 __gmpz_init(_ptr); 1278 } 1279 1280 /// Default conversion base. 1281 enum defaultBase = 10; 1282 1283 /// Returns: evaluation of `this` expression which in this is a no-op. 1284 ref inout(_Z) eval() @safe inout scope return { 1285 pragma(inline, true); 1286 return this; 1287 } 1288 1289 /// Type of limb in internal representation. 1290 alias Limb = __mp_limb_t; // GNU MP alias 1291 1292 /** Returns: limbs. */ 1293 inout(Limb)[] _limbs() inout return @system { 1294 pragma(inline, true); 1295 // import std.math : abs; 1296 return _z._mp_d[0 .. limbCount]; 1297 } 1298 1299 /// Returns: pointer to internal C struct. 1300 inout(__mpz_struct)* _ptr() inout return @system { 1301 pragma(inline, true); 1302 return &_z; 1303 } 1304 1305 static if (cow) { 1306 private __mpz_struct _z; // internal libgmp C struct 1307 private size_t _refCountCopies; ///< Number of copies. 1308 } else { 1309 private __mpz_struct _z; // internal libgmp C struct 1310 } 1311 1312 version(ccc) 1313 { 1314 /** Number of calls made to `__gmpz`--functions that construct or changes 1315 this value. Used to verify correct lowering and evaluation of template 1316 expressions. 1317 1318 For instance the `x` in `x = y + z` should be assigned only once inside 1319 a call to `mpz_add`. 1320 */ 1321 @property size_t mutatingCallCount() const @safe { return _ccc; } 1322 size_t _ccc; // C mutation call count. number of calls to C GMP function calls that mutate this object 1323 } 1324 1325 /// @nogc-variant of `toStringz` with heap allocation of null-terminated C-string `stringz`. 1326 char* _allocStringzCopyOf(in char[] value) @nogc @trusted 1327 { 1328 import core.memory : pureMalloc; 1329 char* stringz = cast(char*)pureMalloc(value.length + 1); // maximum this many characters 1330 size_t i = 0; 1331 foreach (immutable char ch; value[]) 1332 { 1333 if (ch != '_') 1334 { 1335 stringz[i] = ch; 1336 i += 1; 1337 } 1338 } 1339 stringz[i] = '\0'; // set C null terminator 1340 return stringz; 1341 } 1342 1343 // qualified C memory managment 1344 static @trusted extern(C) // locally `@trusted` 1345 { 1346 pragma(mangle, "free") 1347 void qualifiedFree(void* ptr); 1348 } 1349 } 1350 1351 /** Arbitrary precision integer (BigInt) with explicit copying via `.dup`. 1352 1353 For copyable using copy-on-write automatic reference counting semantics, use 1354 `CopyableMpZ`. 1355 */ 1356 alias MpZ = _Z!(false); 1357 static assert(MpZ.sizeof == __mpz_struct.sizeof); 1358 1359 /** Arbitrary precision integer (BigInt) with copy-on-write (CoW) automatic 1360 reference counting (ARC) API-compatible with `std.bigint`. 1361 */ 1362 alias CopyableMpZ = _Z!(true); 1363 static assert(CopyableMpZ.sizeof == __mpz_struct.sizeof + size_t.sizeof); 1364 1365 version(gmp_test) version(unittest) static assert(isMpZExpr!(MpZ)); 1366 1367 version(benchmark) 1368 version(gmp_test) @safe unittest { 1369 import std.datetime.stopwatch : benchmark; 1370 bool odd; 1371 void test() 1372 { 1373 odd = (9.Z^^333_333L).isOdd; 1374 } 1375 immutable results = benchmark!test(1); 1376 import std.stdio; 1377 debug writeln("Took:", results[0]); 1378 } 1379 1380 pure: 1381 1382 /** Instantiator for `MpZ`. */ 1383 _Z!(cow) mpz(bool cow = true, Args...)(Args args) @safe 1384 { 1385 version(LDC) pragma(inline, true); 1386 return typeof(return)(args); 1387 } 1388 1389 /// Swap contents of `x` with contents of `y`. 1390 void swap(bool cow)(ref _Z!(cow) x, ref _Z!(cow) y) nothrow 1391 { 1392 pragma(inline, true); 1393 import std.algorithm.mutation : swap; 1394 swap(x, y); // x.swap(y); 1395 } 1396 1397 /// Get `x` as a `string` in decimal base. 1398 string toDecimalString(bool cow)(auto ref scope const _Z!(cow) x) nothrow @safe // for `std.bigint.BigInt` compatibility 1399 { 1400 version(LDC) pragma(inline, true); 1401 return x.toString(10); 1402 } 1403 1404 /// Get `x` as a uppercased `string` in hexadecimal base without any base prefix (0x). 1405 string toHexadecimalString(bool cow)(auto ref scope const _Z!(cow) x) nothrow @safe 1406 { 1407 version(LDC) pragma(inline, true); 1408 return x.toString(16, true); 1409 } 1410 1411 /// For `std.bigint.BigInt` compatibility. 1412 alias toHex = toHexadecimalString; 1413 1414 /// Get the absolute value of `x` converted to the corresponding unsigned type. 1415 Unsigned!T absUnsign(T, bool cow)(auto ref scope const _Z!(cow) x) nothrow @safe // for `std.bigint.BigInt` compatibility 1416 if (__traits(isIntegral, T)) 1417 { 1418 version(LDC) pragma(inline, true); 1419 return _integralAbs(cast(T)x); 1420 } 1421 1422 /** Get sum of `x` and `y` (`x` + `y`). 1423 */ 1424 _Z!(cow) add(bool cow)(auto ref scope const _Z!(cow) x, auto ref scope const _Z!(cow) y) nothrow @trusted 1425 { 1426 version(LDC) pragma(inline, true); 1427 static if (!__traits(isRef, x) || // r-value `x` 1428 !__traits(isRef, y)) // r-value `y` 1429 { 1430 typeof(return)* zp = null; // reuse: will point to either `x` or `y` 1431 static if (!__traits(isRef, x) && // r-value `x` 1432 !__traits(isRef, y)) // r-value `y` 1433 { 1434 if (x.limbCount > y.limbCount) // larger r-value `x` 1435 zp = (cast(typeof(return)*)(&x)); // @trusted because `MpZ` has no aliased indirections 1436 else // larger r-value `y` 1437 zp = (cast(typeof(return)*)(&y)); // @trusted because `MpZ` has no aliased indirections 1438 } 1439 else static if (!__traits(isRef, x)) // r-value `x` 1440 { 1441 zp = (cast(typeof(return)*)(&x)); // @trusted because `MpZ` has no aliased indirections 1442 } 1443 else static if (!__traits(isRef, y)) // r-value `y` 1444 { 1445 zp = (cast(typeof(return)*)(&y)); // @trusted because `MpZ` has no aliased indirections 1446 } 1447 else 1448 static assert(0); 1449 __gmpz_add(zp._ptr, x._ptr, y._ptr); 1450 static if (cow) { zp.selfdupIfAliased(); } 1451 return move(*zp); // TODO: shouldn't have to call `move` here 1452 } 1453 else // l-value `x` and `y`, no reuse in output 1454 { 1455 typeof(return) z = null; 1456 __gmpz_add(z._ptr, x._ptr, y._ptr); 1457 return z; 1458 } 1459 } 1460 1461 /// 1462 @safe nothrow @nogc version(gmp_test) unittest { 1463 const Z x = Z(2)^^100; 1464 const Z y = 12; 1465 assert(add(x, Z(12)) == // l-value, r-value 1466 add(Z(12), x)); // r-value, l-value 1467 assert(add(x, y) == // l-value, l-value 1468 add(Z(2)^^100, Z(12))); // r-value, r-value 1469 assert(add(Z(12), Z(2)^^100) == // r-value, r-value 1470 add(Z(2)^^100, Z(12))); // r-value, r-value 1471 } 1472 1473 /** Get difference of `x` and `y` (`x` - `y`). 1474 */ 1475 _Z!(cow) sub(bool cow)(auto ref scope const _Z!(cow) x, auto ref scope const _Z!(cow) y) nothrow @trusted 1476 { 1477 version(LDC) pragma(inline, true); 1478 static if (!__traits(isRef, x) || // r-value `x` 1479 !__traits(isRef, y)) // r-value `y` 1480 { 1481 typeof(return)* zp = null; // reuse: will point to either `x` or `y` 1482 static if (!__traits(isRef, x) && // r-value `x` 1483 !__traits(isRef, y)) // r-value `y` 1484 { 1485 if (x.limbCount > y.limbCount) // larger r-value `x` 1486 zp = (cast(typeof(return)*)(&x)); // @trusted because `MpZ` has no aliased indirections 1487 else // larger r-value `y` 1488 zp = (cast(typeof(return)*)(&y)); // @trusted because `MpZ` has no aliased indirections 1489 } 1490 else static if (!__traits(isRef, x)) // r-value `x` 1491 { 1492 zp = (cast(typeof(return)*)(&x)); // @trusted because `MpZ` has no aliased indirections 1493 } 1494 else static if (!__traits(isRef, y)) // r-value `y` 1495 { 1496 zp = (cast(typeof(return)*)(&y)); // @trusted because `MpZ` has no aliased indirections 1497 } 1498 else 1499 static assert(0); 1500 static if (cow) { zp.selfdupIfAliased(); } 1501 __gmpz_sub(zp._ptr, x._ptr, y._ptr); 1502 return move(*zp); // TODO: shouldn't have to call `move` here 1503 } 1504 else // l-value `x` and `y`, no reuse in output 1505 { 1506 typeof(return) z = null; 1507 __gmpz_sub(z._ptr, x._ptr, y._ptr); 1508 return z; 1509 } 1510 } 1511 1512 /// 1513 @safe nothrow @nogc version(gmp_test) unittest { 1514 Z x = 2.Z^^100; 1515 Z y = 12; 1516 assert(sub(x, Z(12)) == // l-value, r-value 1517 -sub(Z(12), x)); // r-value, l-value 1518 assert(sub(x, y) == // l-value, l-value 1519 sub(2.Z^^100, 12.Z)); // r-value, r-value 1520 assert(sub(12.Z, 2.Z^^100) == // r-value, r-value 1521 -sub(2.Z^^100, 12.Z)); // r-value, r-value 1522 } 1523 1524 /** Get product of `x` and `y` (`x` + `y`). 1525 */ 1526 _Z!(cow) mul(bool cow)(auto ref scope const _Z!(cow) x, auto ref scope const _Z!(cow) y) nothrow @trusted 1527 { 1528 version(LDC) pragma(inline, true); 1529 static if (!__traits(isRef, x) || // r-value `x` 1530 !__traits(isRef, y)) // r-value `y` 1531 { 1532 typeof(return)* zp = null; // reuse: will point to either `x` or `y` 1533 static if (!__traits(isRef, x) && // r-value `x` 1534 !__traits(isRef, y)) // r-value `y` 1535 { 1536 if (x.limbCount > y.limbCount) // larger r-value `x` 1537 { 1538 zp = (cast(typeof(return)*)(&x)); // @trusted because `MpZ` has no aliased indirections 1539 } 1540 else // larger r-value `y` 1541 { 1542 zp = (cast(typeof(return)*)(&y)); // @trusted because `MpZ` has no aliased indirections 1543 } 1544 } 1545 else static if (!__traits(isRef, x)) // r-value `x` 1546 { 1547 zp = (cast(typeof(return)*)(&x)); // @trusted because `MpZ` has no aliased indirections 1548 } 1549 else static if (!__traits(isRef, y)) // r-value `y` 1550 { 1551 zp = (cast(typeof(return)*)(&y)); // @trusted because `MpZ` has no aliased indirections 1552 } 1553 else 1554 static assert(0); 1555 static if (cow) { zp.selfdupIfAliased(); } 1556 __gmpz_mul(zp._ptr, x._ptr, y._ptr); 1557 return move(*zp); // TODO: shouldn't have to call `move` here 1558 } 1559 else // l-value `x` and `y`, no reuse in output 1560 { 1561 typeof(return) z = null; 1562 __gmpz_mul(z._ptr, x._ptr, y._ptr); 1563 return z; 1564 } 1565 } 1566 1567 /// 1568 @safe nothrow @nogc version(gmp_test) unittest { 1569 Z x = 2.Z^^100; 1570 Z y = 12; 1571 assert(mul(x, Z(12)) == // l-value, r-value 1572 mul(Z(12), x)); // r-value, l-value 1573 assert(mul(x, y) == // l-value, l-value 1574 mul(2.Z^^100, 12.Z)); // r-value, r-value 1575 assert(mul(12.Z, 2.Z^^100) == // r-value, r-value 1576 mul(2.Z^^100, 12.Z)); // r-value, r-value 1577 } 1578 1579 /** Get absolute value of `x`. 1580 1581 Written as a free function instead of `MpZ`-member because `__traits(isRef, 1582 this)` doesn't currently support member functions. 1583 */ 1584 _Z!(cow) abs(bool cow)(auto ref scope const _Z!(cow) x) @trusted nothrow @nogc 1585 { 1586 version(LDC) pragma(inline, true); 1587 static if (__traits(isRef, x)) // l-value `x` 1588 { 1589 typeof(return) y = null; // must use temporary 1590 __gmpz_abs(y._ptr, x._ptr); 1591 return y; 1592 } 1593 else // r-value `x` 1594 { 1595 typeof(return)* zp = (cast(typeof(return)*)(&x)); // @trusted because `MpZ` has no aliased indirections 1596 static if (cow) { zp.selfdupIfAliased(); } 1597 zp.absolute(); 1598 return move(*zp); // TODO: shouldn't have to call `move` here 1599 } 1600 } 1601 1602 /** Get one's complement of `x`. 1603 1604 Written as a free function instead of `MpZ`-member because `__traits(isRef, 1605 this)` doesn't currently support member functions. 1606 */ 1607 _Z!(cow) onesComplement(bool cow)(auto ref scope const _Z!(cow) x) @trusted nothrow @nogc 1608 { 1609 version(LDC) pragma(inline, true); 1610 static if (__traits(isRef, x)) // l-value `x` 1611 { 1612 typeof(return) y = null; // must use temporary 1613 __gmpz_com(y._ptr, x._ptr); 1614 return y; 1615 } 1616 else // r-value `x` 1617 { 1618 typeof(return)* zp = (cast(typeof(return)*)(&x)); // @trusted because `MpZ` has no aliased indirections 1619 zp.onesComplementSelf(); 1620 return move(*zp); // TODO: shouldn't have to call `move` here 1621 } 1622 } 1623 alias com = onesComplement; 1624 1625 /** Get truncated integer part of the square root of `x`. 1626 1627 Written as a free function instead of `MpZ`-member because `__traits(isRef, 1628 this)` doesn't currently support member functions. 1629 1630 See: https://gmplib.org/manual/Integer-Roots 1631 */ 1632 _Z!(cow) sqrt(bool cow)(auto ref scope const _Z!(cow) x) @trusted nothrow @nogc 1633 { 1634 version(LDC) pragma(inline, true); 1635 static if (__traits(isRef, x)) // l-value `x` 1636 { 1637 typeof(return) y = null; // must use temporary 1638 __gmpz_sqrt(y._ptr, x._ptr); 1639 return y; 1640 } 1641 else // r-value `x` 1642 { 1643 typeof(return)* zp = (cast(typeof(return)*)(&x)); // @trusted because `MpZ` has no aliased indirections 1644 zp.sqrtSelf(); 1645 return move(*zp); // TODO: shouldn't have to call `move` here 1646 } 1647 } 1648 1649 _Z!(cow) sqrtrem(bool cow)(auto ref scope const _Z!(cow) x, out scope _Z!(cow) rem) @trusted nothrow @nogc 1650 { 1651 version(LDC) pragma(inline, true); 1652 static if (__traits(isRef, x)) // l-value `x` 1653 { 1654 typeof(return) y = null; // must use temporary 1655 __gmpz_sqrtrem(y._ptr, rem._ptr, x._ptr); 1656 return y; 1657 } 1658 else // r-value `x` 1659 { 1660 typeof(return)* zp = (cast(typeof(return)*)(&x)); // @trusted because `MpZ` has no aliased indirections 1661 rem = zp.sqrtremSelf(); 1662 return move(*zp); 1663 } 1664 } 1665 1666 /** Get truncated integer part of the `n`:th root of `x`. 1667 1668 See: https://gmplib.org/manual/Integer-Roots 1669 */ 1670 _Z!(cow) root(bool cow)(auto ref scope const _Z!(cow) x, ulong n, out bool isExact) @trusted nothrow @nogc 1671 { 1672 version(LDC) pragma(inline, true); 1673 static if (__traits(isRef, x)) // l-value `x` 1674 { 1675 typeof(return) y = null; // must use temporary 1676 const status = __gmpz_root(y._ptr, x._ptr, n); 1677 isExact = status != 0; 1678 return y; 1679 } 1680 else // r-value `x` 1681 { 1682 typeof(return)* zp = (cast(typeof(return)*)(&x)); // @trusted because `MpZ` has no aliased indirections 1683 isExact = zp.rootSelf(n); 1684 return move(*zp); // TODO: shouldn't have to call `move` here 1685 } 1686 } 1687 1688 _Z!(cow) rootrem(bool cow)(auto ref scope const _Z!(cow) x, ulong n, out scope _Z!(cow) rem) @trusted nothrow @nogc 1689 { 1690 version(LDC) pragma(inline, true); 1691 static if (__traits(isRef, x)) // l-value `x` 1692 { 1693 typeof(return) y = null; // must use temporary 1694 __gmpz_rootrem(y._ptr, rem._ptr, x._ptr, n); 1695 return y; 1696 } 1697 else // r-value `x` 1698 { 1699 typeof(return)* zp = (cast(typeof(return)*)(&x)); // @trusted because `MpZ` has no aliased indirections 1700 rem = zp.rootremSelf(n); 1701 return move(*zp); 1702 } 1703 } 1704 1705 /// Comparison of the absolute values of `x` and `y`. 1706 int cmpabs(bool cow)(auto ref scope const _Z!(cow) x, auto ref scope const _Z!(cow) y) nothrow @nogc @trusted 1707 { 1708 version(LDC) pragma(inline, true); 1709 return __gmpz_cmpabs(x._ptr, y._ptr); 1710 } 1711 /// ditto 1712 int cmpabs(bool cow)(auto ref scope const _Z!(cow) x, double y) nothrow @nogc @trusted 1713 { 1714 version(LDC) pragma(inline, true); 1715 return __gmpz_cmpabs_d(x._ptr, y); 1716 } 1717 /// ditto 1718 int cmpabs(bool cow)(auto ref scope const _Z!(cow) x, ulong y) nothrow @nogc @trusted 1719 { 1720 version(LDC) pragma(inline, true); 1721 return __gmpz_cmpabs_ui(x._ptr, y); 1722 } 1723 1724 /** Get next prime greater than `x`. 1725 1726 Written as a free function instead of `MpZ`-member because `__traits(isRef, 1727 this)` doesn't currently support member functions. 1728 */ 1729 _Z!(cow) nextPrime(bool cow)(auto ref scope const _Z!(cow) x) nothrow @nogc @trusted 1730 { 1731 version(LDC) pragma(inline, true); 1732 static if (__traits(isRef, x)) // l-value `x` 1733 { 1734 typeof(return) y = null; // must use temporary 1735 static if (cow) { y.selfdupIfAliased(); } 1736 __gmpz_nextprime(y._ptr, x._ptr); 1737 return y; 1738 } 1739 else // r-value `x` 1740 { 1741 typeof(return)* zp = (cast(typeof(return)*)(&x)); // @trusted because `MpZ` has no aliased indirections 1742 static if (cow) { zp.selfdupIfAliased(); } 1743 __gmpz_nextprime(zp._ptr, x._ptr); 1744 return move(*zp); // TODO: shouldn't have to call `move` here 1745 } 1746 } 1747 1748 /// Get greatest common divisor (gcd) of `x` and `y`. 1749 _Z!(cow) gcd(bool cow)(auto ref scope const _Z!(cow) x, auto ref scope const _Z!(cow) y) nothrow @nogc @trusted 1750 { 1751 version(LDC) pragma(inline, true); 1752 static if (!__traits(isRef, x) || // r-value `x` 1753 !__traits(isRef, y)) // r-value `y` 1754 { 1755 typeof(return)* zp = null; // reuse: will point to either `x` or `y` 1756 static if (!__traits(isRef, x) && // r-value `x` 1757 !__traits(isRef, y)) // r-value `y` 1758 { 1759 if (x.limbCount > y.limbCount) // larger r-value `x` 1760 zp = (cast(typeof(return)*)(&x)); // @trusted because `MpZ` has no aliased indirections 1761 else // larger r-value `y` 1762 zp = (cast(typeof(return)*)(&y)); // @trusted because `MpZ` has no aliased indirections 1763 } 1764 else static if (!__traits(isRef, x)) // r-value `x` 1765 { 1766 zp = (cast(typeof(return)*)(&x)); // @trusted because `MpZ` has no aliased indirections 1767 } 1768 else static if (!__traits(isRef, y)) // r-value `y` 1769 { 1770 zp = (cast(typeof(return)*)(&y)); // @trusted because `MpZ` has no aliased indirections 1771 } 1772 else 1773 static assert(0); 1774 static if (cow) { zp.selfdupIfAliased(); } 1775 __gmpz_gcd(zp._ptr, x._ptr, y._ptr); 1776 1777 return move(*zp); // TODO: shouldn't have to call `move` here 1778 } 1779 else // l-value `x` and `y`, no reuse in output 1780 { 1781 typeof(return) z = null; 1782 __gmpz_gcd(z._ptr, x._ptr, y._ptr); 1783 return z; 1784 } 1785 } 1786 /// ditto 1787 _Z!(cow) gcd(bool cow)(auto ref scope const _Z!(cow) x, in ulong y) nothrow @nogc @trusted 1788 { 1789 version(LDC) pragma(inline, true); 1790 static if (__traits(isRef, x)) // l-value `x` 1791 { 1792 typeof(return) z = null; 1793 const z_ui = __gmpz_gcd_ui(z._ptr, x._ptr, y); 1794 if (z_ui) 1795 assert(z == z_ui); 1796 return z; 1797 } 1798 else 1799 { 1800 typeof(return)* zp = (cast(typeof(return)*)(&x)); // @trusted because `MpZ` has no aliased indirections 1801 static if (cow) { zp.selfdupIfAliased(); } 1802 const z_ui = __gmpz_gcd_ui(zp._ptr, x._ptr, y); 1803 if (z_ui) 1804 assert(*zp == z_ui); 1805 return move(*zp); // TODO: shouldn't have to call `move` here 1806 } 1807 } 1808 1809 /// Get least common multiple (lcm) of `x` and `y`. 1810 _Z!(cow) lcm(bool cow)(auto ref scope const _Z!(cow) x, auto ref scope const _Z!(cow) y) nothrow @nogc @trusted 1811 { 1812 version(LDC) pragma(inline, true); 1813 static if (!__traits(isRef, x) || // r-value `x` 1814 !__traits(isRef, y)) // r-value `y` 1815 { 1816 typeof(return)* zp = null; // reuse: will point to either `x` or `y` 1817 static if (!__traits(isRef, x) && // r-value `x` 1818 !__traits(isRef, y)) // r-value `y` 1819 { 1820 if (x.limbCount > y.limbCount) // larger r-value `x` 1821 zp = (cast(typeof(return)*)(&x)); // @trusted because `MpZ` has no aliased indirections 1822 else // larger r-value `y` 1823 zp = (cast(typeof(return)*)(&y)); // @trusted because `MpZ` has no aliased indirections 1824 } 1825 else static if (!__traits(isRef, x)) // r-value `x` 1826 { 1827 zp = (cast(typeof(return)*)(&x)); // @trusted because `MpZ` has no aliased indirections 1828 } 1829 else static if (!__traits(isRef, y)) // r-value `y` 1830 { 1831 zp = (cast(typeof(return)*)(&y)); // @trusted because `MpZ` has no aliased indirections 1832 } 1833 else 1834 static assert(0); 1835 static if (cow) { zp.selfdupIfAliased(); } 1836 __gmpz_lcm(zp._ptr, x._ptr, y._ptr); 1837 1838 return move(*zp); // TODO: shouldn't have to call `move` here 1839 } 1840 else // l-value `x` and `y`, no reuse in output 1841 { 1842 typeof(return) z = null; 1843 __gmpz_lcm(z._ptr, x._ptr, y._ptr); 1844 return z; 1845 } 1846 } 1847 /// ditto 1848 _Z!(cow) lcm(bool cow)(auto ref scope const _Z!(cow) x, ulong y) nothrow @nogc @trusted 1849 { 1850 version(LDC) pragma(inline, true); 1851 static if (__traits(isRef, x)) // l-value `x` 1852 { 1853 typeof(return) z = null; 1854 __gmpz_lcm_ui(z._ptr, x._ptr, y); 1855 return z; 1856 } 1857 else 1858 { 1859 typeof(return)* zp = (cast(typeof(return)*)(&x)); // @trusted because `MpZ` has no aliased indirections 1860 static if (cow) { zp.selfdupIfAliased(); } 1861 __gmpz_lcm_ui(zp._ptr, x._ptr, y); 1862 return move(*zp); // TODO: shouldn't have to call `move` here 1863 } 1864 } 1865 1866 /** Get `base` ^^ `exp` (modulo `mod`). 1867 1868 Parameter `exp` must be positive. 1869 */ 1870 _Z!(cow) powm(bool cow)(auto ref scope const _Z!(cow) base, auto ref scope const _Z!(cow) exp, auto ref scope const _Z!(cow) mod) nothrow @nogc @trusted 1871 { 1872 version(LDC) pragma(inline, true); 1873 assert(mod != 0, "Zero modulus"); 1874 typeof(return) y = 0; // result, TODO: reuse `exp` or `mod` if any is an r-value 1875 assert(exp >= 0, "Negative exponent"); 1876 static if (cow) { y.selfdupIfAliased(); } 1877 __gmpz_powm(y._ptr, base._ptr, exp._ptr, mod._ptr); 1878 return y; 1879 } 1880 /// ditto 1881 _Z!(cow) powm(bool cow)(auto ref scope const _Z!(cow) base, ulong exp, auto ref scope const _Z!(cow) mod) nothrow @nogc @trusted 1882 { 1883 version(LDC) pragma(inline, true); 1884 assert(mod != 0, "Zero modulus"); 1885 typeof(return) y = 0; // result, TODO: reuse `exp` or `mod` if any is an r-value 1886 static if (cow) { y.selfdupIfAliased(); } 1887 __gmpz_powm_ui(y._ptr, base._ptr, exp, mod._ptr); 1888 return y; 1889 } 1890 1891 /// For `std.bigint.BigInt` compatibility. 1892 alias powmod = powm; 1893 1894 /** Get `base` ^^ `-1` (modulo `mod`). 1895 1896 Parameter `mod` must be positive. 1897 */ 1898 _Z!(cow) invert(bool cow)(auto ref scope const _Z!(cow) base, auto ref scope const _Z!(cow) mod) nothrow @nogc @trusted 1899 { 1900 version(LDC) pragma(inline, true); 1901 assert(base != 0, "Zero base"); 1902 assert(mod != 0, "Zero modulus"); 1903 static if (!__traits(isRef, base)) // r-value `base` 1904 { 1905 typeof(return)* mut_base = (cast(typeof(return)*)(&base)); // @trusted because `MpZ` has no aliased indirections 1906 static if (cow) { mut_base.selfdupIfAliased(); } 1907 const success = __gmpz_invert(mut_base._ptr, base._ptr, mod._ptr); 1908 assert(success >= 0, "Cannot invert"); 1909 return move(*mut_base); // TODO: shouldn't have to call `move` here 1910 } 1911 else static if (!__traits(isRef, mod)) // r-value `mod` 1912 { 1913 typeof(return)* mut_mod = (cast(typeof(return)*)(&mod)); // @trusted because `MpZ` has no aliased indirections 1914 static if (cow) { mut_mod.selfdupIfAliased(); } 1915 const success = __gmpz_invert(mut_mod._ptr, base._ptr, mod._ptr); 1916 assert(success >= 0, "Cannot invert"); 1917 return move(*mut_mod); // TODO: shouldn't have to call `move` here 1918 } 1919 else // l-value `base` and l-value `mod` 1920 { 1921 typeof(return) y = 0; // result, TODO: reuse `exp` or `mod` if any is an r-value 1922 static if (cow) { y.selfdupIfAliased(); } 1923 const success = __gmpz_invert(y._ptr, base._ptr, mod._ptr); 1924 assert(success >= 0, "Cannot invert"); 1925 return y; 1926 } 1927 } 1928 1929 /// default construction 1930 @safe nothrow @nogc version(gmp_test) unittest { 1931 Z x = null; 1932 Z y = null; 1933 assert(x == y); 1934 assert(x is y); // TODO: is this correct behaviour? 1935 x = y; 1936 y = x; 1937 1938 const Z z = 42; 1939 x = z; 1940 1941 assert(Z.init.dup == Z.init); 1942 assert(Z.init.dup == Z.init.dup); 1943 1944 assert(Z.init.dup !is Z.init); 1945 assert(Z.init.dup !is Z.init.dup); 1946 1947 Z w = null; 1948 w = 42; 1949 } 1950 1951 /// @nogc to ASCII generation 1952 version(gmp_test) @trusted nothrow unittest { 1953 import core.memory : pureFree; 1954 const Z w = null; 1955 auto chars = w.toChars; 1956 scope(exit) pureFree(chars.ptr); 1957 assert(chars == `0`); 1958 } 1959 1960 /// operate on default-constructed instances 1961 version(gmp_test) @safe nothrow unittest { 1962 Z w; 1963 1964 // should be zeroed 1965 assert(w._z._mp_alloc == 0); 1966 assert(w._z._mp_size == 0); 1967 assert(w._z._mp_d is null); 1968 1969 assert(w == 0); 1970 assert(w == 0L); 1971 assert(w == 0UL); 1972 assert(w == 0.0f); 1973 assert(w == 0.0); 1974 1975 assert(w.toString == `0`); 1976 assert(w.toHash == 0); 1977 assert(w.sizeInBase(10) == 1); 1978 assert(w.countOnes == 0); 1979 assert(w.isZero); 1980 assert(-w == w); 1981 assert(abs(w) == w); 1982 1983 assert(w.fitsIn!ulong); 1984 assert(w.fitsIn!long); 1985 assert(w.fitsIn!uint); 1986 assert(w.fitsIn!int); 1987 assert(w.fitsIn!ushort); 1988 assert(w.fitsIn!short); 1989 1990 assert(!w.isOdd); 1991 assert(w.isEven); 1992 assert(!w.isNegative); 1993 assert(w.isPositive); 1994 assert(w.sgn == 0); 1995 1996 w.negate(); 1997 assert(w is Z.init); // should be unchanged 1998 w.negate(); 1999 assert(w is Z.init); // should be unchanged 2000 2001 w = -w; 2002 assert(w is Z.init); // should be unchanged 2003 2004 w = +w; 2005 assert(w is Z.init); // should be unchanged 2006 2007 w.absolute(); 2008 assert(w is Z.init); // should be unchanged 2009 2010 w.onesComplementSelf(); 2011 assert(w is Z.init); // should be unchanged 2012 w.onesComplementSelf(); 2013 assert(w is Z.init); // should be unchanged 2014 2015 static void testSqrt(ulong p, ulong q) @safe pure nothrow @nogc { 2016 const x = p.Z; 2017 assert(sqrt(x)== q); // l-value first-parameter 2018 assert(sqrt(p.Z) == q); // r-value first-parameter 2019 } 2020 testSqrt(1, 1); 2021 testSqrt(2, 1); 2022 testSqrt(3, 1); 2023 testSqrt(4, 2); 2024 testSqrt(5, 2); 2025 testSqrt(6, 2); 2026 testSqrt(7, 2); 2027 testSqrt(8, 2); 2028 testSqrt(9, 3); 2029 testSqrt(16, 4); 2030 2031 { bool isExact; assert(root(16.Z, 2, isExact) == 4 && isExact); } 2032 { bool isExact; assert(root(17.Z, 2, isExact) == 4 && !isExact); } 2033 { bool isExact; assert(root(27.Z, 3, isExact) == 3 && isExact); } 2034 { bool isExact; assert(root(28.Z, 3, isExact) == 3 && !isExact); } 2035 2036 foreach (const ui; 16 .. 20) 2037 { 2038 { 2039 Z u = ui; 2040 Z rem; 2041 const r = rootrem(u, 2, rem); // l-value first-parameter 2042 assert(r == 4); 2043 assert(rem == ui - 16); 2044 } 2045 { 2046 Z rem; 2047 const r = rootrem(ui.Z, 2, rem); // r-value first-parameter 2048 assert(r == 4); 2049 assert(rem == ui - 16); 2050 } 2051 } 2052 2053 foreach (const ui; 16 .. 20) 2054 { 2055 { 2056 Z u = ui; 2057 Z rem; 2058 const r = sqrtrem(u, rem); // l-value first-parameter 2059 assert(r == 4); 2060 assert(rem == ui - 16); 2061 } 2062 { 2063 Z rem; 2064 const r = sqrtrem(ui.Z, rem); // r-value first-parameter 2065 assert(r == 4); 2066 assert(rem == ui - 16); 2067 } 2068 } 2069 2070 assert(w^^10 == 0); 2071 assert(w^^0 == 1); // TODO: correct? 2072 2073 // change it and check its contents 2074 w = 42; 2075 assert(w.toString == `42`); 2076 assert(w.toHash != 0); // should at least be non-zero 2077 2078 { 2079 Z p; 2080 p.setBit(5); 2081 assert(p == 32); 2082 } 2083 { 2084 Z p; 2085 p.clearBit(5); 2086 assert(p == 0); 2087 } 2088 { 2089 Z p; 2090 p.complementBit(5); 2091 assert(p == 32); 2092 } 2093 { 2094 Z p; 2095 assert(p.testBit(5) == 0); 2096 } 2097 { 2098 Z p; 2099 ++p; 2100 assert(p == 1); 2101 } 2102 { 2103 Z p; 2104 --p; 2105 assert(p == -1); 2106 } 2107 2108 assert(Z.init + Z.init == Z.init); 2109 assert(Z.init - Z.init == Z.init); 2110 assert(Z.init * Z.init == Z.init); 2111 2112 assert(Z.init + 1 == 1); 2113 assert(Z.init - 1 == -1); 2114 2115 assert(Z.init * 1 == 0); 2116 assert(Z.init / 1 == 0); 2117 assert(Z.init ^^ 1 == Z.init); 2118 assert(Z.init ^^ 0 == 1); 2119 2120 assert(1 + Z.init == 1); 2121 assert(1 - Z.init == 1); 2122 assert(1 * Z.init == 0); 2123 } 2124 2125 /// null construction 2126 @safe nothrow @nogc version(gmp_test) unittest { 2127 const Z x = null; 2128 const Z y = null; 2129 assert(x == y); 2130 assert(x is y); // TODO: this behaviour recently changed. is this correct? 2131 } 2132 2133 /// 2134 version(gmp_test) @safe @nogc unittest { 2135 const x = 42.Z; 2136 assert(x.unaryMinus() == -42); // l-value `this` 2137 assert(42.Z.unaryMinus() == -42); // r-value `this` 2138 } 2139 2140 /// convert to string 2141 version(gmp_test) @safe unittest { 2142 assert(mpz( 42).toString == `42`); 2143 assert(mpz( -42).toString == `-42`); 2144 assert(mpz(`-101`).toString == `-101`); 2145 2146 assert(mpz(-42).toDecimalString == `-42`); 2147 assert(mpz( 42).toDecimalString == `42`); 2148 2149 assert(mpz( 0).toHex == `0`); 2150 assert(mpz( 1).toHex == `1`); 2151 assert(mpz( 9).toHex == `9`); 2152 assert(mpz(10).toHex == `A`); 2153 assert(mpz(14).toHex == `E`); 2154 assert(mpz(15).toHex == `F`); 2155 assert(mpz(16).toHex == `10`); 2156 2157 assert(mpz(-42).absUnsign!ulong == 42); 2158 assert(mpz( 42).absUnsign!ulong == 42); 2159 } 2160 2161 /// 2162 version(gmp_test) @nogc unittest { 2163 ubyte[int.sizeof] storage; 2164 const ubyte[1] expected = [2]; 2165 assert(storage[0] == 0); 2166 const storage2 = 2.Z.serialize(storage, WordOrder.mostSignificantWordFirst, 1, WordEndianess.littleEndian, 0); 2167 assert(storage2.ptr == storage.ptr); 2168 assert(storage2 == expected); 2169 } 2170 2171 version(gmp_test) unittest { 2172 const ubyte[int.sizeof] storage; 2173 const ubyte[1] expected = [2]; 2174 const ubyte[] storage2 = 2.Z.serialize!(ubyte)(WordOrder.mostSignificantWordFirst, WordEndianess.littleEndian, 0); 2175 assert(storage2 == expected); 2176 } 2177 2178 /// 2179 version(gmp_test) unittest { 2180 auto prime = 33_391.Z; 2181 for (int i = 0; i < 20; ++i) 2182 { 2183 prime = nextPrime(prime); 2184 for (auto order = WordOrder.min; order < WordOrder.max; ++order) 2185 { 2186 for (auto endianess = WordEndianess.min; endianess < WordEndianess.max; ++endianess) 2187 { 2188 ubyte[] data = prime.serialize!(ubyte)(order, endianess, 0); 2189 const samePrime = Z(data, order, 1, endianess, 0); 2190 assert(prime == samePrime); 2191 } 2192 } 2193 } 2194 } 2195 2196 /// opBinary with r-value right-hand-side 2197 version(gmp_test) @safe @nogc unittest { 2198 const Z a = 42; 2199 { 2200 const Z b = a + 1.Z; // r-value `rhs` 2201 assert(b == 43); 2202 } 2203 2204 { 2205 const Z b = a - 1.Z; // r-value `rhs` 2206 assert(b == 41); 2207 } 2208 2209 { 2210 const Z b = a * 2.Z; // r-value `rhs` 2211 assert(b == 84); 2212 } 2213 2214 { 2215 const Z b = a / 2.Z; // r-value `rhs` 2216 assert(b == 21); 2217 } 2218 2219 { 2220 const Z b = a % 10.Z; // r-value `rhs` 2221 assert(b == 2); 2222 } 2223 } 2224 2225 /// 2226 version(gmp_test) @safe unittest { 2227 const _ = (cast(uint)42).Z; 2228 const a = 42.Z; 2229 const b = 43UL.Z; 2230 const c = 43.0.Z; 2231 const z = 0.Z; 2232 2233 // `opOpAssign` with `Unsigned` 2234 auto w = 42.Z; 2235 assert(w == 42); 2236 2237 w += 100UL; 2238 assert(w == 142); 2239 2240 w -= 100.Z; 2241 assert(w == 42); 2242 2243 w += 100UL; 2244 assert(w == 142); 2245 2246 w -= 100UL; 2247 assert(w == 42); 2248 2249 w *= 100UL; 2250 assert(w == 4200); 2251 2252 w /= 100UL; 2253 assert(w == 42); 2254 2255 w %= 10UL; 2256 assert(w == 2); 2257 2258 w ^^= 6UL; 2259 assert(w == 64); 2260 2261 w = 42; 2262 assert(w == 42); 2263 2264 w += 100; 2265 assert(w == 142); 2266 2267 w -= 100; 2268 assert(w == 42); 2269 2270 w *= 100; 2271 assert(w == 4200); 2272 2273 w /= 100; 2274 assert(w == 42); 2275 2276 w *= 100; 2277 assert(w == 4200); 2278 2279 w /= -100; 2280 assert(w == -42); 2281 2282 w *= -1; 2283 assert(w == 42); 2284 2285 w %= 10; 2286 assert(w == 2); 2287 2288 w = 2; 2289 w ^^= 6; 2290 assert(w == 64); 2291 2292 w = 32.0; 2293 assert(w == 32); 2294 2295 w = 42UL; 2296 assert(w == 42); 2297 2298 w /= 2.Z; 2299 assert(w == 21); 2300 2301 w /= -2.Z; 2302 assert(w == -10); 2303 2304 w *= -2.Z; 2305 assert(w == 20); 2306 2307 w %= 3.Z; 2308 assert(w == 2); 2309 2310 w *= -1.Z; 2311 assert(w == -2); 2312 2313 w /= -1.Z; 2314 assert(w == 2); 2315 2316 // equality 2317 assert(z == 0); 2318 assert(z == cast(uint)0); 2319 assert(z == 0L); 2320 assert(z == 0UL); 2321 assert(z == 0.0f); 2322 assert(z == 0.0); 2323 2324 // eval cast 2325 2326 assert(a); 2327 assert(cast(ulong)a == a); 2328 assert(cast(ulong)a == 42); 2329 assert(cast(long)a == a); 2330 assert(cast(long)a == 42); 2331 assert(cast(double)a == 42.0); 2332 2333 // binary 2334 2335 assert(`0b11`.Z == 3); 2336 assert(`0B11`.Z == 3); 2337 assert(Z.fromBinaryString(`11`) == 3); 2338 assert(Z.fromBinaryString(`0b11`) == 3); 2339 assert(Z.fromBinaryString(`0B11`) == 3); 2340 2341 // octal 2342 2343 assert(`07`.Z == 7); 2344 assert(`010`.Z == 8); 2345 2346 // hexadecimal 2347 2348 assert(`0x10`.Z == 16); 2349 assert(`0X10`.Z == 16); 2350 assert(Z(`10`, 16) == 16); 2351 assert(Z.fromHexString(`10`) == 16); 2352 assert(Z.fromHexString(`0x10`) == 16); 2353 assert(Z.fromHexString(`0X10`) == 16); 2354 2355 // decimal 2356 2357 assert(`101`.Z == 101); 2358 assert(`101`.Z == 101); 2359 2360 const ic = 101UL.Z; 2361 2362 assert(a == a.dup); 2363 assert(ic == ic.dup); 2364 2365 // equality 2366 2367 assert(a == a); 2368 assert(a == 42.Z); 2369 assert(a == 42.0); 2370 assert(a == 42); 2371 assert(a == cast(uint)42); 2372 assert(a == 42UL); 2373 assert(_ == 42); 2374 assert(c == 43.0); 2375 2376 // non-equality 2377 2378 assert(a != b); 2379 2380 // less than 2381 2382 assert(a < b); 2383 assert(a < 43.Z); 2384 assert(a < 43); 2385 assert(a < cast(uint)43); 2386 assert(a < 43UL); 2387 assert(a < 43.0); 2388 2389 assert(-1.Z < 0.Z); 2390 assert(-1.Z < 0L); 2391 assert(-1.Z < 0UL); 2392 assert(-1.Z < 0.0); 2393 2394 // greater than 2395 2396 assert(b > a); 2397 assert(b > 42.Z); 2398 assert(b > 42); 2399 assert(b > cast(uint)42); 2400 assert(b > 42UL); 2401 assert(b > 42.0); 2402 2403 assert(+1.Z > 0.Z); 2404 assert(+1.Z > 0L); 2405 assert(+1.Z > 0UL); 2406 assert(+1.Z > 0.0); 2407 2408 // absolute value 2409 2410 assert(abs(a) == a); // free function 2411 assert(a.abs == a); // UFCS 2412 assert(abs(-42.Z) == 42); 2413 assert(abs(-a) == a); 2414 2415 // absolute value comparison 2416 2417 assert(cmpabs(-43.Z, 44.Z) == -1); 2418 assert(cmpabs(-43.Z, -44.Z) == -1); 2419 assert(cmpabs(-44.Z, -43.Z) == +1); 2420 assert(cmpabs(-43.Z, -43.Z) == 0); 2421 2422 assert(cmpabs(-43.Z, 44.0) == -1); 2423 assert(cmpabs(-43.Z, -44.0) == -1); 2424 assert(cmpabs(-44.Z, -43.0) == +1); 2425 assert(cmpabs(-43.Z, -43.0) == 0); 2426 2427 assert(cmpabs(-43.Z, 44) == -1); 2428 assert(cmpabs( 43.Z, 44) == -1); 2429 assert(cmpabs(-44.Z, 43) == +1); 2430 assert(cmpabs( 44.Z, 43) == +1); 2431 assert(cmpabs(-43.Z, 43) == 0); 2432 2433 Z _43 = 43; 2434 Z _4 = 4; 2435 Z _24 = 24; 2436 2437 // next prime 2438 assert(nextPrime(_4) == 5); 2439 assert(nextPrime(24.Z) == 29); 2440 2441 assert(nextPrime(_24) == 29); 2442 assert(nextPrime(24.Z) == 29); 2443 assert(24.Z.nextPrime() == 29); 2444 2445 assert(nextPrime(_43) == 47); 2446 assert(nextPrime(43.Z) == 47); 2447 assert(43.Z.nextPrime() == 47); 2448 2449 // greatest common divisor 2450 2451 assert(gcd(43.Z, 44.Z) == 1); 2452 assert(gcd(4.Z, 24.Z) == 4); 2453 assert(gcd(6.Z, 24.Z) == 6); 2454 assert(gcd(10.Z, 100.Z) == 10); 2455 2456 assert(gcd(43.Z, 44) == 1); 2457 assert(gcd(4.Z, 24) == 4); 2458 assert(gcd(6.Z, 24) == 6); 2459 assert(gcd(10.Z, 100) == 10); 2460 2461 assert(gcd(_43, 44) == 1); 2462 assert(gcd(_4, 24) == 4); 2463 assert(gcd(_4, _24) == 4); 2464 assert(gcd(_4, 24.Z) == 4); 2465 2466 // least common multiple 2467 2468 assert(lcm(43.Z, 44.Z) == 1892); 2469 assert(lcm(4.Z, 24.Z) == 24); 2470 assert(lcm(6.Z, 24.Z) == 24); 2471 assert(lcm(10.Z, 100.Z) == 100); 2472 2473 assert(lcm(43.Z, 44) == 1892); 2474 assert(lcm(4.Z, 24) == 24); 2475 assert(lcm(6.Z, 24) == 24); 2476 assert(lcm(10.Z, 100) == 100); 2477 2478 assert(lcm(_43, 44) == 1892); 2479 assert(lcm(_4, 24) == 24); 2480 assert(lcm(_4, _24) == 24); 2481 assert(lcm(_4, 24.Z) == 24); 2482 2483 // negated value 2484 2485 assert(-a == -42); 2486 assert(-(-a) == a); 2487 2488 auto n = 42.Z; 2489 n.negate(); 2490 assert(n == -42); 2491 n.negate(); 2492 assert(n == 42); 2493 n.negate(); 2494 assert(n == -42); 2495 n.absolute(); 2496 assert(n == 42); 2497 n.absolute(); 2498 assert(n == 42); 2499 2500 n.onesComplementSelf(); 2501 assert(n == -43); 2502 assert(onesComplement(n) == 42); 2503 assert(onesComplement(-43.Z) == 42); 2504 assert(com(n) == 42); 2505 assert(com(-43.Z) == 42); 2506 2507 /*TODO: figure out why this call doesn’t trigger a warn-unused warning when 2508 * the functions below returning `S` above does */ 2509 onesComplement(42.Z); 2510 static if (false) { 2511 struct S(T) { 2512 T x; 2513 T* xp; // this prevents diagnostics 2514 } 2515 static S!int f()() @safe pure nothrow @nogc { return typeof(return).init; } 2516 static S!int g()(scope S!int x) @safe pure nothrow @nogc { return x; } 2517 static const(S!int) h1()(scope const(S!int) x) @safe pure nothrow @nogc { return x; } 2518 static S!int h2()(scope const(S!int) _) @safe pure nothrow @nogc { return typeof(return).init; } 2519 g(S!int(32)); 2520 f(); 2521 h1(S!int(32)); 2522 h2(S!int(32)); 2523 } 2524 2525 // addition 2526 2527 assert(a + b == b + a); // commutative 2528 assert(a + 43.Z == b + a); 2529 assert(a - 43.Z == -(43.Z - a)); 2530 assert(a + 0 == a); 2531 assert(a + 1 != a); 2532 assert(0 + a == a); 2533 assert(1 + a != a); 2534 assert(a + 0UL == a); 2535 assert(a + 1UL != a); 2536 assert(a + b == 42 + 43); 2537 assert(1 + a == 43); 2538 assert(a + (-1) == 41); 2539 assert(1UL + a == 43); 2540 assert(a + 1 == 1 + a); // commutative 2541 assert(a + (-1) == (-1) + a); // commutative 2542 assert(1UL + a == a + 1UL); // commutative 2543 2544 // subtraction 2545 2546 assert(a - 2 == 40); 2547 assert(2 - a == -40); 2548 assert(-2 - a == -44); 2549 assert(a - 2 == -(2 - a)); // commutative 2550 assert(a - (-2) == 44); 2551 assert(44UL - 42.Z == 2); 2552 2553 // multiplication 2554 2555 assert(a * 1UL == a); 2556 assert(a * 1 == a); 2557 assert(1 * a == a); 2558 assert(1UL * a == a); 2559 assert((-1) * a == -a); 2560 assert(a * 2 != a); 2561 assert(a * -2 == -(2*a)); 2562 assert(a * b == b * a); 2563 assert(a * b == 42UL * 43UL); 2564 2565 // division 2566 2567 assert(27.Z / 3.Z == 9); 2568 assert(27.Z / 3 == 9); 2569 2570 assert(27.Z / 10.Z == 2); 2571 assert(27.Z / 10 == 2); 2572 assert(27.Z / 10UL == 2); 2573 2574 assert(27.Z % 10UL == 7); 2575 2576 assert(27.Z / -3 == -9); 2577 assert(27.Z / 3UL == 9); 2578 2579 assert(27.Z / -10 == -2); 2580 2581 assert(28 / 3.Z == 9); 2582 assert(28UL / 3.Z == 9); 2583 2584 assert(28 / -3.Z == -9); 2585 assert(28UL / -3.Z == -9); 2586 2587 // modulo/remainder 2588 2589 assert(27.Z % 3.Z == 0); 2590 assert(27.Z % 10.Z == 7); 2591 2592 assert(27.Z % 3 == 0); 2593 assert(-27.Z % 3 == 0); 2594 2595 assert(27.Z % 10 == 7); 2596 assert(27.Z % 10 == 7); 2597 2598 assert(28 % 3.Z == 1); 2599 assert(28UL % 3.Z == 1); 2600 2601 assert( 28.Z % -3 == -1); // negative divisor gives negative remainder according to https://en.wikipedia.org/wiki/Remainder 2602 assert(-28.Z % 3 == 1); // dividend sign doesn't affect remainder 2603 2604 assert( 28.Z % -3.Z == -1); 2605 assert(-28.Z % 3.Z == 2); 2606 assert( 28 % -3.Z == 1); 2607 assert(-28 % 3.Z == -1); 2608 2609 // modulo/remainder 2610 2611 const one = 1.Z; 2612 const two = 2.Z; 2613 const three = 3.Z; 2614 const four = 4.Z; 2615 const five = 5.Z; 2616 const six = 6.Z; 2617 assert(six % one == 0); 2618 assert(six % two == 0); 2619 assert(six % three == 0); 2620 assert(six % four == 2); 2621 assert(six % five == 1); 2622 assert(six % six == 0); 2623 2624 // subtraction 2625 2626 assert(six - one == 5); 2627 assert(six - 1UL == 5); 2628 assert(six - 1 == 5); 2629 assert(1 - six == -5); 2630 assert(1L - six == -5); 2631 assert(1UL - six == -5); 2632 2633 // exponentiation 2634 assert(0.Z^^0 == 1); 2635 assert(3.Z^^3 == 27); 2636 assert(3.Z^^3L == 27); 2637 assert(2.Z^^8 == 256); 2638 assert(2.Z^^8L == 256); 2639 assert(2.Z^^8UL == 256); 2640 2641 assert(Z.pow(2UL, 8UL) == 256); 2642 assert(Z.pow(2UL, 8) == 256); 2643 assert(Z.pow(2UL, 8) == 256); 2644 assert(Z.pow(2, 8) == 256); 2645 assert(Z.pow(-2, 8) == 256); 2646 assert(Z.pow(-2, 7) == -128); 2647 2648 // disallow power exponent to be an `MpZ` 2649 assert(!__traits(compiles, 2^^8.Z == 256)); 2650 assert(!__traits(compiles, 2L^^8.Z == 256)); 2651 assert(!__traits(compiles, 2UL^^8.Z == 256)); 2652 2653 // exponentiation plus modulus 2654 2655 assert(2.Z.powm(8.Z, 8.Z) == 0.Z); 2656 assert(2.Z.powm(3.Z, 16.Z) == 8.Z); 2657 assert(3.Z.powm(3.Z, 16.Z) == 11.Z); 2658 2659 assert(2.Z.powm(8, 8.Z) == 0.Z); 2660 assert(2.Z.powm(3, 16.Z) == 8.Z); 2661 assert(3.Z.powm(3, 16.Z) == 11.Z); 2662 2663 // modular multiplicative inverse 2664 assert(3.Z.invert(26.Z) == 9.Z); // r-value `base` 2665 assert(3.Z.invert(-26.Z) == 9.Z); // r-value `base` 2666 { 2667 auto base = 3.Z; 2668 assert(base.invert(26.Z) == 9.Z); // l-value `base` and r-value `mod` 2669 } 2670 { 2671 auto base = 3.Z; 2672 auto mod = 26.Z; 2673 assert(base.invert(mod) == 9.Z); // l-value `base` and l-value `mod 2674 } 2675 2676 // bitwise and, or and xor 2677 2678 { 2679 foreach (immutable i; 0 .. 10) 2680 { 2681 foreach (immutable j; 0 .. 10) 2682 { 2683 assert((i.Z & j.Z) == (i & j)); 2684 assert((i.Z | j.Z) == (i | j)); 2685 assert((i.Z ^ j.Z) == (i ^ j)); 2686 2687 Z x = null; 2688 2689 x = i.Z; 2690 x &= j.Z; 2691 assert(x == (i & j)); 2692 2693 x = i.Z; 2694 x |= j.Z; 2695 assert(x == (i | j)); 2696 2697 x = i.Z; 2698 x ^= j.Z; 2699 assert(x == (i ^ j)); 2700 } 2701 } 2702 } 2703 2704 // swap 2705 2706 auto x = 42.Z; 2707 auto y = 43.Z; 2708 2709 assert(x == 42); 2710 assert(y == 43); 2711 2712 x.swap(y); 2713 2714 assert(y == 42); 2715 assert(x == 43); 2716 2717 swap(x, y); 2718 2719 assert(x == 42); 2720 assert(y == 43); 2721 2722 assert(null.Z.fromString("42") == 42.Z); 2723 assert(null.Z.fromString("42") < 43.Z); 2724 assert(null.Z.fromString("42") > 41.Z); 2725 assert(null.Z.fromString("42") == 42); 2726 assert(null.Z.fromString("11", 2) == 3); 2727 assert(null.Z.fromString("7", 8) == 7); 2728 assert(null.Z.fromString("7") == 7); 2729 assert(null.Z.fromString("e", 16) == 14); 2730 assert(null.Z.fromString("f", 16) == 15); 2731 assert(null.Z.fromString("0xe") == 14); 2732 assert(null.Z.fromString("0xf") == 15); 2733 assert(null.Z.fromString("10", 16) == 16); 2734 assert(null.Z.fromString("10", 32) == 32); 2735 2736 // odd and even 2737 2738 assert(0.Z.isEven); 2739 assert(1.Z.isOdd); 2740 assert(2.Z.isEven); 2741 assert(3.Z.isOdd); 2742 2743 assert((-1).Z.isOdd); 2744 assert((-2).Z.isEven); 2745 assert((-3).Z.isOdd); 2746 2747 assert("300000000000000000000000000000000000000".Z.isEven); 2748 assert("300000000000000000000000000000000000001".Z.isOdd); 2749 assert("300000000000000000000000000000000000002".Z.isEven); 2750 assert("300000000000000000000000000000000000003".Z.isOdd); 2751 2752 // negative and positive 2753 2754 assert(0.Z.isPositive); 2755 assert(1.Z.isPositive); 2756 assert(2.Z.isPositive); 2757 assert(3.Z.isPositive); 2758 // TODO: assert(!(-1.Z.isPositive)); 2759 // TODO: assert(!(-2.Z.isPositive)); 2760 // TODO: assert(!(-3.Z.isPositive)); 2761 // TODO: assert(-1.Z.isNegative); 2762 // TODO: assert(-2.Z.isNegative); 2763 // TODO: assert(-3.Z.isNegative); 2764 // TODO: assert(!(1.Z.isNegative)); 2765 // TODO: assert(!(2.Z.isNegative)); 2766 // TODO: assert(!(3.Z.isNegative)); 2767 2768 foreach (const p; 1 .. 10) 2769 { 2770 assert((p^^2).Z.isPerfectSquare); 2771 assert(!(p^^2 + 1).Z.isPerfectSquare); 2772 foreach (const q; 2 .. 5) 2773 assert((p^^q).Z.isPerfectPower); 2774 } 2775 2776 foreach (const d; 1UL .. 10UL) 2777 { 2778 assert( d.Z.isDivisibleBy(d)); 2779 assert( d.Z.isDivisibleBy(d.Z)); 2780 assert(!d.Z.isDivisibleBy(d + 1)); 2781 assert(!d.Z.isDivisibleBy((d + 1).Z)); 2782 } 2783 assert( 1.Z.isDivisibleBy(1.Z)); 2784 assert( 2.Z.isDivisibleBy(1.Z)); 2785 assert(!1.Z.isDivisibleBy(2.Z)); 2786 assert(!3.Z.isDivisibleBy(2.Z)); 2787 assert( 100.Z.isDivisibleBy(10.Z)); 2788 assert( 100.Z.isDivisibleBy(10UL)); 2789 2790 assert((-1).Z.isNegative); 2791 assert((-2).Z.isNegative); 2792 assert((-3).Z.isNegative); 2793 2794 // sign function (sgn) 2795 2796 assert(long.min.Z.sgn == -1); 2797 assert(int.min.Z.sgn == -1); 2798 assert(-2.Z.sgn == -1); 2799 assert(-1.Z.sgn == -1); 2800 assert( 0.Z.sgn == 0); 2801 assert( 1.Z.sgn == 1); 2802 assert( 2.Z.sgn == 1); 2803 assert(int.max.Z.sgn == 1); 2804 assert(long.max.Z.sgn == 1); 2805 2806 assert(!long.min.Z.isZero); 2807 assert(!int.min.Z.isZero); 2808 assert(!(-2).Z.isZero); 2809 assert(!(-1).Z.isZero); 2810 assert( 0.Z.isZero); 2811 assert(! 1.Z.isZero); 2812 assert(! 2.Z.isZero); 2813 assert(!int.max.Z.isZero); 2814 assert(!long.max.Z.isZero); 2815 2816 assert(!long.min.Z.isOne); 2817 assert(!int.min.Z.isOne); 2818 assert(!(-2).Z.isOne); 2819 assert(!(-1).Z.isOne); 2820 assert(!0.Z.isOne); 2821 assert( 1.Z.isOne); 2822 assert(! 2.Z.isOne); 2823 assert(!int.max.Z.isOne); 2824 assert(!long.max.Z.isOne); 2825 2826 assert(0.Z.populationCount == 0); 2827 assert(1.Z.populationCount == 1); 2828 assert(2.Z.populationCount == 1); 2829 assert(3.Z.populationCount == 2); 2830 assert(4.Z.populationCount == 1); 2831 assert(5.Z.populationCount == 2); 2832 assert(6.Z.populationCount == 2); 2833 assert(7.Z.populationCount == 3); 2834 2835 // TODO 2836 // { 2837 // Z g = null; 2838 // assert(!b.testBit(0)); 2839 // g.setBit(0); 2840 // assert(b.testBit(0)); 2841 // g.clearBit(0); 2842 // assert(!b.testBit(0)); 2843 // } 2844 2845 // fits in type 2846 2847 foreach (Integral; AliasSeq!(short, int, long, 2848 ushort, uint, ulong)) 2849 { 2850 assert(Integral.min.Z.fitsIn!Integral); 2851 assert(Integral.max.Z.fitsIn!Integral); 2852 } 2853 2854 // TODO 2855 // assert(short.min.Z.fitsIn!short); 2856 // assert(short.max.Z.fitsIn!short); 2857 // assert(ushort.min.Z.fitsIn!ushort); 2858 // assert(ushort.max.Z.fitsIn!ushort); 2859 2860 // limb count 2861 2862 assert(0.Z.limbCount == 0); 2863 assert(1.Z.limbCount == 1); 2864 assert(2.Z.limbCount == 1); 2865 2866 assert(Z.pow(2UL, 32UL).limbCount == 1); 2867 2868 assert(Z.pow(2UL, 63UL).limbCount == 1); 2869 assert(Z.pow(2UL, 63UL + 1).limbCount == 2); 2870 2871 assert(Z.pow(2UL, 127UL).limbCount == 2); 2872 assert(Z.pow(2UL, 127UL + 1).limbCount == 3); 2873 2874 assert(Z.pow(2UL, 255UL).limbCount == 4); 2875 assert(Z.pow(2UL, 255UL + 1).limbCount == 5); 2876 } 2877 2878 /// generators 2879 version(gmp_test) @safe @nogc unittest { 2880 assert(Z.mersennePrime(15) == 2^^15 - 1); 2881 assert(Z.mersennePrime(15UL) == 2^^15 - 1); 2882 } 2883 2884 /// left shift 2885 version(gmp_test) @safe @nogc unittest { 2886 assert(1.Z << 1.Z == 2^^1); 2887 assert(1.Z << 2.Z == 2^^2); 2888 assert(1.Z << 32.Z == 2UL^^32); 2889 assert(1.Z << 63.Z == 2UL^^63); 2890 assert(16.Z << -3.Z == 2); // `16 << -3` becomes `16 >> 3` 2891 2892 assert(1.Z << 1U == 2^^1); 2893 assert(1.Z << 2U == 2^^2); 2894 assert(1.Z << 32U == 2UL^^32); 2895 assert(1.Z << 63U == 2UL^^63); 2896 assert(16.Z << -3 == 2); // `16 << -3` becomes `16 >> 3` 2897 2898 Z a; 2899 a = 1; 2900 a <<= 1u; 2901 assert(a == 2^^1); 2902 a = 1; 2903 a <<= 2u; 2904 assert(a == 2^^2); 2905 a = 1; 2906 a <<= 32u; 2907 assert(a == 2UL^^32); 2908 a = 1; 2909 a <<= 63u; 2910 assert(a == 2UL^^63); 2911 a = 16; 2912 a <<= -3; 2913 assert(a == 2); 2914 2915 Z b; 2916 a = 1; 2917 b = 1; 2918 a <<= b; 2919 assert(a == 2^^1); 2920 a = 1; 2921 b = 2; 2922 a <<= b; 2923 assert(a == 2^^2); 2924 a = 1; 2925 b = 32; 2926 a <<= b; 2927 assert(a == 2UL^^32); 2928 a = 1; 2929 b = 63; 2930 a <<= b; 2931 assert(a == 2UL^^63); 2932 a = 16; 2933 b = -3; 2934 a <<= b; 2935 assert(a == 2); 2936 } 2937 2938 /// right shift 2939 version(gmp_test) @safe @nogc unittest { 2940 assert(0x4.Z >> 1.Z == 0x2); 2941 assert(0x4.Z >> 2.Z == 0x1); 2942 assert(0x4.Z >> 3.Z == 0x0); 2943 assert(0x123456789ABCDEF.Z >> 4.Z == 0x123456789ABCDEuL); 2944 assert(0xABCDEF.Z >> 8.Z == 0xABCD); 2945 assert(0x1234ABCDEF.Z >> 32.Z == 0x12); 2946 assert(2.Z >> -3.Z == 16); // `2 >> -3` becomes `2 << 3` 2947 2948 assert(0x4.Z >> 1 == 0x2); 2949 assert(0x4.Z >> 2 == 0x1); 2950 assert(0x4.Z >> 3 == 0x0); 2951 assert(0x123456789ABCDEF.Z >> 4 == 0x123456789ABCDEuL); 2952 assert(0xABCDEF.Z >> 8 == 0xABCD); 2953 assert(0x1234ABCDEF.Z >> 32 == 0x12); 2954 assert(2.Z >> -3 == 16); 2955 2956 Z a, b; 2957 a = 4; 2958 a >>= 1; 2959 assert(a == 0x2); 2960 a = 4; 2961 a >>= 2; 2962 assert(a == 0x1); 2963 a = 4; 2964 a >>= 3; 2965 assert(a == 0x0); 2966 a = 0x123456789ABCDEF; 2967 a >>= 4; 2968 assert(a == 0x123456789ABCDEuL); 2969 a = 0xABCDEF; 2970 a >>= 8; 2971 assert(a == 0xABCD); 2972 a = 0x1234ABCDEF; 2973 a >>= 32; 2974 assert(a == 0x12); 2975 a = 2; 2976 a >>= -3; 2977 assert(a == 16); 2978 2979 a = 4; 2980 b = 1; 2981 a >>= b; 2982 assert(a == 0x2); 2983 a = 4; 2984 b = 2; 2985 a >>= b; 2986 assert(a == 0x1); 2987 a = 4; 2988 b = 3; 2989 a >>= b; 2990 assert(a == 0x0); 2991 a = 0x123456789ABCDEF; 2992 b = 4; 2993 a >>= b; 2994 assert(a == 0x123456789ABCDEuL); 2995 a = 0xABCDEF; 2996 b = 8; 2997 a >>= b; 2998 assert(a == 0xABCD); 2999 a = 0x1234ABCDEF; 3000 b = 32; 3001 a >>= b; 3002 assert(a == 0x12); 3003 a = 2; 3004 b = -3; 3005 a >>= b; 3006 assert(a == 16); 3007 3008 } 3009 3010 /// verify compliance with Phobos' `BigInt` 3011 version(gmp_test) @safe unittest { 3012 alias bigInt = mpz; 3013 alias BigInt = Z; // Phobos naming convention 3014 3015 { 3016 const BigInt a = "9588669891916142"; 3017 const BigInt b = "7452469135154800"; 3018 const c = a * b; 3019 assert(c == BigInt("71459266416693160362545788781600")); 3020 auto d = b * a; 3021 assert(d == BigInt("71459266416693160362545788781600")); 3022 assert(d == c); 3023 d = c * BigInt("794628672112"); 3024 assert(d == BigInt("56783581982794522489042432639320434378739200")); 3025 auto e = c + d; 3026 assert(e == BigInt("56783581982865981755459125799682980167520800")); 3027 const f = d + c; 3028 assert(f == e); 3029 auto g = f - c; 3030 assert(g == d); 3031 g = f - d; 3032 assert(g == c); 3033 e = 12_345_678; 3034 g = c + e; 3035 const h = g / b; 3036 const i = g % b; 3037 assert(h == a); 3038 assert(i == e); 3039 BigInt j = "-0x9A56_57f4_7B83_AB78"; 3040 j ^^= 11UL; 3041 j ^^= 2L; 3042 j ^^= 2; 3043 } 3044 3045 { 3046 auto b = BigInt("1_000_000_000"); 3047 3048 b += 12_345; 3049 assert(b == 1_000_012_345); 3050 b += -12_345; 3051 assert(b == 1_000_000_000); 3052 3053 b -= -12_345; 3054 assert(b == 1_000_012_345); 3055 b -= +12_345; 3056 assert(b == 1_000_000_000); 3057 3058 b += 12_345; 3059 assert(b == 1_000_012_345); 3060 3061 b /= 5UL; 3062 assert(b == 200_002_469); 3063 } 3064 3065 { 3066 auto x = BigInt("123"); 3067 const y = BigInt("321"); 3068 x += y; 3069 assert(x == 444); 3070 } 3071 3072 { 3073 const x = BigInt("123"); 3074 const y = BigInt("456"); 3075 const BigInt z = x * y; 3076 assert(z == 56_088); 3077 } 3078 3079 { 3080 auto x = BigInt("123"); 3081 x *= 300; 3082 assert(x == 36_900); 3083 } 3084 3085 { 3086 auto x = BigInt("123"); 3087 x *= -1; 3088 assert(x == -123); 3089 } 3090 3091 { 3092 const x = BigInt("1_000_000_500"); 3093 3094 immutable ulong ul = 2_000_000UL; 3095 immutable uint ui = 500_000; 3096 immutable ushort us = 30_000; 3097 immutable ubyte ub = 50; 3098 3099 immutable long l = 1_000_000L; 3100 immutable int i = 500_000; 3101 immutable short s = 30_000; 3102 immutable byte b = 50; 3103 3104 static assert(is(typeof(x % ul) == ulong)); 3105 static assert(is(typeof(x % ui) == uint)); 3106 static assert(is(typeof(x % us) == ushort)); 3107 static assert(is(typeof(x % ub) == ubyte)); 3108 3109 static assert(is(typeof(x % l) == long)); 3110 static assert(is(typeof(x % i) == int)); 3111 // TODO: static assert(is(typeof(x % s) == short)); 3112 // TODO: static assert(is(typeof(x % b) == byte)); 3113 3114 assert(x % ul == 500); 3115 assert(x % ui == 500); 3116 assert(x % us == 10_500); 3117 assert(x % ub == 0); 3118 3119 assert(x % l == 500L); 3120 assert(x % i == 500); 3121 assert(x % s == 10_500); 3122 assert(x % b == 0); 3123 } 3124 3125 { 3126 const x = BigInt("100"); 3127 const BigInt y = 123 + x; 3128 assert(y == BigInt("223")); 3129 3130 const BigInt z = 123 - x; 3131 assert(z == BigInt("23")); 3132 3133 // Dividing a built-in integer type by BigInt always results in 3134 // something that fits in a built-in type, so the built-in type is 3135 // returned, not BigInt. 3136 static assert(is(typeof(1000 / x) == int)); 3137 assert(1000 / x == 10); 3138 } 3139 3140 { 3141 auto x = BigInt("1234"); 3142 assert(+x == BigInt(" 1234")); 3143 assert(-x == BigInt("-1234")); 3144 ++x; 3145 assert(x == BigInt("1235")); 3146 --x; 3147 assert(x == BigInt("1234")); 3148 } 3149 3150 { 3151 const x = BigInt("12345"); 3152 const y = BigInt("12340"); 3153 immutable int z = 12_345; 3154 immutable int w = 54_321; 3155 assert(x == x); 3156 assert(x != y); 3157 assert(x == y + 5); 3158 assert(x == z); 3159 assert(x != w); 3160 } 3161 3162 { 3163 // non-zero values are regarded as `true` 3164 const x = BigInt("1"); 3165 const y = BigInt("10"); 3166 assert(x); 3167 assert(y); 3168 3169 // zero value is regarded as `false` 3170 const z = BigInt("0"); 3171 assert(!z); 3172 } 3173 3174 { 3175 assert(cast(int)BigInt("0") == 0); 3176 assert(cast(ubyte)BigInt("0") == 0); 3177 3178 assert(cast(ubyte)BigInt(255) == 255); 3179 assert(cast(ushort)BigInt(65_535) == 65_535); 3180 assert(cast(uint)BigInt(uint.max) == uint.max); 3181 assert(cast(ulong)BigInt(ulong.max) == ulong.max); 3182 3183 assert(cast(byte)BigInt(-128) == -128); 3184 assert(cast(short)BigInt(-32_768) == -32_768); 3185 assert(cast(int)BigInt(int.min) == int.min); 3186 assert(cast(long)BigInt(long.min) == long.min); 3187 3188 assert(cast(byte)BigInt(127) == 127); 3189 assert(cast(short)BigInt(32_767) == 32_767); 3190 assert(cast(int)BigInt(int.max) == int.max); 3191 assert(cast(long)BigInt(long.max) == long.max); 3192 3193 // TODO: 3194 // import std.conv : to, ConvOverflowException; 3195 // import std.exception : assertThrown; 3196 // assertThrown!ConvOverflowException(BigInt("256").to!ubyte); 3197 // assertThrown!ConvOverflowException(BigInt("-1").to!ubyte); 3198 } 3199 3200 { 3201 // TODO 3202 // segfaults because with double free 3203 // const(BigInt) x = BigInt("123"); 3204 // BigInt y = cast()x; // cast away const 3205 // assert(y == x); 3206 } 3207 3208 { 3209 const x = BigInt("100"); 3210 const y = BigInt("10"); 3211 const int z = 50; 3212 const int w = 200; 3213 assert(y < x); 3214 assert(x > z); 3215 assert(z > y); 3216 assert(x < w); 3217 } 3218 3219 { 3220 assert(BigInt("12345").toLong() == 12_345); 3221 assert(BigInt("-123450000000000000000000000000").toLong() == long.min); 3222 assert(BigInt("12345000000000000000000000000000").toLong() == long.max); 3223 } 3224 3225 { 3226 assert(BigInt("12345").toInt() == 12_345); 3227 assert(BigInt("-123450000000000000000000000000").toInt() == int.min); 3228 assert(BigInt("12345000000000000000000000000000").toInt() == int.max); 3229 } 3230 } 3231 3232 /// Fermats Little Theorem 3233 version(gmp_test) @safe @nogc unittest { 3234 version (unittestLong) 3235 { 3236 /* 3237 Fermats little theorem: a ^ p ≡ a (mod p) ∀ prime p check Fermats 3238 little theorem for a ≤ 100000 and all mersene primes M(p) : p ≤ 127 3239 */ 3240 foreach (immutable ulong i; [2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127]) 3241 { 3242 foreach (immutable ulong j; 2 .. 100_000) 3243 { 3244 const p = Z.mersennePrime(i); // power 3245 const a = Z(j); // base 3246 const amp = a % p; 3247 const b = a.powm(p, p); // result 3248 assert(b == amp); 3249 } 3250 } 3251 } 3252 } 3253 3254 // Euler's Sum of Powers Conjecture counter example 3255 version(gmp_test) pure @nogc unittest { 3256 /* 3257 a^5 + b^5 + c^5 + d^5 = e^5 Lander & Parkin, 1966 found the first counter 3258 example: 27^5 + 84^5 + 110^5 + 133^5 = 144^5. This test searches for this 3259 counter example by brute force for all positive a, b, c, d ≤ 144 3260 */ 3261 3262 enum LIMIT = 144 + 1; 3263 enum POWER = 5; 3264 3265 version (unittestLong) 3266 { 3267 bool found = false; 3268 Z r1 = 0; 3269 outermost: 3270 foreach (immutable ulong a; 1 .. LIMIT) 3271 { 3272 foreach (immutable ulong b; a .. LIMIT) 3273 { 3274 foreach (immutable ulong c; b .. LIMIT) 3275 { 3276 foreach (immutable ulong d; c .. LIMIT) 3277 { 3278 r1 = ((Z(a) ^^ POWER) + 3279 (Z(b) ^^ POWER) + 3280 (Z(c) ^^ POWER) + 3281 (Z(d) ^^ POWER)); 3282 Z rem = 0; 3283 __gmpz_rootrem(r1._ptr, rem._ptr, r1._ptr, POWER); // TODO: replace with call to D wrapper 3284 if (rem == 0UL) 3285 { 3286 debug printf("Counter Example Found: %lu^5 + %lu^5 + %lu^5 + %lu^5 = %lu^5\n", 3287 a, b, c, d, cast(ulong)r1); 3288 found = true; 3289 break outermost; 3290 } 3291 } 3292 } 3293 } 3294 } 3295 assert(found); 3296 } 3297 } 3298 3299 /// expression template types 3300 3301 /// `MpZ`-`MpZ` adding expression. 3302 private struct AddExpr(bool cow) 3303 { 3304 _Z!(cow) e1; // first term 3305 _Z!(cow) e2; // second term 3306 _Z!(cow) eval() const nothrow @nogc @trusted 3307 { 3308 version(LDC) pragma(inline, true); 3309 typeof(return) y = null; 3310 evalTo(y); 3311 return y; 3312 } 3313 void evalTo(ref _Z!(cow) y) const nothrow @nogc @trusted 3314 { 3315 version(LDC) pragma(inline, true); 3316 __gmpz_add(y._ptr, e1.eval()._ptr, e2.eval()._ptr); 3317 } 3318 } 3319 version(gmp_test) version(unittest) static assert(isMpZExpr!(AddExpr!(true))); 3320 3321 version(gmp_test) @safe @nogc unittest { 3322 assert(AddExpr!(false)(3.Z, 4.Z).eval() == 3 + 4); 3323 3324 const Z x = AddExpr!(false)(3.Z, 4.Z); 3325 assert(x == 7); 3326 3327 Z y = null; 3328 y = AddExpr!(false)(3.Z, 4.Z); 3329 assert(y == 7); 3330 3331 } 3332 3333 /// `MpZ`-`MpZ` subtraction expression. 3334 private struct SubExpr(bool cow) 3335 { 3336 _Z!(cow) e1; // first term 3337 _Z!(cow) e2; // second term 3338 _Z!(cow) eval() const nothrow @nogc @trusted // TODO: move to common place 3339 { 3340 version(LDC) pragma(inline, true); 3341 typeof(return) y = null; 3342 evalTo(y); 3343 return y; 3344 } 3345 void evalTo(ref _Z!(cow) y) const nothrow @nogc @trusted 3346 { 3347 version(LDC) pragma(inline, true); 3348 __gmpz_sub(y._ptr, e1.eval()._ptr, e2.eval()._ptr); 3349 } 3350 } 3351 version(gmp_test) version(unittest) static assert(isMpZExpr!(SubExpr!(false))); 3352 3353 version(gmp_test) @safe @nogc unittest { 3354 assert(SubExpr!(false)(3.Z, 4.Z).eval() == 3 - 4); 3355 const Z x = SubExpr!(false)(3.Z, 4.Z); 3356 assert(x == -1); 3357 } 3358 3359 /// `MpZ`-`MpZ` multiplication expression. 3360 private struct MulExpr(bool cow) 3361 { 3362 _Z!(cow) e1; // first factor 3363 _Z!(cow) e2; // second factor 3364 _Z!(cow) eval() const nothrow @nogc @trusted // TODO: move to common place 3365 { 3366 version(LDC) pragma(inline, true); 3367 typeof(return) y = null; 3368 evalTo(y); 3369 return y; 3370 } 3371 void evalTo(ref _Z!(cow) y) const nothrow @nogc @trusted 3372 { 3373 version(LDC) pragma(inline, true); 3374 __gmpz_mul(y._ptr, e1.eval()._ptr, e2.eval()._ptr); 3375 } 3376 } 3377 version(gmp_test) version(unittest) static assert(isMpZExpr!(MulExpr!(false))); 3378 3379 version(gmp_test) @safe @nogc unittest { 3380 assert(MulExpr!(false)(3.Z, 4.Z).eval() == 3 * 4); 3381 3382 const Z x = MulExpr!(false)(3.Z, 4.Z); 3383 assert(x == 12); 3384 } 3385 3386 /// `MpZ`-`MpZ` division expression. 3387 private struct DivExpr(bool cow) 3388 { 3389 _Z!(cow) e1; // divisor 3390 _Z!(cow) e2; // dividend 3391 _Z!(cow) eval() const nothrow @nogc @trusted // TODO: move to common place 3392 { 3393 version(LDC) pragma(inline, true); 3394 typeof(return) y = null; 3395 evalTo(y); 3396 return y; 3397 } 3398 void evalTo(ref _Z!(cow) y) const nothrow @nogc @trusted 3399 { 3400 version(LDC) pragma(inline, true); 3401 __gmpz_tdiv_q(y._ptr, e1.eval()._ptr, e2.eval()._ptr); 3402 } 3403 } 3404 version(gmp_test) version(unittest) static assert(isMpZExpr!(DivExpr!(false))); 3405 3406 version(gmp_test) @safe @nogc unittest { 3407 assert(DivExpr!(false)(27.Z, 3.Z).eval() == 27 / 3); 3408 assert(DivExpr!(false)(28.Z, 3.Z).eval() == 28 / 3); 3409 assert(DivExpr!(false)(29.Z, 3.Z).eval() == 29 / 3); 3410 assert(DivExpr!(false)(30.Z, 3.Z).eval() == 30 / 3); 3411 3412 const Z x = DivExpr!(false)(28.Z, 3.Z); 3413 assert(x == 9); 3414 } 3415 3416 /// `MpZ`-`MpZ` modulus expression. 3417 private struct ModExpr(bool cow) 3418 { 3419 _Z!(cow) e1; // divisor 3420 _Z!(cow) e2; // dividend 3421 _Z!(cow) eval() const nothrow @nogc @trusted // TODO: move to common place 3422 { 3423 version(LDC) pragma(inline, true); 3424 typeof(return) y = null; 3425 evalTo(y); 3426 return y; 3427 } 3428 void evalTo(ref _Z!(cow) y) const nothrow @nogc @trusted 3429 { 3430 version(LDC) pragma(inline, true); 3431 __gmpz_tdiv_r(y._ptr, e1.eval()._ptr, e2.eval()._ptr); 3432 } 3433 } 3434 version(gmp_test) version(unittest) static assert(isMpZExpr!(ModExpr!(false))); 3435 3436 version(gmp_test) @safe @nogc unittest { 3437 assert(ModExpr!(false)(27.Z, 3.Z).eval() == 27 % 3); 3438 assert(ModExpr!(false)(28.Z, 3.Z).eval() == 28 % 3); 3439 assert(ModExpr!(false)(29.Z, 3.Z).eval() == 29 % 3); 3440 assert(ModExpr!(false)(30.Z, 3.Z).eval() == 30 % 3); 3441 3442 const Z x = ModExpr!(false)(29.Z, 3.Z); 3443 assert(x == 2); 3444 } 3445 3446 /// `MpZ`-`ulong` power expression. 3447 private struct PowUExpr(P, Q) 3448 if (isMpZExpr!P && 3449 __traits(isUnsigned, Q)) 3450 { 3451 P e1; // base 3452 Q e2; // exponent 3453 MpZ eval() const nothrow @nogc @trusted // TODO: move to common place 3454 { 3455 version(LDC) pragma(inline, true); 3456 typeof(return) y = null; 3457 evalTo(y); 3458 return y; 3459 } 3460 void evalTo(ref MpZ y) const nothrow @nogc @trusted 3461 { 3462 version(LDC) pragma(inline, true); 3463 __gmpz_pow_ui(y._ptr, e1.eval()._ptr, e2); 3464 } 3465 } 3466 version(gmp_test) version(unittest) static assert(isMpZExpr!(PowUExpr!(MpZ, ulong))); 3467 3468 version(gmp_test) @safe @nogc unittest { 3469 assert(PowUExpr!(Z, ulong)(3.Z, 3).eval() == 3^^3); 3470 } 3471 3472 /// `MpZ`-`ulong`-`MpZ` power-modulo expression. 3473 private struct PowMUExpr(P, Q, M) 3474 if (isMpZExpr!P && 3475 __traits(isUnsigned, Q) && 3476 isMpZExpr!M) 3477 { 3478 P base; // base 3479 Q exp; // exponent 3480 M mod; // modulo 3481 MpZ eval() const nothrow @nogc @trusted // TODO: move to common place 3482 { 3483 version(LDC) pragma(inline, true); 3484 typeof(return) y = null; 3485 evalTo(y); 3486 return y; 3487 } 3488 void evalTo(ref MpZ y) const nothrow @nogc @trusted 3489 { 3490 version(LDC) pragma(inline, true); 3491 __gmpz_powm_ui(y._ptr, base.eval()._ptr, exp, mod._ptr); 3492 } 3493 } 3494 version(gmp_test) version(unittest) static assert(isMpZExpr!(PowMUExpr!(MpZ, ulong, MpZ))); 3495 3496 version(gmp_test) @safe @nogc unittest { 3497 assert(PowMUExpr!(Z, ulong, Z)(3.Z, 3, 20.Z).eval() == 3^^3 % 20); 3498 } 3499 3500 /// `MpZ` negation expression. 3501 private struct NegExpr(bool cow) 3502 { 3503 _Z!(cow) e1; 3504 _Z!(cow) eval() const nothrow @nogc @trusted // TODO: move to common place 3505 { 3506 version(LDC) pragma(inline, true); 3507 typeof(return) y = null; 3508 evalTo(y); 3509 return y; 3510 } 3511 void evalTo(ref _Z!(cow) y) const nothrow @nogc @trusted 3512 { 3513 version(LDC) pragma(inline, true); 3514 __gmpz_neg(y._ptr, e1.eval()._ptr); 3515 } 3516 } 3517 version(gmp_test) version(unittest) static assert(isMpZExpr!(NegExpr!(false))); 3518 3519 version(gmp_test) @safe @nogc unittest { 3520 assert(NegExpr!(false)(27.Z).eval() == -27); 3521 const Z x = NegExpr!(false)(27.Z); 3522 assert(x == -27); 3523 } 3524 3525 /** `MpZ` square root expression. 3526 3527 See: https://gmplib.org/manual/Integer-Roots 3528 */ 3529 private struct SqrtExpr(bool cow) 3530 { 3531 _Z!(cow) e1; 3532 _Z!(cow) eval() const nothrow @nogc @trusted // TODO: move to common place 3533 { 3534 version(LDC) pragma(inline, true); 3535 typeof(return) y = null; 3536 evalTo(y); 3537 return y; 3538 } 3539 void evalTo(ref _Z!(cow) y) const nothrow @nogc @trusted 3540 { 3541 version(LDC) pragma(inline, true); 3542 __gmpz_sqrt(y._ptr, e1.eval()._ptr); 3543 } 3544 } 3545 version(gmp_test) version(unittest) static assert(isMpZExpr!(SqrtExpr!(false))); 3546 3547 version(gmp_test) @safe @nogc unittest { 3548 foreach (const n; 16 .. 25) 3549 assert(SqrtExpr!(false)(n.Z).eval() == 4); 3550 assert(SqrtExpr!(false)(25.Z).eval() == 5); 3551 } 3552 3553 // Copied from `std.numeric` to prevent unnecessary Phobos deps. 3554 private T _integralAbs(T)(scope const T x) @safe if (__traits(isIntegral, T)) { 3555 pragma(inline, true); 3556 return x >= 0 ? x : -x; 3557 } 3558 3559 /// copyable integer 3560 version(gmp_test) @trusted unittest { 3561 alias CZ = CopyableMpZ; 3562 3563 const CZ a = 42; 3564 3565 const CZ b = a; // copy 3566 assert(a == b); // should equal 3567 assert(a !is b); // but not the same 3568 3569 const CZ c = null; // other value 3570 assert(a != c); // should diff 3571 } 3572 3573 /// to string conversion 3574 version(gmp_test) pure @safe nothrow unittest { 3575 for (int i = -100; i < 100; ++i) 3576 { 3577 import std.conv : to; 3578 assert(i.Z.toString == i.to!string); 3579 } 3580 } 3581 3582 /// `isProbablyPrime` 3583 version(gmp_test) pure @safe nothrow @nogc unittest { 3584 static immutable ulong[] samplePrimes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41]; 3585 import std.algorithm.searching : canFind; 3586 foreach (const i; 2 .. 41) { 3587 const result = Z(i).isProbablyPrime(1); 3588 if (samplePrimes.canFind(i)) 3589 assert(result == 2); 3590 else 3591 assert(result == 0); 3592 } 3593 } 3594 3595 /// `isDefinitelyPrime` 3596 version(gmp_test) pure @safe nothrow @nogc unittest { 3597 static immutable ulong[] samplePrimes = [257, 65_537, 8_191, 131_071, 524_287, 2_147_483_647]; 3598 foreach (const i; samplePrimes) 3599 assert(Z(i).isDefinitelyPrime(1)); 3600 } 3601 3602 version(gmp_test) version(unittest) { 3603 // version = ccc; // do C mutation call count 3604 debug import core.stdc.stdio : printf; 3605 static assert(!isMpZExpr!int); 3606 import std.meta : AliasSeq; 3607 alias Z = MpZ; 3608 alias CZ = CopyableMpZ; 3609 alias RZ = _Z!(true); 3610 } 3611 3612 // C API 3613 package extern(C) pragma(inline, false) 3614 { 3615 alias __mp_limb_t = ulong; // see `mp_limb_t` gmp.h. TODO: detect when it is `uint` instead 3616 struct __mpz_struct 3617 { 3618 int _mp_alloc; /* Number of *limbs* allocated and pointed to by 3619 the _mp_d field. */ 3620 int _mp_size; /* abs(_mp_size) is the number of limbs the last 3621 field points to. If _mp_size is negative 3622 this is a negative number. */ 3623 __mp_limb_t* _mp_d; /* Pointer to the limbs. */ 3624 } 3625 static assert(__mpz_struct.sizeof == 16); // fits in two 64-bit words 3626 3627 alias mpz_srcptr = const(__mpz_struct)*; 3628 alias mpz_ptr = __mpz_struct*; 3629 alias mp_bitcnt_t = ulong; 3630 3631 pure nothrow @nogc: 3632 3633 void __gmpz_init(mpz_ptr); 3634 void __gmpz_init_set(mpz_ptr, mpz_srcptr); 3635 3636 void __gmpz_init_set_d(mpz_ptr, double); 3637 void __gmpz_init_set_si(mpz_ptr, long); 3638 void __gmpz_init_set_ui(mpz_ptr, ulong); 3639 int __gmpz_init_set_str(mpz_ptr, const char*, int); 3640 3641 void __gmpz_set(mpz_ptr rop, mpz_srcptr op); 3642 void __gmpz_set_ui(mpz_ptr rop, ulong op); 3643 void __gmpz_set_si(mpz_ptr rop, long op); 3644 void __gmpz_set_d(mpz_ptr rop, double op); 3645 int __gmpz_set_str(mpz_ptr, const char*, int); 3646 3647 void __gmpz_clear(mpz_ptr); 3648 3649 void __gmpz_abs(mpz_ptr, mpz_srcptr); 3650 void __gmpz_neg(mpz_ptr, mpz_srcptr); 3651 3652 void __gmpz_add(mpz_ptr, mpz_srcptr, mpz_srcptr); 3653 void __gmpz_add_ui(mpz_ptr, mpz_srcptr, ulong); 3654 void __gmpz_addmul(mpz_ptr, mpz_srcptr, mpz_srcptr); 3655 void __gmpz_addmul_ui(mpz_ptr, mpz_srcptr, ulong); 3656 3657 void __gmpz_sub(mpz_ptr, mpz_srcptr, mpz_srcptr); 3658 void __gmpz_sub_ui(mpz_ptr, mpz_srcptr, ulong); 3659 void __gmpz_ui_sub(mpz_ptr, ulong, mpz_srcptr); 3660 3661 void __gmpz_mul(mpz_ptr, mpz_srcptr, mpz_srcptr); 3662 void __gmpz_mul_2exp(mpz_ptr, mpz_srcptr, mp_bitcnt_t); 3663 void __gmpz_mul_si(mpz_ptr, mpz_srcptr, long); 3664 void __gmpz_mul_ui(mpz_ptr, mpz_srcptr, ulong); 3665 3666 void __gmpz_cdiv_q_ui(mpz_ptr, mpz_srcptr, ulong); 3667 ulong __gmpz_cdiv_r_ui(mpz_ptr, mpz_srcptr, ulong); 3668 void __gmpz_cdiv_qr_ui(mpz_ptr, mpz_ptr, mpz_srcptr, ulong); 3669 void __gmpz_cdiv_ui(mpz_srcptr, ulong); 3670 3671 void __gmpz_fdiv_q_ui(mpz_ptr, mpz_srcptr, ulong); 3672 ulong __gmpz_fdiv_r_ui(mpz_ptr, mpz_srcptr, ulong); 3673 void __gmpz_fdiv_qr_ui(mpz_ptr, mpz_ptr, mpz_srcptr, ulong); 3674 void __gmpz_fdiv_ui(mpz_srcptr, ulong); 3675 3676 void __gmpz_tdiv_q(mpz_ptr, mpz_srcptr, mpz_srcptr); 3677 void __gmpz_tdiv_r(mpz_ptr, mpz_srcptr, mpz_srcptr); 3678 void __gmpz_tdiv_q_ui(mpz_ptr, mpz_srcptr, ulong); 3679 ulong __gmpz_tdiv_r_ui(mpz_ptr, mpz_srcptr, ulong); 3680 void __gmpz_tdiv_qr_ui(mpz_ptr, mpz_ptr, mpz_srcptr, ulong); 3681 void __gmpz_tdiv_ui(mpz_srcptr, ulong); 3682 void __gmpz_tdiv_q_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t b); 3683 //void __gmpz_tdiv_r_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t b); 3684 3685 void __gmpz_mod(mpz_ptr, mpz_srcptr, mpz_srcptr); 3686 void __gmpz_mod_ui(mpz_ptr, mpz_srcptr, ulong); 3687 3688 void __gmpz_pow_ui(mpz_ptr, mpz_srcptr, ulong); 3689 void __gmpz_ui_pow_ui(mpz_ptr, ulong, ulong); 3690 3691 void __gmpz_swap(mpz_ptr, mpz_ptr); 3692 3693 int __gmpz_cmp(mpz_srcptr, mpz_srcptr); 3694 int __gmpz_cmp_d(mpz_srcptr, double); 3695 int __gmpz_cmp_si(mpz_srcptr, long); 3696 int __gmpz_cmp_ui(mpz_srcptr, ulong); 3697 3698 int __gmpz_cmpabs(mpz_srcptr, mpz_srcptr); 3699 int __gmpz_cmpabs_d(mpz_srcptr, double); 3700 int __gmpz_cmpabs_ui(mpz_srcptr, ulong); 3701 3702 void __gmpz_nextprime(mpz_ptr, mpz_srcptr); 3703 3704 void __gmpz_gcd(mpz_ptr, mpz_srcptr, mpz_srcptr); 3705 ulong __gmpz_gcd_ui(mpz_ptr, mpz_srcptr, ulong); 3706 3707 void __gmpz_lcm(mpz_ptr, mpz_srcptr, mpz_srcptr); 3708 void __gmpz_lcm_ui(mpz_ptr, mpz_srcptr, ulong); 3709 3710 char *__gmpz_get_str(char*, int, mpz_srcptr); 3711 size_t __gmpz_sizeinbase(mpz_srcptr, int); 3712 void *__gmpz_export(void* , size_t*, int, size_t, int, size_t, mpz_srcptr); 3713 void __gmpz_import(mpz_ptr, size_t, int, size_t, int, size_t, const void *); 3714 3715 void __gmpz_powm(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr); 3716 void __gmpz_powm_ui(mpz_ptr, mpz_srcptr, ulong, mpz_srcptr); 3717 3718 int __gmpz_invert(mpz_ptr, mpz_srcptr, mpz_srcptr); 3719 3720 ulong __gmpz_get_ui(mpz_srcptr); 3721 long __gmpz_get_si(mpz_srcptr); 3722 double __gmpz_get_d(mpz_srcptr); 3723 3724 int __gmpz_fits_ulong_p(mpz_srcptr); 3725 int __gmpz_fits_slong_p(mpz_srcptr); 3726 int __gmpz_fits_uint_p(mpz_srcptr); 3727 int __gmpz_fits_sint_p(mpz_srcptr); 3728 int __gmpz_fits_ushort_p(mpz_srcptr); 3729 int __gmpz_fits_sshort_p(mpz_srcptr); 3730 3731 void __gmpz_and(mpz_ptr, mpz_srcptr, mpz_srcptr); 3732 void __gmpz_ior(mpz_ptr, mpz_srcptr, mpz_srcptr); 3733 void __gmpz_xor(mpz_ptr, mpz_srcptr, mpz_srcptr); 3734 void __gmpz_com(mpz_ptr, mpz_srcptr); 3735 3736 void __gmpz_setbit(mpz_ptr, mp_bitcnt_t); 3737 void __gmpz_clrbit(mpz_ptr, mp_bitcnt_t); 3738 void __gmpz_combit(mpz_ptr, mp_bitcnt_t); 3739 int __gmpz_tstbit(mpz_srcptr, mp_bitcnt_t); 3740 3741 mp_bitcnt_t __gmpz_popcount(mpz_srcptr); 3742 3743 int __gmpz_root(mpz_ptr, mpz_srcptr, ulong); 3744 void __gmpz_rootrem(mpz_ptr, mpz_ptr, mpz_srcptr, ulong); 3745 void __gmpz_sqrt(mpz_ptr, mpz_srcptr); 3746 void __gmpz_sqrtrem(mpz_ptr, mpz_ptr, mpz_srcptr); 3747 int __gmpz_perfect_power_p(mpz_srcptr); 3748 int __gmpz_perfect_square_p(mpz_srcptr); 3749 3750 int __gmpz_divisible_p(mpz_srcptr, mpz_srcptr); 3751 int __gmpz_divisible_ui_p(mpz_srcptr, ulong); 3752 3753 int __gmpz_probab_prime_p (const mpz_srcptr, int); 3754 } 3755 3756 pragma(lib, "gmp"); 3757 pragma(lib, "c"); // needed by `malloc` and `free`