1 #ifndef PyGSL_BLOCK_HELPERS_H
2 #define PyGSL_BLOCK_HELPERS_H 1
3 /*****************************************************************************
4  * The functions in this file are implemented in src/init/block_helpers*     *
5  * These functions try to simplify the conversion between the PyArrayObjects *
6  * and the gsl_vector and gsl_matrix types. Further they try to provide a    *
7  * compatibility layer for the different implementations of the              *
8  * PyArrayObjects (Numeric, numarray, numpy). All code using the functions   *
9  * must:                                                                     *
10  *       Use these functions here :-)					     *
11  *       Declare all varibales referencing dimensions and indexing arrays    *
12  *       "PyGSL_array_index_t"						     *
13  *       Expect these variables to be either of type int or long. This most  *
14  *       probable is only noticable on 64bit architectures.		     *
15  *****************************************************************************/
16 /*
17  * Author:  Pierre Schnizer
18  *
19  * $Id:
20  */
21 #undef __BEGIN_DECLS
22 #undef __END_DECLS
23 #ifdef __cplusplus
24 # define __BEGIN_DECLS extern "C" {
25 # define __END_DECLS }
26 #else
27 # define __BEGIN_DECLS /* empty */
28 # define __END_DECLS /* empty */
29 #endif
30 
31 
32 /*
33 #define PY_ARRAY_UNIQUE_SYMBOL PyGSL_PY_ARRAY_API
34 */
35 
36 #ifndef _PyGSL_API_MODULE
37 /*
38  * Not possible to just import the declaration of the PyArrayObject struct. The
39  * pointer comes along as well ...
40  *
41  */
42 #ifndef PyGSL_IMPORT_ARRAY
43 #define NO_IMPORT_ARRAY
44 #endif
45 #endif  /* _PyGSL_API_MODULE */
46 
47 #include <limits.h>
48 #include <pygsl/intern.h>
49 #include <pygsl/utils.h>
50 #include <pygsl/general_helpers.h>
51 
52 __BEGIN_DECLS
53 
54 /*
55  * Build array info out of various parts.
56  *
57  * array_flag
58  */
59 
60 #if ULONG_MAX < 0xffffff
61 #error "unsigned long not big enough for array info"
62 #else
63 typedef unsigned long PyGSL_array_info_t;
64 #endif
65 
66 
67 
68 /* typedef Py_ssize_t PyGSL_array_index_t; */
69 /*
70 #if PY_VERSION_HEX < 0x02050000
71 typedef int Py_ssize_t;
72 #endif
73 */
74 #include <pygsl/arrayobject.h>
75 #ifndef PyGSL_NUMPY
76 #error "Only numpy interface supported any longer"
77 #endif
78 #ifdef PyGSL_NUMPY
79 #include <numpy/arrayobject.h>
80 #endif
81 #ifdef PyGSL_NUMERIC
82 #include <Numeric/arrayobject.h>
83 #endif
84 #ifdef PyGSL_NUMARRAY
85 #include <numarray/libnumarray.h>
86 #endif
87 #if (!defined PyGSL_NUMPY) && (!defined  PyGSL_NUMERIC) && (!defined PyGSL_NUMARRAY)
88 #error "Neither numpy nor numarray nor Numeric is defined!"
89 #endif
90 /*
91  *  required for 64 bit machines; backward compability. I rather perfer
92  *  to declare it as a long as its just my functions.
93  *
94  *  For now I keep it as the same type as the underlaying array package
95  *  uses for its conversions.
96  */
97 #ifdef PyGSL_NUMERIC
98 typedef int PyGSL_array_index_t;
99 #endif
100 #ifdef PyGSL_NUMARRAY
101 typedef maybelong PyGSL_array_index_t;
102 #endif
103 #ifdef PyGSL_NUMPY
104 /* typedef intp PyGSL_array_index_t; */
105 typedef npy_intp PyGSL_array_index_t;
106 #endif
107 
108 
109 
110 #include <gsl/gsl_vector.h>
111 #include <gsl/gsl_matrix.h>
112 
113 enum PyGSL_Array_Flags {
114      PyGSL_NON_CONTIGUOUS = 0,
115      PyGSL_CONTIGUOUS = 1,
116      /* Additional flags needed for numarray and numpy */
117      PyGSL_INPUT_ARRAY = 2,
118      PyGSL_OUTPUT_ARRAY = 4,
119      PyGSL_IO_ARRAY = 8
120 };
121 
122 /*
123  * Convienience functions for handling the flags
124  */
125 #define PyGSL_GET_ARRAYFLAG(flag) (( (flag) >>  0) & 0x000000ff)
126 #define PyGSL_GET_ARRAYTYPE(flag) (( (flag) >>  8) & 0x000000ff)
127 #define PyGSL_GET_TYPESIZE(flag)  (( (flag) >> 16) & 0x000000ff)
128 #define PyGSL_GET_ARGNUM(flag)    (( (flag) >> 24) & 0x000000ff)
129 
130 #define PyGSL_BUILD_ARRAY_INFO(array_flag, array_type, type_size, argnum) \
131 (\
132  (  ((array_flag) & 0x000000ff) <<  0) + \
133  (  ((array_type) & 0x000000ff) <<  8) + \
134  (  ((type_size)  & 0x000000ff) << 16) + \
135  (  ((argnum)     & 0x000000ff) << 24)   \
136 )
137 
138 
139 #define PyGSL_DARRAY_INFO(array_flag, argnum)  \
140    PyGSL_BUILD_ARRAY_INFO(array_flag, NPY_DOUBLE, sizeof(double), argnum)
141 #define PyGSL_DARRAY_CINPUT(argnum)  PyGSL_DARRAY_INFO(PyGSL_CONTIGUOUS     | PyGSL_INPUT_ARRAY, argnum)
142 #define PyGSL_DARRAY_INPUT(argnum)   PyGSL_DARRAY_INFO(PyGSL_NON_CONTIGUOUS | PyGSL_INPUT_ARRAY, argnum)
143 #define PyGSL_DARRAY_CIO(argnum)     PyGSL_DARRAY_INFO(PyGSL_CONTIGUOUS     | PyGSL_IO_ARRAY,    argnum)
144 
145 
146 #define PyGSL_CARRAY_INFO(array_flag, argnum)				\
147    PyGSL_BUILD_ARRAY_INFO(array_flag, NPY_CDOUBLE, 2 * sizeof(double), argnum)
148 #define PyGSL_CARRAY_CINPUT(argnum)  PyGSL_CARRAY_INFO(PyGSL_CONTIGUOUS     | PyGSL_INPUT_ARRAY, argnum)
149 #define PyGSL_CARRAY_CIO(argnum)     PyGSL_CARRAY_INFO(PyGSL_CONTIGUOUS     | PyGSL_IO_ARRAY,    argnum)
150 
151 /*
152  * PyGSL_New_Array:
153  *                Generate an new array with the specified dimensions.
154  *
155  *                The numpy backend expects an array of int, whereas
156  *                the numarray backend expects  an array of long
157  */
158 PyGSL_API_EXTERN PyArrayObject *
159 PyGSL_New_Array(int nd,  PyGSL_array_index_t *dimensions, int type);
160 
161 /*
162  * PyGSL_Copy_Array:
163  *
164  *                 Copy an array. The output array will have the same
165  *                 size as the input array.
166  */
167 PyGSL_API_EXTERN PyArrayObject *
168 PyGSL_Copy_Array(PyArrayObject *, int type);
169 
170 /*
171  * PyGSL_STRIDE_RECALC:
172  *                                Recalc a stride and check if it is okay
173  *
174  * Numpy calculates strides in bytes, gsl as multiple of the basis type size
175  *
176  * Return value:
177  *         -1: Conversion Failed
178  *         pos : recalculated stride
179  */
180 PyGSL_API_EXTERN int
181 PyGSL_stride_recalc(PyGSL_array_index_t strides, int basis_type_size,
182 		    PyGSL_array_index_t * stride_recalc);
183 
184 
185 
186 
187 /*
188  * PyGSL_PyArray_generate_gsl_vector_view :
189  *                                 Generate an new array of given dimensions .
190  *
191  *  This function will try to convert the object, to a Python integer and
192  *  generate an apropriate one dimensional numpy array.
193  *
194  * Input :
195  *         object              : a general python object
196  *         array_type          : the required C type for the array
197  *         argument number     : The argument number. Used for error reporting
198  *
199  * Output:
200  *                             : a pointer to a PyArrayObject or NULL in case
201  *                              of error. This object must be dereferenced.
202  */
203 PyGSL_API_EXTERN PyArrayObject *
204 PyGSL_PyArray_generate_gsl_vector_view(PyObject *src,
205 				       int array_type,
206 				       int argnum);
207 
208 /*
209  * PyGSL_PyArray_generate_gsl_matrix_view :
210  *                                 Generate an new array of given dimensions .
211  *
212  *  This function will try to convert the object, to a sequence of two Python
213  *  integer and generate an apropriate two dimensional numpy array.
214  *
215  * Input :
216  *         object              : a general python object
217  *         array_type          : the required C type for the array
218  *         argument number     : The argument number. Used for error reporting
219  *
220  * Output:
221  *                             : a pointer to a PyArrayObject or NULL in case
222  *                              of error. This object must be dereferenced.
223  */
224 PyGSL_API_EXTERN PyArrayObject *
225 PyGSL_PyArray_generate_gsl_matrix_view(PyObject *src,
226 				       int array_type,
227 				       int argnum);
228 
229 
230 
231 /*
232  * Check if a python object can be used as a vector. If so return an
233  *  approbriate python array object.
234  *
235  *
236  * Input:
237  *      src        ... the python object
238  *      size       ... the required size. Pass -1 if it should not be checked.
239  *
240  *      array_type ... the required type.
241  *      flag       ... shall be an input or output or inout array?
242  *                 ... shall it be contiguous?
243  *      argnum     ... the positional argument number. Used when reporting an
244  *                     error
245  *
246  *                     Information if the stride of the vector should be
247  *                     recalulated to the native C type.
248  *      type_size  ... the size of the native C type (typically sizeof(type)).
249  *                     If stride is NULL this value is without meaning.
250  *
251  *      *stride    ... the recalculated stride. If NULL stride will not be
252  *                      recalulated, and the following items can be of any value
253  *
254  *      info       ... info structure passed by callbacks for reporting an error
255  *
256  *     Convienience macros:
257  *                PyGSL_DVECTOR_CHECK(src, size, flag, argnum, stride, info)
258  */
259 PyGSL_API_EXTERN PyArrayObject *
260 PyGSL_vector_check(PyObject *src, PyGSL_array_index_t size, PyGSL_array_info_t ainfo,
261 		   PyGSL_array_index_t *stride, PyGSL_error_info * info);
262 
263 
264 /*
265  * Check if a python object can be used as a vector. If so return an
266  * approbriate python array object.
267  *
268  *
269  * Input:
270  *      src        ... the python object
271  *
272  *      size1      ... the required size of the first dimension.  Pass -1 if it
273  *                     should not be checked.
274  *      size2     ...  the required size of the second dimension. Pass -1 if it
275  *                     should not be checked.
276  *
277  *      array_type ... the required type.
278  *      flag       ... shall be an input or output or inout array?
279  *                     shall it be contiguous?
280  *      argnum     ... the positional argument number. Used when reporting an
281  *                     error
282  *
283  *                     Information if the stride of the vector should be
284  *                     recalulated to the native C type.
285  *      type_size  ... the size of the native C type (typically sizeof(type)).
286  *                     If stride is NULL this value is without meaning.
287  *
288  *      *stride1   ... the recalculated stride. If NULL stride will not be
289  *                      recalulated, and the following items can be of any value
290  *      *stride2   ... the recalculated stride. If NULL stride will not be
291  *                      recalulated, and the following items can be of any value
292  *
293  *      info       ... info structure passed by callbacks for reporting an error
294  *
295  *     Convienience macros:
296  *       PyGSL_DMATRIX_CHECK(src, size1, size2, flag, argnum, stride1, stride2, info)
297  */
298 PyGSL_API_EXTERN PyArrayObject *
299 PyGSL_matrix_check(PyObject *src, PyGSL_array_index_t size1, PyGSL_array_index_t size2,
300 		   PyGSL_array_info_t ainfo,
301 		   PyGSL_array_index_t *stride1, PyGSL_array_index_t *stride2,
302 		   PyGSL_error_info * info);
303 
304 /*
305  * PyGSL_copy_pyarray_to_gslvector
306  *                           Copy the contents of a pyarray to a gsl_vector.
307  *
308  *
309  * Input :
310  *         f                   : a pointer to the target vector
311  *         object              : a general python object
312  *         n                   : number of elements
313  *         info                : a PyGSL_Error_info struct. Used for error
314  *                               reporting during callback evaluation. Pass
315  *                               NULL if not needed.
316  *
317  * Output:
318  *                             : GSL_SUCCESS | GSL_FAILURE
319  *
320  */
321 PyGSL_API_EXTERN int
322 PyGSL_copy_pyarray_to_gslvector(gsl_vector *f, PyObject *object, PyGSL_array_index_t n,
323 				PyGSL_error_info * info);
324 
325 /*
326  * PyGSL_copy_pyarray_to_gslmatrix
327  *                           Copy the contents of a pyarray to a gsl_matrix.
328  *
329  *
330  * Input :
331  *         f                   : a pointer to the target gsl_vector
332  *         object              : a general python object referring to a numpy
333  *                               array
334  *         n                   : number of elements in the first dimension
335  *         p                   : number of elements in the second dimension
336  *         info                : a PyGSL_error_info struct. Used for error
337  *                               reporting during callback evaluation. Pass
338  *                               NULL if not needed.
339  *
340  * Output:
341  *                             : GSL_SUCCESS | GSL_FAILURE
342  *
343  */
344 PyGSL_API_EXTERN int
345 PyGSL_copy_pyarray_to_gslmatrix(gsl_matrix *f, PyObject *object,  PyGSL_array_index_t n,
346 				PyGSL_array_index_t p, PyGSL_error_info * info);
347 
348 PyGSL_API_EXTERN PyArrayObject *
349 PyGSL_vector_or_double(PyObject *src, PyGSL_array_info_t ainfo, PyGSL_array_index_t size,
350 		       PyGSL_error_info * info);
351 
352 
353 /*
354  * PyGSL_copy_gslvector_to_pyarrary :
355  *                Generate a new numpy array of approbriate size and copy the
356  *                data of the vector to it.
357  *
358  *
359  * Input :
360  *              x              : a gsl_vector
361  * Output:
362  *                             : a pointer to a PyArrayObject or NULL in case
363  *                              of error. This object must be dereferenced.
364  */
365 PyGSL_API_EXTERN PyArrayObject *
366 PyGSL_copy_gslvector_to_pyarray(const gsl_vector *x);
367 
368 /*
369  * PyGSL_copy_gslmatrix_to_pyarrary :
370  *                Generate a new numpy array of approbriate size and copy the
371  *                data of the matrix to it.
372  *
373  *
374  * Input :
375  *              x              : a gsl_matrix
376  * Output:
377  *                             : a pointer to a PyArrayObject or NULL in case
378  *                              of error. This object must be dereferenced.
379  */
380 PyGSL_API_EXTERN PyArrayObject *
381 PyGSL_copy_gslmatrix_to_pyarray(const gsl_matrix *x);
382 #ifndef _PyGSL_API_MODULE
383 #define PyGSL_stride_recalc \
384 (*(int (*)(PyGSL_array_index_t, int, PyGSL_array_index_t * ))                                        PyGSL_API[PyGSL_stride_recalc_NUM])
385 #define  PyGSL_New_Array  \
386 (*(PyArrayObject * (*)(int, PyGSL_array_index_t *, int))                              PyGSL_API[PyGSL_PyArray_new_NUM])
387 #define  PyGSL_Copy_Array  \
388 (*(PyArrayObject * (*)(PyArrayObject *))                               PyGSL_API[PyGSL_PyArray_copy_NUM])
389 #ifdef NO_PyGSL_LEGACY
390 #define  PyGSL_PyArray_prepare_gsl_vector_view  \
391 (*(PyArrayObject * (*)(PyObject *, int, int,  PyGSL_array_index_t, int, PyGSL_error_info *)) \
392                                                                      PyGSL_API[PyGSL_PyArray_prepare_gsl_vector_view_NUM])
393 #define  PyGSL_PyArray_prepare_gsl_matrix_view  \
394 (*(PyArrayObject * (*)(PyObject *, int, int,  PyGSL_array_index_t, PyGSL_array_index_t, int, PyGSL_error_info *)) \
395                                                                      PyGSL_API[PyGSL_PyArray_prepare_gsl_matrix_view_NUM])
396 #endif /* NO_PyGSL_LEGACY */
397 #define PyGSL_PyArray_generate_gsl_vector_view \
398 (*(PyArrayObject *(*)(PyObject *, int, int))          PyGSL_API[PyGSL_PyArray_generate_gsl_vector_view_NUM])
399 
400 #define PyGSL_PyArray_generate_gsl_matrix_view \
401 (*(PyArrayObject *(*)(PyObject *, int, int))          PyGSL_API[PyGSL_PyArray_generate_gsl_matrix_view_NUM])
402 
403 #define PyGSL_copy_pyarray_to_gslvector \
404 (*(int (*) (gsl_vector *, PyObject *, PyGSL_array_index_t, PyGSL_error_info *))      PyGSL_API[PyGSL_copy_pyarray_to_gslvector_NUM])
405 #define PyGSL_copy_pyarray_to_gslmatrix \
406 (*(int (*) (gsl_matrix *, PyObject *, PyGSL_array_index_t, PyGSL_array_index_t, PyGSL_error_info *)) PyGSL_API[PyGSL_copy_pyarray_to_gslmatrix_NUM])
407 
408 #define PyGSL_copy_gslvector_to_pyarray \
409  (*(PyArrayObject * (*)(const gsl_vector *))                         PyGSL_API[ PyGSL_copy_gslvector_to_pyarray_NUM])
410 
411 #define PyGSL_copy_gslmatrix_to_pyarray \
412  (*(PyArrayObject * (*)(const gsl_matrix *))                         PyGSL_API[ PyGSL_copy_gslmatrix_to_pyarray_NUM])
413 
414 
415 #define  PyGSL_vector_or_double  \
416 (*(PyArrayObject * (*)(PyObject *, PyGSL_array_info_t , PyGSL_array_index_t, PyGSL_error_info *)) \
417                                                                      PyGSL_API[PyGSL_vector_or_double_NUM])
418 
419 #define PyGSL_vector_check  \
420 (*(PyArrayObject * (*) (PyObject *, PyGSL_array_index_t, \
421  PyGSL_array_info_t, PyGSL_array_index_t *, PyGSL_error_info *)) \
422                                                                       PyGSL_API[PyGSL_vector_check_NUM])
423 
424 #define PyGSL_matrix_check  \
425 (*(PyArrayObject * (*) (PyObject *, PyGSL_array_index_t, PyGSL_array_index_t, \
426  PyGSL_array_info_t, PyGSL_array_index_t *, PyGSL_array_index_t *, PyGSL_error_info *)) \
427                                                                       PyGSL_API[PyGSL_matrix_check_NUM])
428 
429 #define PyGSL_array_check (*(int (*)(PyObject *))  PyGSL_API[PyGSL_array_check_NUM])
430 #define PyGSL_array_return(ob) ((PyObject *) ob)
431 #endif /* _PyGSL_API_MODULE */
432 
433 #define PyGSL_STRIDE_RECALC(strides, basis_type_size, stride_recalc) \
434       ( \
435            (((strides) % (basis_type_size)) == 0) \
436          ? \
437            ( ((*(stride_recalc)) = (strides) / (basis_type_size)), GSL_SUCCESS ) \
438          : \
439            PyGSL_stride_recalc(strides, basis_type_size, stride_recalc) \
440      )
441 /*
442 #define PyGSL_DVECTOR_CHECK(src, size, info, stride, info) \
443 PyGSL_vector_check(src, size, PyArray_DOUBLE, sizeof(double), flag, argnum, stride, info)
444 
445 #define PyGSL_DMATRIX_CHECK(src, size1, size2, flag, argnum, stride1, stride2, info) \
446 PyGSL_vector_check(src, size1, size2, PyArray_DOUBLE, sizeof(double), flag, argnum, stride1, stride2, info)
447 */
448 
449 #ifdef PyGSL_NUMPY
450 #include <pygsl/block_helpers_numpy.h>
451 #endif
452 
453 #ifdef PyGSL_NUMERIC
454 #include <pygsl/block_helpers_numeric.h>
455 #endif
456 
457 #ifdef PyGSL_NUMARRAY
458 #include <pygsl/block_helpers_numarray.h>
459 #endif
460 
461 __END_DECLS
462 #endif /* PyGSL_BLOCK_HELPERS_H */
463