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:
@@ -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
|
||||||
|
@@ -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();
|
||||||
|
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user