Fixed a bug with complex numbers made from floats of differing precision.

It used to be that constructing complex numbers from a float and a
double sometimes caused incorrect coercions.
This commit is contained in:
Vincent St-Amour 2010-12-16 18:41:40 -05:00
parent 2bf83832b9
commit b32287fa2d
2 changed files with 42 additions and 12 deletions

View File

@ -2061,6 +2061,22 @@
(dbz-test polar2)))
parts))
;; extra complex tests
;; it used to be that complex numbers whose parts were floating-point
;; numbers of differing precision, coercion to the highest precision
;; when constructing the complex number (usually when reading) could
;; fail non-deterministically (which is why we test 1000 times)
(for ([i (in-range 1000)])
(test #t zero? (with-input-from-string "0.0f0" read)))
(for ([i (in-range 1000)])
(test #t zero? (with-input-from-string "0.0e0+0.0f0i" read)))
(for ([i (in-range 1000)])
(test #t zero? (string->number "0.0e0+0.0f0i")))
(for ([i (in-range 1000)])
(test #t zero? (make-rectangular 0.0e0 (with-input-from-string "0.0f0" read))))
(for ([i (in-range 1000)])
(test #t zero? (make-rectangular 0.0e0 (string->number "0.0f0"))))
(test #f string->number "88" 7)
(test #f string->number "")
(test #f string->number " 1")

View File

@ -84,17 +84,9 @@ Scheme_Object *scheme_complex_normalize(const Scheme_Object *o)
return (Scheme_Object *)c;
}
if (SCHEME_DBLP(c->i)) {
if (!SCHEME_DBLP(c->r)) {
Scheme_Object *r;
r = scheme_make_double(scheme_get_val_as_double(c->r));
c->r = r;
}
} else if (SCHEME_DBLP(c->r)) {
Scheme_Object *i;
i = scheme_make_double(scheme_get_val_as_double(c->i));
c->i = i;
}
/* Coercions: Exact -> float -> double
If the complex contains a float and an exact, we coerce the exact
to a float, etc. */
#ifdef MZ_USE_SINGLE_FLOATS
if (SCHEME_FLTP(c->i)) {
@ -108,9 +100,31 @@ Scheme_Object *scheme_complex_normalize(const Scheme_Object *o)
c->r = v;
}
}
} else if (SCHEME_FLTP(c->r)) {
Scheme_Object *v;
/* Imag part can't be a float, or we'd be in the previous case */
if (SCHEME_DBLP(c->i)) {
v = scheme_make_double(SCHEME_FLT_VAL(c->r));
c->r = v;
} else {
v = scheme_make_float(scheme_get_val_as_float(c->i));
c->i = v;
}
} else
#endif
if (SCHEME_DBLP(c->i)) {
if (!SCHEME_DBLP(c->r)) {
Scheme_Object *r;
r = scheme_make_double(scheme_get_val_as_double(c->r));
c->r = r;
}
} else if (SCHEME_DBLP(c->r)) {
Scheme_Object *i;
i = scheme_make_double(scheme_get_val_as_double(c->i));
c->i = i;
}
return (Scheme_Object *)c;
}