1 #ifndef PyGSL_TRANSFORM_TYPES_H
2 #define PyGSL_TRANSFORM_TYPES_H 1
3 /*
4  * All different transforms are handled by only two functions.
5  *       PyGSL_transform_
6  * and
7  *       PyGSL_transform_2d_.
8  *
9  * This was done as similar functionallity is needed by all the transforms.
10  * Copy the input data (transforms are often in place), check or allocate
11  * help spaces. Call the function and make clean up. To allow that the
12  * functions need to do quite some decisions to prepare all in proper order
13  * and to do the clean up.
14  * In this file various data types are defined. The first two are needed by the
15  * python type which allows to allocate the proper help space and pass it to
16  * the function. All the others are needed to store the information about the
17  * transform.
18  */
19 
20 /* ------------------------------------------------------------------------- */
21 /*
22  * One Python type is used to encapsulate all the different workspaces. This
23  * enum allows the C Code to destinquish between the different types.
24  */
25 
26 enum pygsl_transform_space_type{
27 	NOSPACE=0,
28 	COMPLEX_WORKSPACE,
29 	REAL_WORKSPACE,
30 	COMPLEX_WAVETABLE,
31 	REAL_WAVETABLE,
32 	HALFCOMPLEX_WAVETABLE,
33 	COMPLEX_WORKSPACE_FLOAT,
34 	REAL_WORKSPACE_FLOAT,
35 	COMPLEX_WAVETABLE_FLOAT,
36 	REAL_WAVETABLE_FLOAT,
37 	HALFCOMPLEX_WAVETABLE_FLOAT,
38 	WAVELET_WORKSPACE
39 };
40 
41 #include <pygsl/pygsl_features.h>
42 #include <gsl/gsl_fft.h>
43 #include <gsl/gsl_fft_complex.h>
44 #include <gsl/gsl_fft_real.h>
45 #include <gsl/gsl_fft_halfcomplex.h>
46 #include <gsl/gsl_fft_complex_float.h>
47 #include <gsl/gsl_fft_real_float.h>
48 #include <gsl/gsl_fft_halfcomplex_float.h>
49 #include <gsl/gsl_blas.h>
50 #ifdef  _PYGSL_GSL_HAS_WAVELET
51 #define forward forward_wavelet
52 #define backward backward_wavelet
53 #include <gsl/gsl_wavelet.h>
54 #include <gsl/gsl_wavelet2d.h>
55 #undef forward
56 #undef backward
57 #else /* _PYGSL_GSL_HAS_WAVELET */
58 #endif /* _PYGSL_GSL_HAS_WAVELET */
59 
60 /*
61  * Here the corresponding union to address the pointer as the proper type.
62  */
63 union pygsl_transform_space_t{
64 	gsl_fft_complex_workspace           *cws;
65 	gsl_fft_complex_wavetable           *cwt;
66 	gsl_fft_real_workspace              *rws;
67 	gsl_fft_real_wavetable              *rwt;
68 	gsl_fft_halfcomplex_wavetable       *hcwt;
69 	gsl_fft_complex_workspace_float     *cwsf;
70 	gsl_fft_complex_wavetable_float     *cwtf;
71 	gsl_fft_real_workspace_float        *rwsf;
72 	gsl_fft_real_wavetable_float        *rwtf;
73 	gsl_fft_halfcomplex_wavetable_float *hcwtf;
74 #ifdef _PYGSL_GSL_HAS_WAVELET
75 	gsl_wavelet_workspace               *wws;
76 #endif
77 	void                                *v;
78 };
79 
80 /* ------------------------------------------------------------------------- */
81 /*
82  * From here all data types are defined needed to guide the transform
83  * functions.
84  */
85 /*
86  * Transformation in float or double mode
87  */
88 enum pygsl_transform_mode{
89 	MODE_DOUBLE = 1,
90 	MODE_FLOAT
91 };
92 
93 /*
94  * Input data in ... output data in ...
95  */
96 enum transform_mode{
97 	ComplexComplex = 1,
98 	RealReal,
99 	RealHalfcomplex,
100 	HalfComplexReal
101 
102 };
103 
104 /*
105  * Should be renamed. Originally the transform mode would only handle the FFT.
106  * There one only needed to destinquish between the radix. Wavelets are also a
107  * bit different. Others to come.
108  */
109 enum radix_mode{
110 	RADIX_TWO = 1,
111 	RADIX_FREE,
112 	WAVELET
113 };
114 
115 /*
116  * Does the basis type consist of only one machine type or two. e.g real
117  * is SINGLE_TYPE, complex PACKED_TYPE (a real and an imaginary part).
118  */
119 enum pygsl_packed_type{
120 	SINGLE_TYPE=1,
121 	PACKED_TYPE=2
122 };
123 
124 
125 #define PyGSL_TRANSFORM_MODE_SWITCH(mode, double_element, float_element) \
126         ((mode == MODE_DOUBLE) ? double_element : float_element)
127 
128 typedef int transform(void * data, size_t stride, size_t N, const void *, void *);
129 typedef int transform_r2(void * data, size_t stride, size_t N);
130 #ifdef  _PYGSL_GSL_HAS_WAVELET
131 typedef int wavelet(const gsl_wavelet * W, double *data, size_t stride, size_t N, void *);
132 typedef int wavelet2d(const gsl_wavelet * W, gsl_matrix *m, void *);
133 #endif
134 typedef void * pygsl_transform_helpn_t(int);
135 typedef void * pygsl_transform_help_t(void *);
136 
137 /*
138  * The different transform types.
139  */
140 union transforms{
141 	transform *free;
142 	transform_r2 *radix2;
143 #ifdef  _PYGSL_GSL_HAS_WAVELET
144 	wavelet *wavelet;
145 	wavelet2d *wavelet2d;
146 #endif
147 	void *v;
148 };
149 
150 /*
151  * Functions to construct and destruct the helpers space and the helpers table.
152  * The user can pass them as a proper python type. If not, the proper space
153  * will be allocated using these functions.
154  */
155 struct _pygsl_transform_func_rf_s {
156 	pygsl_transform_helpn_t  * space_alloc;
157 	pygsl_transform_help_t   * space_free;
158 	pygsl_transform_helpn_t  * table_alloc;
159 	pygsl_transform_help_t   * table_free;
160 	enum pygsl_transform_space_type space_type;
161 	enum pygsl_transform_space_type table_type;
162 };
163 
164 /*
165  * Not all transforms need additional workspace. The ones that need it will put
166  * an instance somewhere and point the func to the approbriate initalisers.
167  * free_space and free_table is used to store if the space and table have to be
168  * freeded at the end of the transform.
169  */
170 struct _pygsl_transform_help_rf_s{
171 	const struct _pygsl_transform_func_rf_s *func;
172 	void * space;
173 	void * table;
174 	int free_space;
175 	int free_table;
176 };
177 
178 /*
179  * The info about which transform, what input and output
180  * arrays and so forth. Used by _pygsl_transform_help_s to inform the transform
181  * function about the various properties.
182  */
183 struct _pygsl_transform_info_s {
184 	/*
185 	 *  complex -> complex
186 	 *  real    -> half_complex
187 	 *  half_complex -> real
188 	 *  real -> real
189 	 */
190 	enum transform_mode mode;
191         /* float or double ? */
192 	enum pygsl_transform_mode datatype;
193 	enum NPY_TYPES input_array_type;
194 	enum NPY_TYPES output_array_type;
195         /*
196 	 *  Do I need to add some additional offset to the data
197 	 *  pointer before
198 	 *  calling the function. A trick needed for the real to
199 	 *  halfcomplex transform.
200 	 */
201 	int data_offset;
202 	/* Type of the transform. Should be renamed */
203 	enum radix_mode radix2;
204 	/* one or two machine types make on basis type ? */
205 	enum pygsl_packed_type packed;
206 };
207 
208 /*
209  * Finally the struct which gathers all the information. The split up was made, as the
210  * info struct is always needed, but not the helpers.
211  */
212 struct _pygsl_transform_help_s{
213 	struct _pygsl_transform_info_s *info;
214 	union transforms  transform;
215 	struct _pygsl_transform_help_rf_s *helpers;
216 };
217 typedef  struct _pygsl_transform_help_s pygsl_transform_help_s;
218 
219 /*
220  * The main function doing all the work. Its a function for the ffts and a
221  *  method for the wavelets!
222  */
223 static PyObject *
224 PyGSL_transform_(PyObject *self, PyObject *args, pygsl_transform_help_s *helps);
225 
226 /*
227  * Currently only wavelets provide a 2 dimensional transform
228  */
229 #ifdef _PYGSL_GSL_HAS_WAVELET
230 static PyObject *
231 PyGSL_transform_2d_(PyObject *self, PyObject *args, pygsl_transform_help_s *helps);
232 #endif
233 
234 #endif /* PyGSL_TRANSFORM_TYPES_H */
235 /*
236  * Local Variables:
237  * mode: C
238  * c-file-style: "python"
239  * End:
240  */
241