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 wxLongLongWx
wxLongLongWx::operator<<(int shift
) const
139 wxLongLongWx
ll(*this);
145 wxULongLongWx
wxULongLongWx::operator<<(int shift
) const
147 wxULongLongWx
ll(*this);
153 wxLongLongWx
& wxLongLongWx::operator<<=(int shift
)
160 m_hi
|= m_lo
>> (32 - shift
);
165 m_hi
= m_lo
<< (shift
- 32);
170 #ifdef wxLONGLONG_TEST_MODE
174 #endif // wxLONGLONG_TEST_MODE
179 wxULongLongWx
& wxULongLongWx::operator<<=(int shift
)
186 m_hi
|= m_lo
>> (32 - shift
);
191 m_hi
= m_lo
<< (shift
- 32);
196 #ifdef wxLONGLONG_TEST_MODE
200 #endif // wxLONGLONG_TEST_MODE
205 wxLongLongWx
wxLongLongWx::operator>>(int shift
) const
207 wxLongLongWx
ll(*this);
213 wxULongLongWx
wxULongLongWx::operator>>(int shift
) const
215 wxULongLongWx
ll(*this);
221 wxLongLongWx
& wxLongLongWx::operator>>=(int shift
)
228 m_lo
|= m_hi
<< (32 - shift
);
233 m_lo
= m_hi
>> (shift
- 32);
234 m_hi
= (m_hi
< 0 ? -1L : 0);
238 #ifdef wxLONGLONG_TEST_MODE
242 #endif // wxLONGLONG_TEST_MODE
247 wxULongLongWx
& wxULongLongWx::operator>>=(int shift
)
254 m_lo
|= m_hi
<< (32 - shift
);
259 m_lo
= m_hi
>> (shift
- 32);
264 #ifdef wxLONGLONG_TEST_MODE
268 #endif // wxLONGLONG_TEST_MODE
273 wxLongLongWx
wxLongLongWx::operator+(const wxLongLongWx
& ll
) const
275 wxLongLongWx
res(*this);
281 wxULongLongWx
wxULongLongWx::operator+(const wxULongLongWx
& ll
) const
283 wxULongLongWx
res(*this);
289 wxLongLongWx
wxLongLongWx::operator+(long l
) const
291 wxLongLongWx
res(*this);
297 wxULongLongWx
wxULongLongWx::operator+(unsigned long l
) const
299 wxULongLongWx
res(*this);
305 wxLongLongWx
& wxLongLongWx::operator+=(const wxLongLongWx
& ll
)
307 unsigned long previous
= m_lo
;
312 if ((m_lo
< previous
) || (m_lo
< ll
.m_lo
))
315 #ifdef wxLONGLONG_TEST_MODE
319 #endif // wxLONGLONG_TEST_MODE
324 wxULongLongWx
& wxULongLongWx::operator+=(const wxULongLongWx
& ll
)
326 unsigned long previous
= m_lo
;
331 if ((m_lo
< previous
) || (m_lo
< ll
.m_lo
))
334 #ifdef wxLONGLONG_TEST_MODE
338 #endif // wxLONGLONG_TEST_MODE
343 wxLongLongWx
& wxLongLongWx::operator+=(long l
)
345 unsigned long previous
= m_lo
;
351 if ((m_lo
< previous
) || (m_lo
< (unsigned long)l
))
354 #ifdef wxLONGLONG_TEST_MODE
358 #endif // wxLONGLONG_TEST_MODE
363 wxULongLongWx
& wxULongLongWx::operator+=(unsigned long l
)
365 unsigned long previous
= m_lo
;
369 if ((m_lo
< previous
) || (m_lo
< l
))
372 #ifdef wxLONGLONG_TEST_MODE
376 #endif // wxLONGLONG_TEST_MODE
382 wxLongLongWx
& wxLongLongWx::operator++()
388 #ifdef wxLONGLONG_TEST_MODE
392 #endif // wxLONGLONG_TEST_MODE
397 wxULongLongWx
& wxULongLongWx::operator++()
403 #ifdef wxLONGLONG_TEST_MODE
407 #endif // wxLONGLONG_TEST_MODE
413 wxLongLongWx
wxLongLongWx::operator-() const
415 wxLongLongWx
res(*this);
421 wxLongLongWx
& wxLongLongWx::Negate()
430 #ifdef wxLONGLONG_TEST_MODE
434 #endif // wxLONGLONG_TEST_MODE
441 wxLongLongWx
wxLongLongWx::operator-(const wxLongLongWx
& ll
) const
443 wxLongLongWx
res(*this);
449 wxLongLongWx
wxULongLongWx::operator-(const wxULongLongWx
& ll
) const
451 wxASSERT(m_hi
<= LONG_MAX
);
452 wxASSERT(ll
.m_hi
<= LONG_MAX
);
454 wxLongLongWx
res( (long)m_hi
, m_lo
);
455 wxLongLongWx
op( (long)ll
.m_hi
, ll
.m_lo
);
461 wxLongLongWx
& wxLongLongWx::operator-=(const wxLongLongWx
& ll
)
463 unsigned long previous
= m_lo
;
468 if (previous
< ll
.m_lo
)
471 #ifdef wxLONGLONG_TEST_MODE
475 #endif // wxLONGLONG_TEST_MODE
480 wxULongLongWx
& wxULongLongWx::operator-=(const wxULongLongWx
& ll
)
482 unsigned long previous
= m_lo
;
487 if (previous
< ll
.m_lo
)
490 #ifdef wxLONGLONG_TEST_MODE
494 #endif // wxLONGLONG_TEST_MODE
500 wxLongLongWx
& wxLongLongWx::operator--()
503 if (m_lo
== 0xFFFFFFFF)
506 #ifdef wxLONGLONG_TEST_MODE
510 #endif // wxLONGLONG_TEST_MODE
515 wxULongLongWx
& wxULongLongWx::operator--()
518 if (m_lo
== 0xFFFFFFFF)
521 #ifdef wxLONGLONG_TEST_MODE
525 #endif // wxLONGLONG_TEST_MODE
530 // comparison operators
532 bool wxLongLongWx::operator<(const wxLongLongWx
& ll
) const
534 if ( m_hi
< ll
.m_hi
)
536 else if ( m_hi
== ll
.m_hi
)
537 return m_lo
< ll
.m_lo
;
542 bool wxULongLongWx::operator<(const wxULongLongWx
& ll
) const
544 if ( m_hi
< ll
.m_hi
)
546 else if ( m_hi
== ll
.m_hi
)
547 return m_lo
< ll
.m_lo
;
552 bool wxLongLongWx::operator>(const wxLongLongWx
& ll
) const
554 if ( m_hi
> ll
.m_hi
)
556 else if ( m_hi
== ll
.m_hi
)
557 return m_lo
> ll
.m_lo
;
562 bool wxULongLongWx::operator>(const wxULongLongWx
& ll
) const
564 if ( m_hi
> ll
.m_hi
)
566 else if ( m_hi
== ll
.m_hi
)
567 return m_lo
> ll
.m_lo
;
574 wxLongLongWx
wxLongLongWx::operator&(const wxLongLongWx
& ll
) const
576 return wxLongLongWx(m_hi
& ll
.m_hi
, m_lo
& ll
.m_lo
);
579 wxULongLongWx
wxULongLongWx::operator&(const wxULongLongWx
& ll
) const
581 return wxULongLongWx(m_hi
& ll
.m_hi
, m_lo
& ll
.m_lo
);
584 wxLongLongWx
wxLongLongWx::operator|(const wxLongLongWx
& ll
) const
586 return wxLongLongWx(m_hi
| ll
.m_hi
, m_lo
| ll
.m_lo
);
589 wxULongLongWx
wxULongLongWx::operator|(const wxULongLongWx
& ll
) const
591 return wxULongLongWx(m_hi
| ll
.m_hi
, m_lo
| ll
.m_lo
);
594 wxLongLongWx
wxLongLongWx::operator^(const wxLongLongWx
& ll
) const
596 return wxLongLongWx(m_hi
^ ll
.m_hi
, m_lo
^ ll
.m_lo
);
599 wxULongLongWx
wxULongLongWx::operator^(const wxULongLongWx
& ll
) const
601 return wxULongLongWx(m_hi
^ ll
.m_hi
, m_lo
^ ll
.m_lo
);
604 wxLongLongWx
& wxLongLongWx::operator&=(const wxLongLongWx
& ll
)
609 #ifdef wxLONGLONG_TEST_MODE
613 #endif // wxLONGLONG_TEST_MODE
618 wxULongLongWx
& wxULongLongWx::operator&=(const wxULongLongWx
& ll
)
623 #ifdef wxLONGLONG_TEST_MODE
627 #endif // wxLONGLONG_TEST_MODE
632 wxLongLongWx
& wxLongLongWx::operator|=(const wxLongLongWx
& ll
)
637 #ifdef wxLONGLONG_TEST_MODE
641 #endif // wxLONGLONG_TEST_MODE
646 wxULongLongWx
& wxULongLongWx::operator|=(const wxULongLongWx
& ll
)
651 #ifdef wxLONGLONG_TEST_MODE
655 #endif // wxLONGLONG_TEST_MODE
660 wxLongLongWx
& wxLongLongWx::operator^=(const wxLongLongWx
& ll
)
665 #ifdef wxLONGLONG_TEST_MODE
669 #endif // wxLONGLONG_TEST_MODE
674 wxULongLongWx
& wxULongLongWx::operator^=(const wxULongLongWx
& ll
)
679 #ifdef wxLONGLONG_TEST_MODE
683 #endif // wxLONGLONG_TEST_MODE
688 wxLongLongWx
wxLongLongWx::operator~() const
690 return wxLongLongWx(~m_hi
, ~m_lo
);
693 wxULongLongWx
wxULongLongWx::operator~() const
695 return wxULongLongWx(~m_hi
, ~m_lo
);
700 wxLongLongWx
wxLongLongWx::operator*(const wxLongLongWx
& ll
) const
702 wxLongLongWx
res(*this);
708 wxULongLongWx
wxULongLongWx::operator*(const wxULongLongWx
& ll
) const
710 wxULongLongWx
res(*this);
716 wxLongLongWx
& wxLongLongWx::operator*=(const wxLongLongWx
& ll
)
718 wxLongLongWx
t(m_hi
, m_lo
);
719 wxLongLongWx
q(ll
.m_hi
, ll
.m_lo
);
723 #ifdef wxLONGLONG_TEST_MODE
724 wxLongLong_t llOld
= m_ll
;
726 #endif // wxLONGLONG_TEST_MODE
731 if ((q
.m_lo
& 1) != 0)
737 while ((counter
< 64) && ((q
.m_hi
!= 0) || (q
.m_lo
!= 0)));
739 #ifdef wxLONGLONG_TEST_MODE
740 m_ll
= llOld
* ll
.m_ll
;
743 #endif // wxLONGLONG_TEST_MODE
748 wxULongLongWx
& wxULongLongWx::operator*=(const wxULongLongWx
& ll
)
750 wxULongLongWx
t(m_hi
, m_lo
);
751 wxULongLongWx
q(ll
.m_hi
, ll
.m_lo
);
755 #ifdef wxLONGLONG_TEST_MODE
756 wxULongLong_t llOld
= m_ll
;
758 #endif // wxLONGLONG_TEST_MODE
763 if ((q
.m_lo
& 1) != 0)
769 while ((counter
< 64) && ((q
.m_hi
!= 0) || (q
.m_lo
!= 0)));
771 #ifdef wxLONGLONG_TEST_MODE
772 m_ll
= llOld
* ll
.m_ll
;
775 #endif // wxLONGLONG_TEST_MODE
782 void wxLongLongWx::Divide(const wxLongLongWx
& divisorIn
,
783 wxLongLongWx
& quotient
,
784 wxLongLongWx
& remainder
) const
786 if ((divisorIn
.m_lo
== 0) && (divisorIn
.m_hi
== 0))
788 // provoke division by zero error and silence the compilers warnings
789 // about an expression without effect and unused variable
790 long dummy
= divisorIn
.m_lo
/divisorIn
.m_hi
;
794 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
795 // do this - any improvements are more than welcome
797 // code inspired by the snippet at
798 // http://www.bearcave.com/software/divide.htm
802 // Use of this program, for any purpose, is granted the author, Ian
803 // Kaplan, as long as this copyright notice is included in the source
804 // code or any source code derived from this program. The user assumes
805 // all responsibility for using this code.
808 wxLongLongWx dividend
= *this,
814 // always do unsigned division and adjust the signs later: in C integer
815 // division, the sign of the remainder is the same as the sign of the
816 // dividend, while the sign of the quotient is the product of the signs of
817 // the dividend and divisor. Of course, we also always have
819 // dividend = quotient*divisor + remainder
821 // with 0 <= abs(remainder) < abs(divisor)
822 bool negRemainder
= dividend
.m_hi
< 0;
823 bool negQuotient
= false; // assume positive
824 if ( dividend
.m_hi
< 0 )
826 negQuotient
= !negQuotient
;
827 dividend
= -dividend
;
829 if ( divisor
.m_hi
< 0 )
831 negQuotient
= !negQuotient
;
835 // check for some particular cases
836 if ( divisor
> dividend
)
838 remainder
= dividend
;
840 else if ( divisor
== dividend
)
846 // here: dividend > divisor and both are positive: do unsigned division
850 #define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1)))
852 while ( remainder
< divisor
)
855 if ( IS_MSB_SET(dividend
) )
866 // undo the last loop iteration
871 for ( size_t i
= 0; i
< nBits
; i
++ )
874 if ( IS_MSB_SET(dividend
) )
879 wxLongLongWx t
= remainder
- divisor
;
882 if ( !IS_MSB_SET(t
) )
894 remainder
= -remainder
;
899 quotient
= -quotient
;
903 void wxULongLongWx::Divide(const wxULongLongWx
& divisorIn
,
904 wxULongLongWx
& quotient
,
905 wxULongLongWx
& remainder
) const
907 if ((divisorIn
.m_lo
== 0) && (divisorIn
.m_hi
== 0))
909 // provoke division by zero error and silence the compilers warnings
910 // about an expression without effect and unused variable
911 unsigned long dummy
= divisorIn
.m_lo
/divisorIn
.m_hi
;
915 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
916 // do this - any improvements are more than welcome
918 // code inspired by the snippet at
919 // http://www.bearcave.com/software/divide.htm
923 // Use of this program, for any purpose, is granted the author, Ian
924 // Kaplan, as long as this copyright notice is included in the source
925 // code or any source code derived from this program. The user assumes
926 // all responsibility for using this code.
929 wxULongLongWx dividend
= *this,
935 // check for some particular cases
936 if ( divisor
> dividend
)
938 remainder
= dividend
;
940 else if ( divisor
== dividend
)
946 // here: dividend > divisor
950 #define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1)))
952 while ( remainder
< divisor
)
955 if ( IS_MSB_SET(dividend
) )
966 // undo the last loop iteration
971 for ( size_t i
= 0; i
< nBits
; i
++ )
974 if ( IS_MSB_SET(dividend
) )
979 wxULongLongWx t
= remainder
- divisor
;
982 if ( !IS_MSB_SET(t
) )
992 wxLongLongWx
wxLongLongWx::operator/(const wxLongLongWx
& ll
) const
994 wxLongLongWx quotient
, remainder
;
996 Divide(ll
, quotient
, remainder
);
1001 wxULongLongWx
wxULongLongWx::operator/(const wxULongLongWx
& ll
) const
1003 wxULongLongWx quotient
, remainder
;
1005 Divide(ll
, quotient
, remainder
);
1010 wxLongLongWx
& wxLongLongWx::operator/=(const wxLongLongWx
& ll
)
1012 wxLongLongWx quotient
, remainder
;
1014 Divide(ll
, quotient
, remainder
);
1021 wxULongLongWx
& wxULongLongWx::operator/=(const wxULongLongWx
& ll
)
1023 wxULongLongWx quotient
, remainder
;
1025 Divide(ll
, quotient
, remainder
);
1032 wxLongLongWx
wxLongLongWx::operator%(const wxLongLongWx
& ll
) const
1034 wxLongLongWx quotient
, remainder
;
1036 Divide(ll
, quotient
, remainder
);
1041 wxULongLongWx
wxULongLongWx::operator%(const wxULongLongWx
& ll
) const
1043 wxULongLongWx quotient
, remainder
;
1045 Divide(ll
, quotient
, remainder
);
1050 // ----------------------------------------------------------------------------
1052 // ----------------------------------------------------------------------------
1054 // temporary - just for testing
1055 void *wxLongLongWx::asArray(void) const
1057 static unsigned char temp
[8];
1059 temp
[0] = (char)((m_hi
>> 24) & 0xFF);
1060 temp
[1] = (char)((m_hi
>> 16) & 0xFF);
1061 temp
[2] = (char)((m_hi
>> 8) & 0xFF);
1062 temp
[3] = (char)((m_hi
>> 0) & 0xFF);
1063 temp
[4] = (char)((m_lo
>> 24) & 0xFF);
1064 temp
[5] = (char)((m_lo
>> 16) & 0xFF);
1065 temp
[6] = (char)((m_lo
>> 8) & 0xFF);
1066 temp
[7] = (char)((m_lo
>> 0) & 0xFF);
1071 void *wxULongLongWx::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 #endif // wxUSE_LONGLONG_WX
1089 #define LL_TO_STRING(name) \
1090 wxString name::ToString() const \
1092 /* TODO: this is awfully inefficient, anything better? */ \
1097 bool neg = ll < 0; \
1102 long digit = (ll % 10).ToLong(); \
1103 result.Prepend((wxChar)(_T('0') - digit)); \
1111 long digit = (ll % 10).ToLong(); \
1112 result.Prepend((wxChar)(_T('0') + digit)); \
1117 if ( result.empty() ) \
1120 result.Prepend(_T('-')); \
1125 #define ULL_TO_STRING(name) \
1126 wxString name::ToString() const \
1128 /* TODO: this is awfully inefficient, anything better? */ \
1135 result.Prepend((wxChar)(_T('0') + (ll % 10).ToULong())); \
1139 if ( result.empty() ) \
1145 #if wxUSE_LONGLONG_NATIVE
1146 LL_TO_STRING(wxLongLongNative
)
1147 ULL_TO_STRING(wxULongLongNative
)
1150 #if wxUSE_LONGLONG_WX
1151 LL_TO_STRING(wxLongLongWx
)
1152 ULL_TO_STRING(wxULongLongWx
)
1155 #if wxUSE_STD_IOSTREAM
1159 wxSTD ostream
& operator<< (wxSTD ostream
& o
, const wxLongLong
& ll
)
1161 return o
<< ll
.ToString();
1165 wxSTD ostream
& operator<< (wxSTD ostream
& o
, const wxULongLong
& ll
)
1167 return o
<< ll
.ToString();
1170 #endif // wxUSE_STD_IOSTREAM
1172 WXDLLIMPEXP_BASE wxString
& operator<< (wxString
& s
, const wxLongLong
& ll
)
1174 return s
<< ll
.ToString();
1177 WXDLLIMPEXP_BASE wxString
& operator<< (wxString
& s
, const wxULongLong
& ll
)
1179 return s
<< ll
.ToString();
1182 #endif // wxUSE_LONGLONG