Skip to content

Commit 0ba68f8

Browse files
stinosdpgeorge
authored andcommitted
all: Fix implicit floating point promotion.
Initially some of these were found building the unix coverage variant on MacOS because that build uses clang and has -Wdouble-promotion enabled, and clang performs more vigorous promotion checks than gcc. Additionally the codebase has been compiled with clang and msvc (the latter with warning level 3), and with MICROPY_FLOAT_IMPL_FLOAT to find the rest of the conversions. Fixes are implemented either as explicit casts, or by using the correct type, or by using one of the utility functions to handle floating point casting; these have been moved from nativeglue.c to the public API.
1 parent b909e8b commit 0ba68f8

File tree

11 files changed

+70
-54
lines changed

11 files changed

+70
-54
lines changed

extmod/moductypes.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ STATIC mp_obj_t get_aligned(uint val_type, void *p, mp_int_t index) {
360360
return mp_obj_new_int_from_ll(((int64_t *)p)[index]);
361361
#if MICROPY_PY_BUILTINS_FLOAT
362362
case FLOAT32:
363-
return mp_obj_new_float(((float *)p)[index]);
363+
return mp_obj_new_float_from_f(((float *)p)[index]);
364364
case FLOAT64:
365365
return mp_obj_new_float(((double *)p)[index]);
366366
#endif
@@ -373,11 +373,10 @@ STATIC mp_obj_t get_aligned(uint val_type, void *p, mp_int_t index) {
373373
STATIC void set_aligned(uint val_type, void *p, mp_int_t index, mp_obj_t val) {
374374
#if MICROPY_PY_BUILTINS_FLOAT
375375
if (val_type == FLOAT32 || val_type == FLOAT64) {
376-
mp_float_t v = mp_obj_get_float(val);
377376
if (val_type == FLOAT32) {
378-
((float *)p)[index] = v;
377+
((float *)p)[index] = mp_obj_get_float_to_f(val);
379378
} else {
380-
((double *)p)[index] = v;
379+
((double *)p)[index] = mp_obj_get_float_to_d(val);
381380
}
382381
return;
383382
}

extmod/moduselect.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ STATIC mp_obj_t select_select(size_t n_args, const mp_obj_t *args) {
125125
if (n_args == 4) {
126126
if (args[3] != mp_const_none) {
127127
#if MICROPY_PY_BUILTINS_FLOAT
128-
float timeout_f = mp_obj_get_float(args[3]);
128+
float timeout_f = mp_obj_get_float_to_f(args[3]);
129129
if (timeout_f >= 0) {
130130
timeout = (mp_uint_t)(timeout_f * 1000);
131131
}

ports/unix/modffi.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ STATIC mp_obj_t return_ffi_value(ffi_arg val, char type) {
167167
union { ffi_arg ffi;
168168
float flt;
169169
} val_union = { .ffi = val };
170-
return mp_obj_new_float(val_union.flt);
170+
return mp_obj_new_float_from_f(val_union.flt);
171171
}
172172
case 'd': {
173173
double *p = (double *)&val;
@@ -381,7 +381,7 @@ STATIC mp_obj_t ffifunc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
381381
*p = mp_obj_get_float(a);
382382
} else if (*argtype == 'd') {
383383
double *p = (double *)&values[i];
384-
*p = mp_obj_get_float(a);
384+
*p = mp_obj_get_float_to_d(a);
385385
#endif
386386
} else if (a == mp_const_none) {
387387
values[i] = 0;

ports/unix/modtime.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ static inline int msec_sleep_tv(struct timeval *tv) {
6161
#endif
6262

6363
#if defined(MP_CLOCKS_PER_SEC)
64-
#define CLOCK_DIV (MP_CLOCKS_PER_SEC / 1000.0F)
64+
#define CLOCK_DIV (MP_CLOCKS_PER_SEC / MICROPY_FLOAT_CONST(1000.0))
6565
#else
6666
#error Unsupported clock() implementation
6767
#endif
@@ -84,7 +84,7 @@ STATIC mp_obj_t mod_time_clock(void) {
8484
// float cannot represent full range of int32 precisely, so we pre-divide
8585
// int to reduce resolution, and then actually do float division hoping
8686
// to preserve integer part resolution.
87-
return mp_obj_new_float((float)(clock() / 1000) / CLOCK_DIV);
87+
return mp_obj_new_float((clock() / 1000) / CLOCK_DIV);
8888
#else
8989
return mp_obj_new_int((mp_int_t)clock());
9090
#endif
@@ -95,8 +95,8 @@ STATIC mp_obj_t mod_time_sleep(mp_obj_t arg) {
9595
#if MICROPY_PY_BUILTINS_FLOAT
9696
struct timeval tv;
9797
mp_float_t val = mp_obj_get_float(arg);
98-
double ipart;
99-
tv.tv_usec = round(modf(val, &ipart) * 1000000);
98+
mp_float_t ipart;
99+
tv.tv_usec = MICROPY_FLOAT_C_FUN(round)(MICROPY_FLOAT_C_FUN(modf)(val, &ipart) * MICROPY_FLOAT_CONST(1000000.));
100100
tv.tv_sec = ipart;
101101
int res;
102102
while (1) {

ports/unix/modusocket.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,8 +378,8 @@ STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
378378
if (timeout_in != mp_const_none) {
379379
#if MICROPY_PY_BUILTINS_FLOAT
380380
mp_float_t val = mp_obj_get_float(timeout_in);
381-
double ipart;
382-
tv.tv_usec = round(modf(val, &ipart) * 1000000);
381+
mp_float_t ipart;
382+
tv.tv_usec = MICROPY_FLOAT_C_FUN(round)(MICROPY_FLOAT_C_FUN(modf)(val, &ipart) * MICROPY_FLOAT_CONST(1000000.));
383383
tv.tv_sec = ipart;
384384
#else
385385
tv.tv_sec = mp_obj_get_int(timeout_in);

py/binary.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, size_t index) {
176176
#endif
177177
#if MICROPY_PY_BUILTINS_FLOAT
178178
case 'f':
179-
return mp_obj_new_float(((float *)p)[index]);
179+
return mp_obj_new_float_from_f(((float *)p)[index]);
180180
case 'd':
181181
return mp_obj_new_float(((double *)p)[index]);
182182
#endif
@@ -244,7 +244,7 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte *
244244
union { uint32_t i;
245245
float f;
246246
} fpu = {val};
247-
return mp_obj_new_float(fpu.f);
247+
return mp_obj_new_float_from_f(fpu.f);
248248
} else if (val_type == 'd') {
249249
union { uint64_t i;
250250
double f;
@@ -320,7 +320,7 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p
320320
uint32_t i32[2];
321321
double f;
322322
} fp_dp;
323-
fp_dp.f = mp_obj_get_float(val_in);
323+
fp_dp.f = mp_obj_get_float_to_d(val_in);
324324
if (BYTES_PER_WORD == 8) {
325325
val = fp_dp.i64;
326326
} else {
@@ -362,7 +362,7 @@ void mp_binary_set_val_array(char typecode, void *p, size_t index, mp_obj_t val_
362362
((float *)p)[index] = mp_obj_get_float(val_in);
363363
break;
364364
case 'd':
365-
((double *)p)[index] = mp_obj_get_float(val_in);
365+
((double *)p)[index] = mp_obj_get_float_to_d(val_in);
366366
break;
367367
#endif
368368
// Extension to CPython: array of objects

py/modcmath.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_exp_obj, mp_cmath_exp);
7272
STATIC mp_obj_t mp_cmath_log(mp_obj_t z_obj) {
7373
mp_float_t real, imag;
7474
mp_obj_get_complex(z_obj, &real, &imag);
75-
return mp_obj_new_complex(0.5 * MICROPY_FLOAT_C_FUN(log)(real * real + imag * imag), MICROPY_FLOAT_C_FUN(atan2)(imag, real));
75+
return mp_obj_new_complex(MICROPY_FLOAT_CONST(0.5) * MICROPY_FLOAT_C_FUN(log)(real * real + imag * imag), MICROPY_FLOAT_C_FUN(atan2)(imag, real));
7676
}
7777
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log_obj, mp_cmath_log);
7878

@@ -81,7 +81,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log_obj, mp_cmath_log);
8181
STATIC mp_obj_t mp_cmath_log10(mp_obj_t z_obj) {
8282
mp_float_t real, imag;
8383
mp_obj_get_complex(z_obj, &real, &imag);
84-
return mp_obj_new_complex(0.5 * MICROPY_FLOAT_C_FUN(log10)(real * real + imag * imag), 0.4342944819032518 * MICROPY_FLOAT_C_FUN(atan2)(imag, real));
84+
return mp_obj_new_complex(MICROPY_FLOAT_CONST(0.5) * MICROPY_FLOAT_C_FUN(log10)(real * real + imag * imag), MICROPY_FLOAT_CONST(0.4342944819032518) * MICROPY_FLOAT_C_FUN(atan2)(imag, real));
8585
}
8686
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log10_obj, mp_cmath_log10);
8787
#endif
@@ -90,8 +90,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log10_obj, mp_cmath_log10);
9090
STATIC mp_obj_t mp_cmath_sqrt(mp_obj_t z_obj) {
9191
mp_float_t real, imag;
9292
mp_obj_get_complex(z_obj, &real, &imag);
93-
mp_float_t sqrt_abs = MICROPY_FLOAT_C_FUN(pow)(real * real + imag * imag, 0.25);
94-
mp_float_t theta = 0.5 * MICROPY_FLOAT_C_FUN(atan2)(imag, real);
93+
mp_float_t sqrt_abs = MICROPY_FLOAT_C_FUN(pow)(real * real + imag * imag, MICROPY_FLOAT_CONST(0.25));
94+
mp_float_t theta = MICROPY_FLOAT_CONST(0.5) * MICROPY_FLOAT_C_FUN(atan2)(imag, real);
9595
return mp_obj_new_complex(sqrt_abs * MICROPY_FLOAT_C_FUN(cos)(theta), sqrt_abs * MICROPY_FLOAT_C_FUN(sin)(theta));
9696
}
9797
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_sqrt_obj, mp_cmath_sqrt);

py/nativeglue.c

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -227,25 +227,7 @@ STATIC bool mp_native_yield_from(mp_obj_t gen, mp_obj_t send_value, mp_obj_t *re
227227
return false;
228228
}
229229

230-
#if MICROPY_PY_BUILTINS_FLOAT
231-
232-
STATIC mp_obj_t mp_obj_new_float_from_f(float f) {
233-
return mp_obj_new_float((mp_float_t)f);
234-
}
235-
236-
STATIC mp_obj_t mp_obj_new_float_from_d(double d) {
237-
return mp_obj_new_float((mp_float_t)d);
238-
}
239-
240-
STATIC float mp_obj_get_float_to_f(mp_obj_t o) {
241-
return (float)mp_obj_get_float(o);
242-
}
243-
244-
STATIC double mp_obj_get_float_to_d(mp_obj_t o) {
245-
return (double)mp_obj_get_float(o);
246-
}
247-
248-
#else
230+
#if !MICROPY_PY_BUILTINS_FLOAT
249231

250232
STATIC mp_obj_t mp_obj_new_float_from_f(float f) {
251233
(void)f;

py/obj.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,39 @@ void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, size_t s
820820

821821
#if MICROPY_PY_BUILTINS_FLOAT
822822
// float
823+
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
824+
static inline float mp_obj_get_float_to_f(mp_obj_t o) {
825+
return mp_obj_get_float(o);
826+
}
827+
828+
static inline double mp_obj_get_float_to_d(mp_obj_t o) {
829+
return (double)mp_obj_get_float(o);
830+
}
831+
832+
static inline mp_obj_t mp_obj_new_float_from_f(float o) {
833+
return mp_obj_new_float(o);
834+
}
835+
836+
static inline mp_obj_t mp_obj_new_float_from_d(double o) {
837+
return mp_obj_new_float((mp_float_t)o);
838+
}
839+
#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
840+
static inline float mp_obj_get_float_to_f(mp_obj_t o) {
841+
return (float)mp_obj_get_float(o);
842+
}
843+
844+
static inline double mp_obj_get_float_to_d(mp_obj_t o) {
845+
return mp_obj_get_float(o);
846+
}
847+
848+
static inline mp_obj_t mp_obj_new_float_from_f(float o) {
849+
return mp_obj_new_float((mp_float_t)o);
850+
}
851+
852+
static inline mp_obj_t mp_obj_new_float_from_d(double o) {
853+
return mp_obj_new_float(o);
854+
}
855+
#endif
823856
#if MICROPY_FLOAT_HIGH_QUALITY_HASH
824857
mp_int_t mp_float_hash(mp_float_t val);
825858
#else

py/objfloat.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,13 @@ typedef struct _mp_obj_float_t {
5252
mp_float_t value;
5353
} mp_obj_float_t;
5454

55-
const mp_obj_float_t mp_const_float_e_obj = {{&mp_type_float}, M_E};
56-
const mp_obj_float_t mp_const_float_pi_obj = {{&mp_type_float}, M_PI};
55+
const mp_obj_float_t mp_const_float_e_obj = {{&mp_type_float}, (mp_float_t)M_E};
56+
const mp_obj_float_t mp_const_float_pi_obj = {{&mp_type_float}, (mp_float_t)M_PI};
5757

5858
#endif
5959

60+
#define MICROPY_FLOAT_ZERO MICROPY_FLOAT_CONST(0.0)
61+
6062
#if MICROPY_FLOAT_HIGH_QUALITY_HASH
6163
// must return actual integer value if it fits in mp_int_t
6264
mp_int_t mp_float_hash(mp_float_t src) {
@@ -208,24 +210,24 @@ STATIC void mp_obj_float_divmod(mp_float_t *x, mp_float_t *y) {
208210
mp_float_t div = (*x - mod) / *y;
209211

210212
// Python specs require that mod has same sign as second operand
211-
if (mod == 0.0) {
212-
mod = MICROPY_FLOAT_C_FUN(copysign)(0.0, *y);
213+
if (mod == MICROPY_FLOAT_ZERO) {
214+
mod = MICROPY_FLOAT_C_FUN(copysign)(MICROPY_FLOAT_ZERO, *y);
213215
} else {
214-
if ((mod < 0.0) != (*y < 0.0)) {
216+
if ((mod < MICROPY_FLOAT_ZERO) != (*y < MICROPY_FLOAT_ZERO)) {
215217
mod += *y;
216-
div -= 1.0;
218+
div -= MICROPY_FLOAT_CONST(1.0);
217219
}
218220
}
219221

220222
mp_float_t floordiv;
221-
if (div == 0.0) {
223+
if (div == MICROPY_FLOAT_ZERO) {
222224
// if division is zero, take the correct sign of zero
223-
floordiv = MICROPY_FLOAT_C_FUN(copysign)(0.0, *x / *y);
225+
floordiv = MICROPY_FLOAT_C_FUN(copysign)(MICROPY_FLOAT_ZERO, *x / *y);
224226
} else {
225227
// Python specs require that x == (x//y)*y + (x%y)
226228
floordiv = MICROPY_FLOAT_C_FUN(floor)(div);
227-
if (div - floordiv > 0.5) {
228-
floordiv += 1.0;
229+
if (div - floordiv > MICROPY_FLOAT_CONST(0.5)) {
230+
floordiv += MICROPY_FLOAT_CONST(1.0);
229231
}
230232
}
231233

@@ -273,15 +275,15 @@ mp_obj_t mp_obj_float_binary_op(mp_binary_op_t op, mp_float_t lhs_val, mp_obj_t
273275
break;
274276
case MP_BINARY_OP_MODULO:
275277
case MP_BINARY_OP_INPLACE_MODULO:
276-
if (rhs_val == 0) {
278+
if (rhs_val == MICROPY_FLOAT_ZERO) {
277279
goto zero_division_error;
278280
}
279281
lhs_val = MICROPY_FLOAT_C_FUN(fmod)(lhs_val, rhs_val);
280282
// Python specs require that mod has same sign as second operand
281-
if (lhs_val == 0.0) {
283+
if (lhs_val == MICROPY_FLOAT_ZERO) {
282284
lhs_val = MICROPY_FLOAT_C_FUN(copysign)(0.0, rhs_val);
283285
} else {
284-
if ((lhs_val < 0.0) != (rhs_val < 0.0)) {
286+
if ((lhs_val < MICROPY_FLOAT_ZERO) != (rhs_val < MICROPY_FLOAT_ZERO)) {
285287
lhs_val += rhs_val;
286288
}
287289
}

0 commit comments

Comments
 (0)