![]() |
|
|||
File indexing completed on 2025-09-18 09:09:40
0001 //------------------------------- -*- C++ -*- -------------------------------// 0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details 0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT) 0004 //---------------------------------------------------------------------------// 0005 //! \file corecel/math/ArraySoftUnit.hh 0006 //---------------------------------------------------------------------------// 0007 #pragma once 0008 0009 #include <cmath> 0010 0011 #include "corecel/Types.hh" 0012 #include "corecel/cont/Array.hh" 0013 0014 #include "detail/SoftEqualTraits.hh" 0015 0016 namespace celeritas 0017 { 0018 //---------------------------------------------------------------------------// 0019 /*! 0020 * Test for being approximately a unit vector. 0021 * 0022 * Consider a unit vector \em v with a small perturbation along a unit vector 0023 * \em e : \f[ 0024 \vec v + \epsilon \vec e 0025 \f] 0026 * The magnitude of this "nearly unit" is 0027 * \f[ 0028 m^2 = (v + \epsilon e) \cdot (v + \epsilon e) 0029 = 1 + 2 (v \cdot e) \epsilon + \epsilon^2 0030 \f] 0031 * 0032 * Since by the triangle inequality \f[ |v \cdot e| <= |v||e| = 1 \f] , 0033 * then the magnitude squared of a perturbed unit vector is bounded 0034 * \f[ 0035 m^2 = 1 \pm 2 \epsilon + \epsilon^2 0036 \f] 0037 * 0038 * Instead of calculating the square of the tolerance we use 0039 * \f$ \epsilon^2 < \epsilon \f$ to make the "soft unit vector" condition 0040 * \f[ 0041 | \vec v \vd \vec v - 1 | < 3 \epsilon . 0042 \f] 0043 */ 0044 template<class T = ::celeritas::real_type> 0045 class ArraySoftUnit 0046 { 0047 public: 0048 //!@{ 0049 //! \name Type aliases 0050 using value_type = T; 0051 //!@} 0052 0053 public: 0054 // Construct with explicit tolerance 0055 CELER_FUNCTION inline ArraySoftUnit(value_type tol); 0056 0057 // Construct with default tolerance 0058 CELER_CONSTEXPR_FUNCTION ArraySoftUnit(); 0059 0060 // Calculate whether the array is nearly a unit vector 0061 template<::celeritas::size_type N> 0062 CELER_CONSTEXPR_FUNCTION bool operator()(Array<T, N> const& arr) const; 0063 0064 private: 0065 value_type tol_; 0066 }; 0067 0068 //---------------------------------------------------------------------------// 0069 // TEMPLATE DEDUCTION GUIDES 0070 //---------------------------------------------------------------------------// 0071 template<class T> 0072 CELER_FUNCTION ArraySoftUnit(T) -> ArraySoftUnit<T>; 0073 0074 //---------------------------------------------------------------------------// 0075 // FREE FUNCTIONS 0076 //---------------------------------------------------------------------------// 0077 // Test for being approximately a unit vector 0078 template<class T, size_type N> 0079 CELER_CONSTEXPR_FUNCTION bool is_soft_unit_vector(Array<T, N> const& v); 0080 0081 //---------------------------------------------------------------------------// 0082 // INLINE DEFINITIONS 0083 //---------------------------------------------------------------------------// 0084 /*! 0085 * Construct with explicit tolereance. 0086 */ 0087 template<class T> 0088 CELER_FUNCTION ArraySoftUnit<T>::ArraySoftUnit(T tol) : tol_{3 * tol} 0089 { 0090 CELER_EXPECT(tol_ > 0); 0091 } 0092 0093 //---------------------------------------------------------------------------// 0094 /*! 0095 * Construct with default tolereance. 0096 */ 0097 template<class T> 0098 CELER_CONSTEXPR_FUNCTION ArraySoftUnit<T>::ArraySoftUnit() 0099 : tol_{3 * detail::SoftEqualTraits<T>::rel_prec()} 0100 { 0101 } 0102 0103 //---------------------------------------------------------------------------// 0104 /*! 0105 * Calculate whether the array is nearly a unit vector. 0106 * 0107 * The calculation below is equivalent to 0108 * \code 0109 * return SoftEqual{tol, tol}(1, dot_product(arr, arr)); 0110 * \endcode. 0111 */ 0112 template<class T> 0113 template<::celeritas::size_type N> 0114 CELER_CONSTEXPR_FUNCTION bool 0115 ArraySoftUnit<T>::operator()(Array<T, N> const& arr) const 0116 { 0117 T length_sq{}; 0118 for (size_type i = 0; i != N; ++i) 0119 { 0120 length_sq = std::fma(arr[i], arr[i], length_sq); 0121 } 0122 return std::fabs(length_sq - 1) < tol_ * std::fmax(real_type(1), length_sq); 0123 } 0124 0125 //---------------------------------------------------------------------------// 0126 //! Test with default tolerance for being a unit vector 0127 template<class T, size_type N> 0128 CELER_CONSTEXPR_FUNCTION bool is_soft_unit_vector(Array<T, N> const& v) 0129 { 0130 return ArraySoftUnit<T>{}(v); 0131 } 0132 0133 //---------------------------------------------------------------------------// 0134 } // namespace celeritas
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |