Skip to main content

fixed_dsp/basic/
div.rs

1use crate::common::error::{Error, Result};
2
3/// Fixed-point division for Q15 values.
4///
5/// The returned pair `(quotient, shift)` represents:
6/// `numerator / denominator = quotient * 2^shift`, where `quotient` is normalized.
7///
8/// On divide-by-zero, [`Error::NanInf`] is returned.
9pub fn div_i16(numerator: i16, denominator: i16) -> Result<(i16, i16)> {
10    let mut shift = 0_i16;
11
12    if denominator == 0 {
13        return Err(Error::NanInf);
14    }
15
16    let numerator_abs = numerator.saturating_abs();
17    let denominator_abs = denominator.saturating_abs();
18
19    let mut temp = ((numerator_abs as i32) << 15) / (denominator_abs as i32);
20
21    let shift_for_normalizing = 17 - (temp as u32).leading_zeros() as i16;
22    if shift_for_normalizing > 0 {
23        shift = shift_for_normalizing;
24        temp >>= shift_for_normalizing;
25    }
26
27    if (numerator < 0) ^ (denominator < 0) {
28        temp = -temp;
29    }
30
31    let quotient = temp as i16;
32    Ok((quotient, shift))
33}
34
35/// Fixed-point division for Q31 values.
36///
37/// The returned pair `(quotient, shift)` represents:
38/// `numerator / denominator = quotient * 2^shift`, where `quotient` is normalized.
39///
40/// On divide-by-zero, [`Error::NanInf`] is returned.
41pub fn div_i32(numerator: i32, denominator: i32) -> Result<(i32, i16)> {
42    let mut shift = 0_i16;
43
44    if denominator == 0 {
45        return Err(Error::NanInf);
46    }
47
48    let numerator_abs = numerator.saturating_abs();
49    let denominator_abs = denominator.saturating_abs();
50
51    let mut temp = ((numerator_abs as i64) << 31) / (denominator_abs as i64);
52
53    let shift_for_normalizing = 32 - ((temp >> 31) as u32).leading_zeros() as i16;
54    if shift_for_normalizing > 0 {
55        shift = shift_for_normalizing;
56        temp >>= shift_for_normalizing;
57    }
58
59    if (numerator < 0) ^ (denominator < 0) {
60        temp = -temp;
61    }
62
63    let quotient = temp as i32;
64    Ok((quotient, shift))
65}