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