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