JWS C Library
C language utility library
|
00001 /* 00002 * This work is licensed under a Creative Commons 00003 * Attribution-Noncommercial-Share Alike 3.0 United States License. 00004 * 00005 * http://creativecommons.org/licenses/by-nc-sa/3.0/us/ 00006 * 00007 * You are free: 00008 * 00009 * to Share - to copy, distribute, display, and perform the work 00010 * to Remix - to make derivative works 00011 * 00012 * Under the following conditions: 00013 * 00014 * Attribution. You must attribute the work in the manner specified by the 00015 * author or licensor (but not in any way that suggests that they endorse you 00016 * or your use of the work). 00017 * 00018 * Noncommercial. You may not use this work for commercial purposes. 00019 * 00020 * Share Alike. If you alter, transform, or build upon this work, you may 00021 * distribute the resulting work only under the same or similar license to 00022 * this one. 00023 * 00024 * For any reuse or distribution, you must make clear to others the license 00025 * terms of this work. The best way to do this is by including this header. 00026 * 00027 * Any of the above conditions can be waived if you get permission from the 00028 * copyright holder. 00029 * 00030 * Apart from the remix rights granted under this license, nothing in this 00031 * license impairs or restricts the author's moral rights. 00032 */ 00033 00034 00049 #include <jwsc/config.h> 00050 00051 #include <stdlib.h> 00052 #include <assert.h> 00053 #include <math.h> 00054 #include <inttypes.h> 00055 00056 #include "jwsc/base/error.h" 00057 #include "jwsc/math/complex.h" 00058 #include "jwsc/math/constants.h" 00059 #include "jwsc/math/blas.h" 00060 #include "jwsc/math/lapack.h" 00061 #include "jwsc/vector/vector.h" 00062 #include "jwsc/vector/vector_math.h" 00063 #include "jwsc/matrix/matrix.h" 00064 #include "jwsc/matrix/matrix_math.h" 00065 00066 #ifdef JWSC_HAVE_DMALLOC 00067 #include <dmalloc.h> 00068 #endif 00069 00070 00086 void add_scalar_to_matrix_f 00087 ( 00088 Matrix_f** m_out, 00089 const Matrix_f* m_in, 00090 float a 00091 ) 00092 { 00093 uint32_t num_elts; 00094 uint32_t elt; 00095 float* m_in_elts; 00096 float* m_out_elts; 00097 00098 num_elts = m_in->num_rows*m_in->num_cols; 00099 00100 if (*m_out != m_in) 00101 { 00102 create_matrix_f(m_out, m_in->num_rows, m_in->num_cols); 00103 } 00104 m_out_elts = *((*m_out)->elts); 00105 m_in_elts = *(m_in->elts); 00106 00107 for (elt = 0; elt < num_elts; elt++) 00108 { 00109 m_out_elts[ elt ] = a + m_in_elts[ elt ]; 00110 } 00111 } 00112 00121 void add_scalar_to_matrix_d 00122 ( 00123 Matrix_d** m_out, 00124 const Matrix_d* m_in, 00125 double a 00126 ) 00127 { 00128 uint32_t num_elts; 00129 uint32_t elt; 00130 double* m_in_elts; 00131 double* m_out_elts; 00132 00133 num_elts = m_in->num_rows*m_in->num_cols; 00134 00135 if (*m_out != m_in) 00136 { 00137 create_matrix_d(m_out, m_in->num_rows, m_in->num_cols); 00138 } 00139 m_out_elts = *((*m_out)->elts); 00140 m_in_elts = *(m_in->elts); 00141 00142 for (elt = 0; elt < num_elts; elt++) 00143 { 00144 m_out_elts[ elt ] = a + m_in_elts[ elt ]; 00145 } 00146 } 00147 00156 void add_scalar_to_matrix_cf 00157 ( 00158 Matrix_cf** m_out, 00159 const Matrix_cf* m_in, 00160 Complex_f z 00161 ) 00162 { 00163 uint32_t num_elts; 00164 uint32_t elt; 00165 Complex_f* m_in_elts; 00166 Complex_f* m_out_elts; 00167 00168 num_elts = m_in->num_rows*m_in->num_cols; 00169 00170 if (*m_out != m_in) 00171 { 00172 create_matrix_cf(m_out, m_in->num_rows, m_in->num_cols); 00173 } 00174 m_out_elts = *((*m_out)->elts); 00175 m_in_elts = *(m_in->elts); 00176 00177 for (elt = 0; elt < num_elts; elt++) 00178 { 00179 m_out_elts[ elt ].r = z.r + m_in_elts[ elt ].r; 00180 m_out_elts[ elt ].i = z.i + m_in_elts[ elt ].i; 00181 } 00182 } 00183 00192 void add_scalar_to_matrix_cd 00193 ( 00194 Matrix_cd** m_out, 00195 const Matrix_cd* m_in, 00196 Complex_d z 00197 ) 00198 { 00199 uint32_t num_elts; 00200 uint32_t elt; 00201 Complex_d* m_in_elts; 00202 Complex_d* m_out_elts; 00203 00204 num_elts = m_in->num_rows*m_in->num_cols; 00205 00206 if (*m_out != m_in) 00207 { 00208 create_matrix_cd(m_out, m_in->num_rows, m_in->num_cols); 00209 } 00210 m_out_elts = *((*m_out)->elts); 00211 m_in_elts = *(m_in->elts); 00212 00213 for (elt = 0; elt < num_elts; elt++) 00214 { 00215 m_out_elts[ elt ].r = z.r + m_in_elts[ elt ].r; 00216 m_out_elts[ elt ].i = z.i + m_in_elts[ elt ].i; 00217 } 00218 } 00219 00240 void multiply_matrix_by_scalar_f 00241 ( 00242 Matrix_f** m_out, 00243 const Matrix_f* m_in, 00244 float a 00245 ) 00246 { 00247 uint32_t num_elts; 00248 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00249 #else 00250 uint32_t elt; 00251 float* m_out_elts; 00252 float* m_in_elts; 00253 #endif 00254 00255 num_elts = m_in->num_rows*m_in->num_cols; 00256 00257 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00258 if (*m_out != m_in) 00259 { 00260 copy_matrix_f(m_out, m_in); 00261 } 00262 00263 blas_sscal(num_elts, a, *((*m_out)->elts), 1); 00264 #else 00265 if (*m_out != m_in) 00266 { 00267 create_matrix_f(m_out, m_in->num_rows, m_in->num_cols); 00268 } 00269 00270 m_out_elts = *((*m_out)->elts); 00271 m_in_elts = *(m_in->elts); 00272 00273 for (elt = 0; elt < num_elts; elt++) 00274 { 00275 m_out_elts[ elt ] = a * m_in_elts[ elt ]; 00276 } 00277 #endif 00278 } 00279 00288 void multiply_matrix_by_scalar_d 00289 ( 00290 Matrix_d** m_out, 00291 const Matrix_d* m_in, 00292 double a 00293 ) 00294 { 00295 uint32_t num_elts; 00296 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00297 #else 00298 uint32_t elt; 00299 double* m_out_elts; 00300 double* m_in_elts; 00301 #endif 00302 00303 num_elts = m_in->num_rows*m_in->num_cols; 00304 00305 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00306 if (*m_out != m_in) 00307 { 00308 copy_matrix_d(m_out, m_in); 00309 } 00310 00311 blas_dscal(num_elts, a, *((*m_out)->elts), 1); 00312 #else 00313 if (*m_out != m_in) 00314 { 00315 create_matrix_d(m_out, m_in->num_rows, m_in->num_cols); 00316 } 00317 00318 m_out_elts = *((*m_out)->elts); 00319 m_in_elts = *(m_in->elts); 00320 00321 for (elt = 0; elt < num_elts; elt++) 00322 { 00323 m_out_elts[ elt ] = a * m_in_elts[ elt ]; 00324 } 00325 #endif 00326 } 00327 00336 void multiply_matrix_by_scalar_cf 00337 ( 00338 Matrix_cf** m_out, 00339 const Matrix_cf* m_in, 00340 Complex_f z 00341 ) 00342 { 00343 uint32_t num_elts; 00344 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00345 #else 00346 uint32_t elt; 00347 float r, i; 00348 Complex_f* m_out_elts; 00349 Complex_f* m_in_elts; 00350 #endif 00351 00352 num_elts = m_in->num_rows*m_in->num_cols; 00353 00354 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00355 if (*m_out != m_in) 00356 { 00357 copy_matrix_cf(m_out, m_in); 00358 } 00359 00360 blas_cscal(num_elts, z, *((*m_out)->elts), 1); 00361 #else 00362 if (*m_out != m_in) 00363 { 00364 create_matrix_cf(m_out, m_in->num_rows, m_in->num_cols); 00365 } 00366 00367 m_out_elts = *((*m_out)->elts); 00368 m_in_elts = *(m_in->elts); 00369 00370 for (elt = 0; elt < num_elts; elt++) 00371 { 00372 r = z.r*m_in_elts[ elt ].r - z.i*m_in_elts[ elt ].i; 00373 i = z.i*m_in_elts[ elt ].r + z.r*m_in_elts[ elt ].i; 00374 00375 m_out_elts[ elt ].r = r; 00376 m_out_elts[ elt ].i = i; 00377 } 00378 #endif 00379 } 00380 00389 void multiply_matrix_by_scalar_cd 00390 ( 00391 Matrix_cd** m_out, 00392 const Matrix_cd* m_in, 00393 Complex_d z 00394 ) 00395 { 00396 uint32_t num_elts; 00397 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00398 #else 00399 uint32_t elt; 00400 float r, i; 00401 Complex_d* m_out_elts; 00402 Complex_d* m_in_elts; 00403 #endif 00404 00405 num_elts = m_in->num_rows*m_in->num_cols; 00406 00407 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00408 if (*m_out != m_in) 00409 { 00410 copy_matrix_cd(m_out, m_in); 00411 } 00412 00413 blas_zscal(num_elts, z, *((*m_out)->elts), 1); 00414 #else 00415 if (*m_out != m_in) 00416 { 00417 create_matrix_cd(m_out, m_in->num_rows, m_in->num_cols); 00418 } 00419 00420 m_out_elts = *((*m_out)->elts); 00421 m_in_elts = *(m_in->elts); 00422 00423 for (elt = 0; elt < num_elts; elt++) 00424 { 00425 r = z.r*m_in_elts[ elt ].r - z.i*m_in_elts[ elt ].i; 00426 i = z.i*m_in_elts[ elt ].r + z.r*m_in_elts[ elt ].i; 00427 00428 m_out_elts[ elt ].r = r; 00429 m_out_elts[ elt ].i = i; 00430 } 00431 #endif 00432 } 00433 00462 Error* multiply_matrices_f 00463 ( 00464 Matrix_f** m_out, 00465 const Matrix_f* m_1, 00466 const Matrix_f* m_2 00467 ) 00468 { 00469 uint32_t num_rows, num_cols; 00470 Matrix_f* m; 00471 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00472 #else 00473 uint32_t row, col; 00474 uint32_t elt; 00475 uint32_t length; 00476 float sum; 00477 #endif 00478 00479 if (m_1->num_cols != m_2->num_rows) 00480 { 00481 if (*m_out != m_1 && *m_out != m_2) 00482 { 00483 free_matrix_f(*m_out); *m_out = NULL; 00484 } 00485 return JWSC_EARG("Matrices do not have compatible dimensions"); 00486 } 00487 00488 num_rows = m_1->num_rows; 00489 num_cols = m_2->num_cols; 00490 00491 m = (*m_out == m_1 || *m_out == m_2) ? NULL : *m_out; 00492 create_matrix_f(&m, num_rows, num_cols); 00493 00494 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00495 blas_sgemm('N', 'N', m_1->num_rows, m_2->num_cols, m_1->num_cols, 1, 00496 *(m_1->elts), m_1->num_cols, *(m_2->elts), m_2->num_cols, 0, 00497 *(m->elts), m->num_cols); 00498 #else 00499 length = m_1->num_cols; 00500 for (row = 0; row < num_rows; row++) 00501 { 00502 for (col = 0; col < num_cols; col++) 00503 { 00504 sum = 0; 00505 for (elt = 0; elt < length; elt++) 00506 { 00507 sum += m_1->elts[ row ][ elt ] * m_2->elts[ elt ][ col ]; 00508 } 00509 m->elts[ row ][ col ] = sum; 00510 } 00511 } 00512 #endif 00513 00514 if (*m_out == m_1 || *m_out == m_2) 00515 { 00516 copy_matrix_f(m_out, m); 00517 free_matrix_f(m); 00518 } 00519 else 00520 { 00521 *m_out = m; 00522 } 00523 00524 return NULL; 00525 } 00526 00543 Error* multiply_matrices_d 00544 ( 00545 Matrix_d** m_out, 00546 const Matrix_d* m_1, 00547 const Matrix_d* m_2 00548 ) 00549 { 00550 uint32_t num_rows, num_cols; 00551 Matrix_d* m; 00552 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00553 #else 00554 uint32_t row, col; 00555 uint32_t elt; 00556 uint32_t length; 00557 float sum; 00558 #endif 00559 00560 if (m_1->num_cols != m_2->num_rows) 00561 { 00562 if (*m_out != m_1 && *m_out != m_2) 00563 { 00564 free_matrix_d(*m_out); *m_out = NULL; 00565 } 00566 return JWSC_EARG("Matrices do not have compatible dimensions"); 00567 } 00568 00569 num_rows = m_1->num_rows; 00570 num_cols = m_2->num_cols; 00571 00572 m = (*m_out == m_1 || *m_out == m_2) ? NULL : *m_out; 00573 create_matrix_d(&m, num_rows, num_cols); 00574 00575 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00576 blas_dgemm('N', 'N', m_1->num_rows, m_2->num_cols, m_1->num_cols, 1, 00577 *(m_1->elts), m_1->num_cols, *(m_2->elts), m_2->num_cols, 0, 00578 *(m->elts), m->num_cols); 00579 #else 00580 length = m_1->num_cols; 00581 for (row = 0; row < num_rows; row++) 00582 { 00583 for (col = 0; col < num_cols; col++) 00584 { 00585 sum = 0; 00586 for (elt = 0; elt < length; elt++) 00587 { 00588 sum += m_1->elts[ row ][ elt ] * m_2->elts[ elt ][ col ]; 00589 } 00590 m->elts[ row ][ col ] = sum; 00591 } 00592 } 00593 #endif 00594 00595 if (*m_out == m_1 || *m_out == m_2) 00596 { 00597 copy_matrix_d(m_out, m); 00598 free_matrix_d(m); 00599 } 00600 else 00601 { 00602 *m_out = m; 00603 } 00604 00605 return NULL; 00606 } 00607 00624 Error* multiply_matrices_cf 00625 ( 00626 Matrix_cf** m_out, 00627 const Matrix_cf* m_1, 00628 const Matrix_cf* m_2 00629 ) 00630 { 00631 uint32_t num_rows, num_cols; 00632 Matrix_cf* m; 00633 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00634 Complex_f alpha; 00635 Complex_f beta; 00636 #else 00637 uint32_t row, col; 00638 uint32_t elt; 00639 uint32_t length; 00640 Complex_f sum; 00641 #endif 00642 00643 if (m_1->num_cols != m_2->num_rows) 00644 { 00645 if (*m_out != m_1 && *m_out != m_2) 00646 { 00647 free_matrix_cf(*m_out); *m_out = NULL; 00648 } 00649 return JWSC_EARG("Matrices do not have compatible dimensions"); 00650 } 00651 00652 num_rows = m_1->num_rows; 00653 num_cols = m_2->num_cols; 00654 00655 m = (*m_out == m_1 || *m_out == m_2) ? NULL : *m_out; 00656 create_matrix_cf(&m, num_rows, num_cols); 00657 00658 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00659 alpha.r = 1; alpha.i = 1; 00660 beta.r = 0; beta.i = 0; 00661 blas_cgemm('N', 'N', m_1->num_rows, m_2->num_cols, m_1->num_cols, alpha, 00662 *(m_1->elts), m_1->num_cols, *(m_2->elts), m_2->num_cols, beta, 00663 *(m->elts), m->num_cols); 00664 #else 00665 length = m_1->num_cols; 00666 for (row = 0; row < num_rows; row++) 00667 { 00668 for (col = 0; col < num_cols; col++) 00669 { 00670 sum.r = 0; 00671 sum.i = 0; 00672 for (elt = 0; elt < length; elt++) 00673 { 00674 sum.r += m_1->elts[ row ][ elt ].r * m_2->elts[ elt ][ col ].r - 00675 m_1->elts[ row ][ elt ].i * m_2->elts[ elt ][ col ].i; 00676 sum.i += m_1->elts[ row ][ elt ].i * m_2->elts[ elt ][ col ].r + 00677 m_1->elts[ row ][ elt ].r * m_2->elts[ elt ][ col ].i; 00678 } 00679 m->elts[ row ][ col ].r = sum.r; 00680 m->elts[ row ][ col ].i = sum.i; 00681 } 00682 } 00683 #endif 00684 00685 if (*m_out == m_1 || *m_out == m_2) 00686 { 00687 copy_matrix_cf(m_out, m); 00688 free_matrix_cf(m); 00689 } 00690 else 00691 { 00692 *m_out = m; 00693 } 00694 00695 return NULL; 00696 } 00697 00714 Error* multiply_matrices_cd 00715 ( 00716 Matrix_cd** m_out, 00717 const Matrix_cd* m_1, 00718 const Matrix_cd* m_2 00719 ) 00720 { 00721 uint32_t num_rows, num_cols; 00722 Matrix_cd* m; 00723 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00724 Complex_d alpha; 00725 Complex_d beta; 00726 #else 00727 uint32_t row, col; 00728 uint32_t elt; 00729 uint32_t length; 00730 Complex_d sum; 00731 #endif 00732 00733 if (m_1->num_cols != m_2->num_rows) 00734 { 00735 if (*m_out != m_1 && *m_out != m_2) 00736 { 00737 free_matrix_cd(*m_out); *m_out = NULL; 00738 } 00739 return JWSC_EARG("Matrices do not have compatible dimensions"); 00740 } 00741 00742 num_rows = m_1->num_rows; 00743 num_cols = m_2->num_cols; 00744 00745 m = (*m_out == m_1 || *m_out == m_2) ? NULL : *m_out; 00746 create_matrix_cd(&m, num_rows, num_cols); 00747 00748 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00749 alpha.r = 1; alpha.i = 1; 00750 beta.r = 0; beta.i = 0; 00751 blas_zgemm('N', 'N', m_1->num_rows, m_2->num_cols, m_1->num_cols, alpha, 00752 *(m_1->elts), m_1->num_cols, *(m_2->elts), m_2->num_cols, beta, 00753 *(m->elts), m->num_cols); 00754 #else 00755 length = m_1->num_cols; 00756 for (row = 0; row < num_rows; row++) 00757 { 00758 for (col = 0; col < num_cols; col++) 00759 { 00760 sum.r = 0; 00761 sum.i = 0; 00762 for (elt = 0; elt < length; elt++) 00763 { 00764 sum.r += m_1->elts[ row ][ elt ].r * m_2->elts[ elt ][ col ].r - 00765 m_1->elts[ row ][ elt ].i * m_2->elts[ elt ][ col ].i; 00766 sum.i += m_1->elts[ row ][ elt ].i * m_2->elts[ elt ][ col ].r + 00767 m_1->elts[ row ][ elt ].r * m_2->elts[ elt ][ col ].i; 00768 } 00769 m->elts[ row ][ col ].r = sum.r; 00770 m->elts[ row ][ col ].i = sum.i; 00771 } 00772 } 00773 #endif 00774 00775 if (*m_out == m_1 || *m_out == m_2) 00776 { 00777 copy_matrix_cd(m_out, m); 00778 free_matrix_cd(m); 00779 } 00780 else 00781 { 00782 *m_out = m; 00783 } 00784 00785 return NULL; 00786 } 00787 00815 Error* multiply_matrices_elt_wise_f 00816 ( 00817 Matrix_f** m_out, 00818 const Matrix_f* m_1, 00819 const Matrix_f* m_2 00820 ) 00821 { 00822 uint32_t num_rows, num_cols; 00823 uint32_t num_elts; 00824 uint32_t elt; 00825 float* m_out_elts; 00826 float* m_1_elts; 00827 float* m_2_elts; 00828 00829 num_rows = m_1->num_rows; 00830 num_cols = m_1->num_cols; 00831 00832 if (num_rows != m_2->num_rows || num_cols != m_2->num_cols) 00833 { 00834 if (*m_out != m_1 && *m_out != m_2) 00835 { 00836 free_matrix_f(*m_out); *m_out = NULL; 00837 } 00838 return JWSC_EARG("Matrices do not have the same dimensions"); 00839 } 00840 00841 create_matrix_f(m_out, num_rows, num_cols); 00842 00843 m_out_elts = *((*m_out)->elts); 00844 m_1_elts = *(m_1->elts); 00845 m_2_elts = *(m_2->elts); 00846 00847 num_elts = num_rows*num_cols; 00848 for (elt = 0; elt < num_elts; elt++) 00849 { 00850 m_out_elts[ elt ] = m_1_elts[ elt ]*m_2_elts[ elt ]; 00851 } 00852 00853 return NULL; 00854 } 00855 00857 Error* multiply_matrices_elt_wise_d 00858 ( 00859 Matrix_d** m_out, 00860 const Matrix_d* m_1, 00861 const Matrix_d* m_2 00862 ) 00863 { 00864 uint32_t num_rows, num_cols; 00865 uint32_t num_elts; 00866 uint32_t elt; 00867 double* m_out_elts; 00868 double* m_1_elts; 00869 double* m_2_elts; 00870 00871 num_rows = m_1->num_rows; 00872 num_cols = m_1->num_cols; 00873 00874 if (num_rows != m_2->num_rows || num_cols != m_2->num_cols) 00875 { 00876 if (*m_out != m_1 && *m_out != m_2) 00877 { 00878 free_matrix_d(*m_out); *m_out = NULL; 00879 } 00880 return JWSC_EARG("Matrices do not have the same dimensions"); 00881 } 00882 00883 create_matrix_d(m_out, num_rows, num_cols); 00884 00885 m_out_elts = *((*m_out)->elts); 00886 m_1_elts = *(m_1->elts); 00887 m_2_elts = *(m_2->elts); 00888 00889 num_elts = num_rows*num_cols; 00890 for (elt = 0; elt < num_elts; elt++) 00891 { 00892 m_out_elts[ elt ] = m_1_elts[ elt ]*m_2_elts[ elt ]; 00893 } 00894 00895 return NULL; 00896 } 00897 00901 Error* multiply_matrices_elt_wise_cf 00902 ( 00903 Matrix_cf** m_out, 00904 const Matrix_cf* m_1, 00905 const Matrix_cf* m_2 00906 ) 00907 { 00908 uint32_t num_rows, num_cols; 00909 uint32_t num_elts; 00910 uint32_t elt; 00911 float r, i; 00912 Complex_f* m_out_elts; 00913 Complex_f* m_1_elts; 00914 Complex_f* m_2_elts; 00915 00916 num_rows = m_1->num_rows; 00917 num_cols = m_1->num_cols; 00918 00919 if (num_rows != m_2->num_rows || num_cols != m_2->num_cols) 00920 { 00921 if (*m_out != m_1 && *m_out != m_2) 00922 { 00923 free_matrix_cf(*m_out); *m_out = NULL; 00924 } 00925 return JWSC_EARG("Matrices do not have the same dimensions"); 00926 } 00927 00928 create_matrix_cf(m_out, num_rows, num_cols); 00929 00930 m_out_elts = *((*m_out)->elts); 00931 m_1_elts = *(m_1->elts); 00932 m_2_elts = *(m_2->elts); 00933 00934 num_elts = num_rows*num_cols; 00935 for (elt = 0; elt < num_elts; elt++) 00936 { 00937 r = m_1_elts[ elt ].r * m_2_elts[ elt ].r - 00938 m_1_elts[ elt ].i * m_2_elts[ elt ].i; 00939 i = m_1_elts[ elt ].i * m_2_elts[ elt ].r + 00940 m_1_elts[ elt ].r * m_2_elts[ elt ].i; 00941 00942 m_out_elts[ elt ].r = r; 00943 m_out_elts[ elt ].i = i; 00944 } 00945 00946 return NULL; 00947 } 00948 00952 Error* multiply_matrices_elt_wise_cd 00953 ( 00954 Matrix_cd** m_out, 00955 const Matrix_cd* m_1, 00956 const Matrix_cd* m_2 00957 ) 00958 { 00959 uint32_t num_rows, num_cols; 00960 uint32_t num_elts; 00961 uint32_t elt; 00962 float r, i; 00963 Complex_d* m_out_elts; 00964 Complex_d* m_1_elts; 00965 Complex_d* m_2_elts; 00966 00967 num_rows = m_1->num_rows; 00968 num_cols = m_1->num_cols; 00969 00970 if (num_rows != m_2->num_rows || num_cols != m_2->num_cols) 00971 { 00972 if (*m_out != m_1 && *m_out != m_2) 00973 { 00974 free_matrix_cd(*m_out); *m_out = NULL; 00975 } 00976 return JWSC_EARG("Matrices do not have the same dimensions"); 00977 } 00978 00979 create_matrix_cd(m_out, num_rows, num_cols); 00980 00981 m_out_elts = *((*m_out)->elts); 00982 m_1_elts = *(m_1->elts); 00983 m_2_elts = *(m_2->elts); 00984 00985 num_elts = num_rows*num_cols; 00986 for (elt = 0; elt < num_elts; elt++) 00987 { 00988 r = m_1_elts[ elt ].r * m_2_elts[ elt ].r - 00989 m_1_elts[ elt ].i * m_2_elts[ elt ].i; 00990 i = m_1_elts[ elt ].i * m_2_elts[ elt ].r + 00991 m_1_elts[ elt ].r * m_2_elts[ elt ].i; 00992 00993 m_out_elts[ elt ].r = r; 00994 m_out_elts[ elt ].i = i; 00995 } 00996 00997 return NULL; 00998 } 00999 01019 void transpose_matrix_f(Matrix_f** m_out, const Matrix_f* m_in) 01020 { 01021 uint32_t num_rows, num_cols; 01022 uint32_t row, col; 01023 Matrix_f* m; 01024 01025 num_rows = m_in->num_cols; 01026 num_cols = m_in->num_rows; 01027 01028 m = (*m_out == m_in) ? NULL : *m_out; 01029 create_matrix_f(&m, num_rows, num_cols); 01030 01031 for (row = 0; row < num_rows; row++) 01032 { 01033 for (col = 0; col < num_cols; col++) 01034 { 01035 m->elts[ row ][ col ] = m_in->elts[ col ][ row ]; 01036 } 01037 } 01038 01039 if (*m_out == m_in) 01040 { 01041 copy_matrix_f(m_out, m); 01042 free_matrix_f(m); 01043 } 01044 else 01045 { 01046 *m_out = m; 01047 } 01048 } 01049 01057 void transpose_matrix_d(Matrix_d** m_out, const Matrix_d* m_in) 01058 { 01059 uint32_t num_rows, num_cols; 01060 uint32_t row, col; 01061 Matrix_d* m; 01062 01063 num_rows = m_in->num_cols; 01064 num_cols = m_in->num_rows; 01065 01066 m = (*m_out == m_in) ? NULL : *m_out; 01067 create_matrix_d(&m, num_rows, num_cols); 01068 01069 for (row = 0; row < num_rows; row++) 01070 { 01071 for (col = 0; col < num_cols; col++) 01072 { 01073 m->elts[ row ][ col ] = m_in->elts[ col ][ row ]; 01074 } 01075 } 01076 01077 if (*m_out == m_in) 01078 { 01079 copy_matrix_d(m_out, m); 01080 free_matrix_d(m); 01081 } 01082 else 01083 { 01084 *m_out = m; 01085 } 01086 } 01087 01095 void transpose_matrix_cf(Matrix_cf** m_out, const Matrix_cf* m_in) 01096 { 01097 uint32_t num_rows, num_cols; 01098 uint32_t row, col; 01099 Matrix_cf* m; 01100 01101 num_rows = m_in->num_cols; 01102 num_cols = m_in->num_rows; 01103 01104 m = (*m_out == m_in) ? NULL : *m_out; 01105 create_matrix_cf(&m, num_rows, num_cols); 01106 01107 for (row = 0; row < num_rows; row++) 01108 { 01109 for (col = 0; col < num_cols; col++) 01110 { 01111 m->elts[ row ][ col ] = m_in->elts[ col ][ row ]; 01112 } 01113 } 01114 01115 if (*m_out == m_in) 01116 { 01117 copy_matrix_cf(m_out, m); 01118 free_matrix_cf(m); 01119 } 01120 else 01121 { 01122 *m_out = m; 01123 } 01124 } 01125 01133 void transpose_matrix_cd(Matrix_cd** m_out, const Matrix_cd* m_in) 01134 { 01135 uint32_t num_rows, num_cols; 01136 uint32_t row, col; 01137 Matrix_cd* m; 01138 01139 num_rows = m_in->num_cols; 01140 num_cols = m_in->num_rows; 01141 01142 m = (*m_out == m_in) ? NULL : *m_out; 01143 create_matrix_cd(&m, num_rows, num_cols); 01144 01145 for (row = 0; row < num_rows; row++) 01146 { 01147 for (col = 0; col < num_cols; col++) 01148 { 01149 m->elts[ row ][ col ] = m_in->elts[ col ][ row ]; 01150 } 01151 } 01152 01153 if (*m_out == m_in) 01154 { 01155 copy_matrix_cd(m_out, m); 01156 free_matrix_cd(m); 01157 } 01158 else 01159 { 01160 *m_out = m; 01161 } 01162 } 01163 01193 Error* multiply_matrix_and_vector_f 01194 ( 01195 Vector_f** v_out, 01196 const Matrix_f* m_in, 01197 const Vector_f* v_in 01198 ) 01199 { 01200 Vector_f* v; 01201 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01202 #else 01203 uint32_t num_rows, num_cols; 01204 uint32_t row, col; 01205 float sum; 01206 #endif 01207 01208 if (m_in->num_cols != v_in->num_elts) 01209 { 01210 if (*v_out != v_in) 01211 { 01212 free_vector_f(*v_out); *v_out = NULL; 01213 } 01214 return JWSC_EARG("Matrix and vector do not have compatible dimensions"); 01215 } 01216 01217 v = (*v_out == v_in) ? NULL : *v_out; 01218 create_vector_f(&v, m_in->num_rows); 01219 01220 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01221 blas_sgemv('N', m_in->num_rows, m_in->num_cols, 1, *(m_in->elts), 01222 m_in->num_cols, v_in->elts, 1, 0, v->elts, 1); 01223 #else 01224 num_rows = m_in->num_rows; 01225 num_cols = m_in->num_cols; 01226 01227 for (row = 0; row < num_rows; row++) 01228 { 01229 sum = 0; 01230 for (col = 0; col < num_cols; col++) 01231 { 01232 sum += m_in->elts[ row ][ col ] * v_in->elts[ col ]; 01233 } 01234 v->elts[ row ] = sum; 01235 } 01236 #endif 01237 01238 if (*v_out == v_in) 01239 { 01240 copy_vector_f(v_out, v); 01241 free_vector_f(v); 01242 } 01243 else 01244 { 01245 *v_out = v; 01246 } 01247 01248 return NULL; 01249 } 01250 01268 Error* multiply_matrix_and_vector_d 01269 ( 01270 Vector_d** v_out, 01271 const Matrix_d* m_in, 01272 const Vector_d* v_in 01273 ) 01274 { 01275 Vector_d* v; 01276 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01277 #else 01278 uint32_t num_rows, num_cols; 01279 uint32_t row, col; 01280 double sum; 01281 #endif 01282 01283 if (m_in->num_cols != v_in->num_elts) 01284 { 01285 if (*v_out != v_in) 01286 { 01287 free_vector_d(*v_out); *v_out = NULL; 01288 } 01289 return JWSC_EARG("Matrix and vector do not have compatible dimensions"); 01290 } 01291 01292 v = (*v_out == v_in) ? NULL : *v_out; 01293 create_vector_d(&v, m_in->num_rows); 01294 01295 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01296 blas_dgemv('N', m_in->num_rows, m_in->num_cols, 1, *(m_in->elts), 01297 m_in->num_cols, v_in->elts, 1, 0, v->elts, 1); 01298 #else 01299 num_rows = m_in->num_rows; 01300 num_cols = m_in->num_cols; 01301 01302 for (row = 0; row < num_rows; row++) 01303 { 01304 sum = 0; 01305 for (col = 0; col < num_cols; col++) 01306 { 01307 sum += m_in->elts[ row ][ col ] * v_in->elts[ col ]; 01308 } 01309 v->elts[ row ] = sum; 01310 } 01311 #endif 01312 01313 if (*v_out == v_in) 01314 { 01315 copy_vector_d(v_out, v); 01316 free_vector_d(v); 01317 } 01318 else 01319 { 01320 *v_out = v; 01321 } 01322 01323 return NULL; 01324 } 01325 01343 Error* multiply_matrix_and_vector_cf 01344 ( 01345 Vector_cf** v_out, 01346 const Matrix_cf* m_in, 01347 const Vector_cf* v_in 01348 ) 01349 { 01350 Vector_cf* v; 01351 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01352 Complex_f alpha; 01353 Complex_f beta; 01354 #else 01355 uint32_t num_rows, num_cols; 01356 uint32_t row, col; 01357 Complex_f sum; 01358 #endif 01359 01360 if (m_in->num_cols != v_in->num_elts) 01361 { 01362 if (*v_out != v_in) 01363 { 01364 free_vector_cf(*v_out); *v_out = NULL; 01365 } 01366 return JWSC_EARG("Matrix and vector do not have compatible dimensions"); 01367 } 01368 01369 v = (*v_out == v_in) ? NULL : *v_out; 01370 create_vector_cf(&v, m_in->num_rows); 01371 01372 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01373 alpha.r = 1; alpha.i = 1; 01374 beta.r = 0; beta.i = 0; 01375 blas_cgemv('N', m_in->num_rows, m_in->num_cols, alpha, *(m_in->elts), 01376 m_in->num_cols, v_in->elts, 1, beta, v->elts, 1); 01377 #else 01378 num_rows = m_in->num_rows; 01379 num_cols = m_in->num_cols; 01380 01381 for (row = 0; row < num_rows; row++) 01382 { 01383 sum.r = 0; 01384 sum.i = 0; 01385 for (col = 0; col < num_cols; col++) 01386 { 01387 sum.r += m_in->elts[ row ][ col ].r * v_in->elts[ col ].r - 01388 m_in->elts[ row ][ col ].i * v_in->elts[ col ].i; 01389 sum.i += m_in->elts[ row ][ col ].i * v_in->elts[ col ].r + 01390 m_in->elts[ row ][ col ].r * v_in->elts[ col ].i; 01391 } 01392 v->elts[ row ].r = sum.r; 01393 v->elts[ row ].i = sum.i; 01394 } 01395 #endif 01396 01397 if (*v_out == v_in) 01398 { 01399 copy_vector_cf(v_out, v); 01400 free_vector_cf(v); 01401 } 01402 else 01403 { 01404 *v_out = v; 01405 } 01406 01407 return NULL; 01408 } 01409 01427 Error* multiply_matrix_and_vector_cd 01428 ( 01429 Vector_cd** v_out, 01430 const Matrix_cd* m_in, 01431 const Vector_cd* v_in 01432 ) 01433 { 01434 Vector_cd* v; 01435 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01436 Complex_d alpha; 01437 Complex_d beta; 01438 #else 01439 uint32_t num_rows, num_cols; 01440 uint32_t row, col; 01441 Complex_d sum; 01442 #endif 01443 01444 if (m_in->num_cols != v_in->num_elts) 01445 { 01446 if (*v_out != v_in) 01447 { 01448 free_vector_cd(*v_out); *v_out = NULL; 01449 } 01450 return JWSC_EARG("Matrix and vector do not have compatible dimensions"); 01451 } 01452 01453 v = (*v_out == v_in) ? NULL : *v_out; 01454 create_vector_cd(&v, m_in->num_rows); 01455 01456 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01457 alpha.r = 1; alpha.i = 1; 01458 beta.r = 0; beta.i = 0; 01459 blas_zgemv('N', m_in->num_rows, m_in->num_cols, alpha, *(m_in->elts), 01460 m_in->num_cols, v_in->elts, 1, beta, v->elts, 1); 01461 #else 01462 num_rows = m_in->num_rows; 01463 num_cols = m_in->num_cols; 01464 01465 for (row = 0; row < num_rows; row++) 01466 { 01467 sum.r = 0; 01468 sum.i = 0; 01469 for (col = 0; col < num_cols; col++) 01470 { 01471 sum.r += m_in->elts[ row ][ col ].r * v_in->elts[ col ].r - 01472 m_in->elts[ row ][ col ].i * v_in->elts[ col ].i; 01473 sum.i += m_in->elts[ row ][ col ].i * v_in->elts[ col ].r + 01474 m_in->elts[ row ][ col ].r * v_in->elts[ col ].i; 01475 } 01476 v->elts[ row ].r = sum.r; 01477 v->elts[ row ].i = sum.i; 01478 } 01479 #endif 01480 01481 if (*v_out == v_in) 01482 { 01483 copy_vector_cd(v_out, v); 01484 free_vector_cd(v); 01485 } 01486 else 01487 { 01488 *v_out = v; 01489 } 01490 01491 return NULL; 01492 } 01493 01494 01495 01496 01519 Error* add_matrices_f 01520 ( 01521 Matrix_f** m_out, 01522 const Matrix_f* m_1, 01523 const Matrix_f* m_2 01524 ) 01525 { 01526 uint32_t num_elts; 01527 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01528 #else 01529 uint32_t elt; 01530 float* m_1_elts; 01531 float* m_2_elts; 01532 float* m_out_elts; 01533 #endif 01534 01535 if (m_1->num_rows != m_2->num_rows || m_1->num_cols != m_2->num_cols) 01536 { 01537 if (*m_out != m_1 && *m_out != m_2) 01538 { 01539 free_matrix_f(*m_out); *m_out = NULL; 01540 } 01541 return JWSC_EARG("Adding matrices requires equal dimensions"); 01542 } 01543 01544 num_elts = m_1->num_rows*m_1->num_cols; 01545 01546 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01547 if (*m_out == m_1) 01548 { 01549 blas_saxpy(num_elts, 1, *(m_2->elts), 1, *(m_1->elts), 1); 01550 } 01551 else if (*m_out == m_2) 01552 { 01553 blas_saxpy(num_elts, 1, *(m_1->elts), 1, *(m_2->elts), 1); 01554 } 01555 else 01556 { 01557 copy_matrix_f(m_out, m_2); 01558 blas_saxpy(num_elts, 1, *(m_1->elts), 1, *((*m_out)->elts), 1); 01559 } 01560 #else 01561 m_1_elts = *(m_1->elts); 01562 m_2_elts = *(m_2->elts); 01563 m_out_elts = *((*m_out)->elts); 01564 01565 if (*m_out == m_1) 01566 { 01567 for (elt = 0; elt < num_elts; elt++) 01568 { 01569 m_1_elts[ elt ] += m_2_elts[ elt ]; 01570 } 01571 } 01572 else if (*m_out == m_2) 01573 { 01574 for (elt = 0; elt < num_elts; elt++) 01575 { 01576 m_2_elts[ elt ] += m_1_elts[ elt ]; 01577 } 01578 } 01579 else 01580 { 01581 create_matrix_f(m_out, m_1->num_rows, m_1->num_cols); 01582 for (elt = 0; elt < num_elts; elt++) 01583 { 01584 m_out_elts[ elt ] = m_1_elts[ elt ] + m_2_elts[ elt ]; 01585 } 01586 } 01587 #endif 01588 01589 return NULL; 01590 } 01591 01607 Error* add_matrices_d 01608 ( 01609 Matrix_d** m_out, 01610 const Matrix_d* m_1, 01611 const Matrix_d* m_2 01612 ) 01613 { 01614 uint32_t num_elts; 01615 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01616 #else 01617 uint32_t elt; 01618 double* m_1_elts; 01619 double* m_2_elts; 01620 double* m_out_elts; 01621 #endif 01622 01623 if (m_1->num_rows != m_2->num_rows || m_1->num_cols != m_2->num_cols) 01624 { 01625 if (*m_out != m_1 && *m_out != m_2) 01626 { 01627 free_matrix_d(*m_out); *m_out = NULL; 01628 } 01629 return JWSC_EARG("Adding matrices requires equal dimensions"); 01630 } 01631 01632 num_elts = m_1->num_rows*m_1->num_cols; 01633 01634 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01635 if (*m_out == m_1) 01636 { 01637 blas_daxpy(num_elts, 1, *(m_2->elts), 1, *(m_1->elts), 1); 01638 } 01639 else if (*m_out == m_2) 01640 { 01641 blas_daxpy(num_elts, 1, *(m_1->elts), 1, *(m_2->elts), 1); 01642 } 01643 else 01644 { 01645 copy_matrix_d(m_out, m_2); 01646 blas_daxpy(num_elts, 1, *(m_1->elts), 1, *((*m_out)->elts), 1); 01647 } 01648 #else 01649 m_1_elts = *(m_1->elts); 01650 m_2_elts = *(m_2->elts); 01651 m_out_elts = *((*m_out)->elts); 01652 01653 if (*m_out == m_1) 01654 { 01655 for (elt = 0; elt < num_elts; elt++) 01656 { 01657 m_1_elts[ elt ] += m_2_elts[ elt ]; 01658 } 01659 } 01660 else if (*m_out == m_2) 01661 { 01662 for (elt = 0; elt < num_elts; elt++) 01663 { 01664 m_2_elts[ elt ] += m_1_elts[ elt ]; 01665 } 01666 } 01667 else 01668 { 01669 create_matrix_d(m_out, m_1->num_rows, m_1->num_cols); 01670 for (elt = 0; elt < num_elts; elt++) 01671 { 01672 m_out_elts[ elt ] = m_1_elts[ elt ] + m_2_elts[ elt ]; 01673 } 01674 } 01675 #endif 01676 01677 return NULL; 01678 } 01679 01695 Error* add_matrices_cf 01696 ( 01697 Matrix_cf** m_out, 01698 const Matrix_cf* m_1, 01699 const Matrix_cf* m_2 01700 ) 01701 { 01702 uint32_t num_elts; 01703 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01704 Complex_f z = {1, 0}; 01705 #else 01706 uint32_t elt; 01707 Complex_f* m_1_elts; 01708 Complex_f* m_2_elts; 01709 Complex_f* m_out_elts; 01710 #endif 01711 01712 if (m_1->num_rows != m_2->num_rows || m_1->num_cols != m_2->num_cols) 01713 { 01714 if (*m_out != m_1 && *m_out != m_2) 01715 { 01716 free_matrix_cf(*m_out); *m_out = NULL; 01717 } 01718 return JWSC_EARG("Adding matrices requires equal dimensions"); 01719 } 01720 01721 num_elts = m_1->num_rows*m_1->num_cols; 01722 01723 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01724 if (*m_out == m_1) 01725 { 01726 blas_caxpy(num_elts, z, *(m_2->elts), 1, *(m_1->elts), 1); 01727 } 01728 else if (*m_out == m_2) 01729 { 01730 blas_caxpy(num_elts, z, *(m_1->elts), 1, *(m_2->elts), 1); 01731 } 01732 else 01733 { 01734 copy_matrix_cf(m_out, m_2); 01735 blas_caxpy(num_elts, z, *(m_1->elts), 1, *((*m_out)->elts), 1); 01736 } 01737 #else 01738 m_1_elts = *(m_1->elts); 01739 m_2_elts = *(m_2->elts); 01740 m_out_elts = *((*m_out)->elts); 01741 01742 if (*m_out == m_1) 01743 { 01744 for (elt = 0; elt < num_elts; elt++) 01745 { 01746 m_1_elts[ elt ].r = m_1_elts[ elt ].r + m_2_elts[ elt ].r; 01747 m_1_elts[ elt ].i = m_1_elts[ elt ].i + m_2_elts[ elt ].i; 01748 } 01749 } 01750 else if (*m_out == m_2) 01751 { 01752 for (elt = 0; elt < num_elts; elt++) 01753 { 01754 m_2_elts[ elt ].r = m_1_elts[ elt ].r + m_2_elts[ elt ].r; 01755 m_2_elts[ elt ].i = m_1_elts[ elt ].i + m_2_elts[ elt ].i; 01756 } 01757 } 01758 else 01759 { 01760 create_matrix_cf(m_out, m_1->num_rows, m_1->num_cols); 01761 for (elt = 0; elt < num_elts; elt++) 01762 { 01763 m_out_elts[ elt ].r = m_1_elts[ elt ].r + m_2_elts[ elt ].r; 01764 m_out_elts[ elt ].i = m_1_elts[ elt ].i + m_2_elts[ elt ].i; 01765 } 01766 } 01767 #endif 01768 01769 return NULL; 01770 } 01771 01787 Error* add_matrices_cd 01788 ( 01789 Matrix_cd** m_out, 01790 const Matrix_cd* m_1, 01791 const Matrix_cd* m_2 01792 ) 01793 { 01794 uint32_t num_elts; 01795 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01796 Complex_d z = {1, 0}; 01797 #else 01798 uint32_t elt; 01799 Complex_d* m_1_elts; 01800 Complex_d* m_2_elts; 01801 Complex_d* m_out_elts; 01802 #endif 01803 01804 if (m_1->num_rows != m_2->num_rows || m_1->num_cols != m_2->num_cols) 01805 { 01806 if (*m_out != m_1 && *m_out != m_2) 01807 { 01808 free_matrix_cd(*m_out); *m_out = NULL; 01809 } 01810 return JWSC_EARG("Adding matrices requires equal dimensions"); 01811 } 01812 01813 num_elts = m_1->num_rows*m_1->num_cols; 01814 01815 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01816 if (*m_out == m_1) 01817 { 01818 blas_zaxpy(num_elts, z, *(m_2->elts), 1, *(m_1->elts), 1); 01819 } 01820 else if (*m_out == m_2) 01821 { 01822 blas_zaxpy(num_elts, z, *(m_1->elts), 1, *(m_2->elts), 1); 01823 } 01824 else 01825 { 01826 copy_matrix_cd(m_out, m_2); 01827 blas_zaxpy(num_elts, z, *(m_1->elts), 1, *((*m_out)->elts), 1); 01828 } 01829 #else 01830 m_1_elts = *(m_1->elts); 01831 m_2_elts = *(m_2->elts); 01832 m_out_elts = *((*m_out)->elts); 01833 01834 if (*m_out == m_1) 01835 { 01836 for (elt = 0; elt < num_elts; elt++) 01837 { 01838 m_1_elts[ elt ].r = m_1_elts[ elt ].r + m_2_elts[ elt ].r; 01839 m_1_elts[ elt ].i = m_1_elts[ elt ].i + m_2_elts[ elt ].i; 01840 } 01841 } 01842 else if (*m_out == m_2) 01843 { 01844 for (elt = 0; elt < num_elts; elt++) 01845 { 01846 m_2_elts[ elt ].r = m_1_elts[ elt ].r + m_2_elts[ elt ].r; 01847 m_2_elts[ elt ].i = m_1_elts[ elt ].i + m_2_elts[ elt ].i; 01848 } 01849 } 01850 else 01851 { 01852 create_matrix_cd(m_out, m_1->num_rows, m_1->num_cols); 01853 for (elt = 0; elt < num_elts; elt++) 01854 { 01855 m_out_elts[ elt ].r = m_1_elts[ elt ].r + m_2_elts[ elt ].r; 01856 m_out_elts[ elt ].i = m_1_elts[ elt ].i + m_2_elts[ elt ].i; 01857 } 01858 } 01859 #endif 01860 01861 return NULL; 01862 } 01863 01891 Error* subtract_matrices_f 01892 ( 01893 Matrix_f** m_out, 01894 const Matrix_f* m_1, 01895 const Matrix_f* m_2 01896 ) 01897 { 01898 uint32_t num_elts; 01899 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01900 Matrix_f* m = NULL; 01901 #else 01902 uint32_t elt; 01903 float* m_1_elts; 01904 float* m_2_elts; 01905 float* m_out_elts; 01906 #endif 01907 01908 if (m_1->num_rows != m_2->num_rows || m_1->num_cols != m_2->num_cols) 01909 { 01910 if (*m_out != m_1 && *m_out != m_2) 01911 { 01912 free_matrix_f(*m_out); *m_out = NULL; 01913 } 01914 return JWSC_EARG("Subtracting matrices requires equal dimensions"); 01915 } 01916 01917 num_elts = m_1->num_rows*m_1->num_cols; 01918 01919 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01920 if (*m_out == m_1) 01921 { 01922 blas_saxpy(num_elts, -1, *(m_2->elts), 1, *(m_1->elts), 1); 01923 } 01924 else if (*m_out == m_2) 01925 { 01926 copy_matrix_f(&m, m_1); 01927 blas_saxpy(num_elts, -1, *(m_2->elts), 1, *(m->elts), 1); 01928 copy_matrix_f(m_out, m); 01929 free_matrix_f(m); 01930 } 01931 else 01932 { 01933 copy_matrix_f(m_out, m_1); 01934 blas_saxpy(num_elts, -1, *(m_2->elts), 1, *((*m_out)->elts), 1); 01935 } 01936 #else 01937 m_1_elts = *(m_1->elts); 01938 m_2_elts = *(m_2->elts); 01939 m_out_elts = *((*m_out)->elts); 01940 01941 if (*m_out == m_1) 01942 { 01943 for (elt = 0; elt < num_elts; elt++) 01944 { 01945 m_1_elts[ elt ] = m_1_elts[ elt ] - m_2_elts[ elt ]; 01946 } 01947 } 01948 else if (*m_out == m_2) 01949 { 01950 for (elt = 0; elt < num_elts; elt++) 01951 { 01952 m_2_elts[ elt ] = m_1_elts[ elt ] - m_2_elts[ elt ]; 01953 } 01954 } 01955 else 01956 { 01957 create_matrix_f(m_out, m_1->num_rows, m_1->num_cols); 01958 for (elt = 0; elt < num_elts; elt++) 01959 { 01960 m_out_elts[ elt ] = m_1_elts[ elt ] - m_2_elts[ elt ]; 01961 } 01962 } 01963 #endif 01964 01965 return NULL; 01966 } 01967 01983 Error* subtract_matrices_d 01984 ( 01985 Matrix_d** m_out, 01986 const Matrix_d* m_1, 01987 const Matrix_d* m_2 01988 ) 01989 { 01990 uint32_t num_elts; 01991 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01992 Matrix_d* m = NULL; 01993 #else 01994 uint32_t elt; 01995 double* m_1_elts; 01996 double* m_2_elts; 01997 double* m_out_elts; 01998 #endif 01999 02000 if (m_1->num_rows != m_2->num_rows || m_1->num_cols != m_2->num_cols) 02001 { 02002 if (*m_out != m_1 && *m_out != m_2) 02003 { 02004 free_matrix_d(*m_out); *m_out = NULL; 02005 } 02006 return JWSC_EARG("Subtracting matrices requires equal dimensions"); 02007 } 02008 02009 num_elts = m_1->num_rows*m_1->num_cols; 02010 02011 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 02012 if (*m_out == m_1) 02013 { 02014 blas_daxpy(num_elts, -1, *(m_2->elts), 1, *(m_1->elts), 1); 02015 } 02016 else if (*m_out == m_2) 02017 { 02018 copy_matrix_d(&m, m_1); 02019 blas_daxpy(num_elts, -1, *(m_2->elts), 1, *(m->elts), 1); 02020 copy_matrix_d(m_out, m); 02021 free_matrix_d(m); 02022 } 02023 else 02024 { 02025 copy_matrix_d(m_out, m_1); 02026 blas_daxpy(num_elts, -1, *(m_2->elts), 1, *((*m_out)->elts), 1); 02027 } 02028 #else 02029 m_1_elts = *(m_1->elts); 02030 m_2_elts = *(m_2->elts); 02031 m_out_elts = *((*m_out)->elts); 02032 02033 if (*m_out == m_1) 02034 { 02035 for (elt = 0; elt < num_elts; elt++) 02036 { 02037 m_1_elts[ elt ] = m_1_elts[ elt ] - m_2_elts[ elt ]; 02038 } 02039 } 02040 else if (*m_out == m_2) 02041 { 02042 for (elt = 0; elt < num_elts; elt++) 02043 { 02044 m_2_elts[ elt ] = m_1_elts[ elt ] - m_2_elts[ elt ]; 02045 } 02046 } 02047 else 02048 { 02049 create_matrix_d(m_out, m_1->num_rows, m_1->num_cols); 02050 for (elt = 0; elt < num_elts; elt++) 02051 { 02052 m_out_elts[ elt ] = m_1_elts[ elt ] - m_2_elts[ elt ]; 02053 } 02054 } 02055 #endif 02056 02057 return NULL; 02058 } 02059 02075 Error* subtract_matrices_cf 02076 ( 02077 Matrix_cf** m_out, 02078 const Matrix_cf* m_1, 02079 const Matrix_cf* m_2 02080 ) 02081 { 02082 uint32_t num_elts; 02083 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 02084 Matrix_cf* m = NULL; 02085 Complex_f z = {-1, 0}; 02086 #else 02087 uint32_t elt; 02088 Complex_f* m_1_elts; 02089 Complex_f* m_2_elts; 02090 Complex_f* m_out_elts; 02091 #endif 02092 02093 if (m_1->num_rows != m_2->num_rows || m_1->num_cols != m_2->num_cols) 02094 { 02095 if (*m_out != m_1 && *m_out != m_2) 02096 { 02097 free_matrix_cf(*m_out); *m_out = NULL; 02098 } 02099 return JWSC_EARG("Subtracting matrices requires equal dimensions"); 02100 } 02101 02102 num_elts = m_1->num_rows*m_1->num_cols; 02103 02104 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 02105 if (*m_out == m_1) 02106 { 02107 blas_caxpy(num_elts, z, *(m_2->elts), 1, *(m_1->elts), 1); 02108 } 02109 else if (*m_out == m_2) 02110 { 02111 copy_matrix_cf(&m, m_1); 02112 blas_caxpy(num_elts, z, *(m_2->elts), 1, *(m->elts), 1); 02113 copy_matrix_cf(m_out, m); 02114 free_matrix_cf(m); 02115 } 02116 else 02117 { 02118 copy_matrix_cf(m_out, m_1); 02119 blas_caxpy(num_elts, z, *(m_2->elts), 1, *((*m_out)->elts), 1); 02120 } 02121 #else 02122 m_1_elts = *(m_1->elts); 02123 m_2_elts = *(m_2->elts); 02124 m_out_elts = *((*m_out)->elts); 02125 02126 if (*m_out == m_1) 02127 { 02128 for (elt = 0; elt < num_elts; elt++) 02129 { 02130 m_1_elts[ elt ].r = m_1_elts[ elt ].r - m_2_elts[ elt ].r; 02131 m_1_elts[ elt ].i = m_1_elts[ elt ].i - m_2_elts[ elt ].i; 02132 } 02133 } 02134 else if (*m_out == m_2) 02135 { 02136 for (elt = 0; elt < num_elts; elt++) 02137 { 02138 m_2_elts[ elt ].r = m_1_elts[ elt ].r - m_2_elts[ elt ].r; 02139 m_2_elts[ elt ].i = m_1_elts[ elt ].i - m_2_elts[ elt ].i; 02140 } 02141 } 02142 else 02143 { 02144 create_matrix_cf(m_out, m_1->num_rows, m_1->num_cols); 02145 for (elt = 0; elt < num_elts; elt++) 02146 { 02147 m_out_elts[ elt ].r = m_1_elts[ elt ].r - m_2_elts[ elt ].r; 02148 m_out_elts[ elt ].i = m_1_elts[ elt ].i - m_2_elts[ elt ].i; 02149 } 02150 } 02151 #endif 02152 02153 return NULL; 02154 } 02155 02171 Error* subtract_matrices_cd 02172 ( 02173 Matrix_cd** m_out, 02174 const Matrix_cd* m_1, 02175 const Matrix_cd* m_2 02176 ) 02177 { 02178 uint32_t num_elts; 02179 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 02180 Matrix_cd* m = NULL; 02181 Complex_d z = {-1, 0}; 02182 #else 02183 uint32_t elt; 02184 Complex_d* m_1_elts; 02185 Complex_d* m_2_elts; 02186 Complex_d* m_out_elts; 02187 #endif 02188 02189 if (m_1->num_rows != m_2->num_rows || m_1->num_cols != m_2->num_cols) 02190 { 02191 if (*m_out != m_1 && *m_out != m_2) 02192 { 02193 free_matrix_cd(*m_out); *m_out = NULL; 02194 } 02195 return JWSC_EARG("Subtracting matrices requires equal dimensions"); 02196 } 02197 02198 num_elts = m_1->num_rows*m_1->num_cols; 02199 02200 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 02201 if (*m_out == m_1) 02202 { 02203 blas_zaxpy(num_elts, z, *(m_2->elts), 1, *(m_1->elts), 1); 02204 } 02205 else if (*m_out == m_2) 02206 { 02207 copy_matrix_cd(&m, m_1); 02208 blas_zaxpy(num_elts, z, *(m_2->elts), 1, *(m->elts), 1); 02209 copy_matrix_cd(m_out, m); 02210 free_matrix_cd(m); 02211 } 02212 else 02213 { 02214 copy_matrix_cd(m_out, m_1); 02215 blas_zaxpy(num_elts, z, *(m_2->elts), 1, *((*m_out)->elts), 1); 02216 } 02217 #else 02218 m_1_elts = *(m_1->elts); 02219 m_2_elts = *(m_2->elts); 02220 m_out_elts = *((*m_out)->elts); 02221 02222 if (*m_out == m_1) 02223 { 02224 for (elt = 0; elt < num_elts; elt++) 02225 { 02226 m_1_elts[ elt ].r = m_1_elts[ elt ].r - m_2_elts[ elt ].r; 02227 m_1_elts[ elt ].i = m_1_elts[ elt ].i - m_2_elts[ elt ].i; 02228 } 02229 } 02230 else if (*m_out == m_2) 02231 { 02232 for (elt = 0; elt < num_elts; elt++) 02233 { 02234 m_2_elts[ elt ].r = m_1_elts[ elt ].r - m_2_elts[ elt ].r; 02235 m_2_elts[ elt ].i = m_1_elts[ elt ].i - m_2_elts[ elt ].i; 02236 } 02237 } 02238 else 02239 { 02240 create_matrix_cd(m_out, m_1->num_rows, m_1->num_cols); 02241 for (elt = 0; elt < num_elts; elt++) 02242 { 02243 m_out_elts[ elt ].r = m_1_elts[ elt ].r - m_2_elts[ elt ].r; 02244 m_out_elts[ elt ].i = m_1_elts[ elt ].i - m_2_elts[ elt ].i; 02245 } 02246 } 02247 #endif 02248 02249 return NULL; 02250 } 02251 02268 void calc_matrix_asum_f(float* sum_out, const Matrix_f* m) 02269 { 02270 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 02271 *sum_out = blas_sasum(m->num_rows*m->num_cols, *(m->elts), 1); 02272 #else 02273 uint32_t num_elts; 02274 uint32_t elt; 02275 float* m_elts; 02276 02277 num_elts = m->num_rows*m->num_cols; 02278 m_elts = *(m->elts); 02279 *sum_out = 0; 02280 02281 for (elt = 0; elt < num_elts; elt++) 02282 { 02283 (*sum_out) += (float)fabs(m_elts[ elt ]); 02284 } 02285 #endif 02286 } 02287 02292 void calc_matrix_asum_d(double* sum_out, const Matrix_d* m) 02293 { 02294 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 02295 *sum_out = blas_dasum(m->num_rows*m->num_cols, *(m->elts), 1); 02296 #else 02297 uint32_t num_elts; 02298 uint32_t elt; 02299 double* m_elts; 02300 02301 num_elts = m->num_rows*m->num_cols; 02302 m_elts = *(m->elts); 02303 *sum_out = 0; 02304 02305 for (elt = 0; elt < num_elts; elt++) 02306 { 02307 (*sum_out) += fabs(m_elts[ elt ]); 02308 } 02309 #endif 02310 } 02311 02331 void normalize_matrix_sum_f(Matrix_f** m_out, const Matrix_f* m_in) 02332 { 02333 float sum; 02334 02335 calc_matrix_asum_f(&sum, m_in); 02336 02337 if (sum > 0) 02338 { 02339 multiply_matrix_by_scalar_f(m_out, m_in, 1.0f / sum); 02340 } 02341 else 02342 { 02343 copy_matrix_f(m_out, m_in); 02344 } 02345 } 02346 02354 void normalize_matrix_sum_d(Matrix_d** m_out, const Matrix_d* m_in) 02355 { 02356 double sum; 02357 02358 calc_matrix_asum_d(&sum, m_in); 02359 02360 if (sum > 0) 02361 { 02362 multiply_matrix_by_scalar_d(m_out, m_in, 1.0 / sum); 02363 } 02364 else 02365 { 02366 copy_matrix_d(m_out, m_in); 02367 } 02368 } 02369 02386 void calc_frobenius_norm_f(float* norm_out, const Matrix_f* m) 02387 { 02388 uint32_t row, num_rows; 02389 uint32_t col, num_cols; 02390 float norm; 02391 02392 num_rows = m->num_rows; 02393 num_cols = m->num_cols; 02394 norm = 0; 02395 02396 for (row = 0; row < num_rows; row++) 02397 { 02398 for (col = 0; col < num_cols; col++) 02399 { 02400 norm += m->elts[ row ][ col ] * m->elts[ row ][ col ]; 02401 } 02402 } 02403 02404 *norm_out = sqrt(norm); 02405 } 02406 02411 void calc_frobenius_norm_d(double* norm_out, const Matrix_d* m) 02412 { 02413 uint32_t row, num_rows; 02414 uint32_t col, num_cols; 02415 double norm; 02416 02417 num_rows = m->num_rows; 02418 num_cols = m->num_cols; 02419 norm = 0; 02420 02421 for (row = 0; row < num_rows; row++) 02422 { 02423 for (col = 0; col < num_cols; col++) 02424 { 02425 norm += m->elts[ row ][ col ] * m->elts[ row ][ col ]; 02426 } 02427 } 02428 02429 *norm_out = sqrt(norm); 02430 } 02431 02450 Error* calc_frobenius_norm_diff_f 02451 ( 02452 float* norm_out, 02453 const Matrix_f* m_1, 02454 const Matrix_f* m_2 02455 ) 02456 { 02457 uint32_t row, num_rows; 02458 uint32_t col, num_cols; 02459 float norm; 02460 float d; 02461 02462 num_rows = m_1->num_rows; 02463 num_cols = m_1->num_cols; 02464 02465 if (num_rows != m_2->num_rows || num_cols != m_2->num_cols) 02466 { 02467 return JWSC_EARG("Matrix dimensions do not match"); 02468 } 02469 02470 norm = 0; 02471 02472 for (row = 0; row < num_rows; row++) 02473 { 02474 for (col = 0; col < num_cols; col++) 02475 { 02476 d = m_1->elts[ row ][ col ] - m_2->elts[ row ][ col ]; 02477 02478 norm += d * d; 02479 } 02480 } 02481 02482 *norm_out = sqrt(norm); 02483 02484 return NULL; 02485 } 02486 02492 Error* calc_frobenius_norm_diff_d 02493 ( 02494 double* norm_out, 02495 const Matrix_d* m_1, 02496 const Matrix_d* m_2 02497 ) 02498 { 02499 uint32_t row, num_rows; 02500 uint32_t col, num_cols; 02501 double norm; 02502 double d; 02503 02504 num_rows = m_1->num_rows; 02505 num_cols = m_1->num_cols; 02506 02507 if (num_rows != m_2->num_rows || num_cols != m_2->num_cols) 02508 { 02509 return JWSC_EARG("Matrix dimensions do not match"); 02510 } 02511 02512 norm = 0; 02513 02514 for (row = 0; row < num_rows; row++) 02515 { 02516 for (col = 0; col < num_cols; col++) 02517 { 02518 d = m_1->elts[ row ][ col ] - m_2->elts[ row ][ col ]; 02519 02520 norm += d * d; 02521 } 02522 } 02523 02524 *norm_out = sqrt(norm); 02525 02526 return NULL; 02527 } 02528 02547 Error* calc_frobenius_norm_abs_diff_f 02548 ( 02549 float* norm_out, 02550 const Matrix_f* m_1, 02551 const Matrix_f* m_2 02552 ) 02553 { 02554 uint32_t row, num_rows; 02555 uint32_t col, num_cols; 02556 float norm; 02557 float d; 02558 02559 num_rows = m_1->num_rows; 02560 num_cols = m_1->num_cols; 02561 02562 if (num_rows != m_2->num_rows || num_cols != m_2->num_cols) 02563 { 02564 return JWSC_EARG("Matrix dimensions do not match"); 02565 } 02566 02567 norm = 0; 02568 02569 for (row = 0; row < num_rows; row++) 02570 { 02571 for (col = 0; col < num_cols; col++) 02572 { 02573 d = fabs(m_1->elts[ row ][ col ]) - fabs(m_2->elts[ row ][ col ]); 02574 02575 norm += d * d; 02576 } 02577 } 02578 02579 *norm_out = sqrt(norm); 02580 02581 return NULL; 02582 } 02583 02589 Error* calc_frobenius_norm_abs_diff_d 02590 ( 02591 double* norm_out, 02592 const Matrix_d* m_1, 02593 const Matrix_d* m_2 02594 ) 02595 { 02596 uint32_t row, num_rows; 02597 uint32_t col, num_cols; 02598 double norm; 02599 double d; 02600 02601 num_rows = m_1->num_rows; 02602 num_cols = m_1->num_cols; 02603 02604 if (num_rows != m_2->num_rows || num_cols != m_2->num_cols) 02605 { 02606 return JWSC_EARG("Matrix dimensions do not match"); 02607 } 02608 02609 norm = 0; 02610 02611 for (row = 0; row < num_rows; row++) 02612 { 02613 for (col = 0; col < num_cols; col++) 02614 { 02615 d = fabs(m_1->elts[ row ][ col ]) - fabs(m_2->elts[ row ][ col ]); 02616 02617 norm += d * d; 02618 } 02619 } 02620 02621 *norm_out = sqrt(norm); 02622 02623 return NULL; 02624 } 02625 02631 #if defined JWSC_HAVE_LAPACK 02632 02658 Error* lu_decompose_matrix_f 02659 ( 02660 Matrix_f** m_out, 02661 Vector_i32** pivot_out, 02662 const Matrix_f* m_in 02663 ) 02664 { 02665 int info; 02666 uint32_t pivot_len; 02667 uint32_t num_rows; 02668 uint32_t num_cols; 02669 02670 if (*m_out != m_in) 02671 { 02672 copy_matrix_f(m_out, m_in); 02673 } 02674 02675 num_rows = m_in->num_rows; 02676 num_cols = m_in->num_cols; 02677 02678 pivot_len = (num_rows < num_cols) ? num_rows : num_cols; 02679 create_vector_i32(pivot_out, pivot_len); 02680 02681 lapack_sgetrf(num_rows, num_cols, *((*m_out)->elts), num_rows, 02682 (*pivot_out)->elts, &info); 02683 02684 assert(info >= 0); 02685 if (info > 0) 02686 { 02687 if (*m_out != m_in) 02688 { 02689 free_matrix_f(*m_out); *m_out = NULL; 02690 } 02691 free_vector_i32(*pivot_out); *pivot_out = NULL; 02692 return JWSC_ECALC("Singular matrix"); 02693 } 02694 02695 return NULL; 02696 } 02697 02717 Error* lu_decompose_matrix_d 02718 ( 02719 Matrix_d** m_out, 02720 Vector_i32** pivot_out, 02721 const Matrix_d* m_in 02722 ) 02723 { 02724 int info; 02725 uint32_t pivot_len; 02726 uint32_t num_rows; 02727 uint32_t num_cols; 02728 02729 if (*m_out != m_in) 02730 { 02731 copy_matrix_d(m_out, m_in); 02732 } 02733 02734 num_rows = m_in->num_rows; 02735 num_cols = m_in->num_cols; 02736 02737 pivot_len = (num_rows < num_cols) ? num_rows : num_cols; 02738 create_vector_i32(pivot_out, pivot_len); 02739 02740 lapack_dgetrf(num_rows, num_cols, *((*m_out)->elts), num_rows, 02741 (*pivot_out)->elts, &info); 02742 02743 assert(info >= 0); 02744 if (info > 0) 02745 { 02746 if (*m_out != m_in) 02747 { 02748 free_matrix_d(*m_out); *m_out = NULL; 02749 } 02750 free_vector_i32(*pivot_out); *pivot_out = NULL; 02751 return JWSC_ECALC("Singular matrix"); 02752 } 02753 02754 return NULL; 02755 } 02756 02758 #endif 02759 02760 02761 02762 02763 #if defined JWSC_HAVE_LAPACK 02764 02783 Error* invert_matrix_f(Matrix_f** m_out, const Matrix_f* m_in) 02784 { 02785 Vector_i32* pivot = NULL; 02786 Error* e; 02787 02788 if ((e = lu_decompose_matrix_f(m_out, &pivot, m_in)) != NULL) 02789 { 02790 return e; 02791 } 02792 02793 if ((e = invert_lu_matrix_f(m_out, *m_out, pivot)) != NULL) 02794 { 02795 free_vector_i32(pivot); 02796 return e; 02797 } 02798 02799 free_vector_i32(pivot); 02800 02801 return NULL; 02802 } 02803 02816 Error* invert_matrix_d(Matrix_d** m_out, const Matrix_d* m_in) 02817 { 02818 Vector_i32* pivot = NULL; 02819 Error* e; 02820 02821 if ((e = lu_decompose_matrix_d(m_out, &pivot, m_in)) != NULL) 02822 { 02823 return e; 02824 } 02825 02826 if ((e = invert_lu_matrix_d(m_out, *m_out, pivot)) != NULL) 02827 { 02828 free_vector_i32(pivot); 02829 return e; 02830 } 02831 02832 free_vector_i32(pivot); 02833 02834 return NULL; 02835 } 02836 02838 #endif 02839 02840 02841 02842 02843 #if defined JWSC_HAVE_LAPACK 02844 02869 Error* invert_lu_matrix_f 02870 ( 02871 Matrix_f** m_out, 02872 const Matrix_f* m_in, 02873 const Vector_i32* pivot 02874 ) 02875 { 02876 int info; 02877 uint32_t N; 02878 float* work; 02879 02880 if (*m_out != m_in) 02881 { 02882 copy_matrix_f(m_out, m_in); 02883 } 02884 02885 N = m_in->num_rows; 02886 02887 if (N != m_in->num_cols) 02888 { 02889 if (*m_out != m_in) 02890 { 02891 free_matrix_f(*m_out); *m_out = NULL; 02892 } 02893 return JWSC_EARG("Matrix not square"); 02894 } 02895 02896 assert(work = malloc(N*sizeof(float))); 02897 02898 lapack_sgetri(N, *((*m_out)->elts), N, pivot->elts, 02899 work, N, &info); 02900 02901 free(work); 02902 02903 assert(info >= 0); 02904 if (info > 0) 02905 { 02906 if (*m_out != m_in) 02907 { 02908 free_matrix_f(*m_out); *m_out = NULL; 02909 } 02910 return JWSC_ECALC("Singular matrix"); 02911 } 02912 02913 return NULL; 02914 } 02915 02934 Error* invert_lu_matrix_d 02935 ( 02936 Matrix_d** m_out, 02937 const Matrix_d* m_in, 02938 const Vector_i32* pivot 02939 ) 02940 { 02941 int info; 02942 uint32_t N; 02943 double* work; 02944 02945 if (*m_out != m_in) 02946 { 02947 copy_matrix_d(m_out, m_in); 02948 } 02949 02950 N = m_in->num_rows; 02951 02952 if (N != m_in->num_cols) 02953 { 02954 if (*m_out != m_in) 02955 { 02956 free_matrix_d(*m_out); *m_out = NULL; 02957 } 02958 return JWSC_EARG("Matrix not square"); 02959 } 02960 02961 assert(work = malloc(N*sizeof(double))); 02962 02963 lapack_dgetri(N, *((*m_out)->elts), N, pivot->elts, 02964 work, N, &info); 02965 02966 free(work); 02967 02968 assert(info >= 0); 02969 if (info > 0) 02970 { 02971 if (*m_out != m_in) 02972 { 02973 free_matrix_d(*m_out); *m_out = NULL; 02974 } 02975 return JWSC_ECALC("Singular matrix"); 02976 } 02977 02978 return NULL; 02979 } 02980 02982 #endif 02983 02984 02985 02986 02987 #if defined JWSC_HAVE_LAPACK 02988 03005 Error* calc_matrix_determinant_f(float* det_out, const Matrix_f* m) 03006 { 03007 Matrix_f* lu = NULL; 03008 Vector_i32* pivot = NULL; 03009 Error* e; 03010 03011 if ((e = lu_decompose_matrix_f(&lu, &pivot, m)) != NULL) 03012 { 03013 return e; 03014 } 03015 03016 if ((e = calc_lu_matrix_determinant_f(det_out, lu, pivot)) != NULL) 03017 { 03018 free_matrix_f(lu); 03019 free_vector_i32(pivot); 03020 return e; 03021 } 03022 03023 free_matrix_f(lu); 03024 free_vector_i32(pivot); 03025 03026 return NULL; 03027 } 03028 03039 Error* calc_matrix_determinant_d(double* det_out, const Matrix_d* m) 03040 { 03041 Matrix_d* lu = NULL; 03042 Vector_i32* pivot = NULL; 03043 Error* e; 03044 03045 if ((e = lu_decompose_matrix_d(&lu, &pivot, m)) != NULL) 03046 { 03047 return e; 03048 } 03049 03050 if ((e = calc_lu_matrix_determinant_d(det_out, lu, pivot)) != NULL) 03051 { 03052 free_matrix_d(lu); 03053 free_vector_i32(pivot); 03054 return e; 03055 } 03056 03057 free_matrix_d(lu); 03058 free_vector_i32(pivot); 03059 03060 return NULL; 03061 } 03062 03064 #endif 03065 03066 03067 03068 03085 Error* calc_lu_matrix_determinant_f 03086 ( 03087 float* det_out, 03088 const Matrix_f* m, 03089 const Vector_i32* pivot 03090 ) 03091 { 03092 uint32_t N; 03093 uint32_t n; 03094 03095 N = m->num_rows; 03096 03097 if (N != m->num_cols) 03098 { 03099 return JWSC_EARG("Matrix not square"); 03100 } 03101 03102 *det_out = 1.0f; 03103 03104 for (n = 0; n < N; n++) 03105 { 03106 *det_out *= m->elts[ n ][ n ]; 03107 03108 if (pivot->elts[ n ] != (n+1)) 03109 { 03110 *det_out *= -1.0f; 03111 } 03112 } 03113 03114 return NULL; 03115 } 03116 03126 Error* calc_lu_matrix_determinant_d 03127 ( 03128 double* det_out, 03129 const Matrix_d* m, 03130 const Vector_i32* pivot 03131 ) 03132 { 03133 uint32_t N; 03134 uint32_t n; 03135 03136 N = m->num_rows; 03137 03138 if (N != m->num_cols) 03139 { 03140 return JWSC_EARG("Matrix not square"); 03141 } 03142 03143 *det_out = 1.0; 03144 03145 for (n = 0; n < N; n++) 03146 { 03147 *det_out *= m->elts[ n ][ n ]; 03148 03149 if (pivot->elts[ n ] != (n+1)) 03150 { 03151 *det_out *= -1.0; 03152 } 03153 } 03154 03155 return NULL; 03156 } 03157 03163 #if defined JWSC_HAVE_LAPACK 03164 03193 Error* singular_value_decompose_matrix_f 03194 ( 03195 Matrix_f** U_out, 03196 Vector_f** S_out, 03197 Matrix_f** Vt_out, 03198 const Matrix_f* M 03199 ) 03200 { 03201 uint32_t num_rows; 03202 uint32_t num_cols; 03203 03204 float* work; 03205 int lwork; 03206 int* iwork; 03207 int info; 03208 int max_MN; 03209 int min_MN; 03210 03211 Matrix_f* M_copy = NULL; 03212 03213 copy_matrix_f(&M_copy, M); 03214 03215 num_rows = M->num_rows; 03216 num_cols = M->num_cols; 03217 03218 min_MN = num_rows; 03219 max_MN = num_cols; 03220 if (min_MN > max_MN) 03221 { 03222 min_MN = num_cols; 03223 max_MN = num_rows; 03224 } 03225 03226 create_matrix_f(U_out, num_rows, num_rows); 03227 create_vector_f(S_out, min_MN); 03228 create_matrix_f(Vt_out, num_cols, num_cols); 03229 03230 if (max_MN >= 4*min_MN*(min_MN+1)) 03231 lwork = 3*min_MN*min_MN + max_MN; 03232 else 03233 lwork = 3*min_MN*min_MN + 4*min_MN*(min_MN+1); 03234 03235 assert(work = malloc(lwork*sizeof(float))); 03236 assert(iwork = malloc(8*min_MN*sizeof(int))); 03237 03238 lapack_sgesdd('A', num_rows, num_cols, *(M_copy->elts), num_rows, 03239 (*S_out)->elts, *((*U_out)->elts), num_rows, *((*Vt_out)->elts), 03240 num_cols, work, lwork, iwork, &info); 03241 03242 free(work); 03243 free(iwork); 03244 03245 free_matrix_f(M_copy); 03246 03247 assert(info >= 0); 03248 if (info > 0) 03249 { 03250 free_matrix_f(*U_out); *U_out = NULL; 03251 free_vector_f(*S_out); *S_out = NULL; 03252 free_matrix_f(*Vt_out); *Vt_out = NULL; 03253 return JWSC_ECALC("SVD calculation failed"); 03254 } 03255 03256 return NULL; 03257 } 03258 03281 Error* singular_value_decompose_matrix_d 03282 ( 03283 Matrix_d** U_out, 03284 Vector_d** S_out, 03285 Matrix_d** Vt_out, 03286 const Matrix_d* M 03287 ) 03288 { 03289 uint32_t num_rows; 03290 uint32_t num_cols; 03291 03292 double* work; 03293 int lwork; 03294 int* iwork; 03295 int info; 03296 int max_MN; 03297 int min_MN; 03298 03299 Matrix_d* M_copy = NULL; 03300 03301 copy_matrix_d(&M_copy, M); 03302 03303 num_rows = M->num_rows; 03304 num_cols = M->num_cols; 03305 03306 min_MN = num_rows; 03307 max_MN = num_cols; 03308 if (min_MN > max_MN) 03309 { 03310 min_MN = num_cols; 03311 max_MN = num_rows; 03312 } 03313 03314 create_matrix_d(U_out, num_rows, num_rows); 03315 create_vector_d(S_out, min_MN); 03316 create_matrix_d(Vt_out, num_cols, num_cols); 03317 03318 if (max_MN >= 4*min_MN*(min_MN+1)) 03319 lwork = 3*min_MN*min_MN + max_MN; 03320 else 03321 lwork = 3*min_MN*min_MN + 4*min_MN*(min_MN+1); 03322 03323 assert(work = malloc(lwork*sizeof(double))); 03324 assert(iwork = malloc(8*min_MN*sizeof(int))); 03325 03326 lapack_dgesdd('A', num_rows, num_cols, *(M_copy->elts), num_rows, 03327 (*S_out)->elts, *((*U_out)->elts), num_rows, *((*Vt_out)->elts), 03328 num_cols, work, lwork, iwork, &info); 03329 03330 free(work); 03331 free(iwork); 03332 03333 free_matrix_d(M_copy); 03334 03335 assert(info >= 0); 03336 if (info > 0) 03337 { 03338 free_matrix_d(*U_out); *U_out = NULL; 03339 free_vector_d(*S_out); *S_out = NULL; 03340 free_matrix_d(*Vt_out); *Vt_out = NULL; 03341 return JWSC_ECALC("SVD calculation failed"); 03342 } 03343 03344 return NULL; 03345 } 03346 03348 #endif 03349 03350 03351 03352 03353 #if defined JWSC_HAVE_LAPACK 03354 03388 Error* solve_real_symmetric_matrix_eigenproblem_f 03389 ( 03390 Matrix_f** V_out, 03391 Vector_f** D_out, 03392 const Matrix_f* M 03393 ) 03394 { 03395 uint32_t num_rows; 03396 uint32_t num_cols; 03397 03398 float* work; 03399 int lwork; 03400 int info; 03401 03402 num_rows = M->num_rows; 03403 num_cols = M->num_cols; 03404 03405 if (num_rows != num_cols) 03406 { 03407 return JWSC_EARG("Matrix not symmetric"); 03408 } 03409 03410 copy_matrix_f(V_out, M); 03411 create_vector_f(D_out, num_rows); 03412 03413 lwork = 3*num_rows; 03414 03415 assert(work = malloc(lwork*sizeof(float))); 03416 03417 lapack_ssyev('V', 'U', num_rows, *((*V_out)->elts), num_rows, 03418 (*D_out)->elts, work, lwork, &info); 03419 03420 free(work); 03421 03422 assert(info >= 0); 03423 if (info > 0) 03424 { 03425 free_matrix_f(*V_out); *V_out = NULL; 03426 free_vector_f(*D_out); *D_out = NULL; 03427 return JWSC_ECALC("Eigenproblem solver failed"); 03428 } 03429 03430 return NULL; 03431 } 03432 03460 Error* solve_real_symmetric_matrix_eigenproblem_d 03461 ( 03462 Matrix_d** V_out, 03463 Vector_d** D_out, 03464 const Matrix_d* M 03465 ) 03466 { 03467 uint32_t num_rows; 03468 uint32_t num_cols; 03469 03470 double* work; 03471 int lwork; 03472 int info; 03473 03474 num_rows = M->num_rows; 03475 num_cols = M->num_cols; 03476 03477 if (num_rows != num_cols) 03478 { 03479 return JWSC_EARG("Matrix not symmetric"); 03480 } 03481 03482 copy_matrix_d(V_out, M); 03483 create_vector_d(D_out, num_rows); 03484 03485 lwork = 3*num_rows; 03486 03487 assert(work = malloc(lwork*sizeof(double))); 03488 03489 lapack_dsyev('V', 'U', num_rows, *((*V_out)->elts), num_rows, 03490 (*D_out)->elts, work, lwork, &info); 03491 03492 free(work); 03493 03494 assert(info >= 0); 03495 if (info > 0) 03496 { 03497 free_matrix_d(*V_out); *V_out = NULL; 03498 free_vector_d(*D_out); *D_out = NULL; 03499 return JWSC_ECALC("Eigenproblem solver failed"); 03500 } 03501 03502 return NULL; 03503 } 03504 03506 #endif 03507 03508 03509 03510 03511 #if defined JWSC_HAVE_LAPACK 03512 03537 Error* pseudoinvert_matrix_no_svd_f 03538 ( 03539 Matrix_f** M_out, 03540 const Matrix_f* M_in 03541 ) 03542 { 03543 Matrix_f* Mt = NULL; 03544 Error* err; 03545 03546 transpose_matrix_f(&Mt, M_in); 03547 03548 assert(multiply_matrices_f(M_out, Mt, M_in) == NULL); 03549 03550 if ((err = invert_matrix_f(M_out, *M_out)) != NULL) 03551 { 03552 if (*M_out != M_in) 03553 { 03554 free_matrix_f(*M_out); *M_out = NULL; 03555 } 03556 free_error(err); 03557 return JWSC_ECALC("Pseudoinverse calculation failed"); 03558 } 03559 03560 assert(multiply_matrices_f(M_out, *M_out, Mt) == NULL); 03561 03562 free_matrix_f(Mt); 03563 03564 return NULL; 03565 } 03566 03585 Error* pseudoinvert_matrix_no_svd_d 03586 ( 03587 Matrix_d** M_out, 03588 const Matrix_d* M_in 03589 ) 03590 { 03591 Matrix_d* Mt = NULL; 03592 Error* err; 03593 03594 transpose_matrix_d(&Mt, M_in); 03595 03596 assert(multiply_matrices_d(M_out, Mt, M_in) == NULL); 03597 03598 if ((err = invert_matrix_d(M_out, *M_out)) != NULL) 03599 { 03600 if (*M_out != M_in) 03601 { 03602 free_matrix_d(*M_out); *M_out = NULL; 03603 } 03604 free_error(err); 03605 return JWSC_ECALC("Pseudoinverse calculation failed"); 03606 } 03607 03608 assert(multiply_matrices_d(M_out, *M_out, Mt) == NULL); 03609 03610 free_matrix_d(Mt); 03611 03612 return NULL; 03613 } 03614 03616 #endif 03617 03618 03619 03620 03621 #if defined JWSC_HAVE_LAPACK 03622 03650 Error* pseudoinvert_matrix_f 03651 ( 03652 Matrix_f** M_out, 03653 const Matrix_f* M_in 03654 ) 03655 { 03656 uint32_t i ; 03657 Error* err; 03658 03659 Matrix_f* U = NULL; 03660 Vector_f* S = NULL; 03661 Matrix_f* T = NULL; 03662 Matrix_f* V = NULL; 03663 03664 if ((err = singular_value_decompose_matrix_f(&U, &S, &V, M_in)) != NULL) 03665 { 03666 if (*M_out != M_in) 03667 { 03668 free_matrix_f(*M_out); *M_out = NULL; 03669 } 03670 free_error(err); 03671 return JWSC_ECALC("Pseudoinverse calculation with SVD failed"); 03672 } 03673 03674 transpose_matrix_f(&U, U); 03675 transpose_matrix_f(&V, V); 03676 create_zero_matrix_f(&T, M_in->num_cols, M_in->num_rows); 03677 03678 for (i = 0; i < S->num_elts; i++) 03679 { 03680 if (S->elts[ i ] > 1.0e-16f) 03681 { 03682 T->elts[ i ][ i ] = 1.0f / S->elts[ i ]; 03683 } 03684 } 03685 03686 assert(multiply_matrices_f(M_out, T, U) == NULL); 03687 assert(multiply_matrices_f(M_out, V, *M_out) == NULL); 03688 03689 free_matrix_f(U); 03690 free_vector_f(S); 03691 free_matrix_f(T); 03692 free_matrix_f(V); 03693 03694 return NULL; 03695 } 03696 03718 Error* pseudoinvert_matrix_d 03719 ( 03720 Matrix_d** M_out, 03721 const Matrix_d* M_in 03722 ) 03723 { 03724 uint32_t i ; 03725 Error* err; 03726 03727 Matrix_d* U = NULL; 03728 Vector_d* S = NULL; 03729 Matrix_d* T = NULL; 03730 Matrix_d* V = NULL; 03731 03732 if ((err = singular_value_decompose_matrix_d(&U, &S, &V, M_in)) != NULL) 03733 { 03734 if (*M_out != M_in) 03735 { 03736 free_matrix_d(*M_out); *M_out = NULL; 03737 } 03738 free_error(err); 03739 return JWSC_ECALC("Pseudoinverse calculation with SVD failed"); 03740 } 03741 03742 transpose_matrix_d(&U, U); 03743 transpose_matrix_d(&V, V); 03744 create_zero_matrix_d(&T, M_in->num_cols, M_in->num_rows); 03745 03746 for (i = 0; i < S->num_elts; i++) 03747 { 03748 if (S->elts[ i ] > 1.0e-24) 03749 { 03750 T->elts[ i ][ i ] = 1.0 / S->elts[ i ]; 03751 } 03752 } 03753 03754 assert(multiply_matrices_d(M_out, T, U) == NULL); 03755 assert(multiply_matrices_d(M_out, V, *M_out) == NULL); 03756 03757 free_matrix_d(U); 03758 free_vector_d(S); 03759 free_matrix_d(T); 03760 free_matrix_d(V); 03761 03762 return NULL; 03763 } 03764 03766 #endif 03767 03768 03769 03770 03787 void create_euler_rotation_matrix_f 03788 ( 03789 Matrix_f** m_out, 03790 float phi, 03791 float theta, 03792 float psi 03793 ) 03794 { 03795 float cos_phi, sin_phi; 03796 float cos_theta, sin_theta; 03797 float cos_psi, sin_psi; 03798 03799 cos_phi = (float)cos(phi); 03800 sin_phi = (float)sin(phi); 03801 cos_theta = (float)cos(theta); 03802 sin_theta = (float)sin(theta); 03803 cos_psi = (float)cos(psi); 03804 sin_psi = (float)sin(psi); 03805 03806 create_matrix_f(m_out, 3, 3); 03807 (*m_out)->elts[0][0] = cos_psi*cos_phi - cos_theta*sin_phi*sin_psi; 03808 (*m_out)->elts[0][1] = cos_psi*sin_phi + cos_theta*cos_phi*sin_psi; 03809 (*m_out)->elts[0][2] = sin_psi*sin_theta; 03810 (*m_out)->elts[1][0] = -sin_psi*cos_phi - cos_theta*sin_phi*cos_psi; 03811 (*m_out)->elts[1][1] = -sin_psi*sin_phi + cos_theta*cos_phi*cos_psi; 03812 (*m_out)->elts[1][2] = cos_psi*sin_theta; 03813 (*m_out)->elts[2][0] = sin_theta*sin_phi; 03814 (*m_out)->elts[2][1] = -sin_theta*cos_phi; 03815 (*m_out)->elts[2][2] = cos_theta; 03816 } 03817 03818 03826 void create_euler_rotation_matrix_d 03827 ( 03828 Matrix_d** m_out, 03829 float phi, 03830 float theta, 03831 float psi 03832 ) 03833 { 03834 double cos_phi, sin_phi; 03835 double cos_theta, sin_theta; 03836 double cos_psi, sin_psi; 03837 03838 cos_phi = cos(phi); 03839 sin_phi = sin(phi); 03840 cos_theta = cos(theta); 03841 sin_theta = sin(theta); 03842 cos_psi = cos(psi); 03843 sin_psi = sin(psi); 03844 03845 create_matrix_d(m_out, 3, 3); 03846 (*m_out)->elts[0][0] = cos_psi*cos_phi - cos_theta*sin_phi*sin_psi; 03847 (*m_out)->elts[0][1] = cos_psi*sin_phi + cos_theta*cos_phi*sin_psi; 03848 (*m_out)->elts[0][2] = sin_psi*sin_theta; 03849 (*m_out)->elts[1][0] = -sin_psi*cos_phi - cos_theta*sin_phi*cos_psi; 03850 (*m_out)->elts[1][1] = -sin_psi*sin_phi + cos_theta*cos_phi*cos_psi; 03851 (*m_out)->elts[1][2] = cos_psi*sin_theta; 03852 (*m_out)->elts[2][0] = sin_theta*sin_phi; 03853 (*m_out)->elts[2][1] = -sin_theta*cos_phi; 03854 (*m_out)->elts[2][2] = cos_theta; 03855 } 03856 03884 Error* create_3d_rotation_matrix_1_f 03885 ( 03886 Matrix_f** m_out, 03887 float phi, 03888 const Vector_f* v 03889 ) 03890 { 03891 if (v->num_elts != 3) 03892 { 03893 free_matrix_f(*m_out); *m_out = NULL; 03894 return JWSC_EARG("Vector for 3D rotation must have three dimensions"); 03895 } 03896 03897 return create_3d_rotation_matrix_2_f(m_out, phi, 03898 v->elts[0], v->elts[1], v->elts[2]); 03899 } 03900 03901 03917 Error* create_3d_rotation_matrix_1_d 03918 ( 03919 Matrix_d** m_out, 03920 double phi, 03921 const Vector_d* v 03922 ) 03923 { 03924 if (v->num_elts != 3) 03925 { 03926 free_matrix_d(*m_out); *m_out = NULL; 03927 return JWSC_EARG("Vector for 3D rotation must have three dimensions"); 03928 } 03929 03930 return create_3d_rotation_matrix_2_d(m_out, phi, 03931 v->elts[0], v->elts[1], v->elts[2]); 03932 } 03933 03934 03951 Error* create_3d_rotation_matrix_2_f 03952 ( 03953 Matrix_f** m_out, 03954 float phi, 03955 float x, 03956 float y, 03957 float z 03958 ) 03959 { 03960 float cos_phi, cos_theta, cos_psi; 03961 float sin_phi, sin_theta, sin_psi; 03962 float mag_xyz, mag_xy; 03963 03964 Matrix_f* R_phi = NULL; 03965 Matrix_f* R_theta = NULL; 03966 Matrix_f* R_psi = NULL; 03967 03968 mag_xyz = sqrt(x*x + y*y + z*z); 03969 03970 if (mag_xyz < 1.0e-8f) 03971 { 03972 free_matrix_f(*m_out); *m_out = NULL; 03973 return JWSC_EARG("Magnitude of rotation vector too small"); 03974 } 03975 03976 /* psi used to rotate around z-axis to put vector on the yz-plane. */ 03977 mag_xy = sqrt(x*x + y*y); 03978 if (mag_xy > 1.0e-8f) 03979 { 03980 cos_psi = y / mag_xy; 03981 sin_psi = x / mag_xy; 03982 } 03983 else 03984 { 03985 cos_psi = 0.0f; 03986 sin_psi = 1.0f; 03987 } 03988 03989 /* theta used to rotate around x-axis to put vector onto the z-axis. */ 03990 cos_theta = z / mag_xyz; 03991 sin_theta = mag_xy / mag_xyz; 03992 03993 /* phi used to rotate around z-axis. This is actually the angle to rotate 03994 * around the vector. */ 03995 cos_phi = (float)cos((double)phi); 03996 sin_phi = (float)sin((double)phi); 03997 03998 create_identity_matrix_f(&R_phi, 3); 03999 R_phi->elts[ 0 ][ 0 ] = cos_phi; 04000 R_phi->elts[ 0 ][ 1 ] = sin_phi; 04001 R_phi->elts[ 1 ][ 0 ] = -sin_phi; 04002 R_phi->elts[ 1 ][ 1 ] = cos_phi; 04003 04004 create_identity_matrix_f(&R_theta, 3); 04005 R_theta->elts[ 1 ][ 1 ] = cos_theta; 04006 R_theta->elts[ 1 ][ 2 ] = sin_theta; 04007 R_theta->elts[ 2 ][ 1 ] = -sin_theta; 04008 R_theta->elts[ 2 ][ 2 ] = cos_theta; 04009 04010 create_identity_matrix_f(&R_psi, 3); 04011 R_psi->elts[ 0 ][ 0 ] = cos_psi; 04012 R_psi->elts[ 0 ][ 1 ] = sin_psi; 04013 R_psi->elts[ 1 ][ 0 ] = -sin_psi; 04014 R_psi->elts[ 1 ][ 1 ] = cos_psi; 04015 04016 /* *m_out = R_psi * R_theta * R_phi * R_theta^T * R_psi^T */ 04017 multiply_matrices_f(m_out, R_psi, R_theta); 04018 multiply_matrices_f(m_out, *m_out, R_phi); 04019 transpose_matrix_f(&R_theta, R_theta); 04020 transpose_matrix_f(&R_psi, R_psi); 04021 multiply_matrices_f(m_out, *m_out, R_theta); 04022 multiply_matrices_f(m_out, *m_out, R_psi); 04023 04024 free_matrix_f(R_phi); 04025 free_matrix_f(R_theta); 04026 free_matrix_f(R_psi); 04027 04028 return NULL; 04029 } 04030 04031 04048 Error* create_3d_rotation_matrix_2_d 04049 ( 04050 Matrix_d** m_out, 04051 double phi, 04052 double x, 04053 double y, 04054 double z 04055 ) 04056 { 04057 double cos_phi, cos_theta, cos_psi; 04058 double sin_phi, sin_theta, sin_psi; 04059 double mag_xyz, mag_xy; 04060 04061 Matrix_d* R_phi = NULL; 04062 Matrix_d* R_theta = NULL; 04063 Matrix_d* R_psi = NULL; 04064 04065 mag_xyz = sqrt(x*x + y*y + z*z); 04066 04067 if (mag_xyz < 1.0e-8) 04068 { 04069 free_matrix_d(*m_out); *m_out = NULL; 04070 return JWSC_EARG("Magnitude of rotation vector too small"); 04071 } 04072 04073 /* psi used to rotate around z-axis to put vector on the yz-plane. */ 04074 mag_xy = sqrt(x*x + y*y); 04075 if (mag_xy > 1.0e-8) 04076 { 04077 cos_psi = y / mag_xy; 04078 sin_psi = x / mag_xy; 04079 } 04080 else 04081 { 04082 cos_psi = 0.0; 04083 sin_psi = 1.0; 04084 } 04085 04086 /* theta used to rotate around x-axis to put vector onto the z-axis. */ 04087 cos_theta = z / mag_xyz; 04088 sin_theta = mag_xy / mag_xyz; 04089 04090 /* phi used to rotate around z-axis. This is actually the angle to rotate 04091 * around the vector. */ 04092 cos_phi = cos(phi); 04093 sin_phi = sin(phi); 04094 04095 create_identity_matrix_d(&R_phi, 3); 04096 R_phi->elts[ 0 ][ 0 ] = cos_phi; 04097 R_phi->elts[ 0 ][ 1 ] = sin_phi; 04098 R_phi->elts[ 1 ][ 0 ] = -sin_phi; 04099 R_phi->elts[ 1 ][ 1 ] = cos_phi; 04100 04101 create_identity_matrix_d(&R_theta, 3); 04102 R_theta->elts[ 1 ][ 1 ] = cos_theta; 04103 R_theta->elts[ 1 ][ 2 ] = sin_theta; 04104 R_theta->elts[ 2 ][ 1 ] = -sin_theta; 04105 R_theta->elts[ 2 ][ 2 ] = cos_theta; 04106 04107 create_identity_matrix_d(&R_psi, 3); 04108 R_psi->elts[ 0 ][ 0 ] = cos_psi; 04109 R_psi->elts[ 0 ][ 1 ] = sin_psi; 04110 R_psi->elts[ 1 ][ 0 ] = -sin_psi; 04111 R_psi->elts[ 1 ][ 1 ] = cos_psi; 04112 04113 /* *m_out = R_psi * R_theta * R_phi * R_theta^T * R_psi^T */ 04114 multiply_matrices_d(m_out, R_psi, R_theta); 04115 multiply_matrices_d(m_out, *m_out, R_phi); 04116 transpose_matrix_d(&R_theta, R_theta); 04117 transpose_matrix_d(&R_psi, R_psi); 04118 multiply_matrices_d(m_out, *m_out, R_theta); 04119 multiply_matrices_d(m_out, *m_out, R_psi); 04120 04121 free_matrix_d(R_phi); 04122 free_matrix_d(R_theta); 04123 free_matrix_d(R_psi); 04124 04125 return NULL; 04126 } 04127 04156 Error* create_3d_homo_rotation_matrix_1_f 04157 ( 04158 Matrix_f** m_out, 04159 float phi, 04160 const Vector_f* v 04161 ) 04162 { 04163 if (v->num_elts < 3) 04164 { 04165 free_matrix_f(*m_out); *m_out = NULL; 04166 return JWSC_EARG("Vector for 3D homogeneous rotation is not 3D"); 04167 } 04168 04169 return create_3d_homo_rotation_matrix_2_f(m_out, phi, 04170 v->elts[0], v->elts[1], v->elts[2]); 04171 } 04172 04173 04190 Error* create_3d_homo_rotation_matrix_1_d 04191 ( 04192 Matrix_d** m_out, 04193 double phi, 04194 const Vector_d* v 04195 ) 04196 { 04197 if (v->num_elts < 3) 04198 { 04199 free_matrix_d(*m_out); *m_out = NULL; 04200 return JWSC_EARG("Vector for 3D homogeneous rotation is not 3D"); 04201 } 04202 04203 return create_3d_homo_rotation_matrix_2_d(m_out, phi, 04204 v->elts[0], v->elts[1], v->elts[2]); 04205 } 04206 04207 04224 Error* create_3d_homo_rotation_matrix_2_f 04225 ( 04226 Matrix_f** m_out, 04227 float phi, 04228 float x, 04229 float y, 04230 float z 04231 ) 04232 { 04233 float cos_phi, cos_theta, cos_psi; 04234 float sin_phi, sin_theta, sin_psi; 04235 float mag_xyz, mag_xy; 04236 04237 Matrix_f* R_phi = NULL; 04238 Matrix_f* R_theta = NULL; 04239 Matrix_f* R_psi = NULL; 04240 04241 mag_xyz = sqrt(x*x + y*y + z*z); 04242 04243 if (mag_xyz < 1.0e-8f) 04244 { 04245 free_matrix_f(*m_out); *m_out = NULL; 04246 return JWSC_EARG("Magnitude of rotation vector too small"); 04247 } 04248 04249 /* psi used to rotate around z-axis to put vector on the yz-plane. */ 04250 mag_xy = sqrt(x*x + y*y); 04251 if (mag_xy > 1.0e-8f) 04252 { 04253 cos_psi = y / mag_xy; 04254 sin_psi = x / mag_xy; 04255 } 04256 else 04257 { 04258 cos_psi = 0.0f; 04259 sin_psi = 1.0f; 04260 } 04261 04262 /* theta used to rotate around x-axis to put vector onto the z-axis. */ 04263 cos_theta = z / mag_xyz; 04264 sin_theta = mag_xy / mag_xyz; 04265 04266 /* phi used to rotate around z-axis. This is actually the angle to rotate 04267 * around the vector. */ 04268 cos_phi = (float)cos((double)phi); 04269 sin_phi = (float)sin((double)phi); 04270 04271 create_identity_matrix_f(&R_phi, 4); 04272 R_phi->elts[ 0 ][ 0 ] = cos_phi; 04273 R_phi->elts[ 0 ][ 1 ] = sin_phi; 04274 R_phi->elts[ 1 ][ 0 ] = -sin_phi; 04275 R_phi->elts[ 1 ][ 1 ] = cos_phi; 04276 04277 create_identity_matrix_f(&R_theta, 4); 04278 R_theta->elts[ 1 ][ 1 ] = cos_theta; 04279 R_theta->elts[ 1 ][ 2 ] = sin_theta; 04280 R_theta->elts[ 2 ][ 1 ] = -sin_theta; 04281 R_theta->elts[ 2 ][ 2 ] = cos_theta; 04282 04283 create_identity_matrix_f(&R_psi, 4); 04284 R_psi->elts[ 0 ][ 0 ] = cos_psi; 04285 R_psi->elts[ 0 ][ 1 ] = sin_psi; 04286 R_psi->elts[ 1 ][ 0 ] = -sin_psi; 04287 R_psi->elts[ 1 ][ 1 ] = cos_psi; 04288 04289 /* *m_out = R_psi * R_theta * R_phi * R_theta^T * R_psi^T */ 04290 multiply_matrices_f(m_out, R_psi, R_theta); 04291 multiply_matrices_f(m_out, *m_out, R_phi); 04292 transpose_matrix_f(&R_theta, R_theta); 04293 transpose_matrix_f(&R_psi, R_psi); 04294 multiply_matrices_f(m_out, *m_out, R_theta); 04295 multiply_matrices_f(m_out, *m_out, R_psi); 04296 04297 free_matrix_f(R_phi); 04298 free_matrix_f(R_theta); 04299 free_matrix_f(R_psi); 04300 04301 return NULL; 04302 } 04303 04304 04321 Error* create_3d_homo_rotation_matrix_2_d 04322 ( 04323 Matrix_d** m_out, 04324 double phi, 04325 double x, 04326 double y, 04327 double z 04328 ) 04329 { 04330 double cos_phi, cos_theta, cos_psi; 04331 double sin_phi, sin_theta, sin_psi; 04332 double mag_xyz, mag_xy; 04333 04334 Matrix_d* R_phi = NULL; 04335 Matrix_d* R_theta = NULL; 04336 Matrix_d* R_psi = NULL; 04337 04338 mag_xyz = sqrt(x*x + y*y + z*z); 04339 04340 if (mag_xyz < 1.0e-8) 04341 { 04342 free_matrix_d(*m_out); *m_out = NULL; 04343 return JWSC_EARG("Magnitude of rotation vector too small"); 04344 } 04345 04346 /* psi used to rotate around z-axis to put vector on the yz-plane. */ 04347 mag_xy = sqrt(x*x + y*y); 04348 if (mag_xy > 1.0e-8) 04349 { 04350 cos_psi = y / mag_xy; 04351 sin_psi = x / mag_xy; 04352 } 04353 else 04354 { 04355 cos_psi = 0.0; 04356 sin_psi = 1.0; 04357 } 04358 04359 /* theta used to rotate around x-axis to put vector onto the z-axis. */ 04360 cos_theta = z / mag_xyz; 04361 sin_theta = mag_xy / mag_xyz; 04362 04363 /* phi used to rotate around z-axis. This is actually the angle to rotate 04364 * around the vector. */ 04365 cos_phi = cos(phi); 04366 sin_phi = sin(phi); 04367 04368 create_identity_matrix_d(&R_phi, 4); 04369 R_phi->elts[ 0 ][ 0 ] = cos_phi; 04370 R_phi->elts[ 0 ][ 1 ] = sin_phi; 04371 R_phi->elts[ 1 ][ 0 ] = -sin_phi; 04372 R_phi->elts[ 1 ][ 1 ] = cos_phi; 04373 04374 create_identity_matrix_d(&R_theta, 4); 04375 R_theta->elts[ 1 ][ 1 ] = cos_theta; 04376 R_theta->elts[ 1 ][ 2 ] = sin_theta; 04377 R_theta->elts[ 2 ][ 1 ] = -sin_theta; 04378 R_theta->elts[ 2 ][ 2 ] = cos_theta; 04379 04380 create_identity_matrix_d(&R_psi, 4); 04381 R_psi->elts[ 0 ][ 0 ] = cos_psi; 04382 R_psi->elts[ 0 ][ 1 ] = sin_psi; 04383 R_psi->elts[ 1 ][ 0 ] = -sin_psi; 04384 R_psi->elts[ 1 ][ 1 ] = cos_psi; 04385 04386 /* *m_out = R_psi * R_theta * R_phi * R_theta^T * R_psi^T */ 04387 multiply_matrices_d(m_out, R_psi, R_theta); 04388 multiply_matrices_d(m_out, *m_out, R_phi); 04389 transpose_matrix_d(&R_theta, R_theta); 04390 transpose_matrix_d(&R_psi, R_psi); 04391 multiply_matrices_d(m_out, *m_out, R_theta); 04392 multiply_matrices_d(m_out, *m_out, R_psi); 04393 04394 free_matrix_d(R_phi); 04395 free_matrix_d(R_theta); 04396 free_matrix_d(R_psi); 04397 04398 return NULL; 04399 } 04400 04426 Error* create_3d_scaling_matrix_1_f 04427 ( 04428 Matrix_f** m_out, 04429 const Vector_f* v 04430 ) 04431 { 04432 if (v->num_elts != 3) 04433 { 04434 free_matrix_f(*m_out); *m_out = NULL; 04435 return JWSC_EARG("Vector for 3D scaling is not 3D"); 04436 } 04437 04438 return create_3d_scaling_matrix_2_f(m_out, 04439 v->elts[0], v->elts[1], v->elts[2]); 04440 } 04441 04442 04456 Error* create_3d_scaling_matrix_1_d 04457 ( 04458 Matrix_d** m_out, 04459 const Vector_d* v 04460 ) 04461 { 04462 if (v->num_elts != 3) 04463 { 04464 free_matrix_d(*m_out); *m_out = NULL; 04465 return JWSC_EARG("Vector for 3D scaling is not 3D"); 04466 } 04467 04468 return create_3d_scaling_matrix_2_d(m_out, 04469 v->elts[0], v->elts[1], v->elts[2]); 04470 } 04471 04472 04485 Error* create_3d_scaling_matrix_2_f 04486 ( 04487 Matrix_f** m_out, 04488 float x, 04489 float y, 04490 float z 04491 ) 04492 { 04493 create_zero_matrix_f(m_out, 3, 3); 04494 (*m_out)->elts[ 0 ][ 0 ] = x; 04495 (*m_out)->elts[ 1 ][ 1 ] = y; 04496 (*m_out)->elts[ 2 ][ 2 ] = z; 04497 04498 return NULL; 04499 } 04500 04501 04514 Error* create_3d_scaling_matrix_2_d 04515 ( 04516 Matrix_d** m_out, 04517 double x, 04518 double y, 04519 double z 04520 ) 04521 { 04522 create_zero_matrix_d(m_out, 3, 3); 04523 (*m_out)->elts[ 0 ][ 0 ] = x; 04524 (*m_out)->elts[ 1 ][ 1 ] = y; 04525 (*m_out)->elts[ 2 ][ 2 ] = z; 04526 04527 return NULL; 04528 } 04529 04556 Error* create_3d_homo_scaling_matrix_1_f 04557 ( 04558 Matrix_f** m_out, 04559 const Vector_f* v 04560 ) 04561 { 04562 if (v->num_elts < 3) 04563 { 04564 free_matrix_f(*m_out); *m_out = NULL; 04565 return JWSC_EARG("Vector for 3D homogeneous scaling is not 3D"); 04566 } 04567 04568 return create_3d_homo_scaling_matrix_2_f(m_out, 04569 v->elts[0], v->elts[1], v->elts[2]); 04570 } 04571 04572 04587 Error* create_3d_homo_scaling_matrix_1_d 04588 ( 04589 Matrix_d** m_out, 04590 const Vector_d* v 04591 ) 04592 { 04593 if (v->num_elts < 3) 04594 { 04595 free_matrix_d(*m_out); *m_out = NULL; 04596 return JWSC_EARG("Vector for 3D homogeneous scaling is not 3D"); 04597 } 04598 04599 return create_3d_homo_scaling_matrix_2_d(m_out, 04600 v->elts[0], v->elts[1], v->elts[2]); 04601 } 04602 04603 04616 Error* create_3d_homo_scaling_matrix_2_f 04617 ( 04618 Matrix_f** m_out, 04619 float x, 04620 float y, 04621 float z 04622 ) 04623 { 04624 create_identity_matrix_f(m_out, 4); 04625 (*m_out)->elts[ 0 ][ 0 ] = x; 04626 (*m_out)->elts[ 1 ][ 1 ] = y; 04627 (*m_out)->elts[ 2 ][ 2 ] = z; 04628 04629 return NULL; 04630 } 04631 04632 04645 Error* create_3d_homo_scaling_matrix_2_d 04646 ( 04647 Matrix_d** m_out, 04648 double x, 04649 double y, 04650 double z 04651 ) 04652 { 04653 create_identity_matrix_d(m_out, 4); 04654 (*m_out)->elts[ 0 ][ 0 ] = x; 04655 (*m_out)->elts[ 1 ][ 1 ] = y; 04656 (*m_out)->elts[ 2 ][ 2 ] = z; 04657 04658 return NULL; 04659 } 04660 04687 Error* create_3d_homo_translation_matrix_1_f 04688 ( 04689 Matrix_f** m_out, 04690 const Vector_f* v 04691 ) 04692 { 04693 if (v->num_elts < 3) 04694 { 04695 free_matrix_f(*m_out); *m_out = NULL; 04696 return JWSC_EARG("Vector for 3D homogeneous translation is not 3D"); 04697 } 04698 04699 return create_3d_homo_translation_matrix_2_f(m_out, 04700 v->elts[0], v->elts[1], v->elts[2]); 04701 } 04702 04703 04718 Error* create_3d_homo_translation_matrix_1_d 04719 ( 04720 Matrix_d** m_out, 04721 const Vector_d* v 04722 ) 04723 { 04724 if (v->num_elts < 3) 04725 { 04726 free_matrix_d(*m_out); *m_out = NULL; 04727 return JWSC_EARG("Vector for 3D homogeneous translation is not 3D"); 04728 } 04729 04730 return create_3d_homo_translation_matrix_2_d(m_out, 04731 v->elts[0], v->elts[1], v->elts[2]); 04732 } 04733 04734 04747 Error* create_3d_homo_translation_matrix_2_f 04748 ( 04749 Matrix_f** m_out, 04750 float x, 04751 float y, 04752 float z 04753 ) 04754 { 04755 create_identity_matrix_f(m_out, 4); 04756 (*m_out)->elts[ 0 ][ 3 ] = x; 04757 (*m_out)->elts[ 1 ][ 3 ] = y; 04758 (*m_out)->elts[ 2 ][ 3 ] = z; 04759 04760 return NULL; 04761 } 04762 04763 04776 Error* create_3d_homo_translation_matrix_2_d 04777 ( 04778 Matrix_d** m_out, 04779 double x, 04780 double y, 04781 double z 04782 ) 04783 { 04784 create_identity_matrix_d(m_out, 4); 04785 (*m_out)->elts[ 0 ][ 3 ] = x; 04786 (*m_out)->elts[ 1 ][ 3 ] = y; 04787 (*m_out)->elts[ 2 ][ 3 ] = z; 04788 04789 return NULL; 04790 } 04791