1/*
2 * Copyright (c) 2003-2004, Mark Borgerding. All rights reserved.
3 * This file is part of KISS FFT - https://github.com/mborgerding/kissfft
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 * See COPYING file for more information.
7 */
8
9#include "kfc.h"
10
11typedef struct cached_fft *kfc_cfg;
12
13struct cached_fft
14{
15 int nfft;
16 int inverse;
17 kiss_fft_cfg cfg;
18 kfc_cfg next;
19};
20
21static kfc_cfg cache_root=NULL;
22static int ncached=0;
23
24static kiss_fft_cfg find_cached_fft(int nfft,int inverse)
25{
26 size_t len;
27 kfc_cfg cur=cache_root;
28 kfc_cfg prev=NULL;
29 while ( cur ) {
30 if ( cur->nfft == nfft && inverse == cur->inverse )
31 break;/*found the right node*/
32 prev = cur;
33 cur = prev->next;
34 }
35 if (cur== NULL) {
36 /* no cached node found, need to create a new one*/
37 kiss_fft_alloc(nfft,inverse,0,&len);
38#ifdef USE_SIMD
39 int padding = (16-sizeof(struct cached_fft)) & 15;
40 // make sure the cfg aligns on a 16 byte boundary
41 len += padding;
42#endif
43 cur = (kfc_cfg)KISS_FFT_MALLOC((sizeof(struct cached_fft) + len ));
44 if (cur == NULL)
45 return NULL;
46 cur->cfg = (kiss_fft_cfg)(cur+1);
47#ifdef USE_SIMD
48 cur->cfg = (kiss_fft_cfg) ((char*)(cur+1)+padding);
49#endif
50 kiss_fft_alloc(nfft,inverse,cur->cfg,&len);
51 cur->nfft=nfft;
52 cur->inverse=inverse;
53 cur->next = NULL;
54 if ( prev )
55 prev->next = cur;
56 else
57 cache_root = cur;
58 ++ncached;
59 }
60 return cur->cfg;
61}
62
63void kfc_cleanup(void)
64{
65 kfc_cfg cur=cache_root;
66 kfc_cfg next=NULL;
67 while (cur){
68 next = cur->next;
69 free(cur);
70 cur=next;
71 }
72 ncached=0;
73 cache_root = NULL;
74}
75void kfc_fft(int nfft, const kiss_fft_cpx * fin,kiss_fft_cpx * fout)
76{
77 kiss_fft( find_cached_fft(nfft,0),fin,fout );
78}
79
80void kfc_ifft(int nfft, const kiss_fft_cpx * fin,kiss_fft_cpx * fout)
81{
82 kiss_fft( find_cached_fft(nfft,1),fin,fout );
83}
84
85#ifdef KFC_TEST
86static void check(int nc)
87{
88 if (ncached != nc) {
89 fprintf(stderr,"ncached should be %d,but it is %d\n",nc,ncached);
90 exit(1);
91 }
92}
93
94int main(void)
95{
96 kiss_fft_cpx buf1[1024],buf2[1024];
97 memset(buf1,0,sizeof(buf1));
98 check(0);
99 kfc_fft(512,buf1,buf2);
100 check(1);
101 kfc_fft(512,buf1,buf2);
102 check(1);
103 kfc_ifft(512,buf1,buf2);
104 check(2);
105 kfc_cleanup();
106 check(0);
107 return 0;
108}
109#endif
110