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