X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4e57b0d49515043e7b4083eb596ac5044ccb950e..674ac8b919eecbc201b5f23b470a567cd0565e10:/src/common/longlong.cpp diff --git a/src/common/longlong.cpp b/src/common/longlong.cpp index fd0c992c3f..2dd291fb1c 100644 --- a/src/common/longlong.cpp +++ b/src/common/longlong.cpp @@ -26,10 +26,10 @@ #endif #if wxUSE_LONGLONG - #include "wx/longlong.h" #include // for memset() +#include // for fabs() // ============================================================================ // implementation @@ -57,6 +57,8 @@ void *wxLongLongNative::asArray(void) const return temp; } +#if wxUSE_STD_IOSTREAM + // input/output ostream& operator<< (ostream& o, const wxLongLongNative& ll) { @@ -74,10 +76,32 @@ ostream& operator<< (ostream& o, const wxLongLongNative& ll) return o << result; } +#endif // wxUSE_STD_IOSTREAM + #endif // wxUSE_LONGLONG_NATIVE +// ============================================================================ +// wxLongLongWx: emulation of 'long long' using 2 longs +// ============================================================================ + #if wxUSE_LONGLONG_WX +// assignment +wxLongLongWx& wxLongLongWx::Assign(double d) +{ + if ( fabs(d) <= LONG_MAX ) + { + m_hi = d < 0 ? 1 << (8*sizeof(long) - 1) : 0l; + m_lo = (long)d; + } + else + { + wxFAIL_MSG(_T("TODO")); + } + + return *this; +} + wxLongLongWx wxLongLongWx::operator<<(int shift) const { if (shift == 0) @@ -255,7 +279,7 @@ wxLongLongWx& wxLongLongWx::operator-=(const wxLongLongWx& ll) if (previous < ll.m_lo) m_hi--; - return *this;; + return *this; } // pre decrement @@ -282,54 +306,22 @@ wxLongLongWx& wxLongLongWx::operator--(int) bool wxLongLongWx::operator<(const wxLongLongWx& ll) const { - if (m_lo < ll.m_lo) - return 1; - if (m_lo > ll.m_lo) - return 0; - if (m_hi < ll.m_hi) - return 1; - if (m_hi > ll.m_hi) - return 0; - return 0; + if ( m_hi < ll.m_hi ) + return TRUE; + else if ( m_hi == ll.m_hi ) + return m_lo < ll.m_lo; + else + return FALSE; } bool wxLongLongWx::operator>(const wxLongLongWx& ll) const { - if (m_lo < ll.m_lo) - return 0; - if (m_lo > ll.m_lo) - return 1; - if (m_hi < ll.m_hi) - return 0; - if (m_hi > ll.m_hi) - return 1; - return 0; -} - -bool wxLongLongWx::operator<=(const wxLongLongWx& ll) const -{ - if (m_lo < ll.m_lo) - return 1; - if (m_lo > ll.m_lo) - return 0; - if (m_hi < ll.m_hi) - return 1; - if (m_hi > ll.m_hi) - return 0; - return 1; -} - -bool wxLongLongWx::operator>=(const wxLongLongWx& ll) const -{ - if (m_lo < ll.m_lo) - return 0; - if (m_lo > ll.m_lo) - return 1; - if (m_hi < ll.m_hi) - return 0; - if (m_hi > ll.m_hi) - return 1; - return 1; + if ( m_hi > ll.m_hi ) + return TRUE; + else if ( m_hi == ll.m_hi ) + return m_lo > ll.m_lo; + else + return FALSE; } // bitwise operators @@ -419,38 +411,181 @@ wxLongLongWx& wxLongLongWx::operator*=(const wxLongLongWx& ll) // division -void wxLongLongWx::Divide(const wxLongLongWx& divisor, wxLongLongWx& quotient, wxLongLongWx& remainder) const +void wxLongLongWx::Divide(const wxLongLongWx& divisorIn, + wxLongLongWx& quotient, + wxLongLongWx& remainder) const { - if ((divisor.m_lo == 0) && (divisor.m_hi == 0)) + 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 = divisor.m_lo/divisor.m_hi; + long dummy = divisorIn.m_lo/divisorIn.m_hi; dummy += 0; } - wxFAIL_MSG("not implemented"); + // 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 + wxLongLongWx dividend = *this, + divisor = divisorIn; + + quotient = 0l; + remainder = 0l; + + // check for some particular cases + if ( divisor > dividend ) + { + remainder = dividend; + + return; + } + + if ( divisor == dividend ) + { + quotient = 1l; + + return; + } + + // 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 = dividend.m_hi < 0; + bool negQuotient = FALSE; // assume positive + if ( dividend.m_hi < 0 ) + { + negQuotient = !negQuotient; + dividend = -dividend; + } + if ( divisor.m_hi < 0 ) + { + negQuotient = !negQuotient; + divisor = -divisor; + } + + // here: dividend > divisor and both are positibe: do unsigned division + size_t nBits = 64u; + wxLongLongWx d; + + #define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1))) + + 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; + } + } + + // adjust signs + if ( negRemainder ) + { + remainder = -remainder; + } + + if ( negQuotient ) + { + quotient = -quotient; + } } +wxLongLongWx wxLongLongWx::operator/(const wxLongLongWx& ll) const +{ + wxLongLongWx quotient, remainder; + + Divide(ll, quotient, remainder); + + return quotient; +} + +wxLongLongWx& wxLongLongWx::operator/=(const wxLongLongWx& ll) +{ + wxLongLongWx quotient, remainder; + + Divide(ll, quotient, remainder); + + return *this = quotient; +} + +wxLongLongWx wxLongLongWx::operator%(const wxLongLongWx& ll) const +{ + wxLongLongWx 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] = (m_hi >> 24) & 0xFF; - temp[1] = (m_hi >> 16) & 0xFF; - temp[2] = (m_hi >> 8) & 0xFF; - temp[3] = (m_hi >> 0) & 0xFF; - temp[4] = (m_lo >> 24) & 0xFF; - temp[5] = (m_lo >> 16) & 0xFF; - temp[6] = (m_lo >> 8) & 0xFF; - temp[7] = (m_lo >> 0) & 0xFF; + 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; } -// input/output +#if wxUSE_STD_IOSTREAM +// input/output ostream& operator<< (ostream& o, const wxLongLongWx& ll) { char result[65]; @@ -467,7 +602,8 @@ ostream& operator<< (ostream& o, const wxLongLongWx& ll) return o << result; } -#endif - // wxUSE_LONGLONG_NATIVE +#endif // wxUSE_STD_IOSTREAM + +#endif // wxUSE_LONGLONG_NATIVE #endif // wxUSE_LONGLONG