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