Changeset 1275


Ignore:
Timestamp:
09/09/23 15:16:31 (9 months ago)
Author:
Maciej Komosinski
Message:

More unification of floating point exception handling across platforms

Location:
cpp
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • cpp/common/nonstd_math.cpp

    r1251 r1275  
    8888}
    8989
    90 
    91 
     90namespace fpExcept
     91{ //shared for all platform, using crossplatform constants, can be defined in build_config (but also conditionally changed from the code)
     92int wanted_exceptions =
     93#ifdef WANTED_FP_EXCEPTIONS
     94        WANTED_FP_EXCEPTIONS;
     95#else
     96        FPEX_DIV0; //default when 'WANTED_FP_EXCEPTIONS' is not defined (add more?)
     97#endif
     98}
    9299
    93100// Idea: enable selected floating point exceptions when the app starts and disable them temporarily when dividing values in ExtValue, so that we can directly handle problematic cases there.
     
    96103#ifdef IPHONE
    97104//TODO! -> ? http://stackoverflow.com/questions/12762418/how-to-enable-sigfpe-signal-on-division-by-zero-in-ios-app
    98 void fpExceptInit()
    99 {}
    100 
    101 void fpExceptEnable()
    102 {}
    103 
    104 void fpExceptDisable()
    105 {}
     105namespace fpExcept
     106{
     107        void init() {}
     108        void enable() {}
     109        void disable() {}
     110}
    106111#endif
    107112
    108113#ifdef MACOS
    109 //TODO...?
    110 
    111 void fpExceptInit()
    112 {}
    113 
    114 void fpExceptEnable()
    115 {}
    116 
    117 void fpExceptDisable()
    118 {}
     114//TODO...? (even less reasons to omit this in macos :-P)
     115namespace fpExcept
     116{
     117        void init() {}
     118        void enable() {}
     119        void disable() {}
     120}
    119121#endif
    120122
    121123
    122124#if defined LINUX || defined TIZEN || defined __ANDROID__
    123 
    124125#include <fenv.h>
    125126
    126 static constexpr int WANTED_FP_EXCEPTIONS = FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW;
    127 
    128 void fpExceptInit()
    129 {}
    130 
    131 void fpExceptEnable()
    132 {
    133         feclearexcept(WANTED_FP_EXCEPTIONS);
    134         feenableexcept(WANTED_FP_EXCEPTIONS);
    135 }
    136 
    137 void fpExceptDisable()
    138 {
    139         fedisableexcept(WANTED_FP_EXCEPTIONS);
    140 }
    141 
     127namespace fpExcept
     128{
     129        void init() {}
     130        void enable()
     131        {
     132                feclearexcept(wanted_exceptions);
     133                feenableexcept(wanted_exceptions);
     134        }
     135        void disable()
     136        {
     137                fedisableexcept(wanted_exceptions);
     138        }
     139};
    142140#endif
    143141
     
    146144#if defined(__BORLANDC__) || defined(_MSC_VER)
    147145
     146namespace fpExcept
     147{
    148148// in Borland, there was once a problem like this:
    149149// http://qc.embarcadero.com/wc/qcmain.aspx?d=5128
     
    177177unsigned int fp_control_word_muted;
    178178
    179 
    180 void fpExceptInit()
     179void init()
    181180{
    182181        _controlfp_s(&fp_control_word_std, 0, 0); //in Visual C++, the default value is exactly the masks listed below, and we have to turn them off to enable exceptions
    183182        // Make the new fp env same as the old one, except for the changes we're going to make
    184         fp_control_word_muted = fp_control_word_std & ~(EM_INVALID | /*EM_DENORMAL |*/ EM_ZERODIVIDE | EM_OVERFLOW /* | EM_UNDERFLOW | EM_INEXACT */); //commented out exceptions that occur during proper operation
    185 }
    186 
    187 void fpExceptEnable()
     183        fp_control_word_muted = fp_control_word_std & ~wanted_exceptions;
     184}
     185
     186void enable()
    188187{
    189188        //_fpreset(); //not needed since we just _clearfp()... mentioned in https://stackoverflow.com/questions/4282217/visual-c-weird-behavior-after-enabling-floating-point-exceptions-compiler-b
     
    193192}
    194193
    195 void fpExceptDisable()
     194void disable()
    196195{
    197196        //_fpreset(); //not needed since we just _clearfp()... mentioned in https://stackoverflow.com/questions/4282217/visual-c-weird-behavior-after-enabling-floating-point-exceptions-compiler-b
     
    200199        _controlfp_s(&was, fp_control_word_std, _MCW_EM);
    201200}
    202 #endif
     201       
     202};
     203
     204#endif
  • cpp/common/nonstd_math.h

    r1253 r1275  
    99#ifdef _MSC_VER
    1010 #define _USE_MATH_DEFINES //after this is defined, the next #include <math.h> or <cmath> will define M_PI etc.
    11  #include <math.h> //w vc2008 dzia³a³o tu <cmath>, ale w vc2010 juz nie bo "coœ" (jakiœ inny .h stl'a?) includuje wczeœniej <cmath> bez _USE_MATH_DEFINES, a <cmath> includuje <math.h> (ale tylko raz bo ma "include guards" jak kazdy .h)
     11 #include <math.h> //w vc2008 dzia�a�o tu <cmath>, ale w vc2010 juz nie bo "co�" (jaki� inny .h stl'a?) includuje wcze�niej <cmath> bez _USE_MATH_DEFINES, a <cmath> includuje <math.h> (ale tylko raz bo ma "include guards" jak kazdy .h)
    1212 #include <float.h>
    1313 //#define isnan(x) _isnan(x) //since 2014 we use std::isnan()
     
    6969
    7070#if defined SHP
    71  //#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"
     71 //#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"
    7272 #define isnan(x) false //isnan() sie nie linkuje
    7373 #define finite(x) true //j.w.
     
    7979#endif
    8080
     81#if defined LINUX || defined TIZEN || defined __ANDROID__
     82#include <fenv.h>
     83#endif
     84
     85namespace fpExcept
     86{
    8187//handling floating point exceptions
    82 void fpExceptInit(); //call once, before ...Enable/Disable
    83 void fpExceptEnable();
    84 void fpExceptDisable();
     88#if defined LINUX || defined TIZEN || defined __ANDROID__
     89        //fenv.h values
     90        static constexpr unsigned int FPEX_DIV0 = FE_DIVBYZERO;
     91        static constexpr unsigned int FPEX_INVALID = FE_INVALID;
     92        static constexpr unsigned int FPEX_OVERFLOW = FE_OVERFLOW;
     93#elif defined IPHONE
     94        // (not implemented but these constants are still needed)
     95        static constexpr unsigned int FPEX_DIV0 = 0;
     96        static constexpr unsigned int FPEX_INVALID = 0;
     97        static constexpr unsigned int FPEX_OVERFLOW = 0;
     98#else
     99        //_control87() values
     100        static constexpr unsigned int FPEX_DIV0 = EM_ZERODIVIDE;
     101        static constexpr unsigned int FPEX_INVALID = EM_INVALID;
     102        static constexpr unsigned int FPEX_OVERFLOW = EM_OVERFLOW;
     103#endif
     104        extern int wanted_exceptions;
     105       
     106        void init(); //call once, before ...Enable/Disable
     107        void enable();
     108        void disable();
     109};
    85110
    86111// 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
  • cpp/frams/util/extvalue.cpp

    r1076 r1275  
    703703        else
    704704        {
    705                 fpExceptDisable();
     705                fpExcept::disable();
    706706                double tmp = getDouble() / a;
    707707                if (!std::isfinite(tmp))
     
    714714                //if (isnan(ddata())) //http://www.digitalmars.com/d/archives/c++/Traping_divide_by_zero_5728.html
    715715                //        { logPrintf("ExtValue","divide",LOG_ERROR,"not-a-number",(const char*)getString()); setInvalid(); }
    716                 fpExceptEnable();
     716                fpExcept::enable();
    717717        }
    718718}
Note: See TracChangeset for help on using the changeset viewer.