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
