コード例 #1
0
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;
}
コード例 #2
0
ファイル: decimal.cpp プロジェクト: matt-harvey/jewel
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;
}
コード例 #3
0
ファイル: decimal.cpp プロジェクト: matt-harvey/jewel
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.

}