#[inline]
fn mirror(mut i: isize, len: usize) -> usize {
let n = len as isize;
if n == 1 {
return 0;
}
if i < 0 {
i = -i;
}
let period = 2 * (n - 1);
i %= period;
if i >= n {
i = period - i;
}
i as usize
}
pub fn dwt53_forward_1d(data: &mut [i32]) {
let n = data.len();
if n <= 1 {
return;
}
let n_low = (n + 1) / 2;
let n_high = n / 2;
let src = data.to_vec();
let mut low: Vec<i32> = (0..n_low).map(|i| src[2 * i]).collect();
let mut high: Vec<i32> = (0..n_high).map(|i| src[2 * i + 1]).collect();
for i in 0..n_high {
let left = low[i];
let right_idx = i + 1;
let right = if right_idx < n_low {
low[right_idx]
} else {
low[mirror((right_idx) as isize, n_low)]
};
high[i] -= (left + right) >> 1;
}
for i in 0..n_low {
let left = if i == 0 {
high[mirror(-1_isize, n_high.max(1))]
} else {
high[i - 1]
};
let right = if i < n_high {
high[i]
} else {
high[mirror(i as isize, n_high.max(1))]
};
low[i] += (left + right + 2) >> 2;
}
data[..n_low].copy_from_slice(&low);
data[n_low..].copy_from_slice(&high);
}
pub fn dwt53_inverse_1d(data: &mut [i32]) {
let n = data.len();
if n <= 1 {
return;
}
let n_low = (n + 1) / 2;
let n_high = n / 2;
let mut low = data[..n_low].to_vec();
let mut high = data[n_low..].to_vec();
for i in 0..n_low {
let left = if i == 0 {
high[mirror(-1_isize, n_high.max(1))]
} else {
high[i - 1]
};
let right = if i < n_high {
high[i]
} else {
high[mirror(i as isize, n_high.max(1))]
};
low[i] -= (left + right + 2) >> 2;
}
for i in 0..n_high {
let left = low[i];
let right_idx = i + 1;
let right = if right_idx < n_low {
low[right_idx]
} else {
low[mirror(right_idx as isize, n_low)]
};
high[i] += (left + right) >> 1;
}
for i in 0..n_low {
data[2 * i] = low[i];
}
for i in 0..n_high {
data[2 * i + 1] = high[i];
}
}
pub fn dwt53_forward_2d(data: &mut [i32], width: usize, height: usize, levels: usize) {
let mut w = width;
let mut h = height;
for _ in 0..levels {
if w <= 1 && h <= 1 {
break;
}
for row in 0..h {
let mut row_buf: Vec<i32> = (0..w).map(|c| data[row * width + c]).collect();
dwt53_forward_1d(&mut row_buf);
for c in 0..w {
data[row * width + c] = row_buf[c];
}
}
for col in 0..w {
let mut col_buf: Vec<i32> = (0..h).map(|r| data[r * width + col]).collect();
dwt53_forward_1d(&mut col_buf);
for r in 0..h {
data[r * width + col] = col_buf[r];
}
}
w = (w + 1) / 2;
h = (h + 1) / 2;
}
}
pub fn dwt53_inverse_2d(data: &mut [i32], width: usize, height: usize, levels: usize) {
let mut sizes: Vec<(usize, usize)> = Vec::new();
let mut w = width;
let mut h = height;
for _ in 0..levels {
if w <= 1 && h <= 1 {
break;
}
sizes.push((w, h));
w = (w + 1) / 2;
h = (h + 1) / 2;
}
for &(w, h) in sizes.iter().rev() {
for col in 0..w {
let mut col_buf: Vec<i32> = (0..h).map(|r| data[r * width + col]).collect();
dwt53_inverse_1d(&mut col_buf);
for r in 0..h {
data[r * width + col] = col_buf[r];
}
}
for row in 0..h {
let mut row_buf: Vec<i32> = (0..w).map(|c| data[row * width + c]).collect();
dwt53_inverse_1d(&mut row_buf);
for c in 0..w {
data[row * width + c] = row_buf[c];
}
}
}
}
const ALPHA: f64 = -1.586134342;
const BETA: f64 = -0.052980118;
const GAMMA: f64 = 0.882911075;
const DELTA: f64 = 0.443506852;
const K: f64 = 1.230174105;
const INV_K: f64 = 1.0 / 1.230174105;
#[inline]
fn mirror_f(i: isize, len: usize) -> usize {
mirror(i, len)
}
pub fn dwt97_forward_1d(data: &mut [f64]) {
let n = data.len();
if n <= 1 {
return;
}
let n_low = (n + 1) / 2;
let n_high = n / 2;
let src = data.to_vec();
let mut low: Vec<f64> = (0..n_low).map(|i| src[2 * i]).collect();
let mut high: Vec<f64> = (0..n_high).map(|i| src[2 * i + 1]).collect();
for i in 0..n_high {
let left = low[i];
let right = low[mirror_f(i as isize + 1, n_low)];
high[i] += ALPHA * (left + right);
}
for i in 0..n_low {
let left = high[mirror_f(i as isize - 1, n_high.max(1))];
let right = high[mirror_f(i as isize, n_high.max(1))];
low[i] += BETA * (left + right);
}
for i in 0..n_high {
let left = low[i];
let right = low[mirror_f(i as isize + 1, n_low)];
high[i] += GAMMA * (left + right);
}
for i in 0..n_low {
let left = high[mirror_f(i as isize - 1, n_high.max(1))];
let right = high[mirror_f(i as isize, n_high.max(1))];
low[i] += DELTA * (left + right);
}
for v in low.iter_mut() {
*v *= INV_K;
}
for v in high.iter_mut() {
*v *= K;
}
data[..n_low].copy_from_slice(&low);
data[n_low..].copy_from_slice(&high);
}
pub fn dwt97_inverse_1d(data: &mut [f64]) {
let n = data.len();
if n <= 1 {
return;
}
let n_low = (n + 1) / 2;
let n_high = n / 2;
let mut low = data[..n_low].to_vec();
let mut high = data[n_low..].to_vec();
for v in low.iter_mut() {
*v *= K;
}
for v in high.iter_mut() {
*v *= INV_K;
}
for i in 0..n_low {
let left = high[mirror_f(i as isize - 1, n_high.max(1))];
let right = high[mirror_f(i as isize, n_high.max(1))];
low[i] -= DELTA * (left + right);
}
for i in 0..n_high {
let left = low[i];
let right = low[mirror_f(i as isize + 1, n_low)];
high[i] -= GAMMA * (left + right);
}
for i in 0..n_low {
let left = high[mirror_f(i as isize - 1, n_high.max(1))];
let right = high[mirror_f(i as isize, n_high.max(1))];
low[i] -= BETA * (left + right);
}
for i in 0..n_high {
let left = low[i];
let right = low[mirror_f(i as isize + 1, n_low)];
high[i] -= ALPHA * (left + right);
}
for i in 0..n_low {
data[2 * i] = low[i];
}
for i in 0..n_high {
data[2 * i + 1] = high[i];
}
}
pub fn dwt97_forward_2d(data: &mut [f64], width: usize, height: usize, levels: usize) {
let mut w = width;
let mut h = height;
for _ in 0..levels {
if w <= 1 && h <= 1 {
break;
}
for row in 0..h {
let mut row_buf: Vec<f64> = (0..w).map(|c| data[row * width + c]).collect();
dwt97_forward_1d(&mut row_buf);
for c in 0..w {
data[row * width + c] = row_buf[c];
}
}
for col in 0..w {
let mut col_buf: Vec<f64> = (0..h).map(|r| data[r * width + col]).collect();
dwt97_forward_1d(&mut col_buf);
for r in 0..h {
data[r * width + col] = col_buf[r];
}
}
w = (w + 1) / 2;
h = (h + 1) / 2;
}
}
pub fn dwt97_inverse_2d(data: &mut [f64], width: usize, height: usize, levels: usize) {
let mut sizes: Vec<(usize, usize)> = Vec::new();
let mut w = width;
let mut h = height;
for _ in 0..levels {
if w <= 1 && h <= 1 {
break;
}
sizes.push((w, h));
w = (w + 1) / 2;
h = (h + 1) / 2;
}
for &(w, h) in sizes.iter().rev() {
for col in 0..w {
let mut col_buf: Vec<f64> = (0..h).map(|r| data[r * width + col]).collect();
dwt97_inverse_1d(&mut col_buf);
for r in 0..h {
data[r * width + col] = col_buf[r];
}
}
for row in 0..h {
let mut row_buf: Vec<f64> = (0..w).map(|c| data[row * width + c]).collect();
dwt97_inverse_1d(&mut row_buf);
for c in 0..w {
data[row * width + c] = row_buf[c];
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn mirror_basic() {
assert_eq!(mirror(-1, 4), 1);
assert_eq!(mirror(4, 4), 2);
assert_eq!(mirror(0, 1), 0);
assert_eq!(mirror(3, 4), 3);
}
#[test]
fn dwt53_roundtrip_simple() {
let original = vec![1, 2, 3, 4, 5, 6, 7, 8];
let mut data = original.clone();
dwt53_forward_1d(&mut data);
dwt53_inverse_1d(&mut data);
assert_eq!(data, original);
}
}