1  /* s_ceill.c -- long double version of s_ceil.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  #if defined (LIBM_SCCS) && ! defined (lint)
      16  static char rcsid[] = "$NetBSD: $";
      17  #endif
      18  
      19  /*
      20   * ceill(x)
      21   * Return x rounded toward -inf to integral value
      22   * Method:
      23   *	Bit twiddling.
      24   */
      25  
      26  #define NO_MATH_REDIRECT
      27  #include <math.h>
      28  #include <math_private.h>
      29  #include <libm-alias-ldouble.h>
      30  #include <math-use-builtins.h>
      31  
      32  _Float128
      33  __ceill (_Float128 x)
      34  {
      35  #if USE_CEILL_BUILTIN
      36    return __builtin_ceill (x);
      37  #else
      38    /* Use generic implementation.  */
      39    int64_t i0, i1, j0;
      40    uint64_t i, j;
      41    GET_LDOUBLE_WORDS64 (i0, i1, x);
      42    j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
      43    if (j0 < 48)
      44      {
      45        if (j0 < 0)
      46  	{
      47  	  /* return 0 * sign (x) if |x| < 1  */
      48  	  if (i0 < 0)
      49  	    {
      50  	      i0 = 0x8000000000000000ULL;
      51  	      i1 = 0;
      52  	    }
      53  	  else if ((i0 | i1) != 0)
      54  	    {
      55  	      i0 = 0x3fff000000000000ULL;
      56  	      i1 = 0;
      57  	    }
      58  	}
      59        else
      60  	{
      61  	  i = (0x0000ffffffffffffULL) >> j0;
      62  	  if (((i0 & i) | i1) == 0)
      63  	    return x;		/* x is integral  */
      64  	  if (i0 > 0)
      65  	    i0 += (0x0001000000000000LL) >> j0;
      66  	  i0 &= (~i);
      67  	  i1 = 0;
      68  	}
      69      }
      70    else if (j0 > 111)
      71      {
      72        if (j0 == 0x4000)
      73  	return x + x;		/* inf or NaN  */
      74        else
      75  	return x;		/* x is integral  */
      76      }
      77    else
      78      {
      79        i = -1ULL >> (j0 - 48);
      80        if ((i1 & i) == 0)
      81  	return x;		/* x is integral  */
      82        if (i0 > 0)
      83  	{
      84  	  if (j0 == 48)
      85  	    i0 += 1;
      86  	  else
      87  	    {
      88  	      j = i1 + (1LL << (112 - j0));
      89  	      if (j < i1)
      90  		i0 += 1;	/* got a carry  */
      91  	      i1 = j;
      92  	    }
      93  	}
      94        i1 &= (~i);
      95      }
      96    SET_LDOUBLE_WORDS64 (x, i0, i1);
      97    return x;
      98  #endif /* ! USE_CEILL_BUILTIN  */
      99  }
     100  libm_alias_ldouble (__ceil, ceil)