]>
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"
30 #include "wx/longlong.h"
32 #include <memory.h> // for memset()
33 #include <math.h> // for fabs()
35 // ============================================================================
37 // ============================================================================
39 #if wxUSE_LONGLONG_NATIVE
41 // ----------------------------------------------------------------------------
43 // ----------------------------------------------------------------------------
45 void *wxLongLongNative::asArray(void) const
47 static unsigned char temp
[8];
49 temp
[0] = (m_ll
>> 56) & 0xFF;
50 temp
[1] = (m_ll
>> 48) & 0xFF;
51 temp
[2] = (m_ll
>> 40) & 0xFF;
52 temp
[3] = (m_ll
>> 32) & 0xFF;
53 temp
[4] = (m_ll
>> 24) & 0xFF;
54 temp
[5] = (m_ll
>> 16) & 0xFF;
55 temp
[6] = (m_ll
>> 8) & 0xFF;
56 temp
[7] = (m_ll
>> 0) & 0xFF;
61 #if wxUSE_STD_IOSTREAM
64 ostream
& operator<< (ostream
& o
, const wxLongLongNative
& ll
)
68 memset(result
, 'A', 64);
72 for (int i
= 0; i
< 64; i
++)
74 result
[63 - i
] = '0' + (char) ((ll
.m_ll
>> i
) & 1);
80 #endif // wxUSE_STD_IOSTREAM
82 #endif // wxUSE_LONGLONG_NATIVE
84 // ============================================================================
85 // wxLongLongWx: emulation of 'long long' using 2 longs
86 // ============================================================================
91 wxLongLongWx
& wxLongLongWx::Assign(double d
)
93 if ( fabs(d
) <= LONG_MAX
)
95 m_hi
= d
< 0 ? 1 << (8*sizeof(long) - 1) : 0l;
100 wxFAIL_MSG(_T("TODO"));
106 wxLongLongWx
wxLongLongWx::operator<<(int shift
) const
112 return wxLongLongWx((m_hi
<< shift
) | (m_lo
>> (32 - shift
)),
115 return wxLongLongWx(m_lo
<< (shift
- 32),
119 wxLongLongWx
& wxLongLongWx::operator<<=(int shift
)
127 m_hi
|= m_lo
>> (32 - shift
);
132 m_hi
= m_lo
<< (shift
- 32);
139 wxLongLongWx
wxLongLongWx::operator>>(int shift
) const
145 return wxLongLongWx(m_hi
>> shift
,
146 (m_lo
>> shift
) | (m_hi
<< (32 - shift
)));
148 return wxLongLongWx((m_hi
< 0 ? -1l : 0),
149 m_hi
>> (shift
- 32));
152 wxLongLongWx
& wxLongLongWx::operator>>=(int shift
)
160 m_lo
|= m_hi
<< (32 - shift
);
165 m_lo
= m_hi
>> (shift
- 32);
166 m_hi
= (m_hi
< 0 ? -1L : 0);
172 wxLongLongWx
wxLongLongWx::operator+(const wxLongLongWx
& ll
) const
176 temp
.m_lo
= m_lo
+ ll
.m_lo
;
177 temp
.m_hi
= m_hi
+ ll
.m_hi
;
178 if ((temp
.m_lo
< m_lo
) || (temp
.m_lo
< ll
.m_lo
))
184 wxLongLongWx
wxLongLongWx::operator+(long l
) const
188 temp
.m_lo
= m_lo
+ l
;
193 if ((temp
.m_lo
< m_lo
) || (temp
.m_lo
< (unsigned long)l
))
199 wxLongLongWx
& wxLongLongWx::operator+=(const wxLongLongWx
& ll
)
201 unsigned long previous
= m_lo
;
206 if ((m_lo
< previous
) || (m_lo
< ll
.m_lo
))
212 wxLongLongWx
& wxLongLongWx::operator+=(long l
)
214 unsigned long previous
= m_lo
;
220 if ((m_lo
< previous
) || (m_lo
< (unsigned long)l
))
227 wxLongLongWx
& wxLongLongWx::operator++()
237 wxLongLongWx
& wxLongLongWx::operator++(int)
247 wxLongLongWx
wxLongLongWx::operator-() const
249 wxLongLongWx
temp(~m_hi
, ~m_lo
);
260 wxLongLongWx
wxLongLongWx::operator-(const wxLongLongWx
& ll
) const
264 temp
.m_lo
= m_lo
- ll
.m_lo
;
265 temp
.m_hi
= m_hi
- ll
.m_hi
;
273 wxLongLongWx
& wxLongLongWx::operator-=(const wxLongLongWx
& ll
)
275 unsigned long previous
= m_lo
;
280 if (previous
< ll
.m_lo
)
287 wxLongLongWx
& wxLongLongWx::operator--()
290 if (m_lo
== 0xFFFFFFFF)
297 wxLongLongWx
& wxLongLongWx::operator--(int)
300 if (m_lo
== 0xFFFFFFFF)
306 // comparison operators
308 bool wxLongLongWx::operator<(const wxLongLongWx
& ll
) const
310 if ( m_hi
< ll
.m_hi
)
312 else if ( m_hi
== ll
.m_hi
)
313 return m_lo
< ll
.m_lo
;
318 bool wxLongLongWx::operator>(const wxLongLongWx
& ll
) const
320 if ( m_hi
> ll
.m_hi
)
322 else if ( m_hi
== ll
.m_hi
)
323 return m_lo
> ll
.m_lo
;
330 wxLongLongWx
wxLongLongWx::operator&(const wxLongLongWx
& ll
) const
332 return wxLongLongWx(m_hi
& ll
.m_hi
, m_lo
& ll
.m_lo
);
335 wxLongLongWx
wxLongLongWx::operator|(const wxLongLongWx
& ll
) const
337 return wxLongLongWx(m_hi
| ll
.m_hi
, m_lo
| ll
.m_lo
);
340 wxLongLongWx
wxLongLongWx::operator^(const wxLongLongWx
& ll
) const
342 return wxLongLongWx(m_hi
^ ll
.m_hi
, m_lo
^ ll
.m_lo
);
345 wxLongLongWx
& wxLongLongWx::operator&=(const wxLongLongWx
& ll
)
353 wxLongLongWx
& wxLongLongWx::operator|=(const wxLongLongWx
& ll
)
361 wxLongLongWx
& wxLongLongWx::operator^=(const wxLongLongWx
& ll
)
369 wxLongLongWx
wxLongLongWx::operator~() const
371 return wxLongLongWx(~m_hi
, ~m_lo
);
376 wxLongLongWx
wxLongLongWx::operator*(const wxLongLongWx
& ll
) const
378 wxLongLongWx
t(m_hi
, m_lo
);
379 wxLongLongWx
q(ll
.m_hi
, ll
.m_lo
);
385 if ((q
.m_lo
& 1) != 0)
391 while ((counter
< 64) && ((q
.m_hi
!= 0) || (q
.m_lo
!= 0)));
395 wxLongLongWx
& wxLongLongWx::operator*=(const wxLongLongWx
& ll
)
397 wxLongLongWx
t(m_hi
, m_lo
);
398 wxLongLongWx
q(ll
.m_hi
, ll
.m_lo
);
403 if ((q
.m_lo
& 1) != 0)
409 while ((counter
< 64) && ((q
.m_hi
!= 0) || (q
.m_lo
!= 0)));
415 void wxLongLongWx::Divide(const wxLongLongWx
& divisorIn
,
416 wxLongLongWx
& quotient
,
417 wxLongLongWx
& remainder
) const
419 if ((divisorIn
.m_lo
== 0) && (divisorIn
.m_hi
== 0))
421 // provoke division by zero error and silence the compilers warnings
422 // about an expression without effect and unused variable
423 long dummy
= divisorIn
.m_lo
/divisorIn
.m_hi
;
427 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
428 // do this - any improvements are more than welcome
430 // code inspired by the snippet at
431 // http://www.bearcave.com/software/divide.htm
435 // Use of this program, for any purpose, is granted the author, Ian
436 // Kaplan, as long as this copyright notice is included in the source
437 // code or any source code derived from this program. The user assumes
438 // all responsibility for using this code.
441 wxLongLongWx dividend
= *this,
447 // check for some particular cases
448 if ( divisor
> dividend
)
450 remainder
= dividend
;
455 if ( divisor
== dividend
)
462 // always do unsigned division and adjust the signs later: in C integer
463 // division, the sign of the remainder is the same as the sign of the
464 // dividend, while the sign of the quotient is the product of the signs of
465 // the dividend and divisor. Of course, we also always have
467 // dividend = quotient*divisor + remainder
469 // with 0 <= abs(remainder) < abs(divisor)
470 bool negRemainder
= dividend
.m_hi
< 0;
471 bool negQuotient
= FALSE
; // assume positive
472 if ( dividend
.m_hi
< 0 )
474 negQuotient
= !negQuotient
;
475 dividend
= -dividend
;
477 if ( divisor
.m_hi
< 0 )
479 negQuotient
= !negQuotient
;
483 // here: dividend > divisor and both are positibe: do unsigned division
487 #define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1)))
489 while ( remainder
< divisor
)
492 if ( IS_MSB_SET(dividend
) )
503 // undo the last loop iteration
508 for ( size_t i
= 0; i
< nBits
; i
++ )
511 if ( IS_MSB_SET(dividend
) )
516 wxLongLongWx t
= remainder
- divisor
;
519 if ( !IS_MSB_SET(t
) )
530 remainder
= -remainder
;
535 quotient
= -quotient
;
539 wxLongLongWx
wxLongLongWx::operator/(const wxLongLongWx
& ll
) const
541 wxLongLongWx quotient
, remainder
;
543 Divide(ll
, quotient
, remainder
);
548 wxLongLongWx
& wxLongLongWx::operator/=(const wxLongLongWx
& ll
)
550 wxLongLongWx quotient
, remainder
;
552 Divide(ll
, quotient
, remainder
);
554 return *this = quotient
;
557 wxLongLongWx
wxLongLongWx::operator%(const wxLongLongWx
& ll
) const
559 wxLongLongWx quotient
, remainder
;
561 Divide(ll
, quotient
, remainder
);
566 // ----------------------------------------------------------------------------
568 // ----------------------------------------------------------------------------
570 // temporary - just for testing
571 void *wxLongLongWx::asArray(void) const
573 static unsigned char temp
[8];
575 temp
[0] = (m_hi
>> 24) & 0xFF;
576 temp
[1] = (m_hi
>> 16) & 0xFF;
577 temp
[2] = (m_hi
>> 8) & 0xFF;
578 temp
[3] = (m_hi
>> 0) & 0xFF;
579 temp
[4] = (m_lo
>> 24) & 0xFF;
580 temp
[5] = (m_lo
>> 16) & 0xFF;
581 temp
[6] = (m_lo
>> 8) & 0xFF;
582 temp
[7] = (m_lo
>> 0) & 0xFF;
587 #if wxUSE_STD_IOSTREAM
590 ostream
& operator<< (ostream
& o
, const wxLongLongWx
& ll
)
594 memset(result
, 'A', 64);
598 for (int i
= 0; i
< 32; i
++)
600 result
[31 - i
] = (char) ('0' + (int) ((ll
.m_hi
>> i
) & 1));
601 result
[63 - i
] = (char) ('0' + (int) ((ll
.m_lo
>> i
) & 1));
606 #endif // wxUSE_STD_IOSTREAM
608 #endif // wxUSE_LONGLONG_NATIVE
610 #endif // wxUSE_LONGLONG