]>
git.saurik.com Git - wxWidgets.git/blob - src/common/longlong.cpp
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 // ============================================================================
40 // ============================================================================
42 #if wxUSE_LONGLONG_NATIVE
44 // ----------------------------------------------------------------------------
46 // ----------------------------------------------------------------------------
48 void *wxLongLongNative::asArray() const
50 static unsigned char temp
[8];
52 temp
[0] = (unsigned char)((m_ll
>> 56) & 0xFF);
53 temp
[1] = (unsigned char)((m_ll
>> 48) & 0xFF);
54 temp
[2] = (unsigned char)((m_ll
>> 40) & 0xFF);
55 temp
[3] = (unsigned char)((m_ll
>> 32) & 0xFF);
56 temp
[4] = (unsigned char)((m_ll
>> 24) & 0xFF);
57 temp
[5] = (unsigned char)((m_ll
>> 16) & 0xFF);
58 temp
[6] = (unsigned char)((m_ll
>> 8) & 0xFF);
59 temp
[7] = (unsigned char)((m_ll
>> 0) & 0xFF);
64 void *wxULongLongNative::asArray() const
66 static unsigned char temp
[8];
68 temp
[0] = (unsigned char)((m_ll
>> 56) & 0xFF);
69 temp
[1] = (unsigned char)((m_ll
>> 48) & 0xFF);
70 temp
[2] = (unsigned char)((m_ll
>> 40) & 0xFF);
71 temp
[3] = (unsigned char)((m_ll
>> 32) & 0xFF);
72 temp
[4] = (unsigned char)((m_ll
>> 24) & 0xFF);
73 temp
[5] = (unsigned char)((m_ll
>> 16) & 0xFF);
74 temp
[6] = (unsigned char)((m_ll
>> 8) & 0xFF);
75 temp
[7] = (unsigned char)((m_ll
>> 0) & 0xFF);
81 wxLongLongNative::wxLongLongNative(wxLongLongWx ll
)
83 // assign first to avoid precision loss!
89 wxLongLongNative
& wxLongLongNative::operator=(wxLongLongWx ll
)
91 // assign first to avoid precision loss!
99 #endif // wxUSE_LONGLONG_NATIVE
101 // ============================================================================
102 // wxLongLongWx: emulation of 'long long' using 2 longs
103 // ============================================================================
105 #if wxUSE_LONGLONG_WX
108 wxLongLongWx
& wxLongLongWx::Assign(double d
)
110 bool positive
= d
>= 0;
112 if ( d
<= ULONG_MAX
)
119 m_hi
= (unsigned long)(d
/ (1.0 + (double)ULONG_MAX
));
120 m_lo
= (unsigned long)(d
- ((double)m_hi
* (1.0 + (double)ULONG_MAX
)));
123 #ifdef wxLONGLONG_TEST_MODE
124 m_ll
= (wxLongLong_t
)d
;
127 #endif // wxLONGLONG_TEST_MODE
135 wxLongLongWx
wxLongLongWx::operator<<(int shift
) const
137 wxLongLongWx
ll(*this);
143 wxULongLongWx
wxULongLongWx::operator<<(int shift
) const
145 wxULongLongWx
ll(*this);
151 wxLongLongWx
& wxLongLongWx::operator<<=(int shift
)
158 m_hi
|= m_lo
>> (32 - shift
);
163 m_hi
= m_lo
<< (shift
- 32);
168 #ifdef wxLONGLONG_TEST_MODE
172 #endif // wxLONGLONG_TEST_MODE
177 wxULongLongWx
& wxULongLongWx::operator<<=(int shift
)
184 m_hi
|= m_lo
>> (32 - shift
);
189 m_hi
= m_lo
<< (shift
- 32);
194 #ifdef wxLONGLONG_TEST_MODE
198 #endif // wxLONGLONG_TEST_MODE
203 wxLongLongWx
wxLongLongWx::operator>>(int shift
) const
205 wxLongLongWx
ll(*this);
211 wxULongLongWx
wxULongLongWx::operator>>(int shift
) const
213 wxULongLongWx
ll(*this);
219 wxLongLongWx
& wxLongLongWx::operator>>=(int shift
)
226 m_lo
|= m_hi
<< (32 - shift
);
231 m_lo
= m_hi
>> (shift
- 32);
232 m_hi
= (m_hi
< 0 ? -1L : 0);
236 #ifdef wxLONGLONG_TEST_MODE
240 #endif // wxLONGLONG_TEST_MODE
245 wxULongLongWx
& wxULongLongWx::operator>>=(int shift
)
252 m_lo
|= m_hi
<< (32 - shift
);
257 m_lo
= m_hi
>> (shift
- 32);
262 #ifdef wxLONGLONG_TEST_MODE
266 #endif // wxLONGLONG_TEST_MODE
271 wxLongLongWx
wxLongLongWx::operator+(const wxLongLongWx
& ll
) const
273 wxLongLongWx
res(*this);
279 wxULongLongWx
wxULongLongWx::operator+(const wxULongLongWx
& ll
) const
281 wxULongLongWx
res(*this);
287 wxLongLongWx
wxLongLongWx::operator+(long l
) const
289 wxLongLongWx
res(*this);
295 wxULongLongWx
wxULongLongWx::operator+(unsigned long l
) const
297 wxULongLongWx
res(*this);
303 wxLongLongWx
& wxLongLongWx::operator+=(const wxLongLongWx
& ll
)
305 unsigned long previous
= m_lo
;
310 if ((m_lo
< previous
) || (m_lo
< ll
.m_lo
))
313 #ifdef wxLONGLONG_TEST_MODE
317 #endif // wxLONGLONG_TEST_MODE
322 wxULongLongWx
& wxULongLongWx::operator+=(const wxULongLongWx
& ll
)
324 unsigned long previous
= m_lo
;
329 if ((m_lo
< previous
) || (m_lo
< ll
.m_lo
))
332 #ifdef wxLONGLONG_TEST_MODE
336 #endif // wxLONGLONG_TEST_MODE
341 wxLongLongWx
& wxLongLongWx::operator+=(long l
)
343 unsigned long previous
= m_lo
;
349 if ((m_lo
< previous
) || (m_lo
< (unsigned long)l
))
352 #ifdef wxLONGLONG_TEST_MODE
356 #endif // wxLONGLONG_TEST_MODE
361 wxULongLongWx
& wxULongLongWx::operator+=(unsigned long l
)
363 unsigned long previous
= m_lo
;
367 if ((m_lo
< previous
) || (m_lo
< l
))
370 #ifdef wxLONGLONG_TEST_MODE
374 #endif // wxLONGLONG_TEST_MODE
380 wxLongLongWx
& wxLongLongWx::operator++()
386 #ifdef wxLONGLONG_TEST_MODE
390 #endif // wxLONGLONG_TEST_MODE
395 wxULongLongWx
& wxULongLongWx::operator++()
401 #ifdef wxLONGLONG_TEST_MODE
405 #endif // wxLONGLONG_TEST_MODE
411 wxLongLongWx
wxLongLongWx::operator-() const
413 wxLongLongWx
res(*this);
419 wxLongLongWx
& wxLongLongWx::Negate()
428 #ifdef wxLONGLONG_TEST_MODE
432 #endif // wxLONGLONG_TEST_MODE
439 wxLongLongWx
wxLongLongWx::operator-(const wxLongLongWx
& ll
) const
441 wxLongLongWx
res(*this);
447 wxLongLongWx
wxULongLongWx::operator-(const wxULongLongWx
& ll
) const
449 wxASSERT(m_hi
<= LONG_MAX
);
450 wxASSERT(ll
.m_hi
<= LONG_MAX
);
452 wxLongLongWx
res( (long)m_hi
, m_lo
);
453 wxLongLongWx
op( (long)ll
.m_hi
, ll
.m_lo
);
459 wxLongLongWx
& wxLongLongWx::operator-=(const wxLongLongWx
& ll
)
461 unsigned long previous
= m_lo
;
466 if (previous
< ll
.m_lo
)
469 #ifdef wxLONGLONG_TEST_MODE
473 #endif // wxLONGLONG_TEST_MODE
478 wxULongLongWx
& wxULongLongWx::operator-=(const wxULongLongWx
& ll
)
480 unsigned long previous
= m_lo
;
485 if (previous
< ll
.m_lo
)
488 #ifdef wxLONGLONG_TEST_MODE
492 #endif // wxLONGLONG_TEST_MODE
498 wxLongLongWx
& wxLongLongWx::operator--()
501 if (m_lo
== 0xFFFFFFFF)
504 #ifdef wxLONGLONG_TEST_MODE
508 #endif // wxLONGLONG_TEST_MODE
513 wxULongLongWx
& wxULongLongWx::operator--()
516 if (m_lo
== 0xFFFFFFFF)
519 #ifdef wxLONGLONG_TEST_MODE
523 #endif // wxLONGLONG_TEST_MODE
528 // comparison operators
530 bool wxLongLongWx::operator<(const wxLongLongWx
& ll
) const
532 if ( m_hi
< ll
.m_hi
)
534 else if ( m_hi
== ll
.m_hi
)
535 return m_lo
< ll
.m_lo
;
540 bool wxULongLongWx::operator<(const wxULongLongWx
& ll
) const
542 if ( m_hi
< ll
.m_hi
)
544 else if ( m_hi
== ll
.m_hi
)
545 return m_lo
< ll
.m_lo
;
550 bool wxLongLongWx::operator>(const wxLongLongWx
& ll
) const
552 if ( m_hi
> ll
.m_hi
)
554 else if ( m_hi
== ll
.m_hi
)
555 return m_lo
> ll
.m_lo
;
560 bool wxULongLongWx::operator>(const wxULongLongWx
& ll
) const
562 if ( m_hi
> ll
.m_hi
)
564 else if ( m_hi
== ll
.m_hi
)
565 return m_lo
> ll
.m_lo
;
572 wxLongLongWx
wxLongLongWx::operator&(const wxLongLongWx
& ll
) const
574 return wxLongLongWx(m_hi
& ll
.m_hi
, m_lo
& ll
.m_lo
);
577 wxULongLongWx
wxULongLongWx::operator&(const wxULongLongWx
& ll
) const
579 return wxULongLongWx(m_hi
& ll
.m_hi
, m_lo
& ll
.m_lo
);
582 wxLongLongWx
wxLongLongWx::operator|(const wxLongLongWx
& ll
) const
584 return wxLongLongWx(m_hi
| ll
.m_hi
, m_lo
| ll
.m_lo
);
587 wxULongLongWx
wxULongLongWx::operator|(const wxULongLongWx
& ll
) const
589 return wxULongLongWx(m_hi
| ll
.m_hi
, m_lo
| ll
.m_lo
);
592 wxLongLongWx
wxLongLongWx::operator^(const wxLongLongWx
& ll
) const
594 return wxLongLongWx(m_hi
^ ll
.m_hi
, m_lo
^ ll
.m_lo
);
597 wxULongLongWx
wxULongLongWx::operator^(const wxULongLongWx
& ll
) const
599 return wxULongLongWx(m_hi
^ ll
.m_hi
, m_lo
^ ll
.m_lo
);
602 wxLongLongWx
& wxLongLongWx::operator&=(const wxLongLongWx
& ll
)
607 #ifdef wxLONGLONG_TEST_MODE
611 #endif // wxLONGLONG_TEST_MODE
616 wxULongLongWx
& wxULongLongWx::operator&=(const wxULongLongWx
& ll
)
621 #ifdef wxLONGLONG_TEST_MODE
625 #endif // wxLONGLONG_TEST_MODE
630 wxLongLongWx
& wxLongLongWx::operator|=(const wxLongLongWx
& ll
)
635 #ifdef wxLONGLONG_TEST_MODE
639 #endif // wxLONGLONG_TEST_MODE
644 wxULongLongWx
& wxULongLongWx::operator|=(const wxULongLongWx
& ll
)
649 #ifdef wxLONGLONG_TEST_MODE
653 #endif // wxLONGLONG_TEST_MODE
658 wxLongLongWx
& wxLongLongWx::operator^=(const wxLongLongWx
& ll
)
663 #ifdef wxLONGLONG_TEST_MODE
667 #endif // wxLONGLONG_TEST_MODE
672 wxULongLongWx
& wxULongLongWx::operator^=(const wxULongLongWx
& ll
)
677 #ifdef wxLONGLONG_TEST_MODE
681 #endif // wxLONGLONG_TEST_MODE
686 wxLongLongWx
wxLongLongWx::operator~() const
688 return wxLongLongWx(~m_hi
, ~m_lo
);
691 wxULongLongWx
wxULongLongWx::operator~() const
693 return wxULongLongWx(~m_hi
, ~m_lo
);
698 wxLongLongWx
wxLongLongWx::operator*(const wxLongLongWx
& ll
) const
700 wxLongLongWx
res(*this);
706 wxULongLongWx
wxULongLongWx::operator*(const wxULongLongWx
& ll
) const
708 wxULongLongWx
res(*this);
714 wxLongLongWx
& wxLongLongWx::operator*=(const wxLongLongWx
& ll
)
716 wxLongLongWx
t(m_hi
, m_lo
);
717 wxLongLongWx
q(ll
.m_hi
, ll
.m_lo
);
721 #ifdef wxLONGLONG_TEST_MODE
722 wxLongLong_t llOld
= m_ll
;
724 #endif // wxLONGLONG_TEST_MODE
729 if ((q
.m_lo
& 1) != 0)
735 while ((counter
< 64) && ((q
.m_hi
!= 0) || (q
.m_lo
!= 0)));
737 #ifdef wxLONGLONG_TEST_MODE
738 m_ll
= llOld
* ll
.m_ll
;
741 #endif // wxLONGLONG_TEST_MODE
746 wxULongLongWx
& wxULongLongWx::operator*=(const wxULongLongWx
& ll
)
748 wxULongLongWx
t(m_hi
, m_lo
);
749 wxULongLongWx
q(ll
.m_hi
, ll
.m_lo
);
753 #ifdef wxLONGLONG_TEST_MODE
754 unsigned wxLongLong_t llOld
= m_ll
;
756 #endif // wxLONGLONG_TEST_MODE
761 if ((q
.m_lo
& 1) != 0)
767 while ((counter
< 64) && ((q
.m_hi
!= 0) || (q
.m_lo
!= 0)));
769 #ifdef wxLONGLONG_TEST_MODE
770 m_ll
= llOld
* ll
.m_ll
;
773 #endif // wxLONGLONG_TEST_MODE
780 void wxLongLongWx::Divide(const wxLongLongWx
& divisorIn
,
781 wxLongLongWx
& quotient
,
782 wxLongLongWx
& remainder
) const
784 if ((divisorIn
.m_lo
== 0) && (divisorIn
.m_hi
== 0))
786 // provoke division by zero error and silence the compilers warnings
787 // about an expression without effect and unused variable
788 long dummy
= divisorIn
.m_lo
/divisorIn
.m_hi
;
792 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
793 // do this - any improvements are more than welcome
795 // code inspired by the snippet at
796 // http://www.bearcave.com/software/divide.htm
800 // Use of this program, for any purpose, is granted the author, Ian
801 // Kaplan, as long as this copyright notice is included in the source
802 // code or any source code derived from this program. The user assumes
803 // all responsibility for using this code.
806 wxLongLongWx dividend
= *this,
812 // always do unsigned division and adjust the signs later: in C integer
813 // division, the sign of the remainder is the same as the sign of the
814 // dividend, while the sign of the quotient is the product of the signs of
815 // the dividend and divisor. Of course, we also always have
817 // dividend = quotient*divisor + remainder
819 // with 0 <= abs(remainder) < abs(divisor)
820 bool negRemainder
= dividend
.m_hi
< 0;
821 bool negQuotient
= false; // assume positive
822 if ( dividend
.m_hi
< 0 )
824 negQuotient
= !negQuotient
;
825 dividend
= -dividend
;
827 if ( divisor
.m_hi
< 0 )
829 negQuotient
= !negQuotient
;
833 // check for some particular cases
834 if ( divisor
> dividend
)
836 remainder
= dividend
;
838 else if ( divisor
== dividend
)
844 // here: dividend > divisor and both are positive: do unsigned division
848 #define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1)))
850 while ( remainder
< divisor
)
853 if ( IS_MSB_SET(dividend
) )
864 // undo the last loop iteration
869 for ( size_t i
= 0; i
< nBits
; i
++ )
872 if ( IS_MSB_SET(dividend
) )
877 wxLongLongWx t
= remainder
- divisor
;
880 if ( !IS_MSB_SET(t
) )
892 remainder
= -remainder
;
897 quotient
= -quotient
;
901 void wxULongLongWx::Divide(const wxULongLongWx
& divisorIn
,
902 wxULongLongWx
& quotient
,
903 wxULongLongWx
& remainder
) const
905 if ((divisorIn
.m_lo
== 0) && (divisorIn
.m_hi
== 0))
907 // provoke division by zero error and silence the compilers warnings
908 // about an expression without effect and unused variable
909 unsigned long dummy
= divisorIn
.m_lo
/divisorIn
.m_hi
;
913 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
914 // do this - any improvements are more than welcome
916 // code inspired by the snippet at
917 // http://www.bearcave.com/software/divide.htm
921 // Use of this program, for any purpose, is granted the author, Ian
922 // Kaplan, as long as this copyright notice is included in the source
923 // code or any source code derived from this program. The user assumes
924 // all responsibility for using this code.
927 wxULongLongWx dividend
= *this,
933 // check for some particular cases
934 if ( divisor
> dividend
)
936 remainder
= dividend
;
938 else if ( divisor
== dividend
)
944 // here: dividend > divisor
948 #define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1)))
950 while ( remainder
< divisor
)
953 if ( IS_MSB_SET(dividend
) )
964 // undo the last loop iteration
969 for ( size_t i
= 0; i
< nBits
; i
++ )
972 if ( IS_MSB_SET(dividend
) )
977 wxULongLongWx t
= remainder
- divisor
;
980 if ( !IS_MSB_SET(t
) )
990 wxLongLongWx
wxLongLongWx::operator/(const wxLongLongWx
& ll
) const
992 wxLongLongWx quotient
, remainder
;
994 Divide(ll
, quotient
, remainder
);
999 wxULongLongWx
wxULongLongWx::operator/(const wxULongLongWx
& ll
) const
1001 wxULongLongWx quotient
, remainder
;
1003 Divide(ll
, quotient
, remainder
);
1008 wxLongLongWx
& wxLongLongWx::operator/=(const wxLongLongWx
& ll
)
1010 wxLongLongWx quotient
, remainder
;
1012 Divide(ll
, quotient
, remainder
);
1019 wxULongLongWx
& wxULongLongWx::operator/=(const wxULongLongWx
& ll
)
1021 wxULongLongWx quotient
, remainder
;
1023 Divide(ll
, quotient
, remainder
);
1030 wxLongLongWx
wxLongLongWx::operator%(const wxLongLongWx
& ll
) const
1032 wxLongLongWx quotient
, remainder
;
1034 Divide(ll
, quotient
, remainder
);
1039 wxULongLongWx
wxULongLongWx::operator%(const wxULongLongWx
& ll
) const
1041 wxULongLongWx quotient
, remainder
;
1043 Divide(ll
, quotient
, remainder
);
1048 // ----------------------------------------------------------------------------
1050 // ----------------------------------------------------------------------------
1052 // temporary - just for testing
1053 void *wxLongLongWx::asArray(void) const
1055 static unsigned char temp
[8];
1057 temp
[0] = (char)((m_hi
>> 24) & 0xFF);
1058 temp
[1] = (char)((m_hi
>> 16) & 0xFF);
1059 temp
[2] = (char)((m_hi
>> 8) & 0xFF);
1060 temp
[3] = (char)((m_hi
>> 0) & 0xFF);
1061 temp
[4] = (char)((m_lo
>> 24) & 0xFF);
1062 temp
[5] = (char)((m_lo
>> 16) & 0xFF);
1063 temp
[6] = (char)((m_lo
>> 8) & 0xFF);
1064 temp
[7] = (char)((m_lo
>> 0) & 0xFF);
1069 void *wxULongLongWx::asArray(void) const
1071 static unsigned char temp
[8];
1073 temp
[0] = (char)((m_hi
>> 24) & 0xFF);
1074 temp
[1] = (char)((m_hi
>> 16) & 0xFF);
1075 temp
[2] = (char)((m_hi
>> 8) & 0xFF);
1076 temp
[3] = (char)((m_hi
>> 0) & 0xFF);
1077 temp
[4] = (char)((m_lo
>> 24) & 0xFF);
1078 temp
[5] = (char)((m_lo
>> 16) & 0xFF);
1079 temp
[6] = (char)((m_lo
>> 8) & 0xFF);
1080 temp
[7] = (char)((m_lo
>> 0) & 0xFF);
1085 #endif // wxUSE_LONGLONG_WX
1087 #define LL_TO_STRING(name) \
1088 wxString name::ToString() const \
1090 /* TODO: this is awfully inefficient, anything better? */ \
1108 result.Prepend((wxChar)(_T('0') + (ll % 10).ToLong())); \
1112 if ( result.empty() ) \
1115 result.Prepend(_T('-')); \
1120 #define ULL_TO_STRING(name) \
1121 wxString name::ToString() const \
1123 /* TODO: this is awfully inefficient, anything better? */ \
1130 result.Prepend((wxChar)(_T('0') + (ll % 10).ToULong())); \
1134 if ( result.empty() ) \
1140 #if wxUSE_LONGLONG_NATIVE
1141 LL_TO_STRING(wxLongLongNative
)
1142 ULL_TO_STRING(wxULongLongNative
)
1145 #if wxUSE_LONGLONG_WX
1146 LL_TO_STRING(wxLongLongWx
)
1147 ULL_TO_STRING(wxULongLongWx
)
1150 #if wxUSE_STD_IOSTREAM
1153 wxSTD ostream
& operator<< (wxSTD ostream
& o
, const wxLongLong
& ll
)
1155 return o
<< ll
.ToString();
1158 wxSTD ostream
& operator<< (wxSTD ostream
& o
, const wxULongLong
& ll
)
1160 return o
<< ll
.ToString();
1163 #endif // wxUSE_STD_IOSTREAM
1165 wxString
& operator<< (wxString
& s
, const wxLongLong
& ll
)
1167 return s
<< ll
.ToString();
1170 wxString
& operator<< (wxString
& s
, const wxULongLong
& ll
)
1172 return s
<< ll
.ToString();
1175 #endif // wxUSE_LONGLONG