root/trunk/etc/bigint/bigint_int.d

Revision 37, 32.6 kB (checked in by brad, 7 years ago)

incorporated Stewart Gordon's patches for radix and bigint_int

Line 
1 module etc.bigint.bigint_int;
2 import etc.bigint.exception;
3 import etc.bigint.multiply;
4 import etc.bigint.radix;
5 private import std.c.stdlib;
6 private import std.math;
7 private import std.string;
8
9 /*
10
11 Copyright (c) 2004, Arcane Jill
12
13 All rights reserved. Intellectual Property Me Arse!
14
15 Redistribution and use in source and binary forms, with or without modification, are permitted
16 provided that the following conditions are met:
17
18    * Redistributions of source code must retain the above copyright notice, the phrase
19      "Intellectual Property Me Arse!", this list of conditions, and the following disclaimer.
20    * Redistributions in binary form must reproduce the above copyright notice, the phrase
21      "Intellectual Property Me Arse!", this list of conditions and the following disclaimer
22      in the documentation and/or other materials provided with the distribution.
23    * The name Arcane Jill may not be used to endorse or promote products derived from this
24      software without specific prior written permission.
25
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
27 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
28 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER,
29 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED, AND ON ANY
32 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
33 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 OF SUCH DAMAGE.
35
36 */
37
38 class Int
39 {
40     unittest
41     {
42         Int a,b,c,d;
43
44         //------------------------------------------
45         // Test comparisons
46         a = new Int(0xAAAAAAAA);
47         b = new Int(0xAAAAAAAA);
48         c = new Int(0xCCCCCCCC);
49         d = new Int("0x00000001AAAAAAAA");
50         assert(a == b);
51         assert(a < c);
52         assert(c > a);
53         assert(a < d);
54         assert(d > a);
55         d = new Int(-1);
56         assert(d < a);
57
58         //------------------------------------------
59         // Test add and subtract
60         a = b + c;
61         d = new Int("0x0000000177777776");
62         assert(a == d);
63         assert(a - b == c);
64         c = -d;
65         assert(c+d == 0);
66
67         //------------------------------------------
68         // Test multiply and divide for small values
69         a = new Int(0x11111111);
70         a = -a;
71         b = a * a;
72         c = new Int("0x0123456787654321");
73         assert(b == c);
74         b = b / a;
75         assert(b == a);
76         a = new Int(22);
77         assert(a / 7 == 3);
78         assert(a % 7 == 1);
79         assert(a / -7 == -3);
80         assert(a % -7 == 1);
81         a = -a;
82         assert(a / 7 == -3);
83         assert(a % 7 == -1);
84         assert(a / -7 == 3);
85         assert(a % -7 == -1);
86         a = -a;
87         b = new Int(7);
88         c = -b;
89         assert(divMod(a, b, d, Round.TOWARD_MINUS_INFINITY) == 3);
90         assert(d == 1);
91         assert(divMod(a, c, d, Round.TOWARD_MINUS_INFINITY) == -4);
92         assert(d == -6);
93         a = -a;
94         assert(divMod(a, b, d, Round.TOWARD_MINUS_INFINITY) == -4);
95         assert(d == 6);
96         assert(divMod(a, c, d, Round.TOWARD_MINUS_INFINITY) == 3);
97         assert(d == -1);
98
99         //------------------------------------------
100         // Test multiply and divide for large values
101         a = new Int("0x0111111111111111");
102         b = a * a;
103         c = new Int("0x000123456789ABCDEFEDCBA987654321");
104         assert(b == c);
105         b = b / a;
106         assert(b == a);
107
108         //------------------------------------------
109         // Test binary operations
110         a = new Int("0x1234567812345678");
111         uint n = a & 0xFFFFu;
112         assert(n == 0x5678);
113         b = a & new Int(0xFF00FF);
114         assert(b == new Int(0x340078));
115         c = a | 0xFFFF;
116         assert(c == new Int("0x123456781234FFFF"));
117         d = a ^ 0xFFFFFFFF;
118         assert (d == new Int("0x12345678EDCBA987"));
119         c = d & -1;
120         assert(c == d);
121         c = ~d;
122         assert((c ^ (-1)) == d);
123
124         //------------------------------------------
125         // Test shift left and shift right
126         a = new Int(0x12345678);
127         b = a << 40;
128         c = new Int("0x000000123456780000000000");
129         assert(b == c);
130         d = c << -40;
131         assert(d == a);
132         d = c >>> 40;
133         assert(d == a);
134         c = -c;
135         a = -a;
136         d = c << -40;
137         assert(d == a);
138         try
139         {
140             d = c >>> 40;
141         }
142         catch (IntException)
143         {
144             b = ZERO;
145         }
146         assert(b == 0);
147         d = c >>> 0;
148         assert(c == d);
149
150         //------------------------------------------
151         // Test the array-like functions
152
153         a = new Int("0xFEDCBA98_76543210_00000000_00000000_FEDCBA98_76543210");
154         assert(a[1] == 0xFEDCBA98);
155         assert(a[3000] == 0);
156         assert(a[0..2] == a[4..6]);
157         assert(a[100..115] == a[200..215]);
158         assert(a[0..4] == a[4..8]);
159
160         //------------------------------------------
161         // Test formatting
162
163         a = new Int(123);
164         assert(a.format(10, 0, 0, false, SignMode.NORMAL)           ==   "123");
165         assert(a.format(10, 0, 0, false, SignMode.MINUS_SPACE_PLUS) ==  "+123");
166         assert(a.format(10, 0, 0, true,  SignMode.NORMAL)           ==   "123");
167         assert(a.format(10, 0, 2, false, SignMode.NORMAL)           ==  "1_23");
168         assert(a.format(10, 5, 0, false, SignMode.NORMAL)           == "  123");
169         assert(a.format(10, 5, 0, false, SignMode.MINUS_SPACE_PLUS) == " +123");
170         assert(a.format(10, 5, 0, true,  SignMode.NORMAL)           == "00123");
171         assert(a.format(10, 5, 0, true,  SignMode.MINUS_SPACE_PLUS) == "+0123");
172         assert(a.format(10, 5, 2, false, SignMode.NORMAL)           == " 1_23");
173         a = -a;
174         assert(a.format(10, 5, 0, false, SignMode.NORMAL)           == " -123");
175         assert(a.format(10, 5, 0, true,  SignMode.NORMAL)           == "-0123");
176         assert(a.format(10, 5, 2, false, SignMode.NORMAL)           == "-1_23");
177
178         a = new Int("123456");
179         assert(a.toString() == "123456");
180         a = new Int("0x123456");
181         assert(a.toHexString() == "123456");
182
183         a = new Int("0");
184         assert (a.toString == "0");
185         assert (ZERO.toString == "0");
186         assert (a == ZERO);
187         assert (a == new Int(0));
188     }
189
190     invariant
191     {
192         if (d)
193         {
194             uint n = d.length;
195             assert(n >= 2);                 // array must be sufficiently large (2 uints)
196             int s = d[n-1];
197             assert((s == 0) || (s == -1));  // sign field may not contain rubbish
198             if (n>2)
199             {
200                 assert(d[n-2] != s);        // array must be minimal
201             }
202         }
203     }
204
205     public
206     {
207
208         // -------- Constants --------
209
210         enum Round { TOWARD_ZERO, TOWARD_INFINITY, TOWARD_MINUS_INFINITY }
211
212         static
213         {
214             Int ZERO, ONE, TWO, MINUS_ONE;
215         }
216
217         static this()
218         {
219             ZERO = new Int(0);
220             ONE = new Int(1);
221             TWO = new Int(2);
222             MINUS_ONE = new Int(-1);
223         }
224
225         // -------- Constructors --------
226
227         // Construct from an int
228         this(int n)
229         {
230             d.length = 2;
231             d[0] = n;
232             d[1] = n < 0 ? -1U : 0;
233         }
234
235         static Int opCall(int n) { return new Int(n); }
236
237         // Construct from a uint
238         this(uint n)
239         {
240             d.length = 2;
241             d[0] = n;
242         }
243
244         static Int opCall(uint n) { return new Int(n); }
245
246         // Construct from a long
247         this(long n)
248         {
249             d.length = 3;
250             *(cast(ulong*)d) = n;
251             d[2] = n < 0 ? -1U : 0;
252             minimize(this);
253         }
254
255         static Int opCall(long n) { return new Int(n); }
256
257         // Construct from a ulong
258         this(ulong n)
259         {
260             d.length = 3;
261             *(cast(ulong*)d) = n;
262             minimize(this);
263         }
264
265         static Int opCall(ulong n) { return new Int(n); }
266
267         // Construct from a float
268         this(float x)
269         {
270             this(cast(real) x);
271         }
272
273         static Int opCall(float x) { return new Int(x); }
274
275         // Construct from a double
276         this(double x)
277         {
278             this(cast(real) x);
279         }
280
281         static Int opCall(double x) { return new Int(x); }
282
283         // Construct from a real
284         this(real x)
285         {
286             uint i;
287             d.length = 4;
288             bool sign = (x < 0);
289             if (sign) x = -x;
290             while (x > 0)
291             {
292                 real xq = floor(x / 4294967296.0);
293                 real xr = x - (xq * 4294967296.0);
294                 d[i++] = cast(uint) xr;
295                 if (i == d.length-1) d.length = d.length << 1;
296                 x = xq;
297             }
298             if (sign)
299             {
300                 bigintLLNeg(d, d, d.length);
301             }
302             minimize(this);
303         }
304
305         static Int opCall(real x) { return new Int(x); }
306
307         // Construct from a string.
308         this(char[] s)
309         {
310             this(s, uint.max);
311         }
312
313         static Int opCall(char[] s) { return new Int(s); }
314
315         this(char[] s, uint radix)
316         {
317             bool isNegative = false;
318             if (s.length > 1)
319             {
320                 if (s[0] == '+')
321                 {
322                     s = s[1..s.length];
323                 }
324                 else if (s[0] == '-')
325                 {
326                     s = s[1..s.length];
327                     isNegative = true;
328                 }
329             }
330             d = bigintFromString(s, radix);
331
332             uint len = bigintLLMinimize(d, d.length);
333             if (len == 0)
334             {
335                 d.length = 2;
336                 d[] = isNegative ? -1U : 0;
337             }
338             else
339             {
340                 d.length = len+1;
341             }
342             if (isNegative)
343             {
344                 bigintLLNeg(d, d, d.length);
345                 minimize(this);
346             }
347         }
348
349         static Int opCall(char[] s, uint radix) { return new Int(s, radix); }
350
351         // Construct from a uint array. This copies by value, not by reference;
352         this(uint[] x, bool isNegative)
353         {
354             d.length = x.length + 1;
355             d[0..x.length] = x[0..x.length];
356             d[x.length] = isNegative ? -1U : 0;
357             minimize(this);
358         }
359
360         static Int opCall(uint[] x, bool isNegative) { return new Int(x, isNegative); }
361
362         // -------- Conversions --------
363
364         override
365         {
366             char[] toString()
367             out(s)
368             {
369                 assert(this == new Int(s));
370             }
371             body
372             {
373                 return format(10, 0, 0, false, SignMode.NORMAL);
374             }
375         }
376
377         char[] toHexString()
378         out(s)
379         {
380             assert(this == new Int(s,16));
381         }
382         body
383         {
384             return format(16, 0, 8, false, SignMode.NORMAL);
385         }
386
387         int toInt()
388         {
389             if (isInt()) return d[0];
390             return (sign) ? int.min : int.max;
391         }
392
393         uint toUint()
394         {
395             if (isUint()) return d[0];
396             return uint.max;
397         }
398
399         long toLong()
400         {
401             if (isLong())
402             {
403                 ulong lo = d[0];
404                 ulong hi = d[1];
405                 return (hi << 32) | lo;
406             }
407             return (sign) ? long.min : long.max;
408         }
409
410         ulong toUlong()
411         {
412             if (isUlong())
413             {
414                 ulong lo = d[0];
415                 ulong hi = d[1];
416                 return (hi << 32) | lo;
417             }
418             return ulong.max;
419         }
420
421         float toFloat()
422         {
423             return toReal();
424         }
425
426         double toDouble()
427         {
428             return toReal();
429         }
430
431         real toReal()
432         {
433             if (sign) return -((-this).toReal());
434             real r = 0;
435             for (uint i=0; i<end; ++i)
436             {
437                 r *= 4294967296.0;
438                 r += d[i];
439             }
440             return r;
441         }
442
443         // -------- Tests --------
444
445         bool isInt()
446         {
447             if (d.length > 2) return false;
448             if (sign)
449             {
450                 return (d[0] >= 0x80000000);
451             }
452             else
453             {
454                 return (d[0] < 0x80000000);
455             }
456         }
457
458         bool isUint()
459         {
460             if (sign) return false;
461             return (d.length == 2);
462         }
463
464         bool isLong()
465         {
466             if (d.length > 3) return false;
467             if (sign)
468             {
469                 return (d[d.length-2] >= 0x80000000);
470             }
471             else
472             {
473                 return (d[d.length-2] < 0x80000000);
474             }
475         }
476
477         bool isUlong()
478         {
479             if (sign) return false;
480             return (d.length <= 3);
481         }
482
483         override
484         {
485             int /*I wish this was bool*/ opEquals(Object obj)
486             {
487                 Int y = cast(Int) obj;
488                 assert(y);
489                 return d == y.d;
490             }
491         }
492
493         int /*I wish this was bool*/ opEquals(int n)
494         {
495             return isInt() ? (n == d[0]) : 0;
496         }
497
498         int /*I wish this was bool*/ opEquals(uint n)
499         {
500             return isUint() ? (n == d[0]) : 0;
501         }
502
503         override
504         {
505             int opCmp(Object obj)
506             {
507                 Int y = cast(Int) obj;
508                 assert(y);
509
510                 Int x = this;
511                 if (x === y) return 0;
512                 int xSign = x.sign;
513                 int ySign = y.sign;
514                 if (xSign < ySign) return -1;
515                 if (xSign > ySign) return 1;
516
517                 int r;
518                 int n = x.d.length;
519                 if (x.d.length > y.d.length)
520                 {
521                     n = y.d.length;
522                     r = bigintLLCmpAll(&x.d[y.d.length], y.sign, x.d.length - y.d.length);
523                     if (r < 0) return -1;
524                     if (r > 0) return 1;
525                 }
526                 if (x.d.length < y.d.length)
527                 {
528                     r = bigintLLCmpAll(x.sign, &y.d[x.d.length], y.d.length - x.d.length);
529                     if (r < 0) return -1;
530                     if (r > 0) return 1;
531                 }
532                 r = bigintLLCmp(x.d, y.d, n);
533                 if (r < 0) return -1;
534                 if (r > 0) return 1;
535                 return 0;
536             }
537         }
538
539         int opCmp(int y)
540         {
541             if (isInt())
542             {
543                 int x = d[0];
544                 if (x == y) return 0;
545                 return (x < y) ? -1 : 1;
546             }
547             else
548             {
549                 return opCmp(new Int(y));
550             }
551         }
552
553         int opCmp(uint y)
554         {
555             if (isUint())
556             {
557                 uint x = d[0];
558                 if (x == y) return 0;
559                 return (x < y) ? -1 : 1;
560             }
561             else
562             {
563                 return opCmp(new Int(y));
564             }
565         }
566
567         // -------- Addition --------
568
569         Int opAdd(Int y)
570         {
571             if (y.equalsZero()) return this;
572
573             Int x = this;
574             if (x.d.length < y.d.length)
575             {
576                 x = y;
577                 y = this;
578             }
579             Int r = new Int;
580             r.d.length = x.d.length + 1;
581             uint carry = bigintLLAdd(r.d, x.d, y.d, y.d.length);
582             if (x.d.length > y.d.length)
583             {
584                 carry = bigintLLIncV(&r.d[y.d.length], &x.d[y.d.length], y.sign, carry, x.d.length-y.d.length);
585             }
586             r.d[x.d.length] = x.d[x.d.length-1] + y.d[y.d.length-1] + carry;
587             return minimize(r);
588         }
589
590         Int opAdd(int y)
591         {
592             if (y == 0) return this;
593
594             Int x = this;
595             Int r = new Int;
596             r.d.length = x.d.length + 1;
597
598             ulong t = x.d[0] + cast(ulong) cast(uint) y;
599             r.d[0] = t;
600             uint carry = t > 0xFFFFFFFF;
601
602             carry = bigintLLIncV(&r.d[1], &x.d[1], cast(uint) (y<0?-1:0), carry, x.d.length-1);
603             r.d[x.d.length] = x.d[x.d.length-1] + (y<0?-1:0) + carry;
604             return minimize(r);
605         }
606
607         Int opAdd(uint y)
608         {
609             if (y == 0) return this;
610             uint carry;
611
612             Int x = this;
613             Int r = new Int;
614             r.d.length = x.d.length + 1;
615             carry = bigintLLInc(r.d, x.d, y, x.d.length);
616             r.d[x.d.length] = x.d[x.d.length-1] + carry;
617             return minimize(r);
618         }
619
620         // -------- Subtraction --------
621
622         Int opSub(Int y)
623         {
624             if (y.equalsZero()) return this;
625             bool neg = false;
626
627             Int x = this;
628             if (x.d.length < y.d.length)
629             {
630                 x = y;
631                 y = this;
632                 neg = true;
633             }
634             Int r = new Int;
635             r.d.length = x.d.length + 1;
636
637             uint carry = bigintLLSub(r.d, x.d, y.d, y.d.length);
638             if (x.d.length > y.d.length)
639             {
640                 carry = bigintLLDecV(&r.d[y.d.length], &x.d[y.d.length], y.sign, carry, x.d.length-y.d.length);
641             }
642             r.d[r.d.length-1] = x.d[x.d.length-1] - y.d[y.d.length-1] - carry;
643             minimize(r);
644             return neg ? -r : r;
645         }
646
647         Int opSub(int y)
648         {
649             if (y == 0) return this;
650
651             Int x = this;
652             Int r = new Int;
653             r.d.length = x.d.length + 1;
654
655             ulong t = x.d[0] - cast(ulong) cast(uint) y;
656             r.d[0] = t;
657             uint carry = t > 0xFFFFFFFF;
658
659             carry = bigintLLDecV(&r.d[1], &x.d[1], cast(uint) (y<0?-1:0), carry, x.d.length-1);
660             r.d[x.d.length] = x.d[x.d.length-1] - (y<0?-1:0) - carry;
661             return minimize(r);
662         }
663
664         Int opSub(uint y)
665         {
666             if (y == 0) return this;
667             uint carry;
668
669             Int x = this;
670             Int r = new Int;
671             r.d.length = x.d.length + 1;
672
673             carry = bigintLLDec(r.d, x.d, y, x.d.length);
674             r.d[x.d.length] = x.d[x.d.length-1] - carry;
675             return minimize(r);
676         }
677
678         Int opSub_r(uint n)
679         {
680             return new Int(n) - this;
681         }
682
683         Int opSub_r(int n)
684         {
685             return new Int(n) - this;
686         }
687
688         // -------- Negation --------
689
690         Int opNeg()
691         {
692             if (equalsZero) return this;
693             Int r = new Int;
694             r.d.length = d.length + 1;
695             uint carry = bigintLLNeg(r.d, d, d.length);
696             r.d[r.d.length-1] = 0 - d[d.length-1] - carry;
697             return minimize(r);
698         }
699
700         // -------- Multiplication --------
701
702         Int opMul(Int y)
703         {
704             Int x = this;
705             if (x.sign)
706             {
707                 if (y.sign) return -x * -y;
708                 else return -(-x * y);
709             }
710             if (y.sign)
711             {
712                 return -(x * -y);
713             }
714             if (x.d.length < y.d.length)
715             {
716                 x = y;
717                 y = this;
718             }
719             if (y.isUint())
720             {
721                 return x * y.d[0];
722             }
723
724             Int r = new Int;
725             r.d.length = x.d.length + y.d.length - 1;
726
727             bigintMul(r.d, r.d.length-1, x.d, x.d.length-1, y.d, y.d.length-1);
728             return minimize(r);
729         }
730
731         Int opMul(int y)
732         {
733             return (y < 0) ? -opMul(cast(uint)-y) : opMul(cast(uint)y);
734         }
735
736         Int opMul(uint y)
737         {
738             switch (y)
739             {
740                 case  0: return  ZERO;
741                 case  1: return  this;
742                 case  2: return  this        + this;
743                 case  3: return  this        + this + this;
744                 case  4: return  this << 2u;
745                 case  5: return (this << 2u) + this;
746                 case  6: return (this << 2u) + this + this;
747                 case  7: return (this << 3u) - this;
748                 case  8: return  this << 3u;
749                 case  9: return (this << 3u) + this;
750                 case 10: return (this << 3u) + this + this;
751                 default: break;
752             }
753             Int r = new Int;
754             r.d.length = d.length + 1;
755
756             r.d[d.length-1] = bigintLLMul(r.d, d, y, d.length-1);
757             return minimize(r);
758         }
759
760         // -------- Division --------
761
762         Int opDiv(Int n)
763         {
764             Int r;
765             return divMod(this, n, r, Round.TOWARD_ZERO);
766         }
767
768         Int opDiv(int n)
769         {
770             Int r;
771             return divMod(this, new Int(n), r, Round.TOWARD_ZERO);
772         }
773
774         Int opDiv(uint n)
775         {
776             Int r;
777             return divMod(this, new Int(n), r, Round.TOWARD_ZERO);
778         }
779
780         Int opDiv_r(int n)
781         {
782             return new Int(n) / this;
783         }
784
785         Int opDiv_r(uint n)
786         {
787             return new Int(n) / this;
788         }
789
790         // -------- Remainder from division --------
791
792         Int opMod(Int n)
793         {
794             Int r;
795             divMod(this, n, r, Round.TOWARD_ZERO);
796             return r;
797         }
798
799         Int opMod(int n)
800         {
801             Int r;
802             divMod(this, new Int(n), r, Round.TOWARD_ZERO);
803             return r;
804         }
805
806         Int opMod(uint n)
807         {
808             Int r;
809             divMod(this, new Int(n), r, Round.TOWARD_ZERO);
810             return r;
811         }
812
813         Int opMod_r(int n)
814         {
815             return new Int(n) % this;
816         }
817
818         Int opMod_r(uint n)
819         {
820             return new Int(n) % this;
821         }
822
823         // -------- Binary And  --------
824
825         Int opAnd(Int y)
826         {
827             Int r = new Int;
828             Int x = this;
829             int s = x.sign & y.sign;
830             uint minlen = x.d.length - 1;
831             uint maxlen = minlen;
832             if (x.d.length > y.d.length)
833             {
834                 minlen = y.d.length - 1;
835                 if (y.sign)
836                 {
837                     r.d.length = maxlen+1;
838                     r.d[minlen..maxlen] = x.d[minlen..maxlen];
839                 }
840                 else
841                 {
842                     r.d.length = minlen+1;
843                 }
844             }
845             else if (x.d.length < y.d.length)
846             {
847                 maxlen = y.d.length - 1;
848                 if (x.sign)
849                 {
850                     r.d.length = maxlen+1;
851                     r.d[minlen..maxlen] = y.d[minlen..maxlen];
852                 }
853                 else
854                 {
855                     r.d.length = minlen+1;
856                 }
857             }
858             else
859             {
860                 r.d.length = minlen+1;
861             }
862             bigintLLAnd(r.d, x.d, y.d, minlen);
863             r.d[r.d.length-1] = s;
864             return minimize(r);
865         }
866
867         Int opAnd(int y)
868         {
869             if (y < 0)
870             {
871                 uint n = d[0] & y;
872                 if (n == d[0]) return this;
873                 Int r = new Int(this);
874                 r.d[0] = n;
875                 return r;
876             }
877             else
878             {
879                 return new Int(y & d[0]);
880             }
881         }
882
883         uint opAnd(uint y)
884         {
885             return d[0] & y;
886         }
887
888         // -------- Binary Or --------
889
890         Int opOr(Int y)
891         {
892             Int r = new Int;
893             Int x = this;
894             int s = x.sign | y.sign;
895             uint minlen = x.d.length - 1;
896             uint maxlen = minlen;
897             if (x.d.length > y.d.length)
898             {
899                 minlen = y.d.length - 1;
900                 if (y.sign)
901                 {
902                     r.d.length = minlen+1;
903                 }
904                 else
905                 {
906                     r.d.length = maxlen+1;
907                     r.d[minlen..maxlen] = x.d[minlen..maxlen];
908                 }
909             }
910             else if (x.d.length < y.d.length)
911             {
912                 maxlen = y.d.length - 1;
913                 if (x.sign)
914                 {
915                     r.d.length = minlen+1;
916                 }
917                 else
918                 {
919                     r.d.length = maxlen+1;
920                     r.d[minlen..maxlen] = y.d[minlen..maxlen];
921                 }
922             }
923             else
924             {
925                 r.d.length = minlen+1;
926             }
927             bigintLLOr(r.d, x.d, y.d, minlen);
928             r.d[r.d.length-1] = s;
929             return minimize(r);
930         }
931
932         Int opOr(int y)
933         {
934             if (y < 0)
935             {
936                 return new Int(cast(int) (y | d[0]));
937             }
938             else
939             {
940                 return this | (cast(uint) y);
941             }
942         }
943
944         Int opOr(uint y)
945         {
946             uint n = d[0] | y;
947             if (n == d[0]) return this;
948             Int r = new Int(this);
949             r.d[0] = n;
950             return r;
951         }
952
953
954         // -------- Binary Exclusive Or --------
955
956         Int opXor(Int y)
957         {
958             Int r = new Int;
959             Int x = this;
960             int s = x.sign ^ y.sign;
961             uint minlen = x.d.length - 1;
962             uint maxlen = minlen;
963             if (x.d.length > y.d.length)
964             {
965                 minlen = y.d.length - 1;
966                 r.d.length = maxlen + 1;
967
968                 if (y.sign)
969                 {
970                     bigintLLCom(&r.d[minlen], &x.d[minlen], maxlen-minlen);
971                 }
972             }
973             else if (x.d.length < y.d.length)
974             {
975                 maxlen = y.d.length - 1;
976                 r.d.length = maxlen + 1;
977
978                 if (x.sign)
979                 {
980                     bigintLLCom(&r.d[minlen], &y.d[minlen], maxlen-minlen);
981                 }
982             }
983             else
984             {
985                 r.d.length = minlen + 1;
986             }
987             bigintLLXor(r.d, x.d, y.d, minlen);
988             r.d[maxlen] = s;
989             return minimize(r);
990         }
991
992         Int opXor(int y)
993         {
994             if (y < 0)
995             {
996                 Int r = new Int;
997                 r.d.length = d.length;
998
999                 r.d[0] = d[0] ^ y;
1000                 bigintLLCom(&r.d[1], &d[1], d.length-1);
1001                 return minimize(r);
1002             }
1003             else
1004             {
1005                 return this ^ (cast(uint) y);
1006             }
1007         }
1008
1009         Int opXor(uint y)
1010         {
1011             if (y == 0) return this;
1012             Int r = new Int(this);
1013             r.d[0] ^= y;
1014             return r;
1015         }
1016
1017         // -------- Complement --------
1018
1019         Int opCom()
1020         {
1021             Int r = new Int;
1022             r.d.length = d.length;
1023             bigintLLCom(r.d, d, d.length);
1024             return r;
1025         }
1026
1027         // -------- Shift left --------
1028
1029         Int opShl(Int y)
1030         {
1031             Int x = this;
1032             if (y.isInt())
1033             {
1034                 int k = y.d[0];
1035                 return x << k;
1036             }
1037             if (y.sign) return x >> (-y);
1038             if (x.equalsZero) return this;
1039             throw new IntException("(x << y) overflow: y too big");
1040         }
1041
1042         Int opShl(int y)
1043         {
1044             if (y < 0) return this >> (cast(uint)-y);
1045             return this << (cast(uint)y);
1046         }
1047
1048         Int opShl(uint y)
1049         {
1050             if (y == 0) return this;
1051             uint nDigits = y >> 5;
1052             uint nBits = y & 0x1F;
1053
1054             int neg = sign;
1055             Int r = shlWhole(this, nDigits);
1056             Int s = new Int;
1057             s.d.length = r.d.length + 1;
1058             bigintLLShl(&s.d[nDigits], &r.d[nDigits], nBits, r.d.length-nDigits);
1059             s.d[s.d.length-1] = neg;
1060             return minimize(s);
1061         }
1062
1063         Int opShl_r(int y)
1064         {
1065             return (new Int(y)) << this;
1066         }
1067
1068         Int opShl_r(uint y)
1069         {
1070             return (new Int(y)) << this;
1071         }
1072
1073         // -------- Shift right --------
1074
1075         Int opShr(Int y)
1076         {
1077             if (y.isInt())
1078             {
1079                 int k = y.d[0];
1080                 return this >> k;
1081             }
1082             if (y.sign) return this << (-y);
1083             return new Int(sign());
1084         }
1085
1086         Int opShr(int y)
1087         {
1088             if (y < 0) return this << (cast(uint)-y);
1089             return this >> (cast(uint)y);
1090         }
1091
1092         Int opShr(uint y)
1093         {
1094             if (y == 0) return this;
1095             uint nDigits = y >> 5;
1096             uint nBits = y & 0x1F;
1097
1098             Int r = shrWhole(this, nDigits);
1099             Int s = new Int;
1100             s.d.length = r.d.length;
1101             uint extraBits = (sign) ? (int.min >> nBits) << 1 : 0;
1102             bigintLLShr(s.d, r.d, nBits, r.d.length);
1103             s.d[s.d.length-1] |= extraBits;
1104             return minimize(s);
1105         }
1106
1107         Int opShr_r(uint y)
1108         {
1109             return (new Int(y)) >> this;
1110         }
1111
1112         Int opShr_r(int y)
1113         {
1114             return (new Int(y)) >> this;
1115         }
1116
1117         // -------- Unsigned Shift right --------
1118
1119         Int opUShr(Int y)
1120         {
1121             Int x = this;
1122             if (y.isInt())
1123             {
1124                 int k = y.d[0];
1125                 return x >>> k;
1126             }
1127             if (y.sign) return x << (-y);
1128             if (x.sign) throw new IntException("(x >>> y) not defined for x < 0");
1129             return ZERO;
1130         }
1131
1132         Int opUShr(int y)
1133         {
1134             if (y < 0) return this << (cast(uint)-y);
1135             return this >>> (cast(uint)y);
1136         }
1137
1138         Int opUShr(uint y)
1139         {
1140             if (y == 0) return this;
1141             if (sign) throw new IntException("(x >>> y) not defined for x < 0");
1142             return opShr(y);
1143         }
1144
1145         Int opUShr_r(uint y)
1146         {
1147             return (new Int(y)) >>> this;
1148         }
1149
1150         Int opUShr_r(int y)
1151         {
1152             return (new Int(y)) >>> this;
1153         }
1154
1155         // -------- Array dereferencing --------
1156         //
1157         // These overloads are designed to give the illusion that an Int is actually an infinitely large array
1158
1159         // uint length() purposefully not overloaded, because you can't actually HAVE an infinitely large array
1160         // instead, we offer this:
1161
1162         uint end()
1163         {
1164             return d.length - 1;
1165         }
1166
1167         uint opIndex(int i)
1168         {
1169             return (i < d.length) ? d[i] : d[d.length-1];
1170         }
1171
1172         // uint opIndex(int i, int value) purposefully not overloaded because Ints are immutable
1173
1174         // uint[] opSlice() purposefully not overloaded, because you can't actually HAVE an infinitely large array
1175
1176         uint[] opSlice(int i, int j)
1177         {
1178             uint[] t;
1179             if (i >= j) return t; //empty array
1180             t.length = j-i;
1181             if (j <= d.length)
1182             {
1183                 t[] = d[i..j];
1184             }
1185             else
1186             {
1187                 uint s = sign;
1188                 if (i >= d.length)
1189                 {
1190                     t[] = s;
1191                 }
1192                 else
1193                 {
1194                     t[0..d.length-i] = d[i..d.length];
1195                     t[d.length-i..j-i] = s;
1196                 }
1197             }
1198             return t;
1199         }
1200
1201         /*
1202             And so end the operator overloads.
1203
1204             Now, one big problem with big integers is that printf() doesn't recognise them.
1205             For this reason, we present a format function.
1206             Its parameter is a fragment of a printf() format string, starting with "%" and ending with "d".
1207         */
1208
1209         enum SignMode { NORMAL, MINUS_SPACE, MINUS_SPACE_PLUS }
1210         char[] format(uint radix, uint minWidth, uint groupWidth, bool leadingZeroes, SignMode signMode)
1211         {
1212             // Get a positive version of this
1213             int actualSign = opCmp(0);
1214             Int t = (actualSign < 0) ? -this : this;
1215             char padChar = leadingZeroes ? '0' : ' ';
1216             char[] s = bigintToString(t.d, radix, groupWidth);
1217
1218             // Now make somewhere for the final result
1219             char[] u;
1220             uint tLen = s.length + 1;
1221             if (tLen < minWidth) tLen = minWidth;
1222             u.length = tLen;
1223
1224             // Copy in the string
1225             uint padSpace = u.length - s.length;
1226             u[0..padSpace] = padChar;
1227             u[padSpace..u.length] = s[0..s.length];
1228
1229             // Write in the sign
1230             uint signPos = (leadingZeroes) ? 0 : padSpace-1;
1231             if (actualSign < 0)
1232             {
1233                 u[signPos] = '-';
1234             }
1235             else if (signMode == SignMode.NORMAL)
1236             {
1237                 uint realLength = (s.length > minWidth) ? s.length : minWidth;
1238                 u = u[u.length-realLength..u.length];
1239             }
1240             else if (actualSign == 0 || signMode == SignMode.MINUS_SPACE)
1241             {
1242                 u[signPos] = ' ';
1243             }
1244             else
1245             {
1246                 u[signPos] = '+';
1247             }
1248             s[] = 0;
1249             return u;
1250         }
1251
1252         /*
1253             The functions below are intended to be fast and simple.
1254         */
1255
1256         /* returns true if this is zero; false if this is non-zero */
1257         bool equalsZero()
1258         {
1259             return ((d[0]==0) && (d[1]==0) && (d.length == 2));
1260         }
1261
1262         /* returns true if this is positive; false if this is negative or zero */
1263         bool positive()
1264         {
1265             if (sign) return false;
1266             return (!equalsZero());
1267         }
1268
1269         /* returns true if this is negative; false if this is positive or zero */
1270         bool negative()
1271         {
1272             return (sign < 0);
1273         }
1274
1275         /* returns -1 if this is sign; 0 if this is positive or zero */
1276         int sign()
1277         {
1278             return d[d.length-1];
1279         }
1280
1281         // Change the sign field of a number without negating it. That is, change the interpretation of its bit pattern
1282         Int changeSign()
1283         {
1284             Int r = new Int(this);
1285             r.d[r.d.length-1] = ~r.d[r.d.length-1];
1286             return r;
1287         }
1288     }
1289
1290     package
1291     {
1292         this()
1293         {
1294         }
1295
1296         this(uint[] t)
1297         {
1298             d = t;
1299             minimize(this);
1300         }
1301
1302         this(Int n)
1303         {
1304             d.length = n.d.length;
1305             d[] = n.d[];
1306         }
1307
1308         //-----------------------------------
1309         // The member variables of this class
1310
1311         uint[] d;
1312
1313         //==================================================
1314
1315         // A generalization of this to the power of e.
1316         Int powGen(Int e, Int r, FMul f)
1317         in
1318         {
1319             assert(e >= 0);
1320         }
1321         body
1322         {
1323             Int x = this;
1324             if (x.equalsZero) return x;
1325             if (e.equalsZero) return r;
1326
1327             // We unroll what would otherwise have been the first pass of the i-loop, for speed.
1328             // Note that i starts off at e.length-2, because:
1329             //      e.d[e.length-1] = the sign word, guaranteed to equal 0x00000000 in this case.
1330             //      e.d[e.length-2] = the most significant d of e.
1331
1332             int i = e.d.length - 2;
1333             for (int j=bsr(e.d[i]); j>=0; --j)
1334             {
1335                 r = f(r,r);
1336                 if (bt(&e.d[i],j))
1337                 {
1338                     r = f(r,x);
1339                 }
1340             }
1341
1342             // Below is the rest of the i-loop. From now on, j has to test every single bit.
1343             // Note that i starts off at e.length-3, because the first pass of the loop was
1344             // unrolled, and carried out above.
1345
1346             for (i=e.d.length-3; i>=0; --i)
1347             {
1348                 for (int j=31; j>=0; --j)
1349                 {
1350                     r = f(r, r);
1351                     if (bt(&e.d[i],j))
1352                     {
1353                         r = f(r, x);
1354                     }
1355                 }
1356             }
1357             return r;
1358         }
1359     }
1360 }
1361
1362 // Private helper functions follow
1363
1364 private
1365 {
1366     Int minimize(Int x)
1367     {
1368         uint len = bigintLLMinimizeV(x.d, x.d[x.d.length-1], x.d.length);
1369         if (len <= 1)
1370         {
1371             x.d.length = 2;
1372         }
1373         else
1374         {
1375             x.d.length = len + 1;
1376         }
1377         return x;
1378     }
1379 }
1380
1381 /*  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1382     Public helper functions follow
1383 */
1384
1385 // get the absolute value of a number
1386 Int abs(Int x)
1387 {
1388     return (x.sign) ? -x : x;
1389 }
1390
1391 // Returns -1, 0 or +1 according to the sign of x
1392 int sgn(Int x)
1393 {
1394     if (x.sign) return -1;
1395     return (x.equalsZero) ? 0 : 1;
1396 }
1397
1398 // test a bit
1399 bit bitTest(Int x, uint n)
1400 {
1401     uint nDigits = n >>> 5;
1402     uint nBits = n & 0x1F;
1403     if (nDigits >= x.d.length) return (x.sign == 0) ? 0 : 1;
1404     return (bts(&x.d[nDigits], nBits) == 0) ? 0 : 1;
1405 }
1406
1407 // set a bit. (More precisely, return a copy of x, with the appropriate bit set).
1408 Int bitSet(Int x, int n)
1409 {
1410     return x | pow2(n);
1411 }
1412
1413 // reset a bit.  (More precisely, return a copy of x, with the appropriate bit set).
1414 Int bitClear(Int x, int n)
1415 {
1416     return x & ~pow2(n);
1417 }
1418
1419 // get the number of trailing zero bits in this (ge2 means Greatest Power of 2)
1420 uint ge2(Int x)
1421 {
1422     for (uint i=0; i<x.d.length; ++i)
1423     {
1424         int n = bsf(x.d[i]);
1425         if (n >= 0) return n;
1426     }
1427     throw new IntException("ge2(x) not defined for x == 0");
1428 }
1429
1430 uint ge2(int x)
1431 {
1432     return ge2(cast(uint) x);
1433 }
1434
1435 uint ge2(uint x)
1436 {
1437     int n = bsf(x);
1438     if (n >= 0) return n;
1439     throw new IntException("ge2(x) not defined for x == 0");
1440 }
1441
1442
1443 // get the number of bits in this (less one)
1444 uint log2(Int x)
1445 {
1446     if (!x.positive) throw new IntException("log2(x) not defined for x <= 0");
1447     return bsr(x.d[x.d.length-2]) + ((x.d.length-2)<<5);
1448 }
1449
1450 uint log2(int x)
1451 {
1452     if (x <= 0) throw new IntException("log2(x) not defined for x <= 0");
1453     return bsr(x);
1454 }
1455
1456 uint log2(uint x)
1457 {
1458     if (x == 0) throw new IntException("log2(x) not defined for x == 0");
1459     return bsr(x);
1460 }
1461
1462 // returns two to a given power
1463 Int pow2(int x)
1464 {
1465     if (x < 0) throw new IntException("pow2(x) not defined for x < 0");
1466     uint nDigits = x >>> 5;
1467     uint nBits = x & 0x1F;
1468     Int r = new Int();
1469     r.d.length = nDigits + 2;
1470     r.d[nDigits] = 1 << nBits;
1471     return r;
1472 }
1473
1474 // test whether or not a bigint is an exact power of two
1475 bool isPow2(Int x)
1476 {
1477     if (!x.positive) return false;
1478     if (isPow2(x.d[x.d.length-2]))
1479     {
1480         return bigintLLEqualsZero(x.d, x.d.length-2);
1481     }
1482     return false;
1483 }
1484
1485 bool isPow2(int x)
1486 {
1487     if (x <= 0) return false;
1488     return isPow2(cast(uint) x);
1489 }
1490
1491 bool isPow2(uint x)
1492 {
1493     return (log2Exact(x) >= 0);
1494 }
1495
1496 // Count the number of one bits in a uint
1497 uint countOnes(Int x)
1498 {
1499     if (x.sign) throw new IntException("countOnes(x) not defined for x < 0");
1500     return bigintLLCountOnes(x.d, x.d.length-1);
1501 }
1502
1503 uint countOnes(int x)
1504 {
1505     if (x < 0) throw new IntException("countOnes(x) not defined for x < 0");
1506     return countOnes(cast(uint) x);
1507 }
1508
1509 uint countOnes(uint x)
1510 {
1511     return bigintLLCountOnes(&x, 1);
1512 }
1513
1514 // Shift one number left by a whole number of uints. That is, perform x << (32*y).
1515 Int shlWhole(Int x, uint y)
1516 {
1517     if (y == 0) return x;
1518     Int r = new Int;
1519     r.d.length = x.d.length + y;
1520     r.d[y..r.d.length] = x[0..x.d.length];
1521     return r;
1522 }
1523
1524 Int shlWhole(int x, uint y)
1525 {
1526     Int r = new Int;
1527     r.d.length = y + 2;
1528     r.d[y] = x;
1529     r.d[y+1] = x<0 ? -1U : 0;
1530     return r;
1531 }
1532
1533 Int shrWhole(Int x, uint y)
1534 {
1535     if (y == 0) return x;
1536     Int r = new Int;
1537     if (x.d.length > y+2)
1538     {
1539         r.d.length = x.d.length - y;
1540         r.d[] = x.d[y..x.d.length];
1541     }
1542     else
1543     {
1544         r.d.length = 2;
1545         r.d[] = x.d[x.d.length-2..x.d.length];
1546     }
1547     return r;
1548 }
1549
1550 // Return the low part of a number. That is, x & (1<<(32*y))-1
1551 Int lowWhole(Int x, uint y)
1552 {
1553     if (y == x.end) return x;
1554     Int r = new Int;
1555     r.d.length = y + 1;
1556     r.d[0..y] = x[0..y];
1557     return minimize(r);
1558 }
1559
1560 //  Return x / y and assign d = x % y
1561 Int divMod(Int x, Int y, out Int r)
1562 {
1563     return divMod(x, y, r, Int.Round.TOWARD_ZERO);
1564 }
1565
1566 Int divMod(Int x, Int y, out Int r, Int.Round mode)
1567 out(q)
1568 {
1569     assert(y*q+r == x);
1570 }
1571 body
1572 {
1573     if (y.equalsZero()) throw new IntException("Divide by zero");
1574
1575     int xSign = x.sign;
1576     int ySign = y.sign;
1577     Int xa = (xSign < 0) ? -x : x;
1578     Int ya = (ySign < 0) ? -y : y;
1579
1580     Int q;
1581     if (xa < ya)
1582     {
1583         q = Int.ZERO;
1584         r = xa;
1585     }
1586     else
1587     {
1588         q = new Int;
1589         q.d.length = xa.d.length - ya.d.length + 2;
1590         r = new Int;
1591         r.d.length = ya.d.length;
1592         bigintDivMod(q.d, q.d.length-1, r.d, r.d.length-1, xa.d, xa.d.length-1, ya.d, ya.d.length-1);
1593         minimize(q);
1594         minimize(r);
1595     }
1596
1597     if (xSign != ySign) q = -q;
1598     if (xSign < 0) r = -r;
1599
1600     if (!r.equalsZero())
1601     {
1602         switch (mode)
1603         {
1604         case Int.Round.TOWARD_ZERO:
1605             break;
1606
1607         case Int.Round.TOWARD_INFINITY:
1608             if (xSign == ySign)
1609             {
1610                 q = q + 1;
1611                 r = r - y;
1612             }
1613             break;
1614
1615         case Int.Round.TOWARD_MINUS_INFINITY:
1616             if (xSign != ySign)
1617             {
1618                 q = q - 1;
1619                 r = r + y;
1620             }
1621             break;
1622         }
1623     }
1624     return q;
1625 }
1626
1627 package class FMul
1628 {
1629     abstract Int opCall(Int x, Int y);
1630 }
Note: See TracBrowser for help on using the browser.