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