root/trunk/etc/bigint/squareroot.d

Revision 13, 4.4 kB (checked in by Arcane Jill, 5 years ago)

--

Line 
1 module etc.bigint.squareroot;
2 import etc.bigint.bigint_int;
3
4 /*
5
6 Copyright (c) 2004, Arcane Jill
7
8 All rights reserved. Intellectual Property Me Arse!
9
10 Redistribution and use in source and binary forms, with or without modification, are permitted
11 provided that the following conditions are met:
12
13    * Redistributions of source code must retain the above copyright notice, the phrase
14      "Intellectual Property Me Arse!", this list of conditions, and the following disclaimer.
15    * Redistributions in binary form must reproduce the above copyright notice, the phrase
16      "Intellectual Property Me Arse!", this list of conditions and the following disclaimer
17      in the documentation and/or other materials provided with the distribution.
18    * The name Arcane Jill may not be used to endorse or promote products derived from this
19      software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
22 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER,
24 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED, AND ON ANY
27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
29 OF SUCH DAMAGE.
30
31 */
32
33 /*  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
34     Returns the integer square root of x, ignoring the remainder
35 */
36 Int sqrt(Int x)
37 {
38     Int r;
39     return sqrt(x, r);
40 }
41
42 /*  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
43     Returns the integer square root of x, and the remainder
44 */
45 Int sqrt(Int x, out Int r)
46 out(z)
47 {
48     assert(z*z + r == x);
49 }
50 body
51 {
52     if (x < 0) throw new IntException("sqrt(x) not defined for x < 0");
53     if (x < 2) { r = Int.ZERO; return x; }
54
55     Int q = Int.ZERO;
56     r = Int.ZERO;
57
58     uint msd = x[x.end-1];
59     uint b = bsr(msd) & ~1u;
60     msd <<= 30 - b;
61
62     for (int j=b>>>1; j>=0; --j)
63     {
64         msd = sqrtInternal(q, r, msd);
65     }
66
67     for (int i=x.end-2; i>=0; --i)
68     {
69         msd = x[i];
70         for (int j=15; j>=0; --j)
71         {
72             msd = sqrtInternal(q, r, msd);
73         }
74     }
75
76     return q;
77 }
78
79 private
80 {
81     uint sqrtInternal(inout Int q, inout Int r, uint msd)
82     {
83         q = q + q;
84         r = (r << 2) | (msd >> 30);
85         Int divisor = new Int(q);
86         divisor = (divisor + divisor) | 1u;
87         if (divisor <= r)
88         {
89             r = r - divisor;
90             q = q + 1;
91         }
92         return msd << 2;
93     }
94 }
95
96 bool isSquare(Int x)
97 {
98     // First test is modulo 0x1000
99     if (x.negative) return false;
100     if (x < 2) return true;
101     uint n = x[0] & 0xFFFF;
102     bool b = squareTableLookup(n);
103     if (!b) return false;
104
105     // Next we do a pseudosqaure test
106     /**** NOT YET WRITTEN ****/
107
108     // Finally, we give up and do a square root
109     Int r;
110     sqrt(x, r);
111     return r.equalsZero;
112 }
113
114 private
115 {
116     ubyte[64] SQUARE_TABLE =
117     [
118         0x05, 0x01, 0x04, 0x00, 0x05, 0x00, 0x04, 0x00,
119         0x04, 0x01, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00,
120         0x05, 0x01, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00,
121         0x04, 0x01, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00,
122         0x04, 0x01, 0x04, 0x00, 0x05, 0x00, 0x04, 0x00,
123         0x04, 0x01, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00,
124         0x04, 0x01, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00,
125         0x04, 0x01, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00
126     ];
127
128     bool squareTableLookup(uint n)
129     in
130     {
131         assert(n < 0x10000);
132     }
133     body
134     {
135         uint bitnum = n & 7;
136         uint col = (n >> 3) & 0x0F;
137         uint row = n >> 7;
138         uint lookup;
139         switch (col)
140         {
141             case 1:
142             case 3:
143             case 5:
144             case 6:
145             case 7:
146             case 9:
147             case 10:
148             case 11:
149             case 13:
150             case 14:
151             case 15:
152                 lookup = 0x02;
153                 break;
154
155             case 4:
156             case 12:
157                 lookup = 0x12;
158                 break;
159
160             case 2:
161                 lookup = 0x03;
162                 break;
163
164             case 8:
165                 lookup = ((row & 3) == 0) ? 0x13 : 0x12;
166                 break;
167
168             case 0:
169                 lookup = squareTableLookup2(col);
170                 break;
171         }
172         return (((1 << bitnum) & lookup) != 0);
173     }
174
175     ubyte squareTableLookup2(uint n)
176     {
177         uint bitnum = n & 7;
178         uint col = n >> 3;
179         ubyte lookup = SQUARE_TABLE[col];
180         return (((1 << bitnum) & lookup) != 0) ? 0x13 : 0x12;
181     }
182 }
Note: See TracBrowser for help on using the browser.