openMSX
Math_test.cc
Go to the documentation of this file.
1 #include "catch.hpp"
2 #include "Math.hh"
3 
4 TEST_CASE("Math::log2p1")
5 {
6  CHECK(Math::log2p1(0) == 0);
7  CHECK(Math::log2p1(1) == 1);
8  CHECK(Math::log2p1(2) == 2);
9  CHECK(Math::log2p1(3) == 2);
10  CHECK(Math::log2p1(4) == 3);
11  CHECK(Math::log2p1(5) == 3);
12  CHECK(Math::log2p1(6) == 3);
13  CHECK(Math::log2p1(7) == 3);
14  CHECK(Math::log2p1(8) == 4);
15  CHECK(Math::log2p1(9) == 4);
16  CHECK(Math::log2p1(127) == 7);
17  CHECK(Math::log2p1(128) == 8);
18  CHECK(Math::log2p1(129) == 8);
19  CHECK(Math::log2p1(255) == 8);
20  CHECK(Math::log2p1(256) == 9);
21 
22  constexpr auto x = Math::log2p1(255); static_assert(x == 8);
23 }
24 
25 TEST_CASE("Math::ispow2")
26 {
27  CHECK(!Math::ispow2(0));
28  CHECK( Math::ispow2(1));
29  CHECK( Math::ispow2(2));
30  CHECK(!Math::ispow2(3));
31  CHECK( Math::ispow2(4));
32  CHECK(!Math::ispow2(5));
33  CHECK(!Math::ispow2(6));
34  CHECK(!Math::ispow2(7));
35  CHECK( Math::ispow2(8));
36  CHECK(!Math::ispow2(9));
37  CHECK(!Math::ispow2(15));
38  CHECK( Math::ispow2(16));
39  CHECK(!Math::ispow2(17));
40  CHECK( Math::ispow2(32));
41  CHECK( Math::ispow2(64));
42  CHECK(!Math::ispow2(255));
43  CHECK( Math::ispow2(256));
44  CHECK( Math::ispow2(512));
45  CHECK( Math::ispow2(1024));
46  CHECK( Math::ispow2(2048));
47  CHECK( Math::ispow2(4096));
48  CHECK( Math::ispow2(8192));
49  CHECK(!Math::ispow2(0xffff));
50  CHECK( Math::ispow2(0x10000));
51  CHECK( Math::ispow2(0x80000000));
52  CHECK(!Math::ispow2(0xffffffff));
53 }
54 
55 TEST_CASE("Math::ceil2")
56 {
57  CHECK(Math::ceil2(0) == 1);
58  CHECK(Math::ceil2(1) == 1);
59  CHECK(Math::ceil2(2) == 2);
60  CHECK(Math::ceil2(3) == 4);
61  CHECK(Math::ceil2(4) == 4);
62  CHECK(Math::ceil2(5) == 8);
63  CHECK(Math::ceil2(6) == 8);
64  CHECK(Math::ceil2(7) == 8);
65  CHECK(Math::ceil2(8) == 8);
66  CHECK(Math::ceil2(9) == 16);
67  CHECK(Math::ceil2(15) == 16);
68  CHECK(Math::ceil2(16) == 16);
69  CHECK(Math::ceil2(17) == 32);
70  CHECK(Math::ceil2(32) == 32);
71  CHECK(Math::ceil2(64) == 64);
72  CHECK(Math::ceil2(255) == 256);
73  CHECK(Math::ceil2(256) == 256);
74  CHECK(Math::ceil2(512) == 512);
75  CHECK(Math::ceil2(1024) == 1024);
76  CHECK(Math::ceil2(2048) == 2048);
77  CHECK(Math::ceil2(4096) == 4096);
78  CHECK(Math::ceil2(8192) == 8192);
79  CHECK(Math::ceil2(0xffff) == 0x10000);
80  CHECK(Math::ceil2(0x10000) == 0x10000);
81  CHECK(Math::ceil2(0x80000000) == 0x80000000);
82  // values > 0x80000000 don't work,
83  // result can't be represented in 32bit
84 }
85 
86 TEST_CASE("Math::clipIntToShort")
87 {
88  CHECK(Math::clipIntToShort(-100000) == -32768);
89  CHECK(Math::clipIntToShort( -32769) == -32768);
90  CHECK(Math::clipIntToShort( -32768) == -32768);
91  CHECK(Math::clipIntToShort( -32767) == -32767);
92  CHECK(Math::clipIntToShort( -10000) == -10000);
93  CHECK(Math::clipIntToShort( -10) == -10);
94  CHECK(Math::clipIntToShort( -1) == -1);
95  CHECK(Math::clipIntToShort( 0) == 0);
96  CHECK(Math::clipIntToShort( 1) == 1);
97  CHECK(Math::clipIntToShort( 10) == 10);
98  CHECK(Math::clipIntToShort( 9876) == 9876);
99  CHECK(Math::clipIntToShort( 32766) == 32766);
100  CHECK(Math::clipIntToShort( 32767) == 32767);
101  CHECK(Math::clipIntToShort( 32768) == 32767);
102  CHECK(Math::clipIntToShort( 100000) == 32767);
103 }
104 
105 TEST_CASE("Math::clipIntToByte")
106 {
107  CHECK(Math::clipIntToByte(-100) == 0);
108  CHECK(Math::clipIntToByte( -27) == 0);
109  CHECK(Math::clipIntToByte( -1) == 0);
110  CHECK(Math::clipIntToByte( 0) == 0);
111  CHECK(Math::clipIntToByte( 1) == 1);
112  CHECK(Math::clipIntToByte( 10) == 10);
113  CHECK(Math::clipIntToByte( 127) == 127);
114  CHECK(Math::clipIntToByte( 128) == 128);
115  CHECK(Math::clipIntToByte( 222) == 222);
116  CHECK(Math::clipIntToByte( 255) == 255);
117  CHECK(Math::clipIntToByte( 256) == 255);
118  CHECK(Math::clipIntToByte( 257) == 255);
119  CHECK(Math::clipIntToByte( 327) == 255);
120 }
121 
122 static void testReverseNBits(unsigned x, unsigned n, unsigned expected)
123 {
124  CHECK(Math::reverseNBits(x, n) == expected);
125  CHECK(Math::reverseNBits(expected, n) == x);
126 }
127 TEST_CASE("Math::reverseNBits")
128 {
129  testReverseNBits(0x0, 4, 0x0);
130  testReverseNBits(0x1, 4, 0x8);
131  testReverseNBits(0x2, 4, 0x4);
132  testReverseNBits(0x3, 4, 0xC);
133  testReverseNBits(0x4, 4, 0x2);
134  testReverseNBits(0x8, 4, 0x1);
135  testReverseNBits(0x6, 4, 0x6);
136  testReverseNBits(0xE, 4, 0x7);
137  testReverseNBits(0xF, 4, 0xF);
138  testReverseNBits(0x00012345, 22, 0x0028B120);
139  testReverseNBits(0x0010000F, 32, 0xF0000800);
140 }
141 
142 static void testReverseByte(uint8_t x, uint8_t expected)
143 {
144  CHECK(Math::reverseByte (x ) == expected);
145  CHECK(Math::reverseNBits(x, 8) == expected);
146 
147  CHECK(Math::reverseByte (expected ) == x);
148  CHECK(Math::reverseNBits(expected, 8) == x);
149 }
150 TEST_CASE("Math::reverseByte")
151 {
152  testReverseByte(0x00, 0x00);
153  testReverseByte(0x01, 0x80);
154  testReverseByte(0x02, 0x40);
155  testReverseByte(0x07, 0xE0);
156  testReverseByte(0x12, 0x48);
157  testReverseByte(0x73, 0xCE);
158  testReverseByte(0x7F, 0xFE);
159  testReverseByte(0x8C, 0x31);
160  testReverseByte(0xAB, 0xD5);
161  testReverseByte(0xE4, 0x27);
162  testReverseByte(0xF0, 0x0F);
163 }
164 
165 TEST_CASE("Math::floodRight")
166 {
167  CHECK(Math::floodRight(0) == 0);
168  CHECK(Math::floodRight(1) == 1);
169  CHECK(Math::floodRight(2) == 3);
170  CHECK(Math::floodRight(3) == 3);
171  CHECK(Math::floodRight(4) == 7);
172  CHECK(Math::floodRight(5) == 7);
173  CHECK(Math::floodRight(6) == 7);
174  CHECK(Math::floodRight(7) == 7);
175  CHECK(Math::floodRight(8) == 15);
176  CHECK(Math::floodRight(9) == 15);
177  CHECK(Math::floodRight(15) == 15);
178  CHECK(Math::floodRight(16) == 31);
179  CHECK(Math::floodRight(32) == 63);
180  CHECK(Math::floodRight(64) == 127);
181  CHECK(Math::floodRight(12345) == 16383);
182  CHECK(Math::floodRight(0x7F001234) == 0x7FFFFFFF);
183  CHECK(Math::floodRight(0x80000000) == 0xFFFFFFFF);
184  CHECK(Math::floodRight(0xF0FEDCBA) == 0xFFFFFFFF);
185  CHECK(Math::floodRight(0x1234F0FEDCBAULL) == 0x1FFFFFFFFFFFULL);
186  CHECK(Math::floodRight(uint8_t(0x12)) == uint8_t(0x1F));
187  CHECK(Math::floodRight(uint16_t(0x2512)) == uint16_t(0x3FFF));
188 }
189 
190 TEST_CASE("Math::countLeadingZeros")
191 {
192  // undefined for 0
193  CHECK(Math::countLeadingZeros(0x00000001) == 31);
194  CHECK(Math::countLeadingZeros(0x00000002) == 30);
195  CHECK(Math::countLeadingZeros(0x00000003) == 30);
196  CHECK(Math::countLeadingZeros(0x00000004) == 29);
197  CHECK(Math::countLeadingZeros(0x00000005) == 29);
198  CHECK(Math::countLeadingZeros(0x00000007) == 29);
199  CHECK(Math::countLeadingZeros(0x00000008) == 28);
200  CHECK(Math::countLeadingZeros(0x00000081) == 24);
201  CHECK(Math::countLeadingZeros(0x00000134) == 23);
202  CHECK(Math::countLeadingZeros(0x00000234) == 22);
203  CHECK(Math::countLeadingZeros(0x00008234) == 16);
204  CHECK(Math::countLeadingZeros(0x00021234) == 14);
205  CHECK(Math::countLeadingZeros(0x00421234) == 9);
206  CHECK(Math::countLeadingZeros(0x01421234) == 7);
207  CHECK(Math::countLeadingZeros(0x01421234) == 7);
208  CHECK(Math::countLeadingZeros(0x11421234) == 3);
209  CHECK(Math::countLeadingZeros(0x31421234) == 2);
210  CHECK(Math::countLeadingZeros(0x61421234) == 1);
211  CHECK(Math::countLeadingZeros(0x91421234) == 0);
212  CHECK(Math::countLeadingZeros(0xF1421234) == 0);
213 }
214 
215 TEST_CASE("Math::countTrailingZeros")
216 {
217  // undefined for 0
218  CHECK(Math::countTrailingZeros(0x00000000'00000001ull) == 0);
219  CHECK(Math::countTrailingZeros(0x00000000'00000002ull) == 1);
220  CHECK(Math::countTrailingZeros(0x00000000'00000003ull) == 0);
221  CHECK(Math::countTrailingZeros(0x00000000'00000004ull) == 2);
222  CHECK(Math::countTrailingZeros(0x00000000'00000100ull) == 8);
223  CHECK(Math::countTrailingZeros(0x00000000'80000000ull) == 31);
224  CHECK(Math::countTrailingZeros(0x00000001'00000000ull) == 32);
225  CHECK(Math::countTrailingZeros(0x80000000'00000000ull) == 63);
226  CHECK(Math::countTrailingZeros(0x80000000'00000001ull) == 0);
227 }
228 
229 TEST_CASE("Math::findFirstSet")
230 {
231  // undefined for 0
232  CHECK(Math::findFirstSet(0x00000000ull) == 0);
233  CHECK(Math::findFirstSet(0x00000001ull) == 1);
234  CHECK(Math::findFirstSet(0x00000002ull) == 2);
235  CHECK(Math::findFirstSet(0x00000003ull) == 1);
236  CHECK(Math::findFirstSet(0x00000004ull) == 3);
237  CHECK(Math::findFirstSet(0x00000100ull) == 9);
238  CHECK(Math::findFirstSet(0x80000000ull) == 32);
239  CHECK(Math::findFirstSet(0x80000001ull) == 1);
240 }
TEST_CASE("Math::log2p1")
Definition: Math_test.cc:4
CHECK(m3==m3)
constexpr int countTrailingZeros(uint64_t x)
Count the number of trailing zero-bits in the given word.
Definition: Math.hh:214
constexpr unsigned reverseNBits(unsigned x, unsigned bits)
Reverse the lower N bits of a given value.
Definition: Math.hh:119
constexpr T floodRight(T x) noexcept
Returns the smallest number of the form 2^n-1 that is greater or equal to the given number.
Definition: Math.hh:69
unsigned findFirstSet(uint32_t x)
Find the least significant bit that is set.
Definition: Math.hh:234
constexpr T ceil2(T x) noexcept
Returns the smallest number that is both >=a and a power of two.
Definition: Math.hh:85
uint8_t clipIntToByte(int x)
Clip x to range [0,255].
Definition: Math.hh:109
constexpr T log2p1(T x) noexcept
Returns the number of bits needed to store the value 'x', that is: for x==0 : 0 for x!...
Definition: Math.hh:39
constexpr unsigned countLeadingZeros(uint32_t x)
Count the number of leading zero-bits in the given word.
Definition: Math.hh:193
constexpr uint8_t reverseByte(uint8_t a)
Reverse the bits in a byte.
Definition: Math.hh:169
constexpr bool ispow2(T x) noexcept
Is the given number an integral power of two? That is, does it have exactly one 1-bit in binary repre...
Definition: Math.hh:57
int16_t clipIntToShort(int x)
Clip x to range [-32768,32767].
Definition: Math.hh:100
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:118