Back to index

glibc  2.9
Functions
s_nearbyintl.c File Reference
#include <math.h>
#include <fenv.h>
#include <math_ldbl_opt.h>
#include <float.h>
#include <ieee754.h>

Go to the source code of this file.

Functions

long double __nearbyintl (long double x)
 long_double_symbol (libm, __nearbyintl, nearbyintl)

Function Documentation

long double __nearbyintl ( long double  x)

Definition at line 36 of file s_nearbyintl.c.

{
  fenv_t env;
  static const long double TWO52 = 4503599627370496.0L;
  union ibm_extended_long_double u;
  u.d = x;

  if (fabs (u.dd[0]) < TWO52)
    {
      double high = u.dd[0];
      feholdexcept (&env);
      if (high > 0.0)
       {
         high += TWO52;
         high -= TWO52;
          if (high == -0.0) high = 0.0;
       }
      else if (high < 0.0)
       {
         high -= TWO52;
         high += TWO52;
          if (high == 0.0) high = -0.0;
       }
      u.dd[0] = high;
      u.dd[1] = 0.0;
      fesetenv (&env);
    }
  else if (fabs (u.dd[1]) < TWO52 && u.dd[1] != 0.0)
    {
      double high, low, tau;
      /* In this case we have to round the low double and handle any
         adjustment to the high double that may be caused by rounding
         (up).  This is complicated by the fact that the high double
         may already be rounded and the low double may have the
         opposite sign to compensate.  */
      feholdexcept (&env);
      if (u.dd[0] > 0.0)
       {
         if (u.dd[1] > 0.0)
           {
             /* If the high/low doubles are the same sign then simply
                round the low double.  */
             high = u.dd[0];
             low = u.dd[1];
           }
         else if (u.dd[1] < 0.0)
           {
             /* Else the high double is pre rounded and we need to
                adjust for that.  */

             tau = __nextafter (u.dd[0], 0.0);
             tau = (u.dd[0] - tau) * 2.0;
             high = u.dd[0] - tau;
             low = u.dd[1] + tau;
           }
         low += TWO52;
         low -= TWO52;
       }
      else if (u.dd[0] < 0.0)
       {
         if (u.dd[1] < 0.0)
           {
             /* If the high/low doubles are the same sign then simply
                round the low double.  */
             high = u.dd[0];
             low = u.dd[1];
           }
         else if (u.dd[1] > 0.0)
           {
             /* Else the high double is pre rounded and we need to
                adjust for that.  */
             tau = __nextafter (u.dd[0], 0.0);
             tau = (u.dd[0] - tau) * 2.0;
             high = u.dd[0] - tau;
             low = u.dd[1] + tau;
           }
         low = TWO52 - low;
         low = -(low - TWO52);
       }
      u.dd[0] = high + low;
      u.dd[1] = high - u.dd[0] + low;
      fesetenv (&env);
    }

  return u.d;
}

Here is the call graph for this function: