1 # 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
6 TODO: Fill out more detailed documentation on the operators."""
7
8 from abc import ABCMeta, abstractmethod
9
10 __all__ = ["Number", "Complex", "Real", "Rational", "Integral"]
11
12 class ESC[4;38;5;81mNumber(metaclass=ESC[4;38;5;149mABCMeta):
13 """All numbers inherit from this class.
14
15 If you just want to check if an argument x is a number, without
16 caring what kind, use isinstance(x, Number).
17 """
18 __slots__ = ()
19
20 # Concrete numeric types must provide their own hash implementation
21 __hash__ = None
22
23
24 ## Notes on Decimal
25 ## ----------------
26 ## Decimal has all of the methods specified by the Real abc, but it should
27 ## not be registered as a Real because decimals do not interoperate with
28 ## binary floats (i.e. Decimal('3.14') + 2.71828 is undefined). But,
29 ## abstract reals are expected to interoperate (i.e. R1 + R2 should be
30 ## expected to work if R1 and R2 are both Reals).
31
32 class ESC[4;38;5;81mComplex(ESC[4;38;5;149mNumber):
33 """Complex defines the operations that work on the builtin complex type.
34
35 In short, those are: a conversion to complex, .real, .imag, +, -,
36 *, /, **, abs(), .conjugate, ==, and !=.
37
38 If it is given heterogeneous arguments, and doesn't have special
39 knowledge about them, it should fall back to the builtin complex
40 type as described below.
41 """
42
43 __slots__ = ()
44
45 @abstractmethod
46 def __complex__(self):
47 """Return a builtin complex instance. Called for complex(self)."""
48
49 def __bool__(self):
50 """True if self != 0. Called for bool(self)."""
51 return self != 0
52
53 @property
54 @abstractmethod
55 def real(self):
56 """Retrieve the real component of this number.
57
58 This should subclass Real.
59 """
60 raise NotImplementedError
61
62 @property
63 @abstractmethod
64 def imag(self):
65 """Retrieve the imaginary component of this number.
66
67 This should subclass Real.
68 """
69 raise NotImplementedError
70
71 @abstractmethod
72 def __add__(self, other):
73 """self + other"""
74 raise NotImplementedError
75
76 @abstractmethod
77 def __radd__(self, other):
78 """other + self"""
79 raise NotImplementedError
80
81 @abstractmethod
82 def __neg__(self):
83 """-self"""
84 raise NotImplementedError
85
86 @abstractmethod
87 def __pos__(self):
88 """+self"""
89 raise NotImplementedError
90
91 def __sub__(self, other):
92 """self - other"""
93 return self + -other
94
95 def __rsub__(self, other):
96 """other - self"""
97 return -self + other
98
99 @abstractmethod
100 def __mul__(self, other):
101 """self * other"""
102 raise NotImplementedError
103
104 @abstractmethod
105 def __rmul__(self, other):
106 """other * self"""
107 raise NotImplementedError
108
109 @abstractmethod
110 def __truediv__(self, other):
111 """self / other: Should promote to float when necessary."""
112 raise NotImplementedError
113
114 @abstractmethod
115 def __rtruediv__(self, other):
116 """other / self"""
117 raise NotImplementedError
118
119 @abstractmethod
120 def __pow__(self, exponent):
121 """self**exponent; should promote to float or complex when necessary."""
122 raise NotImplementedError
123
124 @abstractmethod
125 def __rpow__(self, base):
126 """base ** self"""
127 raise NotImplementedError
128
129 @abstractmethod
130 def __abs__(self):
131 """Returns the Real distance from 0. Called for abs(self)."""
132 raise NotImplementedError
133
134 @abstractmethod
135 def conjugate(self):
136 """(x+y*i).conjugate() returns (x-y*i)."""
137 raise NotImplementedError
138
139 @abstractmethod
140 def __eq__(self, other):
141 """self == other"""
142 raise NotImplementedError
143
144 Complex.register(complex)
145
146
147 class ESC[4;38;5;81mReal(ESC[4;38;5;149mComplex):
148 """To Complex, Real adds the operations that work on real numbers.
149
150 In short, those are: a conversion to float, trunc(), divmod,
151 %, <, <=, >, and >=.
152
153 Real also provides defaults for the derived operations.
154 """
155
156 __slots__ = ()
157
158 @abstractmethod
159 def __float__(self):
160 """Any Real can be converted to a native float object.
161
162 Called for float(self)."""
163 raise NotImplementedError
164
165 @abstractmethod
166 def __trunc__(self):
167 """trunc(self): Truncates self to an Integral.
168
169 Returns an Integral i such that:
170 * i>0 iff self>0;
171 * abs(i) <= abs(self);
172 * for any Integral j satisfying the first two conditions,
173 abs(i) >= abs(j) [i.e. i has "maximal" abs among those].
174 i.e. "truncate towards 0".
175 """
176 raise NotImplementedError
177
178 @abstractmethod
179 def __floor__(self):
180 """Finds the greatest Integral <= self."""
181 raise NotImplementedError
182
183 @abstractmethod
184 def __ceil__(self):
185 """Finds the least Integral >= self."""
186 raise NotImplementedError
187
188 @abstractmethod
189 def __round__(self, ndigits=None):
190 """Rounds self to ndigits decimal places, defaulting to 0.
191
192 If ndigits is omitted or None, returns an Integral, otherwise
193 returns a Real. Rounds half toward even.
194 """
195 raise NotImplementedError
196
197 def __divmod__(self, other):
198 """divmod(self, other): The pair (self // other, self % other).
199
200 Sometimes this can be computed faster than the pair of
201 operations.
202 """
203 return (self // other, self % other)
204
205 def __rdivmod__(self, other):
206 """divmod(other, self): The pair (self // other, self % other).
207
208 Sometimes this can be computed faster than the pair of
209 operations.
210 """
211 return (other // self, other % self)
212
213 @abstractmethod
214 def __floordiv__(self, other):
215 """self // other: The floor() of self/other."""
216 raise NotImplementedError
217
218 @abstractmethod
219 def __rfloordiv__(self, other):
220 """other // self: The floor() of other/self."""
221 raise NotImplementedError
222
223 @abstractmethod
224 def __mod__(self, other):
225 """self % other"""
226 raise NotImplementedError
227
228 @abstractmethod
229 def __rmod__(self, other):
230 """other % self"""
231 raise NotImplementedError
232
233 @abstractmethod
234 def __lt__(self, other):
235 """self < other
236
237 < on Reals defines a total ordering, except perhaps for NaN."""
238 raise NotImplementedError
239
240 @abstractmethod
241 def __le__(self, other):
242 """self <= other"""
243 raise NotImplementedError
244
245 # Concrete implementations of Complex abstract methods.
246 def __complex__(self):
247 """complex(self) == complex(float(self), 0)"""
248 return complex(float(self))
249
250 @property
251 def real(self):
252 """Real numbers are their real component."""
253 return +self
254
255 @property
256 def imag(self):
257 """Real numbers have no imaginary component."""
258 return 0
259
260 def conjugate(self):
261 """Conjugate is a no-op for Reals."""
262 return +self
263
264 Real.register(float)
265
266
267 class ESC[4;38;5;81mRational(ESC[4;38;5;149mReal):
268 """.numerator and .denominator should be in lowest terms."""
269
270 __slots__ = ()
271
272 @property
273 @abstractmethod
274 def numerator(self):
275 raise NotImplementedError
276
277 @property
278 @abstractmethod
279 def denominator(self):
280 raise NotImplementedError
281
282 # Concrete implementation of Real's conversion to float.
283 def __float__(self):
284 """float(self) = self.numerator / self.denominator
285
286 It's important that this conversion use the integer's "true"
287 division rather than casting one side to float before dividing
288 so that ratios of huge integers convert without overflowing.
289
290 """
291 return int(self.numerator) / int(self.denominator)
292
293
294 class ESC[4;38;5;81mIntegral(ESC[4;38;5;149mRational):
295 """Integral adds methods that work on integral numbers.
296
297 In short, these are conversion to int, pow with modulus, and the
298 bit-string operations.
299 """
300
301 __slots__ = ()
302
303 @abstractmethod
304 def __int__(self):
305 """int(self)"""
306 raise NotImplementedError
307
308 def __index__(self):
309 """Called whenever an index is needed, such as in slicing"""
310 return int(self)
311
312 @abstractmethod
313 def __pow__(self, exponent, modulus=None):
314 """self ** exponent % modulus, but maybe faster.
315
316 Accept the modulus argument if you want to support the
317 3-argument version of pow(). Raise a TypeError if exponent < 0
318 or any argument isn't Integral. Otherwise, just implement the
319 2-argument version described in Complex.
320 """
321 raise NotImplementedError
322
323 @abstractmethod
324 def __lshift__(self, other):
325 """self << other"""
326 raise NotImplementedError
327
328 @abstractmethod
329 def __rlshift__(self, other):
330 """other << self"""
331 raise NotImplementedError
332
333 @abstractmethod
334 def __rshift__(self, other):
335 """self >> other"""
336 raise NotImplementedError
337
338 @abstractmethod
339 def __rrshift__(self, other):
340 """other >> self"""
341 raise NotImplementedError
342
343 @abstractmethod
344 def __and__(self, other):
345 """self & other"""
346 raise NotImplementedError
347
348 @abstractmethod
349 def __rand__(self, other):
350 """other & self"""
351 raise NotImplementedError
352
353 @abstractmethod
354 def __xor__(self, other):
355 """self ^ other"""
356 raise NotImplementedError
357
358 @abstractmethod
359 def __rxor__(self, other):
360 """other ^ self"""
361 raise NotImplementedError
362
363 @abstractmethod
364 def __or__(self, other):
365 """self | other"""
366 raise NotImplementedError
367
368 @abstractmethod
369 def __ror__(self, other):
370 """other | self"""
371 raise NotImplementedError
372
373 @abstractmethod
374 def __invert__(self):
375 """~self"""
376 raise NotImplementedError
377
378 # Concrete implementations of Rational and Real abstract methods.
379 def __float__(self):
380 """float(self) == float(int(self))"""
381 return float(int(self))
382
383 @property
384 def numerator(self):
385 """Integers are their own numerators."""
386 return +self
387
388 @property
389 def denominator(self):
390 """Integers have a denominator of 1."""
391 return 1
392
393 Integral.register(int)