| 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 |
} |
|---|