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