| /* real.c - software floating point emulation. |
| Copyright (C) 1993-2021 Free Software Foundation, Inc. |
| Contributed by Stephen L. Moshier (moshier@world.std.com). |
| Re-written by Richard Henderson <rth@redhat.com> |
| |
| This file is part of GCC. |
| |
| 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 "tm.h" |
| #include "rtl.h" |
| #include "tree.h" |
| #include "realmpfr.h" |
| #include "dfp.h" |
| |
| /* The floating point model used internally is not exactly IEEE 754 |
| compliant, and close to the description in the ISO C99 standard, |
| section 5.2.4.2.2 Characteristics of floating types. |
| |
| Specifically |
| |
| x = s * b^e * \sum_{k=1}^p f_k * b^{-k} |
| |
| where |
| s = sign (+- 1) |
| b = base or radix, here always 2 |
| e = exponent |
| p = precision (the number of base-b digits in the significand) |
| f_k = the digits of the significand. |
| |
| We differ from typical IEEE 754 encodings in that the entire |
| significand is fractional. Normalized significands are in the |
| range [0.5, 1.0). |
| |
| A requirement of the model is that P be larger than the largest |
| supported target floating-point type by at least 2 bits. This gives |
| us proper rounding when we truncate to the target type. In addition, |
| E must be large enough to hold the smallest supported denormal number |
| in a normalized form. |
| |
| Both of these requirements are easily satisfied. The largest target |
| significand is 113 bits; we store at least 160. The smallest |
| denormal number fits in 17 exponent bits; we store 26. */ |
| |
| |
| /* Used to classify two numbers simultaneously. */ |
| #define CLASS2(A, B) ((A) << 2 | (B)) |
| |
| #if HOST_BITS_PER_LONG != 64 && HOST_BITS_PER_LONG != 32 |
| #error "Some constant folding done by hand to avoid shift count warnings" |
| #endif |
| |
| static void get_zero (REAL_VALUE_TYPE *, int); |
| static void get_canonical_qnan (REAL_VALUE_TYPE *, int); |
| static void get_canonical_snan (REAL_VALUE_TYPE *, int); |
| static void get_inf (REAL_VALUE_TYPE *, int); |
| static bool sticky_rshift_significand (REAL_VALUE_TYPE *, |
| const REAL_VALUE_TYPE *, unsigned int); |
| static void rshift_significand (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, |
| unsigned int); |
| static void lshift_significand (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, |
| unsigned int); |
| static void lshift_significand_1 (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); |
| static bool add_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *, |
| const REAL_VALUE_TYPE *); |
| static bool sub_significands (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, |
| const REAL_VALUE_TYPE *, int); |
| static void neg_significand (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); |
| static int cmp_significands (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); |
| static int cmp_significand_0 (const REAL_VALUE_TYPE *); |
| static void set_significand_bit (REAL_VALUE_TYPE *, unsigned int); |
| static void clear_significand_bit (REAL_VALUE_TYPE *, unsigned int); |
| static bool test_significand_bit (REAL_VALUE_TYPE *, unsigned int); |
| static void clear_significand_below (REAL_VALUE_TYPE *, unsigned int); |
| static bool div_significands (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, |
| const REAL_VALUE_TYPE *); |
| static void normalize (REAL_VALUE_TYPE *); |
| |
| static bool do_add (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, |
| const REAL_VALUE_TYPE *, int); |
| static bool do_multiply (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, |
| const REAL_VALUE_TYPE *); |
| static bool do_divide (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, |
| const REAL_VALUE_TYPE *); |
| static int do_compare (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, int); |
| static void do_fix_trunc (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); |
| |
| static unsigned long rtd_divmod (REAL_VALUE_TYPE *, REAL_VALUE_TYPE *); |
| static void decimal_from_integer (REAL_VALUE_TYPE *); |
| static void decimal_integer_string (char *, const REAL_VALUE_TYPE *, |
| size_t); |
| |
| static const REAL_VALUE_TYPE * ten_to_ptwo (int); |
| static const REAL_VALUE_TYPE * ten_to_mptwo (int); |
| static const REAL_VALUE_TYPE * real_digit (int); |
| static void times_pten (REAL_VALUE_TYPE *, int); |
| |
| static void round_for_format (const struct real_format *, REAL_VALUE_TYPE *); |
| |
| /* Initialize R with a positive zero. */ |
| |
| static inline void |
| get_zero (REAL_VALUE_TYPE *r, int sign) |
| { |
| memset (r, 0, sizeof (*r)); |
| r->sign = sign; |
| } |
| |
| /* Initialize R with the canonical quiet NaN. */ |
| |
| static inline void |
| get_canonical_qnan (REAL_VALUE_TYPE *r, int sign) |
| { |
| memset (r, 0, sizeof (*r)); |
| r->cl = rvc_nan; |
| r->sign = sign; |
| r->canonical = 1; |
| } |
| |
| static inline void |
| get_canonical_snan (REAL_VALUE_TYPE *r, int sign) |
| { |
| memset (r, 0, sizeof (*r)); |
| r->cl = rvc_nan; |
| r->sign = sign; |
| r->signalling = 1; |
| r->canonical = 1; |
| } |
| |
| static inline void |
| get_inf (REAL_VALUE_TYPE *r, int sign) |
| { |
| memset (r, 0, sizeof (*r)); |
| r->cl = rvc_inf; |
| r->sign = sign; |
| } |
| |
| |
| /* Right-shift the significand of A by N bits; put the result in the |
| significand of R. If any one bits are shifted out, return true. */ |
| |
| static bool |
| sticky_rshift_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, |
| unsigned int n) |
| { |
| unsigned long sticky = 0; |
| unsigned int i, ofs = 0; |
| |
| if (n >= HOST_BITS_PER_LONG) |
| { |
| for (i = 0, ofs = n / HOST_BITS_PER_LONG; i < ofs; ++i) |
| sticky |= a->sig[i]; |
| n &= HOST_BITS_PER_LONG - 1; |
| } |
| |
| if (n != 0) |
| { |
| sticky |= a->sig[ofs] & (((unsigned long)1 << n) - 1); |
| for (i = 0; i < SIGSZ; ++i) |
| { |
| r->sig[i] |
| = (((ofs + i >= SIGSZ ? 0 : a->sig[ofs + i]) >> n) |
| | ((ofs + i + 1 >= SIGSZ ? 0 : a->sig[ofs + i + 1]) |
| << (HOST_BITS_PER_LONG - n))); |
| } |
| } |
| else |
| { |
| for (i = 0; ofs + i < SIGSZ; ++i) |
| r->sig[i] = a->sig[ofs + i]; |
| for (; i < SIGSZ; ++i) |
| r->sig[i] = 0; |
| } |
| |
| return sticky != 0; |
| } |
| |
| /* Right-shift the significand of A by N bits; put the result in the |
| significand of R. */ |
| |
| static void |
| rshift_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, |
| unsigned int n) |
| { |
| unsigned int i, ofs = n / HOST_BITS_PER_LONG; |
| |
| n &= HOST_BITS_PER_LONG - 1; |
| if (n != 0) |
| { |
| for (i = 0; i < SIGSZ; ++i) |
| { |
| r->sig[i] |
| = (((ofs + i >= SIGSZ ? 0 : a->sig[ofs + i]) >> n) |
| | ((ofs + i + 1 >= SIGSZ ? 0 : a->sig[ofs + i + 1]) |
| << (HOST_BITS_PER_LONG - n))); |
| } |
| } |
| else |
| { |
| for (i = 0; ofs + i < SIGSZ; ++i) |
| r->sig[i] = a->sig[ofs + i]; |
| for (; i < SIGSZ; ++i) |
| r->sig[i] = 0; |
| } |
| } |
| |
| /* Left-shift the significand of A by N bits; put the result in the |
| significand of R. */ |
| |
| static void |
| lshift_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, |
| unsigned int n) |
| { |
| unsigned int i, ofs = n / HOST_BITS_PER_LONG; |
| |
| n &= HOST_BITS_PER_LONG - 1; |
| if (n == 0) |
| { |
| for (i = 0; ofs + i < SIGSZ; ++i) |
| r->sig[SIGSZ-1-i] = a->sig[SIGSZ-1-i-ofs]; |
| for (; i < SIGSZ; ++i) |
| r->sig[SIGSZ-1-i] = 0; |
| } |
| else |
| for (i = 0; i < SIGSZ; ++i) |
| { |
| r->sig[SIGSZ-1-i] |
| = (((ofs + i >= SIGSZ ? 0 : a->sig[SIGSZ-1-i-ofs]) << n) |
| | ((ofs + i + 1 >= SIGSZ ? 0 : a->sig[SIGSZ-1-i-ofs-1]) |
| >> (HOST_BITS_PER_LONG - n))); |
| } |
| } |
| |
| /* Likewise, but N is specialized to 1. */ |
| |
| static inline void |
| lshift_significand_1 (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a) |
| { |
| unsigned int i; |
| |
| for (i = SIGSZ - 1; i > 0; --i) |
| r->sig[i] = (a->sig[i] << 1) | (a->sig[i-1] >> (HOST_BITS_PER_LONG - 1)); |
| r->sig[0] = a->sig[0] << 1; |
| } |
| |
| /* Add the significands of A and B, placing the result in R. Return |
| true if there was carry out of the most significant word. */ |
| |
| static inline bool |
| add_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, |
| const REAL_VALUE_TYPE *b) |
| { |
| bool carry = false; |
| int i; |
| |
| for (i = 0; i < SIGSZ; ++i) |
| { |
| unsigned long ai = a->sig[i]; |
| unsigned long ri = ai + b->sig[i]; |
| |
| if (carry) |
| { |
| carry = ri < ai; |
| carry |= ++ri == 0; |
| } |
| else |
| carry = ri < ai; |
| |
| r->sig[i] = ri; |
| } |
| |
| return carry; |
| } |
| |
| /* Subtract the significands of A and B, placing the result in R. CARRY is |
| true if there's a borrow incoming to the least significant word. |
| Return true if there was borrow out of the most significant word. */ |
| |
| static inline bool |
| sub_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, |
| const REAL_VALUE_TYPE *b, int carry) |
| { |
| int i; |
| |
| for (i = 0; i < SIGSZ; ++i) |
| { |
| unsigned long ai = a->sig[i]; |
| unsigned long ri = ai - b->sig[i]; |
| |
| if (carry) |
| { |
| carry = ri > ai; |
| carry |= ~--ri == 0; |
| } |
| else |
| carry = ri > ai; |
| |
| r->sig[i] = ri; |
| } |
| |
| return carry; |
| } |
| |
| /* Negate the significand A, placing the result in R. */ |
| |
| static inline void |
| neg_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a) |
| { |
| bool carry = true; |
| int i; |
| |
| for (i = 0; i < SIGSZ; ++i) |
| { |
| unsigned long ri, ai = a->sig[i]; |
| |
| if (carry) |
| { |
| if (ai) |
| { |
| ri = -ai; |
| carry = false; |
| } |
| else |
| ri = ai; |
| } |
| else |
| ri = ~ai; |
| |
| r->sig[i] = ri; |
| } |
| } |
| |
| /* Compare significands. Return tri-state vs zero. */ |
| |
| static inline int |
| cmp_significands (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b) |
| { |
| int i; |
| |
| for (i = SIGSZ - 1; i >= 0; --i) |
| { |
| unsigned long ai = a->sig[i]; |
| unsigned long bi = b->sig[i]; |
| |
| if (ai > bi) |
| return 1; |
| if (ai < bi) |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| /* Return true if A is nonzero. */ |
| |
| static inline int |
| cmp_significand_0 (const REAL_VALUE_TYPE *a) |
| { |
| int i; |
| |
| for (i = SIGSZ - 1; i >= 0; --i) |
| if (a->sig[i]) |
| return 1; |
| |
| return 0; |
| } |
| |
| /* Set bit N of the significand of R. */ |
| |
| static inline void |
| set_significand_bit (REAL_VALUE_TYPE *r, unsigned int n) |
| { |
| r->sig[n / HOST_BITS_PER_LONG] |
| |= (unsigned long)1 << (n % HOST_BITS_PER_LONG); |
| } |
| |
| /* Clear bit N of the significand of R. */ |
| |
| static inline void |
| clear_significand_bit (REAL_VALUE_TYPE *r, unsigned int n) |
| { |
| r->sig[n / HOST_BITS_PER_LONG] |
| &= ~((unsigned long)1 << (n % HOST_BITS_PER_LONG)); |
| } |
| |
| /* Test bit N of the significand of R. */ |
| |
| static inline bool |
| test_significand_bit (REAL_VALUE_TYPE *r, unsigned int n) |
| { |
| /* ??? Compiler bug here if we return this expression directly. |
| The conversion to bool strips the "&1" and we wind up testing |
| e.g. 2 != 0 -> true. Seen in gcc version 3.2 20020520. */ |
| int t = (r->sig[n / HOST_BITS_PER_LONG] >> (n % HOST_BITS_PER_LONG)) & 1; |
| return t; |
| } |
| |
| /* Clear bits 0..N-1 of the significand of R. */ |
| |
| static void |
| clear_significand_below (REAL_VALUE_TYPE *r, unsigned int n) |
| { |
| int i, w = n / HOST_BITS_PER_LONG; |
| |
| for (i = 0; i < w; ++i) |
| r->sig[i] = 0; |
| |
| /* We are actually passing N == SIGNIFICAND_BITS which would result |
| in an out-of-bound access below. */ |
| if (n % HOST_BITS_PER_LONG != 0) |
| r->sig[w] &= ~(((unsigned long)1 << (n % HOST_BITS_PER_LONG)) - 1); |
| } |
| |
| /* Divide the significands of A and B, placing the result in R. Return |
| true if the division was inexact. */ |
| |
| static inline bool |
| div_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, |
| const REAL_VALUE_TYPE *b) |
| { |
| REAL_VALUE_TYPE u; |
| int i, bit = SIGNIFICAND_BITS - 1; |
| unsigned long msb, inexact; |
| |
| u = *a; |
| memset (r->sig, 0, sizeof (r->sig)); |
| |
| msb = 0; |
| goto start; |
| do |
| { |
| msb = u.sig[SIGSZ-1] & SIG_MSB; |
| lshift_significand_1 (&u, &u); |
| start: |
| if (msb || cmp_significands (&u, b) >= 0) |
| { |
| sub_significands (&u, &u, b, 0); |
| set_significand_bit (r, bit); |
| } |
| } |
| while (--bit >= 0); |
| |
| for (i = 0, inexact = 0; i < SIGSZ; i++) |
| inexact |= u.sig[i]; |
| |
| return inexact != 0; |
| } |
| |
| /* Adjust the exponent and significand of R such that the most |
| significant bit is set. We underflow to zero and overflow to |
| infinity here, without denormals. (The intermediate representation |
| exponent is large enough to handle target denormals normalized.) */ |
| |
| static void |
| normalize (REAL_VALUE_TYPE *r) |
| { |
| int shift = 0, exp; |
| int i, j; |
| |
| if (r->decimal) |
| return; |
| |
| /* Find the first word that is nonzero. */ |
| for (i = SIGSZ - 1; i >= 0; i--) |
| if (r->sig[i] == 0) |
| shift += HOST_BITS_PER_LONG; |
| else |
| break; |
| |
| /* Zero significand flushes to zero. */ |
| if (i < 0) |
| { |
| r->cl = rvc_zero; |
| SET_REAL_EXP (r, 0); |
| return; |
| } |
| |
| /* Find the first bit that is nonzero. */ |
| for (j = 0; ; j++) |
| if (r->sig[i] & ((unsigned long)1 << (HOST_BITS_PER_LONG - 1 - j))) |
| break; |
| shift += j; |
| |
| if (shift > 0) |
| { |
| exp = REAL_EXP (r) - shift; |
| if (exp > MAX_EXP) |
| get_inf (r, r->sign); |
| else if (exp < -MAX_EXP) |
| get_zero (r, r->sign); |
| else |
| { |
| SET_REAL_EXP (r, exp); |
| lshift_significand (r, r, shift); |
| } |
| } |
| } |
| |
| /* Calculate R = A + (SUBTRACT_P ? -B : B). Return true if the |
| result may be inexact due to a loss of precision. */ |
| |
| static bool |
| do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, |
| const REAL_VALUE_TYPE *b, int subtract_p) |
| { |
| int dexp, sign, exp; |
| REAL_VALUE_TYPE t; |
| bool inexact = false; |
| |
| /* Determine if we need to add or subtract. */ |
| sign = a->sign; |
| subtract_p = (sign ^ b->sign) ^ subtract_p; |
| |
| switch (CLASS2 (a->cl, b->cl)) |
| { |
| case CLASS2 (rvc_zero, rvc_zero): |
| /* -0 + -0 = -0, -0 - +0 = -0; all other cases yield +0. */ |
| get_zero (r, sign & !subtract_p); |
| return false; |
| |
| case CLASS2 (rvc_zero, rvc_normal): |
| case CLASS2 (rvc_zero, rvc_inf): |
| case CLASS2 (rvc_zero, rvc_nan): |
| /* 0 + ANY = ANY. */ |
| case CLASS2 (rvc_normal, rvc_nan): |
| case CLASS2 (rvc_inf, rvc_nan): |
| case CLASS2 (rvc_nan, rvc_nan): |
| /* ANY + NaN = NaN. */ |
| case CLASS2 (rvc_normal, rvc_inf): |
| /* R + Inf = Inf. */ |
| *r = *b; |
| /* Make resulting NaN value to be qNaN. The caller has the |
| responsibility to avoid the operation if flag_signaling_nans |
| is on. */ |
| r->signalling = 0; |
| r->sign = sign ^ subtract_p; |
| return false; |
| |
| case CLASS2 (rvc_normal, rvc_zero): |
| case CLASS2 (rvc_inf, rvc_zero): |
| case CLASS2 (rvc_nan, rvc_zero): |
| /* ANY + 0 = ANY. */ |
| case CLASS2 (rvc_nan, rvc_normal): |
| case CLASS2 (rvc_nan, rvc_inf): |
| /* NaN + ANY = NaN. */ |
| case CLASS2 (rvc_inf, rvc_normal): |
| /* Inf + R = Inf. */ |
| *r = *a; |
| /* Make resulting NaN value to be qNaN. The caller has the |
| responsibility to avoid the operation if flag_signaling_nans |
| is on. */ |
| r->signalling = 0; |
| return false; |
| |
| case CLASS2 (rvc_inf, rvc_inf): |
| if (subtract_p) |
| /* Inf - Inf = NaN. */ |
| get_canonical_qnan (r, 0); |
| else |
| /* Inf + Inf = Inf. */ |
| *r = *a; |
| return false; |
| |
| case CLASS2 (rvc_normal, rvc_normal): |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| /* Swap the arguments such that A has the larger exponent. */ |
| dexp = REAL_EXP (a) - REAL_EXP (b); |
| if (dexp < 0) |
| { |
| const REAL_VALUE_TYPE *t; |
| t = a, a = b, b = t; |
| dexp = -dexp; |
| sign ^= subtract_p; |
| } |
| exp = REAL_EXP (a); |
| |
| /* If the exponents are not identical, we need to shift the |
| significand of B down. */ |
| if (dexp > 0) |
| { |
| /* If the exponents are too far apart, the significands |
| do not overlap, which makes the subtraction a noop. */ |
| if (dexp >= SIGNIFICAND_BITS) |
| { |
| *r = *a; |
| r->sign = sign; |
| return true; |
| } |
| |
| inexact |= sticky_rshift_significand (&t, b, dexp); |
| b = &t; |
| } |
| |
| if (subtract_p) |
| { |
| if (sub_significands (r, a, b, inexact)) |
| { |
| /* We got a borrow out of the subtraction. That means that |
| A and B had the same exponent, and B had the larger |
| significand. We need to swap the sign and negate the |
| significand. */ |
| sign ^= 1; |
| neg_significand (r, r); |
| } |
| } |
| else |
| { |
| if (add_significands (r, a, b)) |
| { |
| /* We got carry out of the addition. This means we need to |
| shift the significand back down one bit and increase the |
| exponent. */ |
| inexact |= sticky_rshift_significand (r, r, 1); |
| r->sig[SIGSZ-1] |= SIG_MSB; |
| if (++exp > MAX_EXP) |
| { |
| get_inf (r, sign); |
| return true; |
| } |
| } |
| } |
| |
| r->cl = rvc_normal; |
| r->sign = sign; |
| SET_REAL_EXP (r, exp); |
| /* Zero out the remaining fields. */ |
| r->signalling = 0; |
| r->canonical = 0; |
| r->decimal = 0; |
| |
| /* Re-normalize the result. */ |
| normalize (r); |
| |
| /* Special case: if the subtraction results in zero, the result |
| is positive. */ |
| if (r->cl == rvc_zero) |
| r->sign = 0; |
| else |
| r->sig[0] |= inexact; |
| |
| return inexact; |
| } |
| |
| /* Calculate R = A * B. Return true if the result may be inexact. */ |
| |
| static bool |
| do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, |
| const REAL_VALUE_TYPE *b) |
| { |
| REAL_VALUE_TYPE u, t, *rr; |
| unsigned int i, j, k; |
| int sign = a->sign ^ b->sign; |
| bool inexact = false; |
| |
| switch (CLASS2 (a->cl, b->cl)) |
| { |
| case CLASS2 (rvc_zero, rvc_zero): |
| case CLASS2 (rvc_zero, rvc_normal): |
| case CLASS2 (rvc_normal, rvc_zero): |
| /* +-0 * ANY = 0 with appropriate sign. */ |
| get_zero (r, sign); |
| return false; |
| |
| case CLASS2 (rvc_zero, rvc_nan): |
| case CLASS2 (rvc_normal, rvc_nan): |
| case CLASS2 (rvc_inf, rvc_nan): |
| case CLASS2 (rvc_nan, rvc_nan): |
| /* ANY * NaN = NaN. */ |
| *r = *b; |
| /* Make resulting NaN value to be qNaN. The caller has the |
| responsibility to avoid the operation if flag_signaling_nans |
| is on. */ |
| r->signalling = 0; |
| r->sign = sign; |
| return false; |
| |
| case CLASS2 (rvc_nan, rvc_zero): |
| case CLASS2 (rvc_nan, rvc_normal): |
| case CLASS2 (rvc_nan, rvc_inf): |
| /* NaN * ANY = NaN. */ |
| *r = *a; |
| /* Make resulting NaN value to be qNaN. The caller has the |
| responsibility to avoid the operation if flag_signaling_nans |
| is on. */ |
| r->signalling = 0; |
| r->sign = sign; |
| return false; |
| |
| case CLASS2 (rvc_zero, rvc_inf): |
| case CLASS2 (rvc_inf, rvc_zero): |
| /* 0 * Inf = NaN */ |
| get_canonical_qnan (r, sign); |
| return false; |
| |
| case CLASS2 (rvc_inf, rvc_inf): |
| case CLASS2 (rvc_normal, rvc_inf): |
| case CLASS2 (rvc_inf, rvc_normal): |
| /* Inf * Inf = Inf, R * Inf = Inf */ |
| get_inf (r, sign); |
| return false; |
| |
| case CLASS2 (rvc_normal, rvc_normal): |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| if (r == a || r == b) |
| rr = &t; |
| else |
| rr = r; |
| get_zero (rr, 0); |
| |
| /* Collect all the partial products. Since we don't have sure access |
| to a widening multiply, we split each long into two half-words. |
| |
| Consider the long-hand form of a four half-word multiplication: |
| |
| A B C D |
| * E F G H |
| -------------- |
| DE DF DG DH |
| CE CF CG CH |
| BE BF BG BH |
| AE AF AG AH |
| |
| We construct partial products of the widened half-word products |
| that are known to not overlap, e.g. DF+DH. Each such partial |
| product is given its proper exponent, which allows us to sum them |
| and obtain the finished product. */ |
| |
| for (i = 0; i < SIGSZ * 2; ++i) |
| { |
| unsigned long ai = a->sig[i / 2]; |
| if (i & 1) |
| ai >>= HOST_BITS_PER_LONG / 2; |
| else |
| ai &= ((unsigned long)1 << (HOST_BITS_PER_LONG / 2)) - 1; |
| |
| if (ai == 0) |
| continue; |
| |
| for (j = 0; j < 2; ++j) |
| { |
| int exp = (REAL_EXP (a) - (2*SIGSZ-1-i)*(HOST_BITS_PER_LONG/2) |
| + (REAL_EXP (b) - (1-j)*(HOST_BITS_PER_LONG/2))); |
| |
| if (exp > MAX_EXP) |
| { |
| get_inf (r, sign); |
| return true; |
| } |
| if (exp < -MAX_EXP) |
| { |
| /* Would underflow to zero, which we shouldn't bother adding. */ |
| inexact = true; |
| continue; |
| } |
| |
| memset (&u, 0, sizeof (u)); |
| u.cl = rvc_normal; |
| SET_REAL_EXP (&u, exp); |
| |
| for (k = j; k < SIGSZ * 2; k += 2) |
| { |
| unsigned long bi = b->sig[k / 2]; |
| if (k & 1) |
| bi >>= HOST_BITS_PER_LONG / 2; |
| else |
| bi &= ((unsigned long)1 << (HOST_BITS_PER_LONG / 2)) - 1; |
| |
| u.sig[k / 2] = ai * bi; |
| } |
| |
| normalize (&u); |
| inexact |= do_add (rr, rr, &u, 0); |
| } |
| } |
| |
| rr->sign = sign; |
| if (rr != r) |
| *r = t; |
| |
| return inexact; |
| } |
| |
| /* Calculate R = A / B. Return true if the result may be inexact. */ |
| |
| static bool |
| do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, |
| const REAL_VALUE_TYPE *b) |
| { |
| int exp, sign = a->sign ^ b->sign; |
| REAL_VALUE_TYPE t, *rr; |
| bool inexact; |
| |
| switch (CLASS2 (a->cl, b->cl)) |
| { |
| case CLASS2 (rvc_zero, rvc_zero): |
| /* 0 / 0 = NaN. */ |
| case CLASS2 (rvc_inf, rvc_inf): |
| /* Inf / Inf = NaN. */ |
| get_canonical_qnan (r, sign); |
| return false; |
| |
| case CLASS2 (rvc_zero, rvc_normal): |
| case CLASS2 (rvc_zero, rvc_inf): |
| /* 0 / ANY = 0. */ |
| case CLASS2 (rvc_normal, rvc_inf): |
| /* R / Inf = 0. */ |
| get_zero (r, sign); |
| return false; |
| |
| case CLASS2 (rvc_normal, rvc_zero): |
| /* R / 0 = Inf. */ |
| case CLASS2 (rvc_inf, rvc_zero): |
| /* Inf / 0 = Inf. */ |
| get_inf (r, sign); |
| return false; |
| |
| case CLASS2 (rvc_zero, rvc_nan): |
| case CLASS2 (rvc_normal, rvc_nan): |
| case CLASS2 (rvc_inf, rvc_nan): |
| case CLASS2 (rvc_nan, rvc_nan): |
| /* ANY / NaN = NaN. */ |
| *r = *b; |
| /* Make resulting NaN value to be qNaN. The caller has the |
| responsibility to avoid the operation if flag_signaling_nans |
| is on. */ |
| r->signalling = 0; |
| r->sign = sign; |
| return false; |
| |
| case CLASS2 (rvc_nan, rvc_zero): |
| case CLASS2 (rvc_nan, rvc_normal): |
| case CLASS2 (rvc_nan, rvc_inf): |
| /* NaN / ANY = NaN. */ |
| *r = *a; |
| /* Make resulting NaN value to be qNaN. The caller has the |
| responsibility to avoid the operation if flag_signaling_nans |
| is on. */ |
| r->signalling = 0; |
| r->sign = sign; |
| return false; |
| |
| case CLASS2 (rvc_inf, rvc_normal): |
| /* Inf / R = Inf. */ |
| get_inf (r, sign); |
| return false; |
| |
| case CLASS2 (rvc_normal, rvc_normal): |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| if (r == a || r == b) |
| rr = &t; |
| else |
| rr = r; |
| |
| /* Make sure all fields in the result are initialized. */ |
| get_zero (rr, 0); |
| rr->cl = rvc_normal; |
| rr->sign = sign; |
| |
| exp = REAL_EXP (a) - REAL_EXP (b) + 1; |
| if (exp > MAX_EXP) |
| { |
| get_inf (r, sign); |
| return true; |
| } |
| if (exp < -MAX_EXP) |
| { |
| get_zero (r, sign); |
| return true; |
| } |
| SET_REAL_EXP (rr, exp); |
| |
| inexact = div_significands (rr, a, b); |
| |
| /* Re-normalize the result. */ |
| normalize (rr); |
| rr->sig[0] |= inexact; |
| |
| if (rr != r) |
| *r = t; |
| |
| return inexact; |
| } |
| |
| /* Return a tri-state comparison of A vs B. Return NAN_RESULT if |
| one of the two operands is a NaN. */ |
| |
| static int |
| do_compare (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b, |
| int nan_result) |
| { |
| int ret; |
| |
| switch (CLASS2 (a->cl, b->cl)) |
| { |
| case CLASS2 (rvc_zero, rvc_zero): |
| /* Sign of zero doesn't matter for compares. */ |
| return 0; |
| |
| case CLASS2 (rvc_normal, rvc_zero): |
| /* Decimal float zero is special and uses rvc_normal, not rvc_zero. */ |
| if (a->decimal) |
| return decimal_do_compare (a, b, nan_result); |
| /* Fall through. */ |
| case CLASS2 (rvc_inf, rvc_zero): |
| case CLASS2 (rvc_inf, rvc_normal): |
| return (a->sign ? -1 : 1); |
| |
| case CLASS2 (rvc_inf, rvc_inf): |
| return -a->sign - -b->sign; |
| |
| case CLASS2 (rvc_zero, rvc_normal): |
| /* Decimal float zero is special and uses rvc_normal, not rvc_zero. */ |
| if (b->decimal) |
| return decimal_do_compare (a, b, nan_result); |
| /* Fall through. */ |
| case CLASS2 (rvc_zero, rvc_inf): |
| case CLASS2 (rvc_normal, rvc_inf): |
| return (b->sign ? 1 : -1); |
| |
| case CLASS2 (rvc_zero, rvc_nan): |
| case CLASS2 (rvc_normal, rvc_nan): |
| case CLASS2 (rvc_inf, rvc_nan): |
| case CLASS2 (rvc_nan, rvc_nan): |
| case CLASS2 (rvc_nan, rvc_zero): |
| case CLASS2 (rvc_nan, rvc_normal): |
| case CLASS2 (rvc_nan, rvc_inf): |
| return nan_result; |
| |
| case CLASS2 (rvc_normal, rvc_normal): |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| if (a->decimal || b->decimal) |
| return decimal_do_compare (a, b, nan_result); |
| |
| if (a->sign != b->sign) |
| return -a->sign - -b->sign; |
| |
| if (REAL_EXP (a) > REAL_EXP (b)) |
| ret = 1; |
| else if (REAL_EXP (a) < REAL_EXP (b)) |
| ret = -1; |
| else |
| ret = cmp_significands (a, b); |
| |
| return (a->sign ? -ret : ret); |
| } |
| |
| /* Return A truncated to an integral value toward zero. */ |
| |
| static void |
| do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a) |
| { |
| *r = *a; |
| |
| switch (r->cl) |
| { |
| case rvc_zero: |
| case rvc_inf: |
| case rvc_nan: |
| /* Make resulting NaN value to be qNaN. The caller has the |
| responsibility to avoid the operation if flag_signaling_nans |
| is on. */ |
| r->signalling = 0; |
| break; |
| |
| case rvc_normal: |
| if (r->decimal) |
| { |
| decimal_do_fix_trunc (r, a); |
| return; |
| } |
| if (REAL_EXP (r) <= 0) |
| get_zero (r, r->sign); |
| else if (REAL_EXP (r) < SIGNIFICAND_BITS) |
| clear_significand_below (r, SIGNIFICAND_BITS - REAL_EXP (r)); |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* Perform the binary or unary operation described by CODE. |
| For a unary operation, leave OP1 NULL. This function returns |
| true if the result may be inexact due to loss of precision. */ |
| |
| bool |
| real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0, |
| const REAL_VALUE_TYPE *op1) |
| { |
| enum tree_code code = (enum tree_code) icode; |
| |
| if (op0->decimal || (op1 && op1->decimal)) |
| return decimal_real_arithmetic (r, code, op0, op1); |
| |
| switch (code) |
| { |
| case PLUS_EXPR: |
| /* Clear any padding areas in *r if it isn't equal to one of the |
| operands so that we can later do bitwise comparisons later on. */ |
| if (r != op0 && r != op1) |
| memset (r, '\0', sizeof (*r)); |
| return do_add (r, op0, op1, 0); |
| |
| case MINUS_EXPR: |
| if (r != op0 && r != op1) |
| memset (r, '\0', sizeof (*r)); |
| return do_add (r, op0, op1, 1); |
| |
| case MULT_EXPR: |
| if (r != op0 && r != op1) |
| memset (r, '\0', sizeof (*r)); |
| return do_multiply (r, op0, op1); |
| |
| case RDIV_EXPR: |
| if (r != op0 && r != op1) |
| memset (r, '\0', sizeof (*r)); |
| return do_divide (r, op0, op1); |
| |
| case MIN_EXPR: |
| if (op1->cl == rvc_nan) |
| { |
| *r = *op1; |
| /* Make resulting NaN value to be qNaN. The caller has the |
| responsibility to avoid the operation if flag_signaling_nans |
| is on. */ |
| r->signalling = 0; |
| } |
| else if (do_compare (op0, op1, -1) < 0) |
| *r = *op0; |
| else |
| *r = *op1; |
| break; |
| |
| case MAX_EXPR: |
| if (op1->cl == rvc_nan) |
| { |
| *r = *op1; |
| /* Make resulting NaN value to be qNaN. The caller has the |
| responsibility to avoid the operation if flag_signaling_nans |
| is on. */ |
| r->signalling = 0; |
| } |
| else if (do_compare (op0, op1, 1) < 0) |
| *r = *op1; |
| else |
| *r = *op0; |
| break; |
| |
| case NEGATE_EXPR: |
| *r = *op0; |
| r->sign ^= 1; |
| break; |
| |
| case ABS_EXPR: |
| *r = *op0; |
| r->sign = 0; |
| break; |
| |
| case FIX_TRUNC_EXPR: |
| do_fix_trunc (r, op0); |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| return false; |
| } |
| |
| REAL_VALUE_TYPE |
| real_value_negate (const REAL_VALUE_TYPE *op0) |
| { |
| REAL_VALUE_TYPE r; |
| real_arithmetic (&r, NEGATE_EXPR, op0, NULL); |
| return r; |
| } |
| |
| REAL_VALUE_TYPE |
| real_value_abs (const REAL_VALUE_TYPE *op0) |
| { |
| REAL_VALUE_TYPE r; |
| real_arithmetic (&r, ABS_EXPR, op0, NULL); |
| return r; |
| } |
| |
| /* Return whether OP0 == OP1. */ |
| |
| bool |
| real_equal (const REAL_VALUE_TYPE *op0, const REAL_VALUE_TYPE *op1) |
| { |
| return do_compare (op0, op1, -1) == 0; |
| } |
| |
| /* Return whether OP0 < OP1. */ |
| |
| bool |
| real_less (const REAL_VALUE_TYPE *op0, const REAL_VALUE_TYPE *op1) |
| { |
| return do_compare (op0, op1, 1) < 0; |
| } |
| |
| bool |
| real_compare (int icode, const REAL_VALUE_TYPE *op0, |
| const REAL_VALUE_TYPE *op1) |
| { |
| enum tree_code code = (enum tree_code) icode; |
| |
| switch (code) |
| { |
| case LT_EXPR: |
| return real_less (op0, op1); |
| case LE_EXPR: |
| return do_compare (op0, op1, 1) <= 0; |
| case GT_EXPR: |
| return do_compare (op0, op1, -1) > 0; |
| case GE_EXPR: |
| return do_compare (op0, op1, -1) >= 0; |
| case EQ_EXPR: |
| return real_equal (op0, op1); |
| case NE_EXPR: |
| return do_compare (op0, op1, -1) != 0; |
| case UNORDERED_EXPR: |
| return op0->cl == rvc_nan || op1->cl == rvc_nan; |
| case ORDERED_EXPR: |
| return op0->cl != rvc_nan && op1->cl != rvc_nan; |
| case UNLT_EXPR: |
| return do_compare (op0, op1, -1) < 0; |
| case UNLE_EXPR: |
| return do_compare (op0, op1, -1) <= 0; |
| case UNGT_EXPR: |
| return do_compare (op0, op1, 1) > 0; |
| case UNGE_EXPR: |
| return do_compare (op0, op1, 1) >= 0; |
| case UNEQ_EXPR: |
| return do_compare (op0, op1, 0) == 0; |
| case LTGT_EXPR: |
| return do_compare (op0, op1, 0) != 0; |
| |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* Return floor log2(R). */ |
| |
| int |
| real_exponent (const REAL_VALUE_TYPE *r) |
| { |
| switch (r->cl) |
| { |
| case rvc_zero: |
| return 0; |
| case rvc_inf: |
| case rvc_nan: |
| return (unsigned int)-1 >> 1; |
| case rvc_normal: |
| return REAL_EXP (r); |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* R = OP0 * 2**EXP. */ |
| |
| void |
| real_ldexp (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0, int exp) |
| { |
| *r = *op0; |
| switch (r->cl) |
| { |
| case rvc_zero: |
| case rvc_inf: |
| case rvc_nan: |
| /* Make resulting NaN value to be qNaN. The caller has the |
| responsibility to avoid the operation if flag_signaling_nans |
| is on. */ |
| r->signalling = 0; |
| break; |
| |
| case rvc_normal: |
| exp += REAL_EXP (op0); |
| if (exp > MAX_EXP) |
| get_inf (r, r->sign); |
| else if (exp < -MAX_EXP) |
| get_zero (r, r->sign); |
| else |
| SET_REAL_EXP (r, exp); |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* Determine whether a floating-point value X is infinite. */ |
| |
| bool |
| real_isinf (const REAL_VALUE_TYPE *r) |
| { |
| return (r->cl == rvc_inf); |
| } |
| |
| /* Determine whether a floating-point value X is a NaN. */ |
| |
| bool |
| real_isnan (const REAL_VALUE_TYPE *r) |
| { |
| return (r->cl == rvc_nan); |
| } |
| |
| /* Determine whether a floating-point value X is a signaling NaN. */ |
| bool real_issignaling_nan (const REAL_VALUE_TYPE *r) |
| { |
| return real_isnan (r) && r->signalling; |
| } |
| |
| /* Determine whether a floating-point value X is finite. */ |
| |
| bool |
| real_isfinite (const REAL_VALUE_TYPE *r) |
| { |
| return (r->cl != rvc_nan) && (r->cl != rvc_inf); |
| } |
| |
| /* Determine whether a floating-point value X is negative. */ |
| |
| bool |
| real_isneg (const REAL_VALUE_TYPE *r) |
| { |
| return r->sign; |
| } |
| |
| /* Determine whether a floating-point value X is minus zero. */ |
| |
| bool |
| real_isnegzero (const REAL_VALUE_TYPE *r) |
| { |
| return r->sign && r->cl == rvc_zero; |
| } |
| |
| /* Compare two floating-point objects for bitwise identity. */ |
| |
| bool |
| real_identical (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b) |
| { |
| int i; |
| |
| if (a->cl != b->cl) |
| return false; |
| if (a->sign != b->sign) |
| return false; |
| |
| switch (a->cl) |
| { |
| case rvc_zero: |
| case rvc_inf: |
| return true; |
| |
| case rvc_normal: |
| if (a->decimal != b->decimal) |
| return false; |
| if (REAL_EXP (a) != REAL_EXP (b)) |
| return false; |
| break; |
| |
| case rvc_nan: |
| if (a->signalling != b->signalling) |
| return false; |
| /* The significand is ignored for canonical NaNs. */ |
| if (a->canonical || b->canonical) |
| return a->canonical == b->canonical; |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| for (i = 0; i < SIGSZ; ++i) |
| if (a->sig[i] != b->sig[i]) |
| return false; |
| |
| return true; |
| } |
| |
| /* Try to change R into its exact multiplicative inverse in format FMT. |
| Return true if successful. */ |
| |
| bool |
| exact_real_inverse (format_helper fmt, REAL_VALUE_TYPE *r) |
| { |
| const REAL_VALUE_TYPE *one = real_digit (1); |
| REAL_VALUE_TYPE u; |
| int i; |
| |
| if (r->cl != rvc_normal) |
| return false; |
| |
| /* Check for a power of two: all significand bits zero except the MSB. */ |
| for (i = 0; i < SIGSZ-1; ++i) |
| if (r->sig[i] != 0) |
| return false; |
| if (r->sig[SIGSZ-1] != SIG_MSB) |
| return false; |
| |
| /* Find the inverse and truncate to the required format. */ |
| do_divide (&u, one, r); |
| real_convert (&u, fmt, &u); |
| |
| /* The rounding may have overflowed. */ |
| if (u.cl != rvc_normal) |
| return false; |
| for (i = 0; i < SIGSZ-1; ++i) |
| if (u.sig[i] != 0) |
| return false; |
| if (u.sig[SIGSZ-1] != SIG_MSB) |
| return false; |
| |
| *r = u; |
| return true; |
| } |
| |
| /* Return true if arithmetic on values in IMODE that were promoted |
| from values in TMODE is equivalent to direct arithmetic on values |
| in TMODE. */ |
| |
| bool |
| real_can_shorten_arithmetic (machine_mode imode, machine_mode tmode) |
| { |
| const struct real_format *tfmt, *ifmt; |
| tfmt = REAL_MODE_FORMAT (tmode); |
| ifmt = REAL_MODE_FORMAT (imode); |
| /* These conditions are conservative rather than trying to catch the |
| exact boundary conditions; the main case to allow is IEEE float |
| and double. */ |
| return (ifmt->b == tfmt->b |
| && ifmt->p > 2 * tfmt->p |
| && ifmt->emin < 2 * tfmt->emin - tfmt->p - 2 |
| && ifmt->emin < tfmt->emin - tfmt->emax - tfmt->p - 2 |
| && ifmt->emax > 2 * tfmt->emax + 2 |
| && ifmt->emax > tfmt->emax - tfmt->emin + tfmt->p + 2 |
| && ifmt->round_towards_zero == tfmt->round_towards_zero |
| && (ifmt->has_sign_dependent_rounding |
| == tfmt->has_sign_dependent_rounding) |
| && ifmt->has_nans >= tfmt->has_nans |
| && ifmt->has_inf >= tfmt->has_inf |
| && ifmt->has_signed_zero >= tfmt->has_signed_zero |
| && !MODE_COMPOSITE_P (tmode) |
| && !MODE_COMPOSITE_P (imode)); |
| } |
| |
| /* Render R as an integer. */ |
| |
| HOST_WIDE_INT |
| real_to_integer (const REAL_VALUE_TYPE *r) |
| { |
| unsigned HOST_WIDE_INT i; |
| |
| switch (r->cl) |
| { |
| case rvc_zero: |
| underflow: |
| return 0; |
| |
| case rvc_inf: |
| case rvc_nan: |
| overflow: |
| i = HOST_WIDE_INT_1U << (HOST_BITS_PER_WIDE_INT - 1); |
| if (!r->sign) |
| i--; |
| return i; |
| |
| case rvc_normal: |
| if (r->decimal) |
| return decimal_real_to_integer (r); |
| |
| if (REAL_EXP (r) <= 0) |
| goto underflow; |
| /* Only force overflow for unsigned overflow. Signed overflow is |
| undefined, so it doesn't matter what we return, and some callers |
| expect to be able to use this routine for both signed and |
| unsigned conversions. */ |
| if (REAL_EXP (r) > HOST_BITS_PER_WIDE_INT) |
| goto overflow; |
| |
| if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG) |
| i = r->sig[SIGSZ-1]; |
| else |
| { |
| gcc_assert (HOST_BITS_PER_WIDE_INT == 2 * HOST_BITS_PER_LONG); |
| i = r->sig[SIGSZ-1]; |
| i = i << (HOST_BITS_PER_LONG - 1) << 1; |
| i |= r->sig[SIGSZ-2]; |
| } |
| |
| i >>= HOST_BITS_PER_WIDE_INT - REAL_EXP (r); |
| |
| if (r->sign) |
| i = -i; |
| return i; |
| |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* Likewise, but producing a wide-int of PRECISION. If the value cannot |
| be represented in precision, *FAIL is set to TRUE. */ |
| |
| wide_int |
| real_to_integer (const REAL_VALUE_TYPE *r, bool *fail, int precision) |
| { |
| HOST_WIDE_INT val[2 * WIDE_INT_MAX_ELTS]; |
| int exp; |
| int words, w; |
| wide_int result; |
| |
| switch (r->cl) |
| { |
| case rvc_zero: |
| underflow: |
| return wi::zero (precision); |
| |
| case rvc_inf: |
| case rvc_nan: |
| overflow: |
| *fail = true; |
| |
| if (r->sign) |
| return wi::set_bit_in_zero (precision - 1, precision); |
| else |
| return ~wi::set_bit_in_zero (precision - 1, precision); |
| |
| case rvc_normal: |
| if (r->decimal) |
| return decimal_real_to_integer (r, fail, precision); |
| |
| exp = REAL_EXP (r); |
| if (exp <= 0) |
| goto underflow; |
| /* Only force overflow for unsigned overflow. Signed overflow is |
| undefined, so it doesn't matter what we return, and some callers |
| expect to be able to use this routine for both signed and |
| unsigned conversions. */ |
| if (exp > precision) |
| goto overflow; |
| |
| /* Put the significand into a wide_int that has precision W, which |
| is the smallest HWI-multiple that has at least PRECISION bits. |
| This ensures that the top bit of the significand is in the |
| top bit of the wide_int. */ |
| words = (precision + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT; |
| w = words * HOST_BITS_PER_WIDE_INT; |
| |
| #if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG) |
| for (int i = 0; i < words; i++) |
| { |
| int j = SIGSZ - words + i; |
| val[i] = (j < 0) ? 0 : r->sig[j]; |
| } |
| #else |
| gcc_assert (HOST_BITS_PER_WIDE_INT == 2 * HOST_BITS_PER_LONG); |
| for (int i = 0; i < words; i++) |
| { |
| int j = SIGSZ - (words * 2) + (i * 2); |
| if (j < 0) |
| val[i] = 0; |
| else |
| val[i] = r->sig[j]; |
| j += 1; |
| if (j >= 0) |
| val[i] |= (unsigned HOST_WIDE_INT) r->sig[j] << HOST_BITS_PER_LONG; |
| } |
| #endif |
| /* Shift the value into place and truncate to the desired precision. */ |
| result = wide_int::from_array (val, words, w); |
| result = wi::lrshift (result, w - exp); |
| result = wide_int::from (result, precision, UNSIGNED); |
| |
| if (r->sign) |
| return -result; |
| else |
| return result; |
| |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* A subroutine of real_to_decimal. Compute the quotient and remainder |
| of NUM / DEN. Return the quotient and place the remainder in NUM. |
| It is expected that NUM / DEN are close enough that the quotient is |
| small. */ |
| |
| static unsigned long |
| rtd_divmod (REAL_VALUE_TYPE *num, REAL_VALUE_TYPE *den) |
| { |
| unsigned long q, msb; |
| int expn = REAL_EXP (num), expd = REAL_EXP (den); |
| |
| if (expn < expd) |
| return 0; |
| |
| q = msb = 0; |
| goto start; |
| do |
| { |
| msb = num->sig[SIGSZ-1] & SIG_MSB; |
| q <<= 1; |
| lshift_significand_1 (num, num); |
| start: |
| if (msb || cmp_significands (num, den) >= 0) |
| { |
| sub_significands (num, num, den, 0); |
| q |= 1; |
| } |
| } |
| while (--expn >= expd); |
| |
| SET_REAL_EXP (num, expd); |
| normalize (num); |
| |
| return q; |
| } |
| |
| /* Render R as a decimal floating point constant. Emit DIGITS significant |
| digits in the result, bounded by BUF_SIZE. If DIGITS is 0, choose the |
| maximum for the representation. If CROP_TRAILING_ZEROS, strip trailing |
| zeros. If MODE is VOIDmode, round to nearest value. Otherwise, round |
| to a string that, when parsed back in mode MODE, yields the same value. */ |
| |
| #define M_LOG10_2 0.30102999566398119521 |
| |
| void |
| real_to_decimal_for_mode (char *str, const REAL_VALUE_TYPE *r_orig, |
| size_t buf_size, size_t digits, |
| int crop_trailing_zeros, machine_mode mode) |
| { |
| const struct real_format *fmt = NULL; |
| const REAL_VALUE_TYPE *one, *ten; |
| REAL_VALUE_TYPE r, pten, u, v; |
| int dec_exp, cmp_one, digit; |
| size_t max_digits; |
| char *p, *first, *last; |
| bool sign; |
| bool round_up; |
| |
| if (mode != VOIDmode) |
| { |
| fmt = REAL_MODE_FORMAT (mode); |
| gcc_assert (fmt); |
| } |
| |
| r = *r_orig; |
| switch (r.cl) |
| { |
| case rvc_zero: |
| strcpy (str, (r.sign ? "-0.0" : "0.0")); |
| return; |
| case rvc_normal: |
| break; |
| case rvc_inf: |
| strcpy (str, (r.sign ? "-Inf" : "+Inf")); |
| return; |
| case rvc_nan: |
| /* ??? Print the significand as well, if not canonical? */ |
| sprintf (str, "%c%cNaN", (r_orig->sign ? '-' : '+'), |
| (r_orig->signalling ? 'S' : 'Q')); |
| return; |
| default: |
| gcc_unreachable (); |
| } |
| |
| if (r.decimal) |
| { |
| decimal_real_to_decimal (str, &r, buf_size, digits, crop_trailing_zeros); |
| return; |
| } |
| |
| /* Bound the number of digits printed by the size of the representation. */ |
| max_digits = SIGNIFICAND_BITS * M_LOG10_2; |
| if (digits == 0 || digits > max_digits) |
| digits = max_digits; |
| |
| /* Estimate the decimal exponent, and compute the length of the string it |
| will print as. Be conservative and add one to account for possible |
| overflow or rounding error. */ |
| dec_exp = REAL_EXP (&r) * M_LOG10_2; |
| for (max_digits = 1; dec_exp ; max_digits++) |
| dec_exp /= 10; |
| |
| /* Bound the number of digits printed by the size of the output buffer. */ |
| max_digits = buf_size - 1 - 1 - 2 - max_digits - 1; |
| gcc_assert (max_digits <= buf_size); |
| if (digits > max_digits) |
| digits = max_digits; |
| |
| one = real_digit (1); |
| ten = ten_to_ptwo (0); |
| |
| sign = r.sign; |
| r.sign = 0; |
| |
| dec_exp = 0; |
| pten = *one; |
| |
| cmp_one = do_compare (&r, one, 0); |
| if (cmp_one > 0) |
| { |
| int m; |
| |
| /* Number is greater than one. Convert significand to an integer |
| and strip trailing decimal zeros. */ |
| |
| u = r; |
| SET_REAL_EXP (&u, SIGNIFICAND_BITS - 1); |
| |
| /* Largest M, such that 10**2**M fits within SIGNIFICAND_BITS. */ |
| m = floor_log2 (max_digits); |
| |
| /* Iterate over the bits of the possible powers of 10 that might |
| be present in U and eliminate them. That is, if we find that |
| 10**2**M divides U evenly, keep the division and increase |
| DEC_EXP by 2**M. */ |
| do |
| { |
| REAL_VALUE_TYPE t; |
| |
| do_divide (&t, &u, ten_to_ptwo (m)); |
| do_fix_trunc (&v, &t); |
| if (cmp_significands (&v, &t) == 0) |
| { |
| u = t; |
| dec_exp += 1 << m; |
| } |
| } |
| while (--m >= 0); |
| |
| /* Revert the scaling to integer that we performed earlier. */ |
| SET_REAL_EXP (&u, REAL_EXP (&u) + REAL_EXP (&r) |
| - (SIGNIFICAND_BITS - 1)); |
| r = u; |
| |
| /* Find power of 10. Do this by dividing out 10**2**M when |
| this is larger than the current remainder. Fill PTEN with |
| the power of 10 that we compute. */ |
| if (REAL_EXP (&r) > 0) |
| { |
| m = floor_log2 ((int)(REAL_EXP (&r) * M_LOG10_2)) + 1; |
| do |
| { |
| const REAL_VALUE_TYPE *ptentwo = ten_to_ptwo (m); |
| if (do_compare (&u, ptentwo, 0) >= 0) |
| { |
| do_divide (&u, &u, ptentwo); |
| do_multiply (&pten, &pten, ptentwo); |
| dec_exp += 1 << m; |
| } |
| } |
| while (--m >= 0); |
| } |
| else |
| /* We managed to divide off enough tens in the above reduction |
| loop that we've now got a negative exponent. Fall into the |
| less-than-one code to compute the proper value for PTEN. */ |
| cmp_one = -1; |
| } |
| if (cmp_one < 0) |
| { |
| int m; |
| |
| /* Number is less than one. Pad significand with leading |
| decimal zeros. */ |
| |
| v = r; |
| while (1) |
| { |
| /* Stop if we'd shift bits off the bottom. */ |
| if (v.sig[0] & 7) |
| break; |
| |
| do_multiply (&u, &v, ten); |
| |
| /* Stop if we're now >= 1 or zero. */ |
| if (REAL_EXP (&u) > 0 || u.cl == rvc_zero) |
| break; |
| |
| v = u; |
| dec_exp -= 1; |
| } |
| r = v; |
| |
| /* Find power of 10. Do this by multiplying in P=10**2**M when |
| the current remainder is smaller than 1/P. Fill PTEN with the |
| power of 10 that we compute. */ |
| m = floor_log2 ((int)(-REAL_EXP (&r) * M_LOG10_2)) + 1; |
| do |
| { |
| const REAL_VALUE_TYPE *ptentwo = ten_to_ptwo (m); |
| const REAL_VALUE_TYPE *ptenmtwo = ten_to_mptwo (m); |
| |
| if (do_compare (&v, ptenmtwo, 0) <= 0) |
| { |
| do_multiply (&v, &v, ptentwo); |
| do_multiply (&pten, &pten, ptentwo); |
| dec_exp -= 1 << m; |
| } |
| } |
| while (--m >= 0); |
| |
| /* Invert the positive power of 10 that we've collected so far. */ |
| do_divide (&pten, one, &pten); |
| } |
| |
| p = str; |
| if (sign) |
| *p++ = '-'; |
| first = p++; |
| |
| /* At this point, PTEN should contain the nearest power of 10 smaller |
| than R, such that this division produces the first digit. |
| |
| Using a divide-step primitive that returns the complete integral |
| remainder avoids the rounding error that would be produced if |
| we were to use do_divide here and then simply multiply by 10 for |
| each subsequent digit. */ |
| |
| digit = rtd_divmod (&r, &pten); |
| |
| /* Be prepared for error in that division via underflow ... */ |
| if (digit == 0 && cmp_significand_0 (&r)) |
| { |
| /* Multiply by 10 and try again. */ |
| do_multiply (&r, &r, ten); |
| digit = rtd_divmod (&r, &pten); |
| dec_exp -= 1; |
| gcc_assert (digit != 0); |
| } |
| |
| /* ... or overflow. */ |
| if (digit == 10) |
| { |
| *p++ = '1'; |
| if (--digits > 0) |
| *p++ = '0'; |
| dec_exp += 1; |
| } |
| else |
| { |
| gcc_assert (digit <= 10); |
| *p++ = digit + '0'; |
| } |
| |
| /* Generate subsequent digits. */ |
| while (--digits > 0) |
| { |
| do_multiply (&r, &r, ten); |
| digit = rtd_divmod (&r, &pten); |
| *p++ = digit + '0'; |
| } |
| last = p; |
| |
| /* Generate one more digit with which to do rounding. */ |
| do_multiply (&r, &r, ten); |
| digit = rtd_divmod (&r, &pten); |
| |
| /* Round the result. */ |
| if (fmt && fmt->round_towards_zero) |
| { |
| /* If the format uses round towards zero when parsing the string |
| back in, we need to always round away from zero here. */ |
| if (cmp_significand_0 (&r)) |
| digit++; |
| round_up = digit > 0; |
| } |
| else |
| { |
| if (digit == 5) |
| { |
| /* Round to nearest. If R is nonzero there are additional |
| nonzero digits to be extracted. */ |
| if (cmp_significand_0 (&r)) |
| digit++; |
| /* Round to even. */ |
| else if ((p[-1] - '0') & 1) |
| digit++; |
| } |
| |
| round_up = digit > 5; |
| } |
| |
| if (round_up) |
| { |
| while (p > first) |
| { |
| digit = *--p; |
| if (digit == '9') |
| *p = '0'; |
| else |
| { |
| *p = digit + 1; |
| break; |
| } |
| } |
| |
| /* Carry out of the first digit. This means we had all 9's and |
| now have all 0's. "Prepend" a 1 by overwriting the first 0. */ |
| if (p == first) |
| { |
| first[1] = '1'; |
| dec_exp++; |
| } |
| } |
| |
| /* Insert the decimal point. */ |
| first[0] = first[1]; |
| first[1] = '.'; |
| |
| /* If requested, drop trailing zeros. Never crop past "1.0". */ |
| if (crop_trailing_zeros) |
| while (last > first + 3 && last[-1] == '0') |
| last--; |
| |
| /* Append the exponent. */ |
| sprintf (last, "e%+d", dec_exp); |
| |
| /* Verify that we can read the original value back in. */ |
| if (flag_checking && mode != VOIDmode) |
| { |
| real_from_string (&r, str); |
| real_convert (&r, mode, &r); |
| gcc_assert (real_identical (&r, r_orig)); |
| } |
| } |
| |
| /* Likewise, except always uses round-to-nearest. */ |
| |
| void |
| real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size, |
| size_t digits, int crop_trailing_zeros) |
| { |
| real_to_decimal_for_mode (str, r_orig, buf_size, |
| digits, crop_trailing_zeros, VOIDmode); |
| } |
| |
| /* Render R as a hexadecimal floating point constant. Emit DIGITS |
| significant digits in the result, bounded by BUF_SIZE. If DIGITS is 0, |
| choose the maximum for the representation. If CROP_TRAILING_ZEROS, |
| strip trailing zeros. */ |
| |
| void |
| real_to_hexadecimal (char *str, const REAL_VALUE_TYPE *r, size_t buf_size, |
| size_t digits, int crop_trailing_zeros) |
| { |
| int i, j, exp = REAL_EXP (r); |
| char *p, *first; |
| char exp_buf[16]; |
| size_t max_digits; |
| |
| switch (r->cl) |
| { |
| case rvc_zero: |
| exp = 0; |
| break; |
| case rvc_normal: |
| break; |
| case rvc_inf: |
| strcpy (str, (r->sign ? "-Inf" : "+Inf")); |
| return; |
| case rvc_nan: |
| /* ??? Print the significand as well, if not canonical? */ |
| sprintf (str, "%c%cNaN", (r->sign ? '-' : '+'), |
| (r->signalling ? 'S' : 'Q')); |
| return; |
| default: |
| gcc_unreachable (); |
| } |
| |
| if (r->decimal) |
| { |
| /* Hexadecimal format for decimal floats is not interesting. */ |
| strcpy (str, "N/A"); |
| return; |
| } |
| |
| if (digits == 0) |
| digits = SIGNIFICAND_BITS / 4; |
| |
| /* Bound the number of digits printed by the size of the output buffer. */ |
| |
| sprintf (exp_buf, "p%+d", exp); |
| max_digits = buf_size - strlen (exp_buf) - r->sign - 4 - 1; |
| gcc_assert (max_digits <= buf_size); |
| if (digits > max_digits) |
| digits = max_digits; |
| |
| p = str; |
| if (r->sign) |
| *p++ = '-'; |
| *p++ = '0'; |
| *p++ = 'x'; |
| *p++ = '0'; |
| *p++ = '.'; |
| first = p; |
| |
| for (i = SIGSZ - 1; i >= 0; --i) |
| for (j = HOST_BITS_PER_LONG - 4; j >= 0; j -= 4) |
| { |
| *p++ = "0123456789abcdef"[(r->sig[i] >> j) & 15]; |
| if (--digits == 0) |
| goto out; |
| } |
| |
| out: |
| if (crop_trailing_zeros) |
| while (p > first + 1 && p[-1] == '0') |
| p--; |
| |
| sprintf (p, "p%+d", exp); |
| } |
| |
| /* Initialize R from a decimal or hexadecimal string. The string is |
| assumed to have been syntax checked already. Return -1 if the |
| value underflows, +1 if overflows, and 0 otherwise. */ |
| |
| int |
| real_from_string (REAL_VALUE_TYPE *r, const char *str) |
| { |
| int exp = 0; |
| bool sign = false; |
| |
| get_zero (r, 0); |
| |
| if (*str == '-') |
| { |
| sign = true; |
| str++; |
| } |
| else if (*str == '+') |
| str++; |
| |
| if (!strncmp (str, "QNaN", 4)) |
| { |
| get_canonical_qnan (r, sign); |
| return 0; |
| } |
| else if (!strncmp (str, "SNaN", 4)) |
| { |
| get_canonical_snan (r, sign); |
| return 0; |
| } |
| else if (!strncmp (str, "Inf", 3)) |
| { |
| get_inf (r, sign); |
| return 0; |
| } |
| |
| if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) |
| { |
| /* Hexadecimal floating point. */ |
| int pos = SIGNIFICAND_BITS - 4, d; |
| |
| str += 2; |
| |
| while (*str == '0') |
| str++; |
| while (1) |
| { |
| d = hex_value (*str); |
| if (d == _hex_bad) |
| break; |
| if (pos >= 0) |
| { |
| r->sig[pos / HOST_BITS_PER_LONG] |
| |= (unsigned long) d << (pos % HOST_BITS_PER_LONG); |
| pos -= 4; |
| } |
| else if (d) |
| /* Ensure correct rounding by setting last bit if there is |
| a subsequent nonzero digit. */ |
| r->sig[0] |= 1; |
| exp += 4; |
| str++; |
| } |
| if (*str == '.') |
| { |
| str++; |
| if (pos == SIGNIFICAND_BITS - 4) |
| { |
| while (*str == '0') |
| str++, exp -= 4; |
| } |
| while (1) |
| { |
| d = hex_value (*str); |
| if (d == _hex_bad) |
| break; |
| if (pos >= 0) |
| { |
| r->sig[pos / HOST_BITS_PER_LONG] |
| |= (unsigned long) d << (pos % HOST_BITS_PER_LONG); |
| pos -= 4; |
| } |
| else if (d) |
| /* Ensure correct rounding by setting last bit if there is |
| a subsequent nonzero digit. */ |
| r->sig[0] |= 1; |
| str++; |
| } |
| } |
| |
| /* If the mantissa is zero, ignore the exponent. */ |
| if (!cmp_significand_0 (r)) |
| goto is_a_zero; |
| |
| if (*str == 'p' || *str == 'P') |
| { |
| bool exp_neg = false; |
| |
| str++; |
| if (*str == '-') |
| { |
| exp_neg = true; |
| str++; |
| } |
| else if (*str == '+') |
| str++; |
| |
| d = 0; |
| while (ISDIGIT (*str)) |
| { |
| d *= 10; |
| d += *str - '0'; |
| if (d > MAX_EXP) |
| { |
| /* Overflowed the exponent. */ |
| if (exp_neg) |
| goto underflow; |
| else |
| goto overflow; |
| } |
| str++; |
| } |
| if (exp_neg) |
| d = -d; |
| |
| exp += d; |
| } |
| |
| r->cl = rvc_normal; |
| SET_REAL_EXP (r, exp); |
| |
| normalize (r); |
| } |
| else |
| { |
| /* Decimal floating point. */ |
| const char *cstr = str; |
| mpfr_t m; |
| bool inexact; |
| |
| while (*cstr == '0') |
| cstr++; |
| if (*cstr == '.') |
| { |
| cstr++; |
| while (*cstr == '0') |
| cstr++; |
| } |
| |
| /* If the mantissa is zero, ignore the exponent. */ |
| if (!ISDIGIT (*cstr)) |
| goto is_a_zero; |
| |
| /* Nonzero value, possibly overflowing or underflowing. */ |
| mpfr_init2 (m, SIGNIFICAND_BITS); |
| inexact = mpfr_strtofr (m, str, NULL, 10, MPFR_RNDZ); |
| /* The result should never be a NaN, and because the rounding is |
| toward zero should never be an infinity. */ |
| gcc_assert (!mpfr_nan_p (m) && !mpfr_inf_p (m)); |
| if (mpfr_zero_p (m) || mpfr_get_exp (m) < -MAX_EXP + 4) |
| { |
| mpfr_clear (m); |
| goto underflow; |
| } |
| else if (mpfr_get_exp (m) > MAX_EXP - 4) |
| { |
| mpfr_clear (m); |
| goto overflow; |
| } |
| else |
| { |
| real_from_mpfr (r, m, NULL_TREE, MPFR_RNDZ); |
| /* 1 to 3 bits may have been shifted off (with a sticky bit) |
| because the hex digits used in real_from_mpfr did not |
| start with a digit 8 to f, but the exponent bounds above |
| should have avoided underflow or overflow. */ |
| gcc_assert (r->cl == rvc_normal); |
| /* Set a sticky bit if mpfr_strtofr was inexact. */ |
| r->sig[0] |= inexact; |
| mpfr_clear (m); |
| } |
| } |
| |
| r->sign = sign; |
| return 0; |
| |
| is_a_zero: |
| get_zero (r, sign); |
| return 0; |
| |
| underflow: |
| get_zero (r, sign); |
| return -1; |
| |
| overflow: |
| get_inf (r, sign); |
| return 1; |
| } |
| |
| /* Legacy. Similar, but return the result directly. */ |
| |
| REAL_VALUE_TYPE |
| real_from_string2 (const char *s, format_helper fmt) |
| { |
| REAL_VALUE_TYPE r; |
| |
| real_from_string (&r, s); |
| if (fmt) |
| real_convert (&r, fmt, &r); |
| |
| return r; |
| } |
| |
| /* Initialize R from string S and desired format FMT. */ |
| |
| void |
| real_from_string3 (REAL_VALUE_TYPE *r, const char *s, format_helper fmt) |
| { |
| if (fmt.decimal_p ()) |
| decimal_real_from_string (r, s); |
| else |
| real_from_string (r, s); |
| |
| if (fmt) |
| real_convert (r, fmt, r); |
| } |
| |
| /* Initialize R from the wide_int VAL_IN. Round it to format FMT if |
| FMT is nonnull. */ |
| |
| void |
| real_from_integer (REAL_VALUE_TYPE *r, format_helper fmt, |
| const wide_int_ref &val_in, signop sgn) |
| { |
| if (val_in == 0) |
| get_zero (r, 0); |
| else |
| { |
| unsigned int len = val_in.get_precision (); |
| int i, j, e = 0; |
| int maxbitlen = MAX_BITSIZE_MODE_ANY_INT + HOST_BITS_PER_WIDE_INT; |
| const unsigned int realmax = (SIGNIFICAND_BITS / HOST_BITS_PER_WIDE_INT |
| * HOST_BITS_PER_WIDE_INT); |
| |
| memset (r, 0, sizeof (*r)); |
| r->cl = rvc_normal; |
| r->sign = wi::neg_p (val_in, sgn); |
| |
| /* We have to ensure we can negate the largest negative number. */ |
| wide_int val = wide_int::from (val_in, maxbitlen, sgn); |
| |
| if (r->sign) |
| val = -val; |
| |
| /* Ensure a multiple of HOST_BITS_PER_WIDE_INT, ceiling, as elt |
| won't work with precisions that are not a multiple of |
| HOST_BITS_PER_WIDE_INT. */ |
| len += HOST_BITS_PER_WIDE_INT - 1; |
| |
| /* Ensure we can represent the largest negative number. */ |
| len += 1; |
| |
| len = len/HOST_BITS_PER_WIDE_INT * HOST_BITS_PER_WIDE_INT; |
| |
| /* Cap the size to the size allowed by real.h. */ |
| if (len > realmax) |
| { |
| HOST_WIDE_INT cnt_l_z; |
| cnt_l_z = wi::clz (val); |
| |
| if (maxbitlen - cnt_l_z > realmax) |
| { |
| e = maxbitlen - cnt_l_z - realmax; |
| |
| /* This value is too large, we must shift it right to |
| preserve all the bits we can, and then bump the |
| exponent up by that amount. */ |
| val = wi::lrshift (val, e); |
| } |
| len = realmax; |
| } |
| |
| /* Clear out top bits so elt will work with precisions that aren't |
| a multiple of HOST_BITS_PER_WIDE_INT. */ |
| val = wide_int::from (val, len, sgn); |
| len = len / HOST_BITS_PER_WIDE_INT; |
| |
| SET_REAL_EXP (r, len * HOST_BITS_PER_WIDE_INT + e); |
| |
| j = SIGSZ - 1; |
| if (HOST_BITS_PER_LONG == HOST_BITS_PER_WIDE_INT) |
| for (i = len - 1; i >= 0; i--) |
| { |
| r->sig[j--] = val.elt (i); |
| if (j < 0) |
| break; |
| } |
| else |
| { |
| gcc_assert (HOST_BITS_PER_LONG*2 == HOST_BITS_PER_WIDE_INT); |
| for (i = len - 1; i >= 0; i--) |
| { |
| HOST_WIDE_INT e = val.elt (i); |
| r->sig[j--] = e >> (HOST_BITS_PER_LONG - 1) >> 1; |
| if (j < 0) |
| break; |
| r->sig[j--] = e; |
| if (j < 0) |
| break; |
| } |
| } |
| |
| normalize (r); |
| } |
| |
| if (fmt.decimal_p ()) |
| decimal_from_integer (r); |
| if (fmt) |
| real_convert (r, fmt, r); |
| } |
| |
| /* Render R, an integral value, as a floating point constant with no |
| specified exponent. */ |
| |
| static void |
| decimal_integer_string (char *str, const REAL_VALUE_TYPE *r_orig, |
| size_t buf_size) |
| { |
| int dec_exp, digit, digits; |
| REAL_VALUE_TYPE r, pten; |
| char *p; |
| bool sign; |
| |
| r = *r_orig; |
| |
| if (r.cl == rvc_zero) |
| { |
| strcpy (str, "0."); |
| return; |
| } |
| |
| sign = r.sign; |
| r.sign = 0; |
| |
| dec_exp = REAL_EXP (&r) * M_LOG10_2; |
| digits = dec_exp + 1; |
| gcc_assert ((digits + 2) < (int)buf_size); |
| |
| pten = *real_digit (1); |
| times_pten (&pten, dec_exp); |
| |
| p = str; |
| if (sign) |
| *p++ = '-'; |
| |
| digit = rtd_divmod (&r, &pten); |
| gcc_assert (digit >= 0 && digit <= 9); |
| *p++ = digit + '0'; |
| while (--digits > 0) |
| { |
| times_pten (&r, 1); |
| digit = rtd_divmod (&r, &pten); |
| *p++ = digit + '0'; |
| } |
| *p++ = '.'; |
| *p++ = '\0'; |
| } |
| |
| /* Convert a real with an integral value to decimal float. */ |
| |
| static void |
| decimal_from_integer (REAL_VALUE_TYPE *r) |
| { |
| char str[256]; |
| |
| decimal_integer_string (str, r, sizeof (str) - 1); |
| decimal_real_from_string (r, str); |
| } |
| |
| /* Returns 10**2**N. */ |
| |
| static const REAL_VALUE_TYPE * |
| ten_to_ptwo (int n) |
| { |
| static REAL_VALUE_TYPE tens[EXP_BITS]; |
| |
| gcc_assert (n >= 0); |
| gcc_assert (n < EXP_BITS); |
| |
| if (tens[n].cl == rvc_zero) |
| { |
| if (n < (HOST_BITS_PER_WIDE_INT == 64 ? 5 : 4)) |
| { |
| HOST_WIDE_INT t = 10; |
| int i; |
| |
| for (i = 0; i < n; ++i) |
| t *= t; |
| |
| real_from_integer (&tens[n], VOIDmode, t, UNSIGNED); |
| } |
| else |
| { |
| const REAL_VALUE_TYPE *t = ten_to_ptwo (n - 1); |
| do_multiply (&tens[n], t, t); |
| } |
| } |
| |
| return &tens[n]; |
| } |
| |
| /* Returns 10**(-2**N). */ |
| |
| static const REAL_VALUE_TYPE * |
| ten_to_mptwo (int n) |
| { |
| static REAL_VALUE_TYPE tens[EXP_BITS]; |
| |
| gcc_assert (n >= 0); |
| gcc_assert (n < EXP_BITS); |
| |
| if (tens[n].cl == rvc_zero) |
| do_divide (&tens[n], real_digit (1), ten_to_ptwo (n)); |
| |
| return &tens[n]; |
| } |
| |
| /* Returns N. */ |
| |
| static const REAL_VALUE_TYPE * |
| real_digit (int n) |
| { |
| static REAL_VALUE_TYPE num[10]; |
| |
| gcc_assert (n >= 0); |
| gcc_assert (n <= 9); |
| |
| if (n > 0 && num[n].cl == rvc_zero) |
| real_from_integer (&num[n], VOIDmode, n, UNSIGNED); |
| |
| return &num[n]; |
| } |
| |
| /* Multiply R by 10**EXP. */ |
| |
| static void |
| times_pten (REAL_VALUE_TYPE *r, int exp) |
| { |
| REAL_VALUE_TYPE pten, *rr; |
| bool negative = (exp < 0); |
| int i; |
| |
| if (negative) |
| { |
| exp = -exp; |
| pten = *real_digit (1); |
| rr = &pten; |
| } |
| else |
| rr = r; |
| |
| for (i = 0; exp > 0; ++i, exp >>= 1) |
| if (exp & 1) |
| do_multiply (rr, rr, ten_to_ptwo (i)); |
| |
| if (negative) |
| do_divide (r, r, &pten); |
| } |
| |
| /* Returns the special REAL_VALUE_TYPE corresponding to 'e'. */ |
| |
| const REAL_VALUE_TYPE * |
| dconst_e_ptr (void) |
| { |
| static REAL_VALUE_TYPE value; |
| |
| /* Initialize mathematical constants for constant folding builtins. |
| These constants need to be given to at least 160 bits precision. */ |
| if (value.cl == rvc_zero) |
| { |
| mpfr_t m; |
| mpfr_init2 (m, SIGNIFICAND_BITS); |
| mpfr_set_ui (m, 1, MPFR_RNDN); |
| mpfr_exp (m, m, MPFR_RNDN); |
| real_from_mpfr (&value, m, NULL_TREE, MPFR_RNDN); |
| mpfr_clear (m); |
| |
| } |
| return &value; |
| } |
| |
| /* Returns a cached REAL_VALUE_TYPE corresponding to 1/n, for various n. */ |
| |
| #define CACHED_FRACTION(NAME, N) \ |
| const REAL_VALUE_TYPE * \ |
| NAME (void) \ |
| { \ |
| static REAL_VALUE_TYPE value; \ |
| \ |
| /* Initialize mathematical constants for constant folding builtins. \ |
| These constants need to be given to at least 160 bits \ |
| precision. */ \ |
| if (value.cl == rvc_zero) \ |
| real_arithmetic (&value, RDIV_EXPR, &dconst1, real_digit (N)); \ |
| return &value; \ |
| } |
| |
| CACHED_FRACTION (dconst_third_ptr, 3) |
| CACHED_FRACTION (dconst_quarter_ptr, 4) |
| CACHED_FRACTION (dconst_sixth_ptr, 6) |
| CACHED_FRACTION (dconst_ninth_ptr, 9) |
| |
| /* Returns the special REAL_VALUE_TYPE corresponding to sqrt(2). */ |
| |
| const REAL_VALUE_TYPE * |
| dconst_sqrt2_ptr (void) |
| { |
| static REAL_VALUE_TYPE value; |
| |
| /* Initialize mathematical constants for constant folding builtins. |
| These constants need to be given to at least 160 bits precision. */ |
| if (value.cl == rvc_zero) |
| { |
| mpfr_t m; |
| mpfr_init2 (m, SIGNIFICAND_BITS); |
| mpfr_sqrt_ui (m, 2, MPFR_RNDN); |
| real_from_mpfr (&value, m, NULL_TREE, MPFR_RNDN); |
| mpfr_clear (m); |
| } |
| return &value; |
| } |
| |
| /* Fills R with +Inf. */ |
| |
| void |
| real_inf (REAL_VALUE_TYPE *r) |
| { |
| get_inf (r, 0); |
| } |
| |
| /* Fills R with a NaN whose significand is described by STR. If QUIET, |
| we force a QNaN, else we force an SNaN. The string, if not empty, |
| is parsed as a number and placed in the significand. Return true |
| if the string was successfully parsed. */ |
| |
| bool |
| real_nan (REAL_VALUE_TYPE *r, const char *str, int quiet, |
| format_helper fmt) |
| { |
| if (*str == 0) |
| { |
| if (quiet) |
| get_canonical_qnan (r, 0); |
| else |
| get_canonical_snan (r, 0); |
| } |
| else |
| { |
| int base = 10, d; |
| |
| memset (r, 0, sizeof (*r)); |
| r->cl = rvc_nan; |
| |
| /* Parse akin to strtol into the significand of R. */ |
| |
| while (ISSPACE (*str)) |
| str++; |
| if (*str == '-') |
| str++; |
| else if (*str == '+') |
| str++; |
| if (*str == '0') |
| { |
| str++; |
| if (*str == 'x' || *str == 'X') |
| { |
| base = 16; |
| str++; |
| } |
| else |
| base = 8; |
| } |
| |
| while ((d = hex_value (*str)) < base) |
| { |
| REAL_VALUE_TYPE u; |
| |
| switch (base) |
| { |
| case 8: |
| lshift_significand (r, r, 3); |
| break; |
| case 16: |
| lshift_significand (r, r, 4); |
| break; |
| case 10: |
| lshift_significand_1 (&u, r); |
| lshift_significand (r, r, 3); |
| add_significands (r, r, &u); |
| break; |
| default: |
| gcc_unreachable (); |
| } |
| |
| get_zero (&u, 0); |
| u.sig[0] = d; |
| add_significands (r, r, &u); |
| |
| str++; |
| } |
| |
| /* Must have consumed the entire string for success. */ |
| if (*str != 0) |
| return false; |
| |
| /* Shift the significand into place such that the bits |
| are in the most significant bits for the format. */ |
| lshift_significand (r, r, SIGNIFICAND_BITS - fmt->pnan); |
| |
| /* Our MSB is always unset for NaNs. */ |
| r->sig[SIGSZ-1] &= ~SIG_MSB; |
| |
| /* Force quiet or signaling NaN. */ |
| r->signalling = !quiet; |
| } |
| |
| return true; |
| } |
| |
| /* Fills R with the largest finite value representable in mode MODE. |
| If SIGN is nonzero, R is set to the most negative finite value. */ |
| |
| void |
| real_maxval (REAL_VALUE_TYPE *r, int sign, machine_mode mode) |
| { |
| const struct real_format *fmt; |
| int np2; |
| |
| fmt = REAL_MODE_FORMAT (mode); |
| gcc_assert (fmt); |
| memset (r, 0, sizeof (*r)); |
| |
| if (fmt->b == 10) |
| decimal_real_maxval (r, sign, mode); |
| else |
| { |
| r->cl = rvc_normal; |
| r->sign = sign; |
| SET_REAL_EXP (r, fmt->emax); |
| |
| np2 = SIGNIFICAND_BITS - fmt->p; |
| memset (r->sig, -1, SIGSZ * sizeof (unsigned long)); |
| clear_significand_below (r, np2); |
| |
| if (fmt->pnan < fmt->p) |
| /* This is an IBM extended double format made up of two IEEE |
| doubles. The value of the long double is the sum of the |
| values of the two parts. The most significant part is |
| required to be the value of the long double rounded to the |
| nearest double. Rounding means we need a slightly smaller |
| value for LDBL_MAX. */ |
| clear_significand_bit (r, SIGNIFICAND_BITS - fmt->pnan - 1); |
| } |
| } |
| |
| /* Fills R with 2**N. */ |
| |
| void |
| real_2expN (REAL_VALUE_TYPE *r, int n, format_helper fmt) |
| { |
| memset (r, 0, sizeof (*r)); |
| |
| n++; |
| if (n > MAX_EXP) |
| r->cl = rvc_inf; |
| else if (n < -MAX_EXP) |
| ; |
| else |
| { |
| r->cl = rvc_normal; |
| SET_REAL_EXP (r, n); |
| r->sig[SIGSZ-1] = SIG_MSB; |
| } |
| if (fmt.decimal_p ()) |
| decimal_real_convert (r, fmt, r); |
| } |
| |
| |
| static void |
| round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r) |
| { |
| int p2, np2, i, w; |
| int emin2m1, emax2; |
| bool round_up = false; |
| |
| if (r->decimal) |
| { |
| if (fmt->b == 10) |
| { |
| decimal_round_for_format (fmt, r); |
| return; |
| } |
| /* FIXME. We can come here via fp_easy_constant |
| (e.g. -O0 on '_Decimal32 x = 1.0 + 2.0dd'), but have not |
| investigated whether this convert needs to be here, or |
| something else is missing. */ |
| decimal_real_convert (r, REAL_MODE_FORMAT (DFmode), r); |
| } |
| |
| p2 = fmt->p; |
| emin2m1 = fmt->emin - 1; |
| emax2 = fmt->emax; |
| |
| np2 = SIGNIFICAND_BITS - p2; |
| switch (r->cl) |
| { |
| underflow: |
| get_zero (r, r->sign); |
| /* FALLTHRU */ |
| case rvc_zero: |
| if (!fmt->has_signed_zero) |
| r->sign = 0; |
| return; |
| |
| overflow: |
| get_inf (r, r->sign); |
| case rvc_inf: |
| return; |
| |
| case rvc_nan: |
| clear_significand_below (r, np2); |
| return; |
| |
| case rvc_normal: |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| /* Check the range of the exponent. If we're out of range, |
| either underflow or overflow. */ |
| if (REAL_EXP (r) > emax2) |
| goto overflow; |
| else if (REAL_EXP (r) <= emin2m1) |
| { |
| int diff; |
| |
| if (!fmt->has_denorm) |
| { |
| /* Don't underflow completely until we've had a chance to round. */ |
| if (REAL_EXP (r) < emin2m1) |
| goto underflow; |
| } |
| else |
| { |
| diff = emin2m1 - REAL_EXP (r) + 1; |
| if (diff > p2) |
| goto underflow; |
| |
| /* De-normalize the significand. */ |
| r->sig[0] |= sticky_rshift_significand (r, r, diff); |
| SET_REAL_EXP (r, REAL_EXP (r) + diff); |
| } |
| } |
| |
| if (!fmt->round_towards_zero) |
| { |
| /* There are P2 true significand bits, followed by one guard bit, |
| followed by one sticky bit, followed by stuff. Fold nonzero |
| stuff into the sticky bit. */ |
| unsigned long sticky; |
| bool guard, lsb; |
| |
| sticky = 0; |
| for (i = 0, w = (np2 - 1) / HOST_BITS_PER_LONG; i < w; ++i) |
| sticky |= r->sig[i]; |
| sticky |= r->sig[w] |
| & (((unsigned long)1 << ((np2 - 1) % HOST_BITS_PER_LONG)) - 1); |
| |
| guard = test_significand_bit (r, np2 - 1); |
| lsb = test_significand_bit (r, np2); |
| |
| /* Round to even. */ |
| round_up = guard && (sticky || lsb); |
| } |
| |
| if (round_up) |
| { |
| REAL_VALUE_TYPE u; |
| get_zero (&u, 0); |
| set_significand_bit (&u, np2); |
| |
| if (add_significands (r, r, &u)) |
| { |
| /* Overflow. Means the significand had been all ones, and |
| is now all zeros. Need to increase the exponent, and |
| possibly re-normalize it. */ |
| SET_REAL_EXP (r, REAL_EXP (r) + 1); |
| if (REAL_EXP (r) > emax2) |
| goto overflow; |
| r->sig[SIGSZ-1] = SIG_MSB; |
| } |
| } |
| |
| /* Catch underflow that we deferred until after rounding. */ |
| if (REAL_EXP (r) <= emin2m1) |
| goto underflow; |
| |
| /* Clear out trailing garbage. */ |
| clear_significand_below (r, np2); |
| } |
| |
| /* Extend or truncate to a new format. */ |
| |
| void |
| real_convert (REAL_VALUE_TYPE *r, format_helper fmt, |
| const REAL_VALUE_TYPE *a) |
| { |
| *r = *a; |
| |
| if (a->decimal || fmt->b == 10) |
| decimal_real_convert (r, fmt, a); |
| |
| round_for_format (fmt, r); |
| |
| /* Make resulting NaN value to be qNaN. The caller has the |
| responsibility to avoid the operation if flag_signaling_nans |
| is on. */ |
| if (r->cl == rvc_nan) |
| r->signalling = 0; |
| |
| /* round_for_format de-normalizes denormals. Undo just that part. */ |
| if (r->cl == rvc_normal) |
| normalize (r); |
| } |
| |
| /* Legacy. Likewise, except return the struct directly. */ |
| |
| REAL_VALUE_TYPE |
| real_value_truncate (format_helper fmt, REAL_VALUE_TYPE a) |
| { |
| REAL_VALUE_TYPE r; |
| real_convert (&r, fmt, &a); |
| return r; |
| } |
| |
| /* Return true if truncating to FMT is exact. */ |
| |
| bool |
| exact_real_truncate (format_helper fmt, const REAL_VALUE_TYPE *a) |
| { |
| REAL_VALUE_TYPE t; |
| int emin2m1; |
| |
| /* Don't allow conversion to denormals. */ |
| emin2m1 = fmt->emin - 1; |
| if (REAL_EXP (a) <= emin2m1) |
| return false; |
| |
| /* After conversion to the new format, the value must be identical. */ |
| real_convert (&t, fmt, a); |
| return real_identical (&t, a); |
| } |
| |
| /* Write R to the given target format. Place the words of the result |
| in target word order in BUF. There are always 32 bits in each |
| long, no matter the size of the host long. |
| |
| Legacy: return word 0 for implementing REAL_VALUE_TO_TARGET_SINGLE. */ |
| |
| long |
| real_to_target (long *buf, const REAL_VALUE_TYPE *r_orig, |
| format_helper fmt) |
| { |
| REAL_VALUE_TYPE r; |
| long buf1; |
| |
| r = *r_orig; |
| round_for_format (fmt, &r); |
| |
| if (!buf) |
| buf = &buf1; |
| (*fmt->encode) (fmt, buf, &r); |
| |
| return *buf; |
| } |
| |
| /* Read R from the given target format. Read the words of the result |
| in target word order in BUF. There are always 32 bits in each |
| long, no matter the size of the host long. */ |
| |
| void |
| real_from_target (REAL_VALUE_TYPE *r, const long *buf, format_helper fmt) |
| { |
| (*fmt->decode) (fmt, r, buf); |
| } |
| |
| /* Return the number of bits of the largest binary value that the |
| significand of FMT will hold. */ |
| /* ??? Legacy. Should get access to real_format directly. */ |
| |
| int |
| significand_size (format_helper fmt) |
| { |
| if (fmt == NULL) |
| return 0; |
| |
| if (fmt->b == 10) |
| { |
| /* Return the size in bits of the largest binary value that can be |
| held by the decimal coefficient for this format. This is one more |
| than the number of bits required to hold the largest coefficient |
| of this format. */ |
| double log2_10 = 3.3219281; |
| return fmt->p * log2_10; |
| } |
| return fmt->p; |
| } |
| |
| /* Return a hash value for the given real value. */ |
| /* ??? The "unsigned int" return value is intended to be hashval_t, |
| but I didn't want to pull hashtab.h into real.h. */ |
| |
| unsigned int |
| real_hash (const REAL_VALUE_TYPE *r) |
| { |
| unsigned int h; |
| size_t i; |
| |
| h = r->cl | (r->sign << 2); |
| switch (r->cl) |
| { |
| case rvc_zero: |
| case rvc_inf: |
| return h; |
| |
| case rvc_normal: |
| h |= (unsigned int)REAL_EXP (r) << 3; |
| break; |
| |
| case rvc_nan: |
| if (r->signalling) |
| h ^= (unsigned int)-1; |
| if (r->canonical) |
| return h; |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| if (sizeof (unsigned long) > sizeof (unsigned int)) |
| for (i = 0; i < SIGSZ; ++i) |
| { |
| unsigned long s = r->sig[i]; |
| h ^= s ^ (s >> (HOST_BITS_PER_LONG / 2)); |
| } |
| else |
| for (i = 0; i < SIGSZ; ++i) |
| h ^= r->sig[i]; |
| |
| return h; |
| } |
| |
| /* IEEE single-precision format. */ |
| |
| static void encode_ieee_single (const struct real_format *fmt, |
| long *, const REAL_VALUE_TYPE *); |
| static void decode_ieee_single (const struct real_format *, |
| REAL_VALUE_TYPE *, const long *); |
| |
| static void |
| encode_ieee_single (const struct real_format *fmt, long *buf, |
| const REAL_VALUE_TYPE *r) |
| { |
| unsigned long image, sig, exp; |
| unsigned long sign = r->sign; |
| bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0; |
| |
| image = sign << 31; |
| sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff; |
| |
| switch (r->cl) |
| { |
| case rvc_zero: |
| break; |
| |
| case rvc_inf: |
| if (fmt->has_inf) |
| image |= 255 << 23; |
| else |
| image |= 0x7fffffff; |
| break; |
| |
| case rvc_nan: |
| if (fmt->has_nans) |
| { |
| if (r->canonical) |
| sig = (fmt->canonical_nan_lsbs_set ? (1 << 22) - 1 : 0); |
| if (r->signalling == fmt->qnan_msb_set) |
| sig &= ~(1 << 22); |
| else |
| sig |= 1 << 22; |
| if (sig == 0) |
| sig = 1 << 21; |
| |
| image |= 255 << 23; |
| image |= sig; |
| } |
| else |
| image |= 0x7fffffff; |
| break; |
| |
| case rvc_normal: |
| /* Recall that IEEE numbers are interpreted as 1.F x 2**exp, |
| whereas the intermediate representation is 0.F x 2**exp. |
| Which means we're off by one. */ |
| if (denormal) |
| exp = 0; |
| else |
| exp = REAL_EXP (r) + 127 - 1; |
| image |= exp << 23; |
| image |= sig; |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| buf[0] = image; |
| } |
| |
| static void |
| decode_ieee_single (const struct real_format *fmt, REAL_VALUE_TYPE *r, |
| const long *buf) |
| { |
| unsigned long image = buf[0] & 0xffffffff; |
| bool sign = (image >> 31) & 1; |
| int exp = (image >> 23) & 0xff; |
| |
| memset (r, 0, sizeof (*r)); |
| image <<= HOST_BITS_PER_LONG - 24; |
| image &= ~SIG_MSB; |
| |
| if (exp == 0) |
| { |
| if (image && fmt->has_denorm) |
| { |
| r->cl = rvc_normal; |
| r->sign = sign; |
| SET_REAL_EXP (r, -126); |
| r->sig[SIGSZ-1] = image << 1; |
| normalize (r); |
| } |
| else if (fmt->has_signed_zero) |
| r->sign = sign; |
| } |
| else if (exp == 255 && (fmt->has_nans || fmt->has_inf)) |
| { |
| if (image) |
| { |
| r->cl = rvc_nan; |
| r->sign = sign; |
| r->signalling = (((image >> (HOST_BITS_PER_LONG - 2)) & 1) |
| ^ fmt->qnan_msb_set); |
| r->sig[SIGSZ-1] = image; |
| } |
| else |
| { |
| r->cl = rvc_inf; |
| r->sign = sign; |
| } |
| } |
| else |
| { |
| r->cl = rvc_normal; |
| r->sign = sign; |
| SET_REAL_EXP (r, exp - 127 + 1); |
| r->sig[SIGSZ-1] = image | SIG_MSB; |
| } |
| } |
| |
| const struct real_format ieee_single_format = |
| { |
| encode_ieee_single, |
| decode_ieee_single, |
| 2, |
| 24, |
| 24, |
| -125, |
| 128, |
| 31, |
| 31, |
| 32, |
| false, |
| true, |
| true, |
| true, |
| true, |
| true, |
| true, |
| false, |
| "ieee_single" |
| }; |
| |
| const struct real_format mips_single_format = |
| { |
| encode_ieee_single, |
| decode_ieee_single, |
| 2, |
| 24, |
| 24, |
| -125, |
| 128, |
| 31, |
| 31, |
| 32, |
| false, |
| true, |
| true, |
| true, |
| true, |
| true, |
| false, |
| true, |
| "mips_single" |
| }; |
| |
| const struct real_format motorola_single_format = |
| { |
| encode_ieee_single, |
| decode_ieee_single, |
| 2, |
| 24, |
| 24, |
| -125, |
| 128, |
| 31, |
| 31, |
| 32, |
| false, |
| true, |
| true, |
| true, |
| true, |
| true, |
| true, |
| true, |
| "motorola_single" |
| }; |
| |
| /* SPU Single Precision (Extended-Range Mode) format is the same as IEEE |
| single precision with the following differences: |
| - Infinities are not supported. Instead MAX_FLOAT or MIN_FLOAT |
| are generated. |
| - NaNs are not supported. |
| - The range of non-zero numbers in binary is |
| (001)[1.]000...000 to (255)[1.]111...111. |
| - Denormals can be represented, but are treated as +0.0 when |
| used as an operand and are never generated as a result. |
| - -0.0 can be represented, but a zero result is always +0.0. |
| - the only supported rounding mode is trunction (towards zero). */ |
| const struct real_format spu_single_format = |
| { |
| encode_ieee_single, |
| decode_ieee_single, |
| 2, |
| 24, |
| 24, |
| -125, |
| 129, |
| 31, |
| 31, |
| 0, |
| true, |
| false, |
| false, |
| false, |
| true, |
| true, |
| false, |
| false, |
| "spu_single" |
| }; |
| |
| /* IEEE double-precision format. */ |
| |
| static void encode_ieee_double (const struct real_format *fmt, |
| long *, const REAL_VALUE_TYPE *); |
| static void decode_ieee_double (const struct real_format *, |
| REAL_VALUE_TYPE *, const long *); |
| |
| static void |
| encode_ieee_double (const struct real_format *fmt, long *buf, |
| const REAL_VALUE_TYPE *r) |
| { |
| unsigned long image_lo, image_hi, sig_lo, sig_hi, exp; |
| bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0; |
| |
| image_h
|