1 /*
2  * Copyright 2010-2019 Branimir Karadzic. All rights reserved.
3  * License: https://github.com/bkaradzic/bx#license-bsd-2-clause
4  */
5 
6 #include "test.h"
7 #include <bx/math.h>
8 #include <bx/file.h>
9 
10 #include <math.h>
11 
12 #if !BX_COMPILER_MSVC || BX_COMPILER_MSVC >= 1800
13 TEST_CASE("isFinite, isInfinite, isNan", "")
14 {
15 	for (uint64_t ii = 0; ii < UINT32_MAX; ii += rand()%(1<<13)+1)
16 	{
17 		union { uint32_t ui; float f; } u = { uint32_t(ii) };
18 		REQUIRE(std::isnan(u.f)    == bx::isNan(u.f) );
19 		REQUIRE(std::isfinite(u.f) == bx::isFinite(u.f) );
20 		REQUIRE(std::isinf(u.f)    == bx::isInfinite(u.f) );
21 	}
22 }
23 #endif // !BX_COMPILER_MSVC || BX_COMPILER_MSVC >= 1800
24 
log2_test(float _a)25 bool log2_test(float _a)
26 {
27 	return bx::log2(_a) == bx::log(_a) * (1.0f / bx::log(2.0f) );
28 }
29 
30 TEST_CASE("log2", "")
31 {
32 	log2_test(0.0f);
33 	log2_test(256.0f);
34 
35 	REQUIRE(0.0f == bx::log2(1.0f) );
36 	REQUIRE(0 == bx::log2(1) );
37 
38 	REQUIRE(1.0f == bx::log2(2.0f) );
39 	REQUIRE(1 == bx::log2(2) );
40 
41 	REQUIRE(2.0f == bx::log2(4.0f) );
42 	REQUIRE(2 == bx::log2(4) );
43 
44 	REQUIRE(3.0f == bx::log2(8.0f) );
45 	REQUIRE(3 == bx::log2(8) );
46 
47 	REQUIRE(4.0f == bx::log2(16.0f) );
48 	REQUIRE(4 == bx::log2(16) );
49 
50 	REQUIRE(5.0f == bx::log2(32.0f) );
51 	REQUIRE(5 == bx::log2(32) );
52 
53 	REQUIRE(6.0f == bx::log2(64.0f) );
54 	REQUIRE(6 == bx::log2(64) );
55 
56 	REQUIRE(7.0f == bx::log2(128.0f) );
57 	REQUIRE(7 == bx::log2(128) );
58 
59 	REQUIRE(8.0f == bx::log2(256.0f) );
60 	REQUIRE(8 == bx::log2(256) );
61 }
62 
63 TEST_CASE("libm", "")
64 {
65 	bx::WriterI* writer = bx::getNullOut();
66 
67 	REQUIRE(1389.0f == bx::abs(-1389.0f) );
68 	REQUIRE(1389.0f == bx::abs( 1389.0f) );
69 	REQUIRE(   0.0f == bx::abs(-0.0f) );
70 	REQUIRE(   0.0f == bx::abs( 0.0f) );
71 
72 	REQUIRE(389.0f == bx::mod(1389.0f, 1000.0f) );
73 	REQUIRE(bx::isNan(bx::mod(0.0f, 0.0f) ) );
74 
75 	REQUIRE( 13.0f == bx::floor( 13.89f) );
76 	REQUIRE(-14.0f == bx::floor(-13.89f) );
77 	REQUIRE( 14.0f == bx::ceil(  13.89f) );
78 	REQUIRE(-13.0f == bx::ceil( -13.89f) );
79 
80 	REQUIRE( 13.0f == bx::trunc( 13.89f) );
81 	REQUIRE(-13.0f == bx::trunc(-13.89f) );
82 	REQUIRE(bx::equal( 0.89f, bx::fract( 13.89f), 0.000001f) );
83 	REQUIRE(bx::equal(-0.89f, bx::fract(-13.89f), 0.000001f) );
84 
85 	bx::Error err;
86 
87 	for (int32_t yy = -10; yy < 10; ++yy)
88 	{
89 		for (float xx = -100.0f; xx < 100.0f; xx += 0.1f)
90 		{
91 			bx::write(writer, &err, "ldexp(%f, %d) == %f (expected: %f)\n", xx, yy, bx::ldexp(xx, yy), ::ldexpf(xx, yy) );
92 			REQUIRE(bx::equal(bx::ldexp(xx, yy), ::ldexpf(xx, yy), 0.00001f) );
93 		}
94 	}
95 
96 	for (float xx = -80.0f; xx < 80.0f; xx += 0.1f)
97 	{
98 		bx::write(writer, &err, "exp(%f) == %f (expected: %f)\n", xx, bx::exp(xx), ::expf(xx) );
99 		REQUIRE(err.isOk() );
100 		REQUIRE(bx::equal(bx::exp(xx), ::expf(xx), 0.00001f) );
101 	}
102 
103 	for (float xx = 0.0f; xx < 100.0f; xx += 0.1f)
104 	{
105 		bx::write(writer, &err, "rsqrt(%f) == %f (expected: %f)\n", xx, bx::rsqrt(xx), 1.0f/::sqrtf(xx) );
106 		REQUIRE(err.isOk() );
107 		REQUIRE(bx::equal(bx::rsqrt(xx), 1.0f/::sqrtf(xx), 0.00001f) );
108 	}
109 
110 	for (float xx = 0.0f; xx < 100.0f; xx += 0.1f)
111 	{
112 		bx::write(writer, &err, "sqrt(%f) == %f (expected: %f)\n", xx, bx::sqrt(xx), ::sqrtf(xx) );
113 		REQUIRE(err.isOk() );
114 		REQUIRE(bx::equal(bx::sqrt(xx), ::sqrtf(xx), 0.00001f) );
115 	}
116 
117 	for (float xx = -100.0f; xx < 100.0f; xx += 0.1f)
118 	{
119 		bx::write(writer, &err, "pow(1.389f, %f) == %f (expected: %f)\n", xx, bx::pow(1.389f, xx), ::powf(1.389f, xx) );
120 		REQUIRE(err.isOk() );
121 		REQUIRE(bx::equal(bx::pow(1.389f, xx), ::powf(1.389f, xx), 0.00001f) );
122 	}
123 
124 	for (float xx = -1.0f; xx < 1.0f; xx += 0.001f)
125 	{
126 		bx::write(writer, &err, "asin(%f) == %f (expected: %f)\n", xx, bx::asin(xx), ::asinf(xx) );
127 		REQUIRE(err.isOk() );
128 		REQUIRE(bx::equal(bx::asin(xx), ::asinf(xx), 0.0001f) );
129 	}
130 
131 	for (float xx = -100.0f; xx < 100.0f; xx += 0.1f)
132 	{
133 		bx::write(writer, &err, "sin(%f) == %f (expected: %f)\n", xx, bx::sin(xx), ::sinf(xx) );
134 		REQUIRE(err.isOk() );
135 		REQUIRE(bx::equal(bx::sin(xx), ::sinf(xx), 0.00001f) );
136 	}
137 
138 	for (float xx = -1.0f; xx < 1.0f; xx += 0.1f)
139 	{
140 		bx::write(writer, &err, "sinh(%f) == %f (expected: %f)\n", xx, bx::sinh(xx), ::sinhf(xx) );
141 		REQUIRE(err.isOk() );
142 		REQUIRE(bx::equal(bx::sinh(xx), ::sinhf(xx), 0.00001f) );
143 	}
144 
145 	for (float xx = -1.0f; xx < 1.0f; xx += 0.001f)
146 	{
147 		bx::write(writer, &err, "acos(%f) == %f (expected: %f\n)", xx, bx::acos(xx), ::acosf(xx) );
148 		REQUIRE(err.isOk() );
149 		REQUIRE(bx::equal(bx::acos(xx), ::acosf(xx), 0.0001f) );
150 	}
151 
152 	for (float xx = -100.0f; xx < 100.0f; xx += 0.1f)
153 	{
154 		bx::write(writer, &err, "cos(%f) == %f (expected: %f)\n", xx, bx::cos(xx), ::cosf(xx) );
155 		REQUIRE(err.isOk() );
156 		REQUIRE(bx::equal(bx::cos(xx), ::cosf(xx), 0.00001f) );
157 	}
158 
159 	for (float xx = -100.0f; xx < 100.0f; xx += 0.1f)
160 	{
161 		bx::write(writer, &err, "tan(%f) == %f (expected: %f)\n", xx, bx::tan(xx), ::tanf(xx) );
162 		REQUIRE(err.isOk() );
163 		REQUIRE(bx::equal(bx::tan(xx), ::tanf(xx), 0.001f) );
164 	}
165 
166 	for (float xx = -1.0f; xx < 1.0f; xx += 0.1f)
167 	{
168 		bx::write(writer, &err, "tanh(%f) == %f (expected: %f\n", xx, bx::tanh(xx), ::tanhf(xx) );
169 		REQUIRE(err.isOk() );
170 		REQUIRE(bx::equal(bx::tanh(xx), ::tanhf(xx), 0.00001f) );
171 	}
172 
173 	for (float xx = -100.0f; xx < 100.0f; xx += 0.1f)
174 	{
175 		bx::write(writer, &err, "atan(%f) == %f (expected: %f)\n", xx, bx::atan(xx), ::atanf(xx) );
176 		REQUIRE(err.isOk() );
177 		REQUIRE(bx::equal(bx::atan(xx), ::atanf(xx), 0.00001f) );
178 	}
179 
180 	for (float yy = -100.0f; yy < 100.0f; yy += 0.1f)
181 	{
182 		for (float xx = -100.0f; xx < 100.0f; xx += 0.1f)
183 		{
184 			bx::write(writer, &err, "atan2(%f, %f) == %f (expected: %f)\n", yy, xx, bx::atan2(yy, xx), ::atan2f(yy, xx) );
185 			REQUIRE(err.isOk() );
186 			REQUIRE(bx::equal(bx::atan2(yy, xx), ::atan2f(yy, xx), 0.00001f) );
187 		}
188 	}
189 
190 	REQUIRE(bx::equal(bx::atan2(0.0f, 0.0f), ::atan2f(0.0f, 0.0f), 0.00001f) );
191 }
192 
193 TEST_CASE("ToBits", "")
194 {
195 	REQUIRE(UINT32_C(0x12345678)         == bx::floatToBits( bx::bitsToFloat( UINT32_C(0x12345678) ) ) );
196 	REQUIRE(UINT64_C(0x123456789abcdef0) == bx::doubleToBits(bx::bitsToDouble(UINT32_C(0x123456789abcdef0) ) ) );
197 }
198 
mtxCheck(const float * _a,const float * _b)199 void mtxCheck(const float* _a, const float* _b)
200 {
201 	if (!bx::equal(_a, _b, 16, 0.01f) )
202 	{
203 		DBG("\n"
204 			"A:\n"
205 			"%10.4f %10.4f %10.4f %10.4f\n"
206 			"%10.4f %10.4f %10.4f %10.4f\n"
207 			"%10.4f %10.4f %10.4f %10.4f\n"
208 			"%10.4f %10.4f %10.4f %10.4f\n"
209 			"B:\n"
210 			"%10.4f %10.4f %10.4f %10.4f\n"
211 			"%10.4f %10.4f %10.4f %10.4f\n"
212 			"%10.4f %10.4f %10.4f %10.4f\n"
213 			"%10.4f %10.4f %10.4f %10.4f\n"
214 			, _a[ 0], _a[ 1], _a[ 2], _a[ 3]
215 			, _a[ 4], _a[ 5], _a[ 6], _a[ 7]
216 			, _a[ 8], _a[ 9], _a[10], _a[11]
217 			, _a[12], _a[13], _a[14], _a[15]
218 			, _b[ 0], _b[ 1], _b[ 2], _b[ 3]
219 			, _b[ 4], _b[ 5], _b[ 6], _b[ 7]
220 			, _b[ 8], _b[ 9], _b[10], _b[11]
221 			, _b[12], _b[13], _b[14], _b[15]
222 			);
223 
224 		CHECK(false);
225 	}
226 }
227 
228 TEST_CASE("quaternion", "")
229 {
230 	float mtxQ[16];
231 	float mtx[16];
232 
233 	bx::Quaternion quat = { 0.0f, 0.0f, 0.0f, 1.0f };
234 	bx::mtxQuat(mtxQ, quat);
235 	bx::mtxIdentity(mtx);
236 	mtxCheck(mtxQ, mtx);
237 
238 	float ax = bx::kPi/27.0f;
239 	float ay = bx::kPi/13.0f;
240 	float az = bx::kPi/7.0f;
241 
242 	quat = bx::rotateX(ax);
243 	bx::mtxQuat(mtxQ, quat);
244 	bx::mtxRotateX(mtx, ax);
245 	mtxCheck(mtxQ, mtx);
246 
247 	bx::Vec3 euler = bx::toEuler(quat);
248 	CHECK(bx::equal(euler.x, ax, 0.001f) );
249 
250 	quat = bx::rotateY(ay);
251 	bx::mtxQuat(mtxQ, quat);
252 	bx::mtxRotateY(mtx, ay);
253 	mtxCheck(mtxQ, mtx);
254 
255 	euler = bx::toEuler(quat);
256 	CHECK(bx::equal(euler.y, ay, 0.001f) );
257 
258 	quat = bx::rotateZ(az);
259 	bx::mtxQuat(mtxQ, quat);
260 	bx::mtxRotateZ(mtx, az);
261 	mtxCheck(mtxQ, mtx);
262 
263 	euler = bx::toEuler(quat);
264 	CHECK(bx::equal(euler.z, az, 0.001f) );
265 }
266