c++: auto in trailing-return-type in parameter [PR117778]
[gcc.git] / libphobos / src / std / bigint.d
bloba8b389795976cc75d387827a3cc74b3a441527d2
1 /** Arbitrary-precision ('bignum') arithmetic.
3 * Performance is optimized for numbers below ~1000 decimal digits.
4 * For X86 machines, highly optimised assembly routines are used.
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 * )
14 * For very large numbers, consider using the $(HTTP gmplib.org, GMP library) instead.
16 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
17 * Authors: Don Clugston
18 * Source: $(PHOBOSSRC std/bigint.d)
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)
26 module std.bigint;
28 import std.conv : ConvException;
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;
37 /** A struct representing an arbitrary precision integer.
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.
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.)
48 struct BigInt
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.
60 * Params:
61 * s = a finite bidirectional range of any character type
63 * Throws:
64 * $(REF ConvException, std,conv) if the string doesn't represent a valid number
66 this(Range)(Range s)
67 if (isBidirectionalRange!Range &&
68 isSomeChar!(ElementType!Range) &&
69 !isInfinite!Range &&
70 !isNarrowString!Range)
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;
78 enforce!ConvException(!s.empty, "Can't initialize BigInt with an empty range");
80 bool neg = false;
81 bool ok;
83 data = 0UL;
85 // check for signs and if the string is a hex value
86 if (s.front == '+')
88 s.popFront(); // skip '+'
90 else if (s.front == '-')
92 neg = true;
93 s.popFront();
96 if (s.save.startsWith("0x".byChar) ||
97 s.save.startsWith("0X".byChar))
99 s.popFront;
100 s.popFront;
102 if (!s.empty)
103 ok = data.fromHexString(s.filterBidirectional!(a => a != '_'));
104 else
105 ok = false;
107 else
109 ok = data.fromDecimalString(s.filterBidirectional!(a => a != '_'));
112 enforce!ConvException(ok, "Not a valid numerical string");
114 if (isZero())
115 neg = false;
117 sign = neg;
120 /// ditto
121 this(Range)(Range s) pure
122 if (isNarrowString!Range)
124 import std.utf : byCodeUnit;
125 this(s.byCodeUnit);
128 @safe unittest
130 // system because of the dummy ranges eventually call std.array!string
131 import std.exception : assertThrown;
132 import std.internal.test.dummyrange;
134 auto r1 = new ReferenceBidirectionalRange!dchar("101");
135 auto big1 = BigInt(r1);
136 assert(big1 == BigInt(101));
138 auto r2 = new ReferenceBidirectionalRange!dchar("1_000");
139 auto big2 = BigInt(r2);
140 assert(big2 == BigInt(1000));
142 auto r3 = new ReferenceBidirectionalRange!dchar("0x0");
143 auto big3 = BigInt(r3);
144 assert(big3 == BigInt(0));
146 auto r4 = new ReferenceBidirectionalRange!dchar("0x");
147 assertThrown!ConvException(BigInt(r4));
151 * Construct a `BigInt` from a sign and a magnitude.
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.
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
163 this(Range)(bool isNegative, Range magnitude)
164 if (isInputRange!Range &&
165 isUnsigned!(ElementType!Range) &&
166 (hasLength!Range || isForwardRange!Range) &&
167 !isInfinite!Range)
169 data.fromMagnitude(magnitude);
170 sign = isNegative && !data.isZero;
174 pure @safe unittest
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);
183 /// Construct a `BigInt` from a built-in integral type.
184 this(T)(T x) pure nothrow @safe
185 if (isIntegral!T)
187 data = data.init; // @@@: Workaround for compiler bug
188 opAssign(x);
192 @safe unittest
194 ulong data = 1_000_000_000_000;
195 auto bigData = BigInt(data);
196 assert(bigData == BigInt("1_000_000_000_000"));
199 /// Construct a `BigInt` from another `BigInt`.
200 this(T)(T x) pure nothrow @safe
201 if (is(immutable T == immutable BigInt))
203 opAssign(x);
207 @safe unittest
209 const(BigInt) b1 = BigInt("1_234_567_890");
210 BigInt b2 = BigInt(b1);
211 assert(b2 == BigInt("1_234_567_890"));
214 /// Assignment from built-in integer types.
215 BigInt opAssign(T)(T x) pure nothrow @safe
216 if (isIntegral!T)
218 data = cast(ulong) absUnsign(x);
219 sign = (x < 0);
220 return this;
224 @safe unittest
226 auto b = BigInt("123");
227 b = 456;
228 assert(b == BigInt("456"));
231 /// Assignment from another BigInt.
232 BigInt opAssign(T:BigInt)(T x) pure @nogc @safe
234 data = x.data;
235 sign = x.sign;
236 return this;
240 @safe unittest
242 auto b1 = BigInt("123");
243 auto b2 = BigInt("456");
244 b2 = b1;
245 assert(b2 == BigInt("123"));
249 * Implements assignment operators from built-in integers of the form
250 * `BigInt op= integer`.
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)
256 ulong u = absUnsign(y);
258 static if (op=="+")
260 data = BigUint.addOrSubInt!ulong(data, u, wantSub: sign != (y<0), sign);
262 else static if (op=="-")
264 data = BigUint.addOrSubInt!ulong(data, u, wantSub: sign == (y<0), sign);
266 else static if (op=="*")
268 if (y == 0)
270 sign = false;
271 data = 0UL;
273 else
275 sign = ( sign != (y<0) );
276 data = BigUint.mulInt(data, u);
279 else static if (op=="/")
281 assert(y != 0, "Division by zero");
282 static if (T.sizeof <= uint.sizeof)
284 data = BigUint.divInt(data, cast(uint) u);
286 else
288 data = BigUint.divInt(data, u);
290 sign = data.isZero() ? false : sign ^ (y < 0);
292 else static if (op=="%")
294 assert(y != 0, "Division by zero");
295 static if (is(immutable(T) == immutable(long)) || is( immutable(T) == immutable(ulong) ))
297 this %= BigInt(y);
299 else
301 data = cast(ulong) BigUint.modInt(data, cast(uint) u);
302 if (data.isZero())
303 sign = false;
305 // x%y always has the same sign as x.
306 // This is not the same as mathematical mod.
308 else static if (op==">>" || op=="<<")
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=="<<"))
316 // Sign never changes during left shift
317 data = data.opBinary!(op)(u);
319 else
321 data = data.opBinary!(op)(u);
322 if (data.isZero())
323 sign = false;
326 else static if (op=="^^")
328 sign = (y & 1) ? sign : false;
329 if (y < 0)
331 checkDivByZero();
332 data = cast(ulong) (data == 1);
334 else
336 data = BigUint.pow(data, u);
339 else static if (op=="&")
341 if (y >= 0 && (y <= 1 || !sign)) // In these cases we can avoid some allocation.
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;
349 else
351 BigInt b = y;
352 opOpAssign!op(b);
355 else static if (op=="|" || op=="^")
357 BigInt b = y;
358 opOpAssign!op(b);
360 else static assert(0, "BigInt " ~ op[0..$-1] ~ "= " ~ T.stringof ~ " is not supported");
361 return this;
365 @safe unittest
367 auto b = BigInt("1_000_000_000");
369 b += 12345;
370 assert(b == BigInt("1_000_012_345"));
372 b /= 5;
373 assert(b == BigInt("200_002_469"));
376 // https://issues.dlang.org/show_bug.cgi?id=16264
377 @safe unittest
379 auto a = BigInt(
380 `335690982744637013564796917901053301979460129353374296317539383938630086938` ~
381 `465898213033510992292836631752875403891802201862860531801760096359705447768` ~
382 `957432600293361240407059207520920532482429912948952142341440301429494694368` ~
383 `264560802292927144211230021750155988283029753927847924288850436812178022006` ~
384 `408597793414273953252832688620479083497367463977081627995406363446761896298` ~
385 `967177607401918269561385622811274398143647535024987050366350585544531063531` ~
386 `7118554808325723941557169427279911052268935775`);
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`);
401 BigInt c = a * b; // Crashes
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`
425 // https://issues.dlang.org/show_bug.cgi?id=24028
426 @system unittest
428 import std.exception : assertThrown;
429 import core.exception : AssertError;
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);
439 * Implements assignment operators of the form `BigInt op= BigInt`.
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))
444 static if (op == "+")
446 data = BigUint.addOrSub(data, y.data, sign != y.sign, sign);
448 else static if (op == "-")
450 data = BigUint.addOrSub(data, y.data, sign == y.sign, sign);
452 else static if (op == "*")
454 data = BigUint.mul(data, y.data);
455 sign = isZero() ? false : sign ^ y.sign;
457 else static if (op == "/")
459 y.checkDivByZero();
460 if (!isZero())
462 data = BigUint.div(data, y.data);
463 sign = isZero() ? false : sign ^ y.sign;
466 else static if (op == "%")
468 y.checkDivByZero();
469 if (!isZero())
471 data = BigUint.mod(data, y.data);
472 // x%y always has the same sign as x.
473 if (isZero())
474 sign = false;
477 else static if (op == "|" || op == "&" || op == "^")
479 data = BigUint.bitwiseOp!op(data, y.data, sign, y.sign, sign);
481 else static assert(0, "BigInt " ~ op[0..$-1] ~ "= " ~
482 T.stringof ~ " is not supported");
483 return this;
487 @safe unittest
489 auto x = BigInt("123");
490 auto y = BigInt("321");
491 x += y;
492 assert(x == BigInt("444"));
496 * Implements binary operators between `BigInt`s.
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))
502 BigInt r = this;
503 return r.opOpAssign!(op)(y);
507 @safe unittest
509 auto x = BigInt("123");
510 auto y = BigInt("456");
511 BigInt z = x * y;
512 assert(z == BigInt("56088"));
516 * Implements binary operators between `BigInt`'s and built-in integers.
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)
523 BigInt r = this;
524 r.opOpAssign!(op)(y);
525 return r;
529 @safe unittest
531 auto x = BigInt("123");
532 x *= 300;
533 assert(x == BigInt("36900"));
537 Implements a narrowing remainder operation with built-in integer types.
539 This binary operator returns a narrower, built-in integer type
540 where applicable, according to the following table.
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`))
549 auto opBinary(string op, T)(T y) pure nothrow @safe const
550 if (op == "%" && isIntegral!T)
552 assert(y != 0, "% 0 not allowed");
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))
560 auto r = this % BigInt(y);
562 static if (is(immutable T == immutable long))
564 return r.toLong();
566 else
568 // return as-is to avoid overflow
569 return r;
572 else
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;
587 @safe unittest
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;
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);
602 Implements operators with built-in integers on the left-hand side and
603 `BigInt` on the right-hand side.
605 BigInt opBinaryRight(string op, T)(T y) pure nothrow @safe const
606 if ((op=="+" || op=="*" || op=="|" || op=="&" || op=="^") && isIntegral!T)
608 return opBinary!(op)(y);
612 @safe unittest
614 auto x = BigInt("100");
615 BigInt y = 123 + x;
616 assert(y == BigInt("223"));
618 BigInt z = 123 - x;
619 assert(z == BigInt("23"));
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);
628 // BigInt = integer op BigInt
629 /// ditto
630 BigInt opBinaryRight(string op, T)(T y) pure nothrow @safe const
631 if (op == "-" && isIntegral!T)
633 ulong u = absUnsign(y);
634 BigInt r;
635 static if (op == "-")
637 r.sign = sign;
638 r.data = BigUint.addOrSubInt!ulong(data, u, wantSub: sign == (y<0), r.sign);
639 r.negate();
641 return r;
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)
649 checkDivByZero();
651 static if (op == "%")
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);
661 else static if (op == "/")
663 if (data.ulongLength > 1)
664 return 0;
665 return cast(T)(x / data.peekUlong(0));
669 // const unary operations
671 Implements `BigInt` unary operators.
673 BigInt opUnary(string op)() pure nothrow @safe const
674 if (op=="+" || op=="-" || op=="~")
676 static if (op=="-")
678 BigInt r = this;
679 r.negate();
680 return r;
682 else static if (op=="~")
684 return -(this+1);
686 else static if (op=="+")
687 return this;
690 // non-const unary operations
691 /// ditto
692 BigInt opUnary(string op)() pure nothrow @safe
693 if (op=="++" || op=="--")
695 static if (op=="++")
697 data = BigUint.addOrSubInt!ulong(data, 1UL, wantSub: sign, sign);
698 return this;
700 else static if (op=="--")
702 data = BigUint.addOrSubInt!ulong(data, 1UL, wantSub: !sign, sign);
703 return this;
708 @safe unittest
710 auto x = BigInt("1234");
711 assert(-x == BigInt("-1234"));
713 ++x;
714 assert(x == BigInt("1235"));
718 Implements `BigInt` equality test with other `BigInt`'s and built-in
719 numeric types.
721 bool opEquals()(auto ref const BigInt y) const pure @nogc @safe
723 return sign == y.sign && y.data == data;
726 /// ditto
727 bool opEquals(T)(const T y) const pure nothrow @nogc @safe
728 if (isIntegral!T)
730 if (sign != (y<0))
731 return 0;
732 return data.opEquals(cast(ulong) absUnsign(y));
735 /// ditto
736 bool opEquals(T)(const T y) const pure nothrow @nogc
737 if (isFloatingPoint!T)
739 return 0 == opCmp(y);
743 @safe unittest
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);
751 @safe unittest
753 auto x = BigInt("12345");
754 auto y = BigInt("12340");
755 int z = 12345;
756 int w = 54321;
758 assert(x == x);
759 assert(x != y);
760 assert(x == y + 5);
761 assert(x == z);
762 assert(x != w);
765 @safe unittest
767 import std.math.operations : nextDown, nextUp;
769 const x = BigInt("0x1abc_de80_0000_0000_0000_0000_0000_0000");
770 BigInt x1 = x + 1;
771 BigInt x2 = x - 1;
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);
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);
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);
799 Implements casting to `bool`.
801 T opCast(T:bool)() pure nothrow @nogc @safe const
803 return !isZero();
807 @safe unittest
809 // Non-zero values are regarded as true
810 auto x = BigInt("1");
811 auto y = BigInt("10");
812 assert(x);
813 assert(y);
815 // Zero value is regarded as false
816 auto z = BigInt("0");
817 assert(!z);
821 Implements casting to integer types.
823 Throws: $(REF ConvOverflowException, std,conv) if the number exceeds
824 the target type's range.
826 T opCast(T:ulong)() pure @safe const
828 if (isUnsigned!T && sign)
829 { /* throw */ }
830 else
831 if (data.ulongLength == 1)
833 ulong l = data.peekUlong(0);
834 if (isUnsigned!T || !sign)
836 if (l <= T.max)
837 return cast(T) l;
839 else
841 if (l <= ulong(T.max)+1)
842 return cast(T)-long(l); // -long.min == long.min
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));
854 @safe unittest
856 import std.conv : to, ConvOverflowException;
857 import std.exception : assertThrown;
859 assert(BigInt("0").to!int == 0);
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);
867 @safe unittest
869 import std.conv : to, ConvOverflowException;
870 import std.exception : assertThrown;
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);
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);
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);
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);
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);
902 Implements casting to floating point types.
904 T opCast(T)() @safe nothrow @nogc const
905 if (isFloatingPoint!T)
907 return toFloat!(T, "nearest");
911 @system unittest
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);
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);
925 /// Rounding when casting to floating point
926 @system unittest
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.
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);
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);
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);
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);
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);
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);
966 @safe unittest
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);
973 private T toFloat(T, string roundingMode)() @safe nothrow @nogc const
974 if (__traits(isFloating, T) && (roundingMode == "nearest" || roundingMode == "truncate"))
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)
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)
995 sansExponent += 1UL << (64 - totalNeededBits);
996 if (0 <= cast(long) sansExponent) // Use high bit to detect overflow.
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;
1004 static if (T.mant_dig == float.mant_dig)
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)();
1014 else static if (T.mant_dig == double.mant_dig)
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)();
1024 else
1026 import core.math : ldexp;
1027 return ldexp(isNegative ? -cast(real) sansExponent : cast(real) sansExponent,
1028 cast(int) exponent - 65);
1031 else
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--)
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)
1049 acc += ldexp(cast(T) w, scale -= 64);
1050 bitsStillNeeded -= 64;
1052 else
1054 w = (w >>> (64 - bitsStillNeeded)) << (64 - bitsStillNeeded);
1055 acc += ldexp(cast(T) w, scale -= 64);
1056 break;
1059 if (isNegative)
1060 acc = -acc;
1061 return cast(T) acc;
1066 Implements casting to/from qualified `BigInt`'s.
1068 Warning: Casting to/from `const` or `immutable` may break type
1069 system guarantees. Use with care.
1071 T opCast(T)() pure nothrow @nogc const
1072 if (is(immutable T == immutable BigInt))
1074 return this;
1078 @safe unittest
1080 const(BigInt) x = BigInt("123");
1081 BigInt y = cast() x; // cast away const
1082 assert(y == x);
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.
1089 Implements 3-way comparisons of `BigInt` with `BigInt` or `BigInt` with
1090 built-in numeric types.
1092 int opCmp(ref const BigInt y) pure nothrow @nogc @safe const
1094 // Simply redirect to the "real" opCmp implementation.
1095 return this.opCmp!BigInt(y);
1098 /// ditto
1099 int opCmp(T)(const T y) pure nothrow @nogc @safe const
1100 if (isIntegral!T)
1102 if (sign != (y<0) )
1103 return sign ? -1 : 1;
1104 int cmp = data.opCmp(cast(ulong) absUnsign(y));
1105 return sign? -cmp: cmp;
1107 /// ditto
1108 int opCmp(T)(const T y) nothrow @nogc @safe const
1109 if (isFloatingPoint!T)
1111 import core.bitop : bsr;
1112 import std.math.operations : cmp;
1113 import std.math.traits : isFinite;
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)
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;
1137 return 0;
1139 /// ditto
1140 int opCmp(T:BigInt)(const T y) pure nothrow @nogc @safe const
1142 if (sign != y.sign)
1143 return sign ? -1 : 1;
1144 immutable cmp = data.opCmp(y.data);
1145 return sign? -cmp: cmp;
1149 @safe unittest
1151 auto x = BigInt("100");
1152 auto y = BigInt("10");
1153 int z = 50;
1154 const int w = 200;
1156 assert(y < x);
1157 assert(x > z);
1158 assert(z > y);
1159 assert(x < w);
1163 @safe unittest
1165 auto x = BigInt("0x1abc_de80_0000_0000_0000_0000_0000_0000");
1166 BigInt y = x - 1;
1167 BigInt z = x + 1;
1169 double d = 0x1.abcde8p124;
1170 assert(y < d);
1171 assert(z > d);
1172 assert(x >= d && x <= d);
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);
1180 @safe unittest
1182 assert(BigInt("999_999_999_999_999_999_999_999_999_999_999_999_999") < float.infinity);
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;
1189 real d = 0x1.abcde8p124;
1190 assert(y < d);
1191 assert(z > d);
1192 assert(x >= d && x <= d);
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);
1202 double e = 0x1.abcde8p+60;
1203 assert(w1 >= e && w1 <= e);
1204 assert(w2 < e);
1205 assert(w3 > e);
1207 real eL = 0x1.abcde8p+60;
1208 assert(w1 >= eL && w1 <= eL);
1209 assert(w2 < eL);
1210 assert(w3 > eL);
1214 Returns: The value of this `BigInt` as a `long`, or `long.max`/`long.min`
1215 if outside the representable range.
1217 long toLong() @safe pure nothrow const @nogc
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);
1226 @safe unittest
1228 auto b = BigInt("12345");
1229 long l = b.toLong();
1230 assert(l == 12345);
1234 Returns: The value of this `BigInt` as an `int`, or `int.max`/`int.min` if outside
1235 the representable range.
1237 int toInt() @safe pure nothrow @nogc const
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);
1246 @safe unittest
1248 auto big = BigInt("5_000_000");
1249 auto i = big.toInt();
1250 assert(i == 5_000_000);
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);
1258 /// Number of significant `uint`s which are used in storing this number.
1259 /// The absolute value of this `BigInt` is always &lt; 2$(SUPERSCRIPT 32*uintLength)
1260 @property size_t uintLength() @safe pure nothrow @nogc const
1262 return data.uintLength;
1265 /// Number of significant `ulong`s which are used in storing this number.
1266 /// The absolute value of this `BigInt` is always &lt; 2$(SUPERSCRIPT 64*ulongLength)
1267 @property size_t ulongLength() @safe pure nothrow @nogc const
1269 return data.ulongLength;
1272 /** Convert the `BigInt` to `string`, passing it to the given sink.
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.
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") ))
1288 void toString(Writer)(scope ref Writer sink, string formatString) const
1290 auto f = FormatSpec!char(formatString);
1291 f.writeUpToNextSpec(sink);
1292 toString!Writer(sink, f);
1295 /// ditto
1296 void toString(Writer)(scope ref Writer sink, scope const ref FormatSpec!char f) const
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);
1304 char[] buff;
1305 if (spec == 'X')
1307 buff = data.toHexString(0, '_', 0, f.flZero ? '0' : ' ', LetterCase.upper);
1309 else if (spec == 'x')
1311 buff = data.toHexString(0, '_', 0, f.flZero ? '0' : ' ', LetterCase.lower);
1313 else if (spec == 'o')
1315 buff = data.toOctalString();
1317 else
1319 buff = data.toDecimalString(0);
1321 assert(buff.length > 0, "Invalid buffer length");
1323 char signChar = isNegative ? '-' : 0;
1324 auto minw = buff.length + (signChar ? 1 : 0);
1326 if (!hex && !signChar && (f.width == 0 || minw < f.width))
1328 if (f.flPlus)
1330 signChar = '+';
1331 ++minw;
1333 else if (f.flSpace)
1335 signChar = ' ';
1336 ++minw;
1340 immutable maxw = minw < f.width ? f.width : minw;
1341 immutable difw = maxw - minw;
1343 if (!f.flDash && !f.flZero)
1344 foreach (i; 0 .. difw)
1345 put(sink, " ");
1347 if (signChar)
1349 scope char[1] buf = signChar;
1350 put(sink, buf[]);
1353 if (!f.flDash && f.flZero)
1354 foreach (i; 0 .. difw)
1355 put(sink, "0");
1357 put(sink, buff);
1359 if (f.flDash)
1360 foreach (i; 0 .. difw)
1361 put(sink, " ");
1365 `toString` is rarely directly invoked; the usual way of using it is via
1366 $(REF format, std, format):
1368 @safe unittest
1370 import std.format : format;
1372 auto x = BigInt("1_000_000");
1373 x *= 12345;
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");
1381 // for backwards compatibility, see unittest below
1382 /// ditto
1383 void toString(scope void delegate(scope const(char)[]) sink, string formatString) const
1385 toString!(void delegate(scope const(char)[]))(sink, formatString);
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
1392 toString!(void delegate(scope const(char)[]))(sink, f);
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
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");
1415 // Implement toHash so that BigInt works properly as an AA key.
1417 Returns: A unique hash of the `BigInt`'s value suitable for use in a hash
1418 table.
1420 size_t toHash() const @safe pure nothrow @nogc
1422 return data.toHash() + sign;
1426 `toHash` is rarely directly invoked; it is implicitly used when
1427 BigInt is used as the key of an associative array.
1429 @safe pure unittest
1431 string[BigInt] aa;
1432 aa[BigInt(123)] = "abc";
1433 aa[BigInt(456)] = "def";
1435 assert(aa[BigInt(123)] == "abc");
1436 assert(aa[BigInt(456)] == "def");
1440 * Gets the nth number in the underlying representation that makes up the whole
1441 * `BigInt`.
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`.
1450 T getDigit(T = ulong)(size_t n) const
1451 if (is(T == ulong) || is(T == uint))
1453 static if (is(T == ulong))
1455 assert(n < ulongLength(), "getDigit index out of bounds");
1456 return data.peekUlong(n);
1458 else
1460 assert(n < uintLength(), "getDigit index out of bounds");
1461 return data.peekUint(n);
1466 @safe pure unittest
1468 auto a = BigInt("1000");
1469 assert(a.ulongLength() == 1);
1470 assert(a.getDigit(0) == 1000);
1472 assert(a.uintLength() == 1);
1473 assert(a.getDigit!uint(0) == 1000);
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);
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);
1486 private:
1487 void negate() @safe pure nothrow @nogc scope
1489 if (!data.isZero())
1490 sign = !sign;
1492 bool isZero() pure const nothrow @nogc @safe scope
1494 return data.isZero();
1496 alias isNegative = sign;
1498 // Generate a runtime error if division by zero occurs
1499 void checkDivByZero() pure const nothrow @safe scope
1501 assert(!isZero(), "BigInt division by zero");
1506 @safe unittest
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);
1538 Params:
1539 x = The `BigInt` to convert to a decimal `string`.
1541 Returns:
1542 A `string` that represents the `BigInt` as a decimal number.
1545 string toDecimalString(const(BigInt) x) pure nothrow @safe
1547 auto buff = x.data.toDecimalString(x.isNegative ? 1 : 0);
1548 if (x.isNegative)
1549 buff[0] = '-';
1550 return buff;
1554 @safe pure unittest
1556 auto x = BigInt("123");
1557 x *= 1000;
1558 x += 456;
1560 auto xstr = x.toDecimalString();
1561 assert(xstr == "123456");
1565 Params:
1566 x = The `BigInt` to convert to a hexadecimal `string`.
1568 Returns:
1569 A `string` that represents the `BigInt` as a hexadecimal (base 16)
1570 number in upper case.
1573 string toHex(const(BigInt) x) pure @safe
1575 import std.array : appender;
1576 auto outbuff = appender!string();
1577 x.toString(outbuff, "%X");
1578 return outbuff[];
1582 @safe unittest
1584 auto x = BigInt("123");
1585 x *= 1000;
1586 x += 456;
1588 auto xstr = x.toHex();
1589 assert(xstr == "1E240");
1592 /** Returns the absolute value of x converted to the corresponding unsigned
1593 type.
1595 Params:
1596 x = The integral value to return the absolute value of.
1598 Returns:
1599 The absolute value of x.
1602 Unsigned!T absUnsign(T)(T x)
1603 if (isIntegral!T)
1605 static if (isSigned!T)
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.
1612 return unsigned((x < 0) ? cast(T)(0-x) : x);
1614 else
1616 return x;
1621 nothrow pure @safe
1622 unittest
1624 assert((-1).absUnsign == 1);
1625 assert(1.absUnsign == 1);
1628 nothrow pure @safe
1629 unittest
1631 BigInt a, b;
1632 a = 1;
1633 b = 2;
1634 auto c = a + b;
1635 assert(c == 3);
1638 nothrow pure @safe
1639 unittest
1641 long a;
1642 BigInt b;
1643 auto c = a + b;
1644 assert(c == 0);
1645 auto d = b + a;
1646 assert(d == 0);
1649 nothrow pure @safe
1650 unittest
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);
1659 long r1 = x.toLong;
1660 assert(r1 == 1);
1662 BigInt r2 = 10 % x;
1663 assert(r2 == 0);
1665 BigInt r3 = 10 / y;
1666 assert(r3 == 5);
1668 BigInt[] arr = [BigInt(1)];
1669 auto incr = arr[0]++;
1670 assert(arr == [BigInt(2)]);
1671 assert(incr == BigInt(1));
1674 @safe unittest
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");
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);
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
1708 assert(toDecimalString(BigInt("0000000000000000000000000000000000000000001234567"))
1709 == "1234567");
1712 @safe unittest // Minimum signed value bug tests.
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);
1733 // Recursive division (https://issues.dlang.org/show_bug.cgi?id=5568)
1734 @safe unittest
1736 enum Z = 4843;
1737 BigInt m = (BigInt(1) << (Z*8) ) - 1;
1738 m -= (BigInt(1) << (Z*6)) - 1;
1739 BigInt oldm = m;
1741 BigInt a = (BigInt(1) << (Z*4) )-1;
1742 BigInt b = m % a;
1743 m /= a;
1744 m *= a;
1745 assert( m + b == oldm);
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);
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;
1780 @safe unittest
1782 import std.array;
1783 import std.format.write : formattedWrite;
1785 immutable string[][] table = [
1786 /* fmt, +10 -10 */
1787 ["%d", "10", "-10"],
1788 ["%+d", "+10", "-10"],
1789 ["%-d", "10", "-10"],
1790 ["%+-d", "+10", "-10"],
1792 ["%4d", " 10", " -10"],
1793 ["%+4d", " +10", " -10"],
1794 ["%-4d", "10 ", "-10 "],
1795 ["%+-4d", "+10 ", "-10 "],
1797 ["%04d", "0010", "-010"],
1798 ["%+04d", "+010", "-010"],
1799 ["%-04d", "10 ", "-10 "],
1800 ["%+-04d", "+10 ", "-10 "],
1802 ["% 04d", " 010", "-010"],
1803 ["%+ 04d", "+010", "-010"],
1804 ["%- 04d", " 10 ", "-10 "],
1805 ["%+- 04d", "+10 ", "-10 "],
1808 auto w1 = appender!(char[])();
1809 auto w2 = appender!(char[])();
1811 foreach (entry; table)
1813 immutable fmt = entry[0];
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();
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();
1831 @safe unittest
1833 import std.array;
1834 import std.format.write : formattedWrite;
1836 immutable string[][] table = [
1837 /* fmt, +10 -10 */
1838 ["%x", "a", "-a"],
1839 ["%+x", "a", "-a"],
1840 ["%-x", "a", "-a"],
1841 ["%+-x", "a", "-a"],
1843 ["%4x", " a", " -a"],
1844 ["%+4x", " a", " -a"],
1845 ["%-4x", "a ", "-a "],
1846 ["%+-4x", "a ", "-a "],
1848 ["%04x", "000a", "-00a"],
1849 ["%+04x", "000a", "-00a"],
1850 ["%-04x", "a ", "-a "],
1851 ["%+-04x", "a ", "-a "],
1853 ["% 04x", "000a", "-00a"],
1854 ["%+ 04x", "000a", "-00a"],
1855 ["%- 04x", "a ", "-a "],
1856 ["%+- 04x", "a ", "-a "],
1859 auto w1 = appender!(char[])();
1860 auto w2 = appender!(char[])();
1862 foreach (entry; table)
1864 immutable fmt = entry[0];
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();
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();
1882 @safe unittest
1884 import std.array;
1885 import std.format.write : formattedWrite;
1887 immutable string[][] table = [
1888 /* fmt, +10 -10 */
1889 ["%X", "A", "-A"],
1890 ["%+X", "A", "-A"],
1891 ["%-X", "A", "-A"],
1892 ["%+-X", "A", "-A"],
1894 ["%4X", " A", " -A"],
1895 ["%+4X", " A", " -A"],
1896 ["%-4X", "A ", "-A "],
1897 ["%+-4X", "A ", "-A "],
1899 ["%04X", "000A", "-00A"],
1900 ["%+04X", "000A", "-00A"],
1901 ["%-04X", "A ", "-A "],
1902 ["%+-04X", "A ", "-A "],
1904 ["% 04X", "000A", "-00A"],
1905 ["%+ 04X", "000A", "-00A"],
1906 ["%- 04X", "A ", "-A "],
1907 ["%+- 04X", "A ", "-A "],
1910 auto w1 = appender!(char[])();
1911 auto w2 = appender!(char[])();
1913 foreach (entry; table)
1915 immutable fmt = entry[0];
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();
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();
1933 // https://issues.dlang.org/show_bug.cgi?id=6448
1934 @safe unittest
1936 import std.array;
1937 import std.format.write : formattedWrite;
1939 auto w1 = appender!string();
1940 auto w2 = appender!string();
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);
1960 @safe unittest
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);
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);
1971 // opCast!bool
1972 BigInt one = 1, zero;
1973 assert(one && !zero);
1976 // https://issues.dlang.org/show_bug.cgi?id=6850
1977 @safe unittest
1979 pure long pureTest() {
1980 BigInt a = 1;
1981 BigInt b = 1336;
1982 a += b;
1983 return a.toLong();
1986 assert(pureTest() == 1337);
1989 // https://issues.dlang.org/show_bug.cgi?id=8435
1990 // https://issues.dlang.org/show_bug.cgi?id=10118
1991 @safe unittest
1993 auto i = BigInt(100);
1994 auto j = BigInt(100);
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);
2001 // BigInt AA keys should behave consistently.
2002 int[BigInt] aa;
2003 aa[BigInt(123)] = 123;
2004 assert(BigInt(123) in aa);
2006 aa[BigInt(123)] = 321;
2007 assert(aa[BigInt(123)] == 321);
2009 auto keys = aa.byKey;
2010 assert(keys.front == BigInt(123));
2011 keys.popFront();
2012 assert(keys.empty);
2015 // https://issues.dlang.org/show_bug.cgi?id=11148
2016 @safe unittest
2018 void foo(BigInt) {}
2019 const BigInt cbi = 3;
2020 immutable BigInt ibi = 3;
2022 foo(cbi);
2023 foo(ibi);
2025 import std.conv : to;
2026 import std.meta : AliasSeq;
2028 static foreach (T1; AliasSeq!(BigInt, const(BigInt), immutable(BigInt)))
2030 static foreach (T2; AliasSeq!(BigInt, const(BigInt), immutable(BigInt)))
2032 T1 t1 = 2;
2033 T2 t2 = t1;
2035 T2 t2_1 = to!T2(t1);
2036 T2 t2_2 = cast(T2) t1;
2038 assert(t2 == t1);
2039 assert(t2 == 2);
2041 assert(t2_1 == t1);
2042 assert(t2_1 == 2);
2044 assert(t2_2 == t1);
2045 assert(t2_2 == 2);
2049 BigInt n = 2;
2050 n *= 2;
2051 assert(n == 4);
2054 // https://issues.dlang.org/show_bug.cgi?id=8167
2055 @safe unittest
2057 BigInt a = BigInt(3);
2058 BigInt b = BigInt(a);
2059 assert(b == 3);
2062 // https://issues.dlang.org/show_bug.cgi?id=9061
2063 @safe unittest
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;
2071 BigInt b1 = l1;
2072 BigInt b2 = l2;
2073 BigInt b3 = b1 | b2;
2074 BigInt b4 = b1 & b2;
2075 BigInt b5 = b1 ^ b2;
2077 assert(l3 == b3);
2078 assert(l4 == b4);
2079 assert(l5 == b5);
2082 // https://issues.dlang.org/show_bug.cgi?id=11600
2083 @safe unittest
2085 import std.conv;
2086 import std.exception : assertThrown;
2088 // Original bug report
2089 assertThrown!ConvException(to!BigInt("avadakedavra"));
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"));
2098 // https://issues.dlang.org/show_bug.cgi?id=11583
2099 @safe unittest
2101 BigInt x = 0;
2102 assert((x > 0) == false);
2105 // https://issues.dlang.org/show_bug.cgi?id=13391
2106 @safe unittest
2108 BigInt x1 = "123456789";
2109 BigInt x2 = "123456789123456789";
2110 BigInt x3 = "123456789123456789123456789";
2112 import std.meta : AliasSeq;
2113 static foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
2115 assert((x1 * T.max) / T.max == x1);
2116 assert((x2 * T.max) / T.max == x2);
2117 assert((x3 * T.max) / T.max == x3);
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);
2127 assert(x1 / uint.max == 0);
2128 assert(x1 / ulong.max == 0);
2129 assert(x2 / ulong.max == 0);
2131 x1 /= 123456789UL;
2132 assert(x1 == 1);
2133 x2 /= 123456789123456789UL;
2134 assert(x2 == 1);
2137 // https://issues.dlang.org/show_bug.cgi?id=13963
2138 @safe unittest
2140 BigInt x = 1;
2141 import std.meta : AliasSeq;
2142 static foreach (Int; AliasSeq!(byte, ubyte, short, ushort, int))
2144 assert(is(typeof(x % Int(1)) == int));
2146 assert(is(typeof(x % 1U) == long));
2147 assert(is(typeof(x % 1L) == long));
2148 assert(is(typeof(x % 1UL) == BigInt));
2150 auto x0 = BigInt(uint.max - 1);
2151 auto x1 = BigInt(8);
2152 assert(x1 / x == x1);
2153 auto x2 = -BigInt(long.min) + 1;
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));
2161 // long
2162 assert(x1 % 2L == 0L);
2163 assert(-x1 % 2L == 0L);
2165 assert(x1 % 3L == 2L);
2166 assert(x1 % -3L == 2L);
2167 assert(-x1 % 3L == -2L);
2168 assert(-x1 % -3L == -2L);
2170 assert(x1 % 11L == 8L);
2171 assert(x1 % -11L == 8L);
2172 assert(-x1 % 11L == -8L);
2173 assert(-x1 % -11L == -8L);
2175 // ulong
2176 assert(x1 % 2UL == BigInt(0));
2177 assert(-x1 % 2UL == BigInt(0));
2179 assert(x1 % 3UL == BigInt(2));
2180 assert(-x1 % 3UL == -BigInt(2));
2182 assert(x1 % 11UL == BigInt(8));
2183 assert(-x1 % 11UL == -BigInt(8));
2185 assert(x2 % ulong.max == x2);
2186 assert(-x2 % ulong.max == -x2);
2189 // https://issues.dlang.org/show_bug.cgi?id=14124
2190 @safe unittest
2192 auto x = BigInt(-3);
2193 x %= 3;
2194 assert(!x.isNegative);
2195 assert(x.isZero);
2197 x = BigInt(-3);
2198 x %= cast(ushort) 3;
2199 assert(!x.isNegative);
2200 assert(x.isZero);
2202 x = BigInt(-3);
2203 x %= 3L;
2204 assert(!x.isNegative);
2205 assert(x.isZero);
2207 x = BigInt(3);
2208 x %= -3;
2209 assert(!x.isNegative);
2210 assert(x.isZero);
2213 // https://issues.dlang.org/show_bug.cgi?id=15678
2214 @safe unittest
2216 import std.exception : assertThrown;
2217 assertThrown!ConvException(BigInt(""));
2218 assertThrown!ConvException(BigInt("0x1234BARF"));
2219 assertThrown!ConvException(BigInt("1234PUKE"));
2222 // https://issues.dlang.org/show_bug.cgi?id=6447
2223 @safe unittest
2225 import std.algorithm.comparison : equal;
2226 import std.range : iota;
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 ]));
2238 // https://issues.dlang.org/show_bug.cgi?id=17330
2239 @safe unittest
2241 auto b = immutable BigInt("123");
2242 assert(b == 123);
2245 // https://issues.dlang.org/show_bug.cgi?id=14767
2246 @safe pure unittest
2248 static immutable a = BigInt("340282366920938463463374607431768211455");
2249 assert(a == BigInt("340282366920938463463374607431768211455"));
2251 BigInt plusTwo(in BigInt n)
2253 return n + 2;
2256 enum BigInt test1 = BigInt(123);
2257 enum BigInt test2 = plusTwo(test1);
2258 assert(test2 == 125);
2262 * Finds the quotient and remainder for the given dividend and divisor in one operation.
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
2270 void divMod(const BigInt dividend, const BigInt divisor, out BigInt quotient, out BigInt remainder) pure nothrow @safe
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;
2281 @safe pure nothrow unittest
2283 auto a = BigInt(123);
2284 auto b = BigInt(25);
2285 BigInt q, r;
2287 divMod(a, b, q, r);
2289 assert(q == 4);
2290 assert(r == 23);
2291 assert(q * b + r == a);
2294 // https://issues.dlang.org/show_bug.cgi?id=18086
2295 @safe pure nothrow unittest
2297 BigInt q = 1;
2298 BigInt r = 1;
2299 BigInt c = 1024;
2300 BigInt d = 100;
2302 divMod(c, d, q, r);
2303 assert(q == 10);
2304 assert(r == 24);
2305 assert((q * d + r) == c);
2307 divMod(c, -d, q, r);
2308 assert(q == -10);
2309 assert(r == 24);
2310 assert(q * -d + r == c);
2312 divMod(-c, -d, q, r);
2313 assert(q == 10);
2314 assert(r == -24);
2315 assert(q * -d + r == -c);
2317 divMod(-c, d, q, r);
2318 assert(q == -10);
2319 assert(r == -24);
2320 assert(q * d + r == -c);
2323 // https://issues.dlang.org/show_bug.cgi?id=22771
2324 @safe pure nothrow unittest
2326 BigInt quotient, remainder;
2327 divMod(BigInt(-50), BigInt(1), quotient, remainder);
2328 assert(remainder == 0);
2331 // https://issues.dlang.org/show_bug.cgi?id=19740
2332 @safe unittest
2334 BigInt a = BigInt(
2335 "241127122100380210001001124020210001001100000200003101000062221012075223052000021042250111300200000000000" ~
2336 "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
2337 BigInt b = BigInt(
2338 "700200000000500418321000401140010110000022007221432000000141020011323301104104060202100200457210001600142" ~
2339 "000001012245300100001110215200000000120000000000000000000000000000000000000000000000000000000000000000000" ~
2340 "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
2342 BigInt c = a * b;
2343 assert(c == BigInt(
2344 "1688372108948068874722901180228375682334987075822938736581472847151834613694489486296103575639363261807341" ~
2345 "3910091006778604956808730652275328822700182498926542563654351871390166691461743896850906716336187966456064" ~
2346 "2702007176328110013356024000000000000000000000000000000000000000000000000000000000000000000000000000000000" ~
2347 "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ~
2348 "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000"));
2351 @safe unittest
2353 auto n = BigInt("1234"d);
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.
2365 BigInt powmod(BigInt base, BigInt exponent, BigInt modulus) pure nothrow @safe
2367 BigInt result = 1;
2369 while (exponent)
2371 if (exponent.data.peekUint(0) & 1)
2373 result = (result * base) % modulus;
2376 auto tmp = base % modulus;
2377 base = (tmp * tmp) % modulus;
2378 exponent >>= 1;
2381 return result;
2384 /// for powmod
2385 @safe unittest
2387 BigInt base = BigInt("123456789012345678901234567890");
2388 BigInt exponent = BigInt("1234567890123456789012345678901234567");
2389 BigInt modulus = BigInt("1234567");
2391 BigInt result = powmod(base, exponent, modulus);
2392 assert(result == 359079);