int BTEditor::getWallType(int x, int y, int direction) { rationalize(x, y); IShort w = levelMap->getSquare(y, x).getWall(direction); if (w == 0) return 0; int mapType = p3dConfig->findMapType(w, true); if (mapType == 0) return 0; if (-1 != p3dConfig->mapType[mapType - 1]->incompleteType) return p3dConfig->mapType[mapType - 1]->incompleteType; return w; }
Decimal& Decimal::operator/=(Decimal rhs) { // Record original dividend and divisor Decimal const orig = *this; rhs.rationalize(); // Capture division by zero if (rhs.m_intval == 0) { JEWEL_ASSERT (*this == orig); JEWEL_THROW(DecimalDivisionByZeroException, "Division by zero."); } // To prevent complications if ( m_intval == numeric_limits<int_type>::min() || rhs.m_intval == numeric_limits<int_type>::min() ) { JEWEL_ASSERT (*this == orig); JEWEL_THROW ( DecimalDivisionException, "Smallest possible Decimal cannot " "feature in division operation." ); } JEWEL_ASSERT (NumDigits::num_digits(rhs.m_intval) <= maximum_precision()); if (NumDigits::num_digits(rhs.m_intval) == maximum_precision()) { JEWEL_ASSERT (*this == orig); JEWEL_THROW ( DecimalDivisionException, "Dividend has a number of significant" "digits that is greater than or equal to the return value of " "Decimal::maximum_precision(); as a result, division cannot be " "performed safely." ); } // Remember required sign of product bool const diff_signs = ( ( m_intval > 0 && rhs.m_intval < 0) || ( m_intval < 0 && rhs.m_intval > 0) ); // Make absolute JEWEL_ASSERT ( !multiplication_is_unsafe(m_intval, static_cast<int_type>(-1)) ); JEWEL_ASSERT ( !multiplication_is_unsafe(rhs.m_intval, static_cast<int_type>(-1)) ); if (m_intval < 0) m_intval *= -1; if (rhs.m_intval < 0) rhs.m_intval *= -1; // Rescale the dividend as high as we can while (m_places < rhs.m_places && rescale(m_places + 1) == 0) { } if (rhs.m_places > m_places) { // We can't rescale high enough to proceed, so reset and throw *this = orig; JEWEL_THROW(DecimalDivisionException, "Unsafe division."); } // Proceed with basic division algorithm JEWEL_ASSERT (m_places >= rhs.m_places); JEWEL_ASSERT (!subtraction_is_unsafe(m_places, rhs.m_places)); m_places -= rhs.m_places; JEWEL_ASSERT (rhs.m_intval != 0); JEWEL_ASSERT (m_intval != numeric_limits<int_type>::min()); JEWEL_ASSERT (!remainder_is_unsafe(m_intval, rhs.m_intval)); int_type remainder = m_intval % rhs.m_intval; JEWEL_ASSERT (!division_is_unsafe(m_intval, rhs.m_intval)); m_intval /= rhs.m_intval; // Deal with any remainder using "long division" while (remainder != 0 && rescale(m_places + 1) == 0) { JEWEL_ASSERT (!multiplication_is_unsafe(remainder, s_base)); /* * Previously this commented-out section of code dealt * with the case where it was unsafe to multiply remainder * and s_base. However, this is now dealt with by the fact that * an exception is thrown if the number of significant digits * in the dividend is equal to Decimal::maximum_precision(). * This makes for a more straightforward API, since the * below code caused loss of precision under difficult-to-explain * circumstances. if (multiplication_is_unsafe(remainder, s_base)) { // Then we can't proceed with ordinary "long division" safely, // and need to "scale down" first bool add_rounding_right = false; if (rhs.m_intval % s_base >= s_rounding_threshold) { add_rounding_right = true; } rhs.m_intval /= s_base; if (add_rounding_right) { JEWEL_ASSERT (!addition_is_unsafe(rhs.m_intval, JEWEL_NUMERIC_CAST<int_type>(1))); ++(rhs.m_intval); } // Redo the Decimal division on a "safe scale" Decimal lhs = orig; if (lhs.m_intval < 0) lhs.m_intval *= -1; JEWEL_ASSERT (rhs.m_intval >= 0); lhs /= rhs; bool add_rounding_left = false; if (lhs.m_intval % s_base >= s_rounding_threshold) { add_rounding_left = true; } lhs.m_intval /= s_base; if (add_rounding_left) { JEWEL_ASSERT (!addition_is_unsafe(lhs.m_intval, JEWEL_NUMERIC_CAST<int_type>(1))); ++(lhs.m_intval); } if (diff_signs) lhs.m_intval *= -1; *this = lhs; return *this; } */ // It's safe to proceed with ordinary "long division" JEWEL_ASSERT (!multiplication_is_unsafe(remainder, s_base)); remainder *= s_base; JEWEL_ASSERT (rhs.m_intval > 0); JEWEL_ASSERT (!remainder_is_unsafe(remainder, rhs.m_intval)); int_type const temp_remainder = remainder % rhs.m_intval; JEWEL_ASSERT (!division_is_unsafe(remainder, rhs.m_intval)); m_intval += remainder / rhs.m_intval; remainder = temp_remainder; } // Do rounding if required JEWEL_ASSERT (rhs.m_intval >= remainder); JEWEL_ASSERT (!subtraction_is_unsafe(rhs.m_intval, remainder)); if (rhs.m_intval - remainder <= remainder) { // If the required rounding would be unsafe, we throw if (addition_is_unsafe(m_intval, JEWEL_NUMERIC_CAST<int_type>(1))) { *this = orig; JEWEL_THROW(DecimalDivisionException, "Unsafe division."); } // Do the rounding, it's safe ++m_intval; } // Put the correct sign JEWEL_ASSERT (m_intval >= 0); JEWEL_ASSERT ( !multiplication_is_unsafe(m_intval, static_cast<int_type>(-1)) ); if (diff_signs) m_intval *= -1; rationalize(); return *this; }
Decimal& Decimal::operator*=(Decimal rhs) { Decimal orig = *this; rationalize(); rhs.rationalize(); // Rule out problematic smallest Decimal JEWEL_ASSERT (minimum() == Decimal(numeric_limits<int_type>::min(), 0)); JEWEL_ASSERT (maximum() == Decimal(numeric_limits<int_type>::max(), 0)); if (*this == minimum() || rhs == minimum()) { JEWEL_ASSERT (*this == orig); JEWEL_THROW ( DecimalMultiplicationException, "Cannot multiply smallest possible " "Decimal safely." ); } // Make absolute and remember signs bool const signs_differ = ( (m_intval < 0 && rhs.m_intval > 0) || (m_intval > 0 && rhs.m_intval < 0) ); if (m_intval < 0) { JEWEL_ASSERT ( !multiplication_is_unsafe(m_intval, static_cast<int_type>(-1)) ); m_intval *= -1; } if (rhs.m_intval < 0) { JEWEL_ASSERT ( !multiplication_is_unsafe(rhs.m_intval, static_cast<int_type>(-1)) ); rhs.m_intval *= -1; } // Do "unchecked multiply" if we can JEWEL_ASSERT (m_intval >= 0 && rhs.m_intval >= 0); if (!multiplication_is_unsafe(m_intval, rhs.m_intval)) { JEWEL_ASSERT (!addition_is_unsafe(m_places, rhs.m_places)); m_intval *= rhs.m_intval; m_places += rhs.m_places; while (m_places > s_max_places) { JEWEL_ASSERT (m_places > 0); #ifndef NDEBUG int const check = rescale(m_places - 1); JEWEL_ASSERT (check == 0); #else rescale(m_places - 1); #endif } if (signs_differ) { JEWEL_ASSERT (m_intval != numeric_limits<int_type>::min()); JEWEL_ASSERT ( !multiplication_is_unsafe ( m_intval, static_cast<int_type>(-1) ) ); m_intval *= -1; } rationalize(); return *this; } *this = orig; JEWEL_THROW(DecimalMultiplicationException, "Unsafe multiplication."); JEWEL_HARD_ASSERT (false); // Execution should never reach here. return *this; // Silence compiler re. return from non-void function. }