longlong.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,199 行 · 第 1/2 页

CPP
1,199
字号

wxULongLongWx wxULongLongWx::operator|(const wxULongLongWx& ll) const
{
    return wxULongLongWx(m_hi | ll.m_hi, m_lo | ll.m_lo);
}

wxLongLongWx wxLongLongWx::operator^(const wxLongLongWx& ll) const
{
    return wxLongLongWx(m_hi ^ ll.m_hi, m_lo ^ ll.m_lo);
}

wxULongLongWx wxULongLongWx::operator^(const wxULongLongWx& ll) const
{
    return wxULongLongWx(m_hi ^ ll.m_hi, m_lo ^ ll.m_lo);
}

wxLongLongWx& wxLongLongWx::operator&=(const wxLongLongWx& ll)
{
    m_lo &= ll.m_lo;
    m_hi &= ll.m_hi;

#ifdef wxLONGLONG_TEST_MODE
    m_ll &= ll.m_ll;

    Check();
#endif // wxLONGLONG_TEST_MODE

    return *this;
}

wxULongLongWx& wxULongLongWx::operator&=(const wxULongLongWx& ll)
{
    m_lo &= ll.m_lo;
    m_hi &= ll.m_hi;

#ifdef wxLONGLONG_TEST_MODE
    m_ll &= ll.m_ll;

    Check();
#endif // wxLONGLONG_TEST_MODE

    return *this;
}

wxLongLongWx& wxLongLongWx::operator|=(const wxLongLongWx& ll)
{
    m_lo |= ll.m_lo;
    m_hi |= ll.m_hi;

#ifdef wxLONGLONG_TEST_MODE
    m_ll |= ll.m_ll;

    Check();
#endif // wxLONGLONG_TEST_MODE

    return *this;
}

wxULongLongWx& wxULongLongWx::operator|=(const wxULongLongWx& ll)
{
    m_lo |= ll.m_lo;
    m_hi |= ll.m_hi;

#ifdef wxLONGLONG_TEST_MODE
    m_ll |= ll.m_ll;

    Check();
#endif // wxLONGLONG_TEST_MODE

    return *this;
}

wxLongLongWx& wxLongLongWx::operator^=(const wxLongLongWx& ll)
{
    m_lo ^= ll.m_lo;
    m_hi ^= ll.m_hi;

#ifdef wxLONGLONG_TEST_MODE
    m_ll ^= ll.m_ll;

    Check();
#endif // wxLONGLONG_TEST_MODE

    return *this;
}

wxULongLongWx& wxULongLongWx::operator^=(const wxULongLongWx& ll)
{
    m_lo ^= ll.m_lo;
    m_hi ^= ll.m_hi;

#ifdef wxLONGLONG_TEST_MODE
    m_ll ^= ll.m_ll;

    Check();
#endif // wxLONGLONG_TEST_MODE

    return *this;
}

wxLongLongWx wxLongLongWx::operator~() const
{
    return wxLongLongWx(~m_hi, ~m_lo);
}

wxULongLongWx wxULongLongWx::operator~() const
{
    return wxULongLongWx(~m_hi, ~m_lo);
}

// multiplication

wxLongLongWx wxLongLongWx::operator*(const wxLongLongWx& ll) const
{
    wxLongLongWx res(*this);
    res *= ll;

    return res;
}

wxULongLongWx wxULongLongWx::operator*(const wxULongLongWx& ll) const
{
    wxULongLongWx res(*this);
    res *= ll;

    return res;
}

wxLongLongWx& wxLongLongWx::operator*=(const wxLongLongWx& ll)
{
    wxLongLongWx t(m_hi, m_lo);
    wxLongLongWx q(ll.m_hi, ll.m_lo);

    m_hi = m_lo = 0;

#ifdef wxLONGLONG_TEST_MODE
    wxLongLong_t llOld = m_ll;
    m_ll = 0;
#endif // wxLONGLONG_TEST_MODE

    int counter = 0;
    do
    {
        if ((q.m_lo & 1) != 0)
            *this += t;
        q >>= 1;
        t <<= 1;
        counter++;
    }
    while ((counter < 64) && ((q.m_hi != 0) || (q.m_lo != 0)));

#ifdef wxLONGLONG_TEST_MODE
    m_ll = llOld * ll.m_ll;

    Check();
#endif // wxLONGLONG_TEST_MODE

    return *this;
}

wxULongLongWx& wxULongLongWx::operator*=(const wxULongLongWx& ll)
{
    wxULongLongWx t(m_hi, m_lo);
    wxULongLongWx q(ll.m_hi, ll.m_lo);

    m_hi = m_lo = 0;

#ifdef wxLONGLONG_TEST_MODE
    wxULongLong_t llOld = m_ll;
    m_ll = 0;
#endif // wxLONGLONG_TEST_MODE

    int counter = 0;
    do
    {
        if ((q.m_lo & 1) != 0)
            *this += t;
        q >>= 1;
        t <<= 1;
        counter++;
    }
    while ((counter < 64) && ((q.m_hi != 0) || (q.m_lo != 0)));

#ifdef wxLONGLONG_TEST_MODE
    m_ll = llOld * ll.m_ll;

    Check();
#endif // wxLONGLONG_TEST_MODE

    return *this;
}

// division

#define IS_MSB_SET(ll)  ((ll.GetHi()) & (1 << (8*sizeof(long) - 1)))

void wxLongLongWx::Divide(const wxLongLongWx& divisorIn,
                          wxLongLongWx& quotient,
                          wxLongLongWx& remainderIO) const
{
    if ((divisorIn.m_lo == 0) && (divisorIn.m_hi == 0))
    {
        // provoke division by zero error and silence the compilers warnings
        // about an expression without effect and unused variable
        long dummy = divisorIn.m_lo/divisorIn.m_hi;
        dummy += 0;
    }

    // VZ: I'm writing this in a hurry and it's surely not the fastest way to
    //     do this - any improvements are more than welcome
    //
    //     code inspired by the snippet at
    //          http://www.bearcave.com/software/divide.htm
    //
    //     Copyright notice:
    //
    //     Use of this program, for any purpose, is granted the author, Ian
    //     Kaplan, as long as this copyright notice is included in the source
    //     code or any source code derived from this program. The user assumes
    //     all responsibility for using this code.

    // init everything
    wxULongLongWx dividend, divisor, remainder;

    quotient = 0l;
    remainder = 0l;

    // always do unsigned division and adjust the signs later: in C integer
    // division, the sign of the remainder is the same as the sign of the
    // dividend, while the sign of the quotient is the product of the signs of
    // the dividend and divisor. Of course, we also always have
    //
    //      dividend = quotient*divisor + remainder
    //
    // with 0 <= abs(remainder) < abs(divisor)
    bool negRemainder = GetHi() < 0;
    bool negQuotient = false;   // assume positive
    if ( GetHi() < 0 )
    {
        negQuotient = !negQuotient;
        dividend = -*this;
    } else {
        dividend = *this;
    }
    if ( divisorIn.GetHi() < 0 )
    {
        negQuotient = !negQuotient;
        divisor = -divisorIn;
    } else {
        divisor = divisorIn;
    }

    // check for some particular cases
    if ( divisor > dividend )
    {
        remainder = dividend;
    }
    else if ( divisor == dividend )
    {
        quotient = 1l;
    }
    else
    {
        // here: dividend > divisor and both are positive: do unsigned division
        size_t nBits = 64u;
        wxLongLongWx d;

        while ( remainder < divisor )
        {
            remainder <<= 1;
            if ( IS_MSB_SET(dividend) )
            {
                remainder |= 1;
            }

            d = dividend;
            dividend <<= 1;

            nBits--;
        }

        // undo the last loop iteration
        dividend = d;
        remainder >>= 1;
        nBits++;

        for ( size_t i = 0; i < nBits; i++ )
        {
            remainder <<= 1;
            if ( IS_MSB_SET(dividend) )
            {
                remainder |= 1;
            }

            wxLongLongWx t = remainder - divisor;
            dividend <<= 1;
            quotient <<= 1;
            if ( !IS_MSB_SET(t) )
            {
                quotient |= 1;

                remainder = t;
            }
        }
    }

    remainderIO = remainder;

    // adjust signs
    if ( negRemainder )
    {
        remainderIO = -remainderIO;
    }

    if ( negQuotient )
    {
        quotient = -quotient;
    }
}

void wxULongLongWx::Divide(const wxULongLongWx& divisorIn,
                           wxULongLongWx& quotient,
                           wxULongLongWx& remainder) const
{
    if ((divisorIn.m_lo == 0) && (divisorIn.m_hi == 0))
    {
        // provoke division by zero error and silence the compilers warnings
        // about an expression without effect and unused variable
        unsigned long dummy = divisorIn.m_lo/divisorIn.m_hi;
        dummy += 0;
    }

    // VZ: I'm writing this in a hurry and it's surely not the fastest way to
    //     do this - any improvements are more than welcome
    //
    //     code inspired by the snippet at
    //          http://www.bearcave.com/software/divide.htm
    //
    //     Copyright notice:
    //
    //     Use of this program, for any purpose, is granted the author, Ian
    //     Kaplan, as long as this copyright notice is included in the source
    //     code or any source code derived from this program. The user assumes
    //     all responsibility for using this code.

    // init everything
    wxULongLongWx dividend = *this,
                  divisor = divisorIn;

    quotient = 0l;
    remainder = 0l;

    // check for some particular cases
    if ( divisor > dividend )
    {
        remainder = dividend;
    }
    else if ( divisor == dividend )
    {
        quotient = 1l;
    }
    else
    {
        // here: dividend > divisor
        size_t nBits = 64u;
        wxULongLongWx d;

        while ( remainder < divisor )
        {
            remainder <<= 1;
            if ( IS_MSB_SET(dividend) )
            {
                remainder |= 1;
            }

            d = dividend;
            dividend <<= 1;

            nBits--;
        }

        // undo the last loop iteration
        dividend = d;
        remainder >>= 1;
        nBits++;

        for ( size_t i = 0; i < nBits; i++ )
        {
            remainder <<= 1;
            if ( IS_MSB_SET(dividend) )
            {
                remainder |= 1;
            }

            wxULongLongWx t = remainder - divisor;
            dividend <<= 1;
            quotient <<= 1;
            if ( !IS_MSB_SET(t) )
            {
                quotient |= 1;

                remainder = t;
            }
        }
    }
}

wxLongLongWx wxLongLongWx::operator/(const wxLongLongWx& ll) const
{
    wxLongLongWx quotient, remainder;

    Divide(ll, quotient, remainder);

    return quotient;
}

wxULongLongWx wxULongLongWx::operator/(const wxULongLongWx& ll) const
{
    wxULongLongWx quotient, remainder;

    Divide(ll, quotient, remainder);

    return quotient;
}

wxLongLongWx& wxLongLongWx::operator/=(const wxLongLongWx& ll)
{
    wxLongLongWx quotient, remainder;

    Divide(ll, quotient, remainder);

    *this = quotient;

    return *this;
}

wxULongLongWx& wxULongLongWx::operator/=(const wxULongLongWx& ll)
{
    wxULongLongWx quotient, remainder;

    Divide(ll, quotient, remainder);

    *this = quotient;

    return *this;
}

wxLongLongWx wxLongLongWx::operator%(const wxLongLongWx& ll) const
{
    wxLongLongWx quotient, remainder;

    Divide(ll, quotient, remainder);

    return remainder;
}

wxULongLongWx wxULongLongWx::operator%(const wxULongLongWx& ll) const
{
    wxULongLongWx quotient, remainder;

    Divide(ll, quotient, remainder);

    return remainder;
}

// ----------------------------------------------------------------------------
// misc
// ----------------------------------------------------------------------------

// temporary - just for testing
void *wxLongLongWx::asArray(void) const
{
    static unsigned char temp[8];

    temp[0] = (char)((m_hi >> 24) & 0xFF);
    temp[1] = (char)((m_hi >> 16) & 0xFF);
    temp[2] = (char)((m_hi >> 8)  & 0xFF);
    temp[3] = (char)((m_hi >> 0)  & 0xFF);
    temp[4] = (char)((m_lo >> 24) & 0xFF);
    temp[5] = (char)((m_lo >> 16) & 0xFF);
    temp[6] = (char)((m_lo >> 8)  & 0xFF);
    temp[7] = (char)((m_lo >> 0)  & 0xFF);

    return temp;
}

void *wxULongLongWx::asArray(void) const
{
    static unsigned char temp[8];

    temp[0] = (char)((m_hi >> 24) & 0xFF);
    temp[1] = (char)((m_hi >> 16) & 0xFF);
    temp[2] = (char)((m_hi >> 8)  & 0xFF);
    temp[3] = (char)((m_hi >> 0)  & 0xFF);
    temp[4] = (char)((m_lo >> 24) & 0xFF);
    temp[5] = (char)((m_lo >> 16) & 0xFF);
    temp[6] = (char)((m_lo >> 8)  & 0xFF);
    temp[7] = (char)((m_lo >> 0)  & 0xFF);

    return temp;
}

#endif // wxUSE_LONGLONG_WX

#define LL_TO_STRING(name)                                           \
    wxString name::ToString() const                                  \
    {                                                                \
        /* TODO: this is awfully inefficient, anything better? */    \
        wxString result;                                             \
                                                                     \
        name ll = *this;                                             \
                                                                     \
        bool neg = ll < 0;                                           \
        if ( neg )                                                   \
        {                                                            \
            while ( ll != 0 )                                        \
            {                                                        \
                long digit = (ll % 10).ToLong();                     \
                result.Prepend((wxChar)(_T('0') - digit));           \
                ll /= 10;                                            \
            }                                                        \
        }                                                            \
        else                                                         \
        {                                                            \
            while ( ll != 0 )                                        \
            {                                                        \
                long digit = (ll % 10).ToLong();                     \
                result.Prepend((wxChar)(_T('0') + digit));           \
                ll /= 10;                                            \
            }                                                        \
        }                                                            \
                                                                     \
        if ( result.empty() )                                        \
            result = _T('0');                                        \
        else if ( neg )                                              \
            result.Prepend(_T('-'));                                 \
                                                                     \
        return result;                                               \
    }

#define ULL_TO_STRING(name)                                          \
    wxString name::ToString() const                                  \
    {                                                                \
        /* TODO: this is awfully inefficient, anything better? */    \
        wxString result;                                             \
                                                                     \
        name ll = *this;                                             \
                                                                     \
        while ( ll != 0 )                                            \
        {                                                            \
            result.Prepend((wxChar)(_T('0') + (ll % 10).ToULong())); \
            ll /= 10;                                                \
        }                                                            \
                                                                     \
        if ( result.empty() )                                        \
            result = _T('0');                                        \
                                                                     \
        return result;                                               \
    }

#if wxUSE_LONGLONG_NATIVE
    LL_TO_STRING(wxLongLongNative)
    ULL_TO_STRING(wxULongLongNative)
#endif

#if wxUSE_LONGLONG_WX
    LL_TO_STRING(wxLongLongWx)
    ULL_TO_STRING(wxULongLongWx)
#endif

#if wxUSE_STD_IOSTREAM

// input/output
WXDLLIMPEXP_BASE
wxSTD ostream& operator<< (wxSTD ostream& o, const wxLongLong& ll)
{
    return o << ll.ToString();
}

WXDLLIMPEXP_BASE
wxSTD ostream& operator<< (wxSTD ostream& o, const wxULongLong& ll)
{
    return o << ll.ToString();
}

#endif // wxUSE_STD_IOSTREAM

WXDLLIMPEXP_BASE wxString& operator<< (wxString& s, const wxLongLong& ll)
{
    return s << ll.ToString();
}

WXDLLIMPEXP_BASE wxString& operator<< (wxString& s, const wxULongLong& ll)
{
    return s << ll.ToString();
}

#endif // wxUSE_LONGLONG

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?