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