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