1*627f7eb2Smrg /** Arbitrary-precision ('bignum') arithmetic.
2*627f7eb2Smrg *
3*627f7eb2Smrg * Performance is optimized for numbers below ~1000 decimal digits.
4*627f7eb2Smrg * For X86 machines, highly optimised assembly routines are used.
5*627f7eb2Smrg *
6*627f7eb2Smrg * The following algorithms are currently implemented:
7*627f7eb2Smrg * $(UL
8*627f7eb2Smrg * $(LI Karatsuba multiplication)
9*627f7eb2Smrg * $(LI Squaring is optimized independently of multiplication)
10*627f7eb2Smrg * $(LI Divide-and-conquer division)
11*627f7eb2Smrg * $(LI Binary exponentiation)
12*627f7eb2Smrg * )
13*627f7eb2Smrg *
14*627f7eb2Smrg * For very large numbers, consider using the $(HTTP gmplib.org, GMP library) instead.
15*627f7eb2Smrg *
16*627f7eb2Smrg * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
17*627f7eb2Smrg * Authors: Don Clugston
18*627f7eb2Smrg * Source: $(PHOBOSSRC std/_bigint.d)
19*627f7eb2Smrg */
20*627f7eb2Smrg /* Copyright Don Clugston 2008 - 2010.
21*627f7eb2Smrg * Distributed under the Boost Software License, Version 1.0.
22*627f7eb2Smrg * (See accompanying file LICENSE_1_0.txt or copy at
23*627f7eb2Smrg * http://www.boost.org/LICENSE_1_0.txt)
24*627f7eb2Smrg */
25*627f7eb2Smrg
26*627f7eb2Smrg module std.bigint;
27*627f7eb2Smrg
28*627f7eb2Smrg import std.conv : ConvException;
29*627f7eb2Smrg
30*627f7eb2Smrg import std.format : FormatSpec, FormatException;
31*627f7eb2Smrg import std.internal.math.biguintcore;
32*627f7eb2Smrg import std.range.primitives;
33*627f7eb2Smrg import std.traits;
34*627f7eb2Smrg
35*627f7eb2Smrg /** A struct representing an arbitrary precision integer.
36*627f7eb2Smrg *
37*627f7eb2Smrg * All arithmetic operations are supported, except unsigned shift right (>>>).
38*627f7eb2Smrg * Bitwise operations (|, &, ^, ~) are supported, and behave as if BigInt was
39*627f7eb2Smrg * an infinite length 2's complement number.
40*627f7eb2Smrg *
41*627f7eb2Smrg * BigInt implements value semantics using copy-on-write. This means that
42*627f7eb2Smrg * assignment is cheap, but operations such as x++ will cause heap
43*627f7eb2Smrg * allocation. (But note that for most bigint operations, heap allocation is
44*627f7eb2Smrg * inevitable anyway.)
45*627f7eb2Smrg */
46*627f7eb2Smrg struct BigInt
47*627f7eb2Smrg {
48*627f7eb2Smrg private:
49*627f7eb2Smrg BigUint data; // BigInt adds signed arithmetic to BigUint.
50*627f7eb2Smrg bool sign = false;
51*627f7eb2Smrg public:
52*627f7eb2Smrg /**
53*627f7eb2Smrg * Construct a BigInt from a decimal or hexadecimal string. The number must
54*627f7eb2Smrg * be in the form of a decimal or hex literal. It may have a leading `+`
55*627f7eb2Smrg * or `-` sign, followed by `0x` or `0X` if hexadecimal. Underscores are
56*627f7eb2Smrg * permitted in any location after the `0x` and/or the sign of the number.
57*627f7eb2Smrg *
58*627f7eb2Smrg * Params:
59*627f7eb2Smrg * s = a finite bidirectional range of any character type
60*627f7eb2Smrg *
61*627f7eb2Smrg * Throws:
62*627f7eb2Smrg * $(REF ConvException, std,conv) if the string doesn't represent a valid number
63*627f7eb2Smrg */
64*627f7eb2Smrg this(Range)(Range s) if (
65*627f7eb2Smrg isBidirectionalRange!Range &&
66*627f7eb2Smrg isSomeChar!(ElementType!Range) &&
67*627f7eb2Smrg !isInfinite!Range &&
68*627f7eb2Smrg !isSomeString!Range)
69*627f7eb2Smrg {
70*627f7eb2Smrg import std.algorithm.iteration : filterBidirectional;
71*627f7eb2Smrg import std.algorithm.searching : startsWith;
72*627f7eb2Smrg import std.conv : ConvException;
73*627f7eb2Smrg import std.exception : enforce;
74*627f7eb2Smrg import std.utf : byChar;
75*627f7eb2Smrg
76*627f7eb2Smrg enforce!ConvException(!s.empty, "Can't initialize BigInt with an empty range");
77*627f7eb2Smrg
78*627f7eb2Smrg bool neg = false;
79*627f7eb2Smrg bool ok;
80*627f7eb2Smrg
81*627f7eb2Smrg data = 0UL;
82*627f7eb2Smrg
83*627f7eb2Smrg // check for signs and if the string is a hex value
84*627f7eb2Smrg if (s.front == '+')
85*627f7eb2Smrg {
86*627f7eb2Smrg s.popFront(); // skip '+'
87*627f7eb2Smrg }
88*627f7eb2Smrg else if (s.front == '-')
89*627f7eb2Smrg {
90*627f7eb2Smrg neg = true;
91*627f7eb2Smrg s.popFront();
92*627f7eb2Smrg }
93*627f7eb2Smrg
94*627f7eb2Smrg if (s.save.startsWith("0x".byChar) ||
95*627f7eb2Smrg s.save.startsWith("0X".byChar))
96*627f7eb2Smrg {
97*627f7eb2Smrg s.popFront;
98*627f7eb2Smrg s.popFront;
99*627f7eb2Smrg
100*627f7eb2Smrg if (!s.empty)
101*627f7eb2Smrg ok = data.fromHexString(s.filterBidirectional!(a => a != '_'));
102*627f7eb2Smrg else
103*627f7eb2Smrg ok = false;
104*627f7eb2Smrg }
105*627f7eb2Smrg else
106*627f7eb2Smrg {
107*627f7eb2Smrg ok = data.fromDecimalString(s.filterBidirectional!(a => a != '_'));
108*627f7eb2Smrg }
109*627f7eb2Smrg
110*627f7eb2Smrg enforce!ConvException(ok, "Not a valid numerical string");
111*627f7eb2Smrg
112*627f7eb2Smrg if (isZero())
113*627f7eb2Smrg neg = false;
114*627f7eb2Smrg
115*627f7eb2Smrg sign = neg;
116*627f7eb2Smrg }
117*627f7eb2Smrg
118*627f7eb2Smrg /// ditto
119*627f7eb2Smrg this(Range)(Range s) pure if (isSomeString!Range)
120*627f7eb2Smrg {
121*627f7eb2Smrg import std.utf : byCodeUnit;
122*627f7eb2Smrg this(s.byCodeUnit);
123*627f7eb2Smrg }
124*627f7eb2Smrg
125*627f7eb2Smrg @system unittest
126*627f7eb2Smrg {
127*627f7eb2Smrg // system because of the dummy ranges eventually call std.array!string
128*627f7eb2Smrg import std.exception : assertThrown;
129*627f7eb2Smrg import std.internal.test.dummyrange;
130*627f7eb2Smrg
131*627f7eb2Smrg auto r1 = new ReferenceBidirectionalRange!dchar("101");
132*627f7eb2Smrg auto big1 = BigInt(r1);
133*627f7eb2Smrg assert(big1 == BigInt(101));
134*627f7eb2Smrg
135*627f7eb2Smrg auto r2 = new ReferenceBidirectionalRange!dchar("1_000");
136*627f7eb2Smrg auto big2 = BigInt(r2);
137*627f7eb2Smrg assert(big2 == BigInt(1000));
138*627f7eb2Smrg
139*627f7eb2Smrg auto r3 = new ReferenceBidirectionalRange!dchar("0x0");
140*627f7eb2Smrg auto big3 = BigInt(r3);
141*627f7eb2Smrg assert(big3 == BigInt(0));
142*627f7eb2Smrg
143*627f7eb2Smrg auto r4 = new ReferenceBidirectionalRange!dchar("0x");
144*627f7eb2Smrg assertThrown!ConvException(BigInt(r4));
145*627f7eb2Smrg }
146*627f7eb2Smrg
147*627f7eb2Smrg /// Construct a BigInt from a built-in integral type.
148*627f7eb2Smrg this(T)(T x) pure nothrow if (isIntegral!T)
149*627f7eb2Smrg {
150*627f7eb2Smrg data = data.init; // @@@: Workaround for compiler bug
151*627f7eb2Smrg opAssign(x);
152*627f7eb2Smrg }
153*627f7eb2Smrg
154*627f7eb2Smrg ///
155*627f7eb2Smrg @system unittest
156*627f7eb2Smrg {
157*627f7eb2Smrg // @system due to failure in FreeBSD32
158*627f7eb2Smrg ulong data = 1_000_000_000_000;
159*627f7eb2Smrg auto bigData = BigInt(data);
160*627f7eb2Smrg assert(data == BigInt("1_000_000_000_000"));
161*627f7eb2Smrg }
162*627f7eb2Smrg
163*627f7eb2Smrg /// Construct a BigInt from another BigInt.
164*627f7eb2Smrg this(T)(T x) pure nothrow if (is(Unqual!T == BigInt))
165*627f7eb2Smrg {
166*627f7eb2Smrg opAssign(x);
167*627f7eb2Smrg }
168*627f7eb2Smrg
169*627f7eb2Smrg ///
170*627f7eb2Smrg @system unittest
171*627f7eb2Smrg {
172*627f7eb2Smrg const(BigInt) b1 = BigInt("1_234_567_890");
173*627f7eb2Smrg BigInt b2 = BigInt(b1);
174*627f7eb2Smrg assert(b2 == BigInt("1_234_567_890"));
175*627f7eb2Smrg }
176*627f7eb2Smrg
177*627f7eb2Smrg /// Assignment from built-in integer types.
178*627f7eb2Smrg BigInt opAssign(T)(T x) pure nothrow if (isIntegral!T)
179*627f7eb2Smrg {
180*627f7eb2Smrg data = cast(ulong) absUnsign(x);
181*627f7eb2Smrg sign = (x < 0);
182*627f7eb2Smrg return this;
183*627f7eb2Smrg }
184*627f7eb2Smrg
185*627f7eb2Smrg ///
186*627f7eb2Smrg @system unittest
187*627f7eb2Smrg {
188*627f7eb2Smrg auto b = BigInt("123");
189*627f7eb2Smrg b = 456;
190*627f7eb2Smrg assert(b == BigInt("456"));
191*627f7eb2Smrg }
192*627f7eb2Smrg
193*627f7eb2Smrg /// Assignment from another BigInt.
194*627f7eb2Smrg BigInt opAssign(T:BigInt)(T x) pure @nogc
195*627f7eb2Smrg {
196*627f7eb2Smrg data = x.data;
197*627f7eb2Smrg sign = x.sign;
198*627f7eb2Smrg return this;
199*627f7eb2Smrg }
200*627f7eb2Smrg
201*627f7eb2Smrg ///
202*627f7eb2Smrg @system unittest
203*627f7eb2Smrg {
204*627f7eb2Smrg auto b1 = BigInt("123");
205*627f7eb2Smrg auto b2 = BigInt("456");
206*627f7eb2Smrg b2 = b1;
207*627f7eb2Smrg assert(b2 == BigInt("123"));
208*627f7eb2Smrg }
209*627f7eb2Smrg
210*627f7eb2Smrg /**
211*627f7eb2Smrg * Implements assignment operators from built-in integers of the form
212*627f7eb2Smrg * $(D BigInt op= integer).
213*627f7eb2Smrg */
214*627f7eb2Smrg BigInt opOpAssign(string op, T)(T y) pure nothrow
215*627f7eb2Smrg if ((op=="+" || op=="-" || op=="*" || op=="/" || op=="%"
216*627f7eb2Smrg || op==">>" || op=="<<" || op=="^^" || op=="|" || op=="&" || op=="^") && isIntegral!T)
217*627f7eb2Smrg {
218*627f7eb2Smrg ulong u = absUnsign(y);
219*627f7eb2Smrg
220*627f7eb2Smrg static if (op=="+")
221*627f7eb2Smrg {
222*627f7eb2Smrg data = BigUint.addOrSubInt(data, u, sign != (y<0), sign);
223*627f7eb2Smrg }
224*627f7eb2Smrg else static if (op=="-")
225*627f7eb2Smrg {
226*627f7eb2Smrg data = BigUint.addOrSubInt(data, u, sign == (y<0), sign);
227*627f7eb2Smrg }
228*627f7eb2Smrg else static if (op=="*")
229*627f7eb2Smrg {
230*627f7eb2Smrg if (y == 0)
231*627f7eb2Smrg {
232*627f7eb2Smrg sign = false;
233*627f7eb2Smrg data = 0UL;
234*627f7eb2Smrg }
235*627f7eb2Smrg else
236*627f7eb2Smrg {
237*627f7eb2Smrg sign = ( sign != (y<0) );
238*627f7eb2Smrg data = BigUint.mulInt(data, u);
239*627f7eb2Smrg }
240*627f7eb2Smrg }
241*627f7eb2Smrg else static if (op=="/")
242*627f7eb2Smrg {
243*627f7eb2Smrg assert(y != 0, "Division by zero");
244*627f7eb2Smrg static if (T.sizeof <= uint.sizeof)
245*627f7eb2Smrg {
246*627f7eb2Smrg data = BigUint.divInt(data, cast(uint) u);
247*627f7eb2Smrg }
248*627f7eb2Smrg else
249*627f7eb2Smrg {
250*627f7eb2Smrg data = BigUint.divInt(data, u);
251*627f7eb2Smrg }
252*627f7eb2Smrg sign = data.isZero() ? false : sign ^ (y < 0);
253*627f7eb2Smrg }
254*627f7eb2Smrg else static if (op=="%")
255*627f7eb2Smrg {
256*627f7eb2Smrg assert(y != 0, "Division by zero");
257*627f7eb2Smrg static if (is(immutable(T) == immutable(long)) || is( immutable(T) == immutable(ulong) ))
258*627f7eb2Smrg {
259*627f7eb2Smrg this %= BigInt(y);
260*627f7eb2Smrg }
261*627f7eb2Smrg else
262*627f7eb2Smrg {
263*627f7eb2Smrg data = cast(ulong) BigUint.modInt(data, cast(uint) u);
264*627f7eb2Smrg if (data.isZero())
265*627f7eb2Smrg sign = false;
266*627f7eb2Smrg }
267*627f7eb2Smrg // x%y always has the same sign as x.
268*627f7eb2Smrg // This is not the same as mathematical mod.
269*627f7eb2Smrg }
270*627f7eb2Smrg else static if (op==">>" || op=="<<")
271*627f7eb2Smrg {
272*627f7eb2Smrg // Do a left shift if y>0 and <<, or
273*627f7eb2Smrg // if y<0 and >>; else do a right shift.
274*627f7eb2Smrg if (y == 0)
275*627f7eb2Smrg return this;
276*627f7eb2Smrg else if ((y > 0) == (op=="<<"))
277*627f7eb2Smrg {
278*627f7eb2Smrg // Sign never changes during left shift
279*627f7eb2Smrg data = data.opShl(u);
280*627f7eb2Smrg } else
281*627f7eb2Smrg {
282*627f7eb2Smrg data = data.opShr(u);
283*627f7eb2Smrg if (data.isZero())
284*627f7eb2Smrg sign = false;
285*627f7eb2Smrg }
286*627f7eb2Smrg }
287*627f7eb2Smrg else static if (op=="^^")
288*627f7eb2Smrg {
289*627f7eb2Smrg sign = (y & 1) ? sign : false;
290*627f7eb2Smrg data = BigUint.pow(data, u);
291*627f7eb2Smrg }
292*627f7eb2Smrg else static if (op=="|" || op=="&" || op=="^")
293*627f7eb2Smrg {
294*627f7eb2Smrg BigInt b = y;
295*627f7eb2Smrg opOpAssign!op(b);
296*627f7eb2Smrg }
297*627f7eb2Smrg else static assert(0, "BigInt " ~ op[0..$-1] ~ "= " ~ T.stringof ~ " is not supported");
298*627f7eb2Smrg return this;
299*627f7eb2Smrg }
300*627f7eb2Smrg
301*627f7eb2Smrg ///
302*627f7eb2Smrg @system unittest
303*627f7eb2Smrg {
304*627f7eb2Smrg //@system because opOpAssign is @system
305*627f7eb2Smrg auto b = BigInt("1_000_000_000");
306*627f7eb2Smrg
307*627f7eb2Smrg b += 12345;
308*627f7eb2Smrg assert(b == BigInt("1_000_012_345"));
309*627f7eb2Smrg
310*627f7eb2Smrg b /= 5;
311*627f7eb2Smrg assert(b == BigInt("200_002_469"));
312*627f7eb2Smrg }
313*627f7eb2Smrg
314*627f7eb2Smrg /**
315*627f7eb2Smrg * Implements assignment operators of the form $(D BigInt op= BigInt).
316*627f7eb2Smrg */
317*627f7eb2Smrg BigInt opOpAssign(string op, T)(T y) pure nothrow
318*627f7eb2Smrg if ((op=="+" || op== "-" || op=="*" || op=="|" || op=="&" || op=="^" || op=="/" || op=="%")
319*627f7eb2Smrg && is (T: BigInt))
320*627f7eb2Smrg {
321*627f7eb2Smrg static if (op == "+")
322*627f7eb2Smrg {
323*627f7eb2Smrg data = BigUint.addOrSub(data, y.data, sign != y.sign, &sign);
324*627f7eb2Smrg }
325*627f7eb2Smrg else static if (op == "-")
326*627f7eb2Smrg {
327*627f7eb2Smrg data = BigUint.addOrSub(data, y.data, sign == y.sign, &sign);
328*627f7eb2Smrg }
329*627f7eb2Smrg else static if (op == "*")
330*627f7eb2Smrg {
331*627f7eb2Smrg data = BigUint.mul(data, y.data);
332*627f7eb2Smrg sign = isZero() ? false : sign ^ y.sign;
333*627f7eb2Smrg }
334*627f7eb2Smrg else static if (op == "/")
335*627f7eb2Smrg {
336*627f7eb2Smrg y.checkDivByZero();
337*627f7eb2Smrg if (!isZero())
338*627f7eb2Smrg {
339*627f7eb2Smrg data = BigUint.div(data, y.data);
340*627f7eb2Smrg sign = isZero() ? false : sign ^ y.sign;
341*627f7eb2Smrg }
342*627f7eb2Smrg }
343*627f7eb2Smrg else static if (op == "%")
344*627f7eb2Smrg {
345*627f7eb2Smrg y.checkDivByZero();
346*627f7eb2Smrg if (!isZero())
347*627f7eb2Smrg {
348*627f7eb2Smrg data = BigUint.mod(data, y.data);
349*627f7eb2Smrg // x%y always has the same sign as x.
350*627f7eb2Smrg if (isZero())
351*627f7eb2Smrg sign = false;
352*627f7eb2Smrg }
353*627f7eb2Smrg }
354*627f7eb2Smrg else static if (op == "|" || op == "&" || op == "^")
355*627f7eb2Smrg {
356*627f7eb2Smrg data = BigUint.bitwiseOp!op(data, y.data, sign, y.sign, sign);
357*627f7eb2Smrg }
358*627f7eb2Smrg else static assert(0, "BigInt " ~ op[0..$-1] ~ "= " ~
359*627f7eb2Smrg T.stringof ~ " is not supported");
360*627f7eb2Smrg return this;
361*627f7eb2Smrg }
362*627f7eb2Smrg
363*627f7eb2Smrg ///
364*627f7eb2Smrg @system unittest
365*627f7eb2Smrg {
366*627f7eb2Smrg // @system because opOpAssign is @system
367*627f7eb2Smrg auto x = BigInt("123");
368*627f7eb2Smrg auto y = BigInt("321");
369*627f7eb2Smrg x += y;
370*627f7eb2Smrg assert(x == BigInt("444"));
371*627f7eb2Smrg }
372*627f7eb2Smrg
373*627f7eb2Smrg /**
374*627f7eb2Smrg * Implements binary operators between BigInts.
375*627f7eb2Smrg */
376*627f7eb2Smrg BigInt opBinary(string op, T)(T y) pure nothrow const
377*627f7eb2Smrg if ((op=="+" || op == "*" || op=="-" || op=="|" || op=="&" || op=="^" ||
378*627f7eb2Smrg op=="/" || op=="%")
379*627f7eb2Smrg && is (T: BigInt))
380*627f7eb2Smrg {
381*627f7eb2Smrg BigInt r = this;
382*627f7eb2Smrg return r.opOpAssign!(op)(y);
383*627f7eb2Smrg }
384*627f7eb2Smrg
385*627f7eb2Smrg ///
386*627f7eb2Smrg @system unittest
387*627f7eb2Smrg {
388*627f7eb2Smrg auto x = BigInt("123");
389*627f7eb2Smrg auto y = BigInt("456");
390*627f7eb2Smrg BigInt z = x * y;
391*627f7eb2Smrg assert(z == BigInt("56088"));
392*627f7eb2Smrg }
393*627f7eb2Smrg
394*627f7eb2Smrg /**
395*627f7eb2Smrg * Implements binary operators between BigInt's and built-in integers.
396*627f7eb2Smrg */
397*627f7eb2Smrg BigInt opBinary(string op, T)(T y) pure nothrow const
398*627f7eb2Smrg if ((op=="+" || op == "*" || op=="-" || op=="/" || op=="|" || op=="&" ||
399*627f7eb2Smrg op=="^"|| op==">>" || op=="<<" || op=="^^")
400*627f7eb2Smrg && isIntegral!T)
401*627f7eb2Smrg {
402*627f7eb2Smrg BigInt r = this;
403*627f7eb2Smrg return r.opOpAssign!(op)(y);
404*627f7eb2Smrg }
405*627f7eb2Smrg
406*627f7eb2Smrg ///
407*627f7eb2Smrg @system unittest
408*627f7eb2Smrg {
409*627f7eb2Smrg auto x = BigInt("123");
410*627f7eb2Smrg x *= 300;
411*627f7eb2Smrg assert(x == BigInt("36900"));
412*627f7eb2Smrg }
413*627f7eb2Smrg
414*627f7eb2Smrg /**
415*627f7eb2Smrg Implements a narrowing remainder operation with built-in integer types.
416*627f7eb2Smrg
417*627f7eb2Smrg This binary operator returns a narrower, built-in integer type
418*627f7eb2Smrg where applicable, according to the following table.
419*627f7eb2Smrg
420*627f7eb2Smrg $(TABLE ,
421*627f7eb2Smrg $(TR $(TD `BigInt`) $(TD $(CODE_PERCENT)) $(TD `long`) $(TD $(RARR)) $(TD `long`))
422*627f7eb2Smrg $(TR $(TD `BigInt`) $(TD $(CODE_PERCENT)) $(TD `ulong`) $(TD $(RARR)) $(TD `BigInt`))
423*627f7eb2Smrg $(TR $(TD `BigInt`) $(TD $(CODE_PERCENT)) $(TD other type) $(TD $(RARR)) $(TD `int`))
424*627f7eb2Smrg )
425*627f7eb2Smrg */
426*627f7eb2Smrg auto opBinary(string op, T)(T y) pure nothrow const
427*627f7eb2Smrg if (op == "%" && isIntegral!T)
428*627f7eb2Smrg {
429*627f7eb2Smrg assert(y != 0);
430*627f7eb2Smrg
431*627f7eb2Smrg // BigInt % long => long
432*627f7eb2Smrg // BigInt % ulong => BigInt
433*627f7eb2Smrg // BigInt % other_type => int
434*627f7eb2Smrg static if (is(Unqual!T == long) || is(Unqual!T == ulong))
435*627f7eb2Smrg {
436*627f7eb2Smrg auto r = this % BigInt(y);
437*627f7eb2Smrg
438*627f7eb2Smrg static if (is(Unqual!T == long))
439*627f7eb2Smrg {
440*627f7eb2Smrg return r.toLong();
441*627f7eb2Smrg }
442*627f7eb2Smrg else
443*627f7eb2Smrg {
444*627f7eb2Smrg // return as-is to avoid overflow
445*627f7eb2Smrg return r;
446*627f7eb2Smrg }
447*627f7eb2Smrg }
448*627f7eb2Smrg else
449*627f7eb2Smrg {
450*627f7eb2Smrg immutable uint u = absUnsign(y);
451*627f7eb2Smrg int rem = BigUint.modInt(data, u);
452*627f7eb2Smrg // x%y always has the same sign as x.
453*627f7eb2Smrg // This is not the same as mathematical mod.
454*627f7eb2Smrg return sign ? -rem : rem;
455*627f7eb2Smrg }
456*627f7eb2Smrg }
457*627f7eb2Smrg
458*627f7eb2Smrg ///
459*627f7eb2Smrg @system unittest
460*627f7eb2Smrg {
461*627f7eb2Smrg auto x = BigInt("1_000_000_500");
462*627f7eb2Smrg long l = 1_000_000L;
463*627f7eb2Smrg ulong ul = 2_000_000UL;
464*627f7eb2Smrg int i = 500_000;
465*627f7eb2Smrg short s = 30_000;
466*627f7eb2Smrg
467*627f7eb2Smrg assert(is(typeof(x % l) == long) && x % l == 500L);
468*627f7eb2Smrg assert(is(typeof(x % ul) == BigInt) && x % ul == BigInt(500));
469*627f7eb2Smrg assert(is(typeof(x % i) == int) && x % i == 500);
470*627f7eb2Smrg assert(is(typeof(x % s) == int) && x % s == 10500);
471*627f7eb2Smrg }
472*627f7eb2Smrg
473*627f7eb2Smrg /**
474*627f7eb2Smrg Implements operators with built-in integers on the left-hand side and
475*627f7eb2Smrg BigInt on the right-hand side.
476*627f7eb2Smrg */
477*627f7eb2Smrg BigInt opBinaryRight(string op, T)(T y) pure nothrow const
478*627f7eb2Smrg if ((op=="+" || op=="*" || op=="|" || op=="&" || op=="^") && isIntegral!T)
479*627f7eb2Smrg {
480*627f7eb2Smrg return opBinary!(op)(y);
481*627f7eb2Smrg }
482*627f7eb2Smrg
483*627f7eb2Smrg ///
484*627f7eb2Smrg @system unittest
485*627f7eb2Smrg {
486*627f7eb2Smrg auto x = BigInt("100");
487*627f7eb2Smrg BigInt y = 123 + x;
488*627f7eb2Smrg assert(y == BigInt("223"));
489*627f7eb2Smrg
490*627f7eb2Smrg BigInt z = 123 - x;
491*627f7eb2Smrg assert(z == BigInt("23"));
492*627f7eb2Smrg
493*627f7eb2Smrg // Dividing a built-in integer type by BigInt always results in
494*627f7eb2Smrg // something that fits in a built-in type, so the built-in type is
495*627f7eb2Smrg // returned, not BigInt.
496*627f7eb2Smrg assert(is(typeof(1000 / x) == int));
497*627f7eb2Smrg assert(1000 / x == 10);
498*627f7eb2Smrg }
499*627f7eb2Smrg
500*627f7eb2Smrg // BigInt = integer op BigInt
501*627f7eb2Smrg /// ditto
502*627f7eb2Smrg BigInt opBinaryRight(string op, T)(T y) pure nothrow const
503*627f7eb2Smrg if (op == "-" && isIntegral!T)
504*627f7eb2Smrg {
505*627f7eb2Smrg ulong u = absUnsign(y);
506*627f7eb2Smrg BigInt r;
507*627f7eb2Smrg static if (op == "-")
508*627f7eb2Smrg {
509*627f7eb2Smrg r.sign = sign;
510*627f7eb2Smrg r.data = BigUint.addOrSubInt(data, u, sign == (y<0), r.sign);
511*627f7eb2Smrg r.negate();
512*627f7eb2Smrg }
513*627f7eb2Smrg return r;
514*627f7eb2Smrg }
515*627f7eb2Smrg
516*627f7eb2Smrg // integer = integer op BigInt
517*627f7eb2Smrg /// ditto
518*627f7eb2Smrg T opBinaryRight(string op, T)(T x) pure nothrow const
519*627f7eb2Smrg if ((op=="%" || op=="/") && isIntegral!T)
520*627f7eb2Smrg {
521*627f7eb2Smrg checkDivByZero();
522*627f7eb2Smrg
523*627f7eb2Smrg static if (op == "%")
524*627f7eb2Smrg {
525*627f7eb2Smrg // x%y always has the same sign as x.
526*627f7eb2Smrg if (data.ulongLength > 1)
527*627f7eb2Smrg return x;
528*627f7eb2Smrg immutable u = absUnsign(x);
529*627f7eb2Smrg immutable rem = u % data.peekUlong(0);
530*627f7eb2Smrg // x%y always has the same sign as x.
531*627f7eb2Smrg return cast(T)((x<0) ? -rem : rem);
532*627f7eb2Smrg }
533*627f7eb2Smrg else static if (op == "/")
534*627f7eb2Smrg {
535*627f7eb2Smrg if (data.ulongLength > 1)
536*627f7eb2Smrg return 0;
537*627f7eb2Smrg return cast(T)(x / data.peekUlong(0));
538*627f7eb2Smrg }
539*627f7eb2Smrg }
540*627f7eb2Smrg
541*627f7eb2Smrg // const unary operations
542*627f7eb2Smrg /**
543*627f7eb2Smrg Implements BigInt unary operators.
544*627f7eb2Smrg */
545*627f7eb2Smrg BigInt opUnary(string op)() pure nothrow const if (op=="+" || op=="-" || op=="~")
546*627f7eb2Smrg {
547*627f7eb2Smrg static if (op=="-")
548*627f7eb2Smrg {
549*627f7eb2Smrg BigInt r = this;
550*627f7eb2Smrg r.negate();
551*627f7eb2Smrg return r;
552*627f7eb2Smrg }
553*627f7eb2Smrg else static if (op=="~")
554*627f7eb2Smrg {
555*627f7eb2Smrg return -(this+1);
556*627f7eb2Smrg }
557*627f7eb2Smrg else static if (op=="+")
558*627f7eb2Smrg return this;
559*627f7eb2Smrg }
560*627f7eb2Smrg
561*627f7eb2Smrg // non-const unary operations
562*627f7eb2Smrg /// ditto
563*627f7eb2Smrg BigInt opUnary(string op)() pure nothrow if (op=="++" || op=="--")
564*627f7eb2Smrg {
565*627f7eb2Smrg static if (op=="++")
566*627f7eb2Smrg {
567*627f7eb2Smrg data = BigUint.addOrSubInt(data, 1UL, sign, sign);
568*627f7eb2Smrg return this;
569*627f7eb2Smrg }
570*627f7eb2Smrg else static if (op=="--")
571*627f7eb2Smrg {
572*627f7eb2Smrg data = BigUint.addOrSubInt(data, 1UL, !sign, sign);
573*627f7eb2Smrg return this;
574*627f7eb2Smrg }
575*627f7eb2Smrg }
576*627f7eb2Smrg
577*627f7eb2Smrg ///
578*627f7eb2Smrg @system unittest
579*627f7eb2Smrg {
580*627f7eb2Smrg auto x = BigInt("1234");
581*627f7eb2Smrg assert(-x == BigInt("-1234"));
582*627f7eb2Smrg
583*627f7eb2Smrg ++x;
584*627f7eb2Smrg assert(x == BigInt("1235"));
585*627f7eb2Smrg }
586*627f7eb2Smrg
587*627f7eb2Smrg /**
588*627f7eb2Smrg Implements BigInt equality test with other BigInt's and built-in
589*627f7eb2Smrg integer types.
590*627f7eb2Smrg */
opEqualsBigInt591*627f7eb2Smrg bool opEquals()(auto ref const BigInt y) const pure @nogc
592*627f7eb2Smrg {
593*627f7eb2Smrg return sign == y.sign && y.data == data;
594*627f7eb2Smrg }
595*627f7eb2Smrg
596*627f7eb2Smrg /// ditto
597*627f7eb2Smrg bool opEquals(T)(T y) const pure nothrow @nogc if (isIntegral!T)
598*627f7eb2Smrg {
599*627f7eb2Smrg if (sign != (y<0))
600*627f7eb2Smrg return 0;
601*627f7eb2Smrg return data.opEquals(cast(ulong) absUnsign(y));
602*627f7eb2Smrg }
603*627f7eb2Smrg
604*627f7eb2Smrg ///
605*627f7eb2Smrg @system unittest
606*627f7eb2Smrg {
607*627f7eb2Smrg auto x = BigInt("12345");
608*627f7eb2Smrg auto y = BigInt("12340");
609*627f7eb2Smrg int z = 12345;
610*627f7eb2Smrg int w = 54321;
611*627f7eb2Smrg
612*627f7eb2Smrg assert(x == x);
613*627f7eb2Smrg assert(x != y);
614*627f7eb2Smrg assert(x == y + 5);
615*627f7eb2Smrg assert(x == z);
616*627f7eb2Smrg assert(x != w);
617*627f7eb2Smrg }
618*627f7eb2Smrg
619*627f7eb2Smrg /**
620*627f7eb2Smrg Implements casting to bool.
621*627f7eb2Smrg */
622*627f7eb2Smrg T opCast(T:bool)() pure nothrow @nogc const
623*627f7eb2Smrg {
624*627f7eb2Smrg return !isZero();
625*627f7eb2Smrg }
626*627f7eb2Smrg
627*627f7eb2Smrg ///
628*627f7eb2Smrg @system unittest
629*627f7eb2Smrg {
630*627f7eb2Smrg // Non-zero values are regarded as true
631*627f7eb2Smrg auto x = BigInt("1");
632*627f7eb2Smrg auto y = BigInt("10");
633*627f7eb2Smrg assert(x);
634*627f7eb2Smrg assert(y);
635*627f7eb2Smrg
636*627f7eb2Smrg // Zero value is regarded as false
637*627f7eb2Smrg auto z = BigInt("0");
638*627f7eb2Smrg assert(!z);
639*627f7eb2Smrg }
640*627f7eb2Smrg
641*627f7eb2Smrg /**
642*627f7eb2Smrg Implements casting to integer types.
643*627f7eb2Smrg
644*627f7eb2Smrg Throws: $(REF ConvOverflowException, std,conv) if the number exceeds
645*627f7eb2Smrg the target type's range.
646*627f7eb2Smrg */
647*627f7eb2Smrg T opCast(T:ulong)() /*pure*/ const
648*627f7eb2Smrg {
649*627f7eb2Smrg if (isUnsigned!T && sign)
650*627f7eb2Smrg { /* throw */ }
651*627f7eb2Smrg else
652*627f7eb2Smrg if (data.ulongLength == 1)
653*627f7eb2Smrg {
654*627f7eb2Smrg ulong l = data.peekUlong(0);
655*627f7eb2Smrg if (isUnsigned!T || !sign)
656*627f7eb2Smrg {
657*627f7eb2Smrg if (l <= T.max)
658*627f7eb2Smrg return cast(T) l;
659*627f7eb2Smrg }
660*627f7eb2Smrg else
661*627f7eb2Smrg {
662*627f7eb2Smrg if (l <= ulong(T.max)+1)
663*627f7eb2Smrg return cast(T)-long(l); // -long.min == long.min
664*627f7eb2Smrg }
665*627f7eb2Smrg }
666*627f7eb2Smrg
667*627f7eb2Smrg import std.conv : ConvOverflowException;
668*627f7eb2Smrg import std.string : format;
669*627f7eb2Smrg throw new ConvOverflowException(
670*627f7eb2Smrg "BigInt(%d) cannot be represented as a %s"
671*627f7eb2Smrg .format(this, T.stringof));
672*627f7eb2Smrg }
673*627f7eb2Smrg
674*627f7eb2Smrg ///
675*627f7eb2Smrg @system unittest
676*627f7eb2Smrg {
677*627f7eb2Smrg import std.conv : to, ConvOverflowException;
678*627f7eb2Smrg import std.exception : assertThrown;
679*627f7eb2Smrg
680*627f7eb2Smrg assert(BigInt("0").to!int == 0);
681*627f7eb2Smrg
682*627f7eb2Smrg assert(BigInt("0").to!ubyte == 0);
683*627f7eb2Smrg assert(BigInt("255").to!ubyte == 255);
684*627f7eb2Smrg assertThrown!ConvOverflowException(BigInt("256").to!ubyte);
685*627f7eb2Smrg assertThrown!ConvOverflowException(BigInt("-1").to!ubyte);
686*627f7eb2Smrg }
687*627f7eb2Smrg
688*627f7eb2Smrg @system unittest
689*627f7eb2Smrg {
690*627f7eb2Smrg import std.conv : to, ConvOverflowException;
691*627f7eb2Smrg import std.exception : assertThrown;
692*627f7eb2Smrg
693*627f7eb2Smrg assert(BigInt("-1").to!byte == -1);
694*627f7eb2Smrg assert(BigInt("-128").to!byte == -128);
695*627f7eb2Smrg assert(BigInt("127").to!byte == 127);
696*627f7eb2Smrg assertThrown!ConvOverflowException(BigInt("-129").to!byte);
697*627f7eb2Smrg assertThrown!ConvOverflowException(BigInt("128").to!byte);
698*627f7eb2Smrg
699*627f7eb2Smrg assert(BigInt("0").to!uint == 0);
700*627f7eb2Smrg assert(BigInt("4294967295").to!uint == uint.max);
701*627f7eb2Smrg assertThrown!ConvOverflowException(BigInt("4294967296").to!uint);
702*627f7eb2Smrg assertThrown!ConvOverflowException(BigInt("-1").to!uint);
703*627f7eb2Smrg
704*627f7eb2Smrg assert(BigInt("-1").to!int == -1);
705*627f7eb2Smrg assert(BigInt("-2147483648").to!int == int.min);
706*627f7eb2Smrg assert(BigInt("2147483647").to!int == int.max);
707*627f7eb2Smrg assertThrown!ConvOverflowException(BigInt("-2147483649").to!int);
708*627f7eb2Smrg assertThrown!ConvOverflowException(BigInt("2147483648").to!int);
709*627f7eb2Smrg
710*627f7eb2Smrg assert(BigInt("0").to!ulong == 0);
711*627f7eb2Smrg assert(BigInt("18446744073709551615").to!ulong == ulong.max);
712*627f7eb2Smrg assertThrown!ConvOverflowException(BigInt("18446744073709551616").to!ulong);
713*627f7eb2Smrg assertThrown!ConvOverflowException(BigInt("-1").to!ulong);
714*627f7eb2Smrg
715*627f7eb2Smrg assert(BigInt("-1").to!long == -1);
716*627f7eb2Smrg assert(BigInt("-9223372036854775808").to!long == long.min);
717*627f7eb2Smrg assert(BigInt("9223372036854775807").to!long == long.max);
718*627f7eb2Smrg assertThrown!ConvOverflowException(BigInt("-9223372036854775809").to!long);
719*627f7eb2Smrg assertThrown!ConvOverflowException(BigInt("9223372036854775808").to!long);
720*627f7eb2Smrg }
721*627f7eb2Smrg
722*627f7eb2Smrg /**
723*627f7eb2Smrg Implements casting to/from qualified BigInt's.
724*627f7eb2Smrg
725*627f7eb2Smrg Warning: Casting to/from $(D const) or $(D immutable) may break type
726*627f7eb2Smrg system guarantees. Use with care.
727*627f7eb2Smrg */
728*627f7eb2Smrg T opCast(T)() pure nothrow @nogc const
729*627f7eb2Smrg if (is(Unqual!T == BigInt))
730*627f7eb2Smrg {
731*627f7eb2Smrg return this;
732*627f7eb2Smrg }
733*627f7eb2Smrg
734*627f7eb2Smrg ///
735*627f7eb2Smrg @system unittest
736*627f7eb2Smrg {
737*627f7eb2Smrg const(BigInt) x = BigInt("123");
738*627f7eb2Smrg BigInt y = cast() x; // cast away const
739*627f7eb2Smrg assert(y == x);
740*627f7eb2Smrg }
741*627f7eb2Smrg
742*627f7eb2Smrg // Hack to make BigInt's typeinfo.compare work properly.
743*627f7eb2Smrg // Note that this must appear before the other opCmp overloads, otherwise
744*627f7eb2Smrg // DMD won't find it.
745*627f7eb2Smrg /**
746*627f7eb2Smrg Implements 3-way comparisons of BigInt with BigInt or BigInt with
747*627f7eb2Smrg built-in integers.
748*627f7eb2Smrg */
opCmpBigInt749*627f7eb2Smrg int opCmp(ref const BigInt y) pure nothrow @nogc const
750*627f7eb2Smrg {
751*627f7eb2Smrg // Simply redirect to the "real" opCmp implementation.
752*627f7eb2Smrg return this.opCmp!BigInt(y);
753*627f7eb2Smrg }
754*627f7eb2Smrg
755*627f7eb2Smrg /// ditto
756*627f7eb2Smrg int opCmp(T)(T y) pure nothrow @nogc const if (isIntegral!T)
757*627f7eb2Smrg {
758*627f7eb2Smrg if (sign != (y<0) )
759*627f7eb2Smrg return sign ? -1 : 1;
760*627f7eb2Smrg int cmp = data.opCmp(cast(ulong) absUnsign(y));
761*627f7eb2Smrg return sign? -cmp: cmp;
762*627f7eb2Smrg }
763*627f7eb2Smrg /// ditto
764*627f7eb2Smrg int opCmp(T:BigInt)(const T y) pure nothrow @nogc const
765*627f7eb2Smrg {
766*627f7eb2Smrg if (sign != y.sign)
767*627f7eb2Smrg return sign ? -1 : 1;
768*627f7eb2Smrg immutable cmp = data.opCmp(y.data);
769*627f7eb2Smrg return sign? -cmp: cmp;
770*627f7eb2Smrg }
771*627f7eb2Smrg
772*627f7eb2Smrg ///
773*627f7eb2Smrg @system unittest
774*627f7eb2Smrg {
775*627f7eb2Smrg auto x = BigInt("100");
776*627f7eb2Smrg auto y = BigInt("10");
777*627f7eb2Smrg int z = 50;
778*627f7eb2Smrg const int w = 200;
779*627f7eb2Smrg
780*627f7eb2Smrg assert(y < x);
781*627f7eb2Smrg assert(x > z);
782*627f7eb2Smrg assert(z > y);
783*627f7eb2Smrg assert(x < w);
784*627f7eb2Smrg }
785*627f7eb2Smrg
786*627f7eb2Smrg /**
787*627f7eb2Smrg Returns: The value of this BigInt as a long, or +/- long.max if outside
788*627f7eb2Smrg the representable range.
789*627f7eb2Smrg */
toLongBigInt790*627f7eb2Smrg long toLong() @safe pure nothrow const @nogc
791*627f7eb2Smrg {
792*627f7eb2Smrg return (sign ? -1 : 1) *
793*627f7eb2Smrg (data.ulongLength == 1 && (data.peekUlong(0) <= sign+cast(ulong)(long.max)) // 1+long.max = |long.min|
794*627f7eb2Smrg ? cast(long)(data.peekUlong(0))
795*627f7eb2Smrg : long.max);
796*627f7eb2Smrg }
797*627f7eb2Smrg
798*627f7eb2Smrg ///
799*627f7eb2Smrg @system unittest
800*627f7eb2Smrg {
801*627f7eb2Smrg auto b = BigInt("12345");
802*627f7eb2Smrg long l = b.toLong();
803*627f7eb2Smrg assert(l == 12345);
804*627f7eb2Smrg }
805*627f7eb2Smrg
806*627f7eb2Smrg /**
807*627f7eb2Smrg Returns: The value of this BigInt as an int, or +/- int.max if outside
808*627f7eb2Smrg the representable range.
809*627f7eb2Smrg */
toIntBigInt810*627f7eb2Smrg int toInt() @safe pure nothrow @nogc const
811*627f7eb2Smrg {
812*627f7eb2Smrg return (sign ? -1 : 1) *
813*627f7eb2Smrg (data.uintLength == 1 && (data.peekUint(0) <= sign+cast(uint)(int.max)) // 1+int.max = |int.min|
814*627f7eb2Smrg ? cast(int)(data.peekUint(0))
815*627f7eb2Smrg : int.max);
816*627f7eb2Smrg }
817*627f7eb2Smrg
818*627f7eb2Smrg ///
819*627f7eb2Smrg @system unittest
820*627f7eb2Smrg {
821*627f7eb2Smrg auto big = BigInt("5_000_000");
822*627f7eb2Smrg auto i = big.toInt();
823*627f7eb2Smrg assert(i == 5_000_000);
824*627f7eb2Smrg
825*627f7eb2Smrg // Numbers that are too big to fit into an int will be clamped to int.max.
826*627f7eb2Smrg auto tooBig = BigInt("5_000_000_000");
827*627f7eb2Smrg i = tooBig.toInt();
828*627f7eb2Smrg assert(i == int.max);
829*627f7eb2Smrg }
830*627f7eb2Smrg
831*627f7eb2Smrg /// Number of significant uints which are used in storing this number.
832*627f7eb2Smrg /// The absolute value of this BigInt is always < 2$(SUPERSCRIPT 32*uintLength)
uintLengthBigInt833*627f7eb2Smrg @property size_t uintLength() @safe pure nothrow @nogc const
834*627f7eb2Smrg {
835*627f7eb2Smrg return data.uintLength;
836*627f7eb2Smrg }
837*627f7eb2Smrg
838*627f7eb2Smrg /// Number of significant ulongs which are used in storing this number.
839*627f7eb2Smrg /// The absolute value of this BigInt is always < 2$(SUPERSCRIPT 64*ulongLength)
ulongLengthBigInt840*627f7eb2Smrg @property size_t ulongLength() @safe pure nothrow @nogc const
841*627f7eb2Smrg {
842*627f7eb2Smrg return data.ulongLength;
843*627f7eb2Smrg }
844*627f7eb2Smrg
845*627f7eb2Smrg /** Convert the BigInt to string, passing it to the given sink.
846*627f7eb2Smrg *
847*627f7eb2Smrg * Params:
848*627f7eb2Smrg * sink = A delegate for accepting possibly piecewise segments of the
849*627f7eb2Smrg * formatted string.
850*627f7eb2Smrg * formatString = A format string specifying the output format.
851*627f7eb2Smrg *
852*627f7eb2Smrg * $(TABLE Available output formats:,
853*627f7eb2Smrg * $(TR $(TD "d") $(TD Decimal))
854*627f7eb2Smrg * $(TR $(TD "o") $(TD Octal))
855*627f7eb2Smrg * $(TR $(TD "x") $(TD Hexadecimal, lower case))
856*627f7eb2Smrg * $(TR $(TD "X") $(TD Hexadecimal, upper case))
857*627f7eb2Smrg * $(TR $(TD "s") $(TD Default formatting (same as "d") ))
858*627f7eb2Smrg * $(TR $(TD null) $(TD Default formatting (same as "d") ))
859*627f7eb2Smrg * )
860*627f7eb2Smrg */
toStringBigInt861*627f7eb2Smrg void toString(scope void delegate(const (char)[]) sink, string formatString) const
862*627f7eb2Smrg {
863*627f7eb2Smrg auto f = FormatSpec!char(formatString);
864*627f7eb2Smrg f.writeUpToNextSpec(sink);
865*627f7eb2Smrg toString(sink, f);
866*627f7eb2Smrg }
867*627f7eb2Smrg
868*627f7eb2Smrg /// ditto
869*627f7eb2Smrg void toString(scope void delegate(const(char)[]) sink, ref FormatSpec!char f) const
870*627f7eb2Smrg {
871*627f7eb2Smrg immutable hex = (f.spec == 'x' || f.spec == 'X');
872*627f7eb2Smrg if (!(f.spec == 's' || f.spec == 'd' || f.spec =='o' || hex))
873*627f7eb2Smrg throw new FormatException("Format specifier not understood: %" ~ f.spec);
874*627f7eb2Smrg
875*627f7eb2Smrg char[] buff;
876*627f7eb2Smrg if (f.spec == 'X')
877*627f7eb2Smrg {
878*627f7eb2Smrg buff = data.toHexString(0, '_', 0, f.flZero ? '0' : ' ', LetterCase.upper);
879*627f7eb2Smrg }
880*627f7eb2Smrg else if (f.spec == 'x')
881*627f7eb2Smrg {
882*627f7eb2Smrg buff = data.toHexString(0, '_', 0, f.flZero ? '0' : ' ', LetterCase.lower);
883*627f7eb2Smrg }
884*627f7eb2Smrg else if (f.spec == 'o')
885*627f7eb2Smrg {
886*627f7eb2Smrg buff = data.toOctalString();
887*627f7eb2Smrg }
888*627f7eb2Smrg else
889*627f7eb2Smrg {
890*627f7eb2Smrg buff = data.toDecimalString(0);
891*627f7eb2Smrg }
892*627f7eb2Smrg assert(buff.length > 0);
893*627f7eb2Smrg
894*627f7eb2Smrg char signChar = isNegative() ? '-' : 0;
895*627f7eb2Smrg auto minw = buff.length + (signChar ? 1 : 0);
896*627f7eb2Smrg
897*627f7eb2Smrg if (!hex && !signChar && (f.width == 0 || minw < f.width))
898*627f7eb2Smrg {
899*627f7eb2Smrg if (f.flPlus)
900*627f7eb2Smrg {
901*627f7eb2Smrg signChar = '+';
902*627f7eb2Smrg ++minw;
903*627f7eb2Smrg }
904*627f7eb2Smrg else if (f.flSpace)
905*627f7eb2Smrg {
906*627f7eb2Smrg signChar = ' ';
907*627f7eb2Smrg ++minw;
908*627f7eb2Smrg }
909*627f7eb2Smrg }
910*627f7eb2Smrg
911*627f7eb2Smrg immutable maxw = minw < f.width ? f.width : minw;
912*627f7eb2Smrg immutable difw = maxw - minw;
913*627f7eb2Smrg
914*627f7eb2Smrg if (!f.flDash && !f.flZero)
915*627f7eb2Smrg foreach (i; 0 .. difw)
916*627f7eb2Smrg sink(" ");
917*627f7eb2Smrg
918*627f7eb2Smrg if (signChar)
919*627f7eb2Smrg sink((&signChar)[0 .. 1]);
920*627f7eb2Smrg
921*627f7eb2Smrg if (!f.flDash && f.flZero)
922*627f7eb2Smrg foreach (i; 0 .. difw)
923*627f7eb2Smrg sink("0");
924*627f7eb2Smrg
925*627f7eb2Smrg sink(buff);
926*627f7eb2Smrg
927*627f7eb2Smrg if (f.flDash)
928*627f7eb2Smrg foreach (i; 0 .. difw)
929*627f7eb2Smrg sink(" ");
930*627f7eb2Smrg }
931*627f7eb2Smrg
932*627f7eb2Smrg /**
933*627f7eb2Smrg $(D toString) is rarely directly invoked; the usual way of using it is via
934*627f7eb2Smrg $(REF format, std, format):
935*627f7eb2Smrg */
936*627f7eb2Smrg @system unittest
937*627f7eb2Smrg {
938*627f7eb2Smrg import std.format : format;
939*627f7eb2Smrg
940*627f7eb2Smrg auto x = BigInt("1_000_000");
941*627f7eb2Smrg x *= 12345;
942*627f7eb2Smrg
943*627f7eb2Smrg assert(format("%d", x) == "12345000000");
944*627f7eb2Smrg assert(format("%x", x) == "2_dfd1c040");
945*627f7eb2Smrg assert(format("%X", x) == "2_DFD1C040");
946*627f7eb2Smrg assert(format("%o", x) == "133764340100");
947*627f7eb2Smrg }
948*627f7eb2Smrg
949*627f7eb2Smrg // Implement toHash so that BigInt works properly as an AA key.
950*627f7eb2Smrg /**
951*627f7eb2Smrg Returns: A unique hash of the BigInt's value suitable for use in a hash
952*627f7eb2Smrg table.
953*627f7eb2Smrg */
toHashBigInt954*627f7eb2Smrg size_t toHash() const @safe nothrow
955*627f7eb2Smrg {
956*627f7eb2Smrg return data.toHash() + sign;
957*627f7eb2Smrg }
958*627f7eb2Smrg
959*627f7eb2Smrg /**
960*627f7eb2Smrg $(D toHash) is rarely directly invoked; it is implicitly used when
961*627f7eb2Smrg BigInt is used as the key of an associative array.
962*627f7eb2Smrg */
963*627f7eb2Smrg @safe unittest
964*627f7eb2Smrg {
965*627f7eb2Smrg string[BigInt] aa;
966*627f7eb2Smrg aa[BigInt(123)] = "abc";
967*627f7eb2Smrg aa[BigInt(456)] = "def";
968*627f7eb2Smrg
969*627f7eb2Smrg assert(aa[BigInt(123)] == "abc");
970*627f7eb2Smrg assert(aa[BigInt(456)] == "def");
971*627f7eb2Smrg }
972*627f7eb2Smrg
973*627f7eb2Smrg private:
negateBigInt974*627f7eb2Smrg void negate() @safe pure nothrow @nogc
975*627f7eb2Smrg {
976*627f7eb2Smrg if (!data.isZero())
977*627f7eb2Smrg sign = !sign;
978*627f7eb2Smrg }
isZeroBigInt979*627f7eb2Smrg bool isZero() pure const nothrow @nogc @safe
980*627f7eb2Smrg {
981*627f7eb2Smrg return data.isZero();
982*627f7eb2Smrg }
isNegativeBigInt983*627f7eb2Smrg bool isNegative() pure const nothrow @nogc @safe
984*627f7eb2Smrg {
985*627f7eb2Smrg return sign;
986*627f7eb2Smrg }
987*627f7eb2Smrg
988*627f7eb2Smrg // Generate a runtime error if division by zero occurs
checkDivByZeroBigInt989*627f7eb2Smrg void checkDivByZero() pure const nothrow @safe
990*627f7eb2Smrg {
991*627f7eb2Smrg if (isZero())
992*627f7eb2Smrg throw new Error("BigInt division by zero");
993*627f7eb2Smrg }
994*627f7eb2Smrg }
995*627f7eb2Smrg
996*627f7eb2Smrg ///
997*627f7eb2Smrg @system unittest
998*627f7eb2Smrg {
999*627f7eb2Smrg BigInt a = "9588669891916142";
1000*627f7eb2Smrg BigInt b = "7452469135154800";
1001*627f7eb2Smrg auto c = a * b;
1002*627f7eb2Smrg assert(c == BigInt("71459266416693160362545788781600"));
1003*627f7eb2Smrg auto d = b * a;
1004*627f7eb2Smrg assert(d == BigInt("71459266416693160362545788781600"));
1005*627f7eb2Smrg assert(d == c);
1006*627f7eb2Smrg d = c * BigInt("794628672112");
1007*627f7eb2Smrg assert(d == BigInt("56783581982794522489042432639320434378739200"));
1008*627f7eb2Smrg auto e = c + d;
1009*627f7eb2Smrg assert(e == BigInt("56783581982865981755459125799682980167520800"));
1010*627f7eb2Smrg auto f = d + c;
1011*627f7eb2Smrg assert(f == e);
1012*627f7eb2Smrg auto g = f - c;
1013*627f7eb2Smrg assert(g == d);
1014*627f7eb2Smrg g = f - d;
1015*627f7eb2Smrg assert(g == c);
1016*627f7eb2Smrg e = 12345678;
1017*627f7eb2Smrg g = c + e;
1018*627f7eb2Smrg auto h = g / b;
1019*627f7eb2Smrg auto i = g % b;
1020*627f7eb2Smrg assert(h == a);
1021*627f7eb2Smrg assert(i == e);
1022*627f7eb2Smrg BigInt j = "-0x9A56_57f4_7B83_AB78";
1023*627f7eb2Smrg j ^^= 11;
1024*627f7eb2Smrg }
1025*627f7eb2Smrg
1026*627f7eb2Smrg /**
1027*627f7eb2Smrg Params:
1028*627f7eb2Smrg x = The $(D BigInt) to convert to a decimal $(D string).
1029*627f7eb2Smrg
1030*627f7eb2Smrg Returns:
1031*627f7eb2Smrg A $(D string) that represents the $(D BigInt) as a decimal number.
1032*627f7eb2Smrg
1033*627f7eb2Smrg */
toDecimalString(const (BigInt)x)1034*627f7eb2Smrg string toDecimalString(const(BigInt) x)
1035*627f7eb2Smrg {
1036*627f7eb2Smrg string outbuff="";
1037*627f7eb2Smrg void sink(const(char)[] s) { outbuff ~= s; }
1038*627f7eb2Smrg x.toString(&sink, "%d");
1039*627f7eb2Smrg return outbuff;
1040*627f7eb2Smrg }
1041*627f7eb2Smrg
1042*627f7eb2Smrg ///
1043*627f7eb2Smrg @system unittest
1044*627f7eb2Smrg {
1045*627f7eb2Smrg auto x = BigInt("123");
1046*627f7eb2Smrg x *= 1000;
1047*627f7eb2Smrg x += 456;
1048*627f7eb2Smrg
1049*627f7eb2Smrg auto xstr = x.toDecimalString();
1050*627f7eb2Smrg assert(xstr == "123456");
1051*627f7eb2Smrg }
1052*627f7eb2Smrg
1053*627f7eb2Smrg /**
1054*627f7eb2Smrg Params:
1055*627f7eb2Smrg x = The $(D BigInt) to convert to a hexadecimal $(D string).
1056*627f7eb2Smrg
1057*627f7eb2Smrg Returns:
1058*627f7eb2Smrg A $(D string) that represents the $(D BigInt) as a hexadecimal (base 16)
1059*627f7eb2Smrg number in upper case.
1060*627f7eb2Smrg
1061*627f7eb2Smrg */
toHex(const (BigInt)x)1062*627f7eb2Smrg string toHex(const(BigInt) x)
1063*627f7eb2Smrg {
1064*627f7eb2Smrg string outbuff="";
1065*627f7eb2Smrg void sink(const(char)[] s) { outbuff ~= s; }
1066*627f7eb2Smrg x.toString(&sink, "%X");
1067*627f7eb2Smrg return outbuff;
1068*627f7eb2Smrg }
1069*627f7eb2Smrg
1070*627f7eb2Smrg ///
1071*627f7eb2Smrg @system unittest
1072*627f7eb2Smrg {
1073*627f7eb2Smrg auto x = BigInt("123");
1074*627f7eb2Smrg x *= 1000;
1075*627f7eb2Smrg x += 456;
1076*627f7eb2Smrg
1077*627f7eb2Smrg auto xstr = x.toHex();
1078*627f7eb2Smrg assert(xstr == "1E240");
1079*627f7eb2Smrg }
1080*627f7eb2Smrg
1081*627f7eb2Smrg /** Returns the absolute value of x converted to the corresponding unsigned
1082*627f7eb2Smrg type.
1083*627f7eb2Smrg
1084*627f7eb2Smrg Params:
1085*627f7eb2Smrg x = The integral value to return the absolute value of.
1086*627f7eb2Smrg
1087*627f7eb2Smrg Returns:
1088*627f7eb2Smrg The absolute value of x.
1089*627f7eb2Smrg
1090*627f7eb2Smrg */
1091*627f7eb2Smrg Unsigned!T absUnsign(T)(T x)
1092*627f7eb2Smrg if (isIntegral!T)
1093*627f7eb2Smrg {
1094*627f7eb2Smrg static if (isSigned!T)
1095*627f7eb2Smrg {
1096*627f7eb2Smrg import std.conv : unsigned;
1097*627f7eb2Smrg /* This returns the correct result even when x = T.min
1098*627f7eb2Smrg * on two's complement machines because unsigned(T.min) = |T.min|
1099*627f7eb2Smrg * even though -T.min = T.min.
1100*627f7eb2Smrg */
1101*627f7eb2Smrg return unsigned((x < 0) ? cast(T)(0-x) : x);
1102*627f7eb2Smrg }
1103*627f7eb2Smrg else
1104*627f7eb2Smrg {
1105*627f7eb2Smrg return x;
1106*627f7eb2Smrg }
1107*627f7eb2Smrg }
1108*627f7eb2Smrg
1109*627f7eb2Smrg ///
1110*627f7eb2Smrg nothrow pure @system
1111*627f7eb2Smrg unittest
1112*627f7eb2Smrg {
1113*627f7eb2Smrg assert((-1).absUnsign == 1);
1114*627f7eb2Smrg assert(1.absUnsign == 1);
1115*627f7eb2Smrg }
1116*627f7eb2Smrg
1117*627f7eb2Smrg nothrow pure @system
1118*627f7eb2Smrg unittest
1119*627f7eb2Smrg {
1120*627f7eb2Smrg BigInt a, b;
1121*627f7eb2Smrg a = 1;
1122*627f7eb2Smrg b = 2;
1123*627f7eb2Smrg auto c = a + b;
1124*627f7eb2Smrg }
1125*627f7eb2Smrg
1126*627f7eb2Smrg nothrow pure @system
1127*627f7eb2Smrg unittest
1128*627f7eb2Smrg {
1129*627f7eb2Smrg long a;
1130*627f7eb2Smrg BigInt b;
1131*627f7eb2Smrg auto c = a + b;
1132*627f7eb2Smrg auto d = b + a;
1133*627f7eb2Smrg }
1134*627f7eb2Smrg
1135*627f7eb2Smrg nothrow pure @system
1136*627f7eb2Smrg unittest
1137*627f7eb2Smrg {
1138*627f7eb2Smrg BigInt x = 1, y = 2;
1139*627f7eb2Smrg assert(x < y);
1140*627f7eb2Smrg assert(x <= y);
1141*627f7eb2Smrg assert(y >= x);
1142*627f7eb2Smrg assert(y > x);
1143*627f7eb2Smrg assert(x != y);
1144*627f7eb2Smrg
1145*627f7eb2Smrg long r1 = x.toLong;
1146*627f7eb2Smrg assert(r1 == 1);
1147*627f7eb2Smrg
1148*627f7eb2Smrg BigInt r2 = 10 % x;
1149*627f7eb2Smrg assert(r2 == 0);
1150*627f7eb2Smrg
1151*627f7eb2Smrg BigInt r3 = 10 / y;
1152*627f7eb2Smrg assert(r3 == 5);
1153*627f7eb2Smrg
1154*627f7eb2Smrg BigInt[] arr = [BigInt(1)];
1155*627f7eb2Smrg auto incr = arr[0]++;
1156*627f7eb2Smrg assert(arr == [BigInt(2)]);
1157*627f7eb2Smrg assert(incr == BigInt(1));
1158*627f7eb2Smrg }
1159*627f7eb2Smrg
1160*627f7eb2Smrg @system unittest
1161*627f7eb2Smrg {
1162*627f7eb2Smrg // Radix conversion
1163*627f7eb2Smrg assert( toDecimalString(BigInt("-1_234_567_890_123_456_789"))
1164*627f7eb2Smrg == "-1234567890123456789");
1165*627f7eb2Smrg assert( toHex(BigInt("0x1234567890123456789")) == "123_45678901_23456789");
1166*627f7eb2Smrg assert( toHex(BigInt("0x00000000000000000000000000000000000A234567890123456789"))
1167*627f7eb2Smrg == "A23_45678901_23456789");
1168*627f7eb2Smrg assert( toHex(BigInt("0x000_00_000000_000_000_000000000000_000000_")) == "0");
1169*627f7eb2Smrg
1170*627f7eb2Smrg assert(BigInt(-0x12345678).toInt() == -0x12345678);
1171*627f7eb2Smrg assert(BigInt(-0x12345678).toLong() == -0x12345678);
1172*627f7eb2Smrg assert(BigInt(0x1234_5678_9ABC_5A5AL).ulongLength == 1);
1173*627f7eb2Smrg assert(BigInt(0x1234_5678_9ABC_5A5AL).toLong() == 0x1234_5678_9ABC_5A5AL);
1174*627f7eb2Smrg assert(BigInt(-0x1234_5678_9ABC_5A5AL).toLong() == -0x1234_5678_9ABC_5A5AL);
1175*627f7eb2Smrg assert(BigInt(0xF234_5678_9ABC_5A5AL).toLong() == long.max);
1176*627f7eb2Smrg assert(BigInt(-0x123456789ABCL).toInt() == -int.max);
1177*627f7eb2Smrg char[] s1 = "123".dup; // bug 8164
1178*627f7eb2Smrg assert(BigInt(s1) == 123);
1179*627f7eb2Smrg char[] s2 = "0xABC".dup;
1180*627f7eb2Smrg assert(BigInt(s2) == 2748);
1181*627f7eb2Smrg
1182*627f7eb2Smrg assert((BigInt(-2) + BigInt(1)) == BigInt(-1));
1183*627f7eb2Smrg BigInt a = ulong.max - 5;
1184*627f7eb2Smrg auto b = -long.max % a;
1185*627f7eb2Smrg assert( b == -long.max % (ulong.max - 5));
1186*627f7eb2Smrg b = long.max / a;
1187*627f7eb2Smrg assert( b == long.max /(ulong.max - 5));
1188*627f7eb2Smrg assert(BigInt(1) - 1 == 0);
1189*627f7eb2Smrg assert((-4) % BigInt(5) == -4); // bug 5928
1190*627f7eb2Smrg assert(BigInt(-4) % BigInt(5) == -4);
1191*627f7eb2Smrg assert(BigInt(2)/BigInt(-3) == BigInt(0)); // bug 8022
1192*627f7eb2Smrg assert(BigInt("-1") > long.min); // bug 9548
1193*627f7eb2Smrg
1194*627f7eb2Smrg assert(toDecimalString(BigInt("0000000000000000000000000000000000000000001234567"))
1195*627f7eb2Smrg == "1234567");
1196*627f7eb2Smrg }
1197*627f7eb2Smrg
1198*627f7eb2Smrg @system unittest // Minimum signed value bug tests.
1199*627f7eb2Smrg {
1200*627f7eb2Smrg assert(BigInt("-0x8000000000000000") == BigInt(long.min));
1201*627f7eb2Smrg assert(BigInt("-0x8000000000000000")+1 > BigInt(long.min));
1202*627f7eb2Smrg assert(BigInt("-0x80000000") == BigInt(int.min));
1203*627f7eb2Smrg assert(BigInt("-0x80000000")+1 > BigInt(int.min));
1204*627f7eb2Smrg assert(BigInt(long.min).toLong() == long.min); // lossy toLong bug for long.min
1205*627f7eb2Smrg assert(BigInt(int.min).toInt() == int.min); // lossy toInt bug for int.min
1206*627f7eb2Smrg assert(BigInt(long.min).ulongLength == 1);
1207*627f7eb2Smrg assert(BigInt(int.min).uintLength == 1); // cast/sign extend bug in opAssign
1208*627f7eb2Smrg BigInt a;
1209*627f7eb2Smrg a += int.min;
1210*627f7eb2Smrg assert(a == BigInt(int.min));
1211*627f7eb2Smrg a = int.min - BigInt(int.min);
1212*627f7eb2Smrg assert(a == 0);
1213*627f7eb2Smrg a = int.min;
1214*627f7eb2Smrg assert(a == BigInt(int.min));
1215*627f7eb2Smrg assert(int.min % (BigInt(int.min)-1) == int.min);
1216*627f7eb2Smrg assert((BigInt(int.min)-1)%int.min == -1);
1217*627f7eb2Smrg }
1218*627f7eb2Smrg
1219*627f7eb2Smrg @system unittest // Recursive division, bug 5568
1220*627f7eb2Smrg {
1221*627f7eb2Smrg enum Z = 4843;
1222*627f7eb2Smrg BigInt m = (BigInt(1) << (Z*8) ) - 1;
1223*627f7eb2Smrg m -= (BigInt(1) << (Z*6)) - 1;
1224*627f7eb2Smrg BigInt oldm = m;
1225*627f7eb2Smrg
1226*627f7eb2Smrg BigInt a = (BigInt(1) << (Z*4) )-1;
1227*627f7eb2Smrg BigInt b = m % a;
1228*627f7eb2Smrg m /= a;
1229*627f7eb2Smrg m *= a;
1230*627f7eb2Smrg assert( m + b == oldm);
1231*627f7eb2Smrg
1232*627f7eb2Smrg m = (BigInt(1) << (4846 + 4843) ) - 1;
1233*627f7eb2Smrg a = (BigInt(1) << 4846 ) - 1;
1234*627f7eb2Smrg b = (BigInt(1) << (4846*2 + 4843)) - 1;
1235*627f7eb2Smrg BigInt c = (BigInt(1) << (4846*2 + 4843*2)) - 1;
1236*627f7eb2Smrg BigInt w = c - b + a;
1237*627f7eb2Smrg assert(w % m == 0);
1238*627f7eb2Smrg
1239*627f7eb2Smrg // Bug 6819. ^^
1240*627f7eb2Smrg BigInt z1 = BigInt(10)^^64;
1241*627f7eb2Smrg BigInt w1 = BigInt(10)^^128;
1242*627f7eb2Smrg assert(z1^^2 == w1);
1243*627f7eb2Smrg BigInt z2 = BigInt(1)<<64;
1244*627f7eb2Smrg BigInt w2 = BigInt(1)<<128;
1245*627f7eb2Smrg assert(z2^^2 == w2);
1246*627f7eb2Smrg // Bug 7993
1247*627f7eb2Smrg BigInt n7793 = 10;
1248*627f7eb2Smrg assert( n7793 / 1 == 10);
1249*627f7eb2Smrg // Bug 7973
1250*627f7eb2Smrg auto a7973 = 10_000_000_000_000_000;
1251*627f7eb2Smrg const c7973 = 10_000_000_000_000_000;
1252*627f7eb2Smrg immutable i7973 = 10_000_000_000_000_000;
1253*627f7eb2Smrg BigInt v7973 = 2551700137;
1254*627f7eb2Smrg v7973 %= a7973;
1255*627f7eb2Smrg assert(v7973 == 2551700137);
1256*627f7eb2Smrg v7973 %= c7973;
1257*627f7eb2Smrg assert(v7973 == 2551700137);
1258*627f7eb2Smrg v7973 %= i7973;
1259*627f7eb2Smrg assert(v7973 == 2551700137);
1260*627f7eb2Smrg // 8165
1261*627f7eb2Smrg BigInt[2] a8165;
1262*627f7eb2Smrg a8165[0] = a8165[1] = 1;
1263*627f7eb2Smrg }
1264*627f7eb2Smrg
1265*627f7eb2Smrg @system unittest
1266*627f7eb2Smrg {
1267*627f7eb2Smrg import std.array;
1268*627f7eb2Smrg import std.format;
1269*627f7eb2Smrg
1270*627f7eb2Smrg immutable string[][] table = [
1271*627f7eb2Smrg /* fmt, +10 -10 */
1272*627f7eb2Smrg ["%d", "10", "-10"],
1273*627f7eb2Smrg ["%+d", "+10", "-10"],
1274*627f7eb2Smrg ["%-d", "10", "-10"],
1275*627f7eb2Smrg ["%+-d", "+10", "-10"],
1276*627f7eb2Smrg
1277*627f7eb2Smrg ["%4d", " 10", " -10"],
1278*627f7eb2Smrg ["%+4d", " +10", " -10"],
1279*627f7eb2Smrg ["%-4d", "10 ", "-10 "],
1280*627f7eb2Smrg ["%+-4d", "+10 ", "-10 "],
1281*627f7eb2Smrg
1282*627f7eb2Smrg ["%04d", "0010", "-010"],
1283*627f7eb2Smrg ["%+04d", "+010", "-010"],
1284*627f7eb2Smrg ["%-04d", "10 ", "-10 "],
1285*627f7eb2Smrg ["%+-04d", "+10 ", "-10 "],
1286*627f7eb2Smrg
1287*627f7eb2Smrg ["% 04d", " 010", "-010"],
1288*627f7eb2Smrg ["%+ 04d", "+010", "-010"],
1289*627f7eb2Smrg ["%- 04d", " 10 ", "-10 "],
1290*627f7eb2Smrg ["%+- 04d", "+10 ", "-10 "],
1291*627f7eb2Smrg ];
1292*627f7eb2Smrg
1293*627f7eb2Smrg auto w1 = appender!(char[])();
1294*627f7eb2Smrg auto w2 = appender!(char[])();
1295*627f7eb2Smrg
foreach(entry;table)1296*627f7eb2Smrg foreach (entry; table)
1297*627f7eb2Smrg {
1298*627f7eb2Smrg immutable fmt = entry[0];
1299*627f7eb2Smrg
1300*627f7eb2Smrg formattedWrite(w1, fmt, BigInt(10));
1301*627f7eb2Smrg formattedWrite(w2, fmt, 10);
1302*627f7eb2Smrg assert(w1.data == w2.data);
1303*627f7eb2Smrg assert(w1.data == entry[1]);
1304*627f7eb2Smrg w1.clear();
1305*627f7eb2Smrg w2.clear();
1306*627f7eb2Smrg
1307*627f7eb2Smrg formattedWrite(w1, fmt, BigInt(-10));
1308*627f7eb2Smrg formattedWrite(w2, fmt, -10);
1309*627f7eb2Smrg assert(w1.data == w2.data);
1310*627f7eb2Smrg assert(w1.data == entry[2]);
1311*627f7eb2Smrg w1.clear();
1312*627f7eb2Smrg w2.clear();
1313*627f7eb2Smrg }
1314*627f7eb2Smrg }
1315*627f7eb2Smrg
1316*627f7eb2Smrg @system unittest
1317*627f7eb2Smrg {
1318*627f7eb2Smrg import std.array;
1319*627f7eb2Smrg import std.format;
1320*627f7eb2Smrg
1321*627f7eb2Smrg immutable string[][] table = [
1322*627f7eb2Smrg /* fmt, +10 -10 */
1323*627f7eb2Smrg ["%x", "a", "-a"],
1324*627f7eb2Smrg ["%+x", "a", "-a"],
1325*627f7eb2Smrg ["%-x", "a", "-a"],
1326*627f7eb2Smrg ["%+-x", "a", "-a"],
1327*627f7eb2Smrg
1328*627f7eb2Smrg ["%4x", " a", " -a"],
1329*627f7eb2Smrg ["%+4x", " a", " -a"],
1330*627f7eb2Smrg ["%-4x", "a ", "-a "],
1331*627f7eb2Smrg ["%+-4x", "a ", "-a "],
1332*627f7eb2Smrg
1333*627f7eb2Smrg ["%04x", "000a", "-00a"],
1334*627f7eb2Smrg ["%+04x", "000a", "-00a"],
1335*627f7eb2Smrg ["%-04x", "a ", "-a "],
1336*627f7eb2Smrg ["%+-04x", "a ", "-a "],
1337*627f7eb2Smrg
1338*627f7eb2Smrg ["% 04x", "000a", "-00a"],
1339*627f7eb2Smrg ["%+ 04x", "000a", "-00a"],
1340*627f7eb2Smrg ["%- 04x", "a ", "-a "],
1341*627f7eb2Smrg ["%+- 04x", "a ", "-a "],
1342*627f7eb2Smrg ];
1343*627f7eb2Smrg
1344*627f7eb2Smrg auto w1 = appender!(char[])();
1345*627f7eb2Smrg auto w2 = appender!(char[])();
1346*627f7eb2Smrg
foreach(entry;table)1347*627f7eb2Smrg foreach (entry; table)
1348*627f7eb2Smrg {
1349*627f7eb2Smrg immutable fmt = entry[0];
1350*627f7eb2Smrg
1351*627f7eb2Smrg formattedWrite(w1, fmt, BigInt(10));
1352*627f7eb2Smrg formattedWrite(w2, fmt, 10);
1353*627f7eb2Smrg assert(w1.data == w2.data); // Equal only positive BigInt
1354*627f7eb2Smrg assert(w1.data == entry[1]);
1355*627f7eb2Smrg w1.clear();
1356*627f7eb2Smrg w2.clear();
1357*627f7eb2Smrg
1358*627f7eb2Smrg formattedWrite(w1, fmt, BigInt(-10));
1359*627f7eb2Smrg //formattedWrite(w2, fmt, -10);
1360*627f7eb2Smrg //assert(w1.data == w2.data);
1361*627f7eb2Smrg assert(w1.data == entry[2]);
1362*627f7eb2Smrg w1.clear();
1363*627f7eb2Smrg //w2.clear();
1364*627f7eb2Smrg }
1365*627f7eb2Smrg }
1366*627f7eb2Smrg
1367*627f7eb2Smrg @system unittest
1368*627f7eb2Smrg {
1369*627f7eb2Smrg import std.array;
1370*627f7eb2Smrg import std.format;
1371*627f7eb2Smrg
1372*627f7eb2Smrg immutable string[][] table = [
1373*627f7eb2Smrg /* fmt, +10 -10 */
1374*627f7eb2Smrg ["%X", "A", "-A"],
1375*627f7eb2Smrg ["%+X", "A", "-A"],
1376*627f7eb2Smrg ["%-X", "A", "-A"],
1377*627f7eb2Smrg ["%+-X", "A", "-A"],
1378*627f7eb2Smrg
1379*627f7eb2Smrg ["%4X", " A", " -A"],
1380*627f7eb2Smrg ["%+4X", " A", " -A"],
1381*627f7eb2Smrg ["%-4X", "A ", "-A "],
1382*627f7eb2Smrg ["%+-4X", "A ", "-A "],
1383*627f7eb2Smrg
1384*627f7eb2Smrg ["%04X", "000A", "-00A"],
1385*627f7eb2Smrg ["%+04X", "000A", "-00A"],
1386*627f7eb2Smrg ["%-04X", "A ", "-A "],
1387*627f7eb2Smrg ["%+-04X", "A ", "-A "],
1388*627f7eb2Smrg
1389*627f7eb2Smrg ["% 04X", "000A", "-00A"],
1390*627f7eb2Smrg ["%+ 04X", "000A", "-00A"],
1391*627f7eb2Smrg ["%- 04X", "A ", "-A "],
1392*627f7eb2Smrg ["%+- 04X", "A ", "-A "],
1393*627f7eb2Smrg ];
1394*627f7eb2Smrg
1395*627f7eb2Smrg auto w1 = appender!(char[])();
1396*627f7eb2Smrg auto w2 = appender!(char[])();
1397*627f7eb2Smrg
foreach(entry;table)1398*627f7eb2Smrg foreach (entry; table)
1399*627f7eb2Smrg {
1400*627f7eb2Smrg immutable fmt = entry[0];
1401*627f7eb2Smrg
1402*627f7eb2Smrg formattedWrite(w1, fmt, BigInt(10));
1403*627f7eb2Smrg formattedWrite(w2, fmt, 10);
1404*627f7eb2Smrg assert(w1.data == w2.data); // Equal only positive BigInt
1405*627f7eb2Smrg assert(w1.data == entry[1]);
1406*627f7eb2Smrg w1.clear();
1407*627f7eb2Smrg w2.clear();
1408*627f7eb2Smrg
1409*627f7eb2Smrg formattedWrite(w1, fmt, BigInt(-10));
1410*627f7eb2Smrg //formattedWrite(w2, fmt, -10);
1411*627f7eb2Smrg //assert(w1.data == w2.data);
1412*627f7eb2Smrg assert(w1.data == entry[2]);
1413*627f7eb2Smrg w1.clear();
1414*627f7eb2Smrg //w2.clear();
1415*627f7eb2Smrg }
1416*627f7eb2Smrg }
1417*627f7eb2Smrg
1418*627f7eb2Smrg // 6448
1419*627f7eb2Smrg @system unittest
1420*627f7eb2Smrg {
1421*627f7eb2Smrg import std.array;
1422*627f7eb2Smrg import std.format;
1423*627f7eb2Smrg
1424*627f7eb2Smrg auto w1 = appender!string();
1425*627f7eb2Smrg auto w2 = appender!string();
1426*627f7eb2Smrg
1427*627f7eb2Smrg int x = 100;
1428*627f7eb2Smrg formattedWrite(w1, "%010d", x);
1429*627f7eb2Smrg BigInt bx = x;
1430*627f7eb2Smrg formattedWrite(w2, "%010d", bx);
1431*627f7eb2Smrg assert(w1.data == w2.data);
1432*627f7eb2Smrg //8011
1433*627f7eb2Smrg BigInt y = -3;
1434*627f7eb2Smrg ++y;
1435*627f7eb2Smrg assert(y.toLong() == -2);
1436*627f7eb2Smrg y = 1;
1437*627f7eb2Smrg --y;
1438*627f7eb2Smrg assert(y.toLong() == 0);
1439*627f7eb2Smrg --y;
1440*627f7eb2Smrg assert(y.toLong() == -1);
1441*627f7eb2Smrg --y;
1442*627f7eb2Smrg assert(y.toLong() == -2);
1443*627f7eb2Smrg }
1444*627f7eb2Smrg
1445*627f7eb2Smrg @safe unittest
1446*627f7eb2Smrg {
1447*627f7eb2Smrg import std.math : abs;
1448*627f7eb2Smrg auto r = abs(BigInt(-1000)); // 6486
1449*627f7eb2Smrg assert(r == 1000);
1450*627f7eb2Smrg
1451*627f7eb2Smrg auto r2 = abs(const(BigInt)(-500)); // 11188
1452*627f7eb2Smrg assert(r2 == 500);
1453*627f7eb2Smrg auto r3 = abs(immutable(BigInt)(-733)); // 11188
1454*627f7eb2Smrg assert(r3 == 733);
1455*627f7eb2Smrg
1456*627f7eb2Smrg // opCast!bool
1457*627f7eb2Smrg BigInt one = 1, zero;
1458*627f7eb2Smrg assert(one && !zero);
1459*627f7eb2Smrg }
1460*627f7eb2Smrg
1461*627f7eb2Smrg @system unittest // 6850
1462*627f7eb2Smrg {
pureTest()1463*627f7eb2Smrg pure long pureTest() {
1464*627f7eb2Smrg BigInt a = 1;
1465*627f7eb2Smrg BigInt b = 1336;
1466*627f7eb2Smrg a += b;
1467*627f7eb2Smrg return a.toLong();
1468*627f7eb2Smrg }
1469*627f7eb2Smrg
1470*627f7eb2Smrg assert(pureTest() == 1337);
1471*627f7eb2Smrg }
1472*627f7eb2Smrg
1473*627f7eb2Smrg @system unittest // 8435 & 10118
1474*627f7eb2Smrg {
1475*627f7eb2Smrg auto i = BigInt(100);
1476*627f7eb2Smrg auto j = BigInt(100);
1477*627f7eb2Smrg
1478*627f7eb2Smrg // Two separate BigInt instances representing same value should have same
1479*627f7eb2Smrg // hash.
1480*627f7eb2Smrg assert(typeid(i).getHash(&i) == typeid(j).getHash(&j));
1481*627f7eb2Smrg assert(typeid(i).compare(&i, &j) == 0);
1482*627f7eb2Smrg
1483*627f7eb2Smrg // BigInt AA keys should behave consistently.
1484*627f7eb2Smrg int[BigInt] aa;
1485*627f7eb2Smrg aa[BigInt(123)] = 123;
1486*627f7eb2Smrg assert(BigInt(123) in aa);
1487*627f7eb2Smrg
1488*627f7eb2Smrg aa[BigInt(123)] = 321;
1489*627f7eb2Smrg assert(aa[BigInt(123)] == 321);
1490*627f7eb2Smrg
1491*627f7eb2Smrg auto keys = aa.byKey;
1492*627f7eb2Smrg assert(keys.front == BigInt(123));
1493*627f7eb2Smrg keys.popFront();
1494*627f7eb2Smrg assert(keys.empty);
1495*627f7eb2Smrg }
1496*627f7eb2Smrg
1497*627f7eb2Smrg @system unittest // 11148
1498*627f7eb2Smrg {
foo(BigInt)1499*627f7eb2Smrg void foo(BigInt) {}
1500*627f7eb2Smrg const BigInt cbi = 3;
1501*627f7eb2Smrg immutable BigInt ibi = 3;
1502*627f7eb2Smrg
1503*627f7eb2Smrg assert(__traits(compiles, foo(cbi)));
1504*627f7eb2Smrg assert(__traits(compiles, foo(ibi)));
1505*627f7eb2Smrg
1506*627f7eb2Smrg import std.conv : to;
1507*627f7eb2Smrg import std.meta : AliasSeq;
1508*627f7eb2Smrg
1509*627f7eb2Smrg foreach (T1; AliasSeq!(BigInt, const(BigInt), immutable(BigInt)))
1510*627f7eb2Smrg {
1511*627f7eb2Smrg foreach (T2; AliasSeq!(BigInt, const(BigInt), immutable(BigInt)))
1512*627f7eb2Smrg {
1513*627f7eb2Smrg T1 t1 = 2;
1514*627f7eb2Smrg T2 t2 = t1;
1515*627f7eb2Smrg
1516*627f7eb2Smrg T2 t2_1 = to!T2(t1);
1517*627f7eb2Smrg T2 t2_2 = cast(T2) t1;
1518*627f7eb2Smrg
1519*627f7eb2Smrg assert(t2 == t1);
1520*627f7eb2Smrg assert(t2 == 2);
1521*627f7eb2Smrg
1522*627f7eb2Smrg assert(t2_1 == t1);
1523*627f7eb2Smrg assert(t2_1 == 2);
1524*627f7eb2Smrg
1525*627f7eb2Smrg assert(t2_2 == t1);
1526*627f7eb2Smrg assert(t2_2 == 2);
1527*627f7eb2Smrg }
1528*627f7eb2Smrg }
1529*627f7eb2Smrg
1530*627f7eb2Smrg BigInt n = 2;
1531*627f7eb2Smrg n *= 2;
1532*627f7eb2Smrg }
1533*627f7eb2Smrg
1534*627f7eb2Smrg @safe unittest // 8167
1535*627f7eb2Smrg {
1536*627f7eb2Smrg BigInt a = BigInt(3);
1537*627f7eb2Smrg BigInt b = BigInt(a);
1538*627f7eb2Smrg }
1539*627f7eb2Smrg
1540*627f7eb2Smrg @safe unittest // 9061
1541*627f7eb2Smrg {
1542*627f7eb2Smrg long l1 = 0x12345678_90ABCDEF;
1543*627f7eb2Smrg long l2 = 0xFEDCBA09_87654321;
1544*627f7eb2Smrg long l3 = l1 | l2;
1545*627f7eb2Smrg long l4 = l1 & l2;
1546*627f7eb2Smrg long l5 = l1 ^ l2;
1547*627f7eb2Smrg
1548*627f7eb2Smrg BigInt b1 = l1;
1549*627f7eb2Smrg BigInt b2 = l2;
1550*627f7eb2Smrg BigInt b3 = b1 | b2;
1551*627f7eb2Smrg BigInt b4 = b1 & b2;
1552*627f7eb2Smrg BigInt b5 = b1 ^ b2;
1553*627f7eb2Smrg
1554*627f7eb2Smrg assert(l3 == b3);
1555*627f7eb2Smrg assert(l4 == b4);
1556*627f7eb2Smrg assert(l5 == b5);
1557*627f7eb2Smrg }
1558*627f7eb2Smrg
1559*627f7eb2Smrg @system unittest // 11600
1560*627f7eb2Smrg {
1561*627f7eb2Smrg import std.conv;
1562*627f7eb2Smrg import std.exception : assertThrown;
1563*627f7eb2Smrg
1564*627f7eb2Smrg // Original bug report
1565*627f7eb2Smrg assertThrown!ConvException(to!BigInt("avadakedavra"));
1566*627f7eb2Smrg
1567*627f7eb2Smrg // Digit string lookalikes that are actually invalid
1568*627f7eb2Smrg assertThrown!ConvException(to!BigInt("0123hellothere"));
1569*627f7eb2Smrg assertThrown!ConvException(to!BigInt("-hihomarylowe"));
1570*627f7eb2Smrg assertThrown!ConvException(to!BigInt("__reallynow__"));
1571*627f7eb2Smrg assertThrown!ConvException(to!BigInt("-123four"));
1572*627f7eb2Smrg }
1573*627f7eb2Smrg
1574*627f7eb2Smrg @safe unittest // 11583
1575*627f7eb2Smrg {
1576*627f7eb2Smrg BigInt x = 0;
1577*627f7eb2Smrg assert((x > 0) == false);
1578*627f7eb2Smrg }
1579*627f7eb2Smrg
1580*627f7eb2Smrg @system unittest // 13391
1581*627f7eb2Smrg {
1582*627f7eb2Smrg BigInt x1 = "123456789";
1583*627f7eb2Smrg BigInt x2 = "123456789123456789";
1584*627f7eb2Smrg BigInt x3 = "123456789123456789123456789";
1585*627f7eb2Smrg
1586*627f7eb2Smrg import std.meta : AliasSeq;
1587*627f7eb2Smrg foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
1588*627f7eb2Smrg {
1589*627f7eb2Smrg assert((x1 * T.max) / T.max == x1);
1590*627f7eb2Smrg assert((x2 * T.max) / T.max == x2);
1591*627f7eb2Smrg assert((x3 * T.max) / T.max == x3);
1592*627f7eb2Smrg }
1593*627f7eb2Smrg
1594*627f7eb2Smrg assert(x1 / -123456789 == -1);
1595*627f7eb2Smrg assert(x1 / 123456789U == 1);
1596*627f7eb2Smrg assert(x1 / -123456789L == -1);
1597*627f7eb2Smrg assert(x1 / 123456789UL == 1);
1598*627f7eb2Smrg assert(x2 / -123456789123456789L == -1);
1599*627f7eb2Smrg assert(x2 / 123456789123456789UL == 1);
1600*627f7eb2Smrg
1601*627f7eb2Smrg assert(x1 / uint.max == 0);
1602*627f7eb2Smrg assert(x1 / ulong.max == 0);
1603*627f7eb2Smrg assert(x2 / ulong.max == 0);
1604*627f7eb2Smrg
1605*627f7eb2Smrg x1 /= 123456789UL;
1606*627f7eb2Smrg assert(x1 == 1);
1607*627f7eb2Smrg x2 /= 123456789123456789UL;
1608*627f7eb2Smrg assert(x2 == 1);
1609*627f7eb2Smrg }
1610*627f7eb2Smrg
1611*627f7eb2Smrg @system unittest // 13963
1612*627f7eb2Smrg {
1613*627f7eb2Smrg BigInt x = 1;
1614*627f7eb2Smrg import std.meta : AliasSeq;
1615*627f7eb2Smrg foreach (Int; AliasSeq!(byte, ubyte, short, ushort, int, uint))
1616*627f7eb2Smrg {
1617*627f7eb2Smrg assert(is(typeof(x % Int(1)) == int));
1618*627f7eb2Smrg }
1619*627f7eb2Smrg assert(is(typeof(x % 1L) == long));
1620*627f7eb2Smrg assert(is(typeof(x % 1UL) == BigInt));
1621*627f7eb2Smrg
1622*627f7eb2Smrg auto x1 = BigInt(8);
1623*627f7eb2Smrg auto x2 = -BigInt(long.min) + 1;
1624*627f7eb2Smrg
1625*627f7eb2Smrg // long
1626*627f7eb2Smrg assert(x1 % 2L == 0L);
1627*627f7eb2Smrg assert(-x1 % 2L == 0L);
1628*627f7eb2Smrg
1629*627f7eb2Smrg assert(x1 % 3L == 2L);
1630*627f7eb2Smrg assert(x1 % -3L == 2L);
1631*627f7eb2Smrg assert(-x1 % 3L == -2L);
1632*627f7eb2Smrg assert(-x1 % -3L == -2L);
1633*627f7eb2Smrg
1634*627f7eb2Smrg assert(x1 % 11L == 8L);
1635*627f7eb2Smrg assert(x1 % -11L == 8L);
1636*627f7eb2Smrg assert(-x1 % 11L == -8L);
1637*627f7eb2Smrg assert(-x1 % -11L == -8L);
1638*627f7eb2Smrg
1639*627f7eb2Smrg // ulong
1640*627f7eb2Smrg assert(x1 % 2UL == BigInt(0));
1641*627f7eb2Smrg assert(-x1 % 2UL == BigInt(0));
1642*627f7eb2Smrg
1643*627f7eb2Smrg assert(x1 % 3UL == BigInt(2));
1644*627f7eb2Smrg assert(-x1 % 3UL == -BigInt(2));
1645*627f7eb2Smrg
1646*627f7eb2Smrg assert(x1 % 11UL == BigInt(8));
1647*627f7eb2Smrg assert(-x1 % 11UL == -BigInt(8));
1648*627f7eb2Smrg
1649*627f7eb2Smrg assert(x2 % ulong.max == x2);
1650*627f7eb2Smrg assert(-x2 % ulong.max == -x2);
1651*627f7eb2Smrg }
1652*627f7eb2Smrg
1653*627f7eb2Smrg @system unittest // 14124
1654*627f7eb2Smrg {
1655*627f7eb2Smrg auto x = BigInt(-3);
1656*627f7eb2Smrg x %= 3;
1657*627f7eb2Smrg assert(!x.isNegative());
1658*627f7eb2Smrg assert(x.isZero());
1659*627f7eb2Smrg
1660*627f7eb2Smrg x = BigInt(-3);
1661*627f7eb2Smrg x %= cast(ushort) 3;
1662*627f7eb2Smrg assert(!x.isNegative());
1663*627f7eb2Smrg assert(x.isZero());
1664*627f7eb2Smrg
1665*627f7eb2Smrg x = BigInt(-3);
1666*627f7eb2Smrg x %= 3L;
1667*627f7eb2Smrg assert(!x.isNegative());
1668*627f7eb2Smrg assert(x.isZero());
1669*627f7eb2Smrg
1670*627f7eb2Smrg x = BigInt(3);
1671*627f7eb2Smrg x %= -3;
1672*627f7eb2Smrg assert(!x.isNegative());
1673*627f7eb2Smrg assert(x.isZero());
1674*627f7eb2Smrg }
1675*627f7eb2Smrg
1676*627f7eb2Smrg // issue 15678
1677*627f7eb2Smrg @system unittest
1678*627f7eb2Smrg {
1679*627f7eb2Smrg import std.exception : assertThrown;
1680*627f7eb2Smrg assertThrown!ConvException(BigInt(""));
1681*627f7eb2Smrg assertThrown!ConvException(BigInt("0x1234BARF"));
1682*627f7eb2Smrg assertThrown!ConvException(BigInt("1234PUKE"));
1683*627f7eb2Smrg }
1684*627f7eb2Smrg
1685*627f7eb2Smrg // Issue 6447
1686*627f7eb2Smrg @system unittest
1687*627f7eb2Smrg {
1688*627f7eb2Smrg import std.algorithm.comparison : equal;
1689*627f7eb2Smrg import std.range : iota;
1690*627f7eb2Smrg
1691*627f7eb2Smrg auto s = BigInt(1_000_000_000_000);
1692*627f7eb2Smrg auto e = BigInt(1_000_000_000_003);
1693*627f7eb2Smrg auto r = iota(s, e);
1694*627f7eb2Smrg assert(r.equal([
1695*627f7eb2Smrg BigInt(1_000_000_000_000),
1696*627f7eb2Smrg BigInt(1_000_000_000_001),
1697*627f7eb2Smrg BigInt(1_000_000_000_002)
1698*627f7eb2Smrg ]));
1699*627f7eb2Smrg }
1700*627f7eb2Smrg
1701*627f7eb2Smrg // Issue 17330
1702*627f7eb2Smrg @system unittest
1703*627f7eb2Smrg {
1704*627f7eb2Smrg auto b = immutable BigInt("123");
1705*627f7eb2Smrg }
1706