@@ -16,6 +16,8 @@ limitations under the License.
1616#include " tsl/platform/numbers.h"
1717
1818#include < cmath>
19+ #include < cstdlib>
20+ #include < limits>
1921#include < string>
2022
2123#include " absl/strings/str_cat.h"
@@ -381,5 +383,149 @@ TEST(safe_strtod, Double) {
381383 EXPECT_TRUE (std::isnan (result));
382384}
383385
386+ std::string DoubleToString (double d) {
387+ return absl::StrCat (strings::LegacyPrecision (d));
388+ }
389+
390+ TEST (LegacyPrecision, SimpleDoubleToString) {
391+ // Make sure that nice, round decimal numbers are printed using few digits,
392+ // even if they can't be represented exactly in binary.
393+ EXPECT_EQ (" 0" , DoubleToString (0.0 ));
394+ EXPECT_EQ (" 1" , DoubleToString (1.0 ));
395+ EXPECT_EQ (" -1" , DoubleToString (-1.0 ));
396+ EXPECT_EQ (" 0.2" , DoubleToString (0.2 ));
397+ EXPECT_EQ (" 1.1" , DoubleToString (1.1 ));
398+ EXPECT_EQ (" 1e+23" , DoubleToString (1e23 ));
399+ EXPECT_EQ (" 47.8" , DoubleToString (47.8 ));
400+ EXPECT_EQ (" 1000.2" , DoubleToString (1000.2 ));
401+ }
402+
403+ void TestDoubleRoundTrip (double value) {
404+ std::string str = DoubleToString (value);
405+ double rt = std::strtod (str.c_str (), nullptr );
406+ if (std::isnan (value)) {
407+ EXPECT_TRUE (std::isnan (rt));
408+ } else {
409+ EXPECT_EQ (value, rt);
410+ }
411+ }
412+
413+ TEST (LegacyPrecision, DoubleRoundTrip) {
414+ // Make sure round-trips with strtod() work. Note that even though we're
415+ // dealing with floating points, we expect the results to be *exactly*
416+ // equal, not approximately.
417+ TestDoubleRoundTrip (1.2345678901234567 );
418+ TestDoubleRoundTrip (1.2345678901234565 );
419+ TestDoubleRoundTrip (1.2345678901234569 );
420+ TestDoubleRoundTrip (47.800000000000001 );
421+ TestDoubleRoundTrip (0.10000000000000005 );
422+ TestDoubleRoundTrip (0.010000000000000005 );
423+ TestDoubleRoundTrip (0.000000010000000000000005 );
424+ TestDoubleRoundTrip (1.0000000000000005 );
425+ TestDoubleRoundTrip (10.000000000000005 );
426+ TestDoubleRoundTrip (100.00000000000005 );
427+ TestDoubleRoundTrip (1000.0000000000005 );
428+ TestDoubleRoundTrip (100000000000000.05 );
429+
430+ // IEEE-754 double finite values furthest from zero.
431+ TestDoubleRoundTrip (1.7976931348623157e308 );
432+ TestDoubleRoundTrip (-1.7976931348623157e308 );
433+
434+ // IEEE-754 double normalized values closest to zero.
435+ TestDoubleRoundTrip (2.225073858507202e-308 );
436+ TestDoubleRoundTrip (-2.225073858507202e-308 );
437+
438+ // IEEE-754 double denormalized values closest to zero.
439+ TestDoubleRoundTrip (5e-324 );
440+ TestDoubleRoundTrip (-5e-324 );
441+
442+ // Biggest and lowest valid numbers.
443+ TestDoubleRoundTrip (std::numeric_limits<double >::max ());
444+ TestDoubleRoundTrip (std::numeric_limits<double >::lowest ());
445+
446+ // Infinity and NaN.
447+ TestDoubleRoundTrip (std::numeric_limits<double >::infinity ());
448+ TestDoubleRoundTrip (-std::numeric_limits<double >::infinity ());
449+ TestDoubleRoundTrip (std::numeric_limits<double >::quiet_NaN ());
450+ }
451+
452+ std::string FloatToString (float f) {
453+ return absl::StrCat (strings::LegacyPrecision (f));
454+ }
455+
456+ TEST (LegacyPrecision, SimpleFloatToString) {
457+ // Make sure that nice, round decimal numbers are printed using few digits,
458+ // even if they can't be represented exactly in binary.
459+ EXPECT_EQ (" 0" , FloatToString (0 .0f ));
460+ EXPECT_EQ (" -0" , FloatToString (-0 .0f ));
461+ EXPECT_EQ (" 1" , FloatToString (1 .0f ));
462+ EXPECT_EQ (" -1" , FloatToString (-1 .0f ));
463+ EXPECT_EQ (" 0.2" , FloatToString (0 .2f ));
464+ EXPECT_EQ (" 1.1" , FloatToString (1 .1f ));
465+ EXPECT_EQ (" 1e+23" , FloatToString (1e23f));
466+ EXPECT_EQ (" 47.8" , FloatToString (47 .8f ));
467+ EXPECT_EQ (" 1000.2" , FloatToString (1000 .2f ));
468+ EXPECT_EQ (" 1.17549435e-38" , FloatToString (1 .17549435e-38f ));
469+ }
470+
471+ void TestFloatRoundTrip (float value) {
472+ std::string str = FloatToString (value);
473+ float rt = std::strtof (str.c_str (), nullptr );
474+ if (std::isnan (value)) {
475+ EXPECT_TRUE (std::isnan (rt));
476+ } else {
477+ EXPECT_EQ (value, rt);
478+ }
479+ }
480+
481+ TEST (LegacyPrecision, FloatRoundTrip) {
482+ // Make sure round-trips with strtod() work. Note that even though we're
483+ // dealing with floating points, we expect the results to be *exactly*
484+ // equal, not approximately.
485+ FloatToString (1.2345678901234567 );
486+ FloatToString (1.2345678901234565 );
487+ FloatToString (1.2345678901234569 );
488+ FloatToString (47.800005 );
489+ FloatToString (0.10000005 );
490+ FloatToString (0.010000005 );
491+ FloatToString (0.000000010000005 );
492+ FloatToString (1.0000005 );
493+ FloatToString (10.000005 );
494+ FloatToString (100.00005 );
495+ FloatToString (1000.0005 );
496+ FloatToString (100000.05 );
497+ FloatToString (10.0000095 );
498+ FloatToString (10.0000100 );
499+ FloatToString (10.0000105 );
500+ FloatToString (10.0000110 );
501+ FloatToString (10.0000115 );
502+
503+ // IEEE-754 float finite values furthest from zero.
504+ FloatToString (+3 .4028234e38f);
505+ FloatToString (-3 .4028234e38f);
506+
507+ // IEEE-754 float normalized values closest to zero.
508+ FloatToString (+1.175494351e-38 );
509+ FloatToString (-1.175494351e-38 );
510+
511+ // IEEE-754 double denormalized values closest to zero.
512+ FloatToString (+1.4e-45 );
513+ FloatToString (-1.4e-45 );
514+
515+ // Biggest and lowest valid numbers.
516+ FloatToString (std::numeric_limits<float >::max ());
517+ FloatToString (std::numeric_limits<float >::lowest ());
518+
519+ // Infinity and NaN.
520+ FloatToString (std::numeric_limits<float >::infinity ());
521+ FloatToString (-std::numeric_limits<float >::infinity ());
522+ FloatToString (std::numeric_limits<float >::quiet_NaN ());
523+ }
524+
525+ TEST (LegacyPrecision, NoOpTypes) {
526+ EXPECT_EQ (absl::StrCat (strings::LegacyPrecision (1 )), " 1" );
527+ EXPECT_EQ (absl::StrCat (strings::LegacyPrecision (" foo" )), " foo" );
528+ }
529+
384530} // namespace strings
385531} // namespace tsl
0 commit comments