@@ -127,32 +127,32 @@ TEST_CASE("system_info") {
127127 std::cout << std::endl;
128128}
129129
130- TEST_CASE (" float .rounds_to_nearest" ) {
130+ TEST_CASE (" double .rounds_to_nearest" ) {
131131 //
132132 // If this function fails, we may be left in a non-standard rounding state.
133133 //
134- static float volatile fmin = std::numeric_limits<float >::min ();
134+ static double volatile fmin = std::numeric_limits<double >::min ();
135135 fesetround (FE_UPWARD);
136- std::cout << " FE_UPWARD: fmin + 1.0f = " << fHexAndDec (fmin + 1 .0f )
137- << " 1.0f - fmin = " << fHexAndDec (1 .0f - fmin) << std::endl;
136+ std::cout << " FE_UPWARD: fmin + 1.0 = " << fHexAndDec (fmin + 1.0 )
137+ << " 1.0 - fmin = " << fHexAndDec (1.0 - fmin) << std::endl;
138138 CHECK (fegetround () == FE_UPWARD);
139139 CHECK (fast_float::detail::rounds_to_nearest () == false );
140140
141141 fesetround (FE_DOWNWARD);
142- std::cout << " FE_DOWNWARD: fmin + 1.0f = " << fHexAndDec (fmin + 1 .0f )
143- << " 1.0f - fmin = " << fHexAndDec (1 .0f - fmin) << std::endl;
142+ std::cout << " FE_DOWNWARD: fmin + 1.0 = " << fHexAndDec (fmin + 1.0 )
143+ << " 1.0 - fmin = " << fHexAndDec (1.0 - fmin) << std::endl;
144144 CHECK (fegetround () == FE_DOWNWARD);
145145 CHECK (fast_float::detail::rounds_to_nearest () == false );
146146
147147 fesetround (FE_TOWARDZERO);
148- std::cout << " FE_TOWARDZERO: fmin + 1.0f = " << fHexAndDec (fmin + 1 .0f )
149- << " 1.0f - fmin = " << fHexAndDec (1 .0f - fmin) << std::endl;
148+ std::cout << " FE_TOWARDZERO: fmin + 1.0 = " << fHexAndDec (fmin + 1.0 )
149+ << " 1.0 - fmin = " << fHexAndDec (1.0 - fmin) << std::endl;
150150 CHECK (fegetround () == FE_TOWARDZERO);
151151 CHECK (fast_float::detail::rounds_to_nearest () == false );
152152
153153 fesetround (FE_TONEAREST);
154- std::cout << " FE_TONEAREST: fmin + 1.0f = " << fHexAndDec (fmin + 1 .0f )
155- << " 1.0f - fmin = " << fHexAndDec (1 .0f - fmin) << std::endl;
154+ std::cout << " FE_TONEAREST: fmin + 1.0 = " << fHexAndDec (fmin + 1.0 )
155+ << " 1.0 - fmin = " << fHexAndDec (1.0 - fmin) << std::endl;
156156 CHECK (fegetround () == FE_TONEAREST);
157157#if (FLT_EVAL_METHOD == 1) || (FLT_EVAL_METHOD == 0)
158158 CHECK (fast_float::detail::rounds_to_nearest () == true );
@@ -265,6 +265,144 @@ TEST_CASE("double.parse_negative_zero") {
265265 CHECK (float64_parsed == 0x8000'0000'0000'0000 );
266266}
267267
268+ TEST_CASE (" float.rounds_to_nearest" ) {
269+ //
270+ // If this function fails, we may be left in a non-standard rounding state.
271+ //
272+ static float volatile fmin = std::numeric_limits<float >::min ();
273+ fesetround (FE_UPWARD);
274+ std::cout << " FE_UPWARD: fmin + 1.0f = " << fHexAndDec (fmin + 1 .0f )
275+ << " 1.0f - fmin = " << fHexAndDec (1 .0f - fmin) << std::endl;
276+ CHECK (fegetround () == FE_UPWARD);
277+ CHECK (fast_float::detail::rounds_to_nearest () == false );
278+
279+ fesetround (FE_DOWNWARD);
280+ std::cout << " FE_DOWNWARD: fmin + 1.0f = " << fHexAndDec (fmin + 1 .0f )
281+ << " 1.0f - fmin = " << fHexAndDec (1 .0f - fmin) << std::endl;
282+ CHECK (fegetround () == FE_DOWNWARD);
283+ CHECK (fast_float::detail::rounds_to_nearest () == false );
284+
285+ fesetround (FE_TOWARDZERO);
286+ std::cout << " FE_TOWARDZERO: fmin + 1.0f = " << fHexAndDec (fmin + 1 .0f )
287+ << " 1.0f - fmin = " << fHexAndDec (1 .0f - fmin) << std::endl;
288+ CHECK (fegetround () == FE_TOWARDZERO);
289+ CHECK (fast_float::detail::rounds_to_nearest () == false );
290+
291+ fesetround (FE_TONEAREST);
292+ std::cout << " FE_TONEAREST: fmin + 1.0f = " << fHexAndDec (fmin + 1 .0f )
293+ << " 1.0f - fmin = " << fHexAndDec (1 .0f - fmin) << std::endl;
294+ CHECK (fegetround () == FE_TONEAREST);
295+ #if (FLT_EVAL_METHOD == 1) || (FLT_EVAL_METHOD == 0)
296+ CHECK (fast_float::detail::rounds_to_nearest () == true );
297+ #endif
298+ }
299+
300+ TEST_CASE (" float.parse_zero" ) {
301+ //
302+ // If this function fails, we may be left in a non-standard rounding state.
303+ //
304+ char const *zero = " 0" ;
305+ uint32_t float32_parsed;
306+ float f = 0 ;
307+ ::memcpy (&float32_parsed, &f, sizeof (f));
308+ CHECK (float32_parsed == 0 );
309+
310+ fesetround (FE_UPWARD);
311+ auto r1 = fast_float::from_chars (zero, zero + 1 , f);
312+ CHECK (r1.ec == std::errc ());
313+ std::cout << " FE_UPWARD parsed zero as " << fHexAndDec (f) << std::endl;
314+ CHECK (f == 0 );
315+ ::memcpy (&float32_parsed, &f, sizeof (f));
316+ std::cout << " float as uint32_t is " << iHexAndDec (float32_parsed)
317+ << std::endl;
318+ CHECK (float32_parsed == 0 );
319+
320+ fesetround (FE_TOWARDZERO);
321+ auto r2 = fast_float::from_chars (zero, zero + 1 , f);
322+ CHECK (r2.ec == std::errc ());
323+ std::cout << " FE_TOWARDZERO parsed zero as " << fHexAndDec (f) << std::endl;
324+ CHECK (f == 0 );
325+ ::memcpy (&float32_parsed, &f, sizeof (f));
326+ std::cout << " float as uint32_t is " << iHexAndDec (float32_parsed)
327+ << std::endl;
328+ CHECK (float32_parsed == 0 );
329+
330+ fesetround (FE_DOWNWARD);
331+ auto r3 = fast_float::from_chars (zero, zero + 1 , f);
332+ CHECK (r3.ec == std::errc ());
333+ std::cout << " FE_DOWNWARD parsed zero as " << fHexAndDec (f) << std::endl;
334+ CHECK (f == 0 );
335+ ::memcpy (&float32_parsed, &f, sizeof (f));
336+ std::cout << " float as uint32_t is " << iHexAndDec (float32_parsed)
337+ << std::endl;
338+ CHECK (float32_parsed == 0 );
339+
340+ fesetround (FE_TONEAREST);
341+ auto r4 = fast_float::from_chars (zero, zero + 1 , f);
342+ CHECK (r4.ec == std::errc ());
343+ std::cout << " FE_TONEAREST parsed zero as " << fHexAndDec (f) << std::endl;
344+ CHECK (f == 0 );
345+ ::memcpy (&float32_parsed, &f, sizeof (f));
346+ std::cout << " float as uint32_t is " << iHexAndDec (float32_parsed)
347+ << std::endl;
348+ CHECK (float32_parsed == 0 );
349+ }
350+
351+ TEST_CASE (" float.parse_negative_zero" ) {
352+ //
353+ // If this function fails, we may be left in a non-standard rounding state.
354+ //
355+ char const *negative_zero = " -0" ;
356+ uint32_t float32_parsed;
357+ float f = -0 .;
358+ ::memcpy (&float32_parsed, &f, sizeof (f));
359+ CHECK (float32_parsed == 0x8000'0000 );
360+
361+ fesetround (FE_UPWARD);
362+ auto r1 = fast_float::from_chars (negative_zero, negative_zero + 2 , f);
363+ CHECK (r1.ec == std::errc ());
364+ std::cout << " FE_UPWARD parsed negative zero as " << fHexAndDec (f)
365+ << std::endl;
366+ CHECK (f == 0 );
367+ ::memcpy (&float32_parsed, &f, sizeof (f));
368+ std::cout << " float as uint32_t is " << iHexAndDec (float32_parsed)
369+ << std::endl;
370+ CHECK (float32_parsed == 0x8000'0000 );
371+
372+ fesetround (FE_TOWARDZERO);
373+ auto r2 = fast_float::from_chars (negative_zero, negative_zero + 2 , f);
374+ CHECK (r2.ec == std::errc ());
375+ std::cout << " FE_TOWARDZERO parsed negative zero as " << fHexAndDec (f)
376+ << std::endl;
377+ CHECK (f == 0 );
378+ ::memcpy (&float32_parsed, &f, sizeof (f));
379+ std::cout << " float as uint32_t is " << iHexAndDec (float32_parsed)
380+ << std::endl;
381+ CHECK (float32_parsed == 0x8000'0000 );
382+
383+ fesetround (FE_DOWNWARD);
384+ auto r3 = fast_float::from_chars (negative_zero, negative_zero + 2 , f);
385+ CHECK (r3.ec == std::errc ());
386+ std::cout << " FE_DOWNWARD parsed negative zero as " << fHexAndDec (f)
387+ << std::endl;
388+ CHECK (f == 0 );
389+ ::memcpy (&float32_parsed, &f, sizeof (f));
390+ std::cout << " float as uint32_t is " << iHexAndDec (float32_parsed)
391+ << std::endl;
392+ CHECK (float32_parsed == 0x8000'0000 );
393+
394+ fesetround (FE_TONEAREST);
395+ auto r4 = fast_float::from_chars (negative_zero, negative_zero + 2 , f);
396+ CHECK (r4.ec == std::errc ());
397+ std::cout << " FE_TONEAREST parsed negative zero as " << fHexAndDec (f)
398+ << std::endl;
399+ CHECK (f == 0 );
400+ ::memcpy (&float32_parsed, &f, sizeof (f));
401+ std::cout << " float as uint32_t is " << iHexAndDec (float32_parsed)
402+ << std::endl;
403+ CHECK (float32_parsed == 0x8000'0000 );
404+ }
405+
268406#if FASTFLOAT_SUPPLEMENTAL_TESTS
269407// C++ 17 because it is otherwise annoying to browse all files in a directory.
270408// We also only run these tests on little endian systems.
0 commit comments