// Copyright David Abrahams 2002. // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include namespace boost { namespace python { namespace numeric { namespace { enum state_t { failed = -1, unknown, succeeded }; state_t state = unknown; std::string module_name; std::string type_name; handle<> array_module; handle<> array_type; handle<> array_function; void throw_load_failure() { PyErr_Format( PyExc_ImportError , "No module named '%s' or its type '%s' did not follow the NumPy protocol" , module_name.c_str(), type_name.c_str()); throw_error_already_set(); } bool load(bool throw_on_error) { if (!state) { if (module_name.size() == 0) { module_name = "numarray"; type_name = "NDArray"; if (load(false)) return true; module_name = "Numeric"; type_name = "ArrayType"; } state = failed; PyObject* module = ::PyImport_Import(object(module_name).ptr()); if (module) { PyObject* type = ::PyObject_GetAttrString(module, const_cast(type_name.c_str())); if (type && PyType_Check(type)) { array_type = handle<>(type); PyObject* function = ::PyObject_GetAttrString(module, const_cast("array")); if (function && PyCallable_Check(function)) { array_function = handle<>(function); state = succeeded; } } } } if (state == succeeded) return true; if (throw_on_error) throw_load_failure(); PyErr_Clear(); return false; } object demand_array_function() { load(true); return object(array_function); } } void array::set_module_and_type(char const* package_name, char const* type_attribute_name) { state = unknown; module_name = package_name ? package_name : "" ; type_name = type_attribute_name ? type_attribute_name : "" ; } std::string array::get_module_name() { load(false); return module_name; } namespace aux { bool array_object_manager_traits::check(PyObject* obj) { if (!load(false)) return false; return ::PyObject_IsInstance(obj, array_type.get()); } python::detail::new_non_null_reference array_object_manager_traits::adopt(PyObject* obj) { load(true); return detail::new_non_null_reference( pytype_check(downcast(array_type.get()), obj)); } PyTypeObject const* array_object_manager_traits::get_pytype() { load(false); if(!array_type) return 0; return downcast(array_type.get()); } # define BOOST_PYTHON_AS_OBJECT(z, n, _) object(x##n) # define BOOST_PP_LOCAL_MACRO(n) \ array_base::array_base(BOOST_PP_ENUM_PARAMS(n, object const& x)) \ : object(demand_array_function()(BOOST_PP_ENUM_PARAMS(n, x))) \ {} # define BOOST_PP_LOCAL_LIMITS (1, 6) # include BOOST_PP_LOCAL_ITERATE() # undef BOOST_PYTHON_AS_OBJECT array_base::array_base(BOOST_PP_ENUM_PARAMS(7, object const& x)) : object(demand_array_function()(BOOST_PP_ENUM_PARAMS(7, x))) {} object array_base::argmax(long axis) { return attr("argmax")(axis); } object array_base::argmin(long axis) { return attr("argmin")(axis); } object array_base::argsort(long axis) { return attr("argsort")(axis); } object array_base::astype(object const& type) { return attr("astype")(type); } void array_base::byteswap() { attr("byteswap")(); } object array_base::copy() const { return attr("copy")(); } object array_base::diagonal(long offset, long axis1, long axis2) const { return attr("diagonal")(offset, axis1, axis2); } void array_base::info() const { attr("info")(); } bool array_base::is_c_array() const { return extract(attr("is_c_array")()); } bool array_base::isbyteswapped() const { return extract(attr("isbyteswapped")()); } array array_base::new_(object type) const { return extract(attr("new")(type))(); } void array_base::sort() { attr("sort")(); } object array_base::trace(long offset, long axis1, long axis2) const { return attr("trace")(offset, axis1, axis2); } object array_base::type() const { return attr("type")(); } char array_base::typecode() const { return extract(attr("typecode")()); } object array_base::factory( object const& sequence , object const& typecode , bool copy , bool savespace , object type , object shape ) { return attr("factory")(sequence, typecode, copy, savespace, type, shape); } object array_base::getflat() const { return attr("getflat")(); } long array_base::getrank() const { return extract(attr("getrank")()); } object array_base::getshape() const { return attr("getshape")(); } bool array_base::isaligned() const { return extract(attr("isaligned")()); } bool array_base::iscontiguous() const { return extract(attr("iscontiguous")()); } long array_base::itemsize() const { return extract(attr("itemsize")()); } long array_base::nelements() const { return extract(attr("nelements")()); } object array_base::nonzero() const { return attr("nonzero")(); } void array_base::put(object const& indices, object const& values) { attr("put")(indices, values); } void array_base::ravel() { attr("ravel")(); } object array_base::repeat(object const& repeats, long axis) { return attr("repeat")(repeats, axis); } void array_base::resize(object const& shape) { attr("resize")(shape); } void array_base::setflat(object const& flat) { attr("setflat")(flat); } void array_base::setshape(object const& shape) { attr("setshape")(shape); } void array_base::swapaxes(long axis1, long axis2) { attr("swapaxes")(axis1, axis2); } object array_base::take(object const& sequence, long axis) const { return attr("take")(sequence, axis); } void array_base::tofile(object const& file) const { attr("tofile")(file); } str array_base::tostring() const { return str(attr("tostring")()); } void array_base::transpose(object const& axes) { attr("transpose")(axes); } object array_base::view() const { return attr("view")(); } } }}} // namespace boost::python::numeric