Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix math functions for percent #329

Open
wants to merge 2 commits into
base: v3.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions include/units/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -3787,7 +3787,7 @@ namespace units
constexpr auto sqrt(const UnitType& value) noexcept -> unit<traits::strong_t<square_root<typename traits::unit_traits<UnitType>::conversion_factor>>,
detail::floating_point_promotion_t<typename traits::unit_traits<UnitType>::underlying_type>>
{
return decltype(units::sqrt(value))(sqrt(value.value()));
return decltype(units::sqrt(value))(sqrt(value.raw()));
}

/**
Expand Down Expand Up @@ -3821,7 +3821,7 @@ namespace units
template<UnitType UnitType>
constexpr 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 @@ -3834,7 +3834,7 @@ namespace units
template<UnitType UnitType>
constexpr 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 @@ -3864,7 +3864,7 @@ namespace units
template<UnitType UnitType>
constexpr 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 @@ -3878,7 +3878,7 @@ namespace units
template<UnitType UnitType>
constexpr 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 @@ -3897,14 +3897,14 @@ namespace units
template<UnitType UnitTypeLhs, UnitType UnitTypeRhs>
constexpr 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<UnitType UnitTypeLhs, ArithmeticType T>
constexpr 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 @@ -3924,7 +3924,7 @@ namespace units
constexpr 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 @@ -3940,7 +3940,7 @@ namespace units
constexpr 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 @@ -3957,7 +3957,7 @@ namespace units
constexpr 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 @@ -3974,7 +3974,7 @@ namespace units
template<UnitType UnitType>
constexpr 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 @@ -3987,7 +3987,7 @@ namespace units
template<UnitType UnitType>
constexpr UnitType abs(const UnitType x) noexcept
{
return UnitType(std::abs(x.value()));
return UnitType(std::abs(x.raw()));
}

/**
Expand Down Expand Up @@ -4239,7 +4239,7 @@ namespace units
j = u.raw();
}
} // namespace units
#endif
#endif
#endif // #if __has_include(<nlohmann/json.hpp>)
#endif // #if defined __has_include

#endif // UNIT_CORE_H
#endif // UNIT_CORE_H
106 changes: 103 additions & 3 deletions unitTests/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4457,6 +4457,10 @@ TEST_F(UnitMath, min)
constexpr meters d(1);
constexpr centimeters 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 @@ -4468,6 +4472,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, ternaryOperator)
Expand Down Expand Up @@ -4799,7 +4807,11 @@ TEST_F(UnitMath, sqrt)
static_assert(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);

static_assert(std::is_same_v<angle::radians<double>, decltype(sqrt(steradians<double>(16.0)))>);
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);

static_assert(std::is_convertible_v<feet<double>, decltype(sqrt(square_feet<double>(10.0)))>);
Expand Down Expand Up @@ -4828,13 +4840,17 @@ TEST_F(UnitMath, ceil)
{
double val = 101.1;
EXPECT_EQ(ceil(val), ceil(meters<double>(val)).to<double>());
static_assert(std::is_same_v<meters<double>, decltype(ceil(meters<double>(val)))>);
static_assert(std::is_same_v<meters<double>, decltype(ceil(meters<double>(val)))>);

EXPECT_EQ(ceil(val), ceil(percent<double>(val)).raw());
static_assert(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 @@ -4846,12 +4862,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 @@ -4862,38 +4880,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 @@ -4918,6 +4958,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)
{
constexpr meters zero(0.0);
Expand All @@ -4932,6 +4986,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 @@ -4946,6 +5011,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 @@ -4959,6 +5036,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 @@ -4969,6 +5058,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 @@ -5277,4 +5377,4 @@ int main(int argc, char* argv[])
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
}