1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef sw_Math_hpp 16 #define sw_Math_hpp 17 18 #include "Types.hpp" 19 20 #include <cmath> 21 #if defined(_MSC_VER) 22 #include <intrin.h> 23 #endif 24 25 namespace sw 26 { 27 using std::abs; 28 29 #undef min 30 #undef max 31 32 template<class T> 33 inline T max(T a, T b) 34 { 35 return a > b ? a : b; 36 } 37 38 template<class T> 39 inline T min(T a, T b) 40 { 41 return a < b ? a : b; 42 } 43 44 template<class T> 45 inline T max(T a, T b, T c) 46 { 47 return max(max(a, b), c); 48 } 49 50 template<class T> 51 inline T min(T a, T b, T c) 52 { 53 return min(min(a, b), c); 54 } 55 56 template<class T> 57 inline T max(T a, T b, T c, T d) 58 { 59 return max(max(a, b), max(c, d)); 60 } 61 62 template<class T> 63 inline T min(T a, T b, T c, T d) 64 { 65 return min(min(a, b), min(c, d)); 66 } 67 68 template<class T> 69 inline void swap(T &a, T &b) 70 { 71 T t = a; 72 a = b; 73 b = t; 74 } 75 76 inline int iround(float x) 77 { 78 return (int)floor(x + 0.5f); 79 // return _mm_cvtss_si32(_mm_load_ss(&x)); // FIXME: Demands SSE support 80 } 81 82 inline int ifloor(float x) 83 { 84 return (int)floor(x); 85 } 86 87 inline int ceilFix4(int x) 88 { 89 return (x + 0xF) & 0xFFFFFFF0; 90 } 91 92 inline int ceilInt4(int x) 93 { 94 return (x + 0xF) >> 4; 95 } 96 97 #define BITS(x) ( \ 98 !!((x) & 0x80000000) + \ 99 !!((x) & 0xC0000000) + \ 100 !!((x) & 0xE0000000) + \ 101 !!((x) & 0xF0000000) + \ 102 !!((x) & 0xF8000000) + \ 103 !!((x) & 0xFC000000) + \ 104 !!((x) & 0xFE000000) + \ 105 !!((x) & 0xFF000000) + \ 106 !!((x) & 0xFF800000) + \ 107 !!((x) & 0xFFC00000) + \ 108 !!((x) & 0xFFE00000) + \ 109 !!((x) & 0xFFF00000) + \ 110 !!((x) & 0xFFF80000) + \ 111 !!((x) & 0xFFFC0000) + \ 112 !!((x) & 0xFFFE0000) + \ 113 !!((x) & 0xFFFF0000) + \ 114 !!((x) & 0xFFFF8000) + \ 115 !!((x) & 0xFFFFC000) + \ 116 !!((x) & 0xFFFFE000) + \ 117 !!((x) & 0xFFFFF000) + \ 118 !!((x) & 0xFFFFF800) + \ 119 !!((x) & 0xFFFFFC00) + \ 120 !!((x) & 0xFFFFFE00) + \ 121 !!((x) & 0xFFFFFF00) + \ 122 !!((x) & 0xFFFFFF80) + \ 123 !!((x) & 0xFFFFFFC0) + \ 124 !!((x) & 0xFFFFFFE0) + \ 125 !!((x) & 0xFFFFFFF0) + \ 126 !!((x) & 0xFFFFFFF8) + \ 127 !!((x) & 0xFFFFFFFC) + \ 128 !!((x) & 0xFFFFFFFE) + \ 129 !!((x) & 0xFFFFFFFF)) 130 131 #define MAX(x, y) ((x) > (y) ? (x) : (y)) 132 #define MIN(x, y) ((x) < (y) ? (x) : (y)) 133 134 inline float exp2(float x) 135 { 136 return exp2f(x); 137 } 138 139 inline int exp2(int x) 140 { 141 return 1 << x; 142 } 143 144 inline unsigned long log2(int x) 145 { 146 #if defined(_MSC_VER) 147 unsigned long y; 148 _BitScanReverse(&y, x); 149 return y; 150 #else 151 return 31 - __builtin_clz(x); 152 #endif 153 } 154 155 inline int ilog2(float x) 156 { 157 unsigned int y = *(unsigned int*)&x; 158 159 return ((y & 0x7F800000) >> 23) - 127; 160 } 161 162 inline float log2(float x) 163 { 164 return logf(x) * 1.44269504f; // 1.0 / log[e](2) 165 } 166 167 inline bool isPow2(int x) 168 { 169 return (x & -x) == x; 170 } 171 172 template<class T> 173 inline T clamp(T x, T a, T b) 174 { 175 if(x < a) x = a; 176 if(x > b) x = b; 177 178 return x; 179 } 180 181 inline float clamp01(float x) 182 { 183 return clamp(x, 0.0f, 1.0f); 184 } 185 186 inline int ceilPow2(int x) 187 { 188 int i = 1; 189 190 while(i < x) 191 { 192 i <<= 1; 193 } 194 195 return i; 196 } 197 198 inline int floorDiv(int a, int b) 199 { 200 return a / b + ((a % b) >> 31); 201 } 202 203 inline int floorMod(int a, int b) 204 { 205 int r = a % b; 206 return r + ((r >> 31) & b); 207 } 208 209 inline int ceilDiv(int a, int b) 210 { 211 return a / b - (-(a % b) >> 31); 212 } 213 214 inline int ceilMod(int a, int b) 215 { 216 int r = a % b; 217 return r - ((-r >> 31) & b); 218 } 219 220 template<const int n> 221 inline unsigned int unorm(float x) 222 { 223 static const unsigned int max = 0xFFFFFFFF >> (32 - n); 224 static const float maxf = static_cast<float>(max); 225 226 if(x >= 1.0f) 227 { 228 return max; 229 } 230 else if(x <= 0.0f) 231 { 232 return 0; 233 } 234 else 235 { 236 return static_cast<unsigned int>(maxf * x + 0.5f); 237 } 238 } 239 240 template<const int n> 241 inline int snorm(float x) 242 { 243 static const unsigned int min = 0x80000000 >> (32 - n); 244 static const unsigned int max = 0xFFFFFFFF >> (32 - n + 1); 245 static const float maxf = static_cast<float>(max); 246 static const unsigned int range = 0xFFFFFFFF >> (32 - n); 247 248 if(x >= 0.0f) 249 { 250 if(x >= 1.0f) 251 { 252 return max; 253 } 254 else 255 { 256 return static_cast<int>(maxf * x + 0.5f); 257 } 258 } 259 else 260 { 261 if(x <= -1.0f) 262 { 263 return min; 264 } 265 else 266 { 267 return static_cast<int>(maxf * x - 0.5f) & range; 268 } 269 } 270 } 271 272 template<const int n> 273 inline unsigned int ucast(float x) 274 { 275 static const unsigned int max = 0xFFFFFFFF >> (32 - n); 276 static const float maxf = static_cast<float>(max); 277 278 if(x >= maxf) 279 { 280 return max; 281 } 282 else if(x <= 0.0f) 283 { 284 return 0; 285 } 286 else 287 { 288 return static_cast<unsigned int>(x + 0.5f); 289 } 290 } 291 292 template<const int n> 293 inline int scast(float x) 294 { 295 static const unsigned int min = 0x80000000 >> (32 - n); 296 static const unsigned int max = 0xFFFFFFFF >> (32 - n + 1); 297 static const float maxf = static_cast<float>(max); 298 static const unsigned int range = 0xFFFFFFFF >> (32 - n); 299 300 if(x > 0.0f) 301 { 302 if(x >= maxf) 303 { 304 return max; 305 } 306 else 307 { 308 return static_cast<int>(maxf * x + 0.5f); 309 } 310 } 311 else 312 { 313 if(x <= -1.0f) 314 { 315 return min; 316 } 317 else 318 { 319 return static_cast<int>(maxf * x - 0.5f) & range; 320 } 321 } 322 } 323 324 inline float sRGBtoLinear(float c) 325 { 326 if(c <= 0.04045f) 327 { 328 return c * 0.07739938f; // 1.0f / 12.92f; 329 } 330 else 331 { 332 return powf((c + 0.055f) * 0.9478673f, 2.4f); // 1.0f / 1.055f 333 } 334 } 335 336 inline float linearToSRGB(float c) 337 { 338 if(c <= 0.0031308f) 339 { 340 return c * 12.92f; 341 } 342 else 343 { 344 return 1.055f * powf(c, 0.4166667f) - 0.055f; // 1.0f / 2.4f 345 } 346 } 347 348 unsigned char sRGB8toLinear8(unsigned char value); 349 350 uint64_t FNV_1a(const unsigned char *data, int size); // Fowler-Noll-Vo hash function 351 352 // Round up to the next multiple of alignment 353 inline unsigned int align(unsigned int value, unsigned int alignment) 354 { 355 return ((value + alignment - 1) / alignment) * alignment; 356 } 357 358 inline int clampToSignedInt(unsigned int x) 359 { 360 return static_cast<int>(min(x, 0x7FFFFFFFu)); 361 } 362 363 class RGB9E5Data 364 { 365 unsigned int R : 9; 366 unsigned int G : 9; 367 unsigned int B : 9; 368 unsigned int E : 5; 369 370 public: 371 void toRGBFloats(float* rgb) const 372 { 373 static const float Offset = -24.0f; // Exponent Bias (15) + Number of mantissa bits per component (9) = 24 374 375 const float factor = powf(2.0f, static_cast<float>(E) + Offset); 376 rgb[0] = static_cast<float>(R) * factor; 377 rgb[1] = static_cast<float>(G) * factor; 378 rgb[2] = static_cast<float>(B) * factor; 379 } 380 }; 381 382 class R11G11B10FData 383 { 384 unsigned int R : 11; 385 unsigned int G : 11; 386 unsigned int B : 10; 387 388 static inline float float11ToFloat32(unsigned short fp11) 389 { 390 unsigned short exponent = (fp11 >> 6) & 0x1F; 391 unsigned short mantissa = fp11 & 0x3F; 392 393 unsigned int output; 394 if(exponent == 0x1F) 395 { 396 // INF or NAN 397 output = 0x7f800000 | (mantissa << 17); 398 } 399 else 400 { 401 if(exponent != 0) 402 { 403 // normalized 404 } 405 else if(mantissa != 0) 406 { 407 // The value is denormalized 408 exponent = 1; 409 410 do 411 { 412 exponent--; 413 mantissa <<= 1; 414 } while((mantissa & 0x40) == 0); 415 416 mantissa = mantissa & 0x3F; 417 } 418 else // The value is zero 419 { 420 exponent = static_cast<unsigned short>(-112); 421 } 422 423 output = ((exponent + 112) << 23) | (mantissa << 17); 424 } 425 426 return *(float*)(&output); 427 } 428 429 static inline float float10ToFloat32(unsigned short fp10) 430 { 431 unsigned short exponent = (fp10 >> 5) & 0x1F; 432 unsigned short mantissa = fp10 & 0x1F; 433 434 unsigned int output; 435 if(exponent == 0x1F) 436 { 437 // INF or NAN 438 output = 0x7f800000 | (mantissa << 17); 439 } 440 else 441 { 442 if(exponent != 0) 443 { 444 // normalized 445 } 446 else if(mantissa != 0) 447 { 448 // The value is denormalized 449 exponent = 1; 450 451 do 452 { 453 exponent--; 454 mantissa <<= 1; 455 } while((mantissa & 0x20) == 0); 456 457 mantissa = mantissa & 0x1F; 458 } 459 else // The value is zero 460 { 461 exponent = static_cast<unsigned short>(-112); 462 } 463 464 output = ((exponent + 112) << 23) | (mantissa << 18); 465 } 466 467 return *(float*)(&output); 468 } 469 470 public: 471 void toRGBFloats(float* rgb) const 472 { 473 rgb[0] = float11ToFloat32(R); 474 rgb[1] = float11ToFloat32(G); 475 rgb[2] = float10ToFloat32(B); 476 } 477 }; 478 } 479 480 #endif // sw_Math_hpp 481