Beispiel #1
0
    def __pow__(self, other, modulo=None):
        if modulo is not None:
            raise TypeError("mpq.pow() no modulo allowed")

        if isinstance(other, mpq):
            # XXX Optimize
            return self ** gmpy_cffi.mpfr(other)
        elif isinstance(other, (mpz, int, long)):
            other = int(other)
            if 0 <= other <= MAX_UI:
                res = _new_mpq()
                gmp.mpz_pow_ui(
                    gmp.mpq_numref(res), gmp.mpq_numref(self._mpq), other)
                gmp.mpz_pow_ui(
                    gmp.mpq_denref(res), gmp.mpq_denref(self._mpq), other)
                return mpq._from_c_mpq(res)
            elif -MAX_UI <= other < 0:
                if self == 0:
                    raise ZeroDivisionError(
                        "mpq.pow() 0 base to negative exponent")
                res = _new_mpq()
                gmp.mpz_pow_ui(
                    gmp.mpq_numref(res), gmp.mpq_denref(self._mpq), -other)
                gmp.mpz_pow_ui(
                    gmp.mpq_denref(res), gmp.mpq_numref(self._mpq), -other)

                # For Example mpq(-1,1)**-1 == mpq(1, -1) -> mpq(1, 1)
                gmp.mpq_canonicalize(res)
                return mpq._from_c_mpq(res)
            else:
                raise ValueError('mpz.pow with outragous exponent')
        else:
            return NotImplemented
Beispiel #2
0
    def __init__(self, *args):
        """
        mpq() -> mpq(0,1)

             If no argument is given, return mpq(0,1).

        mpq(n) -> mpq

             Return an 'mpq' object with a numeric value n. Decimal and
             Fraction values are converted exactly.

        mpq(n,m) -> mpq

             Return an 'mpq' object with a numeric value n/m.

        mpq(s[, base=10]) -> mpq

             Return an 'mpq' object from a string s made up of digits in
             the given base. s may be made up of two numbers in the same
             base separated by a '/' character.
        """

        #TODO kwargs (base)

        nargs = len(args)
        if nargs == 1 and isinstance(args[0], self.__class__):
            self._mpq = args[0]._mpq
            return

        a = self._mpq = ffi.gc(_new_mpq(), _del_mpq)

        if nargs == 0:
            gmp.mpq_set_ui(a, 0, 1)
        elif nargs == 1:
            if isinstance(args[0], float):
                gmp.mpq_set_d(a, args[0])
            elif isinstance(args[0], (int, long)):
                _pyint_to_mpq(args[0], a)
            elif isinstance(args[0], mpz):
                gmp.mpq_set_z(a, args[0]._mpz)
            elif isinstance(args[0], str):
                _str_to_mpq(args[0], 10, a)
            else:
                raise TypeError('mpq() requires numeric or string argument')
        elif nargs == 2:
            if isinstance(args[0], str):
                _str_to_mpq(args[0], args[1], a)
            elif all(isinstance(arg, (int, long, mpz)) for arg in args):
                # Set Numerator
                if isinstance(args[0], mpz):
                    gmp.mpq_set_num(a, args[0]._mpz)
                else:
                    num = gmp.mpq_numref(a)
                    _pyint_to_mpz(args[0], num)

                # Set Denominator
                if args[1] == 0:
                    raise ZeroDivisionError("zero denominator in 'mpq'")

                if isinstance(args[1], mpz):
                    gmp.mpq_set_den(a, args[1]._mpz)
                else:
                    den = gmp.mpq_denref(a)
                    _pyint_to_mpz(args[1], den)
            else:
                # Numerator
                if isinstance(args[0], mpq):
                    gmp.mpq_set(a, args[0]._mpq)
                elif isinstance(args[0], float):
                    gmp.mpq_set_d(a, args[0])
                elif isinstance(args[0], (int, long)):
                    _pyint_to_mpq(args[0], a)
                elif isinstance(args[0], mpz):
                    gmp.mpq_set_z(a, args[0]._mpz)
                else:
                    raise TypeError('mpq() requires numeric or string argument')

                # Denominator
                b = _new_mpq()
                if isinstance(args[1], mpq):
                    gmp.mpq_set(b, args[1]._mpq)
                elif isinstance(args[1], float):
                    gmp.mpq_set_d(b, args[1])
                elif isinstance(args[1], (int, long)):
                    _pyint_to_mpq(args[1], b)
                elif isinstance(args[1], mpz):
                    gmp.mpq_set_z(b, args[1]._mpz)
                else:
                    raise TypeError('mpq() requires numeric or string argument')

                # Divide them
                if gmp.mpq_sgn(b) == 0:
                    _del_mpq(b)
                    raise ZeroDivisionError

                gmp.mpq_div(a, a, b)
                _del_mpq(b)
        else:
            raise TypeError("mpq() requires 0, 1 or 2 arguments")

        # TODO only canonicalize when required (e.g. optimize mpq(42))
        gmp.mpq_canonicalize(a)