blob: 540e7d59107a17fa84f9acfd687f7bf49dbd55d2 [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
Raymond Hettinger933d3a72009-01-20 20:34:19 +000020 __slots__ = ()
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +000021
Nick Coghlan48361f52008-08-11 15:45:58 +000022 # Concrete numeric types must provide their own hash implementation
23 __hash__ = None
24
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +000025
Raymond Hettingerddb164a2008-02-14 01:08:02 +000026## Notes on Decimal
27## ----------------
28## Decimal has all of the methods specified by the Real abc, but it should
29## not be registered as a Real because decimals do not interoperate with
Raymond Hettinger6b467622008-03-15 20:02:04 +000030## binary floats (i.e. Decimal('3.14') + 2.71828 is undefined). But,
31## abstract reals are expected to interoperate (i.e. R1 + R2 should be
32## expected to work if R1 and R2 are both Reals).
Raymond Hettinger48688d82008-02-11 22:53:01 +000033
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +000034class Complex(Number):
35 """Complex defines the operations that work on the builtin complex type.
36
37 In short, those are: a conversion to complex, .real, .imag, +, -,
38 *, /, abs(), .conjugate, ==, and !=.
39
40 If it is given heterogenous arguments, and doesn't have special
41 knowledge about them, it should fall back to the builtin complex
42 type as described below.
43 """
44
Raymond Hettinger933d3a72009-01-20 20:34:19 +000045 __slots__ = ()
46
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +000047 @abstractmethod
48 def __complex__(self):
49 """Return a builtin complex instance. Called for complex(self)."""
50
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000051 # Will be __bool__ in 3.0.
52 def __nonzero__(self):
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +000053 """True if self != 0. Called for bool(self)."""
54 return self != 0
55
56 @abstractproperty
57 def real(self):
58 """Retrieve the real component of this number.
59
60 This should subclass Real.
61 """
62 raise NotImplementedError
63
64 @abstractproperty
65 def imag(self):
66 """Retrieve the real component of this number.
67
68 This should subclass Real.
69 """
70 raise NotImplementedError
71
72 @abstractmethod
73 def __add__(self, other):
74 """self + other"""
75 raise NotImplementedError
76
77 @abstractmethod
78 def __radd__(self, other):
79 """other + self"""
80 raise NotImplementedError
81
82 @abstractmethod
83 def __neg__(self):
84 """-self"""
85 raise NotImplementedError
86
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000087 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +000088 def __pos__(self):
89 """+self"""
90 raise NotImplementedError
91
92 def __sub__(self, other):
93 """self - other"""
94 return self + -other
95
96 def __rsub__(self, other):
97 """other - self"""
98 return -self + other
99
100 @abstractmethod
101 def __mul__(self, other):
102 """self * other"""
103 raise NotImplementedError
104
105 @abstractmethod
106 def __rmul__(self, other):
107 """other * self"""
108 raise NotImplementedError
109
110 @abstractmethod
111 def __div__(self, other):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000112 """self / other without __future__ division
113
114 May promote to float.
115 """
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000116 raise NotImplementedError
117
118 @abstractmethod
119 def __rdiv__(self, other):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000120 """other / self without __future__ division"""
121 raise NotImplementedError
122
123 @abstractmethod
124 def __truediv__(self, other):
125 """self / other with __future__ division.
126
127 Should promote to float when necessary.
128 """
129 raise NotImplementedError
130
131 @abstractmethod
132 def __rtruediv__(self, other):
133 """other / self with __future__ division"""
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000134 raise NotImplementedError
135
136 @abstractmethod
137 def __pow__(self, exponent):
138 """self**exponent; should promote to float or complex when necessary."""
139 raise NotImplementedError
140
141 @abstractmethod
142 def __rpow__(self, base):
143 """base ** self"""
144 raise NotImplementedError
145
146 @abstractmethod
147 def __abs__(self):
148 """Returns the Real distance from 0. Called for abs(self)."""
149 raise NotImplementedError
150
151 @abstractmethod
152 def conjugate(self):
153 """(x+y*i).conjugate() returns (x-y*i)."""
154 raise NotImplementedError
155
156 @abstractmethod
157 def __eq__(self, other):
158 """self == other"""
159 raise NotImplementedError
160
Jeffrey Yasskin27d33942008-02-08 06:45:40 +0000161 def __ne__(self, other):
162 """self != other"""
163 # The default __ne__ doesn't negate __eq__ until 3.0.
164 return not (self == other)
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000165
166Complex.register(complex)
167
168
169class Real(Complex):
170 """To Complex, Real adds the operations that work on real numbers.
171
172 In short, those are: a conversion to float, trunc(), divmod,
173 %, <, <=, >, and >=.
174
175 Real also provides defaults for the derived operations.
176 """
177
Raymond Hettinger933d3a72009-01-20 20:34:19 +0000178 __slots__ = ()
179
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000180 @abstractmethod
181 def __float__(self):
182 """Any Real can be converted to a native float object.
183
184 Called for float(self)."""
185 raise NotImplementedError
186
187 @abstractmethod
188 def __trunc__(self):
189 """trunc(self): Truncates self to an Integral.
190
191 Returns an Integral i such that:
192 * i>0 iff self>0;
193 * abs(i) <= abs(self);
194 * for any Integral j satisfying the first two conditions,
195 abs(i) >= abs(j) [i.e. i has "maximal" abs among those].
196 i.e. "truncate towards 0".
197 """
198 raise NotImplementedError
199
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000200 def __divmod__(self, other):
201 """divmod(self, other): The pair (self // other, self % other).
202
203 Sometimes this can be computed faster than the pair of
204 operations.
205 """
206 return (self // other, self % other)
207
208 def __rdivmod__(self, other):
209 """divmod(other, self): The pair (self // other, self % other).
210
211 Sometimes this can be computed faster than the pair of
212 operations.
213 """
214 return (other // self, other % self)
215
216 @abstractmethod
217 def __floordiv__(self, other):
218 """self // other: The floor() of self/other."""
219 raise NotImplementedError
220
221 @abstractmethod
222 def __rfloordiv__(self, other):
223 """other // self: The floor() of other/self."""
224 raise NotImplementedError
225
226 @abstractmethod
227 def __mod__(self, other):
228 """self % other"""
229 raise NotImplementedError
230
231 @abstractmethod
232 def __rmod__(self, other):
233 """other % self"""
234 raise NotImplementedError
235
236 @abstractmethod
237 def __lt__(self, other):
238 """self < other
239
240 < on Reals defines a total ordering, except perhaps for NaN."""
241 raise NotImplementedError
242
243 @abstractmethod
244 def __le__(self, other):
245 """self <= other"""
246 raise NotImplementedError
247
248 # Concrete implementations of Complex abstract methods.
249 def __complex__(self):
250 """complex(self) == complex(float(self), 0)"""
251 return complex(float(self))
252
253 @property
254 def real(self):
255 """Real numbers are their real component."""
256 return +self
257
258 @property
259 def imag(self):
260 """Real numbers have no imaginary component."""
261 return 0
262
263 def conjugate(self):
264 """Conjugate is a no-op for Reals."""
265 return +self
266
267Real.register(float)
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000268
269
Raymond Hettingercd6bfab2008-03-15 20:37:50 +0000270class Rational(Real):
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000271 """.numerator and .denominator should be in lowest terms."""
272
Raymond Hettinger933d3a72009-01-20 20:34:19 +0000273 __slots__ = ()
274
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000275 @abstractproperty
276 def numerator(self):
277 raise NotImplementedError
278
279 @abstractproperty
280 def denominator(self):
281 raise NotImplementedError
282
283 # Concrete implementation of Real's conversion to float.
284 def __float__(self):
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000285 """float(self) = self.numerator / self.denominator
286
287 It's important that this conversion use the integer's "true"
288 division rather than casting one side to float before dividing
289 so that ratios of huge integers convert without overflowing.
290
291 """
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000292 return self.numerator / self.denominator
293
294
295class Integral(Rational):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000296 """Integral adds a conversion to long and the bit-string operations."""
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000297
Raymond Hettinger933d3a72009-01-20 20:34:19 +0000298 __slots__ = ()
299
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000300 @abstractmethod
Guido van Rossum21a45e12008-06-17 17:38:02 +0000301 def __long__(self):
302 """long(self)"""
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000303 raise NotImplementedError
304
305 def __index__(self):
306 """index(self)"""
Guido van Rossum21a45e12008-06-17 17:38:02 +0000307 return long(self)
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000308
Guido van Rossum21a45e12008-06-17 17:38:02 +0000309 @abstractmethod
310 def __pow__(self, exponent, modulus=None):
311 """self ** exponent % modulus, but maybe faster.
312
313 Accept the modulus argument if you want to support the
314 3-argument version of pow(). Raise a TypeError if exponent < 0
315 or any argument isn't Integral. Otherwise, just implement the
316 2-argument version described in Complex.
317 """
318 raise NotImplementedError
319
320 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000321 def __lshift__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000322 """self << other"""
323 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000324
Guido van Rossum21a45e12008-06-17 17:38:02 +0000325 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000326 def __rlshift__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000327 """other << self"""
328 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000329
Guido van Rossum21a45e12008-06-17 17:38:02 +0000330 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000331 def __rshift__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000332 """self >> other"""
333 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000334
Guido van Rossum21a45e12008-06-17 17:38:02 +0000335 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000336 def __rrshift__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000337 """other >> self"""
338 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000339
Guido van Rossum21a45e12008-06-17 17:38:02 +0000340 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000341 def __and__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000342 """self & other"""
343 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000344
Guido van Rossum21a45e12008-06-17 17:38:02 +0000345 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000346 def __rand__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000347 """other & self"""
348 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000349
Guido van Rossum21a45e12008-06-17 17:38:02 +0000350 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000351 def __xor__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000352 """self ^ other"""
353 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000354
Guido van Rossum21a45e12008-06-17 17:38:02 +0000355 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000356 def __rxor__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000357 """other ^ self"""
358 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000359
Guido van Rossum21a45e12008-06-17 17:38:02 +0000360 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000361 def __or__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000362 """self | other"""
363 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000364
Guido van Rossum21a45e12008-06-17 17:38:02 +0000365 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000366 def __ror__(self, other):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000367 """other | self"""
368 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000369
Guido van Rossum21a45e12008-06-17 17:38:02 +0000370 @abstractmethod
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000371 def __invert__(self):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000372 """~self"""
373 raise NotImplementedError
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000374
375 # Concrete implementations of Rational and Real abstract methods.
376 def __float__(self):
Guido van Rossum21a45e12008-06-17 17:38:02 +0000377 """float(self) == float(long(self))"""
378 return float(long(self))
Jeffrey Yasskin2f3c16b2008-01-03 02:21:52 +0000379
380 @property
381 def numerator(self):
382 """Integers are their own numerators."""
383 return +self
384
385 @property
386 def denominator(self):
387 """Integers have a denominator of 1."""
388 return 1
389
390Integral.register(int)
391Integral.register(long)