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();