The open source OpenXR runtime
1// Copyright 2022, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Integer low pass filter tests.
6 * @author Rylie Pavlik <rylie.pavlik@collabora.com>
7 */
8
9#include <math/m_rational.hpp>
10
11#include "catch_amalgamated.hpp"
12
13#include <iostream>
14#include <chrono>
15#include <sstream>
16#include <iomanip>
17#include <queue>
18
19using xrt::auxiliary::math::Rational;
20namespace Catch {
21template <typename T> struct StringMaker<Rational<T>>
22{
23 static std::string
24 convert(Rational<T> const &value)
25 {
26 return std::to_string(value.numerator) + "/" + std::to_string(value.denominator);
27 }
28};
29} // namespace Catch
30
31TEMPLATE_TEST_CASE("Rational", "", int32_t, uint32_t, int64_t, uint64_t)
32{
33 using R = Rational<TestType>;
34 using T = TestType;
35 CHECK(R{1, 1} == R::simplestUnity());
36 CHECK((R::simplestUnity() * T{1}) == R::simplestUnity());
37 CHECK((T{1} * R::simplestUnity()) == R::simplestUnity());
38 CHECK(R::simplestUnity().as_float() == 1.0f);
39 CHECK(R::simplestUnity().as_double() == 1.0);
40
41 CHECK(R{5, 8}.reciprocal() == R{8, 5});
42
43 CHECK(R{5, 8}.complement() == R{3, 8});
44 CHECK(R{8, 8}.complement() == R{0, 8});
45
46 CHECK(R{0, 8}.as_float() == 0.0f);
47 CHECK(R{0, 8}.as_double() == 0.0);
48
49 CHECK(R{5, 8}.withNonNegativeDenominator() == R{5, 8});
50
51 if constexpr (std::is_signed<TestType>::value) {
52 CHECK(R{5, -8}.withNonNegativeDenominator() == R{-5, 8});
53 CHECK(R{-5, 8}.withNonNegativeDenominator() == R{-5, 8});
54
55 CHECK(R{-5, 8}.reciprocal() == R{-8, 5});
56 CHECK(R{5, -8}.complement() == R{8 + 5, 8});
57 }
58
59 {
60 R val{5, 8};
61 CAPTURE(val);
62 CHECK((R::simplestUnity() * val) == val);
63 CHECK((val * R::simplestUnity()) == val);
64 CHECK((val * T{1}) == val);
65 CHECK((T{1} * val) == val);
66
67 CHECK((val * val.reciprocal()).numerator == (val * val.reciprocal()).denominator);
68 CHECK((val * val.reciprocal()).isUnity());
69
70 CHECK((val / val).numerator == (val / val).denominator);
71 CHECK((val / val).isUnity());
72
73 CHECK((val / T{1}) == val);
74 }
75
76 if constexpr (std::is_signed<TestType>::value) {
77 R val{5, -8};
78 R valNonNegativeDenominator = val.withNonNegativeDenominator();
79
80 CAPTURE(val);
81 CHECK((R::simplestUnity() * val) == valNonNegativeDenominator);
82 CHECK((val * R::simplestUnity()) == valNonNegativeDenominator);
83 CHECK((val * T{1}) == valNonNegativeDenominator);
84 CHECK((T{1} * val) == valNonNegativeDenominator);
85
86 CHECK((val * val.reciprocal()).numerator == (val * val.reciprocal()).denominator);
87 CHECK((val * val.reciprocal()).isUnity());
88
89 CHECK((val / val).numerator == (val / val).denominator);
90 CHECK((val / val).isUnity());
91
92 CHECK((val / T{1}) == valNonNegativeDenominator);
93 }
94
95 // Check all our predicates, and our float convesions
96 {
97 // This is divide by zero error, all should be false
98 R val{0, 0};
99 CAPTURE(val);
100 CHECK_FALSE(val.isZero());
101 CHECK_FALSE(val.isBetweenZeroAndOne());
102 CHECK_FALSE(val.isUnity());
103 CHECK_FALSE(val.isOverUnity());
104 }
105 {
106 R val{0, 8};
107 CAPTURE(val);
108 CHECK(val.isZero());
109 CHECK_FALSE(val.isBetweenZeroAndOne());
110 CHECK_FALSE(val.isUnity());
111 CHECK_FALSE(val.isOverUnity());
112
113 CHECK(val.as_float() == 0.0f);
114 CHECK(val.as_double() == 0.0);
115 }
116
117 {
118 R val{5, 8};
119 CAPTURE(val);
120 CHECK_FALSE(val.isZero());
121 CHECK(val.isBetweenZeroAndOne());
122 CHECK_FALSE(val.isUnity());
123 CHECK_FALSE(val.isOverUnity());
124
125 CHECK(val.as_float() > 0.0f);
126 CHECK(val.as_float() < 1.0f);
127 CHECK(val.as_double() > 0.0);
128 CHECK(val.as_double() < 1.0);
129 }
130
131 {
132 R val{8, 8};
133 CAPTURE(val);
134 CHECK_FALSE(val.isZero());
135 CHECK_FALSE(val.isBetweenZeroAndOne());
136 CHECK(val.isUnity());
137 CHECK_FALSE(val.isOverUnity());
138
139 CHECK(val.as_float() == 1.0f);
140 CHECK(val.as_double() == 1.0);
141 }
142 {
143 R val = R::simplestUnity();
144 CAPTURE(val);
145 CHECK_FALSE(val.isZero());
146 CHECK_FALSE(val.isBetweenZeroAndOne());
147 CHECK(val.isUnity());
148 CHECK_FALSE(val.isOverUnity());
149
150 CHECK(val.as_float() == 1.0f);
151 CHECK(val.as_double() == 1.0);
152 }
153 {
154 R val{8, 5};
155 CAPTURE(val);
156 CHECK_FALSE(val.isZero());
157 CHECK_FALSE(val.isBetweenZeroAndOne());
158 CHECK_FALSE(val.isUnity());
159 CHECK(val.isOverUnity());
160
161 CHECK(val.as_float() > 1.0f);
162 CHECK(val.as_double() > 1.0);
163 }
164}