]> git.saurik.com Git - wxWidgets.git/blob - src/common/longlong.cpp
limit recursion depth in DumpUDT() to prevent crashes when dumping linked lists
[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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
19 #pragma implementation "longlong.h"
20 #endif
21
22 #include "wx/wxprec.h"
23
24 #ifdef __BORLANDC__
25 #pragma hdrstop
26 #endif
27
28 #if wxUSE_LONGLONG
29 #include "wx/longlong.h"
30 #include "wx/math.h" // for fabs()
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] = (unsigned char)((m_ll >> 56) & 0xFF);
55 temp[1] = (unsigned char)((m_ll >> 48) & 0xFF);
56 temp[2] = (unsigned char)((m_ll >> 40) & 0xFF);
57 temp[3] = (unsigned char)((m_ll >> 32) & 0xFF);
58 temp[4] = (unsigned char)((m_ll >> 24) & 0xFF);
59 temp[5] = (unsigned char)((m_ll >> 16) & 0xFF);
60 temp[6] = (unsigned char)((m_ll >> 8) & 0xFF);
61 temp[7] = (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] = (unsigned char)((m_ll >> 56) & 0xFF);
71 temp[1] = (unsigned char)((m_ll >> 48) & 0xFF);
72 temp[2] = (unsigned char)((m_ll >> 40) & 0xFF);
73 temp[3] = (unsigned char)((m_ll >> 32) & 0xFF);
74 temp[4] = (unsigned char)((m_ll >> 24) & 0xFF);
75 temp[5] = (unsigned char)((m_ll >> 16) & 0xFF);
76 temp[6] = (unsigned char)((m_ll >> 8) & 0xFF);
77 temp[7] = (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 #endif
100
101 #endif // wxUSE_LONGLONG_NATIVE
102
103 // ============================================================================
104 // wxLongLongWx: emulation of 'long long' using 2 longs
105 // ============================================================================
106
107 #if wxUSE_LONGLONG_WX
108
109 // assignment
110 wxLongLongWx& wxLongLongWx::Assign(double d)
111 {
112 bool positive = d >= 0;
113 d = fabs(d);
114 if ( d <= ULONG_MAX )
115 {
116 m_hi = 0;
117 m_lo = (long)d;
118 }
119 else
120 {
121 m_hi = (unsigned long)(d / (1.0 + (double)ULONG_MAX));
122 m_lo = (unsigned long)(d - ((double)m_hi * (1.0 + (double)ULONG_MAX)));
123 }
124
125 #ifdef wxLONGLONG_TEST_MODE
126 m_ll = (wxLongLong_t)d;
127
128 Check();
129 #endif // wxLONGLONG_TEST_MODE
130
131 if ( !positive )
132 Negate();
133
134 return *this;
135 }
136
137 wxLongLongWx wxLongLongWx::operator<<(int shift) const
138 {
139 wxLongLongWx ll(*this);
140 ll <<= shift;
141
142 return ll;
143 }
144
145 wxULongLongWx wxULongLongWx::operator<<(int shift) const
146 {
147 wxULongLongWx ll(*this);
148 ll <<= shift;
149
150 return ll;
151 }
152
153 wxLongLongWx& wxLongLongWx::operator<<=(int shift)
154 {
155 if (shift != 0)
156 {
157 if (shift < 32)
158 {
159 m_hi <<= shift;
160 m_hi |= m_lo >> (32 - shift);
161 m_lo <<= shift;
162 }
163 else
164 {
165 m_hi = m_lo << (shift - 32);
166 m_lo = 0;
167 }
168 }
169
170 #ifdef wxLONGLONG_TEST_MODE
171 m_ll <<= shift;
172
173 Check();
174 #endif // wxLONGLONG_TEST_MODE
175
176 return *this;
177 }
178
179 wxULongLongWx& wxULongLongWx::operator<<=(int shift)
180 {
181 if (shift != 0)
182 {
183 if (shift < 32)
184 {
185 m_hi <<= shift;
186 m_hi |= m_lo >> (32 - shift);
187 m_lo <<= shift;
188 }
189 else
190 {
191 m_hi = m_lo << (shift - 32);
192 m_lo = 0;
193 }
194 }
195
196 #ifdef wxLONGLONG_TEST_MODE
197 m_ll <<= shift;
198
199 Check();
200 #endif // wxLONGLONG_TEST_MODE
201
202 return *this;
203 }
204
205 wxLongLongWx wxLongLongWx::operator>>(int shift) const
206 {
207 wxLongLongWx ll(*this);
208 ll >>= shift;
209
210 return ll;
211 }
212
213 wxULongLongWx wxULongLongWx::operator>>(int shift) const
214 {
215 wxULongLongWx ll(*this);
216 ll >>= shift;
217
218 return ll;
219 }
220
221 wxLongLongWx& wxLongLongWx::operator>>=(int shift)
222 {
223 if (shift != 0)
224 {
225 if (shift < 32)
226 {
227 m_lo >>= shift;
228 m_lo |= m_hi << (32 - shift);
229 m_hi >>= shift;
230 }
231 else
232 {
233 m_lo = m_hi >> (shift - 32);
234 m_hi = (m_hi < 0 ? -1L : 0);
235 }
236 }
237
238 #ifdef wxLONGLONG_TEST_MODE
239 m_ll >>= shift;
240
241 Check();
242 #endif // wxLONGLONG_TEST_MODE
243
244 return *this;
245 }
246
247 wxULongLongWx& wxULongLongWx::operator>>=(int shift)
248 {
249 if (shift != 0)
250 {
251 if (shift < 32)
252 {
253 m_lo >>= shift;
254 m_lo |= m_hi << (32 - shift);
255 m_hi >>= shift;
256 }
257 else
258 {
259 m_lo = m_hi >> (shift - 32);
260 m_hi = 0;
261 }
262 }
263
264 #ifdef wxLONGLONG_TEST_MODE
265 m_ll >>= shift;
266
267 Check();
268 #endif // wxLONGLONG_TEST_MODE
269
270 return *this;
271 }
272
273 wxLongLongWx wxLongLongWx::operator+(const wxLongLongWx& ll) const
274 {
275 wxLongLongWx res(*this);
276 res += ll;
277
278 return res;
279 }
280
281 wxULongLongWx wxULongLongWx::operator+(const wxULongLongWx& ll) const
282 {
283 wxULongLongWx res(*this);
284 res += ll;
285
286 return res;
287 }
288
289 wxLongLongWx wxLongLongWx::operator+(long l) const
290 {
291 wxLongLongWx res(*this);
292 res += l;
293
294 return res;
295 }
296
297 wxULongLongWx wxULongLongWx::operator+(unsigned long l) const
298 {
299 wxULongLongWx res(*this);
300 res += l;
301
302 return res;
303 }
304
305 wxLongLongWx& wxLongLongWx::operator+=(const wxLongLongWx& ll)
306 {
307 unsigned long previous = m_lo;
308
309 m_lo += ll.m_lo;
310 m_hi += ll.m_hi;
311
312 if ((m_lo < previous) || (m_lo < ll.m_lo))
313 m_hi++;
314
315 #ifdef wxLONGLONG_TEST_MODE
316 m_ll += ll.m_ll;
317
318 Check();
319 #endif // wxLONGLONG_TEST_MODE
320
321 return *this;
322 }
323
324 wxULongLongWx& wxULongLongWx::operator+=(const wxULongLongWx& ll)
325 {
326 unsigned long previous = m_lo;
327
328 m_lo += ll.m_lo;
329 m_hi += ll.m_hi;
330
331 if ((m_lo < previous) || (m_lo < ll.m_lo))
332 m_hi++;
333
334 #ifdef wxLONGLONG_TEST_MODE
335 m_ll += ll.m_ll;
336
337 Check();
338 #endif // wxLONGLONG_TEST_MODE
339
340 return *this;
341 }
342
343 wxLongLongWx& wxLongLongWx::operator+=(long l)
344 {
345 unsigned long previous = m_lo;
346
347 m_lo += l;
348 if (l < 0)
349 m_hi += -1l;
350
351 if ((m_lo < previous) || (m_lo < (unsigned long)l))
352 m_hi++;
353
354 #ifdef wxLONGLONG_TEST_MODE
355 m_ll += l;
356
357 Check();
358 #endif // wxLONGLONG_TEST_MODE
359
360 return *this;
361 }
362
363 wxULongLongWx& wxULongLongWx::operator+=(unsigned long l)
364 {
365 unsigned long previous = m_lo;
366
367 m_lo += l;
368
369 if ((m_lo < previous) || (m_lo < l))
370 m_hi++;
371
372 #ifdef wxLONGLONG_TEST_MODE
373 m_ll += l;
374
375 Check();
376 #endif // wxLONGLONG_TEST_MODE
377
378 return *this;
379 }
380
381 // pre increment
382 wxLongLongWx& wxLongLongWx::operator++()
383 {
384 m_lo++;
385 if (m_lo == 0)
386 m_hi++;
387
388 #ifdef wxLONGLONG_TEST_MODE
389 m_ll++;
390
391 Check();
392 #endif // wxLONGLONG_TEST_MODE
393
394 return *this;
395 }
396
397 wxULongLongWx& wxULongLongWx::operator++()
398 {
399 m_lo++;
400 if (m_lo == 0)
401 m_hi++;
402
403 #ifdef wxLONGLONG_TEST_MODE
404 m_ll++;
405
406 Check();
407 #endif // wxLONGLONG_TEST_MODE
408
409 return *this;
410 }
411
412 // negation
413 wxLongLongWx wxLongLongWx::operator-() const
414 {
415 wxLongLongWx res(*this);
416 res.Negate();
417
418 return res;
419 }
420
421 wxLongLongWx& wxLongLongWx::Negate()
422 {
423 m_hi = ~m_hi;
424 m_lo = ~m_lo;
425
426 m_lo++;
427 if ( m_lo == 0 )
428 m_hi++;
429
430 #ifdef wxLONGLONG_TEST_MODE
431 m_ll = -m_ll;
432
433 Check();
434 #endif // wxLONGLONG_TEST_MODE
435
436 return *this;
437 }
438
439 // subtraction
440
441 wxLongLongWx wxLongLongWx::operator-(const wxLongLongWx& ll) const
442 {
443 wxLongLongWx res(*this);
444 res -= ll;
445
446 return res;
447 }
448
449 wxLongLongWx wxULongLongWx::operator-(const wxULongLongWx& ll) const
450 {
451 wxASSERT(m_hi <= LONG_MAX );
452 wxASSERT(ll.m_hi <= LONG_MAX );
453
454 wxLongLongWx res( (long)m_hi , m_lo );
455 wxLongLongWx op( (long)ll.m_hi , ll.m_lo );
456 res -= op;
457
458 return res;
459 }
460
461 wxLongLongWx& wxLongLongWx::operator-=(const wxLongLongWx& ll)
462 {
463 unsigned long previous = m_lo;
464
465 m_lo -= ll.m_lo;
466 m_hi -= ll.m_hi;
467
468 if (previous < ll.m_lo)
469 m_hi--;
470
471 #ifdef wxLONGLONG_TEST_MODE
472 m_ll -= ll.m_ll;
473
474 Check();
475 #endif // wxLONGLONG_TEST_MODE
476
477 return *this;
478 }
479
480 wxULongLongWx& wxULongLongWx::operator-=(const wxULongLongWx& ll)
481 {
482 unsigned long previous = m_lo;
483
484 m_lo -= ll.m_lo;
485 m_hi -= ll.m_hi;
486
487 if (previous < ll.m_lo)
488 m_hi--;
489
490 #ifdef wxLONGLONG_TEST_MODE
491 m_ll -= ll.m_ll;
492
493 Check();
494 #endif // wxLONGLONG_TEST_MODE
495
496 return *this;
497 }
498
499 // pre decrement
500 wxLongLongWx& wxLongLongWx::operator--()
501 {
502 m_lo--;
503 if (m_lo == 0xFFFFFFFF)
504 m_hi--;
505
506 #ifdef wxLONGLONG_TEST_MODE
507 m_ll--;
508
509 Check();
510 #endif // wxLONGLONG_TEST_MODE
511
512 return *this;
513 }
514
515 wxULongLongWx& wxULongLongWx::operator--()
516 {
517 m_lo--;
518 if (m_lo == 0xFFFFFFFF)
519 m_hi--;
520
521 #ifdef wxLONGLONG_TEST_MODE
522 m_ll--;
523
524 Check();
525 #endif // wxLONGLONG_TEST_MODE
526
527 return *this;
528 }
529
530 // comparison operators
531
532 bool wxLongLongWx::operator<(const wxLongLongWx& ll) const
533 {
534 if ( m_hi < ll.m_hi )
535 return true;
536 else if ( m_hi == ll.m_hi )
537 return m_lo < ll.m_lo;
538 else
539 return false;
540 }
541
542 bool wxULongLongWx::operator<(const wxULongLongWx& ll) const
543 {
544 if ( m_hi < ll.m_hi )
545 return true;
546 else if ( m_hi == ll.m_hi )
547 return m_lo < ll.m_lo;
548 else
549 return false;
550 }
551
552 bool wxLongLongWx::operator>(const wxLongLongWx& ll) const
553 {
554 if ( m_hi > ll.m_hi )
555 return true;
556 else if ( m_hi == ll.m_hi )
557 return m_lo > ll.m_lo;
558 else
559 return false;
560 }
561
562 bool wxULongLongWx::operator>(const wxULongLongWx& ll) const
563 {
564 if ( m_hi > ll.m_hi )
565 return true;
566 else if ( m_hi == ll.m_hi )
567 return m_lo > ll.m_lo;
568 else
569 return false;
570 }
571
572 // bitwise operators
573
574 wxLongLongWx wxLongLongWx::operator&(const wxLongLongWx& ll) const
575 {
576 return wxLongLongWx(m_hi & ll.m_hi, m_lo & ll.m_lo);
577 }
578
579 wxULongLongWx wxULongLongWx::operator&(const wxULongLongWx& ll) const
580 {
581 return wxULongLongWx(m_hi & ll.m_hi, m_lo & ll.m_lo);
582 }
583
584 wxLongLongWx wxLongLongWx::operator|(const wxLongLongWx& ll) const
585 {
586 return wxLongLongWx(m_hi | ll.m_hi, m_lo | ll.m_lo);
587 }
588
589 wxULongLongWx wxULongLongWx::operator|(const wxULongLongWx& ll) const
590 {
591 return wxULongLongWx(m_hi | ll.m_hi, m_lo | ll.m_lo);
592 }
593
594 wxLongLongWx wxLongLongWx::operator^(const wxLongLongWx& ll) const
595 {
596 return wxLongLongWx(m_hi ^ ll.m_hi, m_lo ^ ll.m_lo);
597 }
598
599 wxULongLongWx wxULongLongWx::operator^(const wxULongLongWx& ll) const
600 {
601 return wxULongLongWx(m_hi ^ ll.m_hi, m_lo ^ ll.m_lo);
602 }
603
604 wxLongLongWx& wxLongLongWx::operator&=(const wxLongLongWx& ll)
605 {
606 m_lo &= ll.m_lo;
607 m_hi &= ll.m_hi;
608
609 #ifdef wxLONGLONG_TEST_MODE
610 m_ll &= ll.m_ll;
611
612 Check();
613 #endif // wxLONGLONG_TEST_MODE
614
615 return *this;
616 }
617
618 wxULongLongWx& wxULongLongWx::operator&=(const wxULongLongWx& ll)
619 {
620 m_lo &= ll.m_lo;
621 m_hi &= ll.m_hi;
622
623 #ifdef wxLONGLONG_TEST_MODE
624 m_ll &= ll.m_ll;
625
626 Check();
627 #endif // wxLONGLONG_TEST_MODE
628
629 return *this;
630 }
631
632 wxLongLongWx& wxLongLongWx::operator|=(const wxLongLongWx& ll)
633 {
634 m_lo |= ll.m_lo;
635 m_hi |= ll.m_hi;
636
637 #ifdef wxLONGLONG_TEST_MODE
638 m_ll |= ll.m_ll;
639
640 Check();
641 #endif // wxLONGLONG_TEST_MODE
642
643 return *this;
644 }
645
646 wxULongLongWx& wxULongLongWx::operator|=(const wxULongLongWx& ll)
647 {
648 m_lo |= ll.m_lo;
649 m_hi |= ll.m_hi;
650
651 #ifdef wxLONGLONG_TEST_MODE
652 m_ll |= ll.m_ll;
653
654 Check();
655 #endif // wxLONGLONG_TEST_MODE
656
657 return *this;
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
689 {
690 return wxLongLongWx(~m_hi, ~m_lo);
691 }
692
693 wxULongLongWx wxULongLongWx::operator~() const
694 {
695 return wxULongLongWx(~m_hi, ~m_lo);
696 }
697
698 // multiplication
699
700 wxLongLongWx wxLongLongWx::operator*(const wxLongLongWx& ll) const
701 {
702 wxLongLongWx res(*this);
703 res *= ll;
704
705 return res;
706 }
707
708 wxULongLongWx wxULongLongWx::operator*(const wxULongLongWx& ll) const
709 {
710 wxULongLongWx res(*this);
711 res *= ll;
712
713 return res;
714 }
715
716 wxLongLongWx& wxLongLongWx::operator*=(const wxLongLongWx& ll)
717 {
718 wxLongLongWx t(m_hi, m_lo);
719 wxLongLongWx q(ll.m_hi, ll.m_lo);
720
721 m_hi = m_lo = 0;
722
723 #ifdef wxLONGLONG_TEST_MODE
724 wxLongLong_t llOld = m_ll;
725 m_ll = 0;
726 #endif // wxLONGLONG_TEST_MODE
727
728 int counter = 0;
729 do
730 {
731 if ((q.m_lo & 1) != 0)
732 *this += t;
733 q >>= 1;
734 t <<= 1;
735 counter++;
736 }
737 while ((counter < 64) && ((q.m_hi != 0) || (q.m_lo != 0)));
738
739 #ifdef wxLONGLONG_TEST_MODE
740 m_ll = llOld * ll.m_ll;
741
742 Check();
743 #endif // wxLONGLONG_TEST_MODE
744
745 return *this;
746 }
747
748 wxULongLongWx& wxULongLongWx::operator*=(const wxULongLongWx& ll)
749 {
750 wxULongLongWx t(m_hi, m_lo);
751 wxULongLongWx q(ll.m_hi, ll.m_lo);
752
753 m_hi = m_lo = 0;
754
755 #ifdef wxLONGLONG_TEST_MODE
756 wxULongLong_t llOld = m_ll;
757 m_ll = 0;
758 #endif // wxLONGLONG_TEST_MODE
759
760 int counter = 0;
761 do
762 {
763 if ((q.m_lo & 1) != 0)
764 *this += t;
765 q >>= 1;
766 t <<= 1;
767 counter++;
768 }
769 while ((counter < 64) && ((q.m_hi != 0) || (q.m_lo != 0)));
770
771 #ifdef wxLONGLONG_TEST_MODE
772 m_ll = llOld * ll.m_ll;
773
774 Check();
775 #endif // wxLONGLONG_TEST_MODE
776
777 return *this;
778 }
779
780 // division
781
782 void wxLongLongWx::Divide(const wxLongLongWx& divisorIn,
783 wxLongLongWx& quotient,
784 wxLongLongWx& remainder) const
785 {
786 if ((divisorIn.m_lo == 0) && (divisorIn.m_hi == 0))
787 {
788 // provoke division by zero error and silence the compilers warnings
789 // about an expression without effect and unused variable
790 long dummy = divisorIn.m_lo/divisorIn.m_hi;
791 dummy += 0;
792 }
793
794 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
795 // do this - any improvements are more than welcome
796 //
797 // code inspired by the snippet at
798 // http://www.bearcave.com/software/divide.htm
799 //
800 // Copyright notice:
801 //
802 // Use of this program, for any purpose, is granted the author, Ian
803 // Kaplan, as long as this copyright notice is included in the source
804 // code or any source code derived from this program. The user assumes
805 // all responsibility for using this code.
806
807 // init everything
808 wxLongLongWx dividend = *this,
809 divisor = divisorIn;
810
811 quotient = 0l;
812 remainder = 0l;
813
814 // always do unsigned division and adjust the signs later: in C integer
815 // division, the sign of the remainder is the same as the sign of the
816 // dividend, while the sign of the quotient is the product of the signs of
817 // the dividend and divisor. Of course, we also always have
818 //
819 // dividend = quotient*divisor + remainder
820 //
821 // with 0 <= abs(remainder) < abs(divisor)
822 bool negRemainder = dividend.m_hi < 0;
823 bool negQuotient = false; // assume positive
824 if ( dividend.m_hi < 0 )
825 {
826 negQuotient = !negQuotient;
827 dividend = -dividend;
828 }
829 if ( divisor.m_hi < 0 )
830 {
831 negQuotient = !negQuotient;
832 divisor = -divisor;
833 }
834
835 // check for some particular cases
836 if ( divisor > dividend )
837 {
838 remainder = dividend;
839 }
840 else if ( divisor == dividend )
841 {
842 quotient = 1l;
843 }
844 else
845 {
846 // here: dividend > divisor and both are positive: do unsigned division
847 size_t nBits = 64u;
848 wxLongLongWx d;
849
850 #define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1)))
851
852 while ( remainder < divisor )
853 {
854 remainder <<= 1;
855 if ( IS_MSB_SET(dividend) )
856 {
857 remainder |= 1;
858 }
859
860 d = dividend;
861 dividend <<= 1;
862
863 nBits--;
864 }
865
866 // undo the last loop iteration
867 dividend = d;
868 remainder >>= 1;
869 nBits++;
870
871 for ( size_t i = 0; i < nBits; i++ )
872 {
873 remainder <<= 1;
874 if ( IS_MSB_SET(dividend) )
875 {
876 remainder |= 1;
877 }
878
879 wxLongLongWx t = remainder - divisor;
880 dividend <<= 1;
881 quotient <<= 1;
882 if ( !IS_MSB_SET(t) )
883 {
884 quotient |= 1;
885
886 remainder = t;
887 }
888 }
889 }
890
891 // adjust signs
892 if ( negRemainder )
893 {
894 remainder = -remainder;
895 }
896
897 if ( negQuotient )
898 {
899 quotient = -quotient;
900 }
901 }
902
903 void wxULongLongWx::Divide(const wxULongLongWx& divisorIn,
904 wxULongLongWx& quotient,
905 wxULongLongWx& remainder) const
906 {
907 if ((divisorIn.m_lo == 0) && (divisorIn.m_hi == 0))
908 {
909 // provoke division by zero error and silence the compilers warnings
910 // about an expression without effect and unused variable
911 unsigned long dummy = divisorIn.m_lo/divisorIn.m_hi;
912 dummy += 0;
913 }
914
915 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
916 // do this - any improvements are more than welcome
917 //
918 // code inspired by the snippet at
919 // http://www.bearcave.com/software/divide.htm
920 //
921 // Copyright notice:
922 //
923 // Use of this program, for any purpose, is granted the author, Ian
924 // Kaplan, as long as this copyright notice is included in the source
925 // code or any source code derived from this program. The user assumes
926 // all responsibility for using this code.
927
928 // init everything
929 wxULongLongWx dividend = *this,
930 divisor = divisorIn;
931
932 quotient = 0l;
933 remainder = 0l;
934
935 // check for some particular cases
936 if ( divisor > dividend )
937 {
938 remainder = dividend;
939 }
940 else if ( divisor == dividend )
941 {
942 quotient = 1l;
943 }
944 else
945 {
946 // here: dividend > divisor
947 size_t nBits = 64u;
948 wxULongLongWx d;
949
950 #define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1)))
951
952 while ( remainder < divisor )
953 {
954 remainder <<= 1;
955 if ( IS_MSB_SET(dividend) )
956 {
957 remainder |= 1;
958 }
959
960 d = dividend;
961 dividend <<= 1;
962
963 nBits--;
964 }
965
966 // undo the last loop iteration
967 dividend = d;
968 remainder >>= 1;
969 nBits++;
970
971 for ( size_t i = 0; i < nBits; i++ )
972 {
973 remainder <<= 1;
974 if ( IS_MSB_SET(dividend) )
975 {
976 remainder |= 1;
977 }
978
979 wxULongLongWx t = remainder - divisor;
980 dividend <<= 1;
981 quotient <<= 1;
982 if ( !IS_MSB_SET(t) )
983 {
984 quotient |= 1;
985
986 remainder = t;
987 }
988 }
989 }
990 }
991
992 wxLongLongWx wxLongLongWx::operator/(const wxLongLongWx& ll) const
993 {
994 wxLongLongWx quotient, remainder;
995
996 Divide(ll, quotient, remainder);
997
998 return quotient;
999 }
1000
1001 wxULongLongWx wxULongLongWx::operator/(const wxULongLongWx& ll) const
1002 {
1003 wxULongLongWx quotient, remainder;
1004
1005 Divide(ll, quotient, remainder);
1006
1007 return quotient;
1008 }
1009
1010 wxLongLongWx& wxLongLongWx::operator/=(const wxLongLongWx& ll)
1011 {
1012 wxLongLongWx quotient, remainder;
1013
1014 Divide(ll, quotient, remainder);
1015
1016 *this = quotient;
1017
1018 return *this;
1019 }
1020
1021 wxULongLongWx& wxULongLongWx::operator/=(const wxULongLongWx& ll)
1022 {
1023 wxULongLongWx quotient, remainder;
1024
1025 Divide(ll, quotient, remainder);
1026
1027 *this = quotient;
1028
1029 return *this;
1030 }
1031
1032 wxLongLongWx wxLongLongWx::operator%(const wxLongLongWx& ll) const
1033 {
1034 wxLongLongWx quotient, remainder;
1035
1036 Divide(ll, quotient, remainder);
1037
1038 return remainder;
1039 }
1040
1041 wxULongLongWx wxULongLongWx::operator%(const wxULongLongWx& ll) const
1042 {
1043 wxULongLongWx quotient, remainder;
1044
1045 Divide(ll, quotient, remainder);
1046
1047 return remainder;
1048 }
1049
1050 // ----------------------------------------------------------------------------
1051 // misc
1052 // ----------------------------------------------------------------------------
1053
1054 // temporary - just for testing
1055 void *wxLongLongWx::asArray(void) const
1056 {
1057 static unsigned char temp[8];
1058
1059 temp[0] = (char)((m_hi >> 24) & 0xFF);
1060 temp[1] = (char)((m_hi >> 16) & 0xFF);
1061 temp[2] = (char)((m_hi >> 8) & 0xFF);
1062 temp[3] = (char)((m_hi >> 0) & 0xFF);
1063 temp[4] = (char)((m_lo >> 24) & 0xFF);
1064 temp[5] = (char)((m_lo >> 16) & 0xFF);
1065 temp[6] = (char)((m_lo >> 8) & 0xFF);
1066 temp[7] = (char)((m_lo >> 0) & 0xFF);
1067
1068 return temp;
1069 }
1070
1071 void *wxULongLongWx::asArray(void) const
1072 {
1073 static unsigned char temp[8];
1074
1075 temp[0] = (char)((m_hi >> 24) & 0xFF);
1076 temp[1] = (char)((m_hi >> 16) & 0xFF);
1077 temp[2] = (char)((m_hi >> 8) & 0xFF);
1078 temp[3] = (char)((m_hi >> 0) & 0xFF);
1079 temp[4] = (char)((m_lo >> 24) & 0xFF);
1080 temp[5] = (char)((m_lo >> 16) & 0xFF);
1081 temp[6] = (char)((m_lo >> 8) & 0xFF);
1082 temp[7] = (char)((m_lo >> 0) & 0xFF);
1083
1084 return temp;
1085 }
1086
1087 #endif // wxUSE_LONGLONG_WX
1088
1089 #define LL_TO_STRING(name) \
1090 wxString name::ToString() const \
1091 { \
1092 /* TODO: this is awfully inefficient, anything better? */ \
1093 wxString result; \
1094 \
1095 name ll = *this; \
1096 \
1097 bool neg = ll < 0; \
1098 if ( neg ) \
1099 { \
1100 while ( ll != 0 ) \
1101 { \
1102 long digit = (ll % 10).ToLong(); \
1103 result.Prepend((wxChar)(_T('0') - digit)); \
1104 ll /= 10; \
1105 } \
1106 } \
1107 else \
1108 { \
1109 while ( ll != 0 ) \
1110 { \
1111 long digit = (ll % 10).ToLong(); \
1112 result.Prepend((wxChar)(_T('0') + digit)); \
1113 ll /= 10; \
1114 } \
1115 } \
1116 \
1117 if ( result.empty() ) \
1118 result = _T('0'); \
1119 else if ( neg ) \
1120 result.Prepend(_T('-')); \
1121 \
1122 return result; \
1123 }
1124
1125 #define ULL_TO_STRING(name) \
1126 wxString name::ToString() const \
1127 { \
1128 /* TODO: this is awfully inefficient, anything better? */ \
1129 wxString result; \
1130 \
1131 name ll = *this; \
1132 \
1133 while ( ll != 0 ) \
1134 { \
1135 result.Prepend((wxChar)(_T('0') + (ll % 10).ToULong())); \
1136 ll /= 10; \
1137 } \
1138 \
1139 if ( result.empty() ) \
1140 result = _T('0'); \
1141 \
1142 return result; \
1143 }
1144
1145 #if wxUSE_LONGLONG_NATIVE
1146 LL_TO_STRING(wxLongLongNative)
1147 ULL_TO_STRING(wxULongLongNative)
1148 #endif
1149
1150 #if wxUSE_LONGLONG_WX
1151 LL_TO_STRING(wxLongLongWx)
1152 ULL_TO_STRING(wxULongLongWx)
1153 #endif
1154
1155 #if wxUSE_STD_IOSTREAM
1156
1157 // input/output
1158 WXDLLIMPEXP_BASE
1159 wxSTD ostream& operator<< (wxSTD ostream& o, const wxLongLong& ll)
1160 {
1161 return o << ll.ToString();
1162 }
1163
1164 WXDLLIMPEXP_BASE
1165 wxSTD ostream& operator<< (wxSTD ostream& o, const wxULongLong& ll)
1166 {
1167 return o << ll.ToString();
1168 }
1169
1170 #endif // wxUSE_STD_IOSTREAM
1171
1172 WXDLLIMPEXP_BASE wxString& operator<< (wxString& s, const wxLongLong& ll)
1173 {
1174 return s << ll.ToString();
1175 }
1176
1177 WXDLLIMPEXP_BASE wxString& operator<< (wxString& s, const wxULongLong& ll)
1178 {
1179 return s << ll.ToString();
1180 }
1181
1182 #endif // wxUSE_LONGLONG