1 /** Arbitrary-precision ('bignum') arithmetic. 2 * 3 * Performance is optimized for numbers below ~1000 decimal digits. 4 * For X86 machines, highly optimised assembly routines are used. 5 * 6 * The following algorithms are currently implemented: 7 * $(UL 8 * $(LI Karatsuba multiplication) 9 * $(LI Squaring is optimized independently of multiplication) 10 * $(LI Divide-and-conquer division) 11 * $(LI Binary exponentiation) 12 * ) 13 * 14 * For very large numbers, consider using the $(HTTP gmplib.org, GMP library) instead. 15 * 16 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 17 * Authors: Don Clugston 18 * Source: $(PHOBOSSRC std/bigint.d) 19 */ 20 /* Copyright Don Clugston 2008 - 2010. 21 * Distributed under the Boost Software License, Version 1.0. 22 * (See accompanying file LICENSE_1_0.txt or copy at 23 * http://www.boost.org/LICENSE_1_0.txt) 24 */ 25 26 module std.bigint; 27 28 import std.conv : ConvException; 29 30 import std.format : FormatSpec, FormatException; 31 import std.internal.math.biguintcore; 32 import std.range.primitives; 33 import std.traits; 34 35 /** A struct representing an arbitrary precision integer. 36 * 37 * All arithmetic operations are supported, except unsigned shift right (`>>>`). 38 * Bitwise operations (`|`, `&`, `^`, `~`) are supported, and behave as if BigInt was 39 * an infinite length 2's complement number. 40 * 41 * BigInt implements value semantics using copy-on-write. This means that 42 * assignment is cheap, but operations such as x++ will cause heap 43 * allocation. (But note that for most bigint operations, heap allocation is 44 * inevitable anyway.) 45 */ 46 struct BigInt 47 { 48 private: 49 BigUint data; // BigInt adds signed arithmetic to BigUint. 50 bool sign = false; 51 public: 52 /** 53 * Construct a `BigInt` from a decimal or hexadecimal string. The number must 54 * be in the form of a decimal or hex literal. It may have a leading `+` 55 * or `-` sign, followed by `0x` or `0X` if hexadecimal. Underscores are 56 * permitted in any location after the `0x` and/or the sign of the number. 57 * 58 * Params: 59 * s = a finite bidirectional range of any character type 60 * 61 * Throws: 62 * $(REF ConvException, std,conv) if the string doesn't represent a valid number 63 */ 64 this(Range)(Range s) if ( 65 isBidirectionalRange!Range && 66 isSomeChar!(ElementType!Range) && 67 !isInfinite!Range && 68 !isNarrowString!Range) 69 { 70 import std.algorithm.iteration : filterBidirectional; 71 import std.algorithm.searching : startsWith; 72 import std.conv : ConvException; 73 import std.exception : enforce; 74 import std.utf : byChar; 75 76 enforce!ConvException(!s.empty, "Can't initialize BigInt with an empty range"); 77 78 bool neg = false; 79 bool ok; 80 81 data = 0UL; 82 83 // check for signs and if the string is a hex value 84 if (s.front == '+') 85 { 86 s.popFront(); // skip '+' 87 } 88 else if (s.front == '-') 89 { 90 neg = true; 91 s.popFront(); 92 } 93 94 if (s.save.startsWith("0x".byChar) || 95 s.save.startsWith("0X".byChar)) 96 { 97 s.popFront; 98 s.popFront; 99 100 if (!s.empty) 101 ok = data.fromHexString(s.filterBidirectional!(a => a != '_')); 102 else 103 ok = false; 104 } 105 else 106 { 107 ok = data.fromDecimalString(s.filterBidirectional!(a => a != '_')); 108 } 109 110 enforce!ConvException(ok, "Not a valid numerical string"); 111 112 if (isZero()) 113 neg = false; 114 115 sign = neg; 116 } 117 118 /// ditto 119 this(Range)(Range s) pure 120 if (isNarrowString!Range) 121 { 122 import std.utf : byCodeUnit; 123 this(s.byCodeUnit); 124 } 125 126 @safe unittest 127 { 128 // system because of the dummy ranges eventually call std.array!string 129 import std.exception : assertThrown; 130 import std.internal.test.dummyrange; 131 132 auto r1 = new ReferenceBidirectionalRange!dchar("101"); 133 auto big1 = BigInt(r1); 134 assert(big1 == BigInt(101)); 135 136 auto r2 = new ReferenceBidirectionalRange!dchar("1_000"); 137 auto big2 = BigInt(r2); 138 assert(big2 == BigInt(1000)); 139 140 auto r3 = new ReferenceBidirectionalRange!dchar("0x0"); 141 auto big3 = BigInt(r3); 142 assert(big3 == BigInt(0)); 143 144 auto r4 = new ReferenceBidirectionalRange!dchar("0x"); 145 assertThrown!ConvException(BigInt(r4)); 146 } 147 148 /** 149 * Construct a `BigInt` from a sign and a magnitude. 150 * 151 * The magnitude is an $(REF_ALTTEXT input range, isInputRange, std,range,primitives) 152 * of unsigned integers that satisfies either $(REF hasLength, std,range,primitives) 153 * or $(REF isForwardRange, std,range,primitives). The first (leftmost) 154 * element of the magnitude is considered the most significant. 155 * 156 * Params: 157 * isNegative = true for negative, false for non-negative 158 * (ignored when magnitude is zero) 159 * magnitude = a finite range of unsigned integers 160 */ 161 this(Range)(bool isNegative, Range magnitude) if ( 162 isInputRange!Range && 163 isUnsigned!(ElementType!Range) && 164 (hasLength!Range || isForwardRange!Range) && 165 !isInfinite!Range) 166 { 167 data.fromMagnitude(magnitude); 168 sign = isNegative && !data.isZero; 169 } 170 171 /// 172 pure @safe unittest 173 { 174 ubyte[] magnitude = [1, 2, 3, 4, 5, 6]; 175 auto b1 = BigInt(false, magnitude); 176 assert(cast(long) b1 == 0x01_02_03_04_05_06L); 177 auto b2 = BigInt(true, magnitude); 178 assert(cast(long) b2 == -0x01_02_03_04_05_06L); 179 } 180 181 /// Construct a `BigInt` from a built-in integral type. 182 this(T)(T x) pure nothrow @safe if (isIntegral!T) 183 { 184 data = data.init; // @@@: Workaround for compiler bug 185 opAssign(x); 186 } 187 188 /// 189 @safe unittest 190 { 191 ulong data = 1_000_000_000_000; 192 auto bigData = BigInt(data); 193 assert(bigData == BigInt("1_000_000_000_000")); 194 } 195 196 /// Construct a `BigInt` from another `BigInt`. 197 this(T)(T x) pure nothrow @safe if (is(immutable T == immutable BigInt)) 198 { 199 opAssign(x); 200 } 201 202 /// 203 @safe unittest 204 { 205 const(BigInt) b1 = BigInt("1_234_567_890"); 206 BigInt b2 = BigInt(b1); 207 assert(b2 == BigInt("1_234_567_890")); 208 } 209 210 /// Assignment from built-in integer types. 211 BigInt opAssign(T)(T x) pure nothrow @safe if (isIntegral!T) 212 { 213 data = cast(ulong) absUnsign(x); 214 sign = (x < 0); 215 return this; 216 } 217 218 /// 219 @safe unittest 220 { 221 auto b = BigInt("123"); 222 b = 456; 223 assert(b == BigInt("456")); 224 } 225 226 /// Assignment from another BigInt. 227 BigInt opAssign(T:BigInt)(T x) pure @nogc @safe 228 { 229 data = x.data; 230 sign = x.sign; 231 return this; 232 } 233 234 /// 235 @safe unittest 236 { 237 auto b1 = BigInt("123"); 238 auto b2 = BigInt("456"); 239 b2 = b1; 240 assert(b2 == BigInt("123")); 241 } 242 243 /** 244 * Implements assignment operators from built-in integers of the form 245 * `BigInt op= integer`. 246 */ 247 BigInt opOpAssign(string op, T)(T y) pure nothrow @safe 248 if ((op=="+" || op=="-" || op=="*" || op=="/" || op=="%" 249 || op==">>" || op=="<<" || op=="^^" || op=="|" || op=="&" || op=="^") && isIntegral!T) 250 { 251 ulong u = absUnsign(y); 252 253 static if (op=="+") 254 { 255 data = BigUint.addOrSubInt(data, u, sign != (y<0), sign); 256 } 257 else static if (op=="-") 258 { 259 data = BigUint.addOrSubInt(data, u, sign == (y<0), sign); 260 } 261 else static if (op=="*") 262 { 263 if (y == 0) 264 { 265 sign = false; 266 data = 0UL; 267 } 268 else 269 { 270 sign = ( sign != (y<0) ); 271 data = BigUint.mulInt(data, u); 272 } 273 } 274 else static if (op=="/") 275 { 276 assert(y != 0, "Division by zero"); 277 static if (T.sizeof <= uint.sizeof) 278 { 279 data = BigUint.divInt(data, cast(uint) u); 280 } 281 else 282 { 283 data = BigUint.divInt(data, u); 284 } 285 sign = data.isZero() ? false : sign ^ (y < 0); 286 } 287 else static if (op=="%") 288 { 289 assert(y != 0, "Division by zero"); 290 static if (is(immutable(T) == immutable(long)) || is( immutable(T) == immutable(ulong) )) 291 { 292 this %= BigInt(y); 293 } 294 else 295 { 296 data = cast(ulong) BigUint.modInt(data, cast(uint) u); 297 if (data.isZero()) 298 sign = false; 299 } 300 // x%y always has the same sign as x. 301 // This is not the same as mathematical mod. 302 } 303 else static if (op==">>" || op=="<<") 304 { 305 // Do a left shift if y>0 and <<, or 306 // if y<0 and >>; else do a right shift. 307 if (y == 0) 308 return this; 309 else if ((y > 0) == (op=="<<")) 310 { 311 // Sign never changes during left shift 312 data = data.opBinary!(op)(u); 313 } 314 else 315 { 316 data = data.opBinary!(op)(u); 317 if (data.isZero()) 318 sign = false; 319 } 320 } 321 else static if (op=="^^") 322 { 323 sign = (y & 1) ? sign : false; 324 data = BigUint.pow(data, u); 325 } 326 else static if (op=="|" || op=="&" || op=="^") 327 { 328 BigInt b = y; 329 opOpAssign!op(b); 330 } 331 else static assert(0, "BigInt " ~ op[0..$-1] ~ "= " ~ T.stringof ~ " is not supported"); 332 return this; 333 } 334 335 /// 336 @safe unittest 337 { 338 auto b = BigInt("1_000_000_000"); 339 340 b += 12345; 341 assert(b == BigInt("1_000_012_345")); 342 343 b /= 5; 344 assert(b == BigInt("200_002_469")); 345 } 346 347 // https://issues.dlang.org/show_bug.cgi?id=16264 348 @safe unittest 349 { 350 auto a = BigInt( 351 `335690982744637013564796917901053301979460129353374296317539383938630086938` ~ 352 `465898213033510992292836631752875403891802201862860531801760096359705447768` ~ 353 `957432600293361240407059207520920532482429912948952142341440301429494694368` ~ 354 `264560802292927144211230021750155988283029753927847924288850436812178022006` ~ 355 `408597793414273953252832688620479083497367463977081627995406363446761896298` ~ 356 `967177607401918269561385622811274398143647535024987050366350585544531063531` ~ 357 `7118554808325723941557169427279911052268935775`); 358 359 auto b = BigInt( 360 `207672245542926038535480439528441949928508406405023044025560363701392340829` ~ 361 `852529131306106648201340460604257466180580583656068555417076345439694125326` ~ 362 `843947164365500055567495554645796102453565953360564114634705366335703491527` ~ 363 `429426780005741168078089657359833601261803592920462081364401456331489106355` ~ 364 `199133982282631108670436696758342051198891939367812305559960349479160308314` ~ 365 `068518200681530999860641597181672463704794566473241690395901768680673716414` ~ 366 `243691584391572899147223065906633310537507956952626106509069491302359792769` ~ 367 `378934570685117202046921464019396759638376362935855896435623442486036961070` ~ 368 `534574698959398017332214518246531363445309522357827985468581166065335726996` ~ 369 `711467464306784543112544076165391268106101754253962102479935962248302404638` ~ 370 `21737237102628470475027851189594709504`); 371 372 BigInt c = a * b; // Crashes 373 374 assert(c == BigInt( 375 `697137001950904057507249234183127244116872349433141878383548259425589716813` ~ 376 `135440660252012378417669596912108637127036044977634382385990472429604619344` ~ 377 `738746224291111527200379708978133071390303850450970292020176369525401803474` ~ 378 `998613408923490273129022167907826017408385746675184651576154302536663744109` ~ 379 `111018961065316024005076097634601030334948684412785487182572502394847587887` ~ 380 `507385831062796361152176364659197432600147716058873232435238712648552844428` ~ 381 `058885217631715287816333209463171932255049134340904981280717725999710525214` ~ 382 `161541960645335744430049558161514565159449390036287489478108344584188898872` ~ 383 `434914159748515512161981956372737022393466624249130107254611846175580584736` ~ 384 `276213025837422102290580044755202968610542057651282410252208599309841499843` ~ 385 `672251048622223867183370008181364966502137725166782667358559333222947265344` ~ 386 `524195551978394625568228658697170315141077913403482061673401937141405425042` ~ 387 `283546509102861986303306729882186190883772633960389974665467972016939172303` ~ 388 `653623175801495207204880400522581834672918935651426160175413277309985678579` ~ 389 `830872397214091472424064274864210953551447463312267310436493480881235642109` ~ 390 `668498742629676513172286703948381906930297135997498416573231570483993847269` ~ 391 `479552708416124555462530834668011570929850407031109157206202741051573633443` ~ 392 `58105600` 393 )); 394 } 395 396 /** 397 * Implements assignment operators of the form `BigInt op= BigInt`. 398 */ 399 BigInt opOpAssign(string op, T)(T y) pure nothrow @safe 400 if ((op=="+" || op== "-" || op=="*" || op=="|" || op=="&" || op=="^" || op=="/" || op=="%") 401 && is (T: BigInt)) 402 { 403 static if (op == "+") 404 { 405 data = BigUint.addOrSub(data, y.data, sign != y.sign, &sign); 406 } 407 else static if (op == "-") 408 { 409 data = BigUint.addOrSub(data, y.data, sign == y.sign, &sign); 410 } 411 else static if (op == "*") 412 { 413 data = BigUint.mul(data, y.data); 414 sign = isZero() ? false : sign ^ y.sign; 415 } 416 else static if (op == "/") 417 { 418 y.checkDivByZero(); 419 if (!isZero()) 420 { 421 data = BigUint.div(data, y.data); 422 sign = isZero() ? false : sign ^ y.sign; 423 } 424 } 425 else static if (op == "%") 426 { 427 y.checkDivByZero(); 428 if (!isZero()) 429 { 430 data = BigUint.mod(data, y.data); 431 // x%y always has the same sign as x. 432 if (isZero()) 433 sign = false; 434 } 435 } 436 else static if (op == "|" || op == "&" || op == "^") 437 { 438 data = BigUint.bitwiseOp!op(data, y.data, sign, y.sign, sign); 439 } 440 else static assert(0, "BigInt " ~ op[0..$-1] ~ "= " ~ 441 T.stringof ~ " is not supported"); 442 return this; 443 } 444 445 /// 446 @safe unittest 447 { 448 auto x = BigInt("123"); 449 auto y = BigInt("321"); 450 x += y; 451 assert(x == BigInt("444")); 452 } 453 454 /** 455 * Implements binary operators between `BigInt`s. 456 */ 457 BigInt opBinary(string op, T)(T y) pure nothrow @safe const 458 if ((op=="+" || op == "*" || op=="-" || op=="|" || op=="&" || op=="^" || 459 op=="/" || op=="%") 460 && is (T: BigInt)) 461 { 462 BigInt r = this; 463 return r.opOpAssign!(op)(y); 464 } 465 466 /// 467 @safe unittest 468 { 469 auto x = BigInt("123"); 470 auto y = BigInt("456"); 471 BigInt z = x * y; 472 assert(z == BigInt("56088")); 473 } 474 475 /** 476 * Implements binary operators between `BigInt`'s and built-in integers. 477 */ 478 BigInt opBinary(string op, T)(T y) pure nothrow @safe const 479 if ((op=="+" || op == "*" || op=="-" || op=="/" || op=="|" || op=="&" || 480 op=="^"|| op==">>" || op=="<<" || op=="^^") 481 && isIntegral!T) 482 { 483 BigInt r = this; 484 return r.opOpAssign!(op)(y); 485 } 486 487 /// 488 @safe unittest 489 { 490 auto x = BigInt("123"); 491 x *= 300; 492 assert(x == BigInt("36900")); 493 } 494 495 /** 496 Implements a narrowing remainder operation with built-in integer types. 497 498 This binary operator returns a narrower, built-in integer type 499 where applicable, according to the following table. 500 501 $(TABLE , 502 $(TR $(TD `BigInt`) $(TD $(CODE_PERCENT)) $(TD `uint`) $(TD $(RARR)) $(TD `long`)) 503 $(TR $(TD `BigInt`) $(TD $(CODE_PERCENT)) $(TD `long`) $(TD $(RARR)) $(TD `long`)) 504 $(TR $(TD `BigInt`) $(TD $(CODE_PERCENT)) $(TD `ulong`) $(TD $(RARR)) $(TD `BigInt`)) 505 $(TR $(TD `BigInt`) $(TD $(CODE_PERCENT)) $(TD other type) $(TD $(RARR)) $(TD `int`)) 506 ) 507 */ 508 auto opBinary(string op, T)(T y) pure nothrow @safe const 509 if (op == "%" && isIntegral!T) 510 { 511 assert(y != 0, "% 0 not allowed"); 512 513 // BigInt % uint => long 514 // BigInt % long => long 515 // BigInt % ulong => BigInt 516 // BigInt % other_type => int 517 static if (is(immutable T == immutable long) || is(immutable T == immutable ulong)) 518 { 519 auto r = this % BigInt(y); 520 521 static if (is(immutable T == immutable long)) 522 { 523 return r.toLong(); 524 } 525 else 526 { 527 // return as-is to avoid overflow 528 return r; 529 } 530 } 531 else 532 { 533 immutable uint u = absUnsign(y); 534 static if (is(immutable T == immutable uint)) 535 alias R = long; 536 else 537 alias R = int; 538 R rem = BigUint.modInt(data, u); 539 // x%y always has the same sign as x. 540 // This is not the same as mathematical mod. 541 return sign ? -rem : rem; 542 } 543 } 544 545 /// 546 @safe unittest 547 { 548 auto x = BigInt("1_000_000_500"); 549 long l = 1_000_000L; 550 ulong ul = 2_000_000UL; 551 int i = 500_000; 552 short s = 30_000; 553 554 assert(is(typeof(x % l) == long) && x % l == 500L); 555 assert(is(typeof(x % ul) == BigInt) && x % ul == BigInt(500)); 556 assert(is(typeof(x % i) == int) && x % i == 500); 557 assert(is(typeof(x % s) == int) && x % s == 10500); 558 } 559 560 /** 561 Implements operators with built-in integers on the left-hand side and 562 `BigInt` on the right-hand side. 563 */ 564 BigInt opBinaryRight(string op, T)(T y) pure nothrow @safe const 565 if ((op=="+" || op=="*" || op=="|" || op=="&" || op=="^") && isIntegral!T) 566 { 567 return opBinary!(op)(y); 568 } 569 570 /// 571 @safe unittest 572 { 573 auto x = BigInt("100"); 574 BigInt y = 123 + x; 575 assert(y == BigInt("223")); 576 577 BigInt z = 123 - x; 578 assert(z == BigInt("23")); 579 580 // Dividing a built-in integer type by BigInt always results in 581 // something that fits in a built-in type, so the built-in type is 582 // returned, not BigInt. 583 assert(is(typeof(1000 / x) == int)); 584 assert(1000 / x == 10); 585 } 586 587 // BigInt = integer op BigInt 588 /// ditto 589 BigInt opBinaryRight(string op, T)(T y) pure nothrow @safe const 590 if (op == "-" && isIntegral!T) 591 { 592 ulong u = absUnsign(y); 593 BigInt r; 594 static if (op == "-") 595 { 596 r.sign = sign; 597 r.data = BigUint.addOrSubInt(data, u, sign == (y<0), r.sign); 598 r.negate(); 599 } 600 return r; 601 } 602 603 // integer = integer op BigInt 604 /// ditto 605 T opBinaryRight(string op, T)(T x) pure nothrow @safe const 606 if ((op=="%" || op=="/") && isIntegral!T) 607 { 608 checkDivByZero(); 609 610 static if (op == "%") 611 { 612 // x%y always has the same sign as x. 613 if (data.ulongLength > 1) 614 return x; 615 immutable u = absUnsign(x); 616 immutable rem = u % data.peekUlong(0); 617 // x%y always has the same sign as x. 618 return cast(T)((x<0) ? -rem : rem); 619 } 620 else static if (op == "/") 621 { 622 if (data.ulongLength > 1) 623 return 0; 624 return cast(T)(x / data.peekUlong(0)); 625 } 626 } 627 628 // const unary operations 629 /** 630 Implements `BigInt` unary operators. 631 */ 632 BigInt opUnary(string op)() pure nothrow @safe const if (op=="+" || op=="-" || op=="~") 633 { 634 static if (op=="-") 635 { 636 BigInt r = this; 637 r.negate(); 638 return r; 639 } 640 else static if (op=="~") 641 { 642 return -(this+1); 643 } 644 else static if (op=="+") 645 return this; 646 } 647 648 // non-const unary operations 649 /// ditto 650 BigInt opUnary(string op)() pure nothrow @safe if (op=="++" || op=="--") 651 { 652 static if (op=="++") 653 { 654 data = BigUint.addOrSubInt(data, 1UL, sign, sign); 655 return this; 656 } 657 else static if (op=="--") 658 { 659 data = BigUint.addOrSubInt(data, 1UL, !sign, sign); 660 return this; 661 } 662 } 663 664 /// 665 @safe unittest 666 { 667 auto x = BigInt("1234"); 668 assert(-x == BigInt("-1234")); 669 670 ++x; 671 assert(x == BigInt("1235")); 672 } 673 674 /** 675 Implements `BigInt` equality test with other `BigInt`'s and built-in 676 numeric types. 677 */ 678 bool opEquals()(auto ref const BigInt y) const pure @nogc @safe 679 { 680 return sign == y.sign && y.data == data; 681 } 682 683 /// ditto 684 bool opEquals(T)(const T y) const pure nothrow @nogc @safe if (isIntegral!T) 685 { 686 if (sign != (y<0)) 687 return 0; 688 return data.opEquals(cast(ulong) absUnsign(y)); 689 } 690 691 /// ditto 692 bool opEquals(T)(const T y) const nothrow @nogc if (isFloatingPoint!T) 693 { 694 // This is a separate function from the isIntegral!T case 695 // due to the impurity of std.math.scalbn which is used 696 // for 80 bit floats. 697 return 0 == opCmp(y); 698 } 699 700 /// 701 @safe unittest 702 { 703 // Note that when comparing a BigInt to a float or double the 704 // full precision of the BigInt is always considered, unlike 705 // when comparing an int to a float or a long to a double. 706 assert(BigInt(123456789) != cast(float) 123456789); 707 } 708 709 @safe unittest 710 { 711 auto x = BigInt("12345"); 712 auto y = BigInt("12340"); 713 int z = 12345; 714 int w = 54321; 715 716 assert(x == x); 717 assert(x != y); 718 assert(x == y + 5); 719 assert(x == z); 720 assert(x != w); 721 } 722 723 @safe unittest 724 { 725 import std.math : nextDown, nextUp; 726 727 const x = BigInt("0x1abc_de80_0000_0000_0000_0000_0000_0000"); 728 BigInt x1 = x + 1; 729 BigInt x2 = x - 1; 730 731 const d = 0x1.abcde8p124; 732 assert(x == d); 733 assert(x1 != d); 734 assert(x2 != d); 735 assert(x != nextUp(d)); 736 assert(x != nextDown(d)); 737 assert(x != double.nan); 738 739 const dL = 0x1.abcde8p124L; 740 assert(x == dL); 741 assert(x1 != dL); 742 assert(x2 != dL); 743 assert(x != nextUp(dL)); 744 assert(x != nextDown(dL)); 745 assert(x != real.nan); 746 747 assert(BigInt(0) == 0.0f); 748 assert(BigInt(0) == 0.0); 749 assert(BigInt(0) == 0.0L); 750 assert(BigInt(0) == -0.0f); 751 assert(BigInt(0) == -0.0); 752 assert(BigInt(0) == -0.0L); 753 assert(BigInt("999_999_999_999_999_999_999_999_999_999_999_999_999") != float.infinity); 754 } 755 756 /** 757 Implements casting to `bool`. 758 */ 759 T opCast(T:bool)() pure nothrow @nogc @safe const 760 { 761 return !isZero(); 762 } 763 764 /// 765 @safe unittest 766 { 767 // Non-zero values are regarded as true 768 auto x = BigInt("1"); 769 auto y = BigInt("10"); 770 assert(x); 771 assert(y); 772 773 // Zero value is regarded as false 774 auto z = BigInt("0"); 775 assert(!z); 776 } 777 778 /** 779 Implements casting to integer types. 780 781 Throws: $(REF ConvOverflowException, std,conv) if the number exceeds 782 the target type's range. 783 */ 784 T opCast(T:ulong)() pure @safe const 785 { 786 if (isUnsigned!T && sign) 787 { /* throw */ } 788 else 789 if (data.ulongLength == 1) 790 { 791 ulong l = data.peekUlong(0); 792 if (isUnsigned!T || !sign) 793 { 794 if (l <= T.max) 795 return cast(T) l; 796 } 797 else 798 { 799 if (l <= ulong(T.max)+1) 800 return cast(T)-long(l); // -long.min == long.min 801 } 802 } 803 804 import std.conv : ConvOverflowException; 805 import std..string : format; 806 throw new ConvOverflowException( 807 "BigInt(%s) cannot be represented as a %s" 808 .format(this.toDecimalString, T.stringof)); 809 } 810 811 /// 812 @safe unittest 813 { 814 import std.conv : to, ConvOverflowException; 815 import std.exception : assertThrown; 816 817 assert(BigInt("0").to!int == 0); 818 819 assert(BigInt("0").to!ubyte == 0); 820 assert(BigInt("255").to!ubyte == 255); 821 assertThrown!ConvOverflowException(BigInt("256").to!ubyte); 822 assertThrown!ConvOverflowException(BigInt("-1").to!ubyte); 823 } 824 825 @safe unittest 826 { 827 import std.conv : to, ConvOverflowException; 828 import std.exception : assertThrown; 829 830 assert(BigInt("-1").to!byte == -1); 831 assert(BigInt("-128").to!byte == -128); 832 assert(BigInt("127").to!byte == 127); 833 assertThrown!ConvOverflowException(BigInt("-129").to!byte); 834 assertThrown!ConvOverflowException(BigInt("128").to!byte); 835 836 assert(BigInt("0").to!uint == 0); 837 assert(BigInt("4294967295").to!uint == uint.max); 838 assertThrown!ConvOverflowException(BigInt("4294967296").to!uint); 839 assertThrown!ConvOverflowException(BigInt("-1").to!uint); 840 841 assert(BigInt("-1").to!int == -1); 842 assert(BigInt("-2147483648").to!int == int.min); 843 assert(BigInt("2147483647").to!int == int.max); 844 assertThrown!ConvOverflowException(BigInt("-2147483649").to!int); 845 assertThrown!ConvOverflowException(BigInt("2147483648").to!int); 846 847 assert(BigInt("0").to!ulong == 0); 848 assert(BigInt("18446744073709551615").to!ulong == ulong.max); 849 assertThrown!ConvOverflowException(BigInt("18446744073709551616").to!ulong); 850 assertThrown!ConvOverflowException(BigInt("-1").to!ulong); 851 852 assert(BigInt("-1").to!long == -1); 853 assert(BigInt("-9223372036854775808").to!long == long.min); 854 assert(BigInt("9223372036854775807").to!long == long.max); 855 assertThrown!ConvOverflowException(BigInt("-9223372036854775809").to!long); 856 assertThrown!ConvOverflowException(BigInt("9223372036854775808").to!long); 857 } 858 859 /** 860 Implements casting to floating point types. 861 */ 862 T opCast(T)() @safe nothrow @nogc const if (isFloatingPoint!T) 863 { 864 return toFloat!(T, "nearest"); 865 } 866 867 /// 868 @system unittest 869 { 870 assert(0x1.abcd_e8p+124f == cast(float) BigInt("0x1abc_de80_0000_0000_0000_0000_0000_0000")); 871 assert(0x1.abcd_ef12_3456p+124 == cast(double) BigInt("0x1abc_def1_2345_6000_0000_0000_0000_0000")); 872 assert(0x1.abcd_ef12_3456p+124L == cast(real) BigInt("0x1abc_def1_2345_6000_0000_0000_0000_0000")); 873 874 assert(-0x1.3456_78p+108f == cast(float) BigInt("-0x1345_6780_0000_0000_0000_0000_0000")); 875 assert(-0x1.3456_78ab_cdefp+108 == cast(double) BigInt("-0x1345_678a_bcde_f000_0000_0000_0000")); 876 assert(-0x1.3456_78ab_cdefp+108L == cast(real) BigInt("-0x1345_678a_bcde_f000_0000_0000_0000")); 877 } 878 879 /// Rounding when casting to floating point 880 @system unittest 881 { 882 // BigInts whose values cannot be exactly represented as float/double/real 883 // are rounded when cast to float/double/real. When cast to float or 884 // double or 64-bit real the rounding is strictly defined. When cast 885 // to extended-precision real the rounding rules vary by environment. 886 887 // BigInts that fall somewhere between two non-infinite floats/doubles 888 // are rounded to the closer value when cast to float/double. 889 assert(0x1.aaa_aaep+28f == cast(float) BigInt(0x1aaa_aae7)); 890 assert(0x1.aaa_ab0p+28f == cast(float) BigInt(0x1aaa_aaff)); 891 assert(-0x1.aaaaaep+28f == cast(float) BigInt(-0x1aaa_aae7)); 892 assert(-0x1.aaaab0p+28f == cast(float) BigInt(-0x1aaa_aaff)); 893 894 assert(0x1.aaa_aaaa_aaaa_aa00p+60 == cast(double) BigInt(0x1aaa_aaaa_aaaa_aa77)); 895 assert(0x1.aaa_aaaa_aaaa_ab00p+60 == cast(double) BigInt(0x1aaa_aaaa_aaaa_aaff)); 896 assert(-0x1.aaa_aaaa_aaaa_aa00p+60 == cast(double) BigInt(-0x1aaa_aaaa_aaaa_aa77)); 897 assert(-0x1.aaa_aaaa_aaaa_ab00p+60 == cast(double) BigInt(-0x1aaa_aaaa_aaaa_aaff)); 898 899 // BigInts that fall exactly between two non-infinite floats/doubles 900 // are rounded away from zero when cast to float/double. (Note that 901 // in most environments this is NOT the same rounding rule rule used 902 // when casting int/long to float/double.) 903 assert(0x1.aaa_ab0p+28f == cast(float) BigInt(0x1aaa_aaf0)); 904 assert(-0x1.aaaab0p+28f == cast(float) BigInt(-0x1aaa_aaf0)); 905 906 assert(0x1.aaa_aaaa_aaaa_ab00p+60 == cast(double) BigInt(0x1aaa_aaaa_aaaa_aa80)); 907 assert(-0x1.aaa_aaaa_aaaa_ab00p+60 == cast(double) BigInt(-0x1aaa_aaaa_aaaa_aa80)); 908 909 // BigInts that are bounded on one side by the largest positive or 910 // most negative finite float/double and on the other side by infinity 911 // or -infinity are rounded as if in place of infinity was the value 912 // `2^^(T.max_exp)` when cast to float/double. 913 assert(float.infinity == cast(float) BigInt("999_999_999_999_999_999_999_999_999_999_999_999_999")); 914 assert(-float.infinity == cast(float) BigInt("-999_999_999_999_999_999_999_999_999_999_999_999_999")); 915 916 assert(double.infinity > cast(double) BigInt("999_999_999_999_999_999_999_999_999_999_999_999_999")); 917 assert(real.infinity > cast(real) BigInt("999_999_999_999_999_999_999_999_999_999_999_999_999")); 918 } 919 920 @safe unittest 921 { 922 // Test exponent overflow is correct. 923 assert(0x1.000000p+29f == cast(float) BigInt(0x1fffffff)); 924 assert(0x1.000000p+61 == cast(double) BigInt(0x1fff_ffff_ffff_fff0)); 925 } 926 927 private T toFloat(T, string roundingMode)() @safe nothrow @nogc const 928 if (__traits(isFloating, T) && (roundingMode == "nearest" || roundingMode == "truncate")) 929 { 930 import core.bitop : bsr; 931 enum performRounding = (roundingMode == "nearest"); 932 enum performTruncation = (roundingMode == "truncate"); 933 static assert(performRounding || performTruncation, "unrecognized rounding mode"); 934 enum int totalNeededBits = T.mant_dig + int(performRounding); 935 static if (totalNeededBits <= 64) 936 { 937 // We need to examine the top two 64-bit words, not just the top one, 938 // since the top word could have just a single significant bit. 939 const ulongLength = data.ulongLength; 940 const ulong w1 = data.peekUlong(ulongLength - 1); 941 if (w1 == 0) 942 return T(0); // Special: exponent should be all zero bits, plus bsr(w1) is undefined. 943 const ulong w2 = ulongLength < 2 ? 0 : data.peekUlong(ulongLength - 2); 944 const uint w1BitCount = bsr(w1) + 1; 945 ulong sansExponent = (w1 << (64 - w1BitCount)) | (w2 >>> (w1BitCount)); 946 size_t exponent = (ulongLength - 1) * 64 + w1BitCount + 1; 947 static if (performRounding) 948 { 949 sansExponent += 1UL << (64 - totalNeededBits); 950 if (0 <= cast(long) sansExponent) // Use high bit to detect overflow. 951 { 952 // Do not bother filling in the high bit of sansExponent 953 // with 1. It will be discarded by float and double and 80 954 // bit real cannot be on this path with rounding enabled. 955 exponent += 1; 956 } 957 } 958 static if (T.mant_dig == float.mant_dig) 959 { 960 if (exponent >= T.max_exp) 961 return isNegative ? -T.infinity : T.infinity; 962 uint resultBits = (uint(isNegative) << 31) | // sign bit 963 ((0xFF & (exponent - float.min_exp)) << 23) | // exponent 964 cast(uint) ((sansExponent << 1) >>> (64 - 23)); // mantissa. 965 return *cast(float*) &resultBits; 966 } 967 else static if (T.mant_dig == double.mant_dig) 968 { 969 if (exponent >= T.max_exp) 970 return isNegative ? -T.infinity : T.infinity; 971 ulong resultBits = (ulong(isNegative) << 63) | // sign bit 972 ((0x7FFUL & (exponent - double.min_exp)) << 52) | // exponent 973 ((sansExponent << 1) >>> (64 - 52)); // mantissa. 974 return *cast(double*) &resultBits; 975 } 976 else 977 { 978 import std.math : scalbn; 979 return scalbn(isNegative ? -cast(real) sansExponent : cast(real) sansExponent, 980 cast(int) exponent - 65); 981 } 982 } 983 else 984 { 985 import std.math : scalbn; 986 const ulongLength = data.ulongLength; 987 if ((ulongLength - 1) * 64L > int.max) 988 return isNegative ? -T.infinity : T.infinity; 989 int scale = cast(int) ((ulongLength - 1) * 64); 990 const ulong w1 = data.peekUlong(ulongLength - 1); 991 if (w1 == 0) 992 return T(0); // Special: bsr(w1) is undefined. 993 int bitsStillNeeded = totalNeededBits - bsr(w1) - 1; 994 T acc = scalbn(w1, scale); 995 for (ptrdiff_t i = ulongLength - 2; i >= 0 && bitsStillNeeded > 0; i--) 996 { 997 ulong w = data.peekUlong(i); 998 // To round towards zero we must make sure not to use too many bits. 999 if (bitsStillNeeded >= 64) 1000 { 1001 acc += scalbn(w, scale -= 64); 1002 bitsStillNeeded -= 64; 1003 } 1004 else 1005 { 1006 w = (w >>> (64 - bitsStillNeeded)) << (64 - bitsStillNeeded); 1007 acc += scalbn(w, scale -= 64); 1008 break; 1009 } 1010 } 1011 if (isNegative) 1012 acc = -acc; 1013 return cast(T) acc; 1014 } 1015 } 1016 1017 /** 1018 Implements casting to/from qualified `BigInt`'s. 1019 1020 Warning: Casting to/from `const` or `immutable` may break type 1021 system guarantees. Use with care. 1022 */ 1023 T opCast(T)() pure nothrow @nogc const 1024 if (is(immutable T == immutable BigInt)) 1025 { 1026 return this; 1027 } 1028 1029 /// 1030 @safe unittest 1031 { 1032 const(BigInt) x = BigInt("123"); 1033 BigInt y = cast() x; // cast away const 1034 assert(y == x); 1035 } 1036 1037 // Hack to make BigInt's typeinfo.compare work properly. 1038 // Note that this must appear before the other opCmp overloads, otherwise 1039 // DMD won't find it. 1040 /** 1041 Implements 3-way comparisons of `BigInt` with `BigInt` or `BigInt` with 1042 built-in numeric types. 1043 */ 1044 int opCmp(ref const BigInt y) pure nothrow @nogc @safe const 1045 { 1046 // Simply redirect to the "real" opCmp implementation. 1047 return this.opCmp!BigInt(y); 1048 } 1049 1050 /// ditto 1051 int opCmp(T)(const T y) pure nothrow @nogc @safe const if (isIntegral!T) 1052 { 1053 if (sign != (y<0) ) 1054 return sign ? -1 : 1; 1055 int cmp = data.opCmp(cast(ulong) absUnsign(y)); 1056 return sign? -cmp: cmp; 1057 } 1058 /// ditto 1059 int opCmp(T)(const T y) nothrow @nogc @safe const if (isFloatingPoint!T) 1060 { 1061 import core.bitop : bsr; 1062 import std.math : cmp, isFinite; 1063 1064 const asFloat = toFloat!(T, "truncate"); 1065 if (asFloat != y) 1066 return cmp(asFloat, y); // handles +/- NaN. 1067 if (!isFinite(y)) 1068 return isNegative ? 1 : -1; 1069 const ulongLength = data.ulongLength; 1070 const w1 = data.peekUlong(ulongLength - 1); 1071 if (w1 == 0) 1072 return 0; // Special: bsr(w1) is undefined. 1073 const numSignificantBits = (ulongLength - 1) * 64 + bsr(w1) + 1; 1074 for (ptrdiff_t bitsRemainingToCheck = numSignificantBits - T.mant_dig, i = 0; 1075 bitsRemainingToCheck > 0; i++, bitsRemainingToCheck -= 64) 1076 { 1077 auto word = data.peekUlong(i); 1078 if (word == 0) 1079 continue; 1080 // Make sure we're only checking digits that are beyond 1081 // the precision of `y`. 1082 if (bitsRemainingToCheck < 64 && (word << (64 - bitsRemainingToCheck)) == 0) 1083 break; // This can only happen on the last loop iteration. 1084 return isNegative ? -1 : 1; 1085 } 1086 return 0; 1087 } 1088 /// ditto 1089 int opCmp(T:BigInt)(const T y) pure nothrow @nogc @safe const 1090 { 1091 if (sign != y.sign) 1092 return sign ? -1 : 1; 1093 immutable cmp = data.opCmp(y.data); 1094 return sign? -cmp: cmp; 1095 } 1096 1097 /// 1098 @safe unittest 1099 { 1100 auto x = BigInt("100"); 1101 auto y = BigInt("10"); 1102 int z = 50; 1103 const int w = 200; 1104 1105 assert(y < x); 1106 assert(x > z); 1107 assert(z > y); 1108 assert(x < w); 1109 } 1110 1111 /// 1112 @safe unittest 1113 { 1114 auto x = BigInt("0x1abc_de80_0000_0000_0000_0000_0000_0000"); 1115 BigInt y = x - 1; 1116 BigInt z = x + 1; 1117 1118 double d = 0x1.abcde8p124; 1119 assert(y < d); 1120 assert(z > d); 1121 assert(x >= d && x <= d); 1122 1123 // Note that when comparing a BigInt to a float or double the 1124 // full precision of the BigInt is always considered, unlike 1125 // when comparing an int to a float or a long to a double. 1126 assert(BigInt(123456789) < cast(float) 123456789); 1127 } 1128 1129 @safe unittest 1130 { 1131 assert(BigInt("999_999_999_999_999_999_999_999_999_999_999_999_999") < float.infinity); 1132 1133 // Test `real` works. 1134 auto x = BigInt("0x1abc_de80_0000_0000_0000_0000_0000_0000"); 1135 BigInt y = x - 1; 1136 BigInt z = x + 1; 1137 1138 real d = 0x1.abcde8p124; 1139 assert(y < d); 1140 assert(z > d); 1141 assert(x >= d && x <= d); 1142 1143 // Test comparison for numbers of 64 bits or fewer. 1144 auto w1 = BigInt(0x1abc_de80_0000_0000); 1145 auto w2 = w1 - 1; 1146 auto w3 = w1 + 1; 1147 assert(w1.ulongLength == 1); 1148 assert(w2.ulongLength == 1); 1149 assert(w3.ulongLength == 1); 1150 1151 double e = 0x1.abcde8p+60; 1152 assert(w1 >= e && w1 <= e); 1153 assert(w2 < e); 1154 assert(w3 > e); 1155 1156 real eL = 0x1.abcde8p+60; 1157 assert(w1 >= eL && w1 <= eL); 1158 assert(w2 < eL); 1159 assert(w3 > eL); 1160 } 1161 1162 /** 1163 Returns: The value of this `BigInt` as a `long`, or `long.max`/`long.min` 1164 if outside the representable range. 1165 */ 1166 long toLong() @safe pure nothrow const @nogc 1167 { 1168 return (sign ? -1 : 1) * 1169 (data.ulongLength == 1 && (data.peekUlong(0) <= sign+cast(ulong)(long.max)) // 1+long.max = |long.min| 1170 ? cast(long)(data.peekUlong(0)) 1171 : long.max); 1172 } 1173 1174 /// 1175 @safe unittest 1176 { 1177 auto b = BigInt("12345"); 1178 long l = b.toLong(); 1179 assert(l == 12345); 1180 } 1181 1182 /** 1183 Returns: The value of this `BigInt` as an `int`, or `int.max`/`int.min` if outside 1184 the representable range. 1185 */ 1186 int toInt() @safe pure nothrow @nogc const 1187 { 1188 return (sign ? -1 : 1) * 1189 (data.uintLength == 1 && (data.peekUint(0) <= sign+cast(uint)(int.max)) // 1+int.max = |int.min| 1190 ? cast(int)(data.peekUint(0)) 1191 : int.max); 1192 } 1193 1194 /// 1195 @safe unittest 1196 { 1197 auto big = BigInt("5_000_000"); 1198 auto i = big.toInt(); 1199 assert(i == 5_000_000); 1200 1201 // Numbers that are too big to fit into an int will be clamped to int.max. 1202 auto tooBig = BigInt("5_000_000_000"); 1203 i = tooBig.toInt(); 1204 assert(i == int.max); 1205 } 1206 1207 /// Number of significant `uint`s which are used in storing this number. 1208 /// The absolute value of this `BigInt` is always < 2$(SUPERSCRIPT 32*uintLength) 1209 @property size_t uintLength() @safe pure nothrow @nogc const 1210 { 1211 return data.uintLength; 1212 } 1213 1214 /// Number of significant `ulong`s which are used in storing this number. 1215 /// The absolute value of this `BigInt` is always < 2$(SUPERSCRIPT 64*ulongLength) 1216 @property size_t ulongLength() @safe pure nothrow @nogc const 1217 { 1218 return data.ulongLength; 1219 } 1220 1221 /** Convert the `BigInt` to `string`, passing it to the given sink. 1222 * 1223 * Params: 1224 * sink = An OutputRange for accepting possibly piecewise segments of the 1225 * formatted string. 1226 * formatString = A format string specifying the output format. 1227 * 1228 * $(TABLE Available output formats:, 1229 * $(TR $(TD "d") $(TD Decimal)) 1230 * $(TR $(TD "o") $(TD Octal)) 1231 * $(TR $(TD "x") $(TD Hexadecimal, lower case)) 1232 * $(TR $(TD "X") $(TD Hexadecimal, upper case)) 1233 * $(TR $(TD "s") $(TD Default formatting (same as "d") )) 1234 * $(TR $(TD null) $(TD Default formatting (same as "d") )) 1235 * ) 1236 */ 1237 void toString(Writer)(scope ref Writer sink, string formatString) const 1238 { 1239 auto f = FormatSpec!char(formatString); 1240 f.writeUpToNextSpec(sink); 1241 toString!Writer(sink, f); 1242 } 1243 1244 /// ditto 1245 void toString(Writer)(scope ref Writer sink, scope const ref FormatSpec!char f) const 1246 { 1247 import std.range.primitives : put; 1248 const spec = f.spec; 1249 immutable hex = (spec == 'x' || spec == 'X'); 1250 if (!(spec == 's' || spec == 'd' || spec =='o' || hex)) 1251 throw new FormatException("Format specifier not understood: %" ~ spec); 1252 1253 char[] buff; 1254 if (spec == 'X') 1255 { 1256 buff = data.toHexString(0, '_', 0, f.flZero ? '0' : ' ', LetterCase.upper); 1257 } 1258 else if (spec == 'x') 1259 { 1260 buff = data.toHexString(0, '_', 0, f.flZero ? '0' : ' ', LetterCase.lower); 1261 } 1262 else if (spec == 'o') 1263 { 1264 buff = data.toOctalString(); 1265 } 1266 else 1267 { 1268 buff = data.toDecimalString(0); 1269 } 1270 assert(buff.length > 0, "Invalid buffer length"); 1271 1272 char signChar = isNegative() ? '-' : 0; 1273 auto minw = buff.length + (signChar ? 1 : 0); 1274 1275 if (!hex && !signChar && (f.width == 0 || minw < f.width)) 1276 { 1277 if (f.flPlus) 1278 { 1279 signChar = '+'; 1280 ++minw; 1281 } 1282 else if (f.flSpace) 1283 { 1284 signChar = ' '; 1285 ++minw; 1286 } 1287 } 1288 1289 immutable maxw = minw < f.width ? f.width : minw; 1290 immutable difw = maxw - minw; 1291 1292 if (!f.flDash && !f.flZero) 1293 foreach (i; 0 .. difw) 1294 put(sink, " "); 1295 1296 if (signChar) 1297 { 1298 scope char[1] buf = signChar; 1299 put(sink, buf[]); 1300 } 1301 1302 if (!f.flDash && f.flZero) 1303 foreach (i; 0 .. difw) 1304 put(sink, "0"); 1305 1306 put(sink, buff); 1307 1308 if (f.flDash) 1309 foreach (i; 0 .. difw) 1310 put(sink, " "); 1311 } 1312 1313 /** 1314 `toString` is rarely directly invoked; the usual way of using it is via 1315 $(REF format, std, format): 1316 */ 1317 @safe unittest 1318 { 1319 import std.format : format; 1320 1321 auto x = BigInt("1_000_000"); 1322 x *= 12345; 1323 1324 assert(format("%d", x) == "12345000000"); 1325 assert(format("%x", x) == "2_dfd1c040"); 1326 assert(format("%X", x) == "2_DFD1C040"); 1327 assert(format("%o", x) == "133764340100"); 1328 } 1329 1330 // for backwards compatibility, see unittest below 1331 /// ditto 1332 void toString(scope void delegate(const(char)[]) sink, string formatString) const 1333 { 1334 toString!(void delegate(const(char)[]))(sink, formatString); 1335 } 1336 1337 // for backwards compatibility, see unittest below 1338 /// ditto 1339 void toString(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char f) const 1340 { 1341 toString!(void delegate(const(char)[]))(sink, f); 1342 } 1343 1344 // Backwards compatibility test 1345 // BigInt.toString used to only accept a delegate sink function, but this does not work 1346 // well with attributes such as @safe. A template function toString was added that 1347 // works on OutputRanges, but when a delegate was passed in the form of an untyped 1348 // lambda such as `str => dst.put(str)` the parameter type was inferred as `void` and 1349 // the function failed to instantiate. 1350 @system unittest 1351 { 1352 import std.format : FormatSpec; 1353 import std.array : appender; 1354 BigInt num = 503; 1355 auto dst = appender!string(); 1356 num.toString(str => dst.put(str), null); 1357 assert(dst[] == "503"); 1358 num = 504; 1359 auto f = FormatSpec!char(""); 1360 num.toString(str => dst.put(str), f); 1361 assert(dst[] == "503504"); 1362 } 1363 1364 // Implement toHash so that BigInt works properly as an AA key. 1365 /** 1366 Returns: A unique hash of the `BigInt`'s value suitable for use in a hash 1367 table. 1368 */ 1369 size_t toHash() const @safe pure nothrow @nogc 1370 { 1371 return data.toHash() + sign; 1372 } 1373 1374 /** 1375 `toHash` is rarely directly invoked; it is implicitly used when 1376 BigInt is used as the key of an associative array. 1377 */ 1378 @safe pure unittest 1379 { 1380 string[BigInt] aa; 1381 aa[BigInt(123)] = "abc"; 1382 aa[BigInt(456)] = "def"; 1383 1384 assert(aa[BigInt(123)] == "abc"); 1385 assert(aa[BigInt(456)] == "def"); 1386 } 1387 1388 /** 1389 * Gets the nth number in the underlying representation that makes up the whole 1390 * `BigInt`. 1391 * 1392 * Params: 1393 * T = the type to view the underlying representation as 1394 * n = The nth number to retrieve. Must be less than $(LREF ulongLength) or 1395 * $(LREF uintLength) with respect to `T`. 1396 * Returns: 1397 * The nth `ulong` in the representation of this `BigInt`. 1398 */ 1399 T getDigit(T = ulong)(size_t n) const 1400 if (is(T == ulong) || is(T == uint)) 1401 { 1402 static if (is(T == ulong)) 1403 { 1404 assert(n < ulongLength(), "getDigit index out of bounds"); 1405 return data.peekUlong(n); 1406 } 1407 else 1408 { 1409 assert(n < uintLength(), "getDigit index out of bounds"); 1410 return data.peekUint(n); 1411 } 1412 } 1413 1414 /// 1415 @safe pure unittest 1416 { 1417 auto a = BigInt("1000"); 1418 assert(a.ulongLength() == 1); 1419 assert(a.getDigit(0) == 1000); 1420 1421 assert(a.uintLength() == 1); 1422 assert(a.getDigit!uint(0) == 1000); 1423 1424 auto b = BigInt("2_000_000_000_000_000_000_000_000_000"); 1425 assert(b.ulongLength() == 2); 1426 assert(b.getDigit(0) == 4584946418820579328); 1427 assert(b.getDigit(1) == 108420217); 1428 1429 assert(b.uintLength() == 3); 1430 assert(b.getDigit!uint(0) == 3489660928); 1431 assert(b.getDigit!uint(1) == 1067516025); 1432 assert(b.getDigit!uint(2) == 108420217); 1433 } 1434 1435 private: 1436 void negate() @safe pure nothrow @nogc 1437 { 1438 if (!data.isZero()) 1439 sign = !sign; 1440 } 1441 bool isZero() pure const nothrow @nogc @safe 1442 { 1443 return data.isZero(); 1444 } 1445 bool isNegative() pure const nothrow @nogc @safe 1446 { 1447 return sign; 1448 } 1449 1450 // Generate a runtime error if division by zero occurs 1451 void checkDivByZero() pure const nothrow @safe 1452 { 1453 assert(!isZero(), "BigInt division by zero"); 1454 } 1455 } 1456 1457 /// 1458 @safe unittest 1459 { 1460 BigInt a = "9588669891916142"; 1461 BigInt b = "7452469135154800"; 1462 auto c = a * b; 1463 assert(c == BigInt("71459266416693160362545788781600")); 1464 auto d = b * a; 1465 assert(d == BigInt("71459266416693160362545788781600")); 1466 assert(d == c); 1467 d = c * BigInt("794628672112"); 1468 assert(d == BigInt("56783581982794522489042432639320434378739200")); 1469 auto e = c + d; 1470 assert(e == BigInt("56783581982865981755459125799682980167520800")); 1471 auto f = d + c; 1472 assert(f == e); 1473 auto g = f - c; 1474 assert(g == d); 1475 g = f - d; 1476 assert(g == c); 1477 e = 12345678; 1478 g = c + e; 1479 auto h = g / b; 1480 auto i = g % b; 1481 assert(h == a); 1482 assert(i == e); 1483 BigInt j = "-0x9A56_57f4_7B83_AB78"; 1484 BigInt k = j; 1485 j ^^= 11; 1486 assert(k ^^ 11 == j); 1487 } 1488 1489 /** 1490 Params: 1491 x = The `BigInt` to convert to a decimal `string`. 1492 1493 Returns: 1494 A `string` that represents the `BigInt` as a decimal number. 1495 1496 */ 1497 string toDecimalString(const(BigInt) x) pure nothrow @safe 1498 { 1499 auto buff = x.data.toDecimalString(x.isNegative ? 1 : 0); 1500 if (x.isNegative) 1501 buff[0] = '-'; 1502 return buff; 1503 } 1504 1505 /// 1506 @safe pure unittest 1507 { 1508 auto x = BigInt("123"); 1509 x *= 1000; 1510 x += 456; 1511 1512 auto xstr = x.toDecimalString(); 1513 assert(xstr == "123456"); 1514 } 1515 1516 /** 1517 Params: 1518 x = The `BigInt` to convert to a hexadecimal `string`. 1519 1520 Returns: 1521 A `string` that represents the `BigInt` as a hexadecimal (base 16) 1522 number in upper case. 1523 1524 */ 1525 string toHex(const(BigInt) x) @safe 1526 { 1527 import std.array : appender; 1528 auto outbuff = appender!string(); 1529 x.toString(outbuff, "%X"); 1530 return outbuff[]; 1531 } 1532 1533 /// 1534 @safe unittest 1535 { 1536 auto x = BigInt("123"); 1537 x *= 1000; 1538 x += 456; 1539 1540 auto xstr = x.toHex(); 1541 assert(xstr == "1E240"); 1542 } 1543 1544 /** Returns the absolute value of x converted to the corresponding unsigned 1545 type. 1546 1547 Params: 1548 x = The integral value to return the absolute value of. 1549 1550 Returns: 1551 The absolute value of x. 1552 1553 */ 1554 Unsigned!T absUnsign(T)(T x) 1555 if (isIntegral!T) 1556 { 1557 static if (isSigned!T) 1558 { 1559 import std.conv : unsigned; 1560 /* This returns the correct result even when x = T.min 1561 * on two's complement machines because unsigned(T.min) = |T.min| 1562 * even though -T.min = T.min. 1563 */ 1564 return unsigned((x < 0) ? cast(T)(0-x) : x); 1565 } 1566 else 1567 { 1568 return x; 1569 } 1570 } 1571 1572 /// 1573 nothrow pure @safe 1574 unittest 1575 { 1576 assert((-1).absUnsign == 1); 1577 assert(1.absUnsign == 1); 1578 } 1579 1580 nothrow pure @safe 1581 unittest 1582 { 1583 BigInt a, b; 1584 a = 1; 1585 b = 2; 1586 auto c = a + b; 1587 assert(c == 3); 1588 } 1589 1590 nothrow pure @safe 1591 unittest 1592 { 1593 long a; 1594 BigInt b; 1595 auto c = a + b; 1596 assert(c == 0); 1597 auto d = b + a; 1598 assert(d == 0); 1599 } 1600 1601 nothrow pure @safe 1602 unittest 1603 { 1604 BigInt x = 1, y = 2; 1605 assert(x < y); 1606 assert(x <= y); 1607 assert(y >= x); 1608 assert(y > x); 1609 assert(x != y); 1610 1611 long r1 = x.toLong; 1612 assert(r1 == 1); 1613 1614 BigInt r2 = 10 % x; 1615 assert(r2 == 0); 1616 1617 BigInt r3 = 10 / y; 1618 assert(r3 == 5); 1619 1620 BigInt[] arr = [BigInt(1)]; 1621 auto incr = arr[0]++; 1622 assert(arr == [BigInt(2)]); 1623 assert(incr == BigInt(1)); 1624 } 1625 1626 @safe unittest 1627 { 1628 // Radix conversion 1629 assert( toDecimalString(BigInt("-1_234_567_890_123_456_789")) 1630 == "-1234567890123456789"); 1631 assert( toHex(BigInt("0x1234567890123456789")) == "123_45678901_23456789"); 1632 assert( toHex(BigInt("0x00000000000000000000000000000000000A234567890123456789")) 1633 == "A23_45678901_23456789"); 1634 assert( toHex(BigInt("0x000_00_000000_000_000_000000000000_000000_")) == "0"); 1635 1636 assert(BigInt(-0x12345678).toInt() == -0x12345678); 1637 assert(BigInt(-0x12345678).toLong() == -0x12345678); 1638 assert(BigInt(0x1234_5678_9ABC_5A5AL).ulongLength == 1); 1639 assert(BigInt(0x1234_5678_9ABC_5A5AL).toLong() == 0x1234_5678_9ABC_5A5AL); 1640 assert(BigInt(-0x1234_5678_9ABC_5A5AL).toLong() == -0x1234_5678_9ABC_5A5AL); 1641 assert(BigInt(0xF234_5678_9ABC_5A5AL).toLong() == long.max); 1642 assert(BigInt(-0x123456789ABCL).toInt() == -int.max); 1643 char[] s1 = "123".dup; // https://issues.dlang.org/show_bug.cgi?id=8164 1644 assert(BigInt(s1) == 123); 1645 char[] s2 = "0xABC".dup; 1646 assert(BigInt(s2) == 2748); 1647 1648 assert((BigInt(-2) + BigInt(1)) == BigInt(-1)); 1649 BigInt a = ulong.max - 5; 1650 auto b = -long.max % a; 1651 assert( b == -long.max % (ulong.max - 5)); 1652 b = long.max / a; 1653 assert( b == long.max /(ulong.max - 5)); 1654 assert(BigInt(1) - 1 == 0); 1655 assert((-4) % BigInt(5) == -4); // https://issues.dlang.org/show_bug.cgi?id=5928 1656 assert(BigInt(-4) % BigInt(5) == -4); 1657 assert(BigInt(2)/BigInt(-3) == BigInt(0)); // https://issues.dlang.org/show_bug.cgi?id=8022 1658 assert(BigInt("-1") > long.min); // https://issues.dlang.org/show_bug.cgi?id=9548 1659 1660 assert(toDecimalString(BigInt("0000000000000000000000000000000000000000001234567")) 1661 == "1234567"); 1662 } 1663 1664 @safe unittest // Minimum signed value bug tests. 1665 { 1666 assert(BigInt("-0x8000000000000000") == BigInt(long.min)); 1667 assert(BigInt("-0x8000000000000000")+1 > BigInt(long.min)); 1668 assert(BigInt("-0x80000000") == BigInt(int.min)); 1669 assert(BigInt("-0x80000000")+1 > BigInt(int.min)); 1670 assert(BigInt(long.min).toLong() == long.min); // lossy toLong bug for long.min 1671 assert(BigInt(int.min).toInt() == int.min); // lossy toInt bug for int.min 1672 assert(BigInt(long.min).ulongLength == 1); 1673 assert(BigInt(int.min).uintLength == 1); // cast/sign extend bug in opAssign 1674 BigInt a; 1675 a += int.min; 1676 assert(a == BigInt(int.min)); 1677 a = int.min - BigInt(int.min); 1678 assert(a == 0); 1679 a = int.min; 1680 assert(a == BigInt(int.min)); 1681 assert(int.min % (BigInt(int.min)-1) == int.min); 1682 assert((BigInt(int.min)-1)%int.min == -1); 1683 } 1684 1685 // Recursive division (https://issues.dlang.org/show_bug.cgi?id=5568) 1686 @safe unittest 1687 { 1688 enum Z = 4843; 1689 BigInt m = (BigInt(1) << (Z*8) ) - 1; 1690 m -= (BigInt(1) << (Z*6)) - 1; 1691 BigInt oldm = m; 1692 1693 BigInt a = (BigInt(1) << (Z*4) )-1; 1694 BigInt b = m % a; 1695 m /= a; 1696 m *= a; 1697 assert( m + b == oldm); 1698 1699 m = (BigInt(1) << (4846 + 4843) ) - 1; 1700 a = (BigInt(1) << 4846 ) - 1; 1701 b = (BigInt(1) << (4846*2 + 4843)) - 1; 1702 BigInt c = (BigInt(1) << (4846*2 + 4843*2)) - 1; 1703 BigInt w = c - b + a; 1704 assert(w % m == 0); 1705 1706 // https://issues.dlang.org/show_bug.cgi?id=6819 1707 BigInt z1 = BigInt(10)^^64; 1708 BigInt w1 = BigInt(10)^^128; 1709 assert(z1^^2 == w1); 1710 BigInt z2 = BigInt(1)<<64; 1711 BigInt w2 = BigInt(1)<<128; 1712 assert(z2^^2 == w2); 1713 // https://issues.dlang.org/show_bug.cgi?id=7993 1714 BigInt n7793 = 10; 1715 assert( n7793 / 1 == 10); 1716 // https://issues.dlang.org/show_bug.cgi?id=7973 1717 auto a7973 = 10_000_000_000_000_000; 1718 const c7973 = 10_000_000_000_000_000; 1719 immutable i7973 = 10_000_000_000_000_000; 1720 BigInt v7973 = 2551700137; 1721 v7973 %= a7973; 1722 assert(v7973 == 2551700137); 1723 v7973 %= c7973; 1724 assert(v7973 == 2551700137); 1725 v7973 %= i7973; 1726 assert(v7973 == 2551700137); 1727 // https://issues.dlang.org/show_bug.cgi?id=8165 1728 BigInt[2] a8165; 1729 a8165[0] = a8165[1] = 1; 1730 } 1731 1732 @safe unittest 1733 { 1734 import std.array; 1735 import std.format; 1736 1737 immutable string[][] table = [ 1738 /* fmt, +10 -10 */ 1739 ["%d", "10", "-10"], 1740 ["%+d", "+10", "-10"], 1741 ["%-d", "10", "-10"], 1742 ["%+-d", "+10", "-10"], 1743 1744 ["%4d", " 10", " -10"], 1745 ["%+4d", " +10", " -10"], 1746 ["%-4d", "10 ", "-10 "], 1747 ["%+-4d", "+10 ", "-10 "], 1748 1749 ["%04d", "0010", "-010"], 1750 ["%+04d", "+010", "-010"], 1751 ["%-04d", "10 ", "-10 "], 1752 ["%+-04d", "+10 ", "-10 "], 1753 1754 ["% 04d", " 010", "-010"], 1755 ["%+ 04d", "+010", "-010"], 1756 ["%- 04d", " 10 ", "-10 "], 1757 ["%+- 04d", "+10 ", "-10 "], 1758 ]; 1759 1760 auto w1 = appender!(char[])(); 1761 auto w2 = appender!(char[])(); 1762 1763 foreach (entry; table) 1764 { 1765 immutable fmt = entry[0]; 1766 1767 formattedWrite(w1, fmt, BigInt(10)); 1768 formattedWrite(w2, fmt, 10); 1769 assert(w1.data == w2.data); 1770 assert(w1.data == entry[1]); 1771 w1.clear(); 1772 w2.clear(); 1773 1774 formattedWrite(w1, fmt, BigInt(-10)); 1775 formattedWrite(w2, fmt, -10); 1776 assert(w1.data == w2.data); 1777 assert(w1.data == entry[2]); 1778 w1.clear(); 1779 w2.clear(); 1780 } 1781 } 1782 1783 @safe unittest 1784 { 1785 import std.array; 1786 import std.format; 1787 1788 immutable string[][] table = [ 1789 /* fmt, +10 -10 */ 1790 ["%x", "a", "-a"], 1791 ["%+x", "a", "-a"], 1792 ["%-x", "a", "-a"], 1793 ["%+-x", "a", "-a"], 1794 1795 ["%4x", " a", " -a"], 1796 ["%+4x", " a", " -a"], 1797 ["%-4x", "a ", "-a "], 1798 ["%+-4x", "a ", "-a "], 1799 1800 ["%04x", "000a", "-00a"], 1801 ["%+04x", "000a", "-00a"], 1802 ["%-04x", "a ", "-a "], 1803 ["%+-04x", "a ", "-a "], 1804 1805 ["% 04x", "000a", "-00a"], 1806 ["%+ 04x", "000a", "-00a"], 1807 ["%- 04x", "a ", "-a "], 1808 ["%+- 04x", "a ", "-a "], 1809 ]; 1810 1811 auto w1 = appender!(char[])(); 1812 auto w2 = appender!(char[])(); 1813 1814 foreach (entry; table) 1815 { 1816 immutable fmt = entry[0]; 1817 1818 formattedWrite(w1, fmt, BigInt(10)); 1819 formattedWrite(w2, fmt, 10); 1820 assert(w1.data == w2.data); // Equal only positive BigInt 1821 assert(w1.data == entry[1]); 1822 w1.clear(); 1823 w2.clear(); 1824 1825 formattedWrite(w1, fmt, BigInt(-10)); 1826 //formattedWrite(w2, fmt, -10); 1827 //assert(w1.data == w2.data); 1828 assert(w1.data == entry[2]); 1829 w1.clear(); 1830 //w2.clear(); 1831 } 1832 } 1833 1834 @safe unittest 1835 { 1836 import std.array; 1837 import std.format; 1838 1839 immutable string[][] table = [ 1840 /* fmt, +10 -10 */ 1841 ["%X", "A", "-A"], 1842 ["%+X", "A", "-A"], 1843 ["%-X", "A", "-A"], 1844 ["%+-X", "A", "-A"], 1845 1846 ["%4X", " A", " -A"], 1847 ["%+4X", " A", " -A"], 1848 ["%-4X", "A ", "-A "], 1849 ["%+-4X", "A ", "-A "], 1850 1851 ["%04X", "000A", "-00A"], 1852 ["%+04X", "000A", "-00A"], 1853 ["%-04X", "A ", "-A "], 1854 ["%+-04X", "A ", "-A "], 1855 1856 ["% 04X", "000A", "-00A"], 1857 ["%+ 04X", "000A", "-00A"], 1858 ["%- 04X", "A ", "-A "], 1859 ["%+- 04X", "A ", "-A "], 1860 ]; 1861 1862 auto w1 = appender!(char[])(); 1863 auto w2 = appender!(char[])(); 1864 1865 foreach (entry; table) 1866 { 1867 immutable fmt = entry[0]; 1868 1869 formattedWrite(w1, fmt, BigInt(10)); 1870 formattedWrite(w2, fmt, 10); 1871 assert(w1.data == w2.data); // Equal only positive BigInt 1872 assert(w1.data == entry[1]); 1873 w1.clear(); 1874 w2.clear(); 1875 1876 formattedWrite(w1, fmt, BigInt(-10)); 1877 //formattedWrite(w2, fmt, -10); 1878 //assert(w1.data == w2.data); 1879 assert(w1.data == entry[2]); 1880 w1.clear(); 1881 //w2.clear(); 1882 } 1883 } 1884 1885 // https://issues.dlang.org/show_bug.cgi?id=6448 1886 @safe unittest 1887 { 1888 import std.array; 1889 import std.format; 1890 1891 auto w1 = appender!string(); 1892 auto w2 = appender!string(); 1893 1894 int x = 100; 1895 formattedWrite(w1, "%010d", x); 1896 BigInt bx = x; 1897 formattedWrite(w2, "%010d", bx); 1898 assert(w1.data == w2.data); 1899 // https://issues.dlang.org/show_bug.cgi?id=8011 1900 BigInt y = -3; 1901 ++y; 1902 assert(y.toLong() == -2); 1903 y = 1; 1904 --y; 1905 assert(y.toLong() == 0); 1906 --y; 1907 assert(y.toLong() == -1); 1908 --y; 1909 assert(y.toLong() == -2); 1910 } 1911 1912 @safe unittest 1913 { 1914 import std.math : abs; 1915 auto r = abs(BigInt(-1000)); // https://issues.dlang.org/show_bug.cgi?id=6486 1916 assert(r == 1000); 1917 1918 auto r2 = abs(const(BigInt)(-500)); // https://issues.dlang.org/show_bug.cgi?id=11188 1919 assert(r2 == 500); 1920 auto r3 = abs(immutable(BigInt)(-733)); // https://issues.dlang.org/show_bug.cgi?id=11188 1921 assert(r3 == 733); 1922 1923 // opCast!bool 1924 BigInt one = 1, zero; 1925 assert(one && !zero); 1926 } 1927 1928 // https://issues.dlang.org/show_bug.cgi?id=6850 1929 @safe unittest 1930 { 1931 pure long pureTest() { 1932 BigInt a = 1; 1933 BigInt b = 1336; 1934 a += b; 1935 return a.toLong(); 1936 } 1937 1938 assert(pureTest() == 1337); 1939 } 1940 1941 // https://issues.dlang.org/show_bug.cgi?id=8435 1942 // https://issues.dlang.org/show_bug.cgi?id=10118 1943 @safe unittest 1944 { 1945 auto i = BigInt(100); 1946 auto j = BigInt(100); 1947 1948 // Two separate BigInt instances representing same value should have same 1949 // hash. 1950 assert(typeid(i).getHash(&i) == typeid(j).getHash(&j)); 1951 assert(typeid(i).compare(&i, &j) == 0); 1952 1953 // BigInt AA keys should behave consistently. 1954 int[BigInt] aa; 1955 aa[BigInt(123)] = 123; 1956 assert(BigInt(123) in aa); 1957 1958 aa[BigInt(123)] = 321; 1959 assert(aa[BigInt(123)] == 321); 1960 1961 auto keys = aa.byKey; 1962 assert(keys.front == BigInt(123)); 1963 keys.popFront(); 1964 assert(keys.empty); 1965 } 1966 1967 // https://issues.dlang.org/show_bug.cgi?id=11148 1968 @safe unittest 1969 { 1970 void foo(BigInt) {} 1971 const BigInt cbi = 3; 1972 immutable BigInt ibi = 3; 1973 1974 foo(cbi); 1975 foo(ibi); 1976 1977 import std.conv : to; 1978 import std.meta : AliasSeq; 1979 1980 static foreach (T1; AliasSeq!(BigInt, const(BigInt), immutable(BigInt))) 1981 { 1982 static foreach (T2; AliasSeq!(BigInt, const(BigInt), immutable(BigInt))) 1983 {{ 1984 T1 t1 = 2; 1985 T2 t2 = t1; 1986 1987 T2 t2_1 = to!T2(t1); 1988 T2 t2_2 = cast(T2) t1; 1989 1990 assert(t2 == t1); 1991 assert(t2 == 2); 1992 1993 assert(t2_1 == t1); 1994 assert(t2_1 == 2); 1995 1996 assert(t2_2 == t1); 1997 assert(t2_2 == 2); 1998 }} 1999 } 2000 2001 BigInt n = 2; 2002 n *= 2; 2003 assert(n == 4); 2004 } 2005 2006 // https://issues.dlang.org/show_bug.cgi?id=8167 2007 @safe unittest 2008 { 2009 BigInt a = BigInt(3); 2010 BigInt b = BigInt(a); 2011 assert(b == 3); 2012 } 2013 2014 // https://issues.dlang.org/show_bug.cgi?id=9061 2015 @safe unittest 2016 { 2017 long l1 = 0x12345678_90ABCDEF; 2018 long l2 = 0xFEDCBA09_87654321; 2019 long l3 = l1 | l2; 2020 long l4 = l1 & l2; 2021 long l5 = l1 ^ l2; 2022 2023 BigInt b1 = l1; 2024 BigInt b2 = l2; 2025 BigInt b3 = b1 | b2; 2026 BigInt b4 = b1 & b2; 2027 BigInt b5 = b1 ^ b2; 2028 2029 assert(l3 == b3); 2030 assert(l4 == b4); 2031 assert(l5 == b5); 2032 } 2033 2034 // https://issues.dlang.org/show_bug.cgi?id=11600 2035 @safe unittest 2036 { 2037 import std.conv; 2038 import std.exception : assertThrown; 2039 2040 // Original bug report 2041 assertThrown!ConvException(to!BigInt("avadakedavra")); 2042 2043 // Digit string lookalikes that are actually invalid 2044 assertThrown!ConvException(to!BigInt("0123hellothere")); 2045 assertThrown!ConvException(to!BigInt("-hihomarylowe")); 2046 assertThrown!ConvException(to!BigInt("__reallynow__")); 2047 assertThrown!ConvException(to!BigInt("-123four")); 2048 } 2049 2050 // https://issues.dlang.org/show_bug.cgi?id=11583 2051 @safe unittest 2052 { 2053 BigInt x = 0; 2054 assert((x > 0) == false); 2055 } 2056 2057 // https://issues.dlang.org/show_bug.cgi?id=13391 2058 @safe unittest 2059 { 2060 BigInt x1 = "123456789"; 2061 BigInt x2 = "123456789123456789"; 2062 BigInt x3 = "123456789123456789123456789"; 2063 2064 import std.meta : AliasSeq; 2065 static foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong)) 2066 { 2067 assert((x1 * T.max) / T.max == x1); 2068 assert((x2 * T.max) / T.max == x2); 2069 assert((x3 * T.max) / T.max == x3); 2070 } 2071 2072 assert(x1 / -123456789 == -1); 2073 assert(x1 / 123456789U == 1); 2074 assert(x1 / -123456789L == -1); 2075 assert(x1 / 123456789UL == 1); 2076 assert(x2 / -123456789123456789L == -1); 2077 assert(x2 / 123456789123456789UL == 1); 2078 2079 assert(x1 / uint.max == 0); 2080 assert(x1 / ulong.max == 0); 2081 assert(x2 / ulong.max == 0); 2082 2083 x1 /= 123456789UL; 2084 assert(x1 == 1); 2085 x2 /= 123456789123456789UL; 2086 assert(x2 == 1); 2087 } 2088 2089 // https://issues.dlang.org/show_bug.cgi?id=13963 2090 @safe unittest 2091 { 2092 BigInt x = 1; 2093 import std.meta : AliasSeq; 2094 static foreach (Int; AliasSeq!(byte, ubyte, short, ushort, int)) 2095 { 2096 assert(is(typeof(x % Int(1)) == int)); 2097 } 2098 assert(is(typeof(x % 1U) == long)); 2099 assert(is(typeof(x % 1L) == long)); 2100 assert(is(typeof(x % 1UL) == BigInt)); 2101 2102 auto x0 = BigInt(uint.max - 1); 2103 auto x1 = BigInt(8); 2104 assert(x1 / x == x1); 2105 auto x2 = -BigInt(long.min) + 1; 2106 2107 // uint 2108 assert( x0 % uint.max == x0 % BigInt(uint.max)); 2109 assert(-x0 % uint.max == -x0 % BigInt(uint.max)); 2110 assert( x0 % uint.max == long(uint.max - 1)); 2111 assert(-x0 % uint.max == -long(uint.max - 1)); 2112 2113 // long 2114 assert(x1 % 2L == 0L); 2115 assert(-x1 % 2L == 0L); 2116 2117 assert(x1 % 3L == 2L); 2118 assert(x1 % -3L == 2L); 2119 assert(-x1 % 3L == -2L); 2120 assert(-x1 % -3L == -2L); 2121 2122 assert(x1 % 11L == 8L); 2123 assert(x1 % -11L == 8L); 2124 assert(-x1 % 11L == -8L); 2125 assert(-x1 % -11L == -8L); 2126 2127 // ulong 2128 assert(x1 % 2UL == BigInt(0)); 2129 assert(-x1 % 2UL == BigInt(0)); 2130 2131 assert(x1 % 3UL == BigInt(2)); 2132 assert(-x1 % 3UL == -BigInt(2)); 2133 2134 assert(x1 % 11UL == BigInt(8)); 2135 assert(-x1 % 11UL == -BigInt(8)); 2136 2137 assert(x2 % ulong.max == x2); 2138 assert(-x2 % ulong.max == -x2); 2139 } 2140 2141 // https://issues.dlang.org/show_bug.cgi?id=14124 2142 @safe unittest 2143 { 2144 auto x = BigInt(-3); 2145 x %= 3; 2146 assert(!x.isNegative()); 2147 assert(x.isZero()); 2148 2149 x = BigInt(-3); 2150 x %= cast(ushort) 3; 2151 assert(!x.isNegative()); 2152 assert(x.isZero()); 2153 2154 x = BigInt(-3); 2155 x %= 3L; 2156 assert(!x.isNegative()); 2157 assert(x.isZero()); 2158 2159 x = BigInt(3); 2160 x %= -3; 2161 assert(!x.isNegative()); 2162 assert(x.isZero()); 2163 } 2164 2165 // https://issues.dlang.org/show_bug.cgi?id=15678 2166 @safe unittest 2167 { 2168 import std.exception : assertThrown; 2169 assertThrown!ConvException(BigInt("")); 2170 assertThrown!ConvException(BigInt("0x1234BARF")); 2171 assertThrown!ConvException(BigInt("1234PUKE")); 2172 } 2173 2174 // https://issues.dlang.org/show_bug.cgi?id=6447 2175 @safe unittest 2176 { 2177 import std.algorithm.comparison : equal; 2178 import std.range : iota; 2179 2180 auto s = BigInt(1_000_000_000_000); 2181 auto e = BigInt(1_000_000_000_003); 2182 auto r = iota(s, e); 2183 assert(r.equal([ 2184 BigInt(1_000_000_000_000), 2185 BigInt(1_000_000_000_001), 2186 BigInt(1_000_000_000_002) 2187 ])); 2188 } 2189 2190 // https://issues.dlang.org/show_bug.cgi?id=17330 2191 @safe unittest 2192 { 2193 auto b = immutable BigInt("123"); 2194 assert(b == 123); 2195 } 2196 2197 // https://issues.dlang.org/show_bug.cgi?id=14767 2198 @safe pure unittest 2199 { 2200 static immutable a = BigInt("340282366920938463463374607431768211455"); 2201 assert(a == BigInt("340282366920938463463374607431768211455")); 2202 2203 BigInt plusTwo(in BigInt n) 2204 { 2205 return n + 2; 2206 } 2207 2208 enum BigInt test1 = BigInt(123); 2209 enum BigInt test2 = plusTwo(test1); 2210 assert(test2 == 125); 2211 } 2212 2213 /** 2214 * Finds the quotient and remainder for the given dividend and divisor in one operation. 2215 * 2216 * Params: 2217 * dividend = the $(LREF BigInt) to divide 2218 * divisor = the $(LREF BigInt) to divide the dividend by 2219 * quotient = is set to the result of the division 2220 * remainder = is set to the remainder of the division 2221 */ 2222 void divMod(const BigInt dividend, const BigInt divisor, out BigInt quotient, out BigInt remainder) pure nothrow @safe 2223 { 2224 BigUint q, r; 2225 BigUint.divMod(dividend.data, divisor.data, q, r); 2226 quotient.sign = dividend.sign != divisor.sign; 2227 quotient.data = q; 2228 remainder.sign = dividend.sign; 2229 remainder.data = r; 2230 } 2231 2232 /// 2233 @safe pure nothrow unittest 2234 { 2235 auto a = BigInt(123); 2236 auto b = BigInt(25); 2237 BigInt q, r; 2238 2239 divMod(a, b, q, r); 2240 2241 assert(q == 4); 2242 assert(r == 23); 2243 assert(q * b + r == a); 2244 } 2245 2246 // https://issues.dlang.org/show_bug.cgi?id=18086 2247 @safe pure nothrow unittest 2248 { 2249 BigInt q = 1; 2250 BigInt r = 1; 2251 BigInt c = 1024; 2252 BigInt d = 100; 2253 2254 divMod(c, d, q, r); 2255 assert(q == 10); 2256 assert(r == 24); 2257 assert((q * d + r) == c); 2258 2259 divMod(c, -d, q, r); 2260 assert(q == -10); 2261 assert(r == 24); 2262 assert(q * -d + r == c); 2263 2264 divMod(-c, -d, q, r); 2265 assert(q == 10); 2266 assert(r == -24); 2267 assert(q * -d + r == -c); 2268 2269 divMod(-c, d, q, r); 2270 assert(q == -10); 2271 assert(r == -24); 2272 assert(q * d + r == -c); 2273 } 2274 2275 // https://issues.dlang.org/show_bug.cgi?id=19740 2276 @safe unittest 2277 { 2278 BigInt a = BigInt( 2279 "241127122100380210001001124020210001001100000200003101000062221012075223052000021042250111300200000000000" ~ 2280 "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); 2281 BigInt b = BigInt( 2282 "700200000000500418321000401140010110000022007221432000000141020011323301104104060202100200457210001600142" ~ 2283 "000001012245300100001110215200000000120000000000000000000000000000000000000000000000000000000000000000000" ~ 2284 "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); 2285 2286 BigInt c = a * b; 2287 assert(c == BigInt( 2288 "1688372108948068874722901180228375682334987075822938736581472847151834613694489486296103575639363261807341" ~ 2289 "3910091006778604956808730652275328822700182498926542563654351871390166691461743896850906716336187966456064" ~ 2290 "2702007176328110013356024000000000000000000000000000000000000000000000000000000000000000000000000000000000" ~ 2291 "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ~ 2292 "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); 2293 } 2294 2295 @safe unittest 2296 { 2297 auto n = BigInt("1234"d); 2298 } 2299 2300 /** 2301 Fast power modulus calculation for $(LREF BigInt) operands. 2302 Params: 2303 base = the $(LREF BigInt) is basic operands. 2304 exponent = the $(LREF BigInt) is power exponent of base. 2305 modulus = the $(LREF BigInt) is modules to be modular of base ^ exponent. 2306 Returns: 2307 The power modulus value of (base ^ exponent) % modulus. 2308 */ 2309 BigInt powmod(BigInt base, BigInt exponent, BigInt modulus) pure nothrow @safe 2310 { 2311 BigInt result = 1; 2312 2313 while (exponent) 2314 { 2315 if (exponent.data.peekUint(0) & 1) 2316 { 2317 result = (result * base) % modulus; 2318 } 2319 2320 auto tmp = base % modulus; 2321 base = (tmp * tmp) % modulus; 2322 exponent >>= 1; 2323 } 2324 2325 return result; 2326 } 2327 2328 /// for powmod 2329 @safe unittest 2330 { 2331 BigInt base = BigInt("123456789012345678901234567890"); 2332 BigInt exponent = BigInt("1234567890123456789012345678901234567"); 2333 BigInt modulus = BigInt("1234567"); 2334 2335 BigInt result = powmod(base, exponent, modulus); 2336 assert(result == 359079); 2337 }