blob: e391abc387ad33c14203bbcc9ccd2e647492e698 [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
177 # __ne__ is inherited from object and negates whatever __eq__ does.
178
179Complex.register(complex)
180
181
182class Real(Complex):
183 """To Complex, Real adds the operations that work on real numbers.
184
185 In short, those are: a conversion to float, trunc(), divmod,
186 %, <, <=, >, and >=.
187
188 Real also provides defaults for the derived operations.
189 """
190
191 @abstractmethod
192 def __float__(self):
193 """Any Real can be converted to a native float object.
194
195 Called for float(self)."""
196 raise NotImplementedError
197
198 @abstractmethod
199 def __trunc__(self):
200 """trunc(self): Truncates self to an Integral.
201
202 Returns an Integral i such that:
203 * i>0 iff self>0;
204 * abs(i) <= abs(self);
205 * for any Integral j satisfying the first two conditions,
206 abs(i) >= abs(j) [i.e. i has "maximal" abs among those].
207 i.e. "truncate towards 0".
208 """
209 raise NotImplementedError
210
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000211 def __divmod__(self, other):
212 """divmod(self, other): The pair (self // other, self % other).
213
214 Sometimes this can be computed faster than the pair of
215 operations.
216 """
217 return (self // other, self % other)
218
219 def __rdivmod__(self, other):
220 """divmod(other, self): The pair (self // other, self % other).
221
222 Sometimes this can be computed faster than the pair of
223 operations.
224 """
225 return (other // self, other % self)
226
227 @abstractmethod
228 def __floordiv__(self, other):
229 """self // other: The floor() of self/other."""
230 raise NotImplementedError
231
232 @abstractmethod
233 def __rfloordiv__(self, other):
234 """other // self: The floor() of other/self."""
235 raise NotImplementedError
236
237 @abstractmethod
238 def __mod__(self, other):
239 """self % other"""
240 raise NotImplementedError
241
242 @abstractmethod
243 def __rmod__(self, other):
244 """other % self"""
245 raise NotImplementedError
246
247 @abstractmethod
248 def __lt__(self, other):
249 """self < other
250
251 < on Reals defines a total ordering, except perhaps for NaN."""
252 raise NotImplementedError
253
254 @abstractmethod
255 def __le__(self, other):
256 """self <= other"""
257 raise NotImplementedError
258
259 # Concrete implementations of Complex abstract methods.
260 def __complex__(self):
261 """complex(self) == complex(float(self), 0)"""
262 return complex(float(self))
263
264 @property
265 def real(self):
266 """Real numbers are their real component."""
267 return +self
268
269 @property
270 def imag(self):
271 """Real numbers have no imaginary component."""
272 return 0
273
274 def conjugate(self):
275 """Conjugate is a no-op for Reals."""
276 return +self
277
278Real.register(float)
279# Real.register(decimal.Decimal)
280
281
282class Rational(Real, Exact):
283 """.numerator and .denominator should be in lowest terms."""
284
285 @abstractproperty
286 def numerator(self):
287 raise NotImplementedError
288
289 @abstractproperty
290 def denominator(self):
291 raise NotImplementedError
292
293 # Concrete implementation of Real's conversion to float.
294 def __float__(self):
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000295 """float(self) = self.numerator / self.denominator
296
297 It's important that this conversion use the integer's "true"
298 division rather than casting one side to float before dividing
299 so that ratios of huge integers convert without overflowing.
300
301 """
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000302 return self.numerator / self.denominator
303
304
305class Integral(Rational):
306 """Integral adds a conversion to long and the bit-string operations."""
307
308 @abstractmethod
309 def __long__(self):
310 """long(self)"""
311 raise NotImplementedError
312
313 def __index__(self):
314 """index(self)"""
315 return long(self)
316
317 @abstractmethod
318 def __pow__(self, exponent, modulus=None):
319 """self ** exponent % modulus, but maybe faster.
320
321 Accept the modulus argument if you want to support the
322 3-argument version of pow(). Raise a TypeError if exponent < 0
323 or any argument isn't Integral. Otherwise, just implement the
324 2-argument version described in Complex.
325 """
326 raise NotImplementedError
327
328 @abstractmethod
329 def __lshift__(self, other):
330 """self << other"""
331 raise NotImplementedError
332
333 @abstractmethod
334 def __rlshift__(self, other):
335 """other << self"""
336 raise NotImplementedError
337
338 @abstractmethod
339 def __rshift__(self, other):
340 """self >> other"""
341 raise NotImplementedError
342
343 @abstractmethod
344 def __rrshift__(self, other):
345 """other >> self"""
346 raise NotImplementedError
347
348 @abstractmethod
349 def __and__(self, other):
350 """self & other"""
351 raise NotImplementedError
352
353 @abstractmethod
354 def __rand__(self, other):
355 """other & self"""
356 raise NotImplementedError
357
358 @abstractmethod
359 def __xor__(self, other):
360 """self ^ other"""
361 raise NotImplementedError
362
363 @abstractmethod
364 def __rxor__(self, other):
365 """other ^ self"""
366 raise NotImplementedError
367
368 @abstractmethod
369 def __or__(self, other):
370 """self | other"""
371 raise NotImplementedError
372
373 @abstractmethod
374 def __ror__(self, other):
375 """other | self"""
376 raise NotImplementedError
377
378 @abstractmethod
379 def __invert__(self):
380 """~self"""
381 raise NotImplementedError
382
383 # Concrete implementations of Rational and Real abstract methods.
384 def __float__(self):
385 """float(self) == float(long(self))"""
386 return float(long(self))
387
388 @property
389 def numerator(self):
390 """Integers are their own numerators."""
391 return +self
392
393 @property
394 def denominator(self):
395 """Integers have a denominator of 1."""
396 return 1
397
398Integral.register(int)
399Integral.register(long)