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