]>
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 wxWindows 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 license
12 /////////////////////////////////////////////////////////////////////////////
14 // ============================================================================
16 // ============================================================================
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] = (m_ll
>> 56) & 0xFF;
54 temp
[1] = (m_ll
>> 48) & 0xFF;
55 temp
[2] = (m_ll
>> 40) & 0xFF;
56 temp
[3] = (m_ll
>> 32) & 0xFF;
57 temp
[4] = (m_ll
>> 24) & 0xFF;
58 temp
[5] = (m_ll
>> 16) & 0xFF;
59 temp
[6] = (m_ll
>> 8) & 0xFF;
60 temp
[7] = (m_ll
>> 0) & 0xFF;
65 #endif // wxUSE_LONGLONG_NATIVE
67 // ============================================================================
68 // wxLongLongWx: emulation of 'long long' using 2 longs
69 // ============================================================================
74 wxLongLongWx
& wxLongLongWx::Assign(double d
)
76 bool positive
= d
>= 0;
85 m_hi
= (unsigned long)(d
/ (1.0 + (double)ULONG_MAX
));
86 m_lo
= (unsigned long)(d
- ((double)m_hi
* (1.0 + (double)ULONG_MAX
)));
89 #ifdef wxLONGLONG_TEST_MODE
90 m_ll
= (wxLongLong_t
)d
;
93 #endif // wxLONGLONG_TEST_MODE
101 wxLongLongWx
wxLongLongWx::operator<<(int shift
) const
103 wxLongLongWx
ll(*this);
109 wxLongLongWx
& wxLongLongWx::operator<<=(int shift
)
116 m_hi
|= m_lo
>> (32 - shift
);
121 m_hi
= m_lo
<< (shift
- 32);
126 #ifdef wxLONGLONG_TEST_MODE
130 #endif // wxLONGLONG_TEST_MODE
135 wxLongLongWx
wxLongLongWx::operator>>(int shift
) const
137 wxLongLongWx
ll(*this);
143 wxLongLongWx
& wxLongLongWx::operator>>=(int shift
)
150 m_lo
|= m_hi
<< (32 - shift
);
155 m_lo
= m_hi
>> (shift
- 32);
156 m_hi
= (m_hi
< 0 ? -1L : 0);
160 #ifdef wxLONGLONG_TEST_MODE
164 #endif // wxLONGLONG_TEST_MODE
169 wxLongLongWx
wxLongLongWx::operator+(const wxLongLongWx
& ll
) const
171 wxLongLongWx
res(*this);
177 wxLongLongWx
wxLongLongWx::operator+(long l
) const
179 wxLongLongWx
res(*this);
185 wxLongLongWx
& wxLongLongWx::operator+=(const wxLongLongWx
& ll
)
187 unsigned long previous
= m_lo
;
192 if ((m_lo
< previous
) || (m_lo
< ll
.m_lo
))
195 #ifdef wxLONGLONG_TEST_MODE
199 #endif // wxLONGLONG_TEST_MODE
204 wxLongLongWx
& wxLongLongWx::operator+=(long l
)
206 unsigned long previous
= m_lo
;
212 if ((m_lo
< previous
) || (m_lo
< (unsigned long)l
))
215 #ifdef wxLONGLONG_TEST_MODE
219 #endif // wxLONGLONG_TEST_MODE
225 wxLongLongWx
& wxLongLongWx::operator++()
231 #ifdef wxLONGLONG_TEST_MODE
235 #endif // wxLONGLONG_TEST_MODE
241 wxLongLongWx
wxLongLongWx::operator-() const
243 wxLongLongWx
res(*this);
249 wxLongLongWx
& wxLongLongWx::Negate()
258 #ifdef wxLONGLONG_TEST_MODE
262 #endif // wxLONGLONG_TEST_MODE
269 wxLongLongWx
wxLongLongWx::operator-(const wxLongLongWx
& ll
) const
271 wxLongLongWx
res(*this);
277 wxLongLongWx
& wxLongLongWx::operator-=(const wxLongLongWx
& ll
)
279 unsigned long previous
= m_lo
;
284 if (previous
< ll
.m_lo
)
287 #ifdef wxLONGLONG_TEST_MODE
291 #endif // wxLONGLONG_TEST_MODE
297 wxLongLongWx
& wxLongLongWx::operator--()
300 if (m_lo
== 0xFFFFFFFF)
303 #ifdef wxLONGLONG_TEST_MODE
307 #endif // wxLONGLONG_TEST_MODE
312 // comparison operators
314 bool wxLongLongWx::operator<(const wxLongLongWx
& ll
) const
316 if ( m_hi
< ll
.m_hi
)
318 else if ( m_hi
== ll
.m_hi
)
319 return m_lo
< ll
.m_lo
;
324 bool wxLongLongWx::operator>(const wxLongLongWx
& ll
) const
326 if ( m_hi
> ll
.m_hi
)
328 else if ( m_hi
== ll
.m_hi
)
329 return m_lo
> ll
.m_lo
;
336 wxLongLongWx
wxLongLongWx::operator&(const wxLongLongWx
& ll
) const
338 return wxLongLongWx(m_hi
& ll
.m_hi
, m_lo
& ll
.m_lo
);
341 wxLongLongWx
wxLongLongWx::operator|(const wxLongLongWx
& ll
) const
343 return wxLongLongWx(m_hi
| ll
.m_hi
, m_lo
| ll
.m_lo
);
346 wxLongLongWx
wxLongLongWx::operator^(const wxLongLongWx
& ll
) const
348 return wxLongLongWx(m_hi
^ ll
.m_hi
, m_lo
^ ll
.m_lo
);
351 wxLongLongWx
& wxLongLongWx::operator&=(const wxLongLongWx
& ll
)
356 #ifdef wxLONGLONG_TEST_MODE
360 #endif // wxLONGLONG_TEST_MODE
365 wxLongLongWx
& wxLongLongWx::operator|=(const wxLongLongWx
& ll
)
370 #ifdef wxLONGLONG_TEST_MODE
374 #endif // wxLONGLONG_TEST_MODE
379 wxLongLongWx
& wxLongLongWx::operator^=(const wxLongLongWx
& ll
)
384 #ifdef wxLONGLONG_TEST_MODE
388 #endif // wxLONGLONG_TEST_MODE
393 wxLongLongWx
wxLongLongWx::operator~() const
395 return wxLongLongWx(~m_hi
, ~m_lo
);
400 wxLongLongWx
wxLongLongWx::operator*(const wxLongLongWx
& ll
) const
402 wxLongLongWx
res(*this);
408 wxLongLongWx
& wxLongLongWx::operator*=(const wxLongLongWx
& ll
)
410 wxLongLongWx
t(m_hi
, m_lo
);
411 wxLongLongWx
q(ll
.m_hi
, ll
.m_lo
);
415 #ifdef wxLONGLONG_TEST_MODE
416 wxLongLong_t llOld
= m_ll
;
418 #endif // wxLONGLONG_TEST_MODE
423 if ((q
.m_lo
& 1) != 0)
429 while ((counter
< 64) && ((q
.m_hi
!= 0) || (q
.m_lo
!= 0)));
431 #ifdef wxLONGLONG_TEST_MODE
432 m_ll
= llOld
* ll
.m_ll
;
435 #endif // wxLONGLONG_TEST_MODE
442 void wxLongLongWx::Divide(const wxLongLongWx
& divisorIn
,
443 wxLongLongWx
& quotient
,
444 wxLongLongWx
& remainder
) const
446 if ((divisorIn
.m_lo
== 0) && (divisorIn
.m_hi
== 0))
448 // provoke division by zero error and silence the compilers warnings
449 // about an expression without effect and unused variable
450 long dummy
= divisorIn
.m_lo
/divisorIn
.m_hi
;
454 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
455 // do this - any improvements are more than welcome
457 // code inspired by the snippet at
458 // http://www.bearcave.com/software/divide.htm
462 // Use of this program, for any purpose, is granted the author, Ian
463 // Kaplan, as long as this copyright notice is included in the source
464 // code or any source code derived from this program. The user assumes
465 // all responsibility for using this code.
468 wxLongLongWx dividend
= *this,
474 // always do unsigned division and adjust the signs later: in C integer
475 // division, the sign of the remainder is the same as the sign of the
476 // dividend, while the sign of the quotient is the product of the signs of
477 // the dividend and divisor. Of course, we also always have
479 // dividend = quotient*divisor + remainder
481 // with 0 <= abs(remainder) < abs(divisor)
482 bool negRemainder
= dividend
.m_hi
< 0;
483 bool negQuotient
= FALSE
; // assume positive
484 if ( dividend
.m_hi
< 0 )
486 negQuotient
= !negQuotient
;
487 dividend
= -dividend
;
489 if ( divisor
.m_hi
< 0 )
491 negQuotient
= !negQuotient
;
495 // check for some particular cases
496 if ( divisor
> dividend
)
498 remainder
= dividend
;
500 else if ( divisor
== dividend
)
506 // here: dividend > divisor and both are positibe: do unsigned division
510 #define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1)))
512 while ( remainder
< divisor
)
515 if ( IS_MSB_SET(dividend
) )
526 // undo the last loop iteration
531 for ( size_t i
= 0; i
< nBits
; i
++ )
534 if ( IS_MSB_SET(dividend
) )
539 wxLongLongWx t
= remainder
- divisor
;
542 if ( !IS_MSB_SET(t
) )
554 remainder
= -remainder
;
559 quotient
= -quotient
;
563 wxLongLongWx
wxLongLongWx::operator/(const wxLongLongWx
& ll
) const
565 wxLongLongWx quotient
, remainder
;
567 Divide(ll
, quotient
, remainder
);
572 wxLongLongWx
& wxLongLongWx::operator/=(const wxLongLongWx
& ll
)
574 wxLongLongWx quotient
, remainder
;
576 Divide(ll
, quotient
, remainder
);
583 wxLongLongWx
wxLongLongWx::operator%(const wxLongLongWx
& ll
) const
585 wxLongLongWx quotient
, remainder
;
587 Divide(ll
, quotient
, remainder
);
592 // ----------------------------------------------------------------------------
594 // ----------------------------------------------------------------------------
596 // temporary - just for testing
597 void *wxLongLongWx::asArray(void) const
599 static unsigned char temp
[8];
601 temp
[0] = (char)((m_hi
>> 24) & 0xFF);
602 temp
[1] = (char)((m_hi
>> 16) & 0xFF);
603 temp
[2] = (char)((m_hi
>> 8) & 0xFF);
604 temp
[3] = (char)((m_hi
>> 0) & 0xFF);
605 temp
[4] = (char)((m_lo
>> 24) & 0xFF);
606 temp
[5] = (char)((m_lo
>> 16) & 0xFF);
607 temp
[6] = (char)((m_lo
>> 8) & 0xFF);
608 temp
[7] = (char)((m_lo
>> 0) & 0xFF);
613 #endif // wxUSE_LONGLONG_WX
616 #if wxUSE_LONGLONG_NATIVE
617 wxLongLongNative::ToString() const
619 wxLongLongWx::ToString() const
622 // TODO: this is awfully inefficient, anything better?
625 wxLongLong ll
= *this;
640 result
.Prepend((wxChar
)(_T('0') + (ll
% 10).ToLong()));
644 if ( result
.empty() )
647 result
.Prepend(_T('-'));
652 #if wxUSE_STD_IOSTREAM
655 wxSTD ostream
& operator<< (wxSTD ostream
& o
, const wxLongLong
& ll
)
657 return o
<< ll
.ToString();
660 #endif // wxUSE_STD_IOSTREAM
662 #endif // wxUSE_LONGLONG