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