1 /**
2 * BigInt
3 * 
4 * Copyright:
5 * (C) 1999-2008,2012 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *    2007 FlexSecure
8 *
9 * License:
10 * Botan is released under the Simplified BSD License (see LICENSE.md)
11 */
12 module botan.math.bigint.bigint;
13 
14 import botan.constants;
15 public import botan.math.mp.mp_types;
16 public import botan.utils.types;
17 import botan.constants;
18 import botan.rng.rng;
19 import memutils.vector;
20 import botan.utils.charset;
21 import botan.codec.hex;
22 import botan.math.bigint.divide;
23 import botan.math.mp.mp_core;
24 import botan.utils.get_byte;
25 import botan.utils.parsing;
26 import botan.utils.rounding;
27 import botan.utils.parsing;
28 import botan.utils.bit_ops;
29 import std.algorithm;
30 import std.traits : isNumeric, isPointer;
31 
32 /**
33 * Arbitrary precision integer
34 */
35 struct BigInt
36 {
37 public:
38     /*
39     * Write the BigInt into a vector
40     */
41     Vector!char toVector(Base base = Decimal) const
42     {
43         Vector!ubyte buffer = BigInt.encode(this, base);
44         Vector!char ret;
45         size_t skip = 0;
46         while(skip < buffer.length && buffer[skip] == '0')
47             ++skip;
48         ret[] = cast(char[])(buffer.ptr + skip)[0 .. buffer.length - skip];
49         return ret.move();
50     }
51 
52     /*
53     * Write the BigInt into a string
54     */
55     string toString(Base base = Decimal) const
56     {
57         auto vec = toVector(base);
58         //logTrace("toString: ", vec[]);
59         return (vec[]).idup;
60     }
61     alias Base = int;
62     /**
63     * Base enumerator for encoding and decoding
64     */
65     enum : Base { Decimal = 10, Hexadecimal = 16, Binary = 256 }
66 
67     alias Sign = bool;
68     /**
69     * Sign symbol definitions for positive and negative numbers
70     */
71     enum : Sign { Negative = 0, Positive = 1 }
72 
73     /**
74     * DivideByZero Exception
75     */
76     class DivideByZero : Exception
77     { 
78         this() {
79             super("BigInt divide by zero");
80         }
81     }
82 
83     /**
84     * Create BigInt from any integer
85     * Params:
86     *  n = initial value of this BigInt
87     */
88     this(T)(T n)
89         if (isNumeric!T)
90     {
91         import std.algorithm : max;
92         if (n == 0)
93             return;
94         const size_t limbs_needed = std.algorithm.max(1, T.sizeof / word.sizeof);
95         m_reg.resize(4*limbs_needed);
96         foreach (size_t i; 0 .. limbs_needed)
97             m_reg[i] = ((n >> (i*MP_WORD_BITS)) & MP_WORD_MASK);
98     }
99     // Create BigInt from any integer
100     void opAssign(T)(in T number) 
101         if (isNumeric!T)
102     {
103         this(number);
104     }
105 
106     /// Move constructor
107     ref BigInt opAssign(size_t other) const return
108     {
109         (cast(BigInt*)&this).swap(other);
110         
111         return *(cast(BigInt*)&this);
112     }
113 
114 	/// Copy constructor
115 	void load(BigInt* other) {
116 		m_reg[] = other.m_reg[];
117 		m_signedness = other.m_signedness;
118 	}
119 
120     /**
121     * Create BigInt from a string. If the string starts with 0x the
122     * rest of the string will be interpreted as hexadecimal digits.
123     * Otherwise, it will be interpreted as a decimal number.
124     *
125     * Params:
126     *  str = the string to parse for an integer value
127     */
128     this(in string str)
129     {
130         Base base = Decimal;
131         size_t markers = 0;
132         bool negative = false;
133         
134         if (str.length > 0 && str[0] == '-')
135         {
136             markers += 1;
137             negative = true;
138         }
139         
140         if (str.length > markers + 2 && str[markers     ] == '0' &&
141         str[markers + 1] == 'x')
142         {
143             markers += 2;
144             base = Hexadecimal;
145         }
146         auto contents = decode(cast(const(ubyte)*)(str.ptr) + markers, str.length - markers, base);
147         this.swap( &contents );
148 
149         if (negative) setSign(Negative);
150         else          setSign(Positive);
151     }
152 
153     /**
154     * Create a BigInt from an integer in a ubyte array
155     * Params:
156     *  input = the ubyte array holding the value
157     *  length = size of buf
158     *  base = is the number base of the integer in buf
159     */
160     this(const(ubyte)* input, size_t length, Base base = Binary)
161     {
162         auto bn = decode(input, length, base);
163         this.swap( &bn );
164     }
165 
166     /**
167     * Create a random BigInt of the specified size
168     * Params:
169     *  rng = random number generator
170     *  bits = size in bits
171     *  set_high_bit = if true, the highest bit is always set
172     */
173     this(RandomNumberGenerator rng, size_t bits, bool set_high_bit = true)
174     {
175         randomize(rng, bits, set_high_bit);
176     }
177     /**
178     * Create BigInt of specified size, all zeros
179     * Params:
180     *  s = the sign
181     *  size = of the internal register in words
182     */
183     this(Sign s, size_t size)
184     {
185         m_reg.resize(roundUp!size_t(size, 8));
186         m_signedness = s;
187     }
188 
189     /**
190     * Move constructor
191     */
192     this(BigInt* other)
193     {
194         this.swap(other);
195     }
196 
197     this(ALLOC)(auto const ref Vector!(ubyte, ALLOC) payload, in Sign sign) {
198         this(payload.ptr, payload.length, sig_words);
199     }
200 
201     this(ALLOC)(auto const ref RefCounted!(Vector!(ubyte, ALLOC), ALLOC) payload, in Sign sign) {
202         this(payload.ptr, payload.length, sig_words);
203     }
204 
205     this()(auto ref SecureVector!word reg, Sign sign) {
206         import std.algorithm : swap;
207         m_reg.swap(reg);
208         swap(m_signedness, sign);
209     }
210 
211 	void reserve(size_t n) {
212 		m_reg.reserve(n);
213 	}
214 
215     /**
216     * Move assignment
217     */
218     void opAssign(T)(T other)
219         if (!isPointer!T)
220     {
221 		this.swap(other);
222     }
223     void opAssign(T)(T other)
224         if (isPointer!T)
225     {
226 		this.swap(*other);
227     }
228     
229     /**
230     * Move assignment
231     */
232     void opAssign(const BigInt other) nothrow
233     {
234 		this.swap(cast(BigInt*)&other);
235     }
236     /**
237     * Move assignment
238     */
239     void opAssign(BigInt other) const nothrow
240     {
241 		(cast(BigInt*)&this).swap(&other);
242     }
243 
244     /**
245     * Copy assignment
246     */
247     // BigInt operator=(const ref BigInt) = default;
248 
249     /**
250     * Swap this value with another
251     * Params:
252     *  other = BigInt to swap values with
253     */
254     void swap(T)(T other_) nothrow
255     if (!isPointer!T && isNumeric!T)
256     {
257         try {
258             import std.algorithm.mutation : swap;
259             BigInt other = BigInt(other_);
260             m_reg.swap(cast()other.m_reg);
261             m_signedness = cast(Sign)other.m_signedness;
262         } catch(Throwable e) {}
263     }
264 
265     void swap(BigInt* other_) nothrow
266     {
267         try {
268             import std.algorithm.mutation : swap;
269             m_reg.swap(cast()other_.m_reg[]);
270             m_signedness = cast(Sign)other_.m_signedness;
271         } catch(Throwable e) {}
272     }
273 
274     void swap(ref BigInt other_) nothrow
275     {
276         try {
277             import std.algorithm.mutation : swap;
278             m_reg.swap(cast()other_.m_reg[]);
279             m_signedness = cast(Sign)other_.m_signedness;
280         } catch(Throwable e) {}
281     }
282 
283     void swap(BigInt other_) nothrow
284     {
285         swap(other_);
286     }
287 
288     void swapReg(ref SecureVector!word reg)
289     {
290         m_reg.swap(reg);
291     }
292 
293     /**
294     * += operator
295     * Params:
296     *  y = the BigInt to add to this
297     */
298     void opOpAssign(string op)(const(BigInt)* y)
299         if (op == "+")
300     {
301         const size_t x_sw = sigWords(), y_sw = y.sigWords();
302         
303         const size_t reg_size = std.algorithm.max(x_sw, y_sw) + 1;
304         growTo(reg_size);
305         
306         if (sign() == y.sign())
307             bigint_add2(mutablePtr(), reg_size - 1, y.ptr, y_sw);
308         else
309         {
310             int relative_size = bigint_cmp(mutablePtr(), x_sw, y.ptr, y_sw);
311             
312             if (relative_size < 0)
313 			{               
314 				SecureVector!word z = SecureVector!word(reg_size - 1);
315 				bigint_sub3(z.ptr, y.ptr, reg_size - 1, mutablePtr(), x_sw);
316 				m_reg[] = z;
317                 setSign(y.sign());
318             }
319             else if (relative_size == 0)
320             {
321                 zeroise(m_reg);
322 		        setSign(Positive);
323             }
324             else if (relative_size > 0) 
325                 bigint_sub2(mutablePtr(), x_sw, y.ptr, y_sw);
326         }
327         
328     }
329     
330     void opOpAssign(string op)(auto const ref BigInt y)
331         if (op == "+")
332     {
333         opOpAssign!"+"(&y);
334     }
335 
336     void opOpAssign(string op)(in word y)
337         if (op == "+")
338     {
339         this += BigInt(y);
340     }
341 
342     /**
343     * -= operator
344     * Params:
345     *  y = the BigInt to subtract from this
346     */
347     void opOpAssign(string op)(const(BigInt)* y)
348         if (op == "-")
349     {
350         const size_t x_sw = sigWords(), y_sw = y.sigWords();
351         
352         int relative_size = bigint_cmp(mutablePtr(), x_sw, y.ptr, y_sw);
353         
354         const size_t reg_size = std.algorithm.max(x_sw, y_sw) + 1;
355         growTo(reg_size);
356         
357         if (relative_size < 0)
358         {
359             if (sign() == y.sign())
360                 bigint_sub2_rev(mutablePtr(), y.ptr, y_sw);
361             else
362                 bigint_add2(mutablePtr(), reg_size - 1, y.ptr, y_sw);
363             
364             setSign(y.reverseSign());
365         }
366         else if (relative_size == 0)
367         {
368             if (sign() == y.sign())
369             {
370                 clear();
371                 setSign(Positive);
372             }
373             else
374                 bigint_shl1(mutablePtr(), x_sw, 0, 1);
375         }
376         else if (relative_size > 0)
377         {
378             if (sign() == y.sign())
379                 bigint_sub2(mutablePtr(), x_sw, y.ptr, y_sw);
380             else
381                 bigint_add2(mutablePtr(), reg_size - 1, y.ptr, y_sw);
382         }
383     }
384 
385 
386     void opOpAssign(string op)(auto const ref BigInt y)
387         if (op == "-")
388     {
389         opOpAssign!"-"(&y);
390     }
391 
392     void opOpAssign(string op)(in word y)
393         if (op == "-")
394     {
395         this -= BigInt(y);
396     }
397 
398 
399     /**
400     * *= operator
401     * Params:
402     *  y = the BigInt to multiply with this
403     */
404     void opOpAssign(string op)(const(BigInt)* y)
405         if (op == "*")
406     {
407         const size_t x_sw = sigWords();
408         const size_t y_sw = y.sigWords();
409         setSign((sign() == y.sign()) ? Positive : Negative);
410         
411         if (x_sw == 0 || y_sw == 0)
412         {
413             clear();
414             setSign(Positive);
415         }
416         else if (x_sw == 1 && y_sw)
417         {
418             growTo(y_sw + 2);
419             bigint_linmul3(mutablePtr(), y.ptr, y_sw, wordAt(0));
420         }
421         else if (y_sw == 1 && x_sw)
422         {
423             growTo(x_sw + 2);
424             bigint_linmul2(mutablePtr(), x_sw, y.wordAt(0));
425         }
426         else
427         {
428             growTo(size() + y.length);
429             
430             SecureVector!word z = SecureVector!word(mutablePtr()[0 .. x_sw]);
431             SecureVector!word workspace = SecureVector!word(size());
432             
433             bigint_mul(mutablePtr(), size(), workspace.ptr, z.ptr, z.length, x_sw, y.ptr, y.length, y_sw);
434         }
435     }
436 
437     void opOpAssign(string op)(auto const ref BigInt y)
438         if (op == "*")
439     {
440         opOpAssign!"*"(&y);
441     }
442 
443     void opOpAssign(string op)(in word y)
444         if (op == "*")
445     {
446         const BigInt b_y = BigInt(y);
447         this *= b_y;
448     }
449 
450     /**
451     * /= operator
452     * Params:
453     *   y = the BigInt to divide this by
454     */
455     void opOpAssign(string op)(const(BigInt)* y)
456         if (op == "/")
457     {
458         if (y.sigWords() == 1 && isPowerOf2(y.wordAt(0)))
459             this >>= (y.bits() - 1);
460         else
461             this = this / y;
462     }
463 
464     void opOpAssign(string op)(auto const ref BigInt y)
465         if (op == "/")
466     {
467         opOpAssign!"/"(&y);
468     }
469 
470     void opOpAssign(string op)(in word y)
471         if (op == "/")
472     {
473         this /= BigInt(y);
474     }
475 
476 
477     /**
478     * Modulo operator
479     * Params:
480     *  mod = the modulus to reduce this by
481     */
482     void opOpAssign(string op)(const(BigInt)* mod)
483         if (op == "%")
484     {
485         this = this % mod;
486     }
487 
488 
489     void opOpAssign(string op)(auto const ref BigInt mod)
490         if (op == "%")
491     {
492         opOpAssign!"%"(&mod);
493     }
494 
495     /**
496     * Modulo operator
497     * Params:
498     *  mod = the modulus (word) to reduce this by
499     */
500     void opOpAssign(string op)(word mod)
501         if (op == "%")
502     {
503         if (mod == 0)
504             throw new DivideByZero();
505         if (isPowerOf2(mod))
506         {
507             word result = (wordAt(0) & (mod - 1));
508             clear();
509             growTo(2);
510             m_reg[0] = result;
511             return;
512         }
513         
514         word remainder = 0;
515         
516         for (size_t j = sigWords(); j > 0; --j)
517             remainder = bigint_modop(remainder, wordAt(j-1), mod);
518         clear();
519         growTo(2);
520         
521         if (remainder && sign() == Negative)
522             m_reg[0] = mod - remainder;
523         else
524             m_reg[0] = remainder;
525         
526         setSign(Positive);
527     }
528 
529 
530     /**
531     * Left shift operator
532     * Params:
533     *  shift = the number of bits to shift this left by
534     */
535     void opOpAssign(string op)(size_t shift)
536         if (op == "<<")
537     {
538         if (shift)
539         {
540             const size_t shift_words = shift / MP_WORD_BITS;
541             const size_t shift_bits  = shift % MP_WORD_BITS;
542             const size_t words = sigWords();
543             
544             growTo(words + shift_words + (shift_bits ? 1 : 0));
545             bigint_shl1(mutablePtr(), words, shift_words, shift_bits);
546         }
547         
548     }
549 
550     /**
551     * Right shift operator
552     * Params:
553     *  shift = the number of bits to shift this right by
554     */
555     void opOpAssign(string op)(size_t shift)
556         if (op == ">>")
557     {
558         if (shift)
559         {
560             const size_t shift_words = shift / MP_WORD_BITS;
561             const size_t shift_bits  = shift % MP_WORD_BITS;
562             
563             bigint_shr1(mutablePtr(), sigWords(), shift_words, shift_bits);
564             if (isZero())
565                 setSign(Positive);
566         }
567     }
568 
569     /**
570     * Increment operator
571     */
572     ref BigInt opUnary(string op)() if (op == "++") { this += BigInt(1); return this; }
573 
574     /**
575     * Decrement operator
576     */
577     ref BigInt opUnary(string op)() if (op == "--") { this -= BigInt(1); return this; }
578 
579     /**
580     * Unary negation operator
581     * Returns: negative this
582     */
583     BigInt opUnary(string op)() const
584         if (op == "-")
585     {
586         BigInt ret = this.clone;
587         ret.flipSign();
588         return ret;
589     }
590 
591     /**
592     * bool cast
593     * Returns: true iff this is not zero, otherwise false
594     */
595     T opCast(T : bool)() const { return isNonzero(); }
596 
597     /**
598     * Zeroize the BigInt. The size of the underlying register is not
599     * modified.
600     */
601     void clear() 
602     { 
603         import core.stdc.string : memset;
604         if (!m_reg.empty){
605             memset(mutablePtr(), 0, word.sizeof*m_reg.length);
606         }
607     }
608 
609     /**
610     * Compare this to another BigInt
611     * Params:
612     *  other = the BigInt value to compare with
613     *  check_signs = include sign in comparison?
614     * Returns: if (this<n) return -1, if (this>n) return 1, if both
615     * values are identical return 0 [like Perl's <=> operator]
616     */
617     int cmp(const(BigInt)* other, bool check_signs = true) const
618     {
619         if (check_signs)
620         {
621             if (other.isPositive() && this.isNegative())
622                 return -1;
623             
624             if (other.isNegative() && this.isPositive())
625                 return 1;
626             
627             if (other.isNegative() && this.isNegative())
628                 return (-bigint_cmp(m_reg.ptr, this.sigWords(), other.ptr, other.sigWords()));
629         }
630         
631         return bigint_cmp(m_reg.ptr, this.sigWords(), other.ptr, other.sigWords());
632     }
633 
634     int cmp()(auto const ref BigInt other, bool check_signs = true) const
635     {
636         return cmp(&other, check_signs);
637     }
638 
639     /*
640     * Comparison Operators
641     */
642     bool opEquals(const(BigInt)* b) const
643     { return (cmp(b) == 0); }
644 
645     bool opEquals()(auto const ref BigInt b) const
646     { return (cmp(b) == 0); }
647 
648 
649     bool opEquals(in size_t n) const
650     { 
651         BigInt b = n;
652         return (cmp(b) == 0); 
653     }
654 
655 
656     int opCmp(const(BigInt)* b) const
657     { 
658         return cmp(b);
659     }    
660     
661     int opCmp()(auto const ref BigInt b) const
662     { 
663         return cmp(b);
664     }
665 
666     int opCmp(in size_t n) const
667     { 
668         BigInt b = n; 
669         return cmp(b); 
670     }
671 
672     /**
673     * Test if the integer has an even value
674     * Returns: true if the integer is even, false otherwise
675     */
676     bool isEven() const { return (getBit(0) == 0); }
677 
678     /**
679     * Test if the integer has an odd value
680     * Returns: true if the integer is odd, false otherwise
681     */
682     bool isOdd()  const { return (getBit(0) == 1); }
683 
684     /**
685     * Test if the integer is not zero
686     * Returns: true if the integer is non-zero, false otherwise
687     */
688     bool isNonzero() const { return (!isZero()); }
689 
690     /**
691     * Test if the integer is zero
692     * Returns: true if the integer is zero, false otherwise
693     */
694     bool isZero() const
695     {
696 		return sigWords() == 0;
697     }
698 
699     /**
700     * Set bit at specified position
701     * Params:
702     *  n = bit position to set
703     */
704     void setBit(size_t n)
705     {
706         const size_t which = n / MP_WORD_BITS;
707         const word mask = cast(word)(1) << (n % MP_WORD_BITS);
708         if (which >= size()) growTo(which + 1);
709         m_reg[which] |= mask;
710     }
711 
712     /**
713     * Clear bit at specified position
714     * Params:
715     *  n = bit position to clear
716     */
717     void clearBit(size_t n)
718     {
719         const size_t which = n / MP_WORD_BITS;
720         const word mask = cast(word)(1) << (n % MP_WORD_BITS);
721         if (which < size())
722             m_reg[which] &= ~mask;
723     }
724 
725     /**
726     * Clear all but the lowest n bits
727     * Params:
728     *  n = amount of bits to keep
729     */
730     void maskBits(size_t n)
731     {
732         if (n == 0) { clear(); return; }
733         if (n >= bits()) return;
734 
735         const size_t top_word = n / MP_WORD_BITS;
736         const word mask = ((cast(word)1) << (n % MP_WORD_BITS)) - 1;
737         
738         if (top_word < size())
739             clearMem(&m_reg[top_word+1], size() - (top_word + 1));
740         
741         m_reg[top_word] &= mask;
742     }
743 
744     /**
745     * Return bit value at specified position
746     * Params:
747     *  n = the bit offset to test
748     * Returns: true, if the bit at position n is set, false otherwise
749     */
750     bool getBit(size_t n) const
751     {
752         return ((wordAt(n / MP_WORD_BITS) >> (n % MP_WORD_BITS)) & 1);
753     }
754 
755     /**
756     * Return (a maximum of) 32 bits of the complete value
757     * Params:
758     *  offset = the offset to start extracting
759     *  length = amount of bits to extract (starting at offset)
760     * Returns: the integer extracted from the register starting at
761     * offset with specified length
762     */
763     uint getSubstring(size_t offset, size_t length) const
764     {
765         if (length > 32)
766             throw new InvalidArgument("BigInt.getSubstring: Substring size too big");
767         
768         ulong piece = 0;
769         foreach (size_t i; 0 .. 8)
770         {
771             const ubyte part = byteAt((offset / 8) + (7-i));
772             piece = (piece << 8) | part;
773         }
774         
775         const ulong mask = (cast(ulong)(1) << length) - 1;
776         const size_t shift = (offset % 8);
777         
778         return cast(uint)((piece >> shift) & mask);
779     }
780 
781     /**
782     * Convert this value into a uint, if it is in the range
783     * [0 ... 2**32-1], or otherwise throw new an exception.
784     * Returns: the value as a uint if conversion is possible
785     */
786     uint toUint() const
787     {
788         if (isNegative())
789             throw new EncodingError("BigInt.to_uint: Number is negative");
790         if (bits() >= 32)
791             throw new EncodingError("BigInt.to_uint: Number is too big to convert");
792         
793         uint output = 0;
794         for (uint j = 0; j != 4; ++j)
795             output = (output << 8) | byteAt(3-j);
796         return output;
797     }
798 
799     /**
800     * Params:
801     *  n = the offset to get a ubyte from
802     * Returns: ubyte at offset n
803     */
804     ubyte byteAt(size_t n) const
805     {
806         const size_t WORD_BYTES = (word).sizeof;
807         size_t word_num = n / WORD_BYTES;
808         size_t byte_num = n % WORD_BYTES;
809         if (word_num >= size())
810             return 0;
811         else
812             return get_byte(WORD_BYTES - byte_num - 1, m_reg[word_num]);
813     }
814 
815     /**
816     * Return the word at a specified position of the internal register
817     * Params:
818     *  n = position in the register
819     * Returns: value at position n
820     */
821 	pragma(inline, true)
822     word wordAt(size_t n) const
823     { return ((n < size()) ? m_reg[n] : 0); }
824 
825     /**
826     * Tests if the sign of the integer is negative
827     * Returns: true, iff the integer has a negative sign
828     */
829     bool isNegative() const { return (sign() == Negative); }
830 
831     /**
832     * Tests if the sign of the integer is positive
833     * Returns: true, iff the integer has a positive sign
834     */
835     bool isPositive() const { return (sign() == Positive); }
836 
837     /**
838     * Return the sign of the integer
839     * Returns: the sign of the integer
840     */
841 	pragma(inline, true)
842     Sign sign() const { return (m_signedness); }
843 
844     /**
845     * Returns: the opposite sign of the represented integer value
846     */
847     Sign reverseSign() const
848     {
849         if (sign() == Positive)
850             return Negative;
851         return Positive;
852     }
853 
854     /**
855     * Flip the sign of this BigInt
856     */
857     void flipSign()
858     {
859         setSign(reverseSign());
860     }
861 
862     /**
863     * Set sign of the integer
864     * Params:
865     *  s = new Sign to set
866     */
867     void setSign(Sign s)
868     {
869         if (isZero())
870             m_signedness = Positive;
871         else
872             m_signedness = s;
873     }
874 
875     /**
876     * Returns: absolute (positive) value of this
877     */
878     BigInt abs() const
879     {
880         BigInt ret = this.clone;
881         ret.setSign(Positive);
882         return ret;
883     }
884 
885     /**
886     * Give size of internal register
887     * Returns: size of internal register in words
888     */
889 	pragma(inline, true)
890     size_t size() const { return m_reg.length; }
891 
892     // ditto
893 	pragma(inline, true)
894     size_t length() const { return size(); }
895 
896     /**
897     * Return how many words we need to hold this value
898     * Returns: significant words of the represented integer value
899     */
900     size_t sigWords() const
901     {
902         const word* x = m_reg.ptr;
903         size_t sig = m_reg.length;
904 
905         while (sig && (x[sig-1] == 0))
906             sig--;
907         return sig;
908     }
909 
910     /**
911     * Give ubyte length of the integer
912     * Returns: ubyte length of the represented integer value
913     */
914 	pragma(inline, true)
915     size_t bytes() const
916     {
917         return (bits() + 7) / 8;
918     }
919 
920     /**
921     * Get the bit length of the integer
922     * Returns: bit length of the represented integer value
923     */
924     size_t bits() const
925     {
926         const size_t words = sigWords();
927         if (words == 0)
928             return 0;
929         
930         const size_t full_words = words - 1;
931         return (full_words * MP_WORD_BITS + highBit(wordAt(full_words)));
932     }
933 
934     /**
935     * Return a mutable pointer to the register
936     * Returns: a pointer to the start of the internal register
937     */
938     word* mutablePtr() { return m_reg.ptr; }
939 
940     /**
941     * Return a const pointer to the register
942     * Returns: a pointer to the start of the internal register
943     */
944     @property const(word*) ptr() const { return m_reg.ptr; }
945 
946     /**
947     * Increase internal register buffer to at least n words
948     * Params:
949     *  n = new size of register
950     */
951     void growTo(size_t n)
952     {
953         if (n > size()) {
954 			if (m_reg.capacity < n) m_reg.reserve(n*2);
955             m_reg.resize(roundUp!size_t(n, 8));
956 		}
957     }
958 
959     /**
960     * Fill BigInt with a random number with size of bitsize
961     * If set_high_bit is true, the highest bit will be set, which causes
962     * the entropy to be bits-1. Otherwise the highest bit is randomly choosen
963     * by the rng, causing the entropy to be bits.
964     * 
965     * Params:
966     *  rng = the random number generator to use
967     *  bitsize = number of bits the created random value should have
968     *  set_high_bit = if true, the highest bit is always set
969     */
970     void randomize(RandomNumberGenerator rng, size_t bitsize = 0, bool set_high_bit = true)
971     {
972         setSign(Positive);
973         
974         if (bitsize == 0)
975             clear();
976         else
977         {
978             SecureVector!ubyte array = rng.randomVec((bitsize + 7) / 8);
979 			// Always cut unwanted bits
980             if (bitsize % 8)
981                 array[0] &= 0xFF >> (8 - (bitsize % 8));
982 			// Set the highest bit if wanted
983 			if (set_high_bit)
984 				array[0] |= 0x80 >> ((bitsize % 8) ? (8 - bitsize % 8) : 0);
985             binaryDecode(array.ptr, array.length);
986         }
987     }
988 
989     /**
990     * Store BigInt-value in a given ubyte array
991     * Params:
992     *  output = destination ubyte array for the integer value
993     */
994     void binaryEncode(ubyte* output) const
995     {
996         const size_t sig_bytes = bytes();
997         foreach (size_t i; 0 .. sig_bytes) {
998             output[sig_bytes-i-1] = byteAt(i);
999         }
1000     }
1001 
1002     /**
1003     * Read integer value from a ubyte array with given size
1004     * Params:
1005     *  buf = ubyte array buffer containing the integer
1006     *  length = size of buf
1007     */
1008     void binaryDecode(const(ubyte)* buf, size_t length)
1009     {
1010         const size_t WORD_BYTES = (word).sizeof;
1011         
1012         clear();
1013         m_reg.resize(roundUp!size_t((length / WORD_BYTES) + 1, 8));
1014         foreach (size_t i; 0 .. (length / WORD_BYTES))
1015         {
1016             const size_t top = length - WORD_BYTES*i;
1017             for (size_t j = WORD_BYTES; j > 0; --j)
1018                 m_reg[i] = (m_reg[i] << 8) | buf[top - j];
1019         }
1020         
1021         foreach (size_t i; 0 .. (length % WORD_BYTES))
1022             m_reg[length / WORD_BYTES] = (m_reg[length / WORD_BYTES] << 8) | buf[i];
1023     }
1024 
1025     /**
1026     * Read integer value from a ubyte array (SecureVector!ubyte)
1027     * Params:
1028     *  buf = the array to load from
1029     */
1030     void binaryDecode(ALLOC)(auto const ref Vector!(ubyte, ALLOC) buf)
1031     {
1032         binaryDecode(buf.ptr, buf.length);
1033     }
1034 
1035 
1036     void binaryDecode(ALLOC)(const(Vector!(ubyte, ALLOC))* buf)
1037     {
1038         binaryDecode(buf.ptr, buf.length);
1039     }
1040 
1041     /// ditto
1042     void binaryDecode(ALLOC)(auto const ref RefCounted!(Vector!(ubyte, ALLOC), ALLOC) buf)
1043     {
1044         binaryDecode(buf.ptr, buf.length);
1045     }
1046     
1047     void binaryDecode(ALLOC)(const(RefCounted!(Vector!(ubyte, ALLOC), ALLOC))* buf)
1048     {
1049         binaryDecode(buf.ptr, buf.length);
1050     }
1051 
1052     /**
1053     * Params:
1054     *  base = the base to measure the size for
1055     * Returns: size of this integer in base base
1056     */
1057     size_t encodedSize(Base base = Binary) const
1058     {
1059         static const double LOG_2_BASE_10 = 0.30102999566;
1060         
1061         if (base == Binary)
1062             return bytes();
1063         else if (base == Hexadecimal)
1064             return 2*bytes();
1065         else if (base == Decimal)
1066             return cast(size_t)((bits() * LOG_2_BASE_10) + 1);
1067         else
1068             throw new InvalidArgument("Unknown base for BigInt encoding");
1069     }
1070 
1071     /**
1072     * Params:
1073     *  rng = a random number generator
1074     *  min = the minimum value
1075     *  max = the maximum value
1076     * Returns: random integer in [min,max$(RPAREN)
1077     */
1078     static BigInt randomInteger(RandomNumberGenerator rng, const(BigInt)* min, const(BigInt)* max)
1079     {
1080 		BigInt delta_upper_bound = max - min - 1;
1081 
1082         if (delta_upper_bound <= 0)
1083             throw new InvalidArgument("randomInteger: invalid min/max values");
1084 		// Choose x in [0, delta_upper_bound]
1085 		BigInt x;
1086 		do {
1087 			auto bitsize = delta_upper_bound.bits();
1088 			x.randomize(rng, bitsize, false);
1089 		} while (x > delta_upper_bound);
1090 
1091 		return (x + min);
1092     }
1093 
1094     static BigInt randomInteger()(RandomNumberGenerator rng, auto const ref BigInt min, auto const ref BigInt max)
1095     {
1096         return randomInteger(rng, &min, &max);
1097     }
1098     /**
1099     * Create a power of two
1100     * Params:
1101     *  n = the power of two to create
1102     * Returns: bigint representing 2^n
1103     */
1104     static BigInt powerOf2(size_t n)
1105     {
1106         BigInt b;
1107         b.setBit(n);
1108         return b;
1109     }
1110 
1111     /**
1112     * Encode the integer value from a BigInt to an Array of bytes
1113     * Params:
1114     *  n = the BigInt to use as integer source
1115     *  base = number-base of resulting ubyte array representation
1116     * Returns: SecureVector of bytes containing the integer with given base
1117     */
1118     static Vector!ubyte encode(const(BigInt)* n, Base base = Binary)
1119     {
1120         Vector!ubyte output = Vector!ubyte(n.encodedSize(base));
1121         encode(output.ptr, n, base);
1122         if (base != Binary)
1123             for (size_t j = 0; j != output.length; ++j)
1124                 if (output[j] == 0)
1125                     output[j] = '0';
1126         return output.move();
1127     }
1128 
1129     static Vector!ubyte encode()(auto const ref BigInt n, Base base = Binary)
1130     {
1131         return encode(&n, base);
1132     }
1133 
1134     /**
1135     * Encode the integer value from a BigInt to a Secure Array of bytes
1136     * Params:
1137     *  n = the BigInt to use as integer source
1138     *  base = number-base of resulting ubyte array representation
1139     * Returns: SecureVector of bytes containing the integer with given base
1140     */
1141     static SecureVector!ubyte encodeLocked(const(BigInt)* n, Base base = Binary)
1142     {
1143         SecureVector!ubyte output = SecureVector!ubyte(n.encodedSize(base));
1144         encode(output.ptr, n, base);
1145         if (base != Binary)
1146             for (size_t j = 0; j != output.length; ++j)
1147                 if (output[j] == 0)
1148                     output[j] = '0';
1149         return output.move();
1150     }
1151 
1152     static SecureVector!ubyte encodeLocked()(auto const ref BigInt n, Base base = Binary)
1153     {
1154         return encodeLocked(&n, base);
1155     }
1156 
1157     /**
1158     * Encode the integer value from a BigInt to a ubyte array
1159     * Params:
1160     *  output = destination ubyte array for the encoded integer
1161     * value with given base
1162     *  n = the BigInt to use as integer source
1163     *  base = number-base of resulting ubyte array representation
1164     */
1165     static void encode(ubyte* output, const(BigInt)* n, Base base = Binary)
1166     {
1167         if (base == Binary)
1168         {
1169             n.binaryEncode(output);
1170         }
1171         else if (base == Hexadecimal)
1172         {
1173             SecureVector!ubyte binary = SecureVector!ubyte(n.encodedSize(Binary));
1174             n.binaryEncode(binary.ptr);
1175             
1176             hexEncode(cast(char*)(output), binary.ptr, binary.length);
1177         }
1178         else if (base == Decimal)
1179         {
1180             BigInt copy = n.clone();
1181             BigInt remainder;
1182             copy.setSign(Positive);
1183             const size_t output_size = n.encodedSize(Decimal);
1184             foreach (size_t j; 0 .. output_size)
1185             {
1186                 auto bi = BigInt(10);
1187                 divide(&copy, &bi, &copy, &remainder);
1188                 output[output_size - 1 - j] = digit2char(cast(ubyte)(remainder.wordAt(0)));
1189                 if (copy.isZero())
1190                     break;
1191             }
1192         }
1193         else
1194             throw new InvalidArgument("Unknown BigInt encoding method");
1195     }
1196     
1197     static void encode()(ubyte* output, const auto ref BigInt n, Base base = Binary)
1198     {
1199         encode(output, &n, base);
1200     }
1201 
1202     /**
1203     * Create a BigInt from an integer in a ubyte array
1204     * Params:
1205     *  buf = the binary value to load
1206     *  length = size of buf
1207     *  base = number-base of the integer in buf
1208     * Returns: BigInt representing the integer in the ubyte array
1209     */
1210     static BigInt decode(const(ubyte)* buf, size_t length, Base base = Binary)
1211     {
1212         BigInt r;
1213         if (base == Binary)
1214             r.binaryDecode(buf, length);
1215         else if (base == Hexadecimal)
1216         {
1217             SecureVector!ubyte binary;
1218             if (length % 2)
1219             {
1220                 // Handle lack of leading 0
1221                 const char[2] buf0_with_leading_0 = [ '0', cast(char)(buf[0]) ];
1222                 
1223                 binary = hexDecodeLocked(buf0_with_leading_0.ptr, 2);
1224                 binary.reserve(length);
1225                 binary ~= hexDecodeLocked(cast(const(char)*)&buf[1], length - 1, false);
1226             }
1227             else {
1228                 binary = hexDecodeLocked(cast(const(char)*)buf, length, false);
1229             }
1230             r.binaryDecode(binary.ptr, binary.length);
1231         }
1232         else if (base == Decimal)
1233         {
1234             foreach (size_t i; 0 .. length)
1235             {
1236                 if (isSpace(buf[i]))
1237                     continue;
1238                 
1239                 if (!isDigit(buf[i]))
1240                     throw new InvalidArgument("BigInt.decode: " ~ "Invalid character in decimal input");
1241                 
1242                 const ubyte x = char2digit(buf[i]);
1243                 
1244                 if (x >= 10)
1245                     throw new InvalidArgument("BigInt: Invalid decimal string");
1246                 
1247                 r *= 10;
1248                 r += x;
1249             }
1250         }
1251         else
1252             throw new InvalidArgument("Unknown BigInt decoding method");
1253         return r.move;
1254     }
1255 
1256 
1257     /**
1258     * Create a BigInt from an integer in a ubyte array
1259     * Params:
1260     *  buf = the binary value to load
1261     *  base = number-base of the integer in buf
1262     * Returns: BigInt representing the integer in the ubyte array
1263     */
1264     static BigInt decode(ALLOC)(auto const ref RefCounted!(Vector!(ubyte, ALLOC), ALLOC) buf, Base base = Binary)
1265     {
1266         return BigInt.decode(buf.ptr, buf.length, base);
1267     }
1268 
1269     /**
1270     * Create a BigInt from an integer in a ubyte array
1271     * Params:
1272     *  buf = the binary value to load
1273     *  base = number-base of the integer in buf
1274     * Returns: BigInt representing the integer in the ubyte array
1275     */
1276     static BigInt decode(ALLOC)(auto const ref Vector!(ubyte, ALLOC) buf, Base base = Binary)
1277     {
1278         return BigInt.decode(buf.ptr, buf.length, base);
1279     }
1280 
1281     static BigInt decode(ALLOC)(const(Vector!(ubyte, ALLOC)*) buf, Base base = Binary)
1282     {
1283         return BigInt.decode(buf.ptr, buf.length, base);
1284     }
1285 
1286     /**
1287     * Encode a BigInt to a ubyte array according to IEEE 1363
1288     * Params:
1289     *  n = the BigInt to encode
1290     *  bytes = the length of the resulting SecureVector!ubyte
1291     * Returns: a SecureVector!ubyte containing the encoded BigInt
1292     */
1293     static SecureVector!ubyte encode1363(const(BigInt)* n, size_t bytes)
1294     {
1295         const size_t n_bytes = n.bytes();
1296         if (n_bytes > bytes)
1297             throw new EncodingError("encode1363: n is too large to encode properly");
1298         const size_t leading_0s = bytes - n_bytes;
1299         SecureVector!ubyte output = SecureVector!ubyte(bytes);
1300         encode(output.ptr + leading_0s, n, Binary);
1301         return output;
1302     }
1303 
1304     static SecureVector!ubyte encode1363()(auto const ref BigInt n, size_t bytes)
1305     {
1306         return BigInt.encode1363(&n, bytes);
1307     }
1308     /*
1309     * Addition Operator
1310     */
1311     BigInt opBinary(string op)(const(BigInt)* y) const
1312         if (op == "+")
1313     {
1314         const BigInt* x = &this;
1315         const size_t x_sw = x.sigWords(), y_sw = y.sigWords();
1316         
1317         BigInt z = BigInt(x.sign(), std.algorithm.max(x_sw, y_sw) + 1);
1318         
1319         if ((x.sign() == y.sign()))
1320             bigint_add3(z.mutablePtr(), x.ptr, x_sw, y.ptr, y_sw);
1321         else
1322         {
1323             int relative_size = bigint_cmp(x.ptr, x_sw, y.ptr, y_sw);
1324             
1325             if (relative_size < 0)
1326             {
1327                 bigint_sub3(z.mutablePtr(), y.ptr, y_sw, x.ptr, x_sw);
1328                 z.setSign(y.sign());
1329             }
1330             else if (relative_size == 0)
1331                 z.setSign(BigInt.Positive);
1332             else if (relative_size > 0)
1333                 bigint_sub3(z.mutablePtr(), x.ptr, x_sw, y.ptr, y_sw);
1334         }
1335         return z.move();
1336     }
1337 
1338     BigInt opBinary(string op)(ref const(BigInt) y) const
1339         if (op == "+")
1340     {
1341         return opBinary!"+"(&y);
1342     }
1343 
1344     BigInt opBinary(string op)(in word y) const
1345         if (op == "+")
1346     {
1347         auto y_ = BigInt(y);
1348         return this + y_;
1349     }
1350 
1351     /*
1352     * Subtraction Operator
1353     */
1354     BigInt opBinary(string op)(const(BigInt)* y) const
1355         if (op == "-")
1356     {
1357         const BigInt* x = &this;
1358         const size_t x_sw = x.sigWords(), y_sw = y.sigWords();
1359         
1360         int relative_size = bigint_cmp(x.ptr, x_sw, y.ptr, y_sw);
1361         
1362         BigInt z = BigInt(BigInt.Positive, std.algorithm.max(x_sw, y_sw) + 1);
1363         
1364         if (relative_size < 0)
1365         {
1366             if (x.sign() == y.sign())
1367                 bigint_sub3(z.mutablePtr(), y.ptr, y_sw, x.ptr, x_sw);
1368             else
1369                 bigint_add3(z.mutablePtr(), x.ptr, x_sw, y.ptr, y_sw);
1370             z.setSign(y.reverseSign());
1371         }
1372         else if (relative_size == 0)
1373         {
1374             if (x.sign() != y.sign())
1375                 bigint_shl2(z.mutablePtr(), x.ptr, x_sw, 0, 1);
1376         }
1377         else if (relative_size > 0)
1378         {
1379             if (x.sign() == y.sign())
1380                 bigint_sub3(z.mutablePtr(), x.ptr, x_sw, y.ptr, y_sw);
1381             else
1382                 bigint_add3(z.mutablePtr(), x.ptr, x_sw, y.ptr, y_sw);
1383             z.setSign(x.sign());
1384         }
1385         return z.move();
1386     }
1387 
1388     BigInt opBinary(string op)(auto const ref BigInt y) const
1389         if (op == "-")
1390     {
1391         return opBinary!"-"(&y);
1392     }
1393 
1394     BigInt opBinary(string op)(in word y) const
1395         if (op == "-")
1396     {
1397         return this - BigInt(y);
1398     }
1399 
1400     /*
1401     * Multiplication Operator
1402     */
1403     BigInt opBinary(string op)(const(BigInt)* y) const
1404         if (op == "*")
1405     {
1406         const BigInt* x = &this;
1407         const size_t x_sw = x.sigWords();
1408         const size_t y_sw = y.sigWords();
1409         
1410         BigInt z = BigInt(BigInt.Positive, x.length + y.length);
1411         
1412         if (x_sw == 1 && y_sw)
1413             bigint_linmul3(z.mutablePtr(), y.ptr, y_sw, x.wordAt(0));
1414         else if (y_sw == 1 && x_sw)
1415             bigint_linmul3(z.mutablePtr(), x.ptr, x_sw, y.wordAt(0));
1416         else if (x_sw && y_sw)
1417         {
1418             SecureVector!word workspace = SecureVector!word(z.length);
1419             bigint_mul(z.mutablePtr(), z.length, workspace.ptr,
1420                         x.ptr, x.length, x_sw,
1421                         y.ptr, y.length, y_sw);
1422         }
1423         
1424         if (x_sw && y_sw && x.sign() != y.sign())
1425             z.flipSign();
1426         return z.move();
1427     }
1428 
1429     
1430     BigInt opBinary(string op)(auto const ref BigInt y) const
1431         if (op == "*")
1432     {
1433         return BigInt.opBinary!"*"(&y);
1434     }
1435 
1436 
1437     BigInt opBinary(string op)(in word y) const
1438         if (op == "*")
1439     {
1440         return this * BigInt(y);
1441     }
1442     
1443     /*
1444     * Division Operator
1445     */
1446     BigInt opBinary(string op)(const(BigInt)* y) const
1447         if (op == "/")
1448     {
1449         const BigInt* x = &this;
1450         BigInt q, r;
1451         divide(x, y, &q, &r);
1452         return q.move();
1453     }
1454 
1455     BigInt opBinary(string op)(auto const ref BigInt y) const
1456         if (op == "/")
1457     {
1458         return opBinary!"/"(&y);
1459     }    
1460 
1461     BigInt opBinary(string op)(in word y) const
1462         if (op == "/")
1463     {
1464         return this / BigInt(y);
1465     }
1466 
1467     /*
1468     * Modulo Operator
1469     */
1470     BigInt opBinary(string op)(const(BigInt)* mod) const
1471         if (op == "%")
1472     {
1473         const BigInt* n = &this;
1474         if (mod.isZero())
1475             throw new BigInt.DivideByZero();
1476         if (mod.isNegative())
1477             throw new InvalidArgument("BigInt.operator%: modulus must be > 0");
1478         if (n.isPositive() && mod.isPositive() && *n < mod)
1479             return n.clone;
1480         
1481         BigInt q, r;
1482         divide(n, mod, &q, &r);
1483         return r.move();
1484     }
1485 
1486     BigInt opBinary(string op)(auto const ref BigInt mod) const
1487         if (op == "%")
1488     {
1489         return opBinary!"%"(&mod);
1490     }
1491     /*
1492     * Modulo Operator
1493     */
1494     word opBinary(string op)(word mod) const
1495         if (op == "%")
1496     {
1497         const BigInt* n = &this;
1498         if (mod == 0)
1499             throw new BigInt.DivideByZero();
1500         
1501         if (isPowerOf2(mod))
1502             return (n.wordAt(0) & (mod - 1));
1503         
1504         word remainder = 0;
1505         
1506         for (size_t j = n.sigWords(); j > 0; --j)
1507             remainder = bigint_modop(remainder, n.wordAt(j-1), mod);
1508         
1509         if (remainder && n.sign() == BigInt.Negative)
1510             return mod - remainder;
1511         return remainder;
1512     }
1513     
1514     /*
1515     * Left Shift Operator
1516     */
1517     BigInt opBinary(string op)(size_t shift) const
1518         if (op == "<<")
1519     {
1520         const BigInt* x = &this;
1521         if (shift == 0)
1522             return x.clone();
1523         
1524         const size_t shift_words = shift / MP_WORD_BITS,
1525             shift_bits  = shift % MP_WORD_BITS;
1526         
1527         const size_t x_sw = x.sigWords();
1528         
1529         BigInt y = BigInt(x.sign(), x_sw + shift_words + (shift_bits ? 1 : 0));
1530         bigint_shl2(y.mutablePtr(), x.ptr, x_sw, shift_words, shift_bits);
1531         return y.move();
1532     }
1533     
1534     /*
1535     * Right Shift Operator
1536     */
1537     BigInt opBinary(string op)(size_t shift) const
1538         if (op == ">>")
1539     {
1540         if (shift == 0)
1541             return this.clone;
1542         if (bits() <= shift)
1543             return BigInt(0);
1544         
1545         const size_t shift_words = shift / MP_WORD_BITS,
1546             shift_bits  = shift % MP_WORD_BITS,
1547             x_sw = sigWords();
1548         
1549         BigInt y = BigInt(sign(), x_sw - shift_words);
1550         bigint_shr2(y.mutablePtr(), ptr, x_sw, shift_words, shift_bits);
1551         return y.move();
1552     }
1553 
1554     @property BigInt move() {
1555         return BigInt(m_reg, m_signedness);
1556     }
1557 
1558     @property BigInt clone() const {
1559         return BigInt(m_reg.clone(), m_signedness);
1560     }
1561 
1562     @disable @property BigInt dup();
1563     
1564 private:
1565 
1566     SecureVector!word m_reg;
1567     Sign m_signedness = Positive;
1568 }