Honeycomb  0.1
Component-Model Framework
BackSub.h
Go to the documentation of this file.
1 // Honeycomb, Copyright (C) 2015 NewGamePlus Inc. Distributed under the Boost Software License v1.0.
2 #pragma once
3 
5 
6 namespace honey
7 {
8 
10 template<class Real>
11 class BackSub
12 {
13  typedef typename Numeral<Real>::Real_ Real_;
14  typedef typename Real_::DoubleType Double_;
15  typedef typename Double_::Real Double;
16  typedef Alge_<Real> Alge;
17  typedef Alge_<Double> Alge_d;
18 public:
22 
24  template<class T>
25  static bool isFullRank(const MatrixBase<T>& a)
26  {
27  sdt n = Alge::min(a.rows(),a.cols());
28  for (sdt i : range(n))
29  if (a(i,i) == 0) return false;
30  return true;
31  }
32 
34  template<class B, class X>
35  static void solve(const Matrix& r, const MatrixBase<B>& b, MatrixBase<X>& x)
36  {
37  assert(b.rows() == r.rows());
38  assert(isFullRank(r));
39  sdt n = Alge::min(r.rows(),r.cols());
40  sdt nx = b.cols();
41  x = b;
42  for (sdt k = n-1; k >= 0; --k)
43  {
44  for (sdt j = 0; j < nx; ++j)
45  x(k,j) /= r(k,k);
46  for (sdt i = 0; i < k; ++i)
47  for (sdt j = 0; j < nx; ++j)
48  x(i,j) -= x(k,j)*r(i,k);
49  }
50  }
51 
53  template<class B, class X>
54  void solve(const Vec& w, const Matrix& u, const Matrix& vt, const MatrixBase<B>& b, MatrixBase<X>& x)
55  {
56  assert(b.rows() == u.rows());
57  _buffer.resize(b.cols());
58  x.resize(vt.cols(), b.cols());
59  backSubSvd(w, u, vt, optional<const MatrixBase<B>&>(b), x, _buffer);
60  }
61 
63  template<class X>
64  void solve(const Vec& w, const Matrix& u, const Matrix& vt, MatrixBase<X>& x)
65  {
66  _buffer.resize(u.rows());
67  x.resize(vt.cols(), u.rows());
68  backSubSvd(w, u, vt, optional<const MatrixBase<X>&>(optnull), x, _buffer);
69  }
70 
72  template<class B, class X>
73  static void solveFwd(const Matrix& l, const MatrixBase<B>& b, MatrixBase<X>& x)
74  {
75  assert(b.rows() == l.rows());
76  assert(isFullRank(l));
77  sdt n = Alge::min(l.rows(),l.cols());
78  sdt nx = b.cols();
79  x = b;
80  for (sdt k = 0; k < n; ++k)
81  {
82  for (sdt j = 0; j < nx; ++j)
83  x(k,j) /= l(k,k);
84  for (sdt i = k+1; i < n; ++i)
85  for (sdt j = 0; j < nx; ++j)
86  x(i,j) -= x(k,j)*l(i,k);
87  }
88  }
89 
90 private:
91 
92  /* y[0:m,0:n] += diag(a[0:1,0:m]) * x[0:m,0:n] */
93  template<typename T1, typename T2, typename T3>
94  static void matrAXPY(sdt m, sdt n, const T1& x, sdt dx, const T2& a, sdt ai, sdt inca, T3& y, sdt dy)
95  {
96  typedef typename T2::Real R2;
97  typedef typename T3::Real R3;
98 
99  sdt i, j;
100  sdt xi = 0, yi = 0;
101  for( i = 0; i < m; i++, xi += dx, yi += dy )
102  {
103  R2 s = a(ai+i*inca);
104  j=0;
105  //Unrolled iteration
106  for(; j <= n - 4; j += 4 )
107  {
108  R3 t0 = (R3)(y(yi+j) + s*x(xi+j));
109  R3 t1 = (R3)(y(yi+j+1) + s*x(xi+j+1));
110  y(yi+j) = t0;
111  y(yi+j+1) = t1;
112  t0 = (R3)(y(yi+j+2) + s*x(xi+j+2));
113  t1 = (R3)(y(yi+j+3) + s*x(xi+j+3));
114  y(yi+j+2) = t0;
115  y(yi+j+3) = t1;
116  }
117  //Tail of iteration
118  for( ; j < n; j++ )
119  y(yi+j) = (R3)(y(yi+j) + s*x(xi+j));
120  }
121  }
122 
124  template<class B, class X>
125  static void backSubSvd(const Vec& w, const Matrix& u, const Matrix& vt,
126  optional<const MatrixBase<B>&> b, MatrixBase<X>& x, Vec_d& buffer)
127  {
128  Double threshold = 0;
129  Double eps = Double_::epsilon*2;
130  sdt m = u.rows(), n = vt.cols();
131  sdt udelta0 = 1, udelta1 = u.cols();
132  sdt vdelta0 = vt.cols(), vdelta1 = 1;
133  sdt ui = 0, vi = 0;
134  sdt ldb = b ? b->cols() : 0, ldx = x.cols();
135  sdt i, j, nm = Alge::min(m, n);
136  sdt nb = b ? b->cols() : m;
137 
138  x.fromZero();
139 
140  for( i = 0; i < nm; i++ )
141  threshold += w[i];
142  threshold *= eps;
143 
144  // v * inv(w) * uT * b
145  for( i = 0; i < nm; i++, ui += udelta0, vi += vdelta0 )
146  {
147  Double wi = w[i];
148  if( Alge_d::abs(wi) <= threshold )
149  continue;
150  wi = 1/wi;
151 
152  if( nb == 1 )
153  {
154  Double s = 0;
155  if( b )
156  for( j = 0; j < m; j++ )
157  s += u(ui+j*udelta1) * (*b)(j*ldb);
158  else
159  s = u(ui);
160  s *= wi;
161 
162  for( j = 0; j < n; j++ )
163  x(j*ldx) = (Real)(x(j*ldx) + s*vt(vi+j*vdelta1));
164  }
165  else
166  {
167  if( b )
168  {
169  for( j = 0; j < nb; j++ )
170  buffer[j] = 0;
171  matrAXPY( m, nb, *b, ldb, u, ui, udelta1, buffer, 0 );
172  for( j = 0; j < nb; j++ )
173  buffer[j] *= wi;
174  }
175  else
176  {
177  for( j = 0; j < nb; j++ )
178  buffer[j] = u(ui+j*udelta1)*wi;
179  }
180 
181  matrAXPY( n, nb, buffer, 0, vt, vi, vdelta1, x, ldx );
182  }
183  }
184  }
185 
186  Vec_d _buffer;
187 };
188 
189 }
static bool isFullRank(const MatrixBase< T > &a)
Check if a triangular/trapezoidal matrix has full rank (ie. all vectors are linearly independent; no ...
Definition: BackSub.h:25
Algebra.
Definition: Alge.h:13
Vec< matrix::dynamic, Real > Vec
Definition: BackSub.h:21
static optnull_t optnull
Null optional, use to reset an optional to an uninitialized state or test for initialization.
Definition: Optional.h:12
ptrdiff_t sdt
Size difference type, shorthand for ptrdiff_t.
Definition: Core.h:92
static void solveFwd(const Matrix &l, const MatrixBase< B > &b, MatrixBase< X > &x)
Solve where L is a lower triangular/trapezoidal matrix. L and B row sizes must match. L must have full rank.
Definition: BackSub.h:73
void solve(const Vec &w, const Matrix &u, const Matrix &vt, MatrixBase< X > &x)
Solve given the SVD of A. .
Definition: BackSub.h:64
std::enable_if< mt::isIterator< Iter1 >::value, Range_< Iter1, Iter2 > >::type range(Iter1 &&first, Iter2 &&last)
Range from iterators [first, last)
Definition: Range.h:116
static Int abs(Int x)
Get absolute value of signed integer.
Definition: Alge.h:21
static std::common_type< Num, Num2 >::type min(Num a, Num2 b)
Get the minimum of two numbers.
Definition: Alge.h:89
void solve(const Vec &w, const Matrix &u, const Matrix &vt, const MatrixBase< B > &b, MatrixBase< X > &x)
Solve given the SVD of A. A and B row sizes must match. .
Definition: BackSub.h:54
#define assert(...)
Forwards to assert_#args. See assert_1(), assert_2().
Definition: Debug.h:24
float Real
Real number type. See Real_ for real number operations and constants.
Definition: Real.h:21
Numeric type information, use numeral() to get instance safely from a static context.
Definition: Numeral.h:17
MatrixS & resize(sdt rows, sdt cols)
Sets number of rows/columns and reallocates only if the size has changed (rows*cols). All previous data is lost on reallocation. Returns self.
Definition: Base.h:277
Vec< matrix::dynamic, Double > Vec_d
Definition: BackSub.h:20
Enables any type to be optional so it can exist in an uninitialized null state.
Definition: Optional.h:52
static void solve(const Matrix &r, const MatrixBase< B > &b, MatrixBase< X > &x)
Solve where R is an upper triangular/trapezoidal matrix. R and B row sizes must match. R must have full rank.
Definition: BackSub.h:35
double Real
Definition: Real.h:14
Matrix< matrix::dynamic, matrix::dynamic, Real > Matrix
Definition: BackSub.h:19
static const double epsilon
Definition: Double.h:37
Matrix base class.
Definition: Base.h:17
Global Honeycomb namespace.
Back substitute to solve a linear system.
Definition: BackSub.h:11
VecS & resize(sdt dim)
Sets number of dimensions and reallocates only if different. All previous data is lost on reallocatio...
Definition: Base.h:69