Beispiel #1
0
def _pyint_to_mpq(n, a):
    if -sys.maxsize - 1 <= n <= sys.maxsize:
        gmp.mpq_set_si(a, n, 1)
    elif sys.maxsize < n <= MAX_UI:
        gmp.mpq_set_ui(a, n, 1)
    else:
        assert isinstance(n, long)
        num, den = gmp.mpq_numref(a), gmp.mpq_denref(a)
        _pylong_to_mpz(n, num)
        gmp.mpz_set_ui(den, 1)
Beispiel #2
0
def _pyint_to_mpq(n, a):
    if -sys.maxsize - 1 <= n <= sys.maxsize:
        gmp.mpq_set_si(a, n, 1)
    elif sys.maxsize < n <= MAX_UI:
        gmp.mpq_set_ui(a, n, 1)
    else:
        assert isinstance(n, long)
        num, den = gmp.mpq_numref(a), gmp.mpq_denref(a)
        _pylong_to_mpz(n, num)
        gmp.mpz_set_ui(den, 1)
Beispiel #3
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)