Skip to content

Commit aefbc72

Browse files
ZERICO2005adriweb
authored andcommitted
fixed autotests, and modified undefined behaviour when converting long double to an integer
1 parent 4d657fb commit aefbc72

File tree

26 files changed

+11079
-17395
lines changed

26 files changed

+11079
-17395
lines changed

src/crt/float64_to_int.c

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,16 @@ uint64_t _dtoull_c(long double x) {
6464
}
6565
#endif
6666

67+
/**
68+
* @brief set to 0 or 1
69+
* If set to 1, values that truncate to `INT32_MIN`/`INT64_MIN` will be
70+
* handled correctly.
71+
* If set to 0, it can save a little bit of space by removing a comparison from
72+
* `_dtol_c` and `_dtoll_c`. However this will cause values that would truncate
73+
* to `INT32_MIN`/`INT64_MIN` to have an undefined result.
74+
*/
75+
#define HANDLE_INT_MIN 1
76+
6777
/**
6878
* @note val must have the signbit cleared
6979
*/
@@ -92,29 +102,23 @@ static uint64_t f64_to_unsigned(F64_pun val) {
92102
}
93103

94104
uint64_t _dtoull_c(long double x) {
95-
if (signbit(x)) {
96-
return 0;
97-
}
98105
F64_pun val;
99106
val.flt = x;
100107
/* overflow || signbit(x) || isinf(x) || isnan(x) */
101108
if (val.reg.BC >= ((Float64_bias + Float64_u64_max_exp) << Float64_exp_BC_shift)) {
102-
/* undefined return value for negative/inf/NaN values of x */
103-
return UINT64_MAX;
109+
/* undefined return value for negative/overflow/inf/NaN of x */
110+
return 0;
104111
}
105112
return f64_to_unsigned(val);
106113
}
107114

108115
uint32_t _dtoul_c(long double x) {
109-
if (signbit(x)) {
110-
return 0;
111-
}
112116
F64_pun val;
113117
val.flt = x;
114118
/* overflow || signbit(x) || isinf(x) || isnan(x) */
115119
if (val.reg.BC >= ((Float64_bias + Float64_u32_max_exp) << Float64_exp_BC_shift)) {
116-
/* undefined return value for negative/inf/NaN values of x */
117-
return UINT32_MAX;
120+
/* undefined return value for negative/overflow/inf/NaN values of x */
121+
return 0;
118122
}
119123
return (uint32_t)f64_to_unsigned(val);
120124
}
@@ -126,9 +130,16 @@ int64_t _dtoll_c(long double x) {
126130

127131
/* overflow || isinf(x) || isnan(x) */
128132
if (val.reg.BC >= ((Float64_bias + Float64_i64_max_exp) << Float64_exp_BC_shift)) {
129-
/* undefined return value for inf/NaN values of x */
130-
return x_sign ? INT64_MIN : INT64_MAX;
133+
#if HANDLE_INT_MIN != 0
134+
/* if the value truncates to INT64_MIN */
135+
if (x_sign && val.bin == UINT64_C(0x43E0000000000000)) {
136+
return INT64_MIN;
137+
}
138+
#endif
139+
/* undefined return value for underflow/overflow/inf/NaN values of x */
140+
return 0;
131141
}
142+
132143
int64_t ret = (int64_t)f64_to_unsigned(val);
133144
ret = x_sign ? -ret : ret;
134145
return ret;
@@ -141,8 +152,14 @@ int32_t _dtol_c(long double x) {
141152

142153
/* overflow || isinf(x) || isnan(x) */
143154
if (val.reg.BC >= ((Float64_bias + Float64_i32_max_exp) << Float64_exp_BC_shift)) {
144-
/* undefined return value for inf/NaN values of x */
145-
return x_sign ? INT32_MIN : INT32_MAX;
155+
#if HANDLE_INT_MIN != 0
156+
/* if the value truncates to INT32_MIN */
157+
if (x_sign && val.bin <= UINT64_C(0x41E00000001FFFFF)) {
158+
return INT32_MIN;
159+
}
160+
#endif
161+
/* undefined return value for underflow/overflow/inf/NaN values of x */
162+
return 0;
146163
}
147164
int32_t ret = (int32_t)f64_to_unsigned(val);
148165
ret = x_sign ? -ret : ret;

src/libc/frexpf.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,9 @@ float _frexpf_c(float value, int *pExponent)
6969

7070
#else
7171

72-
#include <stdint.h>
72+
#include <limits.h>
7373
#include <math.h>
74+
#include <stdint.h>
7475

7576
typedef union F32_pun {
7677
float flt;
@@ -97,7 +98,7 @@ float _frexpf_c(float x, int *expon) {
9798
case FP_INFINITE:
9899
case FP_NAN: {
99100
// Unspecified exponent value for inf and NaN
100-
*expon = FP_ILOGBNAN;
101+
*expon = INT_MAX;
101102
return val.flt;
102103
}
103104
case FP_ZERO: {

src/libc/frexpl.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <limits.h>
12
#include <math.h>
23
#include <stdint.h>
34

@@ -36,7 +37,7 @@ static long double _frexpl_c_positive(long double x, int *expon) {
3637
/* isinf(x) || isnan(x) */
3738
if (x_exp == Float64_biased_inf_nan_exp) {
3839
// Unspecified exponent value for inf and NaN
39-
*expon = FP_ILOGBNAN;
40+
*expon = INT_MAX;
4041
return val.flt;
4142
}
4243
/* isnormal(x) */

src/softfloat/include/specialize.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,23 +51,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5151
| The values to return on conversions to 32-bit integer formats that raise an
5252
| invalid exception.
5353
*----------------------------------------------------------------------------*/
54-
#define ui32_fromPosOverflow 0xFFFFFFFF
55-
#define ui32_fromNegOverflow 0xFFFFFFFF
56-
#define ui32_fromNaN 0xFFFFFFFF
57-
#define i32_fromPosOverflow (-0x7FFFFFFF - 1)
58-
#define i32_fromNegOverflow (-0x7FFFFFFF - 1)
59-
#define i32_fromNaN (-0x7FFFFFFF - 1)
54+
#define ui32_fromPosOverflow UINT32_C( 0x0 )
55+
#define ui32_fromNegOverflow UINT32_C( 0x0 )
56+
#define ui32_fromNaN UINT32_C( 0x0 )
57+
#define i32_fromPosOverflow INT32_C( 0x0 )
58+
#define i32_fromNegOverflow INT32_C( 0x0 )
59+
#define i32_fromNaN INT32_C( 0x0 )
6060

6161
/*----------------------------------------------------------------------------
6262
| The values to return on conversions to 64-bit integer formats that raise an
6363
| invalid exception.
6464
*----------------------------------------------------------------------------*/
65-
#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF )
66-
#define ui64_fromNegOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF )
67-
#define ui64_fromNaN UINT64_C( 0xFFFFFFFFFFFFFFFF )
68-
#define i64_fromPosOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
69-
#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
70-
#define i64_fromNaN (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
65+
#define ui64_fromPosOverflow UINT64_C( 0x0 )
66+
#define ui64_fromNegOverflow UINT64_C( 0x0 )
67+
#define ui64_fromNaN UINT64_C( 0x0 )
68+
#define i64_fromPosOverflow INT64_C( 0x0 )
69+
#define i64_fromNegOverflow INT64_C( 0x0 )
70+
#define i64_fromNaN INT64_C( 0x0 )
7171

7272
/*----------------------------------------------------------------------------
7373
| "Common NaN" structure, used to transfer NaN representations from one format

0 commit comments

Comments
 (0)