/* -*- C -*- */ /* * Author : Pierre Schnizer * Date : January 2003 * * Changes for better error reporting from * 17. 01. 2003 * Adding a info struct. This struct contains additional information used for * error Reporting. * * Changed to support Numeric and nummarray. */ #define PyGSL_IMPORT_ARRAY 1 #include #include #include #include #include #include #include static const char filename[] = __FILE__; static int PyGSL_stride_recalc(int strides, int basic_type_size, int * stride_recalc) { int line; FUNC_MESS_BEGIN(); line = __LINE__ + 1; if((strides % basic_type_size) == 0) { *stride_recalc = strides / basic_type_size; DEBUG_MESS(2, "\tRecalculated strides to %d", *stride_recalc); FUNC_MESS_END(); return GSL_SUCCESS; } DEBUG_MESS(2, "Failed to convert stride. %d/%d != 0", strides, basic_type_size); gsl_error("Can not convert the stride to a GSL stride", filename, __LINE__, PyGSL_ESTRIDE); PyGSL_add_traceback(NULL, filename, __FUNCTION__, line); return PyGSL_ESTRIDE; } /* ========================================================================= */ /* * Implementation of the above routines. */ static int PyGSL_PyArray_Check(PyArrayObject *a_array, int array_type, int flag, int nd, long *dimensions, int argnum, PyGSL_error_info * info) { int i; int error_flag = GSL_ESANITY, line = -1; FUNC_MESS_BEGIN(); if(!PyArray_Check((PyObject *) a_array)){ gsl_error("Did not recieve an array!", filename, __LINE__, GSL_ESANITY); line = __LINE__ - 2; error_flag = GSL_ESANITY; goto fail; } if(nd < 1 || nd > 2){ DEBUG_MESS(2, "Got an nd of %d", nd); line = __LINE__ - 2; gsl_error("nd must either 1 or 2!", filename, __LINE__, GSL_ESANITY); error_flag = GSL_ESANITY; goto fail; } if (a_array->nd != nd){ DEBUG_MESS(3, "array->nd = %d\t nd = %d", a_array->nd, nd); line = __LINE__ - 1; sprintf(pygsl_error_str, "I could not convert argument number % 3d." " I expected a %s, but got an array of % 3d dimensions!\n", argnum, (nd == 1) ? "vector" : "matrix", a_array->nd); if (info){ info->error_description = pygsl_error_str; PyGSL_set_error_string_for_callback(info); } else { gsl_error(pygsl_error_str, filename, __LINE__, GSL_EBADLEN); } error_flag = GSL_EBADLEN; goto fail; } for(i=0; idimensions[i] != (dimensions[i])){ sprintf(pygsl_error_str, "The size of argument % 3d did not match the expected size for the %d dimension." " I got % 3ld elements but expected % 3ld elements!\n", argnum, i, (long)a_array->dimensions[0], dimensions[0]); if (info){ info->error_description = pygsl_error_str; PyGSL_set_error_string_for_callback(info); } else { gsl_error(pygsl_error_str, filename, __LINE__, GSL_EBADLEN); } error_flag = GSL_EBADLEN; line = __LINE__ - 11; goto fail; } } if( ((PyArrayObject *) (a_array))->data == NULL){ gsl_error("Got an array object were the data was NULL!", filename, __LINE__, GSL_ESANITY); error_flag = GSL_ESANITY; line = __LINE__ - 4; goto fail; } if( ((PyArrayObject *) (a_array))->descr->type_num == (array_type) ) DEBUG_MESS(4, "\t\tArray type matched! %d", 0); else{ gsl_error("The array type did not match the spezified one!", filename, __LINE__, GSL_ESANITY); error_flag = GSL_ESANITY; line = __LINE__ - 6; goto fail; } if ((flag & PyGSL_CONTIGUOUS) == 0){ DEBUG_MESS(2, "\t\t Can deal with discontiguous arrays! %d", 0); } else { if(!(((PyArrayObject *) (a_array))->flags & CONTIGUOUS )){ gsl_error("The array is not contiguous as requested!", filename, __LINE__, GSL_ESANITY); error_flag = GSL_ESANITY; line = __LINE__ - 3; goto fail; } } FUNC_MESS_END(); return GSL_SUCCESS; fail: PyGSL_add_traceback(NULL, filename, __FUNCTION__, line); return error_flag; } static PyArrayObject * PyGSL_PyArray_generate_gsl_vector_view(PyObject *src, int array_type, int argnum) { int dimension; PyObject *tmp; PyArrayObject *a_array = NULL; FUNC_MESS_BEGIN(); tmp = PyNumber_Int(src); if(!tmp){ sprintf(pygsl_error_str, "I could not convert argument number % 3d. to an integer.", argnum); PyErr_SetString(PyExc_TypeError, pygsl_error_str); return NULL; } dimension = PyInt_AS_LONG(src); Py_DECREF(tmp); if(dimension <= 0){ sprintf(pygsl_error_str, "Argument number % 3d is % 10d< 0. Its the size of the vector and thus must be positive!", argnum, dimension); PyErr_SetString(PyExc_TypeError, pygsl_error_str); return NULL; } a_array = (PyArrayObject *) PyGSL_New_Array(1, &dimension, array_type); if(NULL == a_array){ return NULL; } FUNC_MESS_END(); return a_array; } static PyArrayObject * PyGSL_PyArray_generate_gsl_matrix_view(PyObject *src, int array_type, int argnum) { PyObject *tmp; PyArrayObject *a_array = NULL; int dimensions[2], i; FUNC_MESS_BEGIN(); if(!PySequence_Check(src) || PySequence_Size(src) != 2){ sprintf(pygsl_error_str, "I need a sequence of two elements as argument number % 3d", argnum); PyErr_SetString(PyExc_TypeError, pygsl_error_str); return NULL; } for(i = 0; i<2; i++){ tmp = PyNumber_Int(PySequence_GetItem(src, i)); if(!tmp){ sprintf(pygsl_error_str, "I could not convert argument number % 3d. for dimension %3d to an integer.", argnum, i); PyErr_SetString(PyExc_TypeError, pygsl_error_str); return NULL; } dimensions[i] = PyInt_AS_LONG(tmp); Py_DECREF(tmp); if(dimensions[i] <= 0){ sprintf(pygsl_error_str, "Argument number % 3d is % 10d< 0. Its the size of the vector and thus must be positive!", argnum, dimensions[i]); PyErr_SetString(PyExc_TypeError, pygsl_error_str); return NULL; } } a_array = (PyArrayObject *) PyGSL_New_Array(2, dimensions, array_type); if(NULL == a_array){ return NULL; } return a_array; } static PyArrayObject * PyGSL_copy_gslvector_to_pyarray(const gsl_vector *x) { int dimension = -1, i; PyArrayObject *a_array = NULL; double tmp; FUNC_MESS_BEGIN(); dimension = x->size; a_array = (PyArrayObject *) PyGSL_New_Array(1, &dimension, PyArray_DOUBLE); if (a_array == NULL) return NULL; for (i=0;idata)[i] = tmp; DEBUG_MESS(3, "\t\ta_array_%d = %f\n", i, tmp); } FUNC_MESS_END(); return a_array; } static PyArrayObject * PyGSL_copy_gslmatrix_to_pyarray(const gsl_matrix *x) { int dimensions[2], i, j; PyArrayObject *a_array = NULL; double tmp; char *myptr; FUNC_MESS_BEGIN(); dimensions[0] = x->size1; dimensions[1] = x->size2; a_array = (PyArrayObject *) PyGSL_New_Array(2, dimensions, PyArray_DOUBLE); if (a_array == NULL) return NULL; for (i=0;idata + a_array->strides[0] * i + a_array->strides[1] * j; tmp = gsl_matrix_get(x, j, i); *((double *) myptr) = tmp; DEBUG_MESS(3, "\t\ta_array_%d = %f\n", i, tmp); } } FUNC_MESS_END(); return a_array; } /* * Set a descriptive error. The callback name is listed together with the "GSL Object" * that called it, and a error description. */ static int PyGSL_copy_pyarray_to_gslvector(gsl_vector *f, PyObject *object, int n, PyGSL_error_info * info) { PyArrayObject *a_array = NULL; double tmp; int i, argnum = -1; FUNC_MESS_BEGIN(); if (info) argnum = info->argnum; a_array = PyGSL_PyArray_PREPARE_gsl_vector_view(object, PyArray_DOUBLE, PyGSL_NON_CONTIGUOUS | PyGSL_INPUT_ARRAY, n, argnum, info); if(a_array == NULL){ FUNC_MESS("PyArray_FromObject failed"); goto fail; } if(DEBUG>2){ fprintf(stderr, "\t\ta_array->dimensions[0] = %d\n", a_array->dimensions[0]); fprintf(stderr, "\t\ta_array->strides[0] = %d\n", a_array->strides[0]); } for (i=0;idata + a_array->strides[0] * i)); gsl_vector_set(f, i, tmp); DEBUG_MESS(3, "\t\ta_array_%d = %f\n", i, tmp); } FUNC_MESS_END(); Py_DECREF(a_array); return GSL_SUCCESS; fail: PyGSL_add_traceback(NULL, filename, __FUNCTION__, __LINE__); FUNC_MESS("Failure"); Py_XDECREF(a_array); return GSL_FAILURE; } static int PyGSL_copy_pyarray_to_gslmatrix(gsl_matrix *f, PyObject *object, int n, int p, PyGSL_error_info * info) { PyArrayObject *a_array = NULL; double tmp; char *myptr; int i,j, argnum=-1; FUNC_MESS_BEGIN(); if (info) argnum = info->argnum; a_array = PyGSL_PyArray_PREPARE_gsl_matrix_view(object, PyArray_DOUBLE, PyGSL_NON_CONTIGUOUS | PyGSL_INPUT_ARRAY, n, p, info->argnum, info); if(a_array == NULL){ FUNC_MESS(" PyGSL_PyArray_PREPARE_gsl_matrix_view failed!"); goto fail; } assert(f->size1 == (size_t) n); assert(f->size2 == (size_t) p); for (i=0;idata + a_array->strides[0] * i + a_array->strides[1] * j; tmp = *((double *)(myptr)); DEBUG_MESS(3, "\t\ta_array_%d = %f\n", i, tmp); gsl_matrix_set(f, i, j, tmp); } } FUNC_MESS_END(); Py_DECREF(a_array); return GSL_SUCCESS; fail: PyGSL_add_traceback(NULL, filename, __FUNCTION__, __LINE__); FUNC_MESS(" Failure"); Py_XDECREF(a_array); return GSL_FAILURE; } static PyArrayObject * PyGSL_vector_or_double(PyObject *src, int flag, long size, int argnum, PyGSL_error_info * info) { int line = -1; PyArrayObject * r = NULL; FUNC_MESS_BEGIN(); r = PyGSL_PyArray_PREPARE_gsl_vector_view(src, PyArray_DOUBLE, PyGSL_CONTIGUOUS | PyGSL_INPUT_ARRAY, -1, argnum, NULL); if(r == NULL){ /* so try if it is a float ... */ double v; /* was not an array, but lets see if it is a float, so lets clear the error .... */ PyErr_Clear(); FUNC_MESS("PyErr_Clear END"); if(PyGSL_PYFLOAT_TO_DOUBLE(src, &v, NULL) != GSL_SUCCESS){ FUNC_MESS("=> NOT FLOAT"); line = __LINE__ - 1; goto fail; } FUNC_MESS("=> FLOAT"); { int dim = 1; r = (PyArrayObject *) PyGSL_New_Array(1, &dim, PyArray_DOUBLE); } if(r == NULL) { line = __LINE__ - 2; goto fail; } (*(double *)(r->data)) = v; } FUNC_MESS_END(); return r; fail: Py_XDECREF(r); FUNC_MESS("Fail"); return NULL; } #ifdef PyGSL_NUMERIC #include "block_helpers_numpy.ic" #endif #ifdef PyGSL_NUMARRAY #include "block_helpers_numarray.ic" #endif #if (!defined PyGSL_NUMERIC) && (! defined PyGSL_NUMARRAY) #error "Neither numarray nor numeric is defined!" #endif