portability/inf.hpp
1: #ifndef STLPLUS_INF
2: #define STLPLUS_INF
3: ////////////////////////////////////////////////////////////////////////////////
4:
5: // Author: Andy Rushton
6: // Copyright: (c) Andy Rushton, 2007
7: // License: BSD License, see ../docs/license.html
8:
9: // An infinite-precision integer class. This allows calculations on large
10: // integers to be performed without overflow.
11:
12: // this class can throw the following exceptions:
13: // std::out_of_range
14: // std::overflow_error
15: // std::invalid_argument
16: // stlplus::divide_by_zero // why doesn't std have this?
17: // all of these are derivations of the baseclass:
18: // std::logic_error
19: // So you can catch all of them by catching the baseclass
20:
21: // Warning: inf was never intended to be fast, it is just for programs which
22: // need a bit of infinite-precision integer arithmetic. For high-performance
23: // processing, use the Gnu Multi-Precision (GMP) library. The inf type is just
24: // easier to integrate and is already ported to all platforms and compilers
25: // that STLplus is ported to.
26:
27: ////////////////////////////////////////////////////////////////////////////////
28: #include "portability_fixes.hpp"
29: #include "portability_exceptions.hpp"
30: #include <string>
31: #include <iostream>
32:
33: ////////////////////////////////////////////////////////////////////////////////
34:
35: namespace stlplus
36: {
37:
38: ////////////////////////////////////////////////////////////////////////////////
39:
40: class inf
41: {
42: public:
43:
44: //////////////////////////////////////////////////////////////////////////////
45: // constructors and assignments initialise the inf
46:
47: // the void constructor initialises to zero, the others initialise to the
48: // value of the C integer type or the text value contained in the string
49:
50: inf(void);
51: explicit inf(short);
52: explicit inf(unsigned short);
53: explicit inf(int);
54: explicit inf(unsigned);
55: explicit inf(long);
56: explicit inf(unsigned long);
57: explicit inf(const std::string&) throw(std::invalid_argument);
58: inf(const inf&);
59:
60: ~inf(void);
61:
62: // assignments with equivalent behaviour to the constructors
63:
64: inf& operator = (short);
65: inf& operator = (unsigned short);
66: inf& operator = (int);
67: inf& operator = (unsigned);
68: inf& operator = (long);
69: inf& operator = (unsigned long);
70: inf& operator = (const std::string&) throw(std::invalid_argument);
71: inf& operator = (const inf&);
72:
73: //////////////////////////////////////////////////////////////////////////////
74: // conversions back to the C types
75: // truncate: controls the behaviour when the value is too long for the result
76: // true: truncate the value
77: // false: throw an exception
78:
79: short to_short(bool truncate = true) const throw(std::overflow_error);
80: unsigned short to_unsigned_short(bool truncate = true) const throw(std::overflow_error);
81:
82: int to_int(bool truncate = true) const throw(std::overflow_error);
83: unsigned to_unsigned(bool truncate = true) const throw(std::overflow_error);
84:
85: long to_long(bool truncate = true) const throw(std::overflow_error);
86: unsigned long to_unsigned_long(bool truncate = true) const throw(std::overflow_error);
87:
88: //////////////////////////////////////////////////////////////////////////////
89: // bitwise manipulation
90:
91: void resize(unsigned bits);
92: void reduce(void);
93:
94: // the number of significant bits in the value
95: unsigned bits (void) const;
96: unsigned size (void) const;
97:
98: // the number of bits that can be accessed by the bit() method (=bits() rounded up to the next byte)
99: unsigned indexable_bits(void) const;
100:
101: bool bit (unsigned index) const throw(std::out_of_range);
102: bool operator [] (unsigned index) const throw(std::out_of_range);
103:
104: void set (unsigned index) throw(std::out_of_range);
105: void clear (unsigned index) throw(std::out_of_range);
106: void preset (unsigned index, bool value) throw(std::out_of_range);
107:
108: inf slice(unsigned low, unsigned high) const throw(std::out_of_range);
109:
110: //////////////////////////////////////////////////////////////////////////////
111: // tests for common values or ranges
112:
113: bool negative (void) const;
114: bool natural (void) const;
115: bool positive (void) const;
116: bool zero (void) const;
117: bool non_zero (void) const;
118:
119: // tests used in if(i) and if(!i)
120: // operator bool (void) const;
121: bool operator ! (void) const;
122:
123: //////////////////////////////////////////////////////////////////////////////
124: // comparisons
125:
126: bool operator == (const inf&) const;
127: bool operator != (const inf&) const;
128: bool operator < (const inf&) const;
129: bool operator <= (const inf&) const;
130: bool operator > (const inf&) const;
131: bool operator >= (const inf&) const;
132:
133: //////////////////////////////////////////////////////////////////////////////
134: // bitwise logic operations
135:
136: inf& invert (void);
137: inf operator ~ (void) const;
138:
139: inf& operator &= (const inf&);
140: inf operator & (const inf&) const;
141:
142: inf& operator |= (const inf&);
143: inf operator | (const inf&) const;
144:
145: inf& operator ^= (const inf&);
146: inf operator ^ (const inf&) const;
147:
148: inf& operator <<= (unsigned shift);
149: inf operator << (unsigned shift) const;
150:
151: inf& operator >>= (unsigned shift);
152: inf operator >> (unsigned shift) const;
153:
154: //////////////////////////////////////////////////////////////////////////////
155: // arithmetic operations
156:
157: inf& negate (void);
158: inf operator - (void) const;
159:
160: inf& abs(void);
161: friend inf abs(const inf&);
162:
163: inf& operator += (const inf&);
164: inf operator + (const inf&) const;
165:
166: inf& operator -= (const inf&);
167: inf operator - (const inf&) const;
168:
169: inf& operator *= (const inf&);
170: inf operator * (const inf&) const;
171:
172: inf& operator /= (const inf&) throw(divide_by_zero);
173: inf operator / (const inf&) const throw(divide_by_zero);
174:
175: inf& operator %= (const inf&) throw(divide_by_zero);
176: inf operator % (const inf&) const throw(divide_by_zero);
177:
178: // combined division operator - returns the result pair(quotient,remainder) in one go
179: std::pair<inf,inf> divide(const inf&) const throw(divide_by_zero);
180:
181: //////////////////////////////////////////////////////////////////////////////
182: // pre- and post- increment and decrement
183:
184: inf& operator ++ (void);
185: inf operator ++ (int);
186: inf& operator -- (void);
187: inf operator -- (int);
188:
189: //////////////////////////////////////////////////////////////////////////////
190: // string representation and I/O
191:
192: std::string image_debug(void) const;
193:
194: // conversion to a string representation
195: // radix must be 10, 2, 8 or 16
196: std::string to_string(unsigned radix = 10) const
197: throw(std::invalid_argument);
198:
199: // conversion from a string
200: // radix == 0 - radix is deduced from the input - assumed 10 unless number is prefixed by 0b, 0 or 0x
201: // however, you can specify the radix to be 10, 2, 8 or 16 to force that interpretation
202: inf& from_string(const std::string&, unsigned radix = 0)
203: throw(std::invalid_argument);
204:
205: //////////////////////////////////////////////////////////////////////////////
206: private:
207: std::string m_data;
208: public:
209: const std::string& get_bytes(void) const;
210: void set_bytes(const std::string&);
211: };
212:
213: ////////////////////////////////////////////////////////////////////////////////
214: // redefine friends for gcc v4.1
215:
216: inf abs(const inf&);
217:
218: ////////////////////////////////////////////////////////////////////////////////
219:
220: std::ostream& operator << (std::ostream&, const inf&);
221: std::istream& operator >> (std::istream&, inf&);
222:
223: ////////////////////////////////////////////////////////////////////////////////
224:
225: } // end namespace stlplus
226:
227: #endif