• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 __future__ import division
9from abc import ABCMeta, abstractmethod, abstractproperty
10
11__all__ = ["Number", "Complex", "Real", "Rational", "Integral"]
12
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
20    __slots__ = ()
21
22    # Concrete numeric types must provide their own hash implementation
23    __hash__ = None
24
25
26## 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
30## 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).
33
34class 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
45    __slots__ = ()
46
47    @abstractmethod
48    def __complex__(self):
49        """Return a builtin complex instance. Called for complex(self)."""
50
51    # Will be __bool__ in 3.0.
52    def __nonzero__(self):
53        """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 imaginary 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
87    @abstractmethod
88    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):
112        """self / other without __future__ division
113
114        May promote to float.
115        """
116        raise NotImplementedError
117
118    @abstractmethod
119    def __rdiv__(self, other):
120        """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"""
134        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
161    def __ne__(self, other):
162        """self != other"""
163        # The default __ne__ doesn't negate __eq__ until 3.0.
164        return not (self == other)
165
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
178    __slots__ = ()
179
180    @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
200    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)
268
269
270class Rational(Real):
271    """.numerator and .denominator should be in lowest terms."""
272
273    __slots__ = ()
274
275    @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):
285        """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        """
292        return self.numerator / self.denominator
293
294
295class Integral(Rational):
296    """Integral adds a conversion to long and the bit-string operations."""
297
298    __slots__ = ()
299
300    @abstractmethod
301    def __long__(self):
302        """long(self)"""
303        raise NotImplementedError
304
305    def __index__(self):
306        """Called whenever an index is needed, such as in slicing"""
307        return long(self)
308
309    @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
321    def __lshift__(self, other):
322        """self << other"""
323        raise NotImplementedError
324
325    @abstractmethod
326    def __rlshift__(self, other):
327        """other << self"""
328        raise NotImplementedError
329
330    @abstractmethod
331    def __rshift__(self, other):
332        """self >> other"""
333        raise NotImplementedError
334
335    @abstractmethod
336    def __rrshift__(self, other):
337        """other >> self"""
338        raise NotImplementedError
339
340    @abstractmethod
341    def __and__(self, other):
342        """self & other"""
343        raise NotImplementedError
344
345    @abstractmethod
346    def __rand__(self, other):
347        """other & self"""
348        raise NotImplementedError
349
350    @abstractmethod
351    def __xor__(self, other):
352        """self ^ other"""
353        raise NotImplementedError
354
355    @abstractmethod
356    def __rxor__(self, other):
357        """other ^ self"""
358        raise NotImplementedError
359
360    @abstractmethod
361    def __or__(self, other):
362        """self | other"""
363        raise NotImplementedError
364
365    @abstractmethod
366    def __ror__(self, other):
367        """other | self"""
368        raise NotImplementedError
369
370    @abstractmethod
371    def __invert__(self):
372        """~self"""
373        raise NotImplementedError
374
375    # Concrete implementations of Rational and Real abstract methods.
376    def __float__(self):
377        """float(self) == float(long(self))"""
378        return float(long(self))
379
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)
392