Skip to content

Commit

Permalink
Fix math function for percent
Browse files Browse the repository at this point in the history
  • Loading branch information
Stefano Di Martino committed Jan 19, 2024
1 parent da6dd91 commit 3ccfe92
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 14 deletions.
26 changes: 13 additions & 13 deletions include/units/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -3737,7 +3737,7 @@ namespace units
constexpr auto sqrt(const UnitType& value) noexcept -> unit<traits::strong_t<square_root<typename units::traits::unit_traits<UnitType>::conversion_factor>>,
detail::floating_point_promotion_t<typename units::traits::unit_traits<UnitType>::underlying_type>, linear_scale>
{
return decltype(units::sqrt(value))(sqrt(value.value()));
return decltype(units::sqrt(value))(sqrt(value.raw()));
}

/**
Expand Down Expand Up @@ -3771,7 +3771,7 @@ namespace units
template<class UnitType, std::enable_if_t<traits::is_unit_v<UnitType>, int> = 0>
detail::floating_point_promotion_t<UnitType> ceil(const UnitType x) noexcept
{
return detail::floating_point_promotion_t<UnitType>(std::ceil(x.value()));
return detail::floating_point_promotion_t<UnitType>(std::ceil(x.raw()));
}

/**
Expand All @@ -3784,7 +3784,7 @@ namespace units
template<class UnitType, std::enable_if_t<traits::is_unit_v<UnitType>, int> = 0>
detail::floating_point_promotion_t<UnitType> floor(const UnitType x) noexcept
{
return detail::floating_point_promotion_t<UnitType>(std::floor(x.value()));
return detail::floating_point_promotion_t<UnitType>(std::floor(x.raw()));
}

/**
Expand Down Expand Up @@ -3813,7 +3813,7 @@ namespace units
template<class UnitType, std::enable_if_t<traits::is_unit_v<UnitType>, int> = 0>
detail::floating_point_promotion_t<UnitType> trunc(const UnitType x) noexcept
{
return detail::floating_point_promotion_t<UnitType>(std::trunc(x.value()));
return detail::floating_point_promotion_t<UnitType>(std::trunc(x.raw()));
}

/**
Expand All @@ -3827,7 +3827,7 @@ namespace units
template<class UnitType, std::enable_if_t<traits::is_unit_v<UnitType>, int> = 0>
detail::floating_point_promotion_t<UnitType> round(const UnitType x) noexcept
{
return detail::floating_point_promotion_t<UnitType>(std::round(x.value()));
return detail::floating_point_promotion_t<UnitType>(std::round(x.raw()));
}

//----------------------------------
Expand All @@ -3846,14 +3846,14 @@ namespace units
template<class UnitTypeLhs, class UnitTypeRhs, std::enable_if_t<traits::is_unit_v<UnitTypeLhs> && traits::is_unit_v<UnitTypeRhs>, int> = 0>
detail::floating_point_promotion_t<UnitTypeLhs> copysign(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
{
return detail::floating_point_promotion_t<UnitTypeLhs>(std::copysign(x.value(), y.value())); // no need for conversion to get the correct sign.
return detail::floating_point_promotion_t<UnitTypeLhs>(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<class UnitTypeLhs, typename T, std::enable_if_t<std::is_arithmetic_v<T> && traits::is_unit_v<UnitTypeLhs>, int> = 0>
detail::floating_point_promotion_t<UnitTypeLhs> copysign(const UnitTypeLhs x, const T& y) noexcept
{
return detail::floating_point_promotion_t<UnitTypeLhs>(std::copysign(x.value(), y));
return detail::floating_point_promotion_t<UnitTypeLhs>(std::copysign(x.raw(), y));
}

//----------------------------------
Expand All @@ -3872,7 +3872,7 @@ namespace units
detail::floating_point_promotion_t<std::common_type_t<UnitTypeLhs, UnitTypeRhs>> 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()));
}

/**
Expand All @@ -3887,7 +3887,7 @@ namespace units
detail::floating_point_promotion_t<std::common_type_t<UnitTypeLhs, UnitTypeRhs>> 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()));
}

/**
Expand All @@ -3903,7 +3903,7 @@ namespace units
detail::floating_point_promotion_t<std::common_type_t<UnitTypeLhs, UnitTypeRhs>> 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()));
}

//----------------------------------
Expand All @@ -3920,7 +3920,7 @@ namespace units
template<class UnitType, std::enable_if_t<traits::is_unit_v<UnitType>, int> = 0>
detail::floating_point_promotion_t<UnitType> fabs(const UnitType x) noexcept
{
return detail::floating_point_promotion_t<UnitType>(std::fabs(x.value()));
return detail::floating_point_promotion_t<UnitType>(std::fabs(x.raw()));
}

/**
Expand All @@ -3933,7 +3933,7 @@ namespace units
template<class UnitType, std::enable_if_t<traits::is_unit_v<UnitType>, int> = 0>
UnitType abs(const UnitType x) noexcept
{
return UnitType(std::abs(x.value()));
return UnitType(std::abs(x.raw()));
}

/**
Expand Down Expand Up @@ -4058,4 +4058,4 @@ namespace units
#endif
#endif

#endif // units_core_h__
#endif // units_core_h__
101 changes: 100 additions & 1 deletion unitTests/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4381,6 +4381,10 @@ TEST_F(UnitMath, min)
const meters<int> d(1);
const centimeters<int> e(99);
EXPECT_EQ(e, units::min(d, e));

const percent<int> f(1);
const percent<int> g(99);
EXPECT_EQ(f, units::min(f, g));
}

TEST_F(UnitMath, max)
Expand All @@ -4392,6 +4396,10 @@ TEST_F(UnitMath, max)
meters<int> d(1);
centimeters<int> e(101);
EXPECT_EQ(e, max(d, e));

percent<int> f(1);
percent<int> g(101);
EXPECT_EQ(g, max(f, g));
}

TEST_F(UnitMath, cos)
Expand Down Expand Up @@ -4717,6 +4725,9 @@ TEST_F(UnitMath, sqrt)
EXPECT_TRUE((std::is_same_v<meters<double>, decltype(sqrt(square_meters<double>(4.0)))>));
EXPECT_NEAR(meters<double>(2.0).to<double>(), sqrt(square_meters<double>(4.0)).to<double>(), 5.0e-9);

EXPECT_TRUE((std::is_same_v<percent<double>, decltype(sqrt(percent<double>(4.0) * percent<double>(4.0)))>));
EXPECT_NEAR(percent<double>(2.0).raw(), sqrt(percent<double>(4.0)).raw(), 5.0e-9);

EXPECT_TRUE((std::is_same_v<angle::radians<double>, decltype(sqrt(steradians<double>(16.0)))>));
EXPECT_NEAR(angle::radians<double>(4.0).to<double>(), sqrt(steradians<double>(16.0)).to<double>(), 5.0e-9);

Expand All @@ -4743,12 +4754,16 @@ TEST_F(UnitMath, ceil)
double val = 101.1;
EXPECT_EQ(ceil(val), ceil(meters<double>(val)).to<double>());
EXPECT_TRUE((std::is_same_v<meters<double>, decltype(ceil(meters<double>(val)))>));

EXPECT_EQ(ceil(val), ceil(percent<double>(val)).raw());
EXPECT_TRUE((std::is_same_v<percent<double>, decltype(ceil(percent<double>(val)))>));
}

TEST_F(UnitMath, floor)
{
double val = 101.1;
EXPECT_EQ(floor(val), floor(dimensionless<double>(val)));
EXPECT_EQ(floor(val), floor(percent<double>(val)).raw());
}

TEST_F(UnitMath, fmod)
Expand All @@ -4760,12 +4775,14 @@ TEST_F(UnitMath, trunc)
{
double val = 101.1;
EXPECT_EQ(trunc(val), trunc(dimensionless<double>(val)));
EXPECT_EQ(trunc(val), trunc(percent<double>(val)).raw());
}

TEST_F(UnitMath, round)
{
double val = 101.1;
EXPECT_EQ(round(val), round(dimensionless<double>(val)));
EXPECT_EQ(round(val), round(percent<double>(val)).raw());
}

TEST_F(UnitMath, copysign)
Expand All @@ -4776,38 +4793,60 @@ TEST_F(UnitMath, copysign)
EXPECT_EQ(meters<double>(-5.0), copysign(val, angle::radians<double>(sign)));
}

TEST_F(UnitMath, copysign_percent)
{
double sign = -1;
percent<double> val(5.0);
EXPECT_EQ(percent<double>(-5.0), copysign(val, sign));
}

TEST_F(UnitMath, fdim)
{
EXPECT_EQ(meters<double>(0.0), fdim(meters<double>(8.0), meters<double>(10.0)));
EXPECT_EQ(meters<double>(2.0), fdim(meters<double>(10.0), meters<double>(8.0)));
EXPECT_NEAR(meters<double>(9.3904).to<double>(), meters<double>(fdim(meters<double>(10.0), feet<double>(2.0))).to<double>(),
5.0e-320); // not sure why they aren't comparing exactly equal, but clearly they are.

EXPECT_EQ(percent<double>(0.0), fdim(percent<double>(8.0), percent<double>(10.0)));
EXPECT_EQ(percent<double>(2.0), fdim(percent<double>(10.0), percent<double>(8.0)));
}

TEST_F(UnitMath, fmin)
{
EXPECT_EQ(meters<double>(8.0), fmin(meters<double>(8.0), meters<double>(10.0)));
EXPECT_EQ(meters<double>(8.0), fmin(meters<double>(10.0), meters<double>(8.0)));
EXPECT_EQ(feet<double>(2.0), fmin(meters<double>(10.0), feet<double>(2.0)));

EXPECT_EQ(percent<double>(8.0), fmin(percent<double>(8.0), percent<double>(10.0)));
EXPECT_EQ(percent<double>(8.0), fmin(percent<double>(10.0), percent<double>(8.0)));
}

TEST_F(UnitMath, fmax)
{
EXPECT_EQ(meters<double>(10.0), fmax(meters<double>(8.0), meters<double>(10.0)));
EXPECT_EQ(meters<double>(10.0), fmax(meters<double>(10.0), meters<double>(8.0)));
EXPECT_EQ(meters<double>(10.0), fmax(meters<double>(10.0), feet<double>(2.0)));

EXPECT_EQ(percent<double>(10.0), fmax(percent<double>(8.0), percent<double>(10.0)));
EXPECT_EQ(percent<double>(10.0), fmax(percent<double>(10.0), percent<double>(8.0)));
}

TEST_F(UnitMath, fabs)
{
EXPECT_EQ(meters<double>(10.0), fabs(meters<double>(-10.0)));
EXPECT_EQ(meters<double>(10.0), fabs(meters<double>(10.0)));

EXPECT_EQ(percent<double>(10.0), fabs(percent<double>(-10.0)));
EXPECT_EQ(percent<double>(10.0), fabs(percent<double>(10.0)));
}

TEST_F(UnitMath, abs)
{
EXPECT_EQ(meters<double>(10.0), abs(meters<double>(-10.0)));
EXPECT_EQ(meters<double>(10.0), abs(meters<double>(10.0)));

EXPECT_EQ(percent<double>(10.0), abs(percent<double>(-10.0)));
EXPECT_EQ(percent<double>(10.0), abs(percent<double>(10.0)));
}

TEST_F(UnitMath, fma)
Expand All @@ -4832,6 +4871,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);
Expand All @@ -4845,6 +4898,17 @@ TEST_F(UnitMath, isinf)
EXPECT_FALSE(units::isinf(DBL_MIN / 2.0 * 1_m));
}

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)
{
meters<> zero(0.0);
Expand All @@ -4858,6 +4922,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_TRUE(units::isfinite(zero));
EXPECT_TRUE(units::isfinite(DBL_MIN / 2.0 * 1_pct));
}

TEST_F(UnitMath, isnormal)
{
meters<> zero(0.0);
Expand All @@ -4870,6 +4946,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);
Expand All @@ -4881,6 +4969,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)
{
Expand Down Expand Up @@ -5090,4 +5189,4 @@ int main(int argc, char* argv[])
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
}

0 comments on commit 3ccfe92

Please sign in to comment.