1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/longlong.cpp
3 // Purpose: implementation of wxLongLongNative
4 // Author: Jeffrey C. Ollie <jeff@ollie.clive.ia.us>, Vadim Zeitlin
5 // Remarks: this class is not public in wxWidgets 2.0! It is intentionally
6 // not documented and is for private use only.
10 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
11 // Licence: wxWindows licence
12 /////////////////////////////////////////////////////////////////////////////
14 // ============================================================================
16 // ============================================================================
18 #include "wx/wxprec.h"
25 #include "wx/longlong.h"
26 #include "wx/math.h" // for fabs()
28 #if defined(__MWERKS__) && defined(__WXMSW__)
29 #include <string.h> // for memset()
31 #include <memory.h> // for memset()
34 #include "wx/ioswrap.h"
36 // ============================================================================
38 // ============================================================================
40 #if wxUSE_LONGLONG_NATIVE
42 // ----------------------------------------------------------------------------
44 // ----------------------------------------------------------------------------
46 void *wxLongLongNative::asArray() const
48 static unsigned char temp
[8];
50 temp
[0] = wx_truncate_cast(unsigned char, ((m_ll
>> 56) & 0xFF));
51 temp
[1] = wx_truncate_cast(unsigned char, ((m_ll
>> 48) & 0xFF));
52 temp
[2] = wx_truncate_cast(unsigned char, ((m_ll
>> 40) & 0xFF));
53 temp
[3] = wx_truncate_cast(unsigned char, ((m_ll
>> 32) & 0xFF));
54 temp
[4] = wx_truncate_cast(unsigned char, ((m_ll
>> 24) & 0xFF));
55 temp
[5] = wx_truncate_cast(unsigned char, ((m_ll
>> 16) & 0xFF));
56 temp
[6] = wx_truncate_cast(unsigned char, ((m_ll
>> 8) & 0xFF));
57 temp
[7] = wx_truncate_cast(unsigned char, ((m_ll
>> 0) & 0xFF));
62 void *wxULongLongNative::asArray() const
64 static unsigned char temp
[8];
66 temp
[0] = wx_truncate_cast(unsigned char, ((m_ll
>> 56) & 0xFF));
67 temp
[1] = wx_truncate_cast(unsigned char, ((m_ll
>> 48) & 0xFF));
68 temp
[2] = wx_truncate_cast(unsigned char, ((m_ll
>> 40) & 0xFF));
69 temp
[3] = wx_truncate_cast(unsigned char, ((m_ll
>> 32) & 0xFF));
70 temp
[4] = wx_truncate_cast(unsigned char, ((m_ll
>> 24) & 0xFF));
71 temp
[5] = wx_truncate_cast(unsigned char, ((m_ll
>> 16) & 0xFF));
72 temp
[6] = wx_truncate_cast(unsigned char, ((m_ll
>> 8) & 0xFF));
73 temp
[7] = wx_truncate_cast(unsigned char, ((m_ll
>> 0) & 0xFF));
79 wxLongLongNative::wxLongLongNative(wxLongLongWx ll
)
81 // assign first to avoid precision loss!
87 wxLongLongNative
& wxLongLongNative::operator=(wxLongLongWx ll
)
89 // assign first to avoid precision loss!
97 #endif // wxUSE_LONGLONG_NATIVE
99 // ============================================================================
100 // wxLongLongWx: emulation of 'long long' using 2 longs
101 // ============================================================================
103 #if wxUSE_LONGLONG_WX
106 wxLongLongWx
& wxLongLongWx::Assign(double d
)
108 bool positive
= d
>= 0;
110 if ( d
<= ULONG_MAX
)
117 m_hi
= (unsigned long)(d
/ (1.0 + (double)ULONG_MAX
));
118 m_lo
= (unsigned long)(d
- ((double)m_hi
* (1.0 + (double)ULONG_MAX
)));
121 #ifdef wxLONGLONG_TEST_MODE
122 m_ll
= (wxLongLong_t
)d
;
125 #endif // wxLONGLONG_TEST_MODE
133 double wxLongLongWx::ToDouble() const
136 d
*= 1.0 + (double)ULONG_MAX
;
139 #ifdef wxLONGLONG_TEST_MODE
140 wxASSERT( d
== m_ll
);
141 #endif // wxLONGLONG_TEST_MODE
146 wxLongLongWx
wxLongLongWx::operator<<(int shift
) const
148 wxLongLongWx
ll(*this);
154 wxULongLongWx
wxULongLongWx::operator<<(int shift
) const
156 wxULongLongWx
ll(*this);
162 wxLongLongWx
& wxLongLongWx::operator<<=(int shift
)
169 m_hi
|= m_lo
>> (32 - shift
);
174 m_hi
= m_lo
<< (shift
- 32);
179 #ifdef wxLONGLONG_TEST_MODE
183 #endif // wxLONGLONG_TEST_MODE
188 wxULongLongWx
& wxULongLongWx::operator<<=(int shift
)
195 m_hi
|= m_lo
>> (32 - shift
);
200 m_hi
= m_lo
<< (shift
- 32);
205 #ifdef wxLONGLONG_TEST_MODE
209 #endif // wxLONGLONG_TEST_MODE
214 wxLongLongWx
wxLongLongWx::operator>>(int shift
) const
216 wxLongLongWx
ll(*this);
222 wxULongLongWx
wxULongLongWx::operator>>(int shift
) const
224 wxULongLongWx
ll(*this);
230 wxLongLongWx
& wxLongLongWx::operator>>=(int shift
)
237 m_lo
|= m_hi
<< (32 - shift
);
242 m_lo
= m_hi
>> (shift
- 32);
243 m_hi
= (m_hi
< 0 ? -1L : 0);
247 #ifdef wxLONGLONG_TEST_MODE
251 #endif // wxLONGLONG_TEST_MODE
256 wxULongLongWx
& wxULongLongWx::operator>>=(int shift
)
263 m_lo
|= m_hi
<< (32 - shift
);
268 m_lo
= m_hi
>> (shift
- 32);
273 #ifdef wxLONGLONG_TEST_MODE
277 #endif // wxLONGLONG_TEST_MODE
282 wxLongLongWx
wxLongLongWx::operator+(const wxLongLongWx
& ll
) const
284 wxLongLongWx
res(*this);
290 wxULongLongWx
wxULongLongWx::operator+(const wxULongLongWx
& ll
) const
292 wxULongLongWx
res(*this);
298 wxLongLongWx
wxLongLongWx::operator+(long l
) const
300 wxLongLongWx
res(*this);
306 wxULongLongWx
wxULongLongWx::operator+(unsigned long l
) const
308 wxULongLongWx
res(*this);
314 wxLongLongWx
& wxLongLongWx::operator+=(const wxLongLongWx
& ll
)
316 unsigned long previous
= m_lo
;
321 if ((m_lo
< previous
) || (m_lo
< ll
.m_lo
))
324 #ifdef wxLONGLONG_TEST_MODE
328 #endif // wxLONGLONG_TEST_MODE
333 wxULongLongWx
& wxULongLongWx::operator+=(const wxULongLongWx
& ll
)
335 unsigned long previous
= m_lo
;
340 if ((m_lo
< previous
) || (m_lo
< ll
.m_lo
))
343 #ifdef wxLONGLONG_TEST_MODE
347 #endif // wxLONGLONG_TEST_MODE
352 wxLongLongWx
& wxLongLongWx::operator+=(long l
)
354 unsigned long previous
= m_lo
;
360 if ((m_lo
< previous
) || (m_lo
< (unsigned long)l
))
363 #ifdef wxLONGLONG_TEST_MODE
367 #endif // wxLONGLONG_TEST_MODE
372 wxULongLongWx
& wxULongLongWx::operator+=(unsigned long l
)
374 unsigned long previous
= m_lo
;
378 if ((m_lo
< previous
) || (m_lo
< l
))
381 #ifdef wxLONGLONG_TEST_MODE
385 #endif // wxLONGLONG_TEST_MODE
391 wxLongLongWx
& wxLongLongWx::operator++()
397 #ifdef wxLONGLONG_TEST_MODE
401 #endif // wxLONGLONG_TEST_MODE
406 wxULongLongWx
& wxULongLongWx::operator++()
412 #ifdef wxLONGLONG_TEST_MODE
416 #endif // wxLONGLONG_TEST_MODE
422 wxLongLongWx
wxLongLongWx::operator-() const
424 wxLongLongWx
res(*this);
430 wxLongLongWx
& wxLongLongWx::Negate()
439 #ifdef wxLONGLONG_TEST_MODE
443 #endif // wxLONGLONG_TEST_MODE
450 wxLongLongWx
wxLongLongWx::operator-(const wxLongLongWx
& ll
) const
452 wxLongLongWx
res(*this);
458 wxLongLongWx
wxULongLongWx::operator-(const wxULongLongWx
& ll
) const
460 wxASSERT(m_hi
<= LONG_MAX
);
461 wxASSERT(ll
.m_hi
<= LONG_MAX
);
463 wxLongLongWx
res( (long)m_hi
, m_lo
);
464 wxLongLongWx
op( (long)ll
.m_hi
, ll
.m_lo
);
470 wxLongLongWx
& wxLongLongWx::operator-=(const wxLongLongWx
& ll
)
472 unsigned long previous
= m_lo
;
477 if (previous
< ll
.m_lo
)
480 #ifdef wxLONGLONG_TEST_MODE
484 #endif // wxLONGLONG_TEST_MODE
489 wxULongLongWx
& wxULongLongWx::operator-=(const wxULongLongWx
& ll
)
491 unsigned long previous
= m_lo
;
496 if (previous
< ll
.m_lo
)
499 #ifdef wxLONGLONG_TEST_MODE
503 #endif // wxLONGLONG_TEST_MODE
509 wxLongLongWx
& wxLongLongWx::operator--()
512 if (m_lo
== 0xFFFFFFFF)
515 #ifdef wxLONGLONG_TEST_MODE
519 #endif // wxLONGLONG_TEST_MODE
524 wxULongLongWx
& wxULongLongWx::operator--()
527 if (m_lo
== 0xFFFFFFFF)
530 #ifdef wxLONGLONG_TEST_MODE
534 #endif // wxLONGLONG_TEST_MODE
539 // comparison operators
541 bool wxLongLongWx::operator<(const wxLongLongWx
& ll
) const
543 if ( m_hi
< ll
.m_hi
)
545 else if ( m_hi
== ll
.m_hi
)
546 return m_lo
< ll
.m_lo
;
551 bool wxULongLongWx::operator<(const wxULongLongWx
& ll
) const
553 if ( m_hi
< ll
.m_hi
)
555 else if ( m_hi
== ll
.m_hi
)
556 return m_lo
< ll
.m_lo
;
561 bool wxLongLongWx::operator>(const wxLongLongWx
& ll
) const
563 if ( m_hi
> ll
.m_hi
)
565 else if ( m_hi
== ll
.m_hi
)
566 return m_lo
> ll
.m_lo
;
571 bool wxULongLongWx::operator>(const wxULongLongWx
& ll
) const
573 if ( m_hi
> ll
.m_hi
)
575 else if ( m_hi
== ll
.m_hi
)
576 return m_lo
> ll
.m_lo
;
583 wxLongLongWx
wxLongLongWx::operator&(const wxLongLongWx
& ll
) const
585 return wxLongLongWx(m_hi
& ll
.m_hi
, m_lo
& ll
.m_lo
);
588 wxULongLongWx
wxULongLongWx::operator&(const wxULongLongWx
& ll
) const
590 return wxULongLongWx(m_hi
& ll
.m_hi
, m_lo
& ll
.m_lo
);
593 wxLongLongWx
wxLongLongWx::operator|(const wxLongLongWx
& ll
) const
595 return wxLongLongWx(m_hi
| ll
.m_hi
, m_lo
| ll
.m_lo
);
598 wxULongLongWx
wxULongLongWx::operator|(const wxULongLongWx
& ll
) const
600 return wxULongLongWx(m_hi
| ll
.m_hi
, m_lo
| ll
.m_lo
);
603 wxLongLongWx
wxLongLongWx::operator^(const wxLongLongWx
& ll
) const
605 return wxLongLongWx(m_hi
^ ll
.m_hi
, m_lo
^ ll
.m_lo
);
608 wxULongLongWx
wxULongLongWx::operator^(const wxULongLongWx
& ll
) const
610 return wxULongLongWx(m_hi
^ ll
.m_hi
, m_lo
^ ll
.m_lo
);
613 wxLongLongWx
& wxLongLongWx::operator&=(const wxLongLongWx
& ll
)
618 #ifdef wxLONGLONG_TEST_MODE
622 #endif // wxLONGLONG_TEST_MODE
627 wxULongLongWx
& wxULongLongWx::operator&=(const wxULongLongWx
& ll
)
632 #ifdef wxLONGLONG_TEST_MODE
636 #endif // wxLONGLONG_TEST_MODE
641 wxLongLongWx
& wxLongLongWx::operator|=(const wxLongLongWx
& ll
)
646 #ifdef wxLONGLONG_TEST_MODE
650 #endif // wxLONGLONG_TEST_MODE
655 wxULongLongWx
& wxULongLongWx::operator|=(const wxULongLongWx
& ll
)
660 #ifdef wxLONGLONG_TEST_MODE
664 #endif // wxLONGLONG_TEST_MODE
669 wxLongLongWx
& wxLongLongWx::operator^=(const wxLongLongWx
& ll
)
674 #ifdef wxLONGLONG_TEST_MODE
678 #endif // wxLONGLONG_TEST_MODE
683 wxULongLongWx
& wxULongLongWx::operator^=(const wxULongLongWx
& ll
)
688 #ifdef wxLONGLONG_TEST_MODE
692 #endif // wxLONGLONG_TEST_MODE
697 wxLongLongWx
wxLongLongWx::operator~() const
699 return wxLongLongWx(~m_hi
, ~m_lo
);
702 wxULongLongWx
wxULongLongWx::operator~() const
704 return wxULongLongWx(~m_hi
, ~m_lo
);
709 wxLongLongWx
wxLongLongWx::operator*(const wxLongLongWx
& ll
) const
711 wxLongLongWx
res(*this);
717 wxULongLongWx
wxULongLongWx::operator*(const wxULongLongWx
& ll
) const
719 wxULongLongWx
res(*this);
725 wxLongLongWx
& wxLongLongWx::operator*=(const wxLongLongWx
& ll
)
727 wxLongLongWx
t(m_hi
, m_lo
);
728 wxLongLongWx
q(ll
.m_hi
, ll
.m_lo
);
732 #ifdef wxLONGLONG_TEST_MODE
733 wxLongLong_t llOld
= m_ll
;
735 #endif // wxLONGLONG_TEST_MODE
740 if ((q
.m_lo
& 1) != 0)
746 while ((counter
< 64) && ((q
.m_hi
!= 0) || (q
.m_lo
!= 0)));
748 #ifdef wxLONGLONG_TEST_MODE
749 m_ll
= llOld
* ll
.m_ll
;
752 #endif // wxLONGLONG_TEST_MODE
757 wxULongLongWx
& wxULongLongWx::operator*=(const wxULongLongWx
& ll
)
759 wxULongLongWx
t(m_hi
, m_lo
);
760 wxULongLongWx
q(ll
.m_hi
, ll
.m_lo
);
764 #ifdef wxLONGLONG_TEST_MODE
765 wxULongLong_t llOld
= m_ll
;
767 #endif // wxLONGLONG_TEST_MODE
772 if ((q
.m_lo
& 1) != 0)
778 while ((counter
< 64) && ((q
.m_hi
!= 0) || (q
.m_lo
!= 0)));
780 #ifdef wxLONGLONG_TEST_MODE
781 m_ll
= llOld
* ll
.m_ll
;
784 #endif // wxLONGLONG_TEST_MODE
791 #define IS_MSB_SET(ll) ((ll.GetHi()) & (1 << (8*sizeof(long) - 1)))
793 void wxLongLongWx::Divide(const wxLongLongWx
& divisorIn
,
794 wxLongLongWx
& quotient
,
795 wxLongLongWx
& remainderIO
) const
797 if ((divisorIn
.m_lo
== 0) && (divisorIn
.m_hi
== 0))
799 // provoke division by zero error and silence the compilers warnings
800 // about an expression without effect and unused variable
801 long dummy
= divisorIn
.m_lo
/divisorIn
.m_hi
;
805 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
806 // do this - any improvements are more than welcome
808 // code inspired by the snippet at
809 // http://www.bearcave.com/software/divide.htm
813 // Use of this program, for any purpose, is granted the author, Ian
814 // Kaplan, as long as this copyright notice is included in the source
815 // code or any source code derived from this program. The user assumes
816 // all responsibility for using this code.
819 wxULongLongWx dividend
, divisor
, remainder
;
824 // always do unsigned division and adjust the signs later: in C integer
825 // division, the sign of the remainder is the same as the sign of the
826 // dividend, while the sign of the quotient is the product of the signs of
827 // the dividend and divisor. Of course, we also always have
829 // dividend = quotient*divisor + remainder
831 // with 0 <= abs(remainder) < abs(divisor)
832 bool negRemainder
= GetHi() < 0;
833 bool negQuotient
= false; // assume positive
836 negQuotient
= !negQuotient
;
841 if ( divisorIn
.GetHi() < 0 )
843 negQuotient
= !negQuotient
;
844 divisor
= -divisorIn
;
849 // check for some particular cases
850 if ( divisor
> dividend
)
852 remainder
= dividend
;
854 else if ( divisor
== dividend
)
860 // here: dividend > divisor and both are positive: do unsigned division
864 while ( remainder
< divisor
)
867 if ( IS_MSB_SET(dividend
) )
878 // undo the last loop iteration
883 for ( size_t i
= 0; i
< nBits
; i
++ )
886 if ( IS_MSB_SET(dividend
) )
891 wxLongLongWx t
= remainder
- divisor
;
894 if ( !IS_MSB_SET(t
) )
903 remainderIO
= remainder
;
908 remainderIO
= -remainderIO
;
913 quotient
= -quotient
;
917 void wxULongLongWx::Divide(const wxULongLongWx
& divisorIn
,
918 wxULongLongWx
& quotient
,
919 wxULongLongWx
& remainder
) const
921 if ((divisorIn
.m_lo
== 0) && (divisorIn
.m_hi
== 0))
923 // provoke division by zero error and silence the compilers warnings
924 // about an expression without effect and unused variable
925 unsigned long dummy
= divisorIn
.m_lo
/divisorIn
.m_hi
;
929 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
930 // do this - any improvements are more than welcome
932 // code inspired by the snippet at
933 // http://www.bearcave.com/software/divide.htm
937 // Use of this program, for any purpose, is granted the author, Ian
938 // Kaplan, as long as this copyright notice is included in the source
939 // code or any source code derived from this program. The user assumes
940 // all responsibility for using this code.
943 wxULongLongWx dividend
= *this,
949 // check for some particular cases
950 if ( divisor
> dividend
)
952 remainder
= dividend
;
954 else if ( divisor
== dividend
)
960 // here: dividend > divisor
964 while ( remainder
< divisor
)
967 if ( IS_MSB_SET(dividend
) )
978 // undo the last loop iteration
983 for ( size_t i
= 0; i
< nBits
; i
++ )
986 if ( IS_MSB_SET(dividend
) )
991 wxULongLongWx t
= remainder
- divisor
;
994 if ( !IS_MSB_SET(t
) )
1004 wxLongLongWx
wxLongLongWx::operator/(const wxLongLongWx
& ll
) const
1006 wxLongLongWx quotient
, remainder
;
1008 Divide(ll
, quotient
, remainder
);
1013 wxULongLongWx
wxULongLongWx::operator/(const wxULongLongWx
& ll
) const
1015 wxULongLongWx quotient
, remainder
;
1017 Divide(ll
, quotient
, remainder
);
1022 wxLongLongWx
& wxLongLongWx::operator/=(const wxLongLongWx
& ll
)
1024 wxLongLongWx quotient
, remainder
;
1026 Divide(ll
, quotient
, remainder
);
1033 wxULongLongWx
& wxULongLongWx::operator/=(const wxULongLongWx
& ll
)
1035 wxULongLongWx quotient
, remainder
;
1037 Divide(ll
, quotient
, remainder
);
1044 wxLongLongWx
wxLongLongWx::operator%(const wxLongLongWx
& ll
) const
1046 wxLongLongWx quotient
, remainder
;
1048 Divide(ll
, quotient
, remainder
);
1053 wxULongLongWx
wxULongLongWx::operator%(const wxULongLongWx
& ll
) const
1055 wxULongLongWx quotient
, remainder
;
1057 Divide(ll
, quotient
, remainder
);
1062 // ----------------------------------------------------------------------------
1064 // ----------------------------------------------------------------------------
1066 // temporary - just for testing
1067 void *wxLongLongWx::asArray(void) const
1069 static unsigned char temp
[8];
1071 temp
[0] = (char)((m_hi
>> 24) & 0xFF);
1072 temp
[1] = (char)((m_hi
>> 16) & 0xFF);
1073 temp
[2] = (char)((m_hi
>> 8) & 0xFF);
1074 temp
[3] = (char)((m_hi
>> 0) & 0xFF);
1075 temp
[4] = (char)((m_lo
>> 24) & 0xFF);
1076 temp
[5] = (char)((m_lo
>> 16) & 0xFF);
1077 temp
[6] = (char)((m_lo
>> 8) & 0xFF);
1078 temp
[7] = (char)((m_lo
>> 0) & 0xFF);
1083 void *wxULongLongWx::asArray(void) const
1085 static unsigned char temp
[8];
1087 temp
[0] = (char)((m_hi
>> 24) & 0xFF);
1088 temp
[1] = (char)((m_hi
>> 16) & 0xFF);
1089 temp
[2] = (char)((m_hi
>> 8) & 0xFF);
1090 temp
[3] = (char)((m_hi
>> 0) & 0xFF);
1091 temp
[4] = (char)((m_lo
>> 24) & 0xFF);
1092 temp
[5] = (char)((m_lo
>> 16) & 0xFF);
1093 temp
[6] = (char)((m_lo
>> 8) & 0xFF);
1094 temp
[7] = (char)((m_lo
>> 0) & 0xFF);
1099 #endif // wxUSE_LONGLONG_WX
1101 #define LL_TO_STRING(name) \
1102 wxString name::ToString() const \
1104 /* TODO: this is awfully inefficient, anything better? */ \
1109 bool neg = ll < 0; \
1114 long digit = (ll % 10).ToLong(); \
1115 result.Prepend((wxChar)(_T('0') - digit)); \
1123 long digit = (ll % 10).ToLong(); \
1124 result.Prepend((wxChar)(_T('0') + digit)); \
1129 if ( result.empty() ) \
1132 result.Prepend(_T('-')); \
1137 #define ULL_TO_STRING(name) \
1138 wxString name::ToString() const \
1140 /* TODO: this is awfully inefficient, anything better? */ \
1147 result.Prepend((wxChar)(_T('0') + (ll % 10).ToULong())); \
1151 if ( result.empty() ) \
1157 #if wxUSE_LONGLONG_NATIVE
1158 LL_TO_STRING(wxLongLongNative
)
1159 ULL_TO_STRING(wxULongLongNative
)
1162 #if wxUSE_LONGLONG_WX
1163 LL_TO_STRING(wxLongLongWx
)
1164 ULL_TO_STRING(wxULongLongWx
)
1167 #if wxUSE_STD_IOSTREAM
1171 wxSTD ostream
& operator<< (wxSTD ostream
& o
, const wxLongLong
& ll
)
1173 return o
<< ll
.ToString();
1177 wxSTD ostream
& operator<< (wxSTD ostream
& o
, const wxULongLong
& ll
)
1179 return o
<< ll
.ToString();
1182 #endif // wxUSE_STD_IOSTREAM
1184 WXDLLIMPEXP_BASE wxString
& operator<< (wxString
& s
, const wxLongLong
& ll
)
1186 return s
<< ll
.ToString();
1189 WXDLLIMPEXP_BASE wxString
& operator<< (wxString
& s
, const wxULongLong
& ll
)
1191 return s
<< ll
.ToString();
1194 #endif // wxUSE_LONGLONG