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