// This file is a part of Framsticks SDK. http://www.framsticks.com/ // Copyright (C) 1999-2024 Maciej Komosinski and Szymon Ulatowski. // See LICENSE.txt for details. #ifndef _NONSTD_MATH_H_ #define _NONSTD_MATH_H_ #ifdef _MSC_VER #define _USE_MATH_DEFINES //after this is defined, the next #include or will define M_PI etc. #include //in vc2008, worked here, but no longer in vc2010 because "something" (some other .h from stl?) earlier includes without _USE_MATH_DEFINES, and includes (just once because it has "include guards" like any other .h) #include //#define isnan(x) _isnan(x) //since 2014 we use std::isnan() #define finite(x) _finite(x) #else //e.g. __BORLANDC__ #include #endif //random number generator: #include "random.h" RandomGenerator &rndGetInstance(); inline double rndDouble(double limit_exclusive) { return rndGetInstance().getDouble() * limit_exclusive; } inline unsigned int rndUint(unsigned int limit_exclusive) { return (unsigned int)(rndGetInstance().getDouble() * limit_exclusive); } //returns random from 0..limit_exclusive-1 #ifndef __BORLANDC__ //for embarcadero 11u3, unsigned int and size_t are duplicates inline unsigned int rndUint(size_t limit_exclusive) {return rndUint((unsigned int)limit_exclusive);} //just an overload with size_t argument #endif unsigned int rndUint(int limit_exclusive); //just an overload with int argument inline void rndSetSeed(unsigned int seed) { rndGetInstance().setSeed(seed); } inline unsigned int rndRandomizeSeed() { return rndGetInstance().randomize(); } // precision==-1 for full precision, or positive values for the number of digits to print past the decimal point. // Allocated buffer with bufferlen=30 is OK. // Returns the number of chars actually used (not including the ending 0). int doubleToString(double x, int precision, char *buffer, int bufferlen); #include std::string doubleToString(double x, int precision); double round(const double x, const int precision); static inline void clipNegativeZeroIfNeeded(double& value, const double range_low) { if (value == 0.0 && range_low == 0.0) // if we have range_low==0.0 and we get value==-0.0 (which is ==0.0) value = 0.0; //turn -0.0 to 0.0 so that it does not look like exceeding the allowed range (even though -0.0==0.0). This code unnecessarily also "overwrites" value==0.0 with 0.0, but it is faster and simpler than additionally checking std::signbit(value) just to distinguish -0.0 from 0.0. //these conditions are not intended for range_low==-0.0, as we assume nobody would define allowed ranges using -0.0. } //floating point specific numbers #include "stdlib.h" #ifdef __BORLANDC__ #include #define isnan(x) _isnan(x) //http://stackoverflow.com/questions/570669/checking-if-a-double-or-float-is-nan-in-c #define finite(x) _finite(x) #endif #ifdef LINUX #define _isnan(a) isnan(a) #endif #ifdef IPHONE #define finite(x) (!isinf(x)) #define _isnan(a) isnan(a) #endif #if defined SHP //#define __assert_func(a,b,c,d) 0 //Currently, we are sorry to inform you that assert() is not yet supported. We have considered your request for internal discussion. Na szcz�cie jest w�asna (byle by by�a, bo i tak zak�adamy ze assert ktore przeciez dziala tylko w trybie debug nie jest potrzebne na bada) implementacja w "bada-assert.cpp" #define isnan(x) false //isnan() sie nie linkuje #define finite(x) true //j.w. //#include //RAND_MAX defined incorrectly //#ifdef BADA_SIMULATOR //...but only in simulator libs // #undef RAND_MAX // #define RAND_MAX 32768 //...this is the actual value used by rand() //#endif #endif #if defined LINUX || defined TIZEN || defined __ANDROID__ #include #endif namespace fpExcept { //handling floating point exceptions #if defined LINUX || defined TIZEN || defined __ANDROID__ //fenv.h values static constexpr unsigned int FPEX_DIV0 = FE_DIVBYZERO; static constexpr unsigned int FPEX_INVALID = FE_INVALID; static constexpr unsigned int FPEX_OVERFLOW = FE_OVERFLOW; #elif defined IPHONE // (not implemented but these constants are still needed) static constexpr unsigned int FPEX_DIV0 = 0; static constexpr unsigned int FPEX_INVALID = 0; static constexpr unsigned int FPEX_OVERFLOW = 0; #else //_control87() values static constexpr unsigned int FPEX_DIV0 = EM_ZERODIVIDE; static constexpr unsigned int FPEX_INVALID = EM_INVALID; static constexpr unsigned int FPEX_OVERFLOW = EM_OVERFLOW; #endif extern int wanted_exceptions; void init(); //call once, before ...Enable/Disable void enable(); void disable(); }; // std::lerp can be used since C++20 (and has some guaranteed properties probably better than this basic formula) but apparently it is not a template template Value universal_lerp(Value a,Value b,Linear t) {return a*(1-t)+b*t;} template T linearTransform(T value, T min_in, T max_in, T min_out, T max_out) { return min_out + (value-min_in)*(max_out-min_out)/(max_in-min_in); } //in C++20, related: https://en.cppreference.com/w/cpp/numeric/countl_zero #ifdef _WIN32 //visual studio is missing ffs() static inline unsigned ffs(int x) { if (x == 0) return 0u; unsigned r = 1; while ((x & 1) == 0) x >>= 1, ++r; return r; } #endif #endif