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 #include "Half.hpp" 20 21 #include <cmath> 22 #if defined(_MSC_VER) 23 #include <intrin.h> 24 #endif 25 26 namespace sw 27 { 28 using std::abs; 29 30 #undef min 31 #undef max 32 33 template<class T> max(T a,T b)34 inline T max(T a, T b) 35 { 36 return a > b ? a : b; 37 } 38 39 template<class T> min(T a,T b)40 inline T min(T a, T b) 41 { 42 return a < b ? a : b; 43 } 44 45 template<class T> max(T a,T b,T c)46 inline T max(T a, T b, T c) 47 { 48 return max(max(a, b), c); 49 } 50 51 template<class T> min(T a,T b,T c)52 inline T min(T a, T b, T c) 53 { 54 return min(min(a, b), c); 55 } 56 57 template<class T> max(T a,T b,T c,T d)58 inline T max(T a, T b, T c, T d) 59 { 60 return max(max(a, b), max(c, d)); 61 } 62 63 template<class T> min(T a,T b,T c,T d)64 inline T min(T a, T b, T c, T d) 65 { 66 return min(min(a, b), min(c, d)); 67 } 68 69 template<class T> swap(T & a,T & b)70 inline void swap(T &a, T &b) 71 { 72 T t = a; 73 a = b; 74 b = t; 75 } 76 77 template <typename destType, typename sourceType> bitCast(const sourceType & source)78 destType bitCast(const sourceType &source) 79 { 80 union 81 { 82 sourceType s; 83 destType d; 84 } sd; 85 sd.s = source; 86 return sd.d; 87 } 88 iround(float x)89 inline int iround(float x) 90 { 91 return (int)floor(x + 0.5f); 92 // return _mm_cvtss_si32(_mm_load_ss(&x)); // FIXME: Demands SSE support 93 } 94 ifloor(float x)95 inline int ifloor(float x) 96 { 97 return (int)floor(x); 98 } 99 ceilFix4(int x)100 inline int ceilFix4(int x) 101 { 102 return (x + 0xF) & 0xFFFFFFF0; 103 } 104 ceilInt4(int x)105 inline int ceilInt4(int x) 106 { 107 return (x + 0xF) >> 4; 108 } 109 110 #define BITS(x) ( \ 111 !!((x) & 0x80000000) + \ 112 !!((x) & 0xC0000000) + \ 113 !!((x) & 0xE0000000) + \ 114 !!((x) & 0xF0000000) + \ 115 !!((x) & 0xF8000000) + \ 116 !!((x) & 0xFC000000) + \ 117 !!((x) & 0xFE000000) + \ 118 !!((x) & 0xFF000000) + \ 119 !!((x) & 0xFF800000) + \ 120 !!((x) & 0xFFC00000) + \ 121 !!((x) & 0xFFE00000) + \ 122 !!((x) & 0xFFF00000) + \ 123 !!((x) & 0xFFF80000) + \ 124 !!((x) & 0xFFFC0000) + \ 125 !!((x) & 0xFFFE0000) + \ 126 !!((x) & 0xFFFF0000) + \ 127 !!((x) & 0xFFFF8000) + \ 128 !!((x) & 0xFFFFC000) + \ 129 !!((x) & 0xFFFFE000) + \ 130 !!((x) & 0xFFFFF000) + \ 131 !!((x) & 0xFFFFF800) + \ 132 !!((x) & 0xFFFFFC00) + \ 133 !!((x) & 0xFFFFFE00) + \ 134 !!((x) & 0xFFFFFF00) + \ 135 !!((x) & 0xFFFFFF80) + \ 136 !!((x) & 0xFFFFFFC0) + \ 137 !!((x) & 0xFFFFFFE0) + \ 138 !!((x) & 0xFFFFFFF0) + \ 139 !!((x) & 0xFFFFFFF8) + \ 140 !!((x) & 0xFFFFFFFC) + \ 141 !!((x) & 0xFFFFFFFE) + \ 142 !!((x) & 0xFFFFFFFF)) 143 144 #define MAX(x, y) ((x) > (y) ? (x) : (y)) 145 #define MIN(x, y) ((x) < (y) ? (x) : (y)) 146 exp2(float x)147 inline float exp2(float x) 148 { 149 return exp2f(x); 150 } 151 exp2(int x)152 inline int exp2(int x) 153 { 154 return 1 << x; 155 } 156 log2(int x)157 inline unsigned long log2(int x) 158 { 159 #if defined(_MSC_VER) 160 unsigned long y; 161 _BitScanReverse(&y, x); 162 return y; 163 #else 164 return 31 - __builtin_clz(x); 165 #endif 166 } 167 ilog2(float x)168 inline int ilog2(float x) 169 { 170 unsigned int y = *(unsigned int*)&x; 171 172 return ((y & 0x7F800000) >> 23) - 127; 173 } 174 log2(float x)175 inline float log2(float x) 176 { 177 return logf(x) * 1.44269504f; // 1.0 / log[e](2) 178 } 179 isPow2(int x)180 inline bool isPow2(int x) 181 { 182 return (x & -x) == x; 183 } 184 185 template<class T> clamp(T x,T a,T b)186 inline T clamp(T x, T a, T b) 187 { 188 if(x < a) x = a; 189 if(x > b) x = b; 190 191 return x; 192 } 193 clamp01(float x)194 inline float clamp01(float x) 195 { 196 return clamp(x, 0.0f, 1.0f); 197 } 198 ceilPow2(int x)199 inline int ceilPow2(int x) 200 { 201 int i = 1; 202 203 while(i < x) 204 { 205 i <<= 1; 206 } 207 208 return i; 209 } 210 floorDiv(int a,int b)211 inline int floorDiv(int a, int b) 212 { 213 return a / b + ((a % b) >> 31); 214 } 215 floorMod(int a,int b)216 inline int floorMod(int a, int b) 217 { 218 int r = a % b; 219 return r + ((r >> 31) & b); 220 } 221 ceilDiv(int a,int b)222 inline int ceilDiv(int a, int b) 223 { 224 return a / b - (-(a % b) >> 31); 225 } 226 ceilMod(int a,int b)227 inline int ceilMod(int a, int b) 228 { 229 int r = a % b; 230 return r - ((-r >> 31) & b); 231 } 232 233 template<const int n> unorm(float x)234 inline unsigned int unorm(float x) 235 { 236 static const unsigned int max = 0xFFFFFFFF >> (32 - n); 237 static const float maxf = static_cast<float>(max); 238 239 if(x >= 1.0f) 240 { 241 return max; 242 } 243 else if(x <= 0.0f) 244 { 245 return 0; 246 } 247 else 248 { 249 return static_cast<unsigned int>(maxf * x + 0.5f); 250 } 251 } 252 253 template<const int n> snorm(float x)254 inline int snorm(float x) 255 { 256 static const unsigned int min = 0x80000000 >> (32 - n); 257 static const unsigned int max = 0xFFFFFFFF >> (32 - n + 1); 258 static const float maxf = static_cast<float>(max); 259 static const unsigned int range = 0xFFFFFFFF >> (32 - n); 260 261 if(x >= 0.0f) 262 { 263 if(x >= 1.0f) 264 { 265 return max; 266 } 267 else 268 { 269 return static_cast<int>(maxf * x + 0.5f); 270 } 271 } 272 else 273 { 274 if(x <= -1.0f) 275 { 276 return min; 277 } 278 else 279 { 280 return static_cast<int>(maxf * x - 0.5f) & range; 281 } 282 } 283 } 284 285 template<const int n> ucast(float x)286 inline unsigned int ucast(float x) 287 { 288 static const unsigned int max = 0xFFFFFFFF >> (32 - n); 289 static const float maxf = static_cast<float>(max); 290 291 if(x >= maxf) 292 { 293 return max; 294 } 295 else if(x <= 0.0f) 296 { 297 return 0; 298 } 299 else 300 { 301 return static_cast<unsigned int>(x + 0.5f); 302 } 303 } 304 305 template<const int n> scast(float x)306 inline int scast(float x) 307 { 308 static const unsigned int min = 0x80000000 >> (32 - n); 309 static const unsigned int max = 0xFFFFFFFF >> (32 - n + 1); 310 static const float maxf = static_cast<float>(max); 311 static const float minf = static_cast<float>(min); 312 static const unsigned int range = 0xFFFFFFFF >> (32 - n); 313 314 if(x > 0.0f) 315 { 316 if(x >= maxf) 317 { 318 return max; 319 } 320 else 321 { 322 return static_cast<int>(x + 0.5f); 323 } 324 } 325 else 326 { 327 if(x <= -minf) 328 { 329 return min; 330 } 331 else 332 { 333 return static_cast<int>(x - 0.5f) & range; 334 } 335 } 336 } 337 sRGBtoLinear(float c)338 inline float sRGBtoLinear(float c) 339 { 340 if(c <= 0.04045f) 341 { 342 return c * 0.07739938f; // 1.0f / 12.92f; 343 } 344 else 345 { 346 return powf((c + 0.055f) * 0.9478673f, 2.4f); // 1.0f / 1.055f 347 } 348 } 349 linearToSRGB(float c)350 inline float linearToSRGB(float c) 351 { 352 if(c <= 0.0031308f) 353 { 354 return c * 12.92f; 355 } 356 else 357 { 358 return 1.055f * powf(c, 0.4166667f) - 0.055f; // 1.0f / 2.4f 359 } 360 } 361 362 unsigned char sRGB8toLinear8(unsigned char value); 363 364 uint64_t FNV_1a(const unsigned char *data, int size); // Fowler-Noll-Vo hash function 365 366 // Round up to the next multiple of alignment align(unsigned int value,unsigned int alignment)367 inline unsigned int align(unsigned int value, unsigned int alignment) 368 { 369 return ((value + alignment - 1) / alignment) * alignment; 370 } 371 clampToSignedInt(unsigned int x)372 inline int clampToSignedInt(unsigned int x) 373 { 374 return static_cast<int>(min(x, 0x7FFFFFFFu)); 375 } 376 } 377 378 #endif // sw_Math_hpp 379