Skip to main content

fixed_dsp/basic/
mul.rs

1use crate::{sat_i16, sat_i32};
2
3pub fn mul_i16(a: &[i16], b: &[i16], output: &mut [i16]) {
4    output
5        .iter_mut()
6        .zip(a.iter().zip(b.iter()))
7        .for_each(|(out, (&x, &y))| {
8            *out = sat_i16((x as i32 * y as i32) >> 15);
9        });
10}
11
12pub fn mul_i32(a: &[i32], b: &[i32], output: &mut [i32]) {
13    output
14        .iter_mut()
15        .zip(a.iter().zip(b.iter()))
16        .for_each(|(out, (&x, &y))| {
17            *out = sat_i32((x as i64 * y as i64) >> 31);
18        });
19}
20
21#[cfg(test)]
22mod tests {
23    use super::*;
24
25    #[test]
26    fn mul_i16_basic_q15_scaling() {
27        let a = [0x4000_i16, 0x4000_i16, -0x4000_i16]; // 0.5, 0.5, -0.5
28        let b = [0x4000_i16, 0x2000_i16, 0x4000_i16]; // 0.5, 0.25, 0.5
29        let mut out = [0_i16; 3];
30
31        mul_i16(&a, &b, &mut out);
32
33        assert_eq!(out, [0x2000, 0x1000, -0x2000]); // 0.25, 0.125, -0.25
34    }
35
36    #[test]
37    fn mul_i16_saturates_at_positive_limit() {
38        let a = [i16::MIN];
39        let b = [i16::MIN];
40        let mut out = [0_i16; 1];
41
42        mul_i16(&a, &b, &mut out);
43
44        assert_eq!(out[0], i16::MAX);
45    }
46
47    #[test]
48    fn mul_i32_basic_q31_scaling() {
49        let a = [0x4000_0000_i32, 0x4000_0000_i32, -0x4000_0000_i32]; // 0.5, 0.5, -0.5
50        let b = [0x4000_0000_i32, 0x2000_0000_i32, 0x4000_0000_i32]; // 0.5, 0.25, 0.5
51        let mut out = [0_i32; 3];
52
53        mul_i32(&a, &b, &mut out);
54
55        assert_eq!(out, [0x2000_0000, 0x1000_0000, -0x2000_0000]);
56    }
57
58    #[test]
59    fn mul_i32_saturates_at_positive_limit() {
60        let a = [i32::MIN];
61        let b = [i32::MIN];
62        let mut out = [0_i32; 1];
63
64        mul_i32(&a, &b, &mut out);
65
66        assert_eq!(out[0], i32::MAX);
67    }
68}