def F1_cubic(hstar,kappa): ''' F1 function corresponding to a cubic viscosity profile (Nieuwstadt 1983) Parameters ---------- hstar: float Non-dimensional boundary-layer height hstar = h*fc/utau kappa: float Von Karman constant Returns ------- F1: float Value of F1 function ''' C = hstar/kappa alpha = 0.5+0.5*np.sqrt(1+4j*C) F1 = np.zeros((1),dtype=np.float64) F1[0] = 1./kappa*(-np.log(hstar)+ mpmath.re( mpmath.digamma(alpha+1)+ mpmath.digamma(alpha-1)- 2*mpmath.digamma(1.0) ) ) return np.asscalar(F1)
def entropy(df): """ Entropy of Student's t distribution. """ if df <= 0: raise ValueError('df must be greater than 0') with mpmath.extradps(5): df = mpmath.mpf(df) h = df/2 h1 = (df + 1)/2 return (h1*(mpmath.digamma(h1) - mpmath.digamma(h)) + mpmath.log(mpmath.sqrt(df)*mpmath.beta(h, 0.5)))
def mpmath_digamma(x): try: return mpmath.digamma(x) except ValueError: # Hit a pole. if x == 0.0: return -np.copysign(np.inf, x) else: return np.nan
def digammainv(y): """ Inverse of the digamma function (real values only). The `digamma function` [1]_ [2]_ is the logarithmic derivative of the gamma function. For real y, digammainv(y) returns the positive x such that digamma(x) = y. The digamma function is also known as psi_0; `mpmath.digamma(x)` is the same as `mpmath.psi(0, x)`. References ---------- .. [1] "Digamma function", https://en.wikipedia.org/wiki/Digamma_function .. [2] Abramowitz and Stegun, *Handbook of Mathematical Functions* (section 6.3), Dover Publications, New York (1972). Examples -------- >>> import mpmath >>> from mpsci.fun import digammainv >>> mpmath.mp.dps = 25 >>> y = mpmath.mpf('7.89123') >>> y mpf('7.891230000000000000000000011') >>> x = digammainv(y) >>> x mpf('2674.230572001301673812839151') >>> mpmath.digamma(x) mpf('7.891230000000000000000000011') """ # XXX I'm not sure this extra dps is necessary. with mpmath.extradps(5): y = mpmath.mpf(y) # Find a good initial guess for the root. if y > -0.125: x0 = mpmath.exp(y) + mpmath.mpf('0.5') elif y > -3: x0 = mpmath.exp(y / mpmath.mpf(2.332)) + mpmath.mpf(0.08661) else: x0 = -1 / (y + mpmath.euler) solver = 'anderson' x0 = (4 * x0 / 5, 5 * x0 / 4) x = mpmath.findroot(lambda x: mpmath.digamma(x) - y, x0, solver=solver) return x
def test_roundtrip(): # Test that digamma(digammainv(y)) == y with mpmath.workdps(50): for y in [ mpmath.mpf(-100), mpmath.mpf('-3.5'), mpmath.mpf('-0.5'), mpmath.mpf(0), mpmath.mpf('1e-8'), mpmath.mpf('0.5'), mpmath.mpf(5000000) ]: x = digammainv(y) assert mpmath.almosteq(mpmath.digamma(x), y)
def nll_grad(x, k, theta): """ Gamma distribution gradient of the negative log-likelihood function. """ _validate_k_theta(k, theta) k = mpmath.mpf(k) theta = mpmath.mpf(theta) N = len(x) sumx = mpmath.fsum(x) sumlnx = mpmath.fsum(mpmath.log(t) for t in x) dk = sumlnx - N*mpmath.log(theta) - N*mpmath.digamma(k) dtheta = sumx/theta**2 - N*k/theta return [-dk, -dtheta]
def digamma_at_integers(N): values = [np.nan] for n in range(1, N + 1): values.append(mpmath.digamma(n)) return values
def _mle_nu_func(nu, scale, R): # This function is used in mle() to solve log(nu) - digamma(nu) = R. nu = mpmath.mpf(nu) return mpmath.log(nu) - mpmath.digamma(nu) - R
def test_digamma_int(): x = np.arange(1, 11, dtype=np.float64) with mpmath.workdps(30): y = [float(mpmath.digamma(x0)) for x0 in x] assert_equal(sc.digamma(x), y)
def test_recurrence(): # Test that digammainv(digamma(x) + 1/x) == x + 1 with mpmath.workdps(50): for x in [mpmath.mpf('0.25'), mpmath.mpf(25)]: y = digammainv(mpmath.digamma(x) + 1 / x) assert mpmath.almosteq(y, x + 1)