def get_integer_part(expr, no, options, return_ints=False): """ With no = 1, computes ceiling(expr) With no = -1, computes floor(expr) Note: this function either gives the exact result or signals failure. """ import sympy # The expression is likely less than 2^30 or so assumed_size = 30 ire, iim, ire_acc, iim_acc = evalf(expr, assumed_size, options) # We now know the size, so we can calculate how much extra precision # (if any) is needed to get within the nearest integer if ire and iim: gap = max(fastlog(ire) - ire_acc, fastlog(iim) - iim_acc) elif ire: gap = fastlog(ire) - ire_acc elif iim: gap = fastlog(iim) - iim_acc else: # ... or maybe the expression was exactly zero return None, None, None, None margin = 10 if gap >= -margin: ire, iim, ire_acc, iim_acc = \ evalf(expr, margin + assumed_size + gap, options) # We can now easily find the nearest integer, but to find floor/ceil, we # must also calculate whether the difference to the nearest integer is # positive or negative (which may fail if very close). def calc_part(expr, nexpr): from sympy import Add nint = int(to_int(nexpr, rnd)) n, c, p, b = nexpr if (c != 1 and p != 0) or p < 0: expr = Add(expr, -nint, evaluate=False) x, _, x_acc, _ = evalf(expr, 10, options) try: check_target(expr, (x, None, x_acc, None), 3) except PrecisionExhausted: if not expr.equals(0): raise PrecisionExhausted x = fzero nint += int(no * (mpf_cmp(x or fzero, fzero) == no)) nint = from_int(nint) return nint, fastlog(nint) + 10 re, im, re_acc, im_acc = None, None, None, None if ire: re, re_acc = calc_part(sympy.re(expr, evaluate=False), ire) if iim: im, im_acc = calc_part(sympy.im(expr, evaluate=False), iim) if return_ints: return int(to_int(re or fzero)), int(to_int(im or fzero)) return re, im, re_acc, im_acc
def get_integer_part(expr, no, options, return_ints=False): """ With no = 1, computes ceiling(expr) With no = -1, computes floor(expr) Note: this function either gives the exact result or signals failure. """ import sympy # The expression is likely less than 2^30 or so assumed_size = 30 ire, iim, ire_acc, iim_acc = evalf(expr, assumed_size, options) # We now know the size, so we can calculate how much extra precision # (if any) is needed to get within the nearest integer if ire and iim: gap = max(fastlog(ire) - ire_acc, fastlog(iim) - iim_acc) elif ire: gap = fastlog(ire) - ire_acc elif iim: gap = fastlog(iim) - iim_acc else: # ... or maybe the expression was exactly zero return None, None, None, None margin = 10 if gap >= -margin: ire, iim, ire_acc, iim_acc = \ evalf(expr, margin + assumed_size + gap, options) # We can now easily find the nearest integer, but to find floor/ceil, we # must also calculate whether the difference to the nearest integer is # positive or negative (which may fail if very close). def calc_part(expr, nexpr): from sympy import Add nint = int(to_int(nexpr, rnd)) n, c, p, b = nexpr if (c != 1 and p != 0) or p < 0: expr = Add(expr, -nint, evaluate=False) x, _, x_acc, _ = evalf(expr, 10, options) try: check_target(expr, (x, None, x_acc, None), 3) except PrecisionExhausted: if not expr.equals(0): raise PrecisionExhausted x = fzero nint += int(no*(mpf_cmp(x or fzero, fzero) == no)) nint = from_int(nint) return nint, fastlog(nint) + 10 re, im, re_acc, im_acc = None, None, None, None if ire: re, re_acc = calc_part(sympy.re(expr, evaluate=False), ire) if iim: im, im_acc = calc_part(sympy.im(expr, evaluate=False), iim) if return_ints: return int(to_int(re or fzero)), int(to_int(im or fzero)) return re, im, re_acc, im_acc
def npartitions(n, verbose=False): """ Calculate the partition function P(n), i.e. the number of ways that n can be written as a sum of positive integers. P(n) is computed using the Hardy-Ramanujan-Rademacher formula [1]_. The correctness of this implementation has been tested through 10**10. Examples ======== >>> from sympy.ntheory import npartitions >>> npartitions(25) 1958 References ========== .. [1] http://mathworld.wolfram.com/PartitionFunctionP.html """ n = int(n) if n < 0: return 0 if n <= 5: return [1, 1, 2, 3, 5, 7][n] if '_factor' not in globals(): _pre() # Estimate number of bits in p(n). This formula could be tidied pbits = int(( math.pi*(2*n/3.)**0.5 - math.log(4*n))/math.log(10) + 1) * \ math.log(10, 2) prec = p = int(pbits*1.1 + 100) s = fzero M = max(6, int(0.24*n**0.5 + 4)) if M > 10**5: raise ValueError("Input too big") # Corresponds to n > 1.7e11 sq23pi = mpf_mul(mpf_sqrt(from_rational(2, 3, p), p), mpf_pi(p), p) sqrt8 = mpf_sqrt(from_int(8), p) for q in range(1, M): a = _a(n, q, p) d = _d(n, q, p, sq23pi, sqrt8) s = mpf_add(s, mpf_mul(a, d), prec) if verbose: print("step", q, "of", M, to_str(a, 10), to_str(d, 10)) # On average, the terms decrease rapidly in magnitude. # Dynamically reducing the precision greatly improves # performance. p = bitcount(abs(to_int(d))) + 50 return int(to_int(mpf_add(s, fhalf, prec)))
def npartitions(n, verbose=False): """ Calculate the partition function P(n), i.e. the number of ways that n can be written as a sum of positive integers. P(n) is computed using the Hardy-Ramanujan-Rademacher formula [1]_. The correctness of this implementation has been tested through 10**10. Examples ======== >>> from sympy.ntheory import npartitions >>> npartitions(25) 1958 References ========== .. [1] http://mathworld.wolfram.com/PartitionFunctionP.html """ n = int(n) if n < 0: return 0 if n <= 5: return [1, 1, 2, 3, 5, 7][n] if '_factor' not in globals(): _pre() # Estimate number of bits in p(n). This formula could be tidied pbits = int(( math.pi*(2*n/3.)**0.5 - math.log(4*n))/math.log(10) + 1) * \ math.log(10, 2) prec = p = int(pbits * 1.1 + 100) s = fzero M = max(6, int(0.24 * n**0.5 + 4)) if M > 10**5: raise ValueError("Input too big") # Corresponds to n > 1.7e11 sq23pi = mpf_mul(mpf_sqrt(from_rational(2, 3, p), p), mpf_pi(p), p) sqrt8 = mpf_sqrt(from_int(8), p) for q in range(1, M): a = _a(n, q, p) d = _d(n, q, p, sq23pi, sqrt8) s = mpf_add(s, mpf_mul(a, d), prec) if verbose: print("step", q, "of", M, to_str(a, 10), to_str(d, 10)) # On average, the terms decrease rapidly in magnitude. # Dynamically reducing the precision greatly improves # performance. p = bitcount(abs(to_int(d))) + 50 return int(to_int(mpf_add(s, fhalf, prec)))
def npartitions(n): """Calculate the partition function P(n), i.e. the number of ways that n can be written as a sum of positive integers. P(n) is computed using the Hardy-Ramanujan-Rademacher formula. The correctness of this implementation has been tested for 10**n up to n = 8. Examples ======== >>> npartitions(25) 1958 References ========== * https://mathworld.wolfram.com/PartitionFunctionP.html """ n = int(n) if n < 0: return 0 if n <= 5: return [1, 1, 2, 3, 5, 7][n] # Estimate number of bits in p(n). This formula could be tidied pbits = int((math.pi*(2*n/3.)**0.5 - math.log(4*n))/math.log(10) + 1) * \ math.log(10, 2) prec = p = int(pbits * 1.1 + 100) s = fzero M = max(6, int(0.24 * n**0.5 + 4)) sq23pi = mpf_mul(mpf_sqrt(from_rational(2, 3, p), p), mpf_pi(p), p) sqrt8 = mpf_sqrt(from_int(8), p) for q in range(1, M): a = _a(n, q, p) d = _d(n, q, p, sq23pi, sqrt8) s = mpf_add(s, mpf_mul(a, d), prec) debug('step', q, 'of', M, to_str(a, 10), to_str(d, 10)) # On average, the terms decrease rapidly in magnitude. Dynamically # reducing the precision greatly improves performance. p = bitcount(abs(to_int(d))) + 50 return int(to_int(mpf_add(s, fhalf, prec)))
def npartitions(n): """Calculate the partition function P(n), i.e. the number of ways that n can be written as a sum of positive integers. P(n) is computed using the Hardy-Ramanujan-Rademacher formula. The correctness of this implementation has been tested for 10**n up to n = 8. Examples ======== >>> npartitions(25) 1958 References ========== * http://mathworld.wolfram.com/PartitionFunctionP.html """ n = int(n) if n < 0: return 0 if n <= 5: return [1, 1, 2, 3, 5, 7][n] # Estimate number of bits in p(n). This formula could be tidied pbits = int((math.pi*(2*n/3.)**0.5 - math.log(4*n))/math.log(10) + 1) * \ math.log(10, 2) prec = p = int(pbits*1.1 + 100) s = fzero M = max(6, int(0.24*n**0.5 + 4)) sq23pi = mpf_mul(mpf_sqrt(from_rational(2, 3, p), p), mpf_pi(p), p) sqrt8 = mpf_sqrt(from_int(8), p) for q in range(1, M): a = _a(n, q, p) d = _d(n, q, p, sq23pi, sqrt8) s = mpf_add(s, mpf_mul(a, d), prec) debug("step", q, "of", M, to_str(a, 10), to_str(d, 10)) # On average, the terms decrease rapidly in magnitude. Dynamically # reducing the precision greatly improves performance. p = bitcount(abs(to_int(d))) + 50 return int(to_int(mpf_add(s, fhalf, prec)))
def calc_part(expr, nexpr): nint = int(to_int(nexpr, rnd)) n, c, p, b = nexpr if (c != 1 and p != 0) or p < 0: expr = C.Add(expr, -nint, evaluate=False) x, _, x_acc, _ = evalf(expr, 10, options) try: check_target(expr, (x, None, x_acc, None), 3) except PrecisionExhausted: if not expr.equals(0): raise PrecisionExhausted x = fzero nint += int(no*(mpf_cmp(x or fzero, fzero) == no)) nint = from_int(nint) return nint, fastlog(nint) + 10
def calc_part(expr, nexpr): from sympy.core.add import Add nint = int(to_int(nexpr, rnd)) n, c, p, b = nexpr is_int = (p == 0) if not is_int: # if there are subs and they all contain integer re/im parts # then we can (hopefully) safely substitute them into the # expression s = options.get('subs', False) if s: doit = True from sympy.core.compatibility import as_int for v in s.values(): try: as_int(v) except ValueError: try: [as_int(i) for i in v.as_real_imag()] continue except (ValueError, AttributeError): doit = False break if doit: expr = expr.subs(s) expr = Add(expr, -nint, evaluate=False) x, _, x_acc, _ = evalf(expr, 10, options) try: check_target(expr, (x, None, x_acc, None), 3) except PrecisionExhausted: if not expr.equals(0): raise PrecisionExhausted x = fzero nint += int(no * (mpf_cmp(x or fzero, fzero) == no)) nint = from_int(nint) return nint, fastlog(nint) + 10
def calc_part(expr, nexpr): from sympy.core.add import Add nint = int(to_int(nexpr, rnd)) n, c, p, b = nexpr is_int = (p == 0) if not is_int: # if there are subs and they all contain integer re/im parts # then we can (hopefully) safely substitute them into the # expression s = options.get('subs', False) if s: doit = True from sympy.core.compatibility import as_int for v in s.values(): try: as_int(v) except ValueError: try: [as_int(i) for i in v.as_real_imag()] continue except (ValueError, AttributeError): doit = False break if doit: expr = expr.subs(s) expr = Add(expr, -nint, evaluate=False) x, _, x_acc, _ = evalf(expr, 10, options) try: check_target(expr, (x, None, x_acc, None), 3) except PrecisionExhausted: if not expr.equals(0): raise PrecisionExhausted x = fzero nint += int(no*(mpf_cmp(x or fzero, fzero) == no)) nint = from_int(nint) return nint, fastlog(nint) + 10
def get_integer_part(expr, no, options, return_ints=False): """ With no = 1, computes ceiling(expr) With no = -1, computes floor(expr) Note: this function either gives the exact result or signals failure. """ from sympy.functions.elementary.complexes import re, im # The expression is likely less than 2^30 or so assumed_size = 30 ire, iim, ire_acc, iim_acc = evalf(expr, assumed_size, options) # We now know the size, so we can calculate how much extra precision # (if any) is needed to get within the nearest integer if ire and iim: gap = max(fastlog(ire) - ire_acc, fastlog(iim) - iim_acc) elif ire: gap = fastlog(ire) - ire_acc elif iim: gap = fastlog(iim) - iim_acc else: # ... or maybe the expression was exactly zero return None, None, None, None margin = 10 if gap >= -margin: ire, iim, ire_acc, iim_acc = \ evalf(expr, margin + assumed_size + gap, options) # We can now easily find the nearest integer, but to find floor/ceil, we # must also calculate whether the difference to the nearest integer is # positive or negative (which may fail if very close). def calc_part(expr, nexpr): from sympy.core.add import Add nint = int(to_int(nexpr, rnd)) n, c, p, b = nexpr is_int = (p == 0) if not is_int: # if there are subs and they all contain integer re/im parts # then we can (hopefully) safely substitute them into the # expression s = options.get('subs', False) if s: doit = True from sympy.core.compatibility import as_int for v in s.values(): try: as_int(v) except ValueError: try: [as_int(i) for i in v.as_real_imag()] continue except (ValueError, AttributeError): doit = False break if doit: expr = expr.subs(s) expr = Add(expr, -nint, evaluate=False) x, _, x_acc, _ = evalf(expr, 10, options) try: check_target(expr, (x, None, x_acc, None), 3) except PrecisionExhausted: if not expr.equals(0): raise PrecisionExhausted x = fzero nint += int(no * (mpf_cmp(x or fzero, fzero) == no)) nint = from_int(nint) return nint, fastlog(nint) + 10 re_, im_, re_acc, im_acc = None, None, None, None if ire: re_, re_acc = calc_part(re(expr, evaluate=False), ire) if iim: im_, im_acc = calc_part(im(expr, evaluate=False), iim) if return_ints: return int(to_int(re_ or fzero)), int(to_int(im_ or fzero)) return re_, im_, re_acc, im_acc
def get_integer_part(expr, no, options, return_ints=False): """ With no = 1, computes ceiling(expr) With no = -1, computes floor(expr) Note: this function either gives the exact result or signals failure. """ from sympy.functions.elementary.complexes import re, im # The expression is likely less than 2^30 or so assumed_size = 30 ire, iim, ire_acc, iim_acc = evalf(expr, assumed_size, options) # We now know the size, so we can calculate how much extra precision # (if any) is needed to get within the nearest integer if ire and iim: gap = max(fastlog(ire) - ire_acc, fastlog(iim) - iim_acc) elif ire: gap = fastlog(ire) - ire_acc elif iim: gap = fastlog(iim) - iim_acc else: # ... or maybe the expression was exactly zero return None, None, None, None margin = 10 if gap >= -margin: ire, iim, ire_acc, iim_acc = \ evalf(expr, margin + assumed_size + gap, options) # We can now easily find the nearest integer, but to find floor/ceil, we # must also calculate whether the difference to the nearest integer is # positive or negative (which may fail if very close). def calc_part(expr, nexpr): from sympy.core.add import Add nint = int(to_int(nexpr, rnd)) n, c, p, b = nexpr is_int = (p == 0) if not is_int: # if there are subs and they all contain integer re/im parts # then we can (hopefully) safely substitute them into the # expression s = options.get('subs', False) if s: doit = True from sympy.core.compatibility import as_int for v in s.values(): try: as_int(v) except ValueError: try: [as_int(i) for i in v.as_real_imag()] continue except (ValueError, AttributeError): doit = False break if doit: expr = expr.subs(s) expr = Add(expr, -nint, evaluate=False) x, _, x_acc, _ = evalf(expr, 10, options) try: check_target(expr, (x, None, x_acc, None), 3) except PrecisionExhausted: if not expr.equals(0): raise PrecisionExhausted x = fzero nint += int(no*(mpf_cmp(x or fzero, fzero) == no)) nint = from_int(nint) return nint, fastlog(nint) + 10 re_, im_, re_acc, im_acc = None, None, None, None if ire: re_, re_acc = calc_part(re(expr, evaluate=False), ire) if iim: im_, im_acc = calc_part(im(expr, evaluate=False), iim) if return_ints: return int(to_int(re_ or fzero)), int(to_int(im_ or fzero)) return re_, im_, re_acc, im_acc