isqrt.c

00001 /*
00002   \brief 整数型の平方根関数
00003 
00004   http://www.infoeddy.ne.jp/~tensyo/prog/ALGO.HTM#STEPMT より
00005 
00006   \ahthor Satofumi KAMIMURA (maintenance)
00007   $Id$
00008 */
00009 
00010 #include "isqrt.h"
00011 
00012 
00021 unsigned long isqrt(unsigned long i) {
00022   int sft = 0;
00023   unsigned short y, y0, y1, sum;
00024 
00025   if (i < 2) {
00026     return i;
00027   }
00028   while (0 < (signed long)i) { /* MSB=1 になるまで左シフト */
00029     i <<= 1L;
00030     sft++;
00031   }
00032   y1 = (unsigned short)(i >> 16L);
00033   y0 = (~y1) & 0xffff;
00034   y = (y0 * 0x8000) >> 16;
00035   sum = y;
00036   y = (y * y0) >> 16;
00037   y = (y * 0x4000) >> 16;       /* シフトで代用可 */
00038   sum += y;
00039   y = (y * y0) >> 16;
00040   y = (y * 0x8000) >> 16;       /* シフトで代用可 */
00041   sum += y;
00042   y = (y * y0) >> 16;
00043   y = (y * 40960) >> 16;
00044   sum += y;                     /* 40960 = 5*2^13  */
00045   y = (y * y0) >> 16;
00046   y = (y * 45875) >> 16;
00047   sum += y;
00048   y = ~sum;
00049   y +=  ((signed short)((i -(unsigned long)y * (unsigned long)y) >> 16L)) >> 1;
00050   if (sft & 1) {
00051     sft >>= 1;
00052     y = (unsigned short)((0x8000L + (unsigned long)(y >> sft) * 46341L)>> 16L);
00053   }else {
00054     sft >>= 1;
00055     y = y >> sft;
00056   }
00057   return y;
00058 }
00059 

Generated on Mon Apr 13 22:52:04 2009 by  doxygen 1.5.7.1