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 <vector> 8 : 9 : #include "scipp-core_export.h" 10 : #include "scipp/common/index.h" 11 : #include "scipp/core/sizes.h" 12 : #include "scipp/units/dim.h" 13 : 14 : namespace scipp::core { 15 : 16 : /// Dimensions are accessed very frequently, so packing everything into a single 17 : /// (64 Byte) cacheline should be advantageous. 18 : /// We follow the numpy convention: First dimension is outer dimension, last 19 : /// dimension is inner dimension. 20 : class SCIPP_CORE_EXPORT Dimensions : public Sizes { 21 : public: 22 12886968 : Dimensions() noexcept = default; 23 7970 : Dimensions(const Dim dim, const scipp::index size) 24 7970 : : Dimensions({{dim, size}}) {} 25 : Dimensions(scipp::span<const Dim> labels, 26 : scipp::span<const scipp::index> shape); 27 30 : Dimensions(const std::initializer_list<Dim> labels, 28 : const std::initializer_list<scipp::index> shape) 29 30 : : Dimensions({labels.begin(), labels.end()}, 30 30 : {shape.begin(), shape.end()}) {} 31 7970 : Dimensions(const std::initializer_list<std::pair<Dim, scipp::index>> dims) { 32 15940 : for (const auto &[dim, len] : dims) 33 7970 : addInner(dim, len); 34 7970 : } 35 : 36 4414410 : bool operator==(const Dimensions &other) const noexcept { 37 4414410 : if (ndim() != other.ndim()) 38 227549 : return false; 39 7653623 : for (int32_t i = 0; i < ndim(); ++i) { 40 3468192 : if (shape()[i] != other.shape()[i]) 41 1048 : return false; 42 3467144 : if (labels()[i] != other.labels()[i]) 43 382 : return false; 44 : } 45 4185431 : return true; 46 : } 47 469462 : bool operator!=(const Dimensions &other) const noexcept { 48 469462 : return !(*this == other); 49 : } 50 : 51 : /// Return the shape of the space defined by *this. 52 35383995 : [[nodiscard]] scipp::span<const scipp::index> shape() const &noexcept { 53 35383995 : return sizes(); 54 : } 55 : 56 : /// Return the volume of the space defined by *this. 57 20876517 : [[nodiscard]] scipp::index volume() const noexcept { 58 20876517 : scipp::index volume{1}; 59 44107095 : for (const auto &length : shape()) 60 23230578 : volume *= length; 61 20876517 : return volume; 62 : } 63 : 64 : /// Return number of dims 65 36061790 : [[nodiscard]] scipp::index ndim() const noexcept { return Sizes::size(); } 66 : 67 : [[nodiscard]] Dim inner() const noexcept; 68 : 69 : [[nodiscard]] Dim label(const scipp::index i) const; 70 : [[nodiscard]] scipp::index size(const scipp::index i) const; 71 : [[nodiscard]] scipp::index offset(const Dim label) const; 72 : 73 : // TODO Better names required. 74 : void add(const Dim label, const scipp::index size); 75 : void addInner(const Dim label, const scipp::index size); 76 : 77 : [[nodiscard]] Dimensions 78 : rename_dims(const std::vector<std::pair<Dim, Dim>> &names, 79 : const bool fail_on_unknown = true) const; 80 : }; 81 : 82 : [[nodiscard]] SCIPP_CORE_EXPORT Dimensions merge(const Dimensions &a); 83 : 84 : [[nodiscard]] SCIPP_CORE_EXPORT Dimensions merge(const Dimensions &a, 85 : const Dimensions &b); 86 : 87 : template <class... Ts> 88 326533 : Dimensions merge(const Dimensions &a, const Dimensions &b, const Ts &...other) { 89 326533 : return merge(merge(a, b), other...); 90 : } 91 : 92 : [[nodiscard]] SCIPP_CORE_EXPORT Dimensions intersection(const Dimensions &a, 93 : const Dimensions &b); 94 : 95 : [[nodiscard]] SCIPP_CORE_EXPORT Dimensions 96 : transpose(const Dimensions &dims, scipp::span<const Dim> labels = {}); 97 : 98 : [[nodiscard]] SCIPP_CORE_EXPORT Dimensions fold(const Dimensions &old_dims, 99 : const Dim from_dim, 100 : const Dimensions &to_dims); 101 : 102 : } // namespace scipp::core 103 : 104 : namespace scipp { 105 : using core::Dimensions; 106 : }