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