The OpenD Programming Language

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