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 
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()(auto const ref BigInt x, auto const ref BigInt y_arg, ref BigInt q, ref 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             
85             if (x_j0 == y_t)
86                 q_words[j-t-1] = MP_WORD_MAX;
87             else
88                 q_words[j-t-1] = bigint_divop(x_j0, x_j1, y_t);
89             
90             while (divisionCheck(q_words[j-t-1], y_t, y.wordAt(t-1), x_j0, x_j1, r.wordAt(j-2)))
91             {
92                 q_words[j-t-1] -= 1;
93             }
94 			auto y_1 = (y * q_words[j-t-1]);
95 			auto j_t_1 = (j-t-1);
96             r -= y_1 << (MP_WORD_BITS * j_t_1);
97             
98             if (r.isNegative())
99             {
100                 r += y << (MP_WORD_BITS * (j-t-1));
101                 q_words[j-t-1] -= 1;
102             }
103         }
104         r >>= shifts;
105     }
106     
107     signFixup(x, y_arg, q, r);
108 }
109 
110 private:
111 /*
112 * Handle signed operands, if necessary
113 */
114 void signFixup(const ref BigInt x, const ref BigInt y, ref BigInt q, ref BigInt r)
115 {
116     if (x.sign() == BigInt.Negative)
117     {
118         q.flipSign();
119         if (r.isNonzero()) { --q; r = y.abs() - r; }
120     }
121     if (y.sign() == BigInt.Negative)
122         q.flipSign();
123 }
124 
125 bool divisionCheck(word q, word y2, word y1, word x3, word x2, word x1)
126 {
127     // Compute (y3,y2,y1) = (y2,y1) * q
128     
129     word y3 = 0;
130     y1 = word_madd2(q, y1, &y3);
131     y2 = word_madd2(q, y2, &y3);
132 
133     // Return (y3,y2,y1) >? (x3,x2,x1)
134     
135     if (y3 > x3) return true;
136     if (y3 < x3) return false;
137     
138     if (y2 > x2) return true;
139     if (y2 < x2) return false;
140     
141     if (y1 > x1) return true;
142     if (y1 < x1) return false;
143     
144     return false;
145 }