toon-members
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Toon-members] TooN helpers.h sl.h test/sl.cc


From: Gerhard Reitmayr
Subject: [Toon-members] TooN helpers.h sl.h test/sl.cc
Date: Fri, 03 Apr 2009 14:30:39 +0000

CVSROOT:        /cvsroot/toon
Module name:    TooN
Changes by:     Gerhard Reitmayr <gerhard>      09/04/03 14:30:39

Modified files:
        .              : helpers.h 
Added files:
        .              : sl.h 
        test           : sl.cc 

Log message:
        added lie group representation for SL(n), nxn matrices with det() = 1. 
a simple implementation for the matrix exponential in helpers supports it.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/TooN/helpers.h?cvsroot=toon&r1=1.39&r2=1.40
http://cvs.savannah.gnu.org/viewcvs/TooN/sl.h?cvsroot=toon&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/TooN/test/sl.cc?cvsroot=toon&rev=1.1

Patches:
Index: helpers.h
===================================================================
RCS file: /cvsroot/toon/TooN/helpers.h,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -b -r1.39 -r1.40
--- helpers.h   31 Mar 2009 04:30:11 -0000      1.39
+++ helpers.h   3 Apr 2009 14:30:31 -0000       1.40
@@ -195,6 +195,69 @@
        static Operator<Internal::Zero> Zero;
        static Operator<Internal::Identity> Identity;
 
+       /// row sum norm of input matrix m
+       /// computes the maximum of the sums of absolute values over rows
+       template <int R, int C, typename P, typename B>
+       P inline norm_inf( const Matrix<R,C,P,B> & m ){
+               using std::abs;
+               using std::max;
+               P n = 0;
+               for(int r = 0; r < m.num_rows(); ++r){
+                       P s = 0;
+                       for(int c = 0; c < m.num_cols(); ++c)
+                               s += abs(m(r,c));
+                       n = max(n,s);
+               }
+               return n;
+       }
 
+       /// col sum norm of input matrix m
+       /// computes the maximum of the sums of absolute values over columns
+       template <int R, int C, typename P, typename B>
+       P inline norm_1( const Matrix<R,C,P,B> & m ){
+               using std::abs;
+               using std::max;
+               P n = 0;
+               for(int c = 0; c < m.num_cols(); ++c){
+                       P s = 0;
+                       for(int r = 0; r < m.num_rows(); ++r)
+                               s += abs(m(r,c));
+                       n = max(n,s);
+               }
+               return n;
+       }
+
+       namespace Internal {
+               template <int R, int C, typename P, typename B>
+               inline Matrix<R, C, P> exp_taylor( const Matrix<R,C,P,B> & m ){
+                       SizeMismatch<R, C>::test(m.num_rows(), m.num_cols());
+                       Matrix<R,C,P> result = TooN::Zero(m.num_rows(), 
m.num_cols());
+                       Matrix<R,C,P> f = TooN::Identity(m.num_rows());
+                       P k = 1;
+                       while(norm_inf((result+f)-result) > 0){
+                               result += f;
+                               f = (m * f) / k;
+                               k += 1;
+                       }
+                       return result;
+               }
+       };
+       
+       /// computes the matrix exponential of a matrix m by 
+       /// scaling m by 1/(powers of 2), using Taylor series and 
+       /// squaring again.
+       /// @param m input matrix, must be square
+       /// @return result matrix of the same size/type as input
+       template <int R, int C, typename P, typename B>
+       inline Matrix<R, C, P> exp( const Matrix<R,C,P,B> & m ){
+               using std::max;
+               SizeMismatch<R, C>::test(m.num_rows(), m.num_cols());
+               const P l = log2(norm_inf(m));
+               const int s = max(0,(int)ceil(l));
+               Matrix<R,C,P> result = Internal::exp_taylor(m/(1<<s));
+               for(int i = 0; i < s; ++i)
+                       result = result * result;
+               return result;
+       }
 }
 #endif

Index: sl.h
===================================================================
RCS file: sl.h
diff -N sl.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sl.h        3 Apr 2009 14:30:31 -0000       1.1
@@ -0,0 +1,163 @@
+/*                       
+        Copyright (C) 2005,2009 Tom Drummond, G. Reitmayr
+
+     This library is free software; you can redistribute it and/or
+     modify it under the terms of the GNU Lesser General Public
+     License as published by the Free Software Foundation; either
+     version 2.1 of the License, or (at your option) any later version.
+
+     This library is distributed in the hope that it will be useful,
+     but WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Lesser General Public License for more details.
+
+     You should have received a copy of the GNU Lesser General Public
+     License along with this library; if not, write to the Free Software
+     Foundation, Inc.
+     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#ifndef TOON_INCLUDE_SL_H
+#define TOON_INCLUDE_SL_H
+
+#include <TooN/TooN.h>
+#include <TooN/helpers.h>
+#include <TooN/LU.h>
+
+namespace TooN {
+
+template <int N, typename P> class SL;
+template <int N, typename P> std::istream & operator>>(std::istream &, SL<N, 
P> &);
+
+/// represents an element from the group SL(n), the nxn matrices M with det(M) 
= 1.
+/// This can be used to conveniently estimate homographies on n-1 dimentional 
spaces.
+/// The implementation uses the matrix exponential function @ref exp for
+/// exponentiation from an element in the Lie algebra and LU to compute an 
inverse.
+/// 
+/// The Lie algebra are the nxn matrices M with trace(M) = 0. The generators 
used
+/// to represent this vector space are the following:
+/// @item n-1 diag(...,1,-1,...), along the diagonal
+/// @item symmetric generators for every pair of off-diagonal elements
+/// @item anti-symmetric generators for every pair of off-diagonal elements
+/// This choice represents the fact that SL(n) can be interpreted as the 
product
+/// of all symmetric matrices with det() = 1 times SO(n).
+template <int N, typename Precision = double>
+class SL {
+       friend std::istream & operator>> <N,Precision>(std::istream &, SL &);
+public:
+       static const int size = N;
+       static const int dim = N*N - 1;
+
+       SL() : my_matrix(Identity) {}
+       template <int S, typename P, typename B>
+       SL( const Vector<S,P,B> & v ) { *this = exp(v); }
+
+       template <int R, int C, typename P, typename A>
+       SL(Matrix<R,C,P,A>& M) : my_matrix(M) {
+               coerce(M);
+       }
+
+       const Matrix<N,N,Precision> & get_matrix() const { return my_matrix; }
+       SL inverse() const { return SL(*this, Invert()); }
+
+       SL operator*( const SL & rhs) const { return SL(*this, rhs); }
+       SL operator*=( const SL & rhs) { *this = *this*rhs; return *this; }
+
+       template <int S, typename P, typename B>
+       static inline SL exp( const Vector<S,P,B> &);
+
+       static inline Matrix<N,N,Precision> generator(int);
+
+       template <int R, int C, typename P, typename A>
+       static void coerce(Matrix<R,C,P,A>& M){
+               using std::abs;
+               SizeMismatch<N,R>::test(N, M.num_rows());
+               SizeMismatch<N,C>::test(N, M.num_cols());
+               P det = LU<N>(M).determinant();
+               assert(abs(det) > 0);
+               M /= det;
+       }
+
+private:
+       struct Invert {};
+       SL( const SL & from, struct Invert ) : 
my_matrix(LU<N>(from.get_matrix()).get_inverse()) {}
+       SL( const SL & a, const SL & b) : my_matrix(a.get_matrix() * 
b.get_matrix()) {}
+
+       /// these constants indicate which parts of the parameter vector 
+       /// map to which generators
+       ///{
+       static const int COUNT_DIAG = N - 1;
+       static const int COUNT_SYMM = (dim - COUNT_DIAG)/2;
+       static const int COUNT_ASYMM = COUNT_SYMM;
+       static const int DIAG_LIMIT = COUNT_DIAG;
+       static const int SYMM_LIMIT = COUNT_SYMM + DIAG_LIMIT;
+       ///}
+
+       Matrix<N,N,Precision> my_matrix;
+};
+
+template <int N, typename Precision>
+template <int S, typename P, typename B>
+inline SL<N, Precision> SL<N, Precision>::exp( const Vector<S,P,B> & v){
+       SizeMismatch<S,dim>::test(v.size(), dim);
+       Matrix<N,N,Precision> t = Zero;
+       for(int i = 0; i < dim; ++i)
+               t += generator(i) * v[i];
+       SL<N, Precision> result;
+       result.my_matrix = TooN::exp(t);
+       return result;
+}
+
+template <int N, typename Precision>
+inline Matrix<N,N,Precision> SL<N, Precision>::generator(int i){
+       assert( i > -1 && i < dim );
+       Matrix<N,N,Precision> result = Zero;
+       if(i < DIAG_LIMIT) {                            // first ones are the 
diagonal ones
+               result(i,i) = 1;
+               result(i+1,i+1) = -1;
+       } else if(i < SYMM_LIMIT){                      // then the symmetric 
ones
+               int row = 0, col = i - DIAG_LIMIT + 1;
+               while(col > (N - row - 1)){
+                       col -= (N - row - 1); 
+                       ++row;
+               }
+               col += row;
+               result(row, col) = result(col, row) = 1;
+       } else {                                                        // 
finally the antisymmetric ones
+               int row = 0, col = i - SYMM_LIMIT + 1;
+               while(col > N - row - 1){
+                       col -= N - row - 1; 
+                       ++row;
+               }
+               col += row;
+               result(row, col) = -1;
+               result(col, row) = 1;
+       }
+       return result;
+}
+
+template <int S, typename PV, typename B, int N, typename P>
+Vector<N, P> operator*( const SL<N, P> & lhs, const Vector<S,PV,B> & rhs ){
+       return lhs.get_matrix() * rhs;
+}
+
+template <int S, typename PV, typename B, int N, typename P>
+Vector<N, P> operator*( const Vector<S,PV,B> & lhs, const SL<N,P> & rhs ){
+       return lhs * rhs.get_matrix();
+}
+
+template <int N, typename P>
+std::ostream & operator<<(std::ostream & out, const SL<N, P> & h){
+       out << h.get_matrix();
+       return out;
+}
+
+template <int N, typename P>
+std::istream & operator>>(std::istream & in, SL<N, P> & h){
+       in >> h.my_matrix;
+       SL<N,P>::coerce(h.my_matrix);
+       return in;
+}
+
+};
+
+#endif

Index: test/sl.cc
===================================================================
RCS file: test/sl.cc
diff -N test/sl.cc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ test/sl.cc  3 Apr 2009 14:30:34 -0000       1.1
@@ -0,0 +1,26 @@
+#include <TooN/TooN.h>
+#include <TooN/sl.h>
+
+#include <iostream>
+#include <iomanip>
+
+using namespace TooN;
+using namespace std;
+
+int main(int , char ** ){
+       SL<3> h(makeVector(1,0,-1,0,0,0,0,0));
+       cout << h << endl;
+       cout << h.inverse() << endl;
+       cout << SL<3>::exp(makeVector(-1,0,1,0,0,0,0,0)) << endl;
+       cout << h * h.inverse() << endl;
+       
+       for(int i = 0; i < SL<3>::dim; ++i)
+               cout << "generator " << i << "\n" << SL<3>::generator(i) << 
endl;
+
+       for(int i = 0; i < SL<5>::dim; ++i)
+               cout << "generator " << i << "\n" << SL<5>::generator(i) << 
endl;
+       
+       cout << SL<2>::exp(makeVector(1,2,3)) << endl;
+       
+       return 0;
+}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]