1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/common/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.
7 // Modified by:
8 // Created:     10.02.99
9 // RCS-ID:      $Id: longlong.cpp 40750 2006-08-22 19:04:45Z MW $
10 // Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
11 // Licence:     wxWindows licence
12 /////////////////////////////////////////////////////////////////////////////
13 
14 // ============================================================================
15 // headers
16 // ============================================================================
17 
18 #include "wx/wxprec.h"
19 
20 #ifdef __BORLANDC__
21     #pragma hdrstop
22 #endif
23 
24 #if wxUSE_LONGLONG
25 
26 #include "wx/longlong.h"
27 
28 #ifndef WX_PRECOMP
29     #include "wx/math.h"       // for fabs()
30 #endif
31 
32 #if wxUSE_STREAMS
33     #include "wx/txtstrm.h"
34 #endif
35 
36 #include <string.h>            // for memset()
37 
38 #include "wx/ioswrap.h"
39 
40 // ============================================================================
41 // implementation
42 // ============================================================================
43 
44 #if wxUSE_LONGLONG_NATIVE
45 
46 // ----------------------------------------------------------------------------
47 // misc
48 // ----------------------------------------------------------------------------
49 
asArray() const50 void *wxLongLongNative::asArray() const
51 {
52     static unsigned char temp[8];
53 
54     temp[0] = wx_truncate_cast(unsigned char, ((m_ll >> 56) & 0xFF));
55     temp[1] = wx_truncate_cast(unsigned char, ((m_ll >> 48) & 0xFF));
56     temp[2] = wx_truncate_cast(unsigned char, ((m_ll >> 40) & 0xFF));
57     temp[3] = wx_truncate_cast(unsigned char, ((m_ll >> 32) & 0xFF));
58     temp[4] = wx_truncate_cast(unsigned char, ((m_ll >> 24) & 0xFF));
59     temp[5] = wx_truncate_cast(unsigned char, ((m_ll >> 16) & 0xFF));
60     temp[6] = wx_truncate_cast(unsigned char, ((m_ll >> 8)  & 0xFF));
61     temp[7] = wx_truncate_cast(unsigned char, ((m_ll >> 0)  & 0xFF));
62 
63     return temp;
64 }
65 
asArray() const66 void *wxULongLongNative::asArray() const
67 {
68     static unsigned char temp[8];
69 
70     temp[0] = wx_truncate_cast(unsigned char, ((m_ll >> 56) & 0xFF));
71     temp[1] = wx_truncate_cast(unsigned char, ((m_ll >> 48) & 0xFF));
72     temp[2] = wx_truncate_cast(unsigned char, ((m_ll >> 40) & 0xFF));
73     temp[3] = wx_truncate_cast(unsigned char, ((m_ll >> 32) & 0xFF));
74     temp[4] = wx_truncate_cast(unsigned char, ((m_ll >> 24) & 0xFF));
75     temp[5] = wx_truncate_cast(unsigned char, ((m_ll >> 16) & 0xFF));
76     temp[6] = wx_truncate_cast(unsigned char, ((m_ll >> 8)  & 0xFF));
77     temp[7] = wx_truncate_cast(unsigned char, ((m_ll >> 0)  & 0xFF));
78 
79     return temp;
80 }
81 
82 #if wxUSE_LONGLONG_WX
wxLongLongNative(wxLongLongWx ll)83 wxLongLongNative::wxLongLongNative(wxLongLongWx ll)
84 {
85     // assign first to avoid precision loss!
86     m_ll = ll.GetHi();
87     m_ll <<= 32;
88     m_ll |= ll.GetLo();
89 }
90 
operator =(wxLongLongWx ll)91 wxLongLongNative& wxLongLongNative::operator=(wxLongLongWx ll)
92 {
93     // assign first to avoid precision loss!
94     m_ll = ll.GetHi();
95     m_ll <<= 32;
96     m_ll |= ll.GetLo();
97     return *this;
98 }
99 
operator =(const class wxULongLongWx & ll)100 wxLongLongNative& wxLongLongNative::operator=(const class wxULongLongWx &ll)
101 {
102     // assign first to avoid precision loss!
103     m_ll = ll.GetHi();
104     m_ll <<= 32;
105     m_ll |= ll.GetLo();
106     return *this;
107 }
108 
wxULongLongNative(const class wxULongLongWx & ll)109 wxULongLongNative::wxULongLongNative(const class wxULongLongWx &ll)
110 {
111     // assign first to avoid precision loss!
112     m_ll = ll.GetHi();
113     m_ll <<= 32;
114     m_ll |= ((unsigned long) ll.GetLo());
115 }
116 
operator =(wxLongLongWx ll)117 wxULongLongNative& wxULongLongNative::operator=(wxLongLongWx ll)
118 {
119     // assign first to avoid precision loss!
120     m_ll = ll.GetHi();
121     m_ll <<= 32;
122     m_ll |= ((unsigned long) ll.GetLo());
123     return *this;
124 }
125 
operator =(const class wxULongLongWx & ll)126 wxULongLongNative& wxULongLongNative::operator=(const class wxULongLongWx &ll)
127 {
128     // assign first to avoid precision loss!
129     m_ll = ll.GetHi();
130     m_ll <<= 32;
131     m_ll |= ((unsigned long) ll.GetLo());
132     return *this;
133 }
134 #endif
135 
136 #endif // wxUSE_LONGLONG_NATIVE
137 
138 // ============================================================================
139 // wxLongLongWx: emulation of 'long long' using 2 longs
140 // ============================================================================
141 
142 #if wxUSE_LONGLONG_WX
143 
144 // Set value from unsigned wxULongLongWx
operator =(const class wxULongLongWx & ll)145 wxLongLongWx &wxLongLongWx::operator=(const class wxULongLongWx &ll)
146 {
147     m_hi = (unsigned long) ll.GetHi();
148     m_lo = ll.GetLo();
149     return *this;
150 }
151 
152 // assignment
Assign(double d)153 wxLongLongWx& wxLongLongWx::Assign(double d)
154 {
155     bool positive = d >= 0;
156     d = fabs(d);
157     if ( d <= ULONG_MAX )
158     {
159         m_hi = 0;
160         m_lo = (long)d;
161     }
162     else
163     {
164         m_hi = (unsigned long)(d / (1.0 + (double)ULONG_MAX));
165         m_lo = (unsigned long)(d - ((double)m_hi * (1.0 + (double)ULONG_MAX)));
166     }
167 
168 #ifdef wxLONGLONG_TEST_MODE
169     m_ll = (wxLongLong_t)d;
170 
171     Check();
172 #endif // wxLONGLONG_TEST_MODE
173 
174     if ( !positive )
175         Negate();
176 
177     return *this;
178 }
179 
ToDouble() const180 double wxLongLongWx::ToDouble() const
181 {
182     double d = m_hi;
183     d *= 1.0 + (double)ULONG_MAX;
184     d += m_lo;
185 
186 #ifdef wxLONGLONG_TEST_MODE
187     wxASSERT( d == m_ll );
188 #endif // wxLONGLONG_TEST_MODE
189 
190     return d;
191 }
192 
ToDouble() const193 double wxULongLongWx::ToDouble() const
194 {
195     unsigned double d = m_hi;
196     d *= 1.0 + (double)ULONG_MAX;
197     d += m_lo;
198 
199 #ifdef wxLONGLONG_TEST_MODE
200     wxASSERT( d == m_ll );
201 #endif // wxLONGLONG_TEST_MODE
202 
203     return d;
204 }
205 
operator <<(int shift) const206 wxLongLongWx wxLongLongWx::operator<<(int shift) const
207 {
208     wxLongLongWx ll(*this);
209     ll <<= shift;
210 
211     return ll;
212 }
213 
operator <<(int shift) const214 wxULongLongWx wxULongLongWx::operator<<(int shift) const
215 {
216     wxULongLongWx ll(*this);
217     ll <<= shift;
218 
219     return ll;
220 }
221 
operator <<=(int shift)222 wxLongLongWx& wxLongLongWx::operator<<=(int shift)
223 {
224     if (shift != 0)
225     {
226         if (shift < 32)
227         {
228             m_hi <<= shift;
229             m_hi |= m_lo >> (32 - shift);
230             m_lo <<= shift;
231         }
232         else
233         {
234             m_hi = m_lo << (shift - 32);
235             m_lo = 0;
236         }
237     }
238 
239 #ifdef wxLONGLONG_TEST_MODE
240     m_ll <<= shift;
241 
242     Check();
243 #endif // wxLONGLONG_TEST_MODE
244 
245     return *this;
246 }
247 
operator <<=(int shift)248 wxULongLongWx& wxULongLongWx::operator<<=(int shift)
249 {
250     if (shift != 0)
251     {
252         if (shift < 32)
253         {
254             m_hi <<= shift;
255             m_hi |= m_lo >> (32 - shift);
256             m_lo <<= shift;
257         }
258         else
259         {
260             m_hi = m_lo << (shift - 32);
261             m_lo = 0;
262         }
263     }
264 
265 #ifdef wxLONGLONG_TEST_MODE
266     m_ll <<= shift;
267 
268     Check();
269 #endif // wxLONGLONG_TEST_MODE
270 
271     return *this;
272 }
273 
operator >>(int shift) const274 wxLongLongWx wxLongLongWx::operator>>(int shift) const
275 {
276     wxLongLongWx ll(*this);
277     ll >>= shift;
278 
279     return ll;
280 }
281 
operator >>(int shift) const282 wxULongLongWx wxULongLongWx::operator>>(int shift) const
283 {
284     wxULongLongWx ll(*this);
285     ll >>= shift;
286 
287     return ll;
288 }
289 
operator >>=(int shift)290 wxLongLongWx& wxLongLongWx::operator>>=(int shift)
291 {
292     if (shift != 0)
293     {
294         if (shift < 32)
295         {
296             m_lo >>= shift;
297             m_lo |= m_hi << (32 - shift);
298             m_hi >>= shift;
299         }
300         else
301         {
302             m_lo = m_hi >> (shift - 32);
303             m_hi = (m_hi < 0 ? -1L : 0);
304         }
305     }
306 
307 #ifdef wxLONGLONG_TEST_MODE
308     m_ll >>= shift;
309 
310     Check();
311 #endif // wxLONGLONG_TEST_MODE
312 
313     return *this;
314 }
315 
operator >>=(int shift)316 wxULongLongWx& wxULongLongWx::operator>>=(int shift)
317 {
318     if (shift != 0)
319     {
320         if (shift < 32)
321         {
322             m_lo >>= shift;
323             m_lo |= m_hi << (32 - shift);
324             m_hi >>= shift;
325         }
326         else
327         {
328             m_lo = m_hi >> (shift - 32);
329             m_hi = 0;
330         }
331     }
332 
333 #ifdef wxLONGLONG_TEST_MODE
334     m_ll >>= shift;
335 
336     Check();
337 #endif // wxLONGLONG_TEST_MODE
338 
339     return *this;
340 }
341 
operator +(const wxLongLongWx & ll) const342 wxLongLongWx wxLongLongWx::operator+(const wxLongLongWx& ll) const
343 {
344     wxLongLongWx res(*this);
345     res += ll;
346 
347     return res;
348 }
349 
operator +(const wxULongLongWx & ll) const350 wxULongLongWx wxULongLongWx::operator+(const wxULongLongWx& ll) const
351 {
352     wxULongLongWx res(*this);
353     res += ll;
354 
355     return res;
356 }
357 
operator +(long l) const358 wxLongLongWx wxLongLongWx::operator+(long l) const
359 {
360     wxLongLongWx res(*this);
361     res += l;
362 
363     return res;
364 }
365 
operator +(unsigned long l) const366 wxULongLongWx wxULongLongWx::operator+(unsigned long l) const
367 {
368     wxULongLongWx res(*this);
369     res += l;
370 
371     return res;
372 }
373 
operator +=(const wxLongLongWx & ll)374 wxLongLongWx& wxLongLongWx::operator+=(const wxLongLongWx& ll)
375 {
376     unsigned long previous = m_lo;
377 
378     m_lo += ll.m_lo;
379     m_hi += ll.m_hi;
380 
381     if ((m_lo < previous) || (m_lo < ll.m_lo))
382         m_hi++;
383 
384 #ifdef wxLONGLONG_TEST_MODE
385     m_ll += ll.m_ll;
386 
387     Check();
388 #endif // wxLONGLONG_TEST_MODE
389 
390     return *this;
391 }
392 
operator +=(const wxULongLongWx & ll)393 wxULongLongWx& wxULongLongWx::operator+=(const wxULongLongWx& ll)
394 {
395     unsigned long previous = m_lo;
396 
397     m_lo += ll.m_lo;
398     m_hi += ll.m_hi;
399 
400     if ((m_lo < previous) || (m_lo < ll.m_lo))
401         m_hi++;
402 
403 #ifdef wxLONGLONG_TEST_MODE
404     m_ll += ll.m_ll;
405 
406     Check();
407 #endif // wxLONGLONG_TEST_MODE
408 
409     return *this;
410 }
411 
operator +=(long l)412 wxLongLongWx& wxLongLongWx::operator+=(long l)
413 {
414     unsigned long previous = m_lo;
415 
416     m_lo += l;
417     if (l < 0)
418         m_hi += -1l;
419 
420     if ((m_lo < previous) || (m_lo < (unsigned long)l))
421         m_hi++;
422 
423 #ifdef wxLONGLONG_TEST_MODE
424     m_ll += l;
425 
426     Check();
427 #endif // wxLONGLONG_TEST_MODE
428 
429     return *this;
430 }
431 
operator +=(unsigned long l)432 wxULongLongWx& wxULongLongWx::operator+=(unsigned long l)
433 {
434     unsigned long previous = m_lo;
435 
436     m_lo += l;
437 
438     if ((m_lo < previous) || (m_lo < l))
439         m_hi++;
440 
441 #ifdef wxLONGLONG_TEST_MODE
442     m_ll += l;
443 
444     Check();
445 #endif // wxLONGLONG_TEST_MODE
446 
447     return *this;
448 }
449 
450 // pre increment
operator ++()451 wxLongLongWx& wxLongLongWx::operator++()
452 {
453     m_lo++;
454     if (m_lo == 0)
455         m_hi++;
456 
457 #ifdef wxLONGLONG_TEST_MODE
458     m_ll++;
459 
460     Check();
461 #endif // wxLONGLONG_TEST_MODE
462 
463     return *this;
464 }
465 
operator ++()466 wxULongLongWx& wxULongLongWx::operator++()
467 {
468     m_lo++;
469     if (m_lo == 0)
470         m_hi++;
471 
472 #ifdef wxLONGLONG_TEST_MODE
473     m_ll++;
474 
475     Check();
476 #endif // wxLONGLONG_TEST_MODE
477 
478     return *this;
479 }
480 
481 // negation
operator -() const482 wxLongLongWx wxLongLongWx::operator-() const
483 {
484     wxLongLongWx res(*this);
485     res.Negate();
486 
487     return res;
488 }
489 
Negate()490 wxLongLongWx& wxLongLongWx::Negate()
491 {
492     m_hi = ~m_hi;
493     m_lo = ~m_lo;
494 
495     m_lo++;
496     if ( m_lo == 0 )
497         m_hi++;
498 
499 #ifdef wxLONGLONG_TEST_MODE
500     m_ll = -m_ll;
501 
502     Check();
503 #endif // wxLONGLONG_TEST_MODE
504 
505     return *this;
506 }
507 
508 // subtraction
509 
operator -(const wxLongLongWx & ll) const510 wxLongLongWx wxLongLongWx::operator-(const wxLongLongWx& ll) const
511 {
512     wxLongLongWx res(*this);
513     res -= ll;
514 
515     return res;
516 }
517 
operator -(const wxULongLongWx & ll) const518 wxLongLongWx wxULongLongWx::operator-(const wxULongLongWx& ll) const
519 {
520     wxASSERT(m_hi <= LONG_MAX );
521     wxASSERT(ll.m_hi <= LONG_MAX );
522 
523     wxLongLongWx res( (long)m_hi , m_lo );
524     wxLongLongWx op( (long)ll.m_hi , ll.m_lo );
525     res -= op;
526 
527     return res;
528 }
529 
operator -=(const wxLongLongWx & ll)530 wxLongLongWx& wxLongLongWx::operator-=(const wxLongLongWx& ll)
531 {
532     unsigned long previous = m_lo;
533 
534     m_lo -= ll.m_lo;
535     m_hi -= ll.m_hi;
536 
537     if (previous < ll.m_lo)
538         m_hi--;
539 
540 #ifdef wxLONGLONG_TEST_MODE
541     m_ll -= ll.m_ll;
542 
543     Check();
544 #endif // wxLONGLONG_TEST_MODE
545 
546     return *this;
547 }
548 
operator -=(const wxULongLongWx & ll)549 wxULongLongWx& wxULongLongWx::operator-=(const wxULongLongWx& ll)
550 {
551     unsigned long previous = m_lo;
552 
553     m_lo -= ll.m_lo;
554     m_hi -= ll.m_hi;
555 
556     if (previous < ll.m_lo)
557         m_hi--;
558 
559 #ifdef wxLONGLONG_TEST_MODE
560     m_ll -= ll.m_ll;
561 
562     Check();
563 #endif // wxLONGLONG_TEST_MODE
564 
565     return *this;
566 }
567 
568 // pre decrement
operator --()569 wxLongLongWx& wxLongLongWx::operator--()
570 {
571     m_lo--;
572     if (m_lo == 0xFFFFFFFF)
573         m_hi--;
574 
575 #ifdef wxLONGLONG_TEST_MODE
576     m_ll--;
577 
578     Check();
579 #endif // wxLONGLONG_TEST_MODE
580 
581     return *this;
582 }
583 
operator --()584 wxULongLongWx& wxULongLongWx::operator--()
585 {
586     m_lo--;
587     if (m_lo == 0xFFFFFFFF)
588         m_hi--;
589 
590 #ifdef wxLONGLONG_TEST_MODE
591     m_ll--;
592 
593     Check();
594 #endif // wxLONGLONG_TEST_MODE
595 
596     return *this;
597 }
598 
599 // comparison operators
600 
operator <(const wxLongLongWx & ll) const601 bool wxLongLongWx::operator<(const wxLongLongWx& ll) const
602 {
603     if ( m_hi < ll.m_hi )
604         return true;
605     else if ( m_hi == ll.m_hi )
606         return m_lo < ll.m_lo;
607     else
608         return false;
609 }
610 
operator <(const wxULongLongWx & ll) const611 bool wxULongLongWx::operator<(const wxULongLongWx& ll) const
612 {
613     if ( m_hi < ll.m_hi )
614         return true;
615     else if ( m_hi == ll.m_hi )
616         return m_lo < ll.m_lo;
617     else
618         return false;
619 }
620 
operator >(const wxLongLongWx & ll) const621 bool wxLongLongWx::operator>(const wxLongLongWx& ll) const
622 {
623     if ( m_hi > ll.m_hi )
624         return true;
625     else if ( m_hi == ll.m_hi )
626         return m_lo > ll.m_lo;
627     else
628         return false;
629 }
630 
operator >(const wxULongLongWx & ll) const631 bool wxULongLongWx::operator>(const wxULongLongWx& ll) const
632 {
633     if ( m_hi > ll.m_hi )
634         return true;
635     else if ( m_hi == ll.m_hi )
636         return m_lo > ll.m_lo;
637     else
638         return false;
639 }
640 
641 // bitwise operators
642 
operator &(const wxLongLongWx & ll) const643 wxLongLongWx wxLongLongWx::operator&(const wxLongLongWx& ll) const
644 {
645     return wxLongLongWx(m_hi & ll.m_hi, m_lo & ll.m_lo);
646 }
647 
operator &(const wxULongLongWx & ll) const648 wxULongLongWx wxULongLongWx::operator&(const wxULongLongWx& ll) const
649 {
650     return wxULongLongWx(m_hi & ll.m_hi, m_lo & ll.m_lo);
651 }
652 
operator |(const wxLongLongWx & ll) const653 wxLongLongWx wxLongLongWx::operator|(const wxLongLongWx& ll) const
654 {
655     return wxLongLongWx(m_hi | ll.m_hi, m_lo | ll.m_lo);
656 }
657 
operator |(const wxULongLongWx & ll) const658 wxULongLongWx wxULongLongWx::operator|(const wxULongLongWx& ll) const
659 {
660     return wxULongLongWx(m_hi | ll.m_hi, m_lo | ll.m_lo);
661 }
662 
operator ^(const wxLongLongWx & ll) const663 wxLongLongWx wxLongLongWx::operator^(const wxLongLongWx& ll) const
664 {
665     return wxLongLongWx(m_hi ^ ll.m_hi, m_lo ^ ll.m_lo);
666 }
667 
operator ^(const wxULongLongWx & ll) const668 wxULongLongWx wxULongLongWx::operator^(const wxULongLongWx& ll) const
669 {
670     return wxULongLongWx(m_hi ^ ll.m_hi, m_lo ^ ll.m_lo);
671 }
672 
operator &=(const wxLongLongWx & ll)673 wxLongLongWx& wxLongLongWx::operator&=(const wxLongLongWx& ll)
674 {
675     m_lo &= ll.m_lo;
676     m_hi &= ll.m_hi;
677 
678 #ifdef wxLONGLONG_TEST_MODE
679     m_ll &= ll.m_ll;
680 
681     Check();
682 #endif // wxLONGLONG_TEST_MODE
683 
684     return *this;
685 }
686 
operator &=(const wxULongLongWx & ll)687 wxULongLongWx& wxULongLongWx::operator&=(const wxULongLongWx& ll)
688 {
689     m_lo &= ll.m_lo;
690     m_hi &= ll.m_hi;
691 
692 #ifdef wxLONGLONG_TEST_MODE
693     m_ll &= ll.m_ll;
694 
695     Check();
696 #endif // wxLONGLONG_TEST_MODE
697 
698     return *this;
699 }
700 
operator |=(const wxLongLongWx & ll)701 wxLongLongWx& wxLongLongWx::operator|=(const wxLongLongWx& ll)
702 {
703     m_lo |= ll.m_lo;
704     m_hi |= ll.m_hi;
705 
706 #ifdef wxLONGLONG_TEST_MODE
707     m_ll |= ll.m_ll;
708 
709     Check();
710 #endif // wxLONGLONG_TEST_MODE
711 
712     return *this;
713 }
714 
operator |=(const wxULongLongWx & ll)715 wxULongLongWx& wxULongLongWx::operator|=(const wxULongLongWx& ll)
716 {
717     m_lo |= ll.m_lo;
718     m_hi |= ll.m_hi;
719 
720 #ifdef wxLONGLONG_TEST_MODE
721     m_ll |= ll.m_ll;
722 
723     Check();
724 #endif // wxLONGLONG_TEST_MODE
725 
726     return *this;
727 }
728 
operator ^=(const wxLongLongWx & ll)729 wxLongLongWx& wxLongLongWx::operator^=(const wxLongLongWx& ll)
730 {
731     m_lo ^= ll.m_lo;
732     m_hi ^= ll.m_hi;
733 
734 #ifdef wxLONGLONG_TEST_MODE
735     m_ll ^= ll.m_ll;
736 
737     Check();
738 #endif // wxLONGLONG_TEST_MODE
739 
740     return *this;
741 }
742 
operator ^=(const wxULongLongWx & ll)743 wxULongLongWx& wxULongLongWx::operator^=(const wxULongLongWx& ll)
744 {
745     m_lo ^= ll.m_lo;
746     m_hi ^= ll.m_hi;
747 
748 #ifdef wxLONGLONG_TEST_MODE
749     m_ll ^= ll.m_ll;
750 
751     Check();
752 #endif // wxLONGLONG_TEST_MODE
753 
754     return *this;
755 }
756 
operator ~() const757 wxLongLongWx wxLongLongWx::operator~() const
758 {
759     return wxLongLongWx(~m_hi, ~m_lo);
760 }
761 
operator ~() const762 wxULongLongWx wxULongLongWx::operator~() const
763 {
764     return wxULongLongWx(~m_hi, ~m_lo);
765 }
766 
767 // multiplication
768 
operator *(const wxLongLongWx & ll) const769 wxLongLongWx wxLongLongWx::operator*(const wxLongLongWx& ll) const
770 {
771     wxLongLongWx res(*this);
772     res *= ll;
773 
774     return res;
775 }
776 
operator *(const wxULongLongWx & ll) const777 wxULongLongWx wxULongLongWx::operator*(const wxULongLongWx& ll) const
778 {
779     wxULongLongWx res(*this);
780     res *= ll;
781 
782     return res;
783 }
784 
operator *=(const wxLongLongWx & ll)785 wxLongLongWx& wxLongLongWx::operator*=(const wxLongLongWx& ll)
786 {
787     wxLongLongWx t(m_hi, m_lo);
788     wxLongLongWx q(ll.m_hi, ll.m_lo);
789 
790     m_hi = m_lo = 0;
791 
792 #ifdef wxLONGLONG_TEST_MODE
793     wxLongLong_t llOld = m_ll;
794     m_ll = 0;
795 #endif // wxLONGLONG_TEST_MODE
796 
797     int counter = 0;
798     do
799     {
800         if ((q.m_lo & 1) != 0)
801             *this += t;
802         q >>= 1;
803         t <<= 1;
804         counter++;
805     }
806     while ((counter < 64) && ((q.m_hi != 0) || (q.m_lo != 0)));
807 
808 #ifdef wxLONGLONG_TEST_MODE
809     m_ll = llOld * ll.m_ll;
810 
811     Check();
812 #endif // wxLONGLONG_TEST_MODE
813 
814     return *this;
815 }
816 
operator *=(const wxULongLongWx & ll)817 wxULongLongWx& wxULongLongWx::operator*=(const wxULongLongWx& ll)
818 {
819     wxULongLongWx t(m_hi, m_lo);
820     wxULongLongWx q(ll.m_hi, ll.m_lo);
821 
822     m_hi = m_lo = 0;
823 
824 #ifdef wxLONGLONG_TEST_MODE
825     wxULongLong_t llOld = m_ll;
826     m_ll = 0;
827 #endif // wxLONGLONG_TEST_MODE
828 
829     int counter = 0;
830     do
831     {
832         if ((q.m_lo & 1) != 0)
833             *this += t;
834         q >>= 1;
835         t <<= 1;
836         counter++;
837     }
838     while ((counter < 64) && ((q.m_hi != 0) || (q.m_lo != 0)));
839 
840 #ifdef wxLONGLONG_TEST_MODE
841     m_ll = llOld * ll.m_ll;
842 
843     Check();
844 #endif // wxLONGLONG_TEST_MODE
845 
846     return *this;
847 }
848 
849 // division
850 
851 #define IS_MSB_SET(ll)  ((ll.GetHi()) & (1 << (8*sizeof(long) - 1)))
852 
Divide(const wxLongLongWx & divisorIn,wxLongLongWx & quotient,wxLongLongWx & remainderIO) const853 void wxLongLongWx::Divide(const wxLongLongWx& divisorIn,
854                           wxLongLongWx& quotient,
855                           wxLongLongWx& remainderIO) const
856 {
857     if ((divisorIn.m_lo == 0) && (divisorIn.m_hi == 0))
858     {
859         // provoke division by zero error and silence the compilers warnings
860         // about an expression without effect and unused variable
861         long dummy = divisorIn.m_lo/divisorIn.m_hi;
862         dummy += 0;
863     }
864 
865     // VZ: I'm writing this in a hurry and it's surely not the fastest way to
866     //     do this - any improvements are more than welcome
867     //
868     //     code inspired by the snippet at
869     //          http://www.bearcave.com/software/divide.htm
870     //
871     //     Copyright notice:
872     //
873     //     Use of this program, for any purpose, is granted the author, Ian
874     //     Kaplan, as long as this copyright notice is included in the source
875     //     code or any source code derived from this program. The user assumes
876     //     all responsibility for using this code.
877 
878     // init everything
879     wxULongLongWx dividend, divisor, remainder;
880 
881     quotient = 0l;
882     remainder = 0l;
883 
884     // always do unsigned division and adjust the signs later: in C integer
885     // division, the sign of the remainder is the same as the sign of the
886     // dividend, while the sign of the quotient is the product of the signs of
887     // the dividend and divisor. Of course, we also always have
888     //
889     //      dividend = quotient*divisor + remainder
890     //
891     // with 0 <= abs(remainder) < abs(divisor)
892     bool negRemainder = GetHi() < 0;
893     bool negQuotient = false;   // assume positive
894     if ( GetHi() < 0 )
895     {
896         negQuotient = !negQuotient;
897         dividend = -*this;
898     } else {
899         dividend = *this;
900     }
901     if ( divisorIn.GetHi() < 0 )
902     {
903         negQuotient = !negQuotient;
904         divisor = -divisorIn;
905     } else {
906         divisor = divisorIn;
907     }
908 
909     // check for some particular cases
910     if ( divisor > dividend )
911     {
912         remainder = dividend;
913     }
914     else if ( divisor == dividend )
915     {
916         quotient = 1l;
917     }
918     else
919     {
920         // here: dividend > divisor and both are positive: do unsigned division
921         size_t nBits = 64u;
922         wxLongLongWx d;
923 
924         while ( remainder < divisor )
925         {
926             remainder <<= 1;
927             if ( IS_MSB_SET(dividend) )
928             {
929                 remainder |= 1;
930             }
931 
932             d = dividend;
933             dividend <<= 1;
934 
935             nBits--;
936         }
937 
938         // undo the last loop iteration
939         dividend = d;
940         remainder >>= 1;
941         nBits++;
942 
943         for ( size_t i = 0; i < nBits; i++ )
944         {
945             remainder <<= 1;
946             if ( IS_MSB_SET(dividend) )
947             {
948                 remainder |= 1;
949             }
950 
951             wxLongLongWx t = remainder - divisor;
952             dividend <<= 1;
953             quotient <<= 1;
954             if ( !IS_MSB_SET(t) )
955             {
956                 quotient |= 1;
957 
958                 remainder = t;
959             }
960         }
961     }
962 
963     remainderIO = remainder;
964 
965     // adjust signs
966     if ( negRemainder )
967     {
968         remainderIO = -remainderIO;
969     }
970 
971     if ( negQuotient )
972     {
973         quotient = -quotient;
974     }
975 }
976 
Divide(const wxULongLongWx & divisorIn,wxULongLongWx & quotient,wxULongLongWx & remainder) const977 void wxULongLongWx::Divide(const wxULongLongWx& divisorIn,
978                            wxULongLongWx& quotient,
979                            wxULongLongWx& remainder) const
980 {
981     if ((divisorIn.m_lo == 0) && (divisorIn.m_hi == 0))
982     {
983         // provoke division by zero error and silence the compilers warnings
984         // about an expression without effect and unused variable
985         unsigned long dummy = divisorIn.m_lo/divisorIn.m_hi;
986         dummy += 0;
987     }
988 
989     // VZ: I'm writing this in a hurry and it's surely not the fastest way to
990     //     do this - any improvements are more than welcome
991     //
992     //     code inspired by the snippet at
993     //          http://www.bearcave.com/software/divide.htm
994     //
995     //     Copyright notice:
996     //
997     //     Use of this program, for any purpose, is granted the author, Ian
998     //     Kaplan, as long as this copyright notice is included in the source
999     //     code or any source code derived from this program. The user assumes
1000     //     all responsibility for using this code.
1001 
1002     // init everything
1003     wxULongLongWx dividend = *this,
1004                   divisor = divisorIn;
1005 
1006     quotient = 0l;
1007     remainder = 0l;
1008 
1009     // check for some particular cases
1010     if ( divisor > dividend )
1011     {
1012         remainder = dividend;
1013     }
1014     else if ( divisor == dividend )
1015     {
1016         quotient = 1l;
1017     }
1018     else
1019     {
1020         // here: dividend > divisor
1021         size_t nBits = 64u;
1022         wxULongLongWx d;
1023 
1024         while ( remainder < divisor )
1025         {
1026             remainder <<= 1;
1027             if ( IS_MSB_SET(dividend) )
1028             {
1029                 remainder |= 1;
1030             }
1031 
1032             d = dividend;
1033             dividend <<= 1;
1034 
1035             nBits--;
1036         }
1037 
1038         // undo the last loop iteration
1039         dividend = d;
1040         remainder >>= 1;
1041         nBits++;
1042 
1043         for ( size_t i = 0; i < nBits; i++ )
1044         {
1045             remainder <<= 1;
1046             if ( IS_MSB_SET(dividend) )
1047             {
1048                 remainder |= 1;
1049             }
1050 
1051             wxULongLongWx t = remainder - divisor;
1052             dividend <<= 1;
1053             quotient <<= 1;
1054             if ( !IS_MSB_SET(t) )
1055             {
1056                 quotient |= 1;
1057 
1058                 remainder = t;
1059             }
1060         }
1061     }
1062 }
1063 
operator /(const wxLongLongWx & ll) const1064 wxLongLongWx wxLongLongWx::operator/(const wxLongLongWx& ll) const
1065 {
1066     wxLongLongWx quotient, remainder;
1067 
1068     Divide(ll, quotient, remainder);
1069 
1070     return quotient;
1071 }
1072 
operator /(const wxULongLongWx & ll) const1073 wxULongLongWx wxULongLongWx::operator/(const wxULongLongWx& ll) const
1074 {
1075     wxULongLongWx quotient, remainder;
1076 
1077     Divide(ll, quotient, remainder);
1078 
1079     return quotient;
1080 }
1081 
operator /=(const wxLongLongWx & ll)1082 wxLongLongWx& wxLongLongWx::operator/=(const wxLongLongWx& ll)
1083 {
1084     wxLongLongWx quotient, remainder;
1085 
1086     Divide(ll, quotient, remainder);
1087 
1088     *this = quotient;
1089 
1090     return *this;
1091 }
1092 
operator /=(const wxULongLongWx & ll)1093 wxULongLongWx& wxULongLongWx::operator/=(const wxULongLongWx& ll)
1094 {
1095     wxULongLongWx quotient, remainder;
1096 
1097     Divide(ll, quotient, remainder);
1098 
1099     *this = quotient;
1100 
1101     return *this;
1102 }
1103 
operator %(const wxLongLongWx & ll) const1104 wxLongLongWx wxLongLongWx::operator%(const wxLongLongWx& ll) const
1105 {
1106     wxLongLongWx quotient, remainder;
1107 
1108     Divide(ll, quotient, remainder);
1109 
1110     return remainder;
1111 }
1112 
operator %(const wxULongLongWx & ll) const1113 wxULongLongWx wxULongLongWx::operator%(const wxULongLongWx& ll) const
1114 {
1115     wxULongLongWx quotient, remainder;
1116 
1117     Divide(ll, quotient, remainder);
1118 
1119     return remainder;
1120 }
1121 
1122 // ----------------------------------------------------------------------------
1123 // misc
1124 // ----------------------------------------------------------------------------
1125 
1126 // temporary - just for testing
asArray(void) const1127 void *wxLongLongWx::asArray(void) const
1128 {
1129     static unsigned char temp[8];
1130 
1131     temp[0] = (char)((m_hi >> 24) & 0xFF);
1132     temp[1] = (char)((m_hi >> 16) & 0xFF);
1133     temp[2] = (char)((m_hi >> 8)  & 0xFF);
1134     temp[3] = (char)((m_hi >> 0)  & 0xFF);
1135     temp[4] = (char)((m_lo >> 24) & 0xFF);
1136     temp[5] = (char)((m_lo >> 16) & 0xFF);
1137     temp[6] = (char)((m_lo >> 8)  & 0xFF);
1138     temp[7] = (char)((m_lo >> 0)  & 0xFF);
1139 
1140     return temp;
1141 }
1142 
asArray(void) const1143 void *wxULongLongWx::asArray(void) const
1144 {
1145     static unsigned char temp[8];
1146 
1147     temp[0] = (char)((m_hi >> 24) & 0xFF);
1148     temp[1] = (char)((m_hi >> 16) & 0xFF);
1149     temp[2] = (char)((m_hi >> 8)  & 0xFF);
1150     temp[3] = (char)((m_hi >> 0)  & 0xFF);
1151     temp[4] = (char)((m_lo >> 24) & 0xFF);
1152     temp[5] = (char)((m_lo >> 16) & 0xFF);
1153     temp[6] = (char)((m_lo >> 8)  & 0xFF);
1154     temp[7] = (char)((m_lo >> 0)  & 0xFF);
1155 
1156     return temp;
1157 }
1158 
1159 #endif // wxUSE_LONGLONG_WX
1160 
1161 #define LL_TO_STRING(name)                                           \
1162     wxString name::ToString() const                                  \
1163     {                                                                \
1164         /* TODO: this is awfully inefficient, anything better? */    \
1165         wxString result;                                             \
1166                                                                      \
1167         name ll = *this;                                             \
1168                                                                      \
1169         bool neg = ll < 0;                                           \
1170         if ( neg )                                                   \
1171         {                                                            \
1172             while ( ll != 0 )                                        \
1173             {                                                        \
1174                 long digit = (ll % 10).ToLong();                     \
1175                 result.Prepend((wxChar)(_T('0') - digit));           \
1176                 ll /= 10;                                            \
1177             }                                                        \
1178         }                                                            \
1179         else                                                         \
1180         {                                                            \
1181             while ( ll != 0 )                                        \
1182             {                                                        \
1183                 long digit = (ll % 10).ToLong();                     \
1184                 result.Prepend((wxChar)(_T('0') + digit));           \
1185                 ll /= 10;                                            \
1186             }                                                        \
1187         }                                                            \
1188                                                                      \
1189         if ( result.empty() )                                        \
1190             result = _T('0');                                        \
1191         else if ( neg )                                              \
1192             result.Prepend(_T('-'));                                 \
1193                                                                      \
1194         return result;                                               \
1195     }
1196 
1197 #define ULL_TO_STRING(name)                                          \
1198     wxString name::ToString() const                                  \
1199     {                                                                \
1200         /* TODO: this is awfully inefficient, anything better? */    \
1201         wxString result;                                             \
1202                                                                      \
1203         name ll = *this;                                             \
1204                                                                      \
1205         while ( ll != 0 )                                            \
1206         {                                                            \
1207             result.Prepend((wxChar)(_T('0') + (ll % 10).ToULong())); \
1208             ll /= 10;                                                \
1209         }                                                            \
1210                                                                      \
1211         if ( result.empty() )                                        \
1212             result = _T('0');                                        \
1213                                                                      \
1214         return result;                                               \
1215     }
1216 
1217 #if wxUSE_LONGLONG_NATIVE
1218     LL_TO_STRING(wxLongLongNative)
1219     ULL_TO_STRING(wxULongLongNative)
1220 #endif
1221 
1222 #if wxUSE_LONGLONG_WX
1223     LL_TO_STRING(wxLongLongWx)
1224     ULL_TO_STRING(wxULongLongWx)
1225 #endif
1226 
1227 #if wxUSE_STD_IOSTREAM
1228 
1229 // input/output
1230 WXDLLIMPEXP_BASE
1231 wxSTD ostream& operator<< (wxSTD ostream& o, const wxLongLong& ll)
1232 {
1233     return o << ll.ToString();
1234 }
1235 
1236 WXDLLIMPEXP_BASE
operator <<(wxSTD ostream & o,const wxULongLong & ll)1237 wxSTD ostream& operator<< (wxSTD ostream& o, const wxULongLong& ll)
1238 {
1239     return o << ll.ToString();
1240 }
1241 
1242 #endif // wxUSE_STD_IOSTREAM
1243 
operator <<(wxString & s,const wxLongLong & ll)1244 WXDLLIMPEXP_BASE wxString& operator<< (wxString& s, const wxLongLong& ll)
1245 {
1246     return s << ll.ToString();
1247 }
1248 
operator <<(wxString & s,const wxULongLong & ll)1249 WXDLLIMPEXP_BASE wxString& operator<< (wxString& s, const wxULongLong& ll)
1250 {
1251     return s << ll.ToString();
1252 }
1253 
1254 #if wxUSE_STREAMS
1255 
operator <<(wxTextOutputStream & o,const wxULongLong & ll)1256 WXDLLIMPEXP_BASE wxTextOutputStream& operator<< (wxTextOutputStream& o, const wxULongLong& ll)
1257 {
1258     return o << ll.ToString();
1259 }
1260 
operator <<(wxTextOutputStream & o,const wxLongLong & ll)1261 WXDLLIMPEXP_BASE wxTextOutputStream& operator<< (wxTextOutputStream& o, const wxLongLong& ll)
1262 {
1263     return o << ll.ToString();
1264 }
1265 
1266 #define READ_STRING_CHAR(s, idx, len) ((wxChar) ((idx!=len) ? s[idx++] : 0))
1267 
operator >>(class wxTextInputStream & o,wxULongLong & ll)1268 WXDLLIMPEXP_BASE class wxTextInputStream &operator>>(class wxTextInputStream &o, wxULongLong &ll)
1269 {
1270     wxString s = o.ReadWord();
1271 
1272     ll = wxULongLong(0l, 0l);
1273     size_t length = s.length();
1274     size_t idx = 0;
1275 
1276     wxChar ch = READ_STRING_CHAR(s, idx, length);
1277 
1278     // Skip WS
1279     while (ch==wxT(' ') || ch==wxT('\t'))
1280         ch = READ_STRING_CHAR(s, idx, length);
1281 
1282     // Read number
1283     wxULongLong multiplier(0l, 10l);
1284     while (ch>=wxT('0') && ch<=wxT('9')) {
1285         long lValue = (unsigned) (ch - wxT('0'));
1286         ll = ll * multiplier + wxULongLong(0l, lValue);
1287         ch = READ_STRING_CHAR(s, idx, length);
1288     }
1289 
1290     return o;
1291 }
1292 
operator >>(class wxTextInputStream & o,wxLongLong & ll)1293 WXDLLIMPEXP_BASE class wxTextInputStream &operator>>(class wxTextInputStream &o, wxLongLong &ll)
1294 {
1295     wxString s = o.ReadWord();
1296 
1297     ll = wxLongLong(0l, 0l);
1298     size_t length = s.length();
1299     size_t idx = 0;
1300 
1301     wxChar ch = READ_STRING_CHAR(s, idx, length);
1302 
1303     // Skip WS
1304     while (ch==wxT(' ') || ch==wxT('\t'))
1305         ch = READ_STRING_CHAR(s, idx, length);
1306 
1307     // Ask for sign
1308     int iSign = 1;
1309     if (ch==wxT('-') || ch==wxT('+')) {
1310         iSign = ((ch==wxT('-')) ? -1 : 1);
1311         ch = READ_STRING_CHAR(s, idx, length);
1312     }
1313 
1314     // Read number
1315     wxLongLong multiplier(0l, 10l);
1316     while (ch>=wxT('0') && ch<=wxT('9')) {
1317         long lValue = (unsigned) (ch - wxT('0'));
1318         ll = ll * multiplier + wxLongLong(0l, lValue);
1319         ch = READ_STRING_CHAR(s, idx, length);
1320     }
1321 
1322 #if wxUSE_LONGLONG_NATIVE
1323     ll = ll * wxLongLong((wxLongLong_t) iSign);
1324 #else
1325     ll = ll * wxLongLong((long) iSign);
1326 #endif
1327 
1328     return o;
1329 }
1330 
1331 #if wxUSE_LONGLONG_NATIVE
1332 
operator <<(class wxTextOutputStream & o,wxULongLong_t value)1333 WXDLLIMPEXP_BASE class wxTextOutputStream &operator<<(class wxTextOutputStream &o, wxULongLong_t value)
1334 {
1335     return o << wxULongLong(value).ToString();
1336 }
1337 
operator <<(class wxTextOutputStream & o,wxLongLong_t value)1338 WXDLLIMPEXP_BASE class wxTextOutputStream &operator<<(class wxTextOutputStream &o, wxLongLong_t value)
1339 {
1340     return o << wxLongLong(value).ToString();
1341 }
1342 
operator >>(class wxTextInputStream & o,wxULongLong_t & value)1343 WXDLLIMPEXP_BASE class wxTextInputStream &operator>>(class wxTextInputStream &o, wxULongLong_t &value)
1344 {
1345     wxULongLong ll;
1346     o >> ll;
1347     value = ll.GetValue();
1348     return o;
1349 }
1350 
operator >>(class wxTextInputStream & o,wxLongLong_t & value)1351 WXDLLIMPEXP_BASE class wxTextInputStream &operator>>(class wxTextInputStream &o, wxLongLong_t &value)
1352 {
1353     wxLongLong ll;
1354     o >> ll;
1355     value = ll.GetValue();
1356     return o;
1357 }
1358 
1359 #endif // wxUSE_LONGLONG_NATIVE
1360 
1361 #endif // wxUSE_STREAMS
1362 
1363 #endif // wxUSE_LONGLONG
1364