diff --git a/collects/tests/racket/number.rktl b/collects/tests/racket/number.rktl index 6dfaec9d6f..6ea1461516 100644 --- a/collects/tests/racket/number.rktl +++ b/collects/tests/racket/number.rktl @@ -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") diff --git a/src/racket/src/complex.c b/src/racket/src/complex.c index 5cad45a013..6d937bcb9a 100644 --- a/src/racket/src/complex.c +++ b/src/racket/src/complex.c @@ -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; }