nalgebra/examples/convolution.rs

98 lines
2.5 KiB
Rust
Raw Normal View History

2019-02-07 11:15:33 +08:00
extern crate nalgebra as na;
2019-02-10 10:19:42 +08:00
use na::storage::Storage;
2019-02-10 11:53:22 +08:00
use na::{zero, DVector, Dim, Dynamic, Matrix, Real, VecStorage, Vector, U1};
2019-02-07 11:15:33 +08:00
use std::cmp;
2019-02-10 10:19:42 +08:00
enum ConvolveMode {
2019-02-08 09:58:09 +08:00
Full,
Valid,
2019-02-10 10:19:42 +08:00
Same,
2019-02-08 09:58:09 +08:00
}
2019-02-07 11:15:33 +08:00
2019-02-08 09:58:09 +08:00
fn convolve_full<R: Real, D: Dim, E: Dim, S: Storage<R, D>, Q: Storage<R, E>>(
2019-02-10 10:19:42 +08:00
vector: Vector<R, D, S>,
kernel: Vector<R, E, Q>,
) -> Matrix<R, Dynamic, U1, VecStorage<R, Dynamic, U1>> {
let vec = vector.len();
let ker = kernel.len();
let newlen = vec + ker - 1;
let mut conv = DVector::<R>::zeros(newlen);
for i in 0..newlen {
2019-02-10 11:51:20 +08:00
let u_i = if i > ker { i - ker } else { 0 };
2019-02-10 10:19:42 +08:00
let u_f = cmp::min(i, vec - 1);
if u_i == u_f {
conv[i] += vector[u_i] * kernel[(i - u_i)];
} else {
for u in u_i..(u_f + 1) {
if i - u < ker {
conv[i] += vector[u] * kernel[(i - u)];
2019-02-08 09:58:09 +08:00
}
}
}
}
2019-02-10 10:19:42 +08:00
conv
}
2019-02-08 09:58:09 +08:00
fn convolve_valid<R: Real, D: Dim, E: Dim, S: Storage<R, D>, Q: Storage<R, E>>(
2019-02-10 10:19:42 +08:00
vector: Vector<R, D, S>,
kernel: Vector<R, E, Q>,
) -> Matrix<R, Dynamic, U1, VecStorage<R, Dynamic, U1>> {
let vec = vector.len();
let ker = kernel.len();
let newlen = vec - ker + 1;
2019-02-10 11:51:20 +08:00
2019-02-10 10:19:42 +08:00
let mut conv = DVector::<R>::zeros(newlen);
for i in 0..newlen {
for j in 0..ker {
conv[i] += vector[i + j] * kernel[ker - j - 1];
2019-02-07 11:15:33 +08:00
}
2019-02-08 09:58:09 +08:00
}
2019-02-10 10:19:42 +08:00
conv
}
2019-02-08 09:58:09 +08:00
fn convolve_same<R: Real, D: Dim, E: Dim, S: Storage<R, D>, Q: Storage<R, E>>(
2019-02-10 10:19:42 +08:00
vector: Vector<R, D, S>,
kernel: Vector<R, E, Q>,
) -> Matrix<R, Dynamic, U1, VecStorage<R, Dynamic, U1>> {
let vec = vector.len();
let ker = kernel.len();
2019-02-10 11:51:20 +08:00
let mut conv = DVector::<R>::zeros(vec);
2019-02-10 10:19:42 +08:00
2019-02-10 11:51:20 +08:00
for i in 0..vec {
for j in 0..ker {
let val = if i + j < 1 || i + j >= vec + 1 {
zero::<R>()
} else {
vector[i + j - 1]
};
conv[i] += val * kernel[ker - j - 1];
}
2019-02-08 09:58:09 +08:00
}
2019-02-10 10:19:42 +08:00
conv
}
2019-02-08 09:58:09 +08:00
fn convolve<R: Real, D: Dim, E: Dim, S: Storage<R, D>, Q: Storage<R, E>>(
2019-02-10 10:19:42 +08:00
vector: Vector<R, D, S>,
kernel: Vector<R, E, Q>,
mode: Option<ConvolveMode>,
) -> Matrix<R, Dynamic, U1, VecStorage<R, Dynamic, U1>> {
if kernel.len() > vector.len() {
return convolve(kernel, vector, mode);
2019-02-07 11:15:33 +08:00
}
2019-02-10 10:19:42 +08:00
match mode.unwrap_or(ConvolveMode::Full) {
ConvolveMode::Full => return convolve_full(vector, kernel),
ConvolveMode::Valid => return convolve_valid(vector, kernel),
ConvolveMode::Same => return convolve_same(vector, kernel),
}
}
2019-02-07 11:15:33 +08:00
fn main() {
2019-02-10 11:53:22 +08:00
2019-02-10 10:19:42 +08:00
}