]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/longlong.cpp
path/file corrections for Darwin/Mac OS X
[wxWidgets.git] / src / common / longlong.cpp
... / ...
CommitLineData
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
28#if wxUSE_LONGLONG
29#include "wx/longlong.h"
30
31#if defined(__MWERKS__) && defined(__WXMSW__)
32#include <string.h> // for memset()
33#else
34#include <memory.h> // for memset()
35#endif
36
37#include <math.h> // for fabs()
38
39// ============================================================================
40// implementation
41// ============================================================================
42
43#if wxUSE_LONGLONG_NATIVE
44
45// ----------------------------------------------------------------------------
46// misc
47// ----------------------------------------------------------------------------
48
49void *wxLongLongNative::asArray() const
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
65#endif // wxUSE_LONGLONG_NATIVE
66
67// ============================================================================
68// wxLongLongWx: emulation of 'long long' using 2 longs
69// ============================================================================
70
71#if wxUSE_LONGLONG_WX
72
73// assignment
74wxLongLongWx& wxLongLongWx::Assign(double d)
75{
76 bool positive = d >= 0;
77 d = fabs(d);
78 if ( d <= ULONG_MAX )
79 {
80 m_hi = 0;
81 m_lo = (long)d;
82 }
83 else
84 {
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)));
87 }
88
89#ifdef wxLONGLONG_TEST_MODE
90 m_ll = (wxLongLong_t)d;
91
92 Check();
93#endif // wxLONGLONG_TEST_MODE
94
95 if ( !positive )
96 Negate();
97
98 return *this;
99}
100
101wxLongLongWx wxLongLongWx::operator<<(int shift) const
102{
103 wxLongLongWx ll(*this);
104 ll <<= shift;
105
106 return ll;
107}
108
109wxLongLongWx& wxLongLongWx::operator<<=(int shift)
110{
111 if (shift != 0)
112 {
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 }
124 }
125
126#ifdef wxLONGLONG_TEST_MODE
127 m_ll <<= shift;
128
129 Check();
130#endif // wxLONGLONG_TEST_MODE
131
132 return *this;
133}
134
135wxLongLongWx wxLongLongWx::operator>>(int shift) const
136{
137 wxLongLongWx ll(*this);
138 ll >>= shift;
139
140 return ll;
141}
142
143wxLongLongWx& wxLongLongWx::operator>>=(int shift)
144{
145 if (shift != 0)
146 {
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 }
158 }
159
160#ifdef wxLONGLONG_TEST_MODE
161 m_ll >>= shift;
162
163 Check();
164#endif // wxLONGLONG_TEST_MODE
165
166 return *this;
167}
168
169wxLongLongWx wxLongLongWx::operator+(const wxLongLongWx& ll) const
170{
171 wxLongLongWx res(*this);
172 res += ll;
173
174 return res;
175}
176
177wxLongLongWx wxLongLongWx::operator+(long l) const
178{
179 wxLongLongWx res(*this);
180 res += l;
181
182 return res;
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
195#ifdef wxLONGLONG_TEST_MODE
196 m_ll += ll.m_ll;
197
198 Check();
199#endif // wxLONGLONG_TEST_MODE
200
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
215#ifdef wxLONGLONG_TEST_MODE
216 m_ll += l;
217
218 Check();
219#endif // wxLONGLONG_TEST_MODE
220
221 return *this;
222}
223
224// pre increment
225wxLongLongWx& wxLongLongWx::operator++()
226{
227 m_lo++;
228 if (m_lo == 0)
229 m_hi++;
230
231#ifdef wxLONGLONG_TEST_MODE
232 m_ll++;
233
234 Check();
235#endif // wxLONGLONG_TEST_MODE
236
237 return *this;
238}
239
240// negation
241wxLongLongWx wxLongLongWx::operator-() const
242{
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++;
257
258#ifdef wxLONGLONG_TEST_MODE
259 m_ll = -m_ll;
260
261 Check();
262#endif // wxLONGLONG_TEST_MODE
263
264 return *this;
265}
266
267// subtraction
268
269wxLongLongWx wxLongLongWx::operator-(const wxLongLongWx& ll) const
270{
271 wxLongLongWx res(*this);
272 res -= ll;
273
274 return res;
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
287#ifdef wxLONGLONG_TEST_MODE
288 m_ll -= ll.m_ll;
289
290 Check();
291#endif // wxLONGLONG_TEST_MODE
292
293 return *this;
294}
295
296// pre decrement
297wxLongLongWx& wxLongLongWx::operator--()
298{
299 m_lo--;
300 if (m_lo == 0xFFFFFFFF)
301 m_hi--;
302
303#ifdef wxLONGLONG_TEST_MODE
304 m_ll--;
305
306 Check();
307#endif // wxLONGLONG_TEST_MODE
308
309 return *this;
310}
311
312// comparison operators
313
314bool wxLongLongWx::operator<(const wxLongLongWx& ll) const
315{
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;
322}
323
324bool wxLongLongWx::operator>(const wxLongLongWx& ll) const
325{
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;
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
356#ifdef wxLONGLONG_TEST_MODE
357 m_ll &= ll.m_ll;
358
359 Check();
360#endif // wxLONGLONG_TEST_MODE
361
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
370#ifdef wxLONGLONG_TEST_MODE
371 m_ll |= ll.m_ll;
372
373 Check();
374#endif // wxLONGLONG_TEST_MODE
375
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
384#ifdef wxLONGLONG_TEST_MODE
385 m_ll ^= ll.m_ll;
386
387 Check();
388#endif // wxLONGLONG_TEST_MODE
389
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{
402 wxLongLongWx res(*this);
403 res *= ll;
404
405 return res;
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);
412
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;
421 do
422 {
423 if ((q.m_lo & 1) != 0)
424 *this += t;
425 q >>= 1;
426 t <<= 1;
427 counter++;
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
437 return *this;
438}
439
440// division
441
442void wxLongLongWx::Divide(const wxLongLongWx& divisorIn,
443 wxLongLongWx& quotient,
444 wxLongLongWx& remainder) const
445{
446 if ((divisorIn.m_lo == 0) && (divisorIn.m_hi == 0))
447 {
448 // provoke division by zero error and silence the compilers warnings
449 // about an expression without effect and unused variable
450 long dummy = divisorIn.m_lo/divisorIn.m_hi;
451 dummy += 0;
452 }
453
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
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
465 // all responsibility for using this code.
466
467 // init everything
468 wxLongLongWx dividend = *this,
469 divisor = divisorIn;
470
471 quotient = 0l;
472 remainder = 0l;
473
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 }
494
495 // check for some particular cases
496 if ( divisor > dividend )
497 {
498 remainder = dividend;
499 }
500 else if ( divisor == dividend )
501 {
502 quotient = 1l;
503 }
504 else
505 {
506 // here: dividend > divisor and both are positibe: do unsigned division
507 size_t nBits = 64u;
508 wxLongLongWx d;
509
510 #define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1)))
511
512 while ( remainder < divisor )
513 {
514 remainder <<= 1;
515 if ( IS_MSB_SET(dividend) )
516 {
517 remainder |= 1;
518 }
519
520 d = dividend;
521 dividend <<= 1;
522
523 nBits--;
524 }
525
526 // undo the last loop iteration
527 dividend = d;
528 remainder >>= 1;
529 nBits++;
530
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 }
548 }
549 }
550
551 // adjust signs
552 if ( negRemainder )
553 {
554 remainder = -remainder;
555 }
556
557 if ( negQuotient )
558 {
559 quotient = -quotient;
560 }
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
578 *this = quotient;
579
580 return *this;
581}
582
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
596// temporary - just for testing
597void *wxLongLongWx::asArray(void) const
598{
599 static unsigned char temp[8];
600
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);
609
610 return temp;
611}
612
613#endif // wxUSE_LONGLONG_WX
614
615wxString
616#if wxUSE_LONGLONG_NATIVE
617wxLongLongNative::ToString() const
618#else
619wxLongLongWx::ToString() const
620#endif
621{
622 // TODO: this is awfully inefficient, anything better?
623 wxString result;
624
625 wxLongLong ll = *this;
626
627 bool neg;
628 if ( ll < 0 )
629 {
630 ll.Negate();
631 neg = TRUE;
632 }
633 else
634 {
635 neg = FALSE;
636 }
637
638 while ( ll != 0 )
639 {
640 result.Prepend((wxChar)(_T('0') + (ll % 10).ToLong()));
641 ll /= 10;
642 }
643
644 if ( result.empty() )
645 result = _T('0');
646 else if ( neg )
647 result.Prepend(_T('-'));
648
649 return result;
650}
651
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
661
662#endif // wxUSE_LONGLONG