floatspc.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. /*---------------------------------------------------------------------------
  2. * 版 本 号: 1.00 版本号
  3. * 文 件 名: floatspc.c
  4. * 生成日期: 2006.04.30
  5. * 作 者: 钟振新
  6. -----------------------------------------------------------------------------
  7. 单精度浮点数
  8. ----------------------------------
  9. | s | J | A(a22....a0) |
  10. ----------------------------------
  11. | 31 | 30--23 | 22 ------ 0 |
  12. ----------------------------------
  13. s:尾符,1为负数,0为正数;
  14. J:用移码表示的阶码,J=127 + 实际阶码;
  15. A:用原码表示的尾数小数部分,作为规格化的数,整数个位均为1,表示时该位隐含。
  16. -----------------------------------------------------------------------------*/
  17. #include "head.h"
  18. /******************************************************************************
  19. * 长整数快速求平方根,绝对误差不大于0.5,在数小于9702时会出现大于0.5%的误差,
  20. * 在数小于2351时会出现大于1.0%的误差.
  21. ******************************************************************************/
  22. unsigned short sqrt_16(uint32_t x)
  23. {
  24. FAST unsigned short y, i;
  25. FAST uint32_t temp1, temp2; /* 结果、循环计数*/
  26. if (x == 0)
  27. return 0;
  28. y = 0;
  29. temp1 = (x >> 30); /* 取最高位和次高位*/
  30. x <<= 2;
  31. if (temp1 >= 1)
  32. {
  33. y ++; /* 商最高位为1*/
  34. temp1 -= y;
  35. }
  36. for (i = 15; i > 0; i--) /* 求低15位,类似求最高位*/
  37. {
  38. y <<= 1;
  39. temp1 <<= 2;
  40. temp1 += (x >> 30);
  41. temp2 = y;
  42. temp2 = (temp2<<1)+1;
  43. x <<= 2;
  44. if (temp1 >= temp2)
  45. {
  46. temp1 -= temp2;
  47. y ++;
  48. }
  49. }
  50. if ((temp1 << 1) > temp2) /*大于0.5末尾进一位*/
  51. {
  52. y++;
  53. }
  54. /*等于0.5且商为奇数末尾进一位(单进双不进)*/
  55. else if (((temp1 << 1) == temp2) && ((y & 1) == 1))
  56. {
  57. y++;
  58. }
  59. return y;
  60. }
  61. /*******************************************************************************
  62. * float sqrt_32f(uint32_t x)
  63. * 长整数快速求平方根,返回精确浮点数,浮点数只做了一次类型转换和浮点数加法。在无浮点
  64. * 测试:
  65. * 1.边界测试0-0xffffffff无异常现象;
  66. * 2.在0-0xffffffff下绝对误差(e = sqrt_32f(x) - sqrt(x))不超过±0.01,相对误差
  67. * e = sqrt_32f(x)/sqrt(x) - 1,不超过±0.00005。
  68. 测试纪录:
  69. 绝对误差超过0.01的项:无。总测试样例(0-4294967295)。
  70. 相对误差>0.00005的值,共计94项,但不超过0.00006,总测试样例(0-4294967295)。
  71. *******************************************************************************/
  72. float sqrt_32f(uint32_t x)
  73. {
  74. FAST uint32_t y;
  75. FAST uint32_t i,m,n,temp1,temp2,*ulp ;
  76. float t ;
  77. if ((x == 0) || (x == 1)) return x;
  78. y = 0;
  79. m = 0;
  80. n = 0;
  81. ulp = (uint32_t*)&t;
  82. while(x < 16384) /*提高小数值时的精度*/
  83. {
  84. x <<= 14;
  85. m++;
  86. }
  87. /*求整数根的最高位*/
  88. temp1 = (x >> 30);
  89. x <<= 2;
  90. if (temp1 >= 1)
  91. {
  92. y++; /* 最高位为1*/
  93. temp1 -= y;
  94. }
  95. /*求整数根的低15位,类似求最高位*/
  96. for (i = 15; i > 0; i--)
  97. {
  98. y <<= 1;
  99. temp1 <<= 2;
  100. temp1 += (x >> 30);
  101. temp2 = y;
  102. temp2 = (temp2 << 1) + 1;
  103. x <<= 2;
  104. if (temp1 >= temp2)
  105. {
  106. temp1 -= temp2;
  107. y++;
  108. }
  109. }
  110. /*整数根*/
  111. if ((temp1 == 0)) /*|| (temp2 == 0)) 不会出现temp2=0的情况*/
  112. {
  113. while(m) /*检查是否是放大了的数*/
  114. {
  115. m--;
  116. y >>= 7;
  117. }
  118. return y;
  119. }
  120. if (temp1 >= temp2)
  121. {
  122. y++;
  123. while(m) /*检查是否是放大了的数*/
  124. {
  125. m--;
  126. y >>= 7;
  127. }
  128. return y;
  129. }
  130. /*求根的小数部分,返回指定精度浮点数*/
  131. while (temp1 < temp2) /*防止出现浮点数0的情况*/
  132. {
  133. n++;
  134. temp1 = (temp1 << 14);
  135. }
  136. temp1 = temp1 / temp2; /*化小数商为整数,小数点后有效数字4位*/
  137. t = (float)temp1;
  138. while(n)
  139. {
  140. n--;
  141. *ulp -= 0x07000000; /*浮点数指数减14,恢复放大的小数商*/
  142. }
  143. /*合并小数和整数*/
  144. t += y;
  145. /*检查是否是放大了根*/
  146. while(m)
  147. {
  148. m--;
  149. *ulp -= 0x03800000; /*指数减7*/
  150. }
  151. return t;
  152. }
  153. /******************************************************************************
  154. *浮点数快速求平方根
  155. ******************************************************************************/
  156. float sqrt_f(float x)
  157. {
  158. FAST uint32_t m,y;
  159. FAST uint32_t i,j,k,n,temp1,temp2,*ulp;
  160. float t ;
  161. t = x;
  162. j = 0;
  163. k = 0;
  164. n = 0;
  165. y = 0;
  166. ulp = (uint32_t*)&t;
  167. if (((*ulp) & 0x7f800000) == 0) /* 为浮点数0 */
  168. {
  169. return 0;
  170. }
  171. if (((*ulp) & 0x80000000) == 0x80000000) /*负数*/
  172. {
  173. return 0;
  174. }
  175. if (((*ulp) & 0x7f800000) >= 0x4f000000) /*大于等于2^31,缩小,不会丢失有效数字*/
  176. {
  177. k = (((*ulp) & 0x7f800000) - 0x4f000000) & 0x7f000000 ; /*取阶码的差,屏蔽最低位,使之成为偶数*/
  178. k += 0x01000000; /*偶数的阶码差再加2*/
  179. *ulp -= k;
  180. k >>= 1;
  181. }
  182. if (((*ulp) & 0x7f800000) <= 0x47800000) /*小于等于2^17,放大,达到较多的整数位*/
  183. {
  184. j = (0x47800000 - ((*ulp) & 0x7f800000)) & 0x7f000000 ; /*取阶码的差,屏蔽最低位,使之成为偶数*/
  185. j += 0x01000000; /*偶数的阶码差再加2*/
  186. *ulp += j;
  187. j >>= 1;
  188. }
  189. m = (uint32_t )t; /*取调整后的浮点数的整数部分,纯小数取小数后5位小数位*/
  190. /*求结果的最高位*/
  191. temp1 = (m >> 30);
  192. m <<= 2;
  193. if (temp1 >= 1)
  194. {
  195. y++; /* 最高位为1*/
  196. temp1 -= y;
  197. }
  198. /*求低15位,类似求最高位*/
  199. for (i = 15; i > 0; i--)
  200. {
  201. y <<= 1;
  202. temp1 <<= 2;
  203. temp1 += (m >> 30);
  204. temp2 = y;
  205. temp2 = (temp2 << 1) + 1;
  206. m <<= 2;
  207. if (temp1 >= temp2)
  208. {
  209. temp1 -= temp2;
  210. y++;
  211. }
  212. }
  213. /*整数根*/
  214. if ((temp1 == 0)) /*|| (temp2 == 0)) 不会出现temp2=0的情况*/
  215. {
  216. t = y;
  217. if(j != 0)
  218. {
  219. *ulp -= j; /* 恢复放大的根*/
  220. }
  221. if(k != 0)
  222. {
  223. *ulp += k; /* 恢复缩小的根*/
  224. }
  225. return t;
  226. }
  227. if (temp1 >= temp2)
  228. {
  229. y++;
  230. t = y;
  231. if(j != 0)
  232. {
  233. *ulp -= j; /* 恢复放大的根*/
  234. }
  235. if(k != 0)
  236. {
  237. *ulp += k; /* 恢复缩小的根*/
  238. }
  239. return t;
  240. }
  241. /*求小数位*/
  242. while (temp1 < temp2) /*防止出现浮点数0的情况*/
  243. {
  244. n++;
  245. temp1 <<= 14;
  246. }
  247. temp1 = temp1 / temp2; /*化小数商为整数,小数点后有效数字4位*/
  248. t = (float)temp1;
  249. while (n)
  250. {
  251. n--;
  252. *ulp -= 0x07000000; /*浮点数指数减14,恢复放大的小数商*/
  253. }
  254. /*合并小数和整数*/
  255. t = y + t;
  256. /*检查是否有缩小或放大*/
  257. if(j != 0)
  258. {
  259. *ulp -= j; /* 恢复放大的根*/
  260. }
  261. if(k != 0)
  262. {
  263. *ulp += k; /* 恢复缩小的根*/
  264. }
  265. return t; /*返回浮点数根*/
  266. }
  267. // 浮点有效性检查
  268. int isnan_f (void * _f)
  269. {
  270. _rtl_float_t *p = (_rtl_float_t *) _f;
  271. if ((p->i32.s.high16.value & 0x7F80) == 0x7F80) //阶码全为1
  272. {
  273. if (((p->i32.s.high16.value & 0x007F) == 0) && (p->i32.s.low16.value == 0)) //尾数全为0
  274. {
  275. return _FPCLASS_OVER; //无穷大(+INF,-INF)
  276. }
  277. else //非法数据(NaN,no a number)
  278. {
  279. if ((p->i32.s.high16.value & 0x007f) == 0) //尾数最高位为1
  280. {
  281. return _FPCLASS_SNAN; // Signaling NAN returns 1 发信号的NaN(S)
  282. }
  283. else //尾数最高位为0
  284. {
  285. return _FPCLASS_QNAN; // Quiet NAN returns 2 不发信号的NaN(Q)
  286. }
  287. }
  288. }
  289. return 0;
  290. }
  291. /*****************************************************************************
  292. 函数名称:DWORD sqrt_32fix(DWORD x)
  293. 函数版本:V1.00.00
  294. 作 者:钟振新
  295. 创建日期:2007.07.25
  296. 函数功能说明:定点数快速求平方根,高16位为整数部分,低16位为小数部分
  297. 输入参数: x = 无符号长整数
  298. 输出参数: 无
  299. 返 回 值: 32位定点数根
  300. 函数扇出清单:
  301. 函数扇入清单:
  302. 函数体中用到的公共资源:
  303. 更新后的上述资源:
  304. ******************************************************************************/
  305. DWORD sqrt_32fix(DWORD x)
  306. {
  307. DWORD y;
  308. DWORD i,m,n,temp1,temp2;
  309. if (x == 0)
  310. {
  311. y=0;
  312. return y;
  313. }
  314. if (x == 1)
  315. {
  316. y=65536;
  317. return y;
  318. }
  319. y = 0;
  320. m = 0;
  321. n = 0;
  322. while(x < 16384) /*提高小数值时的精度*/
  323. {
  324. x <<= 14;
  325. m++;
  326. }
  327. /* net_section begin */ /*net_section代码来自网络 */
  328. /*求整数根的最高位*/
  329. temp1 = (x >> 30);
  330. x <<= 2;
  331. if (temp1 >= 1)
  332. {
  333. y++; /* 最高位为1*/
  334. temp1 -= y;
  335. }
  336. /*求整数根的低15位,类似求最高位*/
  337. for (i = 15; i > 0; i--)
  338. {
  339. y <<= 1;
  340. temp1 <<= 2;
  341. temp1 += (x >> 30);
  342. temp2 = y;
  343. temp2 = (temp2 << 1) + 1;
  344. x <<= 2;
  345. if (temp1 >= temp2)
  346. {
  347. temp1 -= temp2;
  348. y++;
  349. }
  350. }
  351. /* net section end *******************/
  352. /*整数根*/
  353. if (temp1 == 0)
  354. {
  355. while(m) /*检查是否是放大了的数*/
  356. {
  357. m--;
  358. y >>= 7;
  359. }
  360. return (y << 16);
  361. }
  362. if (temp1 >= temp2)
  363. {
  364. y++;
  365. while(m) /*检查是否是放大了的数*/
  366. {
  367. m--;
  368. y >>= 7;
  369. }
  370. return (y << 16);
  371. }
  372. /*求根的小数部分,返回指定精度浮点数*/
  373. while (temp1 < temp2) /*防止出现浮点数0的情况*/
  374. {
  375. n++;
  376. temp1 = (temp1 << 14);
  377. }
  378. temp1 = temp1 / temp2; /*化小数商为整数,小数点后有效数字4位*/
  379. if (n == 0)
  380. {
  381. temp1 <<= 16;
  382. }
  383. while(n)
  384. {
  385. n--;
  386. temp1 <<= 2; /*浮点数指数减14,恢复放大的小数商(折算为65536的倍数)*/
  387. }
  388. /*合并小数和整数*/
  389. /*检查是否是放大了根*/
  390. while(m)
  391. {
  392. m--;
  393. temp1 += ((y % 128) << 16); /*指数减7*/
  394. temp1 >>= 7;
  395. y >>= 7; /*指数减7*/
  396. }
  397. y = (y << 16) + temp1; /*合并整数和小数部分*/
  398. return y;
  399. }
  400. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  401. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  402. /*********************************************************************************************
  403. * END *
  404. *********************************************************************************************/