Blame sysdeps/ieee754/ldbl-128ibm/s_iscanonicall.c

Packit 6c4009
/* Test whether long double value is canonical.  ldbl-128ibm version.
Packit 6c4009
   Copyright (C) 2016-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <math.h>
Packit 6c4009
#include <math_private.h>
Packit 6c4009
#include <stdint.h>
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
__iscanonicall (long double x)
Packit 6c4009
{
Packit 6c4009
  double xhi, xlo;
Packit 6c4009
  uint64_t hx, lx;
Packit 6c4009
Packit 6c4009
  ldbl_unpack (x, &xhi, &xlo;;
Packit 6c4009
  EXTRACT_WORDS64 (hx, xhi);
Packit 6c4009
  EXTRACT_WORDS64 (lx, xlo);
Packit 6c4009
  int64_t ix = hx & 0x7fffffffffffffffULL;
Packit 6c4009
  int64_t iy = lx & 0x7fffffffffffffffULL;
Packit 6c4009
  int hexp = (ix & 0x7ff0000000000000LL) >> 52;
Packit 6c4009
  int lexp = (iy & 0x7ff0000000000000LL) >> 52;
Packit 6c4009
Packit 6c4009
  if (iy == 0)
Packit 6c4009
    /* Low part 0 is always OK.  */
Packit 6c4009
    return 1;
Packit 6c4009
Packit 6c4009
  if (hexp == 0x7ff)
Packit 6c4009
    /* If a NaN, the low part does not matter.  If an infinity, the
Packit 6c4009
       low part must be 0, in which case we have already returned.  */
Packit 6c4009
    return ix != 0x7ff0000000000000LL;
Packit 6c4009
Packit 6c4009
  /* The high part is finite and the low part is nonzero.  There must
Packit 6c4009
     be sufficient difference between the exponents.  */
Packit 6c4009
  bool low_p2;
Packit 6c4009
  if (lexp == 0)
Packit 6c4009
    {
Packit 6c4009
      /* Adjust the exponent for subnormal low part.  */
Packit 6c4009
      lexp = 12 - __builtin_clzll (iy);
Packit 6c4009
      low_p2 = iy == (1LL << (51 + lexp));
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    low_p2 = (iy & 0xfffffffffffffLL) == 0;
Packit 6c4009
  int expdiff = hexp - lexp;
Packit 6c4009
  return expdiff > 53 || (expdiff == 53 && low_p2 && (ix & 1) == 0);
Packit 6c4009
}
Packit 6c4009
libm_hidden_def (__iscanonicall)