the initial draft of wxLongLong class

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2398 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 1999-05-10 18:16:31 +00:00
parent bacd69f986
commit 8b81872f2e
3 changed files with 823 additions and 0 deletions

View File

@ -0,0 +1,16 @@
\section{\class{wxLongLong}}\label{wxlonglong}
This class represents a signed 64 bit long number. It is implemented using the
native 64 bit type where available (machines with 64 bit longs or compilers
which have (an analog of) {\it long long} type) and uses the emulation code in
the other cases which ensures that it is the most efficient solution for
working with 64 bit integers independently of the architecture.
wxLongLong defines all usual arithmetic operations such as addition,
substraction, bitwise shifts and logical operations as well as multiplication
and division (not yet for the machines without native {\it long long}). It
also has operators for implicit construction from and conversion to the native
{\it long long} type if it exists and {\it long}.
You would usually use this type in exactly the same manner as any other
(built-in) arithmetic type.

338
include/wx/longlong.h Normal file
View File

@ -0,0 +1,338 @@
/////////////////////////////////////////////////////////////////////////////
// Name: wx/longlong.h
// Purpose: declaration of wxLongLong class - best implementation of a 64
// bit integer for the current platform.
// Author: Jeffrey C. Ollie <jeff@ollie.clive.ia.us>, Vadim Zeitlin
// Remarks: this class is not public in wxWindows 2.0! It is intentionally
// not documented and is for private use only.
// Modified by:
// Created: 10.02.99
// RCS-ID: $Id$
// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
#ifndef _WX_LONGLONG_H
#define _WX_LONGLONG_H
#ifdef __GNUG__
#pragma interface "longlong.h"
#endif
// ----------------------------------------------------------------------------
// decide upon which class we will use
// ----------------------------------------------------------------------------
// to avoid compilation problems on 64bit machines with ambiguous method calls
// we will need this
#undef wxLongLongIsLong
// NB: we #define and not typedef wxLongLong_t because we want to be able to
// use 'unsigned wxLongLong_t' as well
#if defined(SIZEOF_LONG) && (SIZEOF_LONG == 8)
#define wxLongLong_t long
#define wxLongLongIsLong
#elif defined(__VISUALC__)
#define wxLongLong_t __int64
#elif defined(__GNUG__)
#define wxLongLong_t long long
#elif defined(__MWERKS__)
#if __option(longlong)
#define wxLongLong_t long long
#else
#error "The 64 bit integer support in CodeWarrior has been disabled."
#error "See the documentation on the 'longlong' pragma."
#endif
#else
#warning "Your compiler does not appear to support 64 bit integers, "\
"using emulation class instead."
#define wxUSE_LONGLONG_WX 1
#endif // compiler
// the user may predefine wxUSE_LONGLONG_NATIVE and/or wxUSE_LONGLONG_NATIVE
// to disable automatic testing (useful for the test program which defines
// both classes) but by default we only use one class
#ifndef wxLongLong_t
#undef wxUSE_LONGLONG_NATIVE
#define wxUSE_LONGLONG_NATIVE 0
class WXDLLEXPORT wxLongLongWx;
typedef wxLongLongWx wxLongLong;
#endif
#ifndef wxUSE_LONGLONG_WX
#define wxUSE_LONGLONG_WX 0
class WXDLLEXPORT wxLongLongNative;
typedef wxLongLongNative wxLongLong;
#endif
// NB: if both wxUSE_LONGLONG_WX and NATIVE are defined, the user code should
// typedef wxLongLong as it wants, we don't do it
// ----------------------------------------------------------------------------
// choose the appropriate class
// ----------------------------------------------------------------------------
// we use iostream for wxLongLong output
#include "wx/ioswrap.h"
#if wxUSE_LONGLONG_NATIVE
class WXDLLEXPORT wxLongLongNative
{
public:
// ctors
// default ctor initializes to 0
wxLongLongNative() { m_ll = 0; }
// from long long
wxLongLongNative(wxLongLong_t ll) { m_ll = ll; }
// from 2 longs
wxLongLongNative(long hi, unsigned long lo)
{
// assign first to avoid precision loss!
m_ll = ((wxLongLong_t) hi) << 32;
m_ll |= (wxLongLong_t) lo;
}
// default copy ctor is ok in both cases
// no dtor
// assignment operators
// from native 64 bit integer
wxLongLongNative& operator=(wxLongLong_t ll)
{ m_ll = ll; return *this; }
// assignment operators from wxLongLongNative is ok
// accessors
// get high part
long GetHi() const
{ return (long)((m_ll & 0xFFFFFFFF00000000ll) >> 32); }
// get low part
unsigned long GetLo() const
{ return (unsigned long) (m_ll & 0x00000000FFFFFFFFll); }
// convert to native long long
wxLongLong_t GetValue() const { return m_ll; }
operator wxLongLong_t() const { return m_ll; }
// operations
// addition
wxLongLongNative operator+(const wxLongLongNative& ll) const
{ return wxLongLongNative(m_ll + ll.m_ll); }
wxLongLongNative& operator+=(const wxLongLongNative& ll)
{ m_ll += ll.m_ll; return *this; }
wxLongLongNative operator+(const wxLongLong_t ll) const
{ return wxLongLongNative(m_ll + ll); }
wxLongLongNative& operator+=(const wxLongLong_t ll)
{ m_ll += ll; return *this; }
// pre increment
wxLongLongNative& operator++()
{ m_ll++; return *this; }
// post increment
wxLongLongNative& operator++(int)
{ m_ll++; return *this; }
// negation operator
wxLongLongNative operator-() const
{ return wxLongLongNative(-m_ll); }
// subtraction
wxLongLongNative operator-(const wxLongLongNative& ll) const
{ return wxLongLongNative(m_ll - ll.m_ll); }
wxLongLongNative& operator-=(const wxLongLongNative& ll)
{ m_ll -= ll.m_ll; return *this; }
wxLongLongNative operator-(const wxLongLong_t ll) const
{ return wxLongLongNative(m_ll - ll); }
wxLongLongNative& operator-=(const wxLongLong_t ll)
{ m_ll -= ll; return *this; }
// pre decrement
wxLongLongNative& operator--()
{ m_ll--; return *this; }
// post decrement
wxLongLongNative& operator--(int)
{ m_ll--; return *this; }
// shifts
// left shift
wxLongLongNative operator<<(int shift) const
{ return wxLongLongNative(m_ll << shift);; }
wxLongLongNative& operator<<=(int shift)
{ m_ll <<= shift; return *this; }
// right shift
wxLongLongNative operator>>(int shift) const
{ return wxLongLongNative(m_ll >> shift);; }
wxLongLongNative& operator>>=(int shift)
{ m_ll >>= shift; return *this; }
// bitwise operators
wxLongLongNative operator&(const wxLongLongNative& ll) const
{ return wxLongLongNative(m_ll & ll.m_ll); }
wxLongLongNative& operator&=(const wxLongLongNative& ll)
{ m_ll &= ll.m_ll; return *this; }
wxLongLongNative operator|(const wxLongLongNative& ll) const
{ return wxLongLongNative(m_ll | ll.m_ll); }
wxLongLongNative& operator|=(const wxLongLongNative& ll)
{ m_ll |= ll.m_ll; return *this; }
wxLongLongNative operator^(const wxLongLongNative& ll) const
{ return wxLongLongNative(m_ll ^ ll.m_ll); }
wxLongLongNative& operator^=(const wxLongLongNative& ll)
{ m_ll ^= ll.m_ll; return *this; }
// multiplication/division TODO
wxLongLongNative operator*(const wxLongLongNative& ll) const
{ return wxLongLongNative(m_ll * ll.m_ll); }
wxLongLongNative& operator*=(const wxLongLongNative& ll)
{ m_ll *= ll.m_ll; return *this; }
wxLongLongNative operator/(const wxLongLongNative& ll) const
{ return wxLongLongNative(m_ll / ll.m_ll); }
wxLongLongNative& operator/=(const wxLongLongNative& ll)
{ m_ll /= ll.m_ll; return *this; }
wxLongLongNative operator%(const wxLongLongNative& ll) const
{ return wxLongLongNative(m_ll % ll.m_ll); }
// comparison
bool operator==(const wxLongLongNative& ll) const
{ return m_ll == ll.m_ll; }
bool operator!=(const wxLongLongNative& ll) const
{ return m_ll != ll.m_ll; }
bool operator<(const wxLongLongNative& ll) const
{ return m_ll < ll.m_ll; }
bool operator>(const wxLongLongNative& ll) const
{ return m_ll > ll.m_ll; }
bool operator<=(const wxLongLongNative& ll) const
{ return m_ll <= ll.m_ll; }
bool operator>=(const wxLongLongNative& ll) const
{ return m_ll >= ll.m_ll; }
// miscellaneous
// conversion to byte array: returns a pointer to static buffer!
void *asArray() const;
// input/output
friend std::ostream& operator<<(ostream&, const wxLongLongNative&);
private:
wxLongLong_t m_ll;
};
#endif // wxUSE_LONGLONG_NATIVE
#if wxUSE_LONGLONG_WX
class WXDLLEXPORT wxLongLongWx
{
public:
// ctors
// default ctor initializes to 0
wxLongLongWx() { m_lo = m_hi = 0; }
// from long
wxLongLongWx(long l)
{ m_lo = l; m_hi = (l < 0 ? -1l : 0l); }
// from 2 longs
wxLongLongWx(long hi, unsigned long lo)
{ m_hi = hi; m_lo = lo; }
// default copy ctor is ok in both cases
// no dtor
// assignment operators
// from long
wxLongLongWx& operator=(long l)
{ m_lo = l; m_hi = (l < 0 ? -1l : 0l); return *this; }
// can't have assignment operator from 2 longs
// accessors
// get high part
long GetHi() const { return m_hi; }
// get low part
unsigned long GetLo() const { return m_lo; }
// operations
// addition
wxLongLongWx operator+(const wxLongLongWx& ll) const;
wxLongLongWx& operator+=(const wxLongLongWx& ll);
wxLongLongWx operator+(long l) const;
wxLongLongWx& operator+=(long l);
// pre increment operator
wxLongLongWx& operator++();
// post increment operator
wxLongLongWx& operator++(int);
// negation operator
wxLongLongWx operator-() const;
// subraction
wxLongLongWx operator-(const wxLongLongWx& ll) const;
wxLongLongWx& operator-=(const wxLongLongWx& ll);
// pre decrement operator
wxLongLongWx& operator--();
// post decrement operator
wxLongLongWx& operator--(int);
// shifts
// left shift
wxLongLongWx operator<<(int shift) const;
wxLongLongWx& operator<<=(int shift);
// right shift
wxLongLongWx operator>>(int shift) const;
wxLongLongWx& operator>>=(int shift);
// bitwise operators
wxLongLongWx operator&(const wxLongLongWx& ll) const;
wxLongLongWx& operator&=(const wxLongLongWx& ll);
wxLongLongWx operator|(const wxLongLongWx& ll) const;
wxLongLongWx& operator|=(const wxLongLongWx& ll);
wxLongLongWx operator^(const wxLongLongWx& ll) const;
wxLongLongWx& operator^=(const wxLongLongWx& ll);
wxLongLongWx operator~() const;
// comparison
bool operator==(const wxLongLongWx& ll) const;
bool operator!=(const wxLongLongWx& ll) const;
bool operator<(const wxLongLongWx& ll) const;
bool operator>(const wxLongLongWx& ll) const;
bool operator<=(const wxLongLongWx& ll) const;
bool operator>=(const wxLongLongWx& ll) const;
// multiplication
wxLongLongWx operator*(const wxLongLongWx& ll) const;
wxLongLongWx& operator*=(const wxLongLongWx& ll);
void *asArray(void) const;
// division
void Divide(const wxLongLongWx& divisor,
wxLongLongWx& quotient,
wxLongLongWx& remainder) const;
// input/output
friend ostream& operator<<(std::ostream&, const wxLongLongWx&);
private:
// long is at least 32 bits, so represent our 64bit number as 2 longs
long m_hi; // signed bit is in the high part
unsigned long m_lo;
};
#endif // wxUSE_LONGLONG_WX
#endif // _WX_LONGLONG_H

469
src/common/longlong.cpp Normal file
View File

@ -0,0 +1,469 @@
/////////////////////////////////////////////////////////////////////////////
// Name: wx/longlong.cpp
// Purpose: implementation of wxLongLongNative
// Author: Jeffrey C. Ollie <jeff@ollie.clive.ia.us>, Vadim Zeitlin
// Remarks: this class is not public in wxWindows 2.0! It is intentionally
// not documented and is for private use only.
// Modified by:
// Created: 10.02.99
// RCS-ID: $Id$
// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// headers
// ============================================================================
#ifdef __GNUG__
#pragma implementation "longlong.h"
#endif
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "wx/longlong.h"
#include <memory.h> // for memset()
// ============================================================================
// implementation
// ============================================================================
#if wxUSE_LONGLONG_NATIVE
// ----------------------------------------------------------------------------
// misc
// ----------------------------------------------------------------------------
void *wxLongLongNative::asArray(void) const
{
static unsigned char temp[8];
temp[0] = (m_ll >> 56) & 0xFF;
temp[1] = (m_ll >> 48) & 0xFF;
temp[2] = (m_ll >> 40) & 0xFF;
temp[3] = (m_ll >> 32) & 0xFF;
temp[4] = (m_ll >> 24) & 0xFF;
temp[5] = (m_ll >> 16) & 0xFF;
temp[6] = (m_ll >> 8) & 0xFF;
temp[7] = (m_ll >> 0) & 0xFF;
return temp;
}
// input/output
std::ostream& operator<< (std::ostream& o, const wxLongLongNative& ll)
{
char result[65];
memset(result, 'A', 64);
result[64] = '\0';
for (int i = 0; i < 64; i++)
{
result[63 - i] = '0' + (char) ((ll.m_ll >> i) & 1);
}
return o << result;
}
#endif // wxUSE_LONGLONG_NATIVE
#if wxUSE_LONGLONG_WX
wxLongLongWx wxLongLongWx::operator<<(int shift) const
{
if (shift == 0)
return *this;
if (shift < 32)
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)
{
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;
}
return *this;
}
wxLongLongWx wxLongLongWx::operator>>(int shift) const
{
if (shift == 0)
return *this;
if (shift < 32)
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)
{
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);
}
return *this;
}
wxLongLongWx wxLongLongWx::operator+(const wxLongLongWx& ll) const
{
wxLongLongWx temp;
temp.m_lo = m_lo + ll.m_lo;
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 temp;
temp.m_lo = m_lo + l;
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)
{
unsigned long previous = m_lo;
m_lo += ll.m_lo;
m_hi += ll.m_hi;
if ((m_lo < previous) || (m_lo < ll.m_lo))
m_hi++;
return *this;
}
wxLongLongWx& wxLongLongWx::operator+=(long l)
{
unsigned long previous = m_lo;
m_lo += l;
if (l < 0)
m_hi += -1l;
if ((m_lo < previous) || (m_lo < (unsigned long)l))
m_hi++;
return *this;
}
// pre increment
wxLongLongWx& wxLongLongWx::operator++()
{
m_lo++;
if (m_lo == 0)
m_hi++;
return *this;
}
// post increment
wxLongLongWx& wxLongLongWx::operator++(int)
{
m_lo++;
if (m_lo == 0)
m_hi++;
return *this;
}
// negation
wxLongLongWx wxLongLongWx::operator-() const
{
wxLongLongWx temp(~m_hi, ~m_lo);
temp.m_lo++;
if (temp.m_lo == 0)
temp.m_hi++;
return temp;
}
// subtraction
wxLongLongWx wxLongLongWx::operator-(const wxLongLongWx& ll) const
{
wxLongLongWx temp;
temp.m_lo = m_lo - ll.m_lo;
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)
{
unsigned long previous = m_lo;
m_lo -= ll.m_lo;
m_hi -= ll.m_hi;
if (previous < ll.m_lo)
m_hi--;
return *this;;
}
// pre decrement
wxLongLongWx& wxLongLongWx::operator--()
{
m_lo--;
if (m_lo == 0xFFFFFFFF)
m_hi--;
return *this;
}
// post decrement
wxLongLongWx& wxLongLongWx::operator--(int)
{
m_lo--;
if (m_lo == 0xFFFFFFFF)
m_hi--;
return *this;
}
// comparison operators
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;
}
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;
}
// bitwise operators
wxLongLongWx wxLongLongWx::operator&(const wxLongLongWx& ll) const
{
return wxLongLongWx(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);
}
wxLongLongWx wxLongLongWx::operator^(const wxLongLongWx& ll) const
{
return wxLongLongWx(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;
return *this;
}
wxLongLongWx& wxLongLongWx::operator|=(const wxLongLongWx& ll)
{
m_lo |= ll.m_lo;
m_hi |= ll.m_hi;
return *this;
}
wxLongLongWx& wxLongLongWx::operator^=(const wxLongLongWx& ll)
{
m_lo ^= ll.m_lo;
m_hi ^= ll.m_hi;
return *this;
}
wxLongLongWx wxLongLongWx::operator~() const
{
return wxLongLongWx(~m_hi, ~m_lo);
}
// multiplication
wxLongLongWx wxLongLongWx::operator*(const wxLongLongWx& ll) const
{
wxLongLongWx t(m_hi, m_lo);
wxLongLongWx q(ll.m_hi, ll.m_lo);
wxLongLongWx p;
int counter = 0;
do
{
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 t(m_hi, m_lo);
wxLongLongWx q(ll.m_hi, ll.m_lo);
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)));
return *this;
}
// division
void wxLongLongWx::Divide(const wxLongLongWx& divisor, wxLongLongWx& quotient, wxLongLongWx& remainder) const
{
if ((divisor.m_lo == 0) && (divisor.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;
dummy += 0;
}
wxFAIL_MSG("not implemented");
}
// 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;
return temp;
}
// input/output
std::ostream& operator<< (std::ostream& o, const wxLongLongWx& ll)
{
char result[65];
memset(result, 'A', 64);
result[64] = '\0';
for (int i = 0; i < 32; i++)
{
result[31 - i] = (char) ('0' + (int) ((ll.m_hi >> i) & 1));
result[63 - i] = (char) ('0' + (int) ((ll.m_lo >> i) & 1));
}
return o << result;
}
#endif wxUSE_LONGLONG_WX