1 /**
2 * Division
3 * 
4 * Copyright:
5 * (C) 1999-2007 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *
8 * License:
9 * Botan is released under the Simplified BSD License (see LICENSE.md)
10 */
11 module botan.math.bigint.divide;
12 
13 import botan.constants;
14 import botan.math.bigint.bigint;
15 import botan.math.mp.mp_core;
16 import botan.constants;
17 import std.algorithm : max;
18 /**
19 * BigInt Division
20 * Params:
21 *  x = an integer
22 *  y_arg = a non-zero integer
23 *  q = will be set to x / y
24 *  r = will be set to x % y
25 */
26 void divide(const(BigInt)* x, const(BigInt)* y_arg, BigInt* q, BigInt* r)
27 {
28     /*
29     * Solve x = q * y + r
30     */
31     if (y_arg.isZero())
32         throw new BigInt.DivideByZero();
33     
34     BigInt y = y_arg.dup;
35     const size_t y_words = y.sigWords();
36     
37     *r = x.dup;
38     *q = 0;
39     
40     r.setSign(BigInt.Positive);
41     y.setSign(BigInt.Positive);
42     
43     int compare = r.cmp(y);
44     
45     if (compare == 0)
46     {
47         *q = 1;
48         *r = 0;
49     }
50     else if (compare > 0)
51     {
52         size_t shifts = 0;
53         word y_top = y.wordAt(y.sigWords()-1);
54         while (y_top < MP_WORD_TOP_BIT) { y_top <<= 1; ++shifts; }
55         y <<= shifts;
56         *r <<= shifts;
57         
58         const size_t n = r.sigWords() - 1, t = y_words - 1;
59         
60         if (n < t)
61             throw new InternalError("BigInt division word sizes");
62         
63         q.growTo(n - t + 1);
64         
65         word* q_words = q.mutablePtr();
66         
67         if (n <= t)
68         {
69             while (*r > y) { *r -= y; ++(*q); }
70             *r >>= shifts;
71             signFixup(x, y_arg, q, r);
72             return;
73         }
74         
75         BigInt temp = y << (MP_WORD_BITS * (n-t));
76         
77         while (*r >= temp) { *r -= temp; q_words[n-t] += 1; }
78         
79         for (size_t j = n; j != t; --j)
80         {
81             const word x_j0  = r.wordAt(j);
82             const word x_j1 = r.wordAt(j-1);
83             const word y_t  = y.wordAt(t);
84             if (y_t == 0)
85                 throw new InvalidArgument("Division by zero due to too large bn");
86             
87             if (x_j0 == y_t)
88                 q_words[j-t-1] = MP_WORD_MAX;
89             else
90                 q_words[j-t-1] = bigint_divop(x_j0, x_j1, y_t);
91             
92             while (divisionCheck(q_words[j-t-1], y_t, y.wordAt(t-1), x_j0, x_j1, r.wordAt(j-2)))
93             {
94                 q_words[j-t-1] -= 1;
95             }
96 			auto y_1 = (y * q_words[j-t-1]);
97 			auto j_t_1 = (j-t-1);
98             y_1 <<= (MP_WORD_BITS * j_t_1);
99             *r -= y_1;
100             
101             if (r.isNegative())
102             {
103                 y <<= (MP_WORD_BITS * (j-t-1));
104                 *r += y;
105                 q_words[j-t-1] -= 1;
106             }
107         }
108         *r >>= shifts;
109     }
110     
111     signFixup(x, y_arg, q, r);
112 }
113 
114 private:
115 /*
116 * Handle signed operands, if necessary
117 */
118 void signFixup(const(BigInt)* x, const(BigInt)* y, BigInt* q, BigInt* r)
119 {
120     if (x.sign() == BigInt.Negative)
121     {
122         q.flipSign();
123         if (r.isNonzero()) { --*q; *r = y.abs() - *r; }
124     }
125     if (y.sign() == BigInt.Negative)
126         q.flipSign();
127 }
128 
129 bool divisionCheck(word q, word y2, word y1, word x3, word x2, word x1)
130 {
131     // Compute (y3,y2,y1) = (y2,y1) * q
132     
133     word y3 = 0;
134     y1 = word_madd2(q, y1, &y3);
135     y2 = word_madd2(q, y2, &y3);
136 
137     // Return (y3,y2,y1) >? (x3,x2,x1)
138     
139     if (y3 > x3) return true;
140     if (y3 < x3) return false;
141     
142     if (y2 > x2) return true;
143     if (y2 < x2) return false;
144     
145     if (y1 > x1) return true;
146     if (y1 < x1) return false;
147     
148     return false;
149 }