blob: b8a5c36db941efd7808f6bd8903fb062975d3948 [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
Raymond Hettinger19a5c292008-02-12 00:48:20 +000052## Notes on Decimal and it how relates to the numeric tower
53## --------------------------------------------------------
Raymond Hettinger116f72f2008-02-12 01:18:03 +000054## Decimal is Real except that it does not support rich comparisons.
Raymond Hettinger48688d82008-02-11 22:53:01 +000055##
56## Decimal has some of the characteristics of Integrals. It provides
57## logical operations but not as operators. The logical operations only apply
58## to a subset of decimals (those that are non-negative, have a zero exponent,
59## and have digits that are only 0 or 1). It does provide __long__() and
60## a three argument form of __pow__ that includes exactness guarantees.
61## It does not provide an __index__() method.
62##
63## Depending on context, decimal operations may be exact or inexact.
64##
65## When decimal is run in a context with small precision and automatic rounding,
66## it is Inexact. See the "Floating point notes" section of the decimal docs
67## for an example of losing the associative and distributive properties of
68## addition.
69##
70## When decimal is used for high precision integer arithmetic, it is Exact.
71## When the decimal used as fixed-point, it is Exact.
72## When it is run with sufficient precision, it is Exact.
73## When the decimal.Inexact trap is set, decimal operations are Exact.
74## For an example, see the float_to_decimal() recipe in the "Decimal FAQ"
75## section of the docs -- it shows an how traps are used in conjunction
76## with variable precision to reliably achieve exact results.
77
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +000078class Complex(Number):
79 """Complex defines the operations that work on the builtin complex type.
80
81 In short, those are: a conversion to complex, .real, .imag, +, -,
82 *, /, abs(), .conjugate, ==, and !=.
83
84 If it is given heterogenous arguments, and doesn't have special
85 knowledge about them, it should fall back to the builtin complex
86 type as described below.
87 """
88
89 @abstractmethod
90 def __complex__(self):
91 """Return a builtin complex instance. Called for complex(self)."""
92
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000093 # Will be __bool__ in 3.0.
94 def __nonzero__(self):
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +000095 """True if self != 0. Called for bool(self)."""
96 return self != 0
97
98 @abstractproperty
99 def real(self):
100 """Retrieve the real component of this number.
101
102 This should subclass Real.
103 """
104 raise NotImplementedError
105
106 @abstractproperty
107 def imag(self):
108 """Retrieve the real component of this number.
109
110 This should subclass Real.
111 """
112 raise NotImplementedError
113
114 @abstractmethod
115 def __add__(self, other):
116 """self + other"""
117 raise NotImplementedError
118
119 @abstractmethod
120 def __radd__(self, other):
121 """other + self"""
122 raise NotImplementedError
123
124 @abstractmethod
125 def __neg__(self):
126 """-self"""
127 raise NotImplementedError
128
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000129 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000130 def __pos__(self):
131 """+self"""
132 raise NotImplementedError
133
134 def __sub__(self, other):
135 """self - other"""
136 return self + -other
137
138 def __rsub__(self, other):
139 """other - self"""
140 return -self + other
141
142 @abstractmethod
143 def __mul__(self, other):
144 """self * other"""
145 raise NotImplementedError
146
147 @abstractmethod
148 def __rmul__(self, other):
149 """other * self"""
150 raise NotImplementedError
151
152 @abstractmethod
153 def __div__(self, other):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000154 """self / other without __future__ division
155
156 May promote to float.
157 """
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000158 raise NotImplementedError
159
160 @abstractmethod
161 def __rdiv__(self, other):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000162 """other / self without __future__ division"""
163 raise NotImplementedError
164
165 @abstractmethod
166 def __truediv__(self, other):
167 """self / other with __future__ division.
168
169 Should promote to float when necessary.
170 """
171 raise NotImplementedError
172
173 @abstractmethod
174 def __rtruediv__(self, other):
175 """other / self with __future__ division"""
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000176 raise NotImplementedError
177
178 @abstractmethod
179 def __pow__(self, exponent):
180 """self**exponent; should promote to float or complex when necessary."""
181 raise NotImplementedError
182
183 @abstractmethod
184 def __rpow__(self, base):
185 """base ** self"""
186 raise NotImplementedError
187
188 @abstractmethod
189 def __abs__(self):
190 """Returns the Real distance from 0. Called for abs(self)."""
191 raise NotImplementedError
192
193 @abstractmethod
194 def conjugate(self):
195 """(x+y*i).conjugate() returns (x-y*i)."""
196 raise NotImplementedError
197
198 @abstractmethod
199 def __eq__(self, other):
200 """self == other"""
201 raise NotImplementedError
202
Jeffrey Yasskin27d33942008-02-08 06:45:40 +0000203 def __ne__(self, other):
204 """self != other"""
205 # The default __ne__ doesn't negate __eq__ until 3.0.
206 return not (self == other)
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000207
208Complex.register(complex)
209
210
211class Real(Complex):
212 """To Complex, Real adds the operations that work on real numbers.
213
214 In short, those are: a conversion to float, trunc(), divmod,
215 %, <, <=, >, and >=.
216
217 Real also provides defaults for the derived operations.
218 """
219
220 @abstractmethod
221 def __float__(self):
222 """Any Real can be converted to a native float object.
223
224 Called for float(self)."""
225 raise NotImplementedError
226
227 @abstractmethod
228 def __trunc__(self):
229 """trunc(self): Truncates self to an Integral.
230
231 Returns an Integral i such that:
232 * i>0 iff self>0;
233 * abs(i) <= abs(self);
234 * for any Integral j satisfying the first two conditions,
235 abs(i) >= abs(j) [i.e. i has "maximal" abs among those].
236 i.e. "truncate towards 0".
237 """
238 raise NotImplementedError
239
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000240 def __divmod__(self, other):
241 """divmod(self, other): The pair (self // other, self % other).
242
243 Sometimes this can be computed faster than the pair of
244 operations.
245 """
246 return (self // other, self % other)
247
248 def __rdivmod__(self, other):
249 """divmod(other, self): The pair (self // other, self % other).
250
251 Sometimes this can be computed faster than the pair of
252 operations.
253 """
254 return (other // self, other % self)
255
256 @abstractmethod
257 def __floordiv__(self, other):
258 """self // other: The floor() of self/other."""
259 raise NotImplementedError
260
261 @abstractmethod
262 def __rfloordiv__(self, other):
263 """other // self: The floor() of other/self."""
264 raise NotImplementedError
265
266 @abstractmethod
267 def __mod__(self, other):
268 """self % other"""
269 raise NotImplementedError
270
271 @abstractmethod
272 def __rmod__(self, other):
273 """other % self"""
274 raise NotImplementedError
275
276 @abstractmethod
277 def __lt__(self, other):
278 """self < other
279
280 < on Reals defines a total ordering, except perhaps for NaN."""
281 raise NotImplementedError
282
283 @abstractmethod
284 def __le__(self, other):
285 """self <= other"""
286 raise NotImplementedError
287
288 # Concrete implementations of Complex abstract methods.
289 def __complex__(self):
290 """complex(self) == complex(float(self), 0)"""
291 return complex(float(self))
292
293 @property
294 def real(self):
295 """Real numbers are their real component."""
296 return +self
297
298 @property
299 def imag(self):
300 """Real numbers have no imaginary component."""
301 return 0
302
303 def conjugate(self):
304 """Conjugate is a no-op for Reals."""
305 return +self
306
307Real.register(float)
308# Real.register(decimal.Decimal)
309
310
311class Rational(Real, Exact):
312 """.numerator and .denominator should be in lowest terms."""
313
314 @abstractproperty
315 def numerator(self):
316 raise NotImplementedError
317
318 @abstractproperty
319 def denominator(self):
320 raise NotImplementedError
321
322 # Concrete implementation of Real's conversion to float.
323 def __float__(self):
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000324 """float(self) = self.numerator / self.denominator
325
326 It's important that this conversion use the integer's "true"
327 division rather than casting one side to float before dividing
328 so that ratios of huge integers convert without overflowing.
329
330 """
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000331 return self.numerator / self.denominator
332
333
334class Integral(Rational):
335 """Integral adds a conversion to long and the bit-string operations."""
336
337 @abstractmethod
338 def __long__(self):
339 """long(self)"""
340 raise NotImplementedError
341
342 def __index__(self):
343 """index(self)"""
344 return long(self)
345
346 @abstractmethod
347 def __pow__(self, exponent, modulus=None):
348 """self ** exponent % modulus, but maybe faster.
349
350 Accept the modulus argument if you want to support the
351 3-argument version of pow(). Raise a TypeError if exponent < 0
352 or any argument isn't Integral. Otherwise, just implement the
353 2-argument version described in Complex.
354 """
355 raise NotImplementedError
356
357 @abstractmethod
358 def __lshift__(self, other):
359 """self << other"""
360 raise NotImplementedError
361
362 @abstractmethod
363 def __rlshift__(self, other):
364 """other << self"""
365 raise NotImplementedError
366
367 @abstractmethod
368 def __rshift__(self, other):
369 """self >> other"""
370 raise NotImplementedError
371
372 @abstractmethod
373 def __rrshift__(self, other):
374 """other >> self"""
375 raise NotImplementedError
376
377 @abstractmethod
378 def __and__(self, other):
379 """self & other"""
380 raise NotImplementedError
381
382 @abstractmethod
383 def __rand__(self, other):
384 """other & self"""
385 raise NotImplementedError
386
387 @abstractmethod
388 def __xor__(self, other):
389 """self ^ other"""
390 raise NotImplementedError
391
392 @abstractmethod
393 def __rxor__(self, other):
394 """other ^ self"""
395 raise NotImplementedError
396
397 @abstractmethod
398 def __or__(self, other):
399 """self | other"""
400 raise NotImplementedError
401
402 @abstractmethod
403 def __ror__(self, other):
404 """other | self"""
405 raise NotImplementedError
406
407 @abstractmethod
408 def __invert__(self):
409 """~self"""
410 raise NotImplementedError
411
412 # Concrete implementations of Rational and Real abstract methods.
413 def __float__(self):
414 """float(self) == float(long(self))"""
415 return float(long(self))
416
417 @property
418 def numerator(self):
419 """Integers are their own numerators."""
420 return +self
421
422 @property
423 def denominator(self):
424 """Integers have a denominator of 1."""
425 return 1
426
427Integral.register(int)
428Integral.register(long)