Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /* lrint adapted to be llrint for Newlib, 2009 by Craig Howland.  */
  2. /* @(#)s_lrint.c 5.1 93/09/24 */
  3. /*
  4.  * ====================================================
  5.  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  6.  *
  7.  * Developed at SunPro, a Sun Microsystems, Inc. business.
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software is freely granted, provided that this notice
  10.  * is preserved.
  11.  * ====================================================
  12.  */
  13.  
  14. /*
  15.  * llrint(x)
  16.  * Return x rounded to integral value according to the prevailing
  17.  * rounding mode.
  18.  * Method:
  19.  *      Using floating addition.
  20.  * Exception:
  21.  *      Inexact flag raised if x not equal to llrint(x).
  22.  */
  23.  
  24. #include "fdlibm.h"
  25.  
  26. #ifndef _DOUBLE_IS_32BITS
  27.  
  28. #ifdef __STDC__
  29. static const double
  30. #else
  31. static double
  32. #endif
  33.  
  34. /* Adding a double, x, to 2^52 will cause the result to be rounded based on
  35.    the fractional part of x, according to the implementation's current rounding
  36.    mode.  2^52 is the smallest double that can be represented using all 52 significant
  37.    digits. */
  38. TWO52[2]={
  39.   4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
  40.  -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
  41. };
  42.  
  43. long long int
  44. #ifdef __STDC__
  45.         llrint(double x)
  46. #else
  47.         llrint(x)
  48.         double x;
  49. #endif
  50. {
  51.   __int32_t i0,j0,sx;
  52.   __uint32_t i1;
  53.   double t;
  54.   volatile double w;
  55.   long long int result;
  56.  
  57.   EXTRACT_WORDS(i0,i1,x);
  58.  
  59.   /* Extract sign bit. */
  60.   sx = (i0>>31)&1;
  61.  
  62.   /* Extract exponent field. */
  63.   j0 = ((i0 & 0x7ff00000) >> 20) - 1023;
  64.   /* j0 in [-1023,1024] */
  65.  
  66.   if(j0 < 20)
  67.     {
  68.       /* j0 in [-1023,19] */
  69.       if(j0 < -1)
  70.         return 0;
  71.       else
  72.         {
  73.           /* j0 in [0,19] */
  74.           /* shift amt in [0,19] */
  75.           w = TWO52[sx] + x;
  76.           t = w - TWO52[sx];
  77.           GET_HIGH_WORD(i0, t);
  78.           /* Detect the all-zeros representation of plus and
  79.              minus zero, which fails the calculation below. */
  80.           if ((i0 & ~((__int32_t)1 << 31)) == 0)
  81.               return 0;
  82.           /* After round:  j0 in [0,20] */
  83.           j0 = ((i0 & 0x7ff00000) >> 20) - 1023;
  84.           i0 &= 0x000fffff;
  85.           i0 |= 0x00100000;
  86.           /* shift amt in [20,0] */
  87.           result = i0 >> (20 - j0);
  88.         }
  89.     }
  90.   else if (j0 < (int)(8 * sizeof (long long int)) - 1)
  91.     {
  92.       /* 64bit return: j0 in [20,62] */
  93.       if (j0 >= 52)
  94.         /* 64bit return: j0 in [52,62] */
  95.         /* 64bit return: left shift amt in [32,42] */
  96.         result = ((long long int) ((i0 & 0x000fffff) | 0x0010000) << (j0 - 20)) |
  97.                 /* 64bit return: right shift amt in [0,10] */
  98.                    (i1 << (j0 - 52));
  99.       else
  100.         {
  101.           /* 64bit return: j0 in [20,51] */
  102.           w = TWO52[sx] + x;
  103.           t = w - TWO52[sx];
  104.           EXTRACT_WORDS (i0, i1, t);
  105.           j0 = ((i0 & 0x7ff00000) >> 20) - 1023;
  106.           i0 &= 0x000fffff;
  107.           i0 |= 0x00100000;
  108.           /* After round:
  109.            * 64bit return: j0 in [20,52] */
  110.           /* 64bit return: left shift amt in [0,32] */
  111.           /* ***64bit return: right shift amt in [32,0] */
  112.           result = ((long long int) i0 << (j0 - 20))
  113.                         | SAFE_RIGHT_SHIFT (i1, (52 - j0));
  114.         }
  115.     }
  116.   else
  117.     {
  118.       return (long long int) x;
  119.     }
  120.  
  121.   return sx ? -result : result;
  122. }
  123.  
  124. #endif /* _DOUBLE_IS_32BITS */
  125.