// Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only // included by sbknumpy.cpp #include "helper.h" #include #include #include #ifdef HAVE_NUMPY namespace Shiboken { namespace Numpy { static std::optional viewTypeFromNumPy(int npt) { switch (npt) { case NPY_SHORT: return View::Int16; case NPY_USHORT: return View::Unsigned16; case NPY_INT: return View::Int; case NPY_UINT: return View::Unsigned; case NPY_LONG: if constexpr (sizeof(long) == sizeof(int)) return View::Int; if constexpr (sizeof(long) == sizeof(int64_t)) return View::Int64; break; case NPY_ULONG: if constexpr (sizeof(long) == sizeof(int)) return View::Unsigned; if constexpr (sizeof(long) == sizeof(int64_t)) return View::Unsigned64; break; case NPY_LONGLONG: if constexpr (sizeof(long long) == 8) return View::Int64; break; case NPY_ULONGLONG: if constexpr (sizeof(long long) == 8) return View::Unsigned64; break; case NPY_FLOAT: return View::Float; case NPY_DOUBLE: return View::Double; default: break; } return {}; } View View::fromPyObject(PyObject *pyIn) { if (pyIn == nullptr || PyArray_Check(pyIn) == 0) return {}; auto *ar = reinterpret_cast(pyIn); if ((PyArray_FLAGS(ar) & NPY_ARRAY_C_CONTIGUOUS) == 0) return {}; const int ndim = PyArray_NDIM(ar); if (ndim > 2) return {}; const auto typeO = viewTypeFromNumPy(PyArray_TYPE(ar)); if (!typeO.has_value()) return {}; View result; result.ndim = ndim; result.type = typeO.value(); result.data = PyArray_DATA(ar); result.dimensions[0] = PyArray_DIMS(ar)[0]; result.stride[0] = PyArray_STRIDES(ar)[0]; if (ndim > 1) { result.dimensions[1] = PyArray_DIMS(ar)[1]; result.stride[1] = PyArray_STRIDES(ar)[1]; } else { result.dimensions[1] = result.stride[1] = 0; } return result; } } // namespace Numpy template static void debugArray(std::ostream &str, const T *data, int n) { static const int maxData = 10; str << " = "; auto *end = data + std::min(n, maxData); for (auto *d = data; d != end; ++d) { if (d != data) str << ", "; str << *d; } if (n > maxData) str << "..."; } std::ostream &operator<<(std::ostream &str, const debugPyArrayObject &a) { str << "PyArrayObject("; if (a.m_object == nullptr) { str << '0'; } else if (PyArray_Check(a.m_object) != 0) { auto *ar = reinterpret_cast(a.m_object); const int ndim = PyArray_NDIM(ar); const int type = PyArray_TYPE(ar); const int flags = PyArray_FLAGS(ar); str << "ndim=" << ndim << " ["; for (int d = 0; d < ndim; ++d) { if (d) str << ", "; str << PyArray_DIMS(ar)[d]; } str << "], type="; switch (type) { case NPY_SHORT: str << "short"; break; case NPY_USHORT: str << "ushort"; break; case NPY_INT: str << "int32"; break; case NPY_UINT: str << "uint32"; break; case NPY_LONG: str << "long"; break; case NPY_ULONG: str << "ulong"; break; case NPY_LONGLONG: str << "long long"; break; case NPY_ULONGLONG: str << "ulong long"; break; case NPY_FLOAT: str << "float"; break; case NPY_DOUBLE: str << "double"; break; default: str << '(' << type << ')'; break; } str << ", flags=0x" << std::hex << flags << std::dec; if ((flags & NPY_ARRAY_C_CONTIGUOUS) != 0) str << " [C-contiguous]"; if ((flags & NPY_ARRAY_F_CONTIGUOUS) != 0) str << " [Fortran-contiguous]"; if ((flags & NPY_ARRAY_ALIGNED) != 0) str << " [aligned]"; if ((flags & NPY_ARRAY_OWNDATA) != 0) str << " [owndata]"; if ((flags & NPY_ARRAY_WRITEABLE) != 0) str << " [writeable]"; if (const int dim0 = PyArray_DIMS(ar)[0]) { auto *data = PyArray_DATA(ar); switch (type) { case NPY_SHORT: debugArray(str, reinterpret_cast(data), dim0); break; case NPY_USHORT: debugArray(str, reinterpret_cast(data), dim0); break; case NPY_INT: debugArray(str, reinterpret_cast(data), dim0); break; case NPY_UINT: debugArray(str, reinterpret_cast(data), dim0); break; case NPY_LONG: debugArray(str, reinterpret_cast(data), dim0); break; case NPY_ULONG: debugArray(str, reinterpret_cast(data), dim0); break; case NPY_LONGLONG: debugArray(str, reinterpret_cast(data), dim0); break; case NPY_ULONGLONG: debugArray(str, reinterpret_cast(data), dim0); break; case NPY_FLOAT: debugArray(str, reinterpret_cast(data), dim0); break; case NPY_DOUBLE: debugArray(str, reinterpret_cast(data), dim0); break; } } } else { str << "Invalid"; } str << ')'; return str; } } //namespace Shiboken #else // HAVE_NUMPY namespace Shiboken::Numpy { View View::fromPyObject(PyObject *) { return {}; } std::ostream &operator<<(std::ostream &str, const debugPyArrayObject &) { str << "Unimplemented function " << __FUNCTION__ << ", (numpy was not found)."; return str; } } //namespace Shiboken::Numpy #endif // !HAVE_NUMPY namespace Shiboken::Numpy { bool View::sameLayout(const View &rhs) const { return rhs && *this && ndim == rhs.ndim && type == rhs.type; } bool View::sameSize(const View &rhs) const { return sameLayout(rhs) && dimensions[0] == rhs.dimensions[0] && dimensions[1] == rhs.dimensions[1]; } std::ostream &operator<<(std::ostream &str, const View &v) { str << "Shiboken::Numpy::View("; if (v) { str << "type=" << v.type << ", ndim=" << v.ndim << " [" << v.dimensions[0]; if (v.ndim > 1) str << ", " << v.dimensions[1]; str << "], stride=[" << v.stride[0]; if (v.ndim > 1) str << ", " << v.stride[1]; str << "], data=" << v.data; } else { str << "invalid"; } str << ')'; return str; } } //namespace Shiboken::Numpy