diff --git a/include/tensorwrapper/buffer/buffer_base.hpp b/include/tensorwrapper/buffer/buffer_base.hpp index a1dd2801..ad46d093 100644 --- a/include/tensorwrapper/buffer/buffer_base.hpp +++ b/include/tensorwrapper/buffer/buffer_base.hpp @@ -28,8 +28,8 @@ namespace tensorwrapper::buffer { * * All classes which wrap existing tensor libraries derive from this class. */ -class BufferBase : public detail_::PolymorphicBase, - public detail_::DSLBase { +class BufferBase : public tensorwrapper::detail_::PolymorphicBase, + public tensorwrapper::detail_::DSLBase { private: /// Type of *this using my_type = BufferBase; @@ -39,7 +39,7 @@ class BufferBase : public detail_::PolymorphicBase, protected: /// Type *this inherits from - using polymorphic_base = detail_::PolymorphicBase; + using polymorphic_base = tensorwrapper::detail_::PolymorphicBase; public: /// Type all buffers inherit from diff --git a/include/tensorwrapper/buffer/contiguous.hpp b/include/tensorwrapper/buffer/contiguous.hpp index 9a944b7c..12b5892c 100644 --- a/include/tensorwrapper/buffer/contiguous.hpp +++ b/include/tensorwrapper/buffer/contiguous.hpp @@ -47,6 +47,8 @@ class Contiguous : public Replicated { /// Type of a read-only reference to an object of type element_type using const_reference = const element_type&; + using element_vector = std::vector; + /// Type of a pointer to a mutable element_type object using pointer = element_type*; @@ -65,77 +67,139 @@ class Contiguous : public Replicated { /// Returns the number of elements in contiguous memory size_type size() const noexcept { return size_(); } - /// Returns a mutable pointer to the first element in contiguous memory - pointer data() noexcept { return data_(); } + /** @brief Returns a mutable pointer to the first element in contiguous + * memory + * + * @warning Returning a mutable pointer to the underlying data makes it + * no longer possible for *this to reliably track changes to that + * data. Calling this method may have performance implications, so + * use only when strictly required. + * + * @return A read/write pointer to the data. + * + * @throw None No throw guarantee. + */ + pointer get_mutable_data() noexcept { return get_mutable_data_(); } - /// Returns a read-only pointer to the first element in contiguous memory - const_pointer data() const noexcept { return data_(); } + /** @brief Returns an immutable pointer to the first element in contiguous + * memory + * + * @return A read-only pointer to the data. + * + * @throw None No throw guarantee. + */ + const_pointer get_immutable_data() const noexcept { + return get_immutable_data_(); + } /** @brief Retrieves a tensor element by offset. * - * @tparam Args The types of each offset. Must decay to integral types. + * This method is used to access the element in an immutable way. * - * @param[in] args The offsets such that the i-th value in @p args is the - * offset of the element along the i-th mode of the tensor. + * @param[in] index The offset of the element being retrieved. * - * @return A mutable reference to the element. + * @return A read-only reference to the element. * * @throw std::runtime_error if the number of indices does not match the * rank of the tensor. Strong throw guarantee. */ - template - reference at(Args&&... args) { - static_assert( - std::conjunction_v>...>, - "Offsets must be integral types"); - if(sizeof...(Args) != this->rank()) + const_reference get_elem(index_vector index) const { + if(index.size() != this->rank()) throw std::runtime_error("Number of offsets must match rank"); - return get_elem_( - index_vector{detail_::to_size_t(std::forward(args))...}); + return get_elem_(index); } - /** @brief Retrieves a tensor element by offset. + /** @brief Sets a tensor element by offset. * - * @tparam Args The types of each offset. Must decay to integral types. + * This method is used to change the value of an element. * - * This method is the same as the non-const version except that the result - * is read-only. See the documentation for the mutable version for more - * details. - * - * @param[in] args The offsets such that the i-th value in @p args is the - * offset of the element along the i-th mode of the tensor. - * - * @return A read-only reference to the element. + * @param[in] index The offset of the element being updated. + * @param[in] new_value The new value of the element. * * @throw std::runtime_error if the number of indices does not match the * rank of the tensor. Strong throw guarantee. */ - template - const_reference at(Args&&... args) const { - static_assert( - std::conjunction_v>...>, - "Offsets must be integral types"); - if(sizeof...(Args) != this->rank()) + void set_elem(index_vector index, element_type new_value) { + if(index.size() != this->rank()) throw std::runtime_error("Number of offsets must match rank"); - return get_elem_( - index_vector{detail_::to_size_t(std::forward(args))...}); + return set_elem_(index, new_value); + } + + /** @brief Retrieves a tensor element by ordinal offset. + * + * This method is used to access the element in an immutable way. + * + * @param[in] index The ordinal offset of the element being retrieved. + * + * @return A read-only reference to the element. + * + * @throw std::runtime_error if the index is greater than the number of + * elements. Strong throw guarantee. + */ + const_reference get_data(size_type index) const { + if(index >= this->size()) + throw std::runtime_error("Index greater than number of elements"); + return get_data_(std::move(index)); } + /** @brief Sets a tensor element by ordinal offset. + * + * This method is used to change the value of an element. + * + * @param[in] index The ordinal offset of the element being updated. + * @param[in] new_value The new value of the element. + * + * @throw std::runtime_error if the index is greater than the number of + * elements. Strong throw guarantee. + */ + void set_data(size_type index, element_type new_value) { + if(index >= this->size()) + throw std::runtime_error("Index greater than number of elements"); + set_data_(index, new_value); + } + + /** @brief Sets all elements to a value. + * + * @param[in] value The new value of all elements. + * + * @throw None No throw guarantee. + */ + void fill(element_type value) { fill_(std::move(value)); } + + /** @brief Sets elements using a list of values. + * + * @param[in] values The new values of all elements. + * + * @throw None No throw guarantee. + */ + void copy(const element_vector& values) { copy_(values); } + protected: /// Derived class can override if it likes virtual size_type size_() const noexcept { return layout().shape().size(); } /// Derived class should implement according to data() description - virtual pointer data_() noexcept = 0; + virtual pointer get_mutable_data_() noexcept = 0; /// Derived class should implement according to data() const description - virtual const_pointer data_() const noexcept = 0; - - /// Derived class should implement according to operator()() - virtual reference get_elem_(index_vector index) = 0; + virtual const_pointer get_immutable_data_() const noexcept = 0; - /// Derived class should implement according to operator()()const + /// Derived class should implement according to get_elem() virtual const_reference get_elem_(index_vector index) const = 0; + + /// Derived class should implement according to set_elem() + virtual void set_elem_(index_vector index, element_type new_value) = 0; + + /// Derived class should implement according to get_data() + virtual const_reference get_data_(size_type index) const = 0; + + /// Derived class should implement according to set_data() + virtual void set_data_(size_type index, element_type new_value) = 0; + + /// Derived class should implement according to fill() + virtual void fill_(element_type) = 0; + + virtual void copy_(const element_vector& values) = 0; }; #define DECLARE_CONTIG_BUFFER(TYPE) extern template class Contiguous diff --git a/include/tensorwrapper/buffer/eigen.hpp b/include/tensorwrapper/buffer/eigen.hpp index 8382c60e..12c00ba1 100644 --- a/include/tensorwrapper/buffer/eigen.hpp +++ b/include/tensorwrapper/buffer/eigen.hpp @@ -52,6 +52,8 @@ class Eigen : public Contiguous { using typename my_base_type::const_pointer; using typename my_base_type::const_reference; using typename my_base_type::dsl_reference; + using typename my_base_type::element_type; + using typename my_base_type::element_vector; using typename my_base_type::index_vector; using typename my_base_type::label_type; using typename my_base_type::layout_pointer; @@ -210,17 +212,29 @@ class Eigen : public Contiguous { const_labeled_reference rhs) override; /// Implements getting the raw pointer - pointer data_() noexcept override; + pointer get_mutable_data_() noexcept override; /// Implements getting the raw pointer (read-only) - const_pointer data_() const noexcept override; - - /// Implements mutable element access - reference get_elem_(index_vector index) override; + const_pointer get_immutable_data_() const noexcept override; /// Implements read-only element access const_reference get_elem_(index_vector index) const override; + // Implements element updating + void set_elem_(index_vector index, element_type new_value) override; + + /// Implements read-only element access by ordinal index + const_reference get_data_(size_type index) const override; + + // Implements element updating by ordinal index + void set_data_(size_type index, element_type new_value) override; + + /// Implements filling the tensor + void fill_(element_type value) override; + + /// Implements copying new values into the tensor + void copy_(const element_vector& values) override; + /// Implements to_string typename polymorphic_base::string_type to_string_() const override; diff --git a/src/python/tensor/export_tensor.cpp b/src/python/tensor/export_tensor.cpp index f22b4364..a174595d 100644 --- a/src/python/tensor/export_tensor.cpp +++ b/src/python/tensor/export_tensor.cpp @@ -39,8 +39,8 @@ auto make_buffer_info(buffer::Contiguous& buffer) { stride_i *= smooth_shape.extent(mode_i); strides[rank_i] = stride_i * nbytes; } - return pybind11::buffer_info(buffer.data(), nbytes, desc, rank, shape, - strides); + return pybind11::buffer_info(buffer.get_mutable_data(), nbytes, desc, rank, + shape, strides); } auto make_tensor(pybind11::buffer b) { @@ -60,8 +60,8 @@ auto make_tensor(pybind11::buffer b) { auto n_elements = std::accumulate(dims.begin(), dims.end(), 1, std::multiplies()); - for(auto i = 0; i < n_elements; ++i) - pBuffer->data()[i] = static_cast(info.ptr)[i]; + auto pData = static_cast(info.ptr); + for(auto i = 0; i < n_elements; ++i) pBuffer->set_data(i, pData[i]); return Tensor(matrix_shape, std::move(pBuffer)); } diff --git a/src/tensorwrapper/allocator/eigen.cpp b/src/tensorwrapper/allocator/eigen.cpp index a97f182c..d493ecae 100644 --- a/src/tensorwrapper/allocator/eigen.cpp +++ b/src/tensorwrapper/allocator/eigen.cpp @@ -100,8 +100,7 @@ typename EIGEN::contiguous_pointer EIGEN::construct_(layout_pointer playout, element_type value) { auto pbuffer = this->allocate(std::move(playout)); auto& contig_buffer = static_cast&>(*pbuffer); - auto* pdata = contig_buffer.data(); - std::fill(pdata, pdata + contig_buffer.size(), value); + contig_buffer.fill(value); return pbuffer; } @@ -115,7 +114,7 @@ typename EIGEN::contiguous_pointer EIGEN::il_construct_(ILType il) { auto playout = std::make_unique(std::move(shape)); auto pbuffer = this->allocate(std::move(playout)); auto& buffer_down = rebind(*pbuffer); - std::copy(data.begin(), data.end(), buffer_down.data()); + buffer_down.copy(data); return pbuffer; } diff --git a/src/tensorwrapper/buffer/detail_/eigen_pimpl.hpp b/src/tensorwrapper/buffer/detail_/eigen_pimpl.hpp index d19107b6..d3a790ee 100644 --- a/src/tensorwrapper/buffer/detail_/eigen_pimpl.hpp +++ b/src/tensorwrapper/buffer/detail_/eigen_pimpl.hpp @@ -33,6 +33,8 @@ class EigenPIMPL using parent_type = Eigen; using pimpl_pointer = typename parent_type::pimpl_pointer; using label_type = typename parent_type::label_type; + using element_type = typename parent_type::element_type; + using element_vector = typename parent_type::element_vector; using reference = typename parent_type::reference; using const_shape_reference = const shape::ShapeBase&; using const_reference = typename parent_type::const_reference; @@ -48,23 +50,44 @@ class EigenPIMPL eigen_rank_type rank() const noexcept { return rank_(); } + size_type size() const noexcept { return size_(); } + size_type extent(eigen_rank_type i) const { assert(i < rank()); return extent_(i); } - pointer data() noexcept { return data_(); } + pointer get_mutable_data() noexcept { return get_mutable_data_(); } - const_pointer data() const noexcept { return data_(); } + const_pointer get_immutable_data() const noexcept { + return get_immutable_data_(); + } - reference get_elem(index_vector index) { + const_reference get_elem(index_vector index) const { assert(index.size() == rank()); return get_elem_(std::move(index)); } - const_reference get_elem(index_vector index) const { + void set_elem(index_vector index, element_type new_value) { assert(index.size() == rank()); - return get_elem_(std::move(index)); + set_elem_(index, new_value); + } + + const_reference get_data(size_type index) const { + assert(index < size()); + return get_data_(std::move(index)); + } + + void set_data(size_type index, element_type new_value) { + assert(index < size()); + set_data_(index, new_value); + } + + void fill(element_type value) { fill_(std::move(value)); } + + void copy(const element_vector& values) { + assert(values.size() <= size()); + copy_(values); } void addition_assignment(label_type this_labels, label_type lhs_labels, @@ -110,39 +133,44 @@ class EigenPIMPL } protected: - virtual eigen_rank_type rank_() const noexcept = 0; - virtual size_type extent_(eigen_rank_type i) const = 0; - virtual pointer data_() noexcept = 0; - virtual const_pointer data_() const noexcept = 0; - virtual reference get_elem_(index_vector index) = 0; - virtual const_reference get_elem_(index_vector index) const = 0; + virtual eigen_rank_type rank_() const noexcept = 0; + virtual size_type size_() const = 0; + virtual size_type extent_(eigen_rank_type i) const = 0; + virtual pointer get_mutable_data_() noexcept = 0; + virtual const_pointer get_immutable_data_() const noexcept = 0; + virtual const_reference get_elem_(index_vector index) const = 0; + virtual void set_elem_(index_vector index, element_type new_value) = 0; + virtual const_reference get_data_(size_type index) const = 0; + virtual void set_data_(size_type index, element_type new_value) = 0; + virtual void fill_(element_type value) = 0; + virtual void copy_(const element_vector& values) = 0; virtual void addition_assignment_(label_type this_labels, label_type lhs_labels, label_type rhs_labels, const_pimpl_reference lhs, - const_pimpl_reference rhs) = 0; + const_pimpl_reference rhs) = 0; virtual void subtraction_assignment_(label_type this_labels, label_type lhs_labels, label_type rhs_labels, const_pimpl_reference lhs, - const_pimpl_reference rhs) = 0; + const_pimpl_reference rhs) = 0; virtual void hadamard_assignment_(label_type this_labels, label_type lhs_labels, label_type rhs_labels, const_pimpl_reference lhs, - const_pimpl_reference rhs) = 0; + const_pimpl_reference rhs) = 0; virtual void contraction_assignment_(label_type this_labels, label_type lhs_labels, label_type rhs_labels, const_shape_reference result_shape, const_pimpl_reference lhs, - const_pimpl_reference rhs) = 0; + const_pimpl_reference rhs) = 0; virtual void permute_assignment_(label_type this_labels, label_type rhs_labels, - const_pimpl_reference rhs) = 0; + const_pimpl_reference rhs) = 0; virtual void scalar_multiplication_(label_type this_labels, label_type rhs_labels, FloatType scalar, - const_pimpl_reference rhs) = 0; + const_pimpl_reference rhs) = 0; }; } // namespace tensorwrapper::buffer::detail_ \ No newline at end of file diff --git a/src/tensorwrapper/buffer/detail_/eigen_tensor.cpp b/src/tensorwrapper/buffer/detail_/eigen_tensor.cpp index dca92628..0d66206f 100644 --- a/src/tensorwrapper/buffer/detail_/eigen_tensor.cpp +++ b/src/tensorwrapper/buffer/detail_/eigen_tensor.cpp @@ -32,9 +32,9 @@ void EIGEN_TENSOR::element_wise_op_(OperationType op, label_type this_labels, const_pimpl_reference rhs) { // Downcast LHS and RHS const auto* lhs_down = dynamic_cast(&lhs); - const auto& lhs_eigen = lhs_down->value(); + const auto& lhs_eigen = lhs_down->m_tensor_; const auto* rhs_down = dynamic_cast(&rhs); - const auto& rhs_eigen = rhs_down->value(); + const auto& rhs_eigen = rhs_down->m_tensor_; // Whose indices match whose? bool this_matches_lhs = (this_labels == lhs_labels); @@ -61,6 +61,7 @@ void EIGEN_TENSOR::element_wise_op_(OperationType op, label_type this_labels, } else { // Everything needs permuted m_tensor_ = op(lhs_eigen.shuffle(l_to_r), rhs_eigen).shuffle(this_to_r); } + mark_for_rehash_(); } TPARAMS @@ -72,6 +73,7 @@ void EIGEN_TENSOR::addition_assignment_(label_type this_labels, auto lambda = [](auto&& lhs, auto&& rhs) { return lhs + rhs; }; element_wise_op_(lambda, std::move(this_labels), std::move(lhs_labels), std::move(rhs_labels), lhs, rhs); + mark_for_rehash_(); } template @@ -110,8 +112,8 @@ void EIGEN_TENSOR::contraction_assignment_(label_type olabels, eigen::data_type buffer(lrows, rcols); - map_t lmatrix(lt->data(), lrows, lcols); - map_t rmatrix(rt->data(), rrows, rcols); + map_t lmatrix(lt->get_mutable_data(), lrows, lcols); + map_t rmatrix(rt->get_mutable_data(), rrows, rcols); map_t omatrix(buffer.data(), lrows, rcols); omatrix = lmatrix * rmatrix; @@ -138,6 +140,7 @@ void EIGEN_TENSOR::contraction_assignment_(label_type olabels, } else { m_tensor_ = tensor; } + mark_for_rehash_(); } TPARAMS @@ -149,6 +152,7 @@ void EIGEN_TENSOR::hadamard_assignment_(label_type this_labels, auto lambda = [](auto&& lhs, auto&& rhs) { return lhs * rhs; }; element_wise_op_(lambda, std::move(this_labels), std::move(lhs_labels), std::move(rhs_labels), lhs, rhs); + mark_for_rehash_(); } TPARAMS @@ -162,10 +166,11 @@ void EIGEN_TENSOR::permute_assignment_(label_type this_labels, auto r_to_l = this_labels.permutation(rhs_labels); // Eigen wants int objects std::vector r_to_l2(r_to_l.begin(), r_to_l.end()); - m_tensor_ = rhs_down->value().shuffle(r_to_l2); + m_tensor_ = rhs_down->m_tensor_.shuffle(r_to_l2); } else { - m_tensor_ = rhs_down->value(); + m_tensor_ = rhs_down->m_tensor_; } + mark_for_rehash_(); } TPARAMS @@ -179,10 +184,11 @@ void EIGEN_TENSOR::scalar_multiplication_(label_type this_labels, auto r_to_l = rhs_labels.permutation(this_labels); // Eigen wants int objects std::vector r_to_l2(r_to_l.begin(), r_to_l.end()); - m_tensor_ = rhs_downcasted->value().shuffle(r_to_l2) * scalar; + m_tensor_ = rhs_downcasted->m_tensor_.shuffle(r_to_l2) * scalar; } else { - m_tensor_ = rhs_downcasted->value() * scalar; + m_tensor_ = rhs_downcasted->m_tensor_ * scalar; } + mark_for_rehash_(); } TPARAMS @@ -194,6 +200,17 @@ void EIGEN_TENSOR::subtraction_assignment_(label_type this_labels, auto lambda = [](auto&& lhs, auto&& rhs) { return lhs - rhs; }; element_wise_op_(lambda, std::move(this_labels), std::move(lhs_labels), std::move(rhs_labels), lhs, rhs); + mark_for_rehash_(); +} + +TPARAMS +void EIGEN_TENSOR::update_hash_() const { + m_hash_ = hash_type{rank_()}; + for(eigen_rank_type i = 0; i < rank_(); ++i) + hash_utilities::hash_input(m_hash_, m_tensor_.dimension(i)); + for(auto i = 0; i < m_tensor_.size(); ++i) + hash_utilities::hash_input(m_hash_, m_tensor_.data()[i]); + m_recalculate_hash_ = false; } #undef EIGEN_TENSOR diff --git a/src/tensorwrapper/buffer/detail_/eigen_tensor.hpp b/src/tensorwrapper/buffer/detail_/eigen_tensor.hpp index 181b8848..ad6d2449 100644 --- a/src/tensorwrapper/buffer/detail_/eigen_tensor.hpp +++ b/src/tensorwrapper/buffer/detail_/eigen_tensor.hpp @@ -16,6 +16,7 @@ #pragma once #include "eigen_pimpl.hpp" +#include "hash_utilities.hpp" #include #include #include @@ -36,6 +37,8 @@ class EigenTensor : public EigenPIMPL { using typename base_type::const_reference; using typename base_type::const_shape_reference; using typename base_type::eigen_rank_type; + using typename base_type::element_type; + using typename base_type::element_vector; using typename base_type::index_vector; using typename base_type::label_type; using typename base_type::pimpl_pointer; @@ -50,6 +53,7 @@ class EigenTensor : public EigenPIMPL { using eigen_data_type = eigen::data_type; using eigen_reference = eigen_data_type&; using const_eigen_reference = const eigen_data_type&; + using hash_type = hash_utilities::hash_type; EigenTensor() = default; @@ -57,16 +61,16 @@ class EigenTensor : public EigenPIMPL { m_tensor_(allocate_from_shape_(shape, std::make_index_sequence())) { } - /// Get a mutable/read-only reference to the Eigen tensor object - ///@{ - eigen_reference value() noexcept { return m_tensor_; } - const_eigen_reference value() const noexcept { return m_tensor_; } - ///@} - /// Tests for exact equality bool operator==(const my_type& rhs) const noexcept { - eigen::data_type eq = (m_tensor_ == rhs.m_tensor_).all(); - return eq(); + return get_hash() == rhs.get_hash(); + } + + // Returns the hash for the current state of *this, computing first if + // needed. + hash_type get_hash() const { + if(m_recalculate_hash_ or !m_hash_caching_) update_hash_(); + return m_hash_; } protected: @@ -76,23 +80,51 @@ class EigenTensor : public EigenPIMPL { eigen_rank_type rank_() const noexcept override { return Rank; } + size_type size_() const noexcept override { return m_tensor_.size(); } + size_type extent_(eigen_rank_type i) const override { return m_tensor_.dimension(i); } - pointer data_() noexcept override { return m_tensor_.data(); } - - const_pointer data_() const noexcept override { return m_tensor_.data(); } + pointer get_mutable_data_() noexcept override { + turn_off_hash_caching_(); + return m_tensor_.data(); + } - reference get_elem_(index_vector index) override { - return unwrap_vector_(std::move(index), - std::make_index_sequence()); + const_pointer get_immutable_data_() const noexcept override { + return m_tensor_.data(); } + const_reference get_elem_(index_vector index) const override { return unwrap_vector_(std::move(index), std::make_index_sequence()); } + void set_elem_(index_vector index, element_type new_value) override { + mark_for_rehash_(); + unwrap_vector_(std::move(index), std::make_index_sequence()) = + new_value; + } + + const_reference get_data_(size_type index) const override { + return m_tensor_.data()[index]; + } + + void set_data_(size_type index, element_type new_value) override { + mark_for_rehash_(); + m_tensor_.data()[index] = new_value; + } + + void fill_(element_type value) override { + mark_for_rehash_(); + std::fill(m_tensor_.data(), m_tensor_.data() + m_tensor_.size(), value); + } + + void copy_(const element_vector& values) override { + mark_for_rehash_(); + std::copy(values.begin(), values.end(), m_tensor_.data()); + } + bool are_equal_(const_base_reference rhs) const noexcept override { return base_type::template are_equal_impl_(rhs); } @@ -160,6 +192,26 @@ class EigenTensor : public EigenPIMPL { return m_tensor_(tensorwrapper::detail_::to_long(index.at(I))...); } + // Computes the hash for the current state of *this + void update_hash_() const; + + // Designates that the state may have changed and to recalculate the hash. + // This function is really just for readability and clarity. + void mark_for_rehash_() const { m_recalculate_hash_ = true; } + + // Designates that state changes are not trackable and we should recalculate + // the hash each time. + void turn_off_hash_caching_() const { m_hash_caching_ = false; } + + // Tracks whether the hash needs to be redetermined + mutable bool m_recalculate_hash_ = true; + + // Tracks whether hash caching has been turned off + mutable bool m_hash_caching_ = true; + + // Holds the computed hash value for this instance's state + mutable hash_type m_hash_; + // The Eigen tensor *this wraps eigen_data_type m_tensor_; }; diff --git a/src/tensorwrapper/buffer/detail_/hash_utilities.hpp b/src/tensorwrapper/buffer/detail_/hash_utilities.hpp new file mode 100644 index 00000000..0ede2495 --- /dev/null +++ b/src/tensorwrapper/buffer/detail_/hash_utilities.hpp @@ -0,0 +1,71 @@ +/* + * Copyright 2025 NWChemEx-Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include +#include + +/** @namespace tensorwrapper::buffer::detail_::hash_utilities + * @brief Utilities for hashing EigenTensor instances + */ +namespace tensorwrapper::buffer::detail_::hash_utilities { + +/// The type of a hash +using hash_type = std::size_t; + +/** @brief Adds the hash of an input value to the seed hash + * + * @tparam InputType The type of the value being added to the hash + * @param[in,out] seed The initial value of the hash, which is overwritten when + * the new value is added. + * @param[in] value The new value being hashed and combined with the @p seed. + * + * @return The updated hash value + * + * @throw none No throw guarantee + */ +template +void hash_input(hash_type& seed, const InputType& value) { + boost::hash_combine(seed, value); +} + +#ifdef ENABLE_SIGMA + +/** @brief Specialization for sigma::Uncertain values + * + * @tparam T The floating point type of the uncertain value + * @param[in,out] seed The initial value of the hash, which is overwritten when + * the new value is added. + * @param[in] value The new uncertain value being hashed and combined with the + * seed. + * + * @return The updated hash value + * + * @throw none No throw guarantee + */ +template +void hash_input(hash_type& seed, const sigma::Uncertain& value) { + hash_input(seed, value.mean()); + hash_input(seed, value.sd()); + for(const auto& [dep, deriv] : value.deps()) { + hash_input(seed, dep); + hash_input(seed, deriv); + } +} + +#endif + +} // namespace tensorwrapper::buffer::detail_::hash_utilities \ No newline at end of file diff --git a/src/tensorwrapper/buffer/eigen.cpp b/src/tensorwrapper/buffer/eigen.cpp index a15010ce..b97a4fc6 100644 --- a/src/tensorwrapper/buffer/eigen.cpp +++ b/src/tensorwrapper/buffer/eigen.cpp @@ -155,28 +155,50 @@ typename EIGEN::dsl_reference EIGEN::scalar_multiplication_( } TPARAMS -typename EIGEN::pointer EIGEN::data_() noexcept { - return m_pimpl_ ? m_pimpl_->data() : nullptr; +typename EIGEN::pointer EIGEN::get_mutable_data_() noexcept { + return m_pimpl_ ? m_pimpl_->get_mutable_data() : nullptr; } TPARAMS -typename EIGEN::const_pointer EIGEN::data_() const noexcept { - return m_pimpl_ ? m_pimpl_->data() : nullptr; +typename EIGEN::const_pointer EIGEN::get_immutable_data_() const noexcept { + return m_pimpl_ ? m_pimpl_->get_immutable_data() : nullptr; } TPARAMS -typename EIGEN::reference EIGEN::get_elem_(index_vector index) { +typename EIGEN::const_reference EIGEN::get_elem_(index_vector index) const { return pimpl_().get_elem(std::move(index)); } TPARAMS -typename EIGEN::const_reference EIGEN::get_elem_(index_vector index) const { - return pimpl_().get_elem(std::move(index)); +void EIGEN::set_elem_(index_vector index, element_type new_value) { + return pimpl_().set_elem(std::move(index), std::move(new_value)); } + +TPARAMS +typename EIGEN::const_reference EIGEN::get_data_(size_type index) const { + return pimpl_().get_data(std::move(index)); +} + +TPARAMS +void EIGEN::set_data_(size_type index, element_type new_value) { + return pimpl_().set_data(std::move(index), std::move(new_value)); +} + +TPARAMS +void EIGEN::fill_(element_type value) { + return pimpl_().fill(std::move(value)); +} + +TPARAMS +void EIGEN::copy_(const element_vector& values) { + return pimpl_().copy(values); +} + TPARAMS typename EIGEN::polymorphic_base::string_type EIGEN::to_string_() const { return m_pimpl_ ? m_pimpl_->to_string() : ""; } + TPARAMS std::ostream& EIGEN::add_to_stream_(std::ostream& os) const { return m_pimpl_ ? m_pimpl_->add_to_stream(os) : os; diff --git a/src/tensorwrapper/operations/approximately_equal.cpp b/src/tensorwrapper/operations/approximately_equal.cpp index a3675b0a..f3174fc3 100644 --- a/src/tensorwrapper/operations/approximately_equal.cpp +++ b/src/tensorwrapper/operations/approximately_equal.cpp @@ -31,7 +31,7 @@ struct Kernel { auto& buffer_down = allocator_type::rebind(result); for(std::size_t i = 0; i < buffer_down.size(); ++i) { - auto diff = *(buffer_down.data() + i); + auto diff = buffer_down.get_data(i); if(diff < zero) diff *= -1.0; if(diff >= ptol) return false; } diff --git a/src/tensorwrapper/operations/norm.cpp b/src/tensorwrapper/operations/norm.cpp index 3021960d..19c45c71 100644 --- a/src/tensorwrapper/operations/norm.cpp +++ b/src/tensorwrapper/operations/norm.cpp @@ -29,7 +29,7 @@ struct InfinityKernel { FloatType max_element{0.0}; const auto& buffer_down = alloc.rebind(t); for(std::size_t i = 0; i < buffer_down.size(); ++i) { - auto elem = types::fabs(*(buffer_down.data() + i)); + auto elem = types::fabs(buffer_down.get_data(i)); if(elem > max_element) max_element = elem; } shape::Smooth s{}; diff --git a/tests/cxx/unit_tests/tensorwrapper/allocator/contiguous.cpp b/tests/cxx/unit_tests/tensorwrapper/allocator/contiguous.cpp index cdf70f29..8c6db1d4 100644 --- a/tests/cxx/unit_tests/tensorwrapper/allocator/contiguous.cpp +++ b/tests/cxx/unit_tests/tensorwrapper/allocator/contiguous.cpp @@ -31,18 +31,18 @@ TEMPLATE_LIST_TEST_CASE("allocator::Contiguous", "", auto matrix_corr = testing::eigen_matrix(); SECTION("allocate(layout)") { - auto pscalar = alloc.allocate(scalar_corr->layout()); - pscalar->at() = 42.0; + auto pscalar = alloc.allocate(scalar_corr->layout()); + pscalar->set_data(0, 42.0); REQUIRE(pscalar->are_equal(*scalar_corr)); } SECTION("allocate(layout*)") { - auto pvector = alloc.allocate(vector_corr->layout()); - pvector->at(0) = 0.0; - pvector->at(1) = 1.0; - pvector->at(2) = 2.0; - pvector->at(3) = 3.0; - pvector->at(4) = 4.0; + auto pvector = alloc.allocate(vector_corr->layout()); + pvector->set_data(0, 0.0); + pvector->set_data(1, 1.0); + pvector->set_data(2, 2.0); + pvector->set_data(3, 3.0); + pvector->set_data(4, 4.0); REQUIRE(pvector->are_equal(*vector_corr)); } @@ -79,11 +79,11 @@ TEMPLATE_LIST_TEST_CASE("allocator::Contiguous", "", } SECTION("construct(layout, value)") { - auto pmatrix = alloc.construct(matrix_corr->layout(), 0.0); - matrix_corr->at(0, 0) = 0.0; - matrix_corr->at(0, 1) = 0.0; - matrix_corr->at(1, 0) = 0.0; - matrix_corr->at(1, 1) = 0.0; + auto pmatrix = alloc.construct(matrix_corr->layout(), 0.0); + matrix_corr->set_elem({0, 0}, 0.0); + matrix_corr->set_elem({0, 1}, 0.0); + matrix_corr->set_elem({1, 0}, 0.0); + matrix_corr->set_elem({1, 1}, 0.0); REQUIRE(pmatrix->are_equal(*matrix_corr)); } @@ -91,10 +91,10 @@ TEMPLATE_LIST_TEST_CASE("allocator::Contiguous", "", SECTION("construct(layout*, value)") { auto pmatrix = alloc.construct( matrix_corr->layout().template clone_as(), 0.0); - matrix_corr->at(0, 0) = 0.0; - matrix_corr->at(0, 1) = 0.0; - matrix_corr->at(1, 0) = 0.0; - matrix_corr->at(1, 1) = 0.0; + matrix_corr->set_elem({0, 0}, 0.0); + matrix_corr->set_elem({0, 1}, 0.0); + matrix_corr->set_elem({1, 0}, 0.0); + matrix_corr->set_elem({1, 1}, 0.0); REQUIRE(pmatrix->are_equal(*matrix_corr)); } diff --git a/tests/cxx/unit_tests/tensorwrapper/allocator/eigen.cpp b/tests/cxx/unit_tests/tensorwrapper/allocator/eigen.cpp index 948fce69..5e50001f 100644 --- a/tests/cxx/unit_tests/tensorwrapper/allocator/eigen.cpp +++ b/tests/cxx/unit_tests/tensorwrapper/allocator/eigen.cpp @@ -35,19 +35,19 @@ TEMPLATE_LIST_TEST_CASE("EigenAllocator", "", types2test) { auto pscalar_corr = testing::eigen_scalar(); auto& scalar_corr = *pscalar_corr; - scalar_corr.at() = 0.0; + scalar_corr.set_elem({}, 0.0); auto pvector_corr = testing::eigen_vector(2); auto& vector_corr = *pvector_corr; - vector_corr.at(0) = 1; - vector_corr.at(1) = 1; - - auto pmatrix_corr = testing::eigen_matrix(2, 2); - auto& matrix_corr = *pmatrix_corr; - matrix_corr.at(0, 0) = 2; - matrix_corr.at(0, 1) = 2; - matrix_corr.at(1, 0) = 2; - matrix_corr.at(1, 1) = 2; + vector_corr.set_elem({0}, 1); + vector_corr.set_elem({1}, 1); + + auto pmatrix_corr = testing::eigen_matrix(2, 2); + auto& matrix_corr = *pmatrix_corr; + matrix_corr.set_elem({0, 0}, 2); + matrix_corr.set_elem({0, 1}, 2); + matrix_corr.set_elem({1, 0}, 2); + matrix_corr.set_elem({1, 1}, 2); alloc_type alloc(rv); diff --git a/tests/cxx/unit_tests/tensorwrapper/buffer/buffer_base.cpp b/tests/cxx/unit_tests/tensorwrapper/buffer/buffer_base.cpp index 81ff984b..3ef4784c 100644 --- a/tests/cxx/unit_tests/tensorwrapper/buffer/buffer_base.cpp +++ b/tests/cxx/unit_tests/tensorwrapper/buffer/buffer_base.cpp @@ -36,13 +36,13 @@ using namespace buffer; TEST_CASE("BufferBase") { auto pscalar = testing::eigen_scalar(); auto& scalar = *pscalar; - scalar.at() = 1.0; + scalar.set_elem({}, 1.0); auto pvector = testing::eigen_vector(2); auto& vector = *pvector; - vector.at(0) = 1.0; - vector.at(1) = 2.0; + vector.set_elem({0}, 1.0); + vector.set_elem({1}, 2.0); auto scalar_layout = testing::scalar_physical(); auto vector_layout = testing::vector_physical(2); diff --git a/tests/cxx/unit_tests/tensorwrapper/buffer/contiguous.cpp b/tests/cxx/unit_tests/tensorwrapper/buffer/contiguous.cpp index e3999e87..5c59e2c8 100644 --- a/tests/cxx/unit_tests/tensorwrapper/buffer/contiguous.cpp +++ b/tests/cxx/unit_tests/tensorwrapper/buffer/contiguous.cpp @@ -46,49 +46,89 @@ TEMPLATE_LIST_TEST_CASE("buffer::Contiguous", "", types::floating_point_types) { REQUIRE(base1.size() == 5); } - SECTION("data()") { - REQUIRE(*base0.data() == TestType(42.0)); - - REQUIRE(*(base1.data() + 0) == TestType(0.0)); - REQUIRE(*(base1.data() + 1) == TestType(1.0)); - REQUIRE(*(base1.data() + 2) == TestType(2.0)); - REQUIRE(*(base1.data() + 3) == TestType(3.0)); - REQUIRE(*(base1.data() + 4) == TestType(4.0)); + SECTION("get_mutable_data()") { + REQUIRE(*base0.get_mutable_data() == TestType(42.0)); + + REQUIRE(*(base1.get_mutable_data() + 0) == TestType(0.0)); + REQUIRE(*(base1.get_mutable_data() + 1) == TestType(1.0)); + REQUIRE(*(base1.get_mutable_data() + 2) == TestType(2.0)); + REQUIRE(*(base1.get_mutable_data() + 3) == TestType(3.0)); + REQUIRE(*(base1.get_mutable_data() + 4) == TestType(4.0)); } - SECTION("data() const") { - REQUIRE(*std::as_const(base0).data() == TestType(42.0)); + SECTION("get_immutable_data() const") { + REQUIRE(*std::as_const(base0).get_immutable_data() == TestType(42.0)); + + REQUIRE(*(std::as_const(base1).get_immutable_data() + 0) == + TestType(0.0)); + REQUIRE(*(std::as_const(base1).get_immutable_data() + 1) == + TestType(1.0)); + REQUIRE(*(std::as_const(base1).get_immutable_data() + 2) == + TestType(2.0)); + REQUIRE(*(std::as_const(base1).get_immutable_data() + 3) == + TestType(3.0)); + REQUIRE(*(std::as_const(base1).get_immutable_data() + 4) == + TestType(4.0)); + } + + SECTION("get_elem() const") { + REQUIRE(base0.get_elem({}) == TestType(42.0)); + + REQUIRE(base1.get_elem({0}) == TestType(0.0)); + REQUIRE(base1.get_elem({1}) == TestType(1.0)); + REQUIRE(base1.get_elem({2}) == TestType(2.0)); + REQUIRE(base1.get_elem({3}) == TestType(3.0)); + REQUIRE(base1.get_elem({4}) == TestType(4.0)); + + REQUIRE_THROWS_AS(base0.get_elem({0}), std::runtime_error); + } - REQUIRE(*(std::as_const(base1).data() + 0) == TestType(0.0)); - REQUIRE(*(std::as_const(base1).data() + 1) == TestType(1.0)); - REQUIRE(*(std::as_const(base1).data() + 2) == TestType(2.0)); - REQUIRE(*(std::as_const(base1).data() + 3) == TestType(3.0)); - REQUIRE(*(std::as_const(base1).data() + 4) == TestType(4.0)); + SECTION("set_elem() const") { + base0.set_elem({}, TestType(43.0)); + REQUIRE(base0.get_elem({}) == TestType(43.0)); + + base1.set_elem({0}, TestType(43.0)); + REQUIRE(base1.get_elem({0}) == TestType(43.0)); + + REQUIRE_THROWS_AS(base0.set_elem({0}, TestType{0.0}), + std::runtime_error); } - SECTION("at()") { - REQUIRE(base0.at() == TestType(42.0)); + SECTION("get_data() const") { + REQUIRE(base0.get_data(0) == TestType(42.0)); - REQUIRE(base1.at(0) == TestType(0.0)); - REQUIRE(base1.at(1) == TestType(1.0)); - REQUIRE(base1.at(2) == TestType(2.0)); - REQUIRE(base1.at(3) == TestType(3.0)); - REQUIRE(base1.at(4) == TestType(4.0)); + REQUIRE(base1.get_data(0) == TestType(0.0)); + REQUIRE(base1.get_data(1) == TestType(1.0)); + REQUIRE(base1.get_data(2) == TestType(2.0)); + REQUIRE(base1.get_data(3) == TestType(3.0)); + REQUIRE(base1.get_data(4) == TestType(4.0)); - REQUIRE_THROWS_AS(base0.at(0), std::runtime_error); - REQUIRE_THROWS_AS(base1.at(0, 1), std::runtime_error); + REQUIRE_THROWS_AS(base0.get_data(1), std::runtime_error); } - SECTION("at()const") { - REQUIRE(std::as_const(base0).at() == TestType(42.0)); + SECTION("set_data() const") { + base0.set_data(0, TestType(43.0)); + REQUIRE(base0.get_elem({}) == TestType(43.0)); - REQUIRE(std::as_const(base1).at(0) == TestType(0.0)); - REQUIRE(std::as_const(base1).at(1) == TestType(1.0)); - REQUIRE(std::as_const(base1).at(2) == TestType(2.0)); - REQUIRE(std::as_const(base1).at(3) == TestType(3.0)); - REQUIRE(std::as_const(base1).at(4) == TestType(4.0)); + REQUIRE_THROWS_AS(base0.set_data(1, TestType{0.0}), std::runtime_error); + } + + SECTION("fill()") { + base1.fill(TestType{43.0}); + REQUIRE(base1.get_data(0) == TestType(43.0)); + REQUIRE(base1.get_data(1) == TestType(43.0)); + REQUIRE(base1.get_data(2) == TestType(43.0)); + REQUIRE(base1.get_data(3) == TestType(43.0)); + REQUIRE(base1.get_data(4) == TestType(43.0)); + } - REQUIRE_THROWS_AS(std::as_const(base0).at(0), std::runtime_error); - REQUIRE_THROWS_AS(std::as_const(base1).at(0, 1), std::runtime_error); + SECTION("copy()") { + auto data = std::vector(5, TestType(43.0)); + base1.copy(data); + REQUIRE(base1.get_data(0) == TestType(43.0)); + REQUIRE(base1.get_data(1) == TestType(43.0)); + REQUIRE(base1.get_data(2) == TestType(43.0)); + REQUIRE(base1.get_data(3) == TestType(43.0)); + REQUIRE(base1.get_data(4) == TestType(43.0)); } } \ No newline at end of file diff --git a/tests/cxx/unit_tests/tensorwrapper/buffer/detail_/eigen_tensor.cpp b/tests/cxx/unit_tests/tensorwrapper/buffer/detail_/eigen_tensor.cpp index 4ca0fcdd..e7f565e6 100644 --- a/tests/cxx/unit_tests/tensorwrapper/buffer/detail_/eigen_tensor.cpp +++ b/tests/cxx/unit_tests/tensorwrapper/buffer/detail_/eigen_tensor.cpp @@ -21,58 +21,95 @@ using namespace tensorwrapper; using namespace testing; +using buffer::detail_::hash_utilities::hash_input; + template using pimpl_type = buffer::detail_::EigenTensor; using shape_type = shape::Smooth; // Should be the same regardless of template parameters using label_type = typename pimpl_type::label_type; +using hash_type = typename pimpl_type::hash_type; TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { pimpl_type scalar(shape_type{}); - scalar.get_elem({}) = 1.0; + scalar.set_elem({}, 1.0); pimpl_type vector(shape_type{2}); - vector.get_elem({0}) = 1.0; - vector.get_elem({1}) = 2.0; + vector.set_elem({0}, 1.0); + vector.set_elem({1}, 2.0); pimpl_type matrix(shape_type{2, 2}); - matrix.get_elem({0, 0}) = 1.0; - matrix.get_elem({0, 1}) = 2.0; - matrix.get_elem({1, 0}) = 3.0; - matrix.get_elem({1, 1}) = 4.0; + matrix.set_elem({0, 0}, 1.0); + matrix.set_elem({0, 1}, 2.0); + matrix.set_elem({1, 0}, 3.0); + matrix.set_elem({1, 1}, 4.0); pimpl_type tensor(shape_type{2, 2, 2}); - tensor.get_elem({0, 0, 0}) = 1.0; - tensor.get_elem({0, 0, 1}) = 2.0; - tensor.get_elem({0, 1, 0}) = 3.0; - tensor.get_elem({0, 1, 1}) = 4.0; - tensor.get_elem({1, 0, 0}) = 5.0; - tensor.get_elem({1, 0, 1}) = 6.0; - tensor.get_elem({1, 1, 0}) = 7.0; - tensor.get_elem({1, 1, 1}) = 8.0; + tensor.set_elem({0, 0, 0}, 1.0); + tensor.set_elem({0, 0, 1}, 2.0); + tensor.set_elem({0, 1, 0}, 3.0); + tensor.set_elem({0, 1, 1}, 4.0); + tensor.set_elem({1, 0, 0}, 5.0); + tensor.set_elem({1, 0, 1}, 6.0); + tensor.set_elem({1, 1, 0}, 7.0); + tensor.set_elem({1, 1, 1}, 8.0); // ------------------------------------------------------------------------- // -- Public methods // ------------------------------------------------------------------------- SECTION("operator==") { - pimpl_type scalar2(scalar); - REQUIRE(scalar2 == scalar); + SECTION("Same State") { + pimpl_type scalar2(scalar); + REQUIRE(scalar2 == scalar); + } - scalar2.get_elem({}) = 42.0; - REQUIRE_FALSE(scalar2 == scalar); + SECTION("Different Value") { + pimpl_type scalar2(scalar); + scalar2.set_elem({}, 42.0); + REQUIRE_FALSE(scalar2 == scalar); + // Ensure hash is recalculated after change + scalar2.set_elem({}, 1.0); + REQUIRE(scalar2 == scalar); + } + + SECTION("Different Extents") { + pimpl_type vector2(shape_type{1}); + vector.set_elem({0}, 1.0); + REQUIRE_FALSE(vector2 == vector); + } if constexpr(types::is_uncertain_v) { SECTION("Check Error Sources Match") { pimpl_type uscalar(shape_type{}); - uscalar.get_elem({}) = TestType(1.0, 0.0); + uscalar.set_elem({}, TestType(1.0, 0.0)); pimpl_type uscalar2(uscalar); REQUIRE(uscalar2 == uscalar); } } } + SECTION("get_hash") { + SECTION("scalar") { + hash_type scalar_hash = scalar.get_hash(); + + hash_type corr{std::as_const(scalar).rank()}; + hash_input(corr, std::as_const(scalar).get_elem({})); + REQUIRE(scalar_hash == corr); + } + SECTION("vector") { + hash_type vector_hash = vector.get_hash(); + + using buffer::detail_::hash_utilities::hash_input; + hash_type corr{std::as_const(vector).rank()}; + hash_input(corr, std::as_const(vector).extent(0)); + hash_input(corr, std::as_const(vector).get_elem({0})); + hash_input(corr, std::as_const(vector).get_elem({1})); + REQUIRE(vector_hash == corr); + } + } + // ------------------------------------------------------------------------- // -- Protected methods // ------------------------------------------------------------------------- @@ -94,6 +131,13 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { REQUIRE(defaulted.rank() == 6); } + SECTION("size_") { + REQUIRE(scalar.size() == 1); + REQUIRE(vector.size() == 2); + REQUIRE(matrix.size() == 4); + REQUIRE(tensor.size() == 8); + } + SECTION("extent_") { REQUIRE(vector.extent(0) == 2); @@ -105,67 +149,75 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { REQUIRE(tensor.extent(2) == 2); } - SECTION("data_()") { - REQUIRE(*scalar.data() == TestType{1.0}); - - REQUIRE(*vector.data() == TestType{1.0}); - REQUIRE(*(vector.data() + 1) == TestType{2.0}); - - REQUIRE(*matrix.data() == TestType{1.0}); - REQUIRE(*(matrix.data() + 1) == TestType{2.0}); - REQUIRE(*(matrix.data() + 2) == TestType{3.0}); - REQUIRE(*(matrix.data() + 3) == TestType{4.0}); - - REQUIRE(*tensor.data() == TestType{1.0}); - REQUIRE(*(tensor.data() + 1) == TestType{2.0}); - REQUIRE(*(tensor.data() + 2) == TestType{3.0}); - REQUIRE(*(tensor.data() + 3) == TestType{4.0}); - REQUIRE(*(tensor.data() + 4) == TestType{5.0}); - REQUIRE(*(tensor.data() + 5) == TestType{6.0}); - REQUIRE(*(tensor.data() + 6) == TestType{7.0}); - REQUIRE(*(tensor.data() + 7) == TestType{8.0}); - } + SECTION("get_mutable_data_()") { + SECTION("accessing") { + REQUIRE(*scalar.get_mutable_data() == TestType{1.0}); + + REQUIRE(*vector.get_mutable_data() == TestType{1.0}); + REQUIRE(*(vector.get_mutable_data() + 1) == TestType{2.0}); + + REQUIRE(*matrix.get_mutable_data() == TestType{1.0}); + REQUIRE(*(matrix.get_mutable_data() + 1) == TestType{2.0}); + REQUIRE(*(matrix.get_mutable_data() + 2) == TestType{3.0}); + REQUIRE(*(matrix.get_mutable_data() + 3) == TestType{4.0}); + + REQUIRE(*tensor.get_mutable_data() == TestType{1.0}); + REQUIRE(*(tensor.get_mutable_data() + 1) == TestType{2.0}); + REQUIRE(*(tensor.get_mutable_data() + 2) == TestType{3.0}); + REQUIRE(*(tensor.get_mutable_data() + 3) == TestType{4.0}); + REQUIRE(*(tensor.get_mutable_data() + 4) == TestType{5.0}); + REQUIRE(*(tensor.get_mutable_data() + 5) == TestType{6.0}); + REQUIRE(*(tensor.get_mutable_data() + 6) == TestType{7.0}); + REQUIRE(*(tensor.get_mutable_data() + 7) == TestType{8.0}); + } - SECTION("data_() const") { - REQUIRE(*std::as_const(scalar).data() == TestType{1.0}); - - REQUIRE(*std::as_const(vector).data() == TestType{1.0}); - REQUIRE(*(std::as_const(vector).data() + 1) == TestType{2.0}); - - REQUIRE(*std::as_const(matrix).data() == TestType{1.0}); - REQUIRE(*(std::as_const(matrix).data() + 1) == TestType{2.0}); - REQUIRE(*(std::as_const(matrix).data() + 2) == TestType{3.0}); - REQUIRE(*(std::as_const(matrix).data() + 3) == TestType{4.0}); - - REQUIRE(*std::as_const(tensor).data() == TestType{1.0}); - REQUIRE(*(std::as_const(tensor).data() + 1) == TestType{2.0}); - REQUIRE(*(std::as_const(tensor).data() + 2) == TestType{3.0}); - REQUIRE(*(std::as_const(tensor).data() + 3) == TestType{4.0}); - REQUIRE(*(std::as_const(tensor).data() + 4) == TestType{5.0}); - REQUIRE(*(std::as_const(tensor).data() + 5) == TestType{6.0}); - REQUIRE(*(std::as_const(tensor).data() + 6) == TestType{7.0}); - REQUIRE(*(std::as_const(tensor).data() + 7) == TestType{8.0}); + SECTION("comparison behavior") { + // Initial state is the same + pimpl_type s(shape_type{}); + s.set_elem({}, 1.0); + REQUIRE(s == scalar); + // Still the same, but the normal hash recalculation flag would be + // reset after this comparison. + auto* pdata = s.get_mutable_data(); + REQUIRE(s == scalar); + // Changes state. The internal hash will have to be recalculated for + // the comparison to be false, ensuring that the hash caching has + // been turned off. + pdata[0] = 2.0; + REQUIRE_FALSE(s == scalar); + } } - SECTION("get_elem_ ()") { - REQUIRE(scalar.get_elem({}) == TestType{1.0}); - - REQUIRE(vector.get_elem({0}) == TestType{1.0}); - REQUIRE(vector.get_elem({1}) == TestType{2.0}); - - REQUIRE(matrix.get_elem({0, 0}) == TestType{1.0}); - REQUIRE(matrix.get_elem({0, 1}) == TestType{2.0}); - REQUIRE(matrix.get_elem({1, 0}) == TestType{3.0}); - REQUIRE(matrix.get_elem({1, 1}) == TestType{4.0}); - - REQUIRE(tensor.get_elem({0, 0, 0}) == TestType{1.0}); - REQUIRE(tensor.get_elem({0, 0, 1}) == TestType{2.0}); - REQUIRE(tensor.get_elem({0, 1, 0}) == TestType{3.0}); - REQUIRE(tensor.get_elem({0, 1, 1}) == TestType{4.0}); - REQUIRE(tensor.get_elem({1, 0, 0}) == TestType{5.0}); - REQUIRE(tensor.get_elem({1, 0, 1}) == TestType{6.0}); - REQUIRE(tensor.get_elem({1, 1, 0}) == TestType{7.0}); - REQUIRE(tensor.get_elem({1, 1, 1}) == TestType{8.0}); + SECTION("get_immutable_data_() const") { + REQUIRE(*std::as_const(scalar).get_immutable_data() == TestType{1.0}); + + REQUIRE(*std::as_const(vector).get_immutable_data() == TestType{1.0}); + REQUIRE(*(std::as_const(vector).get_immutable_data() + 1) == + TestType{2.0}); + + REQUIRE(*std::as_const(matrix).get_immutable_data() == TestType{1.0}); + REQUIRE(*(std::as_const(matrix).get_immutable_data() + 1) == + TestType{2.0}); + REQUIRE(*(std::as_const(matrix).get_immutable_data() + 2) == + TestType{3.0}); + REQUIRE(*(std::as_const(matrix).get_immutable_data() + 3) == + TestType{4.0}); + + REQUIRE(*std::as_const(tensor).get_immutable_data() == TestType{1.0}); + REQUIRE(*(std::as_const(tensor).get_immutable_data() + 1) == + TestType{2.0}); + REQUIRE(*(std::as_const(tensor).get_immutable_data() + 2) == + TestType{3.0}); + REQUIRE(*(std::as_const(tensor).get_immutable_data() + 3) == + TestType{4.0}); + REQUIRE(*(std::as_const(tensor).get_immutable_data() + 4) == + TestType{5.0}); + REQUIRE(*(std::as_const(tensor).get_immutable_data() + 5) == + TestType{6.0}); + REQUIRE(*(std::as_const(tensor).get_immutable_data() + 6) == + TestType{7.0}); + REQUIRE(*(std::as_const(tensor).get_immutable_data() + 7) == + TestType{8.0}); } SECTION("get_elem_() const") { @@ -189,11 +241,63 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { REQUIRE(std::as_const(tensor).get_elem({1, 1, 1}) == TestType{8.0}); } + SECTION("set_elem_()") { + scalar.set_elem({}, TestType{2.0}); + REQUIRE(scalar.get_elem({}) == TestType{2.0}); + + vector.set_elem({0}, TestType{2.0}); + REQUIRE(vector.get_elem({0}) == TestType{2.0}); + REQUIRE(vector.get_elem({1}) == TestType{2.0}); + } + + SECTION("get_data() const") { + REQUIRE(std::as_const(scalar).get_data(0) == TestType{1.0}); + + REQUIRE(std::as_const(vector).get_data(0) == TestType{1.0}); + REQUIRE(std::as_const(vector).get_data(1) == TestType{2.0}); + + REQUIRE(std::as_const(matrix).get_data(0) == TestType{1.0}); + REQUIRE(std::as_const(matrix).get_data(1) == TestType{2.0}); + REQUIRE(std::as_const(matrix).get_data(2) == TestType{3.0}); + REQUIRE(std::as_const(matrix).get_data(3) == TestType{4.0}); + + REQUIRE(std::as_const(tensor).get_data(0) == TestType{1.0}); + REQUIRE(std::as_const(tensor).get_data(1) == TestType{2.0}); + REQUIRE(std::as_const(tensor).get_data(2) == TestType{3.0}); + REQUIRE(std::as_const(tensor).get_data(3) == TestType{4.0}); + REQUIRE(std::as_const(tensor).get_data(4) == TestType{5.0}); + REQUIRE(std::as_const(tensor).get_data(5) == TestType{6.0}); + REQUIRE(std::as_const(tensor).get_data(6) == TestType{7.0}); + REQUIRE(std::as_const(tensor).get_data(7) == TestType{8.0}); + } + + SECTION("set_data_()") { + scalar.set_data(0, TestType{2.0}); + REQUIRE(scalar.get_data(0) == TestType{2.0}); + + vector.set_data(0, TestType{2.0}); + REQUIRE(vector.get_data(0) == TestType{2.0}); + REQUIRE(vector.get_data(1) == TestType{2.0}); + } + + SECTION("fill_()") { + vector.fill(TestType{42.0}); + REQUIRE(vector.get_data(0) == TestType(42.0)); + REQUIRE(vector.get_data(1) == TestType(42.0)); + } + + SECTION("copy_()") { + auto data = std::vector(2, TestType(42.0)); + vector.copy(data); + REQUIRE(vector.get_data(0) == TestType(42.0)); + REQUIRE(vector.get_data(1) == TestType(42.0)); + } + SECTION("are_equal_") { pimpl_type scalar2(scalar); REQUIRE(scalar2.are_equal(scalar)); - scalar2.get_elem({}) = 42.0; + scalar2.set_elem({}, 42.0); REQUIRE_FALSE(scalar2.are_equal(scalar)); } @@ -225,7 +329,7 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.addition_assignment(s, s, s, scalar, scalar); pimpl_type corr(shape_type{}); - corr.get_elem({}) = 2.0; + corr.set_elem({}, 2.0); REQUIRE(output == corr); } @@ -238,14 +342,14 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.addition_assignment(o, l, r, tensor, tensor); pimpl_type corr(shape_type{2, 2, 2}); - corr.get_elem({0, 0, 0}) = 2.0; - corr.get_elem({0, 0, 1}) = 4.0; - corr.get_elem({0, 1, 0}) = 6.0; - corr.get_elem({0, 1, 1}) = 8.0; - corr.get_elem({1, 0, 0}) = 10.0; - corr.get_elem({1, 0, 1}) = 12.0; - corr.get_elem({1, 1, 0}) = 14.0; - corr.get_elem({1, 1, 1}) = 16.0; + corr.set_elem({0, 0, 0}, 2.0); + corr.set_elem({0, 0, 1}, 4.0); + corr.set_elem({0, 1, 0}, 6.0); + corr.set_elem({0, 1, 1}, 8.0); + corr.set_elem({1, 0, 0}, 10.0); + corr.set_elem({1, 0, 1}, 12.0); + corr.set_elem({1, 1, 0}, 14.0); + corr.set_elem({1, 1, 1}, 16.0); REQUIRE(output == corr); } @@ -258,14 +362,14 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.addition_assignment(o, l, r, tensor, tensor); pimpl_type corr(shape_type{2, 2, 2}); - corr.get_elem({0, 0, 0}) = 2.0; - corr.get_elem({0, 0, 1}) = 7.0; - corr.get_elem({0, 1, 0}) = 6.0; - corr.get_elem({0, 1, 1}) = 11.0; - corr.get_elem({1, 0, 0}) = 7.0; - corr.get_elem({1, 0, 1}) = 12.0; - corr.get_elem({1, 1, 0}) = 11.0; - corr.get_elem({1, 1, 1}) = 16.0; + corr.set_elem({0, 0, 0}, 2.0); + corr.set_elem({0, 0, 1}, 7.0); + corr.set_elem({0, 1, 0}, 6.0); + corr.set_elem({0, 1, 1}, 11.0); + corr.set_elem({1, 0, 0}, 7.0); + corr.set_elem({1, 0, 1}, 12.0); + corr.set_elem({1, 1, 0}, 11.0); + corr.set_elem({1, 1, 1}, 16.0); REQUIRE(output == corr); } @@ -278,14 +382,14 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.addition_assignment(o, l, r, tensor, tensor); pimpl_type corr(shape_type{2, 2, 2}); - corr.get_elem({0, 0, 0}) = 2.0; - corr.get_elem({0, 0, 1}) = 7.0; - corr.get_elem({0, 1, 0}) = 6.0; - corr.get_elem({0, 1, 1}) = 11.0; - corr.get_elem({1, 0, 0}) = 7.0; - corr.get_elem({1, 0, 1}) = 12.0; - corr.get_elem({1, 1, 0}) = 11.0; - corr.get_elem({1, 1, 1}) = 16.0; + corr.set_elem({0, 0, 0}, 2.0); + corr.set_elem({0, 0, 1}, 7.0); + corr.set_elem({0, 1, 0}, 6.0); + corr.set_elem({0, 1, 1}, 11.0); + corr.set_elem({1, 0, 0}, 7.0); + corr.set_elem({1, 0, 1}, 12.0); + corr.set_elem({1, 1, 0}, 11.0); + corr.set_elem({1, 1, 1}, 16.0); REQUIRE(output == corr); } @@ -298,14 +402,14 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.addition_assignment(o, l, r, tensor, tensor); pimpl_type corr(shape_type{2, 2, 2}); - corr.get_elem({0, 0, 0}) = 2.0; - corr.get_elem({0, 0, 1}) = 8.0; - corr.get_elem({0, 1, 0}) = 8.0; - corr.get_elem({0, 1, 1}) = 14.0; - corr.get_elem({1, 0, 0}) = 4.0; - corr.get_elem({1, 0, 1}) = 10.0; - corr.get_elem({1, 1, 0}) = 10.0; - corr.get_elem({1, 1, 1}) = 16.0; + corr.set_elem({0, 0, 0}, 2.0); + corr.set_elem({0, 0, 1}, 8.0); + corr.set_elem({0, 1, 0}, 8.0); + corr.set_elem({0, 1, 1}, 14.0); + corr.set_elem({1, 0, 0}, 4.0); + corr.set_elem({1, 0, 1}, 10.0); + corr.set_elem({1, 1, 0}, 10.0); + corr.set_elem({1, 1, 1}, 16.0); REQUIRE(output == corr); } } @@ -317,7 +421,7 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.subtraction_assignment(s, s, s, scalar, scalar); pimpl_type corr(shape_type{}); - corr.get_elem({}) = 0.0; + corr.set_elem({}, 0.0); REQUIRE(output == corr); } @@ -330,14 +434,14 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.subtraction_assignment(o, l, r, tensor, tensor); pimpl_type corr(shape_type{2, 2, 2}); - corr.get_elem({0, 0, 0}) = 0.0; - corr.get_elem({0, 0, 1}) = 0.0; - corr.get_elem({0, 1, 0}) = 0.0; - corr.get_elem({0, 1, 1}) = 0.0; - corr.get_elem({1, 0, 0}) = 0.0; - corr.get_elem({1, 0, 1}) = 0.0; - corr.get_elem({1, 1, 0}) = 0.0; - corr.get_elem({1, 1, 1}) = 0.0; + corr.set_elem({0, 0, 0}, 0.0); + corr.set_elem({0, 0, 1}, 0.0); + corr.set_elem({0, 1, 0}, 0.0); + corr.set_elem({0, 1, 1}, 0.0); + corr.set_elem({1, 0, 0}, 0.0); + corr.set_elem({1, 0, 1}, 0.0); + corr.set_elem({1, 1, 0}, 0.0); + corr.set_elem({1, 1, 1}, 0.0); REQUIRE(output == corr); } @@ -350,14 +454,14 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.subtraction_assignment(o, l, r, tensor, tensor); pimpl_type corr(shape_type{2, 2, 2}); - corr.get_elem({0, 0, 0}) = 0.0; - corr.get_elem({0, 0, 1}) = 3.0; - corr.get_elem({0, 1, 0}) = 0.0; - corr.get_elem({0, 1, 1}) = 3.0; - corr.get_elem({1, 0, 0}) = -3.0; - corr.get_elem({1, 0, 1}) = 0.0; - corr.get_elem({1, 1, 0}) = -3.0; - corr.get_elem({1, 1, 1}) = 0.0; + corr.set_elem({0, 0, 0}, 0.0); + corr.set_elem({0, 0, 1}, 3.0); + corr.set_elem({0, 1, 0}, 0.0); + corr.set_elem({0, 1, 1}, 3.0); + corr.set_elem({1, 0, 0}, -3.0); + corr.set_elem({1, 0, 1}, 0.0); + corr.set_elem({1, 1, 0}, -3.0); + corr.set_elem({1, 1, 1}, 0.0); REQUIRE(output == corr); } @@ -370,14 +474,14 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.subtraction_assignment(o, l, r, tensor, tensor); pimpl_type corr(shape_type{2, 2, 2}); - corr.get_elem({0, 0, 0}) = 0.0; - corr.get_elem({0, 0, 1}) = -3.0; - corr.get_elem({0, 1, 0}) = 0.0; - corr.get_elem({0, 1, 1}) = -3.0; - corr.get_elem({1, 0, 0}) = 3.0; - corr.get_elem({1, 0, 1}) = 0.0; - corr.get_elem({1, 1, 0}) = 3.0; - corr.get_elem({1, 1, 1}) = 0.0; + corr.set_elem({0, 0, 0}, 0.0); + corr.set_elem({0, 0, 1}, -3.0); + corr.set_elem({0, 1, 0}, 0.0); + corr.set_elem({0, 1, 1}, -3.0); + corr.set_elem({1, 0, 0}, 3.0); + corr.set_elem({1, 0, 1}, 0.0); + corr.set_elem({1, 1, 0}, 3.0); + corr.set_elem({1, 1, 1}, 0.0); REQUIRE(output == corr); } @@ -390,14 +494,14 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.subtraction_assignment(o, l, r, tensor, tensor); pimpl_type corr(shape_type{2, 2, 2}); - corr.get_elem({0, 0, 0}) = 0.0; - corr.get_elem({0, 0, 1}) = 2.0; - corr.get_elem({0, 1, 0}) = -2.0; - corr.get_elem({0, 1, 1}) = 0.0; - corr.get_elem({1, 0, 0}) = 0.0; - corr.get_elem({1, 0, 1}) = 2.0; - corr.get_elem({1, 1, 0}) = -2.0; - corr.get_elem({1, 1, 1}) = 0.0; + corr.set_elem({0, 0, 0}, 0.0); + corr.set_elem({0, 0, 1}, 2.0); + corr.set_elem({0, 1, 0}, -2.0); + corr.set_elem({0, 1, 1}, 0.0); + corr.set_elem({1, 0, 0}, 0.0); + corr.set_elem({1, 0, 1}, 2.0); + corr.set_elem({1, 1, 0}, -2.0); + corr.set_elem({1, 1, 1}, 0.0); REQUIRE(output == corr); } } @@ -409,7 +513,7 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.hadamard_assignment(s, s, s, scalar, scalar); pimpl_type corr(shape_type{}); - corr.get_elem({}) = 1.0; + corr.set_elem({}, 1.0); REQUIRE(output == corr); } @@ -422,14 +526,14 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.hadamard_assignment(o, l, r, tensor, tensor); pimpl_type corr(shape_type{2, 2, 2}); - corr.get_elem({0, 0, 0}) = 1.0; - corr.get_elem({0, 0, 1}) = 4.0; - corr.get_elem({0, 1, 0}) = 9.0; - corr.get_elem({0, 1, 1}) = 16.0; - corr.get_elem({1, 0, 0}) = 25.0; - corr.get_elem({1, 0, 1}) = 36.0; - corr.get_elem({1, 1, 0}) = 49.0; - corr.get_elem({1, 1, 1}) = 64.0; + corr.set_elem({0, 0, 0}, 1.0); + corr.set_elem({0, 0, 1}, 4.0); + corr.set_elem({0, 1, 0}, 9.0); + corr.set_elem({0, 1, 1}, 16.0); + corr.set_elem({1, 0, 0}, 25.0); + corr.set_elem({1, 0, 1}, 36.0); + corr.set_elem({1, 1, 0}, 49.0); + corr.set_elem({1, 1, 1}, 64.0); REQUIRE(output == corr); } @@ -442,14 +546,14 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.hadamard_assignment(o, l, r, tensor, tensor); pimpl_type corr(shape_type{2, 2, 2}); - corr.get_elem({0, 0, 0}) = 1.0; - corr.get_elem({0, 0, 1}) = 10.0; - corr.get_elem({0, 1, 0}) = 9.0; - corr.get_elem({0, 1, 1}) = 28.0; - corr.get_elem({1, 0, 0}) = 10.0; - corr.get_elem({1, 0, 1}) = 36.0; - corr.get_elem({1, 1, 0}) = 28.0; - corr.get_elem({1, 1, 1}) = 64.0; + corr.set_elem({0, 0, 0}, 1.0); + corr.set_elem({0, 0, 1}, 10.0); + corr.set_elem({0, 1, 0}, 9.0); + corr.set_elem({0, 1, 1}, 28.0); + corr.set_elem({1, 0, 0}, 10.0); + corr.set_elem({1, 0, 1}, 36.0); + corr.set_elem({1, 1, 0}, 28.0); + corr.set_elem({1, 1, 1}, 64.0); REQUIRE(output == corr); } @@ -462,14 +566,14 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.hadamard_assignment(o, l, r, tensor, tensor); pimpl_type corr(shape_type{2, 2, 2}); - corr.get_elem({0, 0, 0}) = 1.0; - corr.get_elem({0, 0, 1}) = 10.0; - corr.get_elem({0, 1, 0}) = 9.0; - corr.get_elem({0, 1, 1}) = 28.0; - corr.get_elem({1, 0, 0}) = 10.0; - corr.get_elem({1, 0, 1}) = 36.0; - corr.get_elem({1, 1, 0}) = 28.0; - corr.get_elem({1, 1, 1}) = 64.0; + corr.set_elem({0, 0, 0}, 1.0); + corr.set_elem({0, 0, 1}, 10.0); + corr.set_elem({0, 1, 0}, 9.0); + corr.set_elem({0, 1, 1}, 28.0); + corr.set_elem({1, 0, 0}, 10.0); + corr.set_elem({1, 0, 1}, 36.0); + corr.set_elem({1, 1, 0}, 28.0); + corr.set_elem({1, 1, 1}, 64.0); REQUIRE(output == corr); } @@ -482,14 +586,14 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.hadamard_assignment(o, l, r, tensor, tensor); pimpl_type corr(shape_type{2, 2, 2}); - corr.get_elem({0, 0, 0}) = 1.0; - corr.get_elem({0, 0, 1}) = 15.0; - corr.get_elem({0, 1, 0}) = 15.0; - corr.get_elem({0, 1, 1}) = 49.0; - corr.get_elem({1, 0, 0}) = 4.0; - corr.get_elem({1, 0, 1}) = 24.0; - corr.get_elem({1, 1, 0}) = 24.0; - corr.get_elem({1, 1, 1}) = 64.0; + corr.set_elem({0, 0, 0}, 1.0); + corr.set_elem({0, 0, 1}, 15.0); + corr.set_elem({0, 1, 0}, 15.0); + corr.set_elem({0, 1, 1}, 49.0); + corr.set_elem({1, 0, 0}, 4.0); + corr.set_elem({1, 0, 1}, 24.0); + corr.set_elem({1, 1, 0}, 24.0); + corr.set_elem({1, 1, 1}, 64.0); REQUIRE(output == corr); } } @@ -505,7 +609,7 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.contraction_assignment(o, l, r, oshape, tensor, tensor); pimpl_type corr(oshape); - corr.get_elem({}) = 204.0; + corr.set_elem({}, 204.0); REQUIRE(output == corr); } @@ -519,7 +623,7 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.contraction_assignment(o, l, r, oshape, tensor, tensor); pimpl_type corr(oshape); - corr.get_elem({}) = 196.0; + corr.set_elem({}, 196.0); REQUIRE(output == corr); } @@ -533,10 +637,10 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.contraction_assignment(o, l, r, oshape, tensor, tensor); pimpl_type corr(oshape); - corr.get_elem({0, 0}) = 50.0; - corr.get_elem({0, 1}) = 60.0; - corr.get_elem({1, 0}) = 114.0; - corr.get_elem({1, 1}) = 140.0; + corr.set_elem({0, 0}, 50.0); + corr.set_elem({0, 1}, 60.0); + corr.set_elem({1, 0}, 114.0); + corr.set_elem({1, 1}, 140.0); REQUIRE(output == corr); } @@ -550,10 +654,10 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.contraction_assignment(o, l, r, oshape, tensor, tensor); pimpl_type corr(oshape); - corr.get_elem({0, 0}) = 44.0; - corr.get_elem({0, 1}) = 64.0; - corr.get_elem({1, 0}) = 100.0; - corr.get_elem({1, 1}) = 152.0; + corr.set_elem({0, 0}, 44.0); + corr.set_elem({0, 1}, 64.0); + corr.set_elem({1, 0}, 100.0); + corr.set_elem({1, 1}, 152.0); REQUIRE(output == corr); } @@ -567,10 +671,10 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.contraction_assignment(o, l, r, oshape, tensor, tensor); pimpl_type corr(oshape); - corr.get_elem({0, 0}) = 44.0; - corr.get_elem({0, 1}) = 100.0; - corr.get_elem({1, 0}) = 64.0; - corr.get_elem({1, 1}) = 152.0; + corr.set_elem({0, 0}, 44.0); + corr.set_elem({0, 1}, 100.0); + corr.set_elem({1, 0}, 64.0); + corr.set_elem({1, 1}, 152.0); REQUIRE(output == corr); } @@ -584,22 +688,22 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.contraction_assignment(o, l, r, oshape, tensor, tensor); pimpl_type corr(oshape); - corr.get_elem({0, 0, 0, 0}) = 10.0; - corr.get_elem({0, 0, 0, 1}) = 14.0; - corr.get_elem({0, 0, 1, 0}) = 26.0; - corr.get_elem({0, 0, 1, 1}) = 30.0; - corr.get_elem({0, 1, 0, 0}) = 14.0; - corr.get_elem({0, 1, 0, 1}) = 20.0; - corr.get_elem({0, 1, 1, 0}) = 38.0; - corr.get_elem({0, 1, 1, 1}) = 44.0; - corr.get_elem({1, 0, 0, 0}) = 26.0; - corr.get_elem({1, 0, 0, 1}) = 38.0; - corr.get_elem({1, 0, 1, 0}) = 74.0; - corr.get_elem({1, 0, 1, 1}) = 86.0; - corr.get_elem({1, 1, 0, 0}) = 30.0; - corr.get_elem({1, 1, 0, 1}) = 44.0; - corr.get_elem({1, 1, 1, 0}) = 86.0; - corr.get_elem({1, 1, 1, 1}) = 100.0; + corr.set_elem({0, 0, 0, 0}, 10.0); + corr.set_elem({0, 0, 0, 1}, 14.0); + corr.set_elem({0, 0, 1, 0}, 26.0); + corr.set_elem({0, 0, 1, 1}, 30.0); + corr.set_elem({0, 1, 0, 0}, 14.0); + corr.set_elem({0, 1, 0, 1}, 20.0); + corr.set_elem({0, 1, 1, 0}, 38.0); + corr.set_elem({0, 1, 1, 1}, 44.0); + corr.set_elem({1, 0, 0, 0}, 26.0); + corr.set_elem({1, 0, 0, 1}, 38.0); + corr.set_elem({1, 0, 1, 0}, 74.0); + corr.set_elem({1, 0, 1, 1}, 86.0); + corr.set_elem({1, 1, 0, 0}, 30.0); + corr.set_elem({1, 1, 0, 1}, 44.0); + corr.set_elem({1, 1, 1, 0}, 86.0); + corr.set_elem({1, 1, 1, 1}, 100.0); REQUIRE(output == corr); } @@ -614,14 +718,14 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.contraction_assignment(o, l, r, oshape, matrix, tensor); pimpl_type corr(oshape); - corr.get_elem({0, 0, 0}) = 11.0; - corr.get_elem({0, 0, 1}) = 14.0; - corr.get_elem({0, 1, 0}) = 17.0; - corr.get_elem({0, 1, 1}) = 20.0; - corr.get_elem({1, 0, 0}) = 23.0; - corr.get_elem({1, 0, 1}) = 30.0; - corr.get_elem({1, 1, 0}) = 37.0; - corr.get_elem({1, 1, 1}) = 44.0; + corr.set_elem({0, 0, 0}, 11.0); + corr.set_elem({0, 0, 1}, 14.0); + corr.set_elem({0, 1, 0}, 17.0); + corr.set_elem({0, 1, 1}, 20.0); + corr.set_elem({1, 0, 0}, 23.0); + corr.set_elem({1, 0, 1}, 30.0); + corr.set_elem({1, 1, 0}, 37.0); + corr.set_elem({1, 1, 1}, 44.0); REQUIRE(corr == output); } @@ -644,10 +748,10 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.permute_assignment(o, i, matrix); pimpl_type corr(shape_type{2, 2}); - corr.get_elem({0, 0}) = 1.0; - corr.get_elem({0, 1}) = 3.0; - corr.get_elem({1, 0}) = 2.0; - corr.get_elem({1, 1}) = 4.0; + corr.set_elem({0, 0}, 1.0); + corr.set_elem({0, 1}, 3.0); + corr.set_elem({1, 0}, 2.0); + corr.set_elem({1, 1}, 4.0); REQUIRE(output == corr); } } @@ -661,10 +765,10 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.scalar_multiplication(o, i, 2.0, matrix); pimpl_type corr(shape_type{2, 2}); - corr.get_elem({0, 0}) = 2.0; - corr.get_elem({0, 1}) = 4.0; - corr.get_elem({1, 0}) = 6.0; - corr.get_elem({1, 1}) = 8.0; + corr.set_elem({0, 0}, 2.0); + corr.set_elem({0, 1}, 4.0); + corr.set_elem({1, 0}, 6.0); + corr.set_elem({1, 1}, 8.0); REQUIRE(output == corr); } @@ -675,10 +779,10 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { output.scalar_multiplication(o, i, 2.0, matrix); pimpl_type corr(shape_type{2, 2}); - corr.get_elem({0, 0}) = 2.0; - corr.get_elem({0, 1}) = 6.0; - corr.get_elem({1, 0}) = 4.0; - corr.get_elem({1, 1}) = 8.0; + corr.set_elem({0, 0}, 2.0); + corr.set_elem({0, 1}, 6.0); + corr.set_elem({1, 0}, 4.0); + corr.set_elem({1, 1}, 8.0); REQUIRE(output == corr); } } diff --git a/tests/cxx/unit_tests/tensorwrapper/buffer/detail_/hash_utilities.cpp b/tests/cxx/unit_tests/tensorwrapper/buffer/detail_/hash_utilities.cpp new file mode 100644 index 00000000..f484acf8 --- /dev/null +++ b/tests/cxx/unit_tests/tensorwrapper/buffer/detail_/hash_utilities.cpp @@ -0,0 +1,51 @@ +/* + * Copyright 2025 NWChemEx-Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../../testing/testing.hpp" +#include + +using namespace tensorwrapper; +using namespace testing; + +using buffer::detail_::hash_utilities::hash_input; +using hash_type = buffer::detail_::hash_utilities::hash_type; + +// Make sure we know if this changes for some reason +TEST_CASE("hash_type") { REQUIRE(std::is_same_v); } + +// Checking dispatching +TEMPLATE_LIST_TEST_CASE("hash_input", "", types::floating_point_types) { + using value_type = TestType; + hash_type seed{0}; + if constexpr(types::is_uncertain_v) { + value_type value(1.0, 1.0); + hash_input(seed, value); + hash_type corr{0}; + boost::hash_combine(corr, value.mean()); + boost::hash_combine(corr, value.sd()); + for(const auto& [dep, deriv] : value.deps()) { + boost::hash_combine(corr, dep); + boost::hash_combine(corr, deriv); + } + REQUIRE(seed == corr); + } else { + value_type value(1.0); + hash_input(seed, value); + hash_type corr{0}; + boost::hash_combine(corr, value_type{1.0}); + REQUIRE(seed == corr); + } +} \ No newline at end of file diff --git a/tests/cxx/unit_tests/tensorwrapper/buffer/eigen.cpp b/tests/cxx/unit_tests/tensorwrapper/buffer/eigen.cpp index c8d369b8..33361aa8 100644 --- a/tests/cxx/unit_tests/tensorwrapper/buffer/eigen.cpp +++ b/tests/cxx/unit_tests/tensorwrapper/buffer/eigen.cpp @@ -28,30 +28,30 @@ TEMPLATE_LIST_TEST_CASE("Eigen", "", types::floating_point_types) { auto pscalar = testing::eigen_scalar(); auto& eigen_scalar = static_cast(*pscalar); - eigen_scalar.at() = 10.0; + eigen_scalar.set_elem({}, 10.0); auto pvector = testing::eigen_vector(2); auto& eigen_vector = static_cast(*pvector); - eigen_vector.at(0) = 10.0; - eigen_vector.at(1) = 20.0; - - auto pmatrix = testing::eigen_matrix(2, 3); - auto& eigen_matrix = static_cast(*pmatrix); - eigen_matrix.at(0, 0) = 10.0; - eigen_matrix.at(0, 1) = 20.0; - eigen_matrix.at(0, 2) = 30.0; - eigen_matrix.at(1, 0) = 40.0; - eigen_matrix.at(1, 1) = 50.0; - eigen_matrix.at(1, 2) = 60.0; - - auto ptensor = testing::eigen_tensor3(1, 2, 3); - auto& eigen_tensor = static_cast(*ptensor); - eigen_tensor.at(0, 0, 0) = 10.0; - eigen_tensor.at(0, 0, 1) = 20.0; - eigen_tensor.at(0, 0, 2) = 30.0; - eigen_tensor.at(0, 1, 0) = 40.0; - eigen_tensor.at(0, 1, 1) = 50.0; - eigen_tensor.at(0, 1, 2) = 60.0; + eigen_vector.set_elem({0}, 10.0); + eigen_vector.set_elem({1}, 20.0); + + auto pmatrix = testing::eigen_matrix(2, 3); + auto& eigen_matrix = static_cast(*pmatrix); + eigen_matrix.set_elem({0, 0}, 10.0); + eigen_matrix.set_elem({0, 1}, 20.0); + eigen_matrix.set_elem({0, 2}, 30.0); + eigen_matrix.set_elem({1, 0}, 40.0); + eigen_matrix.set_elem({1, 1}, 50.0); + eigen_matrix.set_elem({1, 2}, 60.0); + + auto ptensor = testing::eigen_tensor3(1, 2, 3); + auto& eigen_tensor = static_cast(*ptensor); + eigen_tensor.set_elem({0, 0, 0}, 10.0); + eigen_tensor.set_elem({0, 0, 1}, 20.0); + eigen_tensor.set_elem({0, 0, 2}, 30.0); + eigen_tensor.set_elem({0, 1, 0}, 40.0); + eigen_tensor.set_elem({0, 1, 1}, 50.0); + eigen_tensor.set_elem({0, 1, 2}, 60.0); auto scalar_layout = scalar_physical(); auto vector_layout = vector_physical(2); @@ -61,7 +61,9 @@ TEMPLATE_LIST_TEST_CASE("Eigen", "", types::floating_point_types) { buffer_type defaulted; SECTION("ctors, assignment") { - SECTION("default ctor") { REQUIRE(defaulted.data() == nullptr); } + SECTION("default ctor") { + REQUIRE(defaulted.get_immutable_data() == nullptr); + } SECTION("value ctor") { REQUIRE(eigen_scalar.layout().are_equal(scalar_layout)); @@ -85,7 +87,7 @@ TEMPLATE_LIST_TEST_CASE("Eigen", "", types::floating_point_types) { // Checking Layout/Allocator falls to base class tests auto pscalar2 = testing::eigen_scalar(); auto& eigen_scalar2 = static_cast(*pscalar2); - eigen_scalar2.at() = 10.0; + eigen_scalar2.set_elem({}, 10.0); // Defaulted != scalar REQUIRE_FALSE(defaulted == eigen_scalar); @@ -94,7 +96,7 @@ TEMPLATE_LIST_TEST_CASE("Eigen", "", types::floating_point_types) { REQUIRE(eigen_scalar == eigen_scalar2); SECTION("Different buffer value") { - eigen_scalar2.at() = 2.0; + eigen_scalar2.set_elem({}, 2.0); REQUIRE_FALSE(eigen_scalar == eigen_scalar2); } } @@ -102,10 +104,10 @@ TEMPLATE_LIST_TEST_CASE("Eigen", "", types::floating_point_types) { SECTION("operator!=") { auto pscalar2 = testing::eigen_scalar(); auto& eigen_scalar2 = static_cast(*pscalar2); - eigen_scalar2.at() = 10.0; + eigen_scalar2.set_elem({}, 10.0); REQUIRE_FALSE(eigen_scalar != eigen_scalar2); - eigen_scalar2.at() = 2.0; + eigen_scalar2.set_elem({}, 2.0); REQUIRE(eigen_scalar != eigen_scalar2); } @@ -126,9 +128,9 @@ TEMPLATE_LIST_TEST_CASE("Eigen", "", types::floating_point_types) { auto vi = eigen_vector("i"); output.addition_assignment("i", vi, vi); - auto corr = testing::eigen_vector(2); - corr->at(0) = 20.0; - corr->at(1) = 40.0; + auto corr = testing::eigen_vector(2); + corr->set_elem({0}, 20.0); + corr->set_elem({1}, 40.0); REQUIRE(output.are_equal(*corr)); } @@ -138,9 +140,9 @@ TEMPLATE_LIST_TEST_CASE("Eigen", "", types::floating_point_types) { auto vi = eigen_vector("i"); output.subtraction_assignment("i", vi, vi); - auto corr = testing::eigen_vector(2); - corr->at(0) = 0.0; - corr->at(1) = 0.0; + auto corr = testing::eigen_vector(2); + corr->set_elem({0}, 0.0); + corr->set_elem({1}, 0.0); REQUIRE(output.are_equal(*corr)); } @@ -150,9 +152,9 @@ TEMPLATE_LIST_TEST_CASE("Eigen", "", types::floating_point_types) { auto vi = eigen_vector("i"); output.multiplication_assignment("i", vi, vi); - auto corr = testing::eigen_vector(2); - corr->at(0) = 100.0; - corr->at(1) = 400.0; + auto corr = testing::eigen_vector(2); + corr->set_elem({0}, 100.0); + corr->set_elem({1}, 400.0); REQUIRE(output.are_equal(*corr)); } @@ -162,13 +164,13 @@ TEMPLATE_LIST_TEST_CASE("Eigen", "", types::floating_point_types) { auto mij = eigen_matrix("i,j"); output.permute_assignment("j,i", mij); - auto corr = testing::eigen_matrix(3, 2); - corr->at(0, 0) = 10.0; - corr->at(0, 1) = 40.0; - corr->at(1, 0) = 20.0; - corr->at(1, 1) = 50.0; - corr->at(2, 0) = 30.0; - corr->at(2, 1) = 60.0; + auto corr = testing::eigen_matrix(3, 2); + corr->set_elem({0, 0}, 10.0); + corr->set_elem({0, 1}, 40.0); + corr->set_elem({1, 0}, 20.0); + corr->set_elem({1, 1}, 50.0); + corr->set_elem({2, 0}, 30.0); + corr->set_elem({2, 1}, 60.0); REQUIRE(output.are_equal(*corr)); } @@ -178,35 +180,62 @@ TEMPLATE_LIST_TEST_CASE("Eigen", "", types::floating_point_types) { auto vi = eigen_vector("i"); output.scalar_multiplication("i", 2.0, vi); - auto corr = testing::eigen_vector(2); - corr->at(0) = 20.0; - corr->at(1) = 40.0; + auto corr = testing::eigen_vector(2); + corr->set_elem({0}, 20.0); + corr->set_elem({1}, 40.0); REQUIRE(output.are_equal(*corr)); } - SECTION("data()") { - REQUIRE(defaulted.data() == nullptr); - REQUIRE(*eigen_scalar.data() == TestType{10.0}); - REQUIRE(*eigen_matrix.data() == TestType{10.0}); + SECTION("get_mutable_data_()") { + REQUIRE(defaulted.get_mutable_data() == nullptr); + REQUIRE(*eigen_scalar.get_mutable_data() == TestType{10.0}); + REQUIRE(*eigen_matrix.get_mutable_data() == TestType{10.0}); } - SECTION("data() const") { - REQUIRE(std::as_const(defaulted).data() == nullptr); - REQUIRE(*std::as_const(eigen_scalar).data() == TestType{10.0}); - REQUIRE(*std::as_const(eigen_matrix).data() == TestType{10.0}); + SECTION("get_immutable_data_() const") { + REQUIRE(std::as_const(defaulted).get_immutable_data() == nullptr); + REQUIRE(*std::as_const(eigen_scalar).get_immutable_data() == + TestType{10.0}); + REQUIRE(*std::as_const(eigen_matrix).get_immutable_data() == + TestType{10.0}); } - SECTION("get_elem_()") { - REQUIRE(eigen_scalar.at() == TestType{10.0}); - REQUIRE(eigen_vector.at(0) == TestType{10.0}); - REQUIRE(eigen_matrix.at(0, 0) == TestType{10.0}); + SECTION("get_elem_() const") { + TestType corr{10.0}; + REQUIRE(std::as_const(eigen_scalar).get_elem({}) == corr); + REQUIRE(std::as_const(eigen_vector).get_elem({0}) == corr); + REQUIRE(std::as_const(eigen_matrix).get_elem({0, 0}) == corr); } - SECTION("get_elem_() const") { - REQUIRE(std::as_const(eigen_scalar).at() == TestType{10.0}); - REQUIRE(std::as_const(eigen_vector).at(0) == TestType{10.0}); - REQUIRE(std::as_const(eigen_matrix).at(0, 0) == TestType{10.0}); + SECTION("set_elem_()") { + eigen_vector.set_elem({0}, TestType{42.0}); + REQUIRE(eigen_vector.get_elem({0}) == TestType{42.0}); + } + + SECTION("get_data_() const") { + TestType corr{10.0}; + REQUIRE(std::as_const(eigen_scalar).get_data(0) == corr); + REQUIRE(std::as_const(eigen_vector).get_data(0) == corr); + REQUIRE(std::as_const(eigen_matrix).get_data(0) == corr); + } + + SECTION("set_data_()") { + eigen_vector.set_data(0, TestType{42.0}); + REQUIRE(eigen_vector.get_data(0) == TestType{42.0}); + } + + SECTION("fill_()") { + eigen_vector.fill(TestType{42.0}); + REQUIRE(eigen_vector.get_data(0) == TestType(42.0)); + REQUIRE(eigen_vector.get_data(1) == TestType(42.0)); + } + + SECTION("copy_()") { + auto data = std::vector(2, TestType(42.0)); + eigen_vector.copy(data); + REQUIRE(eigen_vector.get_data(0) == TestType(42.0)); + REQUIRE(eigen_vector.get_data(1) == TestType(42.0)); } } } diff --git a/tests/cxx/unit_tests/tensorwrapper/dsl/dsl.cpp b/tests/cxx/unit_tests/tensorwrapper/dsl/dsl.cpp index d45fbcbd..e2f83e57 100644 --- a/tests/cxx/unit_tests/tensorwrapper/dsl/dsl.cpp +++ b/tests/cxx/unit_tests/tensorwrapper/dsl/dsl.cpp @@ -94,9 +94,9 @@ TEST_CASE("DSLr : buffer::Eigen") { auto& scalar2 = *pscalar2; auto& corr = *pcorr; - scalar0.at() = 1.0; - scalar1.at() = 2.0; - scalar2.at() = 3.0; + scalar0.set_data(0, 1.0); + scalar1.set_data(0, 2.0); + scalar2.set_data(0, 3.0); SECTION("assignment") { SECTION("scalar") { diff --git a/tests/cxx/unit_tests/tensorwrapper/dsl/pairwise_parser.cpp b/tests/cxx/unit_tests/tensorwrapper/dsl/pairwise_parser.cpp index 65151be2..9fca8092 100644 --- a/tests/cxx/unit_tests/tensorwrapper/dsl/pairwise_parser.cpp +++ b/tests/cxx/unit_tests/tensorwrapper/dsl/pairwise_parser.cpp @@ -134,9 +134,9 @@ TEST_CASE("PairwiseParser : buffer::Eigen") { auto& scalar2 = *pscalar2; auto& corr = *pcorr; - scalar0.at() = 1.0; - scalar1.at() = 2.0; - scalar2.at() = 3.0; + scalar0.set_data(0, 1.0); + scalar1.set_data(0, 2.0); + scalar2.set_data(0, 3.0); dsl::PairwiseParser p; diff --git a/tests/cxx/unit_tests/tensorwrapper/operations/approximately_equal.cpp b/tests/cxx/unit_tests/tensorwrapper/operations/approximately_equal.cpp index 77d1a682..e9858dab 100644 --- a/tests/cxx/unit_tests/tensorwrapper/operations/approximately_equal.cpp +++ b/tests/cxx/unit_tests/tensorwrapper/operations/approximately_equal.cpp @@ -31,17 +31,17 @@ using namespace operations; TEMPLATE_LIST_TEST_CASE("approximately_equal", "", types::floating_point_types) { - auto pscalar = testing::eigen_scalar(); - pscalar->at() = 42.0; - auto pvector = testing::eigen_vector(2); - pvector->at(0) = 1.23; - pvector->at(1) = 2.34; + auto pscalar = testing::eigen_scalar(); + pscalar->set_data(0, 42.0); + auto pvector = testing::eigen_vector(2); + pvector->set_data(0, 1.23); + pvector->set_data(1, 2.34); - auto pscalar2 = testing::eigen_scalar(); - pscalar2->at() = 42.0; - auto pvector2 = testing::eigen_vector(2); - pvector2->at(0) = 1.23; - pvector2->at(1) = 2.34; + auto pscalar2 = testing::eigen_scalar(); + pscalar2->set_data(0, 42.0); + auto pvector2 = testing::eigen_vector(2); + pvector2->set_data(0, 1.23); + pvector2->set_data(1, 2.34); shape::Smooth s0{}; shape::Smooth s1{2}; @@ -65,9 +65,9 @@ TEMPLATE_LIST_TEST_CASE("approximately_equal", "", } SECTION("Differ by more than default tolerance") { - double value = 1e-1; - pscalar2->at() = 42.0 + value; - pvector2->at(0) = 1.23 + value; + double value = 1e-1; + pscalar2->set_data(0, 42.0 + value); + pvector2->set_data(0, 1.23 + value); Tensor scalar2(s0, std::move(pscalar2)); Tensor vector2(s1, std::move(pvector2)); REQUIRE_FALSE(approximately_equal(scalar, scalar2)); @@ -77,9 +77,9 @@ TEMPLATE_LIST_TEST_CASE("approximately_equal", "", } SECTION("Differ by less than default tolerance") { - double value = 1e-17; - pscalar2->at() = 42.0 + value; - pvector2->at(0) = 1.23 + value; + double value = 1e-17; + pscalar2->set_data(0, 42.0 + value); + pvector2->set_data(0, 1.23 + value); Tensor scalar2(s0, std::move(pscalar2)); Tensor vector2(s1, std::move(pvector2)); REQUIRE(approximately_equal(scalar, scalar2)); @@ -89,9 +89,9 @@ TEMPLATE_LIST_TEST_CASE("approximately_equal", "", } SECTION("Differ by more than provided tolerance") { - float value = 1e-1; - pscalar2->at() = 43.0; - pvector2->at(0) = 2.23; + float value = 1e-1; + pscalar2->set_data(0, 43.0); + pvector2->set_data(0, 2.23); Tensor scalar2(s0, std::move(pscalar2)); Tensor vector2(s1, std::move(pvector2)); REQUIRE_FALSE(approximately_equal(scalar, scalar2, value)); @@ -101,9 +101,9 @@ TEMPLATE_LIST_TEST_CASE("approximately_equal", "", } SECTION("Differ by less than provided tolerance") { - double value = 1e-10; - pscalar2->at() = 42.0 + value; - pvector2->at(0) = 1.23 + value; + double value = 1e-10; + pscalar2->set_data(0, 42.0 + value); + pvector2->set_data(0, 1.23 + value); Tensor scalar2(s0, std::move(pscalar2)); Tensor vector2(s1, std::move(pvector2)); REQUIRE(approximately_equal(scalar, scalar2, 1e-1)); diff --git a/tests/cxx/unit_tests/tensorwrapper/testing/eigen_buffers.hpp b/tests/cxx/unit_tests/tensorwrapper/testing/eigen_buffers.hpp index fa62af1e..3d3c3f4e 100644 --- a/tests/cxx/unit_tests/tensorwrapper/testing/eigen_buffers.hpp +++ b/tests/cxx/unit_tests/tensorwrapper/testing/eigen_buffers.hpp @@ -43,7 +43,7 @@ auto eigen_vector(std::size_t n = 5) { layout::Physical l(shape::Smooth{n}); auto alloc = make_allocator(); auto buffer = alloc.allocate(l); - for(std::size_t i = 0; i < n; ++i) buffer->at(i) = i; + for(std::size_t i = 0; i < n; ++i) buffer->set_elem({i}, i); return buffer; } @@ -54,7 +54,7 @@ auto eigen_matrix(std::size_t n = 2, std::size_t m = 2) { auto buffer = alloc.allocate(l); double counter = 1.0; for(decltype(n) i = 0; i < n; ++i) - for(decltype(m) j = 0; j < m; ++j) buffer->at(i, j) = counter++; + for(decltype(m) j = 0; j < m; ++j) buffer->set_elem({i, j}, counter++); return buffer; } @@ -66,7 +66,8 @@ auto eigen_tensor3(std::size_t n = 2, std::size_t m = 2, std::size_t l = 2) { double counter = 1.0; for(decltype(n) i = 0; i < n; ++i) for(decltype(m) j = 0; j < m; ++j) - for(decltype(l) k = 0; k < l; ++k) buffer->at(i, j, k) = counter++; + for(decltype(l) k = 0; k < l; ++k) + buffer->set_elem({i, j, k}, counter++); return buffer; } @@ -82,7 +83,7 @@ auto eigen_tensor4(std::array extents = {2, 2, 2, 2}) { for(i[1] = 0; i[1] < extents[1]; ++i[1]) for(i[2] = 0; i[2] < extents[2]; ++i[2]) for(i[3] = 0; i[3] < extents[3]; ++i[3]) - buffer->at(i[0], i[1], i[2], i[3]) = counter++; + buffer->set_elem({i[0], i[1], i[2], i[3]}, counter++); return buffer; } diff --git a/tests/cxx/unit_tests/tensorwrapper/testing/inputs.hpp b/tests/cxx/unit_tests/tensorwrapper/testing/inputs.hpp index 073ea32c..71b9dab1 100644 --- a/tests/cxx/unit_tests/tensorwrapper/testing/inputs.hpp +++ b/tests/cxx/unit_tests/tensorwrapper/testing/inputs.hpp @@ -62,16 +62,16 @@ inline auto smooth_matrix_() { inline auto smooth_matrix_input() { return smooth_matrix_(); } inline auto smooth_symmetric_matrix_input() { - auto pmatrix = eigen_matrix(3, 3); - pmatrix->at(0, 0) = 1.0; - pmatrix->at(0, 1) = 2.0; - pmatrix->at(0, 2) = 3.0; - pmatrix->at(1, 0) = 2.0; - pmatrix->at(1, 1) = 4.0; - pmatrix->at(1, 2) = 5.0; - pmatrix->at(2, 0) = 3.0; - pmatrix->at(2, 1) = 5.0; - pmatrix->at(2, 2) = 6.0; + auto pmatrix = eigen_matrix(3, 3); + pmatrix->set_elem({0, 0}, 1.0); + pmatrix->set_elem({0, 1}, 2.0); + pmatrix->set_elem({0, 2}, 3.0); + pmatrix->set_elem({1, 0}, 2.0); + pmatrix->set_elem({1, 1}, 4.0); + pmatrix->set_elem({1, 2}, 5.0); + pmatrix->set_elem({2, 0}, 3.0); + pmatrix->set_elem({2, 1}, 5.0); + pmatrix->set_elem({2, 2}, 6.0); shape::Smooth shape{3, 3}; symmetry::Permutation p01{0, 1}; symmetry::Group g(p01);