dimension.hpp
1 //*****************************************************************************
2 // Copyright 2017-2021 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //*****************************************************************************
16 
17 #pragma once
18 
19 #include <limits>
20 #include <stddef.h>
21 #include <stdexcept>
22 
23 #include "ngraph/deprecated.hpp"
24 #include "ngraph/interval.hpp"
25 #include "ngraph/ngraph_visibility.hpp"
26 
27 namespace ngraph
28 {
29  /// \brief Class representing a dimension, which may be dynamic (undetermined until runtime),
30  /// in a shape or shape-like object.
31  ///
32  /// Static dimensions may be implicitly converted from value_type. A dynamic dimension is
33  /// constructed with Dimension() or Dimension::dynamic().
34  class NGRAPH_API Dimension
35  {
36  public:
37  using value_type = int64_t;
38 
39  /// \brief Construct a static dimension.
40  /// \param dimension Value of the dimension.
41  Dimension(value_type dimension);
42 
43  /// \brief Construct a dynamic dimension with bounded range
44  /// \param min_dimension The lower inclusive limit for the dimension
45  /// \param mas_dimension The upper inclusive limit for the dimension
46  Dimension(value_type min_dimension, value_type max_dimension);
47 
48  /// \brief Construct a dynamic dimension with range [0, ...]
49  Dimension() = default;
50 
51  bool operator==(const Dimension& dimension) const
52  {
53  return m_dimension == dimension.m_dimension;
54  }
55  bool operator!=(const Dimension& dimension) const
56  {
57  return m_dimension != dimension.m_dimension;
58  }
59  /// \brief Check whether this dimension is static.
60  /// \return `true` if the dimension is static, else `false`.
61  bool is_static() const { return m_dimension.size() == 1; }
62  /// \brief Check whether this dimension is dynamic.
63  /// \return `false` if the dimension is static, else `true`.
64  bool is_dynamic() const { return m_dimension.size() != 1; }
65  /// \brief Convert this dimension to `value_type`. This dimension must be static and
66  /// non-negative.
67  /// \throws std::invalid_argument If this dimension is dynamic or negative.
68  value_type get_length() const;
69 
70  value_type get_min_length() const;
71  value_type get_max_length() const;
72 
73  /// \brief Return the interval of valid lengths
74  const Interval& get_interval() const { return m_dimension; }
75  Interval& get_interval() { return m_dimension; }
76  /// \brief Check whether this dimension represents the same scheme as the argument (both
77  /// dynamic, or equal).
78  /// \param dim The other dimension to compare this dimension to.
79  /// \return `true` if this dimension and `dim` are both dynamic, or if they are both
80  /// static and equal; otherwise, `false`.
81  bool same_scheme(const Dimension& dim) const;
82  /// \brief Try to merge two Dimension objects together.
83  /// \param[out] dst Reference to write the merged Dimension into.
84  /// \param d1 First dimension to merge.
85  /// \param d2 Second dimension to merge.
86  /// \return `true` if merging succeeds, else `false`.
87  ///
88  /// \li If `d1` is dynamic, writes `d2` to `dst` and returns `true`.
89  /// \li If `d2` is dynamic, writes `d1` to `dst` and returns `true`.
90  /// \li If `d1` and `d2` are static and equal, writes `d1` to `dst` and returns `true`.
91  /// \li If `d1` and `d2` are both static and unequal, leaves `dst` unchanged and
92  /// returns `false`.
93  static bool merge(Dimension& dst, const Dimension d1, const Dimension d2);
94 
95  /// \brief Try to merge two Dimension objects together with implicit broadcasting
96  /// of unit-sized dimension to non unit-sized dimension
97  static bool broadcast_merge(Dimension& dst, const Dimension d1, const Dimension d2);
98 
99  /// \brief Check whether this dimension is capable of being merged with the argument
100  /// dimension.
101  /// \param d The dimension to compare this dimension with.
102  /// \return `true` if this dimension is compatible with `d`, else `false`.
103  ///
104  /// Two dimensions are considered compatible if it is possible to merge them. (See
105  /// Dimension::merge.)
106  bool compatible(const Dimension& d) const;
107 
108  /// \brief Check whether this dimension is a relaxation of the argument.
109  /// \param d The dimension to compare this dimension with.
110  /// \return `true` if this dimension relaxes `d`, else `false`.
111  ///
112  /// A dimension `d1` _relaxes_ (or _is a relaxation of_) `d2` if `d1` and `d2` are static
113  /// and equal, or `d1` is dynamic.
114  ///
115  /// `d1.relaxes(d2)` is equivalent to `d2.refines(d1)`.
116  bool relaxes(const Dimension& d) const;
117 
118  /// \brief Check whether this dimension is a refinement of the argument.
119  /// \param d The dimension to compare this dimension with.
120  /// \return `true` if this dimension relaxes `d`, else `false`.
121  ///
122  /// A dimension `d2` _refines_ (or _is a refinement of_) `d1` if `d1` and `d2` are static
123  /// and equal, or `d2` is dynamic.
124  ///
125  /// `d1.refines(d2)` is equivalent to `d2.relaxes(d1)`.
126  bool refines(const Dimension& d) const;
127 
128  /// \brief Create a dynamic dimension.
129  /// \return A dynamic dimension.
130  static Dimension dynamic() { return Dimension(); }
131  /// \brief Addition operator for Dimension.
132  /// \param dim Right operand for addition.
133  /// \return Smallest interval dimension enclosing inputs
134  Dimension operator+(const Dimension& dim) const;
135 
136  /// \brief Subtraction operator for Dimension.
137  /// \param dim Right operand for subtraction.
138  /// \return Smallest interval dimension enclosing inputs
139  Dimension operator-(const Dimension& dim) const;
140 
141  /// \brief Multiplication operator for Dimension.
142  /// \param dim Right operand for multiplicaiton.
143  /// \return Smallest interval containing all "produces" which are 0 if either of `this` or
144  /// `dim` has length `0`, else unbounded if either is unbounded, else product of lengths.
145  Dimension operator*(const Dimension& dim) const;
146 
147  /// \brief Add-into operator for Dimension.
148  /// \param dim Right operand for addition.
149  /// \return A reference to `*this`, after updating `*this` to the value `*this + dim`.
150  Dimension& operator+=(const Dimension& dim) { return (*this = *this + dim); }
151  /// \brief Multiply-into operator for Dimension.
152  /// \param dim Right operand for multiplication.
153  /// \return A reference to `*this`, after updating `*this` to the value `*this * dim`.
154  Dimension& operator*=(const Dimension& dim) { return (*this = *this * dim); }
155  /// \brief Intersection of dimensions
156  Dimension operator&(const Dimension& dim) const;
157  /// \brief Intersection of dimensions
159 
160  private:
161  Dimension(const Interval& interval)
162  : m_dimension(interval)
163  {
164  }
165 
166  // The actual numerical value of the dimension.
167  Interval m_dimension{};
168  };
169 
170  /// \brief Insert a human-readable representation of a dimension into an output stream.
171  /// \param str The output stream targeted for insertion.
172  /// \param dimension The dimension to be inserted into `str`.
173  /// \return A reference to `str` after insertion.
174  ///
175  /// Inserts the string `?` if `dimension` is dynamic; else inserts `dimension.get_length()`.
176  NGRAPH_API
177  std::ostream& operator<<(std::ostream& str, const Dimension& dimension);
178 }
Class representing a dimension, which may be dynamic (undetermined until runtime),...
Definition: dimension.hpp:35
Dimension & operator*=(const Dimension &dim)
Multiply-into operator for Dimension.
Definition: dimension.hpp:154
Dimension & operator+=(const Dimension &dim)
Add-into operator for Dimension.
Definition: dimension.hpp:150
Dimension(value_type dimension)
Construct a static dimension.
const Interval & get_interval() const
Return the interval of valid lengths.
Definition: dimension.hpp:74
static Dimension dynamic()
Create a dynamic dimension.
Definition: dimension.hpp:130
Dimension operator*(const Dimension &dim) const
Multiplication operator for Dimension.
static bool merge(Dimension &dst, const Dimension d1, const Dimension d2)
Try to merge two Dimension objects together.
Dimension()=default
Construct a dynamic dimension with range [0, ...].
Dimension operator-(const Dimension &dim) const
Subtraction operator for Dimension.
bool refines(const Dimension &d) const
Check whether this dimension is a refinement of the argument.
static bool broadcast_merge(Dimension &dst, const Dimension d1, const Dimension d2)
Try to merge two Dimension objects together with implicit broadcasting of unit-sized dimension to non...
Dimension & operator&=(const Dimension &dim)
Intersection of dimensions.
bool same_scheme(const Dimension &dim) const
Check whether this dimension represents the same scheme as the argument (both dynamic,...
bool is_dynamic() const
Check whether this dimension is dynamic.
Definition: dimension.hpp:64
Dimension operator&(const Dimension &dim) const
Intersection of dimensions.
Dimension operator+(const Dimension &dim) const
Addition operator for Dimension.
value_type get_length() const
Convert this dimension to value_type. This dimension must be static and non-negative.
bool is_static() const
Check whether this dimension is static.
Definition: dimension.hpp:61
Dimension(value_type min_dimension, value_type max_dimension)
Construct a dynamic dimension with bounded range.
bool compatible(const Dimension &d) const
Check whether this dimension is capable of being merged with the argument dimension.
bool relaxes(const Dimension &d) const
Check whether this dimension is a relaxation of the argument.
Interval arithmetic.
Definition: interval.hpp:37
The Intel nGraph C++ API.
Definition: attribute_adapter.hpp:28