add digamma and associated tests (#22)

* add digamma and associated tests

* add note on behavior for integers between -7 and 0

This implements the digamma function, and the results match with WolframAlpha. To the best of my knowledge there isn't an implementation in go, although someone was looking for it at SO.

I ported the code from http://web.science.mq.edu.au/~mjohnson/code/digamma.c - his page http://web.science.mq.edu.au/~mjohnson/Software.htm indicates that it can be used as long as he is acknowledged.

I figured there was a tricky way to speed up the difference in log gammas in the mvdist student pdf function, and ran across http://www.johndcook.com/blog/2012/07/14/log-gamma-differences/ (he sure pops up a lot), and found that we don't have an implementation of digamma, and for that matter, no golang projects seem to.

An alternative implementation could use the Chebychev approximations in http://www.ams.org/journals/mcom/1961-15-074/S0025-5718-61-99221-3/S0025-5718-61-99221-3.pdf which might be worth investigating.  There remains some question as to whether the -inf response on integers in [-7,0] is appropriate, or if it should panic or NaN.
This commit is contained in:
Jonathan J Lawlor
2016-10-28 09:13:04 -04:00
committed by GitHub
parent 7f7842bba1
commit c2efe52d56
2 changed files with 55 additions and 0 deletions

27
digamma_test.go Normal file
View File

@@ -0,0 +1,27 @@
// Copyright ©2016 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package mathext
import (
"math"
"testing"
)
func TestDigamma(t *testing.T) {
for i, test := range []struct {
x, want float64
}{
// Results computed using WolframAlpha.
{-100.5, 4.615124601338064117341315601525112558522917517910505881343},
{.5, -1.96351002602142347944097633299875556719315960466043},
{10, 2.251752589066721107647456163885851537211808918028330369448},
{math.Pow10(20), 46.05170185988091368035482909368728415202202143924212618733},
} {
if got := Digamma(test.x); math.Abs(got-test.want) > 1e-10 {
t.Errorf("test %d Digamma(%g) failed: got %g want %g", i, test.x, got, test.want)
}
}
}