00001 #ifndef INCLUDED_fmatCore_h_
00002 #define INCLUDED_fmatCore_h_
00003
00004 #include <cmath>
00005 #include <cstring>
00006 #include <iostream>
00007 #include <sstream>
00008 #include <iomanip>
00009 #include <stdexcept>
00010 #include <limits>
00011 #include "attributes.h"
00012 #include <stdio.h>
00013 #ifdef __APPLE__
00014 # include <AvailabilityMacros.h>
00015 #endif
00016
00017
00018 namespace fmat {
00019
00020 #ifdef FMAT_DEFAULT_DOUBLE
00021 typedef double fmatReal;
00022 #else
00023 typedef float fmatReal;
00024 #endif
00025
00026 struct Length_mismatch_or_non_vector {};
00027 struct NonSquare_Matrix {};
00028 struct SubVector_is_longer_than_source {};
00029 struct SubMatrix_has_more_rows_than_source {};
00030 struct SubMatrix_has_more_columns_than_source {};
00031 struct Rotation_requires_larger_dimensions {};
00032 struct Matrix_multiplication_left_width_must_match_right_height {};
00033
00034 template<size_t N, typename R> class SubVector;
00035 template<size_t H, size_t W, typename T> class SubMatrix;
00036 template<size_t H, size_t W, typename T> class Matrix;
00037 template<size_t N, typename R> class Column;
00038 template<size_t N, typename R> class Row;
00039 template<typename R> inline Column<2,R> packT(R x, R y);
00040 template<typename R> inline Column<3,R> packT(R x, R y, R z);
00041 template<typename R> inline Column<4,R> packT(R x, R y, R z, R d);
00042 inline Column<2,fmatReal> pack(fmatReal x, fmatReal y);
00043 inline Column<3,fmatReal> pack(fmatReal x, fmatReal y, fmatReal z);
00044 inline Column<4,fmatReal> pack(fmatReal x, fmatReal y, fmatReal z, fmatReal d);
00045
00046 extern std::string defaultNumberFormat;
00047
00048 template<typename R>
00049 std::string fullfmt(const R* const data, size_t H, size_t W,
00050 std::string const &numberFormat,
00051 std::string const &firstLineStart, std::string const &nextLineStart, std::string const &lastLineEnd,
00052 std::string const &rowBegin, std::string const &elementSep, std::string const &rowEnd,
00053 std::string const &rowSep)
00054 {
00055 std::ostringstream os;
00056 char buf[100];
00057 os << firstLineStart;
00058 for (size_t r=0; r<H; r++) {
00059 if ( r > 0 )
00060 os << nextLineStart;
00061 os << rowBegin;
00062 for (size_t c=0; c<W; c++) {
00063 snprintf(buf, 100, numberFormat.c_str(), data[c*H+r]);
00064 os << buf;
00065 if ( c < (W-1) )
00066 os << elementSep;
00067 }
00068 os << rowEnd;;
00069 if ( r < (H-1) )
00070 os << rowSep;
00071 }
00072 os << lastLineEnd;
00073 return os.str();
00074 }
00075
00076 namespace fmat_internal {
00077 template<typename T> inline void tmemcpy(T* dst, const T* src, size_t n) { memcpy(dst,src,n*sizeof(T)); }
00078
00079 #if defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_5)
00080
00081 template<typename T, size_t W> struct tmemset_pattern {};
00082 template<typename T> struct tmemset_pattern<T,1> { inline tmemset_pattern(T* dst, const T& src, size_t n) { memset(dst,src,n*sizeof(T)); } };
00083 template<typename T> struct tmemset_pattern<T,4> { inline tmemset_pattern(T* dst, const T& src, size_t n) { memset_pattern4(dst,&src,n*sizeof(T)); } };
00084 template<typename T> struct tmemset_pattern<T,8> { inline tmemset_pattern(T* dst, const T& src, size_t n) { memset_pattern8(dst,&src,n*sizeof(T)); } };
00085 template<typename T> struct tmemset_pattern<T,16> { inline tmemset_pattern(T* dst, const T& src, size_t n) { memset_pattern16(dst,&src,n*sizeof(T)); } };
00086 #else
00087 template<typename T, size_t W> struct tmemset_pattern {
00088 inline tmemset_pattern(T* dst, const T& src, size_t n) { while(n!=0) dst[--n]=src; }
00089 };
00090 template<typename T> struct tmemset_pattern<T,1> { inline tmemset_pattern(T* dst, const T& src, size_t n) { memset(dst,src,n*sizeof(T)); } };
00091 #endif
00092
00093 template<typename T> void tmemset(T* dst, const T& src, size_t n) { tmemset_pattern<T,sizeof(T)>(dst,src,n); }
00094
00095 template<class MSG,bool X> class CompileTimeAssert;
00096 template<class MSG> class CompileTimeAssert<MSG,true> {};
00097
00098 struct NoInit { };
00099
00100 template<typename T> struct precision_trait { };
00101 template<> struct precision_trait<bool> { static const int PRECISION_RANK = 0; };
00102 template<> struct precision_trait<char> { static const int PRECISION_RANK = 100; };
00103 template<> struct precision_trait<unsigned char> { static const int PRECISION_RANK = 200; };
00104 template<> struct precision_trait<short> { static const int PRECISION_RANK = 300; };
00105 template<> struct precision_trait<unsigned short> { static const int PRECISION_RANK = 400; };
00106 template<> struct precision_trait<int> { static const int PRECISION_RANK = 500; };
00107 template<> struct precision_trait<unsigned int> { static const int PRECISION_RANK = 600; };
00108 template<> struct precision_trait<long> { static const int PRECISION_RANK = 700; };
00109 template<> struct precision_trait<unsigned long> { static const int PRECISION_RANK = 800; };
00110 template<> struct precision_trait<float> { static const int PRECISION_RANK = 900; };
00111 template<> struct precision_trait<double> { static const int PRECISION_RANK = 1000; };
00112 template<> struct precision_trait<long double> { static const int PRECISION_RANK = 1100; };
00113
00114 template<typename T> struct unconst { typedef T type; };
00115 template<> struct unconst<const bool> { typedef bool type; };
00116 template<> struct unconst<const char> { typedef char type; };
00117 template<> struct unconst<const unsigned char> { typedef unsigned char type; };
00118 template<> struct unconst<const short> { typedef short type; };
00119 template<> struct unconst<const unsigned short> { typedef unsigned short type; };
00120 template<> struct unconst<const int> { typedef int type; };
00121 template<> struct unconst<const unsigned int> { typedef unsigned int type; };
00122 template<> struct unconst<const long> { typedef long type; };
00123 template<> struct unconst<const unsigned long> { typedef unsigned long type; };
00124 template<> struct unconst<const float> { typedef float type; };
00125 template<> struct unconst<const double> { typedef double type; };
00126 template<> struct unconst<const long double> { typedef long double type; };
00127
00128 template<typename T1, typename T2, bool promoteT1>
00129 struct do_promotion { typedef T1 type; };
00130 template<typename T1, typename T2>
00131 struct do_promotion<T1,T2,false> { typedef T2 type; };
00132
00133 template<typename T1, typename T2>
00134 struct promotion_trait {
00135 typedef typename unconst<T1>::type mT1;
00136 typedef typename unconst<T2>::type mT2;
00137 static const bool USET1 = (precision_trait<mT1>::PRECISION_RANK) > (precision_trait<mT2>::PRECISION_RANK);
00138 typedef typename do_promotion<mT1,mT2,USET1>::type type;
00139 };
00140
00141 template<class T1, class T2>
00142 struct mmops {
00143 typedef typename T1::storage_t R1;
00144 typedef typename T2::storage_t R2;
00145 typedef typename fmat_internal::promotion_trait<R1,R2>::type R;
00146 static Matrix<T1::HEIGHT,T2::WIDTH,R> multiply(const T1& a, const T2& b) {
00147 Matrix<T1::HEIGHT,T2::WIDTH,R> ans=fmat_internal::NoInit();
00148 for(size_t c2=T2::WIDTH; c2--!=0;) {
00149 for(size_t r1=T1::HEIGHT; r1--!=0;) {
00150 R x=0;
00151 for(size_t r2=T1::WIDTH; r2--!=0;)
00152 x+=a(r1,r2)*b(r2,c2);
00153 ans(r1,c2)=x;
00154 }
00155 }
00156 return ans;
00157 }
00158 };
00159
00160 template<class M, class V>
00161 struct mvops {
00162 typedef typename M::storage_t MR;
00163 typedef typename V::storage_t VR;
00164 typedef typename fmat_internal::promotion_trait<MR,VR>::type R;
00165 enum {
00166 H=M::HEIGHT,
00167 N=V::CAP,
00168 W=M::WIDTH
00169 };
00170 static Column<H,R> multiply(const M& a, const V& b) {
00171 (void)sizeof(fmat_internal::CompileTimeAssert<Matrix_multiplication_left_width_must_match_right_height,M::WIDTH==V::HEIGHT>);
00172 Column<H,R> ans=fmat_internal::NoInit();
00173 for(size_t r=H; r--!=0;) {
00174 R x=0;
00175 for(size_t c=N; c--!=0;)
00176 x+=a(r,c)*b[c];
00177 ans[r]=x;
00178 }
00179 return ans;
00180 }
00181 static Row<W,R> multiply(const V& a, const M& b) {
00182 (void)sizeof(fmat_internal::CompileTimeAssert<Matrix_multiplication_left_width_must_match_right_height,V::WIDTH==M::HEIGHT>);
00183 Row<W,R> ans=fmat_internal::NoInit();
00184 for(size_t c=W; c--!=0;) {
00185 R x=0;
00186 for(size_t r=N; r--!=0;)
00187 x+=b[r]*a(r,c);
00188 ans[c]=x;
00189 }
00190 return ans;
00191 }
00192 };
00193 }
00194
00195 template<size_t N, typename R=fmatReal>
00196 class SubVector {
00197 template<size_t S, typename T> friend class SubVector;
00198 template<size_t S, typename T> friend class Column;
00199 template<size_t S, typename T> friend class Row;
00200 template<size_t H, size_t W, typename T> friend class SubMatrix;
00201 template<size_t H, size_t W, typename T> friend class Matrix;
00202 public:
00203
00204 #if defined(__clang__) || !defined(__GNUC__) || (__GNUC__==4 && __GNUC_MINOR__<1)
00205 static const size_t HEIGHT=N;
00206 static const size_t WIDTH=1;
00207 static const size_t CAP=N;
00208 #else
00209 static const size_t HEIGHT;
00210 static const size_t WIDTH;
00211 static const size_t CAP;
00212 #endif
00213 typedef R storage_t;
00214 typedef typename fmat_internal::unconst<R>::type out_t;
00215
00216 explicit SubVector(R* x) : data(x) {}
00217
00218 SubVector(const SubVector& x) : data(x.data) {}
00219 SubVector(Matrix<N,1,out_t>& x) : data(x.data) {}
00220 SubVector(Matrix<1,(N==1?0U:N),out_t>& x) : data(x.data) {}
00221 template<typename T> SubVector(const Matrix<N,1,T>& x) : data(x.data) {}
00222 template<typename T> SubVector(const Matrix<1,(N==1?0U:N),T>& x) : data(x.data) {}
00223
00224
00225
00226 template<size_t S, typename T> explicit SubVector(const SubVector<S,T>& x, size_t offset=0) : data(&x[offset]) {
00227 (void)sizeof(fmat_internal::CompileTimeAssert<SubVector_is_longer_than_source,(N<=S)>);
00228 }
00229
00230
00231 template<size_t S> explicit SubVector(Matrix<1,S,out_t>& x, size_t offset=0) : data(&x.data[offset]) {
00232 (void)sizeof(fmat_internal::CompileTimeAssert<SubVector_is_longer_than_source,(N<=S)>);
00233 }
00234
00235 template<size_t S> explicit SubVector(Matrix<S,1,out_t>& x, size_t offset=0) : data(&x.data[offset]) {
00236 (void)sizeof(fmat_internal::CompileTimeAssert<SubVector_is_longer_than_source,(N<=S)>);
00237 }
00238
00239 template<size_t S, typename T> explicit SubVector(const Matrix<1,S,T>& x, size_t offset=0) : data(&x.data[offset]) {
00240 (void)sizeof(fmat_internal::CompileTimeAssert<SubVector_is_longer_than_source,(N<=S)>);
00241 }
00242
00243 template<size_t S, typename T> explicit SubVector(const Matrix<S,1,T>& x, size_t offset=0) : data(&x.data[offset]) {
00244 (void)sizeof(fmat_internal::CompileTimeAssert<SubVector_is_longer_than_source,(N<=S)>);
00245 }
00246
00247 operator SubVector<N,const R>() const { return SubVector<N,const R>(data); }
00248
00249 template<typename T> SubVector& importFrom(const T& x) { size_t i=N; while(i!=0) { --i; data[i]=x[i]; } return *this; }
00250 template<typename T> T exportTo() const { T x; size_t i=N; while(i!=0) { --i; x[i]=data[i]; } return x; }
00251 template<typename T> T& exportTo(T& x) const { size_t i=N; while(i!=0) { --i; x[i]=data[i]; } return x; }
00252
00253 const SubVector& operator=(R x) const { fmat_internal::tmemset<R>(data,x,N); return *this; }
00254 const SubVector& operator=(const R* x) const { fmat_internal::tmemcpy<R>(data,x,N); return *this; }
00255 const SubVector& operator=(const Matrix<N,1,out_t>& x) const { fmat_internal::tmemcpy<R>(data,x.data,N); return *this; }
00256 const SubVector& operator=(const SubVector& x) const { fmat_internal::tmemcpy<R>(data,x.data,N); return *this; }
00257 template<typename T> const SubVector& operator=(const SubVector<N,T>& x) const { fmat_internal::tmemcpy<R>(data,x.data,N); return *this; }
00258
00259 const SubVector& operator+=(R x) const { size_t i=N; while(i!=0) data[--i]+=x; return *this; }
00260 const SubVector& operator-=(R x) const { size_t i=N; while(i!=0) data[--i]-=x; return *this; }
00261 const SubVector& operator*=(R x) const { size_t i=N; while(i!=0) data[--i]*=x; return *this; }
00262 const SubVector& operator/=(R x) const { x=1/x; size_t i=N; while(i!=0) data[--i]*=x; return *this; }
00263 Column<N,out_t> operator+(R x) const { return Column<N,out_t>(*this)+=x; }
00264 Column<N,out_t> operator-(R x) const { return Column<N,out_t>(*this)-=x; }
00265 Column<N,out_t> operator*(R x) const { return Column<N,out_t>(*this)*=x; }
00266 Column<N,out_t> operator/(R x) const { return Column<N,out_t>(*this)/=x; }
00267 Column<N,out_t> operator-() const { Column<N,out_t> ans(*this); size_t i=N; while(i--!=0) ans.data[i]=-ans.data[i]; return ans; }
00268
00269 friend Column<N,out_t> operator+(R x, const SubVector& a) { return a+x; }
00270 friend Column<N,out_t> operator-(R x, const SubVector& a) { return (-a)+x; }
00271 friend Column<N,out_t> operator*(R x, const SubVector& a) { return a*x; }
00272
00273 template<typename T> const SubVector& operator+=(const Matrix<N,1,T>& x) const { size_t i=N; while(i!=0) { --i; data[i]+=x.data[i]; } return *this; }
00274 template<typename T> const SubVector& operator-=(const Matrix<N,1,T>& x) const { size_t i=N; while(i!=0) { --i; data[i]-=x.data[i]; } return *this; }
00275 template<typename T> const SubVector& operator+=(const SubVector<N,T>& x) const { size_t i=N; while(i!=0) { --i; data[i]+=x.data[i]; } return *this; }
00276 template<typename T> const SubVector& operator-=(const SubVector<N,T>& x) const { size_t i=N; while(i!=0) { --i; data[i]-=x.data[i]; } return *this; }
00277 template<typename T> Column<N,out_t> operator+(const Matrix<N,1,T>& x) const { return Column<N,out_t>(*this)+=x; }
00278 template<typename T> Column<N,out_t> operator-(const Matrix<N,1,T>& x) const { return Column<N,out_t>(*this)-=x; }
00279 template<typename T> Column<N,out_t> operator+(const SubVector<N,T>& x) const { return Column<N,out_t>(*this)+=x; }
00280 template<typename T> Column<N,out_t> operator-(const SubVector<N,T>& x) const { return Column<N,out_t>(*this)-=x; }
00281
00282 template<typename T> bool operator==(const SubVector<N,T>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.data[i]) return false; } return true; }
00283 template<typename T> bool operator!=(const SubVector<N,T>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.data[i]) return true; } return false; }
00284 template<typename T> bool operator<(const SubVector<N,T>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]<x.data[i]) return true; if(x.data[i]<data[i]) return false; } return false; }
00285 template<typename T> bool operator==(const Matrix<N,1,T>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.data[i]) return false; } return true; }
00286 template<typename T> bool operator!=(const Matrix<N,1,T>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.data[i]) return true; } return false; }
00287 template<typename T> bool operator<(const Matrix<N,1,T>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]<x.data[i]) return true; if(x.data[i]<data[i]) return false; } return false; }
00288
00289
00290 template<typename T> bool operator<<(const Matrix<N,1,T>& x) const { size_t i=N; while(i!=0) { --i; if(x.data[i] <= data[i]) return false; } return true; }
00291 template<typename T> bool operator<<(const SubVector<N,T>& x) const { size_t i=N; while(i!=0) { --i; if(x.data[i] <= data[i]) return false; } return true; }
00292
00293 inline R& operator[](size_t i) const { return data[i]; }
00294
00295 out_t norm() const { out_t ans=0; size_t i=N; while(i!=0) { const R x=data[--i]; ans+=x*x; } return std::sqrt(ans); }
00296 out_t sum() const { out_t ans=0; size_t i=N; while(i!=0) { ans+=data[--i]; } return ans; }
00297 out_t sumSq() const { out_t ans=0; size_t i=N; while(i!=0) { const R x=data[--i]; ans+=x*x; } return ans; }
00298 void abs() const { size_t i=N; while(i!=0) { --i; data[i]=std::abs(data[i]); } }
00299 out_t max() const { if(N==0) return out_t(); out_t ans=data[N-1]; size_t i=N-1; while(i--!=0) if(ans<data[i]) ans=data[i]; return ans; }
00300 out_t min() const { if(N==0) return out_t(); out_t ans=data[N-1]; size_t i=N-1; while(i--!=0) if(ans>data[i]) ans=data[i]; return ans; }
00301 template<typename F> void apply(const F& f) const { size_t i=N; while(i--!=0) data[i]=f(data[i]); }
00302 template<typename F> Column<N,out_t> map(const F& f) const { Column<N,out_t> ans; size_t i=N; while(i--!=0) ans.data[i]=f(data[i]); return ans; }
00303
00304 template<typename T> void minimize(const Matrix<N,1,T>& x) { size_t i=N; while(i!=0) { --i; if(x.data[i] < data[i]) data[i]=x.data[i]; } }
00305 template<typename T> void minimize(const SubVector<N,T>& x) { size_t i=N; while(i!=0) { --i; if(x.data[i] < data[i]) data[i]=x.data[i]; } }
00306 template<typename T> void maximize(const Matrix<N,1,T>& x) { size_t i=N; while(i!=0) { --i; if(data[i] < x.data[i]) data[i]=x.data[i]; } }
00307 template<typename T> void maximize(const SubVector<N,T>& x) { size_t i=N; while(i!=0) { --i; if(data[i] < x.data[i]) data[i]=x.data[i]; } }
00308
00309 inline Row<N,out_t> transpose() const ATTR_must_check {
00310 Row<N,out_t> ans=fmat_internal::NoInit();
00311 fmat_internal::tmemcpy<out_t>(ans.data,data,N);
00312 return ans;
00313 }
00314
00315 inline std::string fmt(std::string const &numberFormat=defaultNumberFormat,
00316 std::string const &firstLineStart="{",
00317 std::string const &nextLineStart= "",
00318 std::string const &lastLineEnd= "}",
00319 std::string const &rowBegin="",
00320 std::string const &elementSep="",
00321 std::string const &rowEnd="",
00322 std::string const &rowSep=" ") const
00323 {
00324 return fullfmt(data,N,1,numberFormat,firstLineStart,nextLineStart,lastLineEnd,rowBegin,elementSep,rowEnd,rowSep);
00325 }
00326
00327 protected:
00328 SubVector() : data(NULL) {}
00329 R* data;
00330 };
00331
00332
00333 #if !defined(__clang__) && defined(__GNUC__) && !(__GNUC__==4 && __GNUC_MINOR__<1)
00334 template<size_t N, typename R> const size_t SubVector<N,R>::HEIGHT=N;
00335 template<size_t N, typename R> const size_t SubVector<N,R>::WIDTH=1;
00336 template<size_t N, typename R> const size_t SubVector<N,R>::CAP=N;
00337 #endif
00338
00339
00340 template<size_t H, size_t W, typename R=fmatReal>
00341 class SubMatrix {
00342 template<size_t MH, size_t MW, typename MR> friend class Matrix;
00343 template<size_t MH, size_t MW, typename MR> friend class SubMatrix;
00344 template<size_t MN, typename MR> friend class SubVector;
00345 template<size_t MN, typename MR> friend class Column;
00346 template<size_t MN, typename MR> friend class Row;
00347 public:
00348
00349 #if defined(__clang__) || !defined(__GNUC__) || (__GNUC__==4 && __GNUC_MINOR__<1)
00350 static const size_t HEIGHT=H;
00351 static const size_t WIDTH=W;
00352 static const size_t CAP=H*W;
00353 #else
00354 static const size_t HEIGHT;
00355 static const size_t WIDTH;
00356 static const size_t CAP;
00357 #endif
00358 typedef R storage_t;
00359 typedef typename fmat_internal::unconst<R>::type out_t;
00360
00361 explicit SubMatrix(R* x, size_t colStride=H) { size_t c=W; while(c--!=0) cols[c].data = &x[c*colStride]; }
00362
00363 SubMatrix(const SubMatrix<H,W,out_t>& x) { size_t c=W; while(c--!=0) cols[c].data = x.cols[c].data; }
00364 SubMatrix(Matrix<H,W,out_t>& x) { size_t c=W; while(c--!=0) cols[c].data = &x.data[c*H]; }
00365 template<typename T> SubMatrix(const SubMatrix<H,W,T>& x) { size_t c=W; while(c--!=0) cols[c].data = x.cols[c].data; }
00366 template<typename T> SubMatrix(const Matrix<H,W,T>& x) { size_t c=W; while(c--!=0) cols[c].data = &x.data[c*H]; }
00367
00368
00369
00370 template<size_t SH, size_t SW, typename T> explicit SubMatrix(const SubMatrix<SH,SW,T>& x) {
00371 (void)sizeof(fmat_internal::CompileTimeAssert<SubMatrix_has_more_rows_than_source,(H<=SH)>);
00372 (void)sizeof(fmat_internal::CompileTimeAssert<SubMatrix_has_more_columns_than_source,(W<=SW)>);
00373 size_t c=W; while(c--!=0) cols[c].data = x.cols[c].data;
00374 }
00375
00376
00377 template<size_t SH, size_t SW, typename T> explicit SubMatrix(const SubMatrix<SH,SW,T>& x, size_t rowOff, size_t colOff) {
00378 (void)sizeof(fmat_internal::CompileTimeAssert<SubMatrix_has_more_rows_than_source,(H<=SH)>);
00379 (void)sizeof(fmat_internal::CompileTimeAssert<SubMatrix_has_more_columns_than_source,(W<=SW)>);
00380 size_t c=W; while(c--!=0) cols[c].data = &x.cols[c+colOff].data[rowOff];
00381 }
00382
00383 template<size_t SH, size_t SW> explicit SubMatrix(Matrix<SH,SW,out_t>& x) {
00384 (void)sizeof(fmat_internal::CompileTimeAssert<SubMatrix_has_more_rows_than_source,(H<=SH)>);
00385 (void)sizeof(fmat_internal::CompileTimeAssert<SubMatrix_has_more_columns_than_source,(W<=SW)>);
00386 size_t c=W; while(c--!=0) cols[c].data = &x.data[c*SH];
00387 }
00388
00389 template<size_t SH, size_t SW> explicit SubMatrix(Matrix<SH,SW,out_t>& x, size_t rowOff, size_t colOff) {
00390 (void)sizeof(fmat_internal::CompileTimeAssert<SubMatrix_has_more_rows_than_source,(H<=SH)>);
00391 (void)sizeof(fmat_internal::CompileTimeAssert<SubMatrix_has_more_columns_than_source,(W<=SW)>);
00392 size_t c=W; while(c--!=0) cols[c].data = &x.data[(c+colOff)*SH+rowOff];
00393 }
00394
00395 template<size_t SH, size_t SW, typename T> explicit SubMatrix(const Matrix<SH,SW,T>& x) {
00396 (void)sizeof(fmat_internal::CompileTimeAssert<SubMatrix_has_more_rows_than_source,(H<=SH)>);
00397 (void)sizeof(fmat_internal::CompileTimeAssert<SubMatrix_has_more_columns_than_source,(W<=SW)>);
00398 size_t c=W; while(c--!=0) cols[c].data = &x.data[c*SH];
00399 }
00400
00401 template<size_t SH, size_t SW, typename T> explicit SubMatrix(const Matrix<SH,SW,T>& x, size_t rowOff, size_t colOff) {
00402 (void)sizeof(fmat_internal::CompileTimeAssert<SubMatrix_has_more_rows_than_source,(H<=SH)>);
00403 (void)sizeof(fmat_internal::CompileTimeAssert<SubMatrix_has_more_columns_than_source,(W<=SW)>);
00404 size_t c=W; while(c--!=0) cols[c].data = &x.data[(c+colOff)*SH+rowOff];
00405 }
00406
00407 operator SubMatrix<H,W,const R>() const { return SubMatrix<H,W,const R>(*this); }
00408
00409 template<typename T> SubMatrix& importFrom(const T& x) { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { cols[c].data[r]=x(r,c); } return *this; }
00410 template<typename T> SubMatrix& importFromCMajor(const T& x, size_t stride=H) { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { cols[c].data[r]=x[c*stride+r]; } return *this; }
00411 template<typename T> SubMatrix& importFromRMajor(const T& x, size_t stride=W) { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { cols[c].data[r]=x[r*stride+c]; } return *this; }
00412 template<typename T> SubMatrix& importFrom2DArray(const T& x) { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { cols[c].data[r]=x[r][c]; } return *this; }
00413 template<typename T> SubMatrix& importFromNewmat(const T& x) { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { cols[c].data[r]=x(r+1,c+1); } return *this; }
00414 template<typename T> T exportTo() const { T x; for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { x(r,c)=cols[c].data[r]; } return x; }
00415 template<typename T> T& exportTo(T& x) const { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { x(r,c)=cols[c].data[r]; } return x; }
00416 template<typename T> T& exportToCMajor(T& x, size_t stride=H) const { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { x[c*stride+r]=cols[c].data[r]; } return x; }
00417 template<typename T> T& exportToRMajor(T& x, size_t stride=W) const { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { x[r*stride+c]=cols[c].data[r]; } return x; }
00418 template<typename T> T& exportTo2DArray(T& x) const { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { x[r][c]=cols[c].data[r]; } return x; }
00419 template<typename T> T& exportToNewmat(T& x) const { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { x(r+1,c+1)=cols[c].data[r]; } return x; }
00420
00421 const SubMatrix& operator=(R x) const { size_t c=W; while(c!=0) cols[--c]=x; return *this; }
00422 const SubMatrix& operator=(const R* x) const { size_t c=W; while(c--!=0) cols[c]=&x[c*H]; return *this; }
00423 const SubMatrix& operator=(const Matrix<H,W,out_t>& x) const { size_t c=W; while(c--!=0) cols[c]=&x.data[c*H]; return *this; }
00424 const SubMatrix& operator=(const SubMatrix& x) const { size_t c=W; while(c--!=0) cols[c]=x.cols[c]; return *this; }
00425
00426 template<typename T> const SubMatrix& operator=(const SubMatrix<H,W,T>& x) const { size_t c=W; while(c--!=0) cols[c]=x.cols[c]; return *this; }
00427
00428 const SubMatrix& operator+=(R x) const { size_t c=W; while(c!=0) cols[--c]+=x; return *this; }
00429 const SubMatrix& operator-=(R x) const { size_t c=W; while(c!=0) cols[--c]-=x; return *this; }
00430 const SubMatrix& operator*=(R x) const { size_t c=W; while(c!=0) cols[--c]*=x; return *this; }
00431 const SubMatrix& operator/=(R x) const { x=1/x; size_t c=W; while(c!=0) cols[--c]*=x; return *this; }
00432 Matrix<H,W,out_t> operator+(R x) const { return Matrix<H,W,out_t>(*this)+=x; }
00433 Matrix<H,W,out_t> operator-(R x) const { return Matrix<H,W,out_t>(*this)-=x; }
00434 Matrix<H,W,out_t> operator*(R x) const { return Matrix<H,W,out_t>(*this)*=x; }
00435 Matrix<H,W,out_t> operator/(R x) const { return Matrix<H,W,out_t>(*this)/=x; }
00436 Matrix<H,W,out_t> operator-() const { Matrix<H,W,out_t> ans(*this); size_t i=H*W; while(i--!=0) ans.data[i]=-ans.data[i]; return ans; }
00437
00438 friend Matrix<H,W,out_t> operator+(R x, const SubMatrix& a) { return a+x; }
00439 friend Matrix<H,W,out_t> operator-(R x, const SubMatrix& a) { return (-a)+x; }
00440 friend Matrix<H,W,out_t> operator*(R x, const SubMatrix& a) { return a*x; }
00441
00442 template<typename T> const SubMatrix& operator+=(const SubMatrix<H,W,T>& x) const { size_t c=W; while(c--!=0) cols[c]+=x.cols[c]; return *this; }
00443 template<typename T> const SubMatrix& operator-=(const SubMatrix<H,W,T>& x) const { size_t c=W; while(c--!=0) cols[c]-=x.cols[c]; return *this; }
00444 template<typename T> const SubMatrix& operator+=(const Matrix<H,W,T>& x) const {
00445 for(size_t c=W; c--!=0;) {
00446 const T * const tmp = &x.data[c*H];
00447 for(size_t r=H; r--!=0;)
00448 cols[c].data[r]+=tmp[r];
00449 }
00450 return *this;
00451 }
00452 template<typename T> const SubMatrix& operator-=(const Matrix<H,W,T>& x) const {
00453 for(size_t c=W; c--!=0;) {
00454 const T * const tmp = &x.data[c*H];
00455 for(size_t r=H; r--!=0;)
00456 cols[c].data[r]-=tmp[r];
00457 }
00458 return *this;
00459 }
00460 template<typename T> Matrix<H,W,out_t> operator+(const SubMatrix<H,W,T>& x) const { return Matrix<H,W,out_t>(*this)+=x; }
00461 template<typename T> Matrix<H,W,out_t> operator-(const SubMatrix<H,W,T>& x) const { return Matrix<H,W,out_t>(*this)-=x; }
00462 template<typename T> Matrix<H,W,out_t> operator+(const Matrix<H,W,T>& x) const { return Matrix<H,W,out_t>(*this)+=x; }
00463 template<typename T> Matrix<H,W,out_t> operator-(const Matrix<H,W,T>& x) const { return Matrix<H,W,out_t>(*this)-=x; }
00464
00465 template<typename T> bool operator==(const SubMatrix<H,W,T>& x) const { size_t c=W; while(c!=0) { --c; if(cols[c]!=x.cols[c]) return false; } return true; }
00466 template<typename T> bool operator!=(const SubMatrix<H,W,T>& x) const { size_t c=W; while(c!=0) { --c; if(cols[c]!=x.cols[c]) return true; } return false; }
00467 template<typename T> bool operator==(const Matrix<H,W,T>& x) const { size_t c=W; while(c!=0) { --c; if(cols[c]!=x.column(c)) return false; } return true; }
00468 template<typename T> bool operator!=(const Matrix<H,W,T>& x) const { size_t c=W; while(c!=0) { --c; if(cols[c]!=x.column(c)) return true; } return false; }
00469
00470 inline R& operator()(size_t r, size_t c) { return cols[c].data[r]; }
00471 inline const R& operator()(size_t r, size_t c) const { return cols[c].data[r]; }
00472
00473 inline SubVector<H,R>& column(size_t i) { return cols[i]; }
00474 inline const SubVector<H,R>& column(size_t i) const { return cols[i]; }
00475
00476 inline SubMatrix<1,W,R> row(size_t i) { return SubMatrix<1,W,R>(*this,i,0); }
00477 inline SubMatrix<1,W,const R> row(size_t i) const { return SubMatrix<1,W,const R>(*this,i,0); }
00478
00479 Column<H,R> minC() const {
00480 if(CAP==0) return Column<H,R>();
00481 Column<H,R> ans = cols[0];
00482 size_t c=W; while(--c!=0) { size_t r=H; while(r!=0) { --r; if(cols[c].data[r]<ans[r]) ans[r]=cols[c].data[r]; } }
00483 return ans;
00484 }
00485
00486 Column<H,R> maxC() const {
00487 if(CAP==0) return Column<H,R>();
00488 Column<H,R> ans = cols[0];
00489 size_t c=W; while(--c!=0) { size_t r=H; while(r!=0) { --r; if(ans[r]<cols[c].data[r]) ans[r]=cols[c].data[r]; } }
00490 return ans;
00491 }
00492 Row<W,R> minR() const { Row<W,R> ans=fmat_internal::NoInit(); size_t c=W; while(c!=0) { --c; ans[c]=cols[c].min(); } return ans; }
00493 Row<W,R> maxR() const { Row<W,R> ans=fmat_internal::NoInit(); size_t c=W; while(c!=0) { --c; ans[c]=cols[c].max(); } return ans; }
00494 void abs() const { size_t c=W; while(c!=0) cols[--c].abs(); }
00495 template<typename F> void apply(const F& f) const { size_t c=W; while(c--!=0) cols[c].apply(f); }
00496 template<typename F> Matrix<H,W,out_t> map(const F& f) const {
00497 if(H==0 || W==0) return Matrix<H,W,out_t>();
00498 Matrix<H,W,out_t> ans=fmat_internal::NoInit();
00499 size_t c=W; while(c!=0) { --c; size_t r=H; while(r!=0) { --r; ans.data[c*H+r] = f(cols[c].data[r]); } }
00500 return ans;
00501 }
00502
00503 inline Matrix<W,H,out_t> transpose() const ATTR_must_check {
00504 Matrix<W,H,out_t> ans=fmat_internal::NoInit();
00505 for(size_t c=W; c--!=0;)
00506 for(size_t r=H; r--!=0;)
00507 ans.data[r*W+c]=cols[c].data[r];
00508 return ans;
00509 }
00510
00511 std::string fmt(std::string const &numberFormat=defaultNumberFormat,
00512 std::string const &firstLineStart="{ ",
00513 std::string const &nextLineStart= " ",
00514 std::string const &lastLineEnd= " }",
00515 std::string const &rowBegin="",
00516 std::string const &elementSep=" ",
00517 std::string const &rowEnd="",
00518 std::string const &rowSep="\n") const
00519 {
00520 Matrix<H,W,out_t> m(*this);
00521 return fullfmt(m.data,H,W,numberFormat,firstLineStart,nextLineStart,lastLineEnd,rowBegin,elementSep,rowEnd,rowSep);
00522 }
00523
00524 protected:
00525 SubVector<H,R> cols[(W==0)?1:W];
00526 };
00527
00528 #if !defined(__clang__) && defined(__GNUC__) && !(__GNUC__==4 && __GNUC_MINOR__<1)
00529 template<size_t H, size_t W, typename R> const size_t SubMatrix<H,W,R>::HEIGHT=H;
00530 template<size_t H, size_t W, typename R> const size_t SubMatrix<H,W,R>::WIDTH=W;
00531 template<size_t H, size_t W, typename R> const size_t SubMatrix<H,W,R>::CAP=H*W;
00532 #endif
00533
00534
00535 template<size_t H, size_t W, typename R=fmatReal>
00536 class Matrix {
00537 template<size_t MH, size_t MW, typename MR> friend class Matrix;
00538 template<size_t MH, size_t MW, typename MR> friend class SubMatrix;
00539 template<size_t MN, typename MR> friend class SubVector;
00540 template<size_t MN, typename MR> friend class Column;
00541 template<size_t MN, typename MR> friend class Row;
00542 public:
00543
00544 #if defined(__clang__) || !defined(__GNUC__) || (__GNUC__==4 && __GNUC_MINOR__<1)
00545 static const size_t HEIGHT=H;
00546 static const size_t WIDTH=W;
00547 static const size_t CAP=H*W;
00548 #else
00549 static const size_t HEIGHT;
00550 static const size_t WIDTH;
00551 static const size_t CAP;
00552 #endif
00553 typedef R storage_t;
00554 typedef typename fmat_internal::unconst<R>::type out_t;
00555
00556 Matrix(const fmat_internal::NoInit&) {}
00557
00558 Matrix() { memset(data,0,sizeof(R)*CAP); }
00559 explicit Matrix(const R x) { fmat_internal::tmemset<R>(data,x,CAP); }
00560 explicit Matrix(const R* x, size_t colStride=H) { size_t c=W; while(c--!=0) fmat_internal::tmemcpy<R>(&data[c*H],&x[c*colStride],H); }
00561 Matrix(const SubMatrix<H,W,out_t>& x) { size_t c=W; while(c--!=0) fmat_internal::tmemcpy<R>(&data[c*H],x.cols[c].data,H); }
00562 Matrix(const SubMatrix<H,W,const out_t>& x) { size_t c=W; while(c--!=0) fmat_internal::tmemcpy<R>(&data[c*H],x.cols[c].data,H); }
00563 Matrix(const Matrix<H,W,out_t>& x) { fmat_internal::tmemcpy<R>(data,x.data,CAP); }
00564 Matrix(const Matrix<H,W,const out_t>& x) { fmat_internal::tmemcpy<R>(data,x.data,CAP); }
00565
00566 template<size_t SH, size_t SW, typename T> explicit Matrix(const SubMatrix<SH,SW,T>& x) {
00567 memset(data,0,sizeof(R)*CAP);
00568 size_t toCopy = std::min(H,SH);
00569 size_t c = std::min(W,SW);
00570 while(c--!=0)
00571 fmat_internal::tmemcpy<R>(&data[c*H],&x.cols[c][0],toCopy);
00572 }
00573 template<size_t SH, size_t SW, typename T> explicit Matrix(const SubMatrix<SH,SW,T>& x, size_t rowOff, size_t colOff) {
00574 memset(data,0,sizeof(R)*CAP);
00575 size_t toCopy = std::min(H,SH-rowOff);
00576 size_t c = std::min(W,SW-colOff);
00577 while(c--!=0)
00578 fmat_internal::tmemcpy<R>(&data[c*H],&x.cols[c+colOff][rowOff],toCopy);
00579 }
00580 template<size_t SH, size_t SW> explicit Matrix(const Matrix<SH,SW,R>& x) {
00581 memset(data,0,sizeof(R)*CAP);
00582 size_t toCopy = std::min(H,SH);
00583 size_t c = std::min(W,SW);
00584 while(c--!=0)
00585 fmat_internal::tmemcpy<R>(&data[c*H],&x.data[c*SH],toCopy);
00586 }
00587 template<size_t SH, size_t SW> explicit Matrix(const Matrix<SH,SW,R>& x, size_t rowOff, size_t colOff) {
00588 memset(data,0,sizeof(R)*CAP);
00589 size_t toCopy = std::min(H,SH-rowOff);
00590 size_t c = std::min(W,SW-colOff);
00591 while(c--!=0)
00592 fmat_internal::tmemcpy<R>(&data[c*H],&x.data[(c+colOff)*SH+rowOff],toCopy);
00593 }
00594
00595
00596
00597
00598 static const Matrix& identity() { static IdentityMatrix<H,W,R> ident; return ident; }
00599
00600 template<typename T> Matrix& importFrom(const T& x) { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { data[c*H+r]=x(r,c); } return *this; }
00601 template<typename T> Matrix& importFromCMajor(const T& x, size_t stride=H) { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { data[c*H+r]=x[c*stride+r]; } return *this; }
00602 template<typename T> Matrix& importFromRMajor(const T& x, size_t stride=W) { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { data[c*H+r]=x[r*stride+c]; } return *this; }
00603 template<typename T> Matrix& importFrom2DArray(const T& x) { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { data[c*H+r]=x[r][c]; } return *this; }
00604 template<typename T> Matrix& importFromNewmat(const T& x) { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { data[c*H+r]=x(r+1,c+1); } return *this; }
00605 template<typename T> T exportTo() const { T x; for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { x(r,c)=data[c*H+r]; } return x; }
00606 template<typename T> T& exportTo(T& x) const { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { x(r,c)=data[c*H+r]; } return x; }
00607 template<typename T> T& exportToCMajor(T& x, size_t stride=H) const { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { x[c*stride+r]=data[c*H+r]; } return x; }
00608 template<typename T> T& exportToRMajor(T& x, size_t stride=W) const { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { x[r*stride+c]=data[c*H+r]; } return x; }
00609 template<typename T> T& exportTo2DArray(T& x) const { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { x[r][c]=data[c*H+r]; } return x; }
00610 template<typename T> T& exportToNewmat(T& x) const { for(size_t c=0; c<W; ++c) for(size_t r=0; r<H; ++r) { x((int)r+1,(int)c+1)=data[c*H+r]; } return x; }
00611
00612 Matrix& operator=(const R* x) { fmat_internal::tmemcpy<R>(data,x,CAP); return *this; }
00613 Matrix& operator=(R x) { fmat_internal::tmemset<R>(data,x,CAP); return *this; }
00614 Matrix& operator=(const SubMatrix<H,W,R>& x) { size_t c=W; while(c--!=0) fmat_internal::tmemcpy<R>(&data[c*H],x.cols[c].data,H); return *this; }
00615 Matrix& operator=(const Matrix<H,W,R>& x) { fmat_internal::tmemcpy<R>(data,x.data,CAP); return *this; }
00616
00617 Matrix& operator+=(R x) { size_t i=CAP; while(i!=0) data[--i]+=x; return *this; }
00618 Matrix& operator-=(R x) { size_t i=CAP; while(i!=0) data[--i]-=x; return *this; }
00619 Matrix& operator*=(R x) { size_t i=CAP; while(i!=0) data[--i]*=x; return *this; }
00620 Matrix& operator/=(R x) { x=1/x; size_t i=CAP; while(i!=0) data[--i]*=x; return *this; }
00621 Matrix<H,W,out_t> operator+(R x) const { return Matrix<H,W,out_t>(*this)+=x; }
00622 Matrix<H,W,out_t> operator-(R x) const { return Matrix<H,W,out_t>(*this)-=x; }
00623 Matrix<H,W,out_t> operator*(R x) const { return Matrix<H,W,out_t>(*this)*=x; }
00624 Matrix<H,W,out_t> operator/(R x) const { return Matrix<H,W,out_t>(*this)/=x; }
00625 Matrix<H,W,out_t> operator-() const { Matrix<H,W,out_t> ans(*this); size_t i=H*W; while(i--!=0) ans.data[i]=-ans.data[i]; return ans; }
00626
00627 friend Matrix<H,W,out_t> operator+(R x, const Matrix& a) { return a+x; }
00628 friend Matrix<H,W,out_t> operator-(R x, const Matrix& a) { return (-a)+x; }
00629 friend Matrix<H,W,out_t> operator*(R x, const Matrix& a) { return a*x; }
00630
00631 Matrix& operator+=(const SubMatrix<H,W,out_t>& x) {
00632 for(size_t c=W; c--!=0;) {
00633 R * const tmp = &data[c*H];
00634 for(size_t r=H; r--!=0;)
00635 tmp[r]+=x.cols[c].data[r];
00636 }
00637 return *this;
00638 }
00639 Matrix& operator-=(const SubMatrix<H,W,out_t>& x) {
00640 for(size_t c=W; c--!=0;) {
00641 R * const tmp = &data[c*H];
00642 for(size_t r=H; r--!=0;)
00643 tmp[r]-=x.cols[c].data[r];
00644 }
00645 return *this;
00646 }
00647 Matrix& operator+=(const SubMatrix<H,W,const out_t>& x) {
00648 for(size_t c=W; c--!=0;) {
00649 R * const tmp = &data[c*H];
00650 for(size_t r=H; r--!=0;)
00651 tmp[r]+=x.cols[c].data[r];
00652 }
00653 return *this;
00654 }
00655 Matrix& operator-=(const SubMatrix<H,W,const out_t>& x) {
00656 for(size_t c=W; c--!=0;) {
00657 R * const tmp = &data[c*H];
00658 for(size_t r=H; r--!=0;)
00659 tmp[r]-=x.cols[c].data[r];
00660 }
00661 return *this;
00662 }
00663 Matrix& operator+=(const Matrix<H,W,R>& x) { size_t i=CAP; while(i--!=0) data[i]+=x.data[i]; return *this; }
00664 Matrix& operator-=(const Matrix<H,W,R>& x) { size_t i=CAP; while(i--!=0) data[i]-=x.data[i]; return *this; }
00665 Matrix<H,W,R> operator+(const SubMatrix<H,W,R>& x) const { return Matrix<H,W,R>(*this)+=x; }
00666 Matrix<H,W,R> operator-(const SubMatrix<H,W,R>& x) const { return Matrix<H,W,R>(*this)-=x; }
00667 Matrix<H,W,R> operator+(const Matrix<H,W,R>& x) const { return Matrix<H,W,R>(*this)+=x; }
00668 Matrix<H,W,R> operator-(const Matrix<H,W,R>& x) const { return Matrix<H,W,R>(*this)-=x; }
00669
00670 bool operator==(const SubMatrix<H,W,R>& x) const { size_t c=W; while(c!=0) { --c; if(column(c)!=x.cols[c]) return false; } return true; }
00671 bool operator!=(const SubMatrix<H,W,R>& x) const { size_t c=W; while(c!=0) { --c; if(column(c)!=x.cols[c]) return true; } return false; }
00672 bool operator==(const Matrix<H,W,R>& x) const { size_t i=H*W; while(i!=0) { --i; if(data[i]!=x.data[i]) return false; } return true; }
00673 bool operator!=(const Matrix<H,W,R>& x) const { size_t i=H*W; while(i!=0) { --i; if(data[i]!=x.data[i]) return true; } return false; }
00674
00675 inline R& operator()(size_t r, size_t c) { return data[c*H+r]; }
00676 inline const R& operator()(size_t r, size_t c) const { return data[c*H+r]; }
00677
00678 inline SubVector<H,R> column(size_t i) { return SubVector<H,R>(&data[i*H]); }
00679 inline const SubVector<H,const R> column(size_t i) const { return SubVector<H,const R>(&data[i*H]); }
00680
00681 inline SubMatrix<1,W,R> row(size_t i) { return SubMatrix<1,W,R>(data+i, H); }
00682 inline const SubMatrix<1,W,const R> row(size_t i) const { return SubMatrix<1,W,const R>(data+i, H); }
00683
00684 Column<H,R> minC() const {
00685 if(CAP==0) return Column<H,R>();
00686 Column<H,R> ans(data);
00687 size_t c=W; while(--c!=0) { size_t r=H; while(r!=0) { --r; if(data[c*H+r]<ans[r]) ans[r]=data[c*H+r]; } }
00688 return ans;
00689 }
00690
00691 Column<H,R> maxC() const {
00692 if(CAP==0) return Column<H,R>();
00693 Column<H,R> ans(data);
00694 size_t c=W; while(--c!=0) { size_t r=H; while(r!=0) { --r; if(ans[r]<data[c*H+r]) ans[r]=data[c*H+r]; } }
00695 return ans;
00696 }
00697 Row<W,R> minR() const { Row<W,R> ans=fmat_internal::NoInit(); size_t c=W; while(c!=0) { --c; ans[c]=column(c).min(); } return ans; }
00698 Row<W,R> maxR() const { Row<W,R> ans=fmat_internal::NoInit(); size_t c=W; while(c!=0) { --c; ans[c]=column(c).max(); } return ans; }
00699 void abs() { size_t i=CAP; while(i!=0) { --i; data[i]=std::abs(data[i]); } }
00700 template<typename F> void apply(const F& f) { size_t i=H*W; while(i!=0) { --i; data[i] = f(data[i]); } }
00701 template<typename F> Matrix map(const F& f) const {
00702 if(H==0 || W==0) return Matrix();
00703 Matrix ans=fmat_internal::NoInit();
00704 size_t i=H*W; while(i!=0) { --i; ans.data[i] = f(data[i]); }
00705 return ans;
00706 }
00707
00708 inline Matrix<W,H,R> transpose() const ATTR_must_check {
00709 Matrix<W,H,R> ans=fmat_internal::NoInit();
00710 for(size_t c=W; c--!=0;)
00711 for(size_t r=H; r--!=0;)
00712 ans.data[r*W+c]=data[c*H+r];
00713 return ans;
00714 }
00715
00716 inline std::string fmt(std::string const &numberFormat=defaultNumberFormat,
00717 std::string const &firstLineStart="[ ",
00718 std::string const &nextLineStart= " ",
00719 std::string const &lastLineEnd= " ]",
00720 std::string const &rowBegin="",
00721 std::string const &elementSep=" ",
00722 std::string const &rowEnd="",
00723 std::string const &rowSep="\n") const
00724 {
00725 return fullfmt(&data[0],H,W,numberFormat,firstLineStart,nextLineStart,lastLineEnd,rowBegin,elementSep,rowEnd,rowSep);
00726 }
00727
00728 protected:
00729 R data[(H*W==0)?1:H*W];
00730
00731 template<size_t HH, size_t WW, typename RR=fmatReal>
00732 struct IdentityMatrix : Matrix<HH,WW,RR> {
00733 IdentityMatrix() : Matrix() {
00734 size_t d = std::min(H,W);
00735 for(size_t i=0; i<d; ++i)
00736 this->data[i*H+i]=1;
00737 }
00738 };
00739
00740 };
00741
00742 #if !defined(__clang__) && defined(__GNUC__) && !(__GNUC__==4 && __GNUC_MINOR__<1)
00743 template<size_t H, size_t W, typename R> const size_t Matrix<H,W,R>::HEIGHT=H;
00744 template<size_t H, size_t W, typename R> const size_t Matrix<H,W,R>::WIDTH=W;
00745 template<size_t H, size_t W, typename R> const size_t Matrix<H,W,R>::CAP=H*W;
00746 #endif
00747
00748
00749 template<size_t N, typename R=fmatReal>
00750 class Column : public Matrix<N,1,R> {
00751 template<size_t S, typename T> friend class SubVector;
00752 template<size_t S, typename T> friend class Column;
00753 template<size_t S, typename T> friend class Row;
00754 friend Column<2,R> packT<>(R x, R y);
00755 friend Column<3,R> packT<>(R x, R y, R z);
00756 friend Column<4,R> packT<>(R x, R y, R z, R d);
00757 friend Column<2,fmatReal> pack(fmatReal x, fmatReal y);
00758 friend Column<3,fmatReal> pack(fmatReal x, fmatReal y, fmatReal z);
00759 friend Column<4,fmatReal> pack(fmatReal x, fmatReal y, fmatReal z, fmatReal d);
00760 public:
00761
00762 #if defined(__clang__) || !defined(__GNUC__) || (__GNUC__==4 && __GNUC_MINOR__<1)
00763 static const size_t HEIGHT=N;
00764 static const size_t WIDTH=1;
00765 static const size_t CAP=N;
00766 #else
00767 static const size_t HEIGHT;
00768 static const size_t WIDTH;
00769 static const size_t CAP;
00770 #endif
00771 typedef R storage_t;
00772 typedef typename fmat_internal::unconst<R>::type out_t;
00773
00774 Column(const fmat_internal::NoInit& noinit) : Matrix<N,1,R>(noinit) {}
00775
00776 Column() : Matrix<N,1,R>() {}
00777 explicit Column(const R x) : Matrix<N,1,R>(x) {}
00778 explicit Column(const R* x, size_t stride=sizeof(R)) : Matrix<N,1,R>(fmat_internal::NoInit()) { size_t i=N; while(i!=0) { --i; data[i]=x[i*stride/sizeof(R)]; } }
00779 Column(const SubVector<N,R>& x) : Matrix<N,1,R>(x.data) {}
00780 Column(const SubVector<N,const R>& x) : Matrix<N,1,R>(x.data) {}
00781 Column(const SubMatrix<N,1,R>& x) : Matrix<N,1,R>(x) {}
00782 Column(const SubMatrix<N,1,const R>& x) : Matrix<N,1,R>(x) {}
00783 Column(const Matrix<N,1,R>& x) : Matrix<N,1,R>(x) {}
00784 template<size_t S> explicit Column(const Column<S,R>& x, size_t srcOffset=0) : Matrix<N,1,R>() {
00785 size_t toCopy = std::min(N,S-srcOffset);
00786 fmat_internal::tmemcpy<R>(data,&x.data[srcOffset],toCopy);
00787 }
00788 template<size_t S> explicit Column(const SubVector<S,R>& x, size_t srcOffset=0) : Matrix<N,1,R>() {
00789 size_t toCopy = std::min(N,S-srcOffset);
00790 fmat_internal::tmemcpy<R>(data,&x.data[srcOffset],toCopy);
00791 }
00792 template<size_t S> explicit Column(const SubVector<S,const R>& x, size_t srcOffset=0) : Matrix<N,1,R>() {
00793 size_t toCopy = std::min(N,S-srcOffset);
00794 fmat_internal::tmemcpy<R>(data,&x.data[srcOffset],toCopy);
00795 }
00796 template<typename T> Column& importFrom(const T& x) { size_t i=N; while(i!=0) { --i; data[i]=x[i]; } return *this; }
00797 template<typename T> T exportTo() const { T x; size_t i=N; while(i!=0) { --i; x[i]=data[i]; } return x; }
00798 template<typename T> T& exportTo(T& x) const { size_t i=N; while(i!=0) { --i; x[i]=data[i]; } return x; }
00799
00800
00801
00802
00803 Column& operator=(const R* x) { fmat_internal::tmemcpy<R>(data,x,CAP); return *this; }
00804 Column& operator=(R x) { fmat_internal::tmemset<R>(data,x,CAP); return *this; }
00805 Column& operator=(const SubVector<N,R>& x) { fmat_internal::tmemcpy<R>(data,x.data,N); return *this; }
00806 Column& operator=(const SubVector<N,const R>& x) { fmat_internal::tmemcpy<R>(data,x.data,N); return *this; }
00807 Column& operator=(const SubMatrix<N,1,R>& x) { fmat_internal::tmemcpy<R>(data,x.cols[0].data,N); return *this; }
00808 Column& operator=(const SubMatrix<N,1,const R>& x) { fmat_internal::tmemcpy<R>(data,x.cols[0].data,N); return *this; }
00809 Column& operator=(const Matrix<N,1,R>& x) { fmat_internal::tmemcpy<R>(data,x.data,CAP); return *this; }
00810
00811 Column& operator+=(R x) { size_t i=N; while(i!=0) data[--i]+=x; return *this; }
00812 Column& operator-=(R x) { size_t i=N; while(i!=0) data[--i]-=x; return *this; }
00813 Column& operator*=(R x) { size_t i=N; while(i!=0) data[--i]*=x; return *this; }
00814 Column& operator/=(R x) { x=1/x; size_t i=N; while(i!=0) data[--i]*=x; return *this; }
00815 Column<N,out_t> operator+(R x) const { return Column<N,out_t>(*this)+=x; }
00816 Column<N,out_t> operator-(R x) const { return Column<N,out_t>(*this)-=x; }
00817 Column<N,out_t> operator*(R x) const { return Column<N,out_t>(*this)*=x; }
00818 Column<N,out_t> operator/(R x) const { return Column<N,out_t>(*this)/=x; }
00819 Column<N,out_t> operator-() const { Column<N,out_t> ans(*this); size_t i=N; while(i--!=0) ans.data[i]=-ans.data[i]; return ans; }
00820
00821 friend Column<N,out_t> operator+(R x, const Column& a) { return a+x; }
00822 friend Column<N,out_t> operator-(R x, const Column& a) { return (-a)+x; }
00823 friend Column<N,out_t> operator*(R x, const Column& a) { return a*x; }
00824
00825 Column& operator+=(const SubVector<N,R>& x) { size_t i=CAP; while(i--!=0) data[i]+=x.data[i]; return *this; }
00826 Column& operator-=(const SubVector<N,R>& x) { size_t i=CAP; while(i--!=0) data[i]-=x.data[i]; return *this; }
00827 Column& operator+=(const SubVector<N,const R>& x) { size_t i=CAP; while(i--!=0) data[i]+=x.data[i]; return *this; }
00828 Column& operator-=(const SubVector<N,const R>& x) { size_t i=CAP; while(i--!=0) data[i]-=x.data[i]; return *this; }
00829 Column& operator+=(const SubMatrix<N,1,R>& x) { Matrix<N,1,R>::operator+=(x); return *this;}
00830 Column& operator-=(const SubMatrix<N,1,R>& x) { Matrix<N,1,R>::operator-=(x); return *this;}
00831 Column& operator+=(const SubMatrix<N,1,const R>& x) { Matrix<N,1,R>::operator+=(x); return *this;}
00832 Column& operator-=(const SubMatrix<N,1,const R>& x) { Matrix<N,1,R>::operator-=(x); return *this;}
00833 Column& operator+=(const Matrix<N,1,R>& x) { Matrix<N,1,R>::operator+=(x); return *this;}
00834 Column& operator-=(const Matrix<N,1,R>& x) { Matrix<N,1,R>::operator-=(x); return *this;}
00835
00836 Column operator+(const SubVector<N,R>& x) const { return Column(*this)+=x; }
00837 Column operator-(const SubVector<N,R>& x) const { return Column(*this)-=x; }
00838 Column operator+(const SubVector<N,const R>& x) const { return Column(*this)+=x; }
00839 Column operator-(const SubVector<N,const R>& x) const { return Column(*this)-=x; }
00840 Column operator+(const SubMatrix<N,1,R>& x) const { return Column(*this)+=x; }
00841 Column operator-(const SubMatrix<N,1,R>& x) const { return Column(*this)-=x; }
00842 Column operator+(const SubMatrix<N,1,const R>& x) const { return Column(*this)+=x; }
00843 Column operator-(const SubMatrix<N,1,const R>& x) const { return Column(*this)-=x; }
00844 Column operator+(const Matrix<N,1,R>& x) const { return Column(*this)+=x; }
00845 Column operator-(const Matrix<N,1,R>& x) const { return Column(*this)-=x; }
00846
00847 bool operator==(const SubVector<N,R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.data[i]) return false; } return true; }
00848 bool operator!=(const SubVector<N,R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.data[i]) return true; } return false; }
00849 bool operator<(const SubVector<N,R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]<x.data[i]) return true; if(x.data[i]<data[i]) return false; } return false; }
00850 bool operator==(const SubVector<N,const R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.data[i]) return false; } return true; }
00851 bool operator!=(const SubVector<N,const R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.data[i]) return true; } return false; }
00852 bool operator<(const SubVector<N,const R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]<x.data[i]) return true; if(x.data[i]<data[i]) return false; } return false; }
00853 bool operator==(const SubMatrix<N,1,R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.cols[0][i]) return false; } return true; }
00854 bool operator!=(const SubMatrix<N,1,R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.cols[0][i]) return true; } return false; }
00855 bool operator<(const SubMatrix<N,1,R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]<x.cols[0][i]) return true; if(x.cols[0][i]<data[i]) return false; } return false; }
00856 bool operator==(const SubMatrix<N,1,const R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.cols[0][i]) return false; } return true; }
00857 bool operator!=(const SubMatrix<N,1,const R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.cols[0][i]) return true; } return false; }
00858 bool operator<(const SubMatrix<N,1,const R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]<x.cols[0][i]) return true; if(x.cols[0][i]<data[i]) return false; } return false; }
00859 bool operator==(const Matrix<N,1,R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.data[i]) return false; } return true; }
00860 bool operator!=(const Matrix<N,1,R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.data[i]) return true; } return false; }
00861 bool operator<(const Matrix<N,1,R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]<x.data[i]) return true; if(x.data[i]<data[i]) return false; } return false; }
00862
00863
00864 template<typename T> bool operator<<(const Matrix<N,1,T>& x) const { size_t i=N; while(i!=0) { --i; if(x.data[i] <= data[i]) return false; } return true; }
00865 template<typename T> bool operator<<(const SubVector<N,T>& x) const { size_t i=N; while(i!=0) { --i; if(x.data[i] <= data[i]) return false; } return true; }
00866
00867 inline R& operator[](size_t i) { return data[i]; }
00868 inline const R& operator[](size_t i) const { return data[i]; }
00869
00870 R norm() const ATTR_must_check { R ans=0; size_t i=N; while(i!=0) { const R x=data[--i]; ans+=x*x; } return std::sqrt(ans); }
00871 R sum() const ATTR_must_check { R ans=0; size_t i=N; while(i!=0) { ans+=data[--i]; } return ans; }
00872 R sumSq() const ATTR_must_check { R ans=0; size_t i=N; while(i!=0) { const R x=data[--i]; ans+=x*x; } return ans; }
00873 void abs() { size_t i=N; while(i!=0) { --i; data[i]=std::abs(data[i]); } }
00874 R max() const ATTR_must_check { if(N==0) return R(); R ans=data[N-1]; size_t i=N-1; while(i--!=0) if(ans<data[i]) ans=data[i]; return ans; }
00875 R min() const ATTR_must_check { if(N==0) return R(); R ans=data[N-1]; size_t i=N-1; while(i--!=0) if(ans>data[i]) ans=data[i]; return ans; }
00876 template<typename F> void apply(const F& f) { size_t i=N; while(i--!=0) data[i]=f(data[i]); }
00877 template<typename F> Column<N,R> map(const F& f) const { Column<N,R> ans; size_t i=N; while(i--!=0) ans.data[i]=f(data[i]); return ans; }
00878
00879 template<typename T> void minimize(const Matrix<N,1,T>& x) { size_t i=N; while(i!=0) { --i; if(x.data[i] < data[i]) data[i]=x.data[i]; } }
00880 template<typename T> void minimize(const SubVector<N,T>& x) { size_t i=N; while(i!=0) { --i; if(x.data[i] < data[i]) data[i]=x.data[i]; } }
00881 template<typename T> void maximize(const Matrix<N,1,T>& x) { size_t i=N; while(i!=0) { --i; if(data[i] < x.data[i]) data[i]=x.data[i]; } }
00882 template<typename T> void maximize(const SubVector<N,T>& x) { size_t i=N; while(i!=0) { --i; if(data[i] < x.data[i]) data[i]=x.data[i]; } }
00883
00884 inline Row<N,R> transpose() const ATTR_must_check {
00885 Row<N,R> ans=fmat_internal::NoInit();
00886 fmat_internal::tmemcpy<R>(ans.data,data,N);
00887 return ans;
00888 }
00889
00890 inline std::string fmt(std::string const &numberFormat=defaultNumberFormat,
00891 std::string const &firstLineStart="[",
00892 std::string const &nextLineStart="",
00893 std::string const &lastLineEnd="]\u1D40",
00894 std::string const &rowBegin="",
00895 std::string const &elementSep="",
00896 std::string const &rowEnd="",
00897 std::string const &rowSep=" ") const
00898 {
00899 return fullfmt(&data[0],N,1,numberFormat,firstLineStart,nextLineStart,lastLineEnd,rowBegin,elementSep,rowEnd,rowSep);
00900 }
00901
00902 protected:
00903 using Matrix<N,1,R>::data;
00904 };
00905
00906 #if !defined(__clang__) && defined(__GNUC__) && !(__GNUC__==4 && __GNUC_MINOR__<1)
00907 template<size_t N, typename R> const size_t Column<N,R>::HEIGHT=N;
00908 template<size_t N, typename R> const size_t Column<N,R>::WIDTH=1;
00909 template<size_t N, typename R> const size_t Column<N,R>::CAP=N;
00910 #endif
00911
00912
00913 template<size_t N, typename R=fmatReal>
00914 class Row : public Matrix<1,N,R> {
00915 template<size_t S, typename T> friend class SubVector;
00916 template<size_t S, typename T> friend class Column;
00917 template<size_t S, typename T> friend class Row;
00918 public:
00919 static const size_t HEIGHT=1;
00920 static const size_t WIDTH=N;
00921 static const size_t CAP=N;
00922 typedef R storage_t;
00923 typedef typename fmat_internal::unconst<R>::type out_t;
00924
00925 Row(const fmat_internal::NoInit& noinit) : Matrix<1,N,R>(noinit) {}
00926
00927 Row() : Matrix<1,N,R>() {}
00928 explicit Row(const R x) : Matrix<1,N,R>(x) {}
00929 explicit Row(const R* x, size_t stride=sizeof(R)) : Matrix<1,N,R>(fmat_internal::NoInit()) { size_t i=N; while(i!=0) { --i; data[i]=x[i*stride/sizeof(R)]; } }
00930 Row(const SubVector<N,R>& x) : Matrix<1,N,R>(x.data) {}
00931 Row(const SubVector<N,const R>& x) : Matrix<1,N,R>(x.data) {}
00932 Row(const SubMatrix<1,N,R>& x) : Matrix<1,N,R>(x) {}
00933 Row(const SubMatrix<1,N,const R>& x) : Matrix<1,N,R>(x) {}
00934 Row(const Matrix<1,N,R>& x) : Matrix<1,N,R>(x) {}
00935 template<size_t S> explicit Row(const Row<S,R>& x, size_t srcOffset=0) : Matrix<1,N,R>() {
00936 size_t toCopy = std::min(N,S-srcOffset);
00937 fmat_internal::tmemcpy<R>(data,&x.data[srcOffset],toCopy);
00938 }
00939 template<size_t S> explicit Row(const SubVector<S,R>& x, size_t srcOffset=0) : Matrix<1,N,R>() {
00940 size_t toCopy = std::min(N,S-srcOffset);
00941 fmat_internal::tmemcpy<R>(data,&x.data[srcOffset],toCopy);
00942 }
00943 template<size_t S> explicit Row(const SubVector<S,const R>& x, size_t srcOffset=0) : Matrix<1,N,R>() {
00944 size_t toCopy = std::min(N,S-srcOffset);
00945 fmat_internal::tmemcpy<R>(data,&x.data[srcOffset],toCopy);
00946 }
00947 template<typename T> Row& importFrom(const T& x) { size_t i=N; while(i!=0) { --i; data[i]=x[i]; } return *this; }
00948 template<typename T> T exportTo() const { T x; size_t i=N; while(i!=0) { --i; x[i]=data[i]; } return x; }
00949 template<typename T> T& exportTo(T& x) const { size_t i=N; while(i!=0) { --i; x[i]=data[i]; } return x; }
00950
00951
00952
00953
00954 Row& operator=(const R* x) { fmat_internal::tmemcpy<R>(data,x,CAP); return *this; }
00955 Row& operator=(R x) { fmat_internal::tmemset<R>(data,x,CAP); return *this; }
00956 Row& operator=(const SubVector<N,R>& x) { fmat_internal::tmemcpy<R>(data,x.data,N); return *this; }
00957 Row& operator=(const SubVector<N,const R>& x) { fmat_internal::tmemcpy<R>(data,x.data,N); return *this; }
00958 Row& operator=(const SubMatrix<1,N,R>& x) { fmat_internal::tmemcpy<R>(data,x.cols[0].data,N); return *this; }
00959 Row& operator=(const SubMatrix<1,N,const R>& x) { fmat_internal::tmemcpy<R>(data,x.cols[0].data,N); return *this; }
00960 Row& operator=(const Matrix<1,N,R>& x) { fmat_internal::tmemcpy<R>(data,x.data,CAP); return *this; }
00961
00962 Row& operator+=(R x) { size_t i=N; while(i!=0) data[--i]+=x; return *this; }
00963 Row& operator-=(R x) { size_t i=N; while(i!=0) data[--i]-=x; return *this; }
00964 Row& operator*=(R x) { size_t i=N; while(i!=0) data[--i]*=x; return *this; }
00965 Row& operator/=(R x) { x=1/x; size_t i=N; while(i!=0) data[--i]*=x; return *this; }
00966 Row<N,out_t> operator+(R x) const { return Row<N,R>(*this)+=x; }
00967 Row<N,out_t> operator-(R x) const { return Row<N,R>(*this)-=x; }
00968 Row<N,out_t> operator*(R x) const { return Row<N,R>(*this)*=x; }
00969 Row<N,out_t> operator/(R x) const { return Row<N,R>(*this)/=x; }
00970 Row<N,out_t> operator-() const { Row<N,R> ans(*this); size_t i=N; while(i--!=0) ans.data[i]=-ans.data[i]; return ans; }
00971
00972 friend Row<N,out_t> operator+(R x, const Row& a) { return a+x; }
00973 friend Row<N,out_t> operator-(R x, const Row& a) { return (-a)+x; }
00974 friend Row<N,out_t> operator*(R x, const Row& a) { return a*x; }
00975
00976 Row& operator+=(const SubVector<N,R>& x) { size_t i=CAP; while(i--!=0) data[i]+=x.data[i]; return *this; }
00977 Row& operator-=(const SubVector<N,R>& x) { size_t i=CAP; while(i--!=0) data[i]-=x.data[i]; return *this; }
00978 Row& operator+=(const SubVector<N,const R>& x) { size_t i=CAP; while(i--!=0) data[i]+=x.data[i]; return *this; }
00979 Row& operator-=(const SubVector<N,const R>& x) { size_t i=CAP; while(i--!=0) data[i]-=x.data[i]; return *this; }
00980 Row& operator+=(const SubMatrix<1,N,R>& x) { Matrix<1,N,R>::operator+=(x); return *this;}
00981 Row& operator-=(const SubMatrix<1,N,R>& x) { Matrix<1,N,R>::operator-=(x); return *this;}
00982 Row& operator+=(const SubMatrix<1,N,const R>& x) { Matrix<1,N,R>::operator+=(x); return *this;}
00983 Row& operator-=(const SubMatrix<1,N,const R>& x) { Matrix<1,N,R>::operator-=(x); return *this;}
00984 Row& operator+=(const Matrix<1,N,R>& x) { Matrix<1,N,R>::operator+=(x); return *this;}
00985 Row& operator-=(const Matrix<1,N,R>& x) { Matrix<1,N,R>::operator-=(x); return *this;}
00986
00987 Row operator+(const SubVector<N,R>& x) const { return Row(*this)+=x; }
00988 Row operator-(const SubVector<N,R>& x) const { return Row(*this)-=x; }
00989 Row operator+(const SubVector<N,const R>& x) const { return Row(*this)+=x; }
00990 Row operator-(const SubVector<N,const R>& x) const { return Row(*this)-=x; }
00991 Row operator+(const SubMatrix<1,N,R>& x) const { return Row(*this)+=x; }
00992 Row operator-(const SubMatrix<1,N,R>& x) const { return Row(*this)-=x; }
00993 Row operator+(const SubMatrix<1,N,const R>& x) const { return Row(*this)+=x; }
00994 Row operator-(const SubMatrix<1,N,const R>& x) const { return Row(*this)-=x; }
00995 Row operator+(const Matrix<1,N,R>& x) const { return Row(*this)+=x; }
00996 Row operator-(const Matrix<1,N,R>& x) const { return Row(*this)-=x; }
00997
00998 bool operator==(const SubVector<N,R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.data[i]) return false; } return true; }
00999 bool operator!=(const SubVector<N,R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.data[i]) return true; } return false; }
01000 bool operator<(const SubVector<N,R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]<x.data[i]) return true; if(x.data[i]<data[i]) return false; } return false; }
01001 bool operator==(const SubVector<N,const R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.data[i]) return false; } return true; }
01002 bool operator!=(const SubVector<N,const R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.data[i]) return true; } return false; }
01003 bool operator<(const SubVector<N,const R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]<x.data[i]) return true; if(x.data[i]<data[i]) return false; } return false; }
01004 bool operator==(const SubMatrix<1,N,R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.cols[i][0]) return false; } return true; }
01005 bool operator!=(const SubMatrix<1,N,R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.cols[i][0]) return true; } return false; }
01006 bool operator<(const SubMatrix<1,N,R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]<x.cols[i][0]) return true; if(x.cols[i][0]<data[i]) return false; } return false; }
01007 bool operator==(const SubMatrix<1,N,const R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.cols[i][0]) return false; } return true; }
01008 bool operator!=(const SubMatrix<1,N,const R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.cols[i][0]) return true; } return false; }
01009 bool operator<(const SubMatrix<1,N,const R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]<x.cols[i][0]) return true; if(x.cols[i][0]<data[i]) return false; } return false; }
01010 bool operator==(const Matrix<1,N,R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.data[i]) return false; } return true; }
01011 bool operator!=(const Matrix<1,N,R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]!=x.data[i]) return true; } return false; }
01012 bool operator<(const Matrix<1,N,R>& x) const { size_t i=N; while(i!=0) { --i; if(data[i]<x.data[i]) return true; if(x.data[i]<data[i]) return false; } return false; }
01013
01014
01015 template<typename T> bool operator<<(const Matrix<N,1,T>& x) const { size_t i=N; while(i!=0) { --i; if(x.data[i] <= data[i]) return false; } return true; }
01016 template<typename T> bool operator<<(const SubVector<N,T>& x) const { size_t i=N; while(i!=0) { --i; if(x.data[i] <= data[i]) return false; } return true; }
01017
01018 inline R& operator[](size_t i) { return data[i]; }
01019 inline const R& operator[](size_t i) const { return data[i]; }
01020
01021 R norm() const ATTR_must_check { R ans=0; size_t i=N; while(i!=0) { const R x=data[--i]; ans+=x*x; } return std::sqrt(ans); }
01022 R sum() const ATTR_must_check { R ans=0; size_t i=N; while(i!=0) { ans+=data[--i]; } return ans; }
01023 R sumSq() const ATTR_must_check { R ans=0; size_t i=N; while(i!=0) { const R x=data[--i]; ans+=x*x; } return ans; }
01024 void abs() { size_t i=N; while(i!=0) { --i; data[i]=std::abs(data[i]); } }
01025 R max() const ATTR_must_check { if(N==0) return R(); R ans=data[N-1]; size_t i=N-1; while(i--!=0) if(ans<data[i]) ans=data[i]; return ans; }
01026 R min() const ATTR_must_check { if(N==0) return R(); R ans=data[N-1]; size_t i=N-1; while(i--!=0) if(ans>data[i]) ans=data[i]; return ans; }
01027 template<typename F> void apply(const F& f) { size_t i=N; while(i--!=0) data[i]=f(data[i]); }
01028 template<typename F> Row<N,R> map(const F& f) const { Row<N,R> ans; size_t i=N; while(i--!=0) ans.data[i]=f(data[i]); return ans; }
01029
01030 template<typename T> void minimize(const Matrix<1,N,T>& x) { size_t i=N; while(i!=0) { --i; if(x.data[i] < data[i]) data[i]=x.data[i]; } }
01031 template<typename T> void minimize(const SubVector<N,T>& x) { size_t i=N; while(i!=0) { --i; if(x.data[i] < data[i]) data[i]=x.data[i]; } }
01032 template<typename T> void maximize(const Matrix<1,N,T>& x) { size_t i=N; while(i!=0) { --i; if(data[i] < x.data[i]) data[i]=x.data[i]; } }
01033 template<typename T> void maximize(const SubVector<N,T>& x) { size_t i=N; while(i!=0) { --i; if(data[i] < x.data[i]) data[i]=x.data[i]; } }
01034
01035 inline Column<N,R> transpose() const ATTR_must_check {
01036 Column<N,R> ans=fmat_internal::NoInit();
01037 fmat_internal::tmemcpy<R>(ans.data,data,N);
01038 return ans;
01039 }
01040
01041 inline std::string fmt(std::string const &numberFormat=defaultNumberFormat,
01042 std::string const &firstLineStart="[",
01043 std::string const &nextLineStart="",
01044 std::string const &lastLineEnd="]",
01045 std::string const &rowBegin="",
01046 std::string const &elementSep=" ",
01047 std::string const &rowEnd="",
01048 std::string const &rowSep="") const
01049 {
01050 return fullfmt(&data[0],1,N,numberFormat,firstLineStart,nextLineStart,lastLineEnd,rowBegin,elementSep,rowEnd,rowSep);
01051 }
01052
01053 protected:
01054 using Matrix<1,N,R>::data;
01055 };
01056
01057
01058 extern const Column<2> ZERO2;
01059 extern const Column<3> ZERO3;
01060 extern const Column<4> ZEROH;
01061
01062 extern const Column<2> UNIT2_X;
01063 extern const Column<2> UNIT2_Y;
01064
01065 extern const Column<3> UNIT3_X;
01066 extern const Column<3> UNIT3_Y;
01067 extern const Column<3> UNIT3_Z;
01068
01069
01070 inline Column<2> pack(fmatReal x, fmatReal y) { Column<2> v=fmat_internal::NoInit(); v.data[0]=x; v.data[1]=y; return v; }
01071 inline Column<3> pack(fmatReal x, fmatReal y, fmatReal z) { Column<3> v=fmat_internal::NoInit(); v.data[0]=x; v.data[1]=y; v.data[2]=z; return v; }
01072 inline Column<4> pack(fmatReal x, fmatReal y, fmatReal z, fmatReal d) { Column<4> v=fmat_internal::NoInit(); v.data[0]=x; v.data[1]=y; v.data[2]=z; v.data[3]=d; return v; }
01073
01074
01075
01076
01077
01078
01079
01080 template<typename R> inline Column<2,R> packT(R x, R y) { Column<2,R> v=fmat_internal::NoInit(); v.data[0]=x; v.data[1]=y; return v; }
01081 template<typename R> inline Column<3,R> packT(R x, R y, R z) { Column<3,R> v=fmat_internal::NoInit(); v.data[0]=x; v.data[1]=y; v.data[2]=z; return v; }
01082 template<typename R> inline Column<4,R> packT(R x, R y, R z, R d) { Column<4,R> v=fmat_internal::NoInit(); v.data[0]=x; v.data[1]=y; v.data[2]=z; v.data[3]=d; return v; }
01083
01084
01085 template<template<size_t N, typename R> class T, size_t N, typename R1, typename R2>
01086 Column<N+1,typename fmat_internal::unconst<R1>::type>
01087 pack(const T<N,R1>& x, R2 y) {
01088 Column<N+1,typename fmat_internal::unconst<R1>::type> data(x); data[N]=y; return data;
01089 }
01090 template<template<size_t N, typename R> class T, size_t N, typename R1, typename R2>
01091 Column<N+1,typename fmat_internal::unconst<R2>::type>
01092 pack(R1 x, const T<N,R2>& y) {
01093 Column<N+1,typename fmat_internal::unconst<R2>::type> data=fmat_internal::NoInit(); data[0]=x; SubVector<N>(data,1)=y; return data;
01094 }
01095 template<template<size_t N, typename R> class T1, template<size_t N, typename R> class T2, size_t N1, size_t N2, typename R1, typename R2>
01096 Column<N1+N2,typename fmat_internal::promotion_trait<R1,R2>::type>
01097 pack(const T1<N1,R1>& x, const T2<N2,R2>& y) {
01098 Column<N1+N2,typename fmat_internal::promotion_trait<R1,R2>::type> data(x); SubVector<N2>(data,N1)=y; return data;
01099 }
01100
01101
01102 template<size_t N, typename R1, typename R2>
01103 Column<N+1,typename fmat_internal::unconst<R1>::type> pack(const Column<N,R1>& x, R2 y) {
01104 Column<N+1,typename fmat_internal::unconst<R1>::type> data(x); data[N]=y; return data;
01105 }
01106 template<size_t N, typename R1, typename R2>
01107 Column<N+1,typename fmat_internal::unconst<R2>::type> pack(R1 x, const Column<N,R2>& y) {
01108 Column<N+1,typename fmat_internal::unconst<R2>::type> data=fmat_internal::NoInit(); data[0]=x; SubVector<N,R2>(data,1)=y; return data;
01109 }
01110 template<size_t N1, size_t N2, typename R>
01111 Column<N1+N2,typename fmat_internal::unconst<R>::type> pack(const Column<N1,R>& x, const Column<N2,R>& y) {
01112 Column<N1+N2,typename fmat_internal::unconst<R>::type> data(x); SubVector<N2>(data,N1)=y; return data;
01113 }
01114
01115
01116 template<size_t N, typename R1, typename R2>
01117 Row<N+1,typename fmat_internal::unconst<R1>::type> pack(const Row<N,R1>& x, R2 y) {
01118 Row<N+1,typename fmat_internal::unconst<R1>::type> data(x); data[N]=y; return data;
01119 }
01120 template<size_t N, typename R1, typename R2>
01121 Row<N+1,typename fmat_internal::unconst<R2>::type> pack(R1 x, const Row<N,R2>& y) {
01122 Row<N+1,typename fmat_internal::unconst<R2>::type> data=fmat_internal::NoInit(); data[0]=x; SubVector<N,R2>(data,1)=y; return data;
01123 }
01124 template<size_t N1, size_t N2, typename R>
01125 Row<N1+N2,typename fmat_internal::unconst<R>::type> pack(const Row<N1,R>& x, const Row<N2,R>& y) {
01126 Row<N1+N2,typename fmat_internal::unconst<R>::type> data(x); SubVector<N2>(data,N1)=y; return data;
01127 }
01128
01129
01130 template<size_t N, typename R> inline std::ostream& operator<<(std::ostream& os, const SubVector<N,R>& x) {
01131 return os << x.fmt(); }
01132
01133 template<size_t H, size_t W, typename R> inline std::ostream& operator<<(std::ostream& os, const SubMatrix<H,W,R>& x) {
01134 return os << x.fmt(); }
01135
01136 template<size_t H, size_t W, typename R> inline std::ostream& operator<<(std::ostream& os, const Matrix<H,W,R>& x) {
01137 return os << x.fmt(); }
01138
01139 template<size_t N, typename R> inline std::ostream& operator<<(std::ostream& os, const Column<N,R>& x) {
01140 return os << x.fmt(); }
01141
01142 template<size_t N, typename R> inline std::ostream& operator<<(std::ostream& os, const Row<N,R>& x) {
01143 return os << x.fmt(); }
01144
01145
01146
01147 template<template<size_t H, size_t W, typename R> class T1, template<size_t H, size_t W, typename R> class T2, size_t H, size_t N, size_t W, typename R1, typename R2>
01148 inline Matrix<H,W,typename fmat_internal::promotion_trait<R1,R2>::type>
01149 operator*(const T1<H,N,R1>& a, const T2<N,W,R2>& b) {
01150 return fmat_internal::mmops<T1<H,N,R1>,T2<N,W,R2> >::multiply(a,b);
01151 }
01152
01153
01154
01155
01156
01157
01158
01159 template<template<size_t H, size_t W, typename R> class T1, template<size_t H, size_t W, typename R> class T2, size_t D, typename R1, typename R2>
01160 inline T1<D,D,R1>&
01161 operator*=(T1<D,D,R1>& a, const T2<D,D,R2>& b) {
01162 a=fmat_internal::mmops<T1<D,D,R1>,T2<D,D,R2> >::multiply(a,b);
01163 return a;
01164 }
01165
01166 template<template<size_t H, size_t W, typename R> class T2, size_t D, typename R1, typename R2>
01167 inline const SubMatrix<D,D,R1>&
01168 operator*=(const SubMatrix<D,D,R1>& a, const T2<D,D,R2>& b) {
01169 a=fmat_internal::mmops<SubMatrix<D,D,R1>,T2<D,D,R2> >::multiply(a,b);
01170 return a;
01171 }
01172
01173 template<template<size_t H, size_t W, typename R> class T1, template<size_t N, typename R> class T2, size_t H, size_t N, typename R1, typename R2>
01174 inline Column<H,typename fmat_internal::promotion_trait<R1,R2>::type>
01175 operator*(const T1<H,N,R1>& a, const T2<N,R2>& b) {
01176 return fmat_internal::mvops<T1<H,N,R1>,T2<N,R2> >::multiply(a,b);
01177 }
01178
01179 template<template<size_t W, typename R> class T1, template<size_t H, size_t W, typename R> class T2, size_t N, size_t W, typename R1, typename R2>
01180 inline Row<W,typename fmat_internal::promotion_trait<R1,R2>::type>
01181 operator*(const T1<N,R1>& a, const T2<N,W,R2>& b) {
01182 return fmat_internal::mvops<T2<N,W,R2>,T1<N,R1> >::multiply(a,b);
01183 }
01184
01185 template<template<size_t N, typename R> class T, size_t N, typename R>
01186 inline fmat::Column<N,typename fmat_internal::unconst<R>::type>
01187 abs(const T<N,R>& v) {
01188 fmat::Column<N,typename fmat_internal::unconst<R>::type> ans=fmat_internal::NoInit();
01189 for(size_t i=N; i!=0; ) {
01190 --i;
01191 ans[i]=std::abs(v[i]);
01192 }
01193 return ans;
01194 }
01195
01196 template<template<size_t H, size_t W, typename R> class T, size_t H, size_t W, typename R>
01197 inline fmat::Matrix<H,W,typename fmat_internal::unconst<R>::type>
01198 abs(const T<H,W,R>& m) {
01199 typedef typename fmat_internal::unconst<R>::type out_t;
01200 fmat::Matrix<H,W,out_t> ans=fmat_internal::NoInit();
01201 out_t* ad=&ans(0,0);
01202 const R* md=&m(0,0);
01203 for(size_t i=H*W; i!=0; ) {
01204 --i;
01205 ad[i]=std::abs(md[i]);
01206 }
01207 return ans;
01208 }
01209
01210 template<typename R> inline R atan(const Column<2,R>& v) { return std::atan2(v[1],v[0]); }
01211 template<typename R> inline R atan(const Row<2,R>& v) { return std::atan2(v[1],v[0]); }
01212 template<typename R> inline R atan(const SubVector<2,R>& v) { return std::atan2(v[1],v[0]); }
01213
01214 template<template<size_t N, typename R> class T1, template<size_t N, typename R> class T2, size_t N, typename R1, typename R2>
01215 typename fmat_internal::promotion_trait<R1,R2>::type
01216 dotProduct(const T1<N,R1>& a, const T2<N,R2>& b) {
01217 typename fmat_internal::promotion_trait<R1,R2>::type ans=0;
01218 size_t i=N;
01219 while(i--!=0)
01220 ans+=a[i]*b[i];
01221 return ans;
01222 }
01223
01224 template<class Ta, class Tb>
01225 inline typename fmat_internal::promotion_trait<typename Ta::storage_t,typename Tb::storage_t>::type
01226 dotProduct(const Ta& a, const Tb& b) {
01227 (void)sizeof(fmat_internal::CompileTimeAssert<Length_mismatch_or_non_vector,Ta::CAP==Tb::CAP && Ta::HEIGHT==Ta::CAP && Tb::HEIGHT==Tb::CAP>);
01228 typename fmat_internal::promotion_trait<typename Ta::storage_t,typename Tb::storage_t>::type ans=0;
01229 size_t i=Ta::CAP;
01230 while(i--!=0)
01231 ans+=a[i]*b[i];
01232 return ans;
01233 }
01234
01235 template<class Ta, class Tb>
01236 inline Column<3,typename fmat_internal::promotion_trait<typename Ta::storage_t,typename Tb::storage_t>::type>
01237 crossProduct(const Ta& a, const Tb& b) {
01238 return packT<typename fmat_internal::promotion_trait<typename Ta::storage_t,typename Tb::storage_t>::type>(
01239 a[1] * b[2] - a[2] * b[1],
01240 a[2] * b[0] - a[0] * b[2],
01241 a[0] * b[1] - a[1] * b[0]
01242 );
01243 }
01244
01245 template<template<size_t H, size_t W, typename R> class M, typename R>
01246 typename fmat_internal::unconst<R>::type
01247 determinant(const M<2,2,R>& m) {
01248 return m(0,0) * m(1,1) - m(0,1) * m(1,0);
01249 }
01250
01251 template<template<size_t H, size_t W, typename R> class M, typename R>
01252 typename fmat_internal::unconst<R>::type
01253 determinant(const M<3,3,R>& m) {
01254 return m(0,0) * m(1,1) * m(2,2) + m(0,1) * m(1,2) * m(2,0) + m(0,2) * m(1,0) * m(2,1)
01255 - m(0,0) * m(1,2) * m(2,1) - m(0,1) * m(1,0) * m(2,2) - m(0,2) * m(1,1) * m(2,0);
01256 }
01257
01258
01259
01260
01261 template<typename M>
01262 Matrix<M::HEIGHT,M::WIDTH,typename fmat_internal::unconst<typename M::storage_t>::type >
01263 invert(const M& m) {
01264 (void)sizeof(fmat_internal::CompileTimeAssert<NonSquare_Matrix,M::WIDTH==M::HEIGHT>);
01265 typedef typename fmat_internal::unconst<typename M::storage_t>::type R;
01266 const size_t DIM=M::HEIGHT;
01267
01268 Matrix<DIM*2,DIM,R> x(m);
01269 for(unsigned int c=0; c<DIM; ++c)
01270 x(DIM+c,c)=1;
01271
01272 for(unsigned int c=0; c<DIM; ++c) {
01273
01274 R mx=std::abs(x(c,c));
01275 unsigned int mxi=c;
01276 for(unsigned int r=c+1; r<DIM; ++r) {
01277 const R v=std::abs(x(c,r));
01278 if(v>mx) {
01279 mx=v;
01280 mxi=r;
01281 }
01282 }
01283 if(mx<std::numeric_limits<float>::epsilon())
01284 throw std::underflow_error("low rank matrix, non-invertable");
01285
01286
01287 Column<DIM*2,R> tmp = x.column(c);
01288 x.column(c) = x.column(mxi);
01289 x.column(mxi) = tmp;
01290
01291 {
01292 const R p=x(c,c);
01293 for(unsigned int c2=c+1; c2<DIM*2; ++c2)
01294 x(c2,c)/=p;
01295 x(c,c)=1;
01296 }
01297
01298 for(unsigned int r=c+1; r<DIM; ++r) {
01299 const R p = x(c,r);
01300 for(unsigned int c2=c+1; c2<DIM*2; ++c2)
01301 x(c2,r)-=x(c2,c)*p;
01302 x(c,r)=0;
01303 }
01304 }
01305 for(unsigned int c=0; c<DIM; ++c) {
01306 for(unsigned int r=0; r<c; ++r) {
01307 const R p = x(c,r);
01308 for(unsigned int c2=c+1; c2<DIM*2; ++c2)
01309 x(c2,r)-=x(c2,c)*p;
01310 x(c,r)=0;
01311 }
01312 }
01313 return SubMatrix<DIM,DIM,R>(x,DIM,0);
01314 }
01315
01316
01317 template<template<size_t H, size_t W, typename R> class T, typename R>
01318 inline R det(const T<2,2,R>& m) {
01319 return m(0,0)*m(1,1) - m(1,0)*m(0,1);
01320 }
01321
01322
01323 template<template<size_t H, size_t W, typename R> class T, typename R>
01324 inline R det(const T<3,3,R>& m) {
01325 const R cofactor0 = m(1,1)*m(2,2) - m(1,2)*m(2,1);
01326 const R cofactor1 = m(1,2)*m(2,0) - m(1,0)*m(2,2);
01327 const R cofactor2 = m(1,0)*m(2,1) - m(1,1)*m(2,0);
01328 return m(0,0)*cofactor0 + m(0,1)*cofactor1 + m(0,2)*cofactor2;
01329 }
01330
01331
01332
01333
01334 template<template<size_t N, typename R> class V1, template<size_t N, typename R> class V2, typename R1, typename R2>
01335 inline typename fmat_internal::promotion_trait<R1,R2>::type dotProduct(const V1<2,R1>& a, const V2<2,R2>& b) { return a[0]*b[0] + a[1]*b[1]; }
01336 template<template<size_t N, typename R> class V1, template<size_t N, typename R> class V2, typename R1, typename R2>
01337 inline typename fmat_internal::promotion_trait<R1,R2>::type dotProduct(const V1<3,R1>& a, const V2<3,R2>& b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
01338 template<template<size_t N, typename R> class V1, template<size_t N, typename R> class V2, typename R1, typename R2>
01339 inline typename fmat_internal::promotion_trait<R1,R2>::type dotProduct(const V1<4,R1>& a, const V2<4,R2>& b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3]; }
01340
01341 namespace fmat_internal {
01342 inline float hypot(float a, float b) ATTR_pure ATTR_always_inline;
01343 inline float hypot(float a, float b) { return ::hypotf(a,b); }
01344 inline double hypot(double a, double b) ATTR_pure ATTR_always_inline;
01345 inline double hypot(double a, double b) { return ::hypot(a,b); }
01346 #ifndef PLATFORM_APERIOS
01347 inline long double hypot(long double a, long double b) ATTR_pure ATTR_always_inline;
01348 inline long double hypot(long double a, long double b) { return ::hypotl(a,b); }
01349 #endif
01350 template<class T> T hypot(T a, T b) { return std::sqrt(a*a,b*b); }
01351 }
01352
01353 template<> inline fmatReal Column<2,fmatReal>::norm() const { return fmat_internal::hypot(data[0],data[1]); }
01354 template<> inline fmatReal Column<3,fmatReal>::norm() const { return std::sqrt(data[0]*data[0] + data[1]*data[1] + data[2]*data[2]); }
01355 template<> inline fmatReal Column<4,fmatReal>::norm() const { return std::sqrt(data[0]*data[0] + data[1]*data[1] + data[2]*data[2] + data[3]*data[3]); }
01356 template<> inline fmatReal SubVector<2,fmatReal>::norm() const { return std::sqrt(data[0]*data[0] + data[1]*data[1]); }
01357 template<> inline fmatReal SubVector<3,fmatReal>::norm() const { return std::sqrt(data[0]*data[0] + data[1]*data[1] + data[2]*data[2]); }
01358 template<> inline fmatReal SubVector<4,fmatReal>::norm() const { return std::sqrt(data[0]*data[0] + data[1]*data[1] + data[2]*data[2] + data[3]*data[3]); }
01359 template<> inline fmatReal SubVector<2,const fmatReal>::norm() const { return std::sqrt(data[0]*data[0] + data[1]*data[1]); }
01360 template<> inline fmatReal SubVector<3,const fmatReal>::norm() const { return std::sqrt(data[0]*data[0] + data[1]*data[1] + data[2]*data[2]); }
01361 template<> inline fmatReal SubVector<4,const fmatReal>::norm() const { return std::sqrt(data[0]*data[0] + data[1]*data[1] + data[2]*data[2] + data[3]*data[3]); }
01362 template<> inline fmatReal Row<2,fmatReal>::norm() const { return std::sqrt(data[0]*data[0] + data[1]*data[1]); }
01363 template<> inline fmatReal Row<3,fmatReal>::norm() const { return std::sqrt(data[0]*data[0] + data[1]*data[1] + data[2]*data[2]); }
01364 template<> inline fmatReal Row<4,fmatReal>::norm() const { return std::sqrt(data[0]*data[0] + data[1]*data[1] + data[2]*data[2] + data[3]*data[3]); }
01365
01366 template<> inline fmatReal Column<2,fmatReal>::sumSq() const { return (data[0]*data[0] + data[1]*data[1]); }
01367 template<> inline fmatReal Column<3,fmatReal>::sumSq() const { return (data[0]*data[0] + data[1]*data[1] + data[2]*data[2]); }
01368 template<> inline fmatReal Column<4,fmatReal>::sumSq() const { return (data[0]*data[0] + data[1]*data[1] + data[2]*data[2] + data[3]*data[3]); }
01369 template<> inline fmatReal SubVector<2,fmatReal>::sumSq() const { return (data[0]*data[0] + data[1]*data[1]); }
01370 template<> inline fmatReal SubVector<3,fmatReal>::sumSq() const { return (data[0]*data[0] + data[1]*data[1] + data[2]*data[2]); }
01371 template<> inline fmatReal SubVector<4,fmatReal>::sumSq() const { return (data[0]*data[0] + data[1]*data[1] + data[2]*data[2] + data[3]*data[3]); }
01372 template<> inline fmatReal SubVector<2,const fmatReal>::sumSq() const { return (data[0]*data[0] + data[1]*data[1]); }
01373 template<> inline fmatReal SubVector<3,const fmatReal>::sumSq() const { return (data[0]*data[0] + data[1]*data[1] + data[2]*data[2]); }
01374 template<> inline fmatReal SubVector<4,const fmatReal>::sumSq() const { return (data[0]*data[0] + data[1]*data[1] + data[2]*data[2] + data[3]*data[3]); }
01375 template<> inline fmatReal Row<2,fmatReal>::sumSq() const { return (data[0]*data[0] + data[1]*data[1]); }
01376 template<> inline fmatReal Row<3,fmatReal>::sumSq() const { return (data[0]*data[0] + data[1]*data[1] + data[2]*data[2]); }
01377 template<> inline fmatReal Row<4,fmatReal>::sumSq() const { return (data[0]*data[0] + data[1]*data[1] + data[2]*data[2] + data[3]*data[3]); }
01378
01379
01380 template<> inline Column<2,fmatReal>& Column<2,fmatReal>::operator+=(const SubVector<2,fmatReal>& x) { data[0]+=x.data[0]; data[1]+=x.data[1]; return *this; }
01381 template<> inline Column<3,fmatReal>& Column<3,fmatReal>::operator+=(const SubVector<3,fmatReal>& x) { data[0]+=x.data[0]; data[1]+=x.data[1]; data[2]+=x.data[2]; return *this; }
01382 template<> inline Column<4,fmatReal>& Column<4,fmatReal>::operator+=(const SubVector<4,fmatReal>& x) { data[0]+=x.data[0]; data[1]+=x.data[1]; data[2]+=x.data[2]; data[3]+=x.data[3]; return *this; }
01383 template<> inline Matrix<2,1,fmatReal>& Matrix<2,1,fmatReal>::operator+=(const Matrix<2,1,fmatReal>& x) { data[0]+=x.data[0]; data[1]+=x.data[1]; return *this; }
01384 template<> inline Matrix<3,1,fmatReal>& Matrix<3,1,fmatReal>::operator+=(const Matrix<3,1,fmatReal>& x) { data[0]+=x.data[0]; data[1]+=x.data[1]; data[2]+=x.data[2]; return *this; }
01385 template<> inline Matrix<4,1,fmatReal>& Matrix<4,1,fmatReal>::operator+=(const Matrix<4,1,fmatReal>& x) { data[0]+=x.data[0]; data[1]+=x.data[1]; data[2]+=x.data[2]; data[3]+=x.data[3]; return *this; }
01386 template<> inline Row<2,fmatReal>& Row<2,fmatReal>::operator+=(const SubVector<2,fmatReal>& x) { data[0]+=x.data[0]; data[1]+=x.data[1]; return *this; }
01387 template<> inline Row<3,fmatReal>& Row<3,fmatReal>::operator+=(const SubVector<3,fmatReal>& x) { data[0]+=x.data[0]; data[1]+=x.data[1]; data[2]+=x.data[2]; return *this; }
01388 template<> inline Row<4,fmatReal>& Row<4,fmatReal>::operator+=(const SubVector<4,fmatReal>& x) { data[0]+=x.data[0]; data[1]+=x.data[1]; data[2]+=x.data[2]; data[3]+=x.data[3]; return *this; }
01389
01390 template<> inline Column<2,fmatReal>& Column<2,fmatReal>::operator-=(const SubVector<2,fmatReal>& x) { data[0]-=x.data[0]; data[1]-=x.data[1]; return *this; }
01391 template<> inline Column<3,fmatReal>& Column<3,fmatReal>::operator-=(const SubVector<3,fmatReal>& x) { data[0]-=x.data[0]; data[1]-=x.data[1]; data[2]-=x.data[2]; return *this; }
01392 template<> inline Column<4,fmatReal>& Column<4,fmatReal>::operator-=(const SubVector<4,fmatReal>& x) { data[0]-=x.data[0]; data[1]-=x.data[1]; data[2]-=x.data[2]; data[3]-=x.data[3]; return *this; }
01393 template<> inline Matrix<2,1,fmatReal>& Matrix<2,1,fmatReal>::operator-=(const Matrix<2,1,fmatReal>& x) { data[0]-=x.data[0]; data[1]-=x.data[1]; return *this; }
01394 template<> inline Matrix<3,1,fmatReal>& Matrix<3,1,fmatReal>::operator-=(const Matrix<3,1,fmatReal>& x) { data[0]-=x.data[0]; data[1]-=x.data[1]; data[2]-=x.data[2]; return *this; }
01395 template<> inline Matrix<4,1,fmatReal>& Matrix<4,1,fmatReal>::operator-=(const Matrix<4,1,fmatReal>& x) { data[0]-=x.data[0]; data[1]-=x.data[1]; data[2]-=x.data[2]; data[3]-=x.data[3]; return *this; }
01396 template<> inline Row<2,fmatReal>& Row<2,fmatReal>::operator-=(const SubVector<2,fmatReal>& x) { data[0]-=x.data[0]; data[1]-=x.data[1]; return *this; }
01397 template<> inline Row<3,fmatReal>& Row<3,fmatReal>::operator-=(const SubVector<3,fmatReal>& x) { data[0]-=x.data[0]; data[1]-=x.data[1]; data[2]-=x.data[2]; return *this; }
01398 template<> inline Row<4,fmatReal>& Row<4,fmatReal>::operator-=(const SubVector<4,fmatReal>& x) { data[0]-=x.data[0]; data[1]-=x.data[1]; data[2]-=x.data[2]; data[3]-=x.data[3]; return *this; }
01399
01400 template<> inline const SubVector<2,fmatReal>& SubVector<2,fmatReal>::operator*=(fmatReal x) const { data[0]*=x; data[1]*=x; return *this; }
01401 template<> inline const SubVector<3,fmatReal>& SubVector<3,fmatReal>::operator*=(fmatReal x) const { data[0]*=x; data[1]*=x; data[2]*=x; return *this; }
01402 template<> inline const SubVector<4,fmatReal>& SubVector<4,fmatReal>::operator*=(fmatReal x) const { data[0]*=x; data[1]*=x; data[2]*=x; data[3]*=x; return *this; }
01403 template<> inline Matrix<2,1,fmatReal>& Matrix<2,1,fmatReal>::operator*=(fmatReal x) { data[0]*=x; data[1]*=x; return *this; }
01404 template<> inline Matrix<3,1,fmatReal>& Matrix<3,1,fmatReal>::operator*=(fmatReal x) { data[0]*=x; data[1]*=x; data[2]*=x; return *this; }
01405 template<> inline Matrix<4,1,fmatReal>& Matrix<4,1,fmatReal>::operator*=(fmatReal x) { data[0]*=x; data[1]*=x; data[2]*=x; data[3]*=x; return *this; }
01406 template<> inline Column<2,fmatReal>& Column<2,fmatReal>::operator*=(fmatReal x) { data[0]*=x; data[1]*=x; return *this; }
01407 template<> inline Column<3,fmatReal>& Column<3,fmatReal>::operator*=(fmatReal x) { data[0]*=x; data[1]*=x; data[2]*=x; return *this; }
01408 template<> inline Column<4,fmatReal>& Column<4,fmatReal>::operator*=(fmatReal x) { data[0]*=x; data[1]*=x; data[2]*=x; data[3]*=x; return *this; }
01409 template<> inline Row<2,fmatReal>& Row<2,fmatReal>::operator*=(fmatReal x) { data[0]*=x; data[1]*=x; return *this; }
01410 template<> inline Row<3,fmatReal>& Row<3,fmatReal>::operator*=(fmatReal x) { data[0]*=x; data[1]*=x; data[2]*=x; return *this; }
01411 template<> inline Row<4,fmatReal>& Row<4,fmatReal>::operator*=(fmatReal x) { data[0]*=x; data[1]*=x; data[2]*=x; data[3]*=x; return *this; }
01412
01413 template<> inline const SubVector<2,fmatReal>& SubVector<2,fmatReal>::operator/=(fmatReal x) const { x=1/x; data[0]*=x; data[1]*=x; return *this; }
01414 template<> inline const SubVector<3,fmatReal>& SubVector<3,fmatReal>::operator/=(fmatReal x) const { x=1/x; data[0]*=x; data[1]*=x; data[2]*=x; return *this; }
01415 template<> inline const SubVector<4,fmatReal>& SubVector<4,fmatReal>::operator/=(fmatReal x) const { x=1/x; data[0]*=x; data[1]*=x; data[2]*=x; data[3]*=x; return *this; }
01416 template<> inline Matrix<2,1,fmatReal>& Matrix<2,1,fmatReal>::operator/=(fmatReal x) { x=1/x; data[0]*=x; data[1]*=x; return *this; }
01417 template<> inline Matrix<3,1,fmatReal>& Matrix<3,1,fmatReal>::operator/=(fmatReal x) { x=1/x; data[0]*=x; data[1]*=x; data[2]*=x; return *this; }
01418 template<> inline Matrix<4,1,fmatReal>& Matrix<4,1,fmatReal>::operator/=(fmatReal x) { x=1/x; data[0]*=x; data[1]*=x; data[2]*=x; data[3]*=x; return *this; }
01419 template<> inline Column<2,fmatReal>& Column<2,fmatReal>::operator/=(fmatReal x) { x=1/x; data[0]*=x; data[1]*=x; return *this; }
01420 template<> inline Column<3,fmatReal>& Column<3,fmatReal>::operator/=(fmatReal x) { x=1/x; data[0]*=x; data[1]*=x; data[2]*=x; return *this; }
01421 template<> inline Column<4,fmatReal>& Column<4,fmatReal>::operator/=(fmatReal x) { x=1/x; data[0]*=x; data[1]*=x; data[2]*=x; data[3]*=x; return *this; }
01422 template<> inline Row<2,fmatReal>& Row<2,fmatReal>::operator/=(fmatReal x) { x=1/x; data[0]*=x; data[1]*=x; return *this; }
01423 template<> inline Row<3,fmatReal>& Row<3,fmatReal>::operator/=(fmatReal x) { x=1/x; data[0]*=x; data[1]*=x; data[2]*=x; return *this; }
01424 template<> inline Row<4,fmatReal>& Row<4,fmatReal>::operator/=(fmatReal x) { x=1/x; data[0]*=x; data[1]*=x; data[2]*=x; data[3]*=x; return *this; }
01425
01426 namespace fmat_internal {
01427
01428 template<template<size_t H, size_t W, typename R> class T1, template<size_t N, typename R> class T2, typename R1, typename R2>
01429 struct mvops<T1<2,2,R1>,T2<2,R2> > {
01430 typedef typename fmat_internal::promotion_trait<R1,R2>::type R;
01431 inline static Column<2,R> multiply(const T1<2,2,R1>& ma, const T2<2,R2>& b) {
01432 Column<2,R> ans=fmat_internal::NoInit();
01433 const R1 *a=&ma(0,0);
01434 ans[0] = a[0*2+0]*b[0] + a[1*2+0]*b[1];
01435 ans[1] = a[0*2+1]*b[0] + a[1*2+1]*b[1];
01436 return ans;
01437 }
01438 inline static Row<2,R> multiply(const T2<2,R2>& b, const T1<2,2,R1>& ma) {
01439 Row<2,R> ans=fmat_internal::NoInit();
01440 const R1 *a=&ma(0,0);
01441 ans[0] = a[0*2+0]*b[0] + a[0*2+1]*b[1];
01442 ans[1] = a[1*2+0]*b[0] + a[1*2+1]*b[1];
01443 return ans;
01444 }
01445 };
01446 template<template<size_t H, size_t W, typename R> class T1, template<size_t N, typename R> class T2, typename R1, typename R2>
01447 struct mvops<T1<3,3,R1>,T2<3,R2> > {
01448 typedef typename fmat_internal::promotion_trait<R1,R2>::type R;
01449 inline static Column<3,R> multiply(const T1<3,3,R1>& ma, const T2<3,R2>& b) {
01450 Column<3,R> ans=fmat_internal::NoInit();
01451 const R *a=&ma(0,0);
01452 ans[0] = a[0*3+0]*b[0] + a[1*3+0]*b[1] + a[2*3+0]*b[2];
01453 ans[1] = a[0*3+1]*b[0] + a[1*3+1]*b[1] + a[2*3+1]*b[2];
01454 ans[2] = a[0*3+2]*b[0] + a[1*3+2]*b[1] + a[2*3+2]*b[2];
01455 return ans;
01456 }
01457 inline static Row<3,R> multiply(const T2<3,R2>& b, const T1<3,3,R1>& ma) {
01458 Row<3,R> ans=fmat_internal::NoInit();
01459 const R *a=&ma(0,0);
01460 ans[0] = a[0*3+0]*b[0] + a[0*3+1]*b[1] + a[0*3+2]*b[2];
01461 ans[1] = a[1*3+0]*b[0] + a[1*3+1]*b[1] + a[1*3+2]*b[2];
01462 ans[2] = a[2*3+0]*b[0] + a[2*3+1]*b[1] + a[2*3+2]*b[2];
01463 return ans;
01464 }
01465 };
01466 template<template<size_t H, size_t W, typename R> class T1, template<size_t N, typename R> class T2, typename R1, typename R2>
01467 struct mvops<T1<4,4,R1>,T2<4,R2> > {
01468 typedef typename fmat_internal::promotion_trait<R1,R2>::type R;
01469 inline static Column<4,R> multiply(const T1<4,4,R1>& ma, const T2<4,R2>& b) {
01470 Column<4,R> ans=fmat_internal::NoInit();
01471 const R *a=&ma(0,0);
01472 ans[0] = a[0*4+0]*b[0] + a[1*4+0]*b[1] + a[2*4+0]*b[2] + a[3*4+0]*b[3];
01473 ans[1] = a[0*4+1]*b[0] + a[1*4+1]*b[1] + a[2*4+1]*b[2] + a[3*4+1]*b[3];
01474 ans[2] = a[0*4+2]*b[0] + a[1*4+2]*b[1] + a[2*4+2]*b[2] + a[3*4+2]*b[3];
01475 ans[3] = a[0*4+3]*b[0] + a[1*4+3]*b[1] + a[2*4+3]*b[2] + a[3*4+3]*b[3];
01476 return ans;
01477 }
01478 inline static Row<4,R> multiply(const T2<4,R2>& b, const T1<4,4,R1>& ma) {
01479 Row<4,R> ans=fmat_internal::NoInit();
01480 const R *a=&ma(0,0);
01481 ans[0] = a[0*4+0]*b[0] + a[0*4+1]*b[1] + a[0*4+2]*b[2] + a[0*4+3]*b[3];
01482 ans[1] = a[1*4+0]*b[0] + a[1*4+1]*b[1] + a[1*4+2]*b[2] + a[1*4+3]*b[3];
01483 ans[2] = a[2*4+0]*b[0] + a[2*4+1]*b[1] + a[2*4+2]*b[2] + a[2*4+3]*b[3];
01484 ans[3] = a[3*4+0]*b[0] + a[3*4+1]*b[1] + a[3*4+2]*b[2] + a[3*4+3]*b[3];
01485 return ans;
01486 }
01487 };
01488
01489 template<template<size_t H, size_t W, typename R> class T1, template<size_t H, size_t W, typename R> class T2, typename R1, typename R2>
01490 struct mmops<T1<2,2,R1>,T2<2,2,R2> > {
01491 typedef typename fmat_internal::promotion_trait<R1,R2>::type R;
01492 inline static Matrix<2,2,R> multiply(const T1<2,2,R1>& ma, const T2<2,2,R2>& mb) {
01493 Matrix<2,2,R> mans=fmat_internal::NoInit();
01494 R *ans=&mans(0,0);
01495 const R1 *a=&ma(0,0);
01496 const R2 *b=&mb(0,0);
01497 ans[0+2*0] = a[0+2*0]*b[0+2*0] + a[0+2*1]*b[1+2*0];
01498 ans[1+2*0] = a[1+2*0]*b[0+2*0] + a[1+2*1]*b[1+2*0];
01499 ans[0+2*1] = a[0+2*0]*b[0+2*1] + a[0+2*1]*b[1+2*1];
01500 ans[1+2*1] = a[1+2*0]*b[0+2*1] + a[1+2*1]*b[1+2*1];
01501 return mans;
01502 }
01503 };
01504 template<template<size_t H, size_t W, typename R> class T1, template<size_t H, size_t W, typename R> class T2, typename R1, typename R2>
01505 struct mmops<T1<3,3,R1>,T2<3,3,R2> > {
01506 typedef typename fmat_internal::promotion_trait<R1,R2>::type R;
01507 inline static Matrix<3,3,R> multiply(const T1<3,3,R1>& ma, const T2<3,3,R2>& mb) {
01508 Matrix<3,3,R> mans=fmat_internal::NoInit();
01509 R *ans=&mans(0,0);
01510 const R1 *a=&ma(0,0);
01511 const R2 *b=&mb(0,0);
01512 ans[0+3*0] = a[0+3*0]*b[0+3*0] + a[0+3*1]*b[1+3*0] + a[0+3*2]*b[2+3*0];
01513 ans[1+3*0] = a[1+3*0]*b[0+3*0] + a[1+3*1]*b[1+3*0] + a[1+3*2]*b[2+3*0];
01514 ans[2+3*0] = a[2+3*0]*b[0+3*0] + a[2+3*1]*b[1+3*0] + a[2+3*2]*b[2+3*0];
01515 ans[0+3*1] = a[0+3*0]*b[0+3*1] + a[0+3*1]*b[1+3*1] + a[0+3*2]*b[2+3*1];
01516 ans[1+3*1] = a[1+3*0]*b[0+3*1] + a[1+3*1]*b[1+3*1] + a[1+3*2]*b[2+3*1];
01517 ans[2+3*1] = a[2+3*0]*b[0+3*1] + a[2+3*1]*b[1+3*1] + a[2+3*2]*b[2+3*1];
01518 ans[0+3*2] = a[0+3*0]*b[0+3*2] + a[0+3*1]*b[1+3*2] + a[0+3*2]*b[2+3*2];
01519 ans[1+3*2] = a[1+3*0]*b[0+3*2] + a[1+3*1]*b[1+3*2] + a[1+3*2]*b[2+3*2];
01520 ans[2+3*2] = a[2+3*0]*b[0+3*2] + a[2+3*1]*b[1+3*2] + a[2+3*2]*b[2+3*2];
01521 return mans;
01522 }
01523 };
01524 template<template<size_t H, size_t W, typename R> class T1, template<size_t H, size_t W, typename R> class T2, typename R1, typename R2>
01525 struct mmops<T1<4,4,R1>,T2<4,4,R2> > {
01526 typedef typename fmat_internal::promotion_trait<R1,R2>::type R;
01527 inline static Matrix<4,4,R> multiply(const T1<4,4,R1>& ma, const T2<4,4,R2>& mb) {
01528 Matrix<4,4,R> mans=fmat_internal::NoInit();
01529 R *ans=&mans(0,0);
01530 const R1 *a=&ma(0,0);
01531 const R2 *b=&mb(0,0);
01532 ans[0+4*0] = a[0+4*0]*b[0+4*0] + a[0+4*1]*b[1+4*0] + a[0+4*2]*b[2+4*0] + a[0+4*3]*b[3+4*0];
01533 ans[1+4*0] = a[1+4*0]*b[0+4*0] + a[1+4*1]*b[1+4*0] + a[1+4*2]*b[2+4*0] + a[1+4*3]*b[3+4*0];
01534 ans[2+4*0] = a[2+4*0]*b[0+4*0] + a[2+4*1]*b[1+4*0] + a[2+4*2]*b[2+4*0] + a[2+4*3]*b[3+4*0];
01535 ans[3+4*0] = a[3+4*0]*b[0+4*0] + a[3+4*1]*b[1+4*0] + a[3+4*2]*b[2+4*0] + a[3+4*3]*b[3+4*0];
01536 ans[0+4*1] = a[0+4*0]*b[0+4*1] + a[0+4*1]*b[1+4*1] + a[0+4*2]*b[2+4*1] + a[0+4*3]*b[3+4*1];
01537 ans[1+4*1] = a[1+4*0]*b[0+4*1] + a[1+4*1]*b[1+4*1] + a[1+4*2]*b[2+4*1] + a[1+4*3]*b[3+4*1];
01538 ans[2+4*1] = a[2+4*0]*b[0+4*1] + a[2+4*1]*b[1+4*1] + a[2+4*2]*b[2+4*1] + a[2+4*3]*b[3+4*1];
01539 ans[3+4*1] = a[3+4*0]*b[0+4*1] + a[3+4*1]*b[1+4*1] + a[3+4*2]*b[2+4*1] + a[3+4*3]*b[3+4*1];
01540 ans[0+4*2] = a[0+4*0]*b[0+4*2] + a[0+4*1]*b[1+4*2] + a[0+4*2]*b[2+4*2] + a[0+4*3]*b[3+4*2];
01541 ans[1+4*2] = a[1+4*0]*b[0+4*2] + a[1+4*1]*b[1+4*2] + a[1+4*2]*b[2+4*2] + a[1+4*3]*b[3+4*2];
01542 ans[2+4*2] = a[2+4*0]*b[0+4*2] + a[2+4*1]*b[1+4*2] + a[2+4*2]*b[2+4*2] + a[2+4*3]*b[3+4*2];
01543 ans[3+4*2] = a[3+4*0]*b[0+4*2] + a[3+4*1]*b[1+4*2] + a[3+4*2]*b[2+4*2] + a[3+4*3]*b[3+4*2];
01544 ans[0+4*3] = a[0+4*0]*b[0+4*3] + a[0+4*1]*b[1+4*3] + a[0+4*2]*b[2+4*3] + a[0+4*3]*b[3+4*3];
01545 ans[1+4*3] = a[1+4*0]*b[0+4*3] + a[1+4*1]*b[1+4*3] + a[1+4*2]*b[2+4*3] + a[1+4*3]*b[3+4*3];
01546 ans[2+4*3] = a[2+4*0]*b[0+4*3] + a[2+4*1]*b[1+4*3] + a[2+4*2]*b[2+4*3] + a[2+4*3]*b[3+4*3];
01547 ans[3+4*3] = a[3+4*0]*b[0+4*3] + a[3+4*1]*b[1+4*3] + a[3+4*2]*b[2+4*3] + a[3+4*3]*b[3+4*3];
01548 return mans;
01549 }
01550 };
01551 }
01552
01553 extern template class SubVector<3,fmatReal>;
01554 extern template class Column<3,fmatReal>;
01555 extern template class SubMatrix<3,3,fmatReal>;
01556 extern template class Matrix<3,4,fmatReal>;
01557
01558 }
01559
01560 #endif
01561
01562
01563
01564
01565