diff --git a/CHANGELOG.md b/CHANGELOG.md index f0375ffad..092d49497 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - feat: `quantity_point` support added for `quantity_cast` and `value_cast` - feat: `value_cast` added - (!) refactor: `zero_Fahrenheit` renamed to `zeroth_degree_Fahrenheit` +- (!) refactor: SI-related trigonometric functions moved to the `si` subnamespace - refactor: `math.h` header file broke up to smaller pieces - refactor: math functions constraints refactored - fix: `QuantityLike` conversions required `Q::rep` instead of using one provided by `quantity_like_traits` diff --git a/example/glide_computer.cpp b/example/glide_computer.cpp index c15309b9c..09531727b 100644 --- a/example/glide_computer.cpp +++ b/example/glide_computer.cpp @@ -88,7 +88,7 @@ void print(const R& gliders) ratio, // TODO is it possible to make ADL work below (we need another set of trig // functions for strong angle in a different namespace) - isq::asin(1 / ratio).force_in(si::degree)); + si::asin(1 / ratio).force_in(si::degree)); } std::cout << "\n"; } diff --git a/example/include/geographic.h b/example/include/geographic.h index 0ccda628d..2ebd77673 100644 --- a/example/include/geographic.h +++ b/example/include/geographic.h @@ -176,7 +176,7 @@ distance spherical_distance(position from, position to) using namespace mp_units; constexpr quantity earth_radius = 6'371 * isq::radius[si::kilo]; - using isq::sin, isq::cos, isq::asin, isq::acos; + using si::sin, si::cos, si::asin, si::acos; const quantity from_lat = from.lat.quantity_from(equator); const quantity from_lon = from.lon.quantity_from(prime_meridian); diff --git a/src/utility/include/mp-units/bits/math_si.h b/src/utility/include/mp-units/bits/math_si.h index 3421627a3..a2f5971f2 100644 --- a/src/utility/include/mp-units/bits/math_si.h +++ b/src/utility/include/mp-units/bits/math_si.h @@ -36,46 +36,46 @@ namespace mp_units::si { -template auto R, typename Rep> +template auto R, typename Rep> requires requires(Rep v) { sin(v); } || requires(Rep v) { std::sin(v); } [[nodiscard]] inline QuantityOf auto sin(const quantity& q) noexcept { using std::sin; if constexpr (!treat_as_floating_point) { // check what is the return type when called with the integral value - using rep = decltype(sin(q.force_numerical_value_in(si::radian))); + using rep = decltype(sin(q.force_numerical_value_in(radian))); // use this type ahead of calling the function to prevent narrowing if a unit conversion is needed - return quantity{sin(value_cast(q).numerical_value_in(si::radian)), one}; + return quantity{sin(value_cast(q).numerical_value_in(radian)), one}; } else - return quantity{sin(q.numerical_value_in(si::radian)), one}; + return quantity{sin(q.numerical_value_in(radian)), one}; } -template auto R, typename Rep> +template auto R, typename Rep> requires requires(Rep v) { cos(v); } || requires(Rep v) { std::cos(v); } [[nodiscard]] inline QuantityOf auto cos(const quantity& q) noexcept { using std::cos; if constexpr (!treat_as_floating_point) { // check what is the return type when called with the integral value - using rep = decltype(cos(q.force_numerical_value_in(si::radian))); + using rep = decltype(cos(q.force_numerical_value_in(radian))); // use this type ahead of calling the function to prevent narrowing if a unit conversion is needed - return quantity{cos(value_cast(q).numerical_value_in(si::radian)), one}; + return quantity{cos(value_cast(q).numerical_value_in(radian)), one}; } else - return quantity{cos(q.numerical_value_in(si::radian)), one}; + return quantity{cos(q.numerical_value_in(radian)), one}; } -template auto R, typename Rep> +template auto R, typename Rep> requires requires(Rep v) { tan(v); } || requires(Rep v) { std::tan(v); } [[nodiscard]] inline QuantityOf auto tan(const quantity& q) noexcept { using std::tan; if constexpr (!treat_as_floating_point) { // check what is the return type when called with the integral value - using rep = decltype(tan(q.force_numerical_value_in(si::radian))); + using rep = decltype(tan(q.force_numerical_value_in(radian))); // use this type ahead of calling the function to prevent narrowing if a unit conversion is needed - return quantity{tan(value_cast(q).numerical_value_in(si::radian)), one}; + return quantity{tan(value_cast(q).numerical_value_in(radian)), one}; } else - return quantity{tan(q.numerical_value_in(si::radian)), one}; + return quantity{tan(q.numerical_value_in(radian)), one}; } template auto R, typename Rep> @@ -87,9 +87,9 @@ template auto R, typename Rep> // check what is the return type when called with the integral value using rep = decltype(asin(q.force_numerical_value_in(one))); // use this type ahead of calling the function to prevent narrowing if a unit conversion is needed - return quantity{asin(value_cast(q).numerical_value_in(one)), si::radian}; + return quantity{asin(value_cast(q).numerical_value_in(one)), radian}; } else - return quantity{asin(q.numerical_value_in(one)), si::radian}; + return quantity{asin(q.numerical_value_in(one)), radian}; } template auto R, typename Rep> @@ -101,9 +101,9 @@ template auto R, typename Rep> // check what is the return type when called with the integral value using rep = decltype(acos(q.force_numerical_value_in(one))); // use this type ahead of calling the function to prevent narrowing if a unit conversion is needed - return quantity{acos(value_cast(q).numerical_value_in(one)), si::radian}; + return quantity{acos(value_cast(q).numerical_value_in(one)), radian}; } else - return quantity{acos(q.numerical_value_in(one)), si::radian}; + return quantity{acos(q.numerical_value_in(one)), radian}; } template auto R, typename Rep> @@ -115,9 +115,9 @@ template auto R, typename Rep> // check what is the return type when called with the integral value using rep = decltype(atan(q.force_numerical_value_in(one))); // use this type ahead of calling the function to prevent narrowing if a unit conversion is needed - return quantity{atan(value_cast(q).numerical_value_in(one)), si::radian}; + return quantity{atan(value_cast(q).numerical_value_in(one)), radian}; } else - return quantity{atan(q.numerical_value_in(one)), si::radian}; + return quantity{atan(q.numerical_value_in(one)), radian}; } } // namespace mp_units::si diff --git a/test/unit_test/runtime/math_test.cpp b/test/unit_test/runtime/math_test.cpp index f03dc85c4..47e78d74b 100644 --- a/test/unit_test/runtime/math_test.cpp +++ b/test/unit_test/runtime/math_test.cpp @@ -321,54 +321,54 @@ TEST_CASE("hypot functions", "[hypot]") } } -TEST_CASE("ISQ trigonometric functions", "[trig][isq]") +TEST_CASE("SI trigonometric functions", "[trig][si]") { SECTION("sin") { - REQUIRE_THAT(isq::sin(0 * deg), AlmostEquals(0. * one)); - REQUIRE_THAT(isq::sin(90 * deg), AlmostEquals(1. * one)); - REQUIRE_THAT(isq::sin(180 * deg), AlmostEquals(0. * one)); - REQUIRE_THAT(isq::sin(270 * deg), AlmostEquals(-1. * one)); + REQUIRE_THAT(si::sin(0 * deg), AlmostEquals(0. * one)); + REQUIRE_THAT(si::sin(90 * deg), AlmostEquals(1. * one)); + REQUIRE_THAT(si::sin(180 * deg), AlmostEquals(0. * one)); + REQUIRE_THAT(si::sin(270 * deg), AlmostEquals(-1. * one)); } SECTION("cos") { - REQUIRE_THAT(isq::cos(0 * deg), AlmostEquals(1. * one)); - REQUIRE_THAT(isq::cos(90 * deg), AlmostEquals(0. * one)); - REQUIRE_THAT(isq::cos(180 * deg), AlmostEquals(-1. * one)); - REQUIRE_THAT(isq::cos(270 * deg), AlmostEquals(0. * one)); + REQUIRE_THAT(si::cos(0 * deg), AlmostEquals(1. * one)); + REQUIRE_THAT(si::cos(90 * deg), AlmostEquals(0. * one)); + REQUIRE_THAT(si::cos(180 * deg), AlmostEquals(-1. * one)); + REQUIRE_THAT(si::cos(270 * deg), AlmostEquals(0. * one)); } SECTION("tan") { - REQUIRE_THAT(isq::tan(0 * deg), AlmostEquals(0. * one)); - REQUIRE_THAT(isq::tan(45. * deg), AlmostEquals(1. * one)); - REQUIRE_THAT(isq::tan(135. * deg), AlmostEquals(-1. * one)); - REQUIRE_THAT(isq::tan(180. * deg), AlmostEquals(0. * one)); + REQUIRE_THAT(si::tan(0 * deg), AlmostEquals(0. * one)); + REQUIRE_THAT(si::tan(45. * deg), AlmostEquals(1. * one)); + REQUIRE_THAT(si::tan(135. * deg), AlmostEquals(-1. * one)); + REQUIRE_THAT(si::tan(180. * deg), AlmostEquals(0. * one)); } } -TEST_CASE("ISQ inverse trigonometric functions", "[inv trig][isq]") +TEST_CASE("SI inverse trigonometric functions", "[inv trig][si]") { SECTION("asin") { - REQUIRE_THAT(isq::asin(-1 * one), AlmostEquals(-90. * deg)); - REQUIRE_THAT(isq::asin(0 * one), AlmostEquals(0. * deg)); - REQUIRE_THAT(isq::asin(1 * one), AlmostEquals(90. * deg)); + REQUIRE_THAT(si::asin(-1 * one), AlmostEquals(-90. * deg)); + REQUIRE_THAT(si::asin(0 * one), AlmostEquals(0. * deg)); + REQUIRE_THAT(si::asin(1 * one), AlmostEquals(90. * deg)); } SECTION("acos") { - REQUIRE_THAT(isq::asin(-1 * one), AlmostEquals(-90. * deg)); - REQUIRE_THAT(isq::asin(0 * one), AlmostEquals(0. * deg)); - REQUIRE_THAT(isq::asin(1 * one), AlmostEquals(90. * deg)); + REQUIRE_THAT(si::asin(-1 * one), AlmostEquals(-90. * deg)); + REQUIRE_THAT(si::asin(0 * one), AlmostEquals(0. * deg)); + REQUIRE_THAT(si::asin(1 * one), AlmostEquals(90. * deg)); } SECTION("atan") { - REQUIRE_THAT(isq::atan(-1 * one), AlmostEquals(-45. * deg)); - REQUIRE_THAT(isq::atan(0 * one), AlmostEquals(0. * deg)); - REQUIRE_THAT(isq::atan(1 * one), AlmostEquals(45. * deg)); + REQUIRE_THAT(si::atan(-1 * one), AlmostEquals(-45. * deg)); + REQUIRE_THAT(si::atan(0 * one), AlmostEquals(0. * deg)); + REQUIRE_THAT(si::atan(1 * one), AlmostEquals(45. * deg)); } }