]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/longlong.cpp
Hopefully fixed library names generated by wx-config for OS/2's PM port.
[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#include "wx/ioswrap.h"
39
40// ============================================================================
41// implementation
42// ============================================================================
43
44#if wxUSE_LONGLONG_NATIVE
45
46// ----------------------------------------------------------------------------
47// misc
48// ----------------------------------------------------------------------------
49
50void *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
66void *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
83wxLongLongNative::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
91wxLongLongNative& 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
110wxLongLongWx& 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
137wxLongLongWx wxLongLongWx::operator<<(int shift) const
138{
139 wxLongLongWx ll(*this);
140 ll <<= shift;
141
142 return ll;
143}
144
145wxULongLongWx wxULongLongWx::operator<<(int shift) const
146{
147 wxULongLongWx ll(*this);
148 ll <<= shift;
149
150 return ll;
151}
152
153wxLongLongWx& 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
179wxULongLongWx& 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
205wxLongLongWx wxLongLongWx::operator>>(int shift) const
206{
207 wxLongLongWx ll(*this);
208 ll >>= shift;
209
210 return ll;
211}
212
213wxULongLongWx wxULongLongWx::operator>>(int shift) const
214{
215 wxULongLongWx ll(*this);
216 ll >>= shift;
217
218 return ll;
219}
220
221wxLongLongWx& 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
247wxULongLongWx& 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
273wxLongLongWx wxLongLongWx::operator+(const wxLongLongWx& ll) const
274{
275 wxLongLongWx res(*this);
276 res += ll;
277
278 return res;
279}
280
281wxULongLongWx wxULongLongWx::operator+(const wxULongLongWx& ll) const
282{
283 wxULongLongWx res(*this);
284 res += ll;
285
286 return res;
287}
288
289wxLongLongWx wxLongLongWx::operator+(long l) const
290{
291 wxLongLongWx res(*this);
292 res += l;
293
294 return res;
295}
296
297wxULongLongWx wxULongLongWx::operator+(unsigned long l) const
298{
299 wxULongLongWx res(*this);
300 res += l;
301
302 return res;
303}
304
305wxLongLongWx& 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
324wxULongLongWx& 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
343wxLongLongWx& 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
363wxULongLongWx& 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
382wxLongLongWx& 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
397wxULongLongWx& 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
413wxLongLongWx wxLongLongWx::operator-() const
414{
415 wxLongLongWx res(*this);
416 res.Negate();
417
418 return res;
419}
420
421wxLongLongWx& 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
441wxLongLongWx wxLongLongWx::operator-(const wxLongLongWx& ll) const
442{
443 wxLongLongWx res(*this);
444 res -= ll;
445
446 return res;
447}
448
449wxLongLongWx 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
461wxLongLongWx& 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
480wxULongLongWx& 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
500wxLongLongWx& 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
515wxULongLongWx& 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
532bool 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
542bool 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
552bool 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
562bool 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
574wxLongLongWx wxLongLongWx::operator&(const wxLongLongWx& ll) const
575{
576 return wxLongLongWx(m_hi & ll.m_hi, m_lo & ll.m_lo);
577}
578
579wxULongLongWx wxULongLongWx::operator&(const wxULongLongWx& ll) const
580{
581 return wxULongLongWx(m_hi & ll.m_hi, m_lo & ll.m_lo);
582}
583
584wxLongLongWx wxLongLongWx::operator|(const wxLongLongWx& ll) const
585{
586 return wxLongLongWx(m_hi | ll.m_hi, m_lo | ll.m_lo);
587}
588
589wxULongLongWx wxULongLongWx::operator|(const wxULongLongWx& ll) const
590{
591 return wxULongLongWx(m_hi | ll.m_hi, m_lo | ll.m_lo);
592}
593
594wxLongLongWx wxLongLongWx::operator^(const wxLongLongWx& ll) const
595{
596 return wxLongLongWx(m_hi ^ ll.m_hi, m_lo ^ ll.m_lo);
597}
598
599wxULongLongWx wxULongLongWx::operator^(const wxULongLongWx& ll) const
600{
601 return wxULongLongWx(m_hi ^ ll.m_hi, m_lo ^ ll.m_lo);
602}
603
604wxLongLongWx& 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
618wxULongLongWx& 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
632wxLongLongWx& 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
646wxULongLongWx& 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
660wxLongLongWx& 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
674wxULongLongWx& 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
688wxLongLongWx wxLongLongWx::operator~() const
689{
690 return wxLongLongWx(~m_hi, ~m_lo);
691}
692
693wxULongLongWx wxULongLongWx::operator~() const
694{
695 return wxULongLongWx(~m_hi, ~m_lo);
696}
697
698// multiplication
699
700wxLongLongWx wxLongLongWx::operator*(const wxLongLongWx& ll) const
701{
702 wxLongLongWx res(*this);
703 res *= ll;
704
705 return res;
706}
707
708wxULongLongWx wxULongLongWx::operator*(const wxULongLongWx& ll) const
709{
710 wxULongLongWx res(*this);
711 res *= ll;
712
713 return res;
714}
715
716wxLongLongWx& 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
748wxULongLongWx& 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
782void wxLongLongWx::Divide(const wxLongLongWx& divisorIn,
783 wxLongLongWx& quotient,
784 wxLongLongWx& remainder) const
785{
786 if ((divisorIn.m_lo == 0) && (divisorIn.m_hi == 0))
787 {
788 // provoke division by zero error and silence the compilers warnings
789 // about an expression without effect and unused variable
790 long dummy = divisorIn.m_lo/divisorIn.m_hi;
791 dummy += 0;
792 }
793
794 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
795 // do this - any improvements are more than welcome
796 //
797 // code inspired by the snippet at
798 // http://www.bearcave.com/software/divide.htm
799 //
800 // Copyright notice:
801 //
802 // Use of this program, for any purpose, is granted the author, Ian
803 // Kaplan, as long as this copyright notice is included in the source
804 // code or any source code derived from this program. The user assumes
805 // all responsibility for using this code.
806
807 // init everything
808 wxLongLongWx dividend = *this,
809 divisor = divisorIn;
810
811 quotient = 0l;
812 remainder = 0l;
813
814 // always do unsigned division and adjust the signs later: in C integer
815 // division, the sign of the remainder is the same as the sign of the
816 // dividend, while the sign of the quotient is the product of the signs of
817 // the dividend and divisor. Of course, we also always have
818 //
819 // dividend = quotient*divisor + remainder
820 //
821 // with 0 <= abs(remainder) < abs(divisor)
822 bool negRemainder = dividend.m_hi < 0;
823 bool negQuotient = false; // assume positive
824 if ( dividend.m_hi < 0 )
825 {
826 negQuotient = !negQuotient;
827 dividend = -dividend;
828 }
829 if ( divisor.m_hi < 0 )
830 {
831 negQuotient = !negQuotient;
832 divisor = -divisor;
833 }
834
835 // check for some particular cases
836 if ( divisor > dividend )
837 {
838 remainder = dividend;
839 }
840 else if ( divisor == dividend )
841 {
842 quotient = 1l;
843 }
844 else
845 {
846 // here: dividend > divisor and both are positive: do unsigned division
847 size_t nBits = 64u;
848 wxLongLongWx d;
849
850 #define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1)))
851
852 while ( remainder < divisor )
853 {
854 remainder <<= 1;
855 if ( IS_MSB_SET(dividend) )
856 {
857 remainder |= 1;
858 }
859
860 d = dividend;
861 dividend <<= 1;
862
863 nBits--;
864 }
865
866 // undo the last loop iteration
867 dividend = d;
868 remainder >>= 1;
869 nBits++;
870
871 for ( size_t i = 0; i < nBits; i++ )
872 {
873 remainder <<= 1;
874 if ( IS_MSB_SET(dividend) )
875 {
876 remainder |= 1;
877 }
878
879 wxLongLongWx t = remainder - divisor;
880 dividend <<= 1;
881 quotient <<= 1;
882 if ( !IS_MSB_SET(t) )
883 {
884 quotient |= 1;
885
886 remainder = t;
887 }
888 }
889 }
890
891 // adjust signs
892 if ( negRemainder )
893 {
894 remainder = -remainder;
895 }
896
897 if ( negQuotient )
898 {
899 quotient = -quotient;
900 }
901}
902
903void wxULongLongWx::Divide(const wxULongLongWx& divisorIn,
904 wxULongLongWx& quotient,
905 wxULongLongWx& remainder) const
906{
907 if ((divisorIn.m_lo == 0) && (divisorIn.m_hi == 0))
908 {
909 // provoke division by zero error and silence the compilers warnings
910 // about an expression without effect and unused variable
911 unsigned long dummy = divisorIn.m_lo/divisorIn.m_hi;
912 dummy += 0;
913 }
914
915 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
916 // do this - any improvements are more than welcome
917 //
918 // code inspired by the snippet at
919 // http://www.bearcave.com/software/divide.htm
920 //
921 // Copyright notice:
922 //
923 // Use of this program, for any purpose, is granted the author, Ian
924 // Kaplan, as long as this copyright notice is included in the source
925 // code or any source code derived from this program. The user assumes
926 // all responsibility for using this code.
927
928 // init everything
929 wxULongLongWx dividend = *this,
930 divisor = divisorIn;
931
932 quotient = 0l;
933 remainder = 0l;
934
935 // check for some particular cases
936 if ( divisor > dividend )
937 {
938 remainder = dividend;
939 }
940 else if ( divisor == dividend )
941 {
942 quotient = 1l;
943 }
944 else
945 {
946 // here: dividend > divisor
947 size_t nBits = 64u;
948 wxULongLongWx d;
949
950 #define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1)))
951
952 while ( remainder < divisor )
953 {
954 remainder <<= 1;
955 if ( IS_MSB_SET(dividend) )
956 {
957 remainder |= 1;
958 }
959
960 d = dividend;
961 dividend <<= 1;
962
963 nBits--;
964 }
965
966 // undo the last loop iteration
967 dividend = d;
968 remainder >>= 1;
969 nBits++;
970
971 for ( size_t i = 0; i < nBits; i++ )
972 {
973 remainder <<= 1;
974 if ( IS_MSB_SET(dividend) )
975 {
976 remainder |= 1;
977 }
978
979 wxULongLongWx t = remainder - divisor;
980 dividend <<= 1;
981 quotient <<= 1;
982 if ( !IS_MSB_SET(t) )
983 {
984 quotient |= 1;
985
986 remainder = t;
987 }
988 }
989 }
990}
991
992wxLongLongWx wxLongLongWx::operator/(const wxLongLongWx& ll) const
993{
994 wxLongLongWx quotient, remainder;
995
996 Divide(ll, quotient, remainder);
997
998 return quotient;
999}
1000
1001wxULongLongWx wxULongLongWx::operator/(const wxULongLongWx& ll) const
1002{
1003 wxULongLongWx quotient, remainder;
1004
1005 Divide(ll, quotient, remainder);
1006
1007 return quotient;
1008}
1009
1010wxLongLongWx& wxLongLongWx::operator/=(const wxLongLongWx& ll)
1011{
1012 wxLongLongWx quotient, remainder;
1013
1014 Divide(ll, quotient, remainder);
1015
1016 *this = quotient;
1017
1018 return *this;
1019}
1020
1021wxULongLongWx& wxULongLongWx::operator/=(const wxULongLongWx& ll)
1022{
1023 wxULongLongWx quotient, remainder;
1024
1025 Divide(ll, quotient, remainder);
1026
1027 *this = quotient;
1028
1029 return *this;
1030}
1031
1032wxLongLongWx wxLongLongWx::operator%(const wxLongLongWx& ll) const
1033{
1034 wxLongLongWx quotient, remainder;
1035
1036 Divide(ll, quotient, remainder);
1037
1038 return remainder;
1039}
1040
1041wxULongLongWx wxULongLongWx::operator%(const wxULongLongWx& ll) const
1042{
1043 wxULongLongWx quotient, remainder;
1044
1045 Divide(ll, quotient, remainder);
1046
1047 return remainder;
1048}
1049
1050// ----------------------------------------------------------------------------
1051// misc
1052// ----------------------------------------------------------------------------
1053
1054// temporary - just for testing
1055void *wxLongLongWx::asArray(void) const
1056{
1057 static unsigned char temp[8];
1058
1059 temp[0] = (char)((m_hi >> 24) & 0xFF);
1060 temp[1] = (char)((m_hi >> 16) & 0xFF);
1061 temp[2] = (char)((m_hi >> 8) & 0xFF);
1062 temp[3] = (char)((m_hi >> 0) & 0xFF);
1063 temp[4] = (char)((m_lo >> 24) & 0xFF);
1064 temp[5] = (char)((m_lo >> 16) & 0xFF);
1065 temp[6] = (char)((m_lo >> 8) & 0xFF);
1066 temp[7] = (char)((m_lo >> 0) & 0xFF);
1067
1068 return temp;
1069}
1070
1071void *wxULongLongWx::asArray(void) const
1072{
1073 static unsigned char temp[8];
1074
1075 temp[0] = (char)((m_hi >> 24) & 0xFF);
1076 temp[1] = (char)((m_hi >> 16) & 0xFF);
1077 temp[2] = (char)((m_hi >> 8) & 0xFF);
1078 temp[3] = (char)((m_hi >> 0) & 0xFF);
1079 temp[4] = (char)((m_lo >> 24) & 0xFF);
1080 temp[5] = (char)((m_lo >> 16) & 0xFF);
1081 temp[6] = (char)((m_lo >> 8) & 0xFF);
1082 temp[7] = (char)((m_lo >> 0) & 0xFF);
1083
1084 return temp;
1085}
1086
1087#endif // wxUSE_LONGLONG_WX
1088
1089#define LL_TO_STRING(name) \
1090 wxString name::ToString() const \
1091 { \
1092 /* TODO: this is awfully inefficient, anything better? */ \
1093 wxString result; \
1094 \
1095 name ll = *this; \
1096 \
1097 bool neg = ll < 0; \
1098 if ( neg ) \
1099 { \
1100 while ( ll != 0 ) \
1101 { \
1102 long digit = (ll % 10).ToLong(); \
1103 result.Prepend((wxChar)(_T('0') - digit)); \
1104 ll /= 10; \
1105 } \
1106 } \
1107 else \
1108 { \
1109 while ( ll != 0 ) \
1110 { \
1111 long digit = (ll % 10).ToLong(); \
1112 result.Prepend((wxChar)(_T('0') + digit)); \
1113 ll /= 10; \
1114 } \
1115 } \
1116 \
1117 if ( result.empty() ) \
1118 result = _T('0'); \
1119 else if ( neg ) \
1120 result.Prepend(_T('-')); \
1121 \
1122 return result; \
1123 }
1124
1125#define ULL_TO_STRING(name) \
1126 wxString name::ToString() const \
1127 { \
1128 /* TODO: this is awfully inefficient, anything better? */ \
1129 wxString result; \
1130 \
1131 name ll = *this; \
1132 \
1133 while ( ll != 0 ) \
1134 { \
1135 result.Prepend((wxChar)(_T('0') + (ll % 10).ToULong())); \
1136 ll /= 10; \
1137 } \
1138 \
1139 if ( result.empty() ) \
1140 result = _T('0'); \
1141 \
1142 return result; \
1143 }
1144
1145#if wxUSE_LONGLONG_NATIVE
1146 LL_TO_STRING(wxLongLongNative)
1147 ULL_TO_STRING(wxULongLongNative)
1148#endif
1149
1150#if wxUSE_LONGLONG_WX
1151 LL_TO_STRING(wxLongLongWx)
1152 ULL_TO_STRING(wxULongLongWx)
1153#endif
1154
1155#if wxUSE_STD_IOSTREAM
1156
1157// input/output
1158WXDLLIMPEXP_BASE
1159wxSTD ostream& operator<< (wxSTD ostream& o, const wxLongLong& ll)
1160{
1161 return o << ll.ToString();
1162}
1163
1164WXDLLIMPEXP_BASE
1165wxSTD ostream& operator<< (wxSTD ostream& o, const wxULongLong& ll)
1166{
1167 return o << ll.ToString();
1168}
1169
1170#endif // wxUSE_STD_IOSTREAM
1171
1172WXDLLIMPEXP_BASE wxString& operator<< (wxString& s, const wxLongLong& ll)
1173{
1174 return s << ll.ToString();
1175}
1176
1177WXDLLIMPEXP_BASE wxString& operator<< (wxString& s, const wxULongLong& ll)
1178{
1179 return s << ll.ToString();
1180}
1181
1182#endif // wxUSE_LONGLONG