added support for 64 bit ints in wx stream classes (patch 1203970)
[wxWidgets.git] / src / common / longlong.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/longlong.cpp
3 // Purpose: implementation of wxLongLongNative
4 // Author: Jeffrey C. Ollie <jeff@ollie.clive.ia.us>, Vadim Zeitlin
5 // Remarks: this class is not public in 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 #include "wx/longlong.h"
26 #include "wx/math.h" // for fabs()
27
28 #if wxUSE_STREAMS
29 #include "wx/txtstrm.h"
30 #endif
31
32 #if defined(__MWERKS__) && defined(__WXMSW__)
33 #include <string.h> // for memset()
34 #else
35 #include <memory.h> // for memset()
36 #endif
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 wxLongLongWx wxLongLongWx::operator<<(int shift) const
194 {
195 wxLongLongWx ll(*this);
196 ll <<= shift;
197
198 return ll;
199 }
200
201 wxULongLongWx wxULongLongWx::operator<<(int shift) const
202 {
203 wxULongLongWx ll(*this);
204 ll <<= shift;
205
206 return ll;
207 }
208
209 wxLongLongWx& wxLongLongWx::operator<<=(int shift)
210 {
211 if (shift != 0)
212 {
213 if (shift < 32)
214 {
215 m_hi <<= shift;
216 m_hi |= m_lo >> (32 - shift);
217 m_lo <<= shift;
218 }
219 else
220 {
221 m_hi = m_lo << (shift - 32);
222 m_lo = 0;
223 }
224 }
225
226 #ifdef wxLONGLONG_TEST_MODE
227 m_ll <<= shift;
228
229 Check();
230 #endif // wxLONGLONG_TEST_MODE
231
232 return *this;
233 }
234
235 wxULongLongWx& wxULongLongWx::operator<<=(int shift)
236 {
237 if (shift != 0)
238 {
239 if (shift < 32)
240 {
241 m_hi <<= shift;
242 m_hi |= m_lo >> (32 - shift);
243 m_lo <<= shift;
244 }
245 else
246 {
247 m_hi = m_lo << (shift - 32);
248 m_lo = 0;
249 }
250 }
251
252 #ifdef wxLONGLONG_TEST_MODE
253 m_ll <<= shift;
254
255 Check();
256 #endif // wxLONGLONG_TEST_MODE
257
258 return *this;
259 }
260
261 wxLongLongWx wxLongLongWx::operator>>(int shift) const
262 {
263 wxLongLongWx ll(*this);
264 ll >>= shift;
265
266 return ll;
267 }
268
269 wxULongLongWx wxULongLongWx::operator>>(int shift) const
270 {
271 wxULongLongWx ll(*this);
272 ll >>= shift;
273
274 return ll;
275 }
276
277 wxLongLongWx& wxLongLongWx::operator>>=(int shift)
278 {
279 if (shift != 0)
280 {
281 if (shift < 32)
282 {
283 m_lo >>= shift;
284 m_lo |= m_hi << (32 - shift);
285 m_hi >>= shift;
286 }
287 else
288 {
289 m_lo = m_hi >> (shift - 32);
290 m_hi = (m_hi < 0 ? -1L : 0);
291 }
292 }
293
294 #ifdef wxLONGLONG_TEST_MODE
295 m_ll >>= shift;
296
297 Check();
298 #endif // wxLONGLONG_TEST_MODE
299
300 return *this;
301 }
302
303 wxULongLongWx& wxULongLongWx::operator>>=(int shift)
304 {
305 if (shift != 0)
306 {
307 if (shift < 32)
308 {
309 m_lo >>= shift;
310 m_lo |= m_hi << (32 - shift);
311 m_hi >>= shift;
312 }
313 else
314 {
315 m_lo = m_hi >> (shift - 32);
316 m_hi = 0;
317 }
318 }
319
320 #ifdef wxLONGLONG_TEST_MODE
321 m_ll >>= shift;
322
323 Check();
324 #endif // wxLONGLONG_TEST_MODE
325
326 return *this;
327 }
328
329 wxLongLongWx wxLongLongWx::operator+(const wxLongLongWx& ll) const
330 {
331 wxLongLongWx res(*this);
332 res += ll;
333
334 return res;
335 }
336
337 wxULongLongWx wxULongLongWx::operator+(const wxULongLongWx& ll) const
338 {
339 wxULongLongWx res(*this);
340 res += ll;
341
342 return res;
343 }
344
345 wxLongLongWx wxLongLongWx::operator+(long l) const
346 {
347 wxLongLongWx res(*this);
348 res += l;
349
350 return res;
351 }
352
353 wxULongLongWx wxULongLongWx::operator+(unsigned long l) const
354 {
355 wxULongLongWx res(*this);
356 res += l;
357
358 return res;
359 }
360
361 wxLongLongWx& wxLongLongWx::operator+=(const wxLongLongWx& ll)
362 {
363 unsigned long previous = m_lo;
364
365 m_lo += ll.m_lo;
366 m_hi += ll.m_hi;
367
368 if ((m_lo < previous) || (m_lo < ll.m_lo))
369 m_hi++;
370
371 #ifdef wxLONGLONG_TEST_MODE
372 m_ll += ll.m_ll;
373
374 Check();
375 #endif // wxLONGLONG_TEST_MODE
376
377 return *this;
378 }
379
380 wxULongLongWx& wxULongLongWx::operator+=(const wxULongLongWx& ll)
381 {
382 unsigned long previous = m_lo;
383
384 m_lo += ll.m_lo;
385 m_hi += ll.m_hi;
386
387 if ((m_lo < previous) || (m_lo < ll.m_lo))
388 m_hi++;
389
390 #ifdef wxLONGLONG_TEST_MODE
391 m_ll += ll.m_ll;
392
393 Check();
394 #endif // wxLONGLONG_TEST_MODE
395
396 return *this;
397 }
398
399 wxLongLongWx& wxLongLongWx::operator+=(long l)
400 {
401 unsigned long previous = m_lo;
402
403 m_lo += l;
404 if (l < 0)
405 m_hi += -1l;
406
407 if ((m_lo < previous) || (m_lo < (unsigned long)l))
408 m_hi++;
409
410 #ifdef wxLONGLONG_TEST_MODE
411 m_ll += l;
412
413 Check();
414 #endif // wxLONGLONG_TEST_MODE
415
416 return *this;
417 }
418
419 wxULongLongWx& wxULongLongWx::operator+=(unsigned long l)
420 {
421 unsigned long previous = m_lo;
422
423 m_lo += l;
424
425 if ((m_lo < previous) || (m_lo < l))
426 m_hi++;
427
428 #ifdef wxLONGLONG_TEST_MODE
429 m_ll += l;
430
431 Check();
432 #endif // wxLONGLONG_TEST_MODE
433
434 return *this;
435 }
436
437 // pre increment
438 wxLongLongWx& wxLongLongWx::operator++()
439 {
440 m_lo++;
441 if (m_lo == 0)
442 m_hi++;
443
444 #ifdef wxLONGLONG_TEST_MODE
445 m_ll++;
446
447 Check();
448 #endif // wxLONGLONG_TEST_MODE
449
450 return *this;
451 }
452
453 wxULongLongWx& wxULongLongWx::operator++()
454 {
455 m_lo++;
456 if (m_lo == 0)
457 m_hi++;
458
459 #ifdef wxLONGLONG_TEST_MODE
460 m_ll++;
461
462 Check();
463 #endif // wxLONGLONG_TEST_MODE
464
465 return *this;
466 }
467
468 // negation
469 wxLongLongWx wxLongLongWx::operator-() const
470 {
471 wxLongLongWx res(*this);
472 res.Negate();
473
474 return res;
475 }
476
477 wxLongLongWx& wxLongLongWx::Negate()
478 {
479 m_hi = ~m_hi;
480 m_lo = ~m_lo;
481
482 m_lo++;
483 if ( m_lo == 0 )
484 m_hi++;
485
486 #ifdef wxLONGLONG_TEST_MODE
487 m_ll = -m_ll;
488
489 Check();
490 #endif // wxLONGLONG_TEST_MODE
491
492 return *this;
493 }
494
495 // subtraction
496
497 wxLongLongWx wxLongLongWx::operator-(const wxLongLongWx& ll) const
498 {
499 wxLongLongWx res(*this);
500 res -= ll;
501
502 return res;
503 }
504
505 wxLongLongWx wxULongLongWx::operator-(const wxULongLongWx& ll) const
506 {
507 wxASSERT(m_hi <= LONG_MAX );
508 wxASSERT(ll.m_hi <= LONG_MAX );
509
510 wxLongLongWx res( (long)m_hi , m_lo );
511 wxLongLongWx op( (long)ll.m_hi , ll.m_lo );
512 res -= op;
513
514 return res;
515 }
516
517 wxLongLongWx& wxLongLongWx::operator-=(const wxLongLongWx& ll)
518 {
519 unsigned long previous = m_lo;
520
521 m_lo -= ll.m_lo;
522 m_hi -= ll.m_hi;
523
524 if (previous < ll.m_lo)
525 m_hi--;
526
527 #ifdef wxLONGLONG_TEST_MODE
528 m_ll -= ll.m_ll;
529
530 Check();
531 #endif // wxLONGLONG_TEST_MODE
532
533 return *this;
534 }
535
536 wxULongLongWx& wxULongLongWx::operator-=(const wxULongLongWx& ll)
537 {
538 unsigned long previous = m_lo;
539
540 m_lo -= ll.m_lo;
541 m_hi -= ll.m_hi;
542
543 if (previous < ll.m_lo)
544 m_hi--;
545
546 #ifdef wxLONGLONG_TEST_MODE
547 m_ll -= ll.m_ll;
548
549 Check();
550 #endif // wxLONGLONG_TEST_MODE
551
552 return *this;
553 }
554
555 // pre decrement
556 wxLongLongWx& wxLongLongWx::operator--()
557 {
558 m_lo--;
559 if (m_lo == 0xFFFFFFFF)
560 m_hi--;
561
562 #ifdef wxLONGLONG_TEST_MODE
563 m_ll--;
564
565 Check();
566 #endif // wxLONGLONG_TEST_MODE
567
568 return *this;
569 }
570
571 wxULongLongWx& wxULongLongWx::operator--()
572 {
573 m_lo--;
574 if (m_lo == 0xFFFFFFFF)
575 m_hi--;
576
577 #ifdef wxLONGLONG_TEST_MODE
578 m_ll--;
579
580 Check();
581 #endif // wxLONGLONG_TEST_MODE
582
583 return *this;
584 }
585
586 // comparison operators
587
588 bool wxLongLongWx::operator<(const wxLongLongWx& ll) const
589 {
590 if ( m_hi < ll.m_hi )
591 return true;
592 else if ( m_hi == ll.m_hi )
593 return m_lo < ll.m_lo;
594 else
595 return false;
596 }
597
598 bool wxULongLongWx::operator<(const wxULongLongWx& ll) const
599 {
600 if ( m_hi < ll.m_hi )
601 return true;
602 else if ( m_hi == ll.m_hi )
603 return m_lo < ll.m_lo;
604 else
605 return false;
606 }
607
608 bool wxLongLongWx::operator>(const wxLongLongWx& ll) const
609 {
610 if ( m_hi > ll.m_hi )
611 return true;
612 else if ( m_hi == ll.m_hi )
613 return m_lo > ll.m_lo;
614 else
615 return false;
616 }
617
618 bool wxULongLongWx::operator>(const wxULongLongWx& ll) const
619 {
620 if ( m_hi > ll.m_hi )
621 return true;
622 else if ( m_hi == ll.m_hi )
623 return m_lo > ll.m_lo;
624 else
625 return false;
626 }
627
628 // bitwise operators
629
630 wxLongLongWx wxLongLongWx::operator&(const wxLongLongWx& ll) const
631 {
632 return wxLongLongWx(m_hi & ll.m_hi, m_lo & ll.m_lo);
633 }
634
635 wxULongLongWx wxULongLongWx::operator&(const wxULongLongWx& ll) const
636 {
637 return wxULongLongWx(m_hi & ll.m_hi, m_lo & ll.m_lo);
638 }
639
640 wxLongLongWx wxLongLongWx::operator|(const wxLongLongWx& ll) const
641 {
642 return wxLongLongWx(m_hi | ll.m_hi, m_lo | ll.m_lo);
643 }
644
645 wxULongLongWx wxULongLongWx::operator|(const wxULongLongWx& ll) const
646 {
647 return wxULongLongWx(m_hi | ll.m_hi, m_lo | ll.m_lo);
648 }
649
650 wxLongLongWx wxLongLongWx::operator^(const wxLongLongWx& ll) const
651 {
652 return wxLongLongWx(m_hi ^ ll.m_hi, m_lo ^ ll.m_lo);
653 }
654
655 wxULongLongWx wxULongLongWx::operator^(const wxULongLongWx& ll) const
656 {
657 return wxULongLongWx(m_hi ^ ll.m_hi, m_lo ^ ll.m_lo);
658 }
659
660 wxLongLongWx& wxLongLongWx::operator&=(const wxLongLongWx& ll)
661 {
662 m_lo &= ll.m_lo;
663 m_hi &= ll.m_hi;
664
665 #ifdef wxLONGLONG_TEST_MODE
666 m_ll &= ll.m_ll;
667
668 Check();
669 #endif // wxLONGLONG_TEST_MODE
670
671 return *this;
672 }
673
674 wxULongLongWx& wxULongLongWx::operator&=(const wxULongLongWx& ll)
675 {
676 m_lo &= ll.m_lo;
677 m_hi &= ll.m_hi;
678
679 #ifdef wxLONGLONG_TEST_MODE
680 m_ll &= ll.m_ll;
681
682 Check();
683 #endif // wxLONGLONG_TEST_MODE
684
685 return *this;
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
745 {
746 return wxLongLongWx(~m_hi, ~m_lo);
747 }
748
749 wxULongLongWx wxULongLongWx::operator~() const
750 {
751 return wxULongLongWx(~m_hi, ~m_lo);
752 }
753
754 // multiplication
755
756 wxLongLongWx wxLongLongWx::operator*(const wxLongLongWx& ll) const
757 {
758 wxLongLongWx res(*this);
759 res *= ll;
760
761 return res;
762 }
763
764 wxULongLongWx wxULongLongWx::operator*(const wxULongLongWx& ll) const
765 {
766 wxULongLongWx res(*this);
767 res *= ll;
768
769 return res;
770 }
771
772 wxLongLongWx& wxLongLongWx::operator*=(const wxLongLongWx& ll)
773 {
774 wxLongLongWx t(m_hi, m_lo);
775 wxLongLongWx q(ll.m_hi, ll.m_lo);
776
777 m_hi = m_lo = 0;
778
779 #ifdef wxLONGLONG_TEST_MODE
780 wxLongLong_t llOld = m_ll;
781 m_ll = 0;
782 #endif // wxLONGLONG_TEST_MODE
783
784 int counter = 0;
785 do
786 {
787 if ((q.m_lo & 1) != 0)
788 *this += t;
789 q >>= 1;
790 t <<= 1;
791 counter++;
792 }
793 while ((counter < 64) && ((q.m_hi != 0) || (q.m_lo != 0)));
794
795 #ifdef wxLONGLONG_TEST_MODE
796 m_ll = llOld * ll.m_ll;
797
798 Check();
799 #endif // wxLONGLONG_TEST_MODE
800
801 return *this;
802 }
803
804 wxULongLongWx& wxULongLongWx::operator*=(const wxULongLongWx& ll)
805 {
806 wxULongLongWx t(m_hi, m_lo);
807 wxULongLongWx q(ll.m_hi, ll.m_lo);
808
809 m_hi = m_lo = 0;
810
811 #ifdef wxLONGLONG_TEST_MODE
812 wxULongLong_t llOld = m_ll;
813 m_ll = 0;
814 #endif // wxLONGLONG_TEST_MODE
815
816 int counter = 0;
817 do
818 {
819 if ((q.m_lo & 1) != 0)
820 *this += t;
821 q >>= 1;
822 t <<= 1;
823 counter++;
824 }
825 while ((counter < 64) && ((q.m_hi != 0) || (q.m_lo != 0)));
826
827 #ifdef wxLONGLONG_TEST_MODE
828 m_ll = llOld * ll.m_ll;
829
830 Check();
831 #endif // wxLONGLONG_TEST_MODE
832
833 return *this;
834 }
835
836 // division
837
838 #define IS_MSB_SET(ll) ((ll.GetHi()) & (1 << (8*sizeof(long) - 1)))
839
840 void wxLongLongWx::Divide(const wxLongLongWx& divisorIn,
841 wxLongLongWx& quotient,
842 wxLongLongWx& remainderIO) const
843 {
844 if ((divisorIn.m_lo == 0) && (divisorIn.m_hi == 0))
845 {
846 // provoke division by zero error and silence the compilers warnings
847 // about an expression without effect and unused variable
848 long dummy = divisorIn.m_lo/divisorIn.m_hi;
849 dummy += 0;
850 }
851
852 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
853 // do this - any improvements are more than welcome
854 //
855 // code inspired by the snippet at
856 // http://www.bearcave.com/software/divide.htm
857 //
858 // Copyright notice:
859 //
860 // Use of this program, for any purpose, is granted the author, Ian
861 // Kaplan, as long as this copyright notice is included in the source
862 // code or any source code derived from this program. The user assumes
863 // all responsibility for using this code.
864
865 // init everything
866 wxULongLongWx dividend, divisor, remainder;
867
868 quotient = 0l;
869 remainder = 0l;
870
871 // always do unsigned division and adjust the signs later: in C integer
872 // division, the sign of the remainder is the same as the sign of the
873 // dividend, while the sign of the quotient is the product of the signs of
874 // the dividend and divisor. Of course, we also always have
875 //
876 // dividend = quotient*divisor + remainder
877 //
878 // with 0 <= abs(remainder) < abs(divisor)
879 bool negRemainder = GetHi() < 0;
880 bool negQuotient = false; // assume positive
881 if ( GetHi() < 0 )
882 {
883 negQuotient = !negQuotient;
884 dividend = -*this;
885 } else {
886 dividend = *this;
887 }
888 if ( divisorIn.GetHi() < 0 )
889 {
890 negQuotient = !negQuotient;
891 divisor = -divisorIn;
892 } else {
893 divisor = divisorIn;
894 }
895
896 // check for some particular cases
897 if ( divisor > dividend )
898 {
899 remainder = dividend;
900 }
901 else if ( divisor == dividend )
902 {
903 quotient = 1l;
904 }
905 else
906 {
907 // here: dividend > divisor and both are positive: do unsigned division
908 size_t nBits = 64u;
909 wxLongLongWx d;
910
911 while ( remainder < divisor )
912 {
913 remainder <<= 1;
914 if ( IS_MSB_SET(dividend) )
915 {
916 remainder |= 1;
917 }
918
919 d = dividend;
920 dividend <<= 1;
921
922 nBits--;
923 }
924
925 // undo the last loop iteration
926 dividend = d;
927 remainder >>= 1;
928 nBits++;
929
930 for ( size_t i = 0; i < nBits; i++ )
931 {
932 remainder <<= 1;
933 if ( IS_MSB_SET(dividend) )
934 {
935 remainder |= 1;
936 }
937
938 wxLongLongWx t = remainder - divisor;
939 dividend <<= 1;
940 quotient <<= 1;
941 if ( !IS_MSB_SET(t) )
942 {
943 quotient |= 1;
944
945 remainder = t;
946 }
947 }
948 }
949
950 remainderIO = remainder;
951
952 // adjust signs
953 if ( negRemainder )
954 {
955 remainderIO = -remainderIO;
956 }
957
958 if ( negQuotient )
959 {
960 quotient = -quotient;
961 }
962 }
963
964 void wxULongLongWx::Divide(const wxULongLongWx& divisorIn,
965 wxULongLongWx& quotient,
966 wxULongLongWx& remainder) const
967 {
968 if ((divisorIn.m_lo == 0) && (divisorIn.m_hi == 0))
969 {
970 // provoke division by zero error and silence the compilers warnings
971 // about an expression without effect and unused variable
972 unsigned long dummy = divisorIn.m_lo/divisorIn.m_hi;
973 dummy += 0;
974 }
975
976 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
977 // do this - any improvements are more than welcome
978 //
979 // code inspired by the snippet at
980 // http://www.bearcave.com/software/divide.htm
981 //
982 // Copyright notice:
983 //
984 // Use of this program, for any purpose, is granted the author, Ian
985 // Kaplan, as long as this copyright notice is included in the source
986 // code or any source code derived from this program. The user assumes
987 // all responsibility for using this code.
988
989 // init everything
990 wxULongLongWx dividend = *this,
991 divisor = divisorIn;
992
993 quotient = 0l;
994 remainder = 0l;
995
996 // check for some particular cases
997 if ( divisor > dividend )
998 {
999 remainder = dividend;
1000 }
1001 else if ( divisor == dividend )
1002 {
1003 quotient = 1l;
1004 }
1005 else
1006 {
1007 // here: dividend > divisor
1008 size_t nBits = 64u;
1009 wxULongLongWx d;
1010
1011 while ( remainder < divisor )
1012 {
1013 remainder <<= 1;
1014 if ( IS_MSB_SET(dividend) )
1015 {
1016 remainder |= 1;
1017 }
1018
1019 d = dividend;
1020 dividend <<= 1;
1021
1022 nBits--;
1023 }
1024
1025 // undo the last loop iteration
1026 dividend = d;
1027 remainder >>= 1;
1028 nBits++;
1029
1030 for ( size_t i = 0; i < nBits; i++ )
1031 {
1032 remainder <<= 1;
1033 if ( IS_MSB_SET(dividend) )
1034 {
1035 remainder |= 1;
1036 }
1037
1038 wxULongLongWx t = remainder - divisor;
1039 dividend <<= 1;
1040 quotient <<= 1;
1041 if ( !IS_MSB_SET(t) )
1042 {
1043 quotient |= 1;
1044
1045 remainder = t;
1046 }
1047 }
1048 }
1049 }
1050
1051 wxLongLongWx wxLongLongWx::operator/(const wxLongLongWx& ll) const
1052 {
1053 wxLongLongWx quotient, remainder;
1054
1055 Divide(ll, quotient, remainder);
1056
1057 return quotient;
1058 }
1059
1060 wxULongLongWx wxULongLongWx::operator/(const wxULongLongWx& ll) const
1061 {
1062 wxULongLongWx quotient, remainder;
1063
1064 Divide(ll, quotient, remainder);
1065
1066 return quotient;
1067 }
1068
1069 wxLongLongWx& wxLongLongWx::operator/=(const wxLongLongWx& ll)
1070 {
1071 wxLongLongWx quotient, remainder;
1072
1073 Divide(ll, quotient, remainder);
1074
1075 *this = quotient;
1076
1077 return *this;
1078 }
1079
1080 wxULongLongWx& wxULongLongWx::operator/=(const wxULongLongWx& ll)
1081 {
1082 wxULongLongWx quotient, remainder;
1083
1084 Divide(ll, quotient, remainder);
1085
1086 *this = quotient;
1087
1088 return *this;
1089 }
1090
1091 wxLongLongWx wxLongLongWx::operator%(const wxLongLongWx& ll) const
1092 {
1093 wxLongLongWx quotient, remainder;
1094
1095 Divide(ll, quotient, remainder);
1096
1097 return remainder;
1098 }
1099
1100 wxULongLongWx wxULongLongWx::operator%(const wxULongLongWx& ll) const
1101 {
1102 wxULongLongWx quotient, remainder;
1103
1104 Divide(ll, quotient, remainder);
1105
1106 return remainder;
1107 }
1108
1109 // ----------------------------------------------------------------------------
1110 // misc
1111 // ----------------------------------------------------------------------------
1112
1113 // temporary - just for testing
1114 void *wxLongLongWx::asArray(void) const
1115 {
1116 static unsigned char temp[8];
1117
1118 temp[0] = (char)((m_hi >> 24) & 0xFF);
1119 temp[1] = (char)((m_hi >> 16) & 0xFF);
1120 temp[2] = (char)((m_hi >> 8) & 0xFF);
1121 temp[3] = (char)((m_hi >> 0) & 0xFF);
1122 temp[4] = (char)((m_lo >> 24) & 0xFF);
1123 temp[5] = (char)((m_lo >> 16) & 0xFF);
1124 temp[6] = (char)((m_lo >> 8) & 0xFF);
1125 temp[7] = (char)((m_lo >> 0) & 0xFF);
1126
1127 return temp;
1128 }
1129
1130 void *wxULongLongWx::asArray(void) const
1131 {
1132 static unsigned char temp[8];
1133
1134 temp[0] = (char)((m_hi >> 24) & 0xFF);
1135 temp[1] = (char)((m_hi >> 16) & 0xFF);
1136 temp[2] = (char)((m_hi >> 8) & 0xFF);
1137 temp[3] = (char)((m_hi >> 0) & 0xFF);
1138 temp[4] = (char)((m_lo >> 24) & 0xFF);
1139 temp[5] = (char)((m_lo >> 16) & 0xFF);
1140 temp[6] = (char)((m_lo >> 8) & 0xFF);
1141 temp[7] = (char)((m_lo >> 0) & 0xFF);
1142
1143 return temp;
1144 }
1145
1146 #endif // wxUSE_LONGLONG_WX
1147
1148 #define LL_TO_STRING(name) \
1149 wxString name::ToString() const \
1150 { \
1151 /* TODO: this is awfully inefficient, anything better? */ \
1152 wxString result; \
1153 \
1154 name ll = *this; \
1155 \
1156 bool neg = ll < 0; \
1157 if ( neg ) \
1158 { \
1159 while ( ll != 0 ) \
1160 { \
1161 long digit = (ll % 10).ToLong(); \
1162 result.Prepend((wxChar)(_T('0') - digit)); \
1163 ll /= 10; \
1164 } \
1165 } \
1166 else \
1167 { \
1168 while ( ll != 0 ) \
1169 { \
1170 long digit = (ll % 10).ToLong(); \
1171 result.Prepend((wxChar)(_T('0') + digit)); \
1172 ll /= 10; \
1173 } \
1174 } \
1175 \
1176 if ( result.empty() ) \
1177 result = _T('0'); \
1178 else if ( neg ) \
1179 result.Prepend(_T('-')); \
1180 \
1181 return result; \
1182 }
1183
1184 #define ULL_TO_STRING(name) \
1185 wxString name::ToString() const \
1186 { \
1187 /* TODO: this is awfully inefficient, anything better? */ \
1188 wxString result; \
1189 \
1190 name ll = *this; \
1191 \
1192 while ( ll != 0 ) \
1193 { \
1194 result.Prepend((wxChar)(_T('0') + (ll % 10).ToULong())); \
1195 ll /= 10; \
1196 } \
1197 \
1198 if ( result.empty() ) \
1199 result = _T('0'); \
1200 \
1201 return result; \
1202 }
1203
1204 #if wxUSE_LONGLONG_NATIVE
1205 LL_TO_STRING(wxLongLongNative)
1206 ULL_TO_STRING(wxULongLongNative)
1207 #endif
1208
1209 #if wxUSE_LONGLONG_WX
1210 LL_TO_STRING(wxLongLongWx)
1211 ULL_TO_STRING(wxULongLongWx)
1212 #endif
1213
1214 #if wxUSE_STD_IOSTREAM
1215
1216 // input/output
1217 WXDLLIMPEXP_BASE
1218 wxSTD ostream& operator<< (wxSTD ostream& o, const wxLongLong& ll)
1219 {
1220 return o << ll.ToString();
1221 }
1222
1223 WXDLLIMPEXP_BASE
1224 wxSTD ostream& operator<< (wxSTD ostream& o, const wxULongLong& ll)
1225 {
1226 return o << ll.ToString();
1227 }
1228
1229 #endif // wxUSE_STD_IOSTREAM
1230
1231 WXDLLIMPEXP_BASE wxString& operator<< (wxString& s, const wxLongLong& ll)
1232 {
1233 return s << ll.ToString();
1234 }
1235
1236 WXDLLIMPEXP_BASE wxString& operator<< (wxString& s, const wxULongLong& ll)
1237 {
1238 return s << ll.ToString();
1239 }
1240
1241 #if wxUSE_STREAMS
1242
1243 WXDLLIMPEXP_BASE wxTextOutputStream& operator<< (wxTextOutputStream& o, const wxULongLong& ll)
1244 {
1245 return o << ll.ToString();
1246 }
1247
1248 WXDLLIMPEXP_BASE wxTextOutputStream& operator<< (wxTextOutputStream& o, const wxLongLong& ll)
1249 {
1250 return o << ll.ToString();
1251 }
1252
1253 #define READ_STRING_CHAR(s, idx, len) ((wxChar) ((idx!=len) ? s[idx++] : 0))
1254
1255 WXDLLIMPEXP_BASE class wxTextInputStream &operator>>(class wxTextInputStream &o, wxULongLong &ll)
1256 {
1257 wxString s = o.ReadWord();
1258
1259 ll = wxULongLong(0l, 0l);
1260 size_t length = s.Length();
1261 size_t idx = 0;
1262
1263 wxChar ch = READ_STRING_CHAR(s, idx, length);
1264
1265 // Skip WS
1266 while (ch==wxT(' ') || ch==wxT('\t'))
1267 ch = READ_STRING_CHAR(s, idx, length);
1268
1269 // Read number
1270 wxULongLong multiplier(0l, 10l);
1271 while (ch>=wxT('0') && ch<=wxT('9')) {
1272 long lValue = (unsigned) (ch - wxT('0'));
1273 ll = ll * multiplier + wxULongLong(0l, lValue);
1274 ch = READ_STRING_CHAR(s, idx, length);
1275 }
1276
1277 return o;
1278 }
1279
1280 WXDLLIMPEXP_BASE class wxTextInputStream &operator>>(class wxTextInputStream &o, wxLongLong &ll)
1281 {
1282 wxString s = o.ReadWord();
1283
1284 ll = wxLongLong(0l, 0l);
1285 size_t length = s.Length();
1286 size_t idx = 0;
1287
1288 wxChar ch = READ_STRING_CHAR(s, idx, length);
1289
1290 // Skip WS
1291 while (ch==wxT(' ') || ch==wxT('\t'))
1292 ch = READ_STRING_CHAR(s, idx, length);
1293
1294 // Ask for sign
1295 int iSign = 1;
1296 if (ch==wxT('-') || ch==wxT('+')) {
1297 iSign = ((ch==wxT('-')) ? -1 : 1);
1298 ch = READ_STRING_CHAR(s, idx, length);
1299 }
1300
1301 // Read number
1302 wxLongLong multiplier(0l, 10l);
1303 while (ch>=wxT('0') && ch<=wxT('9')) {
1304 long lValue = (unsigned) (ch - wxT('0'));
1305 ll = ll * multiplier + wxLongLong(0l, lValue);
1306 ch = READ_STRING_CHAR(s, idx, length);
1307 }
1308
1309 #if wxUSE_LONGLONG_NATIVE
1310 ll = ll * wxLongLong((wxLongLong_t) iSign);
1311 #else
1312 ll = ll * wxLongLong((long) iSign);
1313 #endif
1314
1315 return o;
1316 }
1317
1318 #if wxUSE_LONGLONG_NATIVE
1319
1320 WXDLLIMPEXP_BASE class wxTextOutputStream &operator<<(class wxTextOutputStream &o, wxULongLong_t value)
1321 {
1322 return o << wxULongLong(value).ToString();
1323 }
1324
1325 WXDLLIMPEXP_BASE class wxTextOutputStream &operator<<(class wxTextOutputStream &o, wxLongLong_t value)
1326 {
1327 return o << wxLongLong(value).ToString();
1328 }
1329
1330 WXDLLIMPEXP_BASE class wxTextInputStream &operator>>(class wxTextInputStream &o, wxULongLong_t &value)
1331 {
1332 wxULongLong ll;
1333 o >> ll;
1334 value = ll.GetValue();
1335 return o;
1336 }
1337
1338 WXDLLIMPEXP_BASE class wxTextInputStream &operator>>(class wxTextInputStream &o, wxLongLong_t &value)
1339 {
1340 wxLongLong ll;
1341 o >> ll;
1342 value = ll.GetValue();
1343 return o;
1344 }
1345
1346 #endif // wxUSE_LONGLONG_NATIVE
1347
1348 #endif // wxUSE_STREAMS
1349
1350 #endif // wxUSE_LONGLONG