From c43ed94d9bbc916569b42453afa39e7d5bf20521 Mon Sep 17 00:00:00 2001 From: Caleb Schilly Date: Wed, 30 Oct 2024 12:56:08 -0400 Subject: [PATCH] #9: rename inverse to reciprocal; add kokkos ops --- include/pressio/ops.hpp | 3 +- ...rse.hpp => ops_elementwise_reciprocal.hpp} | 12 +-- .../ops/kokkos/ops_elementwise_reciprocal.hpp | 88 +++++++++++++++++++ .../ops_vector_reciprocal_kokkos_functor.hpp | 69 +++++++++++++++ tests/ops/ops_eigen_diag.cc | 4 +- tests/ops/ops_eigen_span.cc | 4 +- tests/ops/ops_eigen_vector.cc | 4 +- tests/ops/ops_kokkos_diag.cc | 27 ++++++ tests/ops/ops_kokkos_span.cc | 26 ++++++ tests/ops/ops_kokkos_vector.cc | 23 +++++ 10 files changed, 247 insertions(+), 13 deletions(-) rename include/pressio/ops/eigen/{ops_elementwise_inverse.hpp => ops_elementwise_reciprocal.hpp} (91%) create mode 100644 include/pressio/ops/kokkos/ops_elementwise_reciprocal.hpp create mode 100644 include/pressio/ops/kokkos/ops_vector_reciprocal_kokkos_functor.hpp diff --git a/include/pressio/ops.hpp b/include/pressio/ops.hpp index 77881ff..a084e4e 100644 --- a/include/pressio/ops.hpp +++ b/include/pressio/ops.hpp @@ -88,7 +88,7 @@ template struct matching_extents; #include "ops/eigen/ops_rank1_update.hpp" #include "ops/eigen/ops_rank2_update.hpp" #include "ops/eigen/ops_elementwise_multiply.hpp" -#include "ops/eigen/ops_elementwise_inverse.hpp" +#include "ops/eigen/ops_elementwise_reciprocal.hpp" #include "ops/eigen/ops_level2.hpp" #include "ops/eigen/ops_level3.hpp" #endif @@ -110,6 +110,7 @@ template struct matching_extents; #include "ops/kokkos/ops_vector_update.hpp" #include "ops/kokkos/ops_rank2_update.hpp" #include "ops/kokkos/ops_elementwise_multiply.hpp" +#include "ops/kokkos/ops_elementwise_reciprocal.hpp" #include "ops/kokkos/ops_level2.hpp" #include "ops/kokkos/ops_level3.hpp" #endif diff --git a/include/pressio/ops/eigen/ops_elementwise_inverse.hpp b/include/pressio/ops/eigen/ops_elementwise_reciprocal.hpp similarity index 91% rename from include/pressio/ops/eigen/ops_elementwise_inverse.hpp rename to include/pressio/ops/eigen/ops_elementwise_reciprocal.hpp index 7141fae..60c6b3e 100644 --- a/include/pressio/ops/eigen/ops_elementwise_inverse.hpp +++ b/include/pressio/ops/eigen/ops_elementwise_reciprocal.hpp @@ -2,7 +2,7 @@ //@HEADER // ************************************************************************ // -// ops_elementwise_inverse.hpp +// ops_elementwise_reciprocal.hpp // Pressio // Copyright 2019 // National Technology & Engineering Solutions of Sandia, LLC (NTESS) @@ -46,8 +46,8 @@ //@HEADER */ -#ifndef PRESSIOOPS_OPS_EIGEN_OPS_ELEMENTWISE_INVERSE_HPP_ -#define PRESSIOOPS_OPS_EIGEN_OPS_ELEMENTWISE_INVERSE_HPP_ +#ifndef PRESSIOOPS_OPS_EIGEN_OPS_elementwise_reciprocal_HPP_ +#define PRESSIOOPS_OPS_EIGEN_OPS_elementwise_reciprocal_HPP_ namespace pressio{ namespace ops{ @@ -57,7 +57,7 @@ namespace pressio{ namespace ops{ template std::enable_if_t< - // common elementwise_inverse constraints + // common elementwise_reciprocal constraints ::pressio::Traits::rank == 1 && ::pressio::Traits::rank == 1 // TPL/container specific @@ -73,7 +73,7 @@ std::enable_if_t< && (std::is_floating_point::scalar_type>::value || std::is_integral::scalar_type>::value) > -elementwise_inverse(const T1 & z, T2 & y) +elementwise_reciprocal(const T1 & z, T2 & y) { assert(::pressio::ops::extent(z, 0)==::pressio::ops::extent(y, 0)); @@ -84,4 +84,4 @@ elementwise_inverse(const T1 & z, T2 & y) } }}//end namespace pressio::ops -#endif // PRESSIOOPS_OPS_EIGEN_OPS_ELEMENTWISE_INVERSE_HPP_ +#endif // PRESSIOOPS_OPS_EIGEN_OPS_elementwise_reciprocal_HPP_ diff --git a/include/pressio/ops/kokkos/ops_elementwise_reciprocal.hpp b/include/pressio/ops/kokkos/ops_elementwise_reciprocal.hpp new file mode 100644 index 0000000..c30d60f --- /dev/null +++ b/include/pressio/ops/kokkos/ops_elementwise_reciprocal.hpp @@ -0,0 +1,88 @@ +/* +//@HEADER +// ************************************************************************ +// +// ops_elementwise_multiply.hpp +// Pressio +// Copyright 2019 +// National Technology & Engineering Solutions of Sandia, LLC (NTESS) +// +// Under the terms of Contract DE-NA0003525 with NTESS, the +// U.S. Government retains certain rights in this software. +// +// Pressio is licensed under BSD-3-Clause terms of use: +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact Francesco Rizzi (fnrizzi@sandia.gov) +// +// ************************************************************************ +//@HEADER +*/ + +#ifndef PRESSIOOPS_OPS_KOKKOS_OPS_ELEMENTWISE_RECIPROCAL_HPP_ +#define PRESSIOOPS_OPS_KOKKOS_OPS_ELEMENTWISE_RECIPROCAL_HPP_ + +#include "ops_vector_reciprocal_kokkos_functor.hpp" + +namespace pressio{ namespace ops{ + +//---------------------------------------------------------------------- +// computing elementwise: y = 1/z +//---------------------------------------------------------------------- +template +std::enable_if_t< + // common elementwise_multiply constraints + ::pressio::Traits::rank == 1 + && ::pressio::Traits::rank == 1 + // TPL/container specific + && (::pressio::is_native_container_kokkos::value + || ::pressio::is_expression_acting_on_kokkos::value) + && (::pressio::is_native_container_kokkos::value + || ::pressio::is_expression_acting_on_kokkos::value) + // scalar compatibility + && ::pressio::all_have_traits_and_same_scalar::value + && (std::is_floating_point::scalar_type>::value + || std::is_integral::scalar_type>::value) + > +elementwise_reciprocal(const T1 & z, T2 & y) +{ + assert(z.extent(0) == y.extent(0)); + + using t1_t = typename impl::NativeType::type; + using t2_t = typename impl::NativeType::type; + using scalar_t = typename ::pressio::Traits::scalar_type; + + using fnctr_t = ::pressio::ops::impl::VectorReciprocalFunctor; + fnctr_t F(impl::get_native(z), impl::get_native(y)); + Kokkos::parallel_for(z.extent(0), F); +} + +}}//end namespace pressio::ops +#endif // PRESSIOOPS_OPS_KOKKOS_OPS_ELEMENTWISE_RECIPROCAL_HPP_ diff --git a/include/pressio/ops/kokkos/ops_vector_reciprocal_kokkos_functor.hpp b/include/pressio/ops/kokkos/ops_vector_reciprocal_kokkos_functor.hpp new file mode 100644 index 0000000..f66d861 --- /dev/null +++ b/include/pressio/ops/kokkos/ops_vector_reciprocal_kokkos_functor.hpp @@ -0,0 +1,69 @@ +/* +//@HEADER +// ************************************************************************ +// +// ops_vector_update_kokkos_functors.hpp +// Pressio +// Copyright 2019 +// National Technology & Engineering Solutions of Sandia, LLC (NTESS) +// +// Under the terms of Contract DE-NA0003525 with NTESS, the +// U.S. Government retains certain rights in this software. +// +// Pressio is licensed under BSD-3-Clause terms of use: +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact Francesco Rizzi (fnrizzi@sandia.gov) +// +// ************************************************************************ +//@HEADER +*/ + +#ifndef PRESSIOOPS_OPS_KOKKOS_OPS_VECTOR_RECIPROCAL_KOKKOS_FUNCTOR_HPP_ +#define PRESSIOOPS_OPS_KOKKOS_OPS_VECTOR_RECIPROCAL_KOKKOS_FUNCTOR_HPP_ + +namespace pressio{ namespace ops{ namespace impl{ + +template + struct VectorReciprocalFunctor { + T1 z_; + T2 y_; + + VectorReciprocalFunctor(T1 z, T2 y) : z_(z), y_(y) {} + + KOKKOS_INLINE_FUNCTION + void operator()(const int i) const { + y_(i) = static_cast(1) / z_(i); + } + }; + + +}}}//end namespace pressio::ops::impl +#endif // PRESSIOOPS_OPS_KOKKOS_OPS_VECTOR_RECIPROCAL_KOKKOS_FUNCTOR_HPP_ diff --git a/tests/ops/ops_eigen_diag.cc b/tests/ops/ops_eigen_diag.cc index 7e03a58..be8c917 100644 --- a/tests/ops/ops_eigen_diag.cc +++ b/tests/ops/ops_eigen_diag.cc @@ -390,7 +390,7 @@ TEST(ops_eigen_diag, elementwiseMultiply) EXPECT_DOUBLE_EQ( y(2), 23.0); } -TEST(ops_eigen_diag, elementwiseInverse) +TEST(ops_eigen_diag, elementwiseReciprocal) { Eigen::MatrixXd M1(3,3); auto y = pressio::diagonal(M1); @@ -407,7 +407,7 @@ TEST(ops_eigen_diag, elementwiseInverse) auto y1 = 1. / z1; auto y2 = 1. / z2; - pressio::ops::elementwise_inverse(z, y); + pressio::ops::elementwise_reciprocal(z, y); EXPECT_DOUBLE_EQ( y(0), y0); EXPECT_DOUBLE_EQ( y(1), y1); EXPECT_DOUBLE_EQ( y(2), y2); diff --git a/tests/ops/ops_eigen_span.cc b/tests/ops/ops_eigen_span.cc index 1e33421..1b9232e 100644 --- a/tests/ops/ops_eigen_span.cc +++ b/tests/ops/ops_eigen_span.cc @@ -267,7 +267,7 @@ TEST(ops_eigen_span, elementwiseMultiply) EXPECT_DOUBLE_EQ( y(2), 23.0); } -TEST(ops_eigen_span, elementwiseInverse) +TEST(ops_eigen_span, elementwiseReciprocal) { Eigen::VectorXd M1(6); auto y = pressio::span(M1,2,3); @@ -284,7 +284,7 @@ TEST(ops_eigen_span, elementwiseInverse) auto y1 = 1. / z1; auto y2 = 1. / z2; - pressio::ops::elementwise_inverse(z, y); + pressio::ops::elementwise_reciprocal(z, y); EXPECT_DOUBLE_EQ( y(0), y0); EXPECT_DOUBLE_EQ( y(1), y1); EXPECT_DOUBLE_EQ( y(2), y2); diff --git a/tests/ops/ops_eigen_vector.cc b/tests/ops/ops_eigen_vector.cc index b4fc886..27f01b8 100644 --- a/tests/ops/ops_eigen_vector.cc +++ b/tests/ops/ops_eigen_vector.cc @@ -415,12 +415,12 @@ TEST(ops_eigen_vector, elementwiseMultiply) EXPECT_DOUBLE_EQ( y(2), 20.0); } -TEST(ops_eigen_vector, elementwiseInverse) +TEST(ops_eigen_vector, elementwiseReciprocal) { V_t y; y << 0.,0.,0.; V_t z; z << 3.,4.,5.; - pressio::ops::elementwise_inverse(z, y); + pressio::ops::elementwise_reciprocal(z, y); EXPECT_DOUBLE_EQ( y(0), 1./3.); EXPECT_DOUBLE_EQ( y(1), 1./4.); EXPECT_DOUBLE_EQ( y(2), 1./5.); diff --git a/tests/ops/ops_kokkos_diag.cc b/tests/ops/ops_kokkos_diag.cc index ddf9761..6e7fa55 100644 --- a/tests/ops/ops_kokkos_diag.cc +++ b/tests/ops/ops_kokkos_diag.cc @@ -380,3 +380,30 @@ TEST(ops_kokkos_diag, elementwiseMultiply) EXPECT_DOUBLE_EQ( M1_h(1,1), 14.0); EXPECT_DOUBLE_EQ( M1_h(2,2), 23.0); } + + +TEST(ops_kokkos_diag, elementwiseReciprocal) +{ + mat_t M1("M1",3,3); + mat_t M3("M3",3,3); + + const auto z0 = 3.; + const auto z1 = 4.; + const auto z2 = 5.; + + auto M1_h = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), M1); + auto M3_h = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), M3); + M3_h(0,0)=z0; M3_h(1,1)=z1; M3_h(2,2)=z2; + + Kokkos::deep_copy(M1, M1_h); + Kokkos::deep_copy(M3, M3_h); + + auto y = pressio::diagonal(M1); + const auto z = pressio::diagonal(M3); + + pressio::ops::elementwise_reciprocal(z, y); + Kokkos::deep_copy(M1_h, M1); + EXPECT_DOUBLE_EQ( M1_h(0,0), 1 / z0); + EXPECT_DOUBLE_EQ( M1_h(1,1), 1 / z1); + EXPECT_DOUBLE_EQ( M1_h(2,2), 1 / z2); +} diff --git a/tests/ops/ops_kokkos_span.cc b/tests/ops/ops_kokkos_span.cc index 483da9a..6cf82f2 100644 --- a/tests/ops/ops_kokkos_span.cc +++ b/tests/ops/ops_kokkos_span.cc @@ -291,3 +291,29 @@ TEST(ops_kokkos_span, elementwiseMultiply) EXPECT_DOUBLE_EQ( M1_h(4), 14.0); EXPECT_DOUBLE_EQ( M1_h(5), 23.0); } + +TEST(ops_kokkos_span, elementwiseReciprocal) +{ + vec_t M1("M1",6); + vec_t M3("M3",8); + + const auto z0 = 3.; + const auto z1 = 4.; + const auto z2 = 5.; + + auto M1_h = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), M1); + auto M3_h = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), M3); + M3_h(4)=z0; M3_h(5)=z1; M3_h(6)=z2; + + Kokkos::deep_copy(M1, M1_h); + Kokkos::deep_copy(M3, M3_h); + + auto y = pressio::span(M1,3,3); + const auto z = pressio::span(M3,4,3); + + pressio::ops::elementwise_reciprocal(z, y); + Kokkos::deep_copy(M1_h, M1); + EXPECT_DOUBLE_EQ( M1_h(3), 1 / z0); + EXPECT_DOUBLE_EQ( M1_h(4), 1 / z1); + EXPECT_DOUBLE_EQ( M1_h(5), 1 / z2); +} \ No newline at end of file diff --git a/tests/ops/ops_kokkos_vector.cc b/tests/ops/ops_kokkos_vector.cc index ef6262c..3c34b7f 100644 --- a/tests/ops/ops_kokkos_vector.cc +++ b/tests/ops/ops_kokkos_vector.cc @@ -479,3 +479,26 @@ TEST(ops_kokkos_vector, vector_elementwiseMultiply) EXPECT_DOUBLE_EQ( y_h(1), 12.0); EXPECT_DOUBLE_EQ( y_h(2), 20.0); } + +TEST(ops_kokkos_vector, vector_elementwiseReciprocal) +{ + Kokkos::View y("y", 3); + Kokkos::View z("z", 3); + + const auto z0 = 3.; + const auto z1 = 4.; + const auto z2 = 5.; + + auto y_h = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), y); + auto z_h = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), z); + z_h(0) = z0; z_h(1) = z1; z_h(2) = z2; + + Kokkos::deep_copy(y, y_h); + Kokkos::deep_copy(z, z_h); + + pressio::ops::elementwise_reciprocal(z, y); + Kokkos::deep_copy(y_h, y); + EXPECT_DOUBLE_EQ( y_h(0), 1 / z0); + EXPECT_DOUBLE_EQ( y_h(1), 1 / z1); + EXPECT_DOUBLE_EQ( y_h(2), 1 / z2); +}