File indexing completed on 2026-05-27 07:23:55
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011
0012 #include "detray/algebra/common/math.hpp"
0013 #include "detray/algebra/concepts.hpp"
0014 #include "detray/definitions/detail/qualifiers.hpp"
0015
0016
0017 #include <concepts>
0018 #include <limits>
0019
0020 namespace detray::algebra {
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 template <concepts::scalar scalar_t, concepts::value value_t>
0034 requires std::convertible_to<scalar_t, value_t>
0035 DETRAY_HOST_DEVICE constexpr auto approx_equal(
0036 const scalar_t a, const scalar_t b,
0037 const value_t rel_error = 16.f * std::numeric_limits<value_t>::epsilon(),
0038 const value_t max_error = std::numeric_limits<value_t>::epsilon()) {
0039 if constexpr (std::integral<scalar_t>) {
0040 return a == b;
0041 } else {
0042
0043 const scalar_t diff{math::fabs(a - b)};
0044
0045
0046 if (diff <= max_error) {
0047 return true;
0048 }
0049
0050
0051 const scalar_t largest = math::max(math::fabs(a), math::fabs(b));
0052
0053 return (diff <= largest * rel_error);
0054 }
0055 }
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066 template <typename vector1_t, typename vector2_t>
0067 requires((concepts::vector<vector1_t> || concepts::point<vector1_t>) &&
0068 (concepts::vector<vector2_t> || concepts::point<vector2_t>) &&
0069 !concepts::simd_scalar<vector1_t> &&
0070 !concepts::simd_scalar<vector2_t>)
0071 DETRAY_HOST_DEVICE constexpr auto approx_equal(
0072 const vector1_t& v1, const vector2_t& v2,
0073 const detray::traits::value_t<vector1_t> rel_error =
0074 16.f *
0075 std::numeric_limits<detray::traits::value_t<vector1_t>>::epsilon(),
0076 const detray::traits::value_t<vector1_t> max_error =
0077 std::numeric_limits<detray::traits::value_t<vector1_t>>::epsilon()) {
0078 static_assert(std::same_as<detray::traits::value_t<vector1_t>,
0079 detray::traits::value_t<vector2_t>>);
0080
0081 using index_t = detray::traits::index_t<vector1_t>;
0082
0083 constexpr index_t size{detray::traits::size<vector1_t>};
0084
0085 bool ret{true};
0086 for (index_t i = 0; i < size; ++i) {
0087 ret = ret &&
0088 ::detray::algebra::approx_equal(v1[i], v2[i], rel_error, max_error);
0089 }
0090
0091 return ret;
0092 }
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 template <concepts::column_matrix vector1_t, concepts::column_matrix vector2_t>
0105 DETRAY_HOST_DEVICE constexpr auto approx_equal(
0106 const vector1_t& v1, const vector2_t& v2,
0107 const detray::traits::value_t<vector1_t> rel_error =
0108 16.f *
0109 std::numeric_limits<detray::traits::value_t<vector1_t>>::epsilon(),
0110 const detray::traits::value_t<vector1_t> max_error =
0111 std::numeric_limits<detray::traits::value_t<vector1_t>>::epsilon()) {
0112 static_assert(std::same_as<detray::traits::value_t<vector1_t>,
0113 detray::traits::value_t<vector2_t>>);
0114
0115 using index_t = detray::traits::index_t<vector1_t>;
0116 using element_getter_t = detray::traits::element_getter_t<vector1_t>;
0117
0118 constexpr index_t rows{detray::traits::rows<vector1_t>};
0119
0120 bool ret{true};
0121 for (index_t i = 0; i < rows; ++i) {
0122 ret = ret && ::detray::algebra::approx_equal(element_getter_t{}(v1, i, 0),
0123 element_getter_t{}(v2, i, 0),
0124 rel_error, max_error);
0125 }
0126
0127 return ret;
0128 }
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139 template <concepts::matrix matrix1_t, concepts::matrix matrix2_t>
0140 DETRAY_HOST_DEVICE constexpr auto approx_equal(
0141 const matrix1_t& m1, const matrix2_t& m2,
0142 const detray::traits::value_t<matrix1_t> rel_error =
0143 16.f *
0144 std::numeric_limits<detray::traits::value_t<matrix1_t>>::epsilon(),
0145 const detray::traits::value_t<matrix1_t> max_error =
0146 std::numeric_limits<detray::traits::value_t<matrix1_t>>::epsilon()) {
0147 static_assert(std::same_as<detray::traits::value_t<matrix1_t>,
0148 detray::traits::value_t<matrix2_t>>);
0149
0150 using index_t = detray::traits::index_t<matrix1_t>;
0151 using element_getter_t = detray::traits::element_getter_t<matrix1_t>;
0152
0153 constexpr index_t rows{detray::traits::rows<matrix1_t>};
0154 constexpr index_t columns{detray::traits::columns<matrix1_t>};
0155
0156 bool ret{true};
0157 for (index_t j = 0; j < columns; ++j) {
0158 for (index_t i = 0; i < rows; ++i) {
0159 ret = ret && ::detray::algebra::approx_equal(element_getter_t{}(m1, i, j),
0160 element_getter_t{}(m2, i, j),
0161 rel_error, max_error);
0162 }
0163 }
0164
0165 return ret;
0166 }
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178 template <concepts::transform3D transform_t>
0179 DETRAY_HOST_DEVICE constexpr auto approx_equal(
0180 const transform_t& trf1, const transform_t& trf2,
0181 const detray::traits::value_t<typename transform_t::scalar_type> rel_error =
0182 16.f * std::numeric_limits<detray::traits::value_t<
0183 typename transform_t::scalar_type>>::epsilon(),
0184 const detray::traits::value_t<typename transform_t::scalar_type> max_error =
0185 std::numeric_limits<detray::traits::value_t<
0186 typename transform_t::scalar_type>>::epsilon()) {
0187 return (::detray::algebra::approx_equal(trf1.matrix(), trf2.matrix(),
0188 rel_error, max_error) &&
0189 ::detray::algebra::approx_equal(trf1.matrix_inverse(),
0190 trf2.matrix_inverse(), rel_error,
0191 max_error));
0192 }
0193
0194 }