blob: fa59fd8e7de93d68a37021269165d27c51649b01 [file] [log] [blame]
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +00001# Copyright 2007 Google, Inc. All Rights Reserved.
2# Licensed to PSF under a Contributor Agreement.
3
4"""Abstract Base Classes (ABCs) for numbers, according to PEP 3141.
5
6TODO: Fill out more detailed documentation on the operators."""
7
Jeffrey Yasskind7b00332008-01-15 07:46:24 +00008from __future__ import division
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +00009from abc import ABCMeta, abstractmethod, abstractproperty
10
Raymond Hettinger6b467622008-03-15 20:02:04 +000011__all__ = ["Number", "Complex", "Real", "Rational", "Integral"]
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +000012
13class Number(object):
14 """All numbers inherit from this class.
15
16 If you just want to check if an argument x is a number, without
17 caring what kind, use isinstance(x, Number).
18 """
19 __metaclass__ = ABCMeta
20
Nick Coghlan48361f52008-08-11 15:45:58 +000021 # Concrete numeric types must provide their own hash implementation
22 __hash__ = None
23
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +000024
Raymond Hettingerddb164a2008-02-14 01:08:02 +000025## Notes on Decimal
26## ----------------
27## Decimal has all of the methods specified by the Real abc, but it should
28## not be registered as a Real because decimals do not interoperate with
Raymond Hettinger6b467622008-03-15 20:02:04 +000029## binary floats (i.e. Decimal('3.14') + 2.71828 is undefined). But,
30## abstract reals are expected to interoperate (i.e. R1 + R2 should be
31## expected to work if R1 and R2 are both Reals).
Raymond Hettinger48688d82008-02-11 22:53:01 +000032
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +000033class Complex(Number):
34 """Complex defines the operations that work on the builtin complex type.
35
36 In short, those are: a conversion to complex, .real, .imag, +, -,
37 *, /, abs(), .conjugate, ==, and !=.
38
39 If it is given heterogenous arguments, and doesn't have special
40 knowledge about them, it should fall back to the builtin complex
41 type as described below.
42 """
43
44 @abstractmethod
45 def __complex__(self):
46 """Return a builtin complex instance. Called for complex(self)."""
47
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000048 # Will be __bool__ in 3.0.
49 def __nonzero__(self):
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +000050 """True if self != 0. Called for bool(self)."""
51 return self != 0
52
53 @abstractproperty
54 def real(self):
55 """Retrieve the real component of this number.
56
57 This should subclass Real.
58 """
59 raise NotImplementedError
60
61 @abstractproperty
62 def imag(self):
63 """Retrieve the real component of this number.
64
65 This should subclass Real.
66 """
67 raise NotImplementedError
68
69 @abstractmethod
70 def __add__(self, other):
71 """self + other"""
72 raise NotImplementedError
73
74 @abstractmethod
75 def __radd__(self, other):
76 """other + self"""
77 raise NotImplementedError
78
79 @abstractmethod
80 def __neg__(self):
81 """-self"""
82 raise NotImplementedError
83
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000084 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +000085 def __pos__(self):
86 """+self"""
87 raise NotImplementedError
88
89 def __sub__(self, other):
90 """self - other"""
91 return self + -other
92
93 def __rsub__(self, other):
94 """other - self"""
95 return -self + other
96
97 @abstractmethod
98 def __mul__(self, other):
99 """self * other"""
100 raise NotImplementedError
101
102 @abstractmethod
103 def __rmul__(self, other):
104 """other * self"""
105 raise NotImplementedError
106
107 @abstractmethod
108 def __div__(self, other):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000109 """self / other without __future__ division
110
111 May promote to float.
112 """
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000113 raise NotImplementedError
114
115 @abstractmethod
116 def __rdiv__(self, other):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000117 """other / self without __future__ division"""
118 raise NotImplementedError
119
120 @abstractmethod
121 def __truediv__(self, other):
122 """self / other with __future__ division.
123
124 Should promote to float when necessary.
125 """
126 raise NotImplementedError
127
128 @abstractmethod
129 def __rtruediv__(self, other):
130 """other / self with __future__ division"""
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000131 raise NotImplementedError
132
133 @abstractmethod
134 def __pow__(self, exponent):
135 """self**exponent; should promote to float or complex when necessary."""
136 raise NotImplementedError
137
138 @abstractmethod
139 def __rpow__(self, base):
140 """base ** self"""
141 raise NotImplementedError
142
143 @abstractmethod
144 def __abs__(self):
145 """Returns the Real distance from 0. Called for abs(self)."""
146 raise NotImplementedError
147
148 @abstractmethod
149 def conjugate(self):
150 """(x+y*i).conjugate() returns (x-y*i)."""
151 raise NotImplementedError
152
153 @abstractmethod
154 def __eq__(self, other):
155 """self == other"""
156 raise NotImplementedError
157
Jeffrey Yasskin27d33942008-02-08 06:45:40 +0000158 def __ne__(self, other):
159 """self != other"""
160 # The default __ne__ doesn't negate __eq__ until 3.0.
161 return not (self == other)
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000162
163Complex.register(complex)
164
165
166class Real(Complex):
167 """To Complex, Real adds the operations that work on real numbers.
168
169 In short, those are: a conversion to float, trunc(), divmod,
170 %, <, <=, >, and >=.
171
172 Real also provides defaults for the derived operations.
173 """
174
175 @abstractmethod
176 def __float__(self):
177 """Any Real can be converted to a native float object.
178
179 Called for float(self)."""
180 raise NotImplementedError
181
182 @abstractmethod
183 def __trunc__(self):
184 """trunc(self): Truncates self to an Integral.
185
186 Returns an Integral i such that:
187 * i>0 iff self>0;
188 * abs(i) <= abs(self);
189 * for any Integral j satisfying the first two conditions,
190 abs(i) >= abs(j) [i.e. i has "maximal" abs among those].
191 i.e. "truncate towards 0".
192 """
193 raise NotImplementedError
194
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000195 def __divmod__(self, other):
196 """divmod(self, other): The pair (self // other, self % other).
197
198 Sometimes this can be computed faster than the pair of
199 operations.
200 """
201 return (self // other, self % other)
202
203 def __rdivmod__(self, other):
204 """divmod(other, self): The pair (self // other, self % other).
205
206 Sometimes this can be computed faster than the pair of
207 operations.
208 """
209 return (other // self, other % self)
210
211 @abstractmethod
212 def __floordiv__(self, other):
213 """self // other: The floor() of self/other."""
214 raise NotImplementedError
215
216 @abstractmethod
217 def __rfloordiv__(self, other):
218 """other // self: The floor() of other/self."""
219 raise NotImplementedError
220
221 @abstractmethod
222 def __mod__(self, other):
223 """self % other"""
224 raise NotImplementedError
225
226 @abstractmethod
227 def __rmod__(self, other):
228 """other % self"""
229 raise NotImplementedError
230
231 @abstractmethod
232 def __lt__(self, other):
233 """self < other
234
235 < on Reals defines a total ordering, except perhaps for NaN."""
236 raise NotImplementedError
237
238 @abstractmethod
239 def __le__(self, other):
240 """self <= other"""
241 raise NotImplementedError
242
243 # Concrete implementations of Complex abstract methods.
244 def __complex__(self):
245 """complex(self) == complex(float(self), 0)"""
246 return complex(float(self))
247
248 @property
249 def real(self):
250 """Real numbers are their real component."""
251 return +self
252
253 @property
254 def imag(self):
255 """Real numbers have no imaginary component."""
256 return 0
257
258 def conjugate(self):
259 """Conjugate is a no-op for Reals."""
260 return +self
261
262Real.register(float)
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000263
264
Raymond Hettingercd6bfab2008-03-15 20:37:50 +0000265class Rational(Real):
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000266 """.numerator and .denominator should be in lowest terms."""
267
268 @abstractproperty
269 def numerator(self):
270 raise NotImplementedError
271
272 @abstractproperty
273 def denominator(self):
274 raise NotImplementedError
275
276 # Concrete implementation of Real's conversion to float.
277 def __float__(self):
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000278 """float(self) = self.numerator / self.denominator
279
280 It's important that this conversion use the integer's "true"
281 division rather than casting one side to float before dividing
282 so that ratios of huge integers convert without overflowing.
283
284 """
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000285 return self.numerator / self.denominator
286
287
288class Integral(Rational):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000289 """Integral adds a conversion to long and the bit-string operations."""
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000290
291 @abstractmethod
Guido van Rossum21a45e12008-06-17 17:38:02 +0000292 def __long__(self):
293 """long(self)"""
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000294 raise NotImplementedError
295
296 def __index__(self):
297 """index(self)"""
Guido van Rossum21a45e12008-06-17 17:38:02 +0000298 return long(self)
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000299
Guido van Rossum21a45e12008-06-17 17:38:02 +0000300 @abstractmethod
301 def __pow__(self, exponent, modulus=None):
302 """self ** exponent % modulus, but maybe faster.
303
304 Accept the modulus argument if you want to support the
305 3-argument version of pow(). Raise a TypeError if exponent < 0
306 or any argument isn't Integral. Otherwise, just implement the
307 2-argument version described in Complex.
308 """
309 raise NotImplementedError
310
311 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000312 def __lshift__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000313 """self << other"""
314 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000315
Guido van Rossum21a45e12008-06-17 17:38:02 +0000316 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000317 def __rlshift__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000318 """other << self"""
319 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000320
Guido van Rossum21a45e12008-06-17 17:38:02 +0000321 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000322 def __rshift__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000323 """self >> other"""
324 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000325
Guido van Rossum21a45e12008-06-17 17:38:02 +0000326 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000327 def __rrshift__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000328 """other >> self"""
329 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000330
Guido van Rossum21a45e12008-06-17 17:38:02 +0000331 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000332 def __and__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000333 """self & other"""
334 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000335
Guido van Rossum21a45e12008-06-17 17:38:02 +0000336 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000337 def __rand__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000338 """other & self"""
339 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000340
Guido van Rossum21a45e12008-06-17 17:38:02 +0000341 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000342 def __xor__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000343 """self ^ other"""
344 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000345
Guido van Rossum21a45e12008-06-17 17:38:02 +0000346 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000347 def __rxor__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000348 """other ^ self"""
349 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000350
Guido van Rossum21a45e12008-06-17 17:38:02 +0000351 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000352 def __or__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000353 """self | other"""
354 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000355
Guido van Rossum21a45e12008-06-17 17:38:02 +0000356 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000357 def __ror__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000358 """other | self"""
359 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000360
Guido van Rossum21a45e12008-06-17 17:38:02 +0000361 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000362 def __invert__(self):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000363 """~self"""
364 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000365
366 # Concrete implementations of Rational and Real abstract methods.
367 def __float__(self):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000368 """float(self) == float(long(self))"""
369 return float(long(self))
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000370
371 @property
372 def numerator(self):
373 """Integers are their own numerators."""
374 return +self
375
376 @property
377 def denominator(self):
378 """Integers have a denominator of 1."""
379 return 1
380
381Integral.register(int)
382Integral.register(long)