File indexing completed on 2026-05-27 07:24:20
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include "detray/definitions/algebra.hpp"
0012 #include "detray/algebra/utils/approximately_equal.hpp"
0013 #include "detray/algebra/utils/casts.hpp"
0014 #include "detray/algebra/utils/print.hpp"
0015
0016
0017
0018 #include "detray/test/framework/types.hpp"
0019
0020
0021 #include <gtest/gtest.h>
0022
0023
0024 #include <array>
0025 #include <limits>
0026
0027 using namespace detray;
0028
0029 using value_t = float;
0030
0031 constexpr value_t tol{1e-5f};
0032
0033
0034 TEST(detray_algebra_soa, vector) {
0035 using test_algebra_t = detray::vc_soa<value_t>;
0036 using vector3_v = dvector3D<test_algebra_t>;
0037
0038
0039 using scalar_t = dscalar<test_algebra_t>;
0040
0041 static_assert(detray::concepts::scalar<scalar_t>);
0042 static_assert(detray::concepts::vector<vector3_v>);
0043 static_assert(detray::concepts::vector3D<vector3_v>);
0044
0045
0046 using scalar_f = Vc::float_v;
0047 using scalar_d = Vc::double_v;
0048 using scalar_i = Vc::int_v;
0049
0050 auto s1 = detray::algebra::cast_to<float>(scalar_t(1.f));
0051 auto s2 = detray::algebra::cast_to<double>(scalar_t(2.f));
0052 auto s3 = detray::algebra::cast_to<int>(scalar_t(3.f));
0053
0054 static_assert(std::same_as<decltype(s1), scalar_f>);
0055 static_assert(std::same_as<decltype(s2), scalar_d>);
0056 static_assert(std::same_as<decltype(s3), scalar_i>);
0057
0058 ASSERT_TRUE((s1 == scalar_f(1.f)).isFull());
0059 ASSERT_TRUE((s2 == scalar_d(2.f)).isFull());
0060 ASSERT_TRUE((s3 == scalar_i(3.f)).isFull());
0061
0062 vector3_v a{1.f, 2.f, 3.f};
0063 vector3_v b{4.f, 5.f, 6.f};
0064
0065 EXPECT_TRUE((a[0] == scalar_t(1.f)).isFull());
0066 EXPECT_TRUE((a[1] == scalar_t(2.f)).isFull());
0067 EXPECT_TRUE((a[2] == scalar_t(3.f)).isFull());
0068
0069
0070 std::cout << a << std::endl;
0071
0072
0073 constexpr auto epsilon{std::numeric_limits<value_t>::epsilon()};
0074
0075 EXPECT_TRUE(detray::algebra::approx_equal(a, a));
0076 EXPECT_TRUE(detray::algebra::approx_equal(a, a, epsilon));
0077 EXPECT_FALSE(detray::algebra::approx_equal(a, b));
0078
0079 value_t rel_err = 1.f + 10.f * epsilon;
0080 vector3_v a_err = rel_err * a;
0081 EXPECT_TRUE(detray::algebra::approx_equal(a, a_err, 11.f * epsilon));
0082 EXPECT_FALSE(detray::algebra::approx_equal(a, a_err, 9.f * epsilon));
0083
0084 rel_err = 1.f + 17.f * epsilon;
0085 a_err = rel_err * a;
0086 EXPECT_TRUE(detray::algebra::approx_equal(a, a_err, 18.f * epsilon));
0087 EXPECT_FALSE(detray::algebra::approx_equal(a, a_err, 16.f * epsilon));
0088
0089
0090 vector3_v a_err_cpy = a_err;
0091 EXPECT_TRUE(a_err_cpy == a_err);
0092 EXPECT_TRUE(detray::algebra::approx_equal(a_err_cpy, a_err));
0093
0094 auto& vec_elem = a_err[0];
0095 vec_elem[0] += 1.f;
0096 EXPECT_FALSE(a_err_cpy == a_err);
0097 EXPECT_FALSE(detray::algebra::approx_equal(a_err_cpy, a_err));
0098
0099 auto a_cast_f = detray::algebra::cast_to<float>(a);
0100 auto a_cast_d = detray::algebra::cast_to<double>(a);
0101 auto a_cast_i = detray::algebra::cast_to<int>(a);
0102
0103 using algebra_f_t = detray::vc_soa<float>;
0104 using algebra_d_t = detray::vc_soa<double>;
0105 using algebra_i_t = detray::vc_soa<int>;
0106 static_assert(std::same_as<decltype(a_cast_f), dvector3D<algebra_f_t>>);
0107 static_assert(std::same_as<decltype(a_cast_d), dvector3D<algebra_d_t>>);
0108 static_assert(std::same_as<decltype(a_cast_i), dvector3D<algebra_i_t>>);
0109
0110 for (int i = 0; i < 3; ++i) {
0111 EXPECT_TRUE(
0112 (a_cast_f[i] == detray::algebra::cast_to<float>(a[i])).isFull());
0113 EXPECT_TRUE(
0114 (a_cast_d[i] == detray::algebra::cast_to<double>(a[i])).isFull());
0115 EXPECT_TRUE((a_cast_i[i] == detray::algebra::cast_to<int>(a[i])).isFull());
0116 }
0117
0118
0119 auto m = a.compare(a);
0120 EXPECT_TRUE(m[0].isFull());
0121 EXPECT_TRUE(m[1].isFull());
0122 EXPECT_TRUE(m[2].isFull());
0123
0124 m = a.compare(b);
0125 EXPECT_FALSE(m[0].isFull());
0126 EXPECT_FALSE(m[1].isFull());
0127 EXPECT_FALSE(m[2].isFull());
0128
0129
0130 EXPECT_TRUE(a == a);
0131 EXPECT_FALSE(a == b);
0132
0133
0134 auto v_add = a + b;
0135 EXPECT_TRUE((v_add[0] == scalar_t(5.f)).isFull());
0136 EXPECT_TRUE((v_add[1] == scalar_t(7.f)).isFull());
0137 EXPECT_TRUE((v_add[2] == scalar_t(9.f)).isFull());
0138
0139
0140 auto v_sub = a - b;
0141 EXPECT_TRUE((v_sub[0] == scalar_t(-3.f)).isFull());
0142 EXPECT_TRUE((v_sub[1] == scalar_t(-3.f)).isFull());
0143 EXPECT_TRUE((v_sub[2] == scalar_t(-3.f)).isFull());
0144
0145
0146 auto v_mul = a * b;
0147 EXPECT_TRUE((v_mul[0] == scalar_t(4.f)).isFull());
0148 EXPECT_TRUE((v_mul[1] == scalar_t(10.f)).isFull());
0149 EXPECT_TRUE((v_mul[2] == scalar_t(18.f)).isFull());
0150
0151
0152 auto v_div = a / b;
0153 EXPECT_TRUE((v_div[0] == scalar_t(0.25f)).isFull());
0154 EXPECT_TRUE((v_div[1] == scalar_t(0.4f)).isFull());
0155 EXPECT_TRUE((v_div[2] == scalar_t(0.5f)).isFull());
0156
0157
0158 auto v_smul = 2.f * b;
0159 EXPECT_TRUE((v_smul[0] == scalar_t(8.f)).isFull());
0160 EXPECT_TRUE((v_smul[1] == scalar_t(10.f)).isFull());
0161 EXPECT_TRUE((v_smul[2] == scalar_t(12.f)).isFull());
0162
0163
0164 auto v_expr = (b / a) - (2.5f * b) + vector3_v{};
0165 EXPECT_TRUE((v_expr[0] == scalar_t(-6.f)).isFull());
0166 EXPECT_TRUE((v_expr[1] == scalar_t(-10.f)).isFull());
0167 EXPECT_TRUE((v_expr[2] == scalar_t(-13.f)).isFull());
0168
0169 auto d{vector::dot(a, b)};
0170 EXPECT_TRUE((d == scalar_t(32.f)).isFull());
0171
0172 scalar_t norms_a{vector::norm(vector::normalize(a))};
0173 scalar_t norms_b{vector::norm(vector::normalize(b))};
0174 for (unsigned int i{0u}; i < norms_a.size(); ++i) {
0175 EXPECT_NEAR(norms_a[i], 1.f, tol);
0176 EXPECT_NEAR(norms_b[i], 1.f, tol);
0177 }
0178
0179 auto cr{vector::cross(a, b)};
0180 EXPECT_TRUE((cr[0] == scalar_t(-3.f)).isFull());
0181 EXPECT_TRUE((cr[1] == scalar_t(6.f)).isFull());
0182 EXPECT_TRUE((cr[2] == scalar_t(-3.f)).isFull());
0183
0184 static_assert(std::is_convertible_v<decltype(v_expr), vector3_v>,
0185 "expression type not convertible");
0186 }
0187
0188
0189 TEST(detray_algebra_soa, getter) {
0190 using test_algebra_t = detray::vc_soa<value_t>;
0191
0192 using vector3_v = dvector3D<test_algebra_t>;
0193
0194 vector3_v a{1.f, 2.f, 3.f};
0195
0196
0197
0198
0199 auto v_phi = vector::phi(a);
0200 EXPECT_NEAR(v_phi[0], static_cast<value_t>(std::atan2(2., 1.)), tol);
0201
0202
0203 auto v_perp = vector::perp(a);
0204 EXPECT_NEAR(v_perp[0], std::sqrt(5.), tol);
0205
0206
0207 auto v_theta = vector::theta(a);
0208 EXPECT_NEAR(v_theta[0], static_cast<value_t>(std::atan2(std::sqrt(5.), 3.)),
0209 tol);
0210
0211
0212 auto v_norm = vector::norm(a);
0213 EXPECT_NEAR(v_norm[0], std::sqrt(14.), tol);
0214
0215
0216 auto v_eta = vector::eta(a);
0217 EXPECT_NEAR(v_eta[0],
0218 static_cast<value_t>(std::atanh(1. / std::sqrt(14.) * 3.)), tol);
0219 }
0220
0221
0222 TEST(detray_algebra_soa, transform3) {
0223 using test_algebra_t = detray::vc_soa<value_t>;
0224
0225
0226 using algebra::operator<<;
0227
0228 using vector3 = dvector3D<test_algebra_t>;
0229 using point3 = dpoint3D<test_algebra_t>;
0230 using scalar_t = dscalar<test_algebra_t>;
0231 using transform3 = dtransform3D<test_algebra_t>;
0232
0233 static_assert(detray::concepts::transform3D<transform3>);
0234
0235 transform3 idty{};
0236
0237 EXPECT_TRUE((idty(0, 0) == scalar_t::One()).isFull());
0238 EXPECT_TRUE((idty(1, 0) == scalar_t::Zero()).isFull());
0239 EXPECT_TRUE((idty(2, 0) == scalar_t::Zero()).isFull());
0240 EXPECT_TRUE((idty(0, 1) == scalar_t::Zero()).isFull());
0241 EXPECT_TRUE((idty(1, 1) == scalar_t::One()).isFull());
0242 EXPECT_TRUE((idty(2, 1) == scalar_t::Zero()).isFull());
0243 EXPECT_TRUE((idty(0, 2) == scalar_t::Zero()).isFull());
0244 EXPECT_TRUE((idty(1, 2) == scalar_t::Zero()).isFull());
0245 EXPECT_TRUE((idty(2, 2) == scalar_t::One()).isFull());
0246 EXPECT_TRUE((idty(0, 3) == scalar_t::Zero()).isFull());
0247 EXPECT_TRUE((idty(1, 3) == scalar_t::Zero()).isFull());
0248 EXPECT_TRUE((idty(2, 3) == scalar_t::Zero()).isFull());
0249
0250
0251 vector3 z = vector::normalize(vector3{3.f, 2.f, 1.f});
0252 vector3 x = vector::normalize(vector3{2.f, -3.f, 0.f});
0253 vector3 y = vector::cross(z, x);
0254 point3 t = {2.f, 3.f, 4.f};
0255
0256
0257 transform3 trf1(t, z, x);
0258 ASSERT_TRUE(trf1 == trf1);
0259 transform3 trf2;
0260 trf2 = trf1;
0261
0262
0263 std::cout << trf1 << std::endl;
0264
0265
0266 constexpr auto epsilon{std::numeric_limits<value_t>::epsilon()};
0267
0268 EXPECT_TRUE(detray::algebra::approx_equal(trf1, trf1));
0269 EXPECT_TRUE(detray::algebra::approx_equal(trf1, trf1, epsilon));
0270
0271 value_t rel_err{1.f + 10.f * epsilon};
0272 transform3 trf1_err(rel_err * t, rel_err * z, rel_err * x);
0273 EXPECT_FALSE(trf1 == trf1_err);
0274 EXPECT_TRUE(detray::algebra::approx_equal(trf1, trf1_err, 200.f * epsilon));
0275 EXPECT_FALSE(detray::algebra::approx_equal(trf1, trf1_err, 10.f * epsilon));
0276
0277 auto trf1_cast_f = detray::algebra::cast_to<float>(trf1);
0278 auto trf1_cast_d = detray::algebra::cast_to<double>(trf1);
0279 auto trf1_cast_i = detray::algebra::cast_to<int>(trf1);
0280
0281 using algebra_f_t = detray::vc_soa<float>;
0282 using algebra_d_t = detray::vc_soa<double>;
0283 using algebra_i_t = detray::vc_soa<int>;
0284 static_assert(std::same_as<decltype(trf1_cast_f), dtransform3D<algebra_f_t>>);
0285 static_assert(std::same_as<decltype(trf1_cast_d), dtransform3D<algebra_d_t>>);
0286 static_assert(std::same_as<decltype(trf1_cast_i), dtransform3D<algebra_i_t>>);
0287
0288 const auto& mat_f = trf1_cast_f.matrix();
0289 const auto& mat_d = trf1_cast_d.matrix();
0290 const auto& mat_i = trf1_cast_i.matrix();
0291 for (int j = 0; j < 3; ++j) {
0292 for (int i = 0; i < 3; ++i) {
0293 const auto& elem_ij = trf1.matrix()[i][j];
0294 EXPECT_TRUE(
0295 (mat_f[i][j] == detray::algebra::cast_to<float>(elem_ij)).isFull());
0296 EXPECT_TRUE(
0297 (mat_d[i][j] == detray::algebra::cast_to<double>(elem_ij)).isFull());
0298 EXPECT_TRUE(
0299 (mat_i[i][j] == detray::algebra::cast_to<int>(elem_ij)).isFull());
0300 }
0301 }
0302
0303 EXPECT_TRUE((trf2(0, 0) == x[0]).isFull());
0304 EXPECT_TRUE((trf2(1, 0) == x[1]).isFull());
0305 EXPECT_TRUE((trf2(2, 0) == x[2]).isFull());
0306 EXPECT_TRUE((trf2(0, 1) == y[0]).isFull());
0307 EXPECT_TRUE((trf2(1, 1) == y[1]).isFull());
0308 EXPECT_TRUE((trf2(2, 1) == y[2]).isFull());
0309 EXPECT_TRUE((trf2(0, 2) == z[0]).isFull());
0310 EXPECT_TRUE((trf2(1, 2) == z[1]).isFull());
0311 EXPECT_TRUE((trf2(2, 2) == z[2]).isFull());
0312 EXPECT_TRUE((trf2(0, 3) == 2.f * scalar_t::One()).isFull());
0313 EXPECT_TRUE((trf2(1, 3) == 3.f * scalar_t::One()).isFull());
0314 EXPECT_TRUE((trf2(2, 3) == 4.f * scalar_t::One()).isFull());
0315
0316
0317 point3 lzero = {0.f, 0.f, 0.f};
0318 point3 gzero = trf2.point_to_global(lzero);
0319 EXPECT_TRUE((gzero[0] == t[0]).isFull());
0320 EXPECT_TRUE((gzero[1] == t[1]).isFull());
0321 EXPECT_TRUE((gzero[2] == t[2]).isFull());
0322
0323
0324 point3 loc_pt = {3.f, 4.f, 5.f};
0325 point3 glob_pt = trf2.point_to_global(loc_pt);
0326 point3 loc_pt_r = trf2.point_to_local(glob_pt);
0327 EXPECT_NEAR(loc_pt[0][0], loc_pt_r[0][0], tol);
0328 EXPECT_NEAR(loc_pt[1][0], loc_pt_r[1][0], tol);
0329 EXPECT_NEAR(loc_pt[2][0], loc_pt_r[2][0], tol);
0330
0331
0332
0333 transform3 ttrf(t);
0334
0335 vector3 glob_vec = {1.f, 1.f, 1.f};
0336 vector3 loc_vec = ttrf.vector_to_local(glob_vec);
0337 EXPECT_NEAR(glob_vec[0][0], loc_vec[0][0], tol);
0338 EXPECT_NEAR(glob_vec[1][0], loc_vec[1][0], tol);
0339 EXPECT_NEAR(glob_vec[2][0], loc_vec[2][0], tol);
0340
0341
0342 vector3 loc_vecB = {7.f, 8.f, 9.f};
0343 vector3 glob_vecB = trf2.vector_to_local(loc_vecB);
0344 vector3 loc_vecC = trf2.vector_to_global(glob_vecB);
0345 EXPECT_NEAR(loc_vecB[0][0], loc_vecC[0][0], tol);
0346 EXPECT_NEAR(loc_vecB[1][0], loc_vecC[1][0], tol);
0347 EXPECT_NEAR(loc_vecB[2][0], loc_vecC[2][0], tol);
0348 }
0349
0350
0351 TEST(detray_algebra_soa, matrix3) {
0352 using test_algebra_t = detray::vc_soa<value_t>;
0353 using matrix_2x3_t = dmatrix<test_algebra_t, 2, 3>;
0354
0355
0356 static_assert(
0357 std::is_same_v<detray::traits::index_t<matrix_2x3_t>, std::size_t>);
0358 static_assert(std::is_same_v<detray::traits::value_t<matrix_2x3_t>, value_t>);
0359 static_assert(std::is_same_v<detray::traits::scalar_t<matrix_2x3_t>,
0360 Vc::Vector<value_t>>);
0361 static_assert(std::is_same_v<detray::traits::vector_t<matrix_2x3_t>,
0362 dvector2D<test_algebra_t>>);
0363
0364 static_assert(detray::traits::rows<matrix_2x3_t> == 2);
0365 static_assert(detray::traits::columns<matrix_2x3_t> == 3);
0366 static_assert(detray::traits::max_rank<matrix_2x3_t> == 2);
0367 static_assert(detray::traits::size<matrix_2x3_t> == 6);
0368 static_assert(!detray::traits::is_square<matrix_2x3_t>);
0369 static_assert(detray::traits::is_square<dmatrix<test_algebra_t, 2, 2>>);
0370 static_assert(detray::traits::is_square<dmatrix<test_algebra_t, 3, 3>>);
0371 }
0372
0373
0374 TEST(detray_algebra_soa, matrix64) {
0375 using test_algebra_t = detray::vc_soa<value_t>;
0376
0377
0378 using matrix_6x4_t = dmatrix<test_algebra_t, 6, 4>;
0379 using scalar_t = dscalar<test_algebra_t>;
0380
0381 matrix_6x4_t m;
0382
0383
0384 static_assert(
0385 std::is_same_v<detray::traits::index_t<matrix_6x4_t>, std::size_t>);
0386 static_assert(std::is_same_v<detray::traits::value_t<matrix_6x4_t>, value_t>);
0387 static_assert(std::is_same_v<detray::traits::scalar_t<matrix_6x4_t>,
0388 Vc::Vector<value_t>>);
0389
0390 static_assert(detray::traits::rows<matrix_6x4_t> == 6);
0391 static_assert(detray::traits::columns<matrix_6x4_t> == 4);
0392 static_assert(detray::traits::max_rank<matrix_6x4_t> == 4);
0393 static_assert(detray::traits::size<matrix_6x4_t> == 24);
0394 static_assert(!detray::traits::is_square<matrix_6x4_t>);
0395 static_assert(detray::traits::is_square<dmatrix<test_algebra_t, 4, 4>>);
0396 static_assert(detray::traits::is_square<dmatrix<test_algebra_t, 6, 6>>);
0397
0398
0399 std::cout << m << std::endl;
0400
0401 auto I64 = detray::matrix::identity<matrix_6x4_t>();
0402
0403
0404 constexpr auto epsilon{std::numeric_limits<value_t>::epsilon()};
0405
0406 EXPECT_TRUE(detray::algebra::approx_equal(m, m));
0407 EXPECT_TRUE(detray::algebra::approx_equal(m, m, epsilon));
0408 EXPECT_FALSE(detray::algebra::approx_equal(m, I64));
0409
0410 value_t rel_err{1.f + 10.f * epsilon};
0411 matrix_6x4_t I64_err = scalar_t(rel_err) * I64;
0412 EXPECT_FALSE(I64 == I64_err);
0413 EXPECT_TRUE(detray::algebra::approx_equal(I64, I64_err, 11.f * epsilon));
0414 EXPECT_FALSE(detray::algebra::approx_equal(I64, I64_err, 9.f * epsilon));
0415
0416 auto m_cast_f = detray::algebra::cast_to<float>(m);
0417 auto m_cast_d = detray::algebra::cast_to<double>(m);
0418 auto m_cast_i = detray::algebra::cast_to<int>(m);
0419
0420 using algebra_f_t = detray::vc_soa<float>;
0421 using algebra_d_t = detray::vc_soa<double>;
0422 using algebra_i_t = detray::vc_soa<int>;
0423 static_assert(std::same_as<decltype(m_cast_f), dmatrix<algebra_f_t, 6, 4>>);
0424 static_assert(std::same_as<decltype(m_cast_d), dmatrix<algebra_d_t, 6, 4>>);
0425 static_assert(std::same_as<decltype(m_cast_i), dmatrix<algebra_i_t, 6, 4>>);
0426 }