Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-27 07:24:19

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 // Test include(s).
0010 #include "detray/test/cpu/algebra_fixture.hpp"
0011 
0012 // Project include(s).
0013 #include "detray/algebra/utils/approximately_equal.hpp"
0014 #include "detray/algebra/utils/casts.hpp"
0015 #include "detray/algebra/utils/print.hpp"
0016 
0017 // GoogleTest include(s).
0018 #include <gtest/gtest.h>
0019 
0020 // System include(s)
0021 #include <array>
0022 #include <iostream>
0023 
0024 namespace detray::test {
0025 
0026 // This defines the transform3 test suite
0027 TEST_F(detray_algebra, transform3D) {
0028   static_assert(detray::concepts::transform3D<transform3>);
0029 
0030   // Preparation work
0031   vector3 z = detray::vector::normalize(vector3{3.f, 2.f, 1.f});
0032   vector3 x = detray::vector::normalize(vector3{2.f, -3.f, 0.f});
0033   vector3 y = detray::vector::cross(z, x);
0034   point3 t = {2.f, 3.f, 4.f};
0035 
0036   // Test constructor from t, z, x
0037   transform3 trf1(t, z, x);
0038   ASSERT_TRUE(trf1 == trf1);
0039   transform3 trf2;
0040   trf2 = trf1;
0041 
0042   // Test printing
0043   std::cout << trf1 << std::endl;
0044 
0045   // Test comparison
0046   ASSERT_TRUE(detray::algebra::approx_equal(trf1, trf1));
0047   ASSERT_TRUE(detray::algebra::approx_equal(trf1, trf1, this->epsilon()));
0048 
0049   scalar rel_err{1.f + 10.f * this->epsilon()};
0050   transform3 trf1_err(rel_err * t, rel_err * z, rel_err * x);
0051   ASSERT_TRUE(
0052       detray::algebra::approx_equal(trf1, trf1_err, 200.f * this->epsilon()));
0053   ASSERT_FALSE(
0054       detray::algebra::approx_equal(trf1, trf1_err, 10.f * this->epsilon()));
0055   // Cast to (different) precision
0056   const auto trf1_cast_f = detray::algebra::cast_to<float>(trf1);
0057   const auto& mat_f = trf1_cast_f.matrix();
0058   const auto& mat_inv_f = trf1_cast_f.matrix_inverse();
0059 
0060   for (std::size_t j = 0u; j < 3u; ++j) {
0061     for (std::size_t i = 0u; i < 2u; ++i) {
0062       auto elem_i = detray::getter::element(mat_f, i, j);
0063       auto elem_inv_i = detray::getter::element(mat_inv_f, i, j);
0064 
0065       static_assert(std::same_as<decltype(elem_i), float>);
0066       static_assert(std::same_as<decltype(elem_inv_i), float>);
0067       ASSERT_FLOAT_EQ(elem_i,
0068                       static_cast<float>(detray::getter::element(mat_f, i, j)));
0069       ASSERT_FLOAT_EQ(elem_inv_i, static_cast<float>(detray::getter::element(
0070                                       mat_inv_f, i, j)));
0071     }
0072   }
0073 
0074   const auto trf1_cast_d = detray::algebra::cast_to<double>(trf1);
0075   const auto& mat_d = trf1_cast_d.matrix();
0076   const auto& mat_inv_d = trf1_cast_d.matrix_inverse();
0077 
0078   for (std::size_t j = 0u; j < 3u; ++j) {
0079     for (std::size_t i = 0u; i < 2u; ++i) {
0080       auto elem_i = detray::getter::element(mat_d, i, j);
0081       auto elem_inv_i = detray::getter::element(mat_inv_d, i, j);
0082 
0083       static_assert(std::same_as<decltype(elem_i), double>);
0084       static_assert(std::same_as<decltype(elem_inv_i), double>);
0085       ASSERT_DOUBLE_EQ(
0086           elem_i, static_cast<double>(detray::getter::element(mat_d, i, j)));
0087       ASSERT_DOUBLE_EQ(elem_inv_i, static_cast<double>(detray::getter::element(
0088                                        mat_inv_d, i, j)));
0089     }
0090   }
0091 
0092   const auto trf1_cast_i = detray::algebra::cast_to<int>(trf1);
0093   const auto& mat_i = trf1_cast_i.matrix();
0094   const auto& mat_inv_i = trf1_cast_i.matrix_inverse();
0095 
0096   for (std::size_t j = 0u; j < 3u; ++j) {
0097     for (std::size_t i = 0u; i < 2u; ++i) {
0098       auto elem_i = detray::getter::element(mat_i, i, j);
0099       auto elem_inv_i = detray::getter::element(mat_inv_i, i, j);
0100 
0101       static_assert(std::same_as<decltype(elem_i), int>);
0102       static_assert(std::same_as<decltype(elem_inv_i), int>);
0103       ASSERT_EQ(elem_i, static_cast<int>(detray::getter::element(mat_i, i, j)));
0104       ASSERT_EQ(elem_inv_i,
0105                 static_cast<int>(detray::getter::element(mat_inv_i, i, j)));
0106     }
0107   }
0108 
0109   const auto rot = trf2.rotation();
0110   ASSERT_NEAR(detray::getter::element(rot, 0, 0), x[0], this->epsilon());
0111   ASSERT_NEAR(detray::getter::element(rot, 1, 0), x[1], this->epsilon());
0112   ASSERT_NEAR(detray::getter::element(rot, 2, 0), x[2], this->epsilon());
0113   ASSERT_NEAR(detray::getter::element(rot, 0, 1), y[0], this->epsilon());
0114   ASSERT_NEAR(detray::getter::element(rot, 1, 1), y[1], this->epsilon());
0115   ASSERT_NEAR(detray::getter::element(rot, 2, 1), y[2], this->epsilon());
0116   ASSERT_NEAR(detray::getter::element(rot, 0, 2), z[0], this->epsilon());
0117   ASSERT_NEAR(detray::getter::element(rot, 1, 2), z[1], this->epsilon());
0118   ASSERT_NEAR(detray::getter::element(rot, 2, 2), z[2], this->epsilon());
0119 
0120   auto trn = trf2.translation();
0121   ASSERT_NEAR(trn[0], 2.f, this->epsilon());
0122   ASSERT_NEAR(trn[1], 3.f, this->epsilon());
0123   ASSERT_NEAR(trn[2], 4.f, this->epsilon());
0124 
0125   // Test constructor from matrix
0126   auto m44 = trf2.matrix();
0127   transform3 trfm(m44);
0128 
0129   // Make sure that detray::getter:vector can be called.
0130   [[maybe_unused]] vector3
0131       test_vector;  // we need to declare a variable in order to use the
0132                     // [[maybe_unused]] attribute here
0133 
0134   test_vector = detray::getter::vector<3>(m44, 0, 0);
0135   test_vector = detray::getter::vector<3>(m44, 0, 1);
0136   test_vector = detray::getter::vector<3>(m44, 0, 2);
0137 
0138   // Test constructor from inverse matrix
0139   auto m44_inv = trf2.matrix_inverse();
0140 
0141   // Make sure that detray::getter:vector can be called.
0142   test_vector = detray::getter::vector<3>(m44_inv, 0, 0);
0143   test_vector = detray::getter::vector<3>(m44_inv, 0, 1);
0144   test_vector = detray::getter::vector<3>(m44_inv, 0, 2);
0145 
0146   // Re-evaluate rot and trn
0147   auto rotm = trfm.rotation();
0148   ASSERT_NEAR(detray::getter::element(rotm, 0, 0), x[0], this->epsilon());
0149   ASSERT_NEAR(detray::getter::element(rotm, 1, 0), x[1], this->epsilon());
0150   ASSERT_NEAR(detray::getter::element(rotm, 2, 0), x[2], this->epsilon());
0151   ASSERT_NEAR(detray::getter::element(rotm, 0, 1), y[0], this->epsilon());
0152   ASSERT_NEAR(detray::getter::element(rotm, 1, 1), y[1], this->epsilon());
0153   ASSERT_NEAR(detray::getter::element(rotm, 2, 1), y[2], this->epsilon());
0154   ASSERT_NEAR(detray::getter::element(rotm, 0, 2), z[0], this->epsilon());
0155   ASSERT_NEAR(detray::getter::element(rotm, 1, 2), z[1], this->epsilon());
0156   ASSERT_NEAR(detray::getter::element(rotm, 2, 2), z[2], this->epsilon());
0157 
0158   auto trnm = trfm.translation();
0159   ASSERT_NEAR(trnm[0], 2.f, this->epsilon());
0160   ASSERT_NEAR(trnm[1], 3.f, this->epsilon());
0161   ASSERT_NEAR(trnm[2], 4.f, this->epsilon());
0162 
0163   // Check a construction from an array[16]
0164   std::array<scalar, 16> matray_helper = {1.f, 0.f, 0.f, 0.f, 0.f, 1.f,
0165                                           0.f, 0.f, 0.f, 0.f, 1.f, 0.f,
0166                                           0.f, 0.f, 0.f, 0.f};
0167   typename transform3::template array_type<16> matray;
0168   for (unsigned int i = 0u; i < 16u; ++i) {
0169     matray[i] = matray_helper[i];
0170   }
0171   transform3 trfma(matray);
0172 
0173   // Re-evaluate rot and trn
0174   auto rotma = trfma.rotation();
0175   ASSERT_NEAR(detray::getter::element(rotma, 0, 0), 1.f, this->epsilon());
0176   ASSERT_NEAR(detray::getter::element(rotma, 1, 0), 0.f, this->epsilon());
0177   ASSERT_NEAR(detray::getter::element(rotma, 2, 0), 0.f, this->epsilon());
0178   ASSERT_NEAR(detray::getter::element(rotma, 0, 1), 0.f, this->epsilon());
0179   ASSERT_NEAR(detray::getter::element(rotma, 1, 1), 1.f, this->epsilon());
0180   ASSERT_NEAR(detray::getter::element(rotma, 2, 1), 0.f, this->epsilon());
0181   ASSERT_NEAR(detray::getter::element(rotma, 0, 2), 0.f, this->epsilon());
0182   ASSERT_NEAR(detray::getter::element(rotma, 1, 2), 0.f, this->epsilon());
0183   ASSERT_NEAR(detray::getter::element(rotma, 2, 2), 1.f, this->epsilon());
0184 
0185   auto trnma = trfma.translation();
0186   ASSERT_NEAR(trnma[0], 0.f, this->epsilon());
0187   ASSERT_NEAR(trnma[1], 0.f, this->epsilon());
0188   ASSERT_NEAR(trnma[2], 0.f, this->epsilon());
0189 }
0190 
0191 // This test global coordinate transforms
0192 TEST_F(detray_algebra, global_transformations) {
0193   // Preparation work
0194   vector3 z = detray::vector::normalize(vector3{3.f, 2.f, 1.f});
0195   vector3 x = detray::vector::normalize(vector3{2.f, -3.f, 0.f});
0196   [[maybe_unused]] vector3 y = detray::vector::cross(z, x);
0197   point3 t = {2.f, 3.f, 4.f};
0198   transform3 trf(t, z, x);
0199 
0200   // Check that local origin translates into global translation
0201   point3 lzero = {0.f, 0.f, 0.f};
0202   point3 gzero = trf.point_to_global(lzero);
0203   ASSERT_NEAR(gzero[0], t[0], this->epsilon());
0204   ASSERT_NEAR(gzero[1], t[1], this->epsilon());
0205   ASSERT_NEAR(gzero[2], t[2], this->epsilon());
0206 
0207   // Check a round trip for point
0208   point3 lpoint = {3.f, 4.f, 5.f};
0209   point3 gpoint = trf.point_to_global(lpoint);
0210   point3 lpoint_r = trf.point_to_local(gpoint);
0211   ASSERT_NEAR(lpoint[0], lpoint_r[0], this->tolerance());
0212   ASSERT_NEAR(lpoint[1], lpoint_r[1], this->tolerance());
0213   ASSERT_NEAR(lpoint[2], lpoint_r[2], this->tolerance());
0214 
0215   // Check a point versus vector transform
0216   // vector should not change if transformed by a pure translation
0217   transform3 ttrf(t);
0218 
0219   vector3 gvector = {1.f, 1.f, 1.f};
0220   vector3 lvector = ttrf.vector_to_local(gvector);
0221   ASSERT_NEAR(gvector[0], lvector[0], this->tolerance());
0222   ASSERT_NEAR(gvector[1], lvector[1], this->tolerance());
0223   ASSERT_NEAR(gvector[2], lvector[2], this->tolerance());
0224 
0225   // Check a round trip for vector
0226   vector3 lvectorB = {7.f, 8.f, 9.f};
0227   vector3 gvectorB = trf.vector_to_local(lvectorB);
0228   vector3 lvectorC = trf.vector_to_global(gvectorB);
0229   ASSERT_NEAR(lvectorB[0], lvectorC[0], this->tolerance());
0230   ASSERT_NEAR(lvectorB[1], lvectorC[1], this->tolerance());
0231   ASSERT_NEAR(lvectorB[2], lvectorC[2], this->tolerance());
0232 }
0233 
0234 }  // namespace detray::test