ACTS
Experiment-independent tracking
Loading...
Searching...
No Matches
approximately_equal.hpp
1// This file is part of the ACTS project.
2//
3// Copyright (C) 2016 CERN for the benefit of the ACTS project
4//
5// This Source Code Form is subject to the terms of the Mozilla Public
6// License, v. 2.0. If a copy of the MPL was not distributed with this
7// file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9#pragma once
10
11// Project include(s)
12#include "detray/algebra/common/math.hpp"
13#include "detray/algebra/concepts.hpp"
14#include "detray/definitions/detail/qualifiers.hpp"
15
16// System include(s)
17#include <concepts>
18#include <limits>
19
20namespace detray::algebra {
21
34template <concepts::scalar scalar_t, concepts::value value_t>
35 requires std::convertible_to<scalar_t, value_t>
36DETRAY_HOST_DEVICE constexpr auto approx_equal(
37 const scalar_t a, const scalar_t b,
38 const value_t rel_error = 16.f * std::numeric_limits<value_t>::epsilon(),
39 const value_t max_error = std::numeric_limits<value_t>::epsilon()) {
40 if constexpr (std::integral<scalar_t>) {
41 return a == b;
42 } else {
43 // Calculate the difference.
44 const scalar_t diff{math::fabs(a - b)};
45
46 // If the numbers are close to zero
47 if (diff <= max_error) {
48 return true;
49 }
50
51 // Find the largest value to scale the epsilon
52 const scalar_t largest = math::max(math::fabs(a), math::fabs(b));
53
54 return (diff <= largest * rel_error);
55 }
56}
57
68template <typename vector1_t, typename vector2_t>
69 requires((concepts::vector<vector1_t> || concepts::point<vector1_t>) &&
70 (concepts::vector<vector2_t> || concepts::point<vector2_t>) &&
71 !concepts::simd_scalar<vector1_t> &&
72 !concepts::simd_scalar<vector2_t>)
73DETRAY_HOST_DEVICE constexpr auto approx_equal(
74 const vector1_t& v1, const vector2_t& v2,
75 const detray::traits::value_t<vector1_t> rel_error =
76 16.f *
77 std::numeric_limits<detray::traits::value_t<vector1_t>>::epsilon(),
78 const detray::traits::value_t<vector1_t> max_error =
79 std::numeric_limits<detray::traits::value_t<vector1_t>>::epsilon()) {
80 static_assert(std::same_as<detray::traits::value_t<vector1_t>,
81 detray::traits::value_t<vector2_t>>);
82
83 using index_t = detray::traits::index_t<vector1_t>;
84
85 constexpr index_t size{detray::traits::size<vector1_t>};
86
87 bool ret{true};
88 for (index_t i = 0; i < size; ++i) {
89 ret = ret &&
90 ::detray::algebra::approx_equal(v1[i], v2[i], rel_error, max_error);
91 }
92
93 return ret;
94}
95
107template <concepts::column_matrix vector1_t, concepts::column_matrix vector2_t>
108DETRAY_HOST_DEVICE constexpr auto approx_equal(
109 const vector1_t& v1, const vector2_t& v2,
110 const detray::traits::value_t<vector1_t> rel_error =
111 16.f *
112 std::numeric_limits<detray::traits::value_t<vector1_t>>::epsilon(),
113 const detray::traits::value_t<vector1_t> max_error =
114 std::numeric_limits<detray::traits::value_t<vector1_t>>::epsilon()) {
115 static_assert(std::same_as<detray::traits::value_t<vector1_t>,
116 detray::traits::value_t<vector2_t>>);
117
118 using index_t = detray::traits::index_t<vector1_t>;
119 using element_getter_t = detray::traits::element_getter_t<vector1_t>;
120
121 constexpr index_t rows{detray::traits::rows<vector1_t>};
122
123 bool ret{true};
124 for (index_t i = 0; i < rows; ++i) {
125 ret = ret && ::detray::algebra::approx_equal(element_getter_t{}(v1, i, 0),
126 element_getter_t{}(v2, i, 0),
127 rel_error, max_error);
128 }
129
130 return ret;
131}
132
143template <concepts::matrix matrix1_t, concepts::matrix matrix2_t>
144DETRAY_HOST_DEVICE constexpr auto approx_equal(
145 const matrix1_t& m1, const matrix2_t& m2,
146 const detray::traits::value_t<matrix1_t> rel_error =
147 16.f *
148 std::numeric_limits<detray::traits::value_t<matrix1_t>>::epsilon(),
149 const detray::traits::value_t<matrix1_t> max_error =
150 std::numeric_limits<detray::traits::value_t<matrix1_t>>::epsilon()) {
151 static_assert(std::same_as<detray::traits::value_t<matrix1_t>,
152 detray::traits::value_t<matrix2_t>>);
153
154 using index_t = detray::traits::index_t<matrix1_t>;
155 using element_getter_t = detray::traits::element_getter_t<matrix1_t>;
156
157 constexpr index_t rows{detray::traits::rows<matrix1_t>};
158 constexpr index_t columns{detray::traits::columns<matrix1_t>};
159
160 bool ret{true};
161 for (index_t j = 0; j < columns; ++j) {
162 for (index_t i = 0; i < rows; ++i) {
163 ret = ret && ::detray::algebra::approx_equal(element_getter_t{}(m1, i, j),
164 element_getter_t{}(m2, i, j),
165 rel_error, max_error);
166 }
167 }
168
169 return ret;
170}
171
183template <concepts::transform3D transform_t>
184DETRAY_HOST_DEVICE constexpr auto approx_equal(
185 const transform_t& trf1, const transform_t& trf2,
186 const detray::traits::value_t<typename transform_t::scalar_type> rel_error =
187 16.f * std::numeric_limits<detray::traits::value_t<
188 typename transform_t::scalar_type>>::epsilon(),
189 const detray::traits::value_t<typename transform_t::scalar_type> max_error =
190 std::numeric_limits<detray::traits::value_t<
191 typename transform_t::scalar_type>>::epsilon()) {
192 return (::detray::algebra::approx_equal(trf1.matrix(), trf2.matrix(),
193 rel_error, max_error) &&
194 ::detray::algebra::approx_equal(trf1.matrix_inverse(),
195 trf2.matrix_inverse(), rel_error,
196 max_error));
197}
198
199} // namespace detray::algebra
constexpr double m2
Square meter.
Definition Units.hpp:110
constexpr decltype(auto) fabs(T &&vec)
Definition vc_soa_math.hpp:71
constexpr decltype(auto) max(T &&vec)
Definition vc_soa_math.hpp:151