Virtual Testbed
Ship dynamics simulator for extreme conditions
blitz.hh
1 #ifndef VTESTBED_BASE_BLITZ_HH
2 #define VTESTBED_BASE_BLITZ_HH
3 
4 #include <array>
5 #include <cmath>
6 #include <functional>
7 #include <limits>
8 #include <ostream>
9 
10 #include <blitz/array.h>
11 
12 #include <vtestbed/base/bstream.hh>
13 #include <vtestbed/base/constants.hh>
14 
16 namespace blitz {
17 
18  inline bool
19  isfinite(float rhs) noexcept {
20  return ::std::isfinite(rhs);
21  }
22 
23  inline bool
24  isfinite(double rhs) noexcept {
25  return ::std::isfinite(rhs);
26  }
27 
28  BZ_DECLARE_FUNCTION(isfinite);
29 
30  inline int
31  is_power_of_two(int n) {
32  return n > 0 && (n & (n-1)) == 0;
33  }
34 
35  BZ_DECLARE_FUNCTION(is_power_of_two);
36 
37  inline int
38  next_power_of_two(int n) {
39  if (n > std::numeric_limits<int>::max()/2) {
40  throw std::overflow_error(__func__);
41  }
42  int m = 1;
43  while (m < n) {
44  m *= 2;
45  }
46  return m;
47  }
48 
49  BZ_DECLARE_FUNCTION(next_power_of_two);
50 
51  inline float radians_to_degrees(float x) {
52  return x*360.f/vtb::base::constants<float>::pi(2);
53  }
54 
55  inline double radians_to_degrees(double x) {
56  return x*360.0/vtb::base::constants<double>::pi(2);
57  }
58 
59  BZ_DECLARE_FUNCTION(radians_to_degrees);
60 
61  template <class T, int N>
62  inline vtb::core::bstream&
63  operator<<(vtb::core::bstream& out, const blitz::TinyVector<T,N>& rhs) {
64  for (int i=0; i<N; ++i) {
65  out << rhs(i);
66  }
67  return out;
68  }
69 
70  template <class T, int N>
71  inline vtb::core::bstream&
72  operator>>(vtb::core::bstream& in, blitz::TinyVector<T,N>& rhs) {
73  for (int i=0; i<N; ++i) {
74  in >> rhs(i);
75  }
76  return in;
77  }
78 
79  template <class T, int N, int M>
80  inline vtb::core::bstream&
81  operator<<(vtb::core::bstream& out, const blitz::TinyMatrix<T,N,M>& rhs) {
82  for (int i=0; i<N; ++i) { for (int j=0; j<M; ++j) { out << rhs(i,j); } }
83  return out;
84  }
85 
86  template <class T, int N, int M>
87  inline vtb::core::bstream&
88  operator>>(vtb::core::bstream& in, blitz::TinyMatrix<T,N,M>& rhs) {
89  for (int i=0; i<N; ++i) { for (int j=0; j<M; ++j) { in >> rhs(i,j); } }
90  return in;
91  }
92 
93  template <class T, int N>
94  inline vtb::core::bstream&
95  operator<<(vtb::core::bstream& out, const blitz::Array<T,N>& rhs) {
96  blitz::TinyVector<uint32_t,N> shape = rhs.shape();
97  out << shape;
98  const T* data = rhs.data();
99  const int n = rhs.numElements();
100  for (int i=0; i<n; ++i) {
101  out << data[i];
102  }
103  return out;
104  }
105 
106  template <class T, int N>
107  inline vtb::core::bstream&
108  operator>>(vtb::core::bstream& in, blitz::Array<T,N>& rhs) {
109  blitz::TinyVector<uint32_t,N> shape;
110  shape = 0;
111  in >> shape;
112  rhs.resize(shape);
113  T* data = rhs.data();
114  const int n = rhs.numElements();
115  for (int i=0; i<n; ++i) {
116  in >> data[i];
117  }
118  return in;
119  }
120 
121  template <class T, int N>
122  inline blitz::TinyVector<T,N>
123  zero(blitz::TinyVector<T,N>) {
124  return blitz::TinyVector<T,N>{T{0}};
125  }
126 
127  template <class T, int N>
128  inline blitz::TinyVector<T,N>
129  one(blitz::TinyVector<T,N>) {
130  return blitz::TinyVector<T,N>{T{1}};
131  }
132 
133  template <class T, int N, int M>
134  inline TinyVector<T,N>
135  product(const TinyMatrix<T,N,M>& lhs, const TinyVector<T,M>& rhs) {
136  TinyVector<T,N> result;
137  for (int i=0; i<N; ++i) {
138  T sum{0};
139  for (int j=0; j<M; ++j) {
140  sum += lhs(i,j)*rhs(j);
141  }
142  result(i) = sum;
143  }
144  return result;
145  }
146 
147  template <class T, int N, int M>
148  inline blitz::TinyVector<T,N>
149  operator*(const TinyMatrix<T,N,M>& lhs, const TinyVector<T,M>& rhs) {
150  return product(lhs, rhs);
151  }
152 
153  template <class T, int N, int M, int K>
154  inline TinyMatrix<T,N,M>
155  product(const TinyMatrix<T,N,K>& lhs, const TinyMatrix<T,K,M>& rhs) {
156  TinyMatrix<T,N,M> result;
157  for (int i=0; i<N; ++i) {
158  for (int j=0; j<M; ++j) {
159  T sum{};
160  for (int k=0; k<K; ++k) { sum += lhs(i,k)*rhs(k,j); }
161  result(i,j) = sum;
162  }
163  }
164  return result;
165  }
166 
167  template <class T, int N, int M, int K>
168  inline TinyMatrix<T,N,M>
169  operator*(const TinyMatrix<T,N,K>& lhs, const TinyMatrix<T,K,M>& rhs) {
170  return product(lhs, rhs);
171  }
172 
173  template <class T, int N>
174  inline bool
175  near(
176  const blitz::TinyVector<T,N>& lhs,
177  const blitz::TinyVector<T,N>& rhs,
178  const T eps
179  ) {
180  using blitz::all;
181  using blitz::abs;
182  return !any(abs(lhs - rhs) > eps);
183  }
184 
185  template <class T, int N>
186  inline bool
187  near(
188  const blitz::TinyVector<T,N>& lhs,
189  const T rhs,
190  const T eps
191  ) {
192  using blitz::all;
193  using blitz::abs;
194  return !any(abs(lhs - rhs) > eps);
195  }
196 
197  template <int N>
198  inline bool
199  empty(const RectDomain<N>& rect){
200  return any(rect.lbound() > rect.ubound());
201  }
202 
203  template <class T,int N,int M>
204  MinMaxValue<TinyVector<T,N>>
205  minmax(Array<TinyVector<T,N>,M> x) {
206  MinMaxValue<TinyVector<T,N>> result;
207  result.min = std::numeric_limits<T>::max();
208  result.max = std::numeric_limits<T>::lowest();
209  if (x.size() == 0) {
210  return result;
211  }
212  for (const auto& v : x) {
213  for (int i=0; i<N; ++i) {
214  T m = v(i);
215  if (m < result.min(i)) {
216  result.min(i) = m;
217  }
218  if (result.max(i) < m) {
219  result.max(i) = m;
220  }
221  }
222  }
223  return result;
224  }
225 
226  template <class T, int N>
227  inline blitz::TinyVector<T,N>
228  min_vector(Array<blitz::TinyVector<T,N>,1> x) {
229  blitz::TinyVector<T,N> m{std::numeric_limits<T>::max()};
230  for (const auto& v : x) {
231  m = blitz::min(m, v);
232  }
233  return m;
234  }
235 
236  template <class T, int N>
237  inline blitz::TinyVector<T,N>
238  max_vector(Array<blitz::TinyVector<T,N>,1> x) {
239  blitz::TinyVector<T,N> m{std::numeric_limits<T>::min()};
240  for (const auto& v : x) {
241  m = blitz::max(m, v);
242  }
243  return m;
244  }
245 
246  template <class T, int N, int M>
247  inline TinyVector<T,N*M>
248  flatten(const TinyVector<T,N> x[M]) {
249  TinyVector<T,N*M> result;
250  for (int i=0; i<M; ++i) {
251  for (int j=0; j<N; ++j) {
252  result(i*N + j) = x[i][j];
253  }
254  }
255  return result;
256  }
257 
258  template <class T, int N, class ... Args>
259  inline TinyVector<T,N*(sizeof...(Args)+1)>
260  flatten(const TinyVector<T,N>& head, const Args& ... tail) {
261  const TinyVector<T,N> args[sizeof...(Args)+1] = {head, tail...};
262  return flatten<T,N,sizeof...(Args)+1>(args);
263  }
264 
265  namespace bits {
266 
267  template <class T, int N, int M>
268  struct Tie {
270  inline void
271  operator=(const TinyVector<T,N*M>& rhs) {
272  for (int i=0; i<M; ++i) {
273  for (int j=0; j<N; ++j) {
274  arr[i].get()[j] = rhs(i*N + j);
275  }
276  }
277  }
278  };
279 
280  }
281 
282  template <class T, int N, class ... Args>
283  inline bits::Tie<T,N,sizeof...(Args)+1>
284  tie(TinyVector<T,N>& head, Args& ... tail) {
285  return {{head, tail...}};
286  }
287 
288  template <class T, int N>
289  inline blitz::TinyMatrix<T,N,N>
290  identity_matrix() {
291  blitz::TinyMatrix<T,N,N> result;
292  result = 0;
293  for (int i=0; i<N; ++i) {
294  result(i,i) = 1;
295  }
296  return result;
297  }
298 
299  template <class T, int N>
300  inline blitz::TinyMatrix<T,N,N>
301  const_matrix(const std::array<T,N*N>& rhs) {
302  blitz::TinyMatrix<T,N,N> m;
303  for (int i=0; i<N*N; ++i) { m.data()[i] = rhs[i]; }
304  return m;
305  }
306 
307  template <class T, int N>
308  inline blitz::TinyVector<T,N>
309  const_vector(T value) {
310  blitz::TinyVector<T,N> result;
311  result = value;
312  return result;
313  }
314 
315  template <class T, int N>
316  inline blitz::TinyVector<T,1>
317  slice(const blitz::TinyVector<T,N>& x, int i) {
318  return {x(i)};
319  }
320 
321  template <class T, int N>
322  inline blitz::TinyVector<T,2>
323  slice(const blitz::TinyVector<T,N>& x, int i, int j) {
324  return {x(i), x(j)};
325  }
326 
327  template <class T, int N>
328  inline blitz::TinyVector<T,3>
329  slice(const blitz::TinyVector<T,N>& x, int i, int j, int k) {
330  return {x(i), x(j), x(k)};
331  }
332 
333  template <class T, int N>
334  inline blitz::TinyVector<T,4>
335  slice(const blitz::TinyVector<T,N>& x, int i, int j, int k, int l) {
336  return {x(i), x(j), x(k), x(l)};
337  }
338 
339  template <class T>
340  inline T
341  clamp(T x, T x_min, T x_max) {
342  if (x < x_min) x = x_min;
343  if (x > x_max) x = x_max;
344  return x;
345  }
346 
347  template <class T, int N>
348  inline blitz::TinyVector<T,N>
349  clamp(
350  const blitz::TinyVector<T,N>& x,
351  const blitz::TinyVector<T,N>& x_min,
352  const blitz::TinyVector<T,N>& x_max
353  ) {
354  return blitz::max(x_min, blitz::min(x_max, x));
355  }
356 
357  inline int
358  div_ceil(int lhs, int rhs) noexcept {
359  return lhs/rhs + (lhs%rhs == 0 ? 0 : 1);
360  }
361 
362  BZ_DECLARE_FUNCTION2(div_ceil);
363 
371  template <class T>
372  class Statistics {
373 
374  private:
375  T _sum1{0};
376  T _sum2{0};
377  int _count = 0;
378 
379  public:
380 
381  inline int
382  count() const noexcept {
383  return this->_count;
384  }
385 
386  inline const T&
387  mean() const noexcept {
388  return this->_sum1;
389  }
390 
391  inline T
392  variance(T addon) const noexcept {
393  return this->_sum2 / (this->_count + addon);
394  }
395 
396  inline T
397  population_variance() const noexcept {
398  return this->variance(0);
399  }
400 
401  inline T
402  unbiased_variance() const noexcept {
403  return this->variance(-1);
404  }
405 
406  inline T
407  variance() const noexcept {
408  return this->unbiased_variance();
409  }
410 
411  inline void
412  update(T x) {
413  ++_count;
414  const T delta = x - _sum1;
415  _sum1 += delta / _count;
416  const T delta2 = x - _sum1;
417  _sum2 += delta*delta2;
418  }
419 
420  inline void
421  clear() {
422  _sum1 = 0;
423  _sum2 = 0;
424  _count = 0;
425  }
426 
427  inline friend std::ostream&
428  operator<<(std::ostream& out, const Statistics& rhs) {
429  return out
430  << "mean=" << rhs.mean()
431  << ",variance=" << rhs.variance();
432  }
433 
434  };
435 
443  template <class T, int N>
444  inline Statistics<T>
445  statistics(const Array<T,N>& rhs) {
446  const int n = rhs.numElements();
447  const T* data = rhs.data();
448  Statistics<T> stats;
449  for (int i=0; i<n; ++i) {
450  stats.update(data[i]);
451  }
452  return stats;
453  }
454 
456  template <class T, int N>
457  inline T
458  variance(const Array<T,N>& rhs) {
459  return statistics<T,N>(rhs).variance();
460  }
461 
462  template <class T, int N>
463  inline const Array<T,N>&
464  real(const Array<T,N>& x) {
465  return x;
466  }
467 
469  template <class T, int N>
470  inline T
471  length(const blitz::TinyVector<T,N>& x) {
472  using blitz::abs;
473  using blitz::max;
474  using blitz::pow2;
475  using blitz::sum;
476  using std::sqrt;
477  const T s = max(abs(x));
478  if (s == T{}) {
479  return s;
480  }
481  return s*sqrt(sum(pow2(x/s)));
482  }
483 
485  template <class T>
486  inline T
487  length(const blitz::TinyVector<T,2>& x) {
488  return blitz::hypot(x(0), x(1));
489  }
490 
491  template <class T>
492  inline T
493  length(const blitz::TinyVector<T,1>& x) {
494  return std::abs(x(0));
495  }
496 
497  template <class T, int N>
498  inline T
499  sum_of_squares(const blitz::TinyVector<T,N>& x) {
500  return sum(pow2(x));
501  }
502 
503  template <class T>
504  inline T
505  sum_of_squares(const blitz::TinyVector<T,2>& x) {
506  return pow2(x(0)) + pow2(x(1));
507  }
508 
509  template <class T>
510  inline T
511  sum_of_squares(const blitz::TinyVector<T,3>& x) {
512  return pow2(x(0)) + pow2(x(1)) + pow2(x(2));
513  }
514 
515  template <class T>
516  inline T
517  sum_of_squares(const blitz::TinyVector<T,4>& x) {
518  return pow2(x(0)) + pow2(x(1)) + pow2(x(2)) + pow2(x(3));
519  }
520 
521  template <class T, int N>
522  inline T
523  distance(const blitz::TinyVector<T,N>& v1, const blitz::TinyVector<T,N>& v2) {
524  return length(blitz::TinyVector<T,N>(v2 - v1));
525  }
526 
527  template <class T, int N>
528  inline void
529  transpose(TinyMatrix<T,N,N>& m) {
530  using std::swap;
531  for (int i=0; i<N; ++i) {
532  for (int j=i+1; j<N; ++j) {
533  swap(m(i,j), m(j,i));
534  }
535  }
536  }
537 
543  template <class T, int N>
544  inline TinyVector<T,N-1>
545  puncture(const TinyVector<T,N>& v, int j) {
546  TinyVector<T,N-1> r;
547  for (int i=0; i<j; ++i) { r(i) = v(i); }
548  for (int i=j+1; i<N; ++i) { r(i-1) = v(i); }
549  return r;
550  }
551 
557  template <class T, int N>
558  inline TinyVector<T,N+1>
559  restore(const TinyVector<T,N>& v, int j) {
560  TinyVector<T,N+1> r;
561  for (int i=0; i<j; ++i) { r(i) = v(i); }
562  r(j) = T{};
563  for (int i=j; i<N; ++i) { r(i+1) = v(i); }
564  return r;
565  }
566 
568  template <class T>
569  inline TinyVector<T,1>
570  cross(const TinyVector<T,2>& a, const TinyVector<T,2>& b) {
571  return a(0)*b(1) - a(1)*b(0);
572  }
573 
574 }
575 
576 #endif // vim:filetype=cpp
T distance(T... args)
TinyVector< T, N-1 > puncture(const TinyVector< T, N > &v, int j)
Remove j dimension of vector v.
Definition: blitz.hh:545
Estimates sample mean and variance without overflows.
Definition: blitz.hh:372
T swap(T... args)
T variance(const Array< T, N > &rhs)
Sample variance.
Definition: blitz.hh:458
TinyVector< T, 1 > cross(const TinyVector< T, 2 > &a, const TinyVector< T, 2 > &b)
Two-dimensional cross product.
Definition: blitz.hh:570
T min(T... args)
TinyVector< T, N+1 > restore(const TinyVector< T, N > &v, int j)
Add dimension j to vector v.
Definition: blitz.hh:559
T lowest(T... args)
New and missing Blitz++ functions.
Definition: blitz.hh:16
static constexpr const T pi()
Definition: constants.hh:18
T max(T... args)
T length(const blitz::TinyVector< T, N > &x)
Computes vector length without overflow.
Definition: blitz.hh:471
Statistics< T > statistics(const Array< T, N > &rhs)
Estimate sample mean and variance.
Definition: blitz.hh:445