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