1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2012 - INRIA - Serge STEER
4 * Copyright (C) 2015 - Scilab Enterprises - Antoine ELIAS
5 *
6 * Copyright (C) 2012 - 2016 - Scilab Enterprises
7 *
8 * This file is hereby licensed under the terms of the GNU GPL v2.0,
9 * pursuant to article 5.3.4 of the CeCILL v.2.1.
10 * This file was originally licensed under the terms of the CeCILL v2.1,
11 * and continues to be available under such terms.
12 * For more information, see the COPYING file which you should have received
13 * along with this program.
14 *
15 */
16
17 #include "fftw_gw.hxx"
18 #include "function.hxx"
19 #include "fftw_common.hxx"
20 extern "C"
21 {
22 #include "localization.h"
23 #include "charEncoding.h"
24 #include "Scierror.h"
25
26 extern int WITHMKL;
27 extern void C2F(dscal)(int *n, double *da, double *dx, int *incx); /* blas routine */
28 extern void C2F(dset)(int *n, double *da, double *dx, int *incx); /* blas routine */
29 }
30 /*-----------------------------------------------------------------------------------*/
31 static int sci_dst_gen(const char *fname, types::Double* A, types::Double** O, int isn, guru_dim_struct gdim, int iopt);
32 /*-----------------------------------------------------------------------------------*/
sci_dst(types::typed_list & in,int _iRetCount,types::typed_list & out)33 types::Function::ReturnValue sci_dst(types::typed_list &in, int _iRetCount, types::typed_list &out)
34 {
35 std::wstring name(L"dst");
36 return fftw_common(name, in, _iRetCount, out, sci_dst_gen);
37 }
38 /*-----------------------------------------------------------------------------------*/
sci_dst_gen(const char * fname,types::Double * A,types::Double ** O,int isn,guru_dim_struct gdim,int iopt)39 int sci_dst_gen(const char *fname, types::Double* A, types::Double** O, int isn, guru_dim_struct gdim, int iopt)
40 {
41 *O = A->clone()->getAs<types::Double>();
42 int ndimsA = (*O)->getDims();
43 int *dimsA = (*O)->getDimsArray();
44 double *Ar = (*O)->get();
45 double *Ai = (*O)->getImg();
46
47 /* Input array variables */
48 int isrealA = (Ai == NULL), lA = 1;
49 double half = 0.5;
50
51 /*FFTW specific library variable */
52 enum Plan_Type type;
53 fftw_r2r_kind *kind = NULL;
54 fftw_plan p = NULL;
55
56 /* for MKL special cases */
57 int * dims1 = NULL;
58 int * incr1 = NULL;
59
60 /* local variable */
61 int one = 1;
62 int i = 0;
63 int errflag = 0;
64
65 for (i = 0; i < ndimsA; i++)
66 {
67 lA *= dimsA[i];
68 }
69
70 /* Set pointers on real and imaginary part of the input */
71
72 /* use inplace transform*/
73 type = R2R_PLAN;
74 if ((kind = (fftw_r2r_kind *)MALLOC(sizeof(fftw_r2r_kind) * gdim.rank)) == NULL)
75 {
76 Scierror(999, _("%s: Cannot allocate more memory.\n"), fname);
77 return 0;
78 }
79
80
81 if (isn == -1)
82 {
83 if (iopt == 0 || iopt == 1)
84 for (i = 0; i < gdim.rank; i++)
85 {
86 kind[i] = FFTW_RODFT00;
87 }
88 else if (iopt == 2)
89 for (i = 0; i < gdim.rank; i++)
90 {
91 kind[i] = FFTW_RODFT10;
92 }
93 else if (iopt == 4)
94 for (i = 0; i < gdim.rank; i++)
95 {
96 kind[i] = FFTW_RODFT11;
97 }
98 }
99 else
100 {
101 if (iopt == 0 || iopt == 1)
102 for (i = 0; i < gdim.rank; i++)
103 {
104 kind[i] = FFTW_RODFT00;
105 }
106 else if (iopt == 3)
107 for (i = 0; i < gdim.rank; i++)
108 {
109 kind[i] = FFTW_RODFT01;
110 }
111 else if (iopt == 4)
112 for (i = 0; i < gdim.rank; i++)
113 {
114 kind[i] = FFTW_RODFT11;
115 }
116 }
117
118 if (!WITHMKL || gdim.howmany_rank <= 1)
119 {
120 /* Set Plan */
121 p = GetFFTWPlan(type, &gdim, Ar, NULL, Ar, NULL, getCurrentFftwFlags(), isn, kind, &errflag);
122
123 if (errflag == 1)
124 {
125 Scierror(999, _("%s: Cannot allocate more memory.\n"), fname);
126 return 0;
127 }
128 else if (errflag == 2)
129 {
130 Scierror(999, _("%s: Creation of requested fftw plan failed.\n"), fname);
131 return 0;
132 }
133 /* execute FFTW plan */
134 ExecuteFFTWPlan(type, p, Ar, NULL, Ar, NULL);
135 if (!isrealA)
136 {
137 ExecuteFFTWPlan(type, p, Ai, NULL, Ai, NULL);
138 }
139
140 }
141 else
142 {
143 /*FFTW MKL does not implement yet guru plan with howmany_rank>1 */
144 /* associated loops described in gdim.howmany_rank and gdim.howmany_dims */
145 /* are implemented here by a set of call with howmany_rank==1 */
146 fftw_iodim *howmany_dims = gdim.howmany_dims;
147 int howmany_rank = gdim.howmany_rank;
148 int i1 = 0, i2 = 0;
149 int nloop = 0;
150 int t = 0;
151
152
153 gdim.howmany_rank = 0;
154 gdim.howmany_dims = NULL;
155
156 p = GetFFTWPlan(type, &gdim, Ar, NULL, Ar, NULL, getCurrentFftwFlags(), isn, kind, &errflag);
157 if (errflag == 1)
158 {
159 Scierror(999, _("%s: Cannot allocate more memory.\n"), fname);
160 FREE(dims1);
161 FREE(incr1);
162 return 0;
163 }
164 else if (errflag == 2)
165 {
166 Scierror(999, _("%s: Creation of requested fftw plan failed.\n"), fname);
167 FREE(dims1);
168 FREE(incr1);
169 return 0;
170 }
171
172 /* flatten nested loops: replace howmany_rank nested loops by a single one*/
173 /* Build temporary arrays used by flatened loop */
174 if ((dims1 = (int *)MALLOC(sizeof(int) * howmany_rank)) == NULL)
175 {
176 Scierror(999, _("%s: Cannot allocate more memory.\n"), fname);
177 FREE(dims1);
178 FREE(incr1);
179 return 0;
180 }
181 dims1[0] = howmany_dims[0].n;
182 for (i = 1; i < howmany_rank; i++)
183 {
184 dims1[i] = dims1[i - 1] * howmany_dims[i].n;
185 }
186 nloop = dims1[howmany_rank - 1];
187
188 if ((incr1 = (int *)MALLOC(sizeof(int) * howmany_rank)) == NULL)
189 {
190 Scierror(999, _("%s: Cannot allocate more memory.\n"), fname);
191 FREE(dims1);
192 FREE(incr1);
193 return 0;
194 }
195 t = 1;
196 for (i = 0; i < howmany_rank; i++)
197 {
198 t += (howmany_dims[i].n - 1) * howmany_dims[i].is;
199 incr1[i] = t;
200 }
201 /*loop on each "plan" */
202 i = 0; /*index on the first plan entry */
203 for (i1 = 1; i1 <= nloop; i1++)
204 {
205 /* the input and output are assumed to be complex because
206 within MKL real cases are transformed to complex ones in
207 previous steps of sci_dst_gen*/
208 ExecuteFFTWPlan(type, p, &Ar[i], NULL, &Ar[i], NULL);
209 if (!isrealA)
210 {
211 ExecuteFFTWPlan(type, p, &Ai[i], NULL, &Ai[i], NULL);
212 }
213
214 i += howmany_dims[0].is;
215 /* check if a loop ends*/
216 for (i2 = howmany_rank - 2; i2 >= 0; i2--)
217 {
218 if ((i1 % dims1[i2]) == 0)
219 {
220 /*loop on dimension i2 ends, compute jump on the first plan entry index*/
221 i += howmany_dims[i2 + 1].is - incr1[i2];
222 break;
223 }
224 }
225 }
226 /* free temporary arrays */
227 FREE(dims1);
228 FREE(incr1);
229 /* reset initial value of gdim for post treatment*/
230 gdim.howmany_rank = howmany_rank;
231 gdim.howmany_dims = howmany_dims;
232
233 }
234
235 /* normalization */
236 if (iopt == 0)
237 {
238 if (isn == -1)
239 {
240 C2F(dscal)(&lA, &half, Ar, &one);
241 if (!isrealA)
242 {
243 C2F(dscal)(&lA, &half, Ai, &one);
244 }
245 }
246 else
247 {
248 if (dst_scale_array(Ar, Ai, gdim, isn) == -1)
249 {
250 Scierror(999, _("%s: Cannot allocate more memory.\n"), fname);
251 return 0;
252 }
253 }
254 }
255 return 1;
256 }
257