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