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