(root)/
glibc-2.38/
sysdeps/
ieee754/
dbl-64/
s_floor.c
       1  /* Round double to integer away from zero.
       2     Copyright (C) 2011-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  /* Based on a version which carries the following copyright:  */
      20  
      21  /*
      22   * ====================================================
      23   * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
      24   *
      25   * Developed at SunPro, a Sun Microsystems, Inc. business.
      26   * Permission to use, copy, modify, and distribute this
      27   * software is freely granted, provided that this notice
      28   * is preserved.
      29   * ====================================================
      30   */
      31  
      32  #define NO_MATH_REDIRECT
      33  #include <math.h>
      34  #include <math_private.h>
      35  #include <stdint.h>
      36  #include <libm-alias-double.h>
      37  #include <math-use-builtins.h>
      38  
      39  /*
      40   * floor(x)
      41   * Return x rounded toward -inf to integral value
      42   * Method:
      43   *	Bit twiddling.
      44   */
      45  
      46  
      47  double
      48  __floor (double x)
      49  {
      50  #if USE_FLOOR_BUILTIN
      51    return __builtin_floor (x);
      52  #else
      53    /* Use generic implementation.  */
      54    int64_t i0;
      55    EXTRACT_WORDS64 (i0, x);
      56    int32_t j0 = ((i0 >> 52) & 0x7ff) - 0x3ff;
      57    if (__glibc_likely (j0 < 52))
      58      {
      59        if (j0 < 0)
      60  	{
      61  	  /* return 0 * sign (x) if |x| < 1  */
      62  	  if (i0 >= 0)
      63  	    i0 = 0;
      64  	  else if ((i0 & 0x7fffffffffffffffl) != 0)
      65  	    i0 = 0xbff0000000000000l;
      66  	}
      67        else
      68  	{
      69  	  uint64_t i = 0x000fffffffffffffl >> j0;
      70  	  if ((i0 & i) == 0)
      71  	    return x;			 /* x is integral */
      72  	  if (i0 < 0)
      73  	    i0 += 0x0010000000000000l >> j0;
      74  	  i0 &= ~i;
      75  	}
      76        INSERT_WORDS64 (x, i0);
      77      }
      78    else if (j0 == 0x400)
      79      return x + x;			/* inf or NaN */
      80    return x;
      81  #endif /* ! USE_FLOOR_BUILTIN  */
      82  }
      83  #ifndef __floor
      84  libm_alias_double (__floor, floor)
      85  #endif