package comp import ( "golang.org/x/exp/constraints" ) func SumInts[I constraints.Integer](s []I) (sum I) { for _, x := range s { sum += x } return } func SumIntsAsFloats[I constraints.Integer, F constraints.Float](s []I) F { w := make([]F, len(s)) for i, x := range s { w[i] = F(x) } return SumFloats(w) } // SumFloats returns the exact sum (if IEEE 754 arithmetic is used). // See https://code.activestate.com/recipes/393090/ . // See information/"Shewchuk – Adaptive precision floating-point arithmetic and fast robust geometric predicates.pdf" . func SumFloats[F constraints.Float](s []F) (sum F) { var partials []F for _, x := range s { var i int for _, y := range partials { if Abs(x) < Abs(y) { x, y = y, x } high := x + y low := y - (high - x) if low != 0 { partials[i] = low i++ } x = high } partials = partials[:i] partials = append(partials, x) // fmt.Printf("i: %d, x: %g, partials: %g\n", i, x, partials) } // fmt.Println() for _, x := range partials { sum += x } return } // Mean returns the arithmetic mean (expected value, expectation) // or panics if the argument slice is empty. func Mean[F constraints.Float](s []F) F { if len(s) == 0 { panic("cannot calculate mean of empty slice") } return SumFloats(s) / F(len(s)) } // CumSum calculates the cumulative sum of a slice. func CumSum[F constraints.Float](s []F) []F { sums := make([]F, len(s)) for i := range s { sums[i] = SumFloats(s[:i+1]) } return sums }