]> git.saurik.com Git - wxWidgets.git/blame - src/common/longlong.cpp
changes to match listctrl.h changes (forgot to commit yesterday, sorry)
[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
5// Remarks: this class is not public in wxWindows 2.0! It is intentionally
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>
11// Licence: wxWindows license
12/////////////////////////////////////////////////////////////////////////////
13
14// ============================================================================
15// headers
16// ============================================================================
17
18#ifdef __GNUG__
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
VZ
29#include "wx/longlong.h"
30
de85a884
VZ
31#if defined(__MWERKS__) && defined(__WXMSW__)
32#include <string.h> // for memset()
33#else
8b81872f 34#include <memory.h> // for memset()
de85a884
VZ
35#endif
36
41acf5c0 37#include <math.h> // for fabs()
8b81872f
VZ
38
39// ============================================================================
40// implementation
41// ============================================================================
42
43#if wxUSE_LONGLONG_NATIVE
44
45// ----------------------------------------------------------------------------
46// misc
47// ----------------------------------------------------------------------------
48
2a310492 49void *wxLongLongNative::asArray() const
8b81872f
VZ
50{
51 static unsigned char temp[8];
52
53 temp[0] = (m_ll >> 56) & 0xFF;
54 temp[1] = (m_ll >> 48) & 0xFF;
55 temp[2] = (m_ll >> 40) & 0xFF;
56 temp[3] = (m_ll >> 32) & 0xFF;
57 temp[4] = (m_ll >> 24) & 0xFF;
58 temp[5] = (m_ll >> 16) & 0xFF;
59 temp[6] = (m_ll >> 8) & 0xFF;
60 temp[7] = (m_ll >> 0) & 0xFF;
61
62 return temp;
63}
64
8b81872f
VZ
65#endif // wxUSE_LONGLONG_NATIVE
66
41acf5c0
VZ
67// ============================================================================
68// wxLongLongWx: emulation of 'long long' using 2 longs
69// ============================================================================
70
8b81872f
VZ
71#if wxUSE_LONGLONG_WX
72
41acf5c0
VZ
73// assignment
74wxLongLongWx& wxLongLongWx::Assign(double d)
75{
2a310492
VZ
76 bool positive = d >= 0;
77 d = fabs(d);
617ec456 78 if ( d <= ULONG_MAX )
41acf5c0 79 {
2a310492 80 m_hi = 0;
41acf5c0
VZ
81 m_lo = (long)d;
82 }
83 else
84 {
617ec456
VZ
85 m_hi = (unsigned long)(d / (1.0 + (double)ULONG_MAX));
86 m_lo = (unsigned long)(d - ((double)m_hi * (1.0 + (double)ULONG_MAX)));
41acf5c0
VZ
87 }
88
2a310492
VZ
89#ifdef wxLONGLONG_TEST_MODE
90 m_ll = (wxLongLong_t)d;
91
92 Check();
93#endif // wxLONGLONG_TEST_MODE
94
617ec456
VZ
95 if ( !positive )
96 Negate();
97
41acf5c0
VZ
98 return *this;
99}
100
8b81872f
VZ
101wxLongLongWx wxLongLongWx::operator<<(int shift) const
102{
2a310492
VZ
103 wxLongLongWx ll(*this);
104 ll <<= shift;
8b81872f 105
2a310492 106 return ll;
8b81872f
VZ
107}
108
109wxLongLongWx& wxLongLongWx::operator<<=(int shift)
110{
2a310492 111 if (shift != 0)
8b81872f 112 {
2a310492
VZ
113 if (shift < 32)
114 {
115 m_hi <<= shift;
116 m_hi |= m_lo >> (32 - shift);
117 m_lo <<= shift;
118 }
119 else
120 {
121 m_hi = m_lo << (shift - 32);
122 m_lo = 0;
123 }
8b81872f
VZ
124 }
125
2a310492
VZ
126#ifdef wxLONGLONG_TEST_MODE
127 m_ll <<= shift;
128
129 Check();
130#endif // wxLONGLONG_TEST_MODE
131
8b81872f
VZ
132 return *this;
133}
134
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
143wxLongLongWx& wxLongLongWx::operator>>=(int shift)
144{
2a310492 145 if (shift != 0)
8b81872f 146 {
2a310492
VZ
147 if (shift < 32)
148 {
149 m_lo >>= shift;
150 m_lo |= m_hi << (32 - shift);
151 m_hi >>= shift;
152 }
153 else
154 {
155 m_lo = m_hi >> (shift - 32);
156 m_hi = (m_hi < 0 ? -1L : 0);
157 }
8b81872f
VZ
158 }
159
2a310492
VZ
160#ifdef wxLONGLONG_TEST_MODE
161 m_ll >>= shift;
162
163 Check();
164#endif // wxLONGLONG_TEST_MODE
165
8b81872f
VZ
166 return *this;
167}
168
169wxLongLongWx wxLongLongWx::operator+(const wxLongLongWx& ll) const
170{
2a310492
VZ
171 wxLongLongWx res(*this);
172 res += ll;
8b81872f 173
2a310492 174 return res;
8b81872f
VZ
175}
176
177wxLongLongWx wxLongLongWx::operator+(long l) const
178{
2a310492
VZ
179 wxLongLongWx res(*this);
180 res += l;
8b81872f 181
2a310492 182 return res;
8b81872f
VZ
183}
184
185wxLongLongWx& wxLongLongWx::operator+=(const wxLongLongWx& ll)
186{
187 unsigned long previous = m_lo;
188
189 m_lo += ll.m_lo;
190 m_hi += ll.m_hi;
191
192 if ((m_lo < previous) || (m_lo < ll.m_lo))
193 m_hi++;
194
2a310492
VZ
195#ifdef wxLONGLONG_TEST_MODE
196 m_ll += ll.m_ll;
197
198 Check();
199#endif // wxLONGLONG_TEST_MODE
200
8b81872f
VZ
201 return *this;
202}
203
204wxLongLongWx& wxLongLongWx::operator+=(long l)
205{
206 unsigned long previous = m_lo;
207
208 m_lo += l;
209 if (l < 0)
210 m_hi += -1l;
211
212 if ((m_lo < previous) || (m_lo < (unsigned long)l))
213 m_hi++;
214
2a310492
VZ
215#ifdef wxLONGLONG_TEST_MODE
216 m_ll += l;
217
218 Check();
219#endif // wxLONGLONG_TEST_MODE
220
8b81872f
VZ
221 return *this;
222}
223
224// pre increment
225wxLongLongWx& wxLongLongWx::operator++()
226{
227 m_lo++;
228 if (m_lo == 0)
229 m_hi++;
230
2a310492
VZ
231#ifdef wxLONGLONG_TEST_MODE
232 m_ll++;
8b81872f 233
2a310492
VZ
234 Check();
235#endif // wxLONGLONG_TEST_MODE
8b81872f
VZ
236
237 return *this;
238}
239
240// negation
241wxLongLongWx wxLongLongWx::operator-() const
242{
2a310492
VZ
243 wxLongLongWx res(*this);
244 res.Negate();
245
246 return res;
247}
248
249wxLongLongWx& wxLongLongWx::Negate()
250{
251 m_hi = ~m_hi;
252 m_lo = ~m_lo;
253
254 m_lo++;
255 if ( m_lo == 0 )
256 m_hi++;
8b81872f 257
2a310492
VZ
258#ifdef wxLONGLONG_TEST_MODE
259 m_ll = -m_ll;
8b81872f 260
2a310492
VZ
261 Check();
262#endif // wxLONGLONG_TEST_MODE
263
264 return *this;
8b81872f
VZ
265}
266
267// subtraction
268
269wxLongLongWx wxLongLongWx::operator-(const wxLongLongWx& ll) const
270{
2a310492
VZ
271 wxLongLongWx res(*this);
272 res -= ll;
8b81872f 273
2a310492 274 return res;
8b81872f
VZ
275}
276
277wxLongLongWx& wxLongLongWx::operator-=(const wxLongLongWx& ll)
278{
279 unsigned long previous = m_lo;
280
281 m_lo -= ll.m_lo;
282 m_hi -= ll.m_hi;
283
284 if (previous < ll.m_lo)
285 m_hi--;
286
2a310492
VZ
287#ifdef wxLONGLONG_TEST_MODE
288 m_ll -= ll.m_ll;
289
290 Check();
291#endif // wxLONGLONG_TEST_MODE
292
13111b2a 293 return *this;
8b81872f
VZ
294}
295
296// pre decrement
297wxLongLongWx& wxLongLongWx::operator--()
298{
299 m_lo--;
300 if (m_lo == 0xFFFFFFFF)
301 m_hi--;
302
2a310492
VZ
303#ifdef wxLONGLONG_TEST_MODE
304 m_ll--;
8b81872f 305
2a310492
VZ
306 Check();
307#endif // wxLONGLONG_TEST_MODE
8b81872f
VZ
308
309 return *this;
310}
311
312// comparison operators
313
314bool wxLongLongWx::operator<(const wxLongLongWx& ll) const
315{
2ea24d9f
VZ
316 if ( m_hi < ll.m_hi )
317 return TRUE;
318 else if ( m_hi == ll.m_hi )
319 return m_lo < ll.m_lo;
320 else
321 return FALSE;
8b81872f
VZ
322}
323
324bool wxLongLongWx::operator>(const wxLongLongWx& ll) const
325{
2ea24d9f
VZ
326 if ( m_hi > ll.m_hi )
327 return TRUE;
328 else if ( m_hi == ll.m_hi )
329 return m_lo > ll.m_lo;
330 else
331 return FALSE;
8b81872f
VZ
332}
333
334// bitwise operators
335
336wxLongLongWx wxLongLongWx::operator&(const wxLongLongWx& ll) const
337{
338 return wxLongLongWx(m_hi & ll.m_hi, m_lo & ll.m_lo);
339}
340
341wxLongLongWx wxLongLongWx::operator|(const wxLongLongWx& ll) const
342{
343 return wxLongLongWx(m_hi | ll.m_hi, m_lo | ll.m_lo);
344}
345
346wxLongLongWx wxLongLongWx::operator^(const wxLongLongWx& ll) const
347{
348 return wxLongLongWx(m_hi ^ ll.m_hi, m_lo ^ ll.m_lo);
349}
350
351wxLongLongWx& wxLongLongWx::operator&=(const wxLongLongWx& ll)
352{
353 m_lo &= ll.m_lo;
354 m_hi &= ll.m_hi;
355
2a310492
VZ
356#ifdef wxLONGLONG_TEST_MODE
357 m_ll &= ll.m_ll;
358
359 Check();
360#endif // wxLONGLONG_TEST_MODE
361
8b81872f
VZ
362 return *this;
363}
364
365wxLongLongWx& wxLongLongWx::operator|=(const wxLongLongWx& ll)
366{
367 m_lo |= ll.m_lo;
368 m_hi |= ll.m_hi;
369
2a310492
VZ
370#ifdef wxLONGLONG_TEST_MODE
371 m_ll |= ll.m_ll;
372
373 Check();
374#endif // wxLONGLONG_TEST_MODE
375
8b81872f
VZ
376 return *this;
377}
378
379wxLongLongWx& wxLongLongWx::operator^=(const wxLongLongWx& ll)
380{
381 m_lo ^= ll.m_lo;
382 m_hi ^= ll.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
393wxLongLongWx wxLongLongWx::operator~() const
394{
395 return wxLongLongWx(~m_hi, ~m_lo);
396}
397
398// multiplication
399
400wxLongLongWx wxLongLongWx::operator*(const wxLongLongWx& ll) const
401{
2a310492
VZ
402 wxLongLongWx res(*this);
403 res *= ll;
8b81872f 404
2a310492 405 return res;
8b81872f
VZ
406}
407
408wxLongLongWx& wxLongLongWx::operator*=(const wxLongLongWx& ll)
409{
410 wxLongLongWx t(m_hi, m_lo);
411 wxLongLongWx q(ll.m_hi, ll.m_lo);
8b81872f 412
2a310492
VZ
413 m_hi = m_lo = 0;
414
415#ifdef wxLONGLONG_TEST_MODE
416 wxLongLong_t llOld = m_ll;
417 m_ll = 0;
418#endif // wxLONGLONG_TEST_MODE
419
420 int counter = 0;
8b81872f
VZ
421 do
422 {
423 if ((q.m_lo & 1) != 0)
2a310492 424 *this += t;
8b81872f
VZ
425 q >>= 1;
426 t <<= 1;
427 counter++;
2a310492
VZ
428 }
429 while ((counter < 64) && ((q.m_hi != 0) || (q.m_lo != 0)));
430
431#ifdef wxLONGLONG_TEST_MODE
432 m_ll = llOld * ll.m_ll;
433
434 Check();
435#endif // wxLONGLONG_TEST_MODE
436
8b81872f
VZ
437 return *this;
438}
439
440// division
441
5e6a0e83 442void wxLongLongWx::Divide(const wxLongLongWx& divisorIn,
cd0b1709
VZ
443 wxLongLongWx& quotient,
444 wxLongLongWx& remainder) const
8b81872f 445{
5e6a0e83 446 if ((divisorIn.m_lo == 0) && (divisorIn.m_hi == 0))
8b81872f
VZ
447 {
448 // provoke division by zero error and silence the compilers warnings
449 // about an expression without effect and unused variable
5e6a0e83 450 long dummy = divisorIn.m_lo/divisorIn.m_hi;
8b81872f
VZ
451 dummy += 0;
452 }
453
2ea24d9f
VZ
454 // VZ: I'm writing this in a hurry and it's surely not the fastest way to
455 // do this - any improvements are more than welcome
5e6a0e83
VZ
456 //
457 // code inspired by the snippet at
458 // http://www.bearcave.com/software/divide.htm
459 //
460 // Copyright notice:
461 //
462 // Use of this program, for any purpose, is granted the author, Ian
463 // Kaplan, as long as this copyright notice is included in the source
464 // code or any source code derived from this program. The user assumes
3a994742 465 // all responsibility for using this code.
5e6a0e83
VZ
466
467 // init everything
468 wxLongLongWx dividend = *this,
469 divisor = divisorIn;
470
471 quotient = 0l;
472 remainder = 0l;
473
5e6a0e83
VZ
474 // always do unsigned division and adjust the signs later: in C integer
475 // division, the sign of the remainder is the same as the sign of the
476 // dividend, while the sign of the quotient is the product of the signs of
477 // the dividend and divisor. Of course, we also always have
478 //
479 // dividend = quotient*divisor + remainder
480 //
481 // with 0 <= abs(remainder) < abs(divisor)
482 bool negRemainder = dividend.m_hi < 0;
483 bool negQuotient = FALSE; // assume positive
484 if ( dividend.m_hi < 0 )
485 {
486 negQuotient = !negQuotient;
487 dividend = -dividend;
488 }
489 if ( divisor.m_hi < 0 )
490 {
491 negQuotient = !negQuotient;
492 divisor = -divisor;
493 }
2ea24d9f 494
2a310492
VZ
495 // check for some particular cases
496 if ( divisor > dividend )
2ea24d9f 497 {
2a310492
VZ
498 remainder = dividend;
499 }
500 else if ( divisor == dividend )
501 {
502 quotient = 1l;
5e6a0e83 503 }
2a310492
VZ
504 else
505 {
506 // here: dividend > divisor and both are positibe: do unsigned division
507 size_t nBits = 64u;
508 wxLongLongWx d;
5e6a0e83 509
2a310492 510 #define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1)))
2ea24d9f 511
2a310492 512 while ( remainder < divisor )
2ea24d9f 513 {
2a310492
VZ
514 remainder <<= 1;
515 if ( IS_MSB_SET(dividend) )
516 {
517 remainder |= 1;
518 }
519
520 d = dividend;
521 dividend <<= 1;
522
523 nBits--;
2ea24d9f
VZ
524 }
525
2a310492
VZ
526 // undo the last loop iteration
527 dividend = d;
528 remainder >>= 1;
529 nBits++;
5e6a0e83 530
2a310492
VZ
531 for ( size_t i = 0; i < nBits; i++ )
532 {
533 remainder <<= 1;
534 if ( IS_MSB_SET(dividend) )
535 {
536 remainder |= 1;
537 }
538
539 wxLongLongWx t = remainder - divisor;
540 dividend <<= 1;
541 quotient <<= 1;
542 if ( !IS_MSB_SET(t) )
543 {
544 quotient |= 1;
545
546 remainder = t;
547 }
5e6a0e83 548 }
2ea24d9f
VZ
549 }
550
5e6a0e83
VZ
551 // adjust signs
552 if ( negRemainder )
2ea24d9f 553 {
5e6a0e83 554 remainder = -remainder;
2ea24d9f
VZ
555 }
556
5e6a0e83
VZ
557 if ( negQuotient )
558 {
559 quotient = -quotient;
560 }
2ea24d9f
VZ
561}
562
563wxLongLongWx wxLongLongWx::operator/(const wxLongLongWx& ll) const
564{
565 wxLongLongWx quotient, remainder;
566
567 Divide(ll, quotient, remainder);
568
569 return quotient;
570}
571
572wxLongLongWx& wxLongLongWx::operator/=(const wxLongLongWx& ll)
573{
574 wxLongLongWx quotient, remainder;
575
576 Divide(ll, quotient, remainder);
577
55dfa8d3 578 *this = quotient;
3a994742 579
55dfa8d3 580 return *this;
8b81872f
VZ
581}
582
2ea24d9f
VZ
583wxLongLongWx wxLongLongWx::operator%(const wxLongLongWx& ll) const
584{
585 wxLongLongWx quotient, remainder;
586
587 Divide(ll, quotient, remainder);
588
589 return remainder;
590}
591
592// ----------------------------------------------------------------------------
593// misc
594// ----------------------------------------------------------------------------
595
8b81872f
VZ
596// temporary - just for testing
597void *wxLongLongWx::asArray(void) const
598{
599 static unsigned char temp[8];
600
13111b2a
VZ
601 temp[0] = (char)((m_hi >> 24) & 0xFF);
602 temp[1] = (char)((m_hi >> 16) & 0xFF);
603 temp[2] = (char)((m_hi >> 8) & 0xFF);
604 temp[3] = (char)((m_hi >> 0) & 0xFF);
605 temp[4] = (char)((m_lo >> 24) & 0xFF);
606 temp[5] = (char)((m_lo >> 16) & 0xFF);
607 temp[6] = (char)((m_lo >> 8) & 0xFF);
608 temp[7] = (char)((m_lo >> 0) & 0xFF);
8b81872f
VZ
609
610 return temp;
611}
612
3a994742 613#endif // wxUSE_LONGLONG_WX
8b81872f 614
3a994742 615wxString
277d672a 616#if wxUSE_LONGLONG_NATIVE
f20f6569 617wxLongLongNative::ToString() const
3a994742 618#else
f20f6569 619wxLongLongWx::ToString() const
3a994742 620#endif
8b81872f 621{
3a994742
VZ
622 // TODO: this is awfully inefficient, anything better?
623 wxString result;
8b81872f 624
3a994742 625 wxLongLong ll = *this;
8b81872f 626
3a994742
VZ
627 bool neg;
628 if ( ll < 0 )
629 {
630 ll.Negate();
631 neg = TRUE;
632 }
633 else
634 {
635 neg = FALSE;
636 }
8b81872f 637
3a994742 638 while ( ll != 0 )
8b81872f 639 {
3a994742
VZ
640 result.Prepend((wxChar)(_T('0') + (ll % 10).ToLong()));
641 ll /= 10;
8b81872f
VZ
642 }
643
3a994742
VZ
644 if ( result.empty() )
645 result = _T('0');
646 else if ( neg )
647 result.Prepend(_T('-'));
648
649 return result;
8b81872f 650}
fcc3d7cb 651
3a994742
VZ
652#if wxUSE_STD_IOSTREAM
653
654// input/output
655wxSTD ostream& operator<< (wxSTD ostream& o, const wxLongLong& ll)
656{
657 return o << ll.ToString();
658}
659
660#endif // wxUSE_STD_IOSTREAM
8b81872f 661
4e57b0d4 662#endif // wxUSE_LONGLONG