6 #define PY_ARRAY_UNIQUE_SYMBOL HippoPyArrayHandle
7 #define NO_IMPORT_ARRAY
10 namespace {
const char*
rcsid =
"$Id: num_util.cpp,v 1.12 2007/05/31 21:17:55 pfkeb Exp $"; }
12 using namespace boost::python;
45 return PyArray_USHORT;
69 PyArray_TYPES getEnum<unsigned long>(void)
75 PyArray_TYPES getEnum<long long>(void)
77 return PyArray_LONGLONG;
81 PyArray_TYPES getEnum<unsigned long long>(void)
83 return PyArray_ULONGLONG;
96 return PyArray_DOUBLE;
101 PyArray_TYPES getEnum<long double>(void)
103 return PyArray_LONGDOUBLE;
107 PyArray_TYPES getEnum<std::complex<float> >(void)
109 return PyArray_CFLOAT;
114 PyArray_TYPES getEnum<std::complex<double> >(void)
116 return PyArray_CDOUBLE;
121 PyArray_TYPES getEnum<std::complex<long double> >(void)
123 return PyArray_CLONGDOUBLE;
128 intp total = std::accumulate(dims.begin(),dims.end(),1,std::multiplies<intp>());
129 boost::python::object obj(boost::python::handle<>(PyArray_FromDims(dims.size(),&dims[0], PyArray_DOUBLE)));
131 void *arr_data = PyArray_DATA((PyArrayObject*) obj.ptr());
132 memcpy(arr_data,
data, PyArray_ITEMSIZE((PyArrayObject*) obj.ptr()) * total);
134 char *arr_data = ((PyArrayObject*) obj.ptr())->
data;
135 memcpy(arr_data,
data,
sizeof(
double) * total);
138 return boost::python::extract<boost::python::numeric::array>(obj);
207 using namespace boost::python;
220 if (!PySequence_Check(x.ptr())){
221 PyErr_SetString(PyExc_ValueError,
"expected a sequence");
222 throw_error_already_set();
225 (PyArray_ContiguousFromObject(x.ptr(),PyArray_NOTYPE,0,0)));
227 return extract<numeric::array>(obj);
231 numeric::array
makeNum(
int n, PyArray_TYPES t=PyArray_DOUBLE){
232 object obj(handle<>(PyArray_FromDims(1, &n, t)));
233 return extract<numeric::array>(obj);
237 numeric::array
makeNum(std::vector<int> dimens,
238 PyArray_TYPES t=PyArray_DOUBLE){
239 object obj(handle<>(PyArray_FromDims(dimens.size(), &dimens[0], t)));
240 return extract<numeric::array>(obj);
243 numeric::array
makeNum(
const numeric::array& arr){
246 return numeric::array(arr);
249 PyArray_TYPES
type(numeric::array arr){
251 return PyArray_TYPES(PyArray_TYPE(arr.ptr()));
258 PyArray_TYPES expected_type){
259 PyArray_TYPES actual_type =
type(arr);
260 if (actual_type != expected_type) {
261 std::ostringstream stream;
262 stream <<
"expected Numeric type " <<
kindstrings[expected_type]
263 <<
", found Numeric type " <<
kindstrings[actual_type] << std::ends;
264 PyErr_SetString(PyExc_TypeError, stream.str().c_str());
265 throw_error_already_set();
273 if(!PyArray_Check(arr.ptr())){
274 PyErr_SetString(PyExc_ValueError,
"expected a PyArrayObject");
275 throw_error_already_set();
278 return PyArray_NDIM(arr.ptr());
280 return ((PyArrayObject*) arr.ptr())->nd;
284 void check_rank(boost::python::numeric::array arr,
int expected_rank){
285 int actual_rank =
rank(arr);
286 if (actual_rank != expected_rank) {
287 std::ostringstream stream;
288 stream <<
"expected rank " << expected_rank
289 <<
", found rank " << actual_rank << std::ends;
290 PyErr_SetString(PyExc_RuntimeError, stream.str().c_str());
291 throw_error_already_set();
298 if(!PyArray_Check(arr.ptr())){
299 PyErr_SetString(PyExc_ValueError,
"expected a PyArrayObject");
300 throw_error_already_set();
302 return PyArray_Size(arr.ptr());
307 if (actual_size != expected_size) {
308 std::ostringstream stream;
309 stream <<
"expected size " << expected_size
310 <<
", found size " << actual_size << std::ends;
311 PyErr_SetString(PyExc_RuntimeError, stream.str().c_str());
312 throw_error_already_set();
317 std::vector<intptr_t>
shape(numeric::array arr){
318 std::vector<intptr_t> out_dims;
319 if(!PyArray_Check(arr.ptr())){
320 PyErr_SetString(PyExc_ValueError,
"expected a PyArrayObject");
321 throw_error_already_set();
324 intp* dims_ptr = PyArray_DIMS(arr.ptr());
326 int* dims_ptr = ((PyArrayObject*) arr.ptr())->dimensions;
328 int the_rank =
rank(arr);
329 for (
int i = 0;
i < the_rank;
i++){
330 out_dims.push_back(*(dims_ptr +
i));
337 int the_rank=
rank(arr);
338 if(the_rank < dimnum){
339 std::ostringstream stream;
340 stream <<
"Error: asked for length of dimension ";
341 stream << dimnum <<
" but rank of array is " << the_rank << std::ends;
342 PyErr_SetString(PyExc_RuntimeError, stream.str().c_str());
343 throw_error_already_set();
345 std::vector<intptr_t> actual_dims =
shape(arr);
346 return actual_dims[dimnum];
349 void check_shape(boost::python::numeric::array arr, std::vector<intptr_t> expected_dims){
350 std::vector<intptr_t> actual_dims =
shape(arr);
351 if (actual_dims != expected_dims) {
352 std::ostringstream stream;
353 stream <<
"expected dimensions " <<
vector_str(expected_dims)
354 <<
", found dimensions " <<
vector_str(actual_dims) << std::ends;
355 PyErr_SetString(PyExc_RuntimeError, stream.str().c_str());
356 throw_error_already_set();
361 void check_dim(boost::python::numeric::array arr,
int dimnum,
intp dimsize){
362 std::vector<intptr_t> actual_dims =
shape(arr);
363 if(actual_dims[dimnum] != dimsize){
364 std::ostringstream stream;
365 stream <<
"Error: expected dimension number ";
366 stream << dimnum <<
" to be length " << dimsize;
367 stream <<
", but found length " << actual_dims[dimnum] << std::ends;
368 PyErr_SetString(PyExc_RuntimeError, stream.str().c_str());
369 throw_error_already_set();
377 return PyArray_ISCONTIGUOUS(arr.ptr());
383 PyErr_SetString(PyExc_RuntimeError,
"expected a contiguous array");
384 throw_error_already_set();
389 void*
data(numeric::array arr){
390 if(!PyArray_Check(arr.ptr())){
391 PyErr_SetString(PyExc_ValueError,
"expected a PyArrayObject");
392 throw_error_already_set();
395 return PyArray_DATA(arr.ptr());
397 return ((PyArrayObject*) arr.ptr())->
data;
402 void copy_data(boost::python::numeric::array arr,
char* new_data){
403 char* arr_data = (
char*)
data(arr);
404 intp nbytes = PyArray_NBYTES(arr.ptr());
405 for (
intp i = 0;
i < nbytes;
i++) {
406 arr_data[
i] = new_data[
i];
412 numeric::array
clone(numeric::array arr){
414 object obj(handle<>(PyArray_NewCopy((PyArrayObject*)arr.ptr(),PyArray_CORDER)));
416 object obj(handle<>(PyArray_Copy((PyArrayObject*)arr.ptr())));
423 numeric::array
astype(boost::python::numeric::array arr, PyArray_TYPES t){
424 return (numeric::array) arr.astype(
type2char(t));
427 std::vector<intp>
strides(numeric::array arr){
428 std::vector<intp> out_strides;
429 if(!PyArray_Check(arr.ptr())){
430 PyErr_SetString(PyExc_ValueError,
"expected a PyArrayObject");
431 throw_error_already_set();
434 intp* strides_ptr = PyArray_STRIDES(arr.ptr());
436 int* strides_ptr = ((PyArrayObject*) arr.ptr())->
strides;
439 for (
intp i = 0;
i < the_rank;
i++){
440 out_strides.push_back(*(strides_ptr +
i));
446 return REFCOUNT(arr.ptr());
451 PyArray_TYPES theType=PyArray_TYPES(PyArray_TYPE(newo.ptr()));
453 PyArrayObject* PyArrayPtr = (PyArrayObject*) newo.ptr();
454 PyArray_TYPES theType=(PyArray_TYPES) PyArrayPtr->descr->type_num;
456 if(theType == PyArray_OBJECT){
457 std::ostringstream stream;
458 stream <<
"array elments have been cast to PyArray_OBJECT, "
459 <<
"numhandle can only accept arrays with numerical elements"
461 PyErr_SetString(PyExc_TypeError, stream.str().c_str());
462 throw_error_already_set();
482 std::ostringstream stream;
483 stream <<
"(" << vec[0];
485 for(std::size_t
i = 1;
i < vec.size();
i++){
486 stream <<
", " << vec[
i];
494 intp total = std::accumulate(dims.begin(),dims.end(),1,std::multiplies<intp>());
496 std::ostringstream stream;
497 stream <<
"expected array size " << n
498 <<
", dimensions give array size " << total << std::ends;
499 PyErr_SetString(PyExc_TypeError, stream.str().c_str());
500 throw_error_already_set();
numeric::array makeNum(object x)
KindTypeMap::value_type KindTypeMapEntry
std::string vector_str(const std::vector< T > &vec)
Constructs a string which contains a list of elements extracted from the input vector.
void check_type(boost::python::numeric::array arr, PyArray_TYPES expected_type)
Throws an exception if the actual array type is not equal to the expected type.
KindStringMap::value_type KindStringMapEntry
void * data(numeric::array arr)
void check_contiguous(numeric::array arr)
PyArray_TYPES getEnum< unsigned int >(void)
static KindTypeMap kindtypes(kindTypeMapEntries, kindTypeMapEntries+numTypeEntries)
char type2char(PyArray_TYPES t_type)
Converts a PyArray_TYPE to its single character typecode.
void check_shape(boost::python::numeric::array arr, std::vector< intptr_t > expected_dims)
int refcount(numeric::array arr)
intp get_dim(boost::python::numeric::array arr, int dimnum)
Returns the size of a specific dimension.
PyArray_TYPES char2type(char e_type)
Coverts a single character typecode to its PyArray_TYPES.
PyArray_TYPES getEnum< unsigned char >(void)
KindStringMapEntry kindStringMapEntries[]
std::string type2string(PyArray_TYPES t_type)
Converts a PyArray_TYPE to its name in string.
PyArray_TYPES getEnum< long >(void)
std::vector< intptr_t > shape(numeric::array arr)
std::map< PyArray_TYPES, std::string > KindStringMap
Mapping from a PyArray_TYPE to its corresponding name in string.
void check_rank(boost::python::numeric::array arr, int expected_rank)
Throws an exception if the actual rank is not equal to the expected rank.
std::vector< intp > strides(numeric::array arr)
KindTypeMapEntry kindTypeMapEntries[]
PyArray_TYPES type(numeric::array arr)
boost::python::numeric::array makeNum< double >(double *data, std::vector< int > dims)
PyArray_TYPES getEnum< signed char >(void)
PyArray_TYPES getEnum< short >(void)
numeric::array clone(numeric::array arr)
intp size(numeric::array arr)
int rank(numeric::array arr)
PyArray_TYPES getEnum< int >(void)
void copy_data(boost::python::numeric::array arr, char *new_data)
Copies data into the array.
void check_PyArrayElementType(object newo)
bool iscontiguous(numeric::array arr)
PyArray_TYPES getEnum< unsigned short >(void)
PyArray_TYPES getEnum< double >(void)
void check_size(boost::python::numeric::array arr, intp expected_size)
Throw an exception if the actual total size of the array is not equal to the expected size...
PyArray_TYPES getEnum< float >(void)
std::map< char, PyArray_TYPES > KindTypeMap
Mapping from a typeID to its corresponding PyArray_TYPE.
void check_dim(boost::python::numeric::array arr, int dimnum, intp dimsize)
Throws an exception if a specific dimension from a numpy array does not match the expected size...
KindCharMap::value_type KindCharMapEntry
static KindCharMap kindchars(kindCharMapEntries, kindCharMapEntries+numCharEntries)
void check_size_match(std::vector< intp > dims, intp n)
Throws an exception if the total size computed from a vector of integer does not match with the expec...
KindCharMapEntry kindCharMapEntries[]
numeric::array astype(boost::python::numeric::array arr, PyArray_TYPES t)
Returns a clone of this array with a new type.
std::map< PyArray_TYPES, char > KindCharMap
Mapping from a PyArray_TYPE to its corresponding typeID in char.
static KindStringMap kindstrings(kindStringMapEntries, kindStringMapEntries+numStringEntries)