MAV'RIC
/home/travis/build/lis-epfl/MAVRIC_Library/util/matrix.hxx
00001 /*******************************************************************************
00002  * Copyright (c) 2009-2016, MAV'RIC Development Team
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright notice,
00009  * this list of conditions and the following disclaimer.
00010  *
00011  * 2. Redistributions in binary form must reproduce the above copyright notice,
00012  * this list of conditions and the following disclaimer in the documentation
00013  * and/or other materials provided with the distribution.
00014  *
00015  * 3. Neither the name of the copyright holder nor the names of its contributors
00016  * may be used to endorse or promote products derived from this software without
00017  * specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00020  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00023  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00024  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00025  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00026  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00027  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00028  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00029  * POSSIBILITY OF SUCH DAMAGE.
00030  ******************************************************************************/
00031 
00032 /*******************************************************************************
00033  * \file    matrix.hxx
00034  *
00035  * \author  MAV'RIC Team
00036  * \author  Julien Lecoeur
00037  *
00038  * \brief   Templated matrix library
00039  *
00040  ******************************************************************************/
00041 
00042 
00043 #ifndef MATRIX_HXX__
00044 #define MATRIX_HXX__
00045 
00046 
00047 template<uint32_t N, uint32_t P, typename T>
00048 Mat<N,P,T>::Mat(T value, bool diag)
00049 {
00050     if (diag == false)
00051     {
00052         for (uint32_t i = 0; i < N*P; ++i)
00053         {
00054             d[i] = value;
00055         }
00056     }
00057     else
00058     {
00059         for (uint32_t i = 0; i < N; ++i)
00060         {
00061             for (uint32_t j = 0; j < P; ++j)
00062             {
00063                 uint32_t index = i*P + j;
00064                 if (i==j)
00065                 {
00066                     d[index] = value;
00067                 }
00068                 else
00069                 {
00070                     d[index] = 0.0f;
00071                 }
00072             }
00073         }
00074     }
00075 }
00076 
00077 
00078 template<uint32_t N, uint32_t P, typename T>
00079 Mat<N,P,T>::Mat(const Mat<N,P>& mat)
00080 {
00081     for (uint32_t i = 0; i < N*P; ++i)
00082     {
00083         d[i] = mat.d[i];
00084     }
00085 }
00086 
00087 
00088 template<uint32_t N, uint32_t P, typename T>
00089 Mat<N,P,T>::Mat(const std::array<T,N*P> arr)
00090 {
00091     for (uint32_t i = 0; i < N*P; ++i)
00092     {
00093         d[i] = arr[i];
00094     }
00095 }
00096 
00097 
00098 template<uint32_t N, uint32_t P, typename T>
00099 Mat<N,P,T>::Mat(const std::initializer_list<T> list)
00100 {
00101     Mat();
00102 
00103     uint32_t size = list.size();
00104     if(size > 0)
00105     {
00106         if (size > N*P)
00107         {
00108             size = N*P;
00109         }
00110 
00111         const T* it = list.begin();
00112 
00113         for (uint32_t i = 0; i < size; ++i)
00114         {
00115             d[i] = *it;
00116             ++it;
00117         }
00118     }
00119 }
00120 
00121 
00122 template<uint32_t N, uint32_t P, typename T>
00123 uint32_t Mat<N,P,T>::rows(void)
00124 {
00125     return N;
00126 }
00127 
00128 
00129 template<uint32_t N, uint32_t P, typename T>
00130 uint32_t Mat<N,P,T>::cols(void)
00131 {
00132     return P;
00133 }
00134 
00135 
00136 template<uint32_t N, uint32_t P, typename T>
00137 uint32_t Mat<N,P,T>::index(uint32_t i, uint32_t j)
00138 {
00139     return i * P + j;
00140 }
00141 
00142 
00143 template<uint32_t N, uint32_t P, typename T>
00144 const T& Mat<N,P,T>::operator()(const uint32_t& i, const uint32_t& j) const
00145 {
00146     if (i < N && j < P)
00147     {
00148         return d[i * P + j];
00149     }
00150     else
00151     {
00152         return d[0];
00153     }
00154 }
00155 
00156 
00157 template<uint32_t N, uint32_t P, typename T>
00158 T& Mat<N,P,T>::operator()(const uint32_t& i, const uint32_t& j)
00159 {
00160     if (i < N && j < P)
00161     {
00162         return d[i * P + j];
00163     }
00164     else
00165     {
00166         return d[0];
00167     }
00168 }
00169 
00170 
00171 template<uint32_t N, uint32_t P, typename T>
00172 const T& Mat<N,P,T>::operator[](const uint32_t& index) const
00173 {
00174     if (index < N * P)
00175     {
00176         return d[index];
00177     }
00178     else
00179     {
00180         return d[0];
00181     }
00182 }
00183 
00184 
00185 template<uint32_t N, uint32_t P, typename T>
00186 T& Mat<N,P,T>::operator[](const uint32_t& index)
00187 {
00188     if (index < N * P)
00189     {
00190         return d[index];
00191     }
00192     else
00193     {
00194         return d[0];
00195     }
00196 }
00197 
00198 
00199 template<uint32_t N, uint32_t P, typename T>
00200 Mat<N,P,T> Mat<N,P,T>::add(const Mat& m) const
00201 {
00202     Mat res;
00203     mat::op::add(*this, m, res);
00204     return res;
00205 }
00206 
00207 
00208 template<uint32_t N, uint32_t P, typename T>
00209 Mat<N,P,T> Mat<N,P,T>::add(const T value) const
00210 {
00211     Mat res;
00212     mat::op::add(*this, value, res);
00213     return res;
00214 }
00215 
00216 
00217 template<uint32_t N, uint32_t P, typename T>
00218 Mat<N,P,T> Mat<N,P,T>::operator+(const Mat& m) const
00219 {
00220     return add(m);
00221 }
00222 
00223 
00224 template<uint32_t N, uint32_t P, typename T>
00225 Mat<N,P,T> Mat<N,P,T>::operator+(T value) const
00226 {
00227     Mat res = add(value);
00228     return res;
00229 }
00230 
00231 
00232 template<uint32_t N, uint32_t P, typename T>
00233 Mat<N,P,T> operator+(const T value, const Mat<N,P,T>& m)
00234 {
00235     return m.add(value);
00236 }
00237 
00238 
00239 template<uint32_t N, uint32_t P, typename T>
00240 void Mat<N,P,T>::add_inplace(const Mat& m)
00241 {
00242     mat::op::add(*this, m, *this);
00243 }
00244 
00245 
00246 template<uint32_t N, uint32_t P, typename T>
00247 void Mat<N,P,T>::add_inplace(const T value)
00248 {
00249     mat::op::add(*this, value, *this);
00250 }
00251 
00252 
00253 template<uint32_t N, uint32_t P, typename T>
00254 void Mat<N,P,T>::operator+=(const Mat& m)
00255 {
00256     add_inplace(m);
00257 }
00258 
00259 
00260 template<uint32_t N, uint32_t P, typename T>
00261 void Mat<N,P,T>::operator+=(const T value)
00262 {
00263     add_inplace(value);
00264 }
00265 
00266 
00267 template<uint32_t N, uint32_t P, typename T>
00268 Mat<N,P,T> Mat<N,P,T>::subtract(const Mat& m) const
00269 {
00270     Mat res;
00271     mat::op::subtract(*this, m, res);
00272     return res;
00273 }
00274 
00275 
00276 template<uint32_t N, uint32_t P, typename T>
00277 Mat<N,P,T> Mat<N,P,T>::subtract(const T value) const
00278 {
00279     Mat res;
00280     mat::op::subtract(*this, value, res);
00281     return res;
00282 }
00283 
00284 
00285 template<uint32_t N, uint32_t P, typename T>
00286 Mat<N,P,T> Mat<N,P,T>::operator-(const Mat& m) const
00287 {
00288     return subtract(m);
00289 }
00290 
00291 
00292 template<uint32_t N, uint32_t P, typename T>
00293 Mat<N,P,T> Mat<N,P,T>::operator-(const T value) const
00294 {
00295     return subtract(value);
00296 }
00297 
00298 
00299 template<uint32_t N, uint32_t P, typename T>
00300 Mat<N,P,T> operator-(const T value, const Mat<N,P,T>& m)
00301 {
00302     Mat<N,P,T> m1(value);
00303     return m1.subtract(m);
00304 }
00305 
00306 
00307 template<uint32_t N, uint32_t P, typename T>
00308 void Mat<N,P,T>::subtract_inplace(const Mat& m)
00309 {
00310     mat::op::subtract(*this, m, *this);
00311 }
00312 
00313 
00314 template<uint32_t N, uint32_t P, typename T>
00315 void Mat<N,P,T>::subtract_inplace(const T value)
00316 {
00317     mat::op::subtract(*this, value, *this);
00318 }
00319 
00320 
00321 template<uint32_t N, uint32_t P, typename T>
00322 void Mat<N,P,T>::operator-=(const Mat& m)
00323 {
00324     subtract_inplace(m);
00325 }
00326 
00327 
00328 template<uint32_t N, uint32_t P, typename T>
00329 void Mat<N,P,T>::operator-=(const T value)
00330 {
00331     subtract_inplace(value);
00332 }
00333 
00334 
00335 template<uint32_t N, uint32_t P, typename T>
00336 Mat<N,P,T> Mat<N,P,T>::multiply(const Mat& m) const
00337 {
00338     Mat res;
00339     mat::op::multiply(*this, m, res);
00340     return res;
00341 }
00342 
00343 
00344 template<uint32_t N, uint32_t P, typename T>
00345 Mat<N,P,T> Mat<N,P,T>::multiply(const T value) const
00346 {
00347     Mat res;
00348     mat::op::multiply(*this, value, res);
00349     return res;
00350 }
00351 
00352 
00353 template<uint32_t N, uint32_t P, typename T>
00354 Mat<N,P,T> Mat<N,P,T>::operator*(const Mat& m) const
00355 {
00356     return multiply(m);
00357 }
00358 
00359 
00360 template<uint32_t N, uint32_t P, typename T>
00361 Mat<N,P,T> Mat<N,P,T>::operator*(const T value) const
00362 {
00363     return multiply(value);
00364 }
00365 
00366 
00367 template<uint32_t N, uint32_t P, typename T>
00368 Mat<N,P,T> operator*(const T value, const Mat<N,P,T>& m)
00369 {
00370     return m.multiply(value);
00371 }
00372 
00373 
00374 template<uint32_t N, uint32_t P, typename T>
00375 void Mat<N,P,T>::multiply_inplace(const Mat& m)
00376 {
00377     mat::op::multiply(*this, m, *this);
00378 }
00379 
00380 
00381 template<uint32_t N, uint32_t P, typename T>
00382 void Mat<N,P,T>::multiply_inplace(const T value)
00383 {
00384     mat::op::multiply(*this, value, *this);
00385 }
00386 
00387 
00388 template<uint32_t N, uint32_t P, typename T>
00389 void Mat<N,P,T>::operator*=(const Mat& m)
00390 {
00391     multiply_inplace(m);
00392 };
00393 
00394 
00395 template<uint32_t N, uint32_t P, typename T>
00396 void Mat<N,P,T>::operator*=(const T value)
00397 {
00398     multiply_inplace(value);
00399 };
00400 
00401 
00402 template<uint32_t N, uint32_t P, typename T>
00403 Mat<P,N,T> Mat<N,P,T>::transpose(void) const
00404 {
00405     Mat<P,N,T> res;
00406     mat::op::transpose(*this, res);
00407     return res;
00408 };
00409 
00410 
00411 template<uint32_t N, uint32_t P, typename T>
00412 Mat<P,N,T> Mat<N,P,T>::operator~(void) const
00413 {
00414     return transpose();
00415 };
00416 
00417 
00418 template<uint32_t N, uint32_t P, typename T>
00419 Mat<N,P,T> Mat<N,P,T>::inverse(bool& success) const
00420 {
00421     Mat<N,N,T> res;
00422     success = mat::op::inverse(*this, res);
00423     return res;
00424 }
00425 
00426 
00427 template<uint32_t N, uint32_t P, typename T>
00428 Mat<N,P,T> Mat<N,P,T>::inv(bool& success) const
00429 {
00430     return inverse(success);
00431 }
00432 
00433 
00434 template<uint32_t N, uint32_t P,  typename T>
00435 template<uint32_t I, uint32_t J, uint32_t Q, uint32_t R>
00436 Mat<N,P,T> Mat<N,P,T>::insert(const Mat<Q,R,T>& m) const
00437 {
00438     Mat<N,P,T> res;
00439     mat::op::insert<N, P, I, J, Q, R, T>(*this, m, res);
00440     // mat::op::insert<I, J>(*this, m, res);
00441     return res;
00442 }
00443 
00444 
00445 template<uint32_t N, uint32_t P, typename T>
00446 template<uint32_t I, uint32_t J, uint32_t Q, uint32_t R>
00447 bool Mat<N,P,T>::insert_inplace(const Mat<Q,R,T>& m)
00448 {
00449     return mat::op::insert_inplace<N, P, I, J, Q, R, T>(*this, m);
00450 }
00451 
00452 
00453 template<uint32_t N, uint32_t P, typename T>
00454 void Mat<N,P,T>::clip(const Mat& min, const Mat& max)
00455 {
00456     mat::op::clip<N, P, T>(*this, min, max);
00457 }
00458 
00459 
00460 template<uint32_t N, uint32_t P, typename T>
00461 void Mat<N,P,T>::clip(float min, float max)
00462 {
00463     mat::op::clip<N, P, T>(*this, min, max);
00464 }
00465 
00466 
00467 namespace mat
00468 {
00469 
00470 template<uint32_t N, uint32_t P, typename T>
00471 void op::add(const Mat<N,P,T>& m1, const Mat<N,P,T>& m2, Mat<N,P,T>& res)
00472 {
00473     for (uint32_t i = 0; i < N*P; ++i)
00474     {
00475         res.d[i] = m1.d[i] + m2.d[i];
00476     }
00477 }
00478 
00479 
00480 template<uint32_t N, uint32_t P, typename T>
00481 void op::add(const Mat<N,P,T>& m1, const T value, Mat<N,P,T>& res)
00482 {
00483     for (uint32_t i = 0; i < N*P; ++i)
00484     {
00485         res.d[i] = m1.d[i] + value;
00486     }
00487 }
00488 
00489 
00490 template<uint32_t N, uint32_t P, typename T>
00491 void op::subtract(const Mat<N,P,T>& m1, const Mat<N,P,T>& m2, Mat<N,P,T>& res)
00492 {
00493     for (uint32_t i = 0; i < N*P; ++i)
00494     {
00495         res.d[i] = m1.d[i] - m2.d[i];
00496     }
00497 }
00498 
00499 
00500 template<uint32_t N, uint32_t P, typename T>
00501 void op::subtract(const Mat<N,P,T>& m1, const T value, Mat<N,P,T>& res)
00502 {
00503     for (uint32_t i = 0; i < N*P; ++i)
00504     {
00505         res.d[i] = m1.d[i] - value;
00506     }
00507 }
00508 
00509 
00510 template<uint32_t N, uint32_t P, typename T>
00511 void op::multiply(const Mat<N,P,T>& m1, const Mat<N,P,T>& m2, Mat<N,P,T>& res)
00512 {
00513     for (uint32_t i = 0; i < N*P; ++i)
00514     {
00515         res.d[i] = m1.d[i] * m2.d[i];
00516     }
00517 }
00518 
00519 
00520 template<uint32_t N, uint32_t P, typename T>
00521 void op::multiply(const Mat<N,P,T>& m1, const T value, Mat<N,P,T>& res)
00522 {
00523     for (uint32_t i = 0; i < N*P; ++i)
00524     {
00525         res.d[i] = m1.d[i] * value;
00526     }
00527 }
00528 
00529 
00530 template<uint32_t N, uint32_t P, typename T>
00531 void op::transpose(const Mat<N,P,T>& m, Mat<P,N,T>& res)
00532 {
00533     uint32_t index  = 0;
00534     uint32_t index2 = 0;
00535 
00536     for (uint32_t i = 0; i < N; ++i)
00537     {
00538         for (uint32_t j = 0; j < P; ++j)
00539         {
00540             index  = i*P + j;
00541             index2 = j*N + i;
00542             res.d[index2] = m.d[index];
00543         }
00544     }
00545 }
00546 
00547 
00548 template<uint32_t N, uint32_t P, uint32_t Q, typename T>
00549 void op::dot(const Mat<N,P,T>& m1, const Mat<P,Q,T>& m2, Mat<N,Q,T>& res)
00550 {
00551     for (uint32_t i = 0; i < N; ++i)
00552     {
00553         for (uint32_t j = 0; j < Q; ++j)
00554         {
00555             res.d[i*Q+j] = 0.0f;
00556 
00557             for (uint32_t k = 0; k < P; ++k)
00558             {
00559                 res.d[i*Q+j] += m1.d[i*P + k] * m2.d[k*Q+j];
00560             }
00561         }
00562     }
00563 }
00564 
00565 
00570 // template<uint32_t N, typename T>
00571 // bool op::inverse(const Mat<N,N,T>& m, Mat<N,N,T>& res)
00572 // {
00573     // Mat<N,2*N,T> aug;
00574 
00575     // for (uint32_t i=0; i < N; i++)
00576     // {
00577     //     for (uint32_t j=0; j < N; j++)
00578     //     {
00579     //         float v = m.d[i * N + j];
00580 
00581     //         //  clean floats
00582     //         float precision = 1.0e-6f;
00583     //         if (-precision < v && v < precision)
00584     //         {
00585     //             v = 0.0f;
00586     //         }
00587 
00588     //         aug(i,j) = v;
00589     //         aug(i,N+j) = (i == j) * 1.0f;    //  right hand side is I3
00590     //     }
00591     // }
00592 
00593     // //  reduce
00594     // for (uint32_t i=0; i < N; i++)   //  iterate over rows
00595     // {
00596     //     //  look for a pivot
00597     //     float p = aug(i,i);
00598 
00599     //     if (p == 0.0f)
00600     //     {
00601     //         bool pFound = false;
00602     //         for (uint32_t k=i+1; k < N; k++)
00603     //         {
00604     //             p = aug(k,i);
00605     //             if (p != 0.0f)
00606     //             {
00607     //                 //  found a pivot
00608     //                 aug.row_swap(i,k);
00609     //                 pFound = true;
00610     //                 break;
00611     //             }
00612     //         }
00613 
00614     //         if (!pFound) {
00615     //             //  singular, give up
00616     //             return false;
00617     //         }
00618     //     }
00619 
00620     //     //  normalize the pivot
00621     //     aug.row_scale(i,  1 / p);
00622 
00623     //     //  pivot is in right place, reduce all rows
00624     //     for (uint32_t k=0; k < N; k++)
00625     //     {
00626     //         if (k != i)
00627     //         {
00628     //             aug.row_madd(k, i, -aug(k,i));
00629     //         }
00630     //     }
00631     // }
00632 
00633     // return aug.template slice <N,N*2> ();
00634 //     return  false;
00635 // }
00636 
00637 template<uint32_t N, uint32_t P, uint32_t I, uint32_t J, uint32_t Q, uint32_t R, typename T>
00638 bool op::insert_inplace(Mat<N,P,T>& m1, const Mat<Q,R,T>& m2)
00639 {
00640     static_assert(I + Q <= N, "Inserted matrix does not fit (rows)");
00641     static_assert(J + R <= P, "Inserted matrix does not fit (columns)");
00642 
00643     // Insert the matrix
00644     for(uint32_t i = I; i < I + Q; i++)
00645     {
00646         for(uint32_t j = J; j <= J + R; j++)
00647         {
00648             m1(i, j) = m2(i - I, j - J);
00649         }
00650     }
00651 
00652     return true;
00653 }
00654 
00655 
00656 template<uint32_t N, uint32_t P, uint32_t I, uint32_t J, uint32_t Q, uint32_t R, typename T>
00657 bool op::insert(const Mat<N,P,T>& m1, const Mat<Q,R,T>& m2, Mat<N,P,T>& res)
00658 {
00659     static_assert(I + Q <= N, "Inserted matrix does not fit (rows)");
00660     static_assert(J + R <= P, "Inserted matrix does not fit (columns)");
00661 
00662     res = m1;
00663     insert_inplace<N,P,I,J,Q,R,T>(res, m2);
00664 
00665     return true;
00666 }
00667 
00668 
00669 template<uint32_t N, uint32_t P, typename T>
00670 void op::clip(Mat<N,P,T>& m, const Mat<N,P,T>& min, const Mat<N,P,T>& max)
00671 {
00672     for (size_t i = 0; i < N; i++)
00673     {
00674         for (size_t j = 0; j < P; j++)
00675         {
00676             if (m(i,j) < min(i,j))
00677             {
00678                 m(i,j) = min(i,j);
00679             }
00680             else if (m(i,j) > max(i,j))
00681             {
00682                 m(i,j) = max(i,j);
00683             }
00684         }
00685     }
00686 }
00687 
00688 
00689 template<uint32_t N, uint32_t P, typename T>
00690 void op::clip(Mat<N,P,T>& m, float min, float max)
00691 {
00692     for (size_t i = 0; i < N; i++)
00693     {
00694         for (size_t j = 0; j < P; j++)
00695         {
00696             if (m(i,j) < min)
00697             {
00698                 m(i,j) = min;
00699             }
00700             else if (m(i,j) > max)
00701             {
00702                 m(i,j) = max;
00703             }
00704         }
00705     }
00706 }
00707 
00708 
00709 }
00710 
00711 #endif /* MATRIX_HXX__ */
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines