]>
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"
31 #if defined(__MWERKS__) && defined(__WXMSW__)
32 #include <string.h> // for memset()
34 #include <memory.h> // for memset()
37 #include <math.h> // for fabs()
39 // ============================================================================
41 // ============================================================================
43 #if wxUSE_LONGLONG_NATIVE
45 // ----------------------------------------------------------------------------
47 // ----------------------------------------------------------------------------
49 void *wxLongLongNative::asArray() const
51 static unsigned char temp
[8];
53 temp
[0] = (unsigned char)((m_ll
>> 56) & 0xFF);
54 temp
[1] = (unsigned char)((m_ll
>> 48) & 0xFF);
55 temp
[2] = (unsigned char)((m_ll
>> 40) & 0xFF);
56 temp
[3] = (unsigned char)((m_ll
>> 32) & 0xFF);
57 temp
[4] = (unsigned char)((m_ll
>> 24) & 0xFF);
58 temp
[5] = (unsigned char)((m_ll
>> 16) & 0xFF);
59 temp
[6] = (unsigned char)((m_ll
>> 8) & 0xFF);
60 temp
[7] = (unsigned char)((m_ll
>> 0) & 0xFF);
65 void *wxULongLongNative::asArray() const
67 static unsigned char temp
[8];
69 temp
[0] = (unsigned char)((m_ll
>> 56) & 0xFF);
70 temp
[1] = (unsigned char)((m_ll
>> 48) & 0xFF);
71 temp
[2] = (unsigned char)((m_ll
>> 40) & 0xFF);
72 temp
[3] = (unsigned char)((m_ll
>> 32) & 0xFF);
73 temp
[4] = (unsigned char)((m_ll
>> 24) & 0xFF);
74 temp
[5] = (unsigned char)((m_ll
>> 16) & 0xFF);
75 temp
[6] = (unsigned char)((m_ll
>> 8) & 0xFF);
76 temp
[7] = (unsigned char)((m_ll
>> 0) & 0xFF);
81 #endif // wxUSE_LONGLONG_NATIVE
83 // ============================================================================
84 // wxLongLongWx: emulation of 'long long' using 2 longs
85 // ============================================================================
90 wxLongLongWx
& wxLongLongWx::Assign(double d
)
92 bool positive
= d
>= 0;
101 m_hi
= (unsigned long)(d
/ (1.0 + (double)ULONG_MAX
));
102 m_lo
= (unsigned long)(d
- ((double)m_hi
* (1.0 + (double)ULONG_MAX
)));
105 #ifdef wxLONGLONG_TEST_MODE
106 m_ll
= (wxLongLong_t
)d
;
109 #endif // wxLONGLONG_TEST_MODE
117 wxLongLongWx
wxLongLongWx::operator<<(int shift
) const
119 wxLongLongWx
ll(*this);
125 wxULongLongWx
wxULongLongWx::operator<<(int shift
) const
127 wxULongLongWx
ll(*this);
133 wxLongLongWx
& wxLongLongWx::operator<<=(int shift
)
140 m_hi
|= m_lo
>> (32 - shift
);
145 m_hi
= m_lo
<< (shift
- 32);
150 #ifdef wxLONGLONG_TEST_MODE
154 #endif // wxLONGLONG_TEST_MODE
159 wxULongLongWx
& wxULongLongWx::operator<<=(int shift
)
166 m_hi
|= m_lo
>> (32 - shift
);
171 m_hi
= m_lo
<< (shift
- 32);
176 #ifdef wxLONGLONG_TEST_MODE
180 #endif // wxLONGLONG_TEST_MODE
185 wxLongLongWx
wxLongLongWx::operator>>(int shift
) const
187 wxLongLongWx
ll(*this);
193 wxULongLongWx
wxULongLongWx::operator>>(int shift
) const
195 wxULongLongWx
ll(*this);
201 wxLongLongWx
& wxLongLongWx::operator>>=(int shift
)
208 m_lo
|= m_hi
<< (32 - shift
);
213 m_lo
= m_hi
>> (shift
- 32);
214 m_hi
= (m_hi
< 0 ? -1L : 0);
218 #ifdef wxLONGLONG_TEST_MODE
222 #endif // wxLONGLONG_TEST_MODE
227 wxULongLongWx
& wxULongLongWx::operator>>=(int shift
)
234 m_lo
|= m_hi
<< (32 - shift
);
239 m_lo
= m_hi
>> (shift
- 32);
244 #ifdef wxLONGLONG_TEST_MODE
248 #endif // wxLONGLONG_TEST_MODE
253 wxLongLongWx
wxLongLongWx::operator+(const wxLongLongWx
& ll
) const
255 wxLongLongWx
res(*this);
261 wxULongLongWx
wxULongLongWx::operator+(const wxULongLongWx
& ll
) const
263 wxULongLongWx
res(*this);
269 wxLongLongWx
wxLongLongWx::operator+(long l
) const
271 wxLongLongWx
res(*this);
277 wxULongLongWx
wxULongLongWx::operator+(unsigned long l
) const
279 wxULongLongWx
res(*this);
285 wxLongLongWx
& wxLongLongWx::operator+=(const wxLongLongWx
& ll
)
287 unsigned long previous
= m_lo
;
292 if ((m_lo
< previous
) || (m_lo
< ll
.m_lo
))
295 #ifdef wxLONGLONG_TEST_MODE
299 #endif // wxLONGLONG_TEST_MODE
304 wxULongLongWx
& wxULongLongWx::operator+=(const wxULongLongWx
& ll
)
306 unsigned long previous
= m_lo
;
311 if ((m_lo
< previous
) || (m_lo
< ll
.m_lo
))
314 #ifdef wxLONGLONG_TEST_MODE
318 #endif // wxLONGLONG_TEST_MODE
323 wxLongLongWx
& wxLongLongWx::operator+=(long l
)
325 unsigned long previous
= m_lo
;
331 if ((m_lo
< previous
) || (m_lo
< (unsigned long)l
))
334 #ifdef wxLONGLONG_TEST_MODE
338 #endif // wxLONGLONG_TEST_MODE
343 wxULongLongWx
& wxULongLongWx::operator+=(unsigned long l
)
345 unsigned long previous
= m_lo
;
349 if ((m_lo
< previous
) || (m_lo
< l
))
352 #ifdef wxLONGLONG_TEST_MODE
356 #endif // wxLONGLONG_TEST_MODE
362 wxLongLongWx
& wxLongLongWx::operator++()
368 #ifdef wxLONGLONG_TEST_MODE
372 #endif // wxLONGLONG_TEST_MODE
377 wxULongLongWx
& wxULongLongWx::operator++()
383 #ifdef wxLONGLONG_TEST_MODE
387 #endif // wxLONGLONG_TEST_MODE
393 wxLongLongWx
wxLongLongWx::operator-() const
395 wxLongLongWx
res(*this);
401 wxLongLongWx
& wxLongLongWx::Negate()
410 #ifdef wxLONGLONG_TEST_MODE
414 #endif // wxLONGLONG_TEST_MODE
421 wxLongLongWx
wxLongLongWx::operator-(const wxLongLongWx
& ll
) const
423 wxLongLongWx
res(*this);
429 wxULongLongWx
wxULongLongWx::operator-(const wxULongLongWx
& ll
) const
431 wxULongLongWx
res(*this);
437 wxLongLongWx
& wxLongLongWx::operator-=(const wxLongLongWx
& ll
)
439 unsigned long previous
= m_lo
;
444 if (previous
< ll
.m_lo
)
447 #ifdef wxLONGLONG_TEST_MODE
451 #endif // wxLONGLONG_TEST_MODE
456 wxULongLongWx
& wxULongLongWx::operator-=(const wxULongLongWx
& ll
)
458 unsigned long previous
= m_lo
;
463 if (previous
< ll
.m_lo
)
466 #ifdef wxLONGLONG_TEST_MODE
470 #endif // wxLONGLONG_TEST_MODE
476 wxLongLongWx
& wxLongLongWx::operator--()
479 if (m_lo
== 0xFFFFFFFF)
482 #ifdef wxLONGLONG_TEST_MODE
486 #endif // wxLONGLONG_TEST_MODE
491 wxULongLongWx
& wxULongLongWx::operator--()
494 if (m_lo
== 0xFFFFFFFF)
497 #ifdef wxLONGLONG_TEST_MODE
501 #endif // wxLONGLONG_TEST_MODE
506 // comparison operators
508 bool wxLongLongWx::operator<(const wxLongLongWx
& ll
) const
510 if ( m_hi
< ll
.m_hi
)
512 else if ( m_hi
== ll
.m_hi
)
513 return m_lo
< ll
.m_lo
;
518 bool wxULongLongWx::operator<(const wxULongLongWx
& ll
) const
520 if ( m_hi
< ll
.m_hi
)
522 else if ( m_hi
== ll
.m_hi
)
523 return m_lo
< ll
.m_lo
;
528 bool wxLongLongWx::operator>(const wxLongLongWx
& ll
) const
530 if ( m_hi
> ll
.m_hi
)
532 else if ( m_hi
== ll
.m_hi
)
533 return m_lo
> ll
.m_lo
;
538 bool wxULongLongWx::operator>(const wxULongLongWx
& ll
) const
540 if ( m_hi
> ll
.m_hi
)
542 else if ( m_hi
== ll
.m_hi
)
543 return m_lo
> ll
.m_lo
;
550 wxLongLongWx
wxLongLongWx::operator&(const wxLongLongWx
& ll
) const
552 return wxLongLongWx(m_hi
& ll
.m_hi
, m_lo
& ll
.m_lo
);
555 wxULongLongWx
wxULongLongWx::operator&(const wxULongLongWx
& ll
) const
557 return wxULongLongWx(m_hi
& ll
.m_hi
, m_lo
& ll
.m_lo
);
560 wxLongLongWx
wxLongLongWx::operator|(const wxLongLongWx
& ll
) const
562 return wxLongLongWx(m_hi
| ll
.m_hi
, m_lo
| ll
.m_lo
);
565 wxULongLongWx
wxULongLongWx::operator|(const wxULongLongWx
& ll
) const
567 return wxULongLongWx(m_hi
| ll
.m_hi
, m_lo
| ll
.m_lo
);
570 wxLongLongWx
wxLongLongWx::operator^(const wxLongLongWx
& ll
) const
572 return wxLongLongWx(m_hi
^ ll
.m_hi
, m_lo
^ ll
.m_lo
);
575 wxULongLongWx
wxULongLongWx::operator^(const wxULongLongWx
& ll
) const
577 return wxULongLongWx(m_hi
^ ll
.m_hi
, m_lo
^ ll
.m_lo
);
580 wxLongLongWx
& wxLongLongWx::operator&=(const wxLongLongWx
& ll
)
585 #ifdef wxLONGLONG_TEST_MODE
589 #endif // wxLONGLONG_TEST_MODE
594 wxULongLongWx
& wxULongLongWx::operator&=(const wxULongLongWx
& ll
)
599 #ifdef wxLONGLONG_TEST_MODE
603 #endif // wxLONGLONG_TEST_MODE
608 wxLongLongWx
& wxLongLongWx::operator|=(const wxLongLongWx
& ll
)
613 #ifdef wxLONGLONG_TEST_MODE
617 #endif // wxLONGLONG_TEST_MODE
622 wxULongLongWx
& wxULongLongWx::operator|=(const wxULongLongWx
& ll
)
627 #ifdef wxLONGLONG_TEST_MODE
631 #endif // wxLONGLONG_TEST_MODE
636 wxLongLongWx
& wxLongLongWx::operator^=(const wxLongLongWx
& ll
)
641 #ifdef wxLONGLONG_TEST_MODE
645 #endif // wxLONGLONG_TEST_MODE
650 wxULongLongWx
& wxULongLongWx::operator^=(const wxULongLongWx
& ll
)
655 #ifdef wxLONGLONG_TEST_MODE
659 #endif // wxLONGLONG_TEST_MODE
664 wxLongLongWx
wxLongLongWx::operator~() const
666 return wxLongLongWx(~m_hi
, ~m_lo
);
669 wxULongLongWx
wxULongLongWx::operator~() const
671 return wxULongLongWx(~m_hi
, ~m_lo
);
676 wxLongLongWx
wxLongLongWx::operator*(const wxLongLongWx
& ll
) const
678 wxLongLongWx
res(*this);
684 wxULongLongWx
wxULongLongWx::operator*(const wxULongLongWx
& ll
) const
686 wxULongLongWx
res(*this);
692 wxLongLongWx
& wxLongLongWx::operator*=(const wxLongLongWx
& ll
)
694 wxLongLongWx
t(m_hi
, m_lo
);
695 wxLongLongWx
q(ll
.m_hi
, ll
.m_lo
);
699 #ifdef wxLONGLONG_TEST_MODE
700 wxLongLong_t llOld
= m_ll
;
702 #endif // wxLONGLONG_TEST_MODE
707 if ((q
.m_lo
& 1) != 0)
713 while ((counter
< 64) && ((q
.m_hi
!= 0) || (q
.m_lo
!= 0)));
715 #ifdef wxLONGLONG_TEST_MODE
716 m_ll
= llOld
* ll
.m_ll
;
719 #endif // wxLONGLONG_TEST_MODE
724 wxULongLongWx
& wxULongLongWx::operator*=(const wxULongLongWx
& ll
)
726 wxULongLongWx
t(m_hi
, m_lo
);
727 wxULongLongWx
q(ll
.m_hi
, ll
.m_lo
);
731 #ifdef wxLONGLONG_TEST_MODE
732 unsigned wxLongLong_t llOld
= m_ll
;
734 #endif // wxLONGLONG_TEST_MODE
739 if ((q
.m_lo
& 1) != 0)
745 while ((counter
< 64) && ((q
.m_hi
!= 0) || (q
.m_lo
!= 0)));
747 #ifdef wxLONGLONG_TEST_MODE
748 m_ll
= llOld
* ll
.m_ll
;
751 #endif // wxLONGLONG_TEST_MODE
758 void wxLongLongWx::Divide(const wxLongLongWx
& divisorIn
,
759 wxLongLongWx
& quotient
,
760 wxLongLongWx
& remainder
) const
762 if ((divisorIn
.m_lo
== 0) && (divisorIn
.m_hi
== 0))
764 // provoke division by zero error and silence the compilers warnings
765 // about an expression without effect and unused variable
766 long dummy
= divisorIn
.m_lo
/divisorIn
.m_hi
;
770 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
771 // do this - any improvements are more than welcome
773 // code inspired by the snippet at
774 // http://www.bearcave.com/software/divide.htm
778 // Use of this program, for any purpose, is granted the author, Ian
779 // Kaplan, as long as this copyright notice is included in the source
780 // code or any source code derived from this program. The user assumes
781 // all responsibility for using this code.
784 wxLongLongWx dividend
= *this,
790 // always do unsigned division and adjust the signs later: in C integer
791 // division, the sign of the remainder is the same as the sign of the
792 // dividend, while the sign of the quotient is the product of the signs of
793 // the dividend and divisor. Of course, we also always have
795 // dividend = quotient*divisor + remainder
797 // with 0 <= abs(remainder) < abs(divisor)
798 bool negRemainder
= dividend
.m_hi
< 0;
799 bool negQuotient
= false; // assume positive
800 if ( dividend
.m_hi
< 0 )
802 negQuotient
= !negQuotient
;
803 dividend
= -dividend
;
805 if ( divisor
.m_hi
< 0 )
807 negQuotient
= !negQuotient
;
811 // check for some particular cases
812 if ( divisor
> dividend
)
814 remainder
= dividend
;
816 else if ( divisor
== dividend
)
822 // here: dividend > divisor and both are positibe: do unsigned division
826 #define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1)))
828 while ( remainder
< divisor
)
831 if ( IS_MSB_SET(dividend
) )
842 // undo the last loop iteration
847 for ( size_t i
= 0; i
< nBits
; i
++ )
850 if ( IS_MSB_SET(dividend
) )
855 wxLongLongWx t
= remainder
- divisor
;
858 if ( !IS_MSB_SET(t
) )
870 remainder
= -remainder
;
875 quotient
= -quotient
;
879 void wxULongLongWx::Divide(const wxULongLongWx
& divisorIn
,
880 wxULongLongWx
& quotient
,
881 wxULongLongWx
& remainder
) const
883 if ((divisorIn
.m_lo
== 0) && (divisorIn
.m_hi
== 0))
885 // provoke division by zero error and silence the compilers warnings
886 // about an expression without effect and unused variable
887 unsigned long dummy
= divisorIn
.m_lo
/divisorIn
.m_hi
;
891 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
892 // do this - any improvements are more than welcome
894 // code inspired by the snippet at
895 // http://www.bearcave.com/software/divide.htm
899 // Use of this program, for any purpose, is granted the author, Ian
900 // Kaplan, as long as this copyright notice is included in the source
901 // code or any source code derived from this program. The user assumes
902 // all responsibility for using this code.
905 wxULongLongWx dividend
= *this,
911 // check for some particular cases
912 if ( divisor
> dividend
)
914 remainder
= dividend
;
916 else if ( divisor
== dividend
)
922 // here: dividend > divisor
926 #define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1)))
928 while ( remainder
< divisor
)
931 if ( IS_MSB_SET(dividend
) )
942 // undo the last loop iteration
947 for ( size_t i
= 0; i
< nBits
; i
++ )
950 if ( IS_MSB_SET(dividend
) )
955 wxULongLongWx t
= remainder
- divisor
;
958 if ( !IS_MSB_SET(t
) )
968 wxLongLongWx
wxLongLongWx::operator/(const wxLongLongWx
& ll
) const
970 wxLongLongWx quotient
, remainder
;
972 Divide(ll
, quotient
, remainder
);
977 wxULongLongWx
wxULongLongWx::operator/(const wxULongLongWx
& ll
) const
979 wxULongLongWx quotient
, remainder
;
981 Divide(ll
, quotient
, remainder
);
986 wxLongLongWx
& wxLongLongWx::operator/=(const wxLongLongWx
& ll
)
988 wxLongLongWx quotient
, remainder
;
990 Divide(ll
, quotient
, remainder
);
997 wxULongLongWx
& wxULongLongWx::operator/=(const wxULongLongWx
& ll
)
999 wxULongLongWx quotient
, remainder
;
1001 Divide(ll
, quotient
, remainder
);
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 // ----------------------------------------------------------------------------
1028 // ----------------------------------------------------------------------------
1030 // temporary - just for testing
1031 void *wxLongLongWx::asArray(void) const
1033 static unsigned char temp
[8];
1035 temp
[0] = (char)((m_hi
>> 24) & 0xFF);
1036 temp
[1] = (char)((m_hi
>> 16) & 0xFF);
1037 temp
[2] = (char)((m_hi
>> 8) & 0xFF);
1038 temp
[3] = (char)((m_hi
>> 0) & 0xFF);
1039 temp
[4] = (char)((m_lo
>> 24) & 0xFF);
1040 temp
[5] = (char)((m_lo
>> 16) & 0xFF);
1041 temp
[6] = (char)((m_lo
>> 8) & 0xFF);
1042 temp
[7] = (char)((m_lo
>> 0) & 0xFF);
1047 void *wxULongLongWx::asArray(void) const
1049 static unsigned char temp
[8];
1051 temp
[0] = (char)((m_hi
>> 24) & 0xFF);
1052 temp
[1] = (char)((m_hi
>> 16) & 0xFF);
1053 temp
[2] = (char)((m_hi
>> 8) & 0xFF);
1054 temp
[3] = (char)((m_hi
>> 0) & 0xFF);
1055 temp
[4] = (char)((m_lo
>> 24) & 0xFF);
1056 temp
[5] = (char)((m_lo
>> 16) & 0xFF);
1057 temp
[6] = (char)((m_lo
>> 8) & 0xFF);
1058 temp
[7] = (char)((m_lo
>> 0) & 0xFF);
1063 #endif // wxUSE_LONGLONG_WX
1066 #if wxUSE_LONGLONG_NATIVE
1067 wxLongLongNative::ToString() const
1069 wxLongLongWx::ToString() const
1072 // TODO: this is awfully inefficient, anything better?
1075 wxLongLong ll
= *this;
1090 result
.Prepend((wxChar
)(_T('0') + (ll
% 10).ToLong()));
1094 if ( result
.empty() )
1097 result
.Prepend(_T('-'));
1103 #if wxUSE_LONGLONG_NATIVE
1104 wxULongLongNative::ToString() const
1106 wxULongLongWx::ToString() const
1109 // TODO: this is awfully inefficient, anything better?
1112 wxULongLong ll
= *this;
1116 result
.Prepend((wxChar
)(_T('0') + (ll
% 10).ToULong()));
1120 if ( result
.empty() )
1126 #if wxUSE_STD_IOSTREAM
1129 wxSTD ostream
& operator<< (wxSTD ostream
& o
, const wxLongLong
& ll
)
1131 return o
<< ll
.ToString();
1134 wxSTD ostream
& operator<< (wxSTD ostream
& o
, const wxULongLong
& ll
)
1136 return o
<< ll
.ToString();
1139 #endif // wxUSE_STD_IOSTREAM
1141 #endif // wxUSE_LONGLONG