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