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 00051 #include <jwsc/config.h> 00052 00053 #include <stdlib.h> 00054 #include <assert.h> 00055 00056 #include "jwsc/math/lapack.h" 00057 00058 #ifdef JWSC_HAVE_DMALLOC 00059 #include <dmalloc.h> 00060 #endif 00061 00062 00063 extern float sgetrf_(int*,int*,float*,int*,int*,int*); 00064 extern double dgetrf_(int*,int*,double*,int*,int*,int*); 00065 00066 extern float sgetri_(int*,float*,int*,int*,float*,int*,int*); 00067 extern double dgetri_(int*,double*,int*,int*,double*,int*,int*); 00068 00069 extern float sgesdd_(char*,int*,int*,float*,int*,float*,float*,int*,float*,int*,float*,int*,int*,int*); 00070 extern double dgesdd_(char*,int*,int*,double*,int*,double*,double*,int*,double*,int*,double*,int*,int*,int*); 00071 00072 extern float ssyev_(char*,char*,int*,float*,int*,float*,float*,int*,int*); 00073 extern double dsyev_(char*,char*,int*,double*,int*,double*,double*,int*,int*); 00074 00075 00077 static void trans_d(double** A_out, const double* A, int M, int N) 00078 { 00079 int m, n; 00080 00081 assert(*A_out != A); 00082 00083 if (*A_out == NULL) 00084 { 00085 assert(*A_out = malloc(M*N*sizeof(double))); 00086 } 00087 00088 for (m = 0; m < M; m++) 00089 { 00090 for (n = 0; n < N; n++) 00091 { 00092 (*A_out)[ n*M + m ] = A[ m*N + n ]; 00093 } 00094 } 00095 } 00096 00097 00099 static void trans_f(float** A_out, const float* A, int M, int N) 00100 { 00101 int i, j; 00102 00103 assert(*A_out != A); 00104 00105 if (*A_out == NULL) 00106 { 00107 assert(*A_out = malloc(M*N*sizeof(float))); 00108 } 00109 00110 for (i = 0; i < M; i++) 00111 { 00112 for (j = 0; j < N; j++) 00113 { 00114 (*A_out)[ j*M + i ] = A[ i*N + j ]; 00115 } 00116 } 00117 } 00118 00119 00147 void lapack_sgetrf 00148 ( 00149 int M, 00150 int N, 00151 float* A, 00152 int lda, 00153 int* ipiv, 00154 int* info 00155 ) 00156 { 00157 float* A_t = NULL; 00158 00159 trans_f(&A_t, A, M, N); 00160 sgetrf_(&N, &M, A_t, &lda, ipiv, info); 00161 trans_f(&A, A_t, N, M); 00162 00163 free(A_t); 00164 } 00165 00166 00194 void lapack_dgetrf 00195 ( 00196 int M, 00197 int N, 00198 double* A, 00199 int lda, 00200 int* ipiv, 00201 int* info 00202 ) 00203 { 00204 double* A_t = NULL; 00205 00206 trans_d(&A_t, A, M, N); 00207 dgetrf_(&M, &N, A_t, &lda, ipiv, info); 00208 trans_d(&A, A_t, N, M); 00209 00210 free(A_t); 00211 } 00212 00213 00242 void lapack_sgetri 00243 ( 00244 int N, 00245 float* A, 00246 int lda, 00247 int* ipiv, 00248 float* work, 00249 int lwork, 00250 int* info 00251 ) 00252 { 00253 float* A_t = NULL; 00254 00255 trans_f(&A_t, A, N, N); 00256 sgetri_(&N, A_t, &lda, ipiv, work, &lwork, info); 00257 trans_f(&A, A_t, N, N); 00258 00259 free(A_t); 00260 } 00261 00262 00291 void lapack_dgetri 00292 ( 00293 int N, 00294 double* A, 00295 int lda, 00296 int* ipiv, 00297 double* work, 00298 int lwork, 00299 int* info 00300 ) 00301 { 00302 double* A_t = NULL; 00303 00304 trans_d(&A_t, A, N, N); 00305 dgetri_(&N, A_t, &lda, ipiv, work, &lwork, info); 00306 trans_d(&A, A_t, N, N); 00307 00308 free(A_t); 00309 } 00310 00311 00419 void lapack_sgesdd 00420 ( 00421 char JOBZ, 00422 int M, 00423 int N, 00424 float* A, 00425 int LDA, 00426 float* S, 00427 float* U, 00428 int LDU, 00429 float* VT, 00430 int LDVT, 00431 float* WORK, 00432 int LWORK, 00433 int* IWORK, 00434 int* INFO 00435 ) 00436 { 00437 int min_MN; 00438 float* A_t = NULL; 00439 float* U_t = NULL; 00440 float* VT_t = NULL; 00441 00442 min_MN = (M <= N) ? M : N; 00443 00444 if (JOBZ == 'A') 00445 { 00446 trans_f(&U_t, U, LDU, M); 00447 trans_f(&VT_t, VT, LDVT, N); 00448 } 00449 else if (JOBZ == 'S') 00450 { 00451 trans_f(&U_t, U, LDU, min_MN); 00452 trans_f(&VT_t, VT, LDVT, min_MN); 00453 } 00454 else if (JOBZ == 'O') 00455 { 00456 if (M < N) 00457 trans_f(&U_t, U, LDU, M); 00458 else 00459 trans_f(&VT_t, VT, LDVT, N); 00460 } 00461 else if (JOBZ == 'N') 00462 { 00463 ; 00464 } 00465 else 00466 { 00467 *INFO = -1; 00468 return; 00469 } 00470 00471 trans_f(&A_t, A, M, N); 00472 sgesdd_(&JOBZ, &M, &N, A_t, &LDA, S, U_t, &LDU, VT_t, &LDVT, WORK, 00473 &LWORK, IWORK, INFO); 00474 trans_f(&A, A_t, N, M); 00475 00476 if (JOBZ == 'A') 00477 { 00478 trans_f(&U, U_t, M, LDU); 00479 trans_f(&VT, VT_t, N, LDVT); 00480 } 00481 else if (JOBZ == 'S') 00482 { 00483 trans_f(&U, U_t, min_MN, LDU); 00484 trans_f(&VT, VT_t, min_MN, LDVT); 00485 } 00486 else if (JOBZ == 'O') 00487 { 00488 if (M < N) 00489 trans_f(&U, U_t, M, LDU); 00490 else 00491 trans_f(&VT, VT_t, N, LDVT); 00492 } 00493 00494 free(A_t); 00495 free(U_t); 00496 free(VT_t); 00497 } 00498 00499 00607 void lapack_dgesdd 00608 ( 00609 char JOBZ, 00610 int M, 00611 int N, 00612 double* A, 00613 int LDA, 00614 double* S, 00615 double* U, 00616 int LDU, 00617 double* VT, 00618 int LDVT, 00619 double* WORK, 00620 int LWORK, 00621 int* IWORK, 00622 int* INFO 00623 ) 00624 { 00625 int min_MN; 00626 double* A_t = NULL; 00627 double* U_t = NULL; 00628 double* VT_t = NULL; 00629 00630 min_MN = (M <= N) ? M : N; 00631 00632 if (JOBZ == 'A') 00633 { 00634 trans_d(&U_t, U, LDU, M); 00635 trans_d(&VT_t, VT, LDVT, N); 00636 } 00637 else if (JOBZ == 'S') 00638 { 00639 trans_d(&U_t, U, LDU, min_MN); 00640 trans_d(&VT_t, VT, LDVT, min_MN); 00641 } 00642 else if (JOBZ == 'O') 00643 { 00644 if (M < N) 00645 trans_d(&U_t, U, LDU, M); 00646 else 00647 trans_d(&VT_t, VT, LDVT, N); 00648 } 00649 else if (JOBZ == 'N') 00650 { 00651 ; 00652 } 00653 else 00654 { 00655 *INFO = -1; 00656 return; 00657 } 00658 00659 trans_d(&A_t, A, M, N); 00660 dgesdd_(&JOBZ, &M, &N, A_t, &LDA, S, U_t, &LDU, VT_t, &LDVT, WORK, 00661 &LWORK, IWORK, INFO); 00662 trans_d(&A, A_t, N, M); 00663 00664 if (JOBZ == 'A') 00665 { 00666 trans_d(&U, U_t, M, LDU); 00667 trans_d(&VT, VT_t, N, LDVT); 00668 } 00669 else if (JOBZ == 'S') 00670 { 00671 trans_d(&U, U_t, min_MN, LDU); 00672 trans_d(&VT, VT_t, min_MN, LDVT); 00673 } 00674 else if (JOBZ == 'O') 00675 { 00676 if (M < N) 00677 trans_d(&U, U_t, M, LDU); 00678 else 00679 trans_d(&VT, VT_t, N, LDVT); 00680 } 00681 00682 free(A_t); 00683 free(U_t); 00684 free(VT_t); 00685 } 00686 00687 00743 void lapack_ssyev 00744 ( 00745 char JOBZ, 00746 char UPLO, 00747 int N, 00748 float* A, 00749 int LDA, 00750 float* W, 00751 float* WORK, 00752 int LWORK, 00753 int* INFO 00754 ) 00755 { 00756 float* A_t = NULL; 00757 00758 if (JOBZ != 'N' && JOBZ != 'V') 00759 { 00760 *INFO = -1; 00761 return; 00762 } 00763 00764 trans_f(&A_t, A, N, N); 00765 ssyev_(&JOBZ, &UPLO, &N, A_t, &LDA, W, WORK, &LWORK, INFO); 00766 trans_f(&A, A_t, N, N); 00767 00768 free(A_t); 00769 } 00770 00771 00827 void lapack_dsyev 00828 ( 00829 char JOBZ, 00830 char UPLO, 00831 int N, 00832 double* A, 00833 int LDA, 00834 double* W, 00835 double* WORK, 00836 int LWORK, 00837 int* INFO 00838 ) 00839 { 00840 double* A_t = NULL; 00841 00842 if (JOBZ != 'N' && JOBZ != 'V') 00843 { 00844 *INFO = -1; 00845 return; 00846 } 00847 00848 trans_d(&A_t, A, N, N); 00849 dsyev_(&JOBZ, &UPLO, &N, A_t, &LDA, W, WORK, &LWORK, INFO); 00850 trans_d(&A, A_t, N, N); 00851 00852 free(A_t); 00853 }