inf.hpp
1: #ifndef INF_HPP
2: #define INF_HPP
3: /*------------------------------------------------------------------------------
4:
5: Author: Andy Rushton
6: Copyright: (c) Andy Rushton, 2004
7: License: BSD License, see ../docs/license.html
8:
9: An infinite-precision integer class
10:
11: ------------------------------------------------------------------------------*/
12: #include "os_fixes.hpp"
13: #include <string>
14: #include <stdexcept>
15: #include "textio.hpp"
16: #include "string_utilities.hpp"
17: #include "persistent.hpp"
18:
19: ////////////////////////////////////////////////////////////////////////////////
20:
21: class inf
22: {
23: public:
24: // this class can throw the following exceptions:
25: // std::out_of_range
26: // std::overflow_error
27: // std::invalid_argument
28: // inf::divide_by_zero // why doesn't std have this?
29: // all of these are derivations of the baseclass:
30: // std::logic_error
31: // So you can catch all of them by catching the baseclass
32: class divide_by_zero : public std::logic_error {
33: public:
34: divide_by_zero (const std::string& what_arg): std::logic_error (what_arg) { }
35: };
36:
37: //////////////////////////////////////////////////////////////////////////////
38: // constructors and assignments initialise the inf
39: // the void constructor initialises to zero, the others initialise to the value of the C integer type
40: // see also the section on string representations
41:
42: inf(void);
43: explicit inf(short);
44: explicit inf(unsigned short);
45: explicit inf(int);
46: explicit inf(unsigned);
47: explicit inf(long);
48: explicit inf(unsigned long);
49: explicit inf(const std::string&) throw(std::invalid_argument);
50: inf(const inf&);
51:
52: ~inf(void);
53:
54: inf& operator = (short);
55: inf& operator = (unsigned short);
56: inf& operator = (int);
57: inf& operator = (unsigned);
58: inf& operator = (long);
59: inf& operator = (unsigned long);
60: inf& operator = (const std::string&) throw(std::invalid_argument);
61: inf& operator = (const inf&);
62:
63: //////////////////////////////////////////////////////////////////////////////
64: // conversions back to the C types - note that the inf must be in range for this to be legal
65:
66: short to_short(void) const throw(std::overflow_error);
67: unsigned short to_ushort(void) const throw(std::overflow_error);
68: int to_int(void) const throw(std::overflow_error);
69: unsigned to_unsigned(void) const throw(std::overflow_error);
70: unsigned to_uint(void) const throw(std::overflow_error);
71: long to_long(void) const throw(std::overflow_error);
72: unsigned long to_ulong(void) const throw(std::overflow_error);
73:
74: //////////////////////////////////////////////////////////////////////////////
75: // bitwise manipulation
76:
77: void resize(unsigned bits);
78: void reduce(void);
79:
80: // the number of significant bits in the value
81: unsigned bits (void) const;
82: unsigned size (void) const;
83:
84: // the number of bits that can be accessed by the bit() method (=bits() rounded up to the next byte)
85: unsigned indexable_bits(void) const;
86:
87: bool bit (unsigned index) const throw(std::out_of_range);
88: bool operator [] (unsigned index) const throw(std::out_of_range);
89:
90: void set (unsigned index) throw(std::out_of_range);
91: void clear (unsigned index) throw(std::out_of_range);
92: void preset (unsigned index, bool value) throw(std::out_of_range);
93:
94: inf slice(unsigned low, unsigned high) const throw(std::out_of_range);
95:
96: //////////////////////////////////////////////////////////////////////////////
97: // tests for common values or ranges
98:
99: bool negative (void) const;
100: bool natural (void) const;
101: bool positive (void) const;
102: bool zero (void) const;
103: bool non_zero (void) const;
104:
105: // tests used in if(i) and if(!i)
106: // operator bool (void) const;
107: bool operator ! (void) const;
108:
109: //////////////////////////////////////////////////////////////////////////////
110: // comparisons
111:
112: friend bool operator == (const inf&, const inf&);
113: friend bool operator != (const inf&, const inf&);
114: friend bool operator < (const inf&, const inf&);
115: friend bool operator <= (const inf&, const inf&);
116: friend bool operator > (const inf&, const inf&);
117: friend bool operator >= (const inf&, const inf&);
118:
119: //////////////////////////////////////////////////////////////////////////////
120: // bitwise logic operations
121:
122: inf& invert (void);
123: friend inf operator ~ (const inf&);
124:
125: inf& operator &= (const inf&);
126: friend inf operator & (const inf&, const inf&);
127:
128: inf& operator |= (const inf&);
129: friend inf operator | (const inf&, const inf&);
130:
131: inf& operator ^= (const inf&);
132: friend inf operator ^ (const inf&, const inf&);
133:
134: inf& operator <<= (unsigned shift);
135: friend inf operator << (const inf&, unsigned shift);
136:
137: inf& operator >>= (unsigned shift);
138: friend inf operator >> (const inf&,unsigned shift);
139:
140: //////////////////////////////////////////////////////////////////////////////
141: // arithmetic operations
142:
143: inf& negate (void);
144: friend inf operator - (const inf&);
145:
146: inf& abs(void);
147: friend inf abs(const inf&);
148:
149: inf& operator += (const inf&);
150: friend inf operator + (const inf&, const inf&);
151:
152: inf& operator -= (const inf&);
153: friend inf operator - (const inf&, const inf&);
154:
155: inf& operator *= (const inf&);
156: friend inf operator * (const inf&, const inf&);
157:
158: inf& operator /= (const inf&) throw(divide_by_zero);
159: friend inf operator / (const inf&, const inf&) throw(divide_by_zero);
160: inf& operator %= (const inf&) throw(divide_by_zero);
161: friend inf operator % (const inf&, const inf&) throw(divide_by_zero);
162:
163: // combined division operator - returns the result pair(quotient,remainder) in one go
164: friend std::pair<inf,inf> divide(const inf&, const inf&) throw(divide_by_zero);
165:
166: //////////////////////////////////////////////////////////////////////////////
167: // pre- and post- increment and decrement
168:
169: inf& operator ++ (void);
170: inf operator ++ (int);
171: inf& operator -- (void);
172: inf operator -- (int);
173:
174: //////////////////////////////////////////////////////////////////////////////
175: // string representation and I/O
176:
177: std::string image_debug(void) const;
178:
179: // conversion to a string representation - see string_utilities for an explanation of the arguments
180: // provided as a method and a friend
181:
182: std::string to_string(unsigned radix = 10, radix_display_t display = radix_c_style_or_hash, unsigned width = 0) const
183: throw(std::invalid_argument);
184:
185: friend std::string to_string(const inf& i,
186: unsigned radix = 10, radix_display_t display = radix_c_style_or_hash, unsigned width = 0)
187: throw(std::invalid_argument);
188:
189: friend inf to_inf(const std::string&, unsigned radix = 0)
190: throw(std::invalid_argument);
191:
192: friend otext& operator << (otext&, const inf&);
193: friend itext& operator >> (itext&, inf&);
194:
195: //////////////////////////////////////////////////////////////////////////////
196: // persistence
197:
198: void dump(dump_context&) const throw(persistent_dump_failed);
199: void restore(restore_context&) throw(persistent_restore_failed);
200:
201: friend void dump(dump_context& str, const inf& data) throw(persistent_dump_failed);
202: friend void restore(restore_context& str, inf& data) throw(persistent_restore_failed);
203:
204: //////////////////////////////////////////////////////////////////////////////
205: private:
206: std::string m_data;
207:
208: void set_head(void);
209: };
210:
211: // redefine friends for gcc v4.1
212: bool operator == (const inf&, const inf&);
213: bool operator != (const inf&, const inf&);
214: bool operator < (const inf&, const inf&);
215: bool operator <= (const inf&, const inf&);
216: bool operator > (const inf&, const inf&);
217: bool operator >= (const inf&, const inf&);
218: inf operator ~ (const inf&);
219: inf operator & (const inf&, const inf&);
220: inf operator | (const inf&, const inf&);
221: inf operator ^ (const inf&, const inf&);
222: inf operator << (const inf&, unsigned shift);
223: inf operator >> (const inf&,unsigned shift);
224: inf operator - (const inf&);
225: inf abs(const inf&);
226: inf operator + (const inf&, const inf&);
227: inf operator - (const inf&, const inf&);
228: inf operator * (const inf&, const inf&);
229: inf operator / (const inf&, const inf&) throw(inf::divide_by_zero);
230: inf operator % (const inf&, const inf&) throw(inf::divide_by_zero);
231: std::pair<inf,inf> divide(const inf&, const inf&) throw(inf::divide_by_zero);
232: std::string to_string(const inf& i, unsigned radix, radix_display_t display, unsigned width) throw(std::invalid_argument);
233: inf to_inf(const std::string&, unsigned radix) throw(std::invalid_argument);
234: otext& operator << (otext&, const inf&);
235: itext& operator >> (itext&, inf&);
236: void dump(dump_context& str, const inf& data) throw(persistent_dump_failed);
237: void restore(restore_context& str, inf& data) throw(persistent_restore_failed);
238:
239: ////////////////////////////////////////////////////////////////////////////////
240: #endif