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