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