| /* 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 ()); |
| } |