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