MAV'RIC
|
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__ */