Because the square root curve is hard to emulate accross the whole range we want then I've had to split-up the ranges...and this highlights an interesting thing about the square root curve: that it is kind of fractal, or scalable, in nature. You'll see that the formulae used are essentially the same for each range, the only difference being that the numbers are appropriately larger for each range (but proportionally the same). So much so that I could have written this routine in a small neat loop, however there would be a little over-head in executing the loop instructions.
The routine doesn't even think about doing square roots of negative numbers -- for negative numbers it will just spit back the negative number it was given.
long integer_square_root2( long v_square ) { // (c) Jon P 1999 register long temp; temp = v_square; if ( temp > 1 ) { if ( temp < 4 ) { temp++; temp >>= 1; } else { if ( temp < 16 ) { temp += 11; temp = temp / 6; } else { if ( temp < 64 ) //(temp & 0xFFFFFFC0) == 0 { temp += 96; temp = 1520 / temp; temp = 17 - temp; } else { if ( temp < 256 ) { temp += 390; temp = 12020 / temp; temp = 34 - temp; } else { if ( temp < 1024 ) { temp += 1535; temp = 95800 / temp; temp = 69 - temp; } else { if ( temp < 4096 ) { temp += 6185; temp = 767232 / temp; temp = 138 - temp; } else { if ( temp < 16384 ) { temp += 24810; temp = 6137856 / temp; temp = 276 - temp; } else { if ( temp < 65536 ) { temp += 99058; temp = 49086464 / temp; temp = 553 - temp; } else { if ( temp < 262144 ) { temp += 396700; temp = 392822784 / temp; temp = 1106 - temp; } else { if ( temp < 1048576 ) { temp >>= 2; //temp / 4; temp += 396700; temp = 392822784 / temp; temp = 1106 - temp; temp <<= 1; //temp * 2; } else { if ( temp < 4194304 ) { temp >>= 4; //temp / 16; temp += 396700; temp = 392822784 / temp; temp = 1106 - temp; temp <<= 2; //temp * 4; } else { if ( temp < 16777216 ) { temp >>= 6; //temp / 64; temp += 396700; temp = 392822784 / temp; temp = 1106 - temp; temp <<= 3; //temp * 8; } else { if ( temp < 67108864 ) { temp >>= 8; //temp / 256; temp += 396700; temp = 392822784 / temp; temp = 1106 - temp; temp <<= 4; //temp * 16; } else { if ( temp < 268435456 ) { temp >>= 10; //temp / 1024; temp += 396700; temp = 392822784 / temp; temp = 1106 - temp; temp <<= 5; //temp * 32; } else { if ( temp < 1073741824 ) { temp >>= 12; //temp / 4096; temp += 396700; temp = 392822784 / temp; temp = 1106 - temp; temp <<= 6; //temp * 64; } else { temp >>= 14; // 16384; temp += 396700; temp = 392822784 / temp; temp = 1106 - temp; temp <<= 7; //temp * 128; } } } } } } } } } } } } } } } } return temp; }