bh_math.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. /*-
  2. * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  3. *
  4. * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  17. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  20. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  22. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26. * SUCH DAMAGE.
  27. *
  28. * $FreeBSD$
  29. */
  30. #include "bh_platform.h"
  31. #define __FDLIBM_STDC__
  32. typedef uint32_t u_int32_t;
  33. typedef uint64_t u_int64_t;
  34. typedef union u32double_tag {
  35. int *pint;
  36. double *pdouble;
  37. } U32DOUBLE;
  38. static inline int *
  39. pdouble2pint(double *pdouble)
  40. {
  41. U32DOUBLE u;
  42. u.pdouble = pdouble;
  43. return u.pint;
  44. }
  45. typedef union
  46. {
  47. double value;
  48. struct
  49. {
  50. u_int32_t lsw;
  51. u_int32_t msw;
  52. } parts;
  53. struct
  54. {
  55. u_int64_t w;
  56. } xparts;
  57. } ieee_double_shape_type_little;
  58. typedef union
  59. {
  60. double value;
  61. struct
  62. {
  63. u_int32_t msw;
  64. u_int32_t lsw;
  65. } parts;
  66. struct
  67. {
  68. u_int64_t w;
  69. } xparts;
  70. } ieee_double_shape_type_big;
  71. typedef union {
  72. double d;
  73. struct {
  74. unsigned int manl :32;
  75. unsigned int manh :20;
  76. unsigned int exp :11;
  77. unsigned int sign :1;
  78. } bits;
  79. } IEEEd2bits_L;
  80. typedef union {
  81. double d;
  82. struct {
  83. unsigned int sign :1;
  84. unsigned int exp :11;
  85. unsigned int manh :20;
  86. unsigned int manl :32;
  87. } bits;
  88. } IEEEd2bits_B;
  89. static union {
  90. int a;
  91. char b;
  92. } __ue = { .a = 1 };
  93. #define is_little_endian() (__ue.b == 1)
  94. #define __HIL(x) *(1+pdouble2pint(&x))
  95. #define __LOL(x) *(pdouble2pint(&x))
  96. #define __HIB(x) *(int*)&x
  97. #define __LOB(x) *(1+(int*)&x)
  98. /* Get two 32 bit ints from a double. */
  99. #define EXTRACT_WORDS_L(ix0,ix1,d) \
  100. do { \
  101. ieee_double_shape_type_little ew_u; \
  102. ew_u.value = (d); \
  103. (ix0) = ew_u.parts.msw; \
  104. (ix1) = ew_u.parts.lsw; \
  105. } while (0)
  106. /* Set a double from two 32 bit ints. */
  107. #define INSERT_WORDS_L(d,ix0,ix1) \
  108. do { \
  109. ieee_double_shape_type_little iw_u; \
  110. iw_u.parts.msw = (ix0); \
  111. iw_u.parts.lsw = (ix1); \
  112. (d) = iw_u.value; \
  113. } while (0)
  114. /* Get two 32 bit ints from a double. */
  115. #define EXTRACT_WORDS_B(ix0,ix1,d) \
  116. do { \
  117. ieee_double_shape_type_big ew_u; \
  118. ew_u.value = (d); \
  119. (ix0) = ew_u.parts.msw; \
  120. (ix1) = ew_u.parts.lsw; \
  121. } while (0)
  122. /* Set a double from two 32 bit ints. */
  123. #define INSERT_WORDS_B(d,ix0,ix1) \
  124. do { \
  125. ieee_double_shape_type_big iw_u; \
  126. iw_u.parts.msw = (ix0); \
  127. iw_u.parts.lsw = (ix1); \
  128. (d) = iw_u.value; \
  129. } while (0)
  130. /* Get the more significant 32 bit int from a double. */
  131. #define GET_HIGH_WORD_L(i,d) \
  132. do { \
  133. ieee_double_shape_type_little gh_u; \
  134. gh_u.value = (d); \
  135. (i) = gh_u.parts.msw; \
  136. } while (0)
  137. /* Get the more significant 32 bit int from a double. */
  138. #define GET_HIGH_WORD_B(i,d) \
  139. do { \
  140. ieee_double_shape_type_big gh_u; \
  141. gh_u.value = (d); \
  142. (i) = gh_u.parts.msw; \
  143. } while (0)
  144. /* Set the more significant 32 bits of a double from an int. */
  145. #define SET_HIGH_WORD_L(d,v) \
  146. do { \
  147. ieee_double_shape_type_little sh_u; \
  148. sh_u.value = (d); \
  149. sh_u.parts.msw = (v); \
  150. (d) = sh_u.value; \
  151. } while (0)
  152. /* Set the more significant 32 bits of a double from an int. */
  153. #define SET_HIGH_WORD_B(d,v) \
  154. do { \
  155. ieee_double_shape_type_big sh_u; \
  156. sh_u.value = (d); \
  157. sh_u.parts.msw = (v); \
  158. (d) = sh_u.value; \
  159. } while (0)
  160. /* Macro wrappers. */
  161. #define EXTRACT_WORDS(ix0,ix1,d) do { \
  162. if (is_little_endian()) \
  163. EXTRACT_WORDS_L(ix0,ix1,d); \
  164. else \
  165. EXTRACT_WORDS_B(ix0,ix1,d); \
  166. } while (0)
  167. #define INSERT_WORDS(d,ix0,ix1) do { \
  168. if (is_little_endian()) \
  169. INSERT_WORDS_L(d,ix0,ix1); \
  170. else \
  171. INSERT_WORDS_B(d,ix0,ix1); \
  172. } while (0)
  173. #define GET_HIGH_WORD(i,d) \
  174. do { \
  175. if (is_little_endian()) \
  176. GET_HIGH_WORD_L(i,d); \
  177. else \
  178. GET_HIGH_WORD_B(i,d); \
  179. } while (0)
  180. #define SET_HIGH_WORD(d,v) \
  181. do { \
  182. if (is_little_endian()) \
  183. SET_HIGH_WORD_L(d,v); \
  184. else \
  185. SET_HIGH_WORD_B(d,v); \
  186. } while (0)
  187. #define __HI(x) (is_little_endian() ? __HIL(x) : __HIB(x))
  188. #define __LO(x) (is_little_endian() ? __LOL(x) : __LOB(x))
  189. /*
  190. * Attempt to get strict C99 semantics for assignment with non-C99 compilers.
  191. */
  192. #if FLT_EVAL_METHOD == 0 || __GNUC__ == 0
  193. #define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval))
  194. #else
  195. #define STRICT_ASSIGN(type, lval, rval) do { \
  196. volatile type __lval; \
  197. \
  198. if (sizeof(type) >= sizeof(long double)) \
  199. (lval) = (rval); \
  200. else { \
  201. __lval = (rval); \
  202. (lval) = __lval; \
  203. } \
  204. } while (0)
  205. #endif
  206. #ifdef __FDLIBM_STDC__
  207. static const double huge = 1.0e300;
  208. #else
  209. static double huge = 1.0e300;
  210. #endif
  211. #ifdef __STDC__
  212. static const double
  213. #else
  214. static double
  215. #endif
  216. tiny = 1.0e-300;
  217. #ifdef __STDC__
  218. static const double
  219. #else
  220. static double
  221. #endif
  222. one= 1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */
  223. #ifdef __STDC__
  224. static const double
  225. #else
  226. static double
  227. #endif
  228. TWO52[2]={
  229. 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
  230. -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
  231. };
  232. static double freebsd_sqrt(double x);
  233. static double freebsd_floor(double x);
  234. static double freebsd_ceil(double x);
  235. static double freebsd_fabs(double x);
  236. static double freebsd_rint(double x);
  237. static int freebsd_isnan(double x);
  238. static double freebsd_sqrt(double x) /* wrapper sqrt */
  239. {
  240. double z;
  241. int32_t sign = (int)0x80000000;
  242. int32_t ix0,s0,q,m,t,i;
  243. u_int32_t r,t1,s1,ix1,q1;
  244. EXTRACT_WORDS(ix0,ix1,x);
  245. /* take care of Inf and NaN */
  246. if((ix0&0x7ff00000)==0x7ff00000) {
  247. return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
  248. sqrt(-inf)=sNaN */
  249. }
  250. /* take care of zero */
  251. if(ix0<=0) {
  252. if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */
  253. else if(ix0<0)
  254. return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
  255. }
  256. /* normalize x */
  257. m = (ix0>>20);
  258. if(m==0) { /* subnormal x */
  259. while(ix0==0) {
  260. m -= 21;
  261. ix0 |= (ix1>>11); ix1 <<= 21;
  262. }
  263. for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1;
  264. m -= i-1;
  265. ix0 |= (ix1>>(32-i));
  266. ix1 <<= i;
  267. }
  268. m -= 1023; /* unbias exponent */
  269. ix0 = (ix0&0x000fffff)|0x00100000;
  270. if(m&1){ /* odd m, double x to make it even */
  271. ix0 += ix0 + ((ix1&sign)>>31);
  272. ix1 += ix1;
  273. }
  274. m >>= 1; /* m = [m/2] */
  275. /* generate sqrt(x) bit by bit */
  276. ix0 += ix0 + ((ix1&sign)>>31);
  277. ix1 += ix1;
  278. q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */
  279. r = 0x00200000; /* r = moving bit from right to left */
  280. while(r!=0) {
  281. t = s0+r;
  282. if(t<=ix0) {
  283. s0 = t+r;
  284. ix0 -= t;
  285. q += r;
  286. }
  287. ix0 += ix0 + ((ix1&sign)>>31);
  288. ix1 += ix1;
  289. r>>=1;
  290. }
  291. r = sign;
  292. while(r!=0) {
  293. t1 = s1+r;
  294. t = s0;
  295. if((t<ix0)||((t==ix0)&&(t1<=ix1))) {
  296. s1 = t1+r;
  297. if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1;
  298. ix0 -= t;
  299. if (ix1 < t1) ix0 -= 1;
  300. ix1 -= t1;
  301. q1 += r;
  302. }
  303. ix0 += ix0 + ((ix1&sign)>>31);
  304. ix1 += ix1;
  305. r>>=1;
  306. }
  307. /* use floating add to find out rounding direction */
  308. if((ix0|ix1)!=0) {
  309. z = one-tiny; /* trigger inexact flag */
  310. if (z>=one) {
  311. z = one+tiny;
  312. if (q1==(u_int32_t)0xffffffff) { q1=0; q += 1;}
  313. else if (z>one) {
  314. if (q1==(u_int32_t)0xfffffffe) q+=1;
  315. q1+=2;
  316. } else
  317. q1 += (q1&1);
  318. }
  319. }
  320. ix0 = (q>>1)+0x3fe00000;
  321. ix1 = q1>>1;
  322. if ((q&1)==1) ix1 |= sign;
  323. ix0 += (m <<20);
  324. INSERT_WORDS(z,ix0,ix1);
  325. return z;
  326. }
  327. static double freebsd_floor(double x)
  328. {
  329. int32_t i0,i1,j0;
  330. u_int32_t i,j;
  331. EXTRACT_WORDS(i0,i1,x);
  332. j0 = ((i0>>20)&0x7ff)-0x3ff;
  333. if(j0<20) {
  334. if(j0<0) { /* raise inexact if x != 0 */
  335. if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
  336. if(i0>=0) {i0=i1=0;}
  337. else if(((i0&0x7fffffff)|i1)!=0)
  338. { i0=0xbff00000;i1=0;}
  339. }
  340. } else {
  341. i = (0x000fffff)>>j0;
  342. if(((i0&i)|i1)==0) return x; /* x is integral */
  343. if(huge+x>0.0) { /* raise inexact flag */
  344. if(i0<0) i0 += (0x00100000)>>j0;
  345. i0 &= (~i); i1=0;
  346. }
  347. }
  348. } else if (j0>51) {
  349. if(j0==0x400) return x+x; /* inf or NaN */
  350. else return x; /* x is integral */
  351. } else {
  352. i = ((u_int32_t)(0xffffffff))>>(j0-20);
  353. if((i1&i)==0) return x; /* x is integral */
  354. if(huge+x>0.0) { /* raise inexact flag */
  355. if(i0<0) {
  356. if(j0==20) i0+=1;
  357. else {
  358. j = i1+(1<<(52-j0));
  359. if(j<i1) i0 +=1 ; /* got a carry */
  360. i1=j;
  361. }
  362. }
  363. i1 &= (~i);
  364. }
  365. }
  366. INSERT_WORDS(x,i0,i1);
  367. return x;
  368. }
  369. static double freebsd_ceil(double x)
  370. {
  371. int32_t i0,i1,j0;
  372. u_int32_t i,j;
  373. EXTRACT_WORDS(i0,i1,x);
  374. j0 = ((i0>>20)&0x7ff)-0x3ff;
  375. if(j0<20) {
  376. if(j0<0) { /* raise inexact if x != 0 */
  377. if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
  378. if(i0<0) {i0=0x80000000;i1=0;}
  379. else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;}
  380. }
  381. } else {
  382. i = (0x000fffff)>>j0;
  383. if(((i0&i)|i1)==0) return x; /* x is integral */
  384. if(huge+x>0.0) { /* raise inexact flag */
  385. if(i0>0) i0 += (0x00100000)>>j0;
  386. i0 &= (~i); i1=0;
  387. }
  388. }
  389. } else if (j0>51) {
  390. if(j0==0x400) return x+x; /* inf or NaN */
  391. else return x; /* x is integral */
  392. } else {
  393. i = ((u_int32_t)(0xffffffff))>>(j0-20);
  394. if((i1&i)==0) return x; /* x is integral */
  395. if(huge+x>0.0) { /* raise inexact flag */
  396. if(i0>0) {
  397. if(j0==20) i0+=1;
  398. else {
  399. j = i1 + (1<<(52-j0));
  400. if(j<i1) i0+=1; /* got a carry */
  401. i1 = j;
  402. }
  403. }
  404. i1 &= (~i);
  405. }
  406. }
  407. INSERT_WORDS(x,i0,i1);
  408. return x;
  409. }
  410. static double freebsd_rint(double x)
  411. {
  412. int32_t i0,j0,sx;
  413. u_int32_t i,i1;
  414. double w,t;
  415. EXTRACT_WORDS(i0,i1,x);
  416. sx = (i0>>31)&1;
  417. j0 = ((i0>>20)&0x7ff)-0x3ff;
  418. if(j0<20) {
  419. if(j0<0) {
  420. if(((i0&0x7fffffff)|i1)==0) return x;
  421. i1 |= (i0&0x0fffff);
  422. i0 &= 0xfffe0000;
  423. i0 |= ((i1|-i1)>>12)&0x80000;
  424. SET_HIGH_WORD(x,i0);
  425. STRICT_ASSIGN(double,w,TWO52[sx]+x);
  426. t = w-TWO52[sx];
  427. GET_HIGH_WORD(i0,t);
  428. SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31));
  429. return t;
  430. } else {
  431. i = (0x000fffff)>>j0;
  432. if(((i0&i)|i1)==0) return x; /* x is integral */
  433. i>>=1;
  434. if(((i0&i)|i1)!=0) {
  435. /*
  436. * Some bit is set after the 0.5 bit. To avoid the
  437. * possibility of errors from double rounding in
  438. * w = TWO52[sx]+x, adjust the 0.25 bit to a lower
  439. * guard bit. We do this for all j0<=51. The
  440. * adjustment is trickiest for j0==18 and j0==19
  441. * since then it spans the word boundary.
  442. */
  443. if(j0==19) i1 = 0x40000000; else
  444. if(j0==18) i1 = 0x80000000; else
  445. i0 = (i0&(~i))|((0x20000)>>j0);
  446. }
  447. }
  448. } else if (j0>51) {
  449. if(j0==0x400) return x+x; /* inf or NaN */
  450. else return x; /* x is integral */
  451. } else {
  452. i = ((u_int32_t)(0xffffffff))>>(j0-20);
  453. if((i1&i)==0) return x; /* x is integral */
  454. i>>=1;
  455. if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20));
  456. }
  457. INSERT_WORDS(x,i0,i1);
  458. STRICT_ASSIGN(double,w,TWO52[sx]+x);
  459. return w-TWO52[sx];
  460. }
  461. static int freebsd_isnan(double d)
  462. {
  463. if (is_little_endian()) {
  464. IEEEd2bits_L u;
  465. u.d = d;
  466. return (u.bits.exp == 2047 && (u.bits.manl != 0 || u.bits.manh != 0));
  467. }
  468. else {
  469. IEEEd2bits_B u;
  470. u.d = d;
  471. return (u.bits.exp == 2047 && (u.bits.manl != 0 || u.bits.manh != 0));
  472. }
  473. }
  474. static double freebsd_fabs(double x)
  475. {
  476. u_int32_t high;
  477. GET_HIGH_WORD(high,x);
  478. SET_HIGH_WORD(x,high&0x7fffffff);
  479. return x;
  480. }
  481. double sqrt(double x)
  482. {
  483. return freebsd_sqrt(x);
  484. }
  485. double floor(double x)
  486. {
  487. return freebsd_floor(x);
  488. }
  489. double ceil(double x)
  490. {
  491. return freebsd_ceil(x);
  492. }
  493. double fmin(double x, double y)
  494. {
  495. return x < y ? x : y;
  496. }
  497. double fmax(double x, double y)
  498. {
  499. return x > y ? x : y;
  500. }
  501. double rint(double x)
  502. {
  503. return freebsd_rint(x);
  504. }
  505. double fabs(double x)
  506. {
  507. return freebsd_fabs(x);
  508. }
  509. int isnan(double x)
  510. {
  511. return freebsd_isnan(x);
  512. }
  513. double trunc(double x)
  514. {
  515. return (x > 0) ? freebsd_floor(x) : freebsd_ceil(x);
  516. }
  517. int signbit(double x)
  518. {
  519. return ((__HI(x) & 0x80000000) >> 31);
  520. }