From 4e647fb6c1f75a0fea0124a0ef861cdae8aafdab Mon Sep 17 00:00:00 2001 From: tang zhixiong Date: Mon, 16 Feb 2026 01:11:58 +0800 Subject: [PATCH 1/6] Add pybind11/eigen.h type_caster for pkbind; simplify RDP bindings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract ndarray_base and ndarray binding classes into include/ndarray_binding.hpp so that the new include/pybind11/eigen.h header can access them. eigen.h provides automatic Eigen ↔ pocketpy ndarray conversion via pkbind's type_caster mechanism: - type_caster for Eigen dense types (Matrix, Vector, Array) - type_caster for Eigen::Ref with persistent storage - Compile-time dimension checking enables Nx2 vs Nx3 overload resolution RDP bindings in numpy.cpp now use Eigen types directly (matching src/pybind.cpp interface), removing ~80 lines of manual conversion helpers. --- include/ndarray_binding.hpp | 2709 ++++++++++++++++++++++++++++++++ include/pybind11/eigen.h | 202 +++ src/numpy.cpp | 2899 +---------------------------------- 3 files changed, 2982 insertions(+), 2828 deletions(-) create mode 100644 include/ndarray_binding.hpp create mode 100644 include/pybind11/eigen.h diff --git a/include/ndarray_binding.hpp b/include/ndarray_binding.hpp new file mode 100644 index 0000000..cc1bcac --- /dev/null +++ b/include/ndarray_binding.hpp @@ -0,0 +1,2709 @@ +#pragma once + +#include +#include +#include +#include + +namespace py = pybind11; + +using bool_ = pkpy::bool_; +using int8 = pkpy::int8; +using int16 = pkpy::int16; +using int32 = pkpy::int32; +using int64 = pkpy::int64; +using int_ = pkpy::int_; +using float32 = pkpy::float32; +using float64 = pkpy::float64; +using float_ = pkpy::float_; + +// Function to parse attributes +inline int parseAttr(const py::object& obj) { + if(py::isinstance(obj)) { + return INT_MAX; + } else if(py::isinstance(obj)) { + return obj.cast(); + } else { + throw std::runtime_error("Unsupported type"); + } +}; + +class ndarray_base { +public: + virtual ~ndarray_base() = default; + + virtual int ndim() const = 0; + + virtual int size() const = 0; + + virtual std::string dtype() const = 0; + + virtual py::tuple shape() const = 0; + + virtual bool all() const = 0; + + virtual bool any() const = 0; + + virtual py::object sum() const = 0; + + virtual py::object sum_axis(int axis) const = 0; + + virtual py::object sum_axes(py::tuple axes) const = 0; + + virtual py::object prod() const = 0; + + virtual py::object prod_axis(int axis) const = 0; + + virtual py::object prod_axes(py::tuple axes) const = 0; + + virtual py::object min() const = 0; + + virtual py::object min_axis(int axis) const = 0; + + virtual py::object min_axes(py::tuple axes) const = 0; + + virtual py::object max() const = 0; + + virtual py::object max_axis(int axis) const = 0; + + virtual py::object max_axes(py::tuple axes) const = 0; + + virtual py::object mean() const = 0; + + virtual py::object mean_axis(int axis) const = 0; + + virtual py::object mean_axes(py::tuple axes) const = 0; + + virtual py::object std() const = 0; + + virtual py::object std_axis(int axis) const = 0; + + virtual py::object std_axes(py::tuple axes) const = 0; + + virtual py::object var() const = 0; + + virtual py::object var_axis(int axis) const = 0; + + virtual py::object var_axes(py::tuple axes) const = 0; + + virtual py::object argmin() const = 0; + + virtual ndarray_base* argmin_axis(int axis) const = 0; + + virtual py::object argmax() const = 0; + + virtual ndarray_base* argmax_axis(int axis) const = 0; + + virtual ndarray_base* argsort() const = 0; + + virtual ndarray_base* argsort_axis(int axis) const = 0; + + virtual void sort() = 0; + + virtual void sort_axis(int axis) = 0; + + virtual ndarray_base* reshape(const std::vector& shape) const = 0; + + virtual void resize(const std::vector& shape) = 0; + + virtual ndarray_base* squeeze() const = 0; + + virtual ndarray_base* squeeze_axis(int axis) const = 0; + + virtual ndarray_base* transpose() const = 0; + + virtual ndarray_base* transpose_tuple(py::tuple permutations) const = 0; + + virtual ndarray_base* transpose_args(py::args args) const = 0; + + virtual ndarray_base* repeat(int repeats, int axis) const = 0; + + virtual ndarray_base* repeat_axis(const std::vector& repeats, int axis) const = 0; + + virtual ndarray_base* round() const = 0; + + virtual ndarray_base* flatten() const = 0; + + virtual ndarray_base* copy() const = 0; + + virtual ndarray_base* astype(const std::string& dtype) const = 0; + + virtual py::list tolist() const = 0; + + virtual ndarray_base* eq(const ndarray_base& other) const = 0; + + virtual ndarray_base* ne(const ndarray_base& other) const = 0; + + virtual ndarray_base* add(const ndarray_base& other) const = 0; + + virtual ndarray_base* add_bool(bool_ other) const = 0; + + virtual ndarray_base* add_int(int_ other) const = 0; + + virtual ndarray_base* add_float(float64 other) const = 0; + + virtual ndarray_base* sub(const ndarray_base& other) const = 0; + + virtual ndarray_base* sub_int(int_ other) const = 0; + + virtual ndarray_base* sub_float(float64 other) const = 0; + + virtual ndarray_base* rsub_int(int_ other) const = 0; + + virtual ndarray_base* rsub_float(float64 other) const = 0; + + virtual ndarray_base* mul(const ndarray_base& other) const = 0; + + virtual ndarray_base* mul_bool(bool_ other) const = 0; + + virtual ndarray_base* mul_int(int_ other) const = 0; + + virtual ndarray_base* mul_float(float64 other) const = 0; + + virtual ndarray_base* div(const ndarray_base& other) const = 0; + + virtual ndarray_base* div_bool(bool_ other) const = 0; + + virtual ndarray_base* div_int(int_ other) const = 0; + + virtual ndarray_base* div_float(float64 other) const = 0; + + virtual ndarray_base* rdiv_bool(bool_ other) const = 0; + + virtual ndarray_base* rdiv_int(int_ other) const = 0; + + virtual ndarray_base* rdiv_float(float64 other) const = 0; + + virtual ndarray_base* matmul(const ndarray_base& other) const = 0; + + virtual ndarray_base* pow(const ndarray_base& other) const = 0; + + virtual ndarray_base* pow_int(int_ other) const = 0; + + virtual ndarray_base* pow_float(float64 other) const = 0; + + virtual ndarray_base* rpow_int(int_ other) const = 0; + + virtual ndarray_base* rpow_float(float64 other) const = 0; + + virtual ndarray_base* and_array(const ndarray_base& other) const = 0; + + virtual ndarray_base* and_bool(bool_ other) const = 0; + + virtual ndarray_base* and_int(int_ other) const = 0; + + virtual ndarray_base* or_array(const ndarray_base& other) const = 0; + + virtual ndarray_base* or_bool(bool_ other) const = 0; + + virtual ndarray_base* or_int(int_ other) const = 0; + + virtual ndarray_base* xor_array(const ndarray_base& other) const = 0; + + virtual ndarray_base* xor_bool(bool_ other) const = 0; + + virtual ndarray_base* xor_int(int_ other) const = 0; + + virtual ndarray_base* invert() const = 0; + + virtual py::object get_item_int(int index) const = 0; + + virtual py::object get_item_tuple(py::tuple indices) const = 0; + + virtual ndarray_base* get_item_vector(const std::vector& indices) const = 0; + + virtual ndarray_base* get_item_slice(py::slice slice) const = 0; + + virtual void set_item_int(int index, int_ value) = 0; + + virtual void set_item_index_int(int index, const std::vector& value) = 0; + + virtual void set_item_index_int_2d(int index, const std::vector>& value) = 0; + + virtual void set_item_index_int_3d(int index, const std::vector>>& value) = 0; + + virtual void set_item_index_int_4d(int index, const std::vector>>>& value) = 0; + + virtual void set_item_float(int index, float64 value) = 0; + + virtual void set_item_index_float(int index, const std::vector& value) = 0; + + virtual void set_item_index_float_2d(int index, const std::vector>& value) = 0; + + virtual void set_item_index_float_3d(int index, const std::vector>>& value) = 0; + + virtual void set_item_index_float_4d(int index, const std::vector>>>& value) = 0; + + virtual void set_item_tuple_int1(py::tuple args, int_ value) = 0; + + virtual void set_item_tuple_int2(py::tuple args, const std::vector& value) = 0; + + virtual void set_item_tuple_int3(py::tuple args, const std::vector>& value) = 0; + + virtual void set_item_tuple_int4(py::tuple args, const std::vector>>& value) = 0; + + virtual void set_item_tuple_int5(py::tuple args, const std::vector>>>& value) = 0; + + virtual void set_item_tuple_float1(py::tuple args, float64 value) = 0; + + virtual void set_item_tuple_float2(py::tuple args, const std::vector& value) = 0; + + virtual void set_item_tuple_float3(py::tuple args, const std::vector>& value) = 0; + + virtual void set_item_tuple_float4(py::tuple args, const std::vector>>& value) = 0; + + virtual void set_item_tuple_float5(py::tuple args, const std::vector>>>& value) = 0; + + virtual void set_item_vector_int1(const std::vector& indices, int_ value) = 0; + + virtual void set_item_vector_int2(const std::vector& indices, const std::vector& value) = 0; + + virtual void set_item_vector_int3(const std::vector& indices, const std::vector>& value) = 0; + + virtual void set_item_vector_int4(const std::vector& indices, const std::vector>>& value) = 0; + + virtual void set_item_vector_int5(const std::vector& indices, const std::vector>>>& value) = 0; + + virtual void set_item_vector_float1(const std::vector& indices, float64 value) = 0; + + virtual void set_item_vector_float2(const std::vector& indices, const std::vector& value) = 0; + + virtual void set_item_vector_float3(const std::vector& indices, const std::vector>& value) = 0; + + virtual void set_item_vector_float4(const std::vector& indices, const std::vector>>& value) = 0; + + virtual void set_item_vector_float5(const std::vector& indices, const std::vector>>>& value) = 0; + + virtual void set_item_slice_int1(py::slice slice, int_ value) = 0; + + virtual void set_item_slice_int2(py::slice slice, const std::vector& value) = 0; + + virtual void set_item_slice_int3(py::slice slice, const std::vector>& value) = 0; + + virtual void set_item_slice_int4(py::slice slice, const std::vector>>& value) = 0; + + virtual void set_item_slice_int5(py::slice slice, const std::vector>>>& value) = 0; + + virtual void set_item_slice_float1(py::slice slice, float64 value) = 0; + + virtual void set_item_slice_float2(py::slice slice, const std::vector& value) = 0; + + virtual void set_item_slice_float3(py::slice slice, const std::vector>& value) = 0; + + virtual void set_item_slice_float4(py::slice slice, const std::vector>>& value) = 0; + + virtual void set_item_slice_float5(py::slice slice, const std::vector>>>& value) = 0; + + virtual int len() const = 0; + + virtual std::string to_string() const = 0; +}; + +template +class ndarray : public ndarray_base { +public: + pkpy::numpy::ndarray data; + // Constructors + ndarray() = default; + + ndarray(const bool_ value) : data(value) {} + + ndarray(const int8 value) : data(value) {} + + ndarray(const int16 value) : data(value) {} + + ndarray(const int32 value) : data(value) {} + + ndarray(const int_ value) : data(static_cast(value)) {} + + ndarray(const float32 value) : data(value) {} + + ndarray(const float64 value) : data(static_cast(value)) {} + + ndarray(const pkpy::numpy::ndarray& _arr) : data(_arr) {} + + ndarray(const std::vector& init_list) : data(pkpy::numpy::adapt(init_list)) {} + + ndarray(const std::vector>& init_list) : data(pkpy::numpy::adapt(init_list)) {} + + ndarray(const std::vector>>& init_list) : data(pkpy::numpy::adapt(init_list)) {} + + ndarray(const std::vector>>>& init_list) : + data(pkpy::numpy::adapt(init_list)) {} + + ndarray(const std::vector>>>>& init_list) : + data(pkpy::numpy::adapt(init_list)) {} + + // Properties + int ndim() const override { return data.ndim(); } + + int size() const override { return data.size(); } + + std::string dtype() const override { return data.dtype(); } + + py::tuple shape() const override { return py::cast(data.shape()); } + + // Boolean Functions + bool all() const override { return data.all(); } + + bool any() const override { return data.any(); } + + // Aggregation Functions + py::object sum() const override { + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v) { + return py::int_(data.sum()); + } else if constexpr(std::is_same_v || std::is_same_v) { + return py::float_(data.sum()); + } else { + throw std::runtime_error("Unsupported type"); + } + } + + py::object sum_axis(int axis) const override { + if ((data.sum(axis)).ndim() == 0) { + return py::cast((data.sum(axis))()); + } else { + return py::cast(ndarray(data.sum(axis))); + } + } + + py::object sum_axes(py::tuple axes) const override { + std::vector axes_; + for(auto item: axes) { + axes_.push_back(py::cast(item)); + } + if ((data.sum(axes_)).ndim() == 0) { + return py::cast((data.sum(axes_))()); + } else { + return py::cast(ndarray(data.sum(axes_))); + } + } + + py::object prod() const override { + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v) { + return py::int_(data.prod()); + } else if constexpr(std::is_same_v || std::is_same_v) { + return py::float_(data.prod()); + } else { + throw std::runtime_error("Unsupported type"); + } + } + + py::object prod_axis(int axis) const override { + if ((data.prod(axis)).ndim() == 0) { + return py::cast((data.prod(axis))()); + } else { + return py::cast(ndarray(data.prod(axis))); + } + } + + py::object prod_axes(py::tuple axes) const override { + std::vector axes_; + for(auto item: axes) { + axes_.push_back(py::cast(item)); + } + if ((data.prod(axes_)).ndim() == 0) { + return py::cast((data.prod(axes_))()); + } else { + return py::cast(ndarray(data.prod(axes_))); + } + } + + py::object min() const override { + if constexpr (std::is_same_v) { + return py::bool_(data.min()); + } else if constexpr (std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v) { + return py::int_(data.min()); + } else if constexpr(std::is_same_v || std::is_same_v) { + return py::float_(data.min()); + } else { + throw std::runtime_error("Unsupported type"); + } + } + + py::object min_axis(int axis) const override { + if ((data.min(axis)).ndim() == 0) { + return py::cast((data.min(axis))()); + } else { + return py::cast(ndarray(data.min(axis))); + } + + } + + py::object min_axes(py::tuple axes) const override { + std::vector axes_; + for(auto item: axes) { + axes_.push_back(py::cast(item)); + } + if ((data.min(axes_)).ndim() == 0) { + return py::cast((data.min(axes_))()); + } else { + return py::cast(ndarray(data.min(axes_))); + } + } + + py::object max() const override { + if constexpr (std::is_same_v) { + return py::bool_(data.max()); + } else if constexpr (std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v) { + return py::int_(data.max()); + } else if constexpr(std::is_same_v || std::is_same_v) { + return py::float_(data.max()); + } else { + throw std::runtime_error("Unsupported type"); + } + } + + py::object max_axis(int axis) const override { + if ((data.max(axis)).ndim() == 0) { + return py::cast((data.max(axis))()); + } else { + return py::cast(ndarray(data.max(axis))); + } + } + + py::object max_axes(py::tuple axes) const override { + std::vector axes_; + for(auto item: axes) { + axes_.push_back(py::cast(item)); + } + if ((data.max(axes_)).ndim() == 0) { + return py::cast((data.max(axes_))()); + } else { + return py::cast(ndarray(data.max(axes_))); + } + } + + py::object mean() const override { + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || std::is_same_v || + std::is_same_v) { + return py::float_(data.mean()); + } else { + throw std::runtime_error("Unsupported type"); + } + } + + py::object mean_axis(int axis) const override { + if ((data.mean(axis)).ndim() == 0) { + return py::cast((data.mean(axis))()); + } else { + return py::cast(ndarray(data.mean(axis))); + } + } + + py::object mean_axes(py::tuple axes) const override { + std::vector axes_; + for(auto item: axes) + axes_.push_back(py::cast(item)); + if ((data.mean(axes_)).ndim() == 0) { + return py::cast((data.mean(axes_))()); + } else { + return py::cast(ndarray(data.mean(axes_))); + } + } + + py::object std() const override { + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || std::is_same_v || + std::is_same_v) { + return py::float_(data.std()); + } else { + throw std::runtime_error("Unsupported type"); + } + } + + py::object std_axis(int axis) const override { + if ((data.std(axis)).ndim() == 0) { + return py::cast((data.std(axis))()); + } else { + return py::cast(ndarray(data.std(axis))); + } + } + + py::object std_axes(py::tuple axes) const override { + std::vector axes_; + for(auto item: axes) + axes_.push_back(py::cast(item)); + if ((data.std(axes_)).ndim() == 0) { + return py::cast((data.std(axes_))()); + } else { + return py::cast(ndarray(data.std(axes_))); + } + } + + py::object var() const override { + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || std::is_same_v || + std::is_same_v) { + return py::float_(data.var()); + } else { + throw std::runtime_error("Unsupported type"); + } + } + + py::object var_axis(int axis) const override { + if ((data.var(axis)).ndim() == 0) { + return py::cast((data.var(axis))()); + } else { + return py::cast(ndarray(data.var(axis))); + } + } + + py::object var_axes(py::tuple axes) const override { + std::vector axes_; + for(auto item: axes) + axes_.push_back(py::cast(item)); + if ((data.var(axes_)).ndim() == 0) { + return py::cast((data.var(axes_))()); + } else { + return py::cast(ndarray(data.var(axes_))); + } + } + + py::object argmin() const override { + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v) { + return py::int_(data.argmin()); + } else if constexpr(std::is_same_v || std::is_same_v) { + return py::int_(data.argmin()); + } else { + throw std::runtime_error("Unsupported type"); + } + } + + ndarray_base* argmin_axis(int axis) const override { return new ndarray(data.argmin(axis)); } + + py::object argmax() const override { + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v) { + return py::int_(data.argmax()); + } else if constexpr(std::is_same_v || std::is_same_v) { + return py::int_(data.argmax()); + } else { + throw std::runtime_error("Unsupported type"); + } + } + + ndarray_base* argmax_axis(int axis) const override { return new ndarray(data.argmax(axis)); } + + ndarray_base* argsort() const override { return new ndarray(data.argsort()); } + + ndarray_base* argsort_axis(int axis) const override { return new ndarray(data.argsort(axis)); } + + void sort() override { data = data.sort(); } + + void sort_axis(int axis) override { data = data.sort(axis); } + + ndarray_base* reshape(const std::vector& shape) const override { return new ndarray(data.reshape(shape)); } + + void resize(const std::vector& shape) override { data = data.resize(shape); } + + ndarray_base* squeeze() const override { return new ndarray(data.squeeze()); } + + ndarray_base* squeeze_axis(int axis) const override { return new ndarray(data.squeeze(axis)); } + + ndarray_base* transpose() const override { return new ndarray(data.transpose()); } + + ndarray_base* transpose_tuple(py::tuple permutations) const override { + std::vector perm; + for(auto item: permutations) + perm.push_back(py::cast(item)); + return new ndarray(data.transpose(perm)); + } + + ndarray_base* transpose_args(py::args args) const override { + std::vector perm; + for(auto item: args) + perm.push_back(py::cast(item)); + return new ndarray(data.transpose(perm)); + } + + ndarray_base* repeat(int repeats, int axis) const override { + if (axis == INT_MAX) { + return new ndarray(data.repeat(repeats, data.ndim() - 1)); + } + return new ndarray(data.repeat(repeats, axis)); + } + + ndarray_base* repeat_axis(const std::vector& repeats, int axis) const override { + return new ndarray(data.repeat(repeats, axis)); + } + + ndarray_base* round() const override { return new ndarray(data.round()); } + + ndarray_base* flatten() const override { return new ndarray(data.flatten()); } + + ndarray_base* copy() const override { return new ndarray(data.copy()); } + + ndarray_base* astype(const std::string& dtype) const override { + if(dtype == "bool_") { + return new ndarray(data.template astype()); + } else if(dtype == "int8") { + return new ndarray(data.template astype()); + } else if(dtype == "int16") { + return new ndarray(data.template astype()); + } else if(dtype == "int32") { + return new ndarray(data.template astype()); + } else if(dtype == "int_") { + return new ndarray(data.template astype()); + } else if(dtype == "float32") { + return new ndarray(data.template astype()); + } else if(dtype == "float64") { + return new ndarray(data.template astype()); + } else { + throw std::invalid_argument("Invalid dtype"); + } + } + + py::list tolist() const override { + py::list list; + if(data.ndim() == 1) { + return py::cast(data.to_list()); + } else { + for(int i = 0; i < data.shape()[0]; i++) { + list.append(ndarray(data[i]).tolist()); + } + } + return list; + } + + // Dunder Methods + ndarray_base* eq(const ndarray_base& other) const override { + if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int8 == int8 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 == int16 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 == int32 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 == int64 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 == float32 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 == float64 */ + return new ndarray(data == p->data); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int16 == int8 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 == int16 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 == int32 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 == int64 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 == float32 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 == float64 */ + return new ndarray(data == p->data); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int32 == int8 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 == int16 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 == int32 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 == int64 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 == float32 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 == float64 */ + return new ndarray(data == p->data); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int64 == int8 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int64 == int16 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int64 == int32 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int64 == int64 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int64 == float32 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int64 == float64 */ + return new ndarray(data == p->data); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* float32 == int8 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float32 == int16 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float32 == int32 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float32 == int64 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float32 == float32 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float32 == float64 */ + return new ndarray(data == p->data); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* float64 == int8 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float64 == int16 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float64 == int32 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float64 == int64 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float64 == float32 */ + return new ndarray(data == p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float64 == float64 */ + return new ndarray(data == p->data); + } + } + + const ndarray& other_ = dynamic_cast&>(other); + return new ndarray(data == other_.data); + } + + ndarray_base* ne(const ndarray_base& other) const override { + if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int8 != int8 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 != int16 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 != int32 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 != int64 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 != float32 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 != float64 */ + return new ndarray(data != p->data); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int16 != int8 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 != int16 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 != int32 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 != int64 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 != float32 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 != float64 */ + return new ndarray(data != p->data); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int32 != int8 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 != int16 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 != int32 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 != int64 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 != float32 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 != float64 */ + return new ndarray(data != p->data); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int64 != int8 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int64 != int16 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int64 != int32 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int64 != int64 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int64 != float32 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int64 != float64 */ + return new ndarray(data != p->data); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* float32 != int8 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float32 != int16 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float32 != int32 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float32 != int64 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float32 != float32 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float32 != float64 */ + return new ndarray(data != p->data); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* float64 != int8 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float64 != int16 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float64 != int32 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float64 != int64 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float64 != float32 */ + return new ndarray(data != p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* float64 != float64 */ + return new ndarray(data != p->data); + } + } + + const ndarray& other_ = dynamic_cast&>(other); + return new ndarray(data != other_.data); + } + + ndarray_base* add(const ndarray_base& other) const override { + if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int8 + int8 */ + return new ndarray(data + p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 + int16 */ + return new ndarray((data + p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 + int32 */ + return new ndarray(data + p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 + int64 */ + return new ndarray(data + p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 + float32 */ + return new ndarray(data + p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 + float64 */ + return new ndarray(data + p->data); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int16 + int8 */ + return new ndarray((data + p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 + int16 */ + return new ndarray(data + p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 + int32 */ + return new ndarray(data + p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 + int64 */ + return new ndarray(data + p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 + float32 */ + return new ndarray(data + p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 + float64 */ + return new ndarray(data + p->data); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int32 + int8 */ + return new ndarray(data + p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 + int16 */ + return new ndarray(data + p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 + int32 */ + return new ndarray(data + p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 + int64 */ + return new ndarray(data + p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 + float32 */ + return new ndarray(data + p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 + float64 */ + return new ndarray(data + p->data); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* int64 + int8 */ + return new ndarray(data + p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 + int16 */ + return new ndarray(data + p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 + int32 */ + return new ndarray(data + p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 + int64 */ + return new ndarray(data + p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 + float32 */ + return new ndarray(data + p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 + float64 */ + return new ndarray(data + p->data); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* float32 + int8 */ + return new ndarray(data + p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 + int16 */ + return new ndarray(data + p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 + int32 */ + return new ndarray(data + p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 + int64 */ + return new ndarray(data + p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 + float32 */ + return new ndarray(data + p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 + float64 */ + return new ndarray(data + p->data); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* float64 + int8 */ + return new ndarray(data + p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 + int16 */ + return new ndarray(data + p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 + int32 */ + return new ndarray(data + p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 + int64 */ + return new ndarray(data + p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 + float32 */ + return new ndarray(data + p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 + float64 */ + return new ndarray(data + p->data); + } + } + + const ndarray& other_ = dynamic_cast&>(other); + return new ndarray(data + other_.data); + } + + ndarray_base* add_bool(bool_ other) const override { + if constexpr(std::is_same_v) { + return new ndarray((data + other).template astype()); + } else if constexpr(std::is_same_v) { + return new ndarray((data + other).template astype()); + } else { + return new ndarray(data + other); + } + } + + ndarray_base* add_int(int_ other) const override { + if constexpr(std::is_same_v) { + return new ndarray(data + other); + } else if constexpr(std::is_same_v) { + return new ndarray((data + other).template astype()); + } else if constexpr(std::is_same_v) { + return new ndarray((data + other).template astype()); + } else if constexpr(std::is_same_v) { + return new ndarray((data + other).template astype()); + } else if constexpr(std::is_same_v) { + return new ndarray(data + other); + } else if constexpr(std::is_same_v) { + return new ndarray(data + other); + } else if constexpr(std::is_same_v) { + return new ndarray(data + other); + } + } + + ndarray_base* add_float(float64 other) const override { return new ndarray(data + other); } + + ndarray_base* sub(const ndarray_base& other) const override { + if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int8 - int8 */ + return new ndarray(data - p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 - int16 */ + return new ndarray((data - p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 - int32 */ + return new ndarray(data - p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 - int64 */ + return new ndarray(data - p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 - float32 */ + return new ndarray(data - p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 - float64 */ + return new ndarray(data - p->data); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int16 - int8 */ + return new ndarray((data - p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 - int16 */ + return new ndarray(data - p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 - int32 */ + return new ndarray(data - p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 - int64 */ + return new ndarray(data - p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 - float32 */ + return new ndarray(data - p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 - float64 */ + return new ndarray(data - p->data); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int32 - int8 */ + return new ndarray(data - p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 - int16 */ + return new ndarray(data - p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 - int32 */ + return new ndarray(data - p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 - int64 */ + return new ndarray(data - p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 - float32 */ + return new ndarray(data - p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 - float64 */ + return new ndarray(data - p->data); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* int64 - int8 */ + return new ndarray(data - p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 - int16 */ + return new ndarray(data - p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 - int32 */ + return new ndarray(data - p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 - int64 */ + return new ndarray(data - p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 - float32 */ + return new ndarray(data - p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 - float64 */ + return new ndarray(data - p->data); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* float32 - int8 */ + return new ndarray(data - p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 - int16 */ + return new ndarray(data - p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 - int32 */ + return new ndarray(data - p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 - int64 */ + return new ndarray(data - p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 - float32 */ + return new ndarray(data - p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 - float64 */ + return new ndarray(data - p->data); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* float64 - int8 */ + return new ndarray(data - p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 - int16 */ + return new ndarray(data - p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 - int32 */ + return new ndarray(data - p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 - int64 */ + return new ndarray(data - p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 - float32 */ + return new ndarray(data - p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 - float64 */ + return new ndarray(data - p->data); + } + } + + const ndarray& other_ = dynamic_cast&>(other); + return new ndarray(data - other_.data); + } + + ndarray_base* sub_int(int_ other) const override { + if constexpr(std::is_same_v) { + return new ndarray(data - other); + } else if constexpr(std::is_same_v) { + return new ndarray((data - other).template astype()); + } else if constexpr(std::is_same_v) { + return new ndarray((data - other).template astype()); + } else if constexpr(std::is_same_v) { + return new ndarray((data - other).template astype()); + } else if constexpr(std::is_same_v) { + return new ndarray(data - other); + } else if constexpr(std::is_same_v) { + return new ndarray(data - other); + } else if constexpr(std::is_same_v) { + return new ndarray(data - other); + } + } + + ndarray_base* sub_float(float64 other) const override { return new ndarray(data - other); } + + ndarray_base* rsub_int(int_ other) const override { + if constexpr(std::is_same_v) { + return new ndarray(other - data); + } else if constexpr(std::is_same_v) { + return new ndarray((other - data).template astype()); + } else if constexpr(std::is_same_v) { + return new ndarray((other - data).template astype()); + } else if constexpr(std::is_same_v) { + return new ndarray((other - data).template astype()); + } else if constexpr(std::is_same_v) { + return new ndarray(other - data); + } else if constexpr(std::is_same_v) { + return new ndarray(other - data); + } else if constexpr(std::is_same_v) { + return new ndarray(other - data); + } + } + + ndarray_base* rsub_float(float64 other) const override { return new ndarray(other - data); } + + ndarray_base* mul(const ndarray_base& other) const override { + if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int8 * int8 */ + return new ndarray(data * p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 * int16 */ + return new ndarray((data * p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 * int32 */ + return new ndarray(data * p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 * int64 */ + return new ndarray(data * p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 * float32 */ + return new ndarray(data * p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 * float64 */ + return new ndarray(data * p->data); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int16 * int8 */ + return new ndarray((data * p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 * int16 */ + return new ndarray(data * p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 * int32 */ + return new ndarray(data * p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 * int64 */ + return new ndarray(data * p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 * float32 */ + return new ndarray(data * p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 * float64 */ + return new ndarray(data * p->data); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int32 * int8 */ + return new ndarray(data * p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 * int16 */ + return new ndarray(data * p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 * int32 */ + return new ndarray(data * p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 * int64 */ + return new ndarray(data * p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 * float32 */ + return new ndarray(data * p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 * float64 */ + return new ndarray(data * p->data); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* int64 * int8 */ + return new ndarray(data * p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 * int16 */ + return new ndarray(data * p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 * int32 */ + return new ndarray(data * p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 * int64 */ + return new ndarray(data * p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 * float32 */ + return new ndarray(data * p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 * float64 */ + return new ndarray(data * p->data); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* float32 * int8 */ + return new ndarray(data * p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 * int16 */ + return new ndarray(data * p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 * int32 */ + return new ndarray(data * p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 * int64 */ + return new ndarray(data * p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 * float32 */ + return new ndarray(data * p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 * float64 */ + return new ndarray(data * p->data); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* float64 * int8 */ + return new ndarray(data * p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 * int16 */ + return new ndarray(data * p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 * int32 */ + return new ndarray(data * p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 * int64 */ + return new ndarray(data * p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 * float32 */ + return new ndarray(data * p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 * float64 */ + return new ndarray(data * p->data); + } + } + + const ndarray& other_ = dynamic_cast&>(other); + return new ndarray(data * other_.data); + } + + ndarray_base* mul_bool(bool_ other) const override { + if constexpr(std::is_same_v) { + return new ndarray((data * other).template astype()); + } else if constexpr(std::is_same_v) { + return new ndarray((data * other).template astype()); + } else { + return new ndarray(data * other); + } + } + + ndarray_base* mul_int(int_ other) const override { + if constexpr(std::is_same_v) { + return new ndarray(data * other); + } else if constexpr(std::is_same_v) { + return new ndarray((data * other).template astype()); + } else if constexpr(std::is_same_v) { + return new ndarray((data * other).template astype()); + } else if constexpr(std::is_same_v) { + return new ndarray((data * other).template astype()); + } else if constexpr(std::is_same_v) { + return new ndarray(data * other); + } else if constexpr(std::is_same_v) { + return new ndarray(data * other); + } else if constexpr(std::is_same_v) { + return new ndarray(data * other); + } + } + + ndarray_base* mul_float(float64 other) const override { return new ndarray(data * other); } + + ndarray_base* div(const ndarray_base& other) const override { + if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* bool / bool */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* bool / int8 */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* bool / int16 */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* bool / int32 */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* bool / int64 */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* bool / float32 */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* bool / float64 */ + return new ndarray(data / p->data); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* int8 / bool */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 / int8 */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 / int16 */ + return new ndarray((data / p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 / int32 */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 / int64 */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 / float32 */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 / float64 */ + return new ndarray(data / p->data); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* int16 / bool */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 / int8 */ + return new ndarray((data / p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 / int16 */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 / int32 */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 / int64 */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 / float32 */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 / float64 */ + return new ndarray(data / p->data); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* int32 / bool */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 / int8 */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 / int16 */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 / int32 */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 / int64 */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 / float32 */ + return new ndarray(data / p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 / float64 */ + return new ndarray(data / p->data); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* int64 / bool */ + return new ndarray(data / p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 / int8 */ + return new ndarray(data / p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 / int16 */ + return new ndarray(data / p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 / int32 */ + return new ndarray(data / p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 / int64 */ + return new ndarray(data / p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 / float32 */ + return new ndarray(data / p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 / float64 */ + return new ndarray(data / p->data); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* float32 / bool */ + return new ndarray(data / p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 / int8 */ + return new ndarray(data / p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 / int16 */ + return new ndarray(data / p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 / int32 */ + return new ndarray(data / p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 / int64 */ + return new ndarray(data / p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 / float32 */ + return new ndarray(data / p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 / float64 */ + return new ndarray(data / p->data); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* float64 / bool */ + return new ndarray(data / p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 / int8 */ + return new ndarray(data / p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 / int16 */ + return new ndarray(data / p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 / int32 */ + return new ndarray(data / p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 / int64 */ + return new ndarray(data / p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 / float32 */ + return new ndarray(data / p->data); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 / float64 */ + return new ndarray(data / p->data); + } + } + + const ndarray& other_ = dynamic_cast&>(other); + return new ndarray(data / other_.data); + } + + ndarray_base* div_bool(bool_ other) const override { return new ndarray(data / other); } + + ndarray_base* div_int(int_ other) const override { return new ndarray(data / other); } + + ndarray_base* div_float(float64 other) const override { return new ndarray(data / other); } + + ndarray_base* rdiv_bool(bool_ other) const override { return new ndarray(other / data); } + + ndarray_base* rdiv_int(int_ other) const override { return new ndarray(other / data); } + + ndarray_base* rdiv_float(float64 other) const override { return new ndarray(other / data); } + + ndarray_base* matmul(const ndarray_base& other) const override { + if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int8 @ int8 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 @ int16 */ + return new ndarray(pkpy::numpy::matmul(data, p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 @ int32 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 @ int64 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 @ float32 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 @ float64 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int16 @ int8 */ + return new ndarray(pkpy::numpy::matmul(data, p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 @ int16 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 @ int32 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 @ int64 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 @ float32 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 @ float64 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int32 @ int8 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 @ int16 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 @ int32 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 @ int64 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 @ float32 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 @ float64 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* int64 @ int8 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 @ int16 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 @ int32 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 @ int64 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 @ float32 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 @ float64 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* float32 @ int8 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 @ int16 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 @ int32 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 @ int64 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 @ float32 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 @ float64 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* float64 @ int8 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 @ int16 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 @ int32 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 @ int64 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 @ float32 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 @ float64 */ + return new ndarray(pkpy::numpy::matmul(data, p->data)); + } + } + + const ndarray& other_ = dynamic_cast&>(other); + return new ndarray(pkpy::numpy::matmul(data, other_.data)); + } + + ndarray_base* pow(const ndarray_base& other) const override { + if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int8 ** int8 */ + return new ndarray(data.pow(p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 ** int16 */ + return new ndarray(data.pow(p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 ** int32 */ + return new ndarray(data.pow(p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 ** int64 */ + return new ndarray(data.pow(p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 ** float32 */ + return new ndarray(data.pow(p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 ** float64 */ + return new ndarray(data.pow(p->data)); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int16 ** int8 */ + return new ndarray(data.pow(p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 ** int16 */ + return new ndarray(data.pow(p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 ** int32 */ + return new ndarray(data.pow(p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 ** int64 */ + return new ndarray(data.pow(p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 ** float32 */ + return new ndarray(data.pow(p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 ** float64 */ + return new ndarray(data.pow(p->data)); + } + } else if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int32 ** int8 */ + return new ndarray(data.pow(p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 ** int16 */ + return new ndarray(data.pow(p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 ** int32 */ + return new ndarray(data.pow(p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 ** int64 */ + return new ndarray(data.pow(p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 ** float32 */ + return new ndarray(data.pow(p->data)); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 ** float64 */ + return new ndarray(data.pow(p->data)); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* int64 ** int8 */ + return new ndarray(data.pow(p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 ** int16 */ + return new ndarray(data.pow(p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 ** int32 */ + return new ndarray(data.pow(p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 ** int64 */ + return new ndarray(data.pow(p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 ** float32 */ + return new ndarray(data.pow(p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* int64 ** float64 */ + return new ndarray(data.pow(p->data)); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* float32 ** int8 */ + return new ndarray(data.pow(p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 ** int16 */ + return new ndarray(data.pow(p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 ** int32 */ + return new ndarray(data.pow(p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 ** int64 */ + return new ndarray(data.pow(p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 ** float32 */ + return new ndarray(data.pow(p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float32 ** float64 */ + return new ndarray(data.pow(p->data)); + } + } else if constexpr(std::is_same_v) { + if (auto p = dynamic_cast*>(&other)) { /* float64 ** int8 */ + return new ndarray(data.pow(p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 ** int16 */ + return new ndarray(data.pow(p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 ** int32 */ + return new ndarray(data.pow(p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 ** int64 */ + return new ndarray(data.pow(p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 ** float32 */ + return new ndarray(data.pow(p->data)); + } else if (auto p = dynamic_cast*>(&other)) { /* float64 ** float64 */ + return new ndarray(data.pow(p->data)); + } + } + + const ndarray& other_ = dynamic_cast&>(other); + return new ndarray(data.pow(other_.data)); + } + + ndarray_base* pow_int(int_ other) const override { return new ndarray(data.pow(other)); } + + ndarray_base* pow_float(float64 other) const override { return new ndarray(data.pow(other)); } + + ndarray_base* rpow_int(int_ other) const override { return new ndarray(pkpy::numpy::pow(other, data)); } + + ndarray_base* rpow_float(float64 other) const override { + return new ndarray(pkpy::numpy::pow(other, data)); + } + + int len() const override { return data.shape()[0]; } + + ndarray_base* and_array(const ndarray_base& other) const override { + if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* bool & bool */ + return new ndarray(data & p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* bool & int8 */ + return new ndarray((data & p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* bool & int16 */ + return new ndarray((data & p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* bool & int32 */ + return new ndarray((data & p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* bool & int64 */ + return new ndarray((data & p->data).template astype()); + } + } else if constexpr (std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int8 & bool */ + return new ndarray(data & p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 & int8 */ + return new ndarray(data & p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 & int16 */ + return new ndarray((data & p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 & int32 */ + return new ndarray((data & p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 & int64 */ + return new ndarray((data & p->data).template astype()); + } + } else if constexpr (std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int16 & bool */ + return new ndarray(data & p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 & int8 */ + return new ndarray(data & p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 & int16 */ + return new ndarray(data & p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 & int32 */ + return new ndarray((data & p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* int16 & int64 */ + return new ndarray((data & p->data).template astype()); + } + } else if constexpr (std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int32 & bool */ + return new ndarray(data & p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 & int8 */ + return new ndarray(data & p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 & int16 */ + return new ndarray(data & p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 & int32 */ + return new ndarray(data & p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int32 & int64 */ + return new ndarray((data & p->data).template astype()); + } + } else if constexpr (std::is_same_v) { + if (auto p = dynamic_cast *>(&other)) { /* int64 & bool */ + return new ndarray(data & p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int64 & int8 */ + return new ndarray(data & p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int64 & int16 */ + return new ndarray(data & p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int64 & int32 */ + return new ndarray(data & p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int64 & int64 */ + return new ndarray(data & p->data); + } + } + + throw std::runtime_error("& operator is not compatible with floating types"); + } + + ndarray_base* and_bool(bool_ other) const override { + if constexpr(std::is_same_v) { + return new ndarray(data & other); + } else if constexpr(std::is_same_v) { + return new ndarray(data & other); + } else if constexpr(std::is_same_v) { + return new ndarray(data & other); + } else if constexpr(std::is_same_v) { + return new ndarray(data & other); + } else if constexpr(std::is_same_v) { + return new ndarray(data & other); + } + + throw std::runtime_error("& operator is not compatible with floating types"); + } + + ndarray_base* and_int(int_ other) const override { + if constexpr(std::is_same_v) { + return new ndarray((data & other).template astype()); + } else if constexpr(std::is_same_v) { + return new ndarray(data & other); + } else if constexpr(std::is_same_v) { + return new ndarray(data & other); + } else if constexpr(std::is_same_v) { + return new ndarray(data & other); + } else if constexpr(std::is_same_v) { + return new ndarray(data & other); + } + + throw std::runtime_error("& operator is not compatible with floating types"); + } + + ndarray_base* or_array(const ndarray_base& other) const override { + if constexpr(std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* bool | bool */ + return new ndarray(data | p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* bool | int8 */ + return new ndarray((data | p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* bool | int16 */ + return new ndarray((data | p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* bool | int32 */ + return new ndarray((data | p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* bool | int64 */ + return new ndarray((data | p->data).template astype()); + } + } else if constexpr (std::is_same_v) { + if(auto p = dynamic_cast*>(&other)) { /* int8 | bool */ + return new ndarray(data | p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 | int8 */ + return new ndarray(data | p->data); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 | int16 */ + return new ndarray((data | p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 | int32 */ + return new ndarray((data | p->data).template astype()); + } else if(auto p = dynamic_cast*>(&other)) { /* int8 | int64 */ + return new ndarray((data | p->data).template astype()); + } + } else if constexpr (std::is_same_v) { + if (auto p = dynamic_cast *>(&other)) { /* int16 | bool */ + return new ndarray(data | p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int16 | int8 */ + return new ndarray(data | p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int16 | int16 */ + return new ndarray(data | p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int16 | int32 */ + return new ndarray((data | p->data).template astype()); + } else if (auto p = dynamic_cast *>(&other)) { /* int16 | int64 */ + return new ndarray((data | p->data).template astype()); + } + } else if constexpr (std::is_same_v) { + if (auto p = dynamic_cast *>(&other)) { /* int32 | bool */ + return new ndarray(data | p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int32 | int8 */ + return new ndarray(data | p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int32 | int16 */ + return new ndarray(data | p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int32 | int32 */ + return new ndarray(data | p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int32 | int64 */ + return new ndarray((data | p->data).template astype()); + } + } else if constexpr (std::is_same_v) { + if (auto p = dynamic_cast *>(&other)) { /* int64 | bool */ + return new ndarray(data | p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int64 | int8 */ + return new ndarray(data | p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int64 | int16 */ + return new ndarray(data | p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int64 | int32 */ + return new ndarray(data | p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int64 | int64 */ + return new ndarray(data | p->data); + } + } + + throw std::runtime_error("| operator is not compatible with floating types"); + } + + ndarray_base* or_bool(bool_ other) const override { + if constexpr(std::is_same_v) { + return new ndarray(data | other); + } else if constexpr(std::is_same_v) { + return new ndarray(data | other); + } else if constexpr(std::is_same_v) { + return new ndarray(data | other); + } else if constexpr(std::is_same_v) { + return new ndarray(data | other); + } else if constexpr(std::is_same_v) { + return new ndarray(data | other); + } + + throw std::runtime_error("| operator is not compatible with floating types"); + } + + ndarray_base* or_int(int_ other) const override { + if constexpr(std::is_same_v) { + return new ndarray((data | other).template astype()); + } else if constexpr(std::is_same_v) { + return new ndarray(data | other); + } else if constexpr(std::is_same_v) { + return new ndarray(data | other); + } else if constexpr(std::is_same_v) { + return new ndarray(data | other); + } else if constexpr(std::is_same_v) { + return new ndarray(data | other); + } + + throw std::runtime_error("| operator is not compatible with floating types"); + } + + ndarray_base* xor_array(const ndarray_base& other) const override { + if constexpr (std::is_same_v) { + if (auto p = dynamic_cast *>(&other)) { /* bool ^ bool */ + return new ndarray(data ^ p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* bool ^ int8 */ + return new ndarray((data ^ p->data).template astype()); + } else if (auto p = dynamic_cast *>(&other)) { /* bool ^ int16 */ + return new ndarray((data ^ p->data).template astype()); + } else if (auto p = dynamic_cast *>(&other)) { /* bool ^ int32 */ + return new ndarray((data ^ p->data).template astype()); + } else if (auto p = dynamic_cast *>(&other)) { /* bool ^ int64 */ + return new ndarray((data ^ p->data).template astype()); + } + } else if constexpr (std::is_same_v) { + if (auto p = dynamic_cast *>(&other)) { /* int8 ^ bool */ + return new ndarray(data ^ p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int8 ^ int8 */ + return new ndarray(data ^ p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int8 ^ int16 */ + return new ndarray((data ^ p->data).template astype()); + } else if (auto p = dynamic_cast *>(&other)) { /* int8 ^ int32 */ + return new ndarray((data ^ p->data).template astype()); + } else if (auto p = dynamic_cast *>(&other)) { /* int8 ^ int64 */ + return new ndarray((data ^ p->data).template astype()); + } + } else if constexpr (std::is_same_v) { + if (auto p = dynamic_cast *>(&other)) { /* int16 ^ bool */ + return new ndarray(data ^ p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int16 ^ int8 */ + return new ndarray(data ^ p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int16 ^ int16 */ + return new ndarray(data ^ p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int16 ^ int32 */ + return new ndarray((data ^ p->data).template astype()); + } else if (auto p = dynamic_cast *>(&other)) { /* int16 ^ int64 */ + return new ndarray((data ^ p->data).template astype()); + } + } else if constexpr (std::is_same_v) { + if (auto p = dynamic_cast *>(&other)) { /* int32 ^ bool */ + return new ndarray(data ^ p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int32 ^ int8 */ + return new ndarray(data ^ p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int32 ^ int16 */ + return new ndarray(data ^ p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int32 ^ int32 */ + return new ndarray(data ^ p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int32 ^ int64 */ + return new ndarray((data ^ p->data).template astype()); + } + } else if constexpr (std::is_same_v) { + if (auto p = dynamic_cast *>(&other)) { /* int64 ^ bool */ + return new ndarray(data ^ p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int64 ^ int8 */ + return new ndarray(data ^ p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int64 ^ int16 */ + return new ndarray(data ^ p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int64 ^ int32 */ + return new ndarray(data ^ p->data); + } else if (auto p = dynamic_cast *>(&other)) { /* int64 ^ int64 */ + return new ndarray(data ^ p->data); + } + } + + throw std::runtime_error("^ operator is not compatible with floating types"); + } + + ndarray_base* xor_bool(bool_ other) const override { + if constexpr(std::is_same_v) { + return new ndarray(data ^ other); + } else if constexpr(std::is_same_v) { + return new ndarray(data ^ other); + } else if constexpr(std::is_same_v) { + return new ndarray(data ^ other); + } else if constexpr(std::is_same_v) { + return new ndarray(data ^ other); + } else if constexpr(std::is_same_v) { + return new ndarray(data ^ other); + } + + throw std::runtime_error("^ operator is not compatible with floating types"); + } + + ndarray_base* xor_int(int_ other) const override { + if constexpr(std::is_same_v) { + return new ndarray((data ^ other).template astype()); + } else if constexpr(std::is_same_v) { + return new ndarray(data ^ other); + } else if constexpr(std::is_same_v) { + return new ndarray(data ^ other); + } else if constexpr(std::is_same_v) { + return new ndarray(data ^ other); + } else if constexpr(std::is_same_v) { + return new ndarray(data ^ other); + } + + throw std::runtime_error("^ operator is not compatible with floating types"); + } + + ndarray_base* invert() const override { + if constexpr(std::is_same_v) { + return new ndarray(!data); + } else if constexpr(std::is_same_v) { + return new ndarray(!data); + } else if constexpr(std::is_same_v) { + return new ndarray(!data); + } else if constexpr(std::is_same_v) { + return new ndarray(!data); + } else if constexpr(std::is_same_v) { + return new ndarray(!data); + } + + throw std::runtime_error("~ operator is not compatible with floating types"); + } + + py::object get_item_int(int index) const override { + if(index < 0) index += data.shape()[0]; + if(data.ndim() == 1) { + if constexpr(std::is_same_v) { + return py::bool_(data(index)); + } else if constexpr(std::is_same_v) { + return py::int_(data(index)); + } else if constexpr(std::is_same_v) { + return py::float_(data(index)); + } + } + return py::cast(ndarray(data[index])); + } + + py::object get_item_tuple(py::tuple args) const override { + pkpy::numpy::ndarray store = data; + std::vector indices; + for(auto item: args) { + indices.push_back(py::cast(item)); + } + for(int i = 0; i < indices.size() - 1; i++) { + if(indices[i] < 0) indices[i] += store.shape()[0]; + pkpy::numpy::ndarray temp = store[indices[i]]; + store = temp; + } + + if(indices[indices.size() - 1] < 0) indices[indices.size() - 1] += store.shape()[0]; + if(store.ndim() == 1) { + if constexpr(std::is_same_v) { + return py::bool_(store(indices[indices.size() - 1])); + } else if constexpr(std::is_same_v) { + return py::int_(store(indices[indices.size() - 1])); + } else if constexpr(std::is_same_v) { + return py::float_(store(indices[indices.size() - 1])); + } + } + return py::cast(ndarray(store[indices[indices.size() - 1]])); + } + + ndarray_base* get_item_vector(const std::vector& indices) const override { + return new ndarray(data[indices]); + } + + ndarray_base* get_item_slice(py::slice slice) const override { + int start = parseAttr(getattr(slice, "start")); + int stop = parseAttr(getattr(slice, "stop")); + int step = parseAttr(getattr(slice, "step")); + + if(step == INT_MAX) step = 1; + if(step > 0) { + if(start == INT_MAX) start = 0; + if(stop == INT_MAX) stop = data.shape()[0]; + } else if(step < 0) { + if(start == INT_MAX) start = data.shape()[0] - 1; + if(stop == INT_MAX) stop = -(1 + data.shape()[0]); + } + + return new ndarray(data[std::make_tuple(start, stop, step)]); + } + + void set_item_int(int index, int_ value) override { + if constexpr(std::is_same_v) { + if (data.ndim() == 1) { + data.set_item(index, value); + } else { + data.set_item(index, pkpy::numpy::adapt(std::vector{value})); + } + } else if constexpr(std::is_same_v) { + if (data.ndim() == 1) { + data.set_item(index, static_cast(value)); + } else { + data.set_item(index, (pkpy::numpy::adapt(std::vector{value})).astype()); + } + } + } + + void set_item_index_int(int index, const std::vector& value) override { + if constexpr(std::is_same_v) { + data.set_item(index, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(index, (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_index_int_2d(int index, const std::vector>& value) override { + if constexpr(std::is_same_v) { + data.set_item(index, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(index, (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_index_int_3d(int index, const std::vector>>& value) override { + if constexpr(std::is_same_v) { + data.set_item(index, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(index, (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_index_int_4d(int index, const std::vector>>>& value) override { + if constexpr(std::is_same_v) { + data.set_item(index, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(index, (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_float(int index, float64 value) override { + if constexpr(std::is_same_v) { + if (data.ndim() == 1) { + data.set_item(index, value); + } else { + data.set_item(index, pkpy::numpy::adapt(std::vector{value})); + } + } else if constexpr(std::is_same_v) { + if (data.ndim() == 1) { + data.set_item(index, static_cast(value)); + } else { + data.set_item(index, (pkpy::numpy::adapt(std::vector{value})).astype()); + } + } + } + + void set_item_index_float(int index, const std::vector& value) override { + if constexpr(std::is_same_v) { + data.set_item(index, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(index, (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_index_float_2d(int index, const std::vector>& value) override { + if constexpr(std::is_same_v) { + data.set_item(index, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(index, (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_index_float_3d(int index, const std::vector>>& value) override { + if constexpr(std::is_same_v) { + data.set_item(index, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(index, (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_index_float_4d(int index, const std::vector>>>& value) override { + if constexpr(std::is_same_v) { + data.set_item(index, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(index, (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_tuple_int1(py::tuple args, int_ value) override { + std::vector indices; + for(auto item: args) { + indices.push_back(py::cast(item)); + } + if(indices.size() == 1) { + int index = indices[0]; + if constexpr(std::is_same_v) { + data.set_item(index, pkpy::numpy::adapt(std::vector{value})); + } else if constexpr(std::is_same_v) { + data.set_item(index, (pkpy::numpy::adapt(std::vector{value})).astype()); + } + } else if(indices.size() == 2 && indices.size() <= data.ndim()) + data.set_item(indices[0], indices[1], static_cast(value)); + else if(indices.size() == 3 && indices.size() <= data.ndim()) + data.set_item(indices[0], indices[1], indices[2], static_cast(value)); + else if(indices.size() == 4 && indices.size() <= data.ndim()) + data.set_item(indices[0], indices[1], indices[2], indices[3], static_cast(value)); + else if(indices.size() == 5 && indices.size() <= data.ndim()) + data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], static_cast(value)); + } + + void set_item_tuple_int2(py::tuple args, const std::vector& value) override { + std::vector indices; + for(auto item: args) { + indices.push_back(py::cast(item)); + } + if(indices.size() == 1) { + int index = indices[0]; + if constexpr(std::is_same_v) { + data.set_item(index, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(index, (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 2 && indices.size() <= data.ndim()) { + if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 3 && indices.size() <= data.ndim()) { + if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 4 && indices.size() <= data.ndim()) { + if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 5 && indices.size() <= data.ndim()) { + if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], (pkpy::numpy::adapt(value)).astype()); + } + } + } + + void set_item_tuple_int3(py::tuple args, const std::vector>& value) override { + std::vector indices; + for(auto item: args) { + indices.push_back(py::cast(item)); + } + if(indices.size() == 1) { + int index = indices[0]; + if constexpr(std::is_same_v) { + data.set_item(index, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(index, (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 2 && indices.size() <= data.ndim()) { + if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 3 && indices.size() <= data.ndim()) { + if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 4 && indices.size() <= data.ndim()) { + if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 5 && indices.size() <= data.ndim()) { + if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], (pkpy::numpy::adapt(value)).astype()); + } + } + } + + void set_item_tuple_int4(py::tuple args, const std::vector>>& value) override { + std::vector indices; + for(auto item: args) { + indices.push_back(py::cast(item)); + } + if(indices.size() == 1) { + int index = indices[0]; + if constexpr(std::is_same_v) { + data.set_item(index, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(index, (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 2 && indices.size() <= data.ndim()) { + if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 3 && indices.size() <= data.ndim()) { + if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 4 && indices.size() <= data.ndim()) { + if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 5 && indices.size() <= data.ndim()) { + if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], (pkpy::numpy::adapt(value)).astype()); + } + } + } + + void set_item_tuple_int5(py::tuple args, const std::vector>>>& value) override { + std::vector indices; + for(auto item: args) { + indices.push_back(py::cast(item)); + } + if(indices.size() == 1) { + int index = indices[0]; + if constexpr(std::is_same_v) { + data.set_item(index, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(index, (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 2 && indices.size() <= data.ndim()) { + if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 3 && indices.size() <= data.ndim()) { + if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 4 && indices.size() <= data.ndim()) { + if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 5 && indices.size() <= data.ndim()) { + if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], (pkpy::numpy::adapt(value)).astype()); + } + } + } + + void set_item_tuple_float1(py::tuple args, float64 value) override { + std::vector indices; + for(auto item: args) { + indices.push_back(py::cast(item)); + } + if(indices.size() == 1) { + int index = indices[0]; + if constexpr(std::is_same_v) { + data.set_item(index, pkpy::numpy::adapt(std::vector{value})); + } else if constexpr(std::is_same_v) { + data.set_item(index, (pkpy::numpy::adapt(std::vector{value})).astype()); + } + } else if(indices.size() == 2 && indices.size() <= data.ndim()) + data.set_item(indices[0], indices[1], static_cast(value)); + else if(indices.size() == 3 && indices.size() <= data.ndim()) + data.set_item(indices[0], indices[1], indices[2], static_cast(value)); + else if(indices.size() == 4 && indices.size() <= data.ndim()) + data.set_item(indices[0], indices[1], indices[2], indices[3], static_cast(value)); + else if(indices.size() == 5 && indices.size() <= data.ndim()) + data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], static_cast(value)); + } + + void set_item_tuple_float2(py::tuple args, const std::vector& value) override { + std::vector indices; + for(auto item: args) { + indices.push_back(py::cast(item)); + } + if(indices.size() == 1) { + int index = indices[0]; + if constexpr(std::is_same_v) { + data.set_item(index, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(index, (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 2 && indices.size() <= data.ndim()) { + if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], pkpy::numpy::adapt(value)); + } else if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], (pkpy::numpy::adapt(value)).astype()); + } + } + else if(indices.size() == 3 && indices.size() <= data.ndim()) { + if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], pkpy::numpy::adapt(value)); + } else if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], (pkpy::numpy::adapt(value)).astype()); + } + } + else if(indices.size() == 4 && indices.size() <= data.ndim()) { + if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], pkpy::numpy::adapt(value)); + } else if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], (pkpy::numpy::adapt(value)).astype()); + } + } + else if(indices.size() == 5 && indices.size() <= data.ndim()) { + if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], pkpy::numpy::adapt(value)); + } else if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], (pkpy::numpy::adapt(value)).astype()); + } + } + } + + void set_item_tuple_float3(py::tuple args, const std::vector>& value) override { + std::vector indices; + for(auto item: args) { + indices.push_back(py::cast(item)); + } + if(indices.size() == 1) { + int index = indices[0]; + if constexpr(std::is_same_v) { + data.set_item(index, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(index, (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 2 && indices.size() <= data.ndim()) { + if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], pkpy::numpy::adapt(value)); + } else if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], (pkpy::numpy::adapt(value)).astype()); + } + } + else if(indices.size() == 3 && indices.size() <= data.ndim()) { + if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], pkpy::numpy::adapt(value)); + } else if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], (pkpy::numpy::adapt(value)).astype()); + } + } + else if(indices.size() == 4 && indices.size() <= data.ndim()) { + if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], pkpy::numpy::adapt(value)); + } else if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], (pkpy::numpy::adapt(value)).astype()); + } + } + else if(indices.size() == 5 && indices.size() <= data.ndim()) { + if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], pkpy::numpy::adapt(value)); + } else if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], (pkpy::numpy::adapt(value)).astype()); + } + } + } + + void set_item_tuple_float4(py::tuple args, const std::vector>>& value) override { + std::vector indices; + for(auto item: args) { + indices.push_back(py::cast(item)); + } + if(indices.size() == 1) { + int index = indices[0]; + if constexpr(std::is_same_v) { + data.set_item(index, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(index, (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 2 && indices.size() <= data.ndim()) { + if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], pkpy::numpy::adapt(value)); + } else if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], (pkpy::numpy::adapt(value)).astype()); + } + } + else if(indices.size() == 3 && indices.size() <= data.ndim()) { + if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], pkpy::numpy::adapt(value)); + } else if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], (pkpy::numpy::adapt(value)).astype()); + } + } + else if(indices.size() == 4 && indices.size() <= data.ndim()) { + if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], pkpy::numpy::adapt(value)); + } else if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], (pkpy::numpy::adapt(value)).astype()); + } + } + else if(indices.size() == 5 && indices.size() <= data.ndim()) { + if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], pkpy::numpy::adapt(value)); + } else if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], (pkpy::numpy::adapt(value)).astype()); + } + } + } + + void set_item_tuple_float5(py::tuple args, const std::vector>>>& value) override { + std::vector indices; + for(auto item: args) { + indices.push_back(py::cast(item)); + } + if(indices.size() == 1) { + int index = indices[0]; + if constexpr(std::is_same_v) { + data.set_item(index, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(index, (pkpy::numpy::adapt(value)).astype()); + } + } else if(indices.size() == 2 && indices.size() <= data.ndim()) { + if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], pkpy::numpy::adapt(value)); + } else if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], (pkpy::numpy::adapt(value)).astype()); + } + } + else if(indices.size() == 3 && indices.size() <= data.ndim()) { + if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], pkpy::numpy::adapt(value)); + } else if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], (pkpy::numpy::adapt(value)).astype()); + } + } + else if(indices.size() == 4 && indices.size() <= data.ndim()) { + if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], pkpy::numpy::adapt(value)); + } else if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], (pkpy::numpy::adapt(value)).astype()); + } + } + else if(indices.size() == 5 && indices.size() <= data.ndim()) { + if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], pkpy::numpy::adapt(value)); + } else if constexpr (std::is_same_v) { + data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], (pkpy::numpy::adapt(value)).astype()); + } + } + } + + void set_item_vector_int1(const std::vector& indices, int_ value) override { + if constexpr(std::is_same_v) { + data.set_item(indices, pkpy::numpy::adapt(std::vector{value})); + } else if constexpr(std::is_same_v) { + data.set_item(indices, (pkpy::numpy::adapt(std::vector{value})).astype()); + } + } + + void set_item_vector_int2(const std::vector& indices, const std::vector& value) override { + if constexpr(std::is_same_v) { + data.set_item(indices, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices, (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_vector_int3(const std::vector& indices, const std::vector>& value) override { + if constexpr(std::is_same_v) { + data.set_item(indices, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices, (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_vector_int4(const std::vector& indices, const std::vector>>& value) override { + if constexpr(std::is_same_v) { + data.set_item(indices, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices, (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_vector_int5(const std::vector& indices, const std::vector>>>& value) override { + if constexpr(std::is_same_v) { + data.set_item(indices, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices, (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_vector_float1(const std::vector& indices, float64 value) override { + if constexpr(std::is_same_v) { + data.set_item(indices, pkpy::numpy::adapt(std::vector{value})); + } else if constexpr(std::is_same_v) { + data.set_item(indices, (pkpy::numpy::adapt(std::vector{value})).astype()); + } + } + + void set_item_vector_float2(const std::vector& indices, const std::vector& value) override { + if constexpr(std::is_same_v) { + data.set_item(indices, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices, (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_vector_float3(const std::vector& indices, const std::vector>& value) override { + if constexpr(std::is_same_v) { + data.set_item(indices, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices, (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_vector_float4(const std::vector& indices, const std::vector>>& value) override { + if constexpr(std::is_same_v) { + data.set_item(indices, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices, (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_vector_float5(const std::vector& indices, const std::vector>>>& value) override { + if constexpr(std::is_same_v) { + data.set_item(indices, pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(indices, (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_slice_int1(py::slice slice, int_ value) override { + int start = parseAttr(getattr(slice, "start")); + int stop = parseAttr(getattr(slice, "stop")); + int step = parseAttr(getattr(slice, "step")); + + if(step == INT_MAX) step = 1; + if(step > 0) { + if(start == INT_MAX) start = 0; + if(stop == INT_MAX) stop = data.shape()[0]; + } else if(step < 0) { + if(start == INT_MAX) start = data.shape()[0] - 1; + if(stop == INT_MAX) stop = -(1 + data.shape()[0]); + } + if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(std::vector{value})); + } else if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), + (pkpy::numpy::adapt(std::vector{value})).astype()); + } + } + + void set_item_slice_int2(py::slice slice, const std::vector& value) override { + int start = parseAttr(getattr(slice, "start")); + int stop = parseAttr(getattr(slice, "stop")); + int step = parseAttr(getattr(slice, "step")); + + if(step == INT_MAX) step = 1; + if(step > 0) { + if(start == INT_MAX) start = 0; + if(stop == INT_MAX) stop = data.shape()[0]; + } else if(step < 0) { + if(start == INT_MAX) start = data.shape()[0] - 1; + if(stop == INT_MAX) stop = -(1 + data.shape()[0]); + } + if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_slice_int3(py::slice slice, const std::vector>& value) override { + int start = parseAttr(getattr(slice, "start")); + int stop = parseAttr(getattr(slice, "stop")); + int step = parseAttr(getattr(slice, "step")); + + if(step == INT_MAX) step = 1; + if(step > 0) { + if(start == INT_MAX) start = 0; + if(stop == INT_MAX) stop = data.shape()[0]; + } else if(step < 0) { + if(start == INT_MAX) start = data.shape()[0] - 1; + if(stop == INT_MAX) stop = -(1 + data.shape()[0]); + } + if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_slice_int4(py::slice slice, const std::vector>>& value) override { + int start = parseAttr(getattr(slice, "start")); + int stop = parseAttr(getattr(slice, "stop")); + int step = parseAttr(getattr(slice, "step")); + + if(step == INT_MAX) step = 1; + if(step > 0) { + if(start == INT_MAX) start = 0; + if(stop == INT_MAX) stop = data.shape()[0]; + } else if(step < 0) { + if(start == INT_MAX) start = data.shape()[0] - 1; + if(stop == INT_MAX) stop = -(1 + data.shape()[0]); + } + if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_slice_int5(py::slice slice, const std::vector>>>& value) override { + int start = parseAttr(getattr(slice, "start")); + int stop = parseAttr(getattr(slice, "stop")); + int step = parseAttr(getattr(slice, "step")); + + if(step == INT_MAX) step = 1; + if(step > 0) { + if(start == INT_MAX) start = 0; + if(stop == INT_MAX) stop = data.shape()[0]; + } else if(step < 0) { + if(start == INT_MAX) start = data.shape()[0] - 1; + if(stop == INT_MAX) stop = -(1 + data.shape()[0]); + } + if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_slice_float1(py::slice slice, float64 value) override { + int start = parseAttr(getattr(slice, "start")); + int stop = parseAttr(getattr(slice, "stop")); + int step = parseAttr(getattr(slice, "step")); + + if(step == INT_MAX) step = 1; + if(step > 0) { + if(start == INT_MAX) start = 0; + if(stop == INT_MAX) stop = data.shape()[0]; + } else if(step < 0) { + if(start == INT_MAX) start = data.shape()[0] - 1; + if(stop == INT_MAX) stop = -(1 + data.shape()[0]); + } + if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(std::vector{value})); + } else if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), + (pkpy::numpy::adapt(std::vector{value})).astype()); + } + } + + void set_item_slice_float2(py::slice slice, const std::vector& value) override { + int start = parseAttr(getattr(slice, "start")); + int stop = parseAttr(getattr(slice, "stop")); + int step = parseAttr(getattr(slice, "step")); + + if(step == INT_MAX) step = 1; + if(step > 0) { + if(start == INT_MAX) start = 0; + if(stop == INT_MAX) stop = data.shape()[0]; + } else if(step < 0) { + if(start == INT_MAX) start = data.shape()[0] - 1; + if(stop == INT_MAX) stop = -(1 + data.shape()[0]); + } + if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_slice_float3(py::slice slice, const std::vector>& value) override { + int start = parseAttr(getattr(slice, "start")); + int stop = parseAttr(getattr(slice, "stop")); + int step = parseAttr(getattr(slice, "step")); + + if(step == INT_MAX) step = 1; + if(step > 0) { + if(start == INT_MAX) start = 0; + if(stop == INT_MAX) stop = data.shape()[0]; + } else if(step < 0) { + if(start == INT_MAX) start = data.shape()[0] - 1; + if(stop == INT_MAX) stop = -(1 + data.shape()[0]); + } + if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_slice_float4(py::slice slice, const std::vector>>& value) override { + int start = parseAttr(getattr(slice, "start")); + int stop = parseAttr(getattr(slice, "stop")); + int step = parseAttr(getattr(slice, "step")); + + if(step == INT_MAX) step = 1; + if(step > 0) { + if(start == INT_MAX) start = 0; + if(stop == INT_MAX) stop = data.shape()[0]; + } else if(step < 0) { + if(start == INT_MAX) start = data.shape()[0] - 1; + if(stop == INT_MAX) stop = -(1 + data.shape()[0]); + } + if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), (pkpy::numpy::adapt(value)).astype()); + } + } + + void set_item_slice_float5(py::slice slice, const std::vector>>>& value) override { + int start = parseAttr(getattr(slice, "start")); + int stop = parseAttr(getattr(slice, "stop")); + int step = parseAttr(getattr(slice, "step")); + + if(step == INT_MAX) step = 1; + if(step > 0) { + if(start == INT_MAX) start = 0; + if(stop == INT_MAX) stop = data.shape()[0]; + } else if(step < 0) { + if(start == INT_MAX) start = data.shape()[0] - 1; + if(stop == INT_MAX) stop = -(1 + data.shape()[0]); + } + if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(value)); + } else if constexpr(std::is_same_v) { + data.set_item(std::make_tuple(start, stop, step), (pkpy::numpy::adapt(value)).astype()); + } + } + + std::string to_string() const override { + std::ostringstream os; + os << data; + std::string result = os.str(); + + size_t pos = 0; + while ((pos = result.find('{', pos)) != std::string::npos) { + result.replace(pos, 1, "["); + pos += 1; + } + pos = 0; + while ((pos = result.find('}', pos)) != std::string::npos) { + result.replace(pos, 1, "]"); + pos += 1; + } + + if constexpr(std::is_same_v) { + size_t pos = 0; + while ((pos = result.find("true", pos)) != std::string::npos) { + result.replace(pos, 4, "True"); + pos += 4; + } + pos = 0; + while ((pos = result.find("false", pos)) != std::string::npos) { + result.replace(pos, 5, "False"); + pos += 5; + } + } + + for(int i = 0; i < result.size(); i++) { + if(result[i] == '\n') { + result.insert(i + 1, " "); + } + } + return result; + } +}; + diff --git a/include/pybind11/eigen.h b/include/pybind11/eigen.h new file mode 100644 index 0000000..3afe5a6 --- /dev/null +++ b/include/pybind11/eigen.h @@ -0,0 +1,202 @@ +#pragma once + +#include +#include +#include + +namespace pkbind { +namespace detail { + +// --- A) Eigen type detection traits --- + +template +struct is_eigen_dense : std::false_type {}; + +template +struct is_eigen_dense, T>>> + : std::true_type {}; + +template +constexpr bool is_eigen_dense_v = is_eigen_dense::value; + +template +struct is_eigen_ref : std::false_type {}; + +template +struct is_eigen_ref> : std::true_type {}; + +template +constexpr bool is_eigen_ref_v = is_eigen_ref::value; + +// --- B) Helper: try to load Eigen from ndarray_base --- + +template +bool try_load_eigen_from_ndarray(EigenType& out, const ndarray_base& base) { + using Scalar = typename EigenType::Scalar; + constexpr int RowsAtCompile = EigenType::RowsAtCompileTime; + constexpr int ColsAtCompile = EigenType::ColsAtCompileTime; + constexpr bool IsVector = EigenType::IsVectorAtCompileTime; + + auto* typed = dynamic_cast*>(&base); + if (!typed) return false; + + const auto& xarr = typed->data.get_array(); + const NdarrayScalar* ptr = xarr.data(); + auto shape = xarr.shape(); + int ndim = (int)xarr.dimension(); + + if constexpr (IsVector) { + // Accept 1D ndarray for Eigen vectors + if (ndim != 1) return false; + int size = (int)shape[0]; + + // Check compile-time size constraint + if constexpr (RowsAtCompile != Eigen::Dynamic) { + if (size != RowsAtCompile) return false; + } + if constexpr (ColsAtCompile != Eigen::Dynamic) { + if (ColsAtCompile != 1 && size != ColsAtCompile) return false; + } + + out.resize(size, 1); + for (int i = 0; i < size; ++i) { + out(i) = static_cast(static_cast(ptr[i])); + } + return true; + } else { + // Accept 2D ndarray for Eigen matrices + if (ndim != 2) return false; + int rows = (int)shape[0]; + int cols = (int)shape[1]; + + // Check compile-time dimension constraints (critical for overload resolution) + if constexpr (RowsAtCompile != Eigen::Dynamic) { + if (rows != RowsAtCompile) return false; + } + if constexpr (ColsAtCompile != Eigen::Dynamic) { + if (cols != ColsAtCompile) return false; + } + + out.resize(rows, cols); + // Copy element by element with cast (xtensor is row-major) + for (int i = 0; i < rows; ++i) { + for (int j = 0; j < cols; ++j) { + out(i, j) = static_cast(static_cast(ptr[i * cols + j])); + } + } + return true; + } +} + +// --- C) Helper: cast Eigen to Python ndarray --- + +template +pkbind::object eigen_to_python(const EigenType& mat) { + using Scalar = typename EigenType::Scalar; + constexpr bool IsVector = EigenType::IsVectorAtCompileTime; + + if constexpr (IsVector) { + int size = (int)mat.size(); + std::vector flat(size); + for (int i = 0; i < size; ++i) { + flat[i] = mat(i); + } + auto* result = new ::ndarray(flat); + return pkbind::cast(std::unique_ptr(result)); + } else { + int rows = (int)mat.rows(); + int cols = (int)mat.cols(); + std::vector> data(rows, std::vector(cols)); + for (int i = 0; i < rows; ++i) { + for (int j = 0; j < cols; ++j) { + data[i][j] = mat(i, j); + } + } + auto* result = new ::ndarray(data); + return pkbind::cast(std::unique_ptr(result)); + } +} + +} // namespace detail + +// --- D) type_caster for Eigen dense plain types (Matrix, Vector, Array) --- + +template +struct type_caster>> { + T data; + + template + static object cast(U&& value, return_value_policy, handle) { + return detail::eigen_to_python(std::forward(value)); + } + + bool load(handle src, bool convert) { + // Use pkbind's built-in type_caster for ndarray_base + type_caster base_caster; + if (!base_caster.load(src, false)) return false; + auto& base = base_caster.value(); + + // Try exact scalar match first (use ::qualified names to avoid pkbind:: types) + using Scalar = typename T::Scalar; + if constexpr (std::is_same_v) { + if (detail::try_load_eigen_from_ndarray(data, base)) return true; + if (detail::try_load_eigen_from_ndarray(data, base)) return true; + } else if constexpr (std::is_same_v) { + if (detail::try_load_eigen_from_ndarray(data, base)) return true; + if (detail::try_load_eigen_from_ndarray(data, base)) return true; + } else if constexpr (std::is_same_v) { + if (detail::try_load_eigen_from_ndarray(data, base)) return true; + if (detail::try_load_eigen_from_ndarray(data, base)) return true; + } else if constexpr (std::is_same_v) { + if (detail::try_load_eigen_from_ndarray(data, base)) return true; + if (detail::try_load_eigen_from_ndarray(data, base)) return true; + } + + // Try type-converting matches if convert is allowed + if (convert) { + if (detail::try_load_eigen_from_ndarray(data, base)) return true; + if (detail::try_load_eigen_from_ndarray(data, base)) return true; + if (detail::try_load_eigen_from_ndarray(data, base)) return true; + if (detail::try_load_eigen_from_ndarray(data, base)) return true; + if (detail::try_load_eigen_from_ndarray(data, base)) return true; + if (detail::try_load_eigen_from_ndarray(data, base)) return true; + } + + return false; + } + + T& value() { return data; } + + constexpr inline static bool is_temporary_v = true; +}; + +// --- E) type_caster for Eigen::Ref --- + +template +struct type_caster> { + using EigenRef = Eigen::Ref; + using PlainNoConst = std::remove_const_t; + + type_caster inner; + std::unique_ptr ref_storage; + + template + static object cast(U&& value, return_value_policy policy, handle parent) { + PlainNoConst plain = value; + return type_caster::cast(std::move(plain), policy, parent); + } + + bool load(handle src, bool convert) { + if (!inner.load(src, convert)) return false; + ref_storage = std::make_unique(inner.value()); + return true; + } + + EigenRef& value() { + return *ref_storage; + } + + constexpr inline static bool is_temporary_v = false; +}; + +} // namespace pkbind diff --git a/src/numpy.cpp b/src/numpy.cpp index bfa5427..3d9421c 100644 --- a/src/numpy.cpp +++ b/src/numpy.cpp @@ -1,2710 +1,7 @@ -#include -#include -#include -#include +#include +#include #include "rdp.hpp" -namespace py = pybind11; - -using bool_ = pkpy::bool_; -using int8 = pkpy::int8; -using int16 = pkpy::int16; -using int32 = pkpy::int32; -using int64 = pkpy::int64; -using int_ = pkpy::int_; -using float32 = pkpy::float32; -using float64 = pkpy::float64; -using float_ = pkpy::float_; - -// Function to parse attributes -int parseAttr(const py::object& obj) { - if(py::isinstance(obj)) { - return INT_MAX; - } else if(py::isinstance(obj)) { - return obj.cast(); - } else { - throw std::runtime_error("Unsupported type"); - } -}; - -class ndarray_base { -public: - virtual ~ndarray_base() = default; - - virtual int ndim() const = 0; - - virtual int size() const = 0; - - virtual std::string dtype() const = 0; - - virtual py::tuple shape() const = 0; - - virtual bool all() const = 0; - - virtual bool any() const = 0; - - virtual py::object sum() const = 0; - - virtual py::object sum_axis(int axis) const = 0; - - virtual py::object sum_axes(py::tuple axes) const = 0; - - virtual py::object prod() const = 0; - - virtual py::object prod_axis(int axis) const = 0; - - virtual py::object prod_axes(py::tuple axes) const = 0; - - virtual py::object min() const = 0; - - virtual py::object min_axis(int axis) const = 0; - - virtual py::object min_axes(py::tuple axes) const = 0; - - virtual py::object max() const = 0; - - virtual py::object max_axis(int axis) const = 0; - - virtual py::object max_axes(py::tuple axes) const = 0; - - virtual py::object mean() const = 0; - - virtual py::object mean_axis(int axis) const = 0; - - virtual py::object mean_axes(py::tuple axes) const = 0; - - virtual py::object std() const = 0; - - virtual py::object std_axis(int axis) const = 0; - - virtual py::object std_axes(py::tuple axes) const = 0; - - virtual py::object var() const = 0; - - virtual py::object var_axis(int axis) const = 0; - - virtual py::object var_axes(py::tuple axes) const = 0; - - virtual py::object argmin() const = 0; - - virtual ndarray_base* argmin_axis(int axis) const = 0; - - virtual py::object argmax() const = 0; - - virtual ndarray_base* argmax_axis(int axis) const = 0; - - virtual ndarray_base* argsort() const = 0; - - virtual ndarray_base* argsort_axis(int axis) const = 0; - - virtual void sort() = 0; - - virtual void sort_axis(int axis) = 0; - - virtual ndarray_base* reshape(const std::vector& shape) const = 0; - - virtual void resize(const std::vector& shape) = 0; - - virtual ndarray_base* squeeze() const = 0; - - virtual ndarray_base* squeeze_axis(int axis) const = 0; - - virtual ndarray_base* transpose() const = 0; - - virtual ndarray_base* transpose_tuple(py::tuple permutations) const = 0; - - virtual ndarray_base* transpose_args(py::args args) const = 0; - - virtual ndarray_base* repeat(int repeats, int axis) const = 0; - - virtual ndarray_base* repeat_axis(const std::vector& repeats, int axis) const = 0; - - virtual ndarray_base* round() const = 0; - - virtual ndarray_base* flatten() const = 0; - - virtual ndarray_base* copy() const = 0; - - virtual ndarray_base* astype(const std::string& dtype) const = 0; - - virtual py::list tolist() const = 0; - - virtual ndarray_base* eq(const ndarray_base& other) const = 0; - - virtual ndarray_base* ne(const ndarray_base& other) const = 0; - - virtual ndarray_base* add(const ndarray_base& other) const = 0; - - virtual ndarray_base* add_bool(bool_ other) const = 0; - - virtual ndarray_base* add_int(int_ other) const = 0; - - virtual ndarray_base* add_float(float64 other) const = 0; - - virtual ndarray_base* sub(const ndarray_base& other) const = 0; - - virtual ndarray_base* sub_int(int_ other) const = 0; - - virtual ndarray_base* sub_float(float64 other) const = 0; - - virtual ndarray_base* rsub_int(int_ other) const = 0; - - virtual ndarray_base* rsub_float(float64 other) const = 0; - - virtual ndarray_base* mul(const ndarray_base& other) const = 0; - - virtual ndarray_base* mul_bool(bool_ other) const = 0; - - virtual ndarray_base* mul_int(int_ other) const = 0; - - virtual ndarray_base* mul_float(float64 other) const = 0; - - virtual ndarray_base* div(const ndarray_base& other) const = 0; - - virtual ndarray_base* div_bool(bool_ other) const = 0; - - virtual ndarray_base* div_int(int_ other) const = 0; - - virtual ndarray_base* div_float(float64 other) const = 0; - - virtual ndarray_base* rdiv_bool(bool_ other) const = 0; - - virtual ndarray_base* rdiv_int(int_ other) const = 0; - - virtual ndarray_base* rdiv_float(float64 other) const = 0; - - virtual ndarray_base* matmul(const ndarray_base& other) const = 0; - - virtual ndarray_base* pow(const ndarray_base& other) const = 0; - - virtual ndarray_base* pow_int(int_ other) const = 0; - - virtual ndarray_base* pow_float(float64 other) const = 0; - - virtual ndarray_base* rpow_int(int_ other) const = 0; - - virtual ndarray_base* rpow_float(float64 other) const = 0; - - virtual ndarray_base* and_array(const ndarray_base& other) const = 0; - - virtual ndarray_base* and_bool(bool_ other) const = 0; - - virtual ndarray_base* and_int(int_ other) const = 0; - - virtual ndarray_base* or_array(const ndarray_base& other) const = 0; - - virtual ndarray_base* or_bool(bool_ other) const = 0; - - virtual ndarray_base* or_int(int_ other) const = 0; - - virtual ndarray_base* xor_array(const ndarray_base& other) const = 0; - - virtual ndarray_base* xor_bool(bool_ other) const = 0; - - virtual ndarray_base* xor_int(int_ other) const = 0; - - virtual ndarray_base* invert() const = 0; - - virtual py::object get_item_int(int index) const = 0; - - virtual py::object get_item_tuple(py::tuple indices) const = 0; - - virtual ndarray_base* get_item_vector(const std::vector& indices) const = 0; - - virtual ndarray_base* get_item_slice(py::slice slice) const = 0; - - virtual void set_item_int(int index, int_ value) = 0; - - virtual void set_item_index_int(int index, const std::vector& value) = 0; - - virtual void set_item_index_int_2d(int index, const std::vector>& value) = 0; - - virtual void set_item_index_int_3d(int index, const std::vector>>& value) = 0; - - virtual void set_item_index_int_4d(int index, const std::vector>>>& value) = 0; - - virtual void set_item_float(int index, float64 value) = 0; - - virtual void set_item_index_float(int index, const std::vector& value) = 0; - - virtual void set_item_index_float_2d(int index, const std::vector>& value) = 0; - - virtual void set_item_index_float_3d(int index, const std::vector>>& value) = 0; - - virtual void set_item_index_float_4d(int index, const std::vector>>>& value) = 0; - - virtual void set_item_tuple_int1(py::tuple args, int_ value) = 0; - - virtual void set_item_tuple_int2(py::tuple args, const std::vector& value) = 0; - - virtual void set_item_tuple_int3(py::tuple args, const std::vector>& value) = 0; - - virtual void set_item_tuple_int4(py::tuple args, const std::vector>>& value) = 0; - - virtual void set_item_tuple_int5(py::tuple args, const std::vector>>>& value) = 0; - - virtual void set_item_tuple_float1(py::tuple args, float64 value) = 0; - - virtual void set_item_tuple_float2(py::tuple args, const std::vector& value) = 0; - - virtual void set_item_tuple_float3(py::tuple args, const std::vector>& value) = 0; - - virtual void set_item_tuple_float4(py::tuple args, const std::vector>>& value) = 0; - - virtual void set_item_tuple_float5(py::tuple args, const std::vector>>>& value) = 0; - - virtual void set_item_vector_int1(const std::vector& indices, int_ value) = 0; - - virtual void set_item_vector_int2(const std::vector& indices, const std::vector& value) = 0; - - virtual void set_item_vector_int3(const std::vector& indices, const std::vector>& value) = 0; - - virtual void set_item_vector_int4(const std::vector& indices, const std::vector>>& value) = 0; - - virtual void set_item_vector_int5(const std::vector& indices, const std::vector>>>& value) = 0; - - virtual void set_item_vector_float1(const std::vector& indices, float64 value) = 0; - - virtual void set_item_vector_float2(const std::vector& indices, const std::vector& value) = 0; - - virtual void set_item_vector_float3(const std::vector& indices, const std::vector>& value) = 0; - - virtual void set_item_vector_float4(const std::vector& indices, const std::vector>>& value) = 0; - - virtual void set_item_vector_float5(const std::vector& indices, const std::vector>>>& value) = 0; - - virtual void set_item_slice_int1(py::slice slice, int_ value) = 0; - - virtual void set_item_slice_int2(py::slice slice, const std::vector& value) = 0; - - virtual void set_item_slice_int3(py::slice slice, const std::vector>& value) = 0; - - virtual void set_item_slice_int4(py::slice slice, const std::vector>>& value) = 0; - - virtual void set_item_slice_int5(py::slice slice, const std::vector>>>& value) = 0; - - virtual void set_item_slice_float1(py::slice slice, float64 value) = 0; - - virtual void set_item_slice_float2(py::slice slice, const std::vector& value) = 0; - - virtual void set_item_slice_float3(py::slice slice, const std::vector>& value) = 0; - - virtual void set_item_slice_float4(py::slice slice, const std::vector>>& value) = 0; - - virtual void set_item_slice_float5(py::slice slice, const std::vector>>>& value) = 0; - - virtual int len() const = 0; - - virtual std::string to_string() const = 0; -}; - -template -class ndarray : public ndarray_base { -public: - pkpy::numpy::ndarray data; - // Constructors - ndarray() = default; - - ndarray(const bool_ value) : data(value) {} - - ndarray(const int8 value) : data(value) {} - - ndarray(const int16 value) : data(value) {} - - ndarray(const int32 value) : data(value) {} - - ndarray(const int_ value) : data(static_cast(value)) {} - - ndarray(const float32 value) : data(value) {} - - ndarray(const float64 value) : data(static_cast(value)) {} - - ndarray(const pkpy::numpy::ndarray& _arr) : data(_arr) {} - - ndarray(const std::vector& init_list) : data(pkpy::numpy::adapt(init_list)) {} - - ndarray(const std::vector>& init_list) : data(pkpy::numpy::adapt(init_list)) {} - - ndarray(const std::vector>>& init_list) : data(pkpy::numpy::adapt(init_list)) {} - - ndarray(const std::vector>>>& init_list) : - data(pkpy::numpy::adapt(init_list)) {} - - ndarray(const std::vector>>>>& init_list) : - data(pkpy::numpy::adapt(init_list)) {} - - // Properties - int ndim() const override { return data.ndim(); } - - int size() const override { return data.size(); } - - std::string dtype() const override { return data.dtype(); } - - py::tuple shape() const override { return py::cast(data.shape()); } - - // Boolean Functions - bool all() const override { return data.all(); } - - bool any() const override { return data.any(); } - - // Aggregation Functions - py::object sum() const override { - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v) { - return py::int_(data.sum()); - } else if constexpr(std::is_same_v || std::is_same_v) { - return py::float_(data.sum()); - } else { - throw std::runtime_error("Unsupported type"); - } - } - - py::object sum_axis(int axis) const override { - if ((data.sum(axis)).ndim() == 0) { - return py::cast((data.sum(axis))()); - } else { - return py::cast(ndarray(data.sum(axis))); - } - } - - py::object sum_axes(py::tuple axes) const override { - std::vector axes_; - for(auto item: axes) { - axes_.push_back(py::cast(item)); - } - if ((data.sum(axes_)).ndim() == 0) { - return py::cast((data.sum(axes_))()); - } else { - return py::cast(ndarray(data.sum(axes_))); - } - } - - py::object prod() const override { - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v) { - return py::int_(data.prod()); - } else if constexpr(std::is_same_v || std::is_same_v) { - return py::float_(data.prod()); - } else { - throw std::runtime_error("Unsupported type"); - } - } - - py::object prod_axis(int axis) const override { - if ((data.prod(axis)).ndim() == 0) { - return py::cast((data.prod(axis))()); - } else { - return py::cast(ndarray(data.prod(axis))); - } - } - - py::object prod_axes(py::tuple axes) const override { - std::vector axes_; - for(auto item: axes) { - axes_.push_back(py::cast(item)); - } - if ((data.prod(axes_)).ndim() == 0) { - return py::cast((data.prod(axes_))()); - } else { - return py::cast(ndarray(data.prod(axes_))); - } - } - - py::object min() const override { - if constexpr (std::is_same_v) { - return py::bool_(data.min()); - } else if constexpr (std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v) { - return py::int_(data.min()); - } else if constexpr(std::is_same_v || std::is_same_v) { - return py::float_(data.min()); - } else { - throw std::runtime_error("Unsupported type"); - } - } - - py::object min_axis(int axis) const override { - if ((data.min(axis)).ndim() == 0) { - return py::cast((data.min(axis))()); - } else { - return py::cast(ndarray(data.min(axis))); - } - - } - - py::object min_axes(py::tuple axes) const override { - std::vector axes_; - for(auto item: axes) { - axes_.push_back(py::cast(item)); - } - if ((data.min(axes_)).ndim() == 0) { - return py::cast((data.min(axes_))()); - } else { - return py::cast(ndarray(data.min(axes_))); - } - } - - py::object max() const override { - if constexpr (std::is_same_v) { - return py::bool_(data.max()); - } else if constexpr (std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v) { - return py::int_(data.max()); - } else if constexpr(std::is_same_v || std::is_same_v) { - return py::float_(data.max()); - } else { - throw std::runtime_error("Unsupported type"); - } - } - - py::object max_axis(int axis) const override { - if ((data.max(axis)).ndim() == 0) { - return py::cast((data.max(axis))()); - } else { - return py::cast(ndarray(data.max(axis))); - } - } - - py::object max_axes(py::tuple axes) const override { - std::vector axes_; - for(auto item: axes) { - axes_.push_back(py::cast(item)); - } - if ((data.max(axes_)).ndim() == 0) { - return py::cast((data.max(axes_))()); - } else { - return py::cast(ndarray(data.max(axes_))); - } - } - - py::object mean() const override { - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v || std::is_same_v || - std::is_same_v) { - return py::float_(data.mean()); - } else { - throw std::runtime_error("Unsupported type"); - } - } - - py::object mean_axis(int axis) const override { - if ((data.mean(axis)).ndim() == 0) { - return py::cast((data.mean(axis))()); - } else { - return py::cast(ndarray(data.mean(axis))); - } - } - - py::object mean_axes(py::tuple axes) const override { - std::vector axes_; - for(auto item: axes) - axes_.push_back(py::cast(item)); - if ((data.mean(axes_)).ndim() == 0) { - return py::cast((data.mean(axes_))()); - } else { - return py::cast(ndarray(data.mean(axes_))); - } - } - - py::object std() const override { - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v || std::is_same_v || - std::is_same_v) { - return py::float_(data.std()); - } else { - throw std::runtime_error("Unsupported type"); - } - } - - py::object std_axis(int axis) const override { - if ((data.std(axis)).ndim() == 0) { - return py::cast((data.std(axis))()); - } else { - return py::cast(ndarray(data.std(axis))); - } - } - - py::object std_axes(py::tuple axes) const override { - std::vector axes_; - for(auto item: axes) - axes_.push_back(py::cast(item)); - if ((data.std(axes_)).ndim() == 0) { - return py::cast((data.std(axes_))()); - } else { - return py::cast(ndarray(data.std(axes_))); - } - } - - py::object var() const override { - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v || std::is_same_v || - std::is_same_v) { - return py::float_(data.var()); - } else { - throw std::runtime_error("Unsupported type"); - } - } - - py::object var_axis(int axis) const override { - if ((data.var(axis)).ndim() == 0) { - return py::cast((data.var(axis))()); - } else { - return py::cast(ndarray(data.var(axis))); - } - } - - py::object var_axes(py::tuple axes) const override { - std::vector axes_; - for(auto item: axes) - axes_.push_back(py::cast(item)); - if ((data.var(axes_)).ndim() == 0) { - return py::cast((data.var(axes_))()); - } else { - return py::cast(ndarray(data.var(axes_))); - } - } - - py::object argmin() const override { - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v) { - return py::int_(data.argmin()); - } else if constexpr(std::is_same_v || std::is_same_v) { - return py::int_(data.argmin()); - } else { - throw std::runtime_error("Unsupported type"); - } - } - - ndarray_base* argmin_axis(int axis) const override { return new ndarray(data.argmin(axis)); } - - py::object argmax() const override { - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v) { - return py::int_(data.argmax()); - } else if constexpr(std::is_same_v || std::is_same_v) { - return py::int_(data.argmax()); - } else { - throw std::runtime_error("Unsupported type"); - } - } - - ndarray_base* argmax_axis(int axis) const override { return new ndarray(data.argmax(axis)); } - - ndarray_base* argsort() const override { return new ndarray(data.argsort()); } - - ndarray_base* argsort_axis(int axis) const override { return new ndarray(data.argsort(axis)); } - - void sort() override { data = data.sort(); } - - void sort_axis(int axis) override { data = data.sort(axis); } - - ndarray_base* reshape(const std::vector& shape) const override { return new ndarray(data.reshape(shape)); } - - void resize(const std::vector& shape) override { data = data.resize(shape); } - - ndarray_base* squeeze() const override { return new ndarray(data.squeeze()); } - - ndarray_base* squeeze_axis(int axis) const override { return new ndarray(data.squeeze(axis)); } - - ndarray_base* transpose() const override { return new ndarray(data.transpose()); } - - ndarray_base* transpose_tuple(py::tuple permutations) const override { - std::vector perm; - for(auto item: permutations) - perm.push_back(py::cast(item)); - return new ndarray(data.transpose(perm)); - } - - ndarray_base* transpose_args(py::args args) const override { - std::vector perm; - for(auto item: args) - perm.push_back(py::cast(item)); - return new ndarray(data.transpose(perm)); - } - - ndarray_base* repeat(int repeats, int axis) const override { - if (axis == INT_MAX) { - return new ndarray(data.repeat(repeats, data.ndim() - 1)); - } - return new ndarray(data.repeat(repeats, axis)); - } - - ndarray_base* repeat_axis(const std::vector& repeats, int axis) const override { - return new ndarray(data.repeat(repeats, axis)); - } - - ndarray_base* round() const override { return new ndarray(data.round()); } - - ndarray_base* flatten() const override { return new ndarray(data.flatten()); } - - ndarray_base* copy() const override { return new ndarray(data.copy()); } - - ndarray_base* astype(const std::string& dtype) const override { - if(dtype == "bool_") { - return new ndarray(data.template astype()); - } else if(dtype == "int8") { - return new ndarray(data.template astype()); - } else if(dtype == "int16") { - return new ndarray(data.template astype()); - } else if(dtype == "int32") { - return new ndarray(data.template astype()); - } else if(dtype == "int_") { - return new ndarray(data.template astype()); - } else if(dtype == "float32") { - return new ndarray(data.template astype()); - } else if(dtype == "float64") { - return new ndarray(data.template astype()); - } else { - throw std::invalid_argument("Invalid dtype"); - } - } - - py::list tolist() const override { - py::list list; - if(data.ndim() == 1) { - return py::cast(data.to_list()); - } else { - for(int i = 0; i < data.shape()[0]; i++) { - list.append(ndarray(data[i]).tolist()); - } - } - return list; - } - - // Dunder Methods - ndarray_base* eq(const ndarray_base& other) const override { - if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int8 == int8 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 == int16 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 == int32 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 == int64 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 == float32 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 == float64 */ - return new ndarray(data == p->data); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int16 == int8 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 == int16 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 == int32 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 == int64 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 == float32 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 == float64 */ - return new ndarray(data == p->data); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int32 == int8 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 == int16 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 == int32 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 == int64 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 == float32 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 == float64 */ - return new ndarray(data == p->data); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int64 == int8 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int64 == int16 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int64 == int32 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int64 == int64 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int64 == float32 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int64 == float64 */ - return new ndarray(data == p->data); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* float32 == int8 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float32 == int16 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float32 == int32 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float32 == int64 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float32 == float32 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float32 == float64 */ - return new ndarray(data == p->data); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* float64 == int8 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float64 == int16 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float64 == int32 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float64 == int64 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float64 == float32 */ - return new ndarray(data == p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float64 == float64 */ - return new ndarray(data == p->data); - } - } - - const ndarray& other_ = dynamic_cast&>(other); - return new ndarray(data == other_.data); - } - - ndarray_base* ne(const ndarray_base& other) const override { - if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int8 != int8 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 != int16 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 != int32 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 != int64 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 != float32 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 != float64 */ - return new ndarray(data != p->data); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int16 != int8 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 != int16 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 != int32 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 != int64 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 != float32 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 != float64 */ - return new ndarray(data != p->data); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int32 != int8 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 != int16 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 != int32 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 != int64 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 != float32 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 != float64 */ - return new ndarray(data != p->data); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int64 != int8 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int64 != int16 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int64 != int32 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int64 != int64 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int64 != float32 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int64 != float64 */ - return new ndarray(data != p->data); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* float32 != int8 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float32 != int16 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float32 != int32 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float32 != int64 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float32 != float32 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float32 != float64 */ - return new ndarray(data != p->data); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* float64 != int8 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float64 != int16 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float64 != int32 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float64 != int64 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float64 != float32 */ - return new ndarray(data != p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* float64 != float64 */ - return new ndarray(data != p->data); - } - } - - const ndarray& other_ = dynamic_cast&>(other); - return new ndarray(data != other_.data); - } - - ndarray_base* add(const ndarray_base& other) const override { - if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int8 + int8 */ - return new ndarray(data + p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 + int16 */ - return new ndarray((data + p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 + int32 */ - return new ndarray(data + p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 + int64 */ - return new ndarray(data + p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 + float32 */ - return new ndarray(data + p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 + float64 */ - return new ndarray(data + p->data); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int16 + int8 */ - return new ndarray((data + p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 + int16 */ - return new ndarray(data + p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 + int32 */ - return new ndarray(data + p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 + int64 */ - return new ndarray(data + p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 + float32 */ - return new ndarray(data + p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 + float64 */ - return new ndarray(data + p->data); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int32 + int8 */ - return new ndarray(data + p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 + int16 */ - return new ndarray(data + p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 + int32 */ - return new ndarray(data + p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 + int64 */ - return new ndarray(data + p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 + float32 */ - return new ndarray(data + p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 + float64 */ - return new ndarray(data + p->data); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* int64 + int8 */ - return new ndarray(data + p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 + int16 */ - return new ndarray(data + p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 + int32 */ - return new ndarray(data + p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 + int64 */ - return new ndarray(data + p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 + float32 */ - return new ndarray(data + p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 + float64 */ - return new ndarray(data + p->data); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* float32 + int8 */ - return new ndarray(data + p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 + int16 */ - return new ndarray(data + p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 + int32 */ - return new ndarray(data + p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 + int64 */ - return new ndarray(data + p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 + float32 */ - return new ndarray(data + p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 + float64 */ - return new ndarray(data + p->data); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* float64 + int8 */ - return new ndarray(data + p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 + int16 */ - return new ndarray(data + p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 + int32 */ - return new ndarray(data + p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 + int64 */ - return new ndarray(data + p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 + float32 */ - return new ndarray(data + p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 + float64 */ - return new ndarray(data + p->data); - } - } - - const ndarray& other_ = dynamic_cast&>(other); - return new ndarray(data + other_.data); - } - - ndarray_base* add_bool(bool_ other) const override { - if constexpr(std::is_same_v) { - return new ndarray((data + other).template astype()); - } else if constexpr(std::is_same_v) { - return new ndarray((data + other).template astype()); - } else { - return new ndarray(data + other); - } - } - - ndarray_base* add_int(int_ other) const override { - if constexpr(std::is_same_v) { - return new ndarray(data + other); - } else if constexpr(std::is_same_v) { - return new ndarray((data + other).template astype()); - } else if constexpr(std::is_same_v) { - return new ndarray((data + other).template astype()); - } else if constexpr(std::is_same_v) { - return new ndarray((data + other).template astype()); - } else if constexpr(std::is_same_v) { - return new ndarray(data + other); - } else if constexpr(std::is_same_v) { - return new ndarray(data + other); - } else if constexpr(std::is_same_v) { - return new ndarray(data + other); - } - } - - ndarray_base* add_float(float64 other) const override { return new ndarray(data + other); } - - ndarray_base* sub(const ndarray_base& other) const override { - if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int8 - int8 */ - return new ndarray(data - p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 - int16 */ - return new ndarray((data - p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 - int32 */ - return new ndarray(data - p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 - int64 */ - return new ndarray(data - p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 - float32 */ - return new ndarray(data - p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 - float64 */ - return new ndarray(data - p->data); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int16 - int8 */ - return new ndarray((data - p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 - int16 */ - return new ndarray(data - p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 - int32 */ - return new ndarray(data - p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 - int64 */ - return new ndarray(data - p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 - float32 */ - return new ndarray(data - p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 - float64 */ - return new ndarray(data - p->data); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int32 - int8 */ - return new ndarray(data - p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 - int16 */ - return new ndarray(data - p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 - int32 */ - return new ndarray(data - p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 - int64 */ - return new ndarray(data - p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 - float32 */ - return new ndarray(data - p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 - float64 */ - return new ndarray(data - p->data); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* int64 - int8 */ - return new ndarray(data - p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 - int16 */ - return new ndarray(data - p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 - int32 */ - return new ndarray(data - p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 - int64 */ - return new ndarray(data - p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 - float32 */ - return new ndarray(data - p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 - float64 */ - return new ndarray(data - p->data); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* float32 - int8 */ - return new ndarray(data - p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 - int16 */ - return new ndarray(data - p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 - int32 */ - return new ndarray(data - p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 - int64 */ - return new ndarray(data - p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 - float32 */ - return new ndarray(data - p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 - float64 */ - return new ndarray(data - p->data); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* float64 - int8 */ - return new ndarray(data - p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 - int16 */ - return new ndarray(data - p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 - int32 */ - return new ndarray(data - p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 - int64 */ - return new ndarray(data - p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 - float32 */ - return new ndarray(data - p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 - float64 */ - return new ndarray(data - p->data); - } - } - - const ndarray& other_ = dynamic_cast&>(other); - return new ndarray(data - other_.data); - } - - ndarray_base* sub_int(int_ other) const override { - if constexpr(std::is_same_v) { - return new ndarray(data - other); - } else if constexpr(std::is_same_v) { - return new ndarray((data - other).template astype()); - } else if constexpr(std::is_same_v) { - return new ndarray((data - other).template astype()); - } else if constexpr(std::is_same_v) { - return new ndarray((data - other).template astype()); - } else if constexpr(std::is_same_v) { - return new ndarray(data - other); - } else if constexpr(std::is_same_v) { - return new ndarray(data - other); - } else if constexpr(std::is_same_v) { - return new ndarray(data - other); - } - } - - ndarray_base* sub_float(float64 other) const override { return new ndarray(data - other); } - - ndarray_base* rsub_int(int_ other) const override { - if constexpr(std::is_same_v) { - return new ndarray(other - data); - } else if constexpr(std::is_same_v) { - return new ndarray((other - data).template astype()); - } else if constexpr(std::is_same_v) { - return new ndarray((other - data).template astype()); - } else if constexpr(std::is_same_v) { - return new ndarray((other - data).template astype()); - } else if constexpr(std::is_same_v) { - return new ndarray(other - data); - } else if constexpr(std::is_same_v) { - return new ndarray(other - data); - } else if constexpr(std::is_same_v) { - return new ndarray(other - data); - } - } - - ndarray_base* rsub_float(float64 other) const override { return new ndarray(other - data); } - - ndarray_base* mul(const ndarray_base& other) const override { - if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int8 * int8 */ - return new ndarray(data * p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 * int16 */ - return new ndarray((data * p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 * int32 */ - return new ndarray(data * p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 * int64 */ - return new ndarray(data * p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 * float32 */ - return new ndarray(data * p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 * float64 */ - return new ndarray(data * p->data); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int16 * int8 */ - return new ndarray((data * p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 * int16 */ - return new ndarray(data * p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 * int32 */ - return new ndarray(data * p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 * int64 */ - return new ndarray(data * p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 * float32 */ - return new ndarray(data * p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 * float64 */ - return new ndarray(data * p->data); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int32 * int8 */ - return new ndarray(data * p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 * int16 */ - return new ndarray(data * p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 * int32 */ - return new ndarray(data * p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 * int64 */ - return new ndarray(data * p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 * float32 */ - return new ndarray(data * p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 * float64 */ - return new ndarray(data * p->data); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* int64 * int8 */ - return new ndarray(data * p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 * int16 */ - return new ndarray(data * p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 * int32 */ - return new ndarray(data * p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 * int64 */ - return new ndarray(data * p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 * float32 */ - return new ndarray(data * p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 * float64 */ - return new ndarray(data * p->data); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* float32 * int8 */ - return new ndarray(data * p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 * int16 */ - return new ndarray(data * p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 * int32 */ - return new ndarray(data * p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 * int64 */ - return new ndarray(data * p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 * float32 */ - return new ndarray(data * p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 * float64 */ - return new ndarray(data * p->data); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* float64 * int8 */ - return new ndarray(data * p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 * int16 */ - return new ndarray(data * p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 * int32 */ - return new ndarray(data * p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 * int64 */ - return new ndarray(data * p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 * float32 */ - return new ndarray(data * p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 * float64 */ - return new ndarray(data * p->data); - } - } - - const ndarray& other_ = dynamic_cast&>(other); - return new ndarray(data * other_.data); - } - - ndarray_base* mul_bool(bool_ other) const override { - if constexpr(std::is_same_v) { - return new ndarray((data * other).template astype()); - } else if constexpr(std::is_same_v) { - return new ndarray((data * other).template astype()); - } else { - return new ndarray(data * other); - } - } - - ndarray_base* mul_int(int_ other) const override { - if constexpr(std::is_same_v) { - return new ndarray(data * other); - } else if constexpr(std::is_same_v) { - return new ndarray((data * other).template astype()); - } else if constexpr(std::is_same_v) { - return new ndarray((data * other).template astype()); - } else if constexpr(std::is_same_v) { - return new ndarray((data * other).template astype()); - } else if constexpr(std::is_same_v) { - return new ndarray(data * other); - } else if constexpr(std::is_same_v) { - return new ndarray(data * other); - } else if constexpr(std::is_same_v) { - return new ndarray(data * other); - } - } - - ndarray_base* mul_float(float64 other) const override { return new ndarray(data * other); } - - ndarray_base* div(const ndarray_base& other) const override { - if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* bool / bool */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* bool / int8 */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* bool / int16 */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* bool / int32 */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* bool / int64 */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* bool / float32 */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* bool / float64 */ - return new ndarray(data / p->data); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* int8 / bool */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 / int8 */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 / int16 */ - return new ndarray((data / p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 / int32 */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 / int64 */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 / float32 */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 / float64 */ - return new ndarray(data / p->data); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* int16 / bool */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 / int8 */ - return new ndarray((data / p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 / int16 */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 / int32 */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 / int64 */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 / float32 */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 / float64 */ - return new ndarray(data / p->data); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* int32 / bool */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 / int8 */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 / int16 */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 / int32 */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 / int64 */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 / float32 */ - return new ndarray(data / p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 / float64 */ - return new ndarray(data / p->data); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* int64 / bool */ - return new ndarray(data / p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 / int8 */ - return new ndarray(data / p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 / int16 */ - return new ndarray(data / p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 / int32 */ - return new ndarray(data / p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 / int64 */ - return new ndarray(data / p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 / float32 */ - return new ndarray(data / p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 / float64 */ - return new ndarray(data / p->data); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* float32 / bool */ - return new ndarray(data / p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 / int8 */ - return new ndarray(data / p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 / int16 */ - return new ndarray(data / p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 / int32 */ - return new ndarray(data / p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 / int64 */ - return new ndarray(data / p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 / float32 */ - return new ndarray(data / p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 / float64 */ - return new ndarray(data / p->data); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* float64 / bool */ - return new ndarray(data / p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 / int8 */ - return new ndarray(data / p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 / int16 */ - return new ndarray(data / p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 / int32 */ - return new ndarray(data / p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 / int64 */ - return new ndarray(data / p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 / float32 */ - return new ndarray(data / p->data); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 / float64 */ - return new ndarray(data / p->data); - } - } - - const ndarray& other_ = dynamic_cast&>(other); - return new ndarray(data / other_.data); - } - - ndarray_base* div_bool(bool_ other) const override { return new ndarray(data / other); } - - ndarray_base* div_int(int_ other) const override { return new ndarray(data / other); } - - ndarray_base* div_float(float64 other) const override { return new ndarray(data / other); } - - ndarray_base* rdiv_bool(bool_ other) const override { return new ndarray(other / data); } - - ndarray_base* rdiv_int(int_ other) const override { return new ndarray(other / data); } - - ndarray_base* rdiv_float(float64 other) const override { return new ndarray(other / data); } - - ndarray_base* matmul(const ndarray_base& other) const override { - if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int8 @ int8 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 @ int16 */ - return new ndarray(pkpy::numpy::matmul(data, p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 @ int32 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 @ int64 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 @ float32 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 @ float64 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int16 @ int8 */ - return new ndarray(pkpy::numpy::matmul(data, p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 @ int16 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 @ int32 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 @ int64 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 @ float32 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 @ float64 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int32 @ int8 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 @ int16 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 @ int32 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 @ int64 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 @ float32 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 @ float64 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* int64 @ int8 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 @ int16 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 @ int32 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 @ int64 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 @ float32 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 @ float64 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* float32 @ int8 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 @ int16 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 @ int32 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 @ int64 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 @ float32 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 @ float64 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* float64 @ int8 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 @ int16 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 @ int32 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 @ int64 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 @ float32 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 @ float64 */ - return new ndarray(pkpy::numpy::matmul(data, p->data)); - } - } - - const ndarray& other_ = dynamic_cast&>(other); - return new ndarray(pkpy::numpy::matmul(data, other_.data)); - } - - ndarray_base* pow(const ndarray_base& other) const override { - if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int8 ** int8 */ - return new ndarray(data.pow(p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 ** int16 */ - return new ndarray(data.pow(p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 ** int32 */ - return new ndarray(data.pow(p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 ** int64 */ - return new ndarray(data.pow(p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 ** float32 */ - return new ndarray(data.pow(p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 ** float64 */ - return new ndarray(data.pow(p->data)); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int16 ** int8 */ - return new ndarray(data.pow(p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 ** int16 */ - return new ndarray(data.pow(p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 ** int32 */ - return new ndarray(data.pow(p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 ** int64 */ - return new ndarray(data.pow(p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 ** float32 */ - return new ndarray(data.pow(p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 ** float64 */ - return new ndarray(data.pow(p->data)); - } - } else if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int32 ** int8 */ - return new ndarray(data.pow(p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 ** int16 */ - return new ndarray(data.pow(p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 ** int32 */ - return new ndarray(data.pow(p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 ** int64 */ - return new ndarray(data.pow(p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 ** float32 */ - return new ndarray(data.pow(p->data)); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 ** float64 */ - return new ndarray(data.pow(p->data)); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* int64 ** int8 */ - return new ndarray(data.pow(p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 ** int16 */ - return new ndarray(data.pow(p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 ** int32 */ - return new ndarray(data.pow(p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 ** int64 */ - return new ndarray(data.pow(p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 ** float32 */ - return new ndarray(data.pow(p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* int64 ** float64 */ - return new ndarray(data.pow(p->data)); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* float32 ** int8 */ - return new ndarray(data.pow(p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 ** int16 */ - return new ndarray(data.pow(p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 ** int32 */ - return new ndarray(data.pow(p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 ** int64 */ - return new ndarray(data.pow(p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 ** float32 */ - return new ndarray(data.pow(p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float32 ** float64 */ - return new ndarray(data.pow(p->data)); - } - } else if constexpr(std::is_same_v) { - if (auto p = dynamic_cast*>(&other)) { /* float64 ** int8 */ - return new ndarray(data.pow(p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 ** int16 */ - return new ndarray(data.pow(p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 ** int32 */ - return new ndarray(data.pow(p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 ** int64 */ - return new ndarray(data.pow(p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 ** float32 */ - return new ndarray(data.pow(p->data)); - } else if (auto p = dynamic_cast*>(&other)) { /* float64 ** float64 */ - return new ndarray(data.pow(p->data)); - } - } - - const ndarray& other_ = dynamic_cast&>(other); - return new ndarray(data.pow(other_.data)); - } - - ndarray_base* pow_int(int_ other) const override { return new ndarray(data.pow(other)); } - - ndarray_base* pow_float(float64 other) const override { return new ndarray(data.pow(other)); } - - ndarray_base* rpow_int(int_ other) const override { return new ndarray(pkpy::numpy::pow(other, data)); } - - ndarray_base* rpow_float(float64 other) const override { - return new ndarray(pkpy::numpy::pow(other, data)); - } - - int len() const override { return data.shape()[0]; } - - ndarray_base* and_array(const ndarray_base& other) const override { - if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* bool & bool */ - return new ndarray(data & p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* bool & int8 */ - return new ndarray((data & p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* bool & int16 */ - return new ndarray((data & p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* bool & int32 */ - return new ndarray((data & p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* bool & int64 */ - return new ndarray((data & p->data).template astype()); - } - } else if constexpr (std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int8 & bool */ - return new ndarray(data & p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 & int8 */ - return new ndarray(data & p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 & int16 */ - return new ndarray((data & p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 & int32 */ - return new ndarray((data & p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 & int64 */ - return new ndarray((data & p->data).template astype()); - } - } else if constexpr (std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int16 & bool */ - return new ndarray(data & p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 & int8 */ - return new ndarray(data & p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 & int16 */ - return new ndarray(data & p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 & int32 */ - return new ndarray((data & p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* int16 & int64 */ - return new ndarray((data & p->data).template astype()); - } - } else if constexpr (std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int32 & bool */ - return new ndarray(data & p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 & int8 */ - return new ndarray(data & p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 & int16 */ - return new ndarray(data & p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 & int32 */ - return new ndarray(data & p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int32 & int64 */ - return new ndarray((data & p->data).template astype()); - } - } else if constexpr (std::is_same_v) { - if (auto p = dynamic_cast *>(&other)) { /* int64 & bool */ - return new ndarray(data & p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int64 & int8 */ - return new ndarray(data & p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int64 & int16 */ - return new ndarray(data & p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int64 & int32 */ - return new ndarray(data & p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int64 & int64 */ - return new ndarray(data & p->data); - } - } - - throw std::runtime_error("& operator is not compatible with floating types"); - } - - ndarray_base* and_bool(bool_ other) const override { - if constexpr(std::is_same_v) { - return new ndarray(data & other); - } else if constexpr(std::is_same_v) { - return new ndarray(data & other); - } else if constexpr(std::is_same_v) { - return new ndarray(data & other); - } else if constexpr(std::is_same_v) { - return new ndarray(data & other); - } else if constexpr(std::is_same_v) { - return new ndarray(data & other); - } - - throw std::runtime_error("& operator is not compatible with floating types"); - } - - ndarray_base* and_int(int_ other) const override { - if constexpr(std::is_same_v) { - return new ndarray((data & other).template astype()); - } else if constexpr(std::is_same_v) { - return new ndarray(data & other); - } else if constexpr(std::is_same_v) { - return new ndarray(data & other); - } else if constexpr(std::is_same_v) { - return new ndarray(data & other); - } else if constexpr(std::is_same_v) { - return new ndarray(data & other); - } - - throw std::runtime_error("& operator is not compatible with floating types"); - } - - ndarray_base* or_array(const ndarray_base& other) const override { - if constexpr(std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* bool | bool */ - return new ndarray(data | p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* bool | int8 */ - return new ndarray((data | p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* bool | int16 */ - return new ndarray((data | p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* bool | int32 */ - return new ndarray((data | p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* bool | int64 */ - return new ndarray((data | p->data).template astype()); - } - } else if constexpr (std::is_same_v) { - if(auto p = dynamic_cast*>(&other)) { /* int8 | bool */ - return new ndarray(data | p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 | int8 */ - return new ndarray(data | p->data); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 | int16 */ - return new ndarray((data | p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 | int32 */ - return new ndarray((data | p->data).template astype()); - } else if(auto p = dynamic_cast*>(&other)) { /* int8 | int64 */ - return new ndarray((data | p->data).template astype()); - } - } else if constexpr (std::is_same_v) { - if (auto p = dynamic_cast *>(&other)) { /* int16 | bool */ - return new ndarray(data | p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int16 | int8 */ - return new ndarray(data | p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int16 | int16 */ - return new ndarray(data | p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int16 | int32 */ - return new ndarray((data | p->data).template astype()); - } else if (auto p = dynamic_cast *>(&other)) { /* int16 | int64 */ - return new ndarray((data | p->data).template astype()); - } - } else if constexpr (std::is_same_v) { - if (auto p = dynamic_cast *>(&other)) { /* int32 | bool */ - return new ndarray(data | p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int32 | int8 */ - return new ndarray(data | p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int32 | int16 */ - return new ndarray(data | p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int32 | int32 */ - return new ndarray(data | p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int32 | int64 */ - return new ndarray((data | p->data).template astype()); - } - } else if constexpr (std::is_same_v) { - if (auto p = dynamic_cast *>(&other)) { /* int64 | bool */ - return new ndarray(data | p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int64 | int8 */ - return new ndarray(data | p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int64 | int16 */ - return new ndarray(data | p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int64 | int32 */ - return new ndarray(data | p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int64 | int64 */ - return new ndarray(data | p->data); - } - } - - throw std::runtime_error("| operator is not compatible with floating types"); - } - - ndarray_base* or_bool(bool_ other) const override { - if constexpr(std::is_same_v) { - return new ndarray(data | other); - } else if constexpr(std::is_same_v) { - return new ndarray(data | other); - } else if constexpr(std::is_same_v) { - return new ndarray(data | other); - } else if constexpr(std::is_same_v) { - return new ndarray(data | other); - } else if constexpr(std::is_same_v) { - return new ndarray(data | other); - } - - throw std::runtime_error("| operator is not compatible with floating types"); - } - - ndarray_base* or_int(int_ other) const override { - if constexpr(std::is_same_v) { - return new ndarray((data | other).template astype()); - } else if constexpr(std::is_same_v) { - return new ndarray(data | other); - } else if constexpr(std::is_same_v) { - return new ndarray(data | other); - } else if constexpr(std::is_same_v) { - return new ndarray(data | other); - } else if constexpr(std::is_same_v) { - return new ndarray(data | other); - } - - throw std::runtime_error("| operator is not compatible with floating types"); - } - - ndarray_base* xor_array(const ndarray_base& other) const override { - if constexpr (std::is_same_v) { - if (auto p = dynamic_cast *>(&other)) { /* bool ^ bool */ - return new ndarray(data ^ p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* bool ^ int8 */ - return new ndarray((data ^ p->data).template astype()); - } else if (auto p = dynamic_cast *>(&other)) { /* bool ^ int16 */ - return new ndarray((data ^ p->data).template astype()); - } else if (auto p = dynamic_cast *>(&other)) { /* bool ^ int32 */ - return new ndarray((data ^ p->data).template astype()); - } else if (auto p = dynamic_cast *>(&other)) { /* bool ^ int64 */ - return new ndarray((data ^ p->data).template astype()); - } - } else if constexpr (std::is_same_v) { - if (auto p = dynamic_cast *>(&other)) { /* int8 ^ bool */ - return new ndarray(data ^ p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int8 ^ int8 */ - return new ndarray(data ^ p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int8 ^ int16 */ - return new ndarray((data ^ p->data).template astype()); - } else if (auto p = dynamic_cast *>(&other)) { /* int8 ^ int32 */ - return new ndarray((data ^ p->data).template astype()); - } else if (auto p = dynamic_cast *>(&other)) { /* int8 ^ int64 */ - return new ndarray((data ^ p->data).template astype()); - } - } else if constexpr (std::is_same_v) { - if (auto p = dynamic_cast *>(&other)) { /* int16 ^ bool */ - return new ndarray(data ^ p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int16 ^ int8 */ - return new ndarray(data ^ p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int16 ^ int16 */ - return new ndarray(data ^ p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int16 ^ int32 */ - return new ndarray((data ^ p->data).template astype()); - } else if (auto p = dynamic_cast *>(&other)) { /* int16 ^ int64 */ - return new ndarray((data ^ p->data).template astype()); - } - } else if constexpr (std::is_same_v) { - if (auto p = dynamic_cast *>(&other)) { /* int32 ^ bool */ - return new ndarray(data ^ p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int32 ^ int8 */ - return new ndarray(data ^ p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int32 ^ int16 */ - return new ndarray(data ^ p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int32 ^ int32 */ - return new ndarray(data ^ p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int32 ^ int64 */ - return new ndarray((data ^ p->data).template astype()); - } - } else if constexpr (std::is_same_v) { - if (auto p = dynamic_cast *>(&other)) { /* int64 ^ bool */ - return new ndarray(data ^ p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int64 ^ int8 */ - return new ndarray(data ^ p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int64 ^ int16 */ - return new ndarray(data ^ p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int64 ^ int32 */ - return new ndarray(data ^ p->data); - } else if (auto p = dynamic_cast *>(&other)) { /* int64 ^ int64 */ - return new ndarray(data ^ p->data); - } - } - - throw std::runtime_error("^ operator is not compatible with floating types"); - } - - ndarray_base* xor_bool(bool_ other) const override { - if constexpr(std::is_same_v) { - return new ndarray(data ^ other); - } else if constexpr(std::is_same_v) { - return new ndarray(data ^ other); - } else if constexpr(std::is_same_v) { - return new ndarray(data ^ other); - } else if constexpr(std::is_same_v) { - return new ndarray(data ^ other); - } else if constexpr(std::is_same_v) { - return new ndarray(data ^ other); - } - - throw std::runtime_error("^ operator is not compatible with floating types"); - } - - ndarray_base* xor_int(int_ other) const override { - if constexpr(std::is_same_v) { - return new ndarray((data ^ other).template astype()); - } else if constexpr(std::is_same_v) { - return new ndarray(data ^ other); - } else if constexpr(std::is_same_v) { - return new ndarray(data ^ other); - } else if constexpr(std::is_same_v) { - return new ndarray(data ^ other); - } else if constexpr(std::is_same_v) { - return new ndarray(data ^ other); - } - - throw std::runtime_error("^ operator is not compatible with floating types"); - } - - ndarray_base* invert() const override { - if constexpr(std::is_same_v) { - return new ndarray(!data); - } else if constexpr(std::is_same_v) { - return new ndarray(!data); - } else if constexpr(std::is_same_v) { - return new ndarray(!data); - } else if constexpr(std::is_same_v) { - return new ndarray(!data); - } else if constexpr(std::is_same_v) { - return new ndarray(!data); - } - - throw std::runtime_error("~ operator is not compatible with floating types"); - } - - py::object get_item_int(int index) const override { - if(index < 0) index += data.shape()[0]; - if(data.ndim() == 1) { - if constexpr(std::is_same_v) { - return py::bool_(data(index)); - } else if constexpr(std::is_same_v) { - return py::int_(data(index)); - } else if constexpr(std::is_same_v) { - return py::float_(data(index)); - } - } - return py::cast(ndarray(data[index])); - } - - py::object get_item_tuple(py::tuple args) const override { - pkpy::numpy::ndarray store = data; - std::vector indices; - for(auto item: args) { - indices.push_back(py::cast(item)); - } - for(int i = 0; i < indices.size() - 1; i++) { - if(indices[i] < 0) indices[i] += store.shape()[0]; - pkpy::numpy::ndarray temp = store[indices[i]]; - store = temp; - } - - if(indices[indices.size() - 1] < 0) indices[indices.size() - 1] += store.shape()[0]; - if(store.ndim() == 1) { - if constexpr(std::is_same_v) { - return py::bool_(store(indices[indices.size() - 1])); - } else if constexpr(std::is_same_v) { - return py::int_(store(indices[indices.size() - 1])); - } else if constexpr(std::is_same_v) { - return py::float_(store(indices[indices.size() - 1])); - } - } - return py::cast(ndarray(store[indices[indices.size() - 1]])); - } - - ndarray_base* get_item_vector(const std::vector& indices) const override { - return new ndarray(data[indices]); - } - - ndarray_base* get_item_slice(py::slice slice) const override { - int start = parseAttr(getattr(slice, "start")); - int stop = parseAttr(getattr(slice, "stop")); - int step = parseAttr(getattr(slice, "step")); - - if(step == INT_MAX) step = 1; - if(step > 0) { - if(start == INT_MAX) start = 0; - if(stop == INT_MAX) stop = data.shape()[0]; - } else if(step < 0) { - if(start == INT_MAX) start = data.shape()[0] - 1; - if(stop == INT_MAX) stop = -(1 + data.shape()[0]); - } - - return new ndarray(data[std::make_tuple(start, stop, step)]); - } - - void set_item_int(int index, int_ value) override { - if constexpr(std::is_same_v) { - if (data.ndim() == 1) { - data.set_item(index, value); - } else { - data.set_item(index, pkpy::numpy::adapt(std::vector{value})); - } - } else if constexpr(std::is_same_v) { - if (data.ndim() == 1) { - data.set_item(index, static_cast(value)); - } else { - data.set_item(index, (pkpy::numpy::adapt(std::vector{value})).astype()); - } - } - } - - void set_item_index_int(int index, const std::vector& value) override { - if constexpr(std::is_same_v) { - data.set_item(index, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(index, (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_index_int_2d(int index, const std::vector>& value) override { - if constexpr(std::is_same_v) { - data.set_item(index, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(index, (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_index_int_3d(int index, const std::vector>>& value) override { - if constexpr(std::is_same_v) { - data.set_item(index, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(index, (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_index_int_4d(int index, const std::vector>>>& value) override { - if constexpr(std::is_same_v) { - data.set_item(index, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(index, (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_float(int index, float64 value) override { - if constexpr(std::is_same_v) { - if (data.ndim() == 1) { - data.set_item(index, value); - } else { - data.set_item(index, pkpy::numpy::adapt(std::vector{value})); - } - } else if constexpr(std::is_same_v) { - if (data.ndim() == 1) { - data.set_item(index, static_cast(value)); - } else { - data.set_item(index, (pkpy::numpy::adapt(std::vector{value})).astype()); - } - } - } - - void set_item_index_float(int index, const std::vector& value) override { - if constexpr(std::is_same_v) { - data.set_item(index, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(index, (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_index_float_2d(int index, const std::vector>& value) override { - if constexpr(std::is_same_v) { - data.set_item(index, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(index, (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_index_float_3d(int index, const std::vector>>& value) override { - if constexpr(std::is_same_v) { - data.set_item(index, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(index, (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_index_float_4d(int index, const std::vector>>>& value) override { - if constexpr(std::is_same_v) { - data.set_item(index, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(index, (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_tuple_int1(py::tuple args, int_ value) override { - std::vector indices; - for(auto item: args) { - indices.push_back(py::cast(item)); - } - if(indices.size() == 1) { - int index = indices[0]; - if constexpr(std::is_same_v) { - data.set_item(index, pkpy::numpy::adapt(std::vector{value})); - } else if constexpr(std::is_same_v) { - data.set_item(index, (pkpy::numpy::adapt(std::vector{value})).astype()); - } - } else if(indices.size() == 2 && indices.size() <= data.ndim()) - data.set_item(indices[0], indices[1], static_cast(value)); - else if(indices.size() == 3 && indices.size() <= data.ndim()) - data.set_item(indices[0], indices[1], indices[2], static_cast(value)); - else if(indices.size() == 4 && indices.size() <= data.ndim()) - data.set_item(indices[0], indices[1], indices[2], indices[3], static_cast(value)); - else if(indices.size() == 5 && indices.size() <= data.ndim()) - data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], static_cast(value)); - } - - void set_item_tuple_int2(py::tuple args, const std::vector& value) override { - std::vector indices; - for(auto item: args) { - indices.push_back(py::cast(item)); - } - if(indices.size() == 1) { - int index = indices[0]; - if constexpr(std::is_same_v) { - data.set_item(index, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(index, (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 2 && indices.size() <= data.ndim()) { - if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 3 && indices.size() <= data.ndim()) { - if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 4 && indices.size() <= data.ndim()) { - if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 5 && indices.size() <= data.ndim()) { - if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], (pkpy::numpy::adapt(value)).astype()); - } - } - } - - void set_item_tuple_int3(py::tuple args, const std::vector>& value) override { - std::vector indices; - for(auto item: args) { - indices.push_back(py::cast(item)); - } - if(indices.size() == 1) { - int index = indices[0]; - if constexpr(std::is_same_v) { - data.set_item(index, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(index, (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 2 && indices.size() <= data.ndim()) { - if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 3 && indices.size() <= data.ndim()) { - if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 4 && indices.size() <= data.ndim()) { - if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 5 && indices.size() <= data.ndim()) { - if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], (pkpy::numpy::adapt(value)).astype()); - } - } - } - - void set_item_tuple_int4(py::tuple args, const std::vector>>& value) override { - std::vector indices; - for(auto item: args) { - indices.push_back(py::cast(item)); - } - if(indices.size() == 1) { - int index = indices[0]; - if constexpr(std::is_same_v) { - data.set_item(index, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(index, (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 2 && indices.size() <= data.ndim()) { - if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 3 && indices.size() <= data.ndim()) { - if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 4 && indices.size() <= data.ndim()) { - if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 5 && indices.size() <= data.ndim()) { - if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], (pkpy::numpy::adapt(value)).astype()); - } - } - } - - void set_item_tuple_int5(py::tuple args, const std::vector>>>& value) override { - std::vector indices; - for(auto item: args) { - indices.push_back(py::cast(item)); - } - if(indices.size() == 1) { - int index = indices[0]; - if constexpr(std::is_same_v) { - data.set_item(index, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(index, (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 2 && indices.size() <= data.ndim()) { - if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 3 && indices.size() <= data.ndim()) { - if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 4 && indices.size() <= data.ndim()) { - if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 5 && indices.size() <= data.ndim()) { - if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], (pkpy::numpy::adapt(value)).astype()); - } - } - } - - void set_item_tuple_float1(py::tuple args, float64 value) override { - std::vector indices; - for(auto item: args) { - indices.push_back(py::cast(item)); - } - if(indices.size() == 1) { - int index = indices[0]; - if constexpr(std::is_same_v) { - data.set_item(index, pkpy::numpy::adapt(std::vector{value})); - } else if constexpr(std::is_same_v) { - data.set_item(index, (pkpy::numpy::adapt(std::vector{value})).astype()); - } - } else if(indices.size() == 2 && indices.size() <= data.ndim()) - data.set_item(indices[0], indices[1], static_cast(value)); - else if(indices.size() == 3 && indices.size() <= data.ndim()) - data.set_item(indices[0], indices[1], indices[2], static_cast(value)); - else if(indices.size() == 4 && indices.size() <= data.ndim()) - data.set_item(indices[0], indices[1], indices[2], indices[3], static_cast(value)); - else if(indices.size() == 5 && indices.size() <= data.ndim()) - data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], static_cast(value)); - } - - void set_item_tuple_float2(py::tuple args, const std::vector& value) override { - std::vector indices; - for(auto item: args) { - indices.push_back(py::cast(item)); - } - if(indices.size() == 1) { - int index = indices[0]; - if constexpr(std::is_same_v) { - data.set_item(index, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(index, (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 2 && indices.size() <= data.ndim()) { - if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], pkpy::numpy::adapt(value)); - } else if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], (pkpy::numpy::adapt(value)).astype()); - } - } - else if(indices.size() == 3 && indices.size() <= data.ndim()) { - if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], pkpy::numpy::adapt(value)); - } else if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], (pkpy::numpy::adapt(value)).astype()); - } - } - else if(indices.size() == 4 && indices.size() <= data.ndim()) { - if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], pkpy::numpy::adapt(value)); - } else if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], (pkpy::numpy::adapt(value)).astype()); - } - } - else if(indices.size() == 5 && indices.size() <= data.ndim()) { - if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], pkpy::numpy::adapt(value)); - } else if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], (pkpy::numpy::adapt(value)).astype()); - } - } - } - - void set_item_tuple_float3(py::tuple args, const std::vector>& value) override { - std::vector indices; - for(auto item: args) { - indices.push_back(py::cast(item)); - } - if(indices.size() == 1) { - int index = indices[0]; - if constexpr(std::is_same_v) { - data.set_item(index, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(index, (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 2 && indices.size() <= data.ndim()) { - if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], pkpy::numpy::adapt(value)); - } else if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], (pkpy::numpy::adapt(value)).astype()); - } - } - else if(indices.size() == 3 && indices.size() <= data.ndim()) { - if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], pkpy::numpy::adapt(value)); - } else if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], (pkpy::numpy::adapt(value)).astype()); - } - } - else if(indices.size() == 4 && indices.size() <= data.ndim()) { - if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], pkpy::numpy::adapt(value)); - } else if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], (pkpy::numpy::adapt(value)).astype()); - } - } - else if(indices.size() == 5 && indices.size() <= data.ndim()) { - if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], pkpy::numpy::adapt(value)); - } else if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], (pkpy::numpy::adapt(value)).astype()); - } - } - } - - void set_item_tuple_float4(py::tuple args, const std::vector>>& value) override { - std::vector indices; - for(auto item: args) { - indices.push_back(py::cast(item)); - } - if(indices.size() == 1) { - int index = indices[0]; - if constexpr(std::is_same_v) { - data.set_item(index, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(index, (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 2 && indices.size() <= data.ndim()) { - if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], pkpy::numpy::adapt(value)); - } else if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], (pkpy::numpy::adapt(value)).astype()); - } - } - else if(indices.size() == 3 && indices.size() <= data.ndim()) { - if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], pkpy::numpy::adapt(value)); - } else if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], (pkpy::numpy::adapt(value)).astype()); - } - } - else if(indices.size() == 4 && indices.size() <= data.ndim()) { - if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], pkpy::numpy::adapt(value)); - } else if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], (pkpy::numpy::adapt(value)).astype()); - } - } - else if(indices.size() == 5 && indices.size() <= data.ndim()) { - if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], pkpy::numpy::adapt(value)); - } else if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], (pkpy::numpy::adapt(value)).astype()); - } - } - } - - void set_item_tuple_float5(py::tuple args, const std::vector>>>& value) override { - std::vector indices; - for(auto item: args) { - indices.push_back(py::cast(item)); - } - if(indices.size() == 1) { - int index = indices[0]; - if constexpr(std::is_same_v) { - data.set_item(index, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(index, (pkpy::numpy::adapt(value)).astype()); - } - } else if(indices.size() == 2 && indices.size() <= data.ndim()) { - if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], pkpy::numpy::adapt(value)); - } else if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], (pkpy::numpy::adapt(value)).astype()); - } - } - else if(indices.size() == 3 && indices.size() <= data.ndim()) { - if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], pkpy::numpy::adapt(value)); - } else if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], (pkpy::numpy::adapt(value)).astype()); - } - } - else if(indices.size() == 4 && indices.size() <= data.ndim()) { - if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], pkpy::numpy::adapt(value)); - } else if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], (pkpy::numpy::adapt(value)).astype()); - } - } - else if(indices.size() == 5 && indices.size() <= data.ndim()) { - if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], pkpy::numpy::adapt(value)); - } else if constexpr (std::is_same_v) { - data.set_item(indices[0], indices[1], indices[2], indices[3], indices[4], (pkpy::numpy::adapt(value)).astype()); - } - } - } - - void set_item_vector_int1(const std::vector& indices, int_ value) override { - if constexpr(std::is_same_v) { - data.set_item(indices, pkpy::numpy::adapt(std::vector{value})); - } else if constexpr(std::is_same_v) { - data.set_item(indices, (pkpy::numpy::adapt(std::vector{value})).astype()); - } - } - - void set_item_vector_int2(const std::vector& indices, const std::vector& value) override { - if constexpr(std::is_same_v) { - data.set_item(indices, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices, (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_vector_int3(const std::vector& indices, const std::vector>& value) override { - if constexpr(std::is_same_v) { - data.set_item(indices, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices, (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_vector_int4(const std::vector& indices, const std::vector>>& value) override { - if constexpr(std::is_same_v) { - data.set_item(indices, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices, (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_vector_int5(const std::vector& indices, const std::vector>>>& value) override { - if constexpr(std::is_same_v) { - data.set_item(indices, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices, (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_vector_float1(const std::vector& indices, float64 value) override { - if constexpr(std::is_same_v) { - data.set_item(indices, pkpy::numpy::adapt(std::vector{value})); - } else if constexpr(std::is_same_v) { - data.set_item(indices, (pkpy::numpy::adapt(std::vector{value})).astype()); - } - } - - void set_item_vector_float2(const std::vector& indices, const std::vector& value) override { - if constexpr(std::is_same_v) { - data.set_item(indices, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices, (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_vector_float3(const std::vector& indices, const std::vector>& value) override { - if constexpr(std::is_same_v) { - data.set_item(indices, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices, (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_vector_float4(const std::vector& indices, const std::vector>>& value) override { - if constexpr(std::is_same_v) { - data.set_item(indices, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices, (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_vector_float5(const std::vector& indices, const std::vector>>>& value) override { - if constexpr(std::is_same_v) { - data.set_item(indices, pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(indices, (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_slice_int1(py::slice slice, int_ value) override { - int start = parseAttr(getattr(slice, "start")); - int stop = parseAttr(getattr(slice, "stop")); - int step = parseAttr(getattr(slice, "step")); - - if(step == INT_MAX) step = 1; - if(step > 0) { - if(start == INT_MAX) start = 0; - if(stop == INT_MAX) stop = data.shape()[0]; - } else if(step < 0) { - if(start == INT_MAX) start = data.shape()[0] - 1; - if(stop == INT_MAX) stop = -(1 + data.shape()[0]); - } - if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(std::vector{value})); - } else if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), - (pkpy::numpy::adapt(std::vector{value})).astype()); - } - } - - void set_item_slice_int2(py::slice slice, const std::vector& value) override { - int start = parseAttr(getattr(slice, "start")); - int stop = parseAttr(getattr(slice, "stop")); - int step = parseAttr(getattr(slice, "step")); - - if(step == INT_MAX) step = 1; - if(step > 0) { - if(start == INT_MAX) start = 0; - if(stop == INT_MAX) stop = data.shape()[0]; - } else if(step < 0) { - if(start == INT_MAX) start = data.shape()[0] - 1; - if(stop == INT_MAX) stop = -(1 + data.shape()[0]); - } - if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_slice_int3(py::slice slice, const std::vector>& value) override { - int start = parseAttr(getattr(slice, "start")); - int stop = parseAttr(getattr(slice, "stop")); - int step = parseAttr(getattr(slice, "step")); - - if(step == INT_MAX) step = 1; - if(step > 0) { - if(start == INT_MAX) start = 0; - if(stop == INT_MAX) stop = data.shape()[0]; - } else if(step < 0) { - if(start == INT_MAX) start = data.shape()[0] - 1; - if(stop == INT_MAX) stop = -(1 + data.shape()[0]); - } - if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_slice_int4(py::slice slice, const std::vector>>& value) override { - int start = parseAttr(getattr(slice, "start")); - int stop = parseAttr(getattr(slice, "stop")); - int step = parseAttr(getattr(slice, "step")); - - if(step == INT_MAX) step = 1; - if(step > 0) { - if(start == INT_MAX) start = 0; - if(stop == INT_MAX) stop = data.shape()[0]; - } else if(step < 0) { - if(start == INT_MAX) start = data.shape()[0] - 1; - if(stop == INT_MAX) stop = -(1 + data.shape()[0]); - } - if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_slice_int5(py::slice slice, const std::vector>>>& value) override { - int start = parseAttr(getattr(slice, "start")); - int stop = parseAttr(getattr(slice, "stop")); - int step = parseAttr(getattr(slice, "step")); - - if(step == INT_MAX) step = 1; - if(step > 0) { - if(start == INT_MAX) start = 0; - if(stop == INT_MAX) stop = data.shape()[0]; - } else if(step < 0) { - if(start == INT_MAX) start = data.shape()[0] - 1; - if(stop == INT_MAX) stop = -(1 + data.shape()[0]); - } - if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_slice_float1(py::slice slice, float64 value) override { - int start = parseAttr(getattr(slice, "start")); - int stop = parseAttr(getattr(slice, "stop")); - int step = parseAttr(getattr(slice, "step")); - - if(step == INT_MAX) step = 1; - if(step > 0) { - if(start == INT_MAX) start = 0; - if(stop == INT_MAX) stop = data.shape()[0]; - } else if(step < 0) { - if(start == INT_MAX) start = data.shape()[0] - 1; - if(stop == INT_MAX) stop = -(1 + data.shape()[0]); - } - if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(std::vector{value})); - } else if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), - (pkpy::numpy::adapt(std::vector{value})).astype()); - } - } - - void set_item_slice_float2(py::slice slice, const std::vector& value) override { - int start = parseAttr(getattr(slice, "start")); - int stop = parseAttr(getattr(slice, "stop")); - int step = parseAttr(getattr(slice, "step")); - - if(step == INT_MAX) step = 1; - if(step > 0) { - if(start == INT_MAX) start = 0; - if(stop == INT_MAX) stop = data.shape()[0]; - } else if(step < 0) { - if(start == INT_MAX) start = data.shape()[0] - 1; - if(stop == INT_MAX) stop = -(1 + data.shape()[0]); - } - if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_slice_float3(py::slice slice, const std::vector>& value) override { - int start = parseAttr(getattr(slice, "start")); - int stop = parseAttr(getattr(slice, "stop")); - int step = parseAttr(getattr(slice, "step")); - - if(step == INT_MAX) step = 1; - if(step > 0) { - if(start == INT_MAX) start = 0; - if(stop == INT_MAX) stop = data.shape()[0]; - } else if(step < 0) { - if(start == INT_MAX) start = data.shape()[0] - 1; - if(stop == INT_MAX) stop = -(1 + data.shape()[0]); - } - if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_slice_float4(py::slice slice, const std::vector>>& value) override { - int start = parseAttr(getattr(slice, "start")); - int stop = parseAttr(getattr(slice, "stop")); - int step = parseAttr(getattr(slice, "step")); - - if(step == INT_MAX) step = 1; - if(step > 0) { - if(start == INT_MAX) start = 0; - if(stop == INT_MAX) stop = data.shape()[0]; - } else if(step < 0) { - if(start == INT_MAX) start = data.shape()[0] - 1; - if(stop == INT_MAX) stop = -(1 + data.shape()[0]); - } - if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), (pkpy::numpy::adapt(value)).astype()); - } - } - - void set_item_slice_float5(py::slice slice, const std::vector>>>& value) override { - int start = parseAttr(getattr(slice, "start")); - int stop = parseAttr(getattr(slice, "stop")); - int step = parseAttr(getattr(slice, "step")); - - if(step == INT_MAX) step = 1; - if(step > 0) { - if(start == INT_MAX) start = 0; - if(stop == INT_MAX) stop = data.shape()[0]; - } else if(step < 0) { - if(start == INT_MAX) start = data.shape()[0] - 1; - if(stop == INT_MAX) stop = -(1 + data.shape()[0]); - } - if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), pkpy::numpy::adapt(value)); - } else if constexpr(std::is_same_v) { - data.set_item(std::make_tuple(start, stop, step), (pkpy::numpy::adapt(value)).astype()); - } - } - - std::string to_string() const override { - std::ostringstream os; - os << data; - std::string result = os.str(); - - size_t pos = 0; - while ((pos = result.find('{', pos)) != std::string::npos) { - result.replace(pos, 1, "["); - pos += 1; - } - pos = 0; - while ((pos = result.find('}', pos)) != std::string::npos) { - result.replace(pos, 1, "]"); - pos += 1; - } - - if constexpr(std::is_same_v) { - size_t pos = 0; - while ((pos = result.find("true", pos)) != std::string::npos) { - result.replace(pos, 4, "True"); - pos += 4; - } - pos = 0; - while ((pos = result.find("false", pos)) != std::string::npos) { - result.replace(pos, 5, "False"); - pos += 5; - } - } - - for(int i = 0; i < result.size(); i++) { - if(result[i] == '\n') { - result.insert(i + 1, " "); - } - } - return result; - } -}; class Random { public: @@ -2869,89 +166,6 @@ void array_creation_registry(py::module_& m) { register_array_float<5>(m); } -// --- RDP helpers: bridge ndarray/list <-> Eigen types --- - -// Helper: extract Nx2 or Nx3 Eigen matrix from ndarray_base -static rdp::RowVectors ndarray_to_eigen(const ndarray_base& base, int& input_cols) { - int dims = base.ndim(); - if (dims != 2) throw std::invalid_argument("rdp: expected 2D array"); - auto shape_vec = base.shape(); - int rows = shape_vec[0].cast(); - int cols = shape_vec[1].cast(); - if (cols != 2 && cols != 3) throw std::invalid_argument("rdp: expected Nx2 or Nx3 array"); - input_cols = cols; - - if (auto* p = dynamic_cast*>(&base)) { - const double* ptr = p->data.get_array().data(); - if (cols == 3) { - return Eigen::Map(ptr, rows, 3); - } else { - rdp::RowVectors result(rows, 3); - result.setZero(); - Eigen::Map map2(ptr, rows, 2); - result.leftCols(2) = map2; - return result; - } - } - if (auto* p = dynamic_cast*>(&base)) { - const int_* iptr = p->data.get_array().data(); - rdp::RowVectors result(rows, 3); - result.setZero(); - for (int i = 0; i < rows; ++i) - for (int j = 0; j < cols; ++j) - result(i, j) = static_cast(iptr[i * cols + j]); - return result; - } - throw std::invalid_argument("rdp: unsupported ndarray dtype"); -} - -// Helper: convert vector> to Eigen Nx3 (zero-pad 2D to 3D) -static rdp::RowVectors vec2d_to_eigen_d(const std::vector>& coords, int& input_cols) { - int rows = (int)coords.size(); - if (rows == 0) throw std::invalid_argument("rdp: empty coords"); - int cols = (int)coords[0].size(); - if (cols != 2 && cols != 3) throw std::invalid_argument("rdp: expected Nx2 or Nx3"); - input_cols = cols; - rdp::RowVectors result(rows, 3); - result.setZero(); - for (int i = 0; i < rows; ++i) - for (int j = 0; j < cols; ++j) - result(i, j) = coords[i][j]; - return result; -} - -// Helper: convert vector> to Eigen Nx3 -static rdp::RowVectors vec2d_to_eigen_i(const std::vector>& coords, int& input_cols) { - int rows = (int)coords.size(); - if (rows == 0) throw std::invalid_argument("rdp: empty coords"); - int cols = (int)coords[0].size(); - if (cols != 2 && cols != 3) throw std::invalid_argument("rdp: expected Nx2 or Nx3"); - input_cols = cols; - rdp::RowVectors result(rows, 3); - result.setZero(); - for (int i = 0; i < rows; ++i) - for (int j = 0; j < cols; ++j) - result(i, j) = static_cast(coords[i][j]); - return result; -} - -// Helper: Eigen RowVectors result -> ndarray_base (return Nx2 or Nx3) -static std::unique_ptr eigen_to_ndarray(const rdp::RowVectors& mat, int output_cols) { - int N = (int)mat.rows(); - std::vector> data(N, std::vector(output_cols)); - for (int i = 0; i < N; ++i) - for (int j = 0; j < output_cols; ++j) - data[i][j] = mat(i, j); - return std::unique_ptr(new ndarray(data)); -} - -// Helper: Eigen VectorXi mask -> ndarray_base (1D int array) -static std::unique_ptr mask_to_ndarray(const Eigen::VectorXi& mask) { - std::vector data(mask.size()); - for (int i = 0; i < mask.size(); ++i) data[i] = mask[i]; - return std::unique_ptr(new ndarray(data)); -} - PYBIND11_MODULE(numpy, m) { m.doc() = "Python bindings for pkpy::numpy::ndarray using pybind11"; @@ -3619,54 +833,83 @@ PYBIND11_MODULE(numpy, m) { py::arg("rtol") = 1e-5, py::arg("atol") = 1e-8); - // --- RDP bindings --- + // --- RDP bindings (Eigen types auto-converted via pybind11/eigen.h type_caster) --- - // rdp from list> - m.def("rdp", [](std::vector> coords, double epsilon, bool recursive) -> std::unique_ptr { - int input_cols; - auto eigen_coords = vec2d_to_eigen_d(coords, input_cols); - auto result = rdp::douglas_simplify(eigen_coords, epsilon, recursive); - return eigen_to_ndarray(result, input_cols); - }, py::arg("coords"), py::arg("epsilon") = 0.0, py::arg("recursive") = true); + auto rdp_doc = R"pbdoc( + Simplifies a given array of points using the Ramer-Douglas-Peucker algorithm. - // rdp from list> - m.def("rdp", [](std::vector> coords, double epsilon, bool recursive) -> std::unique_ptr { - int input_cols; - auto eigen_coords = vec2d_to_eigen_i(coords, input_cols); - auto result = rdp::douglas_simplify(eigen_coords, epsilon, recursive); - return eigen_to_ndarray(result, input_cols); - }, py::arg("coords"), py::arg("epsilon") = 0.0, py::arg("recursive") = true); + Example: + >>> from pocket_numpy import rdp + >>> rdp([[1, 1], [2, 2], [3, 3], [4, 4]]) + [[1, 1], [4, 4]] + )pbdoc"; - // rdp from ndarray - m.def("rdp", [](const ndarray_base& coords, double epsilon, bool recursive) -> std::unique_ptr { - int input_cols; - auto eigen_coords = ndarray_to_eigen(coords, input_cols); - auto result = rdp::douglas_simplify(eigen_coords, epsilon, recursive); - return eigen_to_ndarray(result, input_cols); - }, py::arg("coords"), py::arg("epsilon") = 0.0, py::arg("recursive") = true); + // rdp: Nx3 (auto-converted from ndarray via type_caster) + m.def("rdp", [](const Eigen::Ref& coords, double epsilon, bool recursive) -> rdp::RowVectors { + return rdp::douglas_simplify(coords, epsilon, recursive); + }, rdp_doc, py::arg("coords"), py::arg("epsilon") = 0.0, py::arg("recursive") = true); - // rdp_mask from list> - m.def("rdp_mask", [](std::vector> coords, double epsilon, bool recursive) -> std::unique_ptr { - int input_cols; - auto eigen_coords = vec2d_to_eigen_d(coords, input_cols); - auto mask = rdp::douglas_simplify_mask(eigen_coords, epsilon, recursive); - return mask_to_ndarray(mask); - }, py::arg("coords"), py::arg("epsilon") = 0.0, py::arg("recursive") = true); + // rdp: Nx2 (type_caster rejects Nx3, picks this overload) + m.def("rdp", [](const Eigen::Ref& coords, double epsilon, bool recursive) -> rdp::RowVectorsNx2 { + rdp::RowVectors xyzs(coords.rows(), 3); + xyzs.setZero(); + xyzs.leftCols(2) = coords; + return rdp::douglas_simplify(xyzs, epsilon, recursive).leftCols(2); + }, rdp_doc, py::arg("coords"), py::arg("epsilon") = 0.0, py::arg("recursive") = true); - // rdp_mask from list> - m.def("rdp_mask", [](std::vector> coords, double epsilon, bool recursive) -> std::unique_ptr { - int input_cols; - auto eigen_coords = vec2d_to_eigen_i(coords, input_cols); - auto mask = rdp::douglas_simplify_mask(eigen_coords, epsilon, recursive); - return mask_to_ndarray(mask); + // rdp: from list> (stl.h handles the conversion) + m.def("rdp", [](std::vector> coords, double epsilon, bool recursive) -> std::unique_ptr { + int rows = (int)coords.size(); + if (rows == 0) throw std::invalid_argument("rdp: empty coords"); + int cols = (int)coords[0].size(); + if (cols != 2 && cols != 3) throw std::invalid_argument("rdp: expected Nx2 or Nx3"); + rdp::RowVectors eigen_coords(rows, 3); + eigen_coords.setZero(); + for (int i = 0; i < rows; ++i) + for (int j = 0; j < cols; ++j) + eigen_coords(i, j) = coords[i][j]; + auto result = rdp::douglas_simplify(eigen_coords, epsilon, recursive); + int N = (int)result.rows(); + std::vector> data(N, std::vector(cols)); + for (int i = 0; i < N; ++i) + for (int j = 0; j < cols; ++j) + data[i][j] = result(i, j); + return std::unique_ptr(new ::ndarray(data)); }, py::arg("coords"), py::arg("epsilon") = 0.0, py::arg("recursive") = true); - // rdp_mask from ndarray - m.def("rdp_mask", [](const ndarray_base& coords, double epsilon, bool recursive) -> std::unique_ptr { - int input_cols; - auto eigen_coords = ndarray_to_eigen(coords, input_cols); + auto rdp_mask_doc = R"pbdoc( + Simplifies a given array of points using the Ramer-Douglas-Peucker algorithm. + Returns a mask. + )pbdoc"; + + // rdp_mask: Nx3 + m.def("rdp_mask", [](const Eigen::Ref& coords, double epsilon, bool recursive) -> Eigen::VectorXi { + return rdp::douglas_simplify_mask(coords, epsilon, recursive); + }, rdp_mask_doc, py::arg("coords"), py::arg("epsilon") = 0.0, py::arg("recursive") = true); + + // rdp_mask: Nx2 + m.def("rdp_mask", [](const Eigen::Ref& coords, double epsilon, bool recursive) -> Eigen::VectorXi { + rdp::RowVectors xyzs(coords.rows(), 3); + xyzs.setZero(); + xyzs.leftCols(2) = coords; + return rdp::douglas_simplify_mask(xyzs, epsilon, recursive); + }, rdp_mask_doc, py::arg("coords"), py::arg("epsilon") = 0.0, py::arg("recursive") = true); + + // rdp_mask: from list> + m.def("rdp_mask", [](std::vector> coords, double epsilon, bool recursive) -> std::unique_ptr { + int rows = (int)coords.size(); + if (rows == 0) throw std::invalid_argument("rdp: empty coords"); + int cols = (int)coords[0].size(); + if (cols != 2 && cols != 3) throw std::invalid_argument("rdp: expected Nx2 or Nx3"); + rdp::RowVectors eigen_coords(rows, 3); + eigen_coords.setZero(); + for (int i = 0; i < rows; ++i) + for (int j = 0; j < cols; ++j) + eigen_coords(i, j) = coords[i][j]; auto mask = rdp::douglas_simplify_mask(eigen_coords, epsilon, recursive); - return mask_to_ndarray(mask); + std::vector mask_data(mask.size()); + for (int i = 0; i < mask.size(); ++i) mask_data[i] = mask[i]; + return std::unique_ptr(new ::ndarray(mask_data)); }, py::arg("coords"), py::arg("epsilon") = 0.0, py::arg("recursive") = true); // Create pocket_numpy module that re-exports rdp/rdp_mask from numpy From 71756d691185e5043384a8295c0784ff8fa758de Mon Sep 17 00:00:00 2001 From: tang zhixiong Date: Mon, 16 Feb 2026 01:21:17 +0800 Subject: [PATCH 2/6] update wasm --- README.md | 4 ++++ docs/lib/pocketpy.wasm | Bin 2563488 -> 2570571 bytes 2 files changed, 4 insertions(+) diff --git a/README.md b/README.md index 36ab717..beaaf2b 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,10 @@ python3 -m pocket_numpy --help python3 -m pocket_numpy tests/test_numpy.py ``` +# Try is online + + + --- # How to build (for dev) diff --git a/docs/lib/pocketpy.wasm b/docs/lib/pocketpy.wasm index 494205048c43bfe82091886ae38a9a87dd998c54..05c751c2c901794b7a53549be9bce766be93df9c 100755 GIT binary patch delta 245168 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 z�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 delta 236155 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 Date: Mon, 16 Feb 2026 01:21:51 +0800 Subject: [PATCH 3/6] update version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 829e7d0..8179d5b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build" [project] name = "pocket_numpy" -version = "0.0.2" +version = "0.0.3" description = "pocketpy with numpy" readme = "README.md" authors = [ From 9b3c7505eda4b8afea4477ac5d9cfee7cfdd71f6 Mon Sep 17 00:00:00 2001 From: tang zhixiong Date: Mon, 16 Feb 2026 01:43:16 +0800 Subject: [PATCH 4/6] Move eigen.h from pocketpy submodule to include/pkbind/ Avoid polluting the pocketpy submodule and prevent shadowing the real pybind11/eigen.h used by src/pybind.cpp. Co-Authored-By: Claude Opus 4.6 --- include/{pybind11 => pkbind}/eigen.h | 0 src/numpy.cpp | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename include/{pybind11 => pkbind}/eigen.h (100%) diff --git a/include/pybind11/eigen.h b/include/pkbind/eigen.h similarity index 100% rename from include/pybind11/eigen.h rename to include/pkbind/eigen.h diff --git a/src/numpy.cpp b/src/numpy.cpp index 3d9421c..801e94d 100644 --- a/src/numpy.cpp +++ b/src/numpy.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include "rdp.hpp" From bdcfbca251d7c96ba979c6bc6257b7fba450d069 Mon Sep 17 00:00:00 2001 From: tang zhixiong Date: Mon, 16 Feb 2026 01:45:34 +0800 Subject: [PATCH 5/6] add claude.md --- CLAUDE.md | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..b0f9e03 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,77 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +**pocket_numpy** (repo: xtensor-numpy) is a C++ project that integrates the pocketpy lightweight Python interpreter with numpy-like array functionality powered by xtensor and Eigen. It produces: +- A native CLI (`pocketpy.exe`) that runs Python scripts with numpy support +- Python wheels via pybind11 (package name: `pocket_numpy`) +- A WebAssembly build for browser deployment + +## Build & Test Commands + +```bash +# Build (installs in editable mode with scikit-build-core) +make build + +# Run numpy tests via pocketpy CLI +make test # runs: build/pocketpy.exe tests/test_numpy.py + +# Run a single test file +build/pocketpy.exe tests/test_numpy.py + +# Run tests via pytest (after pip install) +python3 -m pytest tests/ + +# Install as pip package +make python_install + +# Build WASM +make build_wasm + +# Serve WASM demo locally +make serve_wasm +``` + +## Architecture + +### Core Type System (`include/numpy.hpp`) + +Defines C++ type aliases (int8–64, uint8–64, float32, float64, bool_, complex64/128) and `dtype_traits` template for runtime dtype identification. Contains the `ndarray` template backed by `xt::xarray`. + +### Polymorphic ndarray (`include/ndarray_binding.hpp`) + +`ndarray_base` is an abstract base class with ~80+ virtual methods (shape, reductions, slicing, arithmetic, sorting, etc.). `ndarray` is the concrete template implementation. This virtual dispatch pattern enables a single Python-facing interface that works across all numeric types via `std::unique_ptr`. + +### Module Bindings (`src/numpy.cpp`) + +Registers the `numpy` module into pocketpy's runtime. Binds all ndarray methods, array creation functions (ones, zeros, full, arange, linspace, identity), random number generation, and dtype attributes. This is the largest source file. + +### RDP Bindings (`src/pybind.cpp` + `src/rdp.hpp`) + +Ramer-Douglas-Peucker polyline simplification exposed via pybind11 as the `_core` module. Supports 2D and 3D point arrays using Eigen matrix types. + +### CLI Entry Point (`src/main.cpp`) + +Initializes pocketpy, registers the numpy module via `py_module_initialize()`, then executes a Python script or enters REPL mode. + +### Dependencies + +- **pocketpy** — git submodule at `pocketpy/` +- **xtensor, xtl, Eigen** — vendored headers in `include/` +- **pybind11** — required via pip/CMake for Python wheel builds + +### Build Targets (CMake) + +- `numpy` — static library (numpy.cpp + pocketpy) +- `pocketpy_cli` — CLI executable linked against numpy +- `_core` — pybind11 module for RDP bindings + +## Key Conventions + +- C++17 required; C11 for pocketpy C sources +- Default build type is Release with `-O3`; debug uses `-O0 -ggdb` +- xtensor warnings are suppressed by default (`SHOW_XTENSOR_WARNINGS=OFF`) +- Tests are standalone Python scripts (not pytest-based) so they can also run under pocketpy and WASM +- macOS deployment target is 10.14+ (required for `std::visit`) From cdecd0fd5a8929d0fdba3e2d304a1ca6f616dfed Mon Sep 17 00:00:00 2001 From: tang zhixiong Date: Mon, 16 Feb 2026 01:46:45 +0800 Subject: [PATCH 6/6] no amend --- CLAUDE.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index b0f9e03..2eb83d4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -68,6 +68,10 @@ Initializes pocketpy, registers the numpy module via `py_module_initialize()`, t - `pocketpy_cli` — CLI executable linked against numpy - `_core` — pybind11 module for RDP bindings +## Git Policy + +- **NEVER use `git commit --amend`**. Always create a new commit instead. Amending rewrites history and can destroy previous work, especially after a failed pre-commit hook where `--amend` would silently modify the wrong commit. + ## Key Conventions - C++17 required; C11 for pocketpy C sources