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
6TODO: Fill out more detailed documentation on the operators."""
7
8from abc import ABCMeta, abstractmethod
9
10__all__ = ["Number", "Complex", "Real", "Rational", "Integral"]
11
12class Number(metaclass=ABCMeta):
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
32class Complex(Number):
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 heterogenous 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
144Complex.register(complex)
145
146
147class Real(Complex):
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
264Real.register(float)
265
266
267class Rational(Real):
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 self.numerator / self.denominator
292
293
294class Integral(Rational):
295    """Integral adds a conversion to int and the bit-string operations."""
296
297    __slots__ = ()
298
299    @abstractmethod
300    def __int__(self):
301        """int(self)"""
302        raise NotImplementedError
303
304    def __index__(self):
305        """Called whenever an index is needed, such as in slicing"""
306        return int(self)
307
308    @abstractmethod
309    def __pow__(self, exponent, modulus=None):
310        """self ** exponent % modulus, but maybe faster.
311
312        Accept the modulus argument if you want to support the
313        3-argument version of pow(). Raise a TypeError if exponent < 0
314        or any argument isn't Integral. Otherwise, just implement the
315        2-argument version described in Complex.
316        """
317        raise NotImplementedError
318
319    @abstractmethod
320    def __lshift__(self, other):
321        """self << other"""
322        raise NotImplementedError
323
324    @abstractmethod
325    def __rlshift__(self, other):
326        """other << self"""
327        raise NotImplementedError
328
329    @abstractmethod
330    def __rshift__(self, other):
331        """self >> other"""
332        raise NotImplementedError
333
334    @abstractmethod
335    def __rrshift__(self, other):
336        """other >> self"""
337        raise NotImplementedError
338
339    @abstractmethod
340    def __and__(self, other):
341        """self & other"""
342        raise NotImplementedError
343
344    @abstractmethod
345    def __rand__(self, other):
346        """other & self"""
347        raise NotImplementedError
348
349    @abstractmethod
350    def __xor__(self, other):
351        """self ^ other"""
352        raise NotImplementedError
353
354    @abstractmethod
355    def __rxor__(self, other):
356        """other ^ self"""
357        raise NotImplementedError
358
359    @abstractmethod
360    def __or__(self, other):
361        """self | other"""
362        raise NotImplementedError
363
364    @abstractmethod
365    def __ror__(self, other):
366        """other | self"""
367        raise NotImplementedError
368
369    @abstractmethod
370    def __invert__(self):
371        """~self"""
372        raise NotImplementedError
373
374    # Concrete implementations of Rational and Real abstract methods.
375    def __float__(self):
376        """float(self) == float(int(self))"""
377        return float(int(self))
378
379    @property
380    def numerator(self):
381        """Integers are their own numerators."""
382        return +self
383
384    @property
385    def denominator(self):
386        """Integers have a denominator of 1."""
387        return 1
388
389Integral.register(int)
390