github.com/fluhus/gostuff@v0.4.1-0.20240331134726-be71864f2b5d/gnum/gnum.go (about) 1 // Package gnum provides generic numerical functions. 2 package gnum 3 4 import ( 5 "fmt" 6 "math" 7 8 "golang.org/x/exp/constraints" 9 ) 10 11 // Number is a constraint that contains comparable numbers. 12 type Number interface { 13 constraints.Float | constraints.Integer 14 } 15 16 // Max returns the maximal value in the slice or zero if the slice is empty. 17 func Max[S ~[]N, N constraints.Ordered](s S) N { 18 var e N 19 for i, v := range s { 20 if i == 0 || v > e { 21 e = v 22 } 23 } 24 return e 25 } 26 27 // Min returns the maximal value in the slice or zero if the slice is empty. 28 func Min[S ~[]N, N constraints.Ordered](s S) N { 29 var e N 30 for i, v := range s { 31 if i == 0 || v < e { 32 e = v 33 } 34 } 35 return e 36 } 37 38 // Abs returns the absolute value of n. 39 func Abs[N Number](n N) N { 40 if n < 0 { 41 return -n 42 } 43 return n 44 } 45 46 // Diff returns the non-negative difference between a and b. 47 func Diff[N Number](a, b N) N { 48 if a > b { 49 return a - b 50 } 51 return b - a 52 } 53 54 // Sum returns the sum of the slice. 55 func Sum[S ~[]N, N Number](a S) N { 56 var sum N 57 for _, v := range a { 58 sum += v 59 } 60 return sum 61 } 62 63 // Mean returns the average of the slice. 64 func Mean[S ~[]N, N Number](a S) float64 { 65 return float64(Sum(a)) / float64(len(a)) 66 } 67 68 // Cov returns the covariance of a and b. 69 func Cov[S ~[]N, N Number](a, b S) float64 { 70 assertMatchingLengths(a, b) 71 ma := Mean(a) 72 mb := Mean(b) 73 cov := 0.0 74 for i := range a { 75 cov += (float64(a[i]) - ma) * (float64(b[i]) - mb) 76 } 77 cov /= float64(len(a)) 78 return cov 79 } 80 81 // Var returns the variance of a. 82 func Var[S ~[]N, N Number](a S) float64 { 83 return Cov(a, a) 84 } 85 86 // Std returns the standard deviation of a. 87 func Std[S ~[]N, N Number](a S) float64 { 88 return math.Sqrt(Var(a)) 89 } 90 91 // Corr returns the Pearson correlation between the a and b. 92 func Corr[S ~[]N, N Number](a, b S) float64 { 93 return Cov(a, b) / Std(a) / Std(b) 94 } 95 96 // Entropy returns the Shannon-entropy of a. 97 // The elements in a don't have to sum up to 1. 98 func Entropy[S ~[]N, N Number](a S) float64 { 99 sum := float64(Sum(a)) 100 result := 0.0 101 for i, v := range a { 102 if v < 0.0 { 103 panic(fmt.Sprintf("negative value at position %d: %v", 104 i, v)) 105 } 106 if v == 0 { 107 continue 108 } 109 p := float64(v) / sum 110 result -= p * math.Log2(p) 111 } 112 return result 113 }