File indexing completed on 2026-04-01 07:45:48
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 <ostream>
0016 #include <vector>
0017
0018 namespace Acts {
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 class ElementFraction {
0038 public:
0039
0040
0041
0042
0043 constexpr ElementFraction(unsigned int e, float f)
0044 : m_element(static_cast<std::uint8_t>(e)),
0045 m_fraction(static_cast<std::uint8_t>(
0046 f * std::numeric_limits<std::uint8_t>::max())) {
0047 assert((0u < e) && ("The atomic number must be positive"));
0048 assert((0.0f <= f) && (f <= 1.0f) && "Relative fraction must be in [0,1]");
0049 }
0050
0051
0052
0053
0054 constexpr explicit ElementFraction(unsigned int e, unsigned int w)
0055 : m_element(static_cast<std::uint8_t>(e)),
0056 m_fraction(static_cast<std::uint8_t>(w)) {
0057 assert((0u < e) && ("The atomic number must be positive"));
0058 assert((w < 256u) && "Integer weight must be in [0,256)");
0059 }
0060
0061
0062 ElementFraction() = delete;
0063
0064 ElementFraction(ElementFraction&&) = default;
0065
0066 ElementFraction(const ElementFraction&) = default;
0067 ~ElementFraction() = default;
0068
0069
0070 ElementFraction& operator=(ElementFraction&&) = default;
0071
0072
0073 ElementFraction& operator=(const ElementFraction&) = default;
0074
0075
0076
0077 constexpr std::uint8_t element() const { return m_element; }
0078
0079
0080 constexpr float fraction() const {
0081 return static_cast<float>(m_fraction) /
0082 std::numeric_limits<std::uint8_t>::max();
0083 }
0084
0085 private:
0086
0087 std::uint8_t m_element;
0088
0089 std::uint8_t m_fraction;
0090
0091 friend constexpr bool operator==(ElementFraction lhs, ElementFraction rhs) {
0092 return (lhs.m_fraction == rhs.m_fraction) &&
0093 (lhs.m_element == rhs.m_element);
0094 }
0095
0096 friend constexpr bool operator<(ElementFraction lhs, ElementFraction rhs) {
0097 return lhs.m_fraction < rhs.m_fraction;
0098 }
0099 friend class MaterialComposition;
0100
0101
0102 friend std::ostream& operator<<(std::ostream& os, const ElementFraction& ef) {
0103 os << "ElementFraction(Z=" << static_cast<unsigned int>(ef.m_element)
0104 << ", f=" << ef.fraction() << ")";
0105 return os;
0106 }
0107 };
0108
0109
0110
0111
0112 class MaterialComposition {
0113 public:
0114
0115 MaterialComposition() = default;
0116
0117
0118
0119
0120 explicit MaterialComposition(std::vector<ElementFraction> elements)
0121 : m_elements(std::move(elements)) {
0122 std::ranges::sort(m_elements, std::less<ElementFraction>{});
0123
0124 unsigned total = 0u;
0125 for (const auto& element : m_elements) {
0126 total += element.m_fraction;
0127 }
0128
0129 float scale = float{std::numeric_limits<std::uint8_t>::max()} / total;
0130 for (auto& element : m_elements) {
0131 element.m_fraction =
0132 static_cast<std::uint8_t>(element.m_fraction * scale);
0133 }
0134 }
0135
0136
0137 MaterialComposition(MaterialComposition&&) = default;
0138
0139 MaterialComposition(const MaterialComposition&) = default;
0140 ~MaterialComposition() = default;
0141
0142
0143 MaterialComposition& operator=(MaterialComposition&&) = default;
0144
0145
0146 MaterialComposition& operator=(const MaterialComposition&) = default;
0147
0148
0149
0150 auto begin() const { return m_elements.begin(); }
0151
0152
0153 auto end() const { return m_elements.end(); }
0154
0155
0156 explicit operator bool() const { return !m_elements.empty(); }
0157
0158
0159 std::size_t size() const { return m_elements.size(); }
0160
0161 private:
0162 std::vector<ElementFraction> m_elements;
0163
0164 friend inline bool operator==(const MaterialComposition& lhs,
0165 const MaterialComposition& rhs) {
0166 return lhs.m_elements == rhs.m_elements;
0167 }
0168
0169
0170 friend std::ostream& operator<<(std::ostream& os,
0171 const MaterialComposition& mc) {
0172 os << "MaterialComposition(elements=[";
0173 for (std::size_t i = 0; i < mc.m_elements.size(); ++i) {
0174 if (i > 0) {
0175 os << ", ";
0176 }
0177 os << mc.m_elements[i];
0178 }
0179 os << "])";
0180 return os;
0181 }
0182 };
0183
0184 }