]>
git.saurik.com Git - wxWidgets.git/blob - src/common/longlong.cpp
d85b5420fb4b017f5316c7ff7e3a9be8cd85bd45
   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 #include <memory.h>     // for memset() 
  32 #include <math.h>       // for fabs() 
  34 // ============================================================================ 
  36 // ============================================================================ 
  38 #if wxUSE_LONGLONG_NATIVE 
  40 // ---------------------------------------------------------------------------- 
  42 // ---------------------------------------------------------------------------- 
  44 void *wxLongLongNative::asArray() const 
  46     static unsigned char temp
[8]; 
  48     temp
[0] = (m_ll 
>> 56) & 0xFF; 
  49     temp
[1] = (m_ll 
>> 48) & 0xFF; 
  50     temp
[2] = (m_ll 
>> 40) & 0xFF; 
  51     temp
[3] = (m_ll 
>> 32) & 0xFF; 
  52     temp
[4] = (m_ll 
>> 24) & 0xFF; 
  53     temp
[5] = (m_ll 
>> 16) & 0xFF; 
  54     temp
[6] = (m_ll 
>> 8)  & 0xFF; 
  55     temp
[7] = (m_ll 
>> 0)  & 0xFF; 
  60 #if wxUSE_STD_IOSTREAM 
  63 ostream
& operator<< (ostream
& o
, const wxLongLongNative
& ll
) 
  67     memset(result
, 'A', 64); 
  71     for (int i 
= 0; i 
< 64; i
++) 
  73         result
[63 - i
] = '0' + (char) ((ll
.m_ll 
>> i
) & 1); 
  79 #endif // wxUSE_STD_IOSTREAM 
  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 wxLongLongWx
& wxLongLongWx::operator<<=(int shift
) 
 132             m_hi 
|= m_lo 
>> (32 - shift
); 
 137             m_hi 
= m_lo 
<< (shift 
- 32); 
 142 #ifdef wxLONGLONG_TEST_MODE 
 146 #endif // wxLONGLONG_TEST_MODE 
 151 wxLongLongWx 
wxLongLongWx::operator>>(int shift
) const 
 153     wxLongLongWx 
ll(*this); 
 159 wxLongLongWx
& wxLongLongWx::operator>>=(int shift
) 
 166             m_lo 
|= m_hi 
<< (32 - shift
); 
 171             m_lo 
= m_hi 
>> (shift 
- 32); 
 172             m_hi 
= (m_hi 
< 0 ? -1L : 0); 
 176 #ifdef wxLONGLONG_TEST_MODE 
 180 #endif // wxLONGLONG_TEST_MODE 
 185 wxLongLongWx 
wxLongLongWx::operator+(const wxLongLongWx
& ll
) const 
 187     wxLongLongWx 
res(*this); 
 193 wxLongLongWx 
wxLongLongWx::operator+(long l
) const 
 195     wxLongLongWx 
res(*this); 
 201 wxLongLongWx
& wxLongLongWx::operator+=(const wxLongLongWx
& ll
) 
 203     unsigned long previous 
= m_lo
; 
 208     if ((m_lo 
< previous
) || (m_lo 
< ll
.m_lo
)) 
 211 #ifdef wxLONGLONG_TEST_MODE 
 215 #endif // wxLONGLONG_TEST_MODE 
 220 wxLongLongWx
& wxLongLongWx::operator+=(long l
) 
 222     unsigned long previous 
= m_lo
; 
 228     if ((m_lo 
< previous
) || (m_lo 
< (unsigned long)l
)) 
 231 #ifdef wxLONGLONG_TEST_MODE 
 235 #endif // wxLONGLONG_TEST_MODE 
 241 wxLongLongWx
& wxLongLongWx::operator++() 
 247 #ifdef wxLONGLONG_TEST_MODE 
 251 #endif // wxLONGLONG_TEST_MODE 
 257 wxLongLongWx 
wxLongLongWx::operator-() const 
 259     wxLongLongWx 
res(*this); 
 265 wxLongLongWx
& wxLongLongWx::Negate() 
 274 #ifdef wxLONGLONG_TEST_MODE 
 278 #endif // wxLONGLONG_TEST_MODE 
 285 wxLongLongWx 
wxLongLongWx::operator-(const wxLongLongWx
& ll
) const 
 287     wxLongLongWx 
res(*this); 
 293 wxLongLongWx
& wxLongLongWx::operator-=(const wxLongLongWx
& ll
) 
 295     unsigned long previous 
= m_lo
; 
 300     if (previous 
< ll
.m_lo
) 
 303 #ifdef wxLONGLONG_TEST_MODE 
 307 #endif // wxLONGLONG_TEST_MODE 
 313 wxLongLongWx
& wxLongLongWx::operator--() 
 316     if (m_lo 
== 0xFFFFFFFF) 
 319 #ifdef wxLONGLONG_TEST_MODE 
 323 #endif // wxLONGLONG_TEST_MODE 
 328 // comparison operators 
 330 bool wxLongLongWx::operator<(const wxLongLongWx
& ll
) const 
 332     if ( m_hi 
< ll
.m_hi 
) 
 334     else if ( m_hi 
== ll
.m_hi 
) 
 335         return m_lo 
< ll
.m_lo
; 
 340 bool wxLongLongWx::operator>(const wxLongLongWx
& ll
) const 
 342     if ( m_hi 
> ll
.m_hi 
) 
 344     else if ( m_hi 
== ll
.m_hi 
) 
 345         return m_lo 
> ll
.m_lo
; 
 352 wxLongLongWx 
wxLongLongWx::operator&(const wxLongLongWx
& ll
) const 
 354     return wxLongLongWx(m_hi 
& ll
.m_hi
, m_lo 
& ll
.m_lo
); 
 357 wxLongLongWx 
wxLongLongWx::operator|(const wxLongLongWx
& ll
) const 
 359     return wxLongLongWx(m_hi 
| ll
.m_hi
, m_lo 
| ll
.m_lo
); 
 362 wxLongLongWx 
wxLongLongWx::operator^(const wxLongLongWx
& ll
) const 
 364     return wxLongLongWx(m_hi 
^ ll
.m_hi
, m_lo 
^ ll
.m_lo
); 
 367 wxLongLongWx
& wxLongLongWx::operator&=(const wxLongLongWx
& ll
) 
 372 #ifdef wxLONGLONG_TEST_MODE 
 376 #endif // wxLONGLONG_TEST_MODE 
 381 wxLongLongWx
& wxLongLongWx::operator|=(const wxLongLongWx
& ll
) 
 386 #ifdef wxLONGLONG_TEST_MODE 
 390 #endif // wxLONGLONG_TEST_MODE 
 395 wxLongLongWx
& wxLongLongWx::operator^=(const wxLongLongWx
& ll
) 
 400 #ifdef wxLONGLONG_TEST_MODE 
 404 #endif // wxLONGLONG_TEST_MODE 
 409 wxLongLongWx 
wxLongLongWx::operator~() const 
 411     return wxLongLongWx(~m_hi
, ~m_lo
); 
 416 wxLongLongWx 
wxLongLongWx::operator*(const wxLongLongWx
& ll
) const 
 418     wxLongLongWx 
res(*this); 
 424 wxLongLongWx
& wxLongLongWx::operator*=(const wxLongLongWx
& ll
) 
 426     wxLongLongWx 
t(m_hi
, m_lo
); 
 427     wxLongLongWx 
q(ll
.m_hi
, ll
.m_lo
); 
 431 #ifdef wxLONGLONG_TEST_MODE 
 432     wxLongLong_t llOld 
= m_ll
; 
 434 #endif // wxLONGLONG_TEST_MODE 
 439         if ((q
.m_lo 
& 1) != 0) 
 445     while ((counter 
< 64) && ((q
.m_hi 
!= 0) || (q
.m_lo 
!= 0))); 
 447 #ifdef wxLONGLONG_TEST_MODE 
 448     m_ll 
= llOld 
* ll
.m_ll
; 
 451 #endif // wxLONGLONG_TEST_MODE 
 458 void wxLongLongWx::Divide(const wxLongLongWx
& divisorIn
, 
 459                           wxLongLongWx
& quotient
, 
 460                           wxLongLongWx
& remainder
) const 
 462     if ((divisorIn
.m_lo 
== 0) && (divisorIn
.m_hi 
== 0)) 
 464         // provoke division by zero error and silence the compilers warnings 
 465         // about an expression without effect and unused variable 
 466         long dummy 
= divisorIn
.m_lo
/divisorIn
.m_hi
; 
 470     // VZ: I'm writing this in a hurry and it's surely not the fastest way to 
 471     //     do this - any improvements are more than welcome 
 473     //     code inspired by the snippet at 
 474     //          http://www.bearcave.com/software/divide.htm 
 478     //     Use of this program, for any purpose, is granted the author, Ian 
 479     //     Kaplan, as long as this copyright notice is included in the source 
 480     //     code or any source code derived from this program. The user assumes 
 481     //     all responsibility for using this code.  
 484     wxLongLongWx dividend 
= *this, 
 490     // always do unsigned division and adjust the signs later: in C integer 
 491     // division, the sign of the remainder is the same as the sign of the 
 492     // dividend, while the sign of the quotient is the product of the signs of 
 493     // the dividend and divisor. Of course, we also always have 
 495     //      dividend = quotient*divisor + remainder 
 497     // with 0 <= abs(remainder) < abs(divisor) 
 498     bool negRemainder 
= dividend
.m_hi 
< 0; 
 499     bool negQuotient 
= FALSE
;   // assume positive 
 500     if ( dividend
.m_hi 
< 0 ) 
 502         negQuotient 
= !negQuotient
; 
 503         dividend 
= -dividend
; 
 505     if ( divisor
.m_hi 
< 0 ) 
 507         negQuotient 
= !negQuotient
; 
 511     // check for some particular cases 
 512     if ( divisor 
> dividend 
) 
 514         remainder 
= dividend
; 
 516     else if ( divisor 
== dividend 
) 
 522         // here: dividend > divisor and both are positibe: do unsigned division 
 526         #define IS_MSB_SET(ll)  ((ll.m_hi) & (1 << (8*sizeof(long) - 1))) 
 528         while ( remainder 
< divisor 
) 
 531             if ( IS_MSB_SET(dividend
) ) 
 542         // undo the last loop iteration 
 547         for ( size_t i 
= 0; i 
< nBits
; i
++ ) 
 550             if ( IS_MSB_SET(dividend
) ) 
 555             wxLongLongWx t 
= remainder 
- divisor
; 
 558             if ( !IS_MSB_SET(t
) ) 
 570         remainder 
= -remainder
; 
 575         quotient 
= -quotient
; 
 579 wxLongLongWx 
wxLongLongWx::operator/(const wxLongLongWx
& ll
) const 
 581     wxLongLongWx quotient
, remainder
; 
 583     Divide(ll
, quotient
, remainder
); 
 588 wxLongLongWx
& wxLongLongWx::operator/=(const wxLongLongWx
& ll
) 
 590     wxLongLongWx quotient
, remainder
; 
 592     Divide(ll
, quotient
, remainder
); 
 599 wxLongLongWx 
wxLongLongWx::operator%(const wxLongLongWx
& ll
) const 
 601     wxLongLongWx quotient
, remainder
; 
 603     Divide(ll
, quotient
, remainder
); 
 608 // ---------------------------------------------------------------------------- 
 610 // ---------------------------------------------------------------------------- 
 612 // temporary - just for testing 
 613 void *wxLongLongWx::asArray(void) const 
 615     static unsigned char temp
[8]; 
 617     temp
[0] = (char)((m_hi 
>> 24) & 0xFF); 
 618     temp
[1] = (char)((m_hi 
>> 16) & 0xFF); 
 619     temp
[2] = (char)((m_hi 
>> 8)  & 0xFF); 
 620     temp
[3] = (char)((m_hi 
>> 0)  & 0xFF); 
 621     temp
[4] = (char)((m_lo 
>> 24) & 0xFF); 
 622     temp
[5] = (char)((m_lo 
>> 16) & 0xFF); 
 623     temp
[6] = (char)((m_lo 
>> 8)  & 0xFF); 
 624     temp
[7] = (char)((m_lo 
>> 0)  & 0xFF); 
 629 #if wxUSE_STD_IOSTREAM 
 632 ostream
& operator<< (ostream
& o
, const wxLongLongWx
& ll
) 
 636     memset(result
, 'A', 64); 
 640     for (int i 
= 0; i 
< 32; i
++) 
 642         result
[31 - i
] = (char) ('0' + (int) ((ll
.m_hi 
>> i
) & 1)); 
 643         result
[63 - i
] = (char) ('0' + (int) ((ll
.m_lo 
>> i
) & 1)); 
 648 #endif // wxUSE_STD_IOSTREAM 
 650 #endif // wxUSE_LONGLONG_NATIVE 
 652 #endif // wxUSE_LONGLONG