File indexing completed on 2025-01-18 09:10:54
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include <algorithm>
0012 #include <cassert>
0013 #include <cstdint>
0014 #include <limits>
0015 #include <vector>
0016
0017 namespace Acts {
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 class ElementFraction {
0035 public:
0036
0037
0038
0039
0040 constexpr ElementFraction(unsigned int e, float f)
0041 : m_element(static_cast<std::uint8_t>(e)),
0042 m_fraction(static_cast<std::uint8_t>(
0043 f * std::numeric_limits<std::uint8_t>::max())) {
0044 assert((0u < e) && ("The atomic number must be positive"));
0045 assert((0.0f <= f) && (f <= 1.0f) && "Relative fraction must be in [0,1]");
0046 }
0047
0048
0049
0050
0051 constexpr explicit ElementFraction(unsigned int e, unsigned int w)
0052 : m_element(static_cast<std::uint8_t>(e)),
0053 m_fraction(static_cast<std::uint8_t>(w)) {
0054 assert((0u < e) && ("The atomic number must be positive"));
0055 assert((w < 256u) && "Integer weight must be in [0,256)");
0056 }
0057
0058
0059 ElementFraction() = delete;
0060 ElementFraction(ElementFraction&&) = default;
0061 ElementFraction(const ElementFraction&) = default;
0062 ~ElementFraction() = default;
0063 ElementFraction& operator=(ElementFraction&&) = default;
0064 ElementFraction& operator=(const ElementFraction&) = default;
0065
0066
0067 constexpr std::uint8_t element() const { return m_element; }
0068
0069 constexpr float fraction() const {
0070 return static_cast<float>(m_fraction) /
0071 std::numeric_limits<std::uint8_t>::max();
0072 }
0073
0074 private:
0075
0076 std::uint8_t m_element;
0077
0078 std::uint8_t m_fraction;
0079
0080 friend constexpr bool operator==(ElementFraction lhs, ElementFraction rhs) {
0081 return (lhs.m_fraction == rhs.m_fraction) &&
0082 (lhs.m_element == rhs.m_element);
0083 }
0084
0085 friend constexpr bool operator<(ElementFraction lhs, ElementFraction rhs) {
0086 return lhs.m_fraction < rhs.m_fraction;
0087 }
0088 friend class MaterialComposition;
0089 };
0090
0091
0092
0093
0094 class MaterialComposition {
0095 public:
0096
0097 MaterialComposition() = default;
0098
0099
0100
0101 MaterialComposition(std::vector<ElementFraction> elements)
0102 : m_elements(std::move(elements)) {
0103 std::ranges::sort(m_elements, std::less<ElementFraction>{});
0104
0105 unsigned total = 0u;
0106 for (const auto& element : m_elements) {
0107 total += element.m_fraction;
0108 }
0109
0110 float scale = float{std::numeric_limits<std::uint8_t>::max()} / total;
0111 for (auto& element : m_elements) {
0112 element.m_fraction =
0113 static_cast<std::uint8_t>(element.m_fraction * scale);
0114 }
0115 }
0116
0117 MaterialComposition(MaterialComposition&&) = default;
0118 MaterialComposition(const MaterialComposition&) = default;
0119 ~MaterialComposition() = default;
0120 MaterialComposition& operator=(MaterialComposition&&) = default;
0121 MaterialComposition& operator=(const MaterialComposition&) = default;
0122
0123
0124 auto begin() const { return m_elements.begin(); }
0125 auto end() const { return m_elements.end(); }
0126
0127
0128 operator bool() const { return !m_elements.empty(); }
0129
0130 std::size_t size() const { return m_elements.size(); }
0131
0132 private:
0133 std::vector<ElementFraction> m_elements;
0134
0135 friend inline bool operator==(const MaterialComposition& lhs,
0136 const MaterialComposition& rhs) {
0137 return (lhs.m_elements == rhs.m_elements);
0138 }
0139 };
0140
0141 }