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 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 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 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 393Integral.register(int) 394