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