http://atoms.alife.co.uk/sqrt/index.html
/* * Integer Square Root function * Contributors include Arne Steinarson for the basic approximation idea, Dann * Corbit and Mathew Hendry for the first cut at the algorithm, Lawrence Kirby * for the rearrangement, improvments and range optimization, Paul Hsieh * for the round-then-adjust idea, Tim Tyler, for the Java port * and Jeff Lawson for a bug-fix and some code to improve accuracy. * * * v0.02 - 2003/09/07 */ /** * Faster replacements for (int)(java.lang.Math.sqrt(integer)) */ public class SquareRoot { final static int [] table = { 0 , 16 , 22 , 27 , 32 , 35 , 39 , 42 , 45 , 48 , 50 , 53 , 55 , 57 , 59 , 61 , 64 , 65 , 67 , 69 , 71 , 73 , 75 , 76 , 78 , 80 , 81 , 83 , 84 , 86 , 87 , 89 , 90 , 91 , 93 , 94 , 96 , 97 , 98 , 99 , 101 , 102 , 103 , 104 , 106 , 107 , 108 , 109 , 110 , 112 , 113 , 114 , 115 , 116 , 117 , 118 , 119 , 120 , 121 , 122 , 123 , 124 , 125 , 126 , 128 , 128 , 129 , 130 , 131 , 132 , 133 , 134 , 135 , 136 , 137 , 138 , 139 , 140 , 141 , 142 , 143 , 144 , 144 , 145 , 146 , 147 , 148 , 149 , 150 , 150 , 151 , 152 , 153 , 154 , 155 , 155 , 156 , 157 , 158 , 159 , 160 , 160 , 161 , 162 , 163 , 163 , 164 , 165 , 166 , 167 , 167 , 168 , 169 , 170 , 170 , 171 , 172 , 173 , 173 , 174 , 175 , 176 , 176 , 177 , 178 , 178 , 179 , 180 , 181 , 181 , 182 , 183 , 183 , 184 , 185 , 185 , 186 , 187 , 187 , 188 , 189 , 189 , 190 , 191 , 192 , 192 , 193 , 193 , 194 , 195 , 195 , 196 , 197 , 197 , 198 , 199 , 199 , 200 , 201 , 201 , 202 , 203 , 203 , 204 , 204 , 205 , 206 , 206 , 207 , 208 , 208 , 209 , 209 , 210 , 211 , 211 , 212 , 212 , 213 , 214 , 214 , 215 , 215 , 216 , 217 , 217 , 218 , 218 , 219 , 219 , 220 , 221 , 221 , 222 , 222 , 223 , 224 , 224 , 225 , 225 , 226 , 226 , 227 , 227 , 228 , 229 , 229 , 230 , 230 , 231 , 231 , 232 , 232 , 233 , 234 , 234 , 235 , 235 , 236 , 236 , 237 , 237 , 238 , 238 , 239 , 240 , 240 , 241 , 241 , 242 , 242 , 243 , 243 , 244 , 244 , 245 , 245 , 246 , 246 , 247 , 247 , 248 , 248 , 249 , 249 , 250 , 250 , 251 , 251 , 252 , 252 , 253 , 253 , 254 , 254 , 255 }; /** * A faster replacement for (int)(java.lang.Math.sqrt(x)). Completely accurate for x < 2147483648 (i.e. 2^31)... */ static int sqrt( int x) { int xn; if (x >= 0x10000 ) { if (x >= 0x1000000 ) { if (x >= 0x10000000 ) { if (x >= 0x40000000 ) { xn = table[x >> 24 ] << 8 ; } else { xn = table[x >> 22 ] << 7 ; } } else { if (x >= 0x4000000 ) { xn = table[x >> 20 ] << 6 ; } else { xn = table[x >> 18 ] << 5 ; } } xn = (xn + 1 + (x / xn)) >> 1 ; xn = (xn + 1 + (x / xn)) >> 1 ; return ((xn * xn) > x) ? -- xn : xn; } else { if (x >= 0x100000 ) { if (x >= 0x400000 ) { xn = table[x >> 16 ] << 4 ; } else { xn = table[x >> 14 ] << 3 ; } } else { if (x >= 0x40000 ) { xn = table[x >> 12 ] << 2 ; } else { xn = table[x >> 10 ] << 1 ; } } xn = (xn + 1 + (x / xn)) >> 1 ; return ((xn * xn) > x) ? -- xn : xn; } } else { if (x >= 0x100 ) { if (x >= 0x1000 ) { if (x >= 0x4000 ) { xn = (table[x >> 8 ]) + 1 ; } else { xn = (table[x >> 6 ] >> 1 ) + 1 ; } } else { if (x >= 0x400 ) { xn = (table[x >> 4 ] >> 2 ) + 1 ; } else { xn = (table[x >> 2 ] >> 3 ) + 1 ; } } return ((xn * xn) > x) ? -- xn : xn; } else { if (x >= 0 ) { return table[x] >> 4 ; } } } illegalArgument(); return - 1 ; } /** * A faster replacement for (int)(java.lang.Math.sqrt(x)). Completely accurate for x < 2147483648 (i.e. 2^31)... * Adjusted to more closely approximate * "(int)(java.lang.Math.sqrt(x) + 0.5)" * by Jeff Lawson. */ static int accurateSqrt( int x) { int xn; if (x >= 0x10000 ) { if (x >= 0x1000000 ) { if (x >= 0x10000000 ) { if (x >= 0x40000000 ) { xn = table[x >> 24 ] << 8 ; } else { xn = table[x >> 22 ] << 7 ; } } else { if (x >= 0x4000000 ) { xn = table[x >> 20 ] << 6 ; } else { xn = table[x >> 18 ] << 5 ; } } xn = (xn + 1 + (x / xn)) >> 1 ; xn = (xn + 1 + (x / xn)) >> 1 ; return adjustment(x, xn); } else { if (x >= 0x100000 ) { if (x >= 0x400000 ) { xn = table[x >> 16 ] << 4 ; } else { xn = table[x >> 14 ] << 3 ; } } else { if (x >= 0x40000 ) { xn = table[x >> 12 ] << 2 ; } else { xn = table[x >> 10 ] << 1 ; } } xn = (xn + 1 + (x / xn)) >> 1 ; return adjustment(x, xn); } } else { if (x >= 0x100 ) { if (x >= 0x1000 ) { if (x >= 0x4000 ) { xn = (table[x >> 8 ]) + 1 ; } else { xn = (table[x >> 6 ] >> 1 ) + 1 ; } } else { if (x >= 0x400 ) { xn = (table[x >> 4 ] >> 2 ) + 1 ; } else { xn = (table[x >> 2 ] >> 3 ) + 1 ; } } return adjustment(x, xn); } else { if (x >= 0 ) { return adjustment(x, table[x] >> 4 ); } } } illegalArgument(); return - 1 ; } private static int adjustment( int x, int xn) { // Added by Jeff Lawson: // need to test: // if |xn * xn - x| > |x - (xn-1) * (xn-1)| then xn-1 is more accurate // if |xn * xn - x| > |(xn+1) * (xn+1) - x| then xn+1 is more accurate // or, for all cases except x == 0: // if |xn * xn - x| > x - xn * xn + 2 * xn - 1 then xn-1 is more accurate // if |xn * xn - x| > xn * xn + 2 * xn + 1 - x then xn+1 is more accurate int xn2 = xn * xn; // |xn * xn - x| int comparitor0 = xn2 - x; if (comparitor0 < 0 ) { comparitor0 = - comparitor0; } int twice_xn = xn << 1 ; // |x - (xn-1) * (xn-1)| int comparitor1 = x - xn2 + twice_xn - 1 ; if (comparitor1 < 0 ) { // need to correct for x == 0 case? comparitor1 = - comparitor1; // only gets here when x == 0 } // |(xn+1) * (xn+1) - x| int comparitor2 = xn2 + twice_xn + 1 - x; if (comparitor0 > comparitor1) { return (comparitor1 > comparitor2) ? ++ xn : -- xn; } return (comparitor0 > comparitor2) ? ++ xn : xn; } /** * A *much* faster replacement for (int)(java.lang.Math.sqrt(x)). Completely accurate for x < 289... */ static int fastSqrt( int x) { if (x >= 0x10000 ) { if (x >= 0x1000000 ) { if (x >= 0x10000000 ) { if (x >= 0x40000000 ) { return (table[x >> 24 ] << 8 ); } else { return (table[x >> 22 ] << 7 ); } } else if (x >= 0x4000000 ) { return (table[x >> 20 ] << 6 ); } else { return (table[x >> 18 ] << 5 ); } } else if (x >= 0x100000 ) { if (x >= 0x400000 ) { return (table[x >> 16 ] << 4 ); } else { return (table[x >> 14 ] << 3 ); } } else if (x >= 0x40000 ) { return (table[x >> 12 ] << 2 ); } else { return (table[x >> 10 ] << 1 ); } } else if (x >= 0x100 ) { if (x >= 0x1000 ) { if (x >= 0x4000 ) { return (table[x >> 8 ]); } else { return (table[x >> 6 ] >> 1 ); } } else if (x >= 0x400 ) { return (table[x >> 4 ] >> 2 ); } else { return (table[x >> 2 ] >> 3 ); } } else if (x >= 0 ) { return table[x] >> 4 ; } illegalArgument(); return - 1 ; } private static void illegalArgument() { throw new IllegalArgumentException( " Attemt to take the square root of negative number " ); } /** From http://research.microsoft.com/ ~hollasch/cgindex/math/introot.html * where it is presented by Ben Discoe (rodent@netcom.COM) * Not terribly speedy... */ /* static int unrolled_sqrt(int x) { int v; int t = 1<<30; int r = 0; int s; s = t + r; r>>= 1; if (s <= x) { x -= s; r |= t;} t >>= 2; s = t + r; r>>= 1; if (s <= x) { x -= s; r |= t;} t >>= 2; s = t + r; r>>= 1; if (s <= x) { x -= s; r |= t;} t >>= 2; s = t + r; r>>= 1; if (s <= x) { x -= s; r |= t;} t >>= 2; s = t + r; r>>= 1; if (s <= x) { x -= s; r |= t;} t >>= 2; s = t + r; r>>= 1; if (s <= x) { x -= s; r |= t;} t >>= 2; s = t + r; r>>= 1; if (s <= x) { x -= s; r |= t;} t >>= 2; s = t + r; r>>= 1; if (s <= x) { x -= s; r |= t;} t >>= 2; s = t + r; r>>= 1; if (s <= x) { x -= s; r |= t;} t >>= 2; s = t + r; r>>= 1; if (s <= x) { x -= s; r |= t;} t >>= 2; s = t + r; r>>= 1; if (s <= x) { x -= s; r |= t;} t >>= 2; s = t + r; r>>= 1; if (s <= x) { x -= s; r |= t;} t >>= 2; s = t + r; r>>= 1; if (s <= x) { x -= s; r |= t;} t >>= 2; s = t + r; r>>= 1; if (s <= x) { x -= s; r |= t;} t >>= 2; s = t + r; r>>= 1; if (s <= x) { x -= s; r |= t;} t >>= 2; s = t + r; r>>= 1; if (s <= x) { x -= s; r |= t;} return r; } */ /** * Mark Borgerding's algorithm... * Not terribly speedy... */ /* static int mborg_sqrt(int val) { int guess=0; int bit = 1 << 15; do { guess ^= bit; // check to see if we can set this bit without going over sqrt(val)... if (guess * guess > val ) guess ^= bit; // it was too much, unset the bit... } while ((bit >>= 1) != 0); return guess; } */ /** * Taken from http://www.jjj.de/isqrt.cc * Code not tested well... * Attributed to: http://www.tu-chemnitz.de/ ~arndt/joerg.html / email: arndt@physik.tu-chemnitz.de * Slow. */ /* final static int BITS = 32; final static int NN = 0; // range: 0...BITSPERLONG/2 final static int test_sqrt(int x) { int i; int a = 0; // accumulator... int e = 0; // trial product... int r; r=0; // remainder... for (i=0; i < (BITS/2) + NN; i++) { r <<= 2; r += (x >> (BITS - 2)); x <<= 2; a <<= 1; e = (a << 1)+1; if(r >= e) { r -= e; a++; } } return a; } */ /* // Totally hopeless performance... static int test_sqrt(int n) { float r = 2.0F; float s = 0.0F; for(; r < (float)n / r; r *= 2.0F); for(s = (r + (float)n / r) / 2.0F; r - s > 1.0F; s = (r + (float)n / r) / 2.0F) { r = s; } return (int)s; } */ }