source: cpp/common/nonstd_math.h @ 1346

Last change on this file since 1346 was 1346, checked in by Maciej Komosinski, 8 days ago

Added compatibility with MinGW compiler

  • Property svn:eol-style set to native
File size: 6.0 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2025  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5#ifndef _NONSTD_MATH_H_
6#define _NONSTD_MATH_H_
7
8#if defined _MSC_VER || defined __MINGW32__
9 #define _USE_MATH_DEFINES //after this is defined, the next #include <math.h> or <cmath> will define M_PI etc.
10 #include <math.h> //in vc2008, <cmath> worked here, but no longer in vc2010 because "something" (some other .h from stl?) earlier includes <cmath> without _USE_MATH_DEFINES, and <cmath> includes <math.h> (just once because it has "include guards" like any other .h)
11 #include <float.h>
12 //#define isnan(x) _isnan(x) //since 2014 we use std::isnan()
13 #define finite(x) _finite(x)
14#else //e.g. __BORLANDC__
15 #include <math.h>
16#endif
17
18
19
20//random number generator:
21#include "random.h"
22RandomGenerator &rndGetInstance();
23
24inline double rndDouble(double limit_exclusive) { return rndGetInstance().getDouble() * limit_exclusive; }
25inline unsigned int rndUint(unsigned int limit_exclusive) { return (unsigned int)(rndGetInstance().getDouble() * limit_exclusive); } //returns random from 0..limit_exclusive-1
26#if !defined __BORLANDC__ && !defined __ARM_ARCH_7A__ //for 32-bit compilations (embarcadero 11u3 and clang android), unsigned int and size_t function variants are duplicates. Using templates to define an additional function variant only when size_t is different from unsigned int is such a hassle... especially that some variants are inline, some are not. Another approach would be to create a template for all types (or all integer types?) and potentially getting an overflow for longer int types when casting the result of getDouble()*limit_exclusive to unsigned int.
27inline unsigned int rndUint(size_t limit_exclusive) {return rndUint((unsigned int)limit_exclusive);} //just an overload with size_t argument to avoid compiler warnings and avoid hundreds of casts. May limit the range if size_t is larger than unsigned int and somebody would intentionally use such a huge limit_exclusive value.
28#endif
29unsigned int rndUint(int limit_exclusive); //just an overload with int argument
30inline void rndSetSeed(unsigned int seed) { rndGetInstance().setSeed(seed); }
31inline unsigned int rndRandomizeSeed() { return rndGetInstance().randomize(); }
32
33
34
35// precision==-1 for full precision, or positive values for the number of digits to print past the decimal point.
36// Allocated buffer with bufferlen=30 is OK.
37// Returns the number of chars actually used (not including the ending 0).
38int doubleToString(double x, int precision, char *buffer, int bufferlen);
39
40#include <string>
41std::string doubleToString(double x, int precision);
42double round(const double x, const int precision);
43static inline void clipNegativeZeroIfNeeded(double& value, const double range_low)
44{
45        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)
46                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.
47        //these conditions are not intended for range_low==-0.0, as we assume nobody would define allowed ranges using -0.0.
48}
49
50
51
52
53
54//floating point specific numbers
55#include "stdlib.h"
56
57#ifdef __BORLANDC__
58        #include <float.h>
59        #define isnan(x) _isnan(x) //http://stackoverflow.com/questions/570669/checking-if-a-double-or-float-is-nan-in-c
60        #define finite(x) _finite(x)
61#endif
62
63#ifdef LINUX
64  #define _isnan(a) isnan(a)
65#endif
66
67#ifdef IPHONE
68        #define finite(x) (!isinf(x))
69  #define _isnan(a) isnan(a)
70#endif
71
72
73#if defined SHP
74 //#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"
75 #define isnan(x) false //isnan() sie nie linkuje
76 #define finite(x) true //j.w.
77 //#include <cstdlib> //RAND_MAX defined incorrectly
78 //#ifdef BADA_SIMULATOR //...but only in simulator libs
79 // #undef RAND_MAX
80 // #define RAND_MAX 32768 //...this is the actual value used by rand()
81 //#endif
82#endif
83
84#if defined LINUX || defined __MINGW32__ || defined TIZEN || defined __ANDROID__
85#include <fenv.h>
86#endif
87
88namespace fpExcept
89{
90//handling floating point exceptions
91#if defined LINUX || defined __MINGW32__ || defined TIZEN || defined __ANDROID__
92        //fenv.h values
93        static constexpr unsigned int FPEX_DIV0 = FE_DIVBYZERO;
94        static constexpr unsigned int FPEX_INVALID = FE_INVALID;
95        static constexpr unsigned int FPEX_OVERFLOW = FE_OVERFLOW;
96#elif defined IPHONE || defined MACOS
97        // (not implemented but these constants are still needed)
98        static constexpr unsigned int FPEX_DIV0 = 0;
99        static constexpr unsigned int FPEX_INVALID = 0;
100        static constexpr unsigned int FPEX_OVERFLOW = 0;
101#else
102        //_control87() values
103        static constexpr unsigned int FPEX_DIV0 = EM_ZERODIVIDE;
104        static constexpr unsigned int FPEX_INVALID = EM_INVALID;
105        static constexpr unsigned int FPEX_OVERFLOW = EM_OVERFLOW;
106#endif
107        extern int wanted_exceptions;
108       
109        void init(); //call once, before ...Enable/Disable
110        void enable();
111        void disable();
112};
113
114// 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
115template <typename Value, typename Linear> Value universal_lerp(Value a,Value b,Linear t) {return a*(1-t)+b*t;}
116
117template <typename T> T linearTransform(T value, T min_in, T max_in, T min_out, T max_out)
118{
119        return min_out + (value-min_in)*(max_out-min_out)/(max_in-min_in);
120}
121
122//in C++20, related: https://en.cppreference.com/w/cpp/numeric/countl_zero
123#ifdef _WIN32 //visual studio is missing ffs()
124static inline unsigned ffs(int x)
125{
126        if (x == 0) return 0u;
127        unsigned r = 1;
128        while ((x & 1) == 0)
129                x >>= 1, ++r;
130        return r;
131}
132#endif
133
134
135#endif
Note: See TracBrowser for help on using the repository browser.