|
|
|||
File indexing completed on 2026-09-26 08:01:31
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 #pragma once 0010 0011 #include <array> 0012 #include <bit> 0013 #include <cassert> 0014 0015 namespace Acts { 0016 0017 namespace Concepts { 0018 0019 /// @brief check types for requirements needed by interpolation 0020 /// 0021 /// This helper struct provides compile-time information whether the provided 0022 /// @c Point and @c Value types can be used in the Acts::interpolate function. 0023 /// 0024 /// @tparam T type of values to be interpolated 0025 /// @tparam N number of hyper box corners 0026 /// @tparam P1 type for specifying the input point 0027 /// @tparam P2 type for specifying the lower corner of the hyper box 0028 /// @tparam P3 type for specifying the upper corner of the hyper box 0029 template <typename T, std::size_t N, typename P1, typename P2, typename P3> 0030 concept Interpolatable = requires { 0031 std::has_single_bit(N); 0032 { 0033 std::declval<double>() * std::declval<T>() + 0034 std::declval<double>() * std::declval<T>() 0035 } -> std::convertible_to<T>; 0036 { std::declval<P1>()[0] } -> std::convertible_to<double>; 0037 { std::declval<P2>()[0] } -> std::convertible_to<double>; 0038 { std::declval<P3>()[0] } -> std::convertible_to<double>; 0039 }; 0040 0041 } // namespace Concepts 0042 0043 /// performs linear interpolation inside a hyper box 0044 /// 0045 /// @tparam T type of values to be interpolated 0046 /// @tparam N number of hyper box corners 0047 /// @tparam Point1 type specifying the input point 0048 /// @tparam Point2 type specifying the lower corner of the hyper box 0049 /// @tparam Point3 type specifying the upper corner of the hyper box 0050 /// 0051 /// @param point point to which to interpolate 0052 /// @param lowerCorner generalized lower-left corner of hyper box 0053 /// (containing the minima of the hyper box along each dimension) 0054 /// @param upperCorner generalized upper-right corner of hyper box 0055 /// (containing the maxima of the hyper box along each dimension) 0056 /// @param values field values at the hyper box corners sorted in the 0057 /// canonical order defined below. 0058 /// 0059 /// @return interpolated value at given point 0060 /// 0061 /// @pre @c point must be inside the given hyper box, that 0062 /// is \f$\text{lowerCorner}[i] \le \text{point}[i] \le 0063 /// \text{upperCorner}[i] \quad \forall i=0, \dots, d-1\f$. 0064 /// 0065 /// @note 0066 /// - Given @c U and @c V of value type @c T as well as two @c double @c a and 0067 /// @c b, then the following must be a valid expression <tt>a * U + b * V</tt> 0068 /// yielding an object which is (implicitly) convertible to @c T. 0069 /// - All @c Point types must represent d-dimensional points and support 0070 /// coordinate access using @c operator[] which should return a @c double (or a 0071 /// value which is implicitly convertible). Coordinate indices must start at 0. 0072 /// - @c N is the number of hyper box corners which is \f$2^d\f$ where \f$d\f$ 0073 /// is the dimensionality of the hyper box. The dimensionality must be 0074 /// consistent with the provided @c Point types. 0075 /// - Definition of the canonical order for sorting the field values: The hyper 0076 /// box corners are numbered according to the following scheme. Each corner is 0077 /// defined by the set of lower/upper boundary limits in each dimension @c i. 0078 /// This can be represented by a binary code (from left to right) where a @c 0 0079 /// stands for a lower bound along this axis and a @c 1 stand for the upper 0080 /// bound along this axis. The left most bit corresponds to the first dimension 0081 /// and the bits to the left correspond to the 2nd, 3rd... dimension. The binary 0082 /// code can be interpreted as integer which gives the number of the 0083 /// corresponding hyper box corner. The field values are ordered according to 0084 /// ascending hyper box corner numbers.<br /> 0085 /// As an example assume we have a 3D box with @c lowerCorner = (1,2,3) and @c 0086 /// upperCorner = (4,5,6). The eight corners with their bit patterns and corner 0087 /// numbers are: 0088 /// - (1,2,3): 000 = 0 0089 /// - (1,2,6): 001 = 1 0090 /// - (1,5,3): 010 = 2 0091 /// - (1,5,6): 011 = 3 0092 /// - (4,2,3): 100 = 4 0093 /// - (4,2,6): 101 = 5 0094 /// - (4,5,3): 110 = 6 0095 /// - (4,5,6): 111 = 7 0096 template <typename T, std::size_t N, class Point1, class Point2 = Point1, 0097 class Point3 = Point2> 0098 T interpolate(const Point1& point, const Point2& lowerCorner, 0099 const Point3& upperCorner, const std::array<T, N>& values) 0100 requires Concepts::Interpolatable<T, N, Point1, Point2, Point3> 0101 { 0102 static constexpr std::size_t D = std::bit_width(N) - 1; 0103 static constexpr std::size_t I = D - 1; 0104 0105 // get distance to lower boundary relative to total bin width 0106 const double f = 0107 (point[I] - lowerCorner[I]) / (upperCorner[I] - lowerCorner[I]); 0108 assert(f >= 0 && f <= 1 && "point must be inside the given hyper box"); 0109 0110 std::array<T, N / 2> newValues{}; 0111 for (std::size_t i = 0; i < N / 2; ++i) { 0112 newValues[i] = (1 - f) * values[2 * i] + f * values[2 * i + 1]; 0113 } 0114 0115 if constexpr (D == 1) { 0116 return newValues[0]; 0117 } else { 0118 return interpolate(point, lowerCorner, upperCorner, newValues); 0119 } 0120 } 0121 0122 } // namespace Acts
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|