Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions include/tensorwrapper/operations/norm.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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 <tensorwrapper/tensor/tensor.hpp>

namespace tensorwrapper::operations {

/** @brief Returns the infinity norm of @p t.
*
* The infinity norm of the tensor @p t is the element of @p t with the
* largest absolute value.
*
* @param[in] t The tensor to take the norm of.
*
* @return The infinity norm of @p t.
*/
Tensor infinity_norm(const Tensor& t);

} // namespace tensorwrapper::operations
1 change: 1 addition & 0 deletions include/tensorwrapper/operations/operations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#pragma once
#include <tensorwrapper/operations/approximately_equal.hpp>
#include <tensorwrapper/operations/norm.hpp>

/// Namespace for free functions that act on tensors
namespace tensorwrapper::operations {}
21 changes: 21 additions & 0 deletions include/tensorwrapper/types/floating_point.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@ using udouble = sigma::UDouble;

using floating_point_types = std::tuple<float, double, ufloat, udouble>;

template<typename T>
constexpr bool is_uncertain_v =
std::is_same_v<T, ufloat> || std::is_same_v<T, udouble>;

template<typename T>
T fabs(T value) {
if constexpr(is_uncertain_v<T>) {
return sigma::fabs(value);
} else {
return std::fabs(value);
}
}

#define TW_APPLY_FLOATING_POINT_TYPES(MACRO_IN) \
MACRO_IN(float); \
MACRO_IN(double); \
Expand All @@ -40,6 +53,14 @@ using udouble = double;

using floating_point_types = std::tuple<float, double>;

template<typename>
constexpr bool is_uncertain_v = false;

template<typename T>
T fabs(T value) {
return std::fabs(value);
}

#define TW_APPLY_FLOATING_POINT_TYPES(MACRO_IN) \
MACRO_IN(float); \
MACRO_IN(double)
Expand Down
49 changes: 49 additions & 0 deletions src/tensorwrapper/operations/norm.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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 <tensorwrapper/buffer/eigen.hpp>
#include <tensorwrapper/shape/smooth.hpp>
#include <tensorwrapper/tensor/tensor.hpp>
#include <tensorwrapper/utilities/floating_point_dispatch.hpp>

namespace tensorwrapper::operations {
namespace {
struct InfinityKernel {
template<typename FloatType>
Tensor run(const buffer::BufferBase& t) {
using allocator_type = allocator::Eigen<FloatType>;
allocator_type alloc(t.allocator().runtime());
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));
if(elem > max_element) max_element = elem;
}
shape::Smooth s{};
layout::Physical l(s);
auto pbuffer = alloc.construct(l, max_element);
return Tensor(s, std::move(pbuffer));
}
};

} // namespace

Tensor infinity_norm(const Tensor& t) {
InfinityKernel k;
return utilities::floating_point_dispatch(k, t.buffer());
}

} // namespace tensorwrapper::operations
63 changes: 63 additions & 0 deletions tests/cxx/unit_tests/tensorwrapper/operations/norm.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* 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 <tensorwrapper/operations/approximately_equal.hpp>
#include <tensorwrapper/operations/norm.hpp>
#include <testing/testing.hpp>

using namespace tensorwrapper;
using namespace tensorwrapper::operations;

TEMPLATE_LIST_TEST_CASE("infinity_norm", "", types::floating_point_types) {
SECTION("scalar") {
shape::Smooth s{};
Tensor scalar(s, testing::eigen_scalar<TestType>());
auto norm = infinity_norm(scalar);
REQUIRE(approximately_equal(scalar, norm));
}

SECTION("vector") {
shape::Smooth s{5};
Tensor vector(s, testing::eigen_vector<TestType>());
Tensor corr(shape::Smooth{}, testing::eigen_scalar<TestType>(4));
auto norm = infinity_norm(vector);
REQUIRE(approximately_equal(corr, norm));
}

SECTION("matrix") {
shape::Smooth s{2, 2};
Tensor matrix(s, testing::eigen_matrix<TestType>());
Tensor corr(shape::Smooth{}, testing::eigen_scalar<TestType>(4));
auto norm = infinity_norm(matrix);
REQUIRE(approximately_equal(corr, norm));
}

SECTION("rank 3 tensor") {
shape::Smooth s{2, 2, 2};
Tensor t(s, testing::eigen_tensor3<TestType>());
Tensor corr(shape::Smooth{}, testing::eigen_scalar<TestType>(8));
auto norm = infinity_norm(t);
REQUIRE(approximately_equal(corr, norm));
}

SECTION("rank 4 tensor") {
shape::Smooth s{2, 2, 2, 2};
Tensor t(s, testing::eigen_tensor4<TestType>());
Tensor corr(shape::Smooth{}, testing::eigen_scalar<TestType>(16));
auto norm = infinity_norm(t);
REQUIRE(approximately_equal(corr, norm));
}
}
4 changes: 2 additions & 2 deletions tests/cxx/unit_tests/tensorwrapper/testing/eigen_buffers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ auto make_allocator() {
}

template<typename FloatType>
auto eigen_scalar() {
auto eigen_scalar(FloatType value = 42.0) {
auto alloc = make_allocator<FloatType>();
return alloc.construct(42.0);
return alloc.construct(value);
}

template<typename FloatType>
Expand Down