00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef TOON_INCLUDE_SL_H
00032 #define TOON_INCLUDE_SL_H
00033
00034 #include <TooN/TooN.h>
00035 #include <TooN/helpers.h>
00036 #include <TooN/gaussian_elimination.h>
00037 #include <TooN/determinant.h>
00038 #include <cassert>
00039
00040 namespace TooN {
00041
00042 template <int N, typename P> class SL;
00043 template <int N, typename P> std::istream & operator>>(std::istream &, SL<N, P> &);
00044
00058 template <int N, typename Precision = double>
00059 class SL {
00060 friend std::istream & operator>> <N,Precision>(std::istream &, SL &);
00061 public:
00062 static const int size = N;
00063 static const int dim = N*N - 1;
00064
00066 SL() : my_matrix(Identity) {}
00067
00069 template <int S, typename P, typename B>
00070 SL( const Vector<S,P,B> & v ) { *this = exp(v); }
00071
00073 template <int R, int C, typename P, typename A>
00074 SL(const Matrix<R,C,P,A>& M) : my_matrix(M) { coerce(); }
00075
00077 const Matrix<N,N,Precision> & get_matrix() const { return my_matrix; }
00079 SL inverse() const { return SL(*this, Invert()); }
00080
00082 SL operator*( const SL & rhs) const { return SL(*this, rhs); }
00084 SL operator*=( const SL & rhs) { *this = *this*rhs; return *this; }
00085
00088 template <int S, typename P, typename B>
00089 static inline SL exp( const Vector<S,P,B> &);
00090
00094 static inline Matrix<N,N,Precision> generator(int);
00095
00096 private:
00097 struct Invert {};
00098 SL( const SL & from, struct Invert ) {
00099 Matrix<N> id = Identity;
00100 my_matrix = gaussian_elimination(from.my_matrix, id);
00101 }
00102 SL( const SL & a, const SL & b) : my_matrix(a.get_matrix() * b.get_matrix()) {}
00103
00104 void coerce(){
00105 using std::abs;
00106 Precision det = determinant(my_matrix);
00107 assert(abs(det) > 0);
00108 using std::pow;
00109 my_matrix /= pow(det, 1.0/N);
00110 }
00111
00115 static const int COUNT_DIAG = N - 1;
00116 static const int COUNT_SYMM = (dim - COUNT_DIAG)/2;
00117 static const int COUNT_ASYMM = COUNT_SYMM;
00118 static const int DIAG_LIMIT = COUNT_DIAG;
00119 static const int SYMM_LIMIT = COUNT_SYMM + DIAG_LIMIT;
00121
00122 Matrix<N,N,Precision> my_matrix;
00123 };
00124
00125 template <int N, typename Precision>
00126 template <int S, typename P, typename B>
00127 inline SL<N, Precision> SL<N, Precision>::exp( const Vector<S,P,B> & v){
00128 SizeMismatch<S,dim>::test(v.size(), dim);
00129 Matrix<N,N,Precision> t(Zeros);
00130 for(int i = 0; i < dim; ++i)
00131 t += generator(i) * v[i];
00132 SL<N, Precision> result;
00133 result.my_matrix = TooN::exp(t);
00134 return result;
00135 }
00136
00137 template <int N, typename Precision>
00138 inline Matrix<N,N,Precision> SL<N, Precision>::generator(int i){
00139 assert( i > -1 && i < dim );
00140 Matrix<N,N,Precision> result(Zeros);
00141 if(i < DIAG_LIMIT) {
00142 result(i,i) = 1;
00143 result(i+1,i+1) = -1;
00144 } else if(i < SYMM_LIMIT){
00145 int row = 0, col = i - DIAG_LIMIT + 1;
00146 while(col > (N - row - 1)){
00147 col -= (N - row - 1);
00148 ++row;
00149 }
00150 col += row;
00151 result(row, col) = result(col, row) = 1;
00152 } else {
00153 int row = 0, col = i - SYMM_LIMIT + 1;
00154 while(col > N - row - 1){
00155 col -= N - row - 1;
00156 ++row;
00157 }
00158 col += row;
00159 result(row, col) = -1;
00160 result(col, row) = 1;
00161 }
00162 return result;
00163 }
00164
00165 template <int S, typename PV, typename B, int N, typename P>
00166 Vector<N, typename Internal::MultiplyType<P, PV>::type> operator*( const SL<N, P> & lhs, const Vector<S,PV,B> & rhs ){
00167 return lhs.get_matrix() * rhs;
00168 }
00169
00170 template <int S, typename PV, typename B, int N, typename P>
00171 Vector<N, typename Internal::MultiplyType<PV, P>::type> operator*( const Vector<S,PV,B> & lhs, const SL<N,P> & rhs ){
00172 return lhs * rhs.get_matrix();
00173 }
00174
00175 template<int R, int C, typename PM, typename A, int N, typename P> inline
00176 Matrix<N, C, typename Internal::MultiplyType<P, PM>::type> operator*(const SL<N,P>& lhs, const Matrix<R, C, PM, A>& rhs){
00177 return lhs.get_matrix() * rhs;
00178 }
00179
00180 template<int R, int C, typename PM, typename A, int N, typename P> inline
00181 Matrix<R, N, typename Internal::MultiplyType<PM, P>::type> operator*(const Matrix<R, C, PM, A>& lhs, const SL<N,P>& rhs){
00182 return lhs * rhs.get_matrix();
00183 }
00184
00185 template <int N, typename P>
00186 std::ostream & operator<<(std::ostream & out, const SL<N, P> & h){
00187 out << h.get_matrix();
00188 return out;
00189 }
00190
00191 template <int N, typename P>
00192 std::istream & operator>>(std::istream & in, SL<N, P> & h){
00193 in >> h.my_matrix;
00194 h.coerce();
00195 return in;
00196 }
00197
00198 };
00199
00200 #endif