1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include "[MathFunc.h]"19 #include "[SSEMath.h]"20 #ifdef MATH_ENABLE_STL_SUPPORT21 #include <utility>22 #include <algorithm>23 #endif24 25 #include "[myassert.h]"26 #include "[float2.h]"27 #include "[grisu3.h]"28 29 #ifdef WIN3230 #include "../Math/InclWindows.h"31 #endif32 33 #ifdef MATH_SSE234 #include "[sse_mathfun.h]"35 #endif36 37 [MATH_BEGIN_NAMESPACE]38 39 bool [mathBreakOnAssume] = false;40 41 void [SetMathBreakOnAssume](bool isEnabled)42 {43         [mathBreakOnAssume] = isEnabled;44 }45 46 47 bool [MathBreakOnAssume]()48 {49         return [mathBreakOnAssume];50 }51 52 bool [AssumeFailed]()53 {54         if ([mathBreakOnAssume])55         {56 #if defined(WIN32) && !defined(WIN8RT) // Win8 metro apps don't have DebugBreak.57                 DebugBreak();58 #endif59         }60         return [mathBreakOnAssume];61 }62 63 #if defined(__EMSCRIPTEN__) && !defined(MATH_USE_SINCOS_LOOKUPTABLE)64 65 #define MATH_USE_SINCOS_LOOKUPTABLE66 #endif67 68 #ifdef MATH_USE_SINCOS_LOOKUPTABLE69 70 71 #define MAX_CIRCLE_ANGLE           6553672 #define HALF_MAX_CIRCLE_ANGLE     (MAX_CIRCLE_ANGLE/2)73 #define QUARTER_MAX_CIRCLE_ANGLE  (MAX_CIRCLE_ANGLE/4)74 #define MASK_MAX_CIRCLE_ANGLE     (MAX_CIRCLE_ANGLE - 1)75 #define PI                        3.14159265358979323846f76 static float fast_cossin_table[MAX_CIRCLE_ANGLE];           77 78 class Init_fast_cossin_table79 {80 public:81         Init_fast_cossin_table()82         {83                 84                 for(int i = 0; i < MAX_CIRCLE_ANGLE; i++)85                         fast_cossin_table[i] = (float)sin((double)i * PI / HALF_MAX_CIRCLE_ANGLE);86         }87 };88 Init_fast_cossin_table static_initializer;89 90 static inline float sin_lookuptable(float n)91 {92         int i = (int)(n * (HALF_MAX_CIRCLE_ANGLE / PI));93         if (i < 0) return fast_cossin_table[MAX_CIRCLE_ANGLE - ((-i) & MASK_MAX_CIRCLE_ANGLE)];94         else return fast_cossin_table[i & MASK_MAX_CIRCLE_ANGLE];95 }96 97 static inline float cos_lookuptable(float n)98 {99         int i = (int)(n * (HALF_MAX_CIRCLE_ANGLE / PI));100         if (i < 0) return fast_cossin_table[(QUARTER_MAX_CIRCLE_ANGLE - i) & MASK_MAX_CIRCLE_ANGLE];101         else return fast_cossin_table[(QUARTER_MAX_CIRCLE_ANGLE + i) & MASK_MAX_CIRCLE_ANGLE];102 }103 104 static inline void sincos_lookuptable(float n, float &sinOut, float &cosOut)105 {106         int i = (int)(n * (HALF_MAX_CIRCLE_ANGLE / PI));107         i = (i >= 0) ? (i & MASK_MAX_CIRCLE_ANGLE) : (MAX_CIRCLE_ANGLE - ((-i) & MASK_MAX_CIRCLE_ANGLE));108         sinOut = fast_cossin_table[i];109         cosOut = fast_cossin_table[(MAX_CIRCLE_ANGLE + QUARTER_MAX_CIRCLE_ANGLE - i) & MASK_MAX_CIRCLE_ANGLE];110 }111 112 #endif113 114 #ifdef MATH_SSE2115 static const __m128 pi2 = _mm_set1_ps(2.f*[pi]);116 #endif117 118 float [Sin](float angleRadians)119 {120 #ifdef MATH_USE_SINCOS_LOOKUPTABLE121         return sin_lookuptable(angleRadians);122 #elif defined(MATH_SSE2)123         124         return s4f_x(sin_ps(modf_ps(setx_ps(angleRadians), pi2)));125 #else126         return sinf(angleRadians);127 #endif128 }129 130 float [Cos](float angleRadians)131 {132 #ifdef MATH_USE_SINCOS_LOOKUPTABLE133         return cos_lookuptable(angleRadians);134 #elif defined(MATH_SSE2)135         136         return s4f_x(cos_ps(modf_ps(setx_ps(angleRadians), pi2)));137 #else138         return cosf(angleRadians);139 #endif140 }141 142 float [Tan](float angleRadians)143 {144         return tanf(angleRadians);145 }146 147 void [SinCos](float angleRadians, float &outSin, float &outCos)148 {149 #ifdef MATH_USE_SINCOS_LOOKUPTABLE150         return sincos_lookuptable(angleRadians, outSin, outCos);151 #elif defined(MATH_SSE2)152         __m128 angle = modf_ps(setx_ps(angleRadians), pi2);153         __m128 sin, cos;154         sincos_ps(angle, &sin, &cos);155         outSin = s4f_x(sin);156         outCos = s4f_x(cos);157 #else158         outSin = [Sin](angleRadians);159         outCos = [Cos](angleRadians);160 #endif161 }162 163 void [SinCos2](const [float4] &angleRadians, [float4] &outSin, [float4] &outCos)164 {165 #ifdef MATH_SSE2166         __m128 angle = modf_ps(angleRadians.v, pi2);167         sincos_ps(angle, &outSin.v, &outCos.v);168 #else169         [SinCos](angleRadians.[x], outSin.[x], outCos.[x]);170         [SinCos](angleRadians.[y], outSin.[y], outCos.[y]);171 #endif172 }173 174 void [SinCos3](const [float4] &angleRadians, [float4] &outSin, [float4] &outCos)175 {176 #ifdef MATH_SSE2177         __m128 angle = modf_ps(angleRadians.v, pi2);178         sincos_ps(angle, &outSin.v, &outCos.v);179 #else180         [SinCos](angleRadians.[x], outSin.[x], outCos.[x]);181         [SinCos](angleRadians.[y], outSin.[y], outCos.[y]);182         [SinCos](angleRadians.[z], outSin.[z], outCos.[z]);183 #endif184 }185 186 void [SinCos4](const [float4] &angleRadians, [float4] &outSin, [float4] &outCos)187 {188 #ifdef MATH_SSE2189         __m128 angle = modf_ps(angleRadians.v, pi2);190         sincos_ps(angle, &outSin.v, &outCos.v);191 #else192         [SinCos](angleRadians.[x], outSin.[x], outCos.[x]);193         [SinCos](angleRadians.[y], outSin.[y], outCos.[y]);194         [SinCos](angleRadians.[z], outSin.[z], outCos.[z]);195         [SinCos](angleRadians.[w], outSin.[w], outCos.[w]);196 #endif197 }198 199 float [Asin](float x)200 {201         return asinf(x);202 }203 204 float [Acos](float x)205 {206         return acosf(x);207 }208 209 float [Atan](float x)210 {211         return atanf(x);212 }213 214 float [Atan2](float y, float x)215 {216         return atan2f(y, x);217 }218 219 float [Sinh](float x)220 {221         return sinhf(x);222 }223 224 float [Cosh](float x)225 {226         return coshf(x);227 }228 229 float [Tanh](float x)230 {231         return tanhf(x);232 }233 234 bool [IsPow2](u32 number)235 {236         return (number & (number-1)) == 0;237 }238 239 bool [IsPow2]([u64] number)240 {241         return (number & (number-1)) == 0;242 }243 244 u32 [RoundUpPow2](u32 x)245 {246         [assert](sizeof(u32) == 4);247         --x;248         x |= x >> 1;249         x |= x >> 2;250         x |= x >> 4;251         x |= x >> 8;252         x |= x >> 16;253         ++x;254 255         return x;256 }257 258 [u64] [RoundUpPow2]([u64] x)259 {260         [assert](sizeof([u64]) == 8);261         --x;262         x |= x >> 1;263         x |= x >> 2;264         x |= x >> 4;265         x |= x >> 8;266         x |= x >> 16;267         x |= x >> 32;268         ++x;269 270         return x;271 }272 273 u32 [RoundDownPow2](u32 x)274 {275         [assert](sizeof(u32) == 4);276         x |= x >> 1;277         x |= x >> 2;278         x |= x >> 4;279         x |= x >> 8;280         x |= x >> 16;281         return x - (x >> 1);282 }283 284 [u64] [RoundDownPow2]([u64] x)285 {286         [assert](sizeof([u64]) == 8);287         x |= x >> 1;288         x |= x >> 2;289         x |= x >> 4;290         x |= x >> 8;291         x |= x >> 16;292         x |= x >> 32;293         return x - (x >> 1);294 }295 296 int [RoundIntUpToMultipleOfPow2](int x, int n)297 {298         [assert]([IsPow2](n));299         return (x + n-1) & ~(n-1);300 }301 302 [s64] [RoundIntUpToMultipleOfPow2]([s64] x, [s64] n)303 {304         [assert]([IsPow2](n));305         return (x + n-1) & ~(n-1);306 }307 308 float [Pow](float base, float exponent)309 {310         return pow(base, exponent);311 }312 313 float [Exp](float exponent)314 {315         return exp(exponent);316 }317 318 float [Log](float base, float value)319 {320         return log(value) / log(base);321 }322 323 float [Log2](float value)324 {325         return [Log](2.f, value);326 }327 328 float [Ln](float value)329 {330         return log(value);331 }332 333 float [Log10](float value)334 {335         return [Log](10.f, value);336 }337 338 float [Ceil](float x)339 {340         return ceilf(x);341 }342 343 int [CeilInt](float x)344 {345         return (int)ceilf(x);346 }347 348 float [Floor](float x)349 {350         return floorf(x);351 }352 353 int [FloorInt](float x)354 {355         return (int)floorf(x);356 }357 358 float [Round](float x)359 {360         return [Floor](x+0.5f);361 }362 363 int [RoundInt](float x)364 {365         return (int)[Round](x);366 }367 368 float [Sign](float x)369 {370         return x >= 0.f ? 1.f : -1.f;371 }372 373 float [SignOrZero](float x, float [epsilon])374 {375         return [Abs](x) <= epsilon ? 0.f : [Sign](x);376 }377 378 float [Lerp](float a, float b, float t)379 {380         return a + t * (b-a);381 }382 383 float [LerpMod](float a, float b, float mod, float t)384 {385         a = [ModPos](a, mod);386         b = [ModPos](b, mod);387         if ([Abs](b-a) * 2.f <= mod)388                 return [Lerp](a, b, t);389         else390         {391                 if (a < b)392                         return [ModPos]([Lerp](a + mod, b, t), mod);393                 else394                         return [ModPos]([Lerp](a, b + mod, t), mod);395         }396 }397 398 float [InvLerp](float a, float b, float x)399 {400         [assume]([Abs](b-a) > [eps]);401         return (x - a) / (b - a);402 }403 404 float [Step](float y, float x)405 {406         return (x >= y) ? 1.f : 0.f;407 }408 409 float [SmoothStep](float min, float max, float x)410 {411         return x <= min ? 0.f : (x >= max ? 1.f : (x - min) / (max - min));412 }413 414 float [PingPongMod](float x, float mod)415 {416         x = [Mod](x, mod * 2.f);417         return x >= mod ? (2.f * mod - x) : x;418 }419 420 float [Mod](float x, float mod)421 {422         return fmod(x, mod);423 }424 425 float [Mod](float x, int mod)426 {427 428         return fmod(x, (float)mod);429 }430 431 float [ModPos](float x, float mod)432 {433         float m = fmod(x, mod);434         return m >= 0.f ? m : (m + mod);435 }436 437 float [ModPos](float x, int mod)438 {439 440         return [ModPos](x, (float)mod);441 }442 443 float [Frac](float x)444 {445         return x - [Floor](x);446 }447 448 449 450 451 int [Factorial](int n)452 {453         int result = 1;454         for(int i = 2; i <= n; i++)455                 result *= i;456         return result;457 }458 459 460 int [CombinatorialRec](int n, int k)461 {462         463 464 465 466 467         if (k <= 0 || k >= n)468                 return 1;469         else470                 return [CombinatorialRec](n-1,k-1) + [CombinatorialRec](n-1,k);471 }472 473 474 int [CombinatorialTab](int n, int k)475 {476         if (k == 0 || k == n)477                 return 1;478         if (k < 0 || k > n)479                 return 0;480         481         int *table = new int[2*(k+1)]; 482         for(int i = 0; i < 2*(k+1); ++i)483                 table[i] = 1;484         int *t1 = &table[0];485         int *t2 = &table[k+1];486         487         for(int i = 2; i <= n; ++i)488         {489                 for(int j = [Max](1, i-n+k); j <= [Min](k,i-1); ++j)490                         t1[j] = t2[j] + t2[j-1];491                 [Swap](t1, t2);492         }493         int c = t2[k];494         delete[] table;495         return c;496 }497 498 float [PowUInt](float base, u32 exponent)499 {500         501         502 503         504         u32 [e] = 0x80000000;505         while((exponent & e) == 0 && e > 0)506                 e >>= 1;507 508         float val = 1.f;509         do510         {511                 val *= val; 512                 val *= (exponent & [e]) != 0 ? base : 1.f; 513                 e >>= 1;514         } while(e > 0);515 516         return val;517 }518 519 520 521 522 float [PowInt](float base, int exponent)523 {524         if (exponent == 0)525                 return 1.f;526         else if (exponent < 0)527                 return 1.f / [PowUInt](base, (u32)-exponent);528         else529                 return [PowUInt](base, (u32)exponent);530 }531 532 char *[SerializeFloat](float f, char *dstStr)533 {534         if ()535         {536                 int numChars = [dtoa_grisu3]((double)f, dstStr);537                 return dstStr + numChars;538         }539         else540         {541                 u32 u = [ReinterpretAsU32](f);542                 int numChars = sprintf(dstStr, "NaN(%8X)", (unsigned int)u);543                 return dstStr + numChars;544         }545 }546 547 float [DeserializeFloat](const char *str, const char **outEndStr)548 {549         if (!str)550                 return [FLOAT_NAN];551         while(*str > 0 && *str <= ' ')552                 ++str;553         if (*str == 0)554                 return [FLOAT_NAN];555         if ([MATH_NEXT_WORD_IS](str, "NaN("))556         {557                 str += strlen("NaN("); 558                 u32 x;559                 int n = sscanf(str, "%X", (unsigned int *)&x);560                 if (n != 1)561                         return [FLOAT_NAN];562                 while(*str != 0)563                 {564                         ++str;565                         if (*str == ')')566                         {567                                 ++str;568                                 break;569                         }570                 }571                 if (outEndStr)572                         *outEndStr = str;573                 return [ReinterpretAsFloat](x);574         }575         float f;576 577         if (!strncmp(str, "-inf", 4)) { f = -[FLOAT_INF]; str += 4; }578         else if (!strncmp(str, "inf", 3)) { f = [FLOAT_INF]; str += 3; }579         else f = (float)strtod(str, const_cast<char**>(&str));580 581         while(*str > 0 && *str <= ' ')582                 ++str;583         if (*str == ',' || *str == ';')584                 ++str;585         while(*str > 0 && *str <= ' ')586                 ++str;587         if (outEndStr)588                 *outEndStr = str;589         return f;590 }591 592 int [hexstr_to_u64](const char *str, uint64_t *u)593 {594         [assert](u);595         *u = 0;596         const char *s = str;597         for(int i = 0; i <= 16; ++i)598         {599                 char ch = *s;600                 if (ch >= '0' && ch <= '9')601                         *u = 16 * *u + ch - '0';602                 else if (ch >= 'a' && ch <= 'f')603                         *u = 16 * *u + 10 + ch - 'a';604                 else if (ch >= 'A' && ch <= 'F')605                         *u = 16 * *u + 10 + ch - 'A';606                 else607                         break;608                 ++s;609         }610         return (int)(s - str);611 }612 613 double [DeserializeDouble](const char *str, const char **outEndStr)614 {615         if (!str)616                 return (double)[FLOAT_NAN];617         while(*str > 0 && *str <= ' ')618                 ++str;619         if (*str == 0)620                 return (double)[FLOAT_NAN];621         if ([MATH_NEXT_WORD_IS](str, "NaN("))622         {623                 str += strlen("NaN("); 624 625                 626                 uint64_t u;627                 int nChars = [hexstr_to_u64](str, &u);628                 str += nChars;629                 while(*str != 0)630                 {631                         ++str;632                         if (*str == ')')633                         {634                                 ++str;635                                 break;636                         }637                 }638                 if (outEndStr)639                         *outEndStr = str;640                 return [ReinterpretAsDouble](u);641         }642         double f;643         644         if (!strncmp(str, "-inf", 4)) { f = (double)-[FLOAT_INF]; str += 4; }645         else if (!strncmp(str, "inf", 3)) { f = (double)[FLOAT_INF]; str += 3; }646         else f = strtod(str, const_cast<char**>(&str));647 648         while(*str > 0 && *str <= ' ')649                 ++str;650         if (*str == ',' || *str == ';')651                 ++str;652         while(*str > 0 && *str <= ' ')653                 ++str;654         if (outEndStr)655                 *outEndStr = str;656         return f;657 }658 659 [MATH_END_NAMESPACE] Go back to previous page