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