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