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