Fix the tag.
[python/dscho.git] / Lib / numbers.py
blobc72a23df39fd14ba3b8fc6b8c1a532c2f6dc6753
1 # Copyright 2007 Google, Inc. All Rights Reserved.
2 # Licensed to PSF under a Contributor Agreement.
4 """Abstract Base Classes (ABCs) for numbers, according to PEP 3141.
6 TODO: Fill out more detailed documentation on the operators."""
8 from abc import ABCMeta, abstractmethod, abstractproperty
10 __all__ = ["Number", "Complex", "Real", "Rational", "Integral"]
12 class Number(metaclass=ABCMeta):
13 """All numbers inherit from this class.
15 If you just want to check if an argument x is a number, without
16 caring what kind, use isinstance(x, Number).
17 """
20 ## Notes on Decimal
21 ## ----------------
22 ## Decimal has all of the methods specified by the Real abc, but it should
23 ## not be registered as a Real because decimals do not interoperate with
24 ## binary floats (i.e. Decimal('3.14') + 2.71828 is undefined). But,
25 ## abstract reals are expected to interoperate (i.e. R1 + R2 should be
26 ## expected to work if R1 and R2 are both Reals).
28 class Complex(Number):
29 """Complex defines the operations that work on the builtin complex type.
31 In short, those are: a conversion to complex, .real, .imag, +, -,
32 *, /, abs(), .conjugate, ==, and !=.
34 If it is given heterogenous arguments, and doesn't have special
35 knowledge about them, it should fall back to the builtin complex
36 type as described below.
37 """
39 @abstractmethod
40 def __complex__(self):
41 """Return a builtin complex instance. Called for complex(self)."""
43 def __bool__(self):
44 """True if self != 0. Called for bool(self)."""
45 return self != 0
47 @abstractproperty
48 def real(self):
49 """Retrieve the real component of this number.
51 This should subclass Real.
52 """
53 raise NotImplementedError
55 @abstractproperty
56 def imag(self):
57 """Retrieve the real component of this number.
59 This should subclass Real.
60 """
61 raise NotImplementedError
63 @abstractmethod
64 def __add__(self, other):
65 """self + other"""
66 raise NotImplementedError
68 @abstractmethod
69 def __radd__(self, other):
70 """other + self"""
71 raise NotImplementedError
73 @abstractmethod
74 def __neg__(self):
75 """-self"""
76 raise NotImplementedError
78 @abstractmethod
79 def __pos__(self):
80 """+self"""
81 raise NotImplementedError
83 def __sub__(self, other):
84 """self - other"""
85 return self + -other
87 def __rsub__(self, other):
88 """other - self"""
89 return -self + other
91 @abstractmethod
92 def __mul__(self, other):
93 """self * other"""
94 raise NotImplementedError
96 @abstractmethod
97 def __rmul__(self, other):
98 """other * self"""
99 raise NotImplementedError
101 @abstractmethod
102 def __truediv__(self, other):
103 """self / other: Should promote to float when necessary."""
104 raise NotImplementedError
106 @abstractmethod
107 def __rtruediv__(self, other):
108 """other / self"""
109 raise NotImplementedError
111 @abstractmethod
112 def __pow__(self, exponent):
113 """self**exponent; should promote to float or complex when necessary."""
114 raise NotImplementedError
116 @abstractmethod
117 def __rpow__(self, base):
118 """base ** self"""
119 raise NotImplementedError
121 @abstractmethod
122 def __abs__(self):
123 """Returns the Real distance from 0. Called for abs(self)."""
124 raise NotImplementedError
126 @abstractmethod
127 def conjugate(self):
128 """(x+y*i).conjugate() returns (x-y*i)."""
129 raise NotImplementedError
131 @abstractmethod
132 def __eq__(self, other):
133 """self == other"""
134 raise NotImplementedError
136 def __ne__(self, other):
137 """self != other"""
138 # The default __ne__ doesn't negate __eq__ until 3.0.
139 return not (self == other)
141 Complex.register(complex)
144 class Real(Complex):
145 """To Complex, Real adds the operations that work on real numbers.
147 In short, those are: a conversion to float, trunc(), divmod,
148 %, <, <=, >, and >=.
150 Real also provides defaults for the derived operations.
153 @abstractmethod
154 def __float__(self):
155 """Any Real can be converted to a native float object.
157 Called for float(self)."""
158 raise NotImplementedError
160 @abstractmethod
161 def __trunc__(self):
162 """trunc(self): Truncates self to an Integral.
164 Returns an Integral i such that:
165 * i>0 iff self>0;
166 * abs(i) <= abs(self);
167 * for any Integral j satisfying the first two conditions,
168 abs(i) >= abs(j) [i.e. i has "maximal" abs among those].
169 i.e. "truncate towards 0".
171 raise NotImplementedError
173 @abstractmethod
174 def __floor__(self):
175 """Finds the greatest Integral <= self."""
176 raise NotImplementedError
178 @abstractmethod
179 def __ceil__(self):
180 """Finds the least Integral >= self."""
181 raise NotImplementedError
183 @abstractmethod
184 def __round__(self, ndigits:"Integral"=None):
185 """Rounds self to ndigits decimal places, defaulting to 0.
187 If ndigits is omitted or None, returns an Integral, otherwise
188 returns a Real. Rounds half toward even.
190 raise NotImplementedError
192 def __divmod__(self, other):
193 """divmod(self, other): The pair (self // other, self % other).
195 Sometimes this can be computed faster than the pair of
196 operations.
198 return (self // other, self % other)
200 def __rdivmod__(self, other):
201 """divmod(other, self): The pair (self // other, self % other).
203 Sometimes this can be computed faster than the pair of
204 operations.
206 return (other // self, other % self)
208 @abstractmethod
209 def __floordiv__(self, other):
210 """self // other: The floor() of self/other."""
211 raise NotImplementedError
213 @abstractmethod
214 def __rfloordiv__(self, other):
215 """other // self: The floor() of other/self."""
216 raise NotImplementedError
218 @abstractmethod
219 def __mod__(self, other):
220 """self % other"""
221 raise NotImplementedError
223 @abstractmethod
224 def __rmod__(self, other):
225 """other % self"""
226 raise NotImplementedError
228 @abstractmethod
229 def __lt__(self, other):
230 """self < other
232 < on Reals defines a total ordering, except perhaps for NaN."""
233 raise NotImplementedError
235 @abstractmethod
236 def __le__(self, other):
237 """self <= other"""
238 raise NotImplementedError
240 # Concrete implementations of Complex abstract methods.
241 def __complex__(self):
242 """complex(self) == complex(float(self), 0)"""
243 return complex(float(self))
245 @property
246 def real(self):
247 """Real numbers are their real component."""
248 return +self
250 @property
251 def imag(self):
252 """Real numbers have no imaginary component."""
253 return 0
255 def conjugate(self):
256 """Conjugate is a no-op for Reals."""
257 return +self
259 Real.register(float)
262 class Rational(Real):
263 """.numerator and .denominator should be in lowest terms."""
265 @abstractproperty
266 def numerator(self):
267 raise NotImplementedError
269 @abstractproperty
270 def denominator(self):
271 raise NotImplementedError
273 # Concrete implementation of Real's conversion to float.
274 def __float__(self):
275 """float(self) = self.numerator / self.denominator
277 It's important that this conversion use the integer's "true"
278 division rather than casting one side to float before dividing
279 so that ratios of huge integers convert without overflowing.
282 return self.numerator / self.denominator
285 class Integral(Rational):
286 """Integral adds a conversion to int and the bit-string operations."""
288 @abstractmethod
289 def __int__(self):
290 """int(self)"""
291 raise NotImplementedError
293 def __index__(self):
294 """index(self)"""
295 return int(self)
297 @abstractmethod
298 def __pow__(self, exponent, modulus=None):
299 """self ** exponent % modulus, but maybe faster.
301 Accept the modulus argument if you want to support the
302 3-argument version of pow(). Raise a TypeError if exponent < 0
303 or any argument isn't Integral. Otherwise, just implement the
304 2-argument version described in Complex.
306 raise NotImplementedError
308 @abstractmethod
309 def __lshift__(self, other):
310 """self << other"""
311 raise NotImplementedError
313 @abstractmethod
314 def __rlshift__(self, other):
315 """other << self"""
316 raise NotImplementedError
318 @abstractmethod
319 def __rshift__(self, other):
320 """self >> other"""
321 raise NotImplementedError
323 @abstractmethod
324 def __rrshift__(self, other):
325 """other >> self"""
326 raise NotImplementedError
328 @abstractmethod
329 def __and__(self, other):
330 """self & other"""
331 raise NotImplementedError
333 @abstractmethod
334 def __rand__(self, other):
335 """other & self"""
336 raise NotImplementedError
338 @abstractmethod
339 def __xor__(self, other):
340 """self ^ other"""
341 raise NotImplementedError
343 @abstractmethod
344 def __rxor__(self, other):
345 """other ^ self"""
346 raise NotImplementedError
348 @abstractmethod
349 def __or__(self, other):
350 """self | other"""
351 raise NotImplementedError
353 @abstractmethod
354 def __ror__(self, other):
355 """other | self"""
356 raise NotImplementedError
358 @abstractmethod
359 def __invert__(self):
360 """~self"""
361 raise NotImplementedError
363 # Concrete implementations of Rational and Real abstract methods.
364 def __float__(self):
365 """float(self) == float(int(self))"""
366 return float(int(self))
368 @property
369 def numerator(self):
370 """Integers are their own numerators."""
371 return +self
373 @property
374 def denominator(self):
375 """Integers have a denominator of 1."""
376 return 1
378 Integral.register(int)