JWS C Library
C language utility library
lapack.c
Go to the documentation of this file.
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 }