Turi Create  4.0
symmetric_2d_array.hpp
1 /* Copyright © 2017 Apple Inc. All rights reserved.
2  *
3  * Use of this source code is governed by a BSD-3-clause license that can
4  * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
5  */
6 #ifndef TURI_SYMMETRIC_ARRAY_H_
7 #define TURI_SYMMETRIC_ARRAY_H_
8 
9 #include <vector>
10 #include <core/storage/serialization/serialization_includes.hpp>
11 #include <core/logging/assertions.hpp>
12 
13 namespace turi {
14 
15 /** A 2d symmetric n by n array that stores the elements in a
16  * triangular array. The amount of storage required is only n*(n+1) /
17  * 2. Individual manipulation of elements is all that is supported.
18  */
19 template <typename T>
21 public:
22 
24  : n(0)
25  {}
26 
27  /// Init the 2d n x n symmetric array with default_value.
28  symmetric_2d_array(size_t _n, const T& default_value = T())
29  : n(_n)
30  , data(n*(n+1) / 2, default_value)
31  {}
32 
33  /// Return the size of either the rows or the columns. (aka n)
34  size_t size() const { return n; }
35 
36  /// Return the number of rows. (aka n)
37  size_t rows() const { return n; }
38 
39  /// Return the number of columns. (aka n)
40  size_t cols() const { return n; }
41 
42  /// Access item (i, j) -- same as (j, i) -- by reference.
43  inline T& operator()(size_t i, size_t j) {
44  return data[_index(i,j)];
45  }
46 
47  /// Access item (i, j) -- same as (j, i) -- by const reference.
48  inline const T& operator()(size_t i, size_t j) const {
49  return data[_index(i,j)];
50  }
51 
52  /// save to disk
53  void save(turi::oarchive& oarc) const {
54  oarc << n << data;
55  }
56 
57  /// load from disk
58  void load(turi::iarchive& iarc) {
59  iarc >> n >> data;
60  }
61 
62  private:
63  size_t n;
64  std::vector<T> data;
65 
66  /// Gives the index in the data matrix
67  inline size_t _index(size_t r, size_t c) const {
68  DASSERT_LT(r, n);
69  DASSERT_LT(c, n);
70 
71  // have that r > c
72  if(r < c)
73  std::swap(r, c);
74 
75  // with r >= c, we first compute the number of entries in a
76  // triangular matrix of size r -- this is r*(r+1) / 2. The value
77  // in data is c beyond that point. E.g.: element (3, 2) is stored in block 8
78  //
79  // | 0
80  // | 1 | 2
81  // | 3 | 4 | 5
82  // | 6 | 7 | 8 | 9 <-- r = 3 -- there are 3 * 4 / 2 = 6
83  // elements before this row.
84  //
85  // ^
86  // c = 1 --> the index in this row is 1, 6 is the offset to the row start.
87  size_t idx = r*(r + 1) / 2 + c;
88 
89  DASSERT_LT(idx, data.size());
90  return idx;
91  }
92 };
93 
94 }
95 #endif
T & operator()(size_t i, size_t j)
Access item (i, j) – same as (j, i) – by reference.
The serialization input archive object which, provided with a reference to an istream, will read from the istream, providing deserialization capabilities.
Definition: iarchive.hpp:60
symmetric_2d_array(size_t _n, const T &default_value=T())
Init the 2d n x n symmetric array with default_value.
void save(turi::oarchive &oarc) const
save to disk
size_t size() const
Return the size of either the rows or the columns. (aka n)
size_t rows() const
Return the number of rows. (aka n)
void load(turi::iarchive &iarc)
load from disk
The serialization output archive object which, provided with a reference to an ostream, will write to the ostream, providing serialization capabilities.
Definition: oarchive.hpp:80
size_t cols() const
Return the number of columns. (aka n)
const T & operator()(size_t i, size_t j) const
Access item (i, j) – same as (j, i) – by const reference.