Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * ====================================================
  3.  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  4.  *
  5.  * Developed at SunPro, a Sun Microsystems, Inc. business.
  6.  * Permission to use, copy, modify, and distribute this
  7.  * software is freely granted, provided that this notice
  8.  * is preserved.
  9.  * ====================================================
  10.  */
  11. /*
  12. FUNCTION
  13. <<lround>>, <<lroundf>>, <<llround>>, <<llroundf>>--round to integer, to nearest
  14. INDEX
  15.         lround
  16. INDEX
  17.         lroundf
  18. INDEX
  19.         llround
  20. INDEX
  21.         llroundf
  22.  
  23. ANSI_SYNOPSIS
  24.         #include <math.h>
  25.         long int lround(double <[x]>);
  26.         long int lroundf(float <[x]>);
  27.         long long int llround(double <[x]>);
  28.         long long int llroundf(float <[x]>);
  29.  
  30. DESCRIPTION
  31.         The <<lround>> and <<llround>> functions round their argument to the
  32.         nearest integer value, rounding halfway cases away from zero, regardless
  33.         of the current rounding direction.  If the rounded value is outside the
  34.         range of the return type, the numeric result is unspecified (depending
  35.         upon the floating-point implementation, not the library).  A range
  36.         error may occur if the magnitude of x is too large.
  37.  
  38. RETURNS
  39. <[x]> rounded to an integral value as an integer.
  40.  
  41. SEEALSO
  42. See the <<round>> functions for the return being the same floating-point type
  43. as the argument.  <<lrint>>, <<llrint>>.
  44.  
  45. PORTABILITY
  46. ANSI C, POSIX
  47.  
  48. */
  49.  
  50. #include "fdlibm.h"
  51.  
  52. #ifndef _DOUBLE_IS_32BITS
  53.  
  54. #ifdef __STDC__
  55.         long int lround(double x)
  56. #else
  57.         long int lround(x)
  58.         double x;
  59. #endif
  60. {
  61.   __int32_t sign, exponent_less_1023;
  62.   /* Most significant word, least significant word. */
  63.   __uint32_t msw, lsw;
  64.   long int result;
  65.  
  66.   EXTRACT_WORDS(msw, lsw, x);
  67.  
  68.   /* Extract sign. */
  69.   sign = ((msw & 0x80000000) ? -1 : 1);
  70.   /* Extract exponent field. */
  71.   exponent_less_1023 = ((msw & 0x7ff00000) >> 20) - 1023;
  72.   msw &= 0x000fffff;
  73.   msw |= 0x00100000;
  74.   /* exponent_less_1023 in [-1023,1024] */
  75.   if (exponent_less_1023 < 20)
  76.     {
  77.       /* exponent_less_1023 in [-1023,19] */
  78.       if (exponent_less_1023 < 0)
  79.         {
  80.           if (exponent_less_1023 < -1)
  81.             return 0;
  82.           else
  83.             return sign;
  84.         }
  85.       else
  86.         {
  87.           /* exponent_less_1023 in [0,19] */
  88.           /* shift amt in [0,19] */
  89.           msw += 0x80000 >> exponent_less_1023;
  90.           /* shift amt in [20,1] */
  91.           result = msw >> (20 - exponent_less_1023);
  92.         }
  93.     }
  94.   else if (exponent_less_1023 < (8 * sizeof (long int)) - 1)
  95.     {
  96.       /* 32bit long: exponent_less_1023 in [20,30] */
  97.       /* 64bit long: exponent_less_1023 in [20,62] */
  98.       if (exponent_less_1023 >= 52)
  99.         /* 64bit long: exponent_less_1023 in [52,62] */
  100.         /* 64bit long: shift amt in [32,42] */
  101.         result = ((long int) msw << (exponent_less_1023 - 20))
  102.                 /* 64bit long: shift amt in [0,10] */
  103.                 | (lsw << (exponent_less_1023 - 52));
  104.       else
  105.         {
  106.           /* 32bit long: exponent_less_1023 in [20,30] */
  107.           /* 64bit long: exponent_less_1023 in [20,51] */
  108.           unsigned int tmp = lsw
  109.                     /* 32bit long: shift amt in [0,10] */
  110.                     /* 64bit long: shift amt in [0,31] */
  111.                     + (0x80000000 >> (exponent_less_1023 - 20));
  112.           if (tmp < lsw)
  113.             ++msw;
  114.           /* 32bit long: shift amt in [0,10] */
  115.           /* 64bit long: shift amt in [0,31] */
  116.           result = ((long int) msw << (exponent_less_1023 - 20))
  117.                     /* ***32bit long: shift amt in [32,22] */
  118.                     /* ***64bit long: shift amt in [32,1] */
  119.                     | SAFE_RIGHT_SHIFT (tmp, (52 - exponent_less_1023));
  120.         }
  121.     }
  122.   else
  123.     /* Result is too large to be represented by a long int. */
  124.     return (long int)x;
  125.  
  126.   return sign * result;
  127. }
  128.  
  129. #endif /* _DOUBLE_IS_32BITS */
  130.