#include #include #include #ifdef USE_OPENCL #include "opencl/tensor.hpp" OpenCL openCL; #elif USE_CPU #include "cpu/tensor.hpp" #endif namespace py = pybind11; enum class TENSOR_PLATFORM { CPU, OPENCL }; template void register_tensor(py::module &m, const std::string &name) { auto tensor = py::class_>(m, name.c_str()) .def(py::init &>()) .def(py::init &, T>()) .def(py::init &, const std::vector &>()) .def(py::init &, T, T>()) .def("get_shape", &Tensor::getShape) .def("get_axes", &Tensor::getAxes) .def("get_size", &Tensor::getSize) .def(py::self + py::self) .def(py::self - py::self) .def(py::self * py::self) .def(py::self += py::self) .def(py::self -= py::self) .def(py::self *= py::self) .def(py::self + T()) .def(py::self - T()) .def(py::self * T()) .def(py::self / T()) .def(py::self += T()) .def(py::self -= T()) .def(py::self *= T()) .def(py::self /= T()) .def(T() + py::self) .def(T() - py::self) .def(T() * py::self) .def("__pos__", [](const Tensor &t) { return +t; }) .def("__neg__", [](const Tensor &t) { return -t; }) .def("__repr__", &Tensor::toString); if constexpr (Dim >= 2) { tensor .def("transpose", py::overload_cast &>( &Tensor::transpose)) .def("transpose", py::overload_cast(&Tensor::transpose)) .def("t", &Tensor::t); } #ifndef USE_OPENCL if constexpr (Dim != 0) tensor .def( "__getitem__", [](Tensor &t, size_t index) -> T & { if (index >= t.getSize()) throw py::value_error("Index out of range"); return t[index]; }, py::return_value_policy::reference) .def( "__getitem__", [](Tensor &t, const py::tuple &indices) -> T & { if (indices.size() != Dim) throw py::value_error("Expected " + std::to_string(Dim) + " indices, got " + std::to_string(indices.size())); return [&](std::index_sequence) -> T & { return t(py::cast(indices[I])...); }(std::make_index_sequence{}); }, py::return_value_policy::reference) .def("__setitem__", [](Tensor &t, size_t index, const T &value) { if (index >= t.getSize()) throw py::value_error("Index out of range"); t[index] = value; }) .def("__setitem__", [](Tensor &t, const py::tuple &indices, const T &value) { if (indices.size() != Dim) throw py::value_error("Expected " + std::to_string(Dim) + " indices, got " + std::to_string(indices.size())); [&](std::index_sequence) { t(py::cast(indices[I])...) = value; }(std::make_index_sequence{}); }); #endif // if constexpr (Dim == 1 || Dim == 2) if constexpr (Dim == 2) tensor.def("__matmul__", &Tensor::operator%); } PYBIND11_MODULE(tensor, m) { m.doc() = "Tensor math library"; py::enum_(m, "PLATFORM") .value("CPU", TENSOR_PLATFORM::CPU) .value("OPENCL", TENSOR_PLATFORM::OPENCL) .export_values(); #ifdef USE_OPENCL m.attr("MODE") = TENSOR_PLATFORM::OPENCL; #elif USE_CPU m.attr("MODE") = TENSOR_PLATFORM::CPU; #endif register_tensor(m, "Scalar"); register_tensor(m, "Vector"); register_tensor(m, "Matrix"); register_tensor(m, "Tensor3"); #ifdef USE_OPENCL m.def("init", [](const std::string &programsBasePath) { openCL.init(programsBasePath); }); #endif #ifndef USE_OPENCL register_tensor(m, "dScalar"); register_tensor(m, "dVector"); register_tensor(m, "dMatrix"); register_tensor(m, "dTensor3"); register_tensor(m, "iScalar"); register_tensor(m, "iVector"); register_tensor(m, "iMatrix"); register_tensor(m, "iTensor3"); #endif }