00001
00002
00003
00004
00005
00006 #define BOOST_NUMPY_INTERNAL
00007 #include <boost/numpy/internal.hpp>
00008 #include <boost/scoped_array.hpp>
00009
00010 namespace boost
00011 {
00012 namespace python
00013 {
00014 namespace converter
00015 {
00016 NUMPY_OBJECT_MANAGER_TRAITS_IMPL(PyArray_Type, numpy::ndarray)
00017 }
00018 }
00019
00020 namespace numpy
00021 {
00022 namespace detail
00023 {
00024
00025 ndarray::bitflag numpy_to_bitflag(int const f)
00026 {
00027 ndarray::bitflag r = ndarray::NONE;
00028 if (f & NPY_C_CONTIGUOUS) r = (r | ndarray::C_CONTIGUOUS);
00029 if (f & NPY_F_CONTIGUOUS) r = (r | ndarray::F_CONTIGUOUS);
00030 if (f & NPY_ALIGNED) r = (r | ndarray::ALIGNED);
00031 if (f & NPY_WRITEABLE) r = (r | ndarray::WRITEABLE);
00032 return r;
00033 }
00034
00035 int const bitflag_to_numpy(ndarray::bitflag f)
00036 {
00037 int r = 0;
00038 if (f & ndarray::C_CONTIGUOUS) r |= NPY_C_CONTIGUOUS;
00039 if (f & ndarray::F_CONTIGUOUS) r |= NPY_F_CONTIGUOUS;
00040 if (f & ndarray::ALIGNED) r |= NPY_ALIGNED;
00041 if (f & ndarray::WRITEABLE) r |= NPY_WRITEABLE;
00042 return r;
00043 }
00044
00045 bool is_c_contiguous(std::vector<Py_intptr_t> const & shape,
00046 std::vector<Py_intptr_t> const & strides,
00047 int itemsize)
00048 {
00049 std::vector<Py_intptr_t>::const_reverse_iterator j = strides.rbegin();
00050 int total = itemsize;
00051 for (std::vector<Py_intptr_t>::const_reverse_iterator i = shape.rbegin(); i != shape.rend(); ++i, ++j)
00052 {
00053 if (total != *j) return false;
00054 total *= (*i);
00055 }
00056 return true;
00057 }
00058
00059 bool is_f_contiguous(std::vector<Py_intptr_t> const & shape,
00060 std::vector<Py_intptr_t> const & strides,
00061 int itemsize)
00062 {
00063 std::vector<Py_intptr_t>::const_iterator j = strides.begin();
00064 int total = itemsize;
00065 for (std::vector<Py_intptr_t>::const_iterator i = shape.begin(); i != shape.end(); ++i, ++j)
00066 {
00067 if (total != *j) return false;
00068 total *= (*i);
00069 }
00070 return true;
00071 }
00072
00073 bool is_aligned(std::vector<Py_intptr_t> const & strides,
00074 int itemsize)
00075 {
00076 for (std::vector<Py_intptr_t>::const_iterator i = strides.begin(); i != strides.end(); ++i)
00077 {
00078 if (*i % itemsize) return false;
00079 }
00080 return true;
00081 }
00082
00083 inline PyArray_Descr * incref_dtype(dtype const & dt)
00084 {
00085 Py_INCREF(dt.ptr());
00086 return reinterpret_cast<PyArray_Descr*>(dt.ptr());
00087 }
00088
00089 ndarray from_data_impl(void * data,
00090 dtype const & dt,
00091 python::object const & shape,
00092 python::object const & strides,
00093 python::object const & owner,
00094 bool writeable)
00095 {
00096 std::vector<Py_intptr_t> shape_(len(shape));
00097 std::vector<Py_intptr_t> strides_(len(strides));
00098 if (shape_.size() != strides_.size())
00099 {
00100 PyErr_SetString(PyExc_ValueError, "Length of shape and strides arrays do not match.");
00101 python::throw_error_already_set();
00102 }
00103 for (std::size_t i = 0; i < shape_.size(); ++i)
00104 {
00105 shape_[i] = python::extract<Py_intptr_t>(shape[i]);
00106 strides_[i] = python::extract<Py_intptr_t>(strides[i]);
00107 }
00108 return from_data_impl(data, dt, shape_, strides_, owner, writeable);
00109 }
00110
00111 ndarray from_data_impl(void * data,
00112 dtype const & dt,
00113 std::vector<Py_intptr_t> const & shape,
00114 std::vector<Py_intptr_t> const & strides,
00115 python::object const & owner,
00116 bool writeable)
00117 {
00118 if (shape.size() != strides.size())
00119 {
00120 PyErr_SetString(PyExc_ValueError, "Length of shape and strides arrays do not match.");
00121 python::throw_error_already_set();
00122 }
00123 int itemsize = dt.get_itemsize();
00124 int flags = 0;
00125 if (writeable) flags |= NPY_WRITEABLE;
00126 if (is_c_contiguous(shape, strides, itemsize)) flags |= NPY_C_CONTIGUOUS;
00127 if (is_f_contiguous(shape, strides, itemsize)) flags |= NPY_F_CONTIGUOUS;
00128 if (is_aligned(strides, itemsize)) flags |= NPY_ALIGNED;
00129 ndarray r(python::detail::new_reference
00130 (PyArray_NewFromDescr(&PyArray_Type,
00131 incref_dtype(dt),
00132 shape.size(),
00133 const_cast<Py_intptr_t*>(&shape.front()),
00134 const_cast<Py_intptr_t*>(&strides.front()),
00135 data,
00136 flags,
00137 NULL)));
00138 r.set_base(owner);
00139 return r;
00140 }
00141
00142 }
00143
00144 ndarray ndarray::view(dtype const & dt) const
00145 {
00146 return ndarray(python::detail::new_reference
00147 (PyObject_CallMethod(this->ptr(), const_cast<char*>("view"), const_cast<char*>("O"), dt.ptr())));
00148 }
00149
00150 ndarray ndarray::astype(dtype const & dt) const
00151 {
00152 return ndarray(python::detail::new_reference
00153 (PyObject_CallMethod(this->ptr(), const_cast<char*>("astype"), const_cast<char*>("O"), dt.ptr())));
00154 }
00155
00156 ndarray ndarray::copy() const
00157 {
00158 return ndarray(python::detail::new_reference
00159 (PyObject_CallMethod(this->ptr(), const_cast<char*>("copy"), const_cast<char*>(""))));
00160 }
00161
00162 dtype ndarray::get_dtype() const
00163 {
00164 return dtype(python::detail::borrowed_reference(get_struct()->descr));
00165 }
00166
00167 python::object ndarray::get_base() const
00168 {
00169 if (get_struct()->base == NULL) return object();
00170 return python::object(python::detail::borrowed_reference(get_struct()->base));
00171 }
00172
00173 void ndarray::set_base(object const & base)
00174 {
00175 Py_XDECREF(get_struct()->base);
00176 if (base != object())
00177 {
00178 Py_INCREF(base.ptr());
00179 get_struct()->base = base.ptr();
00180 }
00181 else
00182 {
00183 get_struct()->base = NULL;
00184 }
00185 }
00186
00187 ndarray::bitflag const ndarray::get_flags() const
00188 {
00189 return numpy::detail::numpy_to_bitflag(get_struct()->flags);
00190 }
00191
00192 ndarray ndarray::transpose() const
00193 {
00194 return ndarray(python::detail::new_reference
00195 (PyArray_Transpose(reinterpret_cast<PyArrayObject*>(this->ptr()), NULL)));
00196 }
00197
00198 ndarray ndarray::squeeze() const
00199 {
00200 return ndarray(python::detail::new_reference
00201 (PyArray_Squeeze(reinterpret_cast<PyArrayObject*>(this->ptr()))));
00202 }
00203
00204 ndarray ndarray::reshape(python::tuple const & shape) const
00205 {
00206 return ndarray(python::detail::new_reference
00207 (PyArray_Reshape(reinterpret_cast<PyArrayObject*>(this->ptr()), shape.ptr())));
00208 }
00209
00210 python::object ndarray::scalarize() const
00211 {
00212 Py_INCREF(ptr());
00213 return python::object(python::detail::new_reference(PyArray_Return(reinterpret_cast<PyArrayObject*>(ptr()))));
00214 }
00215
00216 ndarray zeros(python::tuple const & shape, dtype const & dt)
00217 {
00218 int nd = len(shape);
00219 boost::scoped_array<Py_intptr_t> dims(new Py_intptr_t[nd]);
00220 for (int n=0; n<nd; ++n) dims[n] = python::extract<Py_intptr_t>(shape[n]);
00221 return ndarray(python::detail::new_reference
00222 (PyArray_Zeros(nd, dims.get(), detail::incref_dtype(dt), 0)));
00223 }
00224
00225 ndarray zeros(int nd, Py_intptr_t const * shape, dtype const & dt)
00226 {
00227 return ndarray(python::detail::new_reference
00228 (PyArray_Zeros(nd, const_cast<Py_intptr_t*>(shape), detail::incref_dtype(dt), 0)));
00229 }
00230
00231 ndarray empty(python::tuple const & shape, dtype const & dt)
00232 {
00233 int nd = len(shape);
00234 boost::scoped_array<Py_intptr_t> dims(new Py_intptr_t[nd]);
00235 for (int n=0; n<nd; ++n) dims[n] = python::extract<Py_intptr_t>(shape[n]);
00236 return ndarray(python::detail::new_reference
00237 (PyArray_Empty(nd, dims.get(), detail::incref_dtype(dt), 0)));
00238 }
00239
00240 ndarray empty(int nd, Py_intptr_t const * shape, dtype const & dt)
00241 {
00242 return ndarray(python::detail::new_reference
00243 (PyArray_Empty(nd, const_cast<Py_intptr_t*>(shape), detail::incref_dtype(dt), 0)));
00244 }
00245
00246 ndarray array(python::object const & obj)
00247 {
00248 return ndarray(python::detail::new_reference
00249 (PyArray_FromAny(obj.ptr(), NULL, 0, 0, NPY_ENSUREARRAY, NULL)));
00250 }
00251
00252 ndarray array(python::object const & obj, dtype const & dt)
00253 {
00254 return ndarray(python::detail::new_reference
00255 (PyArray_FromAny(obj.ptr(), detail::incref_dtype(dt), 0, 0, NPY_ENSUREARRAY, NULL)));
00256 }
00257
00258 ndarray from_object(python::object const & obj, dtype const & dt, int nd_min, int nd_max, ndarray::bitflag flags)
00259 {
00260 int requirements = detail::bitflag_to_numpy(flags);
00261 return ndarray(python::detail::new_reference
00262 (PyArray_FromAny(obj.ptr(),
00263 detail::incref_dtype(dt),
00264 nd_min, nd_max,
00265 requirements,
00266 NULL)));
00267 }
00268
00269 ndarray from_object(python::object const & obj, int nd_min, int nd_max, ndarray::bitflag flags)
00270 {
00271 int requirements = detail::bitflag_to_numpy(flags);
00272 return ndarray(python::detail::new_reference
00273 (PyArray_FromAny(obj.ptr(),
00274 NULL,
00275 nd_min, nd_max,
00276 requirements,
00277 NULL)));
00278 }
00279
00280 }
00281 }