units
Use physical dimensions at compile-time or run-time.
example1.cpp
Go to the documentation of this file.
1 /// @copyright 2019 Thomas E. Vaughan; all rights reserved.
2 /// @license BSD three-clause; see LICENSE.
3 
4 #include <array> // for array
5 #include <eigen3/Eigen/Geometry> // for AngleAxis, Matrix, etc.
6 #include <iostream> // for cout, etc.
7 #include <type_traits> // for remove_const
8 #include <utility> // for index_sequence
9 #include <vnix/units.hpp>
10 
11 using std::array;
12 using std::cerr;
13 using std::cout;
14 using std::endl;
15 using std::index_sequence;
16 using std::make_index_sequence;
17 using std::ostream;
18 
19 namespace vnix {
20 namespace mv {
21 
22 
23 /// Convert element i of array a from type OT to type T.
24 template <typename T, typename OT, size_t N>
25 constexpr T cnv_el(array<OT, N> const &a, size_t i) {
26  return a[i];
27 }
28 
29 /// Convert array of elements of type OT to array of elements of type T.
30 template <typename T, typename OT, size_t... i>
31 constexpr auto _cnv(array<OT, sizeof...(i)> const &a, index_sequence<i...>) {
32  return array<T, sizeof...(i)>{{cnv_el<T>(a, i)...}};
33 }
34 
35 /// Convert array of elements of type OT to array of elements of type T.
36 template <typename T, typename OT, size_t N>
37 constexpr auto cnv_ar(array<OT, N> const &a) {
38  return _cnv<T>(a, make_index_sequence<N>{});
39 }
40 
41 
42 /// Reference to column or row in matrix.
43 template <typename T, size_t S, size_t N> class mref {
44  T *beg_; ///< Pointer to first element.
45 
46 public:
47  constexpr mref(T *b) : beg_(b) {} ///< Initialize aggregate.
48  constexpr static size_t size() { return N; } ///< Number of elements.
49  constexpr T * begin() { return beg_; } ///< First element.
50 
51  /// Pointer to element that is S elements past last element identified by
52  /// mref.
53  constexpr T *end() { return beg_ + S * N; }
54 
55  /// Assign from list.
56  constexpr mref &operator=(std::initializer_list<T> list) {
57  auto i = list.begin();
58  auto j = begin();
59  auto ie = list.end();
60  auto je = end();
61  while (i != ie && j != je) {
62  *j++ = *i;
63  i += S;
64  }
65  return *this;
66  }
67 
68  /// Distance in memory between successive elements.
69  constexpr static size_t stride() { return S; }
70 
71  /// Access element at offset off.
72  constexpr T &operator()(size_t off) const { return beg_[S * off]; }
73 };
74 
75 /// Dot-product of two mrefs.
76 template <typename T1, typename T2, size_t S1, size_t S2, size_t N>
77 constexpr auto dot(mref<T1, S1, N> const &mr1, mref<T2, S2, N> const &mr2) {
78  auto sum = 0 * mr1(0) * mr2(0);
79  for (size_t i = 0; i < N; ++i) { sum += mr1(i) * mr2(i); }
80  return sum;
81 }
82 
83 
84 /// Model of a matrix of quantities.
85 template <typename T, size_t NR, size_t NC> struct mat {
86  array<T, NR * NC> a; ///< Array in which quantities are stored.
87 
88  /// Allow access to every other type of matrix.
89  template <typename OT, size_t ONR, size_t ONC> friend struct mat;
90 
91  mat() {}
92 
93  /// Initialize from list.
94  template <typename... X> constexpr mat(X... xs) : a({T(xs)...}) {}
95 
96  /// Copy from same-size matrix of other element-type OT.
97  template <typename OT>
98  constexpr mat(mat<OT, NR, NC> const &m) : a(cnv_ar<T>(m.a)) {}
99 
100  /// Reference to immutable column.
101  constexpr auto col(size_t off) const {
102  return mref<T const, NC, NR>(a.data() + off);
103  }
104 
105  /// Reference to mutable column.
106  constexpr auto col(size_t off) {
107  using RT = typename std::remove_const<T>::type;
108  return mref<RT, NC, NR>(a.data() + off);
109  }
110 
111  /// Reference to immutable row.
112  constexpr auto row(size_t off) const {
113  return mref<T const, 1, NC>(a.data() + NC * off);
114  }
115 
116  /// Reference to mutable row.
117  constexpr auto row(size_t off) {
118  using RT = typename std::remove_const<T>::type;
119  return mref<RT, 1, NC>(a.data() + NC * off);
120  }
121 };
122 
123 /// Model of column of quantities.
124 template <typename T, size_t NR> using col = mat<T, NR, 1>;
125 
126 /// Model of row of quantities.
127 template <typename T, size_t NC> using row = mat<T, 1, NC>;
128 
129 /// Multiply two matrices.
130 template <typename T1, typename T2, size_t NR1, size_t NC2, size_t N>
131 constexpr auto operator*(mat<T1, NR1, N> const &m1,
132  mat<T2, N, NC2> const &m2) {
133  using TT = decltype(dot(m1.row(0), m2.col(0)));
134  using TP = typename std::remove_const<TT>::type;
135  mat<TP, NR1, NC2> pr; // product
136  for (size_t i = 0; i < NR1; ++i) {
137  auto const m1_rowi = m1.row(i);
138  auto pr_rowi = pr.row(i);
139  for (size_t j = 0; j < NC2; ++j) { pr_rowi(j) = dot(m1_rowi, m2.col(j)); }
140  }
141  return pr;
142 }
143 
144 /// Multiply matrix on left by scalar.
145 template <typename T1, typename T2, size_t NR2, size_t NC2>
146 constexpr auto operator*(T1 const &s1, mat<T2, NR2, NC2> const &m2) {
147  mat<decltype(s1 * m2.row(0)(0)), NR2, NC2> pr; // product
148  for (size_t i = 0; i < NR2; ++i) {
149  auto const m2_rowi = m2.row(i);
150  auto pr_rowi = pr.row(i);
151  for (size_t j = 0; j < NC2; ++j) { pr_rowi(j) = s1 * m2_rowi(j); }
152  }
153  return pr;
154 }
155 
156 /// Print matrix.
157 template <typename T, size_t NR, size_t NC>
158 ostream &operator<<(ostream &os, mat<T, NR, NC> const &m) {
159  for (size_t i = 0; i < NR; ++i) {
160  auto const rowi = m.row(i);
161  os << endl;
162  for (size_t j = 0; j < NC; ++j) { os << rowi(j) << " "; }
163  }
164  return os;
165 }
166 
167 
168 } // namespace mv
169 } // namespace vnix
170 
171 int main() {
172  try {
173  using namespace vnix::mv;
174  mat<float, 3, 3> m1;
175  m1.row(0) = {1, 2, 3};
176  m1.row(1) = {4, 5, 6};
177  m1.row(2) = {7, 8, 9};
178  col<double, 3> v({0.3, 0.2, 0.1});
179  auto f = vnix::units::newtons(m1);
180  auto d = vnix::units::kilometers(v);
181  cout << (f * d) << endl;
182  } catch (char const *e) { cerr << e << endl; }
183 
184  cout << endl;
185 
186  try {
187  using namespace vnix::mv;
188  using namespace vnix::units::flt;
189  force foo;
190  mat<force, 3, 3> f2;
191  f2.row(0) = {1.0_N, 2.0_N, 3.0_N};
192  f2.row(1) = {4.0_N, 5.0_N, 6.0_N};
193  f2.row(2) = {7.0_N, 8.0_N, 9.0_N};
194  col<length, 3> d2({0.3_km, 0.2_km, 0.1_km});
195  cout << (f2 * d2) << endl;
196  } catch (char const *e) { cerr << e << endl; }
197 
198  cout << endl;
199 
200  try {
201  using namespace Eigen;
202  using namespace vnix::units;
203  using namespace vnix::units::flt;
204  AngleAxisf r(M_PI / 6, Vector3f(0, 0, 1));
205  auto f = newtons(Vector3f(1, 0, 0));
206  auto d = meters(Vector3f(0, 1, 0));
207  auto v = d / (2.5_s);
208  flt::time t = 3.0_s;
209  cout << (r.toRotationMatrix() * f).cross(d + v * t) << endl;
210  } catch (char const *e) { cerr << e << endl; }
211 
212  return 0;
213 }
constexpr auto operator*(mat< T1, NR1, N > const &m1, mat< T2, N, NC2 > const &m2)
Multiply two matrices.
Definition: example1.cpp:131
constexpr auto row(size_t off)
Reference to mutable row.
Definition: example1.cpp:117
array< T, NR *NC > a
Array in which quantities are stored.
Definition: example1.cpp:86
constexpr mat(X...xs)
Initialize from list.
Definition: example1.cpp:94
Definition: number.hpp:11
constexpr auto kilometers(T v)
Produce dimensioned quantity from number of kilometers.
Definition: units.hpp:1359
constexpr T cnv_el(array< OT, N > const &a, size_t i)
Convert element i of array a from type OT to type T.
Definition: example1.cpp:25
constexpr auto col(size_t off) const
Reference to immutable column.
Definition: example1.cpp:101
int main()
Definition: example1.cpp:171
Single-precision dimensions and units.
Definition: units.hpp:1663
T * beg_
Pointer to first element.
Definition: example1.cpp:44
constexpr auto operator*(T1 const &s1, mat< T2, NR2, NC2 > const &m2)
Multiply matrix on left by scalar.
Definition: example1.cpp:146
constexpr mat(mat< OT, NR, NC > const &m)
Copy from same-size matrix of other element-type OT.
Definition: example1.cpp:98
constexpr auto row(size_t off) const
Reference to immutable row.
Definition: example1.cpp:112
constexpr T & operator()(size_t off) const
Access element at offset off.
Definition: example1.cpp:72
friend std::ostream & operator<<(std::ostream &s, basic_dim d)
Print to to output stream.
Definition: dim.hpp:251
constexpr auto _cnv(array< OT, sizeof...(i)> const &a, index_sequence< i... >)
Convert array of elements of type OT to array of elements of type T.
Definition: example1.cpp:31
constexpr mref(T *b)
Initialize aggregate.
Definition: example1.cpp:47
constexpr T * end()
Pointer to element that is S elements past last element identified by mref.
Definition: example1.cpp:53
constexpr mref & operator=(std::initializer_list< T > list)
Assign from list.
Definition: example1.cpp:56
constexpr auto dot(mref< T1, S1, N > const &mr1, mref< T2, S2, N > const &mr2)
Dot-product of two mrefs.
Definition: example1.cpp:77
Reference to column or row in matrix.
Definition: example1.cpp:43
constexpr auto cnv_ar(array< OT, N > const &a)
Convert array of elements of type OT to array of elements of type T.
Definition: example1.cpp:37
constexpr auto col(size_t off)
Reference to mutable column.
Definition: example1.cpp:106
static constexpr size_t size()
Number of elements.
Definition: example1.cpp:48
static constexpr size_t stride()
Distance in memory between successive elements.
Definition: example1.cpp:69
Thomas E. Vaughan&#39;s public software.
Definition: rational.hpp:13
Classes and functions supporting a model of physically dimensioned quantities.
constexpr auto newtons(T v)
Produce dimensioned quantity from number of newtons.
Definition: units.hpp:1533
constexpr T * begin()
First element.
Definition: example1.cpp:49