]> git.saurik.com Git - wxWidgets.git/blob - src/common/longlong.cpp
Fix [ 1574240 ] wx.RadioButton doesn't navigate correctly
[wxWidgets.git] / src / common / longlong.cpp
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$
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
50 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
66 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
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
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
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
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
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
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
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
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
180 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
193 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
206 wxLongLongWx wxLongLongWx::operator<<(int shift) const
207 {
208 wxLongLongWx ll(*this);
209 ll <<= shift;
210
211 return ll;
212 }
213
214 wxULongLongWx wxULongLongWx::operator<<(int shift) const
215 {
216 wxULongLongWx ll(*this);
217 ll <<= shift;
218
219 return ll;
220 }
221
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
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
274 wxLongLongWx wxLongLongWx::operator>>(int shift) const
275 {
276 wxLongLongWx ll(*this);
277 ll >>= shift;
278
279 return ll;
280 }
281
282 wxULongLongWx wxULongLongWx::operator>>(int shift) const
283 {
284 wxULongLongWx ll(*this);
285 ll >>= shift;
286
287 return ll;
288 }
289
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
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
342 wxLongLongWx wxLongLongWx::operator+(const wxLongLongWx& ll) const
343 {
344 wxLongLongWx res(*this);
345 res += ll;
346
347 return res;
348 }
349
350 wxULongLongWx wxULongLongWx::operator+(const wxULongLongWx& ll) const
351 {
352 wxULongLongWx res(*this);
353 res += ll;
354
355 return res;
356 }
357
358 wxLongLongWx wxLongLongWx::operator+(long l) const
359 {
360 wxLongLongWx res(*this);
361 res += l;
362
363 return res;
364 }
365
366 wxULongLongWx wxULongLongWx::operator+(unsigned long l) const
367 {
368 wxULongLongWx res(*this);
369 res += l;
370
371 return res;
372 }
373
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
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
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
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
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
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
482 wxLongLongWx wxLongLongWx::operator-() const
483 {
484 wxLongLongWx res(*this);
485 res.Negate();
486
487 return res;
488 }
489
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
510 wxLongLongWx wxLongLongWx::operator-(const wxLongLongWx& ll) const
511 {
512 wxLongLongWx res(*this);
513 res -= ll;
514
515 return res;
516 }
517
518 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
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
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
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
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
601 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
611 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
621 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
631 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
643 wxLongLongWx wxLongLongWx::operator&(const wxLongLongWx& ll) const
644 {
645 return wxLongLongWx(m_hi & ll.m_hi, m_lo & ll.m_lo);
646 }
647
648 wxULongLongWx wxULongLongWx::operator&(const wxULongLongWx& ll) const
649 {
650 return wxULongLongWx(m_hi & ll.m_hi, m_lo & ll.m_lo);
651 }
652
653 wxLongLongWx wxLongLongWx::operator|(const wxLongLongWx& ll) const
654 {
655 return wxLongLongWx(m_hi | ll.m_hi, m_lo | ll.m_lo);
656 }
657
658 wxULongLongWx wxULongLongWx::operator|(const wxULongLongWx& ll) const
659 {
660 return wxULongLongWx(m_hi | ll.m_hi, m_lo | ll.m_lo);
661 }
662
663 wxLongLongWx wxLongLongWx::operator^(const wxLongLongWx& ll) const
664 {
665 return wxLongLongWx(m_hi ^ ll.m_hi, m_lo ^ ll.m_lo);
666 }
667
668 wxULongLongWx wxULongLongWx::operator^(const wxULongLongWx& ll) const
669 {
670 return wxULongLongWx(m_hi ^ ll.m_hi, m_lo ^ ll.m_lo);
671 }
672
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
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
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
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
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
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
757 wxLongLongWx wxLongLongWx::operator~() const
758 {
759 return wxLongLongWx(~m_hi, ~m_lo);
760 }
761
762 wxULongLongWx wxULongLongWx::operator~() const
763 {
764 return wxULongLongWx(~m_hi, ~m_lo);
765 }
766
767 // multiplication
768
769 wxLongLongWx wxLongLongWx::operator*(const wxLongLongWx& ll) const
770 {
771 wxLongLongWx res(*this);
772 res *= ll;
773
774 return res;
775 }
776
777 wxULongLongWx wxULongLongWx::operator*(const wxULongLongWx& ll) const
778 {
779 wxULongLongWx res(*this);
780 res *= ll;
781
782 return res;
783 }
784
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
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
853 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
977 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
1064 wxLongLongWx wxLongLongWx::operator/(const wxLongLongWx& ll) const
1065 {
1066 wxLongLongWx quotient, remainder;
1067
1068 Divide(ll, quotient, remainder);
1069
1070 return quotient;
1071 }
1072
1073 wxULongLongWx wxULongLongWx::operator/(const wxULongLongWx& ll) const
1074 {
1075 wxULongLongWx quotient, remainder;
1076
1077 Divide(ll, quotient, remainder);
1078
1079 return quotient;
1080 }
1081
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
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
1104 wxLongLongWx wxLongLongWx::operator%(const wxLongLongWx& ll) const
1105 {
1106 wxLongLongWx quotient, remainder;
1107
1108 Divide(ll, quotient, remainder);
1109
1110 return remainder;
1111 }
1112
1113 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
1127 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
1143 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
1237 wxSTD ostream& operator<< (wxSTD ostream& o, const wxULongLong& ll)
1238 {
1239 return o << ll.ToString();
1240 }
1241
1242 #endif // wxUSE_STD_IOSTREAM
1243
1244 WXDLLIMPEXP_BASE wxString& operator<< (wxString& s, const wxLongLong& ll)
1245 {
1246 return s << ll.ToString();
1247 }
1248
1249 WXDLLIMPEXP_BASE wxString& operator<< (wxString& s, const wxULongLong& ll)
1250 {
1251 return s << ll.ToString();
1252 }
1253
1254 #if wxUSE_STREAMS
1255
1256 WXDLLIMPEXP_BASE wxTextOutputStream& operator<< (wxTextOutputStream& o, const wxULongLong& ll)
1257 {
1258 return o << ll.ToString();
1259 }
1260
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
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
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
1333 WXDLLIMPEXP_BASE class wxTextOutputStream &operator<<(class wxTextOutputStream &o, wxULongLong_t value)
1334 {
1335 return o << wxULongLong(value).ToString();
1336 }
1337
1338 WXDLLIMPEXP_BASE class wxTextOutputStream &operator<<(class wxTextOutputStream &o, wxLongLong_t value)
1339 {
1340 return o << wxLongLong(value).ToString();
1341 }
1342
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
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