@@ -759,6 +759,66 @@ TEST(Numeric_decimal, to_double_negative_infinity) {
759759 EXPECT_LT (result, 0.0 );
760760}
761761
762+ TEST (Numeric_decimal, to_float_not_exactly_representable_gets_rounded) {
763+ const sourcemeta::core::Decimal value{" 3.2" };
764+ EXPECT_FALSE (value.is_float ());
765+ const float result{value.to_float ()};
766+ EXPECT_FLOAT_EQ (result, 3 .2f );
767+ }
768+
769+ TEST (Numeric_decimal, to_double_not_exactly_representable_gets_rounded) {
770+ const sourcemeta::core::Decimal value{" 3.2" };
771+ EXPECT_FALSE (value.is_double ());
772+ const double result{value.to_double ()};
773+ EXPECT_DOUBLE_EQ (result, 3.2 );
774+ }
775+
776+ TEST (Numeric_decimal, to_float_exceeds_max_float_throws) {
777+ const sourcemeta::core::Decimal value{" 1e100" };
778+ EXPECT_FALSE (value.is_float ());
779+ EXPECT_THROW (
780+ { [[maybe_unused]] const float result = value.to_float (); },
781+ std::out_of_range);
782+ }
783+
784+ TEST (Numeric_decimal, to_double_exceeds_max_double_throws) {
785+ const sourcemeta::core::Decimal value{" 1e500" };
786+ EXPECT_FALSE (value.is_double ());
787+ EXPECT_THROW (
788+ { [[maybe_unused]] const double result = value.to_double (); },
789+ std::out_of_range);
790+ }
791+
792+ TEST (Numeric_decimal, to_float_below_min_float_throws) {
793+ const sourcemeta::core::Decimal value{" 1e-100" };
794+ EXPECT_FALSE (value.is_float ());
795+ EXPECT_THROW (
796+ { [[maybe_unused]] const float result = value.to_float (); },
797+ std::out_of_range);
798+ }
799+
800+ TEST (Numeric_decimal, to_double_below_min_double_throws) {
801+ const sourcemeta::core::Decimal value{" 1e-500" };
802+ EXPECT_FALSE (value.is_double ());
803+ EXPECT_THROW (
804+ { [[maybe_unused]] const double result = value.to_double (); },
805+ std::out_of_range);
806+ }
807+
808+ TEST (Numeric_decimal, to_float_high_precision_gets_rounded) {
809+ const sourcemeta::core::Decimal value{" 1.23456789" };
810+ EXPECT_FALSE (value.is_float ());
811+ const float result{value.to_float ()};
812+ EXPECT_FLOAT_EQ (result, 1 .23456789f );
813+ }
814+
815+ TEST (Numeric_decimal, to_double_high_precision_gets_rounded) {
816+ const sourcemeta::core::Decimal value{" 1.234567890123456789" };
817+ EXPECT_FALSE (value.is_double ());
818+ const double result{value.to_double ()};
819+ EXPECT_DOUBLE_EQ (result, 1.234567890123456789 );
820+ }
821+
762822TEST (Numeric_decimal, divisible_by_integer_true) {
763823 const sourcemeta::core::Decimal dividend{10 };
764824 const sourcemeta::core::Decimal divisor{5 };
@@ -1222,6 +1282,7 @@ TEST(Numeric_decimal, is_uint64_false_too_large) {
12221282 const sourcemeta::core::Decimal value{" 18446744073709551616" };
12231283 EXPECT_FALSE (value.is_uint64 ());
12241284}
1285+
12251286TEST (Numeric_decimal, exception_conversion_syntax_invalid_string) {
12261287 EXPECT_THROW (
12271288 { const sourcemeta::core::Decimal value{" not_a_number" }; },
@@ -1455,3 +1516,105 @@ TEST(Numeric_decimal, negative_zero_preserves_sign) {
14551516 EXPECT_TRUE (copy.is_signed ());
14561517 EXPECT_TRUE (copy.is_zero ());
14571518}
1519+
1520+ TEST (Numeric_decimal, construct_from_float_simple) {
1521+ const float value{3 .5f };
1522+ const sourcemeta::core::Decimal decimal{value};
1523+ EXPECT_TRUE (decimal.is_float ());
1524+ EXPECT_TRUE (decimal.is_double ());
1525+ EXPECT_EQ (decimal.to_float (), 3 .5f );
1526+ EXPECT_EQ (decimal.to_double (), 3.5 );
1527+ EXPECT_EQ (decimal.to_string (), " 3.5" );
1528+ }
1529+
1530+ TEST (Numeric_decimal, construct_from_float_negative) {
1531+ const float value{-7 .25f };
1532+ const sourcemeta::core::Decimal decimal{value};
1533+ EXPECT_TRUE (decimal.is_float ());
1534+ EXPECT_TRUE (decimal.is_double ());
1535+ EXPECT_EQ (decimal.to_float (), -7 .25f );
1536+ EXPECT_EQ (decimal.to_double (), -7.25 );
1537+ EXPECT_EQ (decimal.to_string (), " -7.25" );
1538+ }
1539+
1540+ TEST (Numeric_decimal, construct_from_float_zero) {
1541+ const float value{0 .0f };
1542+ const sourcemeta::core::Decimal decimal{value};
1543+ EXPECT_TRUE (decimal.is_float ());
1544+ EXPECT_TRUE (decimal.is_double ());
1545+ EXPECT_TRUE (decimal.is_zero ());
1546+ EXPECT_EQ (decimal.to_float (), 0 .0f );
1547+ EXPECT_EQ (decimal.to_double (), 0.0 );
1548+ }
1549+
1550+ TEST (Numeric_decimal, construct_from_float_very_small) {
1551+ const float value{0 .125f };
1552+ const sourcemeta::core::Decimal decimal{value};
1553+ EXPECT_TRUE (decimal.is_float ());
1554+ EXPECT_TRUE (decimal.is_double ());
1555+ EXPECT_EQ (decimal.to_float (), 0 .125f );
1556+ EXPECT_EQ (decimal.to_double (), 0.125 );
1557+ EXPECT_EQ (decimal.to_string (), " 0.125" );
1558+ }
1559+
1560+ TEST (Numeric_decimal, construct_from_double_simple) {
1561+ const double value{3.5 };
1562+ const sourcemeta::core::Decimal decimal{value};
1563+ EXPECT_TRUE (decimal.is_double ());
1564+ EXPECT_EQ (decimal.to_double (), 3.5 );
1565+ EXPECT_EQ (decimal.to_string (), " 3.5" );
1566+ }
1567+
1568+ TEST (Numeric_decimal, construct_from_double_negative) {
1569+ const double value{-7.25 };
1570+ const sourcemeta::core::Decimal decimal{value};
1571+ EXPECT_TRUE (decimal.is_double ());
1572+ EXPECT_EQ (decimal.to_double (), -7.25 );
1573+ EXPECT_EQ (decimal.to_string (), " -7.25" );
1574+ }
1575+
1576+ TEST (Numeric_decimal, construct_from_double_zero) {
1577+ const double value{0.0 };
1578+ const sourcemeta::core::Decimal decimal{value};
1579+ EXPECT_TRUE (decimal.is_double ());
1580+ EXPECT_TRUE (decimal.is_zero ());
1581+ EXPECT_EQ (decimal.to_double (), 0.0 );
1582+ }
1583+
1584+ TEST (Numeric_decimal, construct_from_double_very_small) {
1585+ const double value{0.125 };
1586+ const sourcemeta::core::Decimal decimal{value};
1587+ EXPECT_TRUE (decimal.is_double ());
1588+ EXPECT_EQ (decimal.to_double (), 0.125 );
1589+ EXPECT_EQ (decimal.to_string (), " 0.125" );
1590+ }
1591+
1592+ TEST (Numeric_decimal, construct_from_double_roundtrip) {
1593+ const double value{3.2 };
1594+ const sourcemeta::core::Decimal decimal{value};
1595+ EXPECT_TRUE (decimal.is_double ());
1596+ const double roundtrip{decimal.to_double ()};
1597+ EXPECT_EQ (roundtrip, value);
1598+ }
1599+
1600+ TEST (Numeric_decimal, construct_from_float_roundtrip) {
1601+ const float value{3 .2f };
1602+ const sourcemeta::core::Decimal decimal{value};
1603+ EXPECT_TRUE (decimal.is_float ());
1604+ const float roundtrip{decimal.to_float ()};
1605+ EXPECT_EQ (roundtrip, value);
1606+ }
1607+
1608+ TEST (Numeric_decimal, construct_from_double_high_precision) {
1609+ const double value{1.234567890123456 };
1610+ const sourcemeta::core::Decimal decimal{value};
1611+ const double roundtrip{decimal.to_double ()};
1612+ EXPECT_EQ (roundtrip, value);
1613+ }
1614+
1615+ TEST (Numeric_decimal, construct_from_float_high_precision) {
1616+ const float value{1 .234567f };
1617+ const sourcemeta::core::Decimal decimal{value};
1618+ const float roundtrip{decimal.to_float ()};
1619+ EXPECT_EQ (roundtrip, value);
1620+ }
0 commit comments