Home | History | Annotate | Download | only in python2.7
      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 
      6 TODO: Fill out more detailed documentation on the operators."""
      7 
      8 from __future__ import division
      9 from abc import ABCMeta, abstractmethod, abstractproperty
     10 
     11 __all__ = ["Number", "Complex", "Real", "Rational", "Integral"]
     12 
     13 class 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 
     34 class 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 
    166 Complex.register(complex)
    167 
    168 
    169 class 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 
    267 Real.register(float)
    268 
    269 
    270 class 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 
    295 class 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 
    390 Integral.register(int)
    391 Integral.register(long)
    392