1 /* -*- C -*- */
2 /*
3 * Author : Pierre Schnizer
4 * Date : January 2003
5 *
6 * Changes for better error reporting from
7 * 17. 01. 2003
8 * Adding a info struct. This struct contains additional information used for
9 * error Reporting.
10 *
11 * Changed to support Numeric and nummarray.
12 */
13
14 #define PyGSL_IMPORT_ARRAY 1
15 #include <pygsl/block_helpers.h>
16 #include <pygsl/old_numpy_compat.h>
17 #include <pygsl/error_helpers.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <pygsl/profile.h>
21 #include <pygsl/general_helpers.h>
22 #include <pygsl/utils.h>
23
24 static const char filename[] = __FILE__;
25
26 static int
27 PyGSL_array_check(PyObject * ob)
28 {
29 return PyArray_Check(ob);
30 }
31
32 /*
33 * PyGSL_PyArray_PREPARE_gsl_vector_view :
34 * Check if an array can be treated as vector.
35 *
36 * It is provided using a macro / function pair. The macro will accept a
37 * numpy array and return the pointer to the numpy object if the array is one
38 * dimensional and has the required number of elements. Further its
39 * contiguousity is checked. If the object did not fulfill the requirements the
40 * function PyGSL_PyArray_prepare_gsl_vector_view is called. This function will
41 * try to convert the object, or generate an approbriate error message. If the
42 * conversion is successful it will increase the profile counter
43 * pygsl_profile_vector_transform_counter via the macro
44 * PyGSL_INCREASE_vector_transform_counter().
45 *
46 * Input :
47 * object : a general python object
48 * array_type : the required C type for the array
49 * contiguous : 2 copy the original array
capture_ieee8021cb(const guchar * pd,int offset,int len,capture_packet_info_t * cpinfo,const union wtap_pseudo_header * pseudo_header)50 * 1 the array must be contigous,
51 * 0 discontigous ones are acceptable.
52 * size : length of the vector, or -1 if no check
53 * needed.
54 * argument number : The argument number. Used for error reporting
55 * info : a PyGSL_Error_info struct. Used for error
56 * reporting during callback evaluation. Pass
57 * NULL if not needed.
58 *
59 * Output:
60 * : a pointer to a PyArrayObject or NULL in case
61 * of error. This object must be dereferenced.
62 */
63 #ifdef NO_PyGSL_LEGACY
64 #endif /* NO_PyGSL_LEGACY */
65 PyGSL_API_EXTERN PyArrayObject *
66 PyGSL_PyArray_prepare_gsl_vector_view(PyObject *src,
67 int array_type,
68 int flag,
69 PyGSL_array_index_t size, int argnum, PyGSL_error_info * info);
70
71 /*
72 * PyGSL_PyArray_PREPARE_gsl_matrix_view
dissect_ieee8021cb(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)73 * Check if an array can be treated as matrix.
74 *
75 * It is provided using a macro / function pair. The macro will accept a
76 * numpy array and return the pointer to the numpy object if the array is two
77 * dimensional and has the required number of elements in both dimensions.
78 * Further its contiguousity is checked. If the object did not fulfill the
79 * requirements the function PyGSL_PyArray_prepare_gsl_matrix_view is called.
80 * This function will try to convert the object or generate an approbriate
81 * error message. If the conversion is successful it will increase the profile
82 * counter pygsl_profile_matrix_transform_counter via the macro
83 * PyGSL_INCREASE_matrix_transform_counter().
84 *
85 * Input :
86 * PyObject : a general python object
87 * array_type : the required C type for the array
88 * contiguous : 2 make a copy of that array!
89 * 1 the array must be contigous,
90 * 0 discontigous ones are acceptable.
91 * size1 : number of elements in the first dimension, or
92 * -1 if no check needed.
93 * size2 : number of elements in the second dimension, or
94 * -1 if no check needed.
95 * argument number : The argument number. Used for error reporting
96 * info struct : a PyGSL_Error_info struct. Used for error
97 * reporting during callback evaluation. Pass
98 * NULL if not needed.
99 *
100 * Output:
101 * : a pointer to a PyArrayObject or NULL in case
102 * of error. This object must be dereferenced.
103 *
104 * Important: When the data will be passed to gsl via gsl_matrix_view_array,
105 * then you must enforce an contiguous array.
106 */
107
108
109 PyGSL_API_EXTERN PyArrayObject *
110 PyGSL_PyArray_prepare_gsl_matrix_view(PyObject *src,
111 int array_type,
112 int flag,
113 PyGSL_array_index_t size1, PyGSL_array_index_t size2, int argnum,
114 PyGSL_error_info * info);
115
116 static int
117 PyGSL_stride_recalc(PyGSL_array_index_t strides, int basic_type_size,
118 PyGSL_array_index_t * stride_recalc)
119 {
120 int line;
121
122 FUNC_MESS_BEGIN();
123 line = __LINE__ + 1;
124 if((strides % basic_type_size) == 0) {
125 *stride_recalc = strides / basic_type_size;
126 DEBUG_MESS(2, "\tRecalculated strides to %ld", (long)*stride_recalc);
127 FUNC_MESS_END();
128 return GSL_SUCCESS;
129 }
130
131 DEBUG_MESS(2, "Failed to convert stride. %ld/%d != 0",
132 (long)strides, basic_type_size);
133 pygsl_error("Can not convert the stride to a GSL stride",
134 filename, __LINE__, PyGSL_ESTRIDE);
135 PyGSL_add_traceback(NULL, filename, __FUNCTION__, line);
136 return PyGSL_ESTRIDE;
137 }
proto_reg_handoff_ieee8021cb(void)138 /* ========================================================================= */
139 /*
140 * Implementation of the above routines.
141 */
142
143 static int
144 PyGSL_PyArray_Check(PyArrayObject *a_array, int array_type, int flag, int nd,
145 PyGSL_array_index_t *dimensions, int argnum, PyGSL_error_info * info)
146 {
147
148 int i;
149 int error_flag = GSL_ESANITY, line = -1, nd_test, type_num, array_flags;
150 PyGSL_array_index_t dim_temp, *dimensions_test;
151
152 FUNC_MESS_BEGIN();
153 if(!PyArray_Check((PyObject *) a_array)){
154 pygsl_error("Did not recieve an array!", filename, __LINE__, GSL_ESANITY);
155 line = __LINE__ - 2;
156 error_flag = GSL_ESANITY;
157 goto fail;
158 }
159 if(nd < 1 || nd > 2){
160 DEBUG_MESS(2, "Got an nd of %d", nd);
161 line = __LINE__ - 2;
162 pygsl_error("nd must either 1 or 2!", filename, __LINE__, GSL_ESANITY);
163 error_flag = GSL_ESANITY;
164 goto fail;
165 }
166
167 nd_test = PyArray_NDIM(a_array);
168 if (nd_test != nd){
169 DEBUG_MESS(3, "array->nd = %d\t nd = %d", nd_test, nd);
170 line = __LINE__ - 1;
171 sprintf(pygsl_error_str, "I could not convert argument number % 3d."
172 " I expected a %s, but got an array of % 3d dimensions!\n", argnum,
173 (nd == 1) ? "vector" : "matrix", nd_test);
174
175 if (info){
176 info->error_description = pygsl_error_str;
177 PyGSL_set_error_string_for_callback(info);
178 } else {
179 pygsl_error(pygsl_error_str, filename, __LINE__, GSL_EBADLEN);
180 }
181 error_flag = GSL_EBADLEN;
182 goto fail;
183 }
184
185
186
187 dimensions_test = PyArray_DIMS(a_array);
188
189 for(i=0; i<nd; ++i){
190 if(dimensions[i] == -1 ){
191 switch(i){
192 case 0:
193 DEBUG_MESS(2, "\t\t No one cares about its first dimension! %d", 0);
194 break;
195
196 case 1:
197 DEBUG_MESS(2, "\t\t No one cares about its second dimension! %d", 0);
198 break;
199
200 default:
201 error_flag = GSL_ESANITY;
202 line = __LINE__ - 3;
203 goto fail;
204 break;
205 }
206 continue;
207 }
208
209 /* Check to be performed ... */
210 dim_temp = dimensions_test[i];
211 DEBUG_MESS(9, "Dimension %d has %ld elements", i,
212 (unsigned long) dim_temp);
213
214 if(dim_temp != (dimensions[i])){
215 sprintf(pygsl_error_str,
216 "The size of argument % 3d did not match the expected"
217 " size for the %d dimension. I got % 3ld elements but"
218 " expected % 3ld elements!\n", argnum, i,
219 (long)dimensions_test[i],(long)dimensions[i]);
220
221 if (info){
222 info->error_description = pygsl_error_str;
223 PyGSL_set_error_string_for_callback(info);
224 } else {
225 pygsl_error(pygsl_error_str, filename, __LINE__, GSL_EBADLEN);
226 }
227 error_flag = GSL_EBADLEN;
228 line = __LINE__ - 11;
229 goto fail;
230 }
231 }
232
233 if(PyArray_DATA(a_array) == NULL){
234 pygsl_error("Got an array object were the data was NULL!", filename,
235 __LINE__, GSL_ESANITY);
236 error_flag = GSL_ESANITY;
237 line = __LINE__ - 4;
238 goto fail;
239 }
240
241 /* a_array->descr->type_num */
242 type_num = PyArray_TYPE(a_array);
243 if(type_num == array_type){
244 DEBUG_MESS(4, "\t\tArray type matched! %d", 0);
245 }else{
246 pygsl_error("The array type did not match the spezified one!",
247 filename, __LINE__, GSL_ESANITY);
248 DEBUG_MESS(4, "Found an array type of %d but expected %d",
249 (int) type_num, array_type);
250 error_flag = GSL_ESANITY;
251 line = __LINE__ - 6;
252 goto fail;
253 }
254
255 array_flags = PyArray_FLAGS(a_array);
256 if ((flag & PyGSL_CONTIGUOUS) == 0){
257 DEBUG_MESS(2, "\t\t Can deal with discontiguous arrays! flag = %d", flag);
258 } else {
259 if(!(array_flags & CONTIGUOUS)){
260 DEBUG_MESS(3, "array->flags %d requested flags %d",
261 array_flags, flag);
262 pygsl_error("The array is not contiguous as requested!", filename,
263 __LINE__, GSL_ESANITY);
264 error_flag = GSL_ESANITY;
265 line = __LINE__ - 3;
266 goto fail;
267 }
268 }
269 FUNC_MESS_END();
270 return GSL_SUCCESS;
271
272 fail:
273 PyGSL_add_traceback(NULL, filename, __FUNCTION__, line);
274 PyGSL_ERROR_FLAG(error_flag);
275 DEBUG_MESS(4, "common array types: Double %d, CDouble %d", NPY_DOUBLE, NPY_CDOUBLE);
276 DEBUG_MESS(4, "integer: Long %d, Int %d, Short %d", NPY_LONG, NPY_INT, NPY_SHORT);
277 /* DEBUG_MESS(8, "Char type %d Byte type %d String type %d", PyArray_CHAR, PyArray_BYTE, PyArray_STRING); */
278 return error_flag;
279 }
280
281
282 #include "block_helpers_numpy.ic"
283
284 #ifdef PyGSL_PY3K
285 #define _PyGSL_WRAP_LONG_FROM_PyObject(src) PyLong_AS_LONG(((src)))
286 #else
287 #define _PyGSL_WRAP_LONG_FROM_PyObject(src) ( PyInt_AsLong(((src))) )
288 #endif
289
290 static PyArrayObject *
291 PyGSL_PyArray_generate_gsl_vector_view(PyObject *src,
292 int array_type,
293 int argnum)
294 {
295 PyGSL_array_index_t dimension;
296 PyObject *tmp;
297 PyArrayObject *a_array = NULL;
298
299 FUNC_MESS_BEGIN();
300 tmp = PyNumber_Long(src);
301 if(!tmp){
302 sprintf(pygsl_error_str, "I could not convert argument number % 3d. to an integer.",
303 argnum);
304 PyErr_SetString(PyExc_TypeError, pygsl_error_str);
305 return NULL;
306 }
307 dimension = _PyGSL_WRAP_LONG_FROM_PyObject(src);
308 Py_DECREF(tmp);
309 if(dimension <= 0){
310 sprintf(pygsl_error_str,
311 "Argument number % 3d is % 10ld< 0. Its the size of the vector and thus must be positive!",
312 argnum, (long)dimension);
313 PyErr_SetString(PyExc_TypeError, pygsl_error_str);
314 return NULL;
315 }
316
317 a_array = (PyArrayObject *) PyGSL_New_Array(1, &dimension, array_type);
318 if(NULL == a_array){
319 return NULL;
320 }
321 FUNC_MESS_END();
322 return a_array;
323 }
324
325 static PyArrayObject *
326 PyGSL_PyArray_generate_gsl_matrix_view(PyObject *src,
327 int array_type,
328 int argnum)
329 {
330 PyObject *tmp;
331 PyArrayObject *a_array = NULL;
332
333 PyGSL_array_index_t dimensions[2];
334 int i;
335
336 FUNC_MESS_BEGIN();
337 if(!PySequence_Check(src) || PySequence_Size(src) != 2){
338 sprintf(pygsl_error_str, "I need a sequence of two elements as argument number % 3d",
339 argnum);
340 PyErr_SetString(PyExc_TypeError, pygsl_error_str);
341 return NULL;
342
343 }
344
345 for(i = 0; i<2; i++){
346 tmp = PyNumber_Long(PySequence_GetItem(src, i));
347 if(!tmp){
348 sprintf(pygsl_error_str, "I could not convert argument number % 3d. for dimension %3d to an integer.",
349 argnum, i);
350 PyErr_SetString(PyExc_TypeError, pygsl_error_str);
351 return NULL;
352 }
353
354 dimensions[i] = _PyGSL_WRAP_LONG_FROM_PyObject(tmp);
355 Py_DECREF(tmp);
356 if(dimensions[i] <= 0){
357 sprintf(pygsl_error_str, "Argument number % 3d is % 10ld< 0. Its the size of the vector and thus must be positive!",
358 argnum, (long)dimensions[i]);
359 PyErr_SetString(PyExc_TypeError, pygsl_error_str);
360 return NULL;
361 }
362
363 }
364 DEBUG_MESS(2, "Creating an array for a matrix with dimensions %ld %ld",
365 (long) dimensions[0], (long) dimensions[1]);
366
367 a_array = (PyArrayObject *) PyGSL_New_Array(2, dimensions, array_type);
368 if(NULL == a_array){
369 return NULL;
370 }
371 return a_array;
372 }
373
374 static PyArrayObject *
375 PyGSL_copy_gslvector_to_pyarray(const gsl_vector *x)
376 {
377 PyGSL_array_index_t dimension = -1, i;
378 PyArrayObject *a_array = NULL;
379 double tmp, *ptr = NULL;
380
381 FUNC_MESS_BEGIN();
382 dimension = x->size;
383 a_array = (PyArrayObject *) PyGSL_New_Array(1, &dimension, NPY_DOUBLE);
384 if (a_array == NULL) return NULL;
385
386 ptr = ((double *) PyArray_DATA(a_array));
387 for (i=0;i<dimension;i++){
388 tmp = gsl_vector_get(x, i);
389 ptr[i] = tmp;
390 DEBUG_MESS(3, "\t\ta_array_%ld = %f\n", (long)i, tmp);
391 }
392 FUNC_MESS_END();
393 return a_array;
394 }
395
396 static PyArrayObject *
397 PyGSL_copy_gslmatrix_to_pyarray(const gsl_matrix *x)
398 {
399 int i, j;
400 PyGSL_array_index_t dimensions[2], *strides;
401 PyArrayObject *a_array = NULL;
402 double tmp;
403 char *myptr, *data=NULL;
404
405 FUNC_MESS_BEGIN();
406 dimensions[0] = x->size1;
407 dimensions[1] = x->size2;
408 a_array = (PyArrayObject *) PyGSL_New_Array(2, dimensions, NPY_DOUBLE);
409 if (a_array == NULL) return NULL;
410
411 strides = PyArray_STRIDES(a_array);
412 data = (char *) PyArray_DATA(a_array);
413 for (i=0;i<dimensions[1];i++){
414 for (j=0;j<dimensions[0];j++){
415 myptr = data + strides[0] * i + strides[1] * j;
416 tmp = gsl_matrix_get(x, j, i);
417 *((double *) myptr) = tmp;
418 DEBUG_MESS(3, "\t\ta_array_%d = %f\n", i, tmp);
419 }
420 }
421 FUNC_MESS_END();
422 return a_array;
423 }
424
425
426 /*
427 * Set a descriptive error. The callback name is listed together with the "GSL Object"
428 * that called it, and a error description.
429 */
430 static int
431 PyGSL_copy_pyarray_to_gslvector(gsl_vector *f, PyObject *object, PyGSL_array_index_t n, PyGSL_error_info * info)
432 {
433 PyArrayObject *a_array = NULL;
434 double tmp;
435 int i, argnum = -1;
436 char *data;
437
438 PyGSL_array_index_t *dimensions =NULL, *strides = NULL;
439
440 FUNC_MESS_BEGIN();
441 if (info)
442 argnum = info->argnum;
443 a_array = PyGSL_vector_check(object, n, PyGSL_DARRAY_INPUT(argnum), NULL, info);
444 if(a_array == NULL){
445 FUNC_MESS("PyArray_FromObject failed");
446 goto fail;
447 }
448
449
450 dimensions = PyArray_DIMS(a_array);
451 strides = PyArray_STRIDES(a_array);
452 data = (char *) PyArray_DATA(a_array);
453
454 DEBUG_MESS(2, "\t\ta_array->dimensions[0] = %ld\n\t\ta_array->strides[0] = %ld",
455 (long)dimensions[0], (long)strides[0]);
456
457 for (i=0;i<n;i++){
458 tmp = *((double *) (data + strides[0] * i));
459 gsl_vector_set(f, i, tmp);
460 DEBUG_MESS(3, "\t\ta_array_%d = %f\n", i, tmp);
461
462 }
463 FUNC_MESS_END();
464 Py_DECREF(a_array);
465 return GSL_SUCCESS;
466 fail:
467 PyGSL_add_traceback(NULL, filename, __FUNCTION__, __LINE__);
468 FUNC_MESS("Failure");
469 Py_XDECREF(a_array);
470 return GSL_FAILURE;
471 }
472
473
474
475
476 static int
477 PyGSL_copy_pyarray_to_gslmatrix(gsl_matrix *f, PyObject *object, PyGSL_array_index_t n,
478 PyGSL_array_index_t p, PyGSL_error_info * info)
479 {
480 PyArrayObject *a_array = NULL;
481 double tmp;
482 char *myptr, *data=NULL;
483 int argnum=-1;
484 PyGSL_array_index_t *dimensions, *strides, i, j;
485
486 FUNC_MESS_BEGIN();
487
488
489
490 if (info){
491 argnum = info->argnum;
492 }
493
494 a_array = PyGSL_matrix_check(object, n, p, PyGSL_DARRAY_CINPUT(info->argnum), NULL, NULL, info);
495 if(a_array == NULL){
496 FUNC_MESS(" PyGSL_PyArray_PREPARE_gsl_matrix_view failed!");
497 goto fail;
498 }
499
500
501 assert(f->size1 == (size_t) n);
502 assert(f->size2 == (size_t) p);
503
504 strides = PyArray_STRIDES(a_array);
505 dimensions = PyArray_DIMS(a_array);
506 data = (char *) PyArray_DATA(a_array);
507
508 for (i=0;i<n;i++){
509 for (j=0;j<p;j++){
510 myptr = data + strides[0] * i + strides[1] * j;
511 tmp = *((double *)(myptr));
512 DEBUG_MESS(3, "\t\ta_array[%ld,%ld] = %f\n", i, j, tmp);
513 gsl_matrix_set(f, i, j, tmp);
514 }
515 }
516 FUNC_MESS_END();
517 Py_DECREF(a_array);
518 return GSL_SUCCESS;
519 fail:
520 PyGSL_add_traceback(NULL, filename, __FUNCTION__, __LINE__);
521 FUNC_MESS_FAILED();
522 Py_XDECREF(a_array);
523 return GSL_FAILURE;
524 }
525
526 static PyArrayObject *
527 PyGSL_vector_or_double(PyObject *src, PyGSL_array_info_t ainfo, PyGSL_array_index_t size, PyGSL_error_info * info)
528 {
529 int line = -1, status = GSL_EFAILED;
530 PyArrayObject * r = NULL;
531 PyGSL_array_index_t dim = 1;
532
533 FUNC_MESS_BEGIN();
534 if (PyGSL_GET_ARRAYTYPE(ainfo) != NPY_DOUBLE){
535 line = __LINE__ - 1;
536 status = GSL_ESANITY;
537 pygsl_error("Array request for vector or double is not a double array!",
538 __FILE__, line, status);
539 goto fail;
540 }
541 if (PyGSL_GET_TYPESIZE(ainfo) != sizeof(double)){
542 line = __LINE__ - 1;
543 status = GSL_ESANITY;
544 pygsl_error("Type size passed for vector or double is not of sizeof(double)!",
545 __FILE__, line, status);
546 goto fail;
547 }
548
549 r = PyGSL_vector_check(src, -1, ainfo, NULL, info);
550 if(r == NULL){
551 /* so try if it is a float ... */
552 double v;
553 /* was not an array, but lets see if it is a float, so lets clear the error .... */
554 PyErr_Clear();
555 FUNC_MESS("PyErr_Clear END");
556 if(PyGSL_PYFLOAT_TO_DOUBLE(src, &v, NULL) != GSL_SUCCESS){
557 line = __LINE__ - 1;
558 FUNC_MESS("=> NOT FLOAT");
559 goto fail;
560 }
561 FUNC_MESS("=> FLOAT");
562 r = (PyArrayObject *) PyGSL_New_Array(1, &dim, NPY_DOUBLE);
563 if(r == NULL) {
564 line = __LINE__ - 2;
565 goto fail;
566 }
567 (*(double *)PyArray_DATA(r)) = v;
568 }
569 FUNC_MESS_END();
570 return r;
571
572 fail:
573 FUNC_MESS_FAILED();
574 Py_XDECREF(r);
575 PyGSL_add_traceback(NULL, filename, __FUNCTION__, line);
576 PyGSL_ERROR_FLAG(status);
577 return NULL;
578 }
579
580
581 static PyArrayObject *
582 PyGSL_vector_check(PyObject *src, PyGSL_array_index_t size,
583 PyGSL_array_info_t ainfo,
584 PyGSL_array_index_t *stride, PyGSL_error_info * info)
585 {
586
587 int line=-1, tries, status = GSL_EFAILED;
588 PyArrayObject * a_array = NULL;
589 int array_type, flag, argnum, type_size;
590
591 PyGSL_array_index_t *dimensions, *strides;
592
593
594 FUNC_MESS_BEGIN();
595 array_type = PyGSL_GET_ARRAYTYPE(ainfo);
596 flag = PyGSL_GET_ARRAYFLAG(ainfo);
597 type_size = PyGSL_GET_TYPESIZE(ainfo);
598 argnum = PyGSL_GET_ARGNUM(ainfo);
599
600 DEBUG_MESS(2, "Type requests: array_type %d, flag %d, c type_size %d, argnum %d",
601 array_type, flag, type_size, argnum);
602 /*
603 * numpy arrays are which are non contiguous can have a stride which does
604 * not match the basis type. In this case the conversion is repeated and
605 * a contiguous array is demanded.
606 */
607 for(tries = 0; tries <2; ++tries){
608 /* try fast conversion first */
609 #if 0
610 a_array = PyGSL_VECTOR_CONVERT(src, array_type, flag);
611 if(a_array != NULL && a_array->nd == 1 &&
612 (size == -1 || a_array->dimensions[0] == size)) {
613 /* good ... everything fine */
614 ;
615 #else
616 if(0) {
617 ;
618 #endif
619 } else {
620 /* lets try if that goes okay */
621 if(a_array != NULL){
622 /* Array could be allocated previously... */
623 Py_DECREF(a_array);
624 }
625 a_array = PyGSL_PyArray_prepare_gsl_vector_view(src, array_type, flag, size, argnum, info);
626 if(a_array == NULL){
627 line = __LINE__ - 2;
628 goto fail;
629 }
630 }
631 if(stride == NULL){
632 /* no one interested in the stride. so help yourself ... */
633 break; /* will return array */
634 }
635
636 strides = PyArray_STRIDES(a_array);
637
638 if(PyGSL_STRIDE_RECALC(strides[0], type_size, stride) == GSL_SUCCESS){
639 /* everybody happy I hope! */
640 if((flag & PyGSL_CONTIGUOUS) == 1){
641 /*
642 * just a check to see ... could be disabled later on when
643 * the code is tested a little
644 */
645 if(PyGSL_DEBUG_LEVEL() > 0){
646 if(*stride != 1){
647 line = __LINE__ - 1;
648 status = GSL_ESANITY;
649 pygsl_error("Stride not one for a contiguous array!",
650 filename, line, status);
651 goto fail;
652 } /* stride */
653 }/*debug level */
654 }/* contiguous arrays */
655 break; /* will return array */
656 }
657
658
659 /* Lets try to see if it makes sense to meake a copy */
660 DEBUG_MESS(2, "Stride recalc failed type size is %ld, array stride[0] is %ld",
661 (long)type_size, (long)strides[0]);
662
663 if((flag & PyGSL_CONTIGUOUS) == 1){
664 line = __LINE__ - 1;
665 status = GSL_ESANITY;
666 pygsl_error("Why does the stride recalc fail for a contigous array?",
667 filename, line, status);
668 goto fail;
669 } else {
670 /* keep the flags, but demand contiguous this time */
671 flag -= (flag & PyGSL_CONTIGUOUS);
672 assert(a_array);
673 Py_DECREF(a_array);
674 a_array = NULL;
675 }
676
677 }/* number of tries */
678 DEBUG_MESS(7, "Checking refcount src obj @ %p had %ld cts and array @ %p has now %ld cts",
679 (void *) src, src->ob_refcnt, (void *)a_array,
680 PyGSL_PY_ARRAY_GET_REFCNT(a_array));
681
682 /* handling failed stride recalc */
683 FUNC_MESS_END();
684
685 return a_array;
686
687 fail:
688 FUNC_MESS("Fail");
689 PyGSL_ERROR_FLAG(status);
690 PyGSL_add_traceback(NULL, filename, __FUNCTION__, line);
691 Py_XDECREF(a_array);
692 return NULL;
693
694 }
695
696 /*
697 * maximum 0xffffffff
698 *
699 * array_type = flag & 0x000000ff
700 * type_size = flag & 0x0000ff00
701 * array_flag = flag & 0x00ff0000
702 * argnum = flag & 0xff000000
703 */
704
705
706 static PyArrayObject *
707 PyGSL_matrix_check(PyObject *src, PyGSL_array_index_t size1, PyGSL_array_index_t size2,
708 PyGSL_array_info_t ainfo, PyGSL_array_index_t *stride1,
709 PyGSL_array_index_t *stride2, PyGSL_error_info * info)
710 {
711 int line= __LINE__, tries, j;
712 PyArrayObject * a_array = NULL;
713 PyGSL_array_index_t * stride;
714 int array_type, flag, argnum, type_size;
715 PyGSL_array_index_t *dimensions, *strides;
716
717 FUNC_MESS_BEGIN();
718
719 array_type = PyGSL_GET_ARRAYTYPE(ainfo);
720 flag = PyGSL_GET_ARRAYFLAG(ainfo);
721 type_size = PyGSL_GET_TYPESIZE(ainfo);
722 argnum = PyGSL_GET_ARGNUM(ainfo);
723
724
725 /*
726 * numpy arrays are which are non contiguous can have a stride which does
727 * not match the basis type. In this case the conversion is repeated and
728 * a contiguous array is demanded.
729 */
730 for(tries = 0; tries <2; ++tries){
731 #if 0
732 a_array = PyGSL_MATRIX_CONVERT(src, array_type, flag);
733 if(a_array != NULL && a_array->nd == 1 &&
734 (size1 == -1 || a_array->dimensions[0] == size1) &&
735 (size2 == -1 || a_array->dimensions[1] == size2))
736 #else
737 if(0)
738 #endif
739 {
740 /* good ... everything fine */
741 ;
742
743 } else {
744 DEBUG_MESS(4, "PyGSL_MATRIX_CONVERT failed a_array = %p", a_array);
745 /* lets try if that goes okay */
746 if(a_array != NULL){
747 /* Array could be allocated previously... */
748 Py_DECREF(a_array);
749 }
750 a_array = PyGSL_PyArray_prepare_gsl_matrix_view(src, array_type, flag, size1, size2, argnum, info);
751 if(a_array == NULL){
752 line = __LINE__ - 2;
753 goto fail;
754 }
755 }
756
757 strides = PyArray_STRIDES(a_array);
758 for(j = 0; j<2; ++j){
759 switch(j){
760 case 0: stride = stride1; break;
761 case 1: stride = stride2; break;
762 default: assert(0);
763 }
764
765 if(stride == NULL){
766 /* no one interested in the stride. lets check the other one ... */
767 continue;
768 }
769
770
771 if(PyGSL_STRIDE_RECALC(strides[j], type_size, stride) == GSL_SUCCESS){
772 /* everybody happy I hope! */
773 if((flag & PyGSL_CONTIGUOUS) == 1){
774 /*
775 * just a check to see ... could be disabled later on when
776 * the code is tested a little
777 *
778 * 14. Oktober 2009: but only for the last dimension!
779 */
780 if(j == 1 && *stride != 1){
781 line = __LINE__ - 1;
782 DEBUG_MESS(6, "array stride %ld, type size %d, "
783 "found a stride of %ld",
784 (long) strides[j], type_size, (long) *stride);
785 pygsl_error("Stride not one of a contiguous array!",
786 filename, line, GSL_ESANITY);
787 goto fail;
788 }
789 }
790 } else {
791 /* Lets try to see if it makes sense to meake a copy */
792 DEBUG_MESS(2, "Stride recalc failed type size is %ld, array stride[0] is %ld",
793 (long)type_size, (long)strides[j]);
794
795 if((flag & PyGSL_CONTIGUOUS) == 1){
796 line = __LINE__ - 1;
797 pygsl_error("Why does the stride recalc fail for a contigous array?",
798 filename, line, GSL_ESANITY);
799 goto fail;
800 } else {
801 /* keep the flags, but demand contiguous this time */
802 DEBUG_MESS(3, "Matrix %p ot satisfying requests, trying this time contiguous", (void *) a_array);
803 flag -= (flag & PyGSL_CONTIGUOUS);
804 Py_DECREF(a_array);
805 a_array = NULL;
806 break;
807 }
808 } /* recalc stride or try again */
809 } /* check strides */
810 }/* number of tries */
811
812 /* handling failed stride recalc */
813 FUNC_MESS_END();
814 return a_array;
815
816
817 fail:
818 PyGSL_add_traceback(NULL, filename, __FUNCTION__, line);
819 Py_XDECREF(a_array);
820 return NULL;
821
822 }
823
824
825