tcuVectorUtil.hpp revision 3c827367444ee418f129b2c238299f49d3264554
1#ifndef _TCUVECTORUTIL_HPP
2#define _TCUVECTORUTIL_HPP
3/*-------------------------------------------------------------------------
4 * drawElements Quality Program Tester Core
5 * ----------------------------------------
6 *
7 * Copyright 2014 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Vector utility functions.
24 *//*--------------------------------------------------------------------*/
25
26#include "tcuDefs.hpp"
27#include "tcuVector.hpp"
28#include "deMath.h"
29#include "deInt32.h"
30
31#include <ostream>
32#include <math.h>
33
34namespace tcu
35{
36
37static const float PI = 3.141592653589793238f;
38
39#if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_WIN32 && DE_COMPILER == DE_COMPILER_CLANG)
40inline float abs			(float f) { return deFloatAbs(f); }
41#endif
42
43template<typename T> inline T add			(T a, T b) { return a + b; }
44template<typename T> inline T sub			(T a, T b) { return a - b; }
45template<typename T> inline T mul			(T a, T b) { return a * b; }
46template<typename T> inline T div			(T a, T b) { return a / b; }
47
48template<typename T> inline T bitwiseNot	(T a)		{ return ~a; }
49template<typename T> inline T bitwiseAnd	(T a, T b)	{ return a & b; }
50template<typename T> inline T bitwiseOr		(T a, T b)	{ return a | b; }
51template<typename T> inline T bitwiseXor	(T a, T b)	{ return a ^ b; }
52
53template<typename T> inline T logicalNot	(T a)		{ return !a; }
54template<typename T> inline T logicalAnd	(T a, T b)	{ return a && b; }
55template<typename T> inline T logicalOr		(T a, T b)	{ return a || b; }
56
57template<typename T>	inline T		mod		(T a, T b)			{ return a % b; }
58template<>				inline float	mod		(float x, float y)	{ return x - y * floor(x / y); }
59
60template<typename T>	inline	T			negate				(T f)			{ return -f; }
61template<>				inline	deUint32	negate<deUint32>	(deUint32 f)	{ return (deUint32)-(int)f;	}
62
63inline float radians		(float f) { return deFloatRadians(f); }
64inline float degrees		(float f) { return deFloatDegrees(f); }
65inline float exp2			(float f) { return deFloatExp2(f); }
66inline float log2			(float f) { return deFloatLog2(f); }
67inline float inverseSqrt	(float f) { return deFloatRsq(f); }
68inline float sign			(float f) { return (f < 0.0f) ? -1.0f : ((f > 0.0f) ? +1.0f : 0.0f); }
69inline float fract			(float f) { return f - deFloatFloor(f); }
70inline float mix			(float x, float y, float a) { return x * (1.0f - a) + y * a; }
71inline float step			(float edge, float x) { return (x < edge) ? 0.0f : 1.0f; }
72inline float smoothStep		(float edge0, float edge1, float x)
73{
74	if (x <= edge0) return 0.0f;
75	if (x >= edge1) return 1.0f;
76	float t = de::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
77	return t * t * (3.0f - 2.0f * t);
78}
79
80inline float length			(float f) { return deFloatAbs(f); }
81inline float distance		(float x, float y) { return deFloatAbs(x - y); }
82inline float dot			(float x, float y) { return (x * y); }
83
84inline float normalize		(float f) { return sign(f); }
85inline float faceForward	(float n, float i, float ref) { return ((ref * i) < 0.0f) ? n : -n; }
86inline float reflect		(float i, float n) { return i - 2.0f * (n * i) * n; }
87inline float refract		(float i, float n, float eta)
88{
89	float cosAngle = (n * i);
90	float k = 1.0f - eta * eta * (1.0f - cosAngle * cosAngle);
91	if (k < 0.0f)
92		return 0.0f;
93	else
94		return eta * i - (eta * cosAngle + ::sqrt(k)) * n;
95}
96
97inline float asinh			(float a) { return deFloatAsinh(a); }
98inline float acosh			(float a) { return deFloatAcosh(a); }
99inline float atanh			(float a) { return deFloatAtanh(a); }
100
101template<typename T> inline bool	lessThan			(T a, T b) { return (a < b); }
102template<typename T> inline bool	lessThanEqual		(T a, T b) { return (a <= b); }
103template<typename T> inline bool	greaterThan			(T a, T b) { return (a > b); }
104template<typename T> inline bool	greaterThanEqual	(T a, T b) { return (a >= b); }
105template<typename T> inline bool	equal				(T a, T b) { return (a == b); }
106template<typename T> inline bool	notEqual			(T a, T b) { return (a != b); }
107template<typename T> inline bool	allEqual			(T a, T b) { return (a == b); }
108template<typename T> inline bool	anyNotEqual			(T a, T b) { return (a != b); }
109
110inline bool boolNot				(bool a) { return !a; }
111
112inline int chopToInt			(float a) { return deChopFloatToInt32(a); }
113
114inline float trunc				(float a) { return (float)chopToInt(a); }
115
116inline float roundToEven (float a)
117{
118	float q = deFloatFrac(a);
119	float r = a-q;
120
121	if (q > 0.5f)
122		r += 1.0f;
123	else if (q == 0.5 && (((int)r) % 2 != 0))
124		r += 1.0f;
125
126	return r;
127}
128
129template <typename T, int Size>
130inline T dot (const Vector<T, Size>& a, const Vector<T, Size>& b)
131{
132	T res = T();
133	for (int i = 0; i < Size; i++)
134		res += a.m_data[i] * b.m_data[i];
135	return res;
136}
137
138template <typename T, int Size>
139inline T lengthSquared (const Vector<T, Size>& a)
140{
141	T sqSum = T();
142	for (int i = 0; i < Size; i++)
143		sqSum += a.m_data[i] * a.m_data[i];
144	return sqSum;
145}
146
147template <typename T, int Size>
148inline T length (const Vector<T, Size>& a)
149{
150	return ::sqrt(lengthSquared(a));
151}
152
153template <typename T, int Size>
154inline T distance (const Vector<T, Size>& a, const Vector<T, Size>& b)
155{
156	return length(a - b);
157}
158
159template <typename T, int Size>
160inline Vector<T, Size> cross (const Vector<T, Size>& a, const Vector<T, Size>& b)
161{
162	DE_STATIC_ASSERT(Size == 3);
163	return Vector<T, Size>(
164		a.y() * b.z() - b.y() * a.z(),
165		a.z() * b.x() - b.z() * a.x(),
166		a.x() * b.y() - b.x() * a.y());
167}
168
169template <typename T, int Size>
170inline Vector<T, Size> normalize (const Vector<T, Size>& a)
171{
172	T ooLen = T(1) / length(a);
173	Vector<T, Size> res;
174	for (int i = 0; i < Size; i++)
175		res.m_data[i] = ooLen * a.m_data[i];
176	return res;
177}
178
179template <typename T, int Size>
180inline Vector<T, Size> faceForward (const Vector<T, Size>& n, const Vector<T, Size>& i, const Vector<T, Size>& ref)
181{
182	return (dot(ref, i) < T(0)) ? n: -n;
183}
184
185template <typename T, int Size>
186inline Vector<T, Size> reflect (const Vector<T, Size>& i, const Vector<T, Size>& n)
187{
188	return i - T(2) * dot(n, i) * n;
189}
190
191template <typename T, int Size>
192inline Vector<T, Size> refract (const Vector<T, Size>& i, const Vector<T, Size>& n, T eta)
193{
194	Vector<T, Size> res;
195	T cosAngle = dot(n, i);
196	T k = T(1) - eta * eta * (T(1) - cosAngle * cosAngle);
197	if (k < T(0))
198		return Vector<T, Size>(T(0));
199	else
200		return i * eta - n * T(eta * cosAngle + ::sqrt(k));
201}
202
203template <int Size>
204Vector<float, Size> mix (const Vector<float, Size>& x, const Vector<float, Size>& y, float a)
205{
206	Vector<float, Size> res;
207	for (int i = 0; i < Size; i++)
208		res.m_data[i] = deFloatMix(x.m_data[i], y.m_data[i], a);
209	return res;
210}
211
212// Piece-wise compare operators.
213
214template <typename T, int Size>
215inline Vector<bool, Size> equal (const Vector<T, Size>& a, const Vector<T, Size>& b)
216{
217	Vector<bool, Size> res;
218	for (int i = 0; i < Size; i++)
219		res.m_data[i] = a.m_data[i] == b.m_data[i];
220	return res;
221}
222
223template <typename T, int Size>
224inline Vector<bool, Size> notEqual (const Vector<T, Size>& a, const Vector<T, Size>& b)
225{
226	Vector<bool, Size> res;
227	for (int i = 0; i < Size; i++)
228		res.m_data[i] = a.m_data[i] != b.m_data[i];
229	return res;
230}
231
232template <typename T, int Size>
233inline Vector<bool, Size> lessThan (const Vector<T, Size>& a, const Vector<T, Size>& b)
234{
235	Vector<bool, Size> res;
236	for (int i = 0; i < Size; i++)
237		res.m_data[i] = a.m_data[i] < b.m_data[i];
238	return res;
239}
240
241template <typename T, int Size>
242inline Vector<bool, Size> lessThanEqual (const Vector<T, Size>& a, const Vector<T, Size>& b)
243{
244	Vector<bool, Size> res;
245	for (int i = 0; i < Size; i++)
246		res.m_data[i] = a.m_data[i] <= b.m_data[i];
247	return res;
248}
249
250template <typename T, int Size>
251inline Vector<bool, Size> greaterThan (const Vector<T, Size>& a, const Vector<T, Size>& b)
252{
253	Vector<bool, Size> res;
254	for (int i = 0; i < Size; i++)
255		res.m_data[i] = a.m_data[i] > b.m_data[i];
256	return res;
257}
258
259template <typename T, int Size>
260inline Vector<bool, Size> greaterThanEqual (const Vector<T, Size>& a, const Vector<T, Size>& b)
261{
262	Vector<bool, Size> res;
263	for (int i = 0; i < Size; i++)
264		res.m_data[i] = a.m_data[i] >= b.m_data[i];
265	return res;
266}
267
268// Equality comparison operators.
269
270template <typename T, int Size>
271inline bool allEqual (const Vector<T, Size>& a, const Vector<T, Size>& b)
272{
273	bool res = true;
274	for (int i = 0; i < Size; i++)
275		res = res && a.m_data[i] == b.m_data[i];
276	return res;
277}
278
279template <typename T, int Size>
280inline bool anyNotEqual (const Vector<T, Size>& a, const Vector<T, Size>& b)
281{
282	bool res = false;
283	for (int i = 0; i < Size; i++)
284		res = res || a.m_data[i] != b.m_data[i];
285	return res;
286}
287
288// Boolean built-ins.
289
290template <int Size>
291inline Vector<bool, Size> boolNot (const Vector<bool, Size>& a)
292{
293	Vector<bool, Size> res;
294	for (int i = 0; i < Size; i++)
295		res.m_data[i] = !a.m_data[i];
296	return res;
297}
298
299template <int Size>
300inline bool boolAny (const Vector<bool, Size>& a)
301{
302	for (int i = 0; i < Size; i++)
303		if (a.m_data[i] == true)
304			return true;
305	return false;
306}
307
308template <int Size>
309inline bool boolAll (const Vector<bool, Size>& a)
310{
311	for (int i = 0; i < Size; i++)
312		if (a.m_data[i] == false)
313			return false;
314	return true;
315}
316
317template <int Size>
318Vector<int, Size> chopToInt (const Vector<float, Size>& v)
319{
320	Vector<int, Size> res;
321	for (int i = 0; i < Size; i++)
322		res.m_data[i] = chopToInt(v.m_data[i]);
323	return res;
324}
325
326// Vector construction using selection based on boolean vector.
327
328template <typename T, int Size>
329inline Vector<T, Size> select (T trueVal, T falseVal, const Vector<bool, Size>& cond)
330{
331	Vector<T, Size> res;
332	for (int i = 0; i < Size; i++)
333		res[i] = cond[i] ? trueVal : falseVal;
334	return res;
335}
336
337// Component-wise selection.
338
339template <typename T, int Size>
340inline Vector<T, Size> select (const Vector<T, Size>& trueVal, const Vector<T, Size>& falseVal, const Vector<bool, Size>& cond)
341{
342	Vector<T, Size> res;
343	for (int i = 0; i < Size; i++)
344		res[i] = cond[i] ? trueVal[i] : falseVal[i];
345	return res;
346}
347
348// Absolute difference (abs(a - b))
349
350template<typename T, int Size>
351static inline Vector<T, Size> absDiff (const Vector<T, Size>& a, const Vector<T, Size>& b)
352{
353	Vector<T, Size> res;
354
355	for (int ndx = 0; ndx < Size; ndx++)
356		res[ndx] = (a[ndx] > b[ndx]) ? (a[ndx] - b[ndx]) : (b[ndx] - a[ndx]);
357
358	return res;
359}
360
361// Macros for component-wise ops.
362
363#define TCU_DECLARE_VECTOR_UNARY_FUNC(FUNC_NAME, OP_NAME)	\
364template <typename T, int Size>								\
365Vector<T, Size> FUNC_NAME (const Vector<T, Size>& v)		\
366{															\
367	Vector<T, Size> res;									\
368	for (int i = 0; i < Size; i++)							\
369		res.m_data[i] = OP_NAME(v.m_data[i]);				\
370	return res;												\
371}
372
373#define TCU_DECLARE_VECTOR_BINARY_FUNC(FUNC_NAME, OP_NAME)						\
374template <typename T, int Size>													\
375Vector<T, Size> FUNC_NAME (const Vector<T, Size>& a, const Vector<T, Size>& b)	\
376{																				\
377	Vector<T, Size> res;														\
378	for (int i = 0; i < Size; i++)												\
379		res.m_data[i] = OP_NAME(a.m_data[i], b.m_data[i]);						\
380	return res;																	\
381}
382
383#define TCU_DECLARE_VECTOR_TERNARY_FUNC(FUNC_NAME, OP_NAME)													\
384template <typename T, int Size>																				\
385Vector<T, Size> FUNC_NAME (const Vector<T, Size>& a, const Vector<T, Size>& b, const Vector<T, Size>& c)	\
386{																											\
387	Vector<T, Size> res;																					\
388	for (int i = 0; i < Size; i++)																			\
389		res.m_data[i] = OP_NAME(a.m_data[i], b.m_data[i], c.m_data[i]);										\
390	return res;																								\
391}
392
393// \todo [2011-07-01 pyry] Add some prefix to vector funcs and remove this hack.
394#if defined(min)
395#	undef min
396#endif
397#if defined(max)
398#	undef max
399#endif
400
401TCU_DECLARE_VECTOR_UNARY_FUNC(negate, negate)
402TCU_DECLARE_VECTOR_UNARY_FUNC(bitwiseNot, bitwiseNot)
403TCU_DECLARE_VECTOR_BINARY_FUNC(add, add)
404TCU_DECLARE_VECTOR_BINARY_FUNC(sub, sub)
405TCU_DECLARE_VECTOR_BINARY_FUNC(mul, mul)
406TCU_DECLARE_VECTOR_BINARY_FUNC(div, div)
407TCU_DECLARE_VECTOR_BINARY_FUNC(mod, mod)
408TCU_DECLARE_VECTOR_BINARY_FUNC(bitwiseAnd, bitwiseAnd)
409TCU_DECLARE_VECTOR_BINARY_FUNC(bitwiseOr, bitwiseOr)
410TCU_DECLARE_VECTOR_BINARY_FUNC(bitwiseXor, bitwiseXor)
411TCU_DECLARE_VECTOR_UNARY_FUNC(logicalNot, logicalNot)
412TCU_DECLARE_VECTOR_BINARY_FUNC(logicalAnd, logicalAnd)
413TCU_DECLARE_VECTOR_BINARY_FUNC(logicalOr, logicalOr)
414
415TCU_DECLARE_VECTOR_UNARY_FUNC(radians, deFloatRadians)
416TCU_DECLARE_VECTOR_UNARY_FUNC(degrees, deFloatDegrees)
417TCU_DECLARE_VECTOR_UNARY_FUNC(sin, deFloatSin)
418TCU_DECLARE_VECTOR_UNARY_FUNC(cos, deFloatCos)
419TCU_DECLARE_VECTOR_UNARY_FUNC(tan, deFloatTan)
420TCU_DECLARE_VECTOR_UNARY_FUNC(asin, deFloatAsin)
421TCU_DECLARE_VECTOR_UNARY_FUNC(acos, deFloatAcos)
422TCU_DECLARE_VECTOR_UNARY_FUNC(atan, deFloatAtanOver)
423TCU_DECLARE_VECTOR_BINARY_FUNC(atan2, deFloatAtan2)
424TCU_DECLARE_VECTOR_UNARY_FUNC(sinh, deFloatSinh)
425TCU_DECLARE_VECTOR_UNARY_FUNC(cosh, deFloatCosh)
426TCU_DECLARE_VECTOR_UNARY_FUNC(tanh, deFloatTanh)
427TCU_DECLARE_VECTOR_UNARY_FUNC(asinh, deFloatAsinh)
428TCU_DECLARE_VECTOR_UNARY_FUNC(acosh, deFloatAcosh)
429TCU_DECLARE_VECTOR_UNARY_FUNC(atanh, deFloatAtanh)
430
431TCU_DECLARE_VECTOR_BINARY_FUNC(pow, deFloatPow)
432TCU_DECLARE_VECTOR_UNARY_FUNC(exp, deFloatExp)
433TCU_DECLARE_VECTOR_UNARY_FUNC(log, deFloatLog)
434TCU_DECLARE_VECTOR_UNARY_FUNC(exp2, deFloatExp2)
435TCU_DECLARE_VECTOR_UNARY_FUNC(log2, deFloatLog2)
436TCU_DECLARE_VECTOR_UNARY_FUNC(sqrt, deFloatSqrt)
437TCU_DECLARE_VECTOR_UNARY_FUNC(inverseSqrt, deFloatRsq)
438
439TCU_DECLARE_VECTOR_UNARY_FUNC(abs, de::abs)
440TCU_DECLARE_VECTOR_UNARY_FUNC(sign, deFloatSign)
441TCU_DECLARE_VECTOR_UNARY_FUNC(floor, deFloatFloor)
442TCU_DECLARE_VECTOR_UNARY_FUNC(trunc, trunc)
443TCU_DECLARE_VECTOR_UNARY_FUNC(roundToEven, roundToEven)
444TCU_DECLARE_VECTOR_UNARY_FUNC(ceil, deFloatCeil)
445TCU_DECLARE_VECTOR_UNARY_FUNC(fract, deFloatFrac)
446TCU_DECLARE_VECTOR_BINARY_FUNC(min, de::min)
447TCU_DECLARE_VECTOR_BINARY_FUNC(max, de::max)
448TCU_DECLARE_VECTOR_TERNARY_FUNC(clamp, de::clamp)
449TCU_DECLARE_VECTOR_TERNARY_FUNC(mix, deFloatMix)
450TCU_DECLARE_VECTOR_BINARY_FUNC(step, deFloatStep)
451TCU_DECLARE_VECTOR_TERNARY_FUNC(smoothStep, deFloatSmoothStep)
452
453} // tcu
454
455#endif // _TCUVECTORUTIL_HPP
456