Changeset: 4f5781d15c51 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=4f5781d15c51
Modified Files:
        monetdb5/modules/kernel/batmmath.c
        monetdb5/modules/kernel/mmath.c
Branch: Jul2017
Log Message:

Improve math error handling.
If errno is zero, check the result of fetestexcept to produce an error message.


diffs (252 lines):

diff --git a/monetdb5/modules/kernel/batmmath.c 
b/monetdb5/modules/kernel/batmmath.c
--- a/monetdb5/modules/kernel/batmmath.c
+++ b/monetdb5/modules/kernel/batmmath.c
@@ -23,6 +23,10 @@
 #else
 #define feclearexcept(x)
 #define fetestexcept(x)                0
+#define FE_INVALID                     0
+#define FE_DIVBYZERO           0
+#define FE_OVERFLOW                    0
+#define FE_UNDERFLOW           0
 #endif
 
 #define voidresultBAT(X1,X2)                                                   
                \
@@ -43,6 +47,8 @@ str CMDscience_bat_##TYPE##_##FUNC(bat *
 {                                                                              
                                                        \
        BAT *b, *bn;                                                            
                                        \
        TYPE *o, *p, *q;                                                        
                                        \
+       int e = 0, ex = 0;                                                      
                                        \
+                                                                               
                                                        \
        if ((b = BATdescriptor(*bid)) == NULL) {                                
                \
                throw(MAL, #TYPE, RUNTIME_OBJECT_MISSING);                      
                \
        }                                                                       
                                                        \
@@ -60,13 +66,22 @@ str CMDscience_bat_##TYPE##_##FUNC(bat *
                for (; p < q; o++, p++)                                         
                                \
                        *o = *p == TYPE##_nil ? TYPE##_nil : FUNC##SUFF(*p);    
\
        }                                                                       
                                                        \
-       if (errno != 0 ||                                                       
                                        \
-               fetestexcept(FE_INVALID | FE_DIVBYZERO |                        
                \
-                                        FE_OVERFLOW | FE_UNDERFLOW) != 0) {    
                \
-               int e = errno;                                                  
                                        \
+       if ((e = errno) != 0 ||                                                 
                                \
+               (ex = fetestexcept(FE_INVALID | FE_DIVBYZERO |                  
        \
+                                                  FE_OVERFLOW | FE_UNDERFLOW)) 
!= 0) {         \
+               const char *err;                                                
                                        \
                BBPunfix(bn->batCacheid);                                       
                                \
-               throw(MAL, "batmmath." #FUNC, "Math exception: %s",             
        \
-                         strerror(e));                                         
                                        \
+               if (e) {                                                        
                                                \
+                       err = strerror(e);                                      
                                        \
+               } else if (ex & FE_DIVBYZERO)                                   
                        \
+                       err = "Divide by zero";                                 
                                \
+               else if (ex & FE_OVERFLOW)                                      
                                \
+                       err = "Overflow";                                       
                                        \
+               else if (ex & FE_UNDERFLOW)                                     
                                \
+                       err = "Underflow";                                      
                                        \
+               else                                                            
                                                \
+                       err = "Invalid result";                                 
                                \
+               throw(MAL, "batmmath." #FUNC, "Math exception: %s", err);       
\
        }                                                                       
                                                        \
        BATsetcount(bn, BATcount(b));                                           
                        \
        bn->tsorted = 0;                                                        
                                        \
@@ -85,6 +100,7 @@ str CMDscience_bat_cst_##FUNC##_##TYPE(b
 {                                                                              
                                                                \
        BAT *b, *bn;                                                            
                                                \
        TYPE *o, *p, *q;                                                        
                                                \
+       int e = 0, ex = 0;                                                      
                                                \
                                                                                
                                                                \
        if ((b = BATdescriptor(*bid)) == NULL) {                                
                        \
                throw(MAL, #TYPE, RUNTIME_OBJECT_MISSING);                      
                        \
@@ -103,13 +119,22 @@ str CMDscience_bat_cst_##FUNC##_##TYPE(b
                for (; p < q; o++, p++)                                         
                                        \
                        *o = *p == TYPE##_nil ? TYPE##_nil : FUNC##SUFF(*p, 
*d);        \
        }                                                                       
                                                                \
-       if (errno != 0 ||                                                       
                                                \
-               fetestexcept(FE_INVALID | FE_DIVBYZERO |                        
                        \
-                                        FE_OVERFLOW | FE_UNDERFLOW) != 0) {    
                        \
-               int e = errno;                                                  
                                                \
+       if ((e = errno) != 0 ||                                                 
                                        \
+               (ex = fetestexcept(FE_INVALID | FE_DIVBYZERO |                  
                \
+                                                  FE_OVERFLOW | FE_UNDERFLOW)) 
!= 0) {                 \
+               const char *err;                                                
                                                \
                BBPunfix(bn->batCacheid);                                       
                                        \
-               throw(MAL, "batmmath." #FUNC, "Math exception: %s",             
                \
-                         strerror(e));                                         
                                                \
+               if (e) {                                                        
                                                        \
+                       err = strerror(e);                                      
                                                \
+               } else if (ex & FE_DIVBYZERO)                                   
                                \
+                       err = "Divide by zero";                                 
                                        \
+               else if (ex & FE_OVERFLOW)                                      
                                        \
+                       err = "Overflow";                                       
                                                \
+               else if (ex & FE_UNDERFLOW)                                     
                                        \
+                       err = "Underflow";                                      
                                                \
+               else                                                            
                                                        \
+                       err = "Invalid result";                                 
                                        \
+               throw(MAL, "batmmath." #FUNC, "Math exception: %s", err);       
        \
        }                                                                       
                                                                \
        BATsetcount(bn, BATcount(b));                                           
                                \
        bn->tsorted = 0;                                                        
                                                \
@@ -127,6 +152,7 @@ str CMDscience_cst_bat_##FUNC##_##TYPE(b
 {                                                                              
                                                                \
        BAT *b, *bn;                                                            
                                                \
        TYPE *o, *p, *q;                                                        
                                                \
+       int e = 0, ex = 0;                                                      
                                                \
                                                                                
                                                                \
        if ((b = BATdescriptor(*bid)) == NULL) {                                
                        \
                throw(MAL, #TYPE, RUNTIME_OBJECT_MISSING);                      
                        \
@@ -145,13 +171,22 @@ str CMDscience_cst_bat_##FUNC##_##TYPE(b
                for (; p < q; o++, p++)                                         
                                        \
                        *o = *p == TYPE##_nil ? TYPE##_nil : FUNC##SUFF(*d, 
*p);        \
        }                                                                       
                                                                \
-       if (errno != 0 ||                                                       
                                                \
-               fetestexcept(FE_INVALID | FE_DIVBYZERO |                        
                        \
-                                        FE_OVERFLOW | FE_UNDERFLOW) != 0) {    
                        \
-               int e = errno;                                                  
                                                \
+       if ((e = errno) != 0 ||                                                 
                                        \
+               (ex = fetestexcept(FE_INVALID | FE_DIVBYZERO |                  
                \
+                                                  FE_OVERFLOW | FE_UNDERFLOW)) 
!= 0) {                 \
+               const char *err;                                                
                                                \
                BBPunfix(bn->batCacheid);                                       
                                        \
-               throw(MAL, "batmmath." #FUNC, "Math exception: %s",             
                \
-                         strerror(e));                                         
                                                \
+               if (e) {                                                        
                                                        \
+                       err = strerror(e);                                      
                                                \
+               } else if (ex & FE_DIVBYZERO)                                   
                                \
+                       err = "Divide by zero";                                 
                                        \
+               else if (ex & FE_OVERFLOW)                                      
                                        \
+                       err = "Overflow";                                       
                                                \
+               else if (ex & FE_UNDERFLOW)                                     
                                        \
+                       err = "Underflow";                                      
                                                \
+               else                                                            
                                                        \
+                       err = "Invalid result";                                 
                                        \
+               throw(MAL, "batmmath." #FUNC, "Math exception: %s", err);       
        \
        }                                                                       
                                                                \
        BATsetcount(bn, BATcount(b));                                           
                                \
        bn->tsorted = 0;                                                        
                                                \
diff --git a/monetdb5/modules/kernel/mmath.c b/monetdb5/modules/kernel/mmath.c
--- a/monetdb5/modules/kernel/mmath.c
+++ b/monetdb5/modules/kernel/mmath.c
@@ -24,56 +24,84 @@
 #else
 #define feclearexcept(x)
 #define fetestexcept(x)                0
+#define FE_INVALID                     0
+#define FE_DIVBYZERO           0
+#define FE_OVERFLOW                    0
+#define FE_UNDERFLOW           0
 #endif
 
 #define cot(x)                         (1 / tan(x))
 #define radians(x)                     ((x) * 3.14159265358979323846 / 180.0)
 #define degrees(x)                     ((x) * 180.0 / 3.14159265358979323846)
 
-#define unopbaseM5(NAME, FUNC, TYPE)                                           
        \
-str                                                                            
                                                \
-MATHunary##NAME##TYPE(TYPE *res , const TYPE *a)                               
\
-{                                                                              
                                                \
-       if (*a == TYPE##_nil) {                                                 
                        \
-               *res = TYPE##_nil;                                              
                                \
-       } else {                                                                
                                        \
-               double a1 = *a, r;                                              
                                \
-               errno = 0;                                                      
                                        \
-               feclearexcept(FE_ALL_EXCEPT);                                   
                \
-               r = FUNC(a1);                                                   
                                \
-               if (errno != 0 ||                                               
                                \
-                       fetestexcept(FE_INVALID | FE_DIVBYZERO |                
        \
-                                                FE_OVERFLOW | FE_UNDERFLOW) != 
0)              \
-                       throw(MAL, "mmath." #FUNC, "Math exception: %s",        
\
-                                 strerror(errno));                             
                                \
-               *res = (TYPE) r;                                                
                                \
-       }                                                                       
                                                \
-       return MAL_SUCCEED;                                                     
                                \
+#define unopbaseM5(NAME, FUNC, TYPE)                                           
                \
+str                                                                            
                                                        \
+MATHunary##NAME##TYPE(TYPE *res , const TYPE *a)                               
        \
+{                                                                              
                                                        \
+       if (*a == TYPE##_nil) {                                                 
                                \
+               *res = TYPE##_nil;                                              
                                        \
+       } else {                                                                
                                                \
+               double a1 = *a, r;                                              
                                        \
+               int e = 0, ex = 0;                                              
                                        \
+               errno = 0;                                                      
                                                \
+               feclearexcept(FE_ALL_EXCEPT);                                   
                        \
+               r = FUNC(a1);                                                   
                                        \
+               if ((e = errno) != 0 ||                                         
                                \
+                       (ex = fetestexcept(FE_INVALID | FE_DIVBYZERO |          
        \
+                                                          FE_OVERFLOW | 
FE_UNDERFLOW)) != 0) { \
+                       const char *err;                                        
                                        \
+                       if (e) {                                                
                                                \
+                               err = strerror(e);                              
                                        \
+                       } else if (ex & FE_DIVBYZERO)                           
                        \
+                               err = "Divide by zero";                         
                                \
+                       else if (ex & FE_OVERFLOW)                              
                                \
+                               err = "Overflow";                               
                                        \
+                       else if (ex & FE_UNDERFLOW)                             
                                \
+                               err = "Underflow";                              
                                        \
+                       else                                                    
                                                \
+                               err = "Invalid result";                         
                                \
+                       throw(MAL, "mmath." #FUNC, "Math exception: %s", err);  
\
+               }                                                               
                                                        \
+               *res = (TYPE) r;                                                
                                        \
+       }                                                                       
                                                        \
+       return MAL_SUCCEED;                                                     
                                        \
 }
 
 #define unopM5(NAME, FUNC)                                             \
        unopbaseM5(NAME, FUNC, dbl)                                     \
        unopbaseM5(NAME, FUNC, flt)
 
-#define binopbaseM5(NAME, FUNC, TYPE)                                          
        \
-str                                                                            
                                                \
-MATHbinary##NAME##TYPE(TYPE *res, const TYPE *a, const TYPE *b)        \
-{                                                                              
                                                \
-       if (*a == TYPE##_nil || *b == TYPE##_nil) {                             
        \
-               *res = TYPE##_nil;                                              
                                \
-       } else {                                                                
                                        \
-               double r1, a1 = *a, b1 = *b;                                    
                \
-               errno = 0;                                                      
                                        \
-               feclearexcept(FE_ALL_EXCEPT);                                   
                \
-               r1 = FUNC(a1, b1);                                              
                                \
-               if (errno != 0 ||                                               
                                \
-                       fetestexcept(FE_INVALID | FE_DIVBYZERO |                
        \
-                                                FE_OVERFLOW | FE_UNDERFLOW) != 
0)              \
-                       throw(MAL, "mmath." #FUNC, "Math exception: %s",        
\
-                                 strerror(errno));                             
                                \
-               *res= (TYPE) r1;                                                
                                \
-       }                                                                       
                                                \
-       return MAL_SUCCEED;                                                     
                                \
+#define binopbaseM5(NAME, FUNC, TYPE)                                          
                \
+str                                                                            
                                                        \
+MATHbinary##NAME##TYPE(TYPE *res, const TYPE *a, const TYPE *b)                
\
+{                                                                              
                                                        \
+       if (*a == TYPE##_nil || *b == TYPE##_nil) {                             
                \
+               *res = TYPE##_nil;                                              
                                        \
+       } else {                                                                
                                                \
+               double r1, a1 = *a, b1 = *b;                                    
                        \
+               int e = 0, ex = 0;                                              
                                        \
+               errno = 0;                                                      
                                                \
+               feclearexcept(FE_ALL_EXCEPT);                                   
                        \
+               r1 = FUNC(a1, b1);                                              
                                        \
+               if ((e = errno) != 0 ||                                         
                                \
+                       (ex = fetestexcept(FE_INVALID | FE_DIVBYZERO |          
        \
+                                                          FE_OVERFLOW | 
FE_UNDERFLOW)) != 0) { \
+                       const char *err;                                        
                                        \
+                       if (e) {                                                
                                                \
+                               err = strerror(e);                              
                                        \
+                       } else if (ex & FE_DIVBYZERO)                           
                        \
+                               err = "Divide by zero";                         
                                \
+                       else if (ex & FE_OVERFLOW)                              
                                \
+                               err = "Overflow";                               
                                        \
+                       else if (ex & FE_UNDERFLOW)                             
                                \
+                               err = "Underflow";                              
                                        \
+                       else                                                    
                                                \
+                               err = "Invalid result";                         
                                \
+                       throw(MAL, "mmath." #FUNC, "Math exception: %s", err);  
\
+               }                                                               
                                                        \
+               *res= (TYPE) r1;                                                
                                        \
+       }                                                                       
                                                        \
+       return MAL_SUCCEED;                                                     
                                        \
 }
 
 #define unopM5NOT(NAME, FUNC)                                  \
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to