diff --git a/mex/sources/bytecode/ErrorHandling.hh b/mex/sources/bytecode/ErrorHandling.hh index 00e6c8cdb..99f847295 100644 --- a/mex/sources/bytecode/ErrorHandling.hh +++ b/mex/sources/bytecode/ErrorHandling.hh @@ -41,28 +41,14 @@ struct FloatingPointException : public GeneralException } }; -struct LogException : public FloatingPointException +struct UnaryOpException : public FloatingPointException { - LogException(double value, string location_arg) : + UnaryOpException(const string &op, double value, string location_arg) : FloatingPointException { [=] { // We don’t use std::to_string(), because it uses fixed formatting ostringstream s; - s << "log(X) with X=" << defaultfloat << value; - return s.str(); - }(), move(location_arg) } - { - } -}; - -struct Log10Exception : public FloatingPointException -{ - Log10Exception(double value, string location_arg) : - FloatingPointException { [=] - { - // We don’t use std::to_string(), because it uses fixed formatting - ostringstream s; - s << "log10(X) with X=" << defaultfloat << value; + s << op << "(X) with X=" << defaultfloat << value; return s.str(); }(), move(location_arg) } { diff --git a/mex/sources/bytecode/Evaluate.cc b/mex/sources/bytecode/Evaluate.cc index 8736ff3d9..04834f217 100644 --- a/mex/sources/bytecode/Evaluate.cc +++ b/mex/sources/bytecode/Evaluate.cc @@ -643,27 +643,27 @@ Evaluate::print_expression(const Evaluate::it_code_type &expr_begin, const optio case UnaryOpcode::sin: return "sin"; case UnaryOpcode::tan: - return "tan"; + return it_code == faulty_op ? "{tan}" : "tan"; case UnaryOpcode::acos: - return "acos"; + return it_code == faulty_op ? "{acos}" : "acos"; case UnaryOpcode::asin: - return "asin"; + return it_code == faulty_op ? "{asin}" : "asin"; case UnaryOpcode::atan: return "atan"; case UnaryOpcode::cosh: - return "cosh"; + return it_code == faulty_op ? "{cosh}" : "cosh"; case UnaryOpcode::sinh: - return "sinh"; + return it_code == faulty_op ? "{sinh}" : "sinh"; case UnaryOpcode::tanh: return "tanh"; case UnaryOpcode::acosh: - return "acosh"; + return it_code == faulty_op ? "{acosh}" : "acosh"; case UnaryOpcode::asinh: return "asinh"; case UnaryOpcode::atanh: - return "atanh"; + return it_code == faulty_op ? "{atanh}" : "atanh"; case UnaryOpcode::sqrt: - return "sqrt"; + return it_code == faulty_op ? "{sqrt}" : "sqrt"; case UnaryOpcode::cbrt: return "cbrt"; case UnaryOpcode::erf: @@ -1699,7 +1699,7 @@ Evaluate::evaluateBlock(int Per_u_, bool evaluate, bool no_derivative) feclearexcept(FE_ALL_EXCEPT); double tmp {log(v1)}; if (fetestexcept(FE_DIVBYZERO | FE_INVALID)) - throw LogException{v1, error_location(it_code_expr, it_code, steady_state, it_)}; + throw UnaryOpException{"log", v1, error_location(it_code_expr, it_code, steady_state, it_)}; Stack.push(tmp); } #ifdef DEBUG @@ -1711,7 +1711,7 @@ Evaluate::evaluateBlock(int Per_u_, bool evaluate, bool no_derivative) feclearexcept(FE_ALL_EXCEPT); double tmp {log10(v1)}; if (fetestexcept(FE_DIVBYZERO | FE_INVALID)) - throw Log10Exception{v1, error_location(it_code_expr, it_code, steady_state, it_)}; + throw UnaryOpException{"log10", v1, error_location(it_code_expr, it_code, steady_state, it_)}; Stack.push(tmp); } #ifdef DEBUG @@ -1731,19 +1731,37 @@ Evaluate::evaluateBlock(int Per_u_, bool evaluate, bool no_derivative) #endif break; case UnaryOpcode::tan: - Stack.push(tan(v1)); + { + feclearexcept(FE_ALL_EXCEPT); + double tmp {tan(v1)}; + if (fetestexcept(FE_OVERFLOW)) + throw UnaryOpException{"tan", v1, error_location(it_code_expr, it_code, steady_state, it_)}; + Stack.push(tmp); + } #ifdef DEBUG tmp_out << " |tan(" << v1 << ")|"; #endif break; case UnaryOpcode::acos: - Stack.push(acos(v1)); + { + feclearexcept(FE_ALL_EXCEPT); + double tmp {acos(v1)}; + if (fetestexcept(FE_INVALID)) + throw UnaryOpException{"acos", v1, error_location(it_code_expr, it_code, steady_state, it_)}; + Stack.push(tmp); + } #ifdef DEBUG tmp_out << " |acos(" << v1 << ")|"; #endif break; case UnaryOpcode::asin: - Stack.push(asin(v1)); + { + feclearexcept(FE_ALL_EXCEPT); + double tmp {asin(v1)}; + if (fetestexcept(FE_INVALID)) + throw UnaryOpException{"asin", v1, error_location(it_code_expr, it_code, steady_state, it_)}; + Stack.push(tmp); + } #ifdef DEBUG tmp_out << " |asin(" << v1 << ")|"; #endif @@ -1755,13 +1773,25 @@ Evaluate::evaluateBlock(int Per_u_, bool evaluate, bool no_derivative) #endif break; case UnaryOpcode::cosh: - Stack.push(cosh(v1)); + { + feclearexcept(FE_ALL_EXCEPT); + double tmp {cosh(v1)}; + if (fetestexcept(FE_OVERFLOW)) + throw UnaryOpException{"cosh", v1, error_location(it_code_expr, it_code, steady_state, it_)}; + Stack.push(tmp); + } #ifdef DEBUG tmp_out << " |cosh(" << v1 << ")|"; #endif break; case UnaryOpcode::sinh: - Stack.push(sinh(v1)); + { + feclearexcept(FE_ALL_EXCEPT); + double tmp {sinh(v1)}; + if (fetestexcept(FE_OVERFLOW)) + throw UnaryOpException{"sinh", v1, error_location(it_code_expr, it_code, steady_state, it_)}; + Stack.push(tmp); + } #ifdef DEBUG tmp_out << " |sinh(" << v1 << ")|"; #endif @@ -1773,7 +1803,13 @@ Evaluate::evaluateBlock(int Per_u_, bool evaluate, bool no_derivative) #endif break; case UnaryOpcode::acosh: - Stack.push(acosh(v1)); + { + feclearexcept(FE_ALL_EXCEPT); + double tmp {acosh(v1)}; + if (fetestexcept(FE_INVALID)) + throw UnaryOpException{"acosh", v1, error_location(it_code_expr, it_code, steady_state, it_)}; + Stack.push(tmp); + } #ifdef DEBUG tmp_out << " |acosh(" << v1 << ")|"; #endif @@ -1785,13 +1821,25 @@ Evaluate::evaluateBlock(int Per_u_, bool evaluate, bool no_derivative) #endif break; case UnaryOpcode::atanh: - Stack.push(atanh(v1)); + { + feclearexcept(FE_ALL_EXCEPT); + double tmp {atanh(v1)}; + if (fetestexcept(FE_INVALID | FE_DIVBYZERO)) + throw UnaryOpException{"atanh", v1, error_location(it_code_expr, it_code, steady_state, it_)}; + Stack.push(tmp); + } #ifdef DEBUG tmp_out << " |atanh(" << v1 << ")|"; #endif break; case UnaryOpcode::sqrt: - Stack.push(sqrt(v1)); + { + feclearexcept(FE_ALL_EXCEPT); + double tmp {sqrt(v1)}; + if (fetestexcept(FE_INVALID)) + throw UnaryOpException{"sqrt", v1, error_location(it_code_expr, it_code, steady_state, it_)}; + Stack.push(tmp); + } #ifdef DEBUG tmp_out << " |sqrt(" << v1 << ")|"; #endif