Thanks to visit codestin.com
Credit goes to docs.rs

arrayfire/signal/
mod.rs

1use super::core::{
2    af_array, dim_t, AfError, Array, ComplexFloating, ConvDomain, ConvMode, FloatingPoint,
3    HasAfEnum, InterpType, RealFloating, HANDLE_ERROR,
4};
5
6use libc::{c_double, c_float, c_int, c_uint, size_t};
7use num::Complex;
8
9extern "C" {
10    fn af_approx1(
11        out: *mut af_array,
12        inp: af_array,
13        pos: af_array,
14        method: c_uint,
15        off_grid: c_float,
16    ) -> c_int;
17
18    fn af_approx1_v2(
19        out: *mut af_array,
20        inp: af_array,
21        pos: af_array,
22        method: c_uint,
23        off_grid: c_float,
24    ) -> c_int;
25
26    fn af_approx1_uniform(
27        out: *mut af_array,
28        inp: af_array,
29        pos: af_array,
30        interp_dim: c_int,
31        idx_start: c_double,
32        idx_step: c_double,
33        method: c_uint,
34        off_grid: c_float,
35    ) -> c_int;
36
37    fn af_approx1_uniform_v2(
38        out: *mut af_array,
39        inp: af_array,
40        pos: af_array,
41        interp_dim: c_int,
42        idx_start: c_double,
43        idx_step: c_double,
44        method: c_uint,
45        off_grid: c_float,
46    ) -> c_int;
47
48    fn af_approx2(
49        out: *mut af_array,
50        inp: af_array,
51        pos0: af_array,
52        pos1: af_array,
53        method: c_uint,
54        off_grid: c_float,
55    ) -> c_int;
56
57    fn af_approx2_v2(
58        out: *mut af_array,
59        inp: af_array,
60        pos0: af_array,
61        pos1: af_array,
62        method: c_uint,
63        off_grid: c_float,
64    ) -> c_int;
65
66    fn af_approx2_uniform(
67        out: *mut af_array,
68        inp: af_array,
69        pos0: af_array,
70        interp_dim0: c_int,
71        idx_start_dim0: c_double,
72        idx_step_dim0: c_double,
73        pos1: af_array,
74        interp_dim1: c_int,
75        idx_start_dim1: c_double,
76        idx_step_dim1: c_double,
77        method: c_uint,
78        off_grid: c_float,
79    ) -> c_int;
80
81    fn af_approx2_uniform_v2(
82        out: *mut af_array,
83        inp: af_array,
84        pos0: af_array,
85        interp_dim0: c_int,
86        idx_start_dim0: c_double,
87        idx_step_dim0: c_double,
88        pos1: af_array,
89        interp_dim1: c_int,
90        idx_start_dim1: c_double,
91        idx_step_dim1: c_double,
92        method: c_uint,
93        off_grid: c_float,
94    ) -> c_int;
95
96    fn af_set_fft_plan_cache_size(cache_size: size_t) -> c_int;
97
98    fn af_fft(out: *mut af_array, arr: af_array, nfac: c_double, odim0: dim_t) -> c_int;
99
100    fn af_fft2(
101        out: *mut af_array,
102        arr: af_array,
103        nfac: c_double,
104        odim0: dim_t,
105        odim1: dim_t,
106    ) -> c_int;
107
108    fn af_fft3(
109        out: *mut af_array,
110        arr: af_array,
111        nfac: c_double,
112        odim0: dim_t,
113        odim1: dim_t,
114        odim2: dim_t,
115    ) -> c_int;
116
117    fn af_ifft(out: *mut af_array, arr: af_array, nfac: c_double, odim0: dim_t) -> c_int;
118
119    fn af_ifft2(
120        out: *mut af_array,
121        arr: af_array,
122        nfac: c_double,
123        odim0: dim_t,
124        odim1: dim_t,
125    ) -> c_int;
126
127    fn af_ifft3(
128        out: *mut af_array,
129        arr: af_array,
130        nfac: c_double,
131        odim0: dim_t,
132        odim1: dim_t,
133        odim2: dim_t,
134    ) -> c_int;
135
136    fn af_fft_inplace(arr: *mut af_array, nfac: c_double) -> c_int;
137    fn af_fft2_inplace(arr: *mut af_array, nfac: c_double) -> c_int;
138    fn af_fft3_inplace(arr: *mut af_array, nfac: c_double) -> c_int;
139    fn af_ifft_inplace(arr: *mut af_array, nfac: c_double) -> c_int;
140    fn af_ifft2_inplace(arr: *mut af_array, nfac: c_double) -> c_int;
141    fn af_ifft3_inplace(arr: *mut af_array, nfac: c_double) -> c_int;
142
143    fn af_fft_r2c(out: *mut af_array, arr: af_array, nfac: c_double, pad0: dim_t) -> c_int;
144    fn af_fft2_r2c(
145        out: *mut af_array,
146        arr: af_array,
147        nfac: c_double,
148        pad0: dim_t,
149        pad1: dim_t,
150    ) -> c_int;
151    fn af_fft3_r2c(
152        out: *mut af_array,
153        arr: af_array,
154        nfac: c_double,
155        pad0: dim_t,
156        pad1: dim_t,
157        pad2: dim_t,
158    ) -> c_int;
159
160    fn af_fft_c2r(out: *mut af_array, input: af_array, nfac: c_double, is_odd: bool) -> c_int;
161    fn af_fft2_c2r(out: *mut af_array, input: af_array, nfac: c_double, is_odd: bool) -> c_int;
162    fn af_fft3_c2r(out: *mut af_array, input: af_array, nfac: c_double, is_odd: bool) -> c_int;
163
164    fn af_convolve1(out: *mut af_array, s: af_array, f: af_array, m: c_uint, d: c_uint) -> c_int;
165    fn af_convolve2(out: *mut af_array, s: af_array, f: af_array, m: c_uint, d: c_uint) -> c_int;
166    fn af_convolve3(out: *mut af_array, s: af_array, f: af_array, m: c_uint, d: c_uint) -> c_int;
167    fn af_convolve2_sep(
168        o: *mut af_array,
169        c: af_array,
170        r: af_array,
171        s: af_array,
172        m: c_uint,
173    ) -> c_int;
174    fn af_fft_convolve1(out: *mut af_array, s: af_array, f: af_array, m: c_uint) -> c_int;
175    fn af_fft_convolve2(out: *mut af_array, s: af_array, f: af_array, m: c_uint) -> c_int;
176    fn af_fft_convolve3(out: *mut af_array, s: af_array, f: af_array, m: c_uint) -> c_int;
177    fn af_fir(out: *mut af_array, b: af_array, x: af_array) -> c_int;
178    fn af_iir(out: *mut af_array, b: af_array, a: af_array, x: af_array) -> c_int;
179}
180
181/// Perform signal interpolation for 1d signals
182///
183/// # Parameters
184///
185/// - `input` is the input Array
186/// - `pos` Array contains the interpolation locations
187/// - `method` indicates the type of interpolation method that be used. It is of type enum
188/// [InterpType](./enum.InterpType.html)
189/// - `off_grid` is the value that will set in the output Array when certain index is out of bounds
190///
191/// # Return Values
192///
193/// An Array with interpolated values
194pub fn approx1<T, P>(
195    input: &Array<T>,
196    pos: &Array<P>,
197    method: InterpType,
198    off_grid: f32,
199) -> Array<T>
200where
201    T: HasAfEnum + FloatingPoint,
202    P: HasAfEnum + RealFloating,
203{
204    unsafe {
205        let mut temp: af_array = std::ptr::null_mut();
206        let err_val = af_approx1(
207            &mut temp as *mut af_array,
208            input.get(),
209            pos.get(),
210            method as c_uint,
211            off_grid,
212        );
213        HANDLE_ERROR(AfError::from(err_val));
214        temp.into()
215    }
216}
217
218/// Same as [approx1](./fn.approx1.html) but uses existing Array as output
219pub fn approx1_v2<T, P>(
220    output: &mut Array<T>,
221    input: &Array<T>,
222    pos: &Array<P>,
223    method: InterpType,
224    off_grid: f32,
225) where
226    T: HasAfEnum + FloatingPoint,
227    P: HasAfEnum + RealFloating,
228{
229    unsafe {
230        let err_val = af_approx1_v2(
231            output.get() as *mut af_array,
232            input.get(),
233            pos.get(),
234            method as c_uint,
235            off_grid,
236        );
237        HANDLE_ERROR(AfError::from(err_val));
238    }
239}
240
241/// Perform signal interpolation for 1d signals along specified dimension
242///
243/// # Parameters
244///
245/// - `input` is the input Array
246/// - `pos` Array contains the interpolation locations
247/// - `interp_dim` is the dimension along which interpolation is performed
248/// - `start` is the first index along `interp_dim`
249/// - `step` is the uniform spacing value between subsequent indices along `interp_dim`
250/// - `method` indicates the type of interpolation method that be used. It is of type enum
251/// [InterpType](./enum.InterpType.html)
252/// - `off_grid` is the value that will set in the output Array when certain index is out of bounds
253///
254/// # Return Values
255///
256/// An Array with interpolated values
257pub fn approx1_uniform<T, P>(
258    input: &Array<T>,
259    pos: &Array<P>,
260    interp_dim: i32,
261    start: f64,
262    step: f64,
263    method: InterpType,
264    off_grid: f32,
265) -> Array<T>
266where
267    T: HasAfEnum + FloatingPoint,
268    P: HasAfEnum + RealFloating,
269{
270    unsafe {
271        let mut temp: af_array = std::ptr::null_mut();
272        let err_val = af_approx1_uniform(
273            &mut temp as *mut af_array,
274            input.get(),
275            pos.get(),
276            interp_dim,
277            start,
278            step,
279            method as c_uint,
280            off_grid,
281        );
282        HANDLE_ERROR(AfError::from(err_val));
283        temp.into()
284    }
285}
286
287/// Same as [approx1_uniform](./fn.approx1_uniform.html) but uses existing Array as output
288#[allow(clippy::too_many_arguments)]
289pub fn approx1_uniform_v2<T, P>(
290    output: &mut Array<T>,
291    input: &Array<T>,
292    pos: &Array<P>,
293    interp_dim: i32,
294    start: f64,
295    step: f64,
296    method: InterpType,
297    off_grid: f32,
298) where
299    T: HasAfEnum + FloatingPoint,
300    P: HasAfEnum + RealFloating,
301{
302    unsafe {
303        let err_val = af_approx1_uniform_v2(
304            output.get() as *mut af_array,
305            input.get(),
306            pos.get(),
307            interp_dim,
308            start,
309            step,
310            method as c_uint,
311            off_grid,
312        );
313        HANDLE_ERROR(AfError::from(err_val));
314    }
315}
316
317/// Perform signal interpolation for 2d signals
318///
319/// # Parameters
320///
321/// - `input` is the input Array
322/// - `pos0` Array contains the interpolation locations for first dimension
323/// - `pos1` Array contains the interpolation locations for second dimension
324/// - `method` indicates the type of interpolation method that be used. It is of type enum
325/// [InterpType](./enum.InterpType.html)
326/// - `off_grid` is the value that will set in the output Array when certain index is out of bounds
327///
328/// # Return Values
329///
330/// An Array with interpolated values
331pub fn approx2<T, P>(
332    input: &Array<T>,
333    pos0: &Array<P>,
334    pos1: &Array<P>,
335    method: InterpType,
336    off_grid: f32,
337) -> Array<T>
338where
339    T: HasAfEnum + FloatingPoint,
340    P: HasAfEnum + RealFloating,
341{
342    unsafe {
343        let mut temp: af_array = std::ptr::null_mut();
344        let err_val = af_approx2(
345            &mut temp as *mut af_array,
346            input.get(),
347            pos0.get(),
348            pos1.get(),
349            method as c_uint,
350            off_grid,
351        );
352        HANDLE_ERROR(AfError::from(err_val));
353        temp.into()
354    }
355}
356
357/// Same as [approx2](./fn.approx2.html) but uses existing Array as output
358pub fn approx2_v2<T, P>(
359    output: &mut Array<T>,
360    input: &Array<T>,
361    pos0: &Array<P>,
362    pos1: &Array<P>,
363    method: InterpType,
364    off_grid: f32,
365) where
366    T: HasAfEnum + FloatingPoint,
367    P: HasAfEnum + RealFloating,
368{
369    unsafe {
370        let err_val = af_approx2_v2(
371            output.get() as *mut af_array,
372            input.get(),
373            pos0.get(),
374            pos1.get(),
375            method as c_uint,
376            off_grid,
377        );
378        HANDLE_ERROR(AfError::from(err_val));
379    }
380}
381
382/// Perform signal interpolation for 2d signals along a specified dimension
383///
384/// # Parameters
385///
386/// - `input` is the input Array
387/// - `pos0` Array contains the interpolation locations for first dimension
388/// - `interp_dim0` is the dimension along which interpolation is performed
389/// - `start0` is the first index along `interp_dim0`
390/// - `step0` is the uniform spacing value between subsequent indices along `interp_dim0`
391/// - `pos1` Array contains the interpolation locations for second dimension
392/// - `interp_dim0` is the dimension along which interpolation is performed
393/// - `start0` is the first index along `interp_dim1`
394/// - `step0` is the uniform spacing value between subsequent indices along `interp_dim1`
395/// - `method` indicates the type of interpolation method that be used. It is of type enum
396/// [InterpType](./enum.InterpType.html)
397/// - `off_grid` is the value that will set in the output Array when certain index is out of bounds
398///
399/// # Return Values
400///
401/// An Array with interpolated values
402#[allow(clippy::too_many_arguments)]
403pub fn approx2_uniform<T, P>(
404    input: &Array<T>,
405    pos0: &Array<P>,
406    interp_dim0: i32,
407    start0: f64,
408    step0: f64,
409    pos1: &Array<P>,
410    interp_dim1: i32,
411    start1: f64,
412    step1: f64,
413    method: InterpType,
414    off_grid: f32,
415) -> Array<T>
416where
417    T: HasAfEnum + FloatingPoint,
418    P: HasAfEnum + RealFloating,
419{
420    unsafe {
421        let mut temp: af_array = std::ptr::null_mut();
422        let err_val = af_approx2_uniform(
423            &mut temp as *mut af_array,
424            input.get(),
425            pos0.get(),
426            interp_dim0,
427            start0,
428            step0,
429            pos1.get(),
430            interp_dim1,
431            start1,
432            step1,
433            method as c_uint,
434            off_grid,
435        );
436        HANDLE_ERROR(AfError::from(err_val));
437        temp.into()
438    }
439}
440
441/// Same as [approx2_uniform](./fn.approx2_uniform.html) but uses existing Array as output
442#[allow(clippy::too_many_arguments)]
443pub fn approx2_uniform_v2<T, P>(
444    output: &mut Array<T>,
445    input: &Array<T>,
446    pos0: &Array<P>,
447    interp_dim0: i32,
448    start0: f64,
449    step0: f64,
450    pos1: &Array<P>,
451    interp_dim1: i32,
452    start1: f64,
453    step1: f64,
454    method: InterpType,
455    off_grid: f32,
456) where
457    T: HasAfEnum + FloatingPoint,
458    P: HasAfEnum + RealFloating,
459{
460    unsafe {
461        let err_val = af_approx2_uniform_v2(
462            output.get() as *mut af_array,
463            input.get(),
464            pos0.get(),
465            interp_dim0,
466            start0,
467            step0,
468            pos1.get(),
469            interp_dim1,
470            start1,
471            step1,
472            method as c_uint,
473            off_grid,
474        );
475        HANDLE_ERROR(AfError::from(err_val));
476    }
477}
478
479/// Set fft plan cache size
480///
481/// Though this is a low overhead function, it is advised not to change
482/// the fft plan cache size a mid program execution unless that is what
483/// you intend to do.
484pub fn set_fft_plan_cache_size(cache_size: usize) {
485    unsafe {
486        let err_val = af_set_fft_plan_cache_size(cache_size as size_t);
487        HANDLE_ERROR(AfError::from(err_val));
488    }
489}
490
491/// Fast fourier transform for 1d signals
492///
493/// # Parameters
494///
495/// - `input` is the input Array
496/// - `norm_factor` is the normalization factor with which the input is scaled before the
497/// transformation is applied
498/// - `odim0` is the length of output signals - used for either truncating or padding the input
499/// signals
500///
501/// # Return Values
502///
503/// Transformed Array
504pub fn fft<T>(input: &Array<T>, norm_factor: f64, odim0: i64) -> Array<T::ComplexOutType>
505where
506    T: HasAfEnum + FloatingPoint,
507    <T as HasAfEnum>::ComplexOutType: HasAfEnum,
508{
509    unsafe {
510        let mut temp: af_array = std::ptr::null_mut();
511        let err_val = af_fft(&mut temp as *mut af_array, input.get(), norm_factor, odim0);
512        HANDLE_ERROR(AfError::from(err_val));
513        temp.into()
514    }
515}
516
517/// Fast fourier transform for 2d signals
518///
519/// # Parameters
520///
521/// - `input` is the input Array
522/// - `norm_factor` is the normalization factor with which the input is scaled before the
523/// transformation is applied
524/// - `odim0` is the length of output signal first dimension - used for either truncating or padding the input
525/// - `odim1` is the length of output signal second dimension - used for either truncating or padding the input
526///
527/// # Return Values
528///
529/// Transformed Array
530pub fn fft2<T>(
531    input: &Array<T>,
532    norm_factor: f64,
533    odim0: i64,
534    odim1: i64,
535) -> Array<T::ComplexOutType>
536where
537    T: HasAfEnum + FloatingPoint,
538    <T as HasAfEnum>::ComplexOutType: HasAfEnum,
539{
540    unsafe {
541        let mut temp: af_array = std::ptr::null_mut();
542        let err_val = af_fft2(
543            &mut temp as *mut af_array,
544            input.get(),
545            norm_factor,
546            odim0,
547            odim1,
548        );
549        HANDLE_ERROR(AfError::from(err_val));
550        temp.into()
551    }
552}
553
554/// Fast fourier transform for 3d signals
555///
556/// # Parameters
557///
558/// - `input` is the input Array
559/// - `norm_factor` is the normalization factor with which the input is scaled before the
560/// transformation is applied
561/// - `odim0` is the length of output signal first dimension - used for either truncating or padding the input
562/// - `odim1` is the length of output signal second dimension - used for either truncating or padding the input
563/// - `odim2` is the length of output signal third dimension - used for either truncating or padding the input
564///
565/// # Return Values
566///
567/// Transformed Array
568pub fn fft3<T>(
569    input: &Array<T>,
570    norm_factor: f64,
571    odim0: i64,
572    odim1: i64,
573    odim2: i64,
574) -> Array<T::ComplexOutType>
575where
576    T: HasAfEnum + FloatingPoint,
577    <T as HasAfEnum>::ComplexOutType: HasAfEnum,
578{
579    unsafe {
580        let mut temp: af_array = std::ptr::null_mut();
581        let err_val = af_fft3(
582            &mut temp as *mut af_array,
583            input.get(),
584            norm_factor,
585            odim0,
586            odim1,
587            odim2,
588        );
589        HANDLE_ERROR(AfError::from(err_val));
590        temp.into()
591    }
592}
593
594/// Inverse fast fourier transform for 1d signals
595///
596/// # Parameters
597///
598/// - `input` is the input Array
599/// - `norm_factor` is the normalization factor with which the input is scaled before the
600/// transformation is applied
601/// - `odim0` is the length of output signals - used for either truncating or padding the input
602/// signals
603///
604/// # Return Values
605///
606/// Transformed Array
607pub fn ifft<T>(input: &Array<T>, norm_factor: f64, odim0: i64) -> Array<T::ComplexOutType>
608where
609    T: HasAfEnum + FloatingPoint,
610    <T as HasAfEnum>::ComplexOutType: HasAfEnum,
611{
612    unsafe {
613        let mut temp: af_array = std::ptr::null_mut();
614        let err_val = af_ifft(&mut temp as *mut af_array, input.get(), norm_factor, odim0);
615        HANDLE_ERROR(AfError::from(err_val));
616        temp.into()
617    }
618}
619
620/// Inverse fast fourier transform for 2d signals
621///
622/// # Parameters
623///
624/// - `input` is the input Array
625/// - `norm_factor` is the normalization factor with which the input is scaled before the
626/// transformation is applied
627/// - `odim0` is the length of output signal first dimension - used for either truncating or padding the input
628/// - `odim1` is the length of output signal second dimension - used for either truncating or padding the input
629///
630/// # Return Values
631///
632/// Transformed Array
633pub fn ifft2<T>(
634    input: &Array<T>,
635    norm_factor: f64,
636    odim0: i64,
637    odim1: i64,
638) -> Array<T::ComplexOutType>
639where
640    T: HasAfEnum + FloatingPoint,
641    <T as HasAfEnum>::ComplexOutType: HasAfEnum,
642{
643    unsafe {
644        let mut temp: af_array = std::ptr::null_mut();
645        let err_val = af_ifft2(
646            &mut temp as *mut af_array,
647            input.get(),
648            norm_factor,
649            odim0,
650            odim1,
651        );
652        HANDLE_ERROR(AfError::from(err_val));
653        temp.into()
654    }
655}
656
657/// Inverse fast fourier transform for 3d signals
658///
659/// # Parameters
660///
661/// - `input` is the input Array
662/// - `norm_factor` is the normalization factor with which the input is scaled before the
663/// transformation is applied
664/// - `odim0` is the length of output signal first dimension - used for either truncating or padding the input
665/// - `odim1` is the length of output signal second dimension - used for either truncating or padding the input
666/// - `odim2` is the length of output signal third dimension - used for either truncating or padding the input
667///
668/// # Return Values
669///
670/// Transformed Array
671pub fn ifft3<T>(
672    input: &Array<T>,
673    norm_factor: f64,
674    odim0: i64,
675    odim1: i64,
676    odim2: i64,
677) -> Array<T::ComplexOutType>
678where
679    T: HasAfEnum + FloatingPoint,
680    <T as HasAfEnum>::ComplexOutType: HasAfEnum,
681{
682    unsafe {
683        let mut temp: af_array = std::ptr::null_mut();
684        let err_val = af_ifft3(
685            &mut temp as *mut af_array,
686            input.get(),
687            norm_factor,
688            odim0,
689            odim1,
690            odim2,
691        );
692        HANDLE_ERROR(AfError::from(err_val));
693        temp.into()
694    }
695}
696
697macro_rules! conv_func_def {
698    ($doc_str: expr, $fn_name:ident, $ffi_name: ident) => {
699        #[doc=$doc_str]
700        ///
701        ///# Parameters
702        ///
703        /// - `signal` is the input signal
704        /// - `filter` is the signal that shall be flipped for convolution operation
705        /// - `mode` indicates if the convolution should be expanded or not(where output size
706        /// equals input). It takes a value of type [ConvMode](./enum.ConvMode.html)
707        /// - `domain` indicates if the convolution should be performed in frequencey or spatial
708        /// domain. It takes a value of type [ConvDomain](./enum.ConvDomain.html)
709        ///
710        ///# Return Values
711        ///
712        /// Convolved Array
713        pub fn $fn_name<T, F>(
714            signal: &Array<T>,
715            filter: &Array<F>,
716            mode: ConvMode,
717            domain: ConvDomain,
718        ) -> Array<T>
719        where
720            T: HasAfEnum,
721            F: HasAfEnum,
722        {
723            unsafe {
724        let mut temp: af_array = std::ptr::null_mut();
725                let err_val = $ffi_name(
726                    &mut temp as *mut af_array,
727                    signal.get(),
728                    filter.get(),
729                    mode as c_uint,
730                    domain as c_uint,
731                );
732                HANDLE_ERROR(AfError::from(err_val));
733                temp.into()
734            }
735        }
736    };
737}
738
739conv_func_def!("1d convolution", convolve1, af_convolve1);
740conv_func_def!("2d convolution", convolve2, af_convolve2);
741conv_func_def!("3d convolution", convolve3, af_convolve3);
742
743/// Separable convolution for 2d signals
744///
745/// # Parameters
746///
747/// - `cfilt` is the filter to be applied along coloumns
748/// - `rfilt` is the filter to be applied along rows
749/// - `signal` is the input signal
750/// - `mode` indicates if the convolution should be expanded or not(where output size equals input)
751///
752/// # Return Values
753///
754/// The convolved Array
755pub fn convolve2_sep<T, F>(
756    cfilt: &Array<F>,
757    rfilt: &Array<F>,
758    signal: &Array<T>,
759    mode: ConvMode,
760) -> Array<T>
761where
762    T: HasAfEnum,
763    F: HasAfEnum,
764{
765    unsafe {
766        let mut temp: af_array = std::ptr::null_mut();
767        let err_val = af_convolve2_sep(
768            &mut temp as *mut af_array,
769            cfilt.get(),
770            rfilt.get(),
771            signal.get(),
772            mode as c_uint,
773        );
774        HANDLE_ERROR(AfError::from(err_val));
775        temp.into()
776    }
777}
778
779macro_rules! fft_conv_func_def {
780    ($doc_str: expr, $fn_name:ident, $ffi_name: ident) => {
781        #[doc=$doc_str]
782        ///
783        ///# Parameters
784        ///
785        /// - `signal` is the input signal
786        /// - `filter` is the signal that shall be used for convolution operation
787        /// - `mode` indicates if the convolution should be expanded or not(where output size
788        /// equals input). It takes values of type [ConvMode](./enum.ConvMode.html)
789        ///
790        ///# Return Values
791        ///
792        /// Convolved Array
793        pub fn $fn_name<T, F>(signal: &Array<T>, filter: &Array<F>, mode: ConvMode) -> Array<T>
794        where
795            T: HasAfEnum,
796            F: HasAfEnum,
797        {
798            unsafe {
799        let mut temp: af_array = std::ptr::null_mut();
800                let err_val = $ffi_name(
801                    &mut temp as *mut af_array, signal.get(), filter.get(), mode as c_uint);
802                HANDLE_ERROR(AfError::from(err_val));
803                temp.into()
804            }
805        }
806    };
807}
808
809fft_conv_func_def!(
810    "1d convolution using fast-fourier transform",
811    fft_convolve1,
812    af_fft_convolve1
813);
814fft_conv_func_def!(
815    "2d convolution using fast-fourier transform",
816    fft_convolve2,
817    af_fft_convolve2
818);
819fft_conv_func_def!(
820    "3d convolution using fast-fourier transform",
821    fft_convolve3,
822    af_fft_convolve3
823);
824
825/// Finite impulse filter
826///
827/// # Parameters
828///
829/// - `b` is the Array containing the coefficients of the filter
830/// - `x` is the input signal to filter
831///
832/// # Return Values
833///
834/// Filtered Array
835pub fn fir<B, X>(b: &Array<B>, x: &Array<X>) -> Array<X>
836where
837    B: HasAfEnum,
838    X: HasAfEnum,
839{
840    unsafe {
841        let mut temp: af_array = std::ptr::null_mut();
842        let err_val = af_fir(&mut temp as *mut af_array, b.get(), x.get());
843        HANDLE_ERROR(AfError::from(err_val));
844        temp.into()
845    }
846}
847
848/// Infinite impulse response filter
849///
850/// # Parameters
851///
852/// - `b` is the Array containing the feedforward coefficients
853/// - `a` is the Array containing the feedback coefficients
854/// - `x` is the input signal to filter
855///
856/// # Return Values
857///
858/// Filtered Array
859pub fn iir<T: HasAfEnum>(b: &Array<T>, a: &Array<T>, x: &Array<T>) -> Array<T> {
860    unsafe {
861        let mut temp: af_array = std::ptr::null_mut();
862        let err_val = af_iir(&mut temp as *mut af_array, b.get(), a.get(), x.get());
863        HANDLE_ERROR(AfError::from(err_val));
864        temp.into()
865    }
866}
867
868/// In place 1d dimensional Fast fourier transform
869///
870/// # Parameters
871///
872/// - `input` is the input Array
873/// - `norm_factor` is the normalization factor
874pub fn fft_inplace<T>(input: &mut Array<T>, norm_factor: f64)
875where
876    T: HasAfEnum + ComplexFloating,
877{
878    unsafe {
879        let err_val = af_fft_inplace(input.get() as *mut af_array, norm_factor);
880        HANDLE_ERROR(AfError::from(err_val));
881    }
882}
883
884/// In place 2d dimensional Fast fourier transform
885///
886/// # Parameters
887///
888/// - `input` is the input Array
889/// - `norm_factor` is the normalization factor
890pub fn fft2_inplace<T>(input: &mut Array<T>, norm_factor: f64)
891where
892    T: HasAfEnum + ComplexFloating,
893{
894    unsafe {
895        let err_val = af_fft2_inplace(input.get() as *mut af_array, norm_factor);
896        HANDLE_ERROR(AfError::from(err_val));
897    }
898}
899
900/// In place 3d dimensional Fast fourier transform
901///
902/// # Parameters
903///
904/// - `input` is the input Array
905/// - `norm_factor` is the normalization factor
906pub fn fft3_inplace<T>(input: &mut Array<T>, norm_factor: f64)
907where
908    T: HasAfEnum + ComplexFloating,
909{
910    unsafe {
911        let err_val = af_fft3_inplace(input.get() as *mut af_array, norm_factor);
912        HANDLE_ERROR(AfError::from(err_val));
913    }
914}
915
916/// In place 1d dimensional inverse fast fourier transform
917///
918/// # Parameters
919///
920/// - `input` is the input Array
921/// - `norm_factor` is the normalization factor
922pub fn ifft_inplace<T>(input: &mut Array<T>, norm_factor: f64)
923where
924    T: HasAfEnum + ComplexFloating,
925{
926    unsafe {
927        let err_val = af_ifft_inplace(input.get() as *mut af_array, norm_factor);
928        HANDLE_ERROR(AfError::from(err_val));
929    }
930}
931
932/// In place 2d dimensional inverse fast fourier transform
933///
934/// # Parameters
935///
936/// - `input` is the input Array
937/// - `norm_factor` is the normalization factor
938pub fn ifft2_inplace<T>(input: &mut Array<T>, norm_factor: f64)
939where
940    T: HasAfEnum + ComplexFloating,
941{
942    unsafe {
943        let err_val = af_ifft2_inplace(input.get() as *mut af_array, norm_factor);
944        HANDLE_ERROR(AfError::from(err_val));
945    }
946}
947
948/// In place 3d dimensional inverse fast fourier transform
949///
950/// # Parameters
951///
952/// - `input` is the input Array
953/// - `norm_factor` is the normalization factor
954pub fn ifft3_inplace<T>(input: &mut Array<T>, norm_factor: f64)
955where
956    T: HasAfEnum + ComplexFloating,
957{
958    unsafe {
959        let err_val = af_ifft3_inplace(input.get() as *mut af_array, norm_factor);
960        HANDLE_ERROR(AfError::from(err_val));
961    }
962}
963
964/// 1d Real to Complex fast fourier transform
965///
966/// # Parameters
967///
968/// - `input` is the input Array
969/// - `norm_factor` is the normalization factor to be applied before fft is applied
970/// - `pad0` is the padding along 0th dimension of Array
971///
972/// # Return Values
973///
974/// Complex Array
975pub fn fft_r2c<T>(input: &Array<T>, norm_factor: f64, pad0: i64) -> Array<Complex<T>>
976where
977    T: HasAfEnum + RealFloating,
978    Complex<T>: HasAfEnum,
979{
980    unsafe {
981        let mut temp: af_array = std::ptr::null_mut();
982        let err_val = af_fft_r2c(&mut temp as *mut af_array, input.get(), norm_factor, pad0);
983        HANDLE_ERROR(AfError::from(err_val));
984        temp.into()
985    }
986}
987
988/// 2d Real to Complex fast fourier transform
989///
990/// # Parameters
991///
992/// - `input` is the input Array
993/// - `norm_factor` is the normalization factor to be applied before fft is applied
994/// - `pad0` is the padding along 0th dimension of Array
995/// - `pad1` is the padding along 1st dimension of Array
996///
997/// # Return Values
998///
999/// Complex Array
1000pub fn fft2_r2c<T>(input: &Array<T>, norm_factor: f64, pad0: i64, pad1: i64) -> Array<Complex<T>>
1001where
1002    T: HasAfEnum + RealFloating,
1003    Complex<T>: HasAfEnum,
1004{
1005    unsafe {
1006        let mut temp: af_array = std::ptr::null_mut();
1007        let err_val = af_fft2_r2c(
1008            &mut temp as *mut af_array,
1009            input.get(),
1010            norm_factor,
1011            pad0,
1012            pad1,
1013        );
1014        HANDLE_ERROR(AfError::from(err_val));
1015        temp.into()
1016    }
1017}
1018
1019/// 3d Real to Complex fast fourier transform
1020///
1021/// # Parameters
1022///
1023/// - `input` is the input Array
1024/// - `norm_factor` is the normalization factor to be applied before fft is applied
1025/// - `pad0` is the padding along 0th dimension of Array
1026/// - `pad1` is the padding along 1st dimension of Array
1027/// - `pad2` is the padding along 2nd dimension of Array
1028///
1029/// # Return Values
1030///
1031/// Complex Array
1032pub fn fft3_r2c<T>(
1033    input: &Array<T>,
1034    norm_factor: f64,
1035    pad0: i64,
1036    pad1: i64,
1037    pad2: i64,
1038) -> Array<Complex<T>>
1039where
1040    T: HasAfEnum + RealFloating,
1041    Complex<T>: HasAfEnum,
1042{
1043    unsafe {
1044        let mut temp: af_array = std::ptr::null_mut();
1045        let err_val = af_fft3_r2c(
1046            &mut temp as *mut af_array,
1047            input.get(),
1048            norm_factor,
1049            pad0,
1050            pad1,
1051            pad2,
1052        );
1053        HANDLE_ERROR(AfError::from(err_val));
1054        temp.into()
1055    }
1056}
1057
1058/// 1d Complex to Real fast fourier transform
1059///
1060/// # Parameters
1061///
1062/// - `input` is the input Array
1063/// - `norm_factor` is the normalization factor to be applied before fft is applied
1064/// - `is_odd` signifies if the output should be even or odd size
1065///
1066/// # Return Values
1067///
1068/// Complex Array
1069pub fn fft_c2r<T>(input: &Array<T>, norm_factor: f64, is_odd: bool) -> Array<T::BaseType>
1070where
1071    T: HasAfEnum + ComplexFloating,
1072    <T as HasAfEnum>::BaseType: HasAfEnum,
1073{
1074    unsafe {
1075        let mut temp: af_array = std::ptr::null_mut();
1076        let err_val = af_fft_c2r(&mut temp as *mut af_array, input.get(), norm_factor, is_odd);
1077        HANDLE_ERROR(AfError::from(err_val));
1078        temp.into()
1079    }
1080}
1081
1082/// 2d Complex to Real fast fourier transform
1083///
1084/// # Parameters
1085///
1086/// - `input` is the input Array
1087/// - `norm_factor` is the normalization factor to be applied before fft is applied
1088/// - `is_odd` signifies if the output should be even or odd size
1089///
1090/// # Return Values
1091///
1092/// Complex Array
1093pub fn fft2_c2r<T>(input: &Array<T>, norm_factor: f64, is_odd: bool) -> Array<T::BaseType>
1094where
1095    T: HasAfEnum + ComplexFloating,
1096    <T as HasAfEnum>::BaseType: HasAfEnum,
1097{
1098    unsafe {
1099        let mut temp: af_array = std::ptr::null_mut();
1100        let err_val = af_fft2_c2r(&mut temp as *mut af_array, input.get(), norm_factor, is_odd);
1101        HANDLE_ERROR(AfError::from(err_val));
1102        temp.into()
1103    }
1104}
1105
1106/// 3d Complex to Real fast fourier transform
1107///
1108/// # Parameters
1109///
1110/// - `input` is the input Array
1111/// - `norm_factor` is the normalization factor to be applied before fft is applied
1112/// - `is_odd` signifies if the output should be even or odd size
1113///
1114/// # Return Values
1115///
1116/// Complex Array
1117pub fn fft3_c2r<T>(input: &Array<T>, norm_factor: f64, is_odd: bool) -> Array<T::BaseType>
1118where
1119    T: HasAfEnum + ComplexFloating,
1120    <T as HasAfEnum>::BaseType: HasAfEnum,
1121{
1122    unsafe {
1123        let mut temp: af_array = std::ptr::null_mut();
1124        let err_val = af_fft3_c2r(&mut temp as *mut af_array, input.get(), norm_factor, is_odd);
1125        HANDLE_ERROR(AfError::from(err_val));
1126        temp.into()
1127    }
1128}