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