/// 工具函数模块
/// 提供数值计算、数组操作、查找交点等工具函数
///|
/// 查找两个数组的交点索引
/// 返回交点的索引数组(在交点之前的索引)
pub fn nearest_intersection_idx(
a : Array[Double],
b : Array[Double],
) -> Array[Int] {
if a.length() != b.length() {
[]
} else {
let diff = Array::make(a.length(), 0.0)
for i = 0; i < a.length(); i = i + 1 {
diff[i] = a[i] - b[i]
}
let sign_changes = Array::make(0, 0)
for i = 0; i < diff.length() - 1; i = i + 1 {
let sign1 = if diff[i] >= 0.0 { 1 } else { -1 }
let sign2 = if diff[i + 1] >= 0.0 { 1 } else { -1 }
if sign1 != sign2 {
sign_changes.push(i)
}
}
sign_changes
}
}
///|
/// 计算一维数组的一阶导数(使用中心差分)
/// f: 函数值数组
/// x: 坐标数组(可选,如果为None则使用均匀间距)
/// 返回导数数组
pub fn first_derivative(f : Array[Double], x : Array[Double]?) -> Array[Double] {
let n = f.length()
if n < 2 {
[]
} else {
let delta = match x {
Some(x_arr) => {
let d = Array::make(n - 1, 0.0)
for i = 0; i < n - 1; i = i + 1 {
d[i] = x_arr[i + 1] - x_arr[i]
}
d
}
None => Array::make(n - 1, 1.0) // 均匀间距为1
}
let deriv = Array::make(n, 0.0)
// 左边界:前向差分
if n > 1 {
deriv[0] = (f[1] - f[0]) / delta[0]
}
// 中间点:中心差分
for i = 1; i < n - 1; i = i + 1 {
let h = (delta[i - 1] + delta[i]) / 2.0
deriv[i] = (f[i + 1] - f[i - 1]) / (2.0 * h)
}
// 右边界:后向差分
if n > 1 {
deriv[n - 1] = (f[n - 1] - f[n - 2]) / delta[n - 2]
}
deriv
}
}
///|
/// 计算一维数组的二阶导数
pub fn second_derivative(
f : Array[Double],
x : Array[Double]?,
) -> Array[Double] {
let n = f.length()
if n < 3 {
Array::make(n, 0.0)
} else {
let delta = match x {
Some(x_arr) => {
let d = Array::make(n - 1, 0.0)
for i = 0; i < n - 1; i = i + 1 {
d[i] = x_arr[i + 1] - x_arr[i]
}
d
}
None => Array::make(n - 1, 1.0)
}
let deriv2 = Array::make(n, 0.0)
// 左边界
if n > 2 {
let h = delta[0]
deriv2[0] = (f[2] - 2.0 * f[1] + f[0]) / (h * h)
}
// 中间点
for i = 1; i < n - 1; i = i + 1 {
let h = (delta[i - 1] + delta[i]) / 2.0
deriv2[i] = (f[i + 1] - 2.0 * f[i] + f[i - 1]) / (h * h)
}
// 右边界
if n > 2 {
let h = delta[n - 2]
deriv2[n - 1] = (f[n - 1] - 2.0 * f[n - 2] + f[n - 3]) / (h * h)
}
deriv2
}
}
///|
/// 移除 NaN 值(返回非 NaN 值的数组)
/// 注意:MoonBit 的 Double 可能不支持 NaN,这里提供接口以备将来扩展
pub fn remove_nans(arr : Array[Double]) -> Array[Double] {
// MoonBit 目前 Double 不支持 NaN,这里返回原数组
// 如果将来支持,可以添加 NaN 检查逻辑
arr
}
///|
/// 判断两个值是否接近(类似 numpy.isclose)
pub fn is_close(a : Double, b : Double, rtol? : Double, atol? : Double) -> Bool {
let rtol_val = match rtol {
Some(v) => v
None => 0.00001
}
let atol_val = match atol {
Some(v) => v
None => 0.00000001
}
let diff = if a > b { a - b } else { b - a }
diff <= atol_val + rtol_val * (if a > b { a } else { b })
}
///|
/// 比较值是否大于或接近目标值(用于容差比较)
pub fn greater_or_close(
a : Double,
value : Double,
rtol? : Double,
atol? : Double,
) -> Bool {
a > value || is_close(a, value, rtol?, atol?)
}
///|
/// 比较值是否小于或接近目标值
pub fn less_or_close(
a : Double,
value : Double,
rtol? : Double,
atol? : Double,
) -> Bool {
a < value || is_close(a, value, rtol?, atol?)
}
///|
/// 查找数组中的峰值(局部最大值或最小值)
/// arr: 输入数组
/// maxima: true 查找最大值,false 查找最小值
/// 返回峰值索引数组
pub fn find_peaks(arr : Array[Double], maxima? : Bool) -> Array[Int] {
let maxima_val = match maxima {
Some(v) => v
None => true
}
let peaks = Array::make(0, 0)
let n = arr.length()
if n < 3 {
peaks
} else {
for i = 1; i < n - 1; i = i + 1 {
let is_peak = if maxima_val {
arr[i] > arr[i - 1] && arr[i] > arr[i + 1]
} else {
arr[i] < arr[i - 1] && arr[i] < arr[i + 1]
}
if is_peak {
peaks.push(i)
}
}
peaks
}
}
///|
/// 查找数组中值在指定范围内的索引
pub fn find_indices_in_range(
arr : Array[Double],
min_val : Double,
max_val : Double,
) -> Array[Int] {
let indices = Array::make(0, 0)
for i = 0; i < arr.length(); i = i + 1 {
if arr[i] >= min_val && arr[i] <= max_val {
indices.push(i)
}
}
indices
}
///|
/// 线性插值
/// x: 要插值的 x 坐标
/// x_arr: 已知 x 坐标数组(必须单调递增)
/// y_arr: 对应的 y 值数组
/// 返回插值结果
pub fn linear_interpolate(
x : Double,
x_arr : Array[Double],
y_arr : Array[Double],
) -> Double? {
let n = x_arr.length()
if n != y_arr.length() || n < 2 {
None
} else if x < x_arr[0] || x > x_arr[n - 1] {
None // 超出范围
} else {
// 查找 x 所在的区间
let mut i = 0
while i < n - 1 && x_arr[i + 1] < x {
i = i + 1
}
if i >= n - 1 {
Some(y_arr[n - 1])
} else {
let x0 = x_arr[i]
let x1 = x_arr[i + 1]
let y0 = y_arr[i]
let y1 = y_arr[i + 1]
let dx = x1 - x0
if dx == 0.0 {
Some(y0)
} else {
let t = (x - x0) / dx
Some(y0 + t * (y1 - y0))
}
}
}
}
///|
/// 计算数组的统计信息
pub struct Stats {
min : Double
max : Double
mean : Double
sum : Double
}
///|
pub fn array_stats(arr : Array[Double]) -> Stats {
if arr.length() == 0 {
Stats::{ min: 0.0, max: 0.0, mean: 0.0, sum: 0.0 }
} else {
let mut min_val : Double = arr[0]
let mut max_val : Double = arr[0]
let mut sum_val : Double = 0.0
for i = 0; i < arr.length(); i = i + 1 {
let val : Double = arr[i]
if val < min_val {
min_val = val
}
if val > max_val {
max_val = val
}
sum_val = sum_val + val
}
let mean_val : Double = sum_val / Double::from_int(arr.length())
Stats::{ min: min_val, max: max_val, mean: mean_val, sum: sum_val }
}
}
///|
/// 计算数组的梯度(一阶导数,均匀间距)
pub fn gradient(arr : Array[Double]) -> Array[Double] {
first_derivative(arr, None)
}