rndint.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. /*******************************************************************************
  2. ** File: rndint.c
  3. **
  4. ** Contains: C source code for implementations of floating-point
  5. ** functions which round to integral value or format, as
  6. ** defined in header <fp.h>. In particular, this file
  7. ** contains implementations of functions rint, nearbyint,
  8. ** rinttol, round, roundtol, trunc, modf and modfl. This file
  9. ** targets PowerPC or Power platforms.
  10. **
  11. ** Written by: A. Sazegari, Apple AltiVec Group
  12. ** Created originally by Jon Okada, Apple Numerics Group
  13. **
  14. ** Copyright: © 1992-2001 by Apple Computer, Inc., all rights reserved
  15. **
  16. ** Change History (most recent first):
  17. **
  18. ** 13 Jul 01 ram replaced --setflm calls with inline assembly
  19. ** 03 Mar 01 ali first port to os x using gcc, added the crucial __setflm
  20. ** definition.
  21. ** 1. removed double_t, put in double for now.
  22. ** 2. removed iclass from nearbyint.
  23. ** 3. removed wrong comments intrunc.
  24. ** 4.
  25. ** 13 May 97 ali made performance improvements in rint, rinttol, roundtol
  26. ** and trunc by folding some of the taligent ideas into this
  27. ** implementation. nearbyint is faster than the one in taligent,
  28. ** rint is more elegant, but slower by %30 than the taligent one.
  29. ** 09 Apr 97 ali deleted modfl and deferred to AuxiliaryDD.c
  30. ** 15 Sep 94 ali Major overhaul and performance improvements of all functions.
  31. ** 20 Jul 94 PAF New faster version
  32. ** 16 Jul 93 ali Added the modfl function.
  33. ** 18 Feb 93 ali Changed the return value of fenv functions
  34. ** feclearexcept and feraiseexcept to their new
  35. ** NCEG X3J11.1/93-001 definitions.
  36. ** 16 Dec 92 JPO Removed __itrunc implementation to a
  37. ** separate file.
  38. ** 15 Dec 92 JPO Added __itrunc implementation and modified
  39. ** rinttol to include conversion from double
  40. ** to long int format. Modified roundtol to
  41. ** call __itrunc.
  42. ** 10 Dec 92 JPO Added modf (double) implementation.
  43. ** 04 Dec 92 JPO First created.
  44. **
  45. *******************************************************************************/
  46. #include <limits.h>
  47. #include <math.h>
  48. #define SET_INVALID 0x01000000UL
  49. typedef union
  50. {
  51. struct {
  52. #if defined(__BIG_ENDIAN__)
  53. unsigned long int hi;
  54. unsigned long int lo;
  55. #else
  56. unsigned long int lo;
  57. unsigned long int hi;
  58. #endif
  59. } words;
  60. double dbl;
  61. } DblInHex;
  62. static const unsigned long int signMask = 0x80000000ul;
  63. static const double twoTo52 = 4503599627370496.0;
  64. static const double doubleToLong = 4503603922337792.0; // 2^52
  65. static const DblInHex Huge = {{ 0x7FF00000, 0x00000000 }};
  66. static const DblInHex TOWARDZERO = {{ 0x00000000, 0x00000001 }};
  67. /*******************************************************************************
  68. * *
  69. * The function rint rounds its double argument to integral value *
  70. * according to the current rounding direction and returns the result in *
  71. * double format. This function signals inexact if an ordered return *
  72. * value is not equal to the operand. *
  73. * *
  74. ********************************************************************************
  75. * *
  76. * This function calls: fabs. *
  77. * *
  78. *******************************************************************************/
  79. /*******************************************************************************
  80. * First, an elegant implementation. *
  81. ********************************************************************************
  82. *
  83. *double rint ( double x )
  84. * {
  85. * double y;
  86. *
  87. * y = twoTo52.fval;
  88. *
  89. * if ( fabs ( x ) >= y ) // huge case is exact
  90. * return x;
  91. * if ( x < 0 ) y = -y; // negative case
  92. * y = ( x + y ) - y; // force rounding
  93. * if ( y == 0.0 ) // zero results mirror sign of x
  94. * y = copysign ( y, x );
  95. * return ( y );
  96. * }
  97. ********************************************************************************
  98. * Now a bit twidling version that is about %30 faster. *
  99. *******************************************************************************/
  100. double rint ( double x )
  101. {
  102. DblInHex argument;
  103. register double y;
  104. unsigned long int xHead;
  105. register long int target;
  106. argument.dbl = x;
  107. xHead = argument.words.hi & 0x7fffffffUL; // xHead <- high half of |x|
  108. target = ( argument.words.hi < signMask ); // flags positive sign
  109. if ( xHead < 0x43300000ul )
  110. /*******************************************************************************
  111. * Is |x| < 2.0^52? *
  112. *******************************************************************************/
  113. {
  114. if ( xHead < 0x3ff00000ul )
  115. /*******************************************************************************
  116. * Is |x| < 1.0? *
  117. *******************************************************************************/
  118. {
  119. if ( target )
  120. y = ( x + twoTo52 ) - twoTo52; // round at binary point
  121. else
  122. y = ( x - twoTo52 ) + twoTo52; // round at binary point
  123. if ( y == 0.0 )
  124. { // fix sign of zero result
  125. if ( target )
  126. return ( 0.0 );
  127. else
  128. return ( -0.0 );
  129. }
  130. return y;
  131. }
  132. /*******************************************************************************
  133. * Is 1.0 < |x| < 2.0^52? *
  134. *******************************************************************************/
  135. if ( target )
  136. return ( ( x + twoTo52 ) - twoTo52 ); // round at binary pt.
  137. else
  138. return ( ( x - twoTo52 ) + twoTo52 );
  139. }
  140. /*******************************************************************************
  141. * |x| >= 2.0^52 or x is a NaN. *
  142. *******************************************************************************/
  143. return ( x );
  144. }
  145. /*******************************************************************************
  146. * *
  147. * The function nearbyint rounds its double argument to integral value *
  148. * according to the current rounding direction and returns the result in *
  149. * double format. This function does not signal inexact. *
  150. * *
  151. ********************************************************************************
  152. * *
  153. * This function calls fabs and copysign. *
  154. * *
  155. *******************************************************************************/
  156. double nearbyint ( double x )
  157. {
  158. double y;
  159. double OldEnvironment;
  160. y = twoTo52;
  161. asm ("mffs %0" : "=f" (OldEnvironment)); /* get the environement */
  162. if ( fabs ( x ) >= y ) /* huge case is exact */
  163. return x;
  164. if ( x < 0 ) y = -y; /* negative case */
  165. y = ( x + y ) - y; /* force rounding */
  166. if ( y == 0.0 ) /* zero results mirror sign of x */
  167. y = copysign ( y, x );
  168. // restore old flags
  169. asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment ));
  170. return ( y );
  171. }
  172. /*******************************************************************************
  173. * *
  174. * The function rinttol converts its double argument to integral value *
  175. * according to the current rounding direction and returns the result in *
  176. * long int format. This conversion signals invalid if the argument is a *
  177. * NaN or the rounded intermediate result is out of range of the *
  178. * destination long int format, and it delivers an unspecified result in *
  179. * this case. This function signals inexact if the rounded result is *
  180. * within range of the long int format but unequal to the operand. *
  181. * *
  182. *******************************************************************************/
  183. long int rinttol ( double x )
  184. {
  185. register double y;
  186. DblInHex argument, OldEnvironment;
  187. unsigned long int xHead;
  188. register long int target;
  189. argument.dbl = x;
  190. target = ( argument.words.hi < signMask ); // flag positive sign
  191. xHead = argument.words.hi & 0x7ffffffful; // high 32 bits of x
  192. if ( target )
  193. /*******************************************************************************
  194. * Sign of x is positive. *
  195. *******************************************************************************/
  196. {
  197. if ( xHead < 0x41dffffful )
  198. { // x is safely in long range
  199. y = ( x + twoTo52 ) - twoTo52; // round at binary point
  200. argument.dbl = y + doubleToLong; // force result into argument.words.lo
  201. return ( ( long ) argument.words.lo );
  202. }
  203. asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // get environment
  204. if ( xHead > 0x41dffffful )
  205. { // x is safely out of long range
  206. OldEnvironment.words.lo |= SET_INVALID;
  207. asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
  208. return ( LONG_MAX );
  209. }
  210. /*******************************************************************************
  211. * x > 0.0 and may or may not be out of range of long. *
  212. *******************************************************************************/
  213. y = ( x + twoTo52 ) - twoTo52; // do rounding
  214. if ( y > ( double ) LONG_MAX )
  215. { // out of range of long
  216. OldEnvironment.words.lo |= SET_INVALID;
  217. asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
  218. return ( LONG_MAX );
  219. }
  220. argument.dbl = y + doubleToLong; // in range
  221. return ( ( long ) argument.words.lo ); // return result & flags
  222. }
  223. /*******************************************************************************
  224. * Sign of x is negative. *
  225. *******************************************************************************/
  226. if ( xHead < 0x41e00000ul )
  227. { // x is safely in long range
  228. y = ( x - twoTo52 ) + twoTo52;
  229. argument.dbl = y + doubleToLong;
  230. return ( ( long ) argument.words.lo );
  231. }
  232. asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // get environment
  233. if ( xHead > 0x41e00000ul )
  234. { // x is safely out of long range
  235. OldEnvironment.words.lo |= SET_INVALID;
  236. asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
  237. return ( LONG_MIN );
  238. }
  239. /*******************************************************************************
  240. * x < 0.0 and may or may not be out of range of long. *
  241. *******************************************************************************/
  242. y = ( x - twoTo52 ) + twoTo52; // do rounding
  243. if ( y < ( double ) LONG_MIN )
  244. { // out of range of long
  245. OldEnvironment.words.lo |= SET_INVALID;
  246. asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
  247. return ( LONG_MIN );
  248. }
  249. argument.dbl = y + doubleToLong; // in range
  250. return ( ( long ) argument.words.lo ); // return result & flags
  251. }
  252. /*******************************************************************************
  253. * *
  254. * The function round rounds its double argument to integral value *
  255. * according to the "add half to the magnitude and truncate" rounding of *
  256. * Pascal's Round function and FORTRAN's ANINT function and returns the *
  257. * result in double format. This function signals inexact if an ordered *
  258. * return value is not equal to the operand. *
  259. * *
  260. *******************************************************************************/
  261. double round ( double x )
  262. {
  263. DblInHex argument, OldEnvironment;
  264. register double y, z;
  265. register unsigned long int xHead;
  266. register long int target;
  267. argument.dbl = x;
  268. xHead = argument.words.hi & 0x7fffffffUL; // xHead <- high half of |x|
  269. target = ( argument.words.hi < signMask ); // flag positive sign
  270. if ( xHead < 0x43300000ul )
  271. /*******************************************************************************
  272. * Is |x| < 2.0^52? *
  273. *******************************************************************************/
  274. {
  275. if ( xHead < 0x3ff00000ul )
  276. /*******************************************************************************
  277. * Is |x| < 1.0? *
  278. *******************************************************************************/
  279. {
  280. asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // get environment
  281. if ( xHead < 0x3fe00000ul )
  282. /*******************************************************************************
  283. * Is |x| < 0.5? *
  284. *******************************************************************************/
  285. {
  286. if ( ( xHead | argument.words.lo ) != 0ul )
  287. OldEnvironment.words.lo |= 0x02000000ul;
  288. asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
  289. if ( target )
  290. return ( 0.0 );
  291. else
  292. return ( -0.0 );
  293. }
  294. /*******************************************************************************
  295. * Is 0.5 ² |x| < 1.0? *
  296. *******************************************************************************/
  297. OldEnvironment.words.lo |= 0x02000000ul;
  298. asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
  299. if ( target )
  300. return ( 1.0 );
  301. else
  302. return ( -1.0 );
  303. }
  304. /*******************************************************************************
  305. * Is 1.0 < |x| < 2.0^52? *
  306. *******************************************************************************/
  307. if ( target )
  308. { // positive x
  309. y = ( x + twoTo52 ) - twoTo52; // round at binary point
  310. if ( y == x ) // exact case
  311. return ( x );
  312. z = x + 0.5; // inexact case
  313. y = ( z + twoTo52 ) - twoTo52; // round at binary point
  314. if ( y > z )
  315. return ( y - 1.0 );
  316. else
  317. return ( y );
  318. }
  319. /*******************************************************************************
  320. * Is x < 0? *
  321. *******************************************************************************/
  322. else
  323. {
  324. y = ( x - twoTo52 ) + twoTo52; // round at binary point
  325. if ( y == x )
  326. return ( x );
  327. z = x - 0.5;
  328. y = ( z - twoTo52 ) + twoTo52; // round at binary point
  329. if ( y < z )
  330. return ( y + 1.0 );
  331. else
  332. return ( y );
  333. }
  334. }
  335. /*******************************************************************************
  336. * |x| >= 2.0^52 or x is a NaN. *
  337. *******************************************************************************/
  338. return ( x );
  339. }
  340. /*******************************************************************************
  341. * *
  342. * The function roundtol converts its double argument to integral format *
  343. * according to the "add half to the magnitude and chop" rounding mode of *
  344. * Pascal's Round function and FORTRAN's NINT function. This conversion *
  345. * signals invalid if the argument is a NaN or the rounded intermediate *
  346. * result is out of range of the destination long int format, and it *
  347. * delivers an unspecified result in this case. This function signals *
  348. * inexact if the rounded result is within range of the long int format but *
  349. * unequal to the operand. *
  350. * *
  351. *******************************************************************************/
  352. long int roundtol ( double x )
  353. {
  354. register double y, z;
  355. DblInHex argument, OldEnvironment;
  356. register unsigned long int xhi;
  357. register long int target;
  358. const DblInHex kTZ = {{ 0x0, 0x1 }};
  359. const DblInHex kUP = {{ 0x0, 0x2 }};
  360. argument.dbl = x;
  361. xhi = argument.words.hi & 0x7ffffffful; // high 32 bits of x
  362. target = ( argument.words.hi < signMask ); // flag positive sign
  363. if ( xhi > 0x41e00000ul )
  364. /*******************************************************************************
  365. * Is x is out of long range or NaN? *
  366. *******************************************************************************/
  367. {
  368. asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // get environment
  369. OldEnvironment.words.lo |= SET_INVALID;
  370. asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
  371. if ( target ) // pin result
  372. return ( LONG_MAX );
  373. else
  374. return ( LONG_MIN );
  375. }
  376. if ( target )
  377. /*******************************************************************************
  378. * Is sign of x is "+"? *
  379. *******************************************************************************/
  380. {
  381. if ( x < 2147483647.5 )
  382. /*******************************************************************************
  383. * x is in the range of a long. *
  384. *******************************************************************************/
  385. {
  386. y = ( x + doubleToLong ) - doubleToLong; // round at binary point
  387. if ( y != x )
  388. { // inexact case
  389. asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // save environment
  390. asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( kTZ.dbl )); // truncate rounding
  391. z = x + 0.5; // truncate x + 0.5
  392. argument.dbl = z + doubleToLong;
  393. asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
  394. return ( ( long ) argument.words.lo );
  395. }
  396. argument.dbl = y + doubleToLong; // force result into argument.words.lo
  397. return ( ( long ) argument.words.lo ); // return long result
  398. }
  399. /*******************************************************************************
  400. * Rounded positive x is out of the range of a long. *
  401. *******************************************************************************/
  402. asm ("mffs %0" : "=f" (OldEnvironment.dbl));
  403. OldEnvironment.words.lo |= SET_INVALID;
  404. asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
  405. return ( LONG_MAX ); // return pinned result
  406. }
  407. /*******************************************************************************
  408. * x < 0.0 and may or may not be out of the range of a long. *
  409. *******************************************************************************/
  410. if ( x > -2147483648.5 )
  411. /*******************************************************************************
  412. * x is in the range of a long. *
  413. *******************************************************************************/
  414. {
  415. y = ( x + doubleToLong ) - doubleToLong; // round at binary point
  416. if ( y != x )
  417. { // inexact case
  418. asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // save environment
  419. asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( kUP.dbl )); // round up
  420. z = x - 0.5; // truncate x - 0.5
  421. argument.dbl = z + doubleToLong;
  422. asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
  423. return ( ( long ) argument.words.lo );
  424. }
  425. argument.dbl = y + doubleToLong;
  426. return ( ( long ) argument.words.lo ); // return long result
  427. }
  428. /*******************************************************************************
  429. * Rounded negative x is out of the range of a long. *
  430. *******************************************************************************/
  431. asm ("mffs %0" : "=f" (OldEnvironment.dbl));
  432. OldEnvironment.words.lo |= SET_INVALID;
  433. asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
  434. return ( LONG_MIN ); // return pinned result
  435. }
  436. /*******************************************************************************
  437. * *
  438. * The function trunc truncates its double argument to integral value *
  439. * and returns the result in double format. This function signals *
  440. * inexact if an ordered return value is not equal to the operand. *
  441. * *
  442. *******************************************************************************/
  443. double trunc ( double x )
  444. {
  445. DblInHex argument,OldEnvironment;
  446. register double y;
  447. register unsigned long int xhi;
  448. register long int target;
  449. argument.dbl = x;
  450. xhi = argument.words.hi & 0x7fffffffUL; // xhi <- high half of |x|
  451. target = ( argument.words.hi < signMask ); // flag positive sign
  452. if ( xhi < 0x43300000ul )
  453. /*******************************************************************************
  454. * Is |x| < 2.0^53? *
  455. *******************************************************************************/
  456. {
  457. if ( xhi < 0x3ff00000ul )
  458. /*******************************************************************************
  459. * Is |x| < 1.0? *
  460. *******************************************************************************/
  461. {
  462. if ( ( xhi | argument.words.lo ) != 0ul )
  463. { // raise deserved INEXACT
  464. asm ("mffs %0" : "=f" (OldEnvironment.dbl));
  465. OldEnvironment.words.lo |= 0x02000000ul;
  466. asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
  467. }
  468. if ( target ) // return properly signed zero
  469. return ( 0.0 );
  470. else
  471. return ( -0.0 );
  472. }
  473. /*******************************************************************************
  474. * Is 1.0 < |x| < 2.0^52? *
  475. *******************************************************************************/
  476. if ( target )
  477. {
  478. y = ( x + twoTo52 ) - twoTo52; // round at binary point
  479. if ( y > x )
  480. return ( y - 1.0 );
  481. else
  482. return ( y );
  483. }
  484. else
  485. {
  486. y = ( x - twoTo52 ) + twoTo52; // round at binary point.
  487. if ( y < x )
  488. return ( y + 1.0 );
  489. else
  490. return ( y );
  491. }
  492. }
  493. /*******************************************************************************
  494. * Is |x| >= 2.0^52 or x is a NaN. *
  495. *******************************************************************************/
  496. return ( x );
  497. }
  498. /*******************************************************************************
  499. * The modf family of functions separate a floating-point number into its *
  500. * fractional and integral parts, returning the fractional part and writing *
  501. * the integral part in floating-point format to the object pointed to by a *
  502. * pointer argument. If the input argument is integral or infinite in *
  503. * value, the return value is a zero with the sign of the input argument. *
  504. * The modf family of functions raises no floating-point exceptions. older *
  505. * implemenation set the INVALID flag due to signaling NaN input. *
  506. * *
  507. *******************************************************************************/
  508. /*******************************************************************************
  509. * modf is the double implementation. *
  510. *******************************************************************************/
  511. double modf ( double x, double *iptr )
  512. {
  513. register double OldEnvironment, xtrunc;
  514. register unsigned long int xHead, signBit;
  515. DblInHex argument;
  516. argument.dbl = x;
  517. xHead = argument.words.hi & 0x7ffffffful; // |x| high bit pattern
  518. signBit = ( argument.words.hi & 0x80000000ul ); // isolate sign bit
  519. if (xHead == 0x7ff81fe0)
  520. signBit = signBit | 0;
  521. if ( xHead < 0x43300000ul )
  522. /*******************************************************************************
  523. * Is |x| < 2.0^53? *
  524. *******************************************************************************/
  525. {
  526. if ( xHead < 0x3ff00000ul )
  527. /*******************************************************************************
  528. * Is |x| < 1.0? *
  529. *******************************************************************************/
  530. {
  531. argument.words.hi = signBit; // truncate to zero
  532. argument.words.lo = 0ul;
  533. *iptr = argument.dbl;
  534. return ( x );
  535. }
  536. /*******************************************************************************
  537. * Is 1.0 < |x| < 2.0^52? *
  538. *******************************************************************************/
  539. asm ("mffs %0" : "=f" (OldEnvironment)); // save environment
  540. // round toward zero
  541. asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( TOWARDZERO.dbl ));
  542. if ( signBit == 0ul ) // truncate to integer
  543. xtrunc = ( x + twoTo52 ) - twoTo52;
  544. else
  545. xtrunc = ( x - twoTo52 ) + twoTo52;
  546. // restore caller's env
  547. asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment ));
  548. *iptr = xtrunc; // store integral part
  549. if ( x != xtrunc ) // nonzero fraction
  550. return ( x - xtrunc );
  551. else
  552. { // zero with x's sign
  553. argument.words.hi = signBit;
  554. argument.words.lo = 0ul;
  555. return ( argument.dbl );
  556. }
  557. }
  558. *iptr = x; // x is integral or NaN
  559. if ( x != x ) // NaN is returned
  560. return x;
  561. else
  562. { // zero with x's sign
  563. argument.words.hi = signBit;
  564. argument.words.lo = 0ul;
  565. return ( argument.dbl );
  566. }
  567. }