summaryrefslogtreecommitdiff
path: root/gcc/real.c
diff options
context:
space:
mode:
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>1996-10-23 14:20:10 +0000
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>1996-10-23 14:20:10 +0000
commitb0006bb3c98c1a086f598282b0f40e93742e6ece (patch)
tree44168380f1ebf929a9f9ff93150800545db9b3be /gcc/real.c
parent9c4f6a5346ac0f663e892578129c0b6323186315 (diff)
downloadgcc-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/real.c')
-rw-r--r--gcc/real.c62
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