export function* range( start: number, end: number, step = 1, ): Generator { for (let i = start; i < end; i += step) yield i } export type List = IteratorObject | T[] export function count(): (previous: T, current: T) => number { let count = 1 let first = false return () => { if (first) { count++ first = false } return count++ } } export function sum(previous: number, current: number) { return previous + current } export function mean(): (mean: number, value: number) => number { let count = 0 let total = 0 let first = true return (mean: number, value: number) => { if (first) { total = mean first = false } count++ total += value return total / count } } export function stdDeviation(list: List): number { let count = 0 const meanValue = list.reduce(mean()) const deviation = list.reduce((dev, value) => { count++ return dev + (value - meanValue) ** 2 }, 0) return Math.sqrt(deviation / (count - 1)) } export function min(min: number, value: number): number { return value < min ? value : min } export function max(max: number, value: number): number { return value > max ? value : max } export function makeBins(count: number, array: number[]): number[] { const bins: number[] = new Array(count + 1).fill(0) const minValue = array.reduce(min) const maxValue = array.reduce(max) const size = (maxValue - minValue) / count array.forEach((value) => { for (const step of range(0, count + 1)) { if ( value >= minValue + step * size && value < minValue + (step + 1) * size ) { bins[step]++ break } } }) return bins }