///|
pub fn sliding_windows(
values : ArrayView[Double],
width : Int,
stride : Int,
) -> Array[Array[Double]] {
let output : Array[Array[Double]] = []
if width > 0 && stride > 0 {
let mut start = 0
while start + width <= values.length() {
let window = Array::makei(width, fn(i) { values[start + i] })
output.push(window)
start = start + stride
}
}
output
}
///|
pub fn window_means(
values : ArrayView[Double],
width : Int,
stride : Int,
) -> Array[Double] {
sliding_windows(values, width, stride).map(fn(window) { mean(window) })
}
///|
pub fn moving_average(values : ArrayView[Double], width : Int) -> Array[Double] {
let output = zeros(values.length())
if width > 0 {
for i in 0.. Array[Double] {
let output = zeros(values.length())
if values.length() > 0 {
let mut current = values[0]
for i in 0.. Array[Double] {
let output = zeros(values.length())
if values.length() > 0 {
let mut current = values[0]
for i in 0.. Array[Double] {
let minimum = min_value(values, 0.0)
let span = max_value(values, 0.0) - minimum
if span == 0.0 {
values.map(fn(_) { 0.0 })
} else {
values.map(fn(value) { (value - minimum) / span })
}
}
///|
pub fn covariance(
first : ArrayView[Double],
second : ArrayView[Double],
) -> Double {
let count = if first.length() < second.length() {
first.length()
} else {
second.length()
}
if count == 0 {
0.0
} else {
let first_mean = mean(first)
let second_mean = mean(second)
let mut total = 0.0
for i in 0.. Double {
let denominator = sample_variance(first).sqrt() *
sample_variance(second).sqrt()
safe_ratio(covariance(first, second), denominator, 0.0)
}
///|
pub fn downsample_mean(
values : ArrayView[Double],
factor : Int,
) -> Array[Double] {
if factor <= 0 {
[]
} else {
let count = values.length() / factor
Array::makei(count, fn(i) {
mean(Array::makei(factor, fn(j) { values[i * factor + j] }))
})
}
}
///|
pub fn interpolate_series(
values : ArrayView[Double],
count : Int,
) -> Array[Double] {
if count <= 0 || values.length() == 0 {
[]
} else if values.length() == 1 {
Array::make(count, values[0])
} else {
Array::makei(count, fn(i) {
let position = i.to_double() *
(values.length() - 1).to_double() /
(count - 1).max(1).to_double()
let left = position.to_int()
let fraction = position - left.to_double()
lerp(values[left], values[(left + 1).min(values.length() - 1)], fraction)
})
}
}
///|
pub fn analysis_summary(values : ArrayView[Double]) -> String {
let summary = summarize_series("values", values)
summary_to_csv(summary)
}