]>
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 #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 #endif // wxUSE_LONGLONG_NATIVE 
  62 // ============================================================================ 
  63 // wxLongLongWx: emulation of 'long long' using 2 longs 
  64 // ============================================================================ 
  69 wxLongLongWx
& wxLongLongWx::Assign(double d
) 
  71     bool positive 
= d 
>= 0; 
  80         m_hi 
= (unsigned long)(d 
/ (1.0 + (double)ULONG_MAX
)); 
  81         m_lo 
= (unsigned long)(d 
- ((double)m_hi 
* (1.0 + (double)ULONG_MAX
))); 
  84 #ifdef wxLONGLONG_TEST_MODE 
  85     m_ll 
= (wxLongLong_t
)d
; 
  88 #endif // wxLONGLONG_TEST_MODE 
  96 wxLongLongWx 
wxLongLongWx::operator<<(int shift
) const 
  98     wxLongLongWx 
ll(*this); 
 104 wxLongLongWx
& wxLongLongWx::operator<<=(int shift
) 
 111             m_hi 
|= m_lo 
>> (32 - shift
); 
 116             m_hi 
= m_lo 
<< (shift 
- 32); 
 121 #ifdef wxLONGLONG_TEST_MODE 
 125 #endif // wxLONGLONG_TEST_MODE 
 130 wxLongLongWx 
wxLongLongWx::operator>>(int shift
) const 
 132     wxLongLongWx 
ll(*this); 
 138 wxLongLongWx
& wxLongLongWx::operator>>=(int shift
) 
 145             m_lo 
|= m_hi 
<< (32 - shift
); 
 150             m_lo 
= m_hi 
>> (shift 
- 32); 
 151             m_hi 
= (m_hi 
< 0 ? -1L : 0); 
 155 #ifdef wxLONGLONG_TEST_MODE 
 159 #endif // wxLONGLONG_TEST_MODE 
 164 wxLongLongWx 
wxLongLongWx::operator+(const wxLongLongWx
& ll
) const 
 166     wxLongLongWx 
res(*this); 
 172 wxLongLongWx 
wxLongLongWx::operator+(long l
) const 
 174     wxLongLongWx 
res(*this); 
 180 wxLongLongWx
& wxLongLongWx::operator+=(const wxLongLongWx
& ll
) 
 182     unsigned long previous 
= m_lo
; 
 187     if ((m_lo 
< previous
) || (m_lo 
< ll
.m_lo
)) 
 190 #ifdef wxLONGLONG_TEST_MODE 
 194 #endif // wxLONGLONG_TEST_MODE 
 199 wxLongLongWx
& wxLongLongWx::operator+=(long l
) 
 201     unsigned long previous 
= m_lo
; 
 207     if ((m_lo 
< previous
) || (m_lo 
< (unsigned long)l
)) 
 210 #ifdef wxLONGLONG_TEST_MODE 
 214 #endif // wxLONGLONG_TEST_MODE 
 220 wxLongLongWx
& wxLongLongWx::operator++() 
 226 #ifdef wxLONGLONG_TEST_MODE 
 230 #endif // wxLONGLONG_TEST_MODE 
 236 wxLongLongWx 
wxLongLongWx::operator-() const 
 238     wxLongLongWx 
res(*this); 
 244 wxLongLongWx
& wxLongLongWx::Negate() 
 253 #ifdef wxLONGLONG_TEST_MODE 
 257 #endif // wxLONGLONG_TEST_MODE 
 264 wxLongLongWx 
wxLongLongWx::operator-(const wxLongLongWx
& ll
) const 
 266     wxLongLongWx 
res(*this); 
 272 wxLongLongWx
& wxLongLongWx::operator-=(const wxLongLongWx
& ll
) 
 274     unsigned long previous 
= m_lo
; 
 279     if (previous 
< ll
.m_lo
) 
 282 #ifdef wxLONGLONG_TEST_MODE 
 286 #endif // wxLONGLONG_TEST_MODE 
 292 wxLongLongWx
& wxLongLongWx::operator--() 
 295     if (m_lo 
== 0xFFFFFFFF) 
 298 #ifdef wxLONGLONG_TEST_MODE 
 302 #endif // wxLONGLONG_TEST_MODE 
 307 // comparison operators 
 309 bool wxLongLongWx::operator<(const wxLongLongWx
& ll
) const 
 311     if ( m_hi 
< ll
.m_hi 
) 
 313     else if ( m_hi 
== ll
.m_hi 
) 
 314         return m_lo 
< ll
.m_lo
; 
 319 bool wxLongLongWx::operator>(const wxLongLongWx
& ll
) const 
 321     if ( m_hi 
> ll
.m_hi 
) 
 323     else if ( m_hi 
== ll
.m_hi 
) 
 324         return m_lo 
> ll
.m_lo
; 
 331 wxLongLongWx 
wxLongLongWx::operator&(const wxLongLongWx
& ll
) const 
 333     return wxLongLongWx(m_hi 
& ll
.m_hi
, 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
) 
 351 #ifdef wxLONGLONG_TEST_MODE 
 355 #endif // wxLONGLONG_TEST_MODE 
 360 wxLongLongWx
& wxLongLongWx::operator|=(const wxLongLongWx
& ll
) 
 365 #ifdef wxLONGLONG_TEST_MODE 
 369 #endif // wxLONGLONG_TEST_MODE 
 374 wxLongLongWx
& wxLongLongWx::operator^=(const wxLongLongWx
& ll
) 
 379 #ifdef wxLONGLONG_TEST_MODE 
 383 #endif // wxLONGLONG_TEST_MODE 
 388 wxLongLongWx 
wxLongLongWx::operator~() const 
 390     return wxLongLongWx(~m_hi
, ~m_lo
); 
 395 wxLongLongWx 
wxLongLongWx::operator*(const wxLongLongWx
& ll
) const 
 397     wxLongLongWx 
res(*this); 
 403 wxLongLongWx
& wxLongLongWx::operator*=(const wxLongLongWx
& ll
) 
 405     wxLongLongWx 
t(m_hi
, m_lo
); 
 406     wxLongLongWx 
q(ll
.m_hi
, ll
.m_lo
); 
 410 #ifdef wxLONGLONG_TEST_MODE 
 411     wxLongLong_t llOld 
= m_ll
; 
 413 #endif // wxLONGLONG_TEST_MODE 
 418         if ((q
.m_lo 
& 1) != 0) 
 424     while ((counter 
< 64) && ((q
.m_hi 
!= 0) || (q
.m_lo 
!= 0))); 
 426 #ifdef wxLONGLONG_TEST_MODE 
 427     m_ll 
= llOld 
* ll
.m_ll
; 
 430 #endif // wxLONGLONG_TEST_MODE 
 437 void wxLongLongWx::Divide(const wxLongLongWx
& divisorIn
, 
 438                           wxLongLongWx
& quotient
, 
 439                           wxLongLongWx
& remainder
) const 
 441     if ((divisorIn
.m_lo 
== 0) && (divisorIn
.m_hi 
== 0)) 
 443         // provoke division by zero error and silence the compilers warnings 
 444         // about an expression without effect and unused variable 
 445         long dummy 
= divisorIn
.m_lo
/divisorIn
.m_hi
; 
 449     // VZ: I'm writing this in a hurry and it's surely not the fastest way to 
 450     //     do this - any improvements are more than welcome 
 452     //     code inspired by the snippet at 
 453     //          http://www.bearcave.com/software/divide.htm 
 457     //     Use of this program, for any purpose, is granted the author, Ian 
 458     //     Kaplan, as long as this copyright notice is included in the source 
 459     //     code or any source code derived from this program. The user assumes 
 460     //     all responsibility for using this code. 
 463     wxLongLongWx dividend 
= *this, 
 469     // always do unsigned division and adjust the signs later: in C integer 
 470     // division, the sign of the remainder is the same as the sign of the 
 471     // dividend, while the sign of the quotient is the product of the signs of 
 472     // the dividend and divisor. Of course, we also always have 
 474     //      dividend = quotient*divisor + remainder 
 476     // with 0 <= abs(remainder) < abs(divisor) 
 477     bool negRemainder 
= dividend
.m_hi 
< 0; 
 478     bool negQuotient 
= FALSE
;   // assume positive 
 479     if ( dividend
.m_hi 
< 0 ) 
 481         negQuotient 
= !negQuotient
; 
 482         dividend 
= -dividend
; 
 484     if ( divisor
.m_hi 
< 0 ) 
 486         negQuotient 
= !negQuotient
; 
 490     // check for some particular cases 
 491     if ( divisor 
> dividend 
) 
 493         remainder 
= dividend
; 
 495     else if ( divisor 
== dividend 
) 
 501         // here: dividend > divisor and both are positibe: do unsigned division 
 505         #define IS_MSB_SET(ll)  ((ll.m_hi) & (1 << (8*sizeof(long) - 1))) 
 507         while ( remainder 
< divisor 
) 
 510             if ( IS_MSB_SET(dividend
) ) 
 521         // undo the last loop iteration 
 526         for ( size_t i 
= 0; i 
< nBits
; i
++ ) 
 529             if ( IS_MSB_SET(dividend
) ) 
 534             wxLongLongWx t 
= remainder 
- divisor
; 
 537             if ( !IS_MSB_SET(t
) ) 
 549         remainder 
= -remainder
; 
 554         quotient 
= -quotient
; 
 558 wxLongLongWx 
wxLongLongWx::operator/(const wxLongLongWx
& ll
) const 
 560     wxLongLongWx quotient
, remainder
; 
 562     Divide(ll
, quotient
, remainder
); 
 567 wxLongLongWx
& wxLongLongWx::operator/=(const wxLongLongWx
& ll
) 
 569     wxLongLongWx quotient
, remainder
; 
 571     Divide(ll
, quotient
, remainder
); 
 578 wxLongLongWx 
wxLongLongWx::operator%(const wxLongLongWx
& ll
) const 
 580     wxLongLongWx quotient
, remainder
; 
 582     Divide(ll
, quotient
, remainder
); 
 587 // ---------------------------------------------------------------------------- 
 589 // ---------------------------------------------------------------------------- 
 591 // temporary - just for testing 
 592 void *wxLongLongWx::asArray(void) const 
 594     static unsigned char temp
[8]; 
 596     temp
[0] = (char)((m_hi 
>> 24) & 0xFF); 
 597     temp
[1] = (char)((m_hi 
>> 16) & 0xFF); 
 598     temp
[2] = (char)((m_hi 
>> 8)  & 0xFF); 
 599     temp
[3] = (char)((m_hi 
>> 0)  & 0xFF); 
 600     temp
[4] = (char)((m_lo 
>> 24) & 0xFF); 
 601     temp
[5] = (char)((m_lo 
>> 16) & 0xFF); 
 602     temp
[6] = (char)((m_lo 
>> 8)  & 0xFF); 
 603     temp
[7] = (char)((m_lo 
>> 0)  & 0xFF); 
 608 #endif // wxUSE_LONGLONG_WX 
 611 #if wxUSE_LONGLONG_NATIVE 
 612 wxLongLongNative::ToString() const 
 614 wxLongLongWx::ToString() const 
 617     // TODO: this is awfully inefficient, anything better? 
 620     wxLongLong ll 
= *this; 
 635         result
.Prepend((wxChar
)(_T('0') + (ll 
% 10).ToLong())); 
 639     if ( result
.empty() ) 
 642         result
.Prepend(_T('-')); 
 647 #if wxUSE_STD_IOSTREAM 
 650 wxSTD ostream
& operator<< (wxSTD ostream
& o
, const wxLongLong
& ll
) 
 652     return o 
<< ll
.ToString(); 
 655 #endif // wxUSE_STD_IOSTREAM 
 657 #endif // wxUSE_LONGLONG