Line data Source code
1 : // SPDX-License-Identifier: BSD-3-Clause 2 : // Copyright (c) 2023 Scipp contributors (https://github.com/scipp) 3 : /// @file 4 : /// @author Simon Heybrock 5 : #pragma once 6 : 7 : #include "scipp/core/except.h" 8 : 9 : namespace scipp::core { 10 : 11 : /// A values/variances pair based on references to event lists. 12 : /// 13 : /// This is a helper for implementing operations for event_list such as 14 : /// `clear`, and for descending into the event list itself, using a nested 15 : /// call to an iteration function. 16 : template <class T> struct ValuesAndVariances { 17 : using value_type = typename T::value_type; 18 : 19 26880 : ValuesAndVariances(T &val, T &var) : values(val), variances(var) { 20 26880 : expect::sizeMatches(values, variances); 21 26880 : } 22 : ValuesAndVariances &operator=(const ValuesAndVariances<const T> &other) { 23 : values = other.values; 24 : variances = other.variances; 25 : return *this; 26 : } 27 : ValuesAndVariances &operator=(std::pair<T, T> &&data) { 28 : values = std::move(data.first); 29 : variances = std::move(data.second); 30 : return *this; 31 : } 32 : T &values; 33 : T &variances; 34 : 35 : void clear() noexcept { 36 : values.clear(); 37 : variances.clear(); 38 : } 39 : 40 : void reserve(const scipp::index capacity) const { 41 : values.reserve(capacity); 42 : variances.reserve(capacity); 43 : } 44 : 45 : // Note that methods like insert, begin, and end are required as long as we 46 : // support event data via a plain container such as std::vector, e.g., for 47 : // concatenation using a.insert(a.end(), b.begin(), b.end()). We are 48 : // supporting this here by simply working with pairs of iterators. This 49 : // approach is not an actual view iterator and will not compile if client 50 : // code attempts to increment the iterators. We could support `next` and 51 : // `advance` easily, so client code can simply use something like: 52 : // using std::next; 53 : // next(it); 54 : // instead of `++it`. Algorithms like `std::sort` would probably still not 55 : // work though. 56 : // The function arguments are iterator pairs as created by `begin` and `end`. 57 : template <class OutputIt, class InputIt> 58 : auto insert(std::pair<OutputIt, OutputIt> pos, 59 : std::pair<InputIt, InputIt> first, 60 : std::pair<InputIt, InputIt> last) { 61 : values.insert(pos.first, first.first, last.first); 62 : variances.insert(pos.second, first.second, last.second); 63 : } 64 : template <class... Ts> void insert(const Ts &...) { 65 : throw except::VariancesError("Cannot insert data with variances into data " 66 : "without variances, or vice versa."); 67 : } 68 : 69 : auto begin() noexcept { return std::pair(values.begin(), variances.begin()); } 70 : auto begin() const noexcept { 71 : return std::pair(values.begin(), variances.begin()); 72 : } 73 : auto end() noexcept { return std::pair(values.end(), variances.end()); } 74 : auto end() const noexcept { return std::pair(values.end(), variances.end()); } 75 : 76 13088 : constexpr auto size() const noexcept { return values.size(); } 77 : }; 78 : 79 : template <class T> struct is_ValuesAndVariances : std::false_type {}; 80 : template <class T> 81 : struct is_ValuesAndVariances<ValuesAndVariances<T>> : std::true_type {}; 82 : template <class T> 83 : inline constexpr bool is_ValuesAndVariances_v = is_ValuesAndVariances<T>::value; 84 : 85 : } // namespace scipp::core 86 : 87 : namespace scipp { 88 : using core::is_ValuesAndVariances; 89 : using core::is_ValuesAndVariances_v; 90 : using core::ValuesAndVariances; 91 : } // namespace scipp