Vector3 Vector3::Normalized( void ) const throw( DivideByZero ) { float d = Length(); if(d <= Math::EPSILON && -d <= Math::EPSILON) throw DivideByZero(); return Vector3(x / d, y / d, z / d); }
Mtx44 Mtx44::GetInverse() const throw( DivideByZero ) { float a0 = a[ 0]*a[ 5] - a[ 1]*a[ 4]; float a1 = a[ 0]*a[ 6] - a[ 2]*a[ 4]; float a2 = a[ 0]*a[ 7] - a[ 3]*a[ 4]; float a3 = a[ 1]*a[ 6] - a[ 2]*a[ 5]; float a4 = a[ 1]*a[ 7] - a[ 3]*a[ 5]; float a5 = a[ 2]*a[ 7] - a[ 3]*a[ 6]; float b0 = a[ 8]*a[13] - a[ 9]*a[12]; float b1 = a[ 8]*a[14] - a[10]*a[12]; float b2 = a[ 8]*a[15] - a[11]*a[12]; float b3 = a[ 9]*a[14] - a[10]*a[13]; float b4 = a[ 9]*a[15] - a[11]*a[13]; float b5 = a[10]*a[15] - a[11]*a[14]; float det = a0*b5 - a1*b4 + a2*b3 + a3*b2 - a4*b1 + a5*b0; if(abs(det) < Math::EPSILON) throw DivideByZero(); Mtx44 inverse; if (Math::FAbs(det) > Math::EPSILON) { inverse.a[ 0] = + a[ 5]*b5 - a[ 6]*b4 + a[ 7]*b3; inverse.a[ 4] = - a[ 4]*b5 + a[ 6]*b2 - a[ 7]*b1; inverse.a[ 8] = + a[ 4]*b4 - a[ 5]*b2 + a[ 7]*b0; inverse.a[12] = - a[ 4]*b3 + a[ 5]*b1 - a[ 6]*b0; inverse.a[ 1] = - a[ 1]*b5 + a[ 2]*b4 - a[ 3]*b3; inverse.a[ 5] = + a[ 0]*b5 - a[ 2]*b2 + a[ 3]*b1; inverse.a[ 9] = - a[ 0]*b4 + a[ 1]*b2 - a[ 3]*b0; inverse.a[13] = + a[ 0]*b3 - a[ 1]*b1 + a[ 2]*b0; inverse.a[ 2] = + a[13]*a5 - a[14]*a4 + a[15]*a3; inverse.a[ 6] = - a[12]*a5 + a[14]*a2 - a[15]*a1; inverse.a[10] = + a[12]*a4 - a[13]*a2 + a[15]*a0; inverse.a[14] = - a[12]*a3 + a[13]*a1 - a[14]*a0; inverse.a[ 3] = - a[ 9]*a5 + a[10]*a4 - a[11]*a3; inverse.a[ 7] = + a[ 8]*a5 - a[10]*a2 + a[11]*a1; inverse.a[11] = - a[ 8]*a4 + a[ 9]*a2 - a[11]*a0; inverse.a[15] = + a[ 8]*a3 - a[ 9]*a1 + a[10]*a0; float invDet = ((float)1)/det; inverse.a[ 0] *= invDet; inverse.a[ 1] *= invDet; inverse.a[ 2] *= invDet; inverse.a[ 3] *= invDet; inverse.a[ 4] *= invDet; inverse.a[ 5] *= invDet; inverse.a[ 6] *= invDet; inverse.a[ 7] *= invDet; inverse.a[ 8] *= invDet; inverse.a[ 9] *= invDet; inverse.a[10] *= invDet; inverse.a[11] *= invDet; inverse.a[12] *= invDet; inverse.a[13] *= invDet; inverse.a[14] *= invDet; inverse.a[15] *= invDet; } return inverse; }
Vector2 Vector2::Normalized( void ) { float d = Length(); if(d <= Math::EPSILON && -d <= Math::EPSILON) { throw DivideByZero(); } return Vector2(x / d, y / d); }
Vector3& Vector3::Normalize( void ) throw( DivideByZero ) { float d = Length(); if(d <= Math::EPSILON && -d <= Math::EPSILON) throw DivideByZero(); x /= d; y /= d; z /= d; return *this; }
double SimpleCalc::Divide( double lhs, double rhs ) { double result = 0; if ( rhs != 0 ) { result = lhs / rhs; } else { throw DivideByZero(); } return result; }
TEST(fenv, fegetenv_fesetenv) { // Set FE_OVERFLOW only. feclearexcept(FE_ALL_EXCEPT); ASSERT_EQ(0, fetestexcept(FE_ALL_EXCEPT)); ASSERT_EQ(0, feraiseexcept(FE_OVERFLOW)); // fegetenv (unlike feholdexcept) leaves the current state untouched... fenv_t state; ASSERT_EQ(0, fegetenv(&state)); ASSERT_EQ(FE_OVERFLOW, fetestexcept(FE_ALL_EXCEPT)); // Dividing by zero sets the appropriate flag... DivideByZero(); ASSERT_EQ(FE_DIVBYZERO | FE_OVERFLOW, fetestexcept(FE_ALL_EXCEPT)); // And fesetenv (unlike feupdateenv) clobbers that to return to where // we started. ASSERT_EQ(0, fesetenv(&state)); ASSERT_EQ(FE_OVERFLOW, fetestexcept(FE_ALL_EXCEPT)); }
TEST(fenv, feclearexcept_fetestexcept) { // Clearing clears. feclearexcept(FE_ALL_EXCEPT); ASSERT_EQ(0, fetestexcept(FE_ALL_EXCEPT)); // Dividing by zero sets FE_DIVBYZERO. DivideByZero(); int raised = fetestexcept(FE_DIVBYZERO | FE_OVERFLOW); ASSERT_TRUE((raised & FE_OVERFLOW) == 0); ASSERT_TRUE((raised & FE_DIVBYZERO) != 0); // Clearing an unset bit is a no-op. feclearexcept(FE_OVERFLOW); ASSERT_TRUE((raised & FE_OVERFLOW) == 0); ASSERT_TRUE((raised & FE_DIVBYZERO) != 0); // Clearing a set bit works. feclearexcept(FE_DIVBYZERO); ASSERT_EQ(0, fetestexcept(FE_ALL_EXCEPT)); }
TEST(fenv, feholdexcept_feupdateenv) { // Set FE_OVERFLOW only. feclearexcept(FE_ALL_EXCEPT); ASSERT_EQ(0, fetestexcept(FE_ALL_EXCEPT)); ASSERT_EQ(0, feraiseexcept(FE_OVERFLOW)); // feholdexcept (unlike fegetenv) clears everything... fenv_t state; ASSERT_EQ(0, feholdexcept(&state)); ASSERT_EQ(0, fetestexcept(FE_ALL_EXCEPT)); // Dividing by zero sets the appropriate flag... DivideByZero(); ASSERT_EQ(FE_DIVBYZERO, fetestexcept(FE_ALL_EXCEPT)); // And feupdateenv (unlike fesetenv) merges what we started with // (FE_OVERFLOW) with what we now have (FE_DIVBYZERO). ASSERT_EQ(0, feupdateenv(&state)); ASSERT_EQ(FE_DIVBYZERO | FE_OVERFLOW, fetestexcept(FE_ALL_EXCEPT)); }
void Mtx44::SetToRotatePoint(float degrees, float axisX, float axisY, float axisZ) throw(DivideByZero) { double mag = sqrt(axisX * axisX + axisY * axisY + axisZ * axisZ); if (Math::FAbs((float)mag) < Math::EPSILON) throw DivideByZero(); double x = axisX / mag, y = axisY / mag, z = axisZ / mag; double c = cos(degrees * Math::PI / 180), s = sin(degrees * Math::PI / 180); a[0] = (float)(x * x * (1.f - c) + c); a[1] = (float)(y * x * (1.f - c) + z * s); a[2] = (float)(x * z * (1.f - c) - y * s); a[3] = 0; a[4] = (float)(x * y * (1.f - c) - z * s); a[5] = (float)(y * y * (1.f - c) + c); a[6] = (float)(y * z * (1.f - c) + x * s); a[7] = 0; a[8] = (float)(x * z * (1.f - c) + y * s); a[9] = (float)(y * z * (1.f - c) - x * s); a[10] = (float)(z * z * (1.f - c) + c); a[11] = 0; a[12] = 0; a[13] = 0; a[14] = 0; a[15] = 1; }
inline void AssertZero(double nbr) { if(std::fabs(float(nbr)) <= std::numeric_limits<float>::epsilon()) throw DivideByZero(); }
inline void AssertZero(int nbr) { if(!nbr) throw DivideByZero(); }
double Calculator::evaluatePostfix(const char * postfix) { // TODO: uses the stack to evaluate an input string in postfix notation. // If a divide-by-zero error occurs, throw a custom exception and stop. postfix = infixToPostfix(postfix); Stack<double> stackOfDoubles; for (unsigned int i = 0; i < strlen(postfix); i++) // Unsigned int to avoid mismatch { char token = postfix[i]; if (isdigit(token)) { double operand = 0; double convert = 0; int countHowManyDecPlaces = 0; bool isDecimal = false; // FLAG while (i < strlen(postfix) && (isdigit(postfix[i]) || postfix[i] == '.')) { // if it's a decimal if (postfix[i] == '.') { i++; isDecimal = true; continue; } else { operand *= 10; convert = postfix[i] - '0'; operand = operand + convert; i++; if (isDecimal) { countHowManyDecPlaces++; } } } if (countHowManyDecPlaces != 0) // Handling of decimal inputs { // 1 decimal place if (countHowManyDecPlaces == 1) operand = operand / 10; // 2 decimal places if (countHowManyDecPlaces == 2) operand = operand / 100; // 3 decimal places if (countHowManyDecPlaces == 3) operand = operand / 1000; // 4 decimal places if (countHowManyDecPlaces == 4) operand = operand / 10000; // 5 decimal places if (countHowManyDecPlaces == 5) operand = operand / 100000; } i--; // Decrement i inorder to stay return back to track stackOfDoubles.push(operand); } else if (isOperator(token)) { double operand2 = stackOfDoubles.top(); stackOfDoubles.pop(); // Get two operands to prepare for calculator functions double operand1 = stackOfDoubles.top(); stackOfDoubles.pop(); if (operand2 == 0 && (postfix[i] == '/' || postfix[i] == '%')) { throw DivideByZero(); return 0; } if (token == '+') // Perform the operation: operand1 chr operand2 stackOfDoubles.push(operand1 + operand2); if (token == '-') // Perform the operation: operand1 chr operand2 stackOfDoubles.push(operand1 - operand2); if (token == '*') // Perform the operation: operand1 chr operand2 stackOfDoubles.push(operand1 * operand2); if (token == '/') // Perform the operation: operand1 chr operand2 stackOfDoubles.push(operand1 / operand2); } } double answer; answer = stackOfDoubles.top(); return answer; }