Skip to main content

fixed_dsp/basic/
vlog.rs

1const LOG_Q15_ACCURACY: i32 = 15;
2const LOG_Q15_INTEGER_PART: i32 = 4;
3const LOQ_Q15_THRESHOLD: u32 = 1u32 << LOG_Q15_ACCURACY;
4const LOQ_Q15_Q16_HALF: u32 = LOQ_Q15_THRESHOLD;
5const LOG_Q15_INVLOG2EXP: i32 = 0x58b9; // 1.0 / ln(2) in Q15 format
6
7const LOG_Q31_ACCURACY: i32 = 31;
8const LOG_Q31_INTEGER_PART: i32 = 5;
9const LOQ_Q31_THRESHOLD: u64 = 1u64 << LOG_Q31_ACCURACY;
10const LOQ_Q31_Q32_HALF: u64 = LOQ_Q31_THRESHOLD;
11const LOG_Q31_INVLOG2EXP: i64 = 0x58b90bfb; // 1.0 / ln(2) in Q31 format
12
13fn log_i16(x: i16) -> i16 {
14    let src = x as u16 as u32;
15
16    let c = src.leading_zeros() as i32 - 16;
17    let normalization = c;
18
19    let mut inc: u32 = LOQ_Q15_Q16_HALF >> (LOG_Q15_INTEGER_PART + 1);
20
21    let mut xn = src;
22    if (c - 1) < 0 {
23        xn >>= 1 - c;
24    } else {
25        xn <<= c - 1;
26    }
27
28    let mut y: u32 = 0;
29
30    for _ in 0..LOG_Q15_ACCURACY {
31        xn = ((xn as i32 * xn as i32) >> (LOG_Q15_ACCURACY - 1)) as u32;
32
33        if xn >= LOQ_Q15_THRESHOLD {
34            y = y.wrapping_add(inc);
35            xn >>= 1;
36        }
37        inc >>= 1;
38    }
39
40    let tmp = y as i32 - (normalization << (LOG_Q15_ACCURACY - LOG_Q15_INTEGER_PART));
41    (((tmp as i64 * LOG_Q15_INVLOG2EXP as i64) >> 15) as i32) as i16
42}
43
44pub fn vlog_i16(input: &[i16], output: &mut [i16]) {
45    assert_eq!(
46        input.len(),
47        output.len(),
48        "input and output lengths must match"
49    );
50    for (x, y) in input.iter().zip(output.iter_mut()) {
51        *y = log_i16(*x);
52    }
53}
54
55pub fn vlog_i16_in_place(input: &mut [i16]) {
56    for x in input.iter_mut() {
57        *x = log_i16(*x);
58    }
59}
60
61fn log_i32(x: i32) -> i32 {
62    let src = x as u32;
63
64    let c = src.leading_zeros() as i32;
65    let normalization = c;
66
67    let mut inc: u64 = LOQ_Q31_Q32_HALF >> (LOG_Q31_INTEGER_PART + 1);
68
69    let mut xn = src as u64;
70    if (c - 1) < 0 {
71        xn >>= 1 - c;
72    } else {
73        xn <<= c - 1;
74    }
75
76    let mut y: u64 = 0;
77
78    for _ in 0..LOG_Q31_ACCURACY {
79        xn = ((xn * xn) >> (LOG_Q31_ACCURACY - 1)) as u64;
80
81        if xn >= LOQ_Q31_THRESHOLD {
82            y = y.wrapping_add(inc);
83            xn >>= 1;
84        }
85        inc >>= 1;
86    }
87
88    let tmp = y as i64 - ((normalization as i64) << (LOG_Q31_ACCURACY - LOG_Q31_INTEGER_PART));
89    ((tmp * LOG_Q31_INVLOG2EXP) >> 31) as i32
90}
91
92pub fn vlog_i32(input: &[i32], output: &mut [i32]) {
93    assert_eq!(
94        input.len(),
95        output.len(),
96        "input and output lengths must match"
97    );
98    for (x, y) in input.iter().zip(output.iter_mut()) {
99        *y = log_i32(*x);
100    }
101}
102
103pub fn vlog_i32_in_place(input: &mut [i32]) {
104    for x in input.iter_mut() {
105        *x = log_i32(*x);
106    }
107}