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