1  /* s_nearbyintl.c -- long double version of s_nearbyint.c.
       2   */
       3  
       4  /*
       5   * ====================================================
       6   * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
       7   *
       8   * Developed at SunPro, a Sun Microsystems, Inc. business.
       9   * Permission to use, copy, modify, and distribute this
      10   * software is freely granted, provided that this notice
      11   * is preserved.
      12   * ====================================================
      13   */
      14  
      15  /*
      16   * nearbyintl(x)
      17   * Return x rounded to integral value according to the prevailing
      18   * rounding mode.
      19   * Method:
      20   *	Using floating addition.
      21   * Exception:
      22   *	Inexact flag raised if x not equal to rintl(x).
      23   */
      24  
      25  #include <fenv.h>
      26  #include <math.h>
      27  #include <math-barriers.h>
      28  #include <math_private.h>
      29  #include <libm-alias-ldouble.h>
      30  #include <math-use-builtins.h>
      31  
      32  _Float128
      33  __nearbyintl (_Float128 x)
      34  {
      35  #if USE_NEARBYINTL_BUILTIN
      36    return __builtin_nearbyintl (x);
      37  #else
      38    /* Use generic implementation.  */
      39    static const _Float128
      40      TWO112[2] = {
      41  		 L(5.19229685853482762853049632922009600E+33), /* 0x406F000000000000, 0 */
      42  		 L(-5.19229685853482762853049632922009600E+33)  /* 0xC06F000000000000, 0 */
      43    };
      44    fenv_t env;
      45    int64_t i0, j0, sx;
      46    uint64_t i1 __attribute__ ((unused));
      47    _Float128 w, t;
      48    GET_LDOUBLE_WORDS64 (i0, i1, x);
      49    sx = (((uint64_t) i0) >> 63);
      50    j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
      51    if (j0 < 112)
      52      {
      53        if (j0 < 0)
      54  	{
      55  	  feholdexcept (&env);
      56  	  w = TWO112[sx] + math_opt_barrier (x);
      57  	  t = w - TWO112[sx];
      58  	  math_force_eval (t);
      59  	  fesetenv (&env);
      60  	  GET_LDOUBLE_MSW64 (i0, t);
      61  	  SET_LDOUBLE_MSW64 (t, (i0 & 0x7fffffffffffffffLL) | (sx << 63));
      62  	  return t;
      63  	}
      64      }
      65    else
      66      {
      67        if (j0 == 0x4000)
      68  	return x + x;		/* inf or NaN  */
      69        else
      70  	return x;		/* x is integral  */
      71      }
      72    feholdexcept (&env);
      73    w = TWO112[sx] + math_opt_barrier (x);
      74    t = w - TWO112[sx];
      75    math_force_eval (t);
      76    fesetenv (&env);
      77    return t;
      78  #endif /* ! USE_NEARBYINTL_BUILTIN  */
      79  }
      80  libm_alias_ldouble (__nearbyint, nearbyint)