/* -*- 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 <pygsl/block_helpers.h>
#include <pygsl/error_helpers.h>
#include <stdlib.h>
#include <stdio.h>
#include <pygsl/profile.h>
#include <pygsl/general_helpers.h>
#include <pygsl/utils.h>
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; i<nd; ++i){
if(dimensions[i] == -1 ){
switch(i){
case 0: DEBUG_MESS(2, "\t\t No one cares about its first dimension! %d", 0); break;
case 1: DEBUG_MESS(2, "\t\t No one cares about its second dimension! %d", 0); break;
default: error_flag = GSL_ESANITY; line = __LINE__ - 3; goto fail; break;
}
continue;
}
/* Check to be performed ... */
if( ((PyArrayObject *) (a_array))->dimensions[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;i<dimension;i++){
tmp = gsl_vector_get(x, i);
((double *) a_array->data)[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;i<dimensions[1];i++){
for (j=0;j<dimensions[0];j++){
myptr = a_array->data + 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;i<n;i++){
tmp = *((double *) (a_array->data + 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;i<n;i++){
for (j=0;j<p;j++){
myptr = a_array->data + 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
syntax highlighted by Code2HTML, v. 0.9.1