Blame lib/signbitf.c

Packit 9e4112
/* signbit() macro: Determine the sign bit of a floating-point number.
Packit 9e4112
   Copyright (C) 2007, 2009-2018 Free Software Foundation, Inc.
Packit 9e4112
Packit 9e4112
   This program is free software: you can redistribute it and/or modify
Packit 9e4112
   it under the terms of the GNU General Public License as published by
Packit 9e4112
   the Free Software Foundation; either version 3 of the License, or
Packit 9e4112
   (at your option) any later version.
Packit 9e4112
Packit 9e4112
   This program is distributed in the hope that it will be useful,
Packit 9e4112
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 9e4112
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 9e4112
   GNU General Public License for more details.
Packit 9e4112
Packit 9e4112
   You should have received a copy of the GNU General Public License
Packit 9e4112
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
Packit 9e4112
Packit 9e4112
#include <config.h>
Packit 9e4112
Packit 9e4112
/* Specification.  */
Packit 9e4112
#include <math.h>
Packit 9e4112
Packit 9e4112
#include <string.h>
Packit 9e4112
#include "isnanf-nolibm.h"
Packit 9e4112
#include "float+.h"
Packit 9e4112
Packit 9e4112
#ifdef gl_signbitf_OPTIMIZED_MACRO
Packit 9e4112
# undef gl_signbitf
Packit 9e4112
#endif
Packit 9e4112
Packit 9e4112
int
Packit 9e4112
gl_signbitf (float arg)
Packit 9e4112
{
Packit 9e4112
#if defined FLT_SIGNBIT_WORD && defined FLT_SIGNBIT_BIT
Packit 9e4112
  /* The use of a union to extract the bits of the representation of a
Packit 9e4112
     'long double' is safe in practice, despite of the "aliasing rules" of
Packit 9e4112
     C99, because the GCC docs say
Packit 9e4112
       "Even with '-fstrict-aliasing', type-punning is allowed, provided the
Packit 9e4112
        memory is accessed through the union type."
Packit 9e4112
     and similarly for other compilers.  */
Packit 9e4112
# define NWORDS \
Packit 9e4112
    ((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
Packit 9e4112
  union { float value; unsigned int word[NWORDS]; } m;
Packit 9e4112
  m.value = arg;
Packit 9e4112
  return (m.word[FLT_SIGNBIT_WORD] >> FLT_SIGNBIT_BIT) & 1;
Packit 9e4112
#elif HAVE_COPYSIGNF_IN_LIBC
Packit 9e4112
  return copysignf (1.0f, arg) < 0;
Packit 9e4112
#else
Packit 9e4112
  /* This does not do the right thing for NaN, but this is irrelevant for
Packit 9e4112
     most use cases.  */
Packit 9e4112
  if (isnanf (arg))
Packit 9e4112
    return 0;
Packit 9e4112
  if (arg < 0.0f)
Packit 9e4112
    return 1;
Packit 9e4112
  else if (arg == 0.0f)
Packit 9e4112
    {
Packit 9e4112
      /* Distinguish 0.0f and -0.0f.  */
Packit 9e4112
      static float plus_zero = 0.0f;
Packit 9e4112
      float arg_mem = arg;
Packit 9e4112
      return (memcmp (&plus_zero, &arg_mem, SIZEOF_FLT) != 0);
Packit 9e4112
    }
Packit 9e4112
  else
Packit 9e4112
    return 0;
Packit 9e4112
#endif
Packit 9e4112
}