summaryrefslogtreecommitdiff
path: root/src/tool/moneycount/inf.hpp
blob: f28541af6bf9ce7083ffb4f7b26aeb9c8f807321 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#ifndef STLPLUS_INF
#define STLPLUS_INF
////////////////////////////////////////////////////////////////////////////////

//   Author:    Andy Rushton
//   Copyright: (c) Southampton University 1999-2004
//              (c) Andy Rushton           2004-2009
//   License:   BSD License, see ../docs/license.html

//   An infinite-precision integer class. This allows calculations on large
//   integers to be performed without overflow.

//   this class can throw the following exceptions:
//     std::out_of_range
//     std::overflow_error
//     std::invalid_argument
//     stlplus::divide_by_zero    // why doesn't std have this?
//   all of these are derivations of the baseclass:
//     std::logic_error
//   So you can catch all of them by catching the baseclass

//   Warning: inf was never intended to be fast, it is just for programs which
//   need a bit of infinite-precision integer arithmetic. For high-performance
//   processing, use the Gnu Multi-Precision (GMP) library. The inf type is just
//   easier to integrate and is already ported to all platforms and compilers
//   that STLplus is ported to.

////////////////////////////////////////////////////////////////////////////////
#include "portability_fixes.hpp"
#include "portability_exceptions.hpp"
#include <string>
#include <iostream>

////////////////////////////////////////////////////////////////////////////////

namespace stlplus
{

////////////////////////////////////////////////////////////////////////////////

  class inf
  {
  public:

    //////////////////////////////////////////////////////////////////////////////
    // constructors and assignments initialise the inf

    // the void constructor initialises to zero, the others initialise to the
    // value of the C integer type or the text value contained in the string

    inf(void);
    explicit inf(short);
    explicit inf(unsigned short);
    explicit inf(int);
    explicit inf(unsigned);
    explicit inf(long);
    explicit inf(unsigned long);
    explicit inf(const std::string&) throw(std::invalid_argument);
    inf(const inf&);

    ~inf(void);

    // assignments with equivalent behaviour to the constructors

    inf& operator = (short);
    inf& operator = (unsigned short);
    inf& operator = (int);
    inf& operator = (unsigned);
    inf& operator = (long);
    inf& operator = (unsigned long);
    inf& operator = (const std::string&) throw(std::invalid_argument);
    inf& operator = (const inf&);

    //////////////////////////////////////////////////////////////////////////////
    // conversions back to the C types
    // truncate: controls the behaviour when the value is too long for the result
    //           true: truncate the value
    //           false: throw an exception

    short to_short(bool truncate = true) const throw(std::overflow_error);
    unsigned short to_unsigned_short(bool truncate = true) const throw(std::overflow_error);

    int to_int(bool truncate = true) const throw(std::overflow_error);
    unsigned to_unsigned(bool truncate = true) const throw(std::overflow_error);

    long to_long(bool truncate = true) const throw(std::overflow_error);
    unsigned long to_unsigned_long(bool truncate = true) const throw(std::overflow_error);

    //////////////////////////////////////////////////////////////////////////////
    // bitwise manipulation

    void resize(unsigned bits);
    void reduce(void);

    // the number of significant bits in the value
    unsigned bits (void) const;
    unsigned size (void) const;

    // the number of bits that can be accessed by the bit() method (=bits() rounded up to the next byte)
    unsigned indexable_bits(void) const;

    bool bit (unsigned index) const throw(std::out_of_range);
    bool operator [] (unsigned index) const throw(std::out_of_range);

    void set (unsigned index) throw(std::out_of_range);
    void clear (unsigned index) throw(std::out_of_range);
    void preset (unsigned index, bool value) throw(std::out_of_range);

    inf slice(unsigned low, unsigned high) const throw(std::out_of_range);

    //////////////////////////////////////////////////////////////////////////////
    // tests for common values or ranges

    bool negative (void) const;
    bool natural (void) const;
    bool positive (void) const;
    bool zero (void) const;
    bool non_zero (void) const;

    // tests used in if(i) and if(!i)
//  operator bool (void) const;
    bool operator ! (void) const;

    //////////////////////////////////////////////////////////////////////////////
    // comparisons

    bool operator == (const inf&) const;
    bool operator != (const inf&) const;
    bool operator < (const inf&) const;
    bool operator <= (const inf&) const;
    bool operator > (const inf&) const;
    bool operator >= (const inf&) const;

    //////////////////////////////////////////////////////////////////////////////
    // bitwise logic operations

    inf& invert (void);
    inf operator ~ (void) const;

    inf& operator &= (const inf&);
    inf operator & (const inf&) const;

    inf& operator |= (const inf&);
    inf operator | (const inf&) const;

    inf& operator ^= (const inf&);
    inf operator ^ (const inf&) const;

    inf& operator <<= (unsigned shift);
    inf operator << (unsigned shift) const;

    inf& operator >>= (unsigned shift);
    inf operator >> (unsigned shift) const;

    //////////////////////////////////////////////////////////////////////////////
    // arithmetic operations

    inf& negate (void);
    inf operator - (void) const;

    inf& abs(void);
    friend inf abs(const inf&);

    inf& operator += (const inf&);
    inf operator + (const inf&) const;

    inf& operator -= (const inf&);
    inf operator - (const inf&) const;

    inf& operator *= (const inf&);
    inf operator * (const inf&) const;

    inf& operator /= (const inf&) throw(divide_by_zero);
    inf operator / (const inf&) const throw(divide_by_zero);

    inf& operator %= (const inf&) throw(divide_by_zero);
    inf operator % (const inf&) const throw(divide_by_zero);

    // combined division operator - returns the result pair(quotient,remainder) in one go
    std::pair<inf,inf> divide(const inf&) const throw(divide_by_zero);

    //////////////////////////////////////////////////////////////////////////////
    // pre- and post- increment and decrement

    inf& operator ++ (void);
    inf operator ++ (int);
    inf& operator -- (void);
    inf operator -- (int);

    //////////////////////////////////////////////////////////////////////////////
    // string representation and I/O

    std::string image_debug(void) const;

    // conversion to a string representation
    // radix must be 10, 2, 8 or 16
    std::string to_string(unsigned radix = 10) const
      throw(std::invalid_argument);

    // conversion from a string
    // radix == 0 - radix is deduced from the input - assumed 10 unless number is prefixed by 0b, 0 or 0x
    // however, you can specify the radix to be 10, 2, 8 or 16 to force that interpretation
    inf& from_string(const std::string&, unsigned radix = 0)
      throw(std::invalid_argument);

    //////////////////////////////////////////////////////////////////////////////
  private:
    std::string m_data;
  public:
    const std::string& get_bytes(void) const;
    void set_bytes(const std::string&);
  };

  ////////////////////////////////////////////////////////////////////////////////
  // redefine friends for gcc v4.1

  inf abs(const inf&);

  ////////////////////////////////////////////////////////////////////////////////

  std::ostream& operator << (std::ostream&, const inf&);
  std::istream& operator >> (std::istream&, inf&);

  ////////////////////////////////////////////////////////////////////////////////

} // end namespace stlplus

#endif