diff --git a/CMakeLists.txt b/CMakeLists.txt index 6446215..fefe483 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,20 @@ project(NDArray LANGUAGES CXX ) +# Get FetchContent for downloading dependencies +include(FetchContent) + +#=============================================================================== +# Get Boost Container ( for static_vector.hpp ) +message(STATUS "Downloading Boost 1.81.0") +set(BOOST_INCLUDE_LIBRARIES container unordered) +set(BOOST_ENABLE_CMAKE ON) +FetchContent_Declare(Boost + GIT_REPOSITORY https://github.com/boostorg/boost.git + GIT_TAG boost-1.81.0 +) +FetchContent_MakeAvailable(Boost) + include(CMakePackageConfigHelpers) # Add options diff --git a/include/ndarray.hpp b/include/ndarray.hpp index 2bf4771..05c40ff 100644 --- a/include/ndarray.hpp +++ b/include/ndarray.hpp @@ -35,7 +35,7 @@ * */ #ifndef NDARRAY_H #define NDARRAY_H - +#include #include #include #include @@ -46,6 +46,7 @@ #include #include #include +#include // Macro to force function to be inlined. This is done for speed and to try and // force the compiler to vectorize operatrions. @@ -66,10 +67,17 @@ class NDArray { // Constructors and Destructors NDArray(); NDArray(const std::vector& init_shape, bool c_continuous = true); + + template + NDArray(boost::container::static_vector& init_shape, bool c_continuous = true); + + NDArray(const std::vector& data, const std::vector& init_shape, bool c_continuous = true); NDArray(std::vector&& data, const std::vector& init_shape, bool c_continuous = true); + + ~NDArray() = default; NDArray(const NDArray&) = default; NDArray(NDArray&&) = default; @@ -88,6 +96,14 @@ class NDArray { T& operator()(const std::vector& indices); const T& operator()(const std::vector& indices) const; + template + T& operator()(const boost::container::static_vector& indices); + + template + const T& operator()(const boost::container::static_vector& indices) const; + + + // Variadic indexing operators // Access data with array indices. template @@ -141,6 +157,9 @@ class NDArray { // DATA CAN BE LOST IF ARRAY IS SHRUNK void reallocate(const std::vector& new_shape); + template + void reallocate(const boost::container::static_vector& new_shape); + //========================================================================== // Operators for Any Type (Same or Different) template @@ -274,6 +293,33 @@ NDArray::NDArray(const std::vector& init_shape, bool c_continuous) { } } +template +template +NDArray::NDArray(boost::container::static_vector& init_shape, bool c_continuous) { + if (init_shape.size() > 0) { + shape_.clear(); + shape_.reserve( init_shape.size() ); + + for (std::size_t c : init_shape) { + shape_.push_back(c); + } + + dimensions_ = shape_.size(); + + std::size_t ne = init_shape[0]; + for (std::size_t i = 1; i < dimensions_; i++) { + ne *= init_shape[i]; + } + + data_.resize(ne); + + c_continuous_ = c_continuous; + } else { + std::string mssg = "NDArray shape vector must have at least one element."; + throw std::runtime_error(mssg); + } +} + template NDArray::NDArray(const std::vector& data, const std::vector& init_shape, bool c_continuous) { @@ -439,6 +485,65 @@ NDARRAY_INLINE const T& NDArray::operator()( return data_[indx]; } +template +template +T& NDArray::operator()(const boost::container::static_vector& static_indices){ + + std::vector indices; + indices.reserve( static_indices.size() ); + for ( auto& c : static_indices ){ + indices.push_back(c); + } + + /*size_t size_static_indices = static_indices.size(); + + std::array indices; + indices.fill(0); + + for( std::size_t i = 0; i < size_static_indices; i++){ + indices[i] = static_indices[i]; + }*/ + + size_t indx; + if (c_continuous_) { + // Get linear index for row-major order + indx = c_continuous_index(indices); + } else { + // Get linear index for column-major order + indx = fortran_continuous_index(indices); + } + return data_[indx]; +} + +template +template +const T& NDArray::operator()(const boost::container::static_vector& static_indices) const{ + + std::vector indices; + indices.reserve( static_indices.size() ); + for ( auto& c : static_indices ){ + indices.push_back(c); + } + /*size_t size_static_indices = static_indices.size(); + + std::array indices; + indices.fill(0); + + for( std::size_t i = 0; i < size_static_indices; i++){ + indices[i] = static_indices[i]; + }*/ + + size_t indx; + if (c_continuous_) { + // Get linear index for row-major order + indx = c_continuous_index(indices); + } else { + // Get linear index for column-major order + indx = fortran_continuous_index(indices); + } + return data_[indx]; +} + template template NDARRAY_INLINE T& NDArray::operator()(INDS... inds) { @@ -635,6 +740,32 @@ void NDArray::reallocate(const std::vector& new_shape) { } } +template +template +void NDArray::reallocate(const boost::container::static_vector& new_shape) { + // Ensure new shape has proper dimensions + if (new_shape.size() < 1) { + std::string mssg = + "Shape vector must have at least one element to" + " reallocate NDArray."; + throw std::runtime_error(mssg); + } else { + size_t ne = new_shape[0]; + + for (size_t i = 1; i < new_shape.size(); i++) { + ne *= new_shape[i]; + } + shape_.clear(); + shape_.reserve( new_shape.size() ); + for( std::size_t c : new_shape){ + shape_.push_back(c); + } + dimensions_ = shape_.size(); + data_.resize(ne); + } +} + + template template NDArray& NDArray::operator+=(const NDArray& a) {