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