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