]>
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);
82 wxLongLongNative::wxLongLongNative(wxLongLongWx ll
)
84 // assign first to avoid precision loss!
90 wxLongLongNative
& wxLongLongNative::operator=(wxLongLongWx ll
)
92 // assign first to avoid precision loss!
100 #endif // wxUSE_LONGLONG_NATIVE
102 // ============================================================================
103 // wxLongLongWx: emulation of 'long long' using 2 longs
104 // ============================================================================
106 #if wxUSE_LONGLONG_WX
109 wxLongLongWx
& wxLongLongWx::Assign(double d
)
111 bool positive
= d
>= 0;
113 if ( d
<= ULONG_MAX
)
120 m_hi
= (unsigned long)(d
/ (1.0 + (double)ULONG_MAX
));
121 m_lo
= (unsigned long)(d
- ((double)m_hi
* (1.0 + (double)ULONG_MAX
)));
124 #ifdef wxLONGLONG_TEST_MODE
125 m_ll
= (wxLongLong_t
)d
;
128 #endif // wxLONGLONG_TEST_MODE
136 wxLongLongWx
wxLongLongWx::operator<<(int shift
) const
138 wxLongLongWx
ll(*this);
144 wxULongLongWx
wxULongLongWx::operator<<(int shift
) const
146 wxULongLongWx
ll(*this);
152 wxLongLongWx
& wxLongLongWx::operator<<=(int shift
)
159 m_hi
|= m_lo
>> (32 - shift
);
164 m_hi
= m_lo
<< (shift
- 32);
169 #ifdef wxLONGLONG_TEST_MODE
173 #endif // wxLONGLONG_TEST_MODE
178 wxULongLongWx
& wxULongLongWx::operator<<=(int shift
)
185 m_hi
|= m_lo
>> (32 - shift
);
190 m_hi
= m_lo
<< (shift
- 32);
195 #ifdef wxLONGLONG_TEST_MODE
199 #endif // wxLONGLONG_TEST_MODE
204 wxLongLongWx
wxLongLongWx::operator>>(int shift
) const
206 wxLongLongWx
ll(*this);
212 wxULongLongWx
wxULongLongWx::operator>>(int shift
) const
214 wxULongLongWx
ll(*this);
220 wxLongLongWx
& wxLongLongWx::operator>>=(int shift
)
227 m_lo
|= m_hi
<< (32 - shift
);
232 m_lo
= m_hi
>> (shift
- 32);
233 m_hi
= (m_hi
< 0 ? -1L : 0);
237 #ifdef wxLONGLONG_TEST_MODE
241 #endif // wxLONGLONG_TEST_MODE
246 wxULongLongWx
& wxULongLongWx::operator>>=(int shift
)
253 m_lo
|= m_hi
<< (32 - shift
);
258 m_lo
= m_hi
>> (shift
- 32);
263 #ifdef wxLONGLONG_TEST_MODE
267 #endif // wxLONGLONG_TEST_MODE
272 wxLongLongWx
wxLongLongWx::operator+(const wxLongLongWx
& ll
) const
274 wxLongLongWx
res(*this);
280 wxULongLongWx
wxULongLongWx::operator+(const wxULongLongWx
& ll
) const
282 wxULongLongWx
res(*this);
288 wxLongLongWx
wxLongLongWx::operator+(long l
) const
290 wxLongLongWx
res(*this);
296 wxULongLongWx
wxULongLongWx::operator+(unsigned long l
) const
298 wxULongLongWx
res(*this);
304 wxLongLongWx
& wxLongLongWx::operator+=(const wxLongLongWx
& 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 wxULongLongWx
& wxULongLongWx::operator+=(const wxULongLongWx
& ll
)
325 unsigned long previous
= m_lo
;
330 if ((m_lo
< previous
) || (m_lo
< ll
.m_lo
))
333 #ifdef wxLONGLONG_TEST_MODE
337 #endif // wxLONGLONG_TEST_MODE
342 wxLongLongWx
& wxLongLongWx::operator+=(long l
)
344 unsigned long previous
= m_lo
;
350 if ((m_lo
< previous
) || (m_lo
< (unsigned long)l
))
353 #ifdef wxLONGLONG_TEST_MODE
357 #endif // wxLONGLONG_TEST_MODE
362 wxULongLongWx
& wxULongLongWx::operator+=(unsigned long l
)
364 unsigned long previous
= m_lo
;
368 if ((m_lo
< previous
) || (m_lo
< l
))
371 #ifdef wxLONGLONG_TEST_MODE
375 #endif // wxLONGLONG_TEST_MODE
381 wxLongLongWx
& wxLongLongWx::operator++()
387 #ifdef wxLONGLONG_TEST_MODE
391 #endif // wxLONGLONG_TEST_MODE
396 wxULongLongWx
& wxULongLongWx::operator++()
402 #ifdef wxLONGLONG_TEST_MODE
406 #endif // wxLONGLONG_TEST_MODE
412 wxLongLongWx
wxLongLongWx::operator-() const
414 wxLongLongWx
res(*this);
420 wxLongLongWx
& wxLongLongWx::Negate()
429 #ifdef wxLONGLONG_TEST_MODE
433 #endif // wxLONGLONG_TEST_MODE
440 wxLongLongWx
wxLongLongWx::operator-(const wxLongLongWx
& ll
) const
442 wxLongLongWx
res(*this);
448 wxLongLongWx
wxULongLongWx::operator-(const wxULongLongWx
& ll
) const
450 wxASSERT(m_hi
<= LONG_MAX
);
451 wxASSERT(ll
.m_hi
<= LONG_MAX
);
453 wxLongLongWx
res( (long)m_hi
, m_lo
);
454 wxLongLongWx
op( (long)ll
.m_hi
, ll
.m_lo
);
460 wxLongLongWx
& wxLongLongWx::operator-=(const wxLongLongWx
& ll
)
462 unsigned long previous
= m_lo
;
467 if (previous
< ll
.m_lo
)
470 #ifdef wxLONGLONG_TEST_MODE
474 #endif // wxLONGLONG_TEST_MODE
479 wxULongLongWx
& wxULongLongWx::operator-=(const wxULongLongWx
& ll
)
481 unsigned long previous
= m_lo
;
486 if (previous
< ll
.m_lo
)
489 #ifdef wxLONGLONG_TEST_MODE
493 #endif // wxLONGLONG_TEST_MODE
499 wxLongLongWx
& wxLongLongWx::operator--()
502 if (m_lo
== 0xFFFFFFFF)
505 #ifdef wxLONGLONG_TEST_MODE
509 #endif // wxLONGLONG_TEST_MODE
514 wxULongLongWx
& wxULongLongWx::operator--()
517 if (m_lo
== 0xFFFFFFFF)
520 #ifdef wxLONGLONG_TEST_MODE
524 #endif // wxLONGLONG_TEST_MODE
529 // comparison operators
531 bool wxLongLongWx::operator<(const wxLongLongWx
& ll
) const
533 if ( m_hi
< ll
.m_hi
)
535 else if ( m_hi
== ll
.m_hi
)
536 return m_lo
< ll
.m_lo
;
541 bool wxULongLongWx::operator<(const wxULongLongWx
& ll
) const
543 if ( m_hi
< ll
.m_hi
)
545 else if ( m_hi
== ll
.m_hi
)
546 return m_lo
< ll
.m_lo
;
551 bool wxLongLongWx::operator>(const wxLongLongWx
& ll
) const
553 if ( m_hi
> ll
.m_hi
)
555 else if ( m_hi
== ll
.m_hi
)
556 return m_lo
> ll
.m_lo
;
561 bool wxULongLongWx::operator>(const wxULongLongWx
& ll
) const
563 if ( m_hi
> ll
.m_hi
)
565 else if ( m_hi
== ll
.m_hi
)
566 return m_lo
> ll
.m_lo
;
573 wxLongLongWx
wxLongLongWx::operator&(const wxLongLongWx
& ll
) const
575 return wxLongLongWx(m_hi
& ll
.m_hi
, m_lo
& ll
.m_lo
);
578 wxULongLongWx
wxULongLongWx::operator&(const wxULongLongWx
& ll
) const
580 return wxULongLongWx(m_hi
& ll
.m_hi
, m_lo
& ll
.m_lo
);
583 wxLongLongWx
wxLongLongWx::operator|(const wxLongLongWx
& ll
) const
585 return wxLongLongWx(m_hi
| ll
.m_hi
, m_lo
| ll
.m_lo
);
588 wxULongLongWx
wxULongLongWx::operator|(const wxULongLongWx
& ll
) const
590 return wxULongLongWx(m_hi
| ll
.m_hi
, m_lo
| ll
.m_lo
);
593 wxLongLongWx
wxLongLongWx::operator^(const wxLongLongWx
& ll
) const
595 return wxLongLongWx(m_hi
^ ll
.m_hi
, m_lo
^ ll
.m_lo
);
598 wxULongLongWx
wxULongLongWx::operator^(const wxULongLongWx
& ll
) const
600 return wxULongLongWx(m_hi
^ ll
.m_hi
, m_lo
^ ll
.m_lo
);
603 wxLongLongWx
& wxLongLongWx::operator&=(const wxLongLongWx
& ll
)
608 #ifdef wxLONGLONG_TEST_MODE
612 #endif // wxLONGLONG_TEST_MODE
617 wxULongLongWx
& wxULongLongWx::operator&=(const wxULongLongWx
& ll
)
622 #ifdef wxLONGLONG_TEST_MODE
626 #endif // wxLONGLONG_TEST_MODE
631 wxLongLongWx
& wxLongLongWx::operator|=(const wxLongLongWx
& ll
)
636 #ifdef wxLONGLONG_TEST_MODE
640 #endif // wxLONGLONG_TEST_MODE
645 wxULongLongWx
& wxULongLongWx::operator|=(const wxULongLongWx
& ll
)
650 #ifdef wxLONGLONG_TEST_MODE
654 #endif // wxLONGLONG_TEST_MODE
659 wxLongLongWx
& wxLongLongWx::operator^=(const wxLongLongWx
& ll
)
664 #ifdef wxLONGLONG_TEST_MODE
668 #endif // wxLONGLONG_TEST_MODE
673 wxULongLongWx
& wxULongLongWx::operator^=(const wxULongLongWx
& ll
)
678 #ifdef wxLONGLONG_TEST_MODE
682 #endif // wxLONGLONG_TEST_MODE
687 wxLongLongWx
wxLongLongWx::operator~() const
689 return wxLongLongWx(~m_hi
, ~m_lo
);
692 wxULongLongWx
wxULongLongWx::operator~() const
694 return wxULongLongWx(~m_hi
, ~m_lo
);
699 wxLongLongWx
wxLongLongWx::operator*(const wxLongLongWx
& ll
) const
701 wxLongLongWx
res(*this);
707 wxULongLongWx
wxULongLongWx::operator*(const wxULongLongWx
& ll
) const
709 wxULongLongWx
res(*this);
715 wxLongLongWx
& wxLongLongWx::operator*=(const wxLongLongWx
& ll
)
717 wxLongLongWx
t(m_hi
, m_lo
);
718 wxLongLongWx
q(ll
.m_hi
, ll
.m_lo
);
722 #ifdef wxLONGLONG_TEST_MODE
723 wxLongLong_t llOld
= m_ll
;
725 #endif // wxLONGLONG_TEST_MODE
730 if ((q
.m_lo
& 1) != 0)
736 while ((counter
< 64) && ((q
.m_hi
!= 0) || (q
.m_lo
!= 0)));
738 #ifdef wxLONGLONG_TEST_MODE
739 m_ll
= llOld
* ll
.m_ll
;
742 #endif // wxLONGLONG_TEST_MODE
747 wxULongLongWx
& wxULongLongWx::operator*=(const wxULongLongWx
& ll
)
749 wxULongLongWx
t(m_hi
, m_lo
);
750 wxULongLongWx
q(ll
.m_hi
, ll
.m_lo
);
754 #ifdef wxLONGLONG_TEST_MODE
755 unsigned wxLongLong_t llOld
= m_ll
;
757 #endif // wxLONGLONG_TEST_MODE
762 if ((q
.m_lo
& 1) != 0)
768 while ((counter
< 64) && ((q
.m_hi
!= 0) || (q
.m_lo
!= 0)));
770 #ifdef wxLONGLONG_TEST_MODE
771 m_ll
= llOld
* ll
.m_ll
;
774 #endif // wxLONGLONG_TEST_MODE
781 void wxLongLongWx::Divide(const wxLongLongWx
& divisorIn
,
782 wxLongLongWx
& quotient
,
783 wxLongLongWx
& remainder
) const
785 if ((divisorIn
.m_lo
== 0) && (divisorIn
.m_hi
== 0))
787 // provoke division by zero error and silence the compilers warnings
788 // about an expression without effect and unused variable
789 long dummy
= divisorIn
.m_lo
/divisorIn
.m_hi
;
793 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
794 // do this - any improvements are more than welcome
796 // code inspired by the snippet at
797 // http://www.bearcave.com/software/divide.htm
801 // Use of this program, for any purpose, is granted the author, Ian
802 // Kaplan, as long as this copyright notice is included in the source
803 // code or any source code derived from this program. The user assumes
804 // all responsibility for using this code.
807 wxLongLongWx dividend
= *this,
813 // always do unsigned division and adjust the signs later: in C integer
814 // division, the sign of the remainder is the same as the sign of the
815 // dividend, while the sign of the quotient is the product of the signs of
816 // the dividend and divisor. Of course, we also always have
818 // dividend = quotient*divisor + remainder
820 // with 0 <= abs(remainder) < abs(divisor)
821 bool negRemainder
= dividend
.m_hi
< 0;
822 bool negQuotient
= false; // assume positive
823 if ( dividend
.m_hi
< 0 )
825 negQuotient
= !negQuotient
;
826 dividend
= -dividend
;
828 if ( divisor
.m_hi
< 0 )
830 negQuotient
= !negQuotient
;
834 // check for some particular cases
835 if ( divisor
> dividend
)
837 remainder
= dividend
;
839 else if ( divisor
== dividend
)
845 // here: dividend > divisor and both are positive: do unsigned division
849 #define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1)))
851 while ( remainder
< divisor
)
854 if ( IS_MSB_SET(dividend
) )
865 // undo the last loop iteration
870 for ( size_t i
= 0; i
< nBits
; i
++ )
873 if ( IS_MSB_SET(dividend
) )
878 wxLongLongWx t
= remainder
- divisor
;
881 if ( !IS_MSB_SET(t
) )
893 remainder
= -remainder
;
898 quotient
= -quotient
;
902 void wxULongLongWx::Divide(const wxULongLongWx
& divisorIn
,
903 wxULongLongWx
& quotient
,
904 wxULongLongWx
& remainder
) const
906 if ((divisorIn
.m_lo
== 0) && (divisorIn
.m_hi
== 0))
908 // provoke division by zero error and silence the compilers warnings
909 // about an expression without effect and unused variable
910 unsigned long dummy
= divisorIn
.m_lo
/divisorIn
.m_hi
;
914 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
915 // do this - any improvements are more than welcome
917 // code inspired by the snippet at
918 // http://www.bearcave.com/software/divide.htm
922 // Use of this program, for any purpose, is granted the author, Ian
923 // Kaplan, as long as this copyright notice is included in the source
924 // code or any source code derived from this program. The user assumes
925 // all responsibility for using this code.
928 wxULongLongWx dividend
= *this,
934 // check for some particular cases
935 if ( divisor
> dividend
)
937 remainder
= dividend
;
939 else if ( divisor
== dividend
)
945 // here: dividend > divisor
949 #define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1)))
951 while ( remainder
< divisor
)
954 if ( IS_MSB_SET(dividend
) )
965 // undo the last loop iteration
970 for ( size_t i
= 0; i
< nBits
; i
++ )
973 if ( IS_MSB_SET(dividend
) )
978 wxULongLongWx t
= remainder
- divisor
;
981 if ( !IS_MSB_SET(t
) )
991 wxLongLongWx
wxLongLongWx::operator/(const wxLongLongWx
& ll
) const
993 wxLongLongWx quotient
, remainder
;
995 Divide(ll
, quotient
, remainder
);
1000 wxULongLongWx
wxULongLongWx::operator/(const wxULongLongWx
& ll
) const
1002 wxULongLongWx quotient
, remainder
;
1004 Divide(ll
, quotient
, remainder
);
1009 wxLongLongWx
& wxLongLongWx::operator/=(const wxLongLongWx
& ll
)
1011 wxLongLongWx quotient
, remainder
;
1013 Divide(ll
, quotient
, remainder
);
1020 wxULongLongWx
& wxULongLongWx::operator/=(const wxULongLongWx
& ll
)
1022 wxULongLongWx quotient
, remainder
;
1024 Divide(ll
, quotient
, remainder
);
1031 wxLongLongWx
wxLongLongWx::operator%(const wxLongLongWx
& ll
) const
1033 wxLongLongWx quotient
, remainder
;
1035 Divide(ll
, quotient
, remainder
);
1040 wxULongLongWx
wxULongLongWx::operator%(const wxULongLongWx
& ll
) const
1042 wxULongLongWx quotient
, remainder
;
1044 Divide(ll
, quotient
, remainder
);
1049 // ----------------------------------------------------------------------------
1051 // ----------------------------------------------------------------------------
1053 // temporary - just for testing
1054 void *wxLongLongWx::asArray(void) const
1056 static unsigned char temp
[8];
1058 temp
[0] = (char)((m_hi
>> 24) & 0xFF);
1059 temp
[1] = (char)((m_hi
>> 16) & 0xFF);
1060 temp
[2] = (char)((m_hi
>> 8) & 0xFF);
1061 temp
[3] = (char)((m_hi
>> 0) & 0xFF);
1062 temp
[4] = (char)((m_lo
>> 24) & 0xFF);
1063 temp
[5] = (char)((m_lo
>> 16) & 0xFF);
1064 temp
[6] = (char)((m_lo
>> 8) & 0xFF);
1065 temp
[7] = (char)((m_lo
>> 0) & 0xFF);
1070 void *wxULongLongWx::asArray(void) const
1072 static unsigned char temp
[8];
1074 temp
[0] = (char)((m_hi
>> 24) & 0xFF);
1075 temp
[1] = (char)((m_hi
>> 16) & 0xFF);
1076 temp
[2] = (char)((m_hi
>> 8) & 0xFF);
1077 temp
[3] = (char)((m_hi
>> 0) & 0xFF);
1078 temp
[4] = (char)((m_lo
>> 24) & 0xFF);
1079 temp
[5] = (char)((m_lo
>> 16) & 0xFF);
1080 temp
[6] = (char)((m_lo
>> 8) & 0xFF);
1081 temp
[7] = (char)((m_lo
>> 0) & 0xFF);
1086 #endif // wxUSE_LONGLONG_WX
1088 #define LL_TO_STRING(name) \
1089 wxString name::ToString() const \
1091 /* TODO: this is awfully inefficient, anything better? */ \
1109 result.Prepend((wxChar)(_T('0') + (ll % 10).ToLong())); \
1113 if ( result.empty() ) \
1116 result.Prepend(_T('-')); \
1121 #define ULL_TO_STRING(name) \
1122 wxString name::ToString() const \
1124 /* TODO: this is awfully inefficient, anything better? */ \
1131 result.Prepend((wxChar)(_T('0') + (ll % 10).ToULong())); \
1135 if ( result.empty() ) \
1141 #if wxUSE_LONGLONG_NATIVE
1142 LL_TO_STRING(wxLongLongNative
)
1143 ULL_TO_STRING(wxULongLongNative
)
1146 #if wxUSE_LONGLONG_WX
1147 LL_TO_STRING(wxLongLongWx
)
1148 ULL_TO_STRING(wxULongLongWx
)
1151 #if wxUSE_STD_IOSTREAM
1154 wxSTD ostream
& operator<< (wxSTD ostream
& o
, const wxLongLong
& ll
)
1156 return o
<< ll
.ToString();
1159 wxSTD ostream
& operator<< (wxSTD ostream
& o
, const wxULongLong
& ll
)
1161 return o
<< ll
.ToString();
1164 #endif // wxUSE_STD_IOSTREAM
1166 #endif // wxUSE_LONGLONG