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::clip")
87 {
88  CHECK((Math::clip<10, 20>(-6)) == 10);
89  CHECK((Math::clip<10, 20>( 0)) == 10);
90  CHECK((Math::clip<10, 20>( 9)) == 10);
91  CHECK((Math::clip<10, 20>(10)) == 10);
92  CHECK((Math::clip<10, 20>(11)) == 11);
93  CHECK((Math::clip<10, 20>(14)) == 14);
94  CHECK((Math::clip<10, 20>(19)) == 19);
95  CHECK((Math::clip<10, 20>(20)) == 20);
96  CHECK((Math::clip<10, 20>(21)) == 20);
97  CHECK((Math::clip<10, 20>(99)) == 20);
98 
99  CHECK((Math::clip<10, 10>( 9)) == 10);
100  CHECK((Math::clip<10, 10>(10)) == 10);
101  CHECK((Math::clip<10, 10>(11)) == 10);
102 
103  CHECK((Math::clip<-10, 10>(-20)) == -10);
104  CHECK((Math::clip<-10, 10>( -3)) == -3);
105  CHECK((Math::clip<-10, 10>( 20)) == 10);
106 
107  CHECK((Math::clip<-100, -10>(-200)) == -100);
108  CHECK((Math::clip<-100, -10>( -53)) == -53);
109  CHECK((Math::clip<-100, -10>( 200)) == -10);
110 
111  // ok, compiler error (invalid range)
112  //CHECK((Math::clip<6, 3>(1)) == 1);
113 }
114 
115 TEST_CASE("Math::clipIntToShort")
116 {
117  CHECK(Math::clipIntToShort(-100000) == -32768);
118  CHECK(Math::clipIntToShort( -32769) == -32768);
119  CHECK(Math::clipIntToShort( -32768) == -32768);
120  CHECK(Math::clipIntToShort( -32767) == -32767);
121  CHECK(Math::clipIntToShort( -10000) == -10000);
122  CHECK(Math::clipIntToShort( -10) == -10);
123  CHECK(Math::clipIntToShort( -1) == -1);
124  CHECK(Math::clipIntToShort( 0) == 0);
125  CHECK(Math::clipIntToShort( 1) == 1);
126  CHECK(Math::clipIntToShort( 10) == 10);
127  CHECK(Math::clipIntToShort( 9876) == 9876);
128  CHECK(Math::clipIntToShort( 32766) == 32766);
129  CHECK(Math::clipIntToShort( 32767) == 32767);
130  CHECK(Math::clipIntToShort( 32768) == 32767);
131  CHECK(Math::clipIntToShort( 100000) == 32767);
132 }
133 
134 TEST_CASE("Math::clipIntToByte")
135 {
136  CHECK(Math::clipIntToByte(-100) == 0);
137  CHECK(Math::clipIntToByte( -27) == 0);
138  CHECK(Math::clipIntToByte( -1) == 0);
139  CHECK(Math::clipIntToByte( 0) == 0);
140  CHECK(Math::clipIntToByte( 1) == 1);
141  CHECK(Math::clipIntToByte( 10) == 10);
142  CHECK(Math::clipIntToByte( 127) == 127);
143  CHECK(Math::clipIntToByte( 128) == 128);
144  CHECK(Math::clipIntToByte( 222) == 222);
145  CHECK(Math::clipIntToByte( 255) == 255);
146  CHECK(Math::clipIntToByte( 256) == 255);
147  CHECK(Math::clipIntToByte( 257) == 255);
148  CHECK(Math::clipIntToByte( 327) == 255);
149 }
150 
151 static unsigned classic_gcd(unsigned a, unsigned b)
152 {
153  while (unsigned t = b % a) { b = a; a = t; }
154  return a;
155 }
156 static void testGcd(unsigned a, unsigned b)
157 {
158  unsigned expected = classic_gcd(a, b);
159  CHECK(Math::gcd(a, b) == expected);
160  CHECK(Math::gcd(b, a) == expected);
161 }
162 TEST_CASE("Math::gcd")
163 {
164  testGcd(1, 1);
165  testGcd(1, 2);
166  testGcd(1, 1234500);
167  testGcd(14, 1);
168  testGcd(14, 2);
169  testGcd(14, 7);
170  testGcd(14, 21);
171  testGcd(14, 291);
172  testGcd(14, 6398);
173  testGcd(1464, 6398);
174  testGcd(1464, 6398);
175  CHECK(Math::gcd(320, 1280) == 320);
176  CHECK(Math::gcd(123 * 121972, 123 * 9710797) == 123);
177 }
178 
179 static void testReverseNBits(unsigned x, unsigned n, unsigned expected)
180 {
181  CHECK(Math::reverseNBits(x, n) == expected);
182  CHECK(Math::reverseNBits(expected, n) == x);
183 }
184 TEST_CASE("Math::reverseNBits")
185 {
186  testReverseNBits(0x0, 4, 0x0);
187  testReverseNBits(0x1, 4, 0x8);
188  testReverseNBits(0x2, 4, 0x4);
189  testReverseNBits(0x3, 4, 0xC);
190  testReverseNBits(0x4, 4, 0x2);
191  testReverseNBits(0x8, 4, 0x1);
192  testReverseNBits(0x6, 4, 0x6);
193  testReverseNBits(0xE, 4, 0x7);
194  testReverseNBits(0xF, 4, 0xF);
195  testReverseNBits(0x00012345, 22, 0x0028B120);
196  testReverseNBits(0x0010000F, 32, 0xF0000800);
197 }
198 
199 static void testReverseByte(uint8_t x, uint8_t expected)
200 {
201  CHECK(Math::reverseByte (x ) == expected);
202  CHECK(Math::reverseNBits(x, 8) == expected);
203 
204  CHECK(Math::reverseByte (expected ) == x);
205  CHECK(Math::reverseNBits(expected, 8) == x);
206 }
207 TEST_CASE("Math::reverseByte")
208 {
209  testReverseByte(0x00, 0x00);
210  testReverseByte(0x01, 0x80);
211  testReverseByte(0x02, 0x40);
212  testReverseByte(0x07, 0xE0);
213  testReverseByte(0x12, 0x48);
214  testReverseByte(0x73, 0xCE);
215  testReverseByte(0x7F, 0xFE);
216  testReverseByte(0x8C, 0x31);
217  testReverseByte(0xAB, 0xD5);
218  testReverseByte(0xE4, 0x27);
219  testReverseByte(0xF0, 0x0F);
220 }
221 
222 TEST_CASE("Math::floodRight")
223 {
224  CHECK(Math::floodRight(0) == 0);
225  CHECK(Math::floodRight(1) == 1);
226  CHECK(Math::floodRight(2) == 3);
227  CHECK(Math::floodRight(3) == 3);
228  CHECK(Math::floodRight(4) == 7);
229  CHECK(Math::floodRight(5) == 7);
230  CHECK(Math::floodRight(6) == 7);
231  CHECK(Math::floodRight(7) == 7);
232  CHECK(Math::floodRight(8) == 15);
233  CHECK(Math::floodRight(9) == 15);
234  CHECK(Math::floodRight(15) == 15);
235  CHECK(Math::floodRight(16) == 31);
236  CHECK(Math::floodRight(32) == 63);
237  CHECK(Math::floodRight(64) == 127);
238  CHECK(Math::floodRight(12345) == 16383);
239  CHECK(Math::floodRight(0x7F001234) == 0x7FFFFFFF);
240  CHECK(Math::floodRight(0x80000000) == 0xFFFFFFFF);
241  CHECK(Math::floodRight(0xF0FEDCBA) == 0xFFFFFFFF);
242  CHECK(Math::floodRight(0x1234F0FEDCBAULL) == 0x1FFFFFFFFFFFULL);
243  CHECK(Math::floodRight(uint8_t(0x12)) == uint8_t(0x1F));
244  CHECK(Math::floodRight(uint16_t(0x2512)) == uint16_t(0x3FFF));
245 }
246 
247 TEST_CASE("Math::countLeadingZeros")
248 {
249  // undefined for 0
250  CHECK(Math::countLeadingZeros(0x00000001) == 31);
251  CHECK(Math::countLeadingZeros(0x00000002) == 30);
252  CHECK(Math::countLeadingZeros(0x00000003) == 30);
253  CHECK(Math::countLeadingZeros(0x00000004) == 29);
254  CHECK(Math::countLeadingZeros(0x00000005) == 29);
255  CHECK(Math::countLeadingZeros(0x00000007) == 29);
256  CHECK(Math::countLeadingZeros(0x00000008) == 28);
257  CHECK(Math::countLeadingZeros(0x00000081) == 24);
258  CHECK(Math::countLeadingZeros(0x00000134) == 23);
259  CHECK(Math::countLeadingZeros(0x00000234) == 22);
260  CHECK(Math::countLeadingZeros(0x00008234) == 16);
261  CHECK(Math::countLeadingZeros(0x00021234) == 14);
262  CHECK(Math::countLeadingZeros(0x00421234) == 9);
263  CHECK(Math::countLeadingZeros(0x01421234) == 7);
264  CHECK(Math::countLeadingZeros(0x01421234) == 7);
265  CHECK(Math::countLeadingZeros(0x11421234) == 3);
266  CHECK(Math::countLeadingZeros(0x31421234) == 2);
267  CHECK(Math::countLeadingZeros(0x61421234) == 1);
268  CHECK(Math::countLeadingZeros(0x91421234) == 0);
269  CHECK(Math::countLeadingZeros(0xF1421234) == 0);
270 }
Math::countLeadingZeros
unsigned countLeadingZeros(unsigned x)
Count the number of leading zero-bits in the given word.
Definition: Math.hh:236
Math::floodRight
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
t
TclObject t
Definition: TclObject_test.cc:264
CHECK
CHECK(m3==m3)
Math::ispow2
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
TEST_CASE
TEST_CASE("Math::log2p1")
Definition: Math_test.cc:4
Math::clipIntToByte
uint8_t clipIntToByte(int x)
Clip x to range [0,255].
Definition: Math.hh:120
openmsx::x
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:1377
Math::log2p1
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
Math::reverseNBits
unsigned reverseNBits(unsigned x, unsigned bits)
Reverse the lower N bits of a given value.
Definition: Math.hh:163
Math::clipIntToShort
int16_t clipIntToShort(int x)
Clip x to range [-32768,32767].
Definition: Math.hh:111
Math::gcd
unsigned gcd(unsigned a, unsigned b)
Calculate greatest common divider of two strictly positive integers.
Definition: Math.hh:135
Math::reverseByte
uint8_t reverseByte(uint8_t a)
Reverse the bits in a byte.
Definition: Math.hh:213
Math.hh
Math::ceil2
constexpr T ceil2(T x) noexcept
Returns the smallest number that is both >=a and a power of two.
Definition: Math.hh:85