Skip to content

Commit

Permalink
Merge branch 'main' into chiphogg/dependabot-5
Browse files Browse the repository at this point in the history
  • Loading branch information
chiphogg committed Oct 16, 2023
2 parents 587a27f + 22793ad commit b54d254
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 0 deletions.
54 changes: 54 additions & 0 deletions au/math.hh
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,26 @@ constexpr auto clamp(Quantity<UV, RV> v, Quantity<ULo, RLo> lo, Quantity<UHi, RH
return (v < lo) ? ResultT{lo} : (hi < v) ? ResultT{hi} : ResultT{v};
}

// `clamp` overloads for when either boundary is `Zero`.
//
// NOTE: these will not work if _both_ boundaries are `Zero`, or if the quantity being clamped is
// `Zero`. We do not think these use cases are very useful, but we're open to revisiting this if we
// receive a persuasive argument otherwise.
template <typename UV, typename UHi, typename RV, typename RHi>
constexpr auto clamp(Quantity<UV, RV> v, Zero z, Quantity<UHi, RHi> hi) {
using U = CommonUnitT<UV, UHi>;
using R = std::common_type_t<RV, RHi>;
using ResultT = Quantity<U, R>;
return (v < z) ? ResultT{z} : (hi < v) ? ResultT{hi} : ResultT{v};
}
template <typename UV, typename ULo, typename RV, typename RLo>
constexpr auto clamp(Quantity<UV, RV> v, Quantity<ULo, RLo> lo, Zero z) {
using U = CommonUnitT<UV, ULo>;
using R = std::common_type_t<RV, RLo>;
using ResultT = Quantity<U, R>;
return (v < lo) ? ResultT{lo} : (z < v) ? ResultT{z} : ResultT{v};
}

// Clamp the first point to within the range of the second two.
template <typename UV, typename ULo, typename UHi, typename RV, typename RLo, typename RHi>
constexpr auto clamp(QuantityPoint<UV, RV> v,
Expand Down Expand Up @@ -313,6 +333,23 @@ auto max(QuantityPoint<U, R> a, QuantityPoint<U, R> b) {
return std::max(a, b);
}

// `max` overloads for when Zero is one of the arguments.
//
// NOTE: these will not work if _both_ arguments are `Zero`, but we don't plan to support this
// unless we find a compelling use case.
template <typename T>
auto max(Zero z, T x) {
static_assert(std::is_convertible<Zero, T>::value,
"Cannot compare type to abstract notion Zero");
return std::max(T{z}, x);
}
template <typename T>
auto max(T x, Zero z) {
static_assert(std::is_convertible<Zero, T>::value,
"Cannot compare type to abstract notion Zero");
return std::max(x, T{z});
}

// The minimum of two values of the same dimension.
//
// Unlike std::min, returns by value rather than by reference, because the types might differ.
Expand Down Expand Up @@ -341,6 +378,23 @@ auto min(QuantityPoint<U, R> a, QuantityPoint<U, R> b) {
return std::min(a, b);
}

// `min` overloads for when Zero is one of the arguments.
//
// NOTE: these will not work if _both_ arguments are `Zero`, but we don't plan to support this
// unless we find a compelling use case.
template <typename T>
auto min(Zero z, T x) {
static_assert(std::is_convertible<Zero, T>::value,
"Cannot compare type to abstract notion Zero");
return std::min(T{z}, x);
}
template <typename T>
auto min(T x, Zero z) {
static_assert(std::is_convertible<Zero, T>::value,
"Cannot compare type to abstract notion Zero");
return std::min(x, T{z});
}

//
// Round the value of this Quantity to the nearest integer in the given units.
//
Expand Down
33 changes: 33 additions & 0 deletions au/math_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "au/units/celsius.hh"
#include "au/units/degrees.hh"
#include "au/units/fahrenheit.hh"
#include "au/units/feet.hh"
#include "au/units/hertz.hh"
#include "au/units/inches.hh"
#include "au/units/kelvins.hh"
Expand Down Expand Up @@ -133,6 +134,18 @@ TEST(clamp, QuantityPointTakesOffsetIntoAccount) {
EXPECT_EQ(celsius_origin, centi(kelvins_pt)(273'15));
}

TEST(clamp, SupportsZeroForLowerBoundaryArgument) {
EXPECT_THAT(clamp(feet(-1), ZERO, inches(18)), SameTypeAndValue(inches(0)));
EXPECT_THAT(clamp(feet(+1), ZERO, inches(18)), SameTypeAndValue(inches(12)));
EXPECT_THAT(clamp(feet(+2), ZERO, inches(18)), SameTypeAndValue(inches(18)));
}

TEST(clamp, SupportsZeroForUpperBoundaryArgument) {
EXPECT_THAT(clamp(feet(-2), inches(-18), ZERO), SameTypeAndValue(inches(-18)));
EXPECT_THAT(clamp(feet(-1), inches(-18), ZERO), SameTypeAndValue(inches(-12)));
EXPECT_THAT(clamp(feet(+1), inches(-18), ZERO), SameTypeAndValue(inches(0)));
}

TEST(copysign, ReturnsSameTypesAsStdCopysignForSameUnitInputs) {
auto expect_consistent_with_std_copysign = [](auto mag, auto raw_sgn) {
for (const auto test_sgn : {-1, 0, +1}) {
Expand Down Expand Up @@ -273,6 +286,16 @@ TEST(max, SameAsStdMaxForNumericTypes) {
EXPECT_EQ(&b, &max_result);
}

TEST(max, SupportsZeroForFirstArgument) {
EXPECT_THAT(max(ZERO, meters(8)), SameTypeAndValue(meters(8)));
EXPECT_THAT(max(ZERO, meters(-8)), SameTypeAndValue(meters(0)));
}

TEST(max, SupportsZeroForSecondArgument) {
EXPECT_THAT(max(meters(8), ZERO), SameTypeAndValue(meters(8)));
EXPECT_THAT(max(meters(-8), ZERO), SameTypeAndValue(meters(0)));
}

TEST(min, ReturnsSmaller) { EXPECT_EQ(min(centi(meters)(1), inches(1)), centi(meters)(1)); }

TEST(min, HandlesDifferentOriginQuantityPoints) {
Expand Down Expand Up @@ -308,6 +331,16 @@ TEST(min, SameAsStdMinForNumericTypes) {
EXPECT_EQ(&a, &min_result);
}

TEST(min, SupportsZeroForFirstArgument) {
EXPECT_THAT(min(ZERO, meters(8)), SameTypeAndValue(meters(0)));
EXPECT_THAT(min(ZERO, meters(-8)), SameTypeAndValue(meters(-8)));
}

TEST(min, SupportsZeroForSecondArgument) {
EXPECT_THAT(min(meters(8), ZERO), SameTypeAndValue(meters(0)));
EXPECT_THAT(min(meters(-8), ZERO), SameTypeAndValue(meters(-8)));
}

TEST(int_pow, OutputRepMatchesInputRep) {
EXPECT_THAT(int_pow<-1>(meters(2.)), QuantityEquivalent(pow<-1>(meters)(0.5)));
EXPECT_THAT(int_pow<2>(meters(2.)), QuantityEquivalent(squared(meters)(4.)));
Expand Down

0 comments on commit b54d254

Please sign in to comment.