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:
8 * $(LI Karatsuba multiplication)
9 * $(LI Squaring is optimized independently of multiplication)
10 * $(LI Divide-and-conquer division)
11 * $(LI Binary exponentiation)
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)
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
;
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
51 BigUint data
; // BigInt adds signed arithmetic to BigUint.
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.
61 * s = a finite bidirectional range of any character type
64 * $(REF ConvException, std,conv) if the string doesn't represent a valid number
67 if (isBidirectionalRange
!Range
&&
68 isSomeChar
!(ElementType
!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");
85 // check for signs and if the string is a hex value
88 s
.popFront(); // skip '+'
90 else if (s
.front
== '-')
96 if (s
.save
.startsWith("0x".byChar
) ||
97 s
.save
.startsWith("0X".byChar
))
103 ok
= data
.fromHexString(s
.filterBidirectional
!(a
=> a
!= '_'));
109 ok
= data
.fromDecimalString(s
.filterBidirectional
!(a
=> a
!= '_'));
112 enforce
!ConvException(ok
, "Not a valid numerical string");
121 this(Range
)(Range s
) pure
122 if (isNarrowString
!Range
)
124 import std
.utf
: byCodeUnit
;
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.
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
) &&
169 data
.fromMagnitude(magnitude
);
170 sign
= isNegative
&& !data
.isZero
;
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
187 data
= data
.init
; // @@@: Workaround for compiler bug
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
))
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
218 data
= cast(ulong) absUnsign(x
);
226 auto b
= BigInt("123");
228 assert(b
== BigInt("456"));
231 /// Assignment from another BigInt.
232 BigInt
opAssign(T
:BigInt
)(T x
) pure @nogc @safe
242 auto b1
= BigInt("123");
243 auto b2
= BigInt("456");
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
);
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
=="*")
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
);
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) ))
301 data
= cast(ulong) BigUint
.modInt(data
, cast(uint) u
);
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.
314 else if ((y
> 0) == (op
=="<<"))
316 // Sign never changes during left shift
317 data
= data
.opBinary
!(op
)(u
);
321 data
= data
.opBinary
!(op
)(u
);
326 else static if (op
=="^^")
328 sign
= (y
& 1) ? sign
: false;
332 data
= cast(ulong) (data
== 1);
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
;
346 data
= data
.peekUlong(0) & y
;
355 else static if (op
=="|" || op
=="^")
360 else static assert(0, "BigInt " ~ op
[0..$-1] ~ "= " ~ T
.stringof
~ " is not supported");
367 auto b
= BigInt("1_000_000_000");
370 assert(b
== BigInt("1_000_012_345"));
373 assert(b
== BigInt("200_002_469"));
376 // https://issues.dlang.org/show_bug.cgi?id=16264
380 `335690982744637013564796917901053301979460129353374296317539383938630086938` ~
381 `465898213033510992292836631752875403891802201862860531801760096359705447768` ~
382 `957432600293361240407059207520920532482429912948952142341440301429494694368` ~
383 `264560802292927144211230021750155988283029753927847924288850436812178022006` ~
384 `408597793414273953252832688620479083497367463977081627995406363446761896298` ~
385 `967177607401918269561385622811274398143647535024987050366350585544531063531` ~
386 `7118554808325723941557169427279911052268935775`);
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
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` ~
425 // https://issues.dlang.org/show_bug.cgi?id=24028
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
== "/")
462 data
= BigUint
.div(data
, y
.data
);
463 sign
= isZero() ?
false : sign ^ y
.sign
;
466 else static if (op
== "%")
471 data
= BigUint
.mod(data
, y
.data
);
472 // x%y always has the same sign as x.
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");
489 auto x
= BigInt("123");
490 auto y
= BigInt("321");
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
))
503 return r
.opOpAssign
!(op
)(y
);
509 auto x
= BigInt("123");
510 auto y
= BigInt("456");
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
=="^^")
524 r
.opOpAssign
!(op
)(y
);
531 auto x
= BigInt("123");
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.
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))
568 // return as-is to avoid overflow
574 immutable uint u
= absUnsign(y
);
575 static if (is(immutable T
== immutable uint))
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
;
589 auto x
= BigInt("1_000_000_500");
591 ulong ul
= 2_000_000UL;
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
);
614 auto x
= BigInt("100");
616 assert(y
== BigInt("223"));
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
630 BigInt
opBinaryRight(string op
, T
)(T y
) pure nothrow @safe const
631 if (op
== "-" && isIntegral
!T
)
633 ulong u
= absUnsign(y
);
635 static if (op
== "-")
638 r
.data
= BigUint
.addOrSubInt
!ulong(data
, u
, wantSub
: sign
== (y
<0), r
.sign
);
644 // integer = integer op BigInt
646 T
opBinaryRight(string op
, T
)(T x
) pure nothrow @safe const
647 if ((op
=="%" || op
=="/") && isIntegral
!T
)
651 static if (op
== "%")
653 // x%y always has the same sign as x.
654 if (data
.ulongLength
> 1)
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)
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
=="~")
682 else static if (op
=="~")
686 else static if (op
=="+")
690 // non-const unary operations
692 BigInt
opUnary(string op
)() pure nothrow @safe
693 if (op
=="++" || op
=="--")
697 data
= BigUint
.addOrSubInt
!ulong(data
, 1UL, wantSub
: sign
, sign
);
700 else static if (op
=="--")
702 data
= BigUint
.addOrSubInt
!ulong(data
, 1UL, wantSub
: !sign
, sign
);
710 auto x
= BigInt("1234");
711 assert(-x
== BigInt("-1234"));
714 assert(x
== BigInt("1235"));
718 Implements `BigInt` equality test with other `BigInt`'s and built-in
721 bool opEquals()(auto ref const BigInt y
) const pure @nogc @safe
723 return sign
== y
.sign
&& y
.data
== data
;
727 bool opEquals(T
)(const T y
) const pure nothrow @nogc @safe
732 return data
.opEquals(cast(ulong) absUnsign(y
));
736 bool opEquals(T
)(const T y
) const pure nothrow @nogc
737 if (isFloatingPoint
!T
)
739 return 0 == opCmp(y
);
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);
753 auto x
= BigInt("12345");
754 auto y
= BigInt("12340");
767 import std
.math
.operations
: nextDown
, nextUp
;
769 const x
= BigInt("0x1abc_de80_0000_0000_0000_0000_0000_0000");
773 const d
= 0x1.abcde8p124
;
777 assert(x
!= nextUp(d
));
778 assert(x
!= nextDown(d
));
779 assert(x
!= double.nan
);
781 const dL
= 0x1.abcde8p124L
;
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
809 // Non-zero values are regarded as true
810 auto x
= BigInt("1");
811 auto y
= BigInt("10");
815 // Zero value is regarded as false
816 auto z
= BigInt("0");
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
)
831 if (data
.ulongLength
== 1)
833 ulong l
= data
.peekUlong(0);
834 if (isUnsigned
!T ||
!sign
)
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
));
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);
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");
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
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_aae
7) == 0x1.aaa_aaep
+28f);
936 assert(cast(float) BigInt(0x1aaa_aaff
) == 0x1.aaa_ab0p
+28f);
937 assert(cast(float) BigInt(-0x1aaa_aae
7) == -0x1.aaaaaep
+28f);
938 assert(cast(float) BigInt(-0x1aaa_aaff
) == -0x1.aaaab0p
+28f);
940 assert(cast(double) BigInt(0x1aaa_aaaa_aaaa_aa
77) == 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_aa
77) == -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_aaf
0) == 0x1.aaa_ab0p
+28f);
950 assert(cast(float) BigInt(-0x1aaa_aaf
0) == -0x1.aaaab0p
+28f);
952 assert(cast(double) BigInt(0x1aaa_aaaa_aaaa_aa
80) == 0x1.aaa_aaaa_aaaa_ab00p
+60);
953 assert(cast(double) BigInt(-0x1aaa_aaaa_aaaa_aa
80) == -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
);
968 // Test exponent overflow is correct.
969 assert(cast(float) BigInt(0x1fffffff) == 0x1.000000p
+29f);
970 assert(cast(double) BigInt(0x1fff_ffff_ffff_fff
0) == 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);
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.
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
)();
1026 import core
.math
: ldexp
;
1027 return ldexp(isNegative ?
-cast(real) sansExponent
: cast(real) sansExponent
,
1028 cast(int) exponent
- 65);
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);
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;
1054 w
= (w
>>> (64 - bitsStillNeeded
)) << (64 - bitsStillNeeded
);
1055 acc
+= ldexp(cast(T
) w
, scale
-= 64);
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
))
1080 const(BigInt
) x
= BigInt("123");
1081 BigInt y
= cast() x
; // cast away const
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
);
1099 int opCmp(T
)(const T y
) pure nothrow @nogc @safe const
1103 return sign ?
-1 : 1;
1104 int cmp = data
.opCmp(cast(ulong) absUnsign(y
));
1105 return sign?
-cmp: cmp;
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");
1117 return cmp(asFloat
, y
); // handles +/- NaN.
1119 return isNegative ?
1 : -1;
1120 const ulongLength
= data
.ulongLength
;
1121 const w1
= data
.peekUlong(ulongLength
- 1);
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
);
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;
1140 int opCmp(T
:BigInt
)(const T y
) pure nothrow @nogc @safe const
1143 return sign ?
-1 : 1;
1144 immutable cmp = data
.opCmp(y
.data
);
1145 return sign?
-cmp: cmp;
1151 auto x
= BigInt("100");
1152 auto y
= BigInt("10");
1165 auto x
= BigInt("0x1abc_de80_0000_0000_0000_0000_0000_0000");
1169 double d
= 0x1.abcde8p124
;
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);
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");
1189 real d
= 0x1.abcde8p124
;
1192 assert(x
>= d
&& x
<= d
);
1194 // Test comparison for numbers of 64 bits or fewer.
1195 auto w1
= BigInt(0x1abc_de
80_0000_0000);
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
);
1207 real eL
= 0x1.abcde8p
+60;
1208 assert(w1
>= eL
&& w1
<= 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))
1228 auto b
= BigInt("12345");
1229 long l
= b
.toLong();
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))
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");
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 < 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 < 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.
1275 * sink = An OutputRange for accepting possibly piecewise segments of the
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
);
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
);
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();
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
))
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
)
1349 scope char[1] buf
= signChar
;
1353 if (!f
.flDash
&& f
.flZero
)
1354 foreach (i
; 0 .. difw
)
1360 foreach (i
; 0 .. difw
)
1365 `toString` is rarely directly invoked; the usual way of using it is via
1366 $(REF format, std, format):
1370 import std
.format
: format
;
1372 auto x
= BigInt("1_000_000");
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
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
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.
1403 import std
.format
.spec
: FormatSpec
;
1404 import std
.array
: appender
;
1406 auto dst
= appender
!string();
1407 num
.toString(str => dst
.put(str), null);
1408 assert(dst
[] == "503");
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
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.
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
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`.
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
);
1460 assert(n
< uintLength(), "getDigit index out of bounds");
1461 return data
.peekUint(n
);
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);
1487 void negate() @safe pure nothrow @nogc scope
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");
1508 BigInt a
= "9588669891916142";
1509 BigInt b
= "7452469135154800";
1511 assert(c
== BigInt("71459266416693160362545788781600"));
1513 assert(d
== BigInt("71459266416693160362545788781600"));
1515 d
= c
* BigInt("794628672112");
1516 assert(d
== BigInt("56783581982794522489042432639320434378739200"));
1518 assert(e
== BigInt("56783581982865981755459125799682980167520800"));
1531 BigInt j
= "-0x9A56_57f4_7B83_AB78";
1534 assert(k ^^
11 == j
);
1539 x = The `BigInt` to convert to a decimal `string`.
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);
1556 auto x
= BigInt("123");
1560 auto xstr
= x
.toDecimalString();
1561 assert(xstr
== "123456");
1566 x = The `BigInt` to convert to a hexadecimal `string`.
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");
1584 auto x
= BigInt("123");
1588 auto xstr
= x
.toHex();
1589 assert(xstr
== "1E240");
1592 /** Returns the absolute value of x converted to the corresponding unsigned
1596 x = The integral value to return the absolute value of.
1599 The absolute value of x.
1602 Unsigned
!T
absUnsign(T
)(T x
)
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
);
1624 assert((-1).absUnsign
== 1);
1625 assert(1.absUnsign
== 1);
1652 BigInt x
= 1, y
= 2;
1668 BigInt
[] arr
= [BigInt(1)];
1669 auto incr
= arr
[0]++;
1670 assert(arr
== [BigInt(2)]);
1671 assert(incr
== BigInt(1));
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
_5A
5AL
).ulongLength
== 1);
1687 assert(BigInt(0x1234_5678_9ABC
_5A
5AL
).toLong() == 0x1234_5678_9ABC
_5A
5AL
);
1688 assert(BigInt(-0x1234_5678_9ABC
_5A
5AL
).toLong() == -0x1234_5678_9ABC
_5A
5AL
);
1689 assert(BigInt(0xF234_5678_9ABC
_5A
5AL
).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));
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"))
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
1724 assert(a
== BigInt(int.min
));
1725 a
= int.min
- BigInt(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)
1737 BigInt m
= (BigInt(1) << (Z
*8) ) - 1;
1738 m
-= (BigInt(1) << (Z
*6)) - 1;
1741 BigInt a
= (BigInt(1) << (Z
*4) )-1;
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
;
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
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;
1770 assert(v7973
== 2551700137);
1772 assert(v7973
== 2551700137);
1774 assert(v7973
== 2551700137);
1775 // https://issues.dlang.org/show_bug.cgi?id=8165
1777 a8165
[0] = a8165
[1] = 1;
1783 import std
.format
.write
: formattedWrite
;
1785 immutable string
[][] table
= [
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]);
1822 formattedWrite(w1
, fmt
, BigInt(-10));
1823 formattedWrite(w2
, fmt
, -10);
1824 assert(w1
.data
== w2
.data
);
1825 assert(w1
.data
== entry
[2]);
1834 import std
.format
.write
: formattedWrite
;
1836 immutable string
[][] table
= [
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]);
1873 formattedWrite(w1
, fmt
, BigInt(-10));
1874 //formattedWrite(w2, fmt, -10);
1875 //assert(w1.data == w2.data);
1876 assert(w1
.data
== entry
[2]);
1885 import std
.format
.write
: formattedWrite
;
1887 immutable string
[][] table
= [
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]);
1924 formattedWrite(w1
, fmt
, BigInt(-10));
1925 //formattedWrite(w2, fmt, -10);
1926 //assert(w1.data == w2.data);
1927 assert(w1
.data
== entry
[2]);
1933 // https://issues.dlang.org/show_bug.cgi?id=6448
1937 import std
.format
.write
: formattedWrite
;
1939 auto w1
= appender
!string();
1940 auto w2
= appender
!string();
1943 formattedWrite(w1
, "%010d", x
);
1945 formattedWrite(w2
, "%010d", bx
);
1946 assert(w1
.data
== w2
.data
);
1947 // https://issues.dlang.org/show_bug.cgi?id=8011
1950 assert(y
.toLong() == -2);
1953 assert(y
.toLong() == 0);
1955 assert(y
.toLong() == -1);
1957 assert(y
.toLong() == -2);
1962 import std
.math
.algebraic
: abs
;
1963 auto r
= abs(BigInt(-1000)); // https://issues.dlang.org/show_bug.cgi?id=6486
1966 auto r2
= abs(const(BigInt
)(-500)); // https://issues.dlang.org/show_bug.cgi?id=11188
1968 auto r3
= abs(immutable(BigInt
)(-733)); // https://issues.dlang.org/show_bug.cgi?id=11188
1972 BigInt one
= 1, zero
;
1973 assert(one
&& !zero
);
1976 // https://issues.dlang.org/show_bug.cgi?id=6850
1979 pure long pureTest() {
1986 assert(pureTest() == 1337);
1989 // https://issues.dlang.org/show_bug.cgi?id=8435
1990 // https://issues.dlang.org/show_bug.cgi?id=10118
1993 auto i
= BigInt(100);
1994 auto j
= BigInt(100);
1996 // Two separate BigInt instances representing same value should have same
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.
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));
2015 // https://issues.dlang.org/show_bug.cgi?id=11148
2019 const BigInt cbi
= 3;
2020 immutable BigInt ibi
= 3;
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
)))
2035 T2 t2_1
= to
!T2(t1
);
2036 T2 t2_2
= cast(T2
) t1
;
2054 // https://issues.dlang.org/show_bug.cgi?id=8167
2057 BigInt a
= BigInt(3);
2058 BigInt b
= BigInt(a
);
2062 // https://issues.dlang.org/show_bug.cgi?id=9061
2065 long l1
= 0x12345678_90ABCDEF
;
2066 long l2
= 0xFEDCBA09_87654321;
2073 BigInt b3
= b1 | b2
;
2074 BigInt b4
= b1
& b2
;
2075 BigInt b5
= b1 ^ b2
;
2082 // https://issues.dlang.org/show_bug.cgi?id=11600
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
2102 assert((x
> 0) == false);
2105 // https://issues.dlang.org/show_bug.cgi?id=13391
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);
2133 x2
/= 123456789123456789UL;
2137 // https://issues.dlang.org/show_bug.cgi?id=13963
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;
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));
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);
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
2192 auto x
= BigInt(-3);
2194 assert(!x
.isNegative
);
2198 x
%= cast(ushort) 3;
2199 assert(!x
.isNegative
);
2204 assert(!x
.isNegative
);
2209 assert(!x
.isNegative
);
2213 // https://issues.dlang.org/show_bug.cgi?id=15678
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
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
);
2232 BigInt(1_000_000_000_000),
2233 BigInt(1_000_000_000_001),
2234 BigInt(1_000_000_000_002)
2238 // https://issues.dlang.org/show_bug.cgi?id=17330
2241 auto b
= immutable BigInt("123");
2245 // https://issues.dlang.org/show_bug.cgi?id=14767
2248 static immutable a
= BigInt("340282366920938463463374607431768211455");
2249 assert(a
== BigInt("340282366920938463463374607431768211455"));
2251 BigInt
plusTwo(in BigInt n
)
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.
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
2273 BigUint
.divMod(dividend
.data
, divisor
.data
, q
, r
);
2274 quotient
.sign
= dividend
.sign
!= divisor
.sign
;
2276 remainder
.sign
= r
.isZero() ?
false : dividend
.sign
;
2281 @safe pure nothrow unittest
2283 auto a
= BigInt(123);
2284 auto b
= BigInt(25);
2291 assert(q
* b
+ r
== a
);
2294 // https://issues.dlang.org/show_bug.cgi?id=18086
2295 @safe pure nothrow unittest
2305 assert((q
* d
+ r
) == c
);
2307 divMod(c
, -d
, q
, r
);
2310 assert(q
* -d
+ r
== c
);
2312 divMod(-c
, -d
, q
, r
);
2315 assert(q
* -d
+ r
== -c
);
2317 divMod(-c
, d
, q
, r
);
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
2335 "241127122100380210001001124020210001001100000200003101000062221012075223052000021042250111300200000000000" ~
2336 "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
2338 "700200000000500418321000401140010110000022007221432000000141020011323301104104060202100200457210001600142" ~
2339 "000001012245300100001110215200000000120000000000000000000000000000000000000000000000000000000000000000000" ~
2340 "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
2344 "1688372108948068874722901180228375682334987075822938736581472847151834613694489486296103575639363261807341" ~
2345 "3910091006778604956808730652275328822700182498926542563654351871390166691461743896850906716336187966456064" ~
2346 "2702007176328110013356024000000000000000000000000000000000000000000000000000000000000000000000000000000000" ~
2347 "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ~
2348 "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000"));
2353 auto n
= BigInt("1234"d
);
2357 Fast power modulus calculation for $(LREF BigInt) operands.
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.
2363 The power modulus value of (base ^ exponent) % modulus.
2365 BigInt
powmod(BigInt base
, BigInt exponent
, BigInt modulus
) pure nothrow @safe
2371 if (exponent
.data
.peekUint(0) & 1)
2373 result
= (result
* base
) % modulus
;
2376 auto tmp
= base
% modulus
;
2377 base
= (tmp
* tmp
) % modulus
;
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);