Example #1
0
def main(Qstr):
    Q = float(Qstr)
    if shape == 'sphere':
        print("exact", NORM * sp.sas_3j1x_x(Q * RADIUS)**2)
    print("gauss-20", *gauss_quad_2d(Q, n=20))
    print("gauss-76", *gauss_quad_2d(Q, n=76))
    print("gauss-150", *gauss_quad_2d(Q, n=150))
    print("gauss-500", *gauss_quad_2d(Q, n=500))
    print("gauss-1025", *gauss_quad_2d(Q, n=1025))
    print("gauss-2049", *gauss_quad_2d(Q, n=2049))
    print("gauss-20 usub", *gauss_quad_usub(Q, n=20))
    print("gauss-76 usub", *gauss_quad_usub(Q, n=76))
    print("gauss-150 usub", *gauss_quad_usub(Q, n=150))
    #gridded_2d(Q, n=2**8+1)
    gridded_2d(Q, n=2**10 + 1)
    #gridded_2d(Q, n=2**12+1)
    #gridded_2d(Q, n=2**15+1)
    if shape not in ('paracrystal', 'core_shell_parallelepiped'):
        # adaptive forms on models for which the calculations are fast enough
        print("dblquad", *scipy_dblquad_2d(Q))
        print("semi-romberg-100", *semi_romberg_2d(Q, n=100))
        print("romberg", *scipy_romberg_2d(Q))
        with mp.workprec(100):
            print("mpmath", *mp_quad_2d(mp.mpf(Qstr), shape))
    plot_2d(Q, n=200)
Example #2
0
    def apply(self, z, evaluation):
        '%(name)s[z__]'

        args = z.get_sequence()

        if len(args) != self.nargs:
            return

        # if no arguments are inexact attempt to use sympy
        if all(not x.is_inexact() for x in args):
            result = Expression(self.get_name(), *args).to_sympy()
            result = self.prepare_mathics(result)
            result = from_sympy(result)
            # evaluate leaves to convert e.g. Plus[2, I] -> Complex[2, 1]
            result = result.evaluate_leaves(evaluation)
        else:
            prec = min_prec(*args)
            with mpmath.workprec(prec):
                mpmath_args = [sympy2mpmath(x.to_sympy()) for x in args]
                if None in mpmath_args:
                    return
                try:
                    result = self.eval(*mpmath_args)
                    result = from_sympy(mpmath2sympy(result, prec))
                except ValueError, exc:
                    text = str(exc)
                    if text == 'gamma function pole':
                        return Symbol('ComplexInfinity')
                    else:
                        raise
                except ZeroDivisionError:
                    return
                except SpecialValueError, exc:
                    return Symbol(exc.name)
Example #3
0
def single_segment_score_pv(score, raw=True):
    """
    Compute p-value for normalized local score of
    a single high scoring segment.

    Computes formula [1] in Karlin & Altschul, PNAS 1993

    Prob(S' >= x) ~ 1 - exp(-exp(-x))

    :param score:
    :param raw: return raw P-value instead of -log10(pv)
    :return:
    """
    with mpm.workprec(NUM_PREC_KA_PV):
        x = mpm.convert(score)
        complement = mpm.convert('1')
        exponent = mpm.fneg(mpm.exp(mpm.fneg(x)))
        res = mpm.fsub(complement, mpm.exp(exponent))
        if not raw:
            res = mpm.fneg(mpm.log10(res))
            res = float(res)

    # Equivalent implementation using Python standard library:
    #
    # x = score
    # res = 1 - math.exp(-math.exp(-x))
    # if not raw:
    #     res = -1 * math.log10(res)
    return res
Example #4
0
 def apply_N(self, prec, evaluation):
     'N[E, prec_]'
     
     prec = get_precision(prec, evaluation)
     if prec is not None:
         with workprec(prec):
             return Real(mpmath2gmpy(mpmath.e))
Example #5
0
    def _eval_evalf(self, prec):
        # The default code is insufficient for polar arguments.
        # mpmath provides an optional argument "r", which evaluates
        # G(z**(1/r)). I am not sure what its intended use is, but we hijack it
        # here in the following way: to evaluate at a number z of |argument|
        # less than (say) n*pi, we put r=1/n, compute z' = root(z, n)
        # (carefully so as not to loose the branch information), and evaluate
        # G(z'**(1/r)) = G(z'**n) = G(z).
        from sympy.functions import exp_polar, ceiling
        from sympy import Expr
        import mpmath
        znum = self.argument._eval_evalf(prec)
        if znum.has(exp_polar):
            znum, branch = znum.as_coeff_mul(exp_polar)
            if len(branch) != 1:
                return
            branch = branch[0].args[0] / I
        else:
            branch = S.Zero
        n = ceiling(abs(branch / S.Pi)) + 1
        znum = znum**(S.One / n) * exp(I * branch / n)

        # Convert all args to mpf or mpc
        try:
            [z, r, ap, bq] = [
                arg._to_mpmath(prec)
                for arg in [znum, 1 / n, self.args[0], self.args[1]]
            ]
        except ValueError:
            return

        with mpmath.workprec(prec):
            v = mpmath.meijerg(ap, bq, z, r)

        return Expr._from_mpmath(v, prec)
Example #6
0
    def apply(self, z, evaluation):
        '%(name)s[z__]'

        args = z.get_sequence()

        if len(args) != self.nargs:
            return

        # if no arguments are inexact attempt to use sympy
        if all(not x.is_inexact() for x in args):
            result = Expression(self.get_name(), *args).to_sympy()
            result = self.prepare_mathics(result)
            result = from_sympy(result)
            # evaluate leaves to convert e.g. Plus[2, I] -> Complex[2, 1]
            result = result.evaluate_leaves(evaluation)
        else:
            prec = min_prec(*args)
            with mpmath.workprec(prec):
                mpmath_args = [sympy2mpmath(x.to_sympy()) for x in args]
                if None in mpmath_args:
                    return
                try:
                    result = self.eval(*mpmath_args)
                    result = from_sympy(mpmath2sympy(result, prec))
                except ValueError, exc:
                    text = str(exc)
                    if text == 'gamma function pole':
                        return Symbol('ComplexInfinity')
                    else:
                        raise
                except ZeroDivisionError:
                    return
                except SpecialValueError, exc:
                    return Symbol(exc.name)
Example #7
0
def single_segment_expect_pv(expect, raw=True):
    """
    Compute p-value for an expect value of
    a single high scoring segment.

    Prob(E >= x) ~ 1 - exp(-E)

    This function is equivalent to
    single_segment_score_pv
    as long as identical units (log)
    are used to compute scores and expect

    :param expect:
    :param raw: return raw P-value instead of -log10(pv)
    :return:
    """
    with mpm.workprec(NUM_PREC_KA_PV):
        x = mpm.convert(expect)
        complement = mpm.convert('1')
        res = mpm.fsub(complement, mpm.exp(mpm.fneg(x)))
        if not raw:
            res = mpm.fneg(mpm.log10(res))
            res = float(res)

    return res
Example #8
0
    def _eval_evalf(self, prec):
        # The default code is insufficient for polar arguments.
        # mpmath provides an optional argument "r", which evaluates
        # G(z**(1/r)). I am not sure what its intended use is, but we hijack it
        # here in the following way: to evaluate at a number z of |argument|
        # less than (say) n*pi, we put r=1/n, compute z' = root(z, n)
        # (carefully so as not to loose the branch information), and evaluate
        # G(z'**(1/r)) = G(z'**n) = G(z).
        from sympy.functions import exp_polar, ceiling
        from sympy import Expr
        import mpmath
        z = self.argument
        znum = self.argument._eval_evalf(prec)
        if znum.has(exp_polar):
            znum, branch = znum.as_coeff_mul(exp_polar)
            if len(branch) != 1:
                return
            branch = branch[0].args[0]/I
        else:
            branch = S(0)
        n = ceiling(abs(branch/S.Pi)) + 1
        znum = znum**(S(1)/n)*exp(I*branch / n)

        # Convert all args to mpf or mpc
        try:
            [z, r, ap, bq] = [arg._to_mpmath(prec)
                    for arg in [znum, 1/n, self.args[0], self.args[1]]]
        except ValueError:
            return

        with mpmath.workprec(prec):
            v = mpmath.meijerg(ap, bq, z, r)

        return Expr._from_mpmath(v, prec)
Example #9
0
    def apply(self, z, evaluation):
        "%(name)s[z__]"

        args = z.get_sequence()

        if len(args) != self.nargs:
            return

        # if no arguments are inexact attempt to use sympy
        if len([True for x in args if Expression("InexactNumberQ", x).evaluate(evaluation).is_true()]) == 0:
            expr = Expression(self.get_name(), *args).to_sympy()
            result = from_sympy(expr)
            # evaluate leaves to convert e.g. Plus[2, I] -> Complex[2, 1]
            result = result.evaluate_leaves(evaluation)
        else:
            prec = min_prec(*args)
            with mpmath.workprec(prec):
                mpmath_args = [sympy2mpmath(x.to_sympy()) for x in args]
                if None in mpmath_args:
                    return
                try:
                    result = self.eval(*mpmath_args)
                    result = from_sympy(mpmath2sympy(result, prec))
                except ValueError, exc:
                    text = str(exc)
                    if text == "gamma function pole":
                        return Symbol("ComplexInfinity")
                    else:
                        raise
                except ZeroDivisionError:
                    return
                except SpecialValueError, exc:
                    return Symbol(exc.name)
Example #10
0
 def _eval_evalf(self, prec):
     z = self.argument._to_mpmath(prec)
     ap = [a._to_mpmath(prec) for a in self.ap]
     bp = [b._to_mpmath(prec) for b in self.bq]
     with mpmath.workprec(prec):
         res = mpmath.hyper(ap, bp, z, eliminate=False)
     return Expr._from_mpmath(res, prec)
Example #11
0
 def _eval_evalf(self, prec):
     from mpmath import mp, workprec
     from sympy import Expr
     z = self.args[0]._to_mpmath(prec)
     with workprec(prec):
         res = mp.airybi(z, derivative=1)
     return Expr._from_mpmath(res, prec)
Example #12
0
    def partition_functions_for_all_configurations(self):
        """
        Sum the partition functions for all configurations.

        .. math::

           Z_{\\text{all configs}}(T, V) = \\sum_{j} Z_{j}(T, V).

        :return: A vector, the partition function of each volume.
        """
        try:
            import mpmath
        except ImportError:
            raise ImportError(
                "Install ``mpmath`` package to use {0} object!".format(
                    self.__class__.__name__))

        with mpmath.workprec(self.precision):
            # shape = (# of volumes,)
            return np.array([
                mpmath.exp(d) for d in logsumexp(
                    -self.aligned_free_energies_for_each_configuration.T /
                    (K * self.temperature),
                    axis=1,
                    b=self.degeneracies)
            ])
Example #13
0
 def _eval_evalf(self, prec):
     z = self.argument._to_mpmath(prec)
     ap = [a._to_mpmath(prec) for a in self.ap]
     bp = [b._to_mpmath(prec) for b in self.bq]
     with mpmath.workprec(prec):
         res = mpmath.hyper(ap, bp, z, eliminate=False)
     return Expr._from_mpmath(res, prec)
Example #14
0
    def _w_tilde(self, u_bar):
        """Compute w_tilde, the threshold for the word-length w such that
		MSB = computeNaiveMSB    if w >= w_tilde
		MSB = computeNaiveMSB+1  if w < w_tilde
		(this doesn't count into account the roundoff error, as in FxPF)
		See ARITH26 paper
		Parameters:
			- u_bar: vector of bounds on the inputs of the system
		Returns: a vector of thresholds w_tilde

		We use:  w_tilde = 1 + ceil(log2(zeta_bar)) - floor(log2( 2^ceil(log2(zeta_bar)) - zeta_bar ))
		with zeta_bar = <<Hzeta>>.u_bar
		"""
        #TODO: test if zeta_bar is a power of 2 (should be +Inf in that case)
        zeta_bar = self.Hzeta.WCPG() * u_bar

        with mpmath.workprec(500):  # TODO: compute how many bit we need !!
            wtilde = [
                int(1 + mpmath.ceil(mpmath.log(x[0], 2)) - mpmath.floor(
                    mpmath.log(
                        mpmath.power(2, mpmath.ceil(mpmath.log(x[0], 2))) -
                        x[0], 2))) for x in zeta_bar.tolist()
            ]

        return wtilde
Example #15
0
 def _eval_evalf(self, prec):
     from mpmath import mp, workprec
     from sympy import Expr
     z = self.args[0]._to_mpmath(prec)
     with workprec(prec):
         res = mp.airybi(z, derivative=1)
     return Expr._from_mpmath(res, prec)
Example #16
0
def real_power(x, y):
    x = g_mpf(x)
    y = g_mpf(y)
    prec = min(x.getprec(), y.getprec())
    with workprec(prec):
        x = gmpy2mpmath(x)
        y = gmpy2mpmath(y)
        return mpmath2gmpy(x**y)
Example #17
0
 def _eval_evalf(self, prec):
     if all(x.is_number for x in self.args):
         a = self.args[0]._to_mpmath(prec)
         z = self.args[1]._to_mpmath(prec)
         with workprec(prec):
             res = mp.gammainc(a, z, mp.inf)
         return Expr._from_mpmath(res, prec)
     return self
Example #18
0
    def _eval_evalf(self, prec):
        m = self.args[0]

        if m.is_Integer and m.is_nonnegative:
            m = m._to_mpmath(prec)
            with workprec(prec):
                res = mp.eulernum(m)
            return Expr._from_mpmath(res, prec)
Example #19
0
 def _eval_evalf(self, prec):
     from mpmath import mp, workprec
     from ... import Expr
     a = self.args[0]._to_mpmath(prec)
     z = self.args[1]._to_mpmath(prec)
     with workprec(prec):
         res = mp.gammainc(a, z, mp.inf)
     return Expr._from_mpmath(res, prec)
Example #20
0
    def _eval_evalf(self, prec):
        m = self.args[0]

        if m.is_Integer and m.is_nonnegative:
            m = m._to_mpmath(prec)
            with workprec(prec):
                res = mp.eulernum(m)
            return Expr._from_mpmath(res, prec)
Example #21
0
def real_power(x, y):
    x = g_mpf(x)
    y = g_mpf(y)
    prec = min(x.getprec(), y.getprec())
    with workprec(prec):
        x = gmpy2mpmath(x)
        y = gmpy2mpmath(y)
        return mpmath2gmpy(x ** y)
Example #22
0
 def _eval_evalf(self, prec):
     from mpmath import mp, workprec
     from sympy import Expr
     a = self.args[0]._to_mpmath(prec)
     z = self.args[1]._to_mpmath(prec)
     with workprec(prec):
         res = mp.gammainc(a, z, mp.inf)
     return Expr._from_mpmath(res, prec)
Example #23
0
    def _eval_evalf(self, prec):
        """Evaluate this complex root to the given precision. """
        with workprec(prec):
            g = self.poly.gen
            if not g.is_Symbol:
                d = Dummy('x')
                func = lambdify(d, self.expr.subs(g, d))
            else:
                func = lambdify(g, self.expr)

            interval = self._get_interval()
            if not self.is_real:
                # For complex intervals, we need to keep refining until the
                # imaginary interval is disjunct with other roots, that is,
                # until both ends get refined.
                ay = interval.ay
                by = interval.by
                while interval.ay == ay or interval.by == by:
                    interval = interval.refine()

            while True:
                if self.is_real:
                    x0 = mpf(str(interval.center))
                else:
                    x0 = mpc(*map(str, interval.center))
                try:
                    root = findroot(func, x0, verify=False)
                    # If the (real or complex) root is not in the 'interval',
                    # then keep refining the interval. This happens if findroot
                    # accidentally finds a different root outside of this
                    # interval because our initial estimate 'x0' was not close
                    # enough.
                    if self.is_real:
                        a = mpf(str(interval.a))
                        b = mpf(str(interval.b))
                        if a == b:
                            root = a
                            break
                        if not (a < root < b):
                            raise ValueError("Root not in the interval.")
                    else:
                        ax = mpf(str(interval.ax))
                        bx = mpf(str(interval.bx))
                        ay = mpf(str(interval.ay))
                        by = mpf(str(interval.by))
                        if ax == bx and ay == by:
                            root = ax + S.ImaginaryUnit * by
                            break
                        if not (ax < root.real < bx and ay < root.imag < by):
                            raise ValueError("Root not in the interval.")
                except ValueError:
                    interval = interval.refine()
                    continue
                else:
                    break

        return Float._new(root.real._mpf_,
                          prec) + I * Float._new(root.imag._mpf_, prec)
Example #24
0
    def apply(self, z, evaluation):
        '%(name)s[z__]'

        args = z.numerify(evaluation).get_sequence()
        mpmath_function = self.get_mpmath_function(args)
        result = None

        # if no arguments are inexact attempt to use sympy
        if all(not x.is_inexact() for x in args):
            result = Expression(self.get_name(), *args).to_sympy()
            result = self.prepare_mathics(result)
            result = from_sympy(result)
            # evaluate leaves to convert e.g. Plus[2, I] -> Complex[2, 1]
            return result.evaluate_leaves(evaluation)
        elif mpmath_function is None:
            return

        if not all(isinstance(arg, Number) for arg in args):
            return

        if any(arg.is_machine_precision() for arg in args):
            # if any argument has machine precision then the entire calculation
            # is done with machine precision.
            float_args = [
                arg.round().get_float_value(permit_complex=True)
                for arg in args
            ]
            if None in float_args:
                return

            result = self.call_mpmath(mpmath_function, float_args)
            if isinstance(result, (mpmath.mpc, mpmath.mpf)):
                if mpmath.isinf(result) and isinstance(result, mpmath.mpc):
                    result = Symbol('ComplexInfinity')
                elif mpmath.isinf(result) and result > 0:
                    result = Expression('DirectedInfinity', Integer(1))
                elif mpmath.isinf(result) and result < 0:
                    result = Expression('DirectedInfinity', Integer(-1))
                elif mpmath.isnan(result):
                    result = Symbol('Indeterminate')
                else:
                    result = Number.from_mpmath(result)
        else:
            prec = min_prec(*args)
            d = dps(prec)
            args = [
                Expression('N', arg, Integer(d)).evaluate(evaluation)
                for arg in args
            ]
            with mpmath.workprec(prec):
                mpmath_args = [x.to_mpmath() for x in args]
                if None in mpmath_args:
                    return
                result = self.call_mpmath(mpmath_function, mpmath_args)
                if isinstance(result, (mpmath.mpc, mpmath.mpf)):
                    result = Number.from_mpmath(result, d)
        return result
Example #25
0
 def value_interval(self):
     with mpmath.workprec(self.wordlength + 1):  # wl bits is enough
         if self.signed:
             return interval(
                 -mpmath.ldexp(1, self.msb),
                 mpmath.ldexp(1, self.msb) - mpmath.ldexp(1, self.lsb))
         return interval(
             0,
             mpmath.ldexp(1, self.msb) - mpmath.ldexp(1, self.lsb))
Example #26
0
    def _eval_evalf(self, prec):
        """Evaluate this complex root to the given precision. """
        with workprec(prec):
            g = self.poly.gen
            if not g.is_Symbol:
                d = Dummy('x')
                func = lambdify(d, self.expr.subs(g, d))
            else:
                func = lambdify(g, self.expr)

            interval = self._get_interval()
            if not self.is_real:
                # For complex intervals, we need to keep refining until the
                # imaginary interval is disjunct with other roots, that is,
                # until both ends get refined.
                ay = interval.ay
                by = interval.by
                while interval.ay == ay or interval.by == by:
                    interval = interval.refine()

            while True:
                if self.is_real:
                    x0 = mpf(str(interval.center))
                else:
                    x0 = mpc(*map(str, interval.center))
                try:
                    root = findroot(func, x0, verify=False)
                    # If the (real or complex) root is not in the 'interval',
                    # then keep refining the interval. This happens if findroot
                    # accidentally finds a different root outside of this
                    # interval because our initial estimate 'x0' was not close
                    # enough.
                    if self.is_real:
                        a = mpf(str(interval.a))
                        b = mpf(str(interval.b))
                        if a == b:
                            root = a
                            break
                        if not (a < root < b):
                            raise ValueError("Root not in the interval.")
                    else:
                        ax = mpf(str(interval.ax))
                        bx = mpf(str(interval.bx))
                        ay = mpf(str(interval.ay))
                        by = mpf(str(interval.by))
                        if ax == bx and ay == by:
                            root = ax + S.ImaginaryUnit*by
                            break
                        if not (ax < root.real < bx and ay < root.imag < by):
                            raise ValueError("Root not in the interval.")
                except ValueError:
                    interval = interval.refine()
                    continue
                else:
                    break

        return Float._new(root.real._mpf_, prec) + I*Float._new(root.imag._mpf_, prec)
Example #27
0
    def _eval_evalf(self, prec):
        """Evaluate this complex root to the given precision. """
        with workprec(prec):
            g = self.poly.gen
            if not g.is_Symbol:
                d = Dummy('x')
                func = lambdify(d, self.expr.subs(g, d), "mpmath")
            else:
                func = lambdify(g, self.expr, "mpmath")

            try:
                interval = self.interval
            except KeyError:
                return super()._eval_evalf(prec)

            while True:
                if self.is_extended_real:
                    a = mpf(str(interval.a))
                    b = mpf(str(interval.b))
                    if a == b:
                        root = a
                        break
                    x0 = mpf(str(interval.center))
                else:
                    ax = mpf(str(interval.ax))
                    bx = mpf(str(interval.bx))
                    ay = mpf(str(interval.ay))
                    by = mpf(str(interval.by))
                    x0 = mpc(*map(str, interval.center))
                    if ax == bx and ay == by:
                        root = x0
                        break

                try:
                    root = findroot(func, x0)
                    # If the (real or complex) root is not in the 'interval',
                    # then keep refining the interval. This happens if findroot
                    # accidentally finds a different root outside of this
                    # interval because our initial estimate 'x0' was not close
                    # enough. It is also possible that the secant method will
                    # get trapped by a max/min in the interval; the root
                    # verification by findroot will raise a ValueError in this
                    # case and the interval will then be tightened -- and
                    # eventually the root will be found.
                    if self.is_extended_real:
                        if (a <= root <= b):
                            break
                    elif (ax <= root.real <= bx and ay <= root.imag <= by
                          and (interval.ay > 0 or interval.by < 0)):
                        break
                except (ValueError, UnboundLocalError):
                    pass
                self.refine()
                interval = self.interval

        return ((Float._new(root.real._mpf_, prec) if not self.is_imaginary
                 else 0) + I * Float._new(root.imag._mpf_, prec))
Example #28
0
    def _eval_evalf(self, prec):
        """Evaluate this complex root to the given precision."""
        with workprec(prec):
            g = self.poly.gen
            if not g.is_Symbol:
                d = Dummy('x')
                func = lambdify(d, self.expr.subs({g: d}), "mpmath")
            else:
                func = lambdify(g, self.expr, "mpmath")

            try:
                interval = self.interval
            except DomainError:
                return super()._eval_evalf(prec)

            while True:
                if self.is_extended_real:
                    a = mpf(str(interval.a))
                    b = mpf(str(interval.b))
                    if a == b:
                        root = a
                        break
                    x0 = mpf(str(interval.center))
                else:
                    ax = mpf(str(interval.ax))
                    bx = mpf(str(interval.bx))
                    ay = mpf(str(interval.ay))
                    by = mpf(str(interval.by))
                    x0 = mpc(*map(str, interval.center))
                    if ax == bx and ay == by:
                        root = x0
                        break

                try:
                    root = findroot(func, x0)
                    # If the (real or complex) root is not in the 'interval',
                    # then keep refining the interval. This happens if findroot
                    # accidentally finds a different root outside of this
                    # interval because our initial estimate 'x0' was not close
                    # enough. It is also possible that the secant method will
                    # get trapped by a max/min in the interval; the root
                    # verification by findroot will raise a ValueError in this
                    # case and the interval will then be tightened -- and
                    # eventually the root will be found.
                    if self.is_extended_real:
                        if (a <= root <= b):
                            break
                    elif (ax <= root.real <= bx and ay <= root.imag <= by
                          and (interval.ay > 0 or interval.by < 0)):
                        break
                except (ValueError, UnboundLocalError):
                    pass
                self.refine()
                interval = self.interval

        return ((Float._new(root.real._mpf_, prec) if not self.is_imaginary else 0) +
                I*Float._new(root.imag._mpf_, prec))
Example #29
0
    def apply_N(self, k, precision, evaluation):
        'N[AiryBiZero[k_Integer], precision_]'

        prec = get_precision(precision, evaluation)
        k_int = k.get_int_value()

        with mpmath.workprec(prec):
            result = mpmath2sympy(mpmath.airybizero(k_int), prec)
        return from_sympy(result)
Example #30
0
    def apply_N(self, k, precision, evaluation):
        'N[AiryBiZero[k_Integer], precision_]'

        prec = get_precision(precision, evaluation)
        k_int = k.get_int_value()

        with mpmath.workprec(prec):
            result = mpmath2sympy(mpmath.airybizero(k_int), prec)
        return from_sympy(result)
Example #31
0
	def minmax(self):
		"""Gives the interval a variable of this FPF may belong to.
		Returns:
			a tuple (min, max)
		"""
		with workprec(self._wl+1):      # wl bits is enough
			if self._signed:
				return -ldexp(1, self._msb), ldexp(1, self._msb) - ldexp(1, self.lsb)
			else:
				return 0, ldexp(1, self._msb+1) - ldexp(1, self.lsb)
Example #32
0
 def _eval_evalf(self, prec):
     from mpmath import mp, workprec
     from sympy import Expr
     if all(x.is_number for x in self.args):
         a = self.args[0]._to_mpmath(prec)
         z = self.args[1]._to_mpmath(prec)
         with workprec(prec):
             res = mp.gammainc(a, 0, z)
         return Expr._from_mpmath(res, prec)
     else:
         return self
Example #33
0
 def _eval_evalf(self, prec):
     from mpmath import mp, workprec
     from sympy import Expr
     if all(x.is_number for x in self.args):
         a = self.args[0]._to_mpmath(prec)
         z = self.args[1]._to_mpmath(prec)
         with workprec(prec):
             res = mp.gammainc(a, 0, z)
         return Expr._from_mpmath(res, prec)
     else:
         return self
 def _eval_evalf(self, prec):
     # Note: works without this function by just calling
     #       mpmath for Legendre polynomials. But using
     #       the dedicated function directly is cleaner.
     from mpmath import mp, workprec
     n = self.args[0]._to_mpmath(prec)
     m = self.args[1]._to_mpmath(prec)
     theta = self.args[2]._to_mpmath(prec)
     phi = self.args[3]._to_mpmath(prec)
     with workprec(prec):
         res = mp.spherharm(n, m, theta, phi)
     return Expr._from_mpmath(res, prec)
Example #35
0
def gmpy2mpmath(value):
    if isinstance(value, mpcomplex):
        return value.to_mpmath()
    else:
        if get_type(value) != 'f':
            value = g_mpf(value)
        with workprec(value.getprec()):
            value = str(g_mpf(value))
            if value and value[0] == '-':
                return -mp_mpf(value[1:])
            else:
                return mp_mpf(value)
Example #36
0
def gmpy2mpmath(value):
    if isinstance(value, mpcomplex):
        return value.to_mpmath()
    else:
        if get_type(value) != 'f':
            value = g_mpf(value)
        with workprec(value.getprec()):
            value = str(g_mpf(value))
            if value and value[0] == '-':
                return -mp_mpf(value[1:])
            else:
                return mp_mpf(value)
Example #37
0
    def apply_inexact(self, n, k, evaluation):
        'Binomial[n_?InexactNumberQ, k_?NumberQ]'

        with workprec(min_prec(n, k)):
            n = gmpy2mpmath(n.value)
            k = gmpy2mpmath(k.value)
            result = mpmath.binomial(n, k)
            try:
                result = mpmath2gmpy(result)
            except SpecialValueError, exc:
                return Symbol(exc.name)
            number = Number.from_mp(result)
            return number
Example #38
0
 def _eval_evalf(self, prec):
     # Note: works without this function by just calling
     #       mpmath for Legendre polynomials. But using
     #       the dedicated function directly is cleaner.
     from mpmath import mp, workprec
     from sympy import Expr
     n = self.args[0]._to_mpmath(prec)
     m = self.args[1]._to_mpmath(prec)
     theta = self.args[2]._to_mpmath(prec)
     phi = self.args[3]._to_mpmath(prec)
     with workprec(prec):
         res = mp.spherharm(n, m, theta, phi)
     return Expr._from_mpmath(res, prec)
Example #39
0
 def apply_inexact(self, n, k, evaluation):
     'Binomial[n_?InexactNumberQ, k_?NumberQ]'
     
     with workprec(min_prec(n, k)):
         n = gmpy2mpmath(n.value)
         k = gmpy2mpmath(k.value)
         result = mpmath.binomial(n, k)
         try:
             result = mpmath2gmpy(result)
         except SpecialValueError, exc:
             return Symbol(exc.name)
         number = Number.from_mp(result)
         return number
Example #40
0
    def apply(self, z, evaluation):
        '%(name)s[z__]'

        args = z.numerify(evaluation).get_sequence()
        mpmath_function = self.get_mpmath_function(args)
        result = None

        # if no arguments are inexact attempt to use sympy
        if all(not x.is_inexact() for x in args):
            result = Expression(self.get_name(), *args).to_sympy()
            result = self.prepare_mathics(result)
            result = from_sympy(result)
            # evaluate leaves to convert e.g. Plus[2, I] -> Complex[2, 1]
            return result.evaluate_leaves(evaluation)
        elif mpmath_function is None:
            return

        if not all(isinstance(arg, Number) for arg in args):
            return

        if any(arg.is_machine_precision() for arg in args):
            # if any argument has machine precision then the entire calculation
            # is done with machine precision.
            float_args = [arg.round().get_float_value(permit_complex=True) for arg in args]
            if None in float_args:
                return

            result = self.call_mpmath(mpmath_function, float_args)
            if isinstance(result, (mpmath.mpc, mpmath.mpf)):
                if mpmath.isinf(result) and isinstance(result, mpmath.mpc):
                    result = Symbol('ComplexInfinity')
                elif mpmath.isinf(result) and result > 0:
                    result = Expression('DirectedInfinity', Integer(1))
                elif mpmath.isinf(result) and result < 0:
                    result = Expression('DirectedInfinity', Integer(-1))
                elif mpmath.isnan(result):
                    result = Symbol('Indeterminate')
                else:
                    result = Number.from_mpmath(result)
        else:
            prec = min_prec(*args)
            d = dps(prec)
            args = [Expression('N', arg, Integer(d)).evaluate(evaluation) for arg in args]
            with mpmath.workprec(prec):
                mpmath_args = [x.to_mpmath() for x in args]
                if None in mpmath_args:
                    return
                result = self.call_mpmath(mpmath_function, mpmath_args)
                if isinstance(result, (mpmath.mpc, mpmath.mpf)):
                    result = Number.from_mpmath(result, d)
        return result
Example #41
0
def multi_segment_score_pv(score, num_segments, raw=True):
    """
    Compute p-value for normalized score when considering
    multiple high scoring segments. This functions considers
    the normalized score Sr', i.e., the normalized score
    of the HSP at rank r. For r=1, this formula is equivalent
    to single_segment_score_pv

    Computes formula [3] in Karlin & Altschul, PNAS 1993

    Prob(Sr' >= x) ~ 1 - exp(-exp(-x)) * SUM (k=0 ... r - 1) { exp(-kx) / k! }

    Implementation detail:
    Python's range is not right-inclusive,
    go up to r, not r - 1 for summation

    :param score:
    :param num_segments:
    :param raw: return raw P-value instead of -log10(pv)
    :return:
    """

    with mpm.workprec(NUM_PREC_KA_PV):

        def create_summand(sum_x, k):
            prec_k = mpm.convert(k)
            enum = mpm.exp(mpm.fneg(mpm.fmul(prec_k, sum_x)))
            denom = mpm.factorial(prec_k)
            summand = mpm.fdiv(enum, denom)
            return summand

        x = mpm.convert(score)
        r = num_segments
        complement = mpm.convert('1')
        factor1 = mpm.exp(mpm.fneg(mpm.exp(mpm.fneg(x))))
        factor2 = mpm.fsum(map(lambda k: create_summand(x, k), range(0, r)))
        res = mpm.fsub(complement, mpm.fmul(factor1, factor2))
        if not raw:
            res = mpm.fneg(mpm.log10(res))
            res = float(res)

    # Equivalent implementation using Python standard library:
    #
    # x = score
    # r = num_segments
    # factor_1 = math.exp(-math.exp(-x))
    # factor_2 = math.fsum(map(lambda k: math.exp(-k * x) / math.factorial(k), range(0, r)))
    # res = 1 - factor_1 * factor_2
    # if not raw:
    #     res = -1 * math.log10(res)
    return res
Example #42
0
    def computeNaiveMSB(self, u_bar, output_info=None):
        """Compute the MSB of t, x and y without taking into account the errors in the filter evaluation, and the
		errors in the computation of this MSB (the WCPG computation and the log2 associated)
		Returns a vector of MSB"""

        # compute the WCPG of Hzeta
        zeta_bar = self.Hzeta.WCPG(output_info) * u_bar

        with workprec(
                500
        ):  # TODO: use right precision !! Or do it as it should be done, as in FxPF (see Nastia thesis p113)
            # and then the log2
            msb = [int(ceil(log(x[0], 2))) for x in zeta_bar.tolist()]

        return msb
Example #43
0
    def apply_inexact(self, z, evaluation):
        '%(name)s[z_Real|z_Complex?InexactNumberQ]'

        with workprec(z.get_precision()):
            z = gmpy2mpmath(z.value)
            try:
                result = self.eval(z)
            except ValueError, exc:
                text = str(exc)
                if text == 'gamma function pole':
                    return Symbol('ComplexInfinity')
                else:
                    raise
            except ZeroDivisionError:
                return
Example #44
0
 def apply_inexact(self, z, evaluation):
     '%(name)s[z_Real|z_Complex?InexactNumberQ]'
     
     with workprec(z.get_precision()):
         z = gmpy2mpmath(z.value)
         try:
             result = self.eval(z)
         except ValueError, exc:
             text = str(exc)
             if text == 'gamma function pole':
                 return Symbol('ComplexInfinity')
             else:
                 raise
         except ZeroDivisionError:
             return
Example #45
0
    def w_tilde(self, u_bar):
        """compute w_tilde, the threshold for the word-length w such that
		MSB = computeNaiveMSB    if w >= w_tilde
		MSB = computeNaiveMSB+1  if w < w_tilde
		(this doesn't count into account the roundoff error, as in FxPF"""

        zeta_bar = self.Hzeta.WCPG() * u_bar

        with workprec(500):  # TODO: compute how many bit we need !!
            wtilde = [
                int(1 + ceil(log(x[0], 2)) -
                    floor(log(power(2, ceil(log(x[0], 2))) - x[0], 2)))
                for x in zeta_bar.tolist()
            ]

        return wtilde
Example #46
0
    def apply_N(self, k, precision, evaluation):
        'N[AiryBiZero[k_Integer], precision_]'

        try:
            d = get_precision(precision, evaluation)
        except PrecisionValueError:
            return

        if d is None:
            p = machine_precision
        else:
            p = _prec(d)

        k_int = k.get_int_value()

        with mpmath.workprec(p):
            result = mpmath.airybizero(k_int)
            return Number.from_mpmath(result, d)
Example #47
0
    def apply_N(self, k, precision, evaluation):
        "N[AiryBiZero[k_Integer], precision_]"

        try:
            d = get_precision(precision, evaluation)
        except PrecisionValueError:
            return

        if d is None:
            p = machine_precision
        else:
            p = _prec(d)

        k_int = k.get_int_value()

        with mpmath.workprec(p):
            result = mpmath.airybizero(k_int)
            return from_mpmath(result, d)
Example #48
0
 def apply_inexact(self, z, evaluation):
     '%(name)s[z_Real|z_Complex?InexactNumberQ]'
     
     prec = z.get_precision()
     with mpmath.workprec(prec):
         z = sympy2mpmath(z.to_sympy())
         if z is None:
             return
         try:
             result = self.eval(z)
             result = mpmath2sympy(result, prec)
         except ValueError, exc:
             text = str(exc)
             if text == 'gamma function pole':
                 return Symbol('ComplexInfinity')
             else:
                 raise
         except ZeroDivisionError:
             return
Example #49
0
def find_limit_reverse(
    func,
    limit,
    xstart=None,
    xstop=None,
    nulp=0,
    prec=None,
):

    fmt = ieee_format(prec)

    if xstart is None:
        xstart = fmt.min_value()

    if xstop is None:
        xstop = one

    def xstep(x):
        return x * two

    if nulp:

        def compare(fx, lx):
            return abs(fx - lx) > fmt.ulp(fx)

    else:
        compare = ne

    with workprec(prec or mp.prec):
        n_min, x_n = find_fp(
            func,
            limit,
            xstart,
            xstop,
            xstep,
            compare,
            max_steps=abs(fmt.min_exp()),
        )

        n_min = abs(fmt.min_exp()) - n_min + 1
        steps, limit = bisect_limit(func, limit, x_n / two, x_n, nulp, prec)

    return limit, n_min, steps
def test_main():
    with mpmath.workprec(100):
        generate_cases()
Example #51
0
    def apply(self, items, evaluation):
        'Times[items___]'

        items = items.numerify(evaluation).get_sequence()
        leaves = []
        numbers = []

        prec = min_prec(*items)
        is_machine_precision = any(item.is_machine_precision() for item in items)

        # find numbers and simplify Times -> Power
        for item in items:
            if isinstance(item, Number):
                numbers.append(item)
            elif leaves and item == leaves[-1]:
                leaves[-1] = Expression('Power', leaves[-1], Integer(2))
            elif (leaves and item.has_form('Power', 2) and
                  leaves[-1].has_form('Power', 2) and
                  item.leaves[0].same(leaves[-1].leaves[0])):
                leaves[-1].leaves[1] = Expression(
                    'Plus', item.leaves[1], leaves[-1].leaves[1])
            elif (leaves and item.has_form('Power', 2) and
                  item.leaves[0].same(leaves[-1])):
                leaves[-1] = Expression(
                    'Power', leaves[-1],
                    Expression('Plus', item.leaves[1], Integer(1)))
            elif (leaves and leaves[-1].has_form('Power', 2) and
                  leaves[-1].leaves[0].same(item)):
                leaves[-1] = Expression('Power', item, Expression(
                    'Plus', Integer(1), leaves[-1].leaves[1]))
            else:
                leaves.append(item)

        if numbers:
            if prec is not None:
                if is_machine_precision:
                    numbers = [item.to_mpmath() for item in numbers]
                    number = mpmath.fprod(numbers)
                    number = Number.from_mpmath(number)
                else:
                    with mpmath.workprec(prec):
                        numbers = [item.to_mpmath() for item in numbers]
                        number = mpmath.fprod(numbers)
                        number = Number.from_mpmath(number, dps(prec))
            else:
                number = sympy.Mul(*[item.to_sympy() for item in numbers])
                number = from_sympy(number)
        else:
            number = Integer(1)

        if number.same(Integer(1)):
            number = None
        elif number.is_zero:
            return number
        elif number.same(Integer(-1)) and leaves and leaves[0].has_form('Plus', None):
            leaves[0].leaves = [Expression('Times', Integer(-1), leaf)
                                for leaf in leaves[0].leaves]
            number = None

        for leaf in leaves:
            leaf.last_evaluated = None

        if number is not None:
            leaves.insert(0, number)

        if not leaves:
            return Integer(1)
        elif len(leaves) == 1:
            return leaves[0]
        else:
            return Expression('Times', *leaves)
Example #52
0
    def apply(self, items, evaluation):
        'Plus[items___]'

        items = items.numerify(evaluation).get_sequence()
        leaves = []
        last_item = last_count = None

        prec = min_prec(*items)
        is_machine_precision = any(item.is_machine_precision() for item in items)
        numbers = []

        def append_last():
            if last_item is not None:
                if last_count == 1:
                    leaves.append(last_item)
                else:
                    if last_item.has_form('Times', None):
                        last_item.leaves.insert(0, from_sympy(last_count))
                        leaves.append(last_item)
                    else:
                        leaves.append(Expression(
                            'Times', from_sympy(last_count), last_item))

        for item in items:
            if isinstance(item, Number):
                numbers.append(item)
            else:
                count = rest = None
                if item.has_form('Times', None):
                    for leaf in item.leaves:
                        if isinstance(leaf, Number):
                            count = leaf.to_sympy()
                            rest = item.leaves[:]
                            rest.remove(leaf)
                            if len(rest) == 1:
                                rest = rest[0]
                            else:
                                rest.sort()
                                rest = Expression('Times', *rest)
                            break
                if count is None:
                    count = sympy.Integer(1)
                    rest = item
                if last_item is not None and last_item == rest:
                    last_count = last_count + count
                else:
                    append_last()
                    last_item = rest
                    last_count = count
        append_last()

        if numbers:
            if prec is not None:
                if is_machine_precision:
                    numbers = [item.to_mpmath() for item in numbers]
                    number = mpmath.fsum(numbers)
                    number = Number.from_mpmath(number)
                else:
                    with mpmath.workprec(prec):
                        numbers = [item.to_mpmath() for item in numbers]
                        number = mpmath.fsum(numbers)
                        number = Number.from_mpmath(number, dps(prec))
            else:
                number = from_sympy(sum(item.to_sympy() for item in numbers))
        else:
            number = Integer(0)

        if not number.same(Integer(0)):
            leaves.insert(0, number)

        if not leaves:
            return Integer(0)
        elif len(leaves) == 1:
            return leaves[0]
        else:
            leaves.sort()
            return Expression('Plus', *leaves)
Example #53
0
 def test_testfile_mpmath(self):
     # Run the mpmath module on the same material: consistency check during development.
     with mpmath.workprec(100) :
         self.test_testfile(mpmath, 1, 1)
Example #54
0
    def apply(self, items, evaluation):
        "Power[items__]"

        items_sequence = items.get_sequence()

        if len(items_sequence) == 2:
            x, y = items_sequence
        else:
            return Expression("Power", *items_sequence)

        if y.get_int_value() == 1:
            return x
        elif x.get_int_value() == 1:
            return x
        elif y.get_int_value() == 0:
            if x.get_int_value() == 0:
                evaluation.message("Power", "indet", Expression("Power", x, y))
                return Symbol("Indeterminate")
            else:
                return Integer(1)

        elif x.has_form("Power", 2) and isinstance(y, Integer):
            return Expression("Power", x.leaves[0], Expression("Times", x.leaves[1], y))
        elif x.has_form("Times", None) and isinstance(y, Integer):
            return Expression("Times", *[Expression("Power", leaf, y) for leaf in x.leaves])

        elif isinstance(x, Number) and isinstance(y, Number) and not (x.is_inexact() or y.is_inexact()):
            sym_x, sym_y = x.to_sympy(), y.to_sympy()
            try:
                if sym_y >= 0:
                    result = sym_x ** sym_y
                else:
                    if sym_x == 0:
                        evaluation.message("Power", "infy")
                        return Symbol("ComplexInfinity")
                    result = sympy.Integer(1) / (sym_x ** (-sym_y))
                if isinstance(result, sympy.Pow):
                    result = result.simplify()
                    args = [from_sympy(expr) for expr in result.as_base_exp()]
                    result = Expression("Power", *args)
                    result = result.evaluate_leaves(evaluation)
                    return result

                return from_sympy(result)
            except ValueError:
                return Expression("Power", x, y)
            except ZeroDivisionError:
                evaluation.message("Power", "infy")
                return Symbol("ComplexInfinity")

        elif isinstance(x, Number) and isinstance(y, Number) and (x.is_inexact() or y.is_inexact()):
            try:
                prec = min(max(x.get_precision(), 64), max(y.get_precision(), 64))
                with mpmath.workprec(prec):
                    mp_x = sympy2mpmath(x.to_sympy())
                    mp_y = sympy2mpmath(y.to_sympy())
                    result = mp_x ** mp_y
                    if isinstance(result, mpmath.mpf):
                        return Real(str(result), prec)
                    elif isinstance(result, mpmath.mpc):
                        return Complex(str(result.real), str(result.imag), prec)
            except ZeroDivisionError:
                evaluation.message("Power", "infy")
                return Symbol("ComplexInfinity")
        else:
            numerified_items = items.numerify(evaluation)
            return Expression("Power", *numerified_items.get_sequence())
Example #55
0
def do_integral(expr, prec, options):
    func = expr.args[0]
    x, xlow, xhigh = expr.args[1]
    if xlow == xhigh:
        xlow = xhigh = 0
    elif x not in func.free_symbols:
        # only the difference in limits matters in this case
        # so if there is a symbol in common that will cancel
        # out when taking the difference, then use that
        # difference
        if xhigh.free_symbols & xlow.free_symbols:
            diff = xhigh - xlow
            if not diff.free_symbols:
                xlow, xhigh = 0, diff

    oldmaxprec = options.get('maxprec', DEFAULT_MAXPREC)
    options['maxprec'] = min(oldmaxprec, 2*prec)

    with workprec(prec + 5):
        xlow = as_mpmath(xlow, prec + 15, options)
        xhigh = as_mpmath(xhigh, prec + 15, options)

        # Integration is like summation, and we can phone home from
        # the integrand function to update accuracy summation style
        # Note that this accuracy is inaccurate, since it fails
        # to account for the variable quadrature weights,
        # but it is better than nothing

        from sympy import cos, sin, Wild

        have_part = [False, False]
        max_real_term = [MINUS_INF]
        max_imag_term = [MINUS_INF]

        def f(t):
            re, im, re_acc, im_acc = evalf(func, mp.prec, {'subs': {x: t}})

            have_part[0] = re or have_part[0]
            have_part[1] = im or have_part[1]

            max_real_term[0] = max(max_real_term[0], fastlog(re))
            max_imag_term[0] = max(max_imag_term[0], fastlog(im))

            if im:
                return mpc(re or fzero, im)
            return mpf(re or fzero)

        if options.get('quad') == 'osc':
            A = Wild('A', exclude=[x])
            B = Wild('B', exclude=[x])
            D = Wild('D')
            m = func.match(cos(A*x + B)*D)
            if not m:
                m = func.match(sin(A*x + B)*D)
            if not m:
                raise ValueError("An integrand of the form sin(A*x+B)*f(x) "
                  "or cos(A*x+B)*f(x) is required for oscillatory quadrature")
            period = as_mpmath(2*S.Pi/m[A], prec + 15, options)
            result = quadosc(f, [xlow, xhigh], period=period)
            # XXX: quadosc does not do error detection yet
            quadrature_error = MINUS_INF
        else:
            result, quadrature_error = quadts(f, [xlow, xhigh], error=1)
            quadrature_error = fastlog(quadrature_error._mpf_)

    options['maxprec'] = oldmaxprec

    if have_part[0]:
        re = result.real._mpf_
        if re == fzero:
            re, re_acc = scaled_zero(
                min(-prec, -max_real_term[0], -quadrature_error))
            re = scaled_zero(re)  # handled ok in evalf_integral
        else:
            re_acc = -max(max_real_term[0] - fastlog(re) -
                          prec, quadrature_error)
    else:
        re, re_acc = None, None

    if have_part[1]:
        im = result.imag._mpf_
        if im == fzero:
            im, im_acc = scaled_zero(
                min(-prec, -max_imag_term[0], -quadrature_error))
            im = scaled_zero(im)  # handled ok in evalf_integral
        else:
            im_acc = -max(max_imag_term[0] - fastlog(im) -
                          prec, quadrature_error)
    else:
        im, im_acc = None, None

    result = re, im, re_acc, im_acc
    return result
Example #56
0
    def _eval_evalf(self, prec):
        """Evaluate this complex root to the given precision. """
        with workprec(prec):
            g = self.poly.gen
            if not g.is_Symbol:
                d = Dummy('x')
                func = lambdify(d, self.expr.subs(g, d))
            else:
                func = lambdify(g, self.expr)

            interval = self._get_interval()
            if not self.is_real:
                # For complex intervals, we need to keep refining until the
                # imaginary interval is disjunct with other roots, that is,
                # until both ends get refined.
                ay = interval.ay
                by = interval.by
                while interval.ay == ay or interval.by == by:
                    interval = interval.refine()

            while True:
                if self.is_real:
                    a = mpf(str(interval.a))
                    b = mpf(str(interval.b))
                    if a == b:
                        root = a
                        break
                    x0 = mpf(str(interval.center))
                else:
                    ax = mpf(str(interval.ax))
                    bx = mpf(str(interval.bx))
                    ay = mpf(str(interval.ay))
                    by = mpf(str(interval.by))
                    if ax == bx and ay == by:
                        # the sign of the imaginary part will be assigned
                        # according to the desired index using the fact that
                        # roots are sorted with negative imag parts coming
                        # before positive (and all imag roots coming after real
                        # roots)
                        deg = self.poly.degree()
                        i = self.index  # a positive attribute after creation
                        if (deg - i) % 2:
                            if ay < 0:
                                ay = -ay
                        else:
                            if ay > 0:
                                ay = -ay
                        root = mpc(ax, ay)
                        break
                    x0 = mpc(*map(str, interval.center))

                try:
                    root = findroot(func, x0)
                    # If the (real or complex) root is not in the 'interval',
                    # then keep refining the interval. This happens if findroot
                    # accidentally finds a different root outside of this
                    # interval because our initial estimate 'x0' was not close
                    # enough. It is also possible that the secant method will
                    # get trapped by a max/min in the interval; the root
                    # verification by findroot will raise a ValueError in this
                    # case and the interval will then be tightened -- and
                    # eventually the root will be found.
                    #
                    # It is also possible that findroot will not have any
                    # successful iterations to process (in which case it
                    # will fail to initialize a variable that is tested
                    # after the iterations and raise an UnboundLocalError).
                    if self.is_real:
                        if (a <= root <= b):
                            break
                    elif (ax <= root.real <= bx and ay <= root.imag <= by):
                        break
                except (UnboundLocalError, ValueError):
                    pass
                interval = interval.refine()

        return (Float._new(root.real._mpf_, prec)
                + I*Float._new(root.imag._mpf_, prec))
Example #57
0
    def eval_approx(self, n):
        """Evaluate this complex root to the given precision.

        This uses secant method and root bounds are used to both
        generate an initial guess and to check that the root
        returned is valid. If ever the method converges outside the
        root bounds, the bounds will be made smaller and updated.
        """
        prec = dps_to_prec(n)
        with workprec(prec):
            g = self.poly.gen
            if not g.is_Symbol:
                d = Dummy('x')
                if self.is_imaginary:
                    d *= I
                func = lambdify(d, self.expr.subs(g, d))
            else:
                expr = self.expr
                if self.is_imaginary:
                    expr = self.expr.subs(g, I*g)
                func = lambdify(g, expr)

            interval = self._get_interval()
            while True:
                if self.is_real:
                    a = mpf(str(interval.a))
                    b = mpf(str(interval.b))
                    if a == b:
                        root = a
                        break
                    x0 = mpf(str(interval.center))
                    x1 = x0 + mpf(str(interval.dx))/4
                elif self.is_imaginary:
                    a = mpf(str(interval.ay))
                    b = mpf(str(interval.by))
                    if a == b:
                        root = mpc(mpf('0'), a)
                        break
                    x0 = mpf(str(interval.center[1]))
                    x1 = x0 + mpf(str(interval.dy))/4
                else:
                    ax = mpf(str(interval.ax))
                    bx = mpf(str(interval.bx))
                    ay = mpf(str(interval.ay))
                    by = mpf(str(interval.by))
                    if ax == bx and ay == by:
                        root = mpc(ax, ay)
                        break
                    x0 = mpc(*map(str, interval.center))
                    x1 = x0 + mpc(*map(str, (interval.dx, interval.dy)))/4
                try:
                    # without a tolerance, this will return when (to within
                    # the given precision) x_i == x_{i-1}
                    root = findroot(func, (x0, x1))
                    # If the (real or complex) root is not in the 'interval',
                    # then keep refining the interval. This happens if findroot
                    # accidentally finds a different root outside of this
                    # interval because our initial estimate 'x0' was not close
                    # enough. It is also possible that the secant method will
                    # get trapped by a max/min in the interval; the root
                    # verification by findroot will raise a ValueError in this
                    # case and the interval will then be tightened -- and
                    # eventually the root will be found.
                    #
                    # It is also possible that findroot will not have any
                    # successful iterations to process (in which case it
                    # will fail to initialize a variable that is tested
                    # after the iterations and raise an UnboundLocalError).
                    if self.is_real or self.is_imaginary:
                        if not bool(root.imag) == self.is_real and (
                                a <= root <= b):
                            if self.is_imaginary:
                                root = mpc(mpf('0'), root.real)
                            break
                    elif (ax <= root.real <= bx and ay <= root.imag <= by):
                        break
                except (UnboundLocalError, ValueError):
                    pass
                interval = interval.refine()

        # update the interval so we at least (for this precision or
        # less) don't have much work to do to recompute the root
        self._set_interval(interval)
        return (Float._new(root.real._mpf_, prec) +
            I*Float._new(root.imag._mpf_, prec))
Example #58
0
 def _eval_evalf(self, prec):
     a = self.args[0]._to_mpmath(prec)
     z = self.args[1]._to_mpmath(prec)
     with workprec(prec):
         res = mp.gammainc(a, z, mp.inf)
     return Expr._from_mpmath(res, prec)
Example #59
0
def hypsum(expr, n, start, prec):
    """
    Sum a rapidly convergent infinite hypergeometric series with
    given general term, e.g. e = hypsum(1/factorial(n), n). The
    quotient between successive terms must be a quotient of integer
    polynomials.
    """
    from sympy import Float, hypersimp, lambdify

    if prec == float('inf'):
        raise NotImplementedError('does not support inf prec')

    if start:
        expr = expr.subs(n, n + start)
    hs = hypersimp(expr, n)
    if hs is None:
        raise NotImplementedError("a hypergeometric series is required")
    num, den = hs.as_numer_denom()

    func1 = lambdify(n, num)
    func2 = lambdify(n, den)

    h, g, p = check_convergence(num, den, n)

    if h < 0:
        raise ValueError("Sum diverges like (n!)^%i" % (-h))

    term = expr.subs(n, 0)
    if not term.is_Rational:
        raise NotImplementedError("Non rational term functionality is not implemented.")

    # Direct summation if geometric or faster
    if h > 0 or (h == 0 and abs(g) > 1):
        term = (MPZ(term.p) << prec) // term.q
        s = term
        k = 1
        while abs(term) > 5:
            term *= MPZ(func1(k - 1))
            term //= MPZ(func2(k - 1))
            s += term
            k += 1
        return from_man_exp(s, -prec)
    else:
        alt = g < 0
        if abs(g) < 1:
            raise ValueError("Sum diverges like (%i)^n" % abs(1/g))
        if p < 1 or (p == 1 and not alt):
            raise ValueError("Sum diverges like n^%i" % (-p))
        # We have polynomial convergence: use Richardson extrapolation
        vold = None
        ndig = prec_to_dps(prec)
        while True:
            # Need to use at least quad precision because a lot of cancellation
            # might occur in the extrapolation process; we check the answer to
            # make sure that the desired precision has been reached, too.
            prec2 = 4*prec
            term0 = (MPZ(term.p) << prec2) // term.q

            def summand(k, _term=[term0]):
                if k:
                    k = int(k)
                    _term[0] *= MPZ(func1(k - 1))
                    _term[0] //= MPZ(func2(k - 1))
                return make_mpf(from_man_exp(_term[0], -prec2))

            with workprec(prec):
                v = nsum(summand, [0, mpmath_inf], method='richardson')
            vf = Float(v, ndig)
            if vold is not None and vold == vf:
                break
            prec += prec  # double precision each time
            vold = vf

        return v._mpf_