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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
19 #pragma implementation "longlong.h"
22 #include "wx/wxprec.h"
29 #include "wx/longlong.h"
30 #include "wx/math.h" // for fabs()
32 #if defined(__MWERKS__) && defined(__WXMSW__)
33 #include <string.h> // for memset()
35 #include <memory.h> // for memset()
38 #include "wx/ioswrap.h"
40 // ============================================================================
42 // ============================================================================
44 #if wxUSE_LONGLONG_NATIVE
46 // ----------------------------------------------------------------------------
48 // ----------------------------------------------------------------------------
50 void *wxLongLongNative::asArray() const
52 static unsigned char temp
[8];
54 temp
[0] = (unsigned char)((m_ll
>> 56) & 0xFF);
55 temp
[1] = (unsigned char)((m_ll
>> 48) & 0xFF);
56 temp
[2] = (unsigned char)((m_ll
>> 40) & 0xFF);
57 temp
[3] = (unsigned char)((m_ll
>> 32) & 0xFF);
58 temp
[4] = (unsigned char)((m_ll
>> 24) & 0xFF);
59 temp
[5] = (unsigned char)((m_ll
>> 16) & 0xFF);
60 temp
[6] = (unsigned char)((m_ll
>> 8) & 0xFF);
61 temp
[7] = (unsigned char)((m_ll
>> 0) & 0xFF);
66 void *wxULongLongNative::asArray() const
68 static unsigned char temp
[8];
70 temp
[0] = (unsigned char)((m_ll
>> 56) & 0xFF);
71 temp
[1] = (unsigned char)((m_ll
>> 48) & 0xFF);
72 temp
[2] = (unsigned char)((m_ll
>> 40) & 0xFF);
73 temp
[3] = (unsigned char)((m_ll
>> 32) & 0xFF);
74 temp
[4] = (unsigned char)((m_ll
>> 24) & 0xFF);
75 temp
[5] = (unsigned char)((m_ll
>> 16) & 0xFF);
76 temp
[6] = (unsigned char)((m_ll
>> 8) & 0xFF);
77 temp
[7] = (unsigned char)((m_ll
>> 0) & 0xFF);
83 wxLongLongNative::wxLongLongNative(wxLongLongWx ll
)
85 // assign first to avoid precision loss!
91 wxLongLongNative
& wxLongLongNative::operator=(wxLongLongWx ll
)
93 // assign first to avoid precision loss!
101 #endif // wxUSE_LONGLONG_NATIVE
103 // ============================================================================
104 // wxLongLongWx: emulation of 'long long' using 2 longs
105 // ============================================================================
107 #if wxUSE_LONGLONG_WX
110 wxLongLongWx
& wxLongLongWx::Assign(double d
)
112 bool positive
= d
>= 0;
114 if ( d
<= ULONG_MAX
)
121 m_hi
= (unsigned long)(d
/ (1.0 + (double)ULONG_MAX
));
122 m_lo
= (unsigned long)(d
- ((double)m_hi
* (1.0 + (double)ULONG_MAX
)));
125 #ifdef wxLONGLONG_TEST_MODE
126 m_ll
= (wxLongLong_t
)d
;
129 #endif // wxLONGLONG_TEST_MODE
137 double wxLongLongWx::ToDouble() const
140 d
*= 1.0 + (double)ULONG_MAX
;
143 #ifdef wxLONGLONG_TEST_MODE
144 wxASSERT( d
== m_ll
);
145 #endif // wxLONGLONG_TEST_MODE
150 wxLongLongWx
wxLongLongWx::operator<<(int shift
) const
152 wxLongLongWx
ll(*this);
158 wxULongLongWx
wxULongLongWx::operator<<(int shift
) const
160 wxULongLongWx
ll(*this);
166 wxLongLongWx
& wxLongLongWx::operator<<=(int shift
)
173 m_hi
|= m_lo
>> (32 - shift
);
178 m_hi
= m_lo
<< (shift
- 32);
183 #ifdef wxLONGLONG_TEST_MODE
187 #endif // wxLONGLONG_TEST_MODE
192 wxULongLongWx
& wxULongLongWx::operator<<=(int shift
)
199 m_hi
|= m_lo
>> (32 - shift
);
204 m_hi
= m_lo
<< (shift
- 32);
209 #ifdef wxLONGLONG_TEST_MODE
213 #endif // wxLONGLONG_TEST_MODE
218 wxLongLongWx
wxLongLongWx::operator>>(int shift
) const
220 wxLongLongWx
ll(*this);
226 wxULongLongWx
wxULongLongWx::operator>>(int shift
) const
228 wxULongLongWx
ll(*this);
234 wxLongLongWx
& wxLongLongWx::operator>>=(int shift
)
241 m_lo
|= m_hi
<< (32 - shift
);
246 m_lo
= m_hi
>> (shift
- 32);
247 m_hi
= (m_hi
< 0 ? -1L : 0);
251 #ifdef wxLONGLONG_TEST_MODE
255 #endif // wxLONGLONG_TEST_MODE
260 wxULongLongWx
& wxULongLongWx::operator>>=(int shift
)
267 m_lo
|= m_hi
<< (32 - shift
);
272 m_lo
= m_hi
>> (shift
- 32);
277 #ifdef wxLONGLONG_TEST_MODE
281 #endif // wxLONGLONG_TEST_MODE
286 wxLongLongWx
wxLongLongWx::operator+(const wxLongLongWx
& ll
) const
288 wxLongLongWx
res(*this);
294 wxULongLongWx
wxULongLongWx::operator+(const wxULongLongWx
& ll
) const
296 wxULongLongWx
res(*this);
302 wxLongLongWx
wxLongLongWx::operator+(long l
) const
304 wxLongLongWx
res(*this);
310 wxULongLongWx
wxULongLongWx::operator+(unsigned long l
) const
312 wxULongLongWx
res(*this);
318 wxLongLongWx
& wxLongLongWx::operator+=(const wxLongLongWx
& ll
)
320 unsigned long previous
= m_lo
;
325 if ((m_lo
< previous
) || (m_lo
< ll
.m_lo
))
328 #ifdef wxLONGLONG_TEST_MODE
332 #endif // wxLONGLONG_TEST_MODE
337 wxULongLongWx
& wxULongLongWx::operator+=(const wxULongLongWx
& ll
)
339 unsigned long previous
= m_lo
;
344 if ((m_lo
< previous
) || (m_lo
< ll
.m_lo
))
347 #ifdef wxLONGLONG_TEST_MODE
351 #endif // wxLONGLONG_TEST_MODE
356 wxLongLongWx
& wxLongLongWx::operator+=(long l
)
358 unsigned long previous
= m_lo
;
364 if ((m_lo
< previous
) || (m_lo
< (unsigned long)l
))
367 #ifdef wxLONGLONG_TEST_MODE
371 #endif // wxLONGLONG_TEST_MODE
376 wxULongLongWx
& wxULongLongWx::operator+=(unsigned long l
)
378 unsigned long previous
= m_lo
;
382 if ((m_lo
< previous
) || (m_lo
< l
))
385 #ifdef wxLONGLONG_TEST_MODE
389 #endif // wxLONGLONG_TEST_MODE
395 wxLongLongWx
& wxLongLongWx::operator++()
401 #ifdef wxLONGLONG_TEST_MODE
405 #endif // wxLONGLONG_TEST_MODE
410 wxULongLongWx
& wxULongLongWx::operator++()
416 #ifdef wxLONGLONG_TEST_MODE
420 #endif // wxLONGLONG_TEST_MODE
426 wxLongLongWx
wxLongLongWx::operator-() const
428 wxLongLongWx
res(*this);
434 wxLongLongWx
& wxLongLongWx::Negate()
443 #ifdef wxLONGLONG_TEST_MODE
447 #endif // wxLONGLONG_TEST_MODE
454 wxLongLongWx
wxLongLongWx::operator-(const wxLongLongWx
& ll
) const
456 wxLongLongWx
res(*this);
462 wxLongLongWx
wxULongLongWx::operator-(const wxULongLongWx
& ll
) const
464 wxASSERT(m_hi
<= LONG_MAX
);
465 wxASSERT(ll
.m_hi
<= LONG_MAX
);
467 wxLongLongWx
res( (long)m_hi
, m_lo
);
468 wxLongLongWx
op( (long)ll
.m_hi
, ll
.m_lo
);
474 wxLongLongWx
& wxLongLongWx::operator-=(const wxLongLongWx
& ll
)
476 unsigned long previous
= m_lo
;
481 if (previous
< ll
.m_lo
)
484 #ifdef wxLONGLONG_TEST_MODE
488 #endif // wxLONGLONG_TEST_MODE
493 wxULongLongWx
& wxULongLongWx::operator-=(const wxULongLongWx
& ll
)
495 unsigned long previous
= m_lo
;
500 if (previous
< ll
.m_lo
)
503 #ifdef wxLONGLONG_TEST_MODE
507 #endif // wxLONGLONG_TEST_MODE
513 wxLongLongWx
& wxLongLongWx::operator--()
516 if (m_lo
== 0xFFFFFFFF)
519 #ifdef wxLONGLONG_TEST_MODE
523 #endif // wxLONGLONG_TEST_MODE
528 wxULongLongWx
& wxULongLongWx::operator--()
531 if (m_lo
== 0xFFFFFFFF)
534 #ifdef wxLONGLONG_TEST_MODE
538 #endif // wxLONGLONG_TEST_MODE
543 // comparison operators
545 bool wxLongLongWx::operator<(const wxLongLongWx
& ll
) const
547 if ( m_hi
< ll
.m_hi
)
549 else if ( m_hi
== ll
.m_hi
)
550 return m_lo
< ll
.m_lo
;
555 bool wxULongLongWx::operator<(const wxULongLongWx
& ll
) const
557 if ( m_hi
< ll
.m_hi
)
559 else if ( m_hi
== ll
.m_hi
)
560 return m_lo
< ll
.m_lo
;
565 bool wxLongLongWx::operator>(const wxLongLongWx
& ll
) const
567 if ( m_hi
> ll
.m_hi
)
569 else if ( m_hi
== ll
.m_hi
)
570 return m_lo
> ll
.m_lo
;
575 bool wxULongLongWx::operator>(const wxULongLongWx
& ll
) const
577 if ( m_hi
> ll
.m_hi
)
579 else if ( m_hi
== ll
.m_hi
)
580 return m_lo
> ll
.m_lo
;
587 wxLongLongWx
wxLongLongWx::operator&(const wxLongLongWx
& ll
) const
589 return wxLongLongWx(m_hi
& ll
.m_hi
, m_lo
& ll
.m_lo
);
592 wxULongLongWx
wxULongLongWx::operator&(const wxULongLongWx
& ll
) const
594 return wxULongLongWx(m_hi
& ll
.m_hi
, m_lo
& ll
.m_lo
);
597 wxLongLongWx
wxLongLongWx::operator|(const wxLongLongWx
& ll
) const
599 return wxLongLongWx(m_hi
| ll
.m_hi
, m_lo
| ll
.m_lo
);
602 wxULongLongWx
wxULongLongWx::operator|(const wxULongLongWx
& ll
) const
604 return wxULongLongWx(m_hi
| ll
.m_hi
, m_lo
| ll
.m_lo
);
607 wxLongLongWx
wxLongLongWx::operator^(const wxLongLongWx
& ll
) const
609 return wxLongLongWx(m_hi
^ ll
.m_hi
, m_lo
^ ll
.m_lo
);
612 wxULongLongWx
wxULongLongWx::operator^(const wxULongLongWx
& ll
) const
614 return wxULongLongWx(m_hi
^ ll
.m_hi
, m_lo
^ ll
.m_lo
);
617 wxLongLongWx
& wxLongLongWx::operator&=(const wxLongLongWx
& ll
)
622 #ifdef wxLONGLONG_TEST_MODE
626 #endif // wxLONGLONG_TEST_MODE
631 wxULongLongWx
& wxULongLongWx::operator&=(const wxULongLongWx
& ll
)
636 #ifdef wxLONGLONG_TEST_MODE
640 #endif // wxLONGLONG_TEST_MODE
645 wxLongLongWx
& wxLongLongWx::operator|=(const wxLongLongWx
& ll
)
650 #ifdef wxLONGLONG_TEST_MODE
654 #endif // wxLONGLONG_TEST_MODE
659 wxULongLongWx
& wxULongLongWx::operator|=(const wxULongLongWx
& ll
)
664 #ifdef wxLONGLONG_TEST_MODE
668 #endif // wxLONGLONG_TEST_MODE
673 wxLongLongWx
& wxLongLongWx::operator^=(const wxLongLongWx
& ll
)
678 #ifdef wxLONGLONG_TEST_MODE
682 #endif // wxLONGLONG_TEST_MODE
687 wxULongLongWx
& wxULongLongWx::operator^=(const wxULongLongWx
& ll
)
692 #ifdef wxLONGLONG_TEST_MODE
696 #endif // wxLONGLONG_TEST_MODE
701 wxLongLongWx
wxLongLongWx::operator~() const
703 return wxLongLongWx(~m_hi
, ~m_lo
);
706 wxULongLongWx
wxULongLongWx::operator~() const
708 return wxULongLongWx(~m_hi
, ~m_lo
);
713 wxLongLongWx
wxLongLongWx::operator*(const wxLongLongWx
& ll
) const
715 wxLongLongWx
res(*this);
721 wxULongLongWx
wxULongLongWx::operator*(const wxULongLongWx
& ll
) const
723 wxULongLongWx
res(*this);
729 wxLongLongWx
& wxLongLongWx::operator*=(const wxLongLongWx
& ll
)
731 wxLongLongWx
t(m_hi
, m_lo
);
732 wxLongLongWx
q(ll
.m_hi
, ll
.m_lo
);
736 #ifdef wxLONGLONG_TEST_MODE
737 wxLongLong_t llOld
= m_ll
;
739 #endif // wxLONGLONG_TEST_MODE
744 if ((q
.m_lo
& 1) != 0)
750 while ((counter
< 64) && ((q
.m_hi
!= 0) || (q
.m_lo
!= 0)));
752 #ifdef wxLONGLONG_TEST_MODE
753 m_ll
= llOld
* ll
.m_ll
;
756 #endif // wxLONGLONG_TEST_MODE
761 wxULongLongWx
& wxULongLongWx::operator*=(const wxULongLongWx
& ll
)
763 wxULongLongWx
t(m_hi
, m_lo
);
764 wxULongLongWx
q(ll
.m_hi
, ll
.m_lo
);
768 #ifdef wxLONGLONG_TEST_MODE
769 wxULongLong_t llOld
= m_ll
;
771 #endif // wxLONGLONG_TEST_MODE
776 if ((q
.m_lo
& 1) != 0)
782 while ((counter
< 64) && ((q
.m_hi
!= 0) || (q
.m_lo
!= 0)));
784 #ifdef wxLONGLONG_TEST_MODE
785 m_ll
= llOld
* ll
.m_ll
;
788 #endif // wxLONGLONG_TEST_MODE
795 #define IS_MSB_SET(ll) ((ll.GetHi()) & (1 << (8*sizeof(long) - 1)))
797 void wxLongLongWx::Divide(const wxLongLongWx
& divisorIn
,
798 wxLongLongWx
& quotient
,
799 wxLongLongWx
& remainderIO
) const
801 if ((divisorIn
.m_lo
== 0) && (divisorIn
.m_hi
== 0))
803 // provoke division by zero error and silence the compilers warnings
804 // about an expression without effect and unused variable
805 long dummy
= divisorIn
.m_lo
/divisorIn
.m_hi
;
809 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
810 // do this - any improvements are more than welcome
812 // code inspired by the snippet at
813 // http://www.bearcave.com/software/divide.htm
817 // Use of this program, for any purpose, is granted the author, Ian
818 // Kaplan, as long as this copyright notice is included in the source
819 // code or any source code derived from this program. The user assumes
820 // all responsibility for using this code.
823 wxULongLongWx dividend
, divisor
, remainder
;
828 // always do unsigned division and adjust the signs later: in C integer
829 // division, the sign of the remainder is the same as the sign of the
830 // dividend, while the sign of the quotient is the product of the signs of
831 // the dividend and divisor. Of course, we also always have
833 // dividend = quotient*divisor + remainder
835 // with 0 <= abs(remainder) < abs(divisor)
836 bool negRemainder
= GetHi() < 0;
837 bool negQuotient
= false; // assume positive
840 negQuotient
= !negQuotient
;
845 if ( divisorIn
.GetHi() < 0 )
847 negQuotient
= !negQuotient
;
848 divisor
= -divisorIn
;
853 // check for some particular cases
854 if ( divisor
> dividend
)
856 remainder
= dividend
;
858 else if ( divisor
== dividend
)
864 // here: dividend > divisor and both are positive: do unsigned division
868 while ( remainder
< divisor
)
871 if ( IS_MSB_SET(dividend
) )
882 // undo the last loop iteration
887 for ( size_t i
= 0; i
< nBits
; i
++ )
890 if ( IS_MSB_SET(dividend
) )
895 wxLongLongWx t
= remainder
- divisor
;
898 if ( !IS_MSB_SET(t
) )
907 remainderIO
= remainder
;
912 remainderIO
= -remainderIO
;
917 quotient
= -quotient
;
921 void wxULongLongWx::Divide(const wxULongLongWx
& divisorIn
,
922 wxULongLongWx
& quotient
,
923 wxULongLongWx
& remainder
) const
925 if ((divisorIn
.m_lo
== 0) && (divisorIn
.m_hi
== 0))
927 // provoke division by zero error and silence the compilers warnings
928 // about an expression without effect and unused variable
929 unsigned long dummy
= divisorIn
.m_lo
/divisorIn
.m_hi
;
933 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
934 // do this - any improvements are more than welcome
936 // code inspired by the snippet at
937 // http://www.bearcave.com/software/divide.htm
941 // Use of this program, for any purpose, is granted the author, Ian
942 // Kaplan, as long as this copyright notice is included in the source
943 // code or any source code derived from this program. The user assumes
944 // all responsibility for using this code.
947 wxULongLongWx dividend
= *this,
953 // check for some particular cases
954 if ( divisor
> dividend
)
956 remainder
= dividend
;
958 else if ( divisor
== dividend
)
964 // here: dividend > divisor
968 while ( remainder
< divisor
)
971 if ( IS_MSB_SET(dividend
) )
982 // undo the last loop iteration
987 for ( size_t i
= 0; i
< nBits
; i
++ )
990 if ( IS_MSB_SET(dividend
) )
995 wxULongLongWx t
= remainder
- divisor
;
998 if ( !IS_MSB_SET(t
) )
1008 wxLongLongWx
wxLongLongWx::operator/(const wxLongLongWx
& ll
) const
1010 wxLongLongWx quotient
, remainder
;
1012 Divide(ll
, quotient
, remainder
);
1017 wxULongLongWx
wxULongLongWx::operator/(const wxULongLongWx
& ll
) const
1019 wxULongLongWx quotient
, remainder
;
1021 Divide(ll
, quotient
, remainder
);
1026 wxLongLongWx
& wxLongLongWx::operator/=(const wxLongLongWx
& ll
)
1028 wxLongLongWx quotient
, remainder
;
1030 Divide(ll
, quotient
, remainder
);
1037 wxULongLongWx
& wxULongLongWx::operator/=(const wxULongLongWx
& ll
)
1039 wxULongLongWx quotient
, remainder
;
1041 Divide(ll
, quotient
, remainder
);
1048 wxLongLongWx
wxLongLongWx::operator%(const wxLongLongWx
& ll
) const
1050 wxLongLongWx quotient
, remainder
;
1052 Divide(ll
, quotient
, remainder
);
1057 wxULongLongWx
wxULongLongWx::operator%(const wxULongLongWx
& ll
) const
1059 wxULongLongWx quotient
, remainder
;
1061 Divide(ll
, quotient
, remainder
);
1066 // ----------------------------------------------------------------------------
1068 // ----------------------------------------------------------------------------
1070 // temporary - just for testing
1071 void *wxLongLongWx::asArray(void) const
1073 static unsigned char temp
[8];
1075 temp
[0] = (char)((m_hi
>> 24) & 0xFF);
1076 temp
[1] = (char)((m_hi
>> 16) & 0xFF);
1077 temp
[2] = (char)((m_hi
>> 8) & 0xFF);
1078 temp
[3] = (char)((m_hi
>> 0) & 0xFF);
1079 temp
[4] = (char)((m_lo
>> 24) & 0xFF);
1080 temp
[5] = (char)((m_lo
>> 16) & 0xFF);
1081 temp
[6] = (char)((m_lo
>> 8) & 0xFF);
1082 temp
[7] = (char)((m_lo
>> 0) & 0xFF);
1087 void *wxULongLongWx::asArray(void) const
1089 static unsigned char temp
[8];
1091 temp
[0] = (char)((m_hi
>> 24) & 0xFF);
1092 temp
[1] = (char)((m_hi
>> 16) & 0xFF);
1093 temp
[2] = (char)((m_hi
>> 8) & 0xFF);
1094 temp
[3] = (char)((m_hi
>> 0) & 0xFF);
1095 temp
[4] = (char)((m_lo
>> 24) & 0xFF);
1096 temp
[5] = (char)((m_lo
>> 16) & 0xFF);
1097 temp
[6] = (char)((m_lo
>> 8) & 0xFF);
1098 temp
[7] = (char)((m_lo
>> 0) & 0xFF);
1103 #endif // wxUSE_LONGLONG_WX
1105 #define LL_TO_STRING(name) \
1106 wxString name::ToString() const \
1108 /* TODO: this is awfully inefficient, anything better? */ \
1113 bool neg = ll < 0; \
1118 long digit = (ll % 10).ToLong(); \
1119 result.Prepend((wxChar)(_T('0') - digit)); \
1127 long digit = (ll % 10).ToLong(); \
1128 result.Prepend((wxChar)(_T('0') + digit)); \
1133 if ( result.empty() ) \
1136 result.Prepend(_T('-')); \
1141 #define ULL_TO_STRING(name) \
1142 wxString name::ToString() const \
1144 /* TODO: this is awfully inefficient, anything better? */ \
1151 result.Prepend((wxChar)(_T('0') + (ll % 10).ToULong())); \
1155 if ( result.empty() ) \
1161 #if wxUSE_LONGLONG_NATIVE
1162 LL_TO_STRING(wxLongLongNative
)
1163 ULL_TO_STRING(wxULongLongNative
)
1166 #if wxUSE_LONGLONG_WX
1167 LL_TO_STRING(wxLongLongWx
)
1168 ULL_TO_STRING(wxULongLongWx
)
1171 #if wxUSE_STD_IOSTREAM
1175 wxSTD ostream
& operator<< (wxSTD ostream
& o
, const wxLongLong
& ll
)
1177 return o
<< ll
.ToString();
1181 wxSTD ostream
& operator<< (wxSTD ostream
& o
, const wxULongLong
& ll
)
1183 return o
<< ll
.ToString();
1186 #endif // wxUSE_STD_IOSTREAM
1188 WXDLLIMPEXP_BASE wxString
& operator<< (wxString
& s
, const wxLongLong
& ll
)
1190 return s
<< ll
.ToString();
1193 WXDLLIMPEXP_BASE wxString
& operator<< (wxString
& s
, const wxULongLong
& ll
)
1195 return s
<< ll
.ToString();
1198 #endif // wxUSE_LONGLONG