added test mode to wxLongLongWx which allowed to find the bug in operator*=()

which was breaking wxDateTime - now seems to work


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@5297 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2000-01-07 20:35:34 +00:00
parent 95837b4d96
commit 2a31049201
3 changed files with 466 additions and 183 deletions

View File

@@ -25,7 +25,15 @@
#include <limits.h> // for LONG_MAX #include <limits.h> // for LONG_MAX
// #define wxUSE_LONGLONG_WX 1 // for testing (VZ) // define this to compile wxLongLongWx in "test" mode: the results of all
// calculations will be compared with the real results taken from
// wxLongLongNative
#define wxLONGLONG_TEST_MODE
#ifdef wxLONGLONG_TEST_MODE
#define wxUSE_LONGLONG_WX 1
#define wxUSE_LONGLONG_NATIVE 1
#endif // wxLONGLONG_TEST_MODE
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// decide upon which class we will use // decide upon which class we will use
@@ -73,8 +81,12 @@
// to disable automatic testing (useful for the test program which defines // to disable automatic testing (useful for the test program which defines
// both classes) but by default we only use one class // both classes) but by default we only use one class
#if (defined(wxUSE_LONGLONG_WX) && wxUSE_LONGLONG_WX) || !defined(wxLongLong_t) #if (defined(wxUSE_LONGLONG_WX) && wxUSE_LONGLONG_WX) || !defined(wxLongLong_t)
#undef wxUSE_LONGLONG_NATIVE // don't use both classes unless wxUSE_LONGLONG_NATIVE was explicitly set:
#define wxUSE_LONGLONG_NATIVE 0 // this is useful in test programs nad only there
#ifndef wxUSE_LONGLONG_NATIVE
#define wxUSE_LONGLONG_NATIVE 0
#endif
class WXDLLEXPORT wxLongLongWx; class WXDLLEXPORT wxLongLongWx;
typedef wxLongLongWx wxLongLong; typedef wxLongLongWx wxLongLong;
#else #else
@@ -307,13 +319,32 @@ class WXDLLEXPORT wxLongLongWx
public: public:
// ctors // ctors
// default ctor initializes to 0 // default ctor initializes to 0
wxLongLongWx() { m_lo = m_hi = 0; } wxLongLongWx()
{
m_lo = m_hi = 0;
#ifdef wxLONGLONG_TEST_MODE
m_ll = 0;
Check();
#endif // wxLONGLONG_TEST_MODE
}
// from long // from long
wxLongLongWx(long l) wxLongLongWx(long l) { *this = l; }
{ m_lo = l; m_hi = (l < 0 ? -1l : 0l); }
// from 2 longs // from 2 longs
wxLongLongWx(long hi, unsigned long lo) wxLongLongWx(long hi, unsigned long lo)
{ m_hi = hi; m_lo = lo; } {
m_hi = hi;
m_lo = lo;
#ifdef wxLONGLONG_TEST_MODE
m_ll = hi;
m_ll <<= 32;
m_ll |= lo;
Check();
#endif // wxLONGLONG_TEST_MODE
}
// default copy ctor is ok in both cases // default copy ctor is ok in both cases
@@ -322,7 +353,18 @@ public:
// assignment operators // assignment operators
// from long // from long
wxLongLongWx& operator=(long l) wxLongLongWx& operator=(long l)
{ m_lo = l; m_hi = (l < 0 ? -1l : 0l); return *this; } {
m_lo = l;
m_hi = (l < 0 ? -1l : 0l);
#ifdef wxLONGLONG_TEST_MODE
m_ll = l;
Check();
#endif // wxLONGLONG_TEST_MODE
return *this;
}
// from double // from double
wxLongLongWx& Assign(double d); wxLongLongWx& Assign(double d);
// can't have assignment operator from 2 longs // can't have assignment operator from 2 longs
@@ -335,12 +377,25 @@ public:
// get absolute value // get absolute value
wxLongLongWx Abs() const { return wxLongLongWx(*this).Abs(); } wxLongLongWx Abs() const { return wxLongLongWx(*this).Abs(); }
wxLongLongWx& Abs() { if ( m_hi < 0 ) m_hi = -m_hi; return *this; } wxLongLongWx& Abs()
{
if ( m_hi < 0 )
m_hi = -m_hi;
#ifdef wxLONGLONG_TEST_MODE
if ( m_ll < 0 )
m_ll = -m_ll;
Check();
#endif // wxLONGLONG_TEST_MODE
return *this;
}
// convert to long with range checking in the debug mode (only!) // convert to long with range checking in the debug mode (only!)
long ToLong() const long ToLong() const
{ {
wxASSERT_MSG( m_hi == 0l, wxASSERT_MSG( (m_hi == 0l) || (m_hi == -1l),
_T("wxLongLong to long conversion loss of precision") ); _T("wxLongLong to long conversion loss of precision") );
return (long)m_lo; return (long)m_lo;
@@ -357,10 +412,11 @@ public:
wxLongLongWx& operator++(); wxLongLongWx& operator++();
// post increment operator // post increment operator
wxLongLongWx& operator++(int); wxLongLongWx& operator++(int) { return ++(*this); }
// negation operator // negation operator
wxLongLongWx operator-() const; wxLongLongWx operator-() const;
wxLongLongWx& Negate();
// subraction // subraction
wxLongLongWx operator-(const wxLongLongWx& ll) const; wxLongLongWx operator-(const wxLongLongWx& ll) const;
@@ -370,7 +426,7 @@ public:
wxLongLongWx& operator--(); wxLongLongWx& operator--();
// post decrement operator // post decrement operator
wxLongLongWx& operator--(int); wxLongLongWx& operator--(int) { return --(*this); }
// shifts // shifts
// left shift // left shift
@@ -421,13 +477,22 @@ public:
friend ostream& operator<<(ostream&, const wxLongLongWx&); friend ostream& operator<<(ostream&, const wxLongLongWx&);
#endif // wxUSE_STD_IOSTREAM #endif // wxUSE_STD_IOSTREAM
void *asArray(void) const; void *asArray() const;
private: private:
// long is at least 32 bits, so represent our 64bit number as 2 longs // long is at least 32 bits, so represent our 64bit number as 2 longs
long m_hi; // signed bit is in the high part long m_hi; // signed bit is in the high part
unsigned long m_lo; unsigned long m_lo;
#ifdef wxLONGLONG_TEST_MODE
void Check()
{
wxASSERT( (m_ll >> 32) == m_hi && (unsigned long)m_ll == m_lo );
}
wxLongLong_t m_ll;
#endif // wxLONGLONG_TEST_MODE
}; };
#endif // wxUSE_LONGLONG_WX #endif // wxUSE_LONGLONG_WX

View File

@@ -30,14 +30,14 @@
// what to test? // what to test?
//#define TEST_ARRAYS //#define TEST_ARRAYS
#define TEST_CMDLINE //#define TEST_CMDLINE
//#define TEST_DIR //#define TEST_DIR
//#define TEST_LOG //#define TEST_LOG
//#define TEST_LONGLONG //#define TEST_LONGLONG
//#define TEST_MIME //#define TEST_MIME
//#define TEST_STRINGS //#define TEST_STRINGS
//#define TEST_THREADS //#define TEST_THREADS
//#define TEST_TIME #define TEST_TIME
// ============================================================================ // ============================================================================
// implementation // implementation
@@ -219,6 +219,19 @@ static void TestMimeEnum()
#include <wx/longlong.h> #include <wx/longlong.h>
#include <wx/timer.h> #include <wx/timer.h>
// make a 64 bit number from 4 16 bit ones
#define MAKE_LL(x1, x2, x3, x4) wxLongLong((x1 << 16) | x2, (x3 << 16) | x3)
// get a random 64 bit number
#define RAND_LL() MAKE_LL(rand(), rand(), rand(), rand())
#if wxUSE_LONGLONG_NATIVE
inline bool operator==(const wxLongLongWx& a, const wxLongLongNative& b)
{ return a.GetHi() == b.GetHi() && a.GetLo() == b.GetLo(); }
inline bool operator==(const wxLongLongNative& a, const wxLongLongWx& b)
{ return a.GetHi() == b.GetHi() && a.GetLo() == b.GetLo(); }
#endif // wxUSE_LONGLONG_NATIVE
static void TestSpeed() static void TestSpeed()
{ {
static const long max = 100000000; static const long max = 100000000;
@@ -263,15 +276,76 @@ static void TestSpeed()
} }
} }
static void TestLongLongConversion()
{
puts("*** Testing wxLongLong conversions ***\n");
wxLongLong a;
size_t nTested = 0;
for ( size_t n = 0; n < 100000; n++ )
{
a = RAND_LL();
#if wxUSE_LONGLONG_NATIVE
wxLongLongNative b(a.GetHi(), a.GetLo());
wxASSERT_MSG( a == b, "conversions failure" );
#else
puts("Can't do it without native long long type, test skipped.");
return;
#endif // wxUSE_LONGLONG_NATIVE
if ( !(nTested % 1000) )
{
putchar('.');
fflush(stdout);
}
nTested++;
}
puts(" done!");
}
static void TestMultiplication()
{
puts("*** Testing wxLongLong multiplication ***\n");
wxLongLong a, b;
size_t nTested = 0;
for ( size_t n = 0; n < 100000; n++ )
{
a = RAND_LL();
b = RAND_LL();
#if wxUSE_LONGLONG_NATIVE
wxLongLongNative aa(a.GetHi(), a.GetLo());
wxLongLongNative bb(b.GetHi(), b.GetLo());
wxASSERT_MSG( a*b == aa*bb, "multiplication failure" );
#else // !wxUSE_LONGLONG_NATIVE
puts("Can't do it without native long long type, test skipped.");
return;
#endif // wxUSE_LONGLONG_NATIVE
if ( !(nTested % 1000) )
{
putchar('.');
fflush(stdout);
}
nTested++;
}
puts(" done!");
}
static void TestDivision() static void TestDivision()
{ {
puts("*** Testing wxLongLong division ***\n"); puts("*** Testing wxLongLong division ***\n");
#define MAKE_LL(x1, x2, x3, x4) wxLongLong((x1 << 16) | x2, (x3 << 16) | x3)
// seed pseudo random generator
srand((unsigned)time(NULL));
wxLongLong q, r; wxLongLong q, r;
size_t nTested = 0; size_t nTested = 0;
for ( size_t n = 0; n < 100000; n++ ) for ( size_t n = 0; n < 100000; n++ )
@@ -285,8 +359,15 @@ static void TestDivision()
q = ll / l; q = ll / l;
r = ll % l; r = ll % l;
#if wxUSE_LONGLONG_NATIVE
wxLongLongNative m(ll.GetHi(), ll.GetLo());
wxLongLongNative p = m / l, s = m % l;
wxASSERT_MSG( q == p && r == s, "division failure" );
#else // !wxUSE_LONGLONG_NATIVE
// verify the result // verify the result
wxASSERT_MSG( ll == q*l + r, "division failure" ); wxASSERT_MSG( ll == q*l + r, "division failure" );
#endif // wxUSE_LONGLONG_NATIVE
if ( !(nTested % 1000) ) if ( !(nTested % 1000) )
{ {
@@ -298,10 +379,87 @@ static void TestDivision()
} }
puts(" done!"); puts(" done!");
#undef MAKE_LL
} }
static void TestAddition()
{
puts("*** Testing wxLongLong addition ***\n");
wxLongLong a, b, c;
size_t nTested = 0;
for ( size_t n = 0; n < 100000; n++ )
{
a = RAND_LL();
b = RAND_LL();
c = a + b;
#if wxUSE_LONGLONG_NATIVE
wxASSERT_MSG( c == wxLongLongNative(a.GetHi(), a.GetLo()) +
wxLongLongNative(b.GetHi(), b.GetLo()),
"addition failure" );
#else // !wxUSE_LONGLONG_NATIVE
wxASSERT_MSG( c - b == a, "addition failure" );
#endif // wxUSE_LONGLONG_NATIVE
if ( !(nTested % 1000) )
{
putchar('.');
fflush(stdout);
}
nTested++;
}
puts(" done!");
}
static void TestBitOperations()
{
puts("*** Testing wxLongLong bit operation ***\n");
wxLongLong a, c;
size_t nTested = 0;
for ( size_t n = 0; n < 100000; n++ )
{
a = RAND_LL();
#if wxUSE_LONGLONG_NATIVE
for ( size_t n = 0; n < 33; n++ )
{
wxLongLongNative b(a.GetHi(), a.GetLo());
b >>= n;
c = a >> n;
wxASSERT_MSG( b == c, "bit shift failure" );
b = wxLongLongNative(a.GetHi(), a.GetLo()) << n;
c = a << n;
wxASSERT_MSG( b == c, "bit shift failure" );
}
#else // !wxUSE_LONGLONG_NATIVE
puts("Can't do it without native long long type, test skipped.");
return;
#endif // wxUSE_LONGLONG_NATIVE
if ( !(nTested % 1000) )
{
putchar('.');
fflush(stdout);
}
nTested++;
}
puts(" done!");
}
#undef MAKE_LL
#undef RAND_LL
#endif // TEST_LONGLONG #endif // TEST_LONGLONG
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -1703,10 +1861,21 @@ int main(int argc, char **argv)
#endif // TEST_THREADS #endif // TEST_THREADS
#ifdef TEST_LONGLONG #ifdef TEST_LONGLONG
// seed pseudo random generator
srand((unsigned)time(NULL));
if ( 0 ) if ( 0 )
{
TestSpeed(); TestSpeed();
if ( 1 ) }
TestMultiplication();
if ( 0 )
{
TestDivision(); TestDivision();
TestAddition();
TestLongLongConversion();
TestBitOperations();
}
#endif // TEST_LONGLONG #endif // TEST_LONGLONG
#ifdef TEST_MIME #ifdef TEST_MIME
@@ -1714,7 +1883,7 @@ int main(int argc, char **argv)
#endif // TEST_MIME #endif // TEST_MIME
#ifdef TEST_TIME #ifdef TEST_TIME
if ( 0 ) if ( 1 )
{ {
TestTimeSet(); TestTimeSet();
TestTimeStatic(); TestTimeStatic();

View File

@@ -41,7 +41,7 @@
// misc // misc
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void *wxLongLongNative::asArray(void) const void *wxLongLongNative::asArray() const
{ {
static unsigned char temp[8]; static unsigned char temp[8];
@@ -89,110 +89,121 @@ ostream& operator<< (ostream& o, const wxLongLongNative& ll)
// assignment // assignment
wxLongLongWx& wxLongLongWx::Assign(double d) wxLongLongWx& wxLongLongWx::Assign(double d)
{ {
if ( fabs(d) <= LONG_MAX ) bool positive = d >= 0;
d = fabs(d);
if ( d <= LONG_MAX )
{ {
m_hi = d < 0 ? 1 << (8*sizeof(long) - 1) : 0l; m_hi = 0;
m_lo = (long)d; m_lo = (long)d;
} }
else else
{ {
wxFAIL_MSG(_T("TODO")); #if 0
m_lo = (long)d;
d -= m_lo;
d /= 0x1000;
d /= 0x1000;
d /= 0x100;
m_hi = (long)d;
#else
wxFAIL_MSG(_T("TODO"));
#endif
} }
if ( !positive )
m_hi = -m_hi;
#ifdef wxLONGLONG_TEST_MODE
m_ll = (wxLongLong_t)d;
Check();
#endif // wxLONGLONG_TEST_MODE
return *this; return *this;
} }
wxLongLongWx wxLongLongWx::operator<<(int shift) const wxLongLongWx wxLongLongWx::operator<<(int shift) const
{ {
if (shift == 0) wxLongLongWx ll(*this);
return *this; ll <<= shift;
if (shift < 32) return ll;
return wxLongLongWx((m_hi << shift) | (m_lo >> (32 - shift)),
m_lo << shift);
else
return wxLongLongWx(m_lo << (shift - 32),
0);
} }
wxLongLongWx& wxLongLongWx::operator<<=(int shift) wxLongLongWx& wxLongLongWx::operator<<=(int shift)
{ {
if (shift == 0) if (shift != 0)
return *this; {
if (shift < 32)
{
m_hi <<= shift;
m_hi |= m_lo >> (32 - shift);
m_lo <<= shift;
}
else
{
m_hi = m_lo << (shift - 32);
m_lo = 0;
}
}
if (shift < 32) #ifdef wxLONGLONG_TEST_MODE
{ m_ll <<= shift;
m_hi <<= shift;
m_hi |= m_lo >> (32 - shift); Check();
m_lo <<= shift; #endif // wxLONGLONG_TEST_MODE
}
else
{
m_hi = m_lo << (shift - 32);
m_lo = 0;
}
return *this; return *this;
} }
wxLongLongWx wxLongLongWx::operator>>(int shift) const wxLongLongWx wxLongLongWx::operator>>(int shift) const
{ {
if (shift == 0) wxLongLongWx ll(*this);
return *this; ll >>= shift;
if (shift < 32) return ll;
return wxLongLongWx(m_hi >> shift,
(m_lo >> shift) | (m_hi << (32 - shift)));
else
return wxLongLongWx((m_hi < 0 ? -1l : 0),
m_hi >> (shift - 32));
} }
wxLongLongWx& wxLongLongWx::operator>>=(int shift) wxLongLongWx& wxLongLongWx::operator>>=(int shift)
{ {
if (shift == 0) if (shift != 0)
return *this; {
if (shift < 32)
{
m_lo >>= shift;
m_lo |= m_hi << (32 - shift);
m_hi >>= shift;
}
else
{
m_lo = m_hi >> (shift - 32);
m_hi = (m_hi < 0 ? -1L : 0);
}
}
if (shift < 32) #ifdef wxLONGLONG_TEST_MODE
{ m_ll >>= shift;
m_lo >>= shift;
m_lo |= m_hi << (32 - shift); Check();
m_hi >>= shift; #endif // wxLONGLONG_TEST_MODE
}
else
{
m_lo = m_hi >> (shift - 32);
m_hi = (m_hi < 0 ? -1L : 0);
}
return *this; return *this;
} }
wxLongLongWx wxLongLongWx::operator+(const wxLongLongWx& ll) const wxLongLongWx wxLongLongWx::operator+(const wxLongLongWx& ll) const
{ {
wxLongLongWx temp; wxLongLongWx res(*this);
res += ll;
temp.m_lo = m_lo + ll.m_lo; return res;
temp.m_hi = m_hi + ll.m_hi;
if ((temp.m_lo < m_lo) || (temp.m_lo < ll.m_lo))
temp.m_hi++;
return temp;
} }
wxLongLongWx wxLongLongWx::operator+(long l) const wxLongLongWx wxLongLongWx::operator+(long l) const
{ {
wxLongLongWx temp; wxLongLongWx res(*this);
res += l;
temp.m_lo = m_lo + l; return res;
if (l < 0)
temp.m_hi += -1l;
if ((temp.m_lo < m_lo) || (temp.m_lo < (unsigned long)l))
temp.m_hi++;
return temp;
} }
wxLongLongWx& wxLongLongWx::operator+=(const wxLongLongWx& ll) wxLongLongWx& wxLongLongWx::operator+=(const wxLongLongWx& ll)
@@ -205,6 +216,12 @@ wxLongLongWx& wxLongLongWx::operator+=(const wxLongLongWx& ll)
if ((m_lo < previous) || (m_lo < ll.m_lo)) if ((m_lo < previous) || (m_lo < ll.m_lo))
m_hi++; m_hi++;
#ifdef wxLONGLONG_TEST_MODE
m_ll += ll.m_ll;
Check();
#endif // wxLONGLONG_TEST_MODE
return *this; return *this;
} }
@@ -219,6 +236,12 @@ wxLongLongWx& wxLongLongWx::operator+=(long l)
if ((m_lo < previous) || (m_lo < (unsigned long)l)) if ((m_lo < previous) || (m_lo < (unsigned long)l))
m_hi++; m_hi++;
#ifdef wxLONGLONG_TEST_MODE
m_ll += l;
Check();
#endif // wxLONGLONG_TEST_MODE
return *this; return *this;
} }
@@ -229,15 +252,11 @@ wxLongLongWx& wxLongLongWx::operator++()
if (m_lo == 0) if (m_lo == 0)
m_hi++; m_hi++;
return *this; #ifdef wxLONGLONG_TEST_MODE
} m_ll++;
// post increment Check();
wxLongLongWx& wxLongLongWx::operator++(int) #endif // wxLONGLONG_TEST_MODE
{
m_lo++;
if (m_lo == 0)
m_hi++;
return *this; return *this;
} }
@@ -245,28 +264,38 @@ wxLongLongWx& wxLongLongWx::operator++(int)
// negation // negation
wxLongLongWx wxLongLongWx::operator-() const wxLongLongWx wxLongLongWx::operator-() const
{ {
wxLongLongWx temp(~m_hi, ~m_lo); wxLongLongWx res(*this);
res.Negate();
temp.m_lo++; return res;
if (temp.m_lo == 0) }
temp.m_hi++;
return temp; wxLongLongWx& wxLongLongWx::Negate()
{
m_hi = ~m_hi;
m_lo = ~m_lo;
m_lo++;
if ( m_lo == 0 )
m_hi++;
#ifdef wxLONGLONG_TEST_MODE
m_ll = -m_ll;
Check();
#endif // wxLONGLONG_TEST_MODE
return *this;
} }
// subtraction // subtraction
wxLongLongWx wxLongLongWx::operator-(const wxLongLongWx& ll) const wxLongLongWx wxLongLongWx::operator-(const wxLongLongWx& ll) const
{ {
wxLongLongWx temp; wxLongLongWx res(*this);
res -= ll;
temp.m_lo = m_lo - ll.m_lo; return res;
temp.m_hi = m_hi - ll.m_hi;
if (m_lo < ll.m_lo)
temp.m_hi--;
return temp;
} }
wxLongLongWx& wxLongLongWx::operator-=(const wxLongLongWx& ll) wxLongLongWx& wxLongLongWx::operator-=(const wxLongLongWx& ll)
@@ -279,6 +308,12 @@ wxLongLongWx& wxLongLongWx::operator-=(const wxLongLongWx& ll)
if (previous < ll.m_lo) if (previous < ll.m_lo)
m_hi--; m_hi--;
#ifdef wxLONGLONG_TEST_MODE
m_ll -= ll.m_ll;
Check();
#endif // wxLONGLONG_TEST_MODE
return *this; return *this;
} }
@@ -289,15 +324,11 @@ wxLongLongWx& wxLongLongWx::operator--()
if (m_lo == 0xFFFFFFFF) if (m_lo == 0xFFFFFFFF)
m_hi--; m_hi--;
return *this; #ifdef wxLONGLONG_TEST_MODE
} m_ll--;
// post decrement Check();
wxLongLongWx& wxLongLongWx::operator--(int) #endif // wxLONGLONG_TEST_MODE
{
m_lo--;
if (m_lo == 0xFFFFFFFF)
m_hi--;
return *this; return *this;
} }
@@ -346,6 +377,12 @@ wxLongLongWx& wxLongLongWx::operator&=(const wxLongLongWx& ll)
m_lo &= ll.m_lo; m_lo &= ll.m_lo;
m_hi &= ll.m_hi; m_hi &= ll.m_hi;
#ifdef wxLONGLONG_TEST_MODE
m_ll &= ll.m_ll;
Check();
#endif // wxLONGLONG_TEST_MODE
return *this; return *this;
} }
@@ -354,6 +391,12 @@ wxLongLongWx& wxLongLongWx::operator|=(const wxLongLongWx& ll)
m_lo |= ll.m_lo; m_lo |= ll.m_lo;
m_hi |= ll.m_hi; m_hi |= ll.m_hi;
#ifdef wxLONGLONG_TEST_MODE
m_ll |= ll.m_ll;
Check();
#endif // wxLONGLONG_TEST_MODE
return *this; return *this;
} }
@@ -362,6 +405,12 @@ wxLongLongWx& wxLongLongWx::operator^=(const wxLongLongWx& ll)
m_lo ^= ll.m_lo; m_lo ^= ll.m_lo;
m_hi ^= ll.m_hi; m_hi ^= ll.m_hi;
#ifdef wxLONGLONG_TEST_MODE
m_ll ^= ll.m_ll;
Check();
#endif // wxLONGLONG_TEST_MODE
return *this; return *this;
} }
@@ -374,38 +423,41 @@ wxLongLongWx wxLongLongWx::operator~() const
wxLongLongWx wxLongLongWx::operator*(const wxLongLongWx& ll) const wxLongLongWx wxLongLongWx::operator*(const wxLongLongWx& ll) const
{ {
wxLongLongWx t(m_hi, m_lo); wxLongLongWx res(*this);
wxLongLongWx q(ll.m_hi, ll.m_lo); res *= ll;
wxLongLongWx p;
int counter = 0;
do return res;
{
if ((q.m_lo & 1) != 0)
p += t;
q >>= 1;
t <<= 1;
counter++;
}
while ((counter < 64) && ((q.m_hi != 0) || (q.m_lo != 0)));
return p;
} }
wxLongLongWx& wxLongLongWx::operator*=(const wxLongLongWx& ll) wxLongLongWx& wxLongLongWx::operator*=(const wxLongLongWx& ll)
{ {
wxLongLongWx t(m_hi, m_lo); wxLongLongWx t(m_hi, m_lo);
wxLongLongWx q(ll.m_hi, ll.m_lo); wxLongLongWx q(ll.m_hi, ll.m_lo);
int counter = 0;
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 do
{ {
if ((q.m_lo & 1) != 0) if ((q.m_lo & 1) != 0)
*this += t; *this += t;
q >>= 1; q >>= 1;
t <<= 1; t <<= 1;
counter++; counter++;
} }
while ((counter < 64) && ((q.m_hi != 0) || (q.m_lo != 0))); 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; return *this;
} }
@@ -443,21 +495,6 @@ void wxLongLongWx::Divide(const wxLongLongWx& divisorIn,
quotient = 0l; quotient = 0l;
remainder = 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 // 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 // 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 // dividend, while the sign of the quotient is the product of the signs of
@@ -479,47 +516,59 @@ void wxLongLongWx::Divide(const wxLongLongWx& divisorIn,
divisor = -divisor; divisor = -divisor;
} }
// here: dividend > divisor and both are positibe: do unsigned division // check for some particular cases
size_t nBits = 64u; if ( divisor > dividend )
wxLongLongWx d;
#define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1)))
while ( remainder < divisor )
{ {
remainder <<= 1; remainder = dividend;
if ( IS_MSB_SET(dividend) )
{
remainder |= 1;
}
d = dividend;
dividend <<= 1;
nBits--;
} }
else if ( divisor == dividend )
// undo the last loop iteration
dividend = d;
remainder >>= 1;
nBits++;
for ( size_t i = 0; i < nBits; i++ )
{ {
remainder <<= 1; quotient = 1l;
if ( IS_MSB_SET(dividend) ) }
else
{
// 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; remainder <<= 1;
if ( IS_MSB_SET(dividend) )
{
remainder |= 1;
}
d = dividend;
dividend <<= 1;
nBits--;
} }
wxLongLongWx t = remainder - divisor; // undo the last loop iteration
dividend <<= 1; dividend = d;
quotient <<= 1; remainder >>= 1;
if ( !IS_MSB_SET(t) ) nBits++;
{
quotient |= 1;
remainder = t; 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;
}
} }
} }