aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--math/test-misc.c37
-rw-r--r--sysdeps/i386/fpu/s_frexpl.S20
3 files changed, 63 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index b85c7d1..ed1ddaf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2000-12-03 Ulrich Drepper <drepper@redhat.com>
+
+ * math/test-misc.c (main): Add tests for frexp.
+ Reported by Fred J. Tydeman <tydeman@tybor.com>.
+ * sysdeps/i386/fpu/s_frexpl.S: Don't overflow during the computation.
+
2000-12-02 H.J. Lu <hjl@gnu.org>
* locale/lc-time.c (_nl_init_era_entries): Pass L'\0' instead of
diff --git a/math/test-misc.c b/math/test-misc.c
index 515277f..c0b8d0f 100644
--- a/math/test-misc.c
+++ b/math/test-misc.c
@@ -39,6 +39,43 @@ main (void)
result = 1;
}
}
+
+# if __GNUC__ >= 3 || __GNUC_MINOR__ >= 96
+ {
+ long double x = LDBL_MAX / ldexpl (1.0L, LDBL_MANT_DIG + 1);
+ long double m;
+ int i;
+
+# if LDBL_MANT_DIG == 64
+ m = 0xf.fffffffffffffffp-4L;
+# else
+# error "Please adjust"
+# endif
+
+ for (i = 0; i < LDBL_MANT_DIG + 1; ++i, x *= 2.0L)
+ {
+ long double r;
+ int e;
+
+ printf ("2^%d: ", LDBL_MAX_EXP - (LDBL_MANT_DIG + 1) + i);
+
+ r = frexpl (x, &e);
+ if (r != m)
+ {
+ printf ("mantissa incorrect: %.20La\n", r);
+ result = 1;
+ continue;
+ }
+ if (e != LDBL_MAX_EXP - (LDBL_MANT_DIG + 1) + i)
+ {
+ printf ("exponent wrong %d (%.20Lg)\n", e, x);
+ result = 1;
+ continue;
+ }
+ puts ("ok");
+ }
+ }
+# endif
#endif
{
diff --git a/sysdeps/i386/fpu/s_frexpl.S b/sysdeps/i386/fpu/s_frexpl.S
index cb943f7..2645d22 100644
--- a/sysdeps/i386/fpu/s_frexpl.S
+++ b/sysdeps/i386/fpu/s_frexpl.S
@@ -32,6 +32,12 @@
ASM_TYPE_DIRECTIVE(two64,@object)
two64: .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x43
ASM_SIZE_DIRECTIVE(two64)
+ /* The following is LDBL_MAX / ldexp (1.0, 64), the largest
+ number we can handle the normal way. */
+ ASM_TYPE_DIRECTIVE(largest,@object)
+largest:
+ .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0x7f, 0, 0
+ ASM_SIZE_DIRECTIVE(largest)
#ifdef PIC
#define MO(op) op##@GOTOFF(%edx)
@@ -63,12 +69,16 @@ ENTRY (BP_SYM (__frexpl))
cmpl $0, %eax
je 2f
+ cmpl $0x7fbe, %eax
+ ja 4f
+
fldt VAL0(%esp)
#ifdef PIC
call 3f
3: popl %edx
addl $_GLOBAL_OFFSET_TABLE_+[.-3b], %edx
#endif
+
fmull MO(two64) /* It's not necessary to use a 80bit factor */
movl $-64, %ecx
fstpt VAL0(%esp)
@@ -92,5 +102,15 @@ ENTRY (BP_SYM (__frexpl))
LEAVE
ret
+
+4: movl VAL2(%esp), %ecx
+ movl %ecx, %edx
+ andl $0x7fff, %ecx
+
+ andl $0x8000, %edx
+ subl $16382, %ecx
+ orl $0x3ffe, %edx
+ movl %edx, VAL2(%esp)
+ jmp 1b
END (BP_SYM (__frexpl))
weak_alias (BP_SYM (__frexpl), BP_SYM (frexpl))