Free Electron
MatrixPower.h
Go to the documentation of this file.
1 /* Copyright (C) 2003-2021 Free Electron Organization
2  Any use of this software requires a license. If a valid license
3  was not distributed with this file, visit freeelectron.org. */
4 
5 /** @file */
6 
7 #ifndef __geometry_MatrixPower_h__
8 #define __geometry_MatrixPower_h__
9 
10 #define MRP_DEBUG FALSE
11 #define MRP_VALIDATE (FE_CODEGEN<=FE_DEBUG)
12 
13 namespace fe
14 {
15 namespace ext
16 {
17 
18 
19 // NOTE fraction: 23 bits for single and 52 for double
20 /**************************************************************************//**
21  @brief solve B = A^^power, where A is a matrix
22 
23  @ingroup geometry
24 
25  The power can be any arbitrary real number.
26 
27  Execution time is roughly proportional to the number of set bits in
28  the integer portion of the floating point power and a fixed number
29  of iterations for the fractional part.
30 
31  The number of iterations used to compute of the fractional portion
32  of the power can be changed. The maximum error after each iteration
33  is half of the previous iteration, starting with one half. The entire
34  integer portion of the power is always computed.
35 *//***************************************************************************/
36 template <typename MATRIX>
38 {
39  public:
40  MatrixPower(void):
41  m_iterations(16) {}
42 
43  template <typename T>
44  void solve(MATRIX& B, const MATRIX& A, T a_power) const;
45 
46  void setIterations(U32 iterations) { m_iterations=iterations; }
47 
48  private:
49  MatrixSqrt<MATRIX> m_matrixSqrt;
50  U32 m_iterations;
51 };
52 
53 template <typename MATRIX>
54 template <typename T>
55 inline void MatrixPower<MATRIX>::solve(MATRIX& B, const MATRIX& A,
56  T a_power) const
57 {
58  T absolute=a_power;
59 
60 #if MRP_DEBUG
61  feLog("\nA\n%s\npower=%.6G\n",print(A).c_str(),absolute);
62 #endif
63 
64  const BWORD inverted=(absolute<0.0);
65  if(inverted)
66  {
67  absolute= -absolute;
68  }
69 
70  U32 whole=U32(absolute);
71  F32 fraction=absolute-whole;
72 
73 #if MRP_DEBUG
74  feLog("\nwhole=%d\nfraction=%.6G\n",whole,fraction);
75 #endif
76 
77  MATRIX R;
78  setIdentity(R);
79 
80  MATRIX partial=A;
81  F32 contribution=1.0;
82  U32 iteration;
83  for(iteration=0;iteration<m_iterations;iteration++)
84  {
85  m_matrixSqrt.solve(partial,partial);
86  contribution*=0.5;
87 #if MRP_DEBUG
88  feLog("\ncontribution=%.6G\nfraction=%.6G\n",contribution,fraction);
89 #endif
90  if(fraction>=contribution)
91  {
92  R*=partial;
93  fraction-=contribution;
94  }
95  }
96 
97  partial=A;
98  while(whole)
99  {
100 #if MRP_DEBUG
101  feLog("\nwhole=%d\n",whole);
102 #endif
103  if(whole&1)
104  {
105  R*=partial;
106  }
107  whole>>=1;
108  if(whole)
109  {
110  partial*=partial;
111  }
112  }
113 
114 #if MRP_VALIDATE
115  BWORD invalid=FALSE;
116  for(U32 m=0;m<width(R);m++)
117  {
118  for(U32 n=0;n<height(R);n++)
119  {
120  if(FE_INVALID_SCALAR(R(m,n)))
121  {
122  invalid=TRUE;
123  }
124  }
125  }
126  if(invalid)
127  {
128  feLog("MatrixPower< %s >::solve invalid results power=%.6G\n",
129  FE_TYPESTRING(MATRIX).c_str(),a_power);
130  feLog("\nA\n%s\n",print(A).c_str());
131  feLog("\nB\n%s\n",print(R).c_str());
132 
133  feX("MatrixPower<>::solve","invalid result");
134  }
135 #endif
136 
137  if(inverted)
138  {
139  invert(B,R);
140  }
141  else
142  {
143  B=R;
144  }
145 }
146 
147 } /* namespace ext */
148 } /* namespace fe */
149 
150 #endif /* __geometry_MatrixPower_h__ */
151 
kernel
Definition: namespace.dox:3
Matrix< 4, 4, T > & invert(Matrix< 4, 4, T > &a_inverted, const Matrix< 4, 4, T > &a_matrix)
4x4 full matrix inversion
Definition: Matrix.h:1033
solve A=B*B for B, given A
Definition: MatrixSqrt.h:40
solve B = A^^power, where A is a matrix
Definition: MatrixPower.h:37