144 lines
3.2 KiB
C++
144 lines
3.2 KiB
C++
/* d-ctfloat.cc -- D frontend interface to the gcc back-end.
|
|
Copyright (C) 2020-2021 Free Software Foundation, Inc.
|
|
|
|
GCC is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3, or (at your option)
|
|
any later version.
|
|
|
|
GCC is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GCC; see the file COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#include "config.h"
|
|
#include "system.h"
|
|
#include "coretypes.h"
|
|
|
|
#include "dmd/root/ctfloat.h"
|
|
#include "dmd/target.h"
|
|
|
|
#include "tree.h"
|
|
|
|
|
|
/* Implements the CTFloat interface defined by the frontend.
|
|
Compile-time floating-pointer helper functions. */
|
|
|
|
/* Return the absolute value of R. */
|
|
|
|
real_t
|
|
CTFloat::fabs (real_t r)
|
|
{
|
|
real_t x;
|
|
real_arithmetic (&x.rv (), ABS_EXPR, &r.rv (), NULL);
|
|
return x.normalize ();
|
|
}
|
|
|
|
/* Return the value of R * 2 ^^ EXP. */
|
|
|
|
real_t
|
|
CTFloat::ldexp (real_t r, int exp)
|
|
{
|
|
real_t x;
|
|
real_ldexp (&x.rv (), &r.rv (), exp);
|
|
return x.normalize ();
|
|
}
|
|
|
|
/* Return true if longdouble value X is identical to Y. */
|
|
|
|
bool
|
|
CTFloat::isIdentical (real_t x, real_t y)
|
|
{
|
|
real_value rx = x.rv ();
|
|
real_value ry = y.rv ();
|
|
return (REAL_VALUE_ISNAN (rx) && REAL_VALUE_ISNAN (ry))
|
|
|| real_identical (&rx, &ry);
|
|
}
|
|
|
|
/* Return true if real_t value R is NaN. */
|
|
|
|
bool
|
|
CTFloat::isNaN (real_t r)
|
|
{
|
|
return REAL_VALUE_ISNAN (r.rv ());
|
|
}
|
|
|
|
/* Same as isNaN, but also check if is signalling. */
|
|
|
|
bool
|
|
CTFloat::isSNaN (real_t r)
|
|
{
|
|
return REAL_VALUE_ISSIGNALING_NAN (r.rv ());
|
|
}
|
|
|
|
/* Return true if real_t value is +Inf. */
|
|
|
|
bool
|
|
CTFloat::isInfinity (real_t r)
|
|
{
|
|
return REAL_VALUE_ISINF (r.rv ());
|
|
}
|
|
|
|
/* Return a real_t value from string BUFFER rounded to long double mode. */
|
|
|
|
real_t
|
|
CTFloat::parse (const char *buffer, bool *overflow)
|
|
{
|
|
real_t r;
|
|
real_from_string3 (&r.rv (), buffer, TYPE_MODE (long_double_type_node));
|
|
|
|
/* Front-end checks overflow to see if the value is representable. */
|
|
if (overflow && r == target.RealProperties.infinity)
|
|
*overflow = true;
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Format the real_t value R to string BUFFER as a decimal or hexadecimal,
|
|
converting the result to uppercase if FMT requests it. */
|
|
|
|
int
|
|
CTFloat::sprint (char *buffer, char fmt, real_t r)
|
|
{
|
|
if (fmt == 'a' || fmt == 'A')
|
|
{
|
|
/* Converting to a hexadecimal string. */
|
|
real_to_hexadecimal (buffer, &r.rv (), 32, 0, 1);
|
|
int buflen;
|
|
|
|
switch (fmt)
|
|
{
|
|
case 'A':
|
|
buflen = strlen (buffer);
|
|
for (int i = 0; i < buflen; i++)
|
|
buffer[i] = TOUPPER (buffer[i]);
|
|
|
|
return buflen;
|
|
|
|
case 'a':
|
|
return strlen (buffer);
|
|
|
|
default:
|
|
gcc_unreachable ();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Note: restricting the precision of significant digits to 18. */
|
|
real_to_decimal (buffer, &r.rv (), 32, 18, 1);
|
|
return strlen (buffer);
|
|
}
|
|
}
|
|
|
|
/* Return a hash value for real_t value R. */
|
|
|
|
size_t
|
|
CTFloat::hash (real_t r)
|
|
{
|
|
return real_hash (&r.rv ());
|
|
}
|