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