summaryrefslogtreecommitdiff
path: root/gcc/real.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/real.c')
-rw-r--r--gcc/real.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/gcc/real.c b/gcc/real.c
index d9a4b801e3d..1598254c993 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -23,6 +23,8 @@
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "toplev.h"
#include "real.h"
@@ -2721,6 +2723,7 @@ const struct real_format ieee_single_format =
24,
-125,
128,
+ 31,
true,
true,
true,
@@ -2914,6 +2917,7 @@ const struct real_format ieee_double_format =
53,
-1021,
1024,
+ 63,
true,
true,
true,
@@ -3169,6 +3173,7 @@ const struct real_format ieee_extended_motorola_format =
64,
-16382,
16384,
+ 95,
true,
true,
true,
@@ -3185,6 +3190,7 @@ const struct real_format ieee_extended_intel_96_format =
64,
-16381,
16384,
+ 79,
true,
true,
true,
@@ -3201,6 +3207,7 @@ const struct real_format ieee_extended_intel_128_format =
64,
-16381,
16384,
+ 79,
true,
true,
true,
@@ -3294,6 +3301,7 @@ const struct real_format ibm_extended_format =
53 + 53,
-1021,
1024,
+ -1,
true,
true,
true,
@@ -3547,6 +3555,7 @@ const struct real_format ieee_quad_format =
113,
-16381,
16384,
+ 127,
true,
true,
true,
@@ -3854,6 +3863,7 @@ const struct real_format vax_f_format =
24,
-127,
127,
+ 15,
false,
false,
false,
@@ -3870,6 +3880,7 @@ const struct real_format vax_d_format =
56,
-127,
127,
+ 15,
false,
false,
false,
@@ -3886,6 +3897,7 @@ const struct real_format vax_g_format =
53,
-1023,
1023,
+ 15,
false,
false,
false,
@@ -4067,6 +4079,7 @@ const struct real_format i370_single_format =
6,
-64,
63,
+ 31,
false,
false,
false, /* ??? The encoding does allow for "unnormals". */
@@ -4083,6 +4096,7 @@ const struct real_format i370_double_format =
14,
-64,
63,
+ 63,
false,
false,
false, /* ??? The encoding does allow for "unnormals". */
@@ -4297,6 +4311,7 @@ const struct real_format c4x_single_format =
24,
-126,
128,
+ -1,
false,
false,
false,
@@ -4313,6 +4328,7 @@ const struct real_format c4x_extended_format =
32,
-126,
128,
+ -1,
false,
false,
false,
@@ -4358,6 +4374,7 @@ const struct real_format real_internal_format =
SIGNIFICAND_BITS - 2,
-MAX_EXP,
MAX_EXP,
+ -1,
true,
true,
false,
@@ -4381,3 +4398,86 @@ const struct real_format *real_format_for_mode[TFmode - QFmode + 1] =
NULL, /* XFmode */
&ieee_quad_format /* TFmode */
};
+
+
+/* Calculate the square root of X in mode MODE, and store the result
+ in R. For details see "High Precision Division and Square Root",
+ Alan H. Karp and Peter Markstein, HP Lab Report 93-93-42, June
+ 1993. http://www.hpl.hp.com/techreports/93/HPL-93-42.pdf. */
+
+void
+real_sqrt (r, mode, x)
+ REAL_VALUE_TYPE *r;
+ enum machine_mode mode;
+ const REAL_VALUE_TYPE *x;
+{
+ static REAL_VALUE_TYPE halfthree;
+ static REAL_VALUE_TYPE half;
+ static bool init = false;
+ REAL_VALUE_TYPE h, t, i;
+ int iter, exp;
+
+ /* sqrt(-0.0) is -0.0. */
+ if (real_isnegzero (x))
+ {
+ *r = *x;
+ return;
+ }
+
+ /* Negative arguments return NaN. */
+ if (real_isneg (x))
+ {
+ /* Mode is ignored for canonical NaN. */
+ real_nan (r, "", 1, SFmode);
+ return;
+ }
+
+ /* Infinity and NaN return themselves. */
+ if (real_isinf (x) || real_isnan (x))
+ {
+ *r = *x;
+ return;
+ }
+
+ if (!init)
+ {
+ real_arithmetic (&half, RDIV_EXPR, &dconst1, &dconst2);
+ real_arithmetic (&halfthree, PLUS_EXPR, &dconst1, &half);
+ init = true;
+ }
+
+ /* Initial guess for reciprocal sqrt, i. */
+ exp = real_exponent (x);
+ real_ldexp (&i, &dconst1, -exp/2);
+
+ /* Newton's iteration for reciprocal sqrt, i. */
+ for (iter = 0; iter < 16; iter++)
+ {
+ /* i(n+1) = i(n) * (1.5 - 0.5*i(n)*i(n)*x). */
+ real_arithmetic (&t, MULT_EXPR, x, &i);
+ real_arithmetic (&h, MULT_EXPR, &t, &i);
+ real_arithmetic (&t, MULT_EXPR, &h, &half);
+ real_arithmetic (&h, MINUS_EXPR, &halfthree, &t);
+ real_arithmetic (&t, MULT_EXPR, &i, &h);
+
+ /* Check for early convergence. */
+ if (iter >= 6 && real_identical (&i, &t))
+ break;
+
+ /* ??? Unroll loop to avoid copying. */
+ i = t;
+ }
+
+ /* Final iteration: r = i*x + 0.5*i*x*(1.0 - i*(i*x)). */
+ real_arithmetic (&t, MULT_EXPR, x, &i);
+ real_arithmetic (&h, MULT_EXPR, &t, &i);
+ real_arithmetic (&i, MINUS_EXPR, &dconst1, &h);
+ real_arithmetic (&h, MULT_EXPR, &t, &i);
+ real_arithmetic (&i, MULT_EXPR, &half, &h);
+ real_arithmetic (&h, PLUS_EXPR, &t, &i);
+
+ /* ??? We need a Tuckerman test to get the last bit. */
+
+ real_convert (r, mode, &h);
+}
+