From 5e6d1b5dd6c1f34d8e05152a868896fc00e0e4f5 Mon Sep 17 00:00:00 2001 From: Stefano Di Martino Date: Fri, 19 Jan 2024 14:02:30 +0100 Subject: [PATCH] fix math function for percent --- include/units/core.h | 54 ++++++++++----------- unitTests/main.cpp | 110 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 133 insertions(+), 31 deletions(-) diff --git a/include/units/core.h b/include/units/core.h index c1cdaed0..c832f1d3 100644 --- a/include/units/core.h +++ b/include/units/core.h @@ -3606,7 +3606,7 @@ namespace units template, int> = 0> dimensionless> exp(const dimensionlessUnit x) noexcept { - return std::exp(x.value()); + return std::exp(x.raw()); } /** @@ -3621,7 +3621,7 @@ namespace units template, int> = 0> dimensionless> log(const dimensionlessUnit x) noexcept { - return std::log(x.value()); + return std::log(x.raw()); } /** @@ -3635,7 +3635,7 @@ namespace units template, int> = 0> dimensionless> log10(const dimensionlessUnit x) noexcept { - return std::log10(x.value()); + return std::log10(x.raw()); } /** @@ -3669,7 +3669,7 @@ namespace units template, int> = 0> dimensionless> exp2(const dimensionlessUnit x) noexcept { - return std::exp2(x.value()); + return std::exp2(x.raw()); } /** @@ -3683,7 +3683,7 @@ namespace units template, int> = 0> dimensionless> expm1(const dimensionlessUnit x) noexcept { - return std::expm1(x.value()); + return std::expm1(x.raw()); } /** @@ -3698,7 +3698,7 @@ namespace units template, int> = 0> dimensionless> log1p(const dimensionlessUnit x) noexcept { - return std::log1p(x.value()); + return std::log1p(x.raw()); } /** @@ -3712,7 +3712,7 @@ namespace units template, int> = 0> dimensionless> log2(const dimensionlessUnit x) noexcept { - return std::log2(x.value()); + return std::log2(x.raw()); } //---------------------------------- @@ -3737,7 +3737,7 @@ namespace units constexpr auto sqrt(const UnitType& value) noexcept -> unit::conversion_factor>>, detail::floating_point_promotion_t::underlying_type>, linear_scale> { - return decltype(units::sqrt(value))(sqrt(value.value())); + return decltype(units::sqrt(value))(sqrt(value.raw())); } /** @@ -3754,7 +3754,7 @@ namespace units detail::floating_point_promotion_t> hypot(const UnitTypeLhs& x, const UnitTypeRhs& y) { using CommonUnit = decltype(units::hypot(x, y)); - return CommonUnit(std::hypot(CommonUnit(x).value(), CommonUnit(y).value())); + return CommonUnit(std::hypot(CommonUnit(x).raw(), CommonUnit(y).raw())); } //---------------------------------- @@ -3771,7 +3771,7 @@ namespace units template, int> = 0> detail::floating_point_promotion_t ceil(const UnitType x) noexcept { - return detail::floating_point_promotion_t(std::ceil(x.value())); + return detail::floating_point_promotion_t(std::ceil(x.raw())); } /** @@ -3784,7 +3784,7 @@ namespace units template, int> = 0> detail::floating_point_promotion_t floor(const UnitType x) noexcept { - return detail::floating_point_promotion_t(std::floor(x.value())); + return detail::floating_point_promotion_t(std::floor(x.raw())); } /** @@ -3799,7 +3799,7 @@ namespace units detail::floating_point_promotion_t> fmod(const UnitTypeLhs numer, const UnitTypeRhs denom) noexcept { using CommonUnit = decltype(units::fmod(numer, denom)); - return CommonUnit(std::fmod(CommonUnit(numer).value(), CommonUnit(denom).value())); + return CommonUnit(std::fmod(CommonUnit(numer).raw(), CommonUnit(denom).raw())); } /** @@ -3813,7 +3813,7 @@ namespace units template, int> = 0> detail::floating_point_promotion_t trunc(const UnitType x) noexcept { - return detail::floating_point_promotion_t(std::trunc(x.value())); + return detail::floating_point_promotion_t(std::trunc(x.raw())); } /** @@ -3827,7 +3827,7 @@ namespace units template, int> = 0> detail::floating_point_promotion_t round(const UnitType x) noexcept { - return detail::floating_point_promotion_t(std::round(x.value())); + return detail::floating_point_promotion_t(std::round(x.raw())); } //---------------------------------- @@ -3846,14 +3846,14 @@ namespace units template && traits::is_unit_v, int> = 0> detail::floating_point_promotion_t copysign(const UnitTypeLhs x, const UnitTypeRhs y) noexcept { - return detail::floating_point_promotion_t(std::copysign(x.value(), y.value())); // no need for conversion to get the correct sign. + return detail::floating_point_promotion_t(std::copysign(x.raw(), y.raw())); // no need for conversion to get the correct sign. } /// Overload to copy the sign from a raw double template && traits::is_unit_v, int> = 0> detail::floating_point_promotion_t copysign(const UnitTypeLhs x, const T& y) noexcept { - return detail::floating_point_promotion_t(std::copysign(x.value(), y)); + return detail::floating_point_promotion_t(std::copysign(x.raw(), y)); } //---------------------------------- @@ -3872,7 +3872,7 @@ namespace units detail::floating_point_promotion_t> fdim(const UnitTypeLhs x, const UnitTypeRhs y) noexcept { using CommonUnit = decltype(units::fdim(x, y)); - return CommonUnit(std::fdim(CommonUnit(x).value(), CommonUnit(y).value())); + return CommonUnit(std::fdim(CommonUnit(x).raw(), CommonUnit(y).raw())); } /** @@ -3887,7 +3887,7 @@ namespace units detail::floating_point_promotion_t> fmax(const UnitTypeLhs x, const UnitTypeRhs y) noexcept { using CommonUnit = decltype(units::fmax(x, y)); - return CommonUnit(std::fmax(CommonUnit(x).value(), CommonUnit(y).value())); + return CommonUnit(std::fmax(CommonUnit(x).raw(), CommonUnit(y).raw())); } /** @@ -3903,7 +3903,7 @@ namespace units detail::floating_point_promotion_t> fmin(const UnitTypeLhs x, const UnitTypeRhs y) noexcept { using CommonUnit = decltype(units::fmin(x, y)); - return CommonUnit(std::fmin(CommonUnit(x).value(), CommonUnit(y).value())); + return CommonUnit(std::fmin(CommonUnit(x).raw(), CommonUnit(y).raw())); } //---------------------------------- @@ -3920,7 +3920,7 @@ namespace units template, int> = 0> detail::floating_point_promotion_t fabs(const UnitType x) noexcept { - return detail::floating_point_promotion_t(std::fabs(x.value())); + return detail::floating_point_promotion_t(std::fabs(x.raw())); } /** @@ -3933,7 +3933,7 @@ namespace units template, int> = 0> UnitType abs(const UnitType x) noexcept { - return UnitType(std::abs(x.value())); + return UnitType(std::abs(x.raw())); } /** @@ -3956,7 +3956,7 @@ namespace units -> std::common_type_t(x) * detail::floating_point_promotion_t(y)), UnitAdd> { using CommonUnit = decltype(units::fma(x, y, z)); - return CommonUnit(std::fma(x.value(), y.value(), CommonUnit(z).value())); + return CommonUnit(std::fma(x.raw(), y.raw(), CommonUnit(z).raw())); } //---------------------------- @@ -3966,31 +3966,31 @@ namespace units template>> inline bool isnan(const UnitType& x) noexcept { - return std::isnan(x.value()); + return std::isnan(x.raw()); } template>> inline bool isinf(const UnitType& x) noexcept { - return std::isinf(x.value()); + return std::isinf(x.raw()); } template>> inline bool isfinite(const UnitType& x) noexcept { - return std::isfinite(x.value()); + return std::isfinite(x.raw()); } template>> inline bool isnormal(const UnitType& x) noexcept { - return std::isnormal(x.value()); + return std::isnormal(x.raw()); } template>> inline bool isunordered(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept { - return std::isunordered(lhs.value(), rhs.value()); + return std::isunordered(lhs.raw(), rhs.raw()); } } // end namespace units diff --git a/unitTests/main.cpp b/unitTests/main.cpp index 8e516ecd..31d147eb 100644 --- a/unitTests/main.cpp +++ b/unitTests/main.cpp @@ -4381,6 +4381,10 @@ TEST_F(UnitMath, min) const meters d(1); const centimeters e(99); EXPECT_EQ(e, units::min(d, e)); + + const percent f(1); + const percent g(99); + EXPECT_EQ(f, units::min(f, g)); } TEST_F(UnitMath, max) @@ -4392,6 +4396,10 @@ TEST_F(UnitMath, max) meters d(1); centimeters e(101); EXPECT_EQ(e, max(d, e)); + + percent f(1); + percent g(101); + EXPECT_EQ(g, max(f, g)); } TEST_F(UnitMath, cos) @@ -4717,6 +4725,9 @@ TEST_F(UnitMath, sqrt) EXPECT_TRUE((std::is_same_v, decltype(sqrt(square_meters(4.0)))>)); EXPECT_NEAR(meters(2.0).to(), sqrt(square_meters(4.0)).to(), 5.0e-9); + EXPECT_TRUE((std::is_same_v, decltype(sqrt(percent(4.0) * percent(4.0)))>)); + EXPECT_NEAR(percent(2.0).raw(), sqrt(percent(4.0)).raw(), 5.0e-9); + EXPECT_TRUE((std::is_same_v, decltype(sqrt(steradians(16.0)))>)); EXPECT_NEAR(angle::radians(4.0).to(), sqrt(steradians(16.0)).to(), 5.0e-9); @@ -4736,6 +4747,9 @@ TEST_F(UnitMath, hypot) static_assert(traits::is_same_dimension_unit_v, decltype(hypot(feet(3.0), meters(1.2192)))>); EXPECT_NEAR(feet(5.0).to(), feet(hypot(feet(3.0), meters(1.2192))).to(), 5.0e-9); + + EXPECT_TRUE((std::is_same_v, decltype(hypot(percent(3.0), percent(4.0)))>)); + EXPECT_NEAR(percent(5.0).raw(), (hypot(percent(3.0), percent(4.0))).raw(), 5.0e-9); } TEST_F(UnitMath, ceil) @@ -4743,29 +4757,36 @@ TEST_F(UnitMath, ceil) double val = 101.1; EXPECT_EQ(ceil(val), ceil(meters(val)).to()); EXPECT_TRUE((std::is_same_v, decltype(ceil(meters(val)))>)); + + EXPECT_EQ(ceil(val), ceil(percent(val)).raw()); + EXPECT_TRUE((std::is_same_v, decltype(ceil(percent(val)))>)); } TEST_F(UnitMath, floor) { double val = 101.1; EXPECT_EQ(floor(val), floor(dimensionless(val))); + EXPECT_EQ(floor(val), floor(percent(val)).raw()); } TEST_F(UnitMath, fmod) { EXPECT_EQ(fmod(100.0, 101.2), fmod(meters(100.0), meters(101.2)).to()); + EXPECT_EQ(fmod(100.0, 101.2), fmod(percent(100.0), percent(101.2)).raw()); } TEST_F(UnitMath, trunc) { double val = 101.1; EXPECT_EQ(trunc(val), trunc(dimensionless(val))); + EXPECT_EQ(trunc(val), trunc(percent(val)).raw()); } TEST_F(UnitMath, round) { double val = 101.1; EXPECT_EQ(round(val), round(dimensionless(val))); + EXPECT_EQ(round(val), round(percent(val)).raw()); } TEST_F(UnitMath, copysign) @@ -4776,12 +4797,22 @@ TEST_F(UnitMath, copysign) EXPECT_EQ(meters(-5.0), copysign(val, angle::radians(sign))); } +TEST_F(UnitMath, copysign_percent) +{ + double sign = -1; + percent val(5.0); + EXPECT_EQ(percent(-5.0), copysign(val, sign)); +} + TEST_F(UnitMath, fdim) { EXPECT_EQ(meters(0.0), fdim(meters(8.0), meters(10.0))); EXPECT_EQ(meters(2.0), fdim(meters(10.0), meters(8.0))); EXPECT_NEAR(meters(9.3904).to(), meters(fdim(meters(10.0), feet(2.0))).to(), 5.0e-320); // not sure why they aren't comparing exactly equal, but clearly they are. + + EXPECT_EQ(percent(0.0), fdim(percent(8.0), percent(10.0))); + EXPECT_EQ(percent(2.0), fdim(percent(10.0), percent(8.0))); } TEST_F(UnitMath, fmin) @@ -4789,6 +4820,9 @@ TEST_F(UnitMath, fmin) EXPECT_EQ(meters(8.0), fmin(meters(8.0), meters(10.0))); EXPECT_EQ(meters(8.0), fmin(meters(10.0), meters(8.0))); EXPECT_EQ(feet(2.0), fmin(meters(10.0), feet(2.0))); + + EXPECT_EQ(percent(8.0), fmin(percent(8.0), percent(10.0))); + EXPECT_EQ(percent(8.0), fmin(percent(10.0), percent(8.0))); } TEST_F(UnitMath, fmax) @@ -4796,18 +4830,27 @@ TEST_F(UnitMath, fmax) EXPECT_EQ(meters(10.0), fmax(meters(8.0), meters(10.0))); EXPECT_EQ(meters(10.0), fmax(meters(10.0), meters(8.0))); EXPECT_EQ(meters(10.0), fmax(meters(10.0), feet(2.0))); + + EXPECT_EQ(percent(10.0), fmax(percent(8.0), percent(10.0))); + EXPECT_EQ(percent(10.0), fmax(percent(10.0), percent(8.0))); } TEST_F(UnitMath, fabs) { EXPECT_EQ(meters(10.0), fabs(meters(-10.0))); EXPECT_EQ(meters(10.0), fabs(meters(10.0))); + + EXPECT_EQ(percent(10.0), fabs(percent(-10.0))); + EXPECT_EQ(percent(10.0), fabs(percent(10.0))); } TEST_F(UnitMath, abs) { EXPECT_EQ(meters(10.0), abs(meters(-10.0))); EXPECT_EQ(meters(10.0), abs(meters(10.0))); + + EXPECT_EQ(percent(10.0), abs(percent(-10.0))); + EXPECT_EQ(percent(10.0), abs(percent(10.0))); } TEST_F(UnitMath, fma) @@ -4832,6 +4875,20 @@ TEST_F(UnitMath, isnan) EXPECT_TRUE(units::isnan(inf - inf)); } +TEST_F(UnitMath, isnan_percent) +{ + percent<> zero(0.0); + percent<> nan(NAN); + percent<> inf(INFINITY); + + EXPECT_TRUE(units::isnan(nan)); + EXPECT_FALSE(units::isnan(inf)); + EXPECT_FALSE(units::isnan(zero)); + EXPECT_FALSE(units::isnan(DBL_MIN / 2.0 * 1_pct)); + EXPECT_TRUE(units::isnan(zero / zero)); + EXPECT_TRUE(units::isnan(inf - inf)); +} + TEST_F(UnitMath, isinf) { meters<> zero(0.0); @@ -4840,9 +4897,19 @@ TEST_F(UnitMath, isinf) EXPECT_FALSE(units::isinf(nan)); EXPECT_TRUE(units::isinf(inf)); - EXPECT_FALSE(units::isinf(0.0_m)); - EXPECT_TRUE(units::isinf(exp(1600_rad / 2_rad))); - EXPECT_FALSE(units::isinf(DBL_MIN / 2.0 * 1_m)); + EXPECT_FALSE(units::isinf(zero)); + EXPECT_FALSE(units::isinf(DBL_MIN / 2.0 * 1_pct)); +} + +TEST_F(UnitMath, isinf_percent) +{ + percent<> zero(0.0); + percent<> nan(NAN); + percent<> inf(INFINITY); + + EXPECT_FALSE(units::isinf(nan)); + EXPECT_TRUE(units::isinf(inf)); + EXPECT_FALSE(units::isinf(zero)); } TEST_F(UnitMath, isfinite) @@ -4858,6 +4925,18 @@ TEST_F(UnitMath, isfinite) EXPECT_TRUE(units::isfinite(DBL_MIN / 2.0 * 1_m)); } +TEST_F(UnitMath, isfinite_percent) +{ + percent<> zero(0.0); + percent<> nan(NAN); + percent<> inf(INFINITY); + + EXPECT_FALSE(units::isfinite(nan)); + EXPECT_FALSE(units::isfinite(inf)); + EXPECT_FALSE(units::isfinite(zero)); + EXPECT_TRUE(units::isfinite(DBL_MIN / 2.0 * 1_pct)); +} + TEST_F(UnitMath, isnormal) { meters<> zero(0.0); @@ -4870,6 +4949,18 @@ TEST_F(UnitMath, isnormal) EXPECT_TRUE(units::isnormal(1.0_m)); } +TEST_F(UnitMath, isnormal_percent) +{ + percent<> zero(0.0); + percent<> nan(NAN); + percent<> inf(INFINITY); + + EXPECT_FALSE(units::isnormal(nan)); + EXPECT_FALSE(units::isnormal(inf)); + EXPECT_FALSE(units::isnormal(zero)); + EXPECT_TRUE(units::isnormal(1.0_pct)); +} + TEST_F(UnitMath, isunordered) { meters<> zero(0.0); @@ -4881,6 +4972,17 @@ TEST_F(UnitMath, isunordered) EXPECT_FALSE(units::isunordered(zero, zero)); } +TEST_F(UnitMath, isunordered_percent) +{ + percent<> zero(0.0); + percent<> nan(NAN); + percent<> inf(INFINITY); + + EXPECT_TRUE(units::isunordered(nan, zero)); + EXPECT_TRUE(units::isunordered(zero, nan)); + EXPECT_FALSE(units::isunordered(zero, zero)); +} + // Constexpr TEST_F(Constexpr, construction) { @@ -5090,4 +5192,4 @@ int main(int argc, char* argv[]) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} \ No newline at end of file +}