diff options
author | kenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4> | 1996-10-23 14:20:10 +0000 |
---|---|---|
committer | kenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4> | 1996-10-23 14:20:10 +0000 |
commit | b0006bb3c98c1a086f598282b0f40e93742e6ece (patch) | |
tree | 44168380f1ebf929a9f9ff93150800545db9b3be /gcc | |
parent | 9c4f6a5346ac0f663e892578129c0b6323186315 (diff) | |
download | gcc-b0006bb3c98c1a086f598282b0f40e93742e6ece.tar.gz |
(exact_real_inverse): New function, if REAL_ARITHMETIC.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@13002 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/real.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/gcc/real.c b/gcc/real.c index aab1e40882b..f7e22eae3bb 100644 --- a/gcc/real.c +++ b/gcc/real.c @@ -1043,6 +1043,68 @@ real_value_truncate (mode, arg) return (r); } +/* Try to change R into its exact multiplicative inverse in machine mode + MODE. Return nonzero function value if successful. */ + +int +exact_real_inverse (mode, r) + enum machine_mode mode; + REAL_VALUE_TYPE *r; +{ + unsigned EMUSHORT e[NE], einv[NE]; + REAL_VALUE_TYPE rinv; + int i; + + GET_REAL (r, e); + + /* Test for input in range. Don't transform IEEE special values. */ + if (eisinf (e) || eisnan (e) || (ecmp (e, ezero) == 0)) + return 0; + + /* Test for a power of 2: all significand bits zero except the MSB. + We are assuming the target has binary (or hex) arithmetic. */ + if (e[NE - 2] != 0x8000) + return 0; + + for (i = 0; i < NE - 2; i++) + { + if (e[i] != 0) + return 0; + } + + /* Compute the inverse and truncate it to the required mode. */ + ediv (e, eone, einv); + PUT_REAL (einv, &rinv); + rinv = real_value_truncate (mode, rinv); + +#ifdef CHECK_FLOAT_VALUE + /* This check is not redundant. It may, for example, flush + a supposedly IEEE denormal value to zero. */ + i = 0; + if (CHECK_FLOAT_VALUE (mode, rinv, i)) + return 0; +#endif + GET_REAL (&rinv, einv); + + /* Check the bits again, because the truncation might have + generated an arbitrary saturation value on overflow. */ + if (einv[NE - 2] != 0x8000) + return 0; + + for (i = 0; i < NE - 2; i++) + { + if (einv[i] != 0) + return 0; + } + + /* Fail if the computed inverse is out of range. */ + if (eisinf (einv) || eisnan (einv) || (ecmp (einv, ezero) == 0)) + return 0; + + /* Output the reciprocal and return success flag. */ + PUT_REAL (einv, r); + return 1; +} #endif /* REAL_ARITHMETIC defined */ /* Used for debugging--print the value of R in human-readable format |