From 8b81872f2efe2948592096f155729ec4ba5640a2 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 10 May 1999 18:16:31 +0000 Subject: [PATCH] the initial draft of wxLongLong class git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2398 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/longlong.tex | 16 ++ include/wx/longlong.h | 338 ++++++++++++++++++++++++++ src/common/longlong.cpp | 469 +++++++++++++++++++++++++++++++++++++ 3 files changed, 823 insertions(+) create mode 100644 docs/latex/wx/longlong.tex create mode 100644 include/wx/longlong.h create mode 100644 src/common/longlong.cpp diff --git a/docs/latex/wx/longlong.tex b/docs/latex/wx/longlong.tex new file mode 100644 index 0000000000..7ead0bfeaf --- /dev/null +++ b/docs/latex/wx/longlong.tex @@ -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. diff --git a/include/wx/longlong.h b/include/wx/longlong.h new file mode 100644 index 0000000000..5f0b712947 --- /dev/null +++ b/include/wx/longlong.h @@ -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 , 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 +// 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 diff --git a/src/common/longlong.cpp b/src/common/longlong.cpp new file mode 100644 index 0000000000..4303386f7c --- /dev/null +++ b/src/common/longlong.cpp @@ -0,0 +1,469 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/longlong.cpp +// Purpose: implementation of wxLongLongNative +// Author: Jeffrey C. Ollie , 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 +// 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 // 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 +