Open3D (C++ API)
SizeVector.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - Open3D: www.open3d.org -
3 // ----------------------------------------------------------------------------
4 // The MIT License (MIT)
5 //
6 // Copyright (c) 2018 www.open3d.org
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 // IN THE SOFTWARE.
25 // ----------------------------------------------------------------------------
26 
27 #pragma once
28 
29 #include <cstddef>
30 #include <numeric>
31 #include <string>
32 #include <vector>
33 
34 #include "Open3D/Utility/Console.h"
35 
36 namespace open3d {
37 
40 class SizeVector : public std::vector<int64_t> {
41 public:
42  SizeVector(const std::initializer_list<int64_t>& dim_sizes)
43  : std::vector<int64_t>(dim_sizes) {}
44 
45  SizeVector(const std::vector<int64_t>& dim_sizes)
46  : std::vector<int64_t>(dim_sizes) {}
47 
48  SizeVector(const SizeVector& other) : std::vector<int64_t>(other) {}
49 
50  explicit SizeVector(int64_t n, int64_t initial_value = 0)
51  : std::vector<int64_t>(n, initial_value) {}
52 
53  template <class InputIterator>
54  SizeVector(InputIterator first, InputIterator last)
55  : std::vector<int64_t>(first, last) {}
56 
58 
60  static_cast<std::vector<int64_t>*>(this)->operator=(v);
61  return *this;
62  }
63 
65  static_cast<std::vector<int64_t>*>(this)->operator=(v);
66  return *this;
67  }
68 
69  int64_t NumElements() const {
70  if (this->size() == 0) {
71  return 1;
72  }
73  return std::accumulate(this->begin(), this->end(), 1LL,
74  std::multiplies<int64_t>());
75  }
76 
77  std::string ToString() const { return fmt::format("{}", *this); }
78 };
79 
88 static inline int64_t WrapDim(int64_t dim,
89  int64_t max_dim,
90  bool inclusive = false) {
91  if (max_dim <= 0) {
92  utility::LogError("max_dim {} must be >= 0");
93  }
94  int64_t min = -max_dim;
95  int64_t max = inclusive ? max_dim : max_dim - 1;
96 
97  if (dim < min || dim > max) {
99  "Index out-of-range: dim == {}, but it must satisfy {} <= dim "
100  "<= {}",
101  dim, min, max);
102  }
103  if (dim < 0) {
104  dim += max_dim;
105  }
106  return dim;
107 }
108 
109 // Infers the size of a dim with size -1, if it exists. Also checks that new
110 // shape is compatible with the number of elements.
111 //
112 // E.g. Shape({2, -1, 4}) with num_elemnts 24, will be inferred as {2, 3, 4}.
113 //
114 // Ref: PyTorch's aten/src/ATen/InferSize.h
115 inline SizeVector InferShape(SizeVector shape, int64_t num_elements) {
116  SizeVector inferred_shape = shape;
117  int64_t new_size = 1;
118  bool has_inferred_dim = false;
119  int64_t inferred_dim;
120  for (int64_t dim = 0, ndim = shape.size(); dim != ndim; dim++) {
121  if (shape[dim] == -1) {
122  if (has_inferred_dim) {
124  "Proposed shape {}, but at most one dimension can be "
125  "-1 (inferred).",
126  shape.ToString());
127  }
128  inferred_dim = dim;
129  } else if (shape[dim] >= 0) {
130  new_size *= shape[dim];
131  } else {
132  utility::LogError("Invalid shape dimension {}", shape[dim]);
133  }
134  }
135 
136  if (num_elements == new_size ||
137  (has_inferred_dim && new_size > 0 && num_elements % new_size == 0)) {
138  if (has_inferred_dim) {
139  // We have a degree of freedom here to select the dimension size;
140  // follow NumPy semantics and just bail. However, a nice error
141  // message is needed because users often use `view` as a way to
142  // flatten & unflatten dimensions and will otherwise be confused why
143  // empty_tensor.view( 0, 0)
144  // works yet
145  // empty_tensor.view(-1, 0)
146  // doesn't.
147  if (new_size == 0) {
149  "Cannot reshape tensor of 0 elements into shape {}, "
150  "because the unspecified dimension size -1 can be any "
151  "value and is ambiguous.",
152  shape.ToString());
153  }
154  inferred_shape[inferred_dim] = num_elements / new_size;
155  }
156  return inferred_shape;
157  }
158 
159  utility::LogError("Shape {} is invalid for {} number of elements.", shape,
160  num_elements);
161 }
162 
163 } // namespace open3d
int64_t NumElements() const
Definition: SizeVector.h:69
SizeVector InferShape(SizeVector shape, int64_t num_elements)
Definition: SizeVector.h:115
void LogError(const char *format, const Args &... args)
Definition: Console.h:174
Definition: RendererHandle.h:165
SizeVector(InputIterator first, InputIterator last)
Definition: SizeVector.h:54
std::string ToString() const
Definition: SizeVector.h:77
SizeVector(const std::initializer_list< int64_t > &dim_sizes)
Definition: SizeVector.h:42
int size
Definition: FilePCD.cpp:57
Definition: SizeVector.h:40
SizeVector()
Definition: SizeVector.h:57
SizeVector(const SizeVector &other)
Definition: SizeVector.h:48
Definition: Open3DViewer.h:29
filament::Texture::InternalFormat format
Definition: FilamentResourceManager.cpp:155
SizeVector & operator=(SizeVector &&v)
Definition: SizeVector.h:64
SizeVector(const std::vector< int64_t > &dim_sizes)
Definition: SizeVector.h:45
SizeVector & operator=(const SizeVector &v)
Definition: SizeVector.h:59
SizeVector(int64_t n, int64_t initial_value=0)
Definition: SizeVector.h:50