def fdot(ctx, A, B=None): r""" Computes the dot product of the iterables `A` and `B`, .. math :: \sum_{k=0} A_k B_k. Alternatively, :func:`fdot` accepts a single iterable of pairs. In other words, ``fdot(A,B)`` and ``fdot(zip(A,B))`` are equivalent. The elements are automatically converted to mpmath numbers. Examples:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> A = [2, 1.5, 3] >>> B = [1, -1, 2] >>> fdot(A, B) mpf('6.5') >>> zip(A, B) [(2, 1), (1.5, -1), (3, 2)] >>> fdot(_) mpf('6.5') """ if B: A = zip(A, B) prec, rnd = ctx._prec_rounding real = [] imag = [] other = 0 hasattr_ = hasattr types = (ctx.mpf, ctx.mpc) for a, b in A: if type(a) not in types: a = ctx.convert(a) if type(b) not in types: b = ctx.convert(b) a_real = hasattr_(a, "_mpf_") b_real = hasattr_(b, "_mpf_") if a_real and b_real: real.append(mpf_mul(a._mpf_, b._mpf_)) continue a_complex = hasattr_(a, "_mpc_") b_complex = hasattr_(b, "_mpc_") if a_real and b_complex: aval = a._mpf_ bre, bim = b._mpc_ real.append(mpf_mul(aval, bre)) imag.append(mpf_mul(aval, bim)) elif b_real and a_complex: are, aim = a._mpc_ bval = b._mpf_ real.append(mpf_mul(are, bval)) imag.append(mpf_mul(aim, bval)) elif a_complex and b_complex: re, im = mpc_mul(a._mpc_, b._mpc_, prec + 20) real.append(re) imag.append(im) else: other += a * b s = mpf_sum(real, prec, rnd) if imag: s = ctx.make_mpc((s, mpf_sum(imag, prec, rnd))) else: s = ctx.make_mpf(s) if other is 0: return s else: return s + other
def fsum(ctx, terms, absolute=False, squared=False): """ Calculates a sum containing a finite number of terms (for infinite series, see :func:`nsum`). The terms will be converted to mpmath numbers. For len(terms) > 2, this function is generally faster and produces more accurate results than the builtin Python function :func:`sum`. >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> fsum([1, 2, 0.5, 7]) mpf('10.5') With squared=True each term is squared, and with absolute=True the absolute value of each term is used. """ prec, rnd = ctx._prec_rounding real = [] imag = [] other = 0 for term in terms: reval = imval = 0 if hasattr(term, "_mpf_"): reval = term._mpf_ elif hasattr(term, "_mpc_"): reval, imval = term._mpc_ else: term = ctx.convert(term) if hasattr(term, "_mpf_"): reval = term._mpf_ elif hasattr(term, "_mpc_"): reval, imval = term._mpc_ else: if absolute: term = ctx.absmax(term) if squared: term = term**2 other += term continue if imval: if squared: if absolute: real.append(mpf_mul(reval, reval)) real.append(mpf_mul(imval, imval)) else: reval, imval = mpc_pow_int((reval, imval), 2, prec + 10) real.append(reval) imag.append(imval) elif absolute: real.append(mpc_abs((reval, imval), prec)) else: real.append(reval) imag.append(imval) else: if squared: reval = mpf_mul(reval, reval) elif absolute: reval = mpf_abs(reval) real.append(reval) s = mpf_sum(real, prec, rnd, absolute) if imag: s = ctx.make_mpc((s, mpf_sum(imag, prec, rnd))) else: s = ctx.make_mpf(s) if other is 0: return s else: return s + other
def fmul(ctx, x, y, **kwargs): """ Multiplies the numbers *x* and *y*, giving a floating-point result, optionally using a custom precision and rounding mode. See the documentation of :func:`fadd` for a detailed description of how to specify precision and rounding. **Examples** The result is an mpmath number:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> fmul(2, 5.0) mpf('10.0') >>> fmul(0.5j, 0.5) mpc(real='0.0', imag='0.25') Avoiding roundoff:: >>> x, y = 10**10+1, 10**15+1 >>> print x*y 10000000001000010000000001 >>> print mpf(x) * mpf(y) 1.0000000001e+25 >>> print int(mpf(x) * mpf(y)) 10000000001000011026399232 >>> print int(fmul(x, y)) 10000000001000011026399232 >>> print int(fmul(x, y, dps=25)) 10000000001000010000000001 >>> print int(fmul(x, y, exact=True)) 10000000001000010000000001 Exact multiplication with complex numbers can be inefficient and may be impossible to perform with large magnitude differences between real and imaginary parts:: >>> x = 1+2j >>> y = mpc(2, '1e-100000000000000000000') >>> fmul(x, y) mpc(real='2.0', imag='4.0') >>> fmul(x, y, rounding='u') mpc(real='2.0', imag='4.0000000000000009') >>> fmul(x, y, exact=True) Traceback (most recent call last): ... OverflowError: the exact result does not fit in memory """ prec, rounding = ctx._parse_prec(kwargs) x = ctx.convert(x) y = ctx.convert(y) try: if hasattr(x, '_mpf_'): if hasattr(y, '_mpf_'): return ctx.make_mpf(mpf_mul(x._mpf_, y._mpf_, prec, rounding)) if hasattr(y, '_mpc_'): return ctx.make_mpc(mpc_mul_mpf(y._mpc_, x._mpf_, prec, rounding)) if hasattr(x, '_mpc_'): if hasattr(y, '_mpf_'): return ctx.make_mpc(mpc_mul_mpf(x._mpc_, y._mpf_, prec, rounding)) if hasattr(y, '_mpc_'): return ctx.make_mpc(mpc_mul(x._mpc_, y._mpc_, prec, rounding)) except (ValueError, OverflowError): raise OverflowError(ctx._exact_overflow_msg) raise ValueError("Arguments need to be mpf or mpc compatible numbers")
def fmul(ctx, x, y, **kwargs): """ Multiplies the numbers *x* and *y*, giving a floating-point result, optionally using a custom precision and rounding mode. See the documentation of :func:`~mpmath.fadd` for a detailed description of how to specify precision and rounding. **Examples** The result is an mpmath number:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> fmul(2, 5.0) mpf('10.0') >>> fmul(0.5j, 0.5) mpc(real='0.0', imag='0.25') Avoiding roundoff:: >>> x, y = 10**10+1, 10**15+1 >>> print x*y 10000000001000010000000001 >>> print mpf(x) * mpf(y) 1.0000000001e+25 >>> print int(mpf(x) * mpf(y)) 10000000001000011026399232 >>> print int(fmul(x, y)) 10000000001000011026399232 >>> print int(fmul(x, y, dps=25)) 10000000001000010000000001 >>> print int(fmul(x, y, exact=True)) 10000000001000010000000001 Exact multiplication with complex numbers can be inefficient and may be impossible to perform with large magnitude differences between real and imaginary parts:: >>> x = 1+2j >>> y = mpc(2, '1e-100000000000000000000') >>> fmul(x, y) mpc(real='2.0', imag='4.0') >>> fmul(x, y, rounding='u') mpc(real='2.0', imag='4.0000000000000009') >>> fmul(x, y, exact=True) Traceback (most recent call last): ... OverflowError: the exact result does not fit in memory """ prec, rounding = ctx._parse_prec(kwargs) x = ctx.convert(x) y = ctx.convert(y) try: if hasattr(x, '_mpf_'): if hasattr(y, '_mpf_'): return ctx.make_mpf(mpf_mul(x._mpf_, y._mpf_, prec, rounding)) if hasattr(y, '_mpc_'): return ctx.make_mpc(mpc_mul_mpf(y._mpc_, x._mpf_, prec, rounding)) if hasattr(x, '_mpc_'): if hasattr(y, '_mpf_'): return ctx.make_mpc(mpc_mul_mpf(x._mpc_, y._mpf_, prec, rounding)) if hasattr(y, '_mpc_'): return ctx.make_mpc(mpc_mul(x._mpc_, y._mpc_, prec, rounding)) except (ValueError, OverflowError): raise OverflowError(ctx._exact_overflow_msg) raise ValueError("Arguments need to be mpf or mpc compatible numbers")
def fdot(ctx, A, B=None): r""" Computes the dot product of the iterables `A` and `B`, .. math :: \sum_{k=0} A_k B_k. Alternatively, :func:`fdot` accepts a single iterable of pairs. In other words, ``fdot(A,B)`` and ``fdot(zip(A,B))`` are equivalent. The elements are automatically converted to mpmath numbers. Examples:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> A = [2, 1.5, 3] >>> B = [1, -1, 2] >>> fdot(A, B) mpf('6.5') >>> zip(A, B) [(2, 1), (1.5, -1), (3, 2)] >>> fdot(_) mpf('6.5') """ if B: A = zip(A, B) prec, rnd = ctx._prec_rounding real = [] imag = [] other = 0 hasattr_ = hasattr types = (ctx.mpf, ctx.mpc) for a, b in A: if type(a) not in types: a = ctx.convert(a) if type(b) not in types: b = ctx.convert(b) a_real = hasattr_(a, "_mpf_") b_real = hasattr_(b, "_mpf_") if a_real and b_real: real.append(mpf_mul(a._mpf_, b._mpf_)) continue a_complex = hasattr_(a, "_mpc_") b_complex = hasattr_(b, "_mpc_") if a_real and b_complex: aval = a._mpf_ bre, bim = b._mpc_ real.append(mpf_mul(aval, bre)) imag.append(mpf_mul(aval, bim)) elif b_real and a_complex: are, aim = a._mpc_ bval = b._mpf_ real.append(mpf_mul(are, bval)) imag.append(mpf_mul(aim, bval)) elif a_complex and b_complex: re, im = mpc_mul(a._mpc_, b._mpc_, prec+20) real.append(re) imag.append(im) else: other += a*b s = mpf_sum(real, prec, rnd) if imag: s = ctx.make_mpc((s, mpf_sum(imag, prec, rnd))) else: s = ctx.make_mpf(s) if other is 0: return s else: return s + other
def fsum(ctx, terms, absolute=False, squared=False): """ Calculates a sum containing a finite number of terms (for infinite series, see :func:`nsum`). The terms will be converted to mpmath numbers. For len(terms) > 2, this function is generally faster and produces more accurate results than the builtin Python function :func:`sum`. >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> fsum([1, 2, 0.5, 7]) mpf('10.5') With squared=True each term is squared, and with absolute=True the absolute value of each term is used. """ prec, rnd = ctx._prec_rounding real = [] imag = [] other = 0 for term in terms: reval = imval = 0 if hasattr(term, "_mpf_"): reval = term._mpf_ elif hasattr(term, "_mpc_"): reval, imval = term._mpc_ else: term = ctx.convert(term) if hasattr(term, "_mpf_"): reval = term._mpf_ elif hasattr(term, "_mpc_"): reval, imval = term._mpc_ else: if absolute: term = ctx.absmax(term) if squared: term = term**2 other += term continue if imval: if squared: if absolute: real.append(mpf_mul(reval,reval)) real.append(mpf_mul(imval,imval)) else: reval, imval = mpc_pow_int((reval,imval),2,prec+10) real.append(reval) imag.append(imval) elif absolute: real.append(mpc_abs((reval,imval), prec)) else: real.append(reval) imag.append(imval) else: if squared: reval = mpf_mul(reval, reval) elif absolute: reval = mpf_abs(reval) real.append(reval) s = mpf_sum(real, prec, rnd, absolute) if imag: s = ctx.make_mpc((s, mpf_sum(imag, prec, rnd))) else: s = ctx.make_mpf(s) if other is 0: return s else: return s + other