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