blob: cbcecedeca1c404c55a6eae8d99507a17afcd739 [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
11__all__ = ["Number", "Exact", "Inexact",
12 "Complex", "Real", "Rational", "Integral",
13 ]
14
15
16class Number(object):
17 """All numbers inherit from this class.
18
19 If you just want to check if an argument x is a number, without
20 caring what kind, use isinstance(x, Number).
21 """
22 __metaclass__ = ABCMeta
23
24
25class Exact(Number):
26 """Operations on instances of this type are exact.
27
28 As long as the result of a homogenous operation is of the same
29 type, you can assume that it was computed exactly, and there are
30 no round-off errors. Laws like commutativity and associativity
31 hold.
32 """
33
34Exact.register(int)
35Exact.register(long)
36
37
38class Inexact(Number):
39 """Operations on instances of this type are inexact.
40
41 Given X, an instance of Inexact, it is possible that (X + -X) + 3
42 == 3, but X + (-X + 3) == 0. The exact form this error takes will
43 vary by type, but it's generally unsafe to compare this type for
44 equality.
45 """
46
47Inexact.register(complex)
48Inexact.register(float)
49# Inexact.register(decimal.Decimal)
50
51
52class Complex(Number):
53 """Complex defines the operations that work on the builtin complex type.
54
55 In short, those are: a conversion to complex, .real, .imag, +, -,
56 *, /, abs(), .conjugate, ==, and !=.
57
58 If it is given heterogenous arguments, and doesn't have special
59 knowledge about them, it should fall back to the builtin complex
60 type as described below.
61 """
62
63 @abstractmethod
64 def __complex__(self):
65 """Return a builtin complex instance. Called for complex(self)."""
66
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000067 # Will be __bool__ in 3.0.
68 def __nonzero__(self):
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +000069 """True if self != 0. Called for bool(self)."""
70 return self != 0
71
72 @abstractproperty
73 def real(self):
74 """Retrieve the real component of this number.
75
76 This should subclass Real.
77 """
78 raise NotImplementedError
79
80 @abstractproperty
81 def imag(self):
82 """Retrieve the real component of this number.
83
84 This should subclass Real.
85 """
86 raise NotImplementedError
87
88 @abstractmethod
89 def __add__(self, other):
90 """self + other"""
91 raise NotImplementedError
92
93 @abstractmethod
94 def __radd__(self, other):
95 """other + self"""
96 raise NotImplementedError
97
98 @abstractmethod
99 def __neg__(self):
100 """-self"""
101 raise NotImplementedError
102
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000103 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000104 def __pos__(self):
105 """+self"""
106 raise NotImplementedError
107
108 def __sub__(self, other):
109 """self - other"""
110 return self + -other
111
112 def __rsub__(self, other):
113 """other - self"""
114 return -self + other
115
116 @abstractmethod
117 def __mul__(self, other):
118 """self * other"""
119 raise NotImplementedError
120
121 @abstractmethod
122 def __rmul__(self, other):
123 """other * self"""
124 raise NotImplementedError
125
126 @abstractmethod
127 def __div__(self, other):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000128 """self / other without __future__ division
129
130 May promote to float.
131 """
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000132 raise NotImplementedError
133
134 @abstractmethod
135 def __rdiv__(self, other):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000136 """other / self without __future__ division"""
137 raise NotImplementedError
138
139 @abstractmethod
140 def __truediv__(self, other):
141 """self / other with __future__ division.
142
143 Should promote to float when necessary.
144 """
145 raise NotImplementedError
146
147 @abstractmethod
148 def __rtruediv__(self, other):
149 """other / self with __future__ division"""
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000150 raise NotImplementedError
151
152 @abstractmethod
153 def __pow__(self, exponent):
154 """self**exponent; should promote to float or complex when necessary."""
155 raise NotImplementedError
156
157 @abstractmethod
158 def __rpow__(self, base):
159 """base ** self"""
160 raise NotImplementedError
161
162 @abstractmethod
163 def __abs__(self):
164 """Returns the Real distance from 0. Called for abs(self)."""
165 raise NotImplementedError
166
167 @abstractmethod
168 def conjugate(self):
169 """(x+y*i).conjugate() returns (x-y*i)."""
170 raise NotImplementedError
171
172 @abstractmethod
173 def __eq__(self, other):
174 """self == other"""
175 raise NotImplementedError
176
Jeffrey Yasskin27d33942008-02-08 06:45:40 +0000177 def __ne__(self, other):
178 """self != other"""
179 # The default __ne__ doesn't negate __eq__ until 3.0.
180 return not (self == other)
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000181
182Complex.register(complex)
183
184
185class Real(Complex):
186 """To Complex, Real adds the operations that work on real numbers.
187
188 In short, those are: a conversion to float, trunc(), divmod,
189 %, <, <=, >, and >=.
190
191 Real also provides defaults for the derived operations.
192 """
193
194 @abstractmethod
195 def __float__(self):
196 """Any Real can be converted to a native float object.
197
198 Called for float(self)."""
199 raise NotImplementedError
200
201 @abstractmethod
202 def __trunc__(self):
203 """trunc(self): Truncates self to an Integral.
204
205 Returns an Integral i such that:
206 * i>0 iff self>0;
207 * abs(i) <= abs(self);
208 * for any Integral j satisfying the first two conditions,
209 abs(i) >= abs(j) [i.e. i has "maximal" abs among those].
210 i.e. "truncate towards 0".
211 """
212 raise NotImplementedError
213
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000214 def __divmod__(self, other):
215 """divmod(self, other): The pair (self // other, self % other).
216
217 Sometimes this can be computed faster than the pair of
218 operations.
219 """
220 return (self // other, self % other)
221
222 def __rdivmod__(self, other):
223 """divmod(other, self): The pair (self // other, self % other).
224
225 Sometimes this can be computed faster than the pair of
226 operations.
227 """
228 return (other // self, other % self)
229
230 @abstractmethod
231 def __floordiv__(self, other):
232 """self // other: The floor() of self/other."""
233 raise NotImplementedError
234
235 @abstractmethod
236 def __rfloordiv__(self, other):
237 """other // self: The floor() of other/self."""
238 raise NotImplementedError
239
240 @abstractmethod
241 def __mod__(self, other):
242 """self % other"""
243 raise NotImplementedError
244
245 @abstractmethod
246 def __rmod__(self, other):
247 """other % self"""
248 raise NotImplementedError
249
250 @abstractmethod
251 def __lt__(self, other):
252 """self < other
253
254 < on Reals defines a total ordering, except perhaps for NaN."""
255 raise NotImplementedError
256
257 @abstractmethod
258 def __le__(self, other):
259 """self <= other"""
260 raise NotImplementedError
261
262 # Concrete implementations of Complex abstract methods.
263 def __complex__(self):
264 """complex(self) == complex(float(self), 0)"""
265 return complex(float(self))
266
267 @property
268 def real(self):
269 """Real numbers are their real component."""
270 return +self
271
272 @property
273 def imag(self):
274 """Real numbers have no imaginary component."""
275 return 0
276
277 def conjugate(self):
278 """Conjugate is a no-op for Reals."""
279 return +self
280
281Real.register(float)
282# Real.register(decimal.Decimal)
283
284
285class Rational(Real, Exact):
286 """.numerator and .denominator should be in lowest terms."""
287
288 @abstractproperty
289 def numerator(self):
290 raise NotImplementedError
291
292 @abstractproperty
293 def denominator(self):
294 raise NotImplementedError
295
296 # Concrete implementation of Real's conversion to float.
297 def __float__(self):
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000298 """float(self) = self.numerator / self.denominator
299
300 It's important that this conversion use the integer's "true"
301 division rather than casting one side to float before dividing
302 so that ratios of huge integers convert without overflowing.
303
304 """
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000305 return self.numerator / self.denominator
306
307
308class Integral(Rational):
309 """Integral adds a conversion to long and the bit-string operations."""
310
311 @abstractmethod
312 def __long__(self):
313 """long(self)"""
314 raise NotImplementedError
315
316 def __index__(self):
317 """index(self)"""
318 return long(self)
319
320 @abstractmethod
321 def __pow__(self, exponent, modulus=None):
322 """self ** exponent % modulus, but maybe faster.
323
324 Accept the modulus argument if you want to support the
325 3-argument version of pow(). Raise a TypeError if exponent < 0
326 or any argument isn't Integral. Otherwise, just implement the
327 2-argument version described in Complex.
328 """
329 raise NotImplementedError
330
331 @abstractmethod
332 def __lshift__(self, other):
333 """self << other"""
334 raise NotImplementedError
335
336 @abstractmethod
337 def __rlshift__(self, other):
338 """other << self"""
339 raise NotImplementedError
340
341 @abstractmethod
342 def __rshift__(self, other):
343 """self >> other"""
344 raise NotImplementedError
345
346 @abstractmethod
347 def __rrshift__(self, other):
348 """other >> self"""
349 raise NotImplementedError
350
351 @abstractmethod
352 def __and__(self, other):
353 """self & other"""
354 raise NotImplementedError
355
356 @abstractmethod
357 def __rand__(self, other):
358 """other & self"""
359 raise NotImplementedError
360
361 @abstractmethod
362 def __xor__(self, other):
363 """self ^ other"""
364 raise NotImplementedError
365
366 @abstractmethod
367 def __rxor__(self, other):
368 """other ^ self"""
369 raise NotImplementedError
370
371 @abstractmethod
372 def __or__(self, other):
373 """self | other"""
374 raise NotImplementedError
375
376 @abstractmethod
377 def __ror__(self, other):
378 """other | self"""
379 raise NotImplementedError
380
381 @abstractmethod
382 def __invert__(self):
383 """~self"""
384 raise NotImplementedError
385
386 # Concrete implementations of Rational and Real abstract methods.
387 def __float__(self):
388 """float(self) == float(long(self))"""
389 return float(long(self))
390
391 @property
392 def numerator(self):
393 """Integers are their own numerators."""
394 return +self
395
396 @property
397 def denominator(self):
398 """Integers have a denominator of 1."""
399 return 1
400
401Integral.register(int)
402Integral.register(long)