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]; let b = [0x4000_i16, 0x2000_i16, 0x4000_i16]; let mut out = [0_i16; 3];
30
31 mul_i16(&a, &b, &mut out);
32
33 assert_eq!(out, [0x2000, 0x1000, -0x2000]); }
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]; let b = [0x4000_0000_i32, 0x2000_0000_i32, 0x4000_0000_i32]; 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}