Blame sysdeps/powerpc/powerpc32/fpu/s_llroundf.c

Packit Service 82fcde
/* Round float value to long long int.
Packit Service 82fcde
   Copyright (C) 1997-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <math.h>
Packit Service 82fcde
#include <math_private.h>
Packit Service 82fcde
#include <stdint.h>
Packit Service 82fcde
#include <libm-alias-float.h>
Packit Service 82fcde
Packit Service 82fcde
/* Round to the nearest integer, with values exactly on a 0.5 boundary
Packit Service 82fcde
   rounded away from zero, regardless of the current rounding mode.
Packit Service 82fcde
   If (long long)x, when x is out of range of a long long, clips at
Packit Service 82fcde
   LLONG_MAX or LLONG_MIN, then this implementation also clips.  */
Packit Service 82fcde
Packit Service 82fcde
long long int
Packit Service 82fcde
__llroundf (float x)
Packit Service 82fcde
{
Packit Service 82fcde
  long long xr;
Packit Service 82fcde
  if (HAVE_PPC_FCTIDZ)
Packit Service 82fcde
    xr = (long long) x;
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      float ax = fabsf (x);
Packit Service 82fcde
      /* Avoid incorrect exceptions from libgcc conversions (as of GCC
Packit Service 82fcde
	 5): <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59412>.  */
Packit Service 82fcde
      if (ax < 0x1p31f)
Packit Service 82fcde
	xr = (long long int) (long int) x;
Packit Service 82fcde
      else if (!(ax < 0x1p55f))
Packit Service 82fcde
	xr = (long long int) (long int) (x * 0x1p-32f) << 32;
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  uint32_t i0;
Packit Service 82fcde
	  GET_FLOAT_WORD (i0, x);
Packit Service 82fcde
	  int exponent = ((i0 >> 23) & 0xff) - 0x7f;
Packit Service 82fcde
	  unsigned long long int mant = (i0 & 0x7fffff) | 0x800000;
Packit Service 82fcde
	  mant <<= exponent - 23;
Packit Service 82fcde
	  xr = (long long int) ((i0 & 0x80000000) != 0 ? -mant : mant);
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
  /* Avoid spurious "inexact" converting LLONG_MAX to float, and from
Packit Service 82fcde
     subtraction when the result is out of range, by returning early
Packit Service 82fcde
     for arguments large enough that no rounding is needed.  */
Packit Service 82fcde
  if (!(fabsf (x) < 0x1p23f))
Packit Service 82fcde
    return xr;
Packit Service 82fcde
  float xrf = (float) xr;
Packit Service 82fcde
Packit Service 82fcde
  if (x >= 0.0)
Packit Service 82fcde
    {
Packit Service 82fcde
      if (x - xrf >= 0.5)
Packit Service 82fcde
	xr += (long long) ((unsigned long long) xr + 1) > 0;
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      if (xrf - x >= 0.5)
Packit Service 82fcde
	xr -= (long long) ((unsigned long long) xr - 1) < 0;
Packit Service 82fcde
    }
Packit Service 82fcde
  return xr;
Packit Service 82fcde
}
Packit Service 82fcde
libm_alias_float (__llround, llround)