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