expt: fix floating point contagion

Examples of the bug

(expt -1.4d0 #C(1 2)) -> #C(-0.0020444484 -0.0016295447)
(expt #C(1.0 3.0) 0.0d0) -> #C(1.0 0.0)

These return a (complex single-float), should be (complex double-float).

The code incorrectly assumed that the numbers associated to the types
tx and ty were ordered such that long floats and complex long floats
have higher numbers than double floats and complex double floats.
This commit is contained in:
Marius Gerbershagen 2025-12-12 22:37:12 +01:00
parent 95566d1380
commit f1091f4cd6
2 changed files with 17 additions and 9 deletions

View file

@ -80,8 +80,14 @@ expt_zero(cl_object x, cl_object y)
return ecl_make_complex(z, ecl_make_fixnum(0));
#ifdef ECL_COMPLEX_FLOAT
case t_csfloat:
if (tx == t_longfloat || ty == t_longfloat)
return clfloat_one;
if (tx == t_doublefloat || ty == t_doublefloat)
return cdfloat_one;
return csfloat_one;
case t_cdfloat:
if (tx == t_longfloat || ty == t_longfloat)
return clfloat_one;
return cdfloat_one;
case t_clfloat:
return clfloat_one;
@ -149,21 +155,17 @@ ecl_expt_complex_float(cl_object x, cl_object y) {
cl_object ret;
ECL_MATHERR_CLEAR;
switch ((ty > tx)? ty : tx) {
case t_clfloat:
case t_longfloat:
if (tx == t_clfloat || tx == t_longfloat ||
ty == t_clfloat || ty == t_longfloat) {
ret = ecl_make_clfloat
(cpowl(ecl_to_clfloat(x), ecl_to_clfloat(y)));
break;
case t_cdfloat:
case t_doublefloat:
} else if (tx == t_cdfloat || tx == t_doublefloat ||
ty == t_cdfloat || ty == t_doublefloat) {
ret = ecl_make_cdfloat
(cpow (ecl_to_cdfloat(x), ecl_to_cdfloat(y)));
break;
default:
} else {
ret = ecl_make_csfloat
(cpowf(ecl_to_csfloat(x), ecl_to_csfloat(y)));
break;
}
ECL_MATHERR_TEST;
return ret;

View file

@ -304,3 +304,9 @@
;;
(test csfloat.0010.issue-547
(finishes (expt #c(1.0 0.0) 2))))
(test complex.0011.expt-float-contagion
(is (typep (expt -1.4d0 #C(1 2)) '(complex double-float)))
(is (typep (expt -1.4l0 #C(1 2)) '(complex long-float)))
(is (typep (expt #C(1.0 3.0) 0.0d0) '(complex double-float)))
(is (typep (expt #C(1.0 3.0) 0.0l0) '(complex long-float))))