// Copyright 2022, Collabora, Ltd. // SPDX-License-Identifier: BSL-1.0 /*! * @file * @brief Integer low pass filter tests. * @author Rylie Pavlik */ #include #include "catch/catch.hpp" #include #include #include #include #include using xrt::auxiliary::math::Rational; namespace Catch { template struct StringMaker> { static std::string convert(Rational const &value) { return std::to_string(value.numerator) + "/" + std::to_string(value.denominator); } }; } // namespace Catch TEMPLATE_TEST_CASE("Rational", "", int32_t, uint32_t, int64_t, uint64_t) { using R = Rational; using T = TestType; CHECK(R{1, 1} == R::simplestUnity()); CHECK((R::simplestUnity() * T{1}) == R::simplestUnity()); CHECK((T{1} * R::simplestUnity()) == R::simplestUnity()); CHECK(R::simplestUnity().as_float() == 1.0f); CHECK(R::simplestUnity().as_double() == 1.0); CHECK(R{5, 8}.reciprocal() == R{8, 5}); CHECK(R{5, 8}.complement() == R{3, 8}); CHECK(R{8, 8}.complement() == R{0, 8}); CHECK(R{0, 8}.as_float() == 0.0f); CHECK(R{0, 8}.as_double() == 0.0); CHECK(R{5, 8}.withNonNegativeDenominator() == R{5, 8}); if constexpr (std::is_signed::value) { CHECK(R{5, -8}.withNonNegativeDenominator() == R{-5, 8}); CHECK(R{-5, 8}.withNonNegativeDenominator() == R{-5, 8}); CHECK(R{-5, 8}.reciprocal() == R{-8, 5}); CHECK(R{5, -8}.complement() == R{8 + 5, 8}); } { R val{5, 8}; CAPTURE(val); CHECK((R::simplestUnity() * val) == val); CHECK((val * R::simplestUnity()) == val); CHECK((val * T{1}) == val); CHECK((T{1} * val) == val); CHECK((val * val.reciprocal()).numerator == (val * val.reciprocal()).denominator); CHECK((val * val.reciprocal()).isUnity()); CHECK((val / val).numerator == (val / val).denominator); CHECK((val / val).isUnity()); CHECK((val / T{1}) == val); } if constexpr (std::is_signed::value) { R val{5, -8}; R valNonNegativeDenominator = val.withNonNegativeDenominator(); CAPTURE(val); CHECK((R::simplestUnity() * val) == valNonNegativeDenominator); CHECK((val * R::simplestUnity()) == valNonNegativeDenominator); CHECK((val * T{1}) == valNonNegativeDenominator); CHECK((T{1} * val) == valNonNegativeDenominator); CHECK((val * val.reciprocal()).numerator == (val * val.reciprocal()).denominator); CHECK((val * val.reciprocal()).isUnity()); CHECK((val / val).numerator == (val / val).denominator); CHECK((val / val).isUnity()); CHECK((val / T{1}) == valNonNegativeDenominator); } // Check all our predicates, and our float convesions { // This is divide by zero error, all should be false R val{0, 0}; CAPTURE(val); CHECK_FALSE(val.isZero()); CHECK_FALSE(val.isBetweenZeroAndOne()); CHECK_FALSE(val.isUnity()); CHECK_FALSE(val.isOverUnity()); } { R val{0, 8}; CAPTURE(val); CHECK(val.isZero()); CHECK_FALSE(val.isBetweenZeroAndOne()); CHECK_FALSE(val.isUnity()); CHECK_FALSE(val.isOverUnity()); CHECK(val.as_float() == 0.0f); CHECK(val.as_double() == 0.0); } { R val{5, 8}; CAPTURE(val); CHECK_FALSE(val.isZero()); CHECK(val.isBetweenZeroAndOne()); CHECK_FALSE(val.isUnity()); CHECK_FALSE(val.isOverUnity()); CHECK(val.as_float() > 0.0f); CHECK(val.as_float() < 1.0f); CHECK(val.as_double() > 0.0); CHECK(val.as_double() < 1.0); } { R val{8, 8}; CAPTURE(val); CHECK_FALSE(val.isZero()); CHECK_FALSE(val.isBetweenZeroAndOne()); CHECK(val.isUnity()); CHECK_FALSE(val.isOverUnity()); CHECK(val.as_float() == 1.0f); CHECK(val.as_double() == 1.0); } { R val = R::simplestUnity(); CAPTURE(val); CHECK_FALSE(val.isZero()); CHECK_FALSE(val.isBetweenZeroAndOne()); CHECK(val.isUnity()); CHECK_FALSE(val.isOverUnity()); CHECK(val.as_float() == 1.0f); CHECK(val.as_double() == 1.0); } { R val{8, 5}; CAPTURE(val); CHECK_FALSE(val.isZero()); CHECK_FALSE(val.isBetweenZeroAndOne()); CHECK_FALSE(val.isUnity()); CHECK(val.isOverUnity()); CHECK(val.as_float() > 1.0f); CHECK(val.as_double() > 1.0); } }