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