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 #define IS_MSB_SET(ll) ((ll.GetHi()) & (1 << (8*sizeof(long) - 1)))
784 void wxLongLongWx::Divide(const wxLongLongWx
& divisorIn
,
785 wxLongLongWx
& quotient
,
786 wxLongLongWx
& remainderIO
) const
788 if ((divisorIn
.m_lo
== 0) && (divisorIn
.m_hi
== 0))
790 // provoke division by zero error and silence the compilers warnings
791 // about an expression without effect and unused variable
792 long dummy
= divisorIn
.m_lo
/divisorIn
.m_hi
;
796 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
797 // do this - any improvements are more than welcome
799 // code inspired by the snippet at
800 // http://www.bearcave.com/software/divide.htm
804 // Use of this program, for any purpose, is granted the author, Ian
805 // Kaplan, as long as this copyright notice is included in the source
806 // code or any source code derived from this program. The user assumes
807 // all responsibility for using this code.
810 wxULongLongWx dividend
, divisor
, remainder
;
815 // always do unsigned division and adjust the signs later: in C integer
816 // division, the sign of the remainder is the same as the sign of the
817 // dividend, while the sign of the quotient is the product of the signs of
818 // the dividend and divisor. Of course, we also always have
820 // dividend = quotient*divisor + remainder
822 // with 0 <= abs(remainder) < abs(divisor)
823 bool negRemainder
= GetHi() < 0;
824 bool negQuotient
= false; // assume positive
827 negQuotient
= !negQuotient
;
832 if ( divisorIn
.GetHi() < 0 )
834 negQuotient
= !negQuotient
;
835 divisor
= -divisorIn
;
840 // check for some particular cases
841 if ( divisor
> dividend
)
843 remainder
= dividend
;
845 else if ( divisor
== dividend
)
851 // here: dividend > divisor and both are positive: do unsigned division
855 while ( remainder
< divisor
)
858 if ( IS_MSB_SET(dividend
) )
869 // undo the last loop iteration
874 for ( size_t i
= 0; i
< nBits
; i
++ )
877 if ( IS_MSB_SET(dividend
) )
882 wxLongLongWx t
= remainder
- divisor
;
885 if ( !IS_MSB_SET(t
) )
894 remainderIO
= remainder
;
899 remainderIO
= -remainderIO
;
904 quotient
= -quotient
;
908 void wxULongLongWx::Divide(const wxULongLongWx
& divisorIn
,
909 wxULongLongWx
& quotient
,
910 wxULongLongWx
& remainder
) const
912 if ((divisorIn
.m_lo
== 0) && (divisorIn
.m_hi
== 0))
914 // provoke division by zero error and silence the compilers warnings
915 // about an expression without effect and unused variable
916 unsigned long dummy
= divisorIn
.m_lo
/divisorIn
.m_hi
;
920 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
921 // do this - any improvements are more than welcome
923 // code inspired by the snippet at
924 // http://www.bearcave.com/software/divide.htm
928 // Use of this program, for any purpose, is granted the author, Ian
929 // Kaplan, as long as this copyright notice is included in the source
930 // code or any source code derived from this program. The user assumes
931 // all responsibility for using this code.
934 wxULongLongWx dividend
= *this,
940 // check for some particular cases
941 if ( divisor
> dividend
)
943 remainder
= dividend
;
945 else if ( divisor
== dividend
)
951 // here: dividend > divisor
955 while ( remainder
< divisor
)
958 if ( IS_MSB_SET(dividend
) )
969 // undo the last loop iteration
974 for ( size_t i
= 0; i
< nBits
; i
++ )
977 if ( IS_MSB_SET(dividend
) )
982 wxULongLongWx t
= remainder
- divisor
;
985 if ( !IS_MSB_SET(t
) )
995 wxLongLongWx
wxLongLongWx::operator/(const wxLongLongWx
& ll
) const
997 wxLongLongWx quotient
, remainder
;
999 Divide(ll
, quotient
, remainder
);
1004 wxULongLongWx
wxULongLongWx::operator/(const wxULongLongWx
& ll
) const
1006 wxULongLongWx quotient
, remainder
;
1008 Divide(ll
, quotient
, remainder
);
1013 wxLongLongWx
& wxLongLongWx::operator/=(const wxLongLongWx
& ll
)
1015 wxLongLongWx quotient
, remainder
;
1017 Divide(ll
, quotient
, remainder
);
1024 wxULongLongWx
& wxULongLongWx::operator/=(const wxULongLongWx
& ll
)
1026 wxULongLongWx quotient
, remainder
;
1028 Divide(ll
, quotient
, remainder
);
1035 wxLongLongWx
wxLongLongWx::operator%(const wxLongLongWx
& ll
) const
1037 wxLongLongWx quotient
, remainder
;
1039 Divide(ll
, quotient
, remainder
);
1044 wxULongLongWx
wxULongLongWx::operator%(const wxULongLongWx
& ll
) const
1046 wxULongLongWx quotient
, remainder
;
1048 Divide(ll
, quotient
, remainder
);
1053 // ----------------------------------------------------------------------------
1055 // ----------------------------------------------------------------------------
1057 // temporary - just for testing
1058 void *wxLongLongWx::asArray(void) const
1060 static unsigned char temp
[8];
1062 temp
[0] = (char)((m_hi
>> 24) & 0xFF);
1063 temp
[1] = (char)((m_hi
>> 16) & 0xFF);
1064 temp
[2] = (char)((m_hi
>> 8) & 0xFF);
1065 temp
[3] = (char)((m_hi
>> 0) & 0xFF);
1066 temp
[4] = (char)((m_lo
>> 24) & 0xFF);
1067 temp
[5] = (char)((m_lo
>> 16) & 0xFF);
1068 temp
[6] = (char)((m_lo
>> 8) & 0xFF);
1069 temp
[7] = (char)((m_lo
>> 0) & 0xFF);
1074 void *wxULongLongWx::asArray(void) const
1076 static unsigned char temp
[8];
1078 temp
[0] = (char)((m_hi
>> 24) & 0xFF);
1079 temp
[1] = (char)((m_hi
>> 16) & 0xFF);
1080 temp
[2] = (char)((m_hi
>> 8) & 0xFF);
1081 temp
[3] = (char)((m_hi
>> 0) & 0xFF);
1082 temp
[4] = (char)((m_lo
>> 24) & 0xFF);
1083 temp
[5] = (char)((m_lo
>> 16) & 0xFF);
1084 temp
[6] = (char)((m_lo
>> 8) & 0xFF);
1085 temp
[7] = (char)((m_lo
>> 0) & 0xFF);
1090 #endif // wxUSE_LONGLONG_WX
1092 #define LL_TO_STRING(name) \
1093 wxString name::ToString() const \
1095 /* TODO: this is awfully inefficient, anything better? */ \
1100 bool neg = ll < 0; \
1105 long digit = (ll % 10).ToLong(); \
1106 result.Prepend((wxChar)(_T('0') - digit)); \
1114 long digit = (ll % 10).ToLong(); \
1115 result.Prepend((wxChar)(_T('0') + digit)); \
1120 if ( result.empty() ) \
1123 result.Prepend(_T('-')); \
1128 #define ULL_TO_STRING(name) \
1129 wxString name::ToString() const \
1131 /* TODO: this is awfully inefficient, anything better? */ \
1138 result.Prepend((wxChar)(_T('0') + (ll % 10).ToULong())); \
1142 if ( result.empty() ) \
1148 #if wxUSE_LONGLONG_NATIVE
1149 LL_TO_STRING(wxLongLongNative
)
1150 ULL_TO_STRING(wxULongLongNative
)
1153 #if wxUSE_LONGLONG_WX
1154 LL_TO_STRING(wxLongLongWx
)
1155 ULL_TO_STRING(wxULongLongWx
)
1158 #if wxUSE_STD_IOSTREAM
1162 wxSTD ostream
& operator<< (wxSTD ostream
& o
, const wxLongLong
& ll
)
1164 return o
<< ll
.ToString();
1168 wxSTD ostream
& operator<< (wxSTD ostream
& o
, const wxULongLong
& ll
)
1170 return o
<< ll
.ToString();
1173 #endif // wxUSE_STD_IOSTREAM
1175 WXDLLIMPEXP_BASE wxString
& operator<< (wxString
& s
, const wxLongLong
& ll
)
1177 return s
<< ll
.ToString();
1180 WXDLLIMPEXP_BASE wxString
& operator<< (wxString
& s
, const wxULongLong
& ll
)
1182 return s
<< ll
.ToString();
1185 #endif // wxUSE_LONGLONG