1#![allow(
29    clippy::excessive_precision,
30    clippy::unreadable_literal,
31    clippy::module_name_repetitions,
32    unused_parens,
33    clippy::wildcard_imports
34)]
35
36use zune_core::log::debug;
37use zune_core::options::DecoderOptions;
38
39use crate::decoder::IDCTPtr;
40use crate::idct::scalar::idct_int;
41
42#[cfg(feature = "x86")]
43pub mod avx2;
44#[cfg(feature = "neon")]
45pub mod neon;
46
47pub mod scalar;
48
49#[allow(unused_variables)]
51pub fn choose_idct_func(options: &DecoderOptions) -> IDCTPtr {
52    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
53    #[cfg(feature = "x86")]
54    {
55        if options.use_avx2() {
56            debug!("Using vector integer IDCT");
57            return crate::idct::avx2::idct_avx2;
59        }
60    }
61    #[cfg(target_arch = "aarch64")]
62    #[cfg(feature = "neon")]
63    {
64        if options.use_neon() {
65            debug!("Using vector integer IDCT");
66            return crate::idct::neon::idct_neon;
67        }
68    }
69    debug!("Using scalar integer IDCT");
70    return idct_int;
72}
73
74#[cfg(test)]
75#[allow(unreachable_code)]
76#[allow(dead_code)]
77mod tests {
78    use super::*;
79
80    #[test]
81    fn idct_test0() {
82        let stride = 8;
83        let mut coeff = [10; 64];
84        let mut coeff2 = [10; 64];
85        let mut output_scalar = [0; 64];
86        let mut output_vector = [0; 64];
87        idct_fnc()(&mut coeff, &mut output_vector, stride);
88        idct_int(&mut coeff2, &mut output_scalar, stride);
89        assert_eq!(output_scalar, output_vector, "IDCT and scalar do not match");
90    }
91
92    #[test]
93    fn do_idct_test1() {
94        let stride = 8;
95        let mut coeff = [14; 64];
96        let mut coeff2 = [14; 64];
97        let mut output_scalar = [0; 64];
98        let mut output_vector = [0; 64];
99        idct_fnc()(&mut coeff, &mut output_vector, stride);
100        idct_int(&mut coeff2, &mut output_scalar, stride);
101        assert_eq!(output_scalar, output_vector, "IDCT and scalar do not match");
102    }
103
104    #[test]
105    fn do_idct_test2() {
106        let stride = 8;
107        let mut coeff = [0; 64];
108        coeff[0] = 255;
109        coeff[63] = -256;
110        let mut coeff2 = coeff;
111        let mut output_scalar = [0; 64];
112        let mut output_vector = [0; 64];
113        idct_fnc()(&mut coeff, &mut output_vector, stride);
114        idct_int(&mut coeff2, &mut output_scalar, stride);
115        assert_eq!(output_scalar, output_vector, "IDCT and scalar do not match");
116    }
117
118    #[test]
119    fn do_idct_zeros() {
120        let stride = 8;
121        let mut coeff = [0; 64];
122        let mut coeff2 = [0; 64];
123        let mut output_scalar = [0; 64];
124        let mut output_vector = [0; 64];
125        idct_fnc()(&mut coeff, &mut output_vector, stride);
126        idct_int(&mut coeff2, &mut output_scalar, stride);
127        assert_eq!(output_scalar, output_vector, "IDCT and scalar do not match");
128    }
129
130    fn idct_fnc() -> IDCTPtr {
131        #[cfg(feature = "neon")]
132        #[cfg(target_arch = "aarch64")]
133        {
134            use crate::idct::neon::idct_neon;
135            return idct_neon;
136        }
137
138        #[cfg(feature = "x86")]
139        #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
140        {
141            use crate::idct::avx2::idct_avx2;
142            return idct_avx2;
143        }
144
145        idct_int
146    }
147}