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 <optional> 8 : #include <type_traits> 9 : 10 : #include "scipp/core/dimensions.h" 11 : #include "scipp/core/dtype.h" 12 : #include "scipp/core/element_array.h" 13 : #include "scipp/units/dim.h" 14 : #include "scipp/units/unit.h" 15 : 16 : #include "scipp-variable_export.h" 17 : 18 : namespace scipp::variable { 19 : 20 : namespace detail { 21 : template <class U> struct vector { 22 : std::vector<U> data; 23 : template <class... Args> 24 1365521 : vector(Args &&...args) : data(std::forward<Args>(args)...) {} 25 : template <class A, class B> // avoid use of vector(size, value) 26 : vector(A &&a, B &&b) : data(std::initializer_list<U>{a, b}) {} 27 : template <class T> 28 1004 : vector(std::initializer_list<T> init) : data(init.begin(), init.end()) {} 29 : }; 30 : 31 : template <template <class...> class Derived, class... Args> struct arg_tuple { 32 : std::tuple<std::decay_t<Args>...> tuple; 33 673931 : arg_tuple(Args &&...args) : tuple(std::forward<Args>(args)...) {} 34 : }; 35 : } // namespace detail 36 : 37 : using Shape = detail::vector<scipp::index>; 38 : using Dims = detail::vector<Dim>; 39 : 40 : template <class... Args> 41 : struct Values : public detail::arg_tuple<Values, Args...> { 42 : using detail::arg_tuple<Values, Args...>::arg_tuple; 43 : template <class T> 44 : Values(std::initializer_list<T> init) 45 : : detail::arg_tuple<Values, Args...>(std::move(init)) {} 46 : }; 47 : template <class... Args> 48 : struct Variances : public detail::arg_tuple<Variances, Args...> { 49 : using detail::arg_tuple<Variances, Args...>::arg_tuple; 50 : template <class T> 51 : Variances(std::initializer_list<T> init) 52 : : detail::arg_tuple<Variances, Args...>(std::move(init)) {} 53 : }; 54 : 55 : template <class... Args> Values(Args &&...args) -> Values<Args...>; 56 : template <class T> 57 : Values(std::initializer_list<T>) -> Values<std::initializer_list<T>>; 58 : 59 : template <class... Args> Variances(Args &&...args) -> Variances<Args...>; 60 : template <class T> 61 : Variances(std::initializer_list<T>) -> Variances<std::initializer_list<T>>; 62 : 63 : namespace detail { 64 : 65 : SCIPP_VARIABLE_EXPORT void 66 : throw_keyword_arg_constructor_bad_dtype(const DType dtype); 67 : 68 : /// Convert "keyword" args to tuple that can be used to construct Variable 69 : /// 70 : /// This is an implementation detail of `makeVariable`. 71 : template <class ElemT> struct ArgParser { 72 : std::tuple<std::optional<units::Unit>, Dimensions, element_array<ElemT>, 73 : std::optional<element_array<ElemT>>> 74 : args; 75 : Dims dims; 76 : Shape shape; 77 : 78 641887 : void parse(const units::Unit &arg) { 79 641887 : std::get<std::optional<units::Unit>>(args) = arg; 80 641887 : } 81 : 82 68516 : void parse(const Dimensions &arg) { std::get<Dimensions>(args) = arg; } 83 : 84 502 : void parse(const Dims &arg) { 85 502 : if (shape.data.empty()) 86 502 : dims = arg; 87 : else 88 0 : std::get<Dimensions>(args) = Dimensions(arg.data, shape.data); 89 502 : } 90 : 91 529 : void parse(const Shape &arg) { 92 529 : if (dims.data.empty()) 93 27 : shape = arg; 94 : else 95 502 : std::get<Dimensions>(args) = Dimensions(dims.data, arg.data); 96 529 : } 97 : 98 673165 : template <class... Args> void parse(Values<Args...> &&arg) { 99 : if constexpr (std::is_constructible_v<element_array<ElemT>, Args...>) 100 673165 : std::get<2>(args) = 101 673165 : std::make_from_tuple<element_array<ElemT>>(std::move(arg.tuple)); 102 : else 103 0 : throw_keyword_arg_constructor_bad_dtype(core::dtype<ElemT>); 104 673165 : } 105 : 106 766 : template <class... Args> void parse(Variances<Args...> &&arg) { 107 : if constexpr (std::is_constructible_v<element_array<ElemT>, Args...>) 108 766 : std::get<3>(args) = 109 766 : std::make_from_tuple<element_array<ElemT>>(std::move(arg.tuple)); 110 : else 111 0 : throw_keyword_arg_constructor_bad_dtype(core::dtype<ElemT>); 112 766 : } 113 : }; 114 : 115 : } // namespace detail 116 : } // namespace scipp::variable