]> git.saurik.com Git - wxWidgets.git/blame - src/common/longlong.cpp
wxOS2/OW warning and build fixes.
[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
6984e414
VZ
782#define IS_MSB_SET(ll) ((ll.GetHi()) & (1 << (8*sizeof(long) - 1)))
783
5e6a0e83 784void wxLongLongWx::Divide(const wxLongLongWx& divisorIn,
cd0b1709 785 wxLongLongWx& quotient,
6984e414 786 wxLongLongWx& remainderIO) const
8b81872f 787{
5e6a0e83 788 if ((divisorIn.m_lo == 0) && (divisorIn.m_hi == 0))
8b81872f
VZ
789 {
790 // provoke division by zero error and silence the compilers warnings
791 // about an expression without effect and unused variable
5e6a0e83 792 long dummy = divisorIn.m_lo/divisorIn.m_hi;
8b81872f
VZ
793 dummy += 0;
794 }
795
2ea24d9f
VZ
796 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
797 // do this - any improvements are more than welcome
5e6a0e83
VZ
798 //
799 // code inspired by the snippet at
800 // http://www.bearcave.com/software/divide.htm
801 //
802 // Copyright notice:
803 //
804 // Use of this program, for any purpose, is granted the author, Ian
805 // Kaplan, as long as this copyright notice is included in the source
806 // code or any source code derived from this program. The user assumes
3a994742 807 // all responsibility for using this code.
5e6a0e83
VZ
808
809 // init everything
6984e414 810 wxULongLongWx dividend, divisor, remainder;
5e6a0e83
VZ
811
812 quotient = 0l;
813 remainder = 0l;
814
5e6a0e83
VZ
815 // always do unsigned division and adjust the signs later: in C integer
816 // division, the sign of the remainder is the same as the sign of the
817 // dividend, while the sign of the quotient is the product of the signs of
818 // the dividend and divisor. Of course, we also always have
819 //
820 // dividend = quotient*divisor + remainder
821 //
822 // with 0 <= abs(remainder) < abs(divisor)
6984e414 823 bool negRemainder = GetHi() < 0;
f644b28c 824 bool negQuotient = false; // assume positive
6984e414 825 if ( GetHi() < 0 )
5e6a0e83
VZ
826 {
827 negQuotient = !negQuotient;
6984e414
VZ
828 dividend = -*this;
829 } else {
830 dividend = *this;
5e6a0e83 831 }
6984e414 832 if ( divisorIn.GetHi() < 0 )
5e6a0e83
VZ
833 {
834 negQuotient = !negQuotient;
6984e414
VZ
835 divisor = -divisorIn;
836 } else {
837 divisor = divisorIn;
5e6a0e83 838 }
2ea24d9f 839
2a310492
VZ
840 // check for some particular cases
841 if ( divisor > dividend )
2ea24d9f 842 {
2a310492
VZ
843 remainder = dividend;
844 }
845 else if ( divisor == dividend )
846 {
847 quotient = 1l;
5e6a0e83 848 }
2a310492
VZ
849 else
850 {
842215bb 851 // here: dividend > divisor and both are positive: do unsigned division
2a310492
VZ
852 size_t nBits = 64u;
853 wxLongLongWx d;
5e6a0e83 854
2a310492 855 while ( remainder < divisor )
2ea24d9f 856 {
2a310492
VZ
857 remainder <<= 1;
858 if ( IS_MSB_SET(dividend) )
859 {
860 remainder |= 1;
861 }
862
863 d = dividend;
864 dividend <<= 1;
865
866 nBits--;
2ea24d9f
VZ
867 }
868
2a310492
VZ
869 // undo the last loop iteration
870 dividend = d;
871 remainder >>= 1;
872 nBits++;
5e6a0e83 873
2a310492
VZ
874 for ( size_t i = 0; i < nBits; i++ )
875 {
876 remainder <<= 1;
877 if ( IS_MSB_SET(dividend) )
878 {
879 remainder |= 1;
880 }
881
882 wxLongLongWx t = remainder - divisor;
883 dividend <<= 1;
884 quotient <<= 1;
885 if ( !IS_MSB_SET(t) )
886 {
887 quotient |= 1;
888
889 remainder = t;
890 }
5e6a0e83 891 }
2ea24d9f
VZ
892 }
893
6984e414
VZ
894 remainderIO = remainder;
895
5e6a0e83
VZ
896 // adjust signs
897 if ( negRemainder )
2ea24d9f 898 {
6984e414 899 remainderIO = -remainderIO;
2ea24d9f
VZ
900 }
901
5e6a0e83
VZ
902 if ( negQuotient )
903 {
904 quotient = -quotient;
905 }
2ea24d9f
VZ
906}
907
8e38fd1f
RL
908void wxULongLongWx::Divide(const wxULongLongWx& divisorIn,
909 wxULongLongWx& quotient,
910 wxULongLongWx& remainder) const
911{
912 if ((divisorIn.m_lo == 0) && (divisorIn.m_hi == 0))
913 {
914 // provoke division by zero error and silence the compilers warnings
915 // about an expression without effect and unused variable
916 unsigned long dummy = divisorIn.m_lo/divisorIn.m_hi;
917 dummy += 0;
918 }
919
920 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
921 // do this - any improvements are more than welcome
922 //
923 // code inspired by the snippet at
924 // http://www.bearcave.com/software/divide.htm
925 //
926 // Copyright notice:
927 //
928 // Use of this program, for any purpose, is granted the author, Ian
929 // Kaplan, as long as this copyright notice is included in the source
930 // code or any source code derived from this program. The user assumes
931 // all responsibility for using this code.
932
933 // init everything
934 wxULongLongWx dividend = *this,
935 divisor = divisorIn;
936
937 quotient = 0l;
938 remainder = 0l;
939
940 // check for some particular cases
941 if ( divisor > dividend )
942 {
943 remainder = dividend;
944 }
945 else if ( divisor == dividend )
946 {
947 quotient = 1l;
948 }
949 else
950 {
951 // here: dividend > divisor
952 size_t nBits = 64u;
953 wxULongLongWx d;
954
8e38fd1f
RL
955 while ( remainder < divisor )
956 {
957 remainder <<= 1;
958 if ( IS_MSB_SET(dividend) )
959 {
960 remainder |= 1;
961 }
962
963 d = dividend;
964 dividend <<= 1;
965
966 nBits--;
967 }
968
969 // undo the last loop iteration
970 dividend = d;
971 remainder >>= 1;
972 nBits++;
973
974 for ( size_t i = 0; i < nBits; i++ )
975 {
976 remainder <<= 1;
977 if ( IS_MSB_SET(dividend) )
978 {
979 remainder |= 1;
980 }
981
982 wxULongLongWx t = remainder - divisor;
983 dividend <<= 1;
984 quotient <<= 1;
985 if ( !IS_MSB_SET(t) )
986 {
987 quotient |= 1;
988
989 remainder = t;
990 }
991 }
992 }
993}
994
2ea24d9f
VZ
995wxLongLongWx wxLongLongWx::operator/(const wxLongLongWx& ll) const
996{
997 wxLongLongWx quotient, remainder;
998
999 Divide(ll, quotient, remainder);
1000
1001 return quotient;
1002}
1003
8e38fd1f
RL
1004wxULongLongWx wxULongLongWx::operator/(const wxULongLongWx& ll) const
1005{
1006 wxULongLongWx quotient, remainder;
1007
1008 Divide(ll, quotient, remainder);
1009
1010 return quotient;
1011}
1012
2ea24d9f
VZ
1013wxLongLongWx& wxLongLongWx::operator/=(const wxLongLongWx& ll)
1014{
1015 wxLongLongWx quotient, remainder;
1016
1017 Divide(ll, quotient, remainder);
1018
55dfa8d3 1019 *this = quotient;
3a994742 1020
55dfa8d3 1021 return *this;
8b81872f
VZ
1022}
1023
8e38fd1f
RL
1024wxULongLongWx& wxULongLongWx::operator/=(const wxULongLongWx& ll)
1025{
c35c7d01 1026 wxULongLongWx quotient, remainder;
8e38fd1f
RL
1027
1028 Divide(ll, quotient, remainder);
1029
1030 *this = quotient;
1031
1032 return *this;
1033}
1034
2ea24d9f
VZ
1035wxLongLongWx wxLongLongWx::operator%(const wxLongLongWx& ll) const
1036{
1037 wxLongLongWx quotient, remainder;
1038
1039 Divide(ll, quotient, remainder);
1040
1041 return remainder;
1042}
1043
8e38fd1f
RL
1044wxULongLongWx wxULongLongWx::operator%(const wxULongLongWx& ll) const
1045{
1046 wxULongLongWx quotient, remainder;
1047
1048 Divide(ll, quotient, remainder);
1049
1050 return remainder;
1051}
1052
2ea24d9f
VZ
1053// ----------------------------------------------------------------------------
1054// misc
1055// ----------------------------------------------------------------------------
1056
8b81872f
VZ
1057// temporary - just for testing
1058void *wxLongLongWx::asArray(void) const
1059{
1060 static unsigned char temp[8];
1061
13111b2a
VZ
1062 temp[0] = (char)((m_hi >> 24) & 0xFF);
1063 temp[1] = (char)((m_hi >> 16) & 0xFF);
1064 temp[2] = (char)((m_hi >> 8) & 0xFF);
1065 temp[3] = (char)((m_hi >> 0) & 0xFF);
1066 temp[4] = (char)((m_lo >> 24) & 0xFF);
1067 temp[5] = (char)((m_lo >> 16) & 0xFF);
1068 temp[6] = (char)((m_lo >> 8) & 0xFF);
1069 temp[7] = (char)((m_lo >> 0) & 0xFF);
8b81872f
VZ
1070
1071 return temp;
1072}
1073
8e38fd1f
RL
1074void *wxULongLongWx::asArray(void) const
1075{
1076 static unsigned char temp[8];
1077
1078 temp[0] = (char)((m_hi >> 24) & 0xFF);
1079 temp[1] = (char)((m_hi >> 16) & 0xFF);
1080 temp[2] = (char)((m_hi >> 8) & 0xFF);
1081 temp[3] = (char)((m_hi >> 0) & 0xFF);
1082 temp[4] = (char)((m_lo >> 24) & 0xFF);
1083 temp[5] = (char)((m_lo >> 16) & 0xFF);
1084 temp[6] = (char)((m_lo >> 8) & 0xFF);
1085 temp[7] = (char)((m_lo >> 0) & 0xFF);
1086
1087 return temp;
1088}
1089
3a994742 1090#endif // wxUSE_LONGLONG_WX
8b81872f 1091
842215bb
WS
1092#define LL_TO_STRING(name) \
1093 wxString name::ToString() const \
1094 { \
1095 /* TODO: this is awfully inefficient, anything better? */ \
1096 wxString result; \
1097 \
1098 name ll = *this; \
1099 \
21b9b5e2
VZ
1100 bool neg = ll < 0; \
1101 if ( neg ) \
842215bb 1102 { \
21b9b5e2
VZ
1103 while ( ll != 0 ) \
1104 { \
1105 long digit = (ll % 10).ToLong(); \
1106 result.Prepend((wxChar)(_T('0') - digit)); \
1107 ll /= 10; \
1108 } \
842215bb
WS
1109 } \
1110 else \
1111 { \
21b9b5e2
VZ
1112 while ( ll != 0 ) \
1113 { \
1114 long digit = (ll % 10).ToLong(); \
1115 result.Prepend((wxChar)(_T('0') + digit)); \
1116 ll /= 10; \
1117 } \
842215bb
WS
1118 } \
1119 \
1120 if ( result.empty() ) \
1121 result = _T('0'); \
1122 else if ( neg ) \
1123 result.Prepend(_T('-')); \
1124 \
1125 return result; \
3a994742 1126 }
8b81872f 1127
842215bb
WS
1128#define ULL_TO_STRING(name) \
1129 wxString name::ToString() const \
1130 { \
1131 /* TODO: this is awfully inefficient, anything better? */ \
1132 wxString result; \
1133 \
1134 name ll = *this; \
1135 \
1136 while ( ll != 0 ) \
1137 { \
1138 result.Prepend((wxChar)(_T('0') + (ll % 10).ToULong())); \
1139 ll /= 10; \
1140 } \
1141 \
1142 if ( result.empty() ) \
1143 result = _T('0'); \
1144 \
1145 return result; \
8b81872f
VZ
1146 }
1147
8e38fd1f 1148#if wxUSE_LONGLONG_NATIVE
842215bb
WS
1149 LL_TO_STRING(wxLongLongNative)
1150 ULL_TO_STRING(wxULongLongNative)
8e38fd1f 1151#endif
8e38fd1f 1152
842215bb
WS
1153#if wxUSE_LONGLONG_WX
1154 LL_TO_STRING(wxLongLongWx)
1155 ULL_TO_STRING(wxULongLongWx)
1156#endif
8e38fd1f 1157
3a994742
VZ
1158#if wxUSE_STD_IOSTREAM
1159
1160// input/output
a353dc98 1161WXDLLIMPEXP_BASE
3a994742
VZ
1162wxSTD ostream& operator<< (wxSTD ostream& o, const wxLongLong& ll)
1163{
1164 return o << ll.ToString();
1165}
1166
a353dc98 1167WXDLLIMPEXP_BASE
8e38fd1f
RL
1168wxSTD ostream& operator<< (wxSTD ostream& o, const wxULongLong& ll)
1169{
1170 return o << ll.ToString();
1171}
1172
3a994742 1173#endif // wxUSE_STD_IOSTREAM
8b81872f 1174
059a684d 1175WXDLLIMPEXP_BASE wxString& operator<< (wxString& s, const wxLongLong& ll)
51496782
WS
1176{
1177 return s << ll.ToString();
1178}
1179
059a684d 1180WXDLLIMPEXP_BASE wxString& operator<< (wxString& s, const wxULongLong& ll)
51496782
WS
1181{
1182 return s << ll.ToString();
1183}
1184
4e57b0d4 1185#endif // wxUSE_LONGLONG