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