diff options
author | langou <julien.langou@ucdenver.edu> | 2016-12-16 09:28:47 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-12-16 09:28:47 +0100 |
commit | c83c6cdf3e9f86625611cfc332831b4a4b6da9e4 (patch) | |
tree | 5c00daefdb88c62ae900d8a307e74d1f264eda47 | |
parent | 0c852a609795bd0b962f28b534052492e319afff (diff) | |
parent | c695e9434398eda74936b25243927e2057ee35bd (diff) |
Merge pull request #101 from karturov/master
TS QR: changed API, added LAPACKE interfaces and fixes.
87 files changed, 7226 insertions, 2267 deletions
diff --git a/LAPACKE/include/lapacke.h b/LAPACKE/include/lapacke.h index e4d66943..d43c6c6b 100644 --- a/LAPACKE/include/lapacke.h +++ b/LAPACKE/include/lapacke.h @@ -11815,6 +11815,191 @@ lapack_int LAPACKE_zhecon_3_work( int matrix_layout, char uplo, lapack_int n, const lapack_int* ipiv, double anorm, double* rcond, lapack_complex_double* work ); +lapack_int LAPACKE_sgelq( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, + float* t, lapack_int tsize ); +lapack_int LAPACKE_dgelq( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, + double* t, lapack_int tsize ); +lapack_int LAPACKE_cgelq( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* t, lapack_int tsize ); +lapack_int LAPACKE_zgelq( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* t, lapack_int tsize ); + +lapack_int LAPACKE_sgelq_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, + float* t, lapack_int tsize, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgelq_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, + double* t, lapack_int tsize, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgelq_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* t, lapack_int tsize, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgelq_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* t, lapack_int tsize, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgemlq( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, + const float* t, lapack_int tsize, + float* c, lapack_int ldc ); +lapack_int LAPACKE_dgemlq( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, + const double* t, lapack_int tsize, + double* c, lapack_int ldc ); +lapack_int LAPACKE_cgemlq( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* t, lapack_int tsize, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zgemlq( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* t, lapack_int tsize, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_sgemlq_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, + const float* t, lapack_int tsize, + float* c, lapack_int ldc, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgemlq_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, + const double* t, lapack_int tsize, + double* c, lapack_int ldc, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgemlq_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* t, lapack_int tsize, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgemlq_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* t, lapack_int tsize, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgeqr( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, + float* t, lapack_int tsize ); +lapack_int LAPACKE_dgeqr( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, + double* t, lapack_int tsize ); +lapack_int LAPACKE_cgeqr( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* t, lapack_int tsize ); +lapack_int LAPACKE_zgeqr( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* t, lapack_int tsize ); + +lapack_int LAPACKE_sgeqr_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, + float* t, lapack_int tsize, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgeqr_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, + double* t, lapack_int tsize, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgeqr_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* t, lapack_int tsize, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgeqr_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* t, lapack_int tsize, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgemqr( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, + const float* t, lapack_int tsize, + float* c, lapack_int ldc ); +lapack_int LAPACKE_dgemqr( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, + const double* t, lapack_int tsize, + double* c, lapack_int ldc ); +lapack_int LAPACKE_cgemqr( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* t, lapack_int tsize, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zgemqr( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* t, lapack_int tsize, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_sgemqr_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, + const float* t, lapack_int tsize, + float* c, lapack_int ldc, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgemqr_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, + const double* t, lapack_int tsize, + double* c, lapack_int ldc, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgemqr_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* t, lapack_int tsize, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgemqr_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* t, lapack_int tsize, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgetsls( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* b, lapack_int ldb ); +lapack_int LAPACKE_dgetsls( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* b, lapack_int ldb ); +lapack_int LAPACKE_cgetsls( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zgetsls( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sgetsls_work( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgetsls_work( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* b, lapack_int ldb, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgetsls_work( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgetsls_work( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* work, lapack_int lwork ); #define LAPACK_sgetrf LAPACK_GLOBAL(sgetrf,SGETRF) #define LAPACK_dgetrf LAPACK_GLOBAL(dgetrf,DGETRF) @@ -12973,6 +13158,26 @@ lapack_int LAPACKE_zhecon_3_work( int matrix_layout, char uplo, lapack_int n, #define LAPACK_zsycon_3 LAPACK_GLOBAL(zsycon_3,ZSYCON_3) #define LAPACK_checon_3 LAPACK_GLOBAL(checon_3,CHECON_3) #define LAPACK_zhecon_3 LAPACK_GLOBAL(zhecon_3,ZHECON_3) +#define LAPACK_sgelq LAPACK_GLOBAL(sgelq,SGELQ) +#define LAPACK_dgelq LAPACK_GLOBAL(dgelq,DGELQ) +#define LAPACK_cgelq LAPACK_GLOBAL(cgelq,CGELQ) +#define LAPACK_zgelq LAPACK_GLOBAL(zgelq,ZGELQ) +#define LAPACK_sgemlq LAPACK_GLOBAL(sgemlq,SGEMLQ) +#define LAPACK_dgemlq LAPACK_GLOBAL(dgemlq,DGEMLQ) +#define LAPACK_cgemlq LAPACK_GLOBAL(cgemlq,CGEMLQ) +#define LAPACK_zgemlq LAPACK_GLOBAL(zgemlq,ZGEMLQ) +#define LAPACK_sgeqr LAPACK_GLOBAL(sgeqr,SGEQR) +#define LAPACK_dgeqr LAPACK_GLOBAL(dgeqr,DGEQR) +#define LAPACK_cgeqr LAPACK_GLOBAL(cgeqr,CGEQR) +#define LAPACK_zgeqr LAPACK_GLOBAL(zgeqr,ZGEQR) +#define LAPACK_sgemqr LAPACK_GLOBAL(sgemqr,SGEMQR) +#define LAPACK_dgemqr LAPACK_GLOBAL(dgemqr,DGEMQR) +#define LAPACK_cgemqr LAPACK_GLOBAL(cgemqr,CGEMQR) +#define LAPACK_zgemqr LAPACK_GLOBAL(zgemqr,ZGEMQR) +#define LAPACK_sgetsls LAPACK_GLOBAL(sgetsls,SGETSLS) +#define LAPACK_dgetsls LAPACK_GLOBAL(dgetsls,DGETSLS) +#define LAPACK_cgetsls LAPACK_GLOBAL(cgetsls,CGETSLS) +#define LAPACK_zgetsls LAPACK_GLOBAL(zgetsls,ZGETSLS) void LAPACK_sgetrf( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, @@ -18195,6 +18400,99 @@ void LAPACK_zhecon_3( char* uplo, lapack_int* n, const lapack_complex_double* a, double* rcond, lapack_complex_double* work, lapack_int *info ); +void LAPACK_sgelq( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* t, lapack_int* tsize, float* work, lapack_int* lwork, + lapack_int* info ); +void LAPACK_dgelq( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* t, lapack_int* tsize, double* work, lapack_int* lwork, + lapack_int* info ); +void LAPACK_cgelq( lapack_int* m, lapack_int* n, lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* t, lapack_int* tsize, lapack_complex_float* work, lapack_int* lwork, + lapack_int* info ); +void LAPACK_zgelq( lapack_int* m, lapack_int* n, lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* t, lapack_int* tsize, lapack_complex_double* work, lapack_int* lwork, + lapack_int* info ); + +void LAPACK_sgemlq( char* side, char* trans, lapack_int* m, lapack_int* n, lapack_int* k, + const float* a, lapack_int* lda, + const float* t, lapack_int* tsize, + float* c, lapack_int* ldc, + float* work, lapack_int* lwork, + lapack_int* info ); +void LAPACK_dgemlq( char* side, char* trans, lapack_int* m, lapack_int* n, lapack_int* k, + const double* a, lapack_int* lda, + const double* t, lapack_int* tsize, + double* c, lapack_int* ldc, + double* work, lapack_int* lwork, + lapack_int* info ); +void LAPACK_cgemlq( char* side, char* trans, lapack_int* m, lapack_int* n, lapack_int* k, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* t, lapack_int* tsize, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int* lwork, + lapack_int* info ); +void LAPACK_zgemlq( char* side, char* trans, lapack_int* m, lapack_int* n, lapack_int* k, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* t, lapack_int* tsize, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work, lapack_int* lwork, + lapack_int* info ); + +void LAPACK_sgeqr( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* t, lapack_int* tsize, float* work, lapack_int* lwork, + lapack_int* info ); +void LAPACK_dgeqr( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* t, lapack_int* tsize, double* work, lapack_int* lwork, + lapack_int* info ); +void LAPACK_cgeqr( lapack_int* m, lapack_int* n, lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* t, lapack_int* tsize, lapack_complex_float* work, lapack_int* lwork, + lapack_int* info ); +void LAPACK_zgeqr( lapack_int* m, lapack_int* n, lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* t, lapack_int* tsize, lapack_complex_double* work, lapack_int* lwork, + lapack_int* info ); + +void LAPACK_sgemqr( char* side, char* trans, lapack_int* m, lapack_int* n, lapack_int* k, + const float* a, lapack_int* lda, + const float* t, lapack_int* tsize, + float* c, lapack_int* ldc, + float* work, lapack_int* lwork, + lapack_int* info ); +void LAPACK_dgemqr( char* side, char* trans, lapack_int* m, lapack_int* n, lapack_int* k, + const double* a, lapack_int* lda, + const double* t, lapack_int* tsize, + double* c, lapack_int* ldc, + double* work, lapack_int* lwork, + lapack_int* info ); +void LAPACK_cgemqr( char* side, char* trans, lapack_int* m, lapack_int* n, lapack_int* k, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* t, lapack_int* tsize, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int* lwork, + lapack_int* info ); +void LAPACK_zgemqr( char* side, char* trans, lapack_int* m, lapack_int* n, lapack_int* k, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* t, lapack_int* tsize, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work, lapack_int* lwork, + lapack_int* info ); + +void LAPACK_sgetsls( char* trans, lapack_int* m, lapack_int* n, lapack_int* nrhs, + float* a, lapack_int* lda, float* b, lapack_int* ldb, + float* work, lapack_int* lwork, lapack_int *info ); +void LAPACK_dgetsls( char* trans, lapack_int* m, lapack_int* n, lapack_int* nrhs, + double* a, lapack_int* lda, double* b, lapack_int* ldb, + double* work, lapack_int* lwork, lapack_int *info ); +void LAPACK_cgetsls( char* trans, lapack_int* m, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zgetsls( char* trans, lapack_int* m, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/LAPACKE/src/CMakeLists.txt b/LAPACKE/src/CMakeLists.txt index eb14a548..0f5b0baf 100644 --- a/LAPACKE/src/CMakeLists.txt +++ b/LAPACKE/src/CMakeLists.txt @@ -59,6 +59,8 @@ lapacke_cgelss.c lapacke_cgelss_work.c lapacke_cgelsy.c lapacke_cgelsy_work.c +lapacke_cgemqr.c +lapacke_cgemqr_work.c lapacke_cgemqrt.c lapacke_cgemqrt_work.c lapacke_cgeqlf.c @@ -103,6 +105,8 @@ lapacke_cgetri.c lapacke_cgetri_work.c lapacke_cgetrs.c lapacke_cgetrs_work.c +lapacke_cgetsls.c +lapacke_cgetsls_work.c lapacke_cggbak.c lapacke_cggbak_work.c lapacke_cggbal.c @@ -623,6 +627,8 @@ lapacke_dgelss.c lapacke_dgelss_work.c lapacke_dgelsy.c lapacke_dgelsy_work.c +lapacke_dgemqr.c +lapacke_dgemqr_work.c lapacke_dgemqrt.c lapacke_dgemqrt_work.c lapacke_dgeqlf.c @@ -667,6 +673,8 @@ lapacke_dgetri.c lapacke_dgetri_work.c lapacke_dgetrs.c lapacke_dgetrs_work.c +lapacke_dgetsls.c +lapacke_dgetsls_work.c lapacke_dggbak.c lapacke_dggbak_work.c lapacke_dggbal.c @@ -1151,6 +1159,8 @@ lapacke_sgelss.c lapacke_sgelss_work.c lapacke_sgelsy.c lapacke_sgelsy_work.c +lapacke_sgemqr.c +lapacke_sgemqr_work.c lapacke_sgemqrt.c lapacke_sgemqrt_work.c lapacke_sgeqlf.c @@ -1195,6 +1205,8 @@ lapacke_sgetri.c lapacke_sgetri_work.c lapacke_sgetrs.c lapacke_sgetrs_work.c +lapacke_sgetsls.c +lapacke_sgetsls_work.c lapacke_sggbak.c lapacke_sggbak_work.c lapacke_sggbal.c @@ -1673,6 +1685,8 @@ lapacke_zgelss.c lapacke_zgelss_work.c lapacke_zgelsy.c lapacke_zgelsy_work.c +lapacke_zgemqr.c +lapacke_zgemqr_work.c lapacke_zgemqrt.c lapacke_zgemqrt_work.c lapacke_zgeqlf.c @@ -1717,6 +1731,8 @@ lapacke_zgetri.c lapacke_zgetri_work.c lapacke_zgetrs.c lapacke_zgetrs_work.c +lapacke_zgetsls.c +lapacke_zgetsls_work.c lapacke_zggbak.c lapacke_zggbak_work.c lapacke_zggbal.c diff --git a/LAPACKE/src/Makefile b/LAPACKE/src/Makefile index b608f851..f32be2ee 100644 --- a/LAPACKE/src/Makefile +++ b/LAPACKE/src/Makefile @@ -93,6 +93,8 @@ lapacke_cgelss.o \ lapacke_cgelss_work.o \ lapacke_cgelsy.o \ lapacke_cgelsy_work.o \ +lapacke_cgemqr.o \ +lapacke_cgemqr_work.o \ lapacke_cgemqrt.o \ lapacke_cgemqrt_work.o \ lapacke_cgeqlf.o \ @@ -137,6 +139,8 @@ lapacke_cgetri.o \ lapacke_cgetri_work.o \ lapacke_cgetrs.o \ lapacke_cgetrs_work.o \ +lapacke_cgetsls.o \ +lapacke_cgetsls_work.o \ lapacke_cggbak.o \ lapacke_cggbak_work.o \ lapacke_cggbal.o \ @@ -657,6 +661,8 @@ lapacke_dgelss.o \ lapacke_dgelss_work.o \ lapacke_dgelsy.o \ lapacke_dgelsy_work.o \ +lapacke_dgemqr.o \ +lapacke_dgemqr_work.o \ lapacke_dgemqrt.o \ lapacke_dgemqrt_work.o \ lapacke_dgeqlf.o \ @@ -701,6 +707,8 @@ lapacke_dgetri.o \ lapacke_dgetri_work.o \ lapacke_dgetrs.o \ lapacke_dgetrs_work.o \ +lapacke_dgetsls.o \ +lapacke_dgetsls_work.o \ lapacke_dggbak.o \ lapacke_dggbak_work.o \ lapacke_dggbal.o \ @@ -1185,6 +1193,8 @@ lapacke_sgelss.o \ lapacke_sgelss_work.o \ lapacke_sgelsy.o \ lapacke_sgelsy_work.o \ +lapacke_sgemqr.o \ +lapacke_sgemqr_work.o \ lapacke_sgemqrt.o \ lapacke_sgemqrt_work.o \ lapacke_sgeqlf.o \ @@ -1229,6 +1239,8 @@ lapacke_sgetri.o \ lapacke_sgetri_work.o \ lapacke_sgetrs.o \ lapacke_sgetrs_work.o \ +lapacke_sgetsls.o \ +lapacke_sgetsls_work.o \ lapacke_sggbak.o \ lapacke_sggbak_work.o \ lapacke_sggbal.o \ @@ -1707,6 +1719,8 @@ lapacke_zgelss.o \ lapacke_zgelss_work.o \ lapacke_zgelsy.o \ lapacke_zgelsy_work.o \ +lapacke_zgemqr.o \ +lapacke_zgemqr_work.o \ lapacke_zgemqrt.o \ lapacke_zgemqrt_work.o \ lapacke_zgeqlf.o \ @@ -1751,6 +1765,8 @@ lapacke_zgetri.o \ lapacke_zgetri_work.o \ lapacke_zgetrs.o \ lapacke_zgetrs_work.o \ +lapacke_zgetsls.o \ +lapacke_zgetsls_work.o \ lapacke_zggbak.o \ lapacke_zggbak_work.o \ lapacke_zggbal.o \ diff --git a/LAPACKE/src/lapacke_cgelq.c b/LAPACKE/src/lapacke_cgelq.c new file mode 100644 index 00000000..0d23bce7 --- /dev/null +++ b/LAPACKE/src/lapacke_cgelq.c @@ -0,0 +1,79 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function cgelq +* Author: Intel Corporation +* Generated November 2015 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_cgelq_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* t, lapack_int tsize ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + lapack_complex_float* work = NULL; + lapack_complex_float work_query; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_cgelq", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + if( LAPACKE_cge_nancheck( matrix_layout, m, n, a, lda ) ) { + return -4; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_cgelq_work( matrix_layout, m, n, a, lda, t, tsize, &work_query, + lwork ); + if( info != 0 ) { + goto exit_level_0; + } + if( tsize == -1 || tsize == -2 ) { + goto exit_level_0; + } + lwork = (lapack_int)work_query; + /* Allocate memory for work arrays */ + work = (lapack_complex_float*)LAPACKE_malloc( sizeof(lapack_complex_float) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_cgelq_work( matrix_layout, m, n, a, lda, t, tsize, work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_cgelq", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_cgelq_work.c b/LAPACKE/src/lapacke_cgelq_work.c new file mode 100644 index 00000000..dd56097d --- /dev/null +++ b/LAPACKE/src/lapacke_cgelq_work.c @@ -0,0 +1,88 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function cgelq +* Author: Intel Corporation +* Generated November 2015 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_cgelq_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* t, lapack_int tsize, + lapack_complex_float* work, lapack_int lwork ) +{ + lapack_int info = 0; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_cgelq( &m, &n, a, &lda, t, &tsize, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + lapack_int lda_t = MAX(1,m); + lapack_complex_float* a_t = NULL; + /* Check leading dimension(s) */ + if( lda < n ) { + info = -5; + LAPACKE_xerbla( "LAPACKE_cgelq_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( tsize == -1 || tsize == -2 || lwork == -1 || lwork == -2) { + LAPACK_cgelq( &m, &n, a, &lda_t, t, &tsize, work, &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + a_t = (lapack_complex_float*)LAPACKE_malloc( sizeof(lapack_complex_float) * lda_t * MAX(1,n) ); + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + /* Transpose input matrices */ + LAPACKE_cge_trans( matrix_layout, m, n, a, lda, a_t, lda_t ); + /* Call LAPACK function and adjust info */ + LAPACK_cgelq( &m, &n, a_t, &lda_t, t, &tsize, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_cge_trans( LAPACK_COL_MAJOR, m, n, a_t, lda_t, a, lda ); + /* Release memory and exit */ + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_cgelq_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_cgelq_work", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_cgemlq.c b/LAPACKE/src/lapacke_cgemlq.c new file mode 100644 index 00000000..0fbaa8a0 --- /dev/null +++ b/LAPACKE/src/lapacke_cgemlq.c @@ -0,0 +1,85 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function cgemlq +* Author: Intel Corporation +* Generated November 2015 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_cgemlq( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* t, lapack_int tsize, + lapack_complex_float* c, lapack_int ldc ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + lapack_complex_float* work = NULL; + lapack_complex_float work_query; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_cgemlq", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + if( LAPACKE_cge_nancheck( matrix_layout, k, m, a, lda ) ) { + return -7; + } + if( LAPACKE_cge_nancheck( matrix_layout, m, n, c, ldc ) ) { + return -10; + } + if( LAPACKE_d_nancheck( tsize, t, 1 ) ) { + return -9; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_cgemlq_work( matrix_layout, side, trans, m, n, k, a, lda, + t, tsize, c, ldc, &work_query, lwork ); + if( info != 0 ) { + goto exit_level_0; + } + lwork = (lapack_int)work_query; + /* Allocate memory for work arrays */ + work = (lapack_complex_float*)LAPACKE_malloc( sizeof(lapack_complex_float) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_cgemlq_work( matrix_layout, side, trans, m, n, k, a, lda, + t, tsize, c, ldc, work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_cgemlq", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_cgemlq_work.c b/LAPACKE/src/lapacke_cgemlq_work.c new file mode 100644 index 00000000..e2f7fc91 --- /dev/null +++ b/LAPACKE/src/lapacke_cgemlq_work.c @@ -0,0 +1,114 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function cgemlq +* Author: Intel Corporation +* Generated June 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_cgemlq_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* t, lapack_int tsize, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ) +{ + lapack_int info = 0; + lapack_int r; + lapack_int lda_t, ldc_t; + lapack_complex_float *a_t = NULL, *c_t = NULL; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_cgemlq( &side, &trans, &m, &n, &k, a, &lda, t, &tsize, + c, &ldc, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + r = LAPACKE_lsame( side, 'l' ) ? m : n; + lda_t = MAX(1,k); + ldc_t = MAX(1,m); + /* Check leading dimension(s) */ + if( lda < r ) { + info = -8; + LAPACKE_xerbla( "LAPACKE_cgemlq_work", info ); + return info; + } + if( ldc < n ) { + info = -11; + LAPACKE_xerbla( "LAPACKE_cgemlq_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( lwork == -1 ) { + LAPACK_cgemlq( &side, &trans, &m, &n, &k, a, &lda_t, t, &tsize, + c, &ldc_t, work, &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + if( LAPACKE_lsame( side, 'l' ) ) { + a_t = (lapack_complex_float*)LAPACKE_malloc( sizeof(lapack_complex_float) * lda_t * MAX(1,m) ); + } else { + a_t = (lapack_complex_float*)LAPACKE_malloc( sizeof(lapack_complex_float) * lda_t * MAX(1,n) ); + } + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + c_t = (lapack_complex_float*)LAPACKE_malloc( sizeof(lapack_complex_float) * ldc_t * MAX(1,n) ); + if( c_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_1; + } + /* Transpose input matrices */ + LAPACKE_cge_trans( matrix_layout, k, m, a, lda, a_t, lda_t ); + LAPACKE_cge_trans( matrix_layout, m, n, c, ldc, c_t, ldc_t ); + /* Call LAPACK function and adjust info */ + LAPACK_cgemlq( &side, &trans, &m, &n, &k, a_t, &lda_t, t, &tsize, + c_t, &ldc_t, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_cge_trans( LAPACK_COL_MAJOR, m, n, c_t, ldc_t, c, ldc ); + /* Release memory and exit */ + LAPACKE_free( c_t ); +exit_level_1: + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_cgemlq_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_cgemlq_work", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_cgemqr.c b/LAPACKE/src/lapacke_cgemqr.c new file mode 100644 index 00000000..229a4132 --- /dev/null +++ b/LAPACKE/src/lapacke_cgemqr.c @@ -0,0 +1,88 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function cgemqr +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_cgemqr( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* t, lapack_int tsize, + lapack_complex_float* c, lapack_int ldc ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + lapack_complex_float* work = NULL; + lapack_complex_float work_query; + lapack_int r; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_cgemqr", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + r = LAPACKE_lsame( side, 'l' ) ? m : n; + if( LAPACKE_cge_nancheck( matrix_layout, r, k, a, lda ) ) { + return -7; + } + if( LAPACKE_cge_nancheck( matrix_layout, m, n, c, ldc ) ) { + return -10; + } + if( LAPACKE_c_nancheck( tsize, t, 1 ) ) { + return -9; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_cgemqr_work( matrix_layout, side, trans, m, n, k, a, lda, + t, tsize, c, ldc, &work_query, lwork ); + if( info != 0 ) { + goto exit_level_0; + } + lwork = LAPACK_C2INT( work_query ); + /* Allocate memory for work arrays */ + work = (lapack_complex_float*) + LAPACKE_malloc( sizeof(lapack_complex_float) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_cgemqr_work( matrix_layout, side, trans, m, n, k, a, lda, + t, tsize, c, ldc, work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_cgemqr", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_cgemqr_work.c b/LAPACKE/src/lapacke_cgemqr_work.c new file mode 100644 index 00000000..9b9e5a44 --- /dev/null +++ b/LAPACKE/src/lapacke_cgemqr_work.c @@ -0,0 +1,112 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function cgemqr +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_cgemqr_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* t, lapack_int tsize, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ) +{ + lapack_int info = 0; + lapack_int r; + lapack_int lda_t, ldc_t; + lapack_complex_float *a_t = NULL, *c_t = NULL; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_cgemqr( &side, &trans, &m, &n, &k, a, &lda, t, &tsize, c, &ldc, + work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + r = LAPACKE_lsame( side, 'l' ) ? m : n; + lda_t = MAX(1,r); + ldc_t = MAX(1,m); + /* Check leading dimension(s) */ + if( lda < k ) { + info = -8; + LAPACKE_xerbla( "LAPACKE_cgemqr_work", info ); + return info; + } + if( ldc < n ) { + info = -11; + LAPACKE_xerbla( "LAPACKE_cgemqr_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( lwork == -1 ) { + LAPACK_cgemqr( &side, &trans, &m, &n, &k, a, &lda_t, t, &tsize, + c, &ldc_t, work, &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + a_t = (lapack_complex_float*) + LAPACKE_malloc( sizeof(lapack_complex_float) * lda_t * MAX(1,k) ); + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + c_t = (lapack_complex_float*) + LAPACKE_malloc( sizeof(lapack_complex_float) * ldc_t * MAX(1,n) ); + if( c_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_1; + } + /* Transpose input matrices */ + LAPACKE_cge_trans( matrix_layout, r, k, a, lda, a_t, lda_t ); + LAPACKE_cge_trans( matrix_layout, m, n, c, ldc, c_t, ldc_t ); + /* Call LAPACK function and adjust info */ + LAPACK_cgemqr( &side, &trans, &m, &n, &k, a_t, &lda_t, t, &tsize, + c_t, &ldc_t, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_cge_trans( LAPACK_COL_MAJOR, m, n, c_t, ldc_t, c, ldc ); + /* Release memory and exit */ + LAPACKE_free( c_t ); +exit_level_1: + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_cgemqr_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_cgemqr_work", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_cgeqr.c b/LAPACKE/src/lapacke_cgeqr.c new file mode 100644 index 00000000..beabeb8f --- /dev/null +++ b/LAPACKE/src/lapacke_cgeqr.c @@ -0,0 +1,80 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function cgeqr +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_cgeqr( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* t, lapack_int tsize ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + lapack_complex_float* work = NULL; + lapack_complex_float work_query; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_cgeqr", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + if( LAPACKE_cge_nancheck( matrix_layout, m, n, a, lda ) ) { + return -4; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_cgeqr_work( matrix_layout, m, n, a, lda, t, tsize, &work_query, + lwork ); + if( info != 0 ) { + goto exit_level_0; + } + if( tsize == -1 || tsize == -2 ) { + goto exit_level_0; + } + lwork = (lapack_int)work_query; + /* Allocate memory for work arrays */ + work = (lapack_complex_float*) + LAPACKE_malloc( sizeof(lapack_complex_float) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_cgeqr_work( matrix_layout, m, n, a, lda, t, tsize, work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_cgeqr", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_cgeqr_work.c b/LAPACKE/src/lapacke_cgeqr_work.c new file mode 100644 index 00000000..ff5cc9bc --- /dev/null +++ b/LAPACKE/src/lapacke_cgeqr_work.c @@ -0,0 +1,89 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function cgeqr +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_cgeqr_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* t, lapack_int tsize, + lapack_complex_float* work, lapack_int lwork ) +{ + lapack_int info = 0; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_cgeqr( &m, &n, a, &lda, t, &tsize, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + lapack_int lda_t = MAX(1,m); + lapack_complex_float* a_t = NULL; + /* Check leading dimension(s) */ + if( lda < n ) { + info = -5; + LAPACKE_xerbla( "LAPACKE_cgeqr_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( tsize == -1 || tsize == -2 || lwork == -1 || lwork == -2) { + LAPACK_cgeqr( &m, &n, a, &lda_t, t, &tsize, work, &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + a_t = (lapack_complex_float*) + LAPACKE_malloc( sizeof(lapack_complex_float) * lda_t * MAX(1,n) ); + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + /* Transpose input matrices */ + LAPACKE_cge_trans( matrix_layout, m, n, a, lda, a_t, lda_t ); + /* Call LAPACK function and adjust info */ + LAPACK_cgeqr( &m, &n, a_t, &lda_t, t, &tsize, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_cge_trans( LAPACK_COL_MAJOR, m, n, a_t, lda_t, a, lda ); + /* Release memory and exit */ + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_cgeqr_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_cgeqr_work", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_cgetsls.c b/LAPACKE/src/lapacke_cgetsls.c new file mode 100644 index 00000000..8b35c105 --- /dev/null +++ b/LAPACKE/src/lapacke_cgetsls.c @@ -0,0 +1,82 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function cgetsls +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_cgetsls( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + lapack_complex_float* work = NULL; + lapack_complex_float work_query; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_cgetsls", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + if( LAPACKE_cge_nancheck( matrix_layout, m, n, a, lda ) ) { + return -6; + } + if( LAPACKE_cge_nancheck( matrix_layout, MAX(m,n), nrhs, b, ldb ) ) { + return -8; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_cgetsls_work( matrix_layout, trans, m, n, nrhs, a, lda, b, ldb, + &work_query, lwork ); + if( info != 0 ) { + goto exit_level_0; + } + lwork = LAPACK_C2INT( work_query ); + /* Allocate memory for work arrays */ + work = (lapack_complex_float*) + LAPACKE_malloc( sizeof(lapack_complex_float) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_cgetsls_work( matrix_layout, trans, m, n, nrhs, a, lda, b, ldb, + work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_cgetsls", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_cgetsls_work.c b/LAPACKE/src/lapacke_cgetsls_work.c new file mode 100644 index 00000000..8f2ed4d0 --- /dev/null +++ b/LAPACKE/src/lapacke_cgetsls_work.c @@ -0,0 +1,112 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function cgetsls +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_cgetsls_work( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* work, lapack_int lwork ) +{ + lapack_int info = 0; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_cgetsls( &trans, &m, &n, &nrhs, a, &lda, b, &ldb, work, &lwork, + &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + lapack_int lda_t = MAX(1,m); + lapack_int ldb_t = MAX(1,MAX(m,n)); + lapack_complex_float* a_t = NULL; + lapack_complex_float* b_t = NULL; + /* Check leading dimension(s) */ + if( lda < n ) { + info = -7; + LAPACKE_xerbla( "LAPACKE_cgetsls_work", info ); + return info; + } + if( ldb < nrhs ) { + info = -9; + LAPACKE_xerbla( "LAPACKE_cgetsls_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( lwork == -1 ) { + LAPACK_cgetsls( &trans, &m, &n, &nrhs, a, &lda_t, b, &ldb_t, work, + &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + a_t = (lapack_complex_float*) + LAPACKE_malloc( sizeof(lapack_complex_float) * lda_t * MAX(1,n) ); + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + b_t = (lapack_complex_float*) + LAPACKE_malloc( sizeof(lapack_complex_float) * + ldb_t * MAX(1,nrhs) ); + if( b_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_1; + } + /* Transpose input matrices */ + LAPACKE_cge_trans( matrix_layout, m, n, a, lda, a_t, lda_t ); + LAPACKE_cge_trans( matrix_layout, MAX(m,n), nrhs, b, ldb, b_t, ldb_t ); + /* Call LAPACK function and adjust info */ + LAPACK_cgetsls( &trans, &m, &n, &nrhs, a_t, &lda_t, b_t, &ldb_t, work, + &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_cge_trans( LAPACK_COL_MAJOR, m, n, a_t, lda_t, a, lda ); + LAPACKE_cge_trans( LAPACK_COL_MAJOR, MAX(m,n), nrhs, b_t, ldb_t, b, + ldb ); + /* Release memory and exit */ + LAPACKE_free( b_t ); +exit_level_1: + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_cgetsls_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_cgetsls_work", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_dgelq.c b/LAPACKE/src/lapacke_dgelq.c new file mode 100644 index 00000000..80b8dd90 --- /dev/null +++ b/LAPACKE/src/lapacke_dgelq.c @@ -0,0 +1,79 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function dgelq +* Author: Intel Corporation +* Generated November 2015 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_dgelq_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, + double* t, lapack_int tsize ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + double* work = NULL; + double work_query; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_dgelq", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + if( LAPACKE_dge_nancheck( matrix_layout, m, n, a, lda ) ) { + return -4; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_dgelq_work( matrix_layout, m, n, a, lda, t, tsize, &work_query, + lwork ); + if( info != 0 ) { + goto exit_level_0; + } + if( tsize == -1 || tsize == -2 ) { + goto exit_level_0; + } + lwork = (lapack_int)work_query; + /* Allocate memory for work arrays */ + work = (double*)LAPACKE_malloc( sizeof(double) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_dgelq_work( matrix_layout, m, n, a, lda, t, tsize, work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_dgelq", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_dgelq_work.c b/LAPACKE/src/lapacke_dgelq_work.c new file mode 100644 index 00000000..e5a1dfa4 --- /dev/null +++ b/LAPACKE/src/lapacke_dgelq_work.c @@ -0,0 +1,88 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function dgelq +* Author: Intel Corporation +* Generated November 2015 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_dgelq_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, + double* t, lapack_int tsize, + double* work, lapack_int lwork ) +{ + lapack_int info = 0; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_dgelq( &m, &n, a, &lda, t, &tsize, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + lapack_int lda_t = MAX(1,m); + double* a_t = NULL; + /* Check leading dimension(s) */ + if( lda < n ) { + info = -5; + LAPACKE_xerbla( "LAPACKE_dgelq_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( tsize == -1 || tsize == -2 || lwork == -1 || lwork == -2) { + LAPACK_dgelq( &m, &n, a, &lda_t, t, &tsize, work, &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + a_t = (double*)LAPACKE_malloc( sizeof(double) * lda_t * MAX(1,n) ); + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + /* Transpose input matrices */ + LAPACKE_dge_trans( matrix_layout, m, n, a, lda, a_t, lda_t ); + /* Call LAPACK function and adjust info */ + LAPACK_dgelq( &m, &n, a_t, &lda_t, t, &tsize, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_dge_trans( LAPACK_COL_MAJOR, m, n, a_t, lda_t, a, lda ); + /* Release memory and exit */ + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_dgelq_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_dgelq_work", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_dgemlq.c b/LAPACKE/src/lapacke_dgemlq.c new file mode 100644 index 00000000..5fa6e0ec --- /dev/null +++ b/LAPACKE/src/lapacke_dgemlq.c @@ -0,0 +1,85 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function dgemlq +* Author: Intel Corporation +* Generated November 2015 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_dgemlq( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, + const double* t, lapack_int tsize, + double* c, lapack_int ldc ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + double* work = NULL; + double work_query; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_dgemlq", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + if( LAPACKE_dge_nancheck( matrix_layout, k, m, a, lda ) ) { + return -7; + } + if( LAPACKE_dge_nancheck( matrix_layout, m, n, c, ldc ) ) { + return -10; + } + if( LAPACKE_d_nancheck( tsize, t, 1 ) ) { + return -9; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_dgemlq_work( matrix_layout, side, trans, m, n, k, a, lda, + t, tsize, c, ldc, &work_query, lwork ); + if( info != 0 ) { + goto exit_level_0; + } + lwork = (lapack_int)work_query; + /* Allocate memory for work arrays */ + work = (double*)LAPACKE_malloc( sizeof(double) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_dgemlq_work( matrix_layout, side, trans, m, n, k, a, lda, + t, tsize, c, ldc, work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_dgemlq", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_dgemlq_work.c b/LAPACKE/src/lapacke_dgemlq_work.c new file mode 100644 index 00000000..e85252a1 --- /dev/null +++ b/LAPACKE/src/lapacke_dgemlq_work.c @@ -0,0 +1,114 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function dgemlq +* Author: Intel Corporation +* Generated June 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_dgemlq_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, + const double* t, lapack_int tsize, + double* c, lapack_int ldc, + double* work, lapack_int lwork ) +{ + lapack_int info = 0; + lapack_int r; + lapack_int lda_t, ldc_t; + double *a_t = NULL, *c_t = NULL; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_dgemlq( &side, &trans, &m, &n, &k, a, &lda, t, &tsize, + c, &ldc, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + r = LAPACKE_lsame( side, 'l' ) ? m : n; + lda_t = MAX(1,k); + ldc_t = MAX(1,m); + /* Check leading dimension(s) */ + if( lda < r ) { + info = -8; + LAPACKE_xerbla( "LAPACKE_dgemlq_work", info ); + return info; + } + if( ldc < n ) { + info = -11; + LAPACKE_xerbla( "LAPACKE_dgemlq_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( lwork == -1 ) { + LAPACK_dgemlq( &side, &trans, &m, &n, &k, a, &lda_t, t, &tsize, + c, &ldc_t, work, &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + if( LAPACKE_lsame( side, 'l' ) ) { + a_t = (double*)LAPACKE_malloc( sizeof(double) * lda_t * MAX(1,m) ); + } else { + a_t = (double*)LAPACKE_malloc( sizeof(double) * lda_t * MAX(1,n) ); + } + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + c_t = (double*)LAPACKE_malloc( sizeof(double) * ldc_t * MAX(1,n) ); + if( c_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_1; + } + /* Transpose input matrices */ + LAPACKE_dge_trans( matrix_layout, k, m, a, lda, a_t, lda_t ); + LAPACKE_dge_trans( matrix_layout, m, n, c, ldc, c_t, ldc_t ); + /* Call LAPACK function and adjust info */ + LAPACK_dgemlq( &side, &trans, &m, &n, &k, a_t, &lda_t, t, &tsize, + c_t, &ldc_t, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_dge_trans( LAPACK_COL_MAJOR, m, n, c_t, ldc_t, c, ldc ); + /* Release memory and exit */ + LAPACKE_free( c_t ); +exit_level_1: + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_dgemlq_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_dgemlq_work", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_dgemqr.c b/LAPACKE/src/lapacke_dgemqr.c new file mode 100644 index 00000000..86566d9c --- /dev/null +++ b/LAPACKE/src/lapacke_dgemqr.c @@ -0,0 +1,87 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function dgemqr +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_dgemqr( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, + const double* t, lapack_int tsize, + double* c, lapack_int ldc ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + double* work = NULL; + double work_query; + lapack_int r; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_dgemqr", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + r = LAPACKE_lsame( side, 'l' ) ? m : n; + if( LAPACKE_dge_nancheck( matrix_layout, r, k, a, lda ) ) { + return -7; + } + if( LAPACKE_dge_nancheck( matrix_layout, m, n, c, ldc ) ) { + return -10; + } + if( LAPACKE_d_nancheck( tsize, t, 1 ) ) { + return -9; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_dgemqr_work( matrix_layout, side, trans, m, n, k, a, lda, + t, tsize, c, ldc, &work_query, lwork ); + if( info != 0 ) { + goto exit_level_0; + } + lwork = (lapack_int)work_query; + /* Allocate memory for work arrays */ + work = (double*)LAPACKE_malloc( sizeof(double) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_dgemqr_work( matrix_layout, side, trans, m, n, k, a, lda, + t, tsize, c, ldc, work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_dgemqr", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_dgemqr_work.c b/LAPACKE/src/lapacke_dgemqr_work.c new file mode 100644 index 00000000..a1179a46 --- /dev/null +++ b/LAPACKE/src/lapacke_dgemqr_work.c @@ -0,0 +1,112 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function dgemqr +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_dgemqr_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, + const double* t, lapack_int tsize, + double* c, lapack_int ldc, + double* work, lapack_int lwork ) +{ + lapack_int info = 0; + lapack_int r; + lapack_int lda_t, ldc_t; + double *a_t = NULL, *c_t = NULL; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_dgemqr( &side, &trans, &m, &n, &k, a, &lda, t, &tsize, c, &ldc, + work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + r = LAPACKE_lsame( side, 'l' ) ? m : n; + lda_t = MAX(1,r); + ldc_t = MAX(1,m); + /* Check leading dimension(s) */ + if( lda < k ) { + info = -8; + LAPACKE_xerbla( "LAPACKE_dgemqr_work", info ); + return info; + } + if( ldc < n ) { + info = -11; + LAPACKE_xerbla( "LAPACKE_dgemqr_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( lwork == -1 ) { + LAPACK_dgemqr( &side, &trans, &m, &n, &k, a, &lda_t, t, &tsize, + c, &ldc_t, work, &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + a_t = (double*) + LAPACKE_malloc( sizeof(double) * lda_t * MAX(1,k) ); + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + c_t = (double*) + LAPACKE_malloc( sizeof(double) * ldc_t * MAX(1,n) ); + if( c_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_1; + } + /* Transpose input matrices */ + LAPACKE_dge_trans( matrix_layout, r, k, a, lda, a_t, lda_t ); + LAPACKE_dge_trans( matrix_layout, m, n, c, ldc, c_t, ldc_t ); + /* Call LAPACK function and adjust info */ + LAPACK_dgemqr( &side, &trans, &m, &n, &k, a_t, &lda_t, t, &tsize, + c_t, &ldc_t, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_dge_trans( LAPACK_COL_MAJOR, m, n, c_t, ldc_t, c, ldc ); + /* Release memory and exit */ + LAPACKE_free( c_t ); +exit_level_1: + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_dgemqr_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_dgemqr_work", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_dgeqr.c b/LAPACKE/src/lapacke_dgeqr.c new file mode 100644 index 00000000..7f9f9d29 --- /dev/null +++ b/LAPACKE/src/lapacke_dgeqr.c @@ -0,0 +1,79 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function dgeqr +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_dgeqr( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, + double* t, lapack_int tsize ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + double* work = NULL; + double work_query; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_dgeqr", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + if( LAPACKE_dge_nancheck( matrix_layout, m, n, a, lda ) ) { + return -4; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_dgeqr_work( matrix_layout, m, n, a, lda, t, tsize, &work_query, + lwork ); + if( info != 0 ) { + goto exit_level_0; + } + if( tsize == -1 || tsize == -2 ) { + goto exit_level_0; + } + lwork = (lapack_int)work_query; + /* Allocate memory for work arrays */ + work = (double*)LAPACKE_malloc( sizeof(double) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_dgeqr_work( matrix_layout, m, n, a, lda, t, tsize, work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_dgeqr", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_dgeqr_work.c b/LAPACKE/src/lapacke_dgeqr_work.c new file mode 100644 index 00000000..8bc3b1cb --- /dev/null +++ b/LAPACKE/src/lapacke_dgeqr_work.c @@ -0,0 +1,89 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function dgeqr +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_dgeqr_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, + double* t, lapack_int tsize, + double* work, lapack_int lwork ) +{ + lapack_int info = 0; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_dgeqr( &m, &n, a, &lda, t, &tsize, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + lapack_int lda_t = MAX(1,m); + double* a_t = NULL; + /* Check leading dimension(s) */ + if( lda < n ) { + info = -5; + LAPACKE_xerbla( "LAPACKE_dgeqr_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( tsize == -1 || tsize == -2 || lwork == -1 || lwork == -2) { + LAPACK_dgeqr( &m, &n, a, &lda_t, t, &tsize, work, &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + a_t = (double*) + LAPACKE_malloc( sizeof(double) * lda_t * MAX(1,n) ); + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + /* Transpose input matrices */ + LAPACKE_dge_trans( matrix_layout, m, n, a, lda, a_t, lda_t ); + /* Call LAPACK function and adjust info */ + LAPACK_dgeqr( &m, &n, a_t, &lda_t, t, &tsize, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_dge_trans( LAPACK_COL_MAJOR, m, n, a_t, lda_t, a, lda ); + /* Release memory and exit */ + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_dgeqr_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_dgeqr_work", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_dgetsls.c b/LAPACKE/src/lapacke_dgetsls.c new file mode 100644 index 00000000..57563f5e --- /dev/null +++ b/LAPACKE/src/lapacke_dgetsls.c @@ -0,0 +1,80 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function dgetsls +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_dgetsls( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* b, lapack_int ldb ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + double* work = NULL; + double work_query; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_dgetsls", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + if( LAPACKE_dge_nancheck( matrix_layout, m, n, a, lda ) ) { + return -6; + } + if( LAPACKE_dge_nancheck( matrix_layout, MAX(m,n), nrhs, b, ldb ) ) { + return -8; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_dgetsls_work( matrix_layout, trans, m, n, nrhs, a, lda, b, ldb, + &work_query, lwork ); + if( info != 0 ) { + goto exit_level_0; + } + lwork = (lapack_int)work_query; + /* Allocate memory for work arrays */ + work = (double*)LAPACKE_malloc( sizeof(double) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_dgetsls_work( matrix_layout, trans, m, n, nrhs, a, lda, b, ldb, + work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_dgetsls", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_dgetsls_work.c b/LAPACKE/src/lapacke_dgetsls_work.c new file mode 100644 index 00000000..6f84d674 --- /dev/null +++ b/LAPACKE/src/lapacke_dgetsls_work.c @@ -0,0 +1,108 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function dgetsls +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_dgetsls_work( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* b, lapack_int ldb, + double* work, lapack_int lwork ) +{ + lapack_int info = 0; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_dgetsls( &trans, &m, &n, &nrhs, a, &lda, b, &ldb, work, &lwork, + &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + lapack_int lda_t = MAX(1,m); + lapack_int ldb_t = MAX(1,MAX(m,n)); + double* a_t = NULL; + double* b_t = NULL; + /* Check leading dimension(s) */ + if( lda < n ) { + info = -7; + LAPACKE_xerbla( "LAPACKE_dgetsls_work", info ); + return info; + } + if( ldb < nrhs ) { + info = -9; + LAPACKE_xerbla( "LAPACKE_dgetsls_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( lwork == -1 ) { + LAPACK_dgetsls( &trans, &m, &n, &nrhs, a, &lda_t, b, &ldb_t, work, + &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + a_t = (double*)LAPACKE_malloc( sizeof(double) * lda_t * MAX(1,n) ); + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + b_t = (double*)LAPACKE_malloc( sizeof(double) * ldb_t * MAX(1,nrhs) ); + if( b_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_1; + } + /* Transpose input matrices */ + LAPACKE_dge_trans( matrix_layout, m, n, a, lda, a_t, lda_t ); + LAPACKE_dge_trans( matrix_layout, MAX(m,n), nrhs, b, ldb, b_t, ldb_t ); + /* Call LAPACK function and adjust info */ + LAPACK_dgetsls( &trans, &m, &n, &nrhs, a_t, &lda_t, b_t, &ldb_t, work, + &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_dge_trans( LAPACK_COL_MAJOR, m, n, a_t, lda_t, a, lda ); + LAPACKE_dge_trans( LAPACK_COL_MAJOR, MAX(m,n), nrhs, b_t, ldb_t, b, + ldb ); + /* Release memory and exit */ + LAPACKE_free( b_t ); +exit_level_1: + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_dgetsls_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_dgetsls_work", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_sgelq.c b/LAPACKE/src/lapacke_sgelq.c new file mode 100644 index 00000000..7cbc7700 --- /dev/null +++ b/LAPACKE/src/lapacke_sgelq.c @@ -0,0 +1,79 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function sgelq +* Author: Intel Corporation +* Generated November 2015 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_sgelq_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, + float* t, lapack_int tsize ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + float* work = NULL; + float work_query; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_sgelq", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + if( LAPACKE_sge_nancheck( matrix_layout, m, n, a, lda ) ) { + return -4; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_sgelq_work( matrix_layout, m, n, a, lda, t, tsize, &work_query, + lwork ); + if( info != 0 ) { + goto exit_level_0; + } + if( tsize == -1 || tsize == -2 ) { + goto exit_level_0; + } + lwork = (lapack_int)work_query; + /* Allocate memory for work arrays */ + work = (float*)LAPACKE_malloc( sizeof(float) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_sgelq_work( matrix_layout, m, n, a, lda, t, tsize, work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_sgelq", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_sgelq_work.c b/LAPACKE/src/lapacke_sgelq_work.c new file mode 100644 index 00000000..437c57b1 --- /dev/null +++ b/LAPACKE/src/lapacke_sgelq_work.c @@ -0,0 +1,88 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function sgelq +* Author: Intel Corporation +* Generated November 2015 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_sgelq_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, + float* t, lapack_int tsize, + float* work, lapack_int lwork ) +{ + lapack_int info = 0; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_sgelq( &m, &n, a, &lda, t, &tsize, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + lapack_int lda_t = MAX(1,m); + float* a_t = NULL; + /* Check leading dimension(s) */ + if( lda < n ) { + info = -5; + LAPACKE_xerbla( "LAPACKE_sgelq_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( tsize == -1 || tsize == -2 || lwork == -1 || lwork == -2) { + LAPACK_sgelq( &m, &n, a, &lda_t, t, &tsize, work, &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + a_t = (float*)LAPACKE_malloc( sizeof(float) * lda_t * MAX(1,n) ); + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + /* Transpose input matrices */ + LAPACKE_sge_trans( matrix_layout, m, n, a, lda, a_t, lda_t ); + /* Call LAPACK function and adjust info */ + LAPACK_sgelq( &m, &n, a_t, &lda_t, t, &tsize, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_sge_trans( LAPACK_COL_MAJOR, m, n, a_t, lda_t, a, lda ); + /* Release memory and exit */ + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_sgelq_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_sgelq_work", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_sgemlq.c b/LAPACKE/src/lapacke_sgemlq.c new file mode 100644 index 00000000..162c1c7a --- /dev/null +++ b/LAPACKE/src/lapacke_sgemlq.c @@ -0,0 +1,85 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function sgemlq +* Author: Intel Corporation +* Generated November 2015 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_sgemlq( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, + const float* t, lapack_int tsize, + float* c, lapack_int ldc ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + float* work = NULL; + float work_query; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_sgemlq", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + if( LAPACKE_sge_nancheck( matrix_layout, k, m, a, lda ) ) { + return -7; + } + if( LAPACKE_sge_nancheck( matrix_layout, m, n, c, ldc ) ) { + return -10; + } + if( LAPACKE_d_nancheck( tsize, t, 1 ) ) { + return -9; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_sgemlq_work( matrix_layout, side, trans, m, n, k, a, lda, + t, tsize, c, ldc, &work_query, lwork ); + if( info != 0 ) { + goto exit_level_0; + } + lwork = (lapack_int)work_query; + /* Allocate memory for work arrays */ + work = (float*)LAPACKE_malloc( sizeof(float) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_sgemlq_work( matrix_layout, side, trans, m, n, k, a, lda, + t, tsize, c, ldc, work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_sgemlq", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_sgemlq_work.c b/LAPACKE/src/lapacke_sgemlq_work.c new file mode 100644 index 00000000..9931ec13 --- /dev/null +++ b/LAPACKE/src/lapacke_sgemlq_work.c @@ -0,0 +1,114 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function sgemlq +* Author: Intel Corporation +* Generated June 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_sgemlq_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, + const float* t, lapack_int tsize, + float* c, lapack_int ldc, + float* work, lapack_int lwork ) +{ + lapack_int info = 0; + lapack_int r; + lapack_int lda_t, ldc_t; + float *a_t = NULL, *c_t = NULL; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_sgemlq( &side, &trans, &m, &n, &k, a, &lda, t, &tsize, + c, &ldc, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + r = LAPACKE_lsame( side, 'l' ) ? m : n; + lda_t = MAX(1,k); + ldc_t = MAX(1,m); + /* Check leading dimension(s) */ + if( lda < r ) { + info = -8; + LAPACKE_xerbla( "LAPACKE_sgemlq_work", info ); + return info; + } + if( ldc < n ) { + info = -11; + LAPACKE_xerbla( "LAPACKE_sgemlq_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( lwork == -1 ) { + LAPACK_sgemlq( &side, &trans, &m, &n, &k, a, &lda_t, t, &tsize, + c, &ldc_t, work, &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + if( LAPACKE_lsame( side, 'l' ) ) { + a_t = (float*)LAPACKE_malloc( sizeof(float) * lda_t * MAX(1,m) ); + } else { + a_t = (float*)LAPACKE_malloc( sizeof(float) * lda_t * MAX(1,n) ); + } + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + c_t = (float*)LAPACKE_malloc( sizeof(float) * ldc_t * MAX(1,n) ); + if( c_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_1; + } + /* Transpose input matrices */ + LAPACKE_sge_trans( matrix_layout, k, m, a, lda, a_t, lda_t ); + LAPACKE_sge_trans( matrix_layout, m, n, c, ldc, c_t, ldc_t ); + /* Call LAPACK function and adjust info */ + LAPACK_sgemlq( &side, &trans, &m, &n, &k, a_t, &lda_t, t, &tsize, + c_t, &ldc_t, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_sge_trans( LAPACK_COL_MAJOR, m, n, c_t, ldc_t, c, ldc ); + /* Release memory and exit */ + LAPACKE_free( c_t ); +exit_level_1: + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_sgemlq_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_sgemlq_work", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_sgemqr.c b/LAPACKE/src/lapacke_sgemqr.c new file mode 100644 index 00000000..4619d927 --- /dev/null +++ b/LAPACKE/src/lapacke_sgemqr.c @@ -0,0 +1,87 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function sgemqr +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_sgemqr( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, + const float* t, lapack_int tsize, + float* c, lapack_int ldc ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + float* work = NULL; + float work_query; + lapack_int r; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_sgemqr", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + r = LAPACKE_lsame( side, 'l' ) ? m : n; + if( LAPACKE_sge_nancheck( matrix_layout, r, k, a, lda ) ) { + return -7; + } + if( LAPACKE_sge_nancheck( matrix_layout, m, n, c, ldc ) ) { + return -10; + } + if( LAPACKE_s_nancheck( tsize, t, 1 ) ) { + return -9; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_sgemqr_work( matrix_layout, side, trans, m, n, k, a, lda, + t, tsize, c, ldc, &work_query, lwork ); + if( info != 0 ) { + goto exit_level_0; + } + lwork = (lapack_int)work_query; + /* Allocate memory for work arrays */ + work = (float*)LAPACKE_malloc( sizeof(float) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_sgemqr_work( matrix_layout, side, trans, m, n, k, a, lda, + t, tsize, c, ldc, work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_sgemqr", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_sgemqr_work.c b/LAPACKE/src/lapacke_sgemqr_work.c new file mode 100644 index 00000000..d41b500c --- /dev/null +++ b/LAPACKE/src/lapacke_sgemqr_work.c @@ -0,0 +1,112 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function sgemqr +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_sgemqr_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, + const float* t, lapack_int tsize, + float* c, lapack_int ldc, + float* work, lapack_int lwork ) +{ + lapack_int info = 0; + lapack_int r; + lapack_int lda_t, ldc_t; + float *a_t = NULL, *c_t = NULL; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_sgemqr( &side, &trans, &m, &n, &k, a, &lda, t, &tsize, c, &ldc, + work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + r = LAPACKE_lsame( side, 'l' ) ? m : n; + lda_t = MAX(1,r); + ldc_t = MAX(1,m); + /* Check leading dimension(s) */ + if( lda < k ) { + info = -8; + LAPACKE_xerbla( "LAPACKE_sgemqr_work", info ); + return info; + } + if( ldc < n ) { + info = -11; + LAPACKE_xerbla( "LAPACKE_sgemqr_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( lwork == -1 ) { + LAPACK_sgemqr( &side, &trans, &m, &n, &k, a, &lda_t, t, &tsize, + c, &ldc_t, work, &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + a_t = (float*) + LAPACKE_malloc( sizeof(float) * lda_t * MAX(1,k) ); + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + c_t = (float*) + LAPACKE_malloc( sizeof(float) * ldc_t * MAX(1,n) ); + if( c_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_1; + } + /* Transpose input matrices */ + LAPACKE_sge_trans( matrix_layout, r, k, a, lda, a_t, lda_t ); + LAPACKE_sge_trans( matrix_layout, m, n, c, ldc, c_t, ldc_t ); + /* Call LAPACK function and adjust info */ + LAPACK_sgemqr( &side, &trans, &m, &n, &k, a_t, &lda_t, t, &tsize, + c_t, &ldc_t, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_sge_trans( LAPACK_COL_MAJOR, m, n, c_t, ldc_t, c, ldc ); + /* Release memory and exit */ + LAPACKE_free( c_t ); +exit_level_1: + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_sgemqr_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_sgemqr_work", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_sgeqr.c b/LAPACKE/src/lapacke_sgeqr.c new file mode 100644 index 00000000..60323f53 --- /dev/null +++ b/LAPACKE/src/lapacke_sgeqr.c @@ -0,0 +1,79 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function sgeqr +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_sgeqr( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, + float* t, lapack_int tsize ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + float* work = NULL; + float work_query; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_sgeqr", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + if( LAPACKE_sge_nancheck( matrix_layout, m, n, a, lda ) ) { + return -4; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_sgeqr_work( matrix_layout, m, n, a, lda, t, tsize, &work_query, + lwork ); + if( info != 0 ) { + goto exit_level_0; + } + if( tsize == -1 || tsize == -2 ) { + goto exit_level_0; + } + lwork = (lapack_int)work_query; + /* Allocate memory for work arrays */ + work = (float*)LAPACKE_malloc( sizeof(float) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_sgeqr_work( matrix_layout, m, n, a, lda, t, tsize, work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_sgeqr", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_sgeqr_work.c b/LAPACKE/src/lapacke_sgeqr_work.c new file mode 100644 index 00000000..21c222a9 --- /dev/null +++ b/LAPACKE/src/lapacke_sgeqr_work.c @@ -0,0 +1,89 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function sgeqr +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_sgeqr_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, + float* t, lapack_int tsize, + float* work, lapack_int lwork ) +{ + lapack_int info = 0; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_sgeqr( &m, &n, a, &lda, t, &tsize, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + lapack_int lda_t = MAX(1,m); + float* a_t = NULL; + /* Check leading dimension(s) */ + if( lda < n ) { + info = -5; + LAPACKE_xerbla( "LAPACKE_sgeqr_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( tsize == -1 || tsize == -2 || lwork == -1 || lwork == -2) { + LAPACK_sgeqr( &m, &n, a, &lda_t, t, &tsize, work, &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + a_t = (float*) + LAPACKE_malloc( sizeof(float) * lda_t * MAX(1,n) ); + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + /* Transpose input matrices */ + LAPACKE_sge_trans( matrix_layout, m, n, a, lda, a_t, lda_t ); + /* Call LAPACK function and adjust info */ + LAPACK_sgeqr( &m, &n, a_t, &lda_t, t, &tsize, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_sge_trans( LAPACK_COL_MAJOR, m, n, a_t, lda_t, a, lda ); + /* Release memory and exit */ + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_sgeqr_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_sgeqr_work", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_sgetsls.c b/LAPACKE/src/lapacke_sgetsls.c new file mode 100644 index 00000000..1a1d8f3a --- /dev/null +++ b/LAPACKE/src/lapacke_sgetsls.c @@ -0,0 +1,80 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function sgetsls +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_sgetsls( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* b, lapack_int ldb ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + float* work = NULL; + float work_query; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_sgetsls", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + if( LAPACKE_sge_nancheck( matrix_layout, m, n, a, lda ) ) { + return -6; + } + if( LAPACKE_sge_nancheck( matrix_layout, MAX(m,n), nrhs, b, ldb ) ) { + return -8; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_sgetsls_work( matrix_layout, trans, m, n, nrhs, a, lda, b, ldb, + &work_query, lwork ); + if( info != 0 ) { + goto exit_level_0; + } + lwork = (lapack_int)work_query; + /* Allocate memory for work arrays */ + work = (float*)LAPACKE_malloc( sizeof(float) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_sgetsls_work( matrix_layout, trans, m, n, nrhs, a, lda, b, ldb, + work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_sgetsls", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_sgetsls_work.c b/LAPACKE/src/lapacke_sgetsls_work.c new file mode 100644 index 00000000..6f36379c --- /dev/null +++ b/LAPACKE/src/lapacke_sgetsls_work.c @@ -0,0 +1,108 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function sgetsls +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_sgetsls_work( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* work, lapack_int lwork ) +{ + lapack_int info = 0; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_sgetsls( &trans, &m, &n, &nrhs, a, &lda, b, &ldb, work, &lwork, + &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + lapack_int lda_t = MAX(1,m); + lapack_int ldb_t = MAX(1,MAX(m,n)); + float* a_t = NULL; + float* b_t = NULL; + /* Check leading dimension(s) */ + if( lda < n ) { + info = -7; + LAPACKE_xerbla( "LAPACKE_sgetsls_work", info ); + return info; + } + if( ldb < nrhs ) { + info = -9; + LAPACKE_xerbla( "LAPACKE_sgetsls_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( lwork == -1 ) { + LAPACK_sgetsls( &trans, &m, &n, &nrhs, a, &lda_t, b, &ldb_t, work, + &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + a_t = (float*)LAPACKE_malloc( sizeof(float) * lda_t * MAX(1,n) ); + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + b_t = (float*)LAPACKE_malloc( sizeof(float) * ldb_t * MAX(1,nrhs) ); + if( b_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_1; + } + /* Transpose input matrices */ + LAPACKE_sge_trans( matrix_layout, m, n, a, lda, a_t, lda_t ); + LAPACKE_sge_trans( matrix_layout, MAX(m,n), nrhs, b, ldb, b_t, ldb_t ); + /* Call LAPACK function and adjust info */ + LAPACK_sgetsls( &trans, &m, &n, &nrhs, a_t, &lda_t, b_t, &ldb_t, work, + &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_sge_trans( LAPACK_COL_MAJOR, m, n, a_t, lda_t, a, lda ); + LAPACKE_sge_trans( LAPACK_COL_MAJOR, MAX(m,n), nrhs, b_t, ldb_t, b, + ldb ); + /* Release memory and exit */ + LAPACKE_free( b_t ); +exit_level_1: + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_sgetsls_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_sgetsls_work", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_zgelq.c b/LAPACKE/src/lapacke_zgelq.c new file mode 100644 index 00000000..2aba1f5b --- /dev/null +++ b/LAPACKE/src/lapacke_zgelq.c @@ -0,0 +1,79 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function zgelq +* Author: Intel Corporation +* Generated November 2015 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_zgelq_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* t, lapack_int tsize ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + lapack_complex_double* work = NULL; + lapack_complex_double work_query; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_zgelq", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + if( LAPACKE_zge_nancheck( matrix_layout, m, n, a, lda ) ) { + return -4; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_zgelq_work( matrix_layout, m, n, a, lda, t, tsize, &work_query, + lwork ); + if( info != 0 ) { + goto exit_level_0; + } + if( tsize == -1 || tsize == -2 ) { + goto exit_level_0; + } + lwork = (lapack_int)work_query; + /* Allocate memory for work arrays */ + work = (lapack_complex_double*)LAPACKE_malloc( sizeof(lapack_complex_double) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_zgelq_work( matrix_layout, m, n, a, lda, t, tsize, work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_zgelq", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_zgelq_work.c b/LAPACKE/src/lapacke_zgelq_work.c new file mode 100644 index 00000000..282b67d6 --- /dev/null +++ b/LAPACKE/src/lapacke_zgelq_work.c @@ -0,0 +1,88 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function zgelq +* Author: Intel Corporation +* Generated November 2015 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_zgelq_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* t, lapack_int tsize, + lapack_complex_double* work, lapack_int lwork ) +{ + lapack_int info = 0; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_zgelq( &m, &n, a, &lda, t, &tsize, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + lapack_int lda_t = MAX(1,m); + lapack_complex_double* a_t = NULL; + /* Check leading dimension(s) */ + if( lda < n ) { + info = -5; + LAPACKE_xerbla( "LAPACKE_zgelq_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( tsize == -1 || tsize == -2 || lwork == -1 || lwork == -2) { + LAPACK_zgelq( &m, &n, a, &lda_t, t, &tsize, work, &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + a_t = (lapack_complex_double*)LAPACKE_malloc( sizeof(lapack_complex_double) * lda_t * MAX(1,n) ); + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + /* Transpose input matrices */ + LAPACKE_zge_trans( matrix_layout, m, n, a, lda, a_t, lda_t ); + /* Call LAPACK function and adjust info */ + LAPACK_zgelq( &m, &n, a_t, &lda_t, t, &tsize, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_zge_trans( LAPACK_COL_MAJOR, m, n, a_t, lda_t, a, lda ); + /* Release memory and exit */ + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_zgelq_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_zgelq_work", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_zgemlq.c b/LAPACKE/src/lapacke_zgemlq.c new file mode 100644 index 00000000..355a0804 --- /dev/null +++ b/LAPACKE/src/lapacke_zgemlq.c @@ -0,0 +1,85 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function zgemlq +* Author: Intel Corporation +* Generated November 2015 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_zgemlq( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* t, lapack_int tsize, + lapack_complex_double* c, lapack_int ldc ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + lapack_complex_double* work = NULL; + lapack_complex_double work_query; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_zgemlq", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + if( LAPACKE_zge_nancheck( matrix_layout, k, m, a, lda ) ) { + return -7; + } + if( LAPACKE_zge_nancheck( matrix_layout, m, n, c, ldc ) ) { + return -10; + } + if( LAPACKE_d_nancheck( tsize, t, 1 ) ) { + return -9; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_zgemlq_work( matrix_layout, side, trans, m, n, k, a, lda, + t, tsize, c, ldc, &work_query, lwork ); + if( info != 0 ) { + goto exit_level_0; + } + lwork = (lapack_int)work_query; + /* Allocate memory for work arrays */ + work = (lapack_complex_double*)LAPACKE_malloc( sizeof(lapack_complex_double) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_zgemlq_work( matrix_layout, side, trans, m, n, k, a, lda, + t, tsize, c, ldc, work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_zgemlq", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_zgemlq_work.c b/LAPACKE/src/lapacke_zgemlq_work.c new file mode 100644 index 00000000..d10e7306 --- /dev/null +++ b/LAPACKE/src/lapacke_zgemlq_work.c @@ -0,0 +1,114 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function zgemlq +* Author: Intel Corporation +* Generated June 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_zgemlq_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* t, lapack_int tsize, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ) +{ + lapack_int info = 0; + lapack_int r; + lapack_int lda_t, ldc_t; + lapack_complex_double *a_t = NULL, *c_t = NULL; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_zgemlq( &side, &trans, &m, &n, &k, a, &lda, t, &tsize, + c, &ldc, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + r = LAPACKE_lsame( side, 'l' ) ? m : n; + lda_t = MAX(1,k); + ldc_t = MAX(1,m); + /* Check leading dimension(s) */ + if( lda < r ) { + info = -8; + LAPACKE_xerbla( "LAPACKE_zgemlq_work", info ); + return info; + } + if( ldc < n ) { + info = -11; + LAPACKE_xerbla( "LAPACKE_zgemlq_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( lwork == -1 ) { + LAPACK_zgemlq( &side, &trans, &m, &n, &k, a, &lda_t, t, &tsize, + c, &ldc_t, work, &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + if( LAPACKE_lsame( side, 'l' ) ) { + a_t = (lapack_complex_double*)LAPACKE_malloc( sizeof(lapack_complex_double) * lda_t * MAX(1,m) ); + } else { + a_t = (lapack_complex_double*)LAPACKE_malloc( sizeof(lapack_complex_double) * lda_t * MAX(1,n) ); + } + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + c_t = (lapack_complex_double*)LAPACKE_malloc( sizeof(lapack_complex_double) * ldc_t * MAX(1,n) ); + if( c_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_1; + } + /* Transpose input matrices */ + LAPACKE_zge_trans( matrix_layout, k, m, a, lda, a_t, lda_t ); + LAPACKE_zge_trans( matrix_layout, m, n, c, ldc, c_t, ldc_t ); + /* Call LAPACK function and adjust info */ + LAPACK_zgemlq( &side, &trans, &m, &n, &k, a_t, &lda_t, t, &tsize, + c_t, &ldc_t, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_zge_trans( LAPACK_COL_MAJOR, m, n, c_t, ldc_t, c, ldc ); + /* Release memory and exit */ + LAPACKE_free( c_t ); +exit_level_1: + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_zgemlq_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_zgemlq_work", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_zgemqr.c b/LAPACKE/src/lapacke_zgemqr.c new file mode 100644 index 00000000..07e1a7aa --- /dev/null +++ b/LAPACKE/src/lapacke_zgemqr.c @@ -0,0 +1,88 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function zgemqr +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_zgemqr( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* t, lapack_int tsize, + lapack_complex_double* c, lapack_int ldc ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + lapack_complex_double* work = NULL; + lapack_complex_double work_query; + lapack_int r; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_zgemqr", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + r = LAPACKE_lsame( side, 'l' ) ? m : n; + if( LAPACKE_zge_nancheck( matrix_layout, r, k, a, lda ) ) { + return -7; + } + if( LAPACKE_zge_nancheck( matrix_layout, m, n, c, ldc ) ) { + return -10; + } + if( LAPACKE_z_nancheck( tsize, t, 1 ) ) { + return -9; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_zgemqr_work( matrix_layout, side, trans, m, n, k, a, lda, + t, tsize, c, ldc, &work_query, lwork ); + if( info != 0 ) { + goto exit_level_0; + } + lwork = LAPACK_Z2INT( work_query ); + /* Allocate memory for work arrays */ + work = (lapack_complex_double*) + LAPACKE_malloc( sizeof(lapack_complex_double) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_zgemqr_work( matrix_layout, side, trans, m, n, k, a, lda, + t, tsize, c, ldc, work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_zgemqr", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_zgemqr_work.c b/LAPACKE/src/lapacke_zgemqr_work.c new file mode 100644 index 00000000..f17fa84e --- /dev/null +++ b/LAPACKE/src/lapacke_zgemqr_work.c @@ -0,0 +1,112 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function zgemqr +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_zgemqr_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* t, lapack_int tsize, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ) +{ + lapack_int info = 0; + lapack_int r; + lapack_int lda_t, ldc_t; + lapack_complex_double *a_t = NULL, *c_t = NULL; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_zgemqr( &side, &trans, &m, &n, &k, a, &lda, t, &tsize, c, &ldc, + work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + r = LAPACKE_lsame( side, 'l' ) ? m : n; + lda_t = MAX(1,r); + ldc_t = MAX(1,m); + /* Check leading dimension(s) */ + if( lda < k ) { + info = -8; + LAPACKE_xerbla( "LAPACKE_zgemqr_work", info ); + return info; + } + if( ldc < n ) { + info = -11; + LAPACKE_xerbla( "LAPACKE_zgemqr_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( lwork == -1 ) { + LAPACK_zgemqr( &side, &trans, &m, &n, &k, a, &lda_t, t, &tsize, + c, &ldc_t, work, &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + a_t = (lapack_complex_double*) + LAPACKE_malloc( sizeof(lapack_complex_double) * lda_t * MAX(1,k) ); + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + c_t = (lapack_complex_double*) + LAPACKE_malloc( sizeof(lapack_complex_double) * ldc_t * MAX(1,n) ); + if( c_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_1; + } + /* Transpose input matrices */ + LAPACKE_zge_trans( matrix_layout, r, k, a, lda, a_t, lda_t ); + LAPACKE_zge_trans( matrix_layout, m, n, c, ldc, c_t, ldc_t ); + /* Call LAPACK function and adjust info */ + LAPACK_zgemqr( &side, &trans, &m, &n, &k, a_t, &lda_t, t, &tsize, + c_t, &ldc_t, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_zge_trans( LAPACK_COL_MAJOR, m, n, c_t, ldc_t, c, ldc ); + /* Release memory and exit */ + LAPACKE_free( c_t ); +exit_level_1: + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_zgemqr_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_zgemqr_work", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_zgeqr.c b/LAPACKE/src/lapacke_zgeqr.c new file mode 100644 index 00000000..61a179de --- /dev/null +++ b/LAPACKE/src/lapacke_zgeqr.c @@ -0,0 +1,80 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function zgeqr +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_zgeqr( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* t, lapack_int tsize ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + lapack_complex_double* work = NULL; + lapack_complex_double work_query; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_zgeqr", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + if( LAPACKE_zge_nancheck( matrix_layout, m, n, a, lda ) ) { + return -4; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_zgeqr_work( matrix_layout, m, n, a, lda, t, tsize, &work_query, + lwork ); + if( info != 0 ) { + goto exit_level_0; + } + if( tsize == -1 || tsize == -2 ) { + goto exit_level_0; + } + lwork = (lapack_int)work_query; + /* Allocate memory for work arrays */ + work = (lapack_complex_double*) + LAPACKE_malloc( sizeof(lapack_complex_double) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_zgeqr_work( matrix_layout, m, n, a, lda, t, tsize, work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_zgeqr", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_zgeqr_work.c b/LAPACKE/src/lapacke_zgeqr_work.c new file mode 100644 index 00000000..304738b4 --- /dev/null +++ b/LAPACKE/src/lapacke_zgeqr_work.c @@ -0,0 +1,89 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function zgeqr +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_zgeqr_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* t, lapack_int tsize, + lapack_complex_double* work, lapack_int lwork ) +{ + lapack_int info = 0; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_zgeqr( &m, &n, a, &lda, t, &tsize, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + lapack_int lda_t = MAX(1,m); + lapack_complex_double* a_t = NULL; + /* Check leading dimension(s) */ + if( lda < n ) { + info = -5; + LAPACKE_xerbla( "LAPACKE_zgeqr_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( tsize == -1 || tsize == -2 || lwork == -1 || lwork == -2) { + LAPACK_zgeqr( &m, &n, a, &lda_t, t, &tsize, work, &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + a_t = (lapack_complex_double*) + LAPACKE_malloc( sizeof(lapack_complex_double) * lda_t * MAX(1,n) ); + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + /* Transpose input matrices */ + LAPACKE_zge_trans( matrix_layout, m, n, a, lda, a_t, lda_t ); + /* Call LAPACK function and adjust info */ + LAPACK_zgeqr( &m, &n, a_t, &lda_t, t, &tsize, work, &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_zge_trans( LAPACK_COL_MAJOR, m, n, a_t, lda_t, a, lda ); + /* Release memory and exit */ + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_zgeqr_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_zgeqr_work", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_zgetsls.c b/LAPACKE/src/lapacke_zgetsls.c new file mode 100644 index 00000000..6e73657d --- /dev/null +++ b/LAPACKE/src/lapacke_zgetsls.c @@ -0,0 +1,82 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native high-level C interface to LAPACK function zgetsls +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_zgetsls( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb ) +{ + lapack_int info = 0; + lapack_int lwork = -1; + lapack_complex_double* work = NULL; + lapack_complex_double work_query; + if( matrix_layout != LAPACK_COL_MAJOR && matrix_layout != LAPACK_ROW_MAJOR ) { + LAPACKE_xerbla( "LAPACKE_zgetsls", -1 ); + return -1; + } +#ifndef LAPACK_DISABLE_NAN_CHECK + /* Optionally check input matrices for NaNs */ + if( LAPACKE_zge_nancheck( matrix_layout, m, n, a, lda ) ) { + return -6; + } + if( LAPACKE_zge_nancheck( matrix_layout, MAX(m,n), nrhs, b, ldb ) ) { + return -8; + } +#endif + /* Query optimal working array(s) size */ + info = LAPACKE_zgetsls_work( matrix_layout, trans, m, n, nrhs, a, lda, b, ldb, + &work_query, lwork ); + if( info != 0 ) { + goto exit_level_0; + } + lwork = LAPACK_Z2INT( work_query ); + /* Allocate memory for work arrays */ + work = (lapack_complex_double*) + LAPACKE_malloc( sizeof(lapack_complex_double) * lwork ); + if( work == NULL ) { + info = LAPACK_WORK_MEMORY_ERROR; + goto exit_level_0; + } + /* Call middle-level interface */ + info = LAPACKE_zgetsls_work( matrix_layout, trans, m, n, nrhs, a, lda, b, ldb, + work, lwork ); + /* Release memory and exit */ + LAPACKE_free( work ); +exit_level_0: + if( info == LAPACK_WORK_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_zgetsls", info ); + } + return info; +} diff --git a/LAPACKE/src/lapacke_zgetsls_work.c b/LAPACKE/src/lapacke_zgetsls_work.c new file mode 100644 index 00000000..dca7d49a --- /dev/null +++ b/LAPACKE/src/lapacke_zgetsls_work.c @@ -0,0 +1,112 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************** +* Contents: Native middle-level C interface to LAPACK function zgetsls +* Author: Intel Corporation +* Generated December 2016 +*****************************************************************************/ + +#include "lapacke_utils.h" + +lapack_int LAPACKE_zgetsls_work( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* work, lapack_int lwork ) +{ + lapack_int info = 0; + if( matrix_layout == LAPACK_COL_MAJOR ) { + /* Call LAPACK function and adjust info */ + LAPACK_zgetsls( &trans, &m, &n, &nrhs, a, &lda, b, &ldb, work, &lwork, + &info ); + if( info < 0 ) { + info = info - 1; + } + } else if( matrix_layout == LAPACK_ROW_MAJOR ) { + lapack_int lda_t = MAX(1,m); + lapack_int ldb_t = MAX(1,MAX(m,n)); + lapack_complex_double* a_t = NULL; + lapack_complex_double* b_t = NULL; + /* Check leading dimension(s) */ + if( lda < n ) { + info = -7; + LAPACKE_xerbla( "LAPACKE_zgetsls_work", info ); + return info; + } + if( ldb < nrhs ) { + info = -9; + LAPACKE_xerbla( "LAPACKE_zgetsls_work", info ); + return info; + } + /* Query optimal working array(s) size if requested */ + if( lwork == -1 ) { + LAPACK_zgetsls( &trans, &m, &n, &nrhs, a, &lda_t, b, &ldb_t, work, + &lwork, &info ); + return (info < 0) ? (info - 1) : info; + } + /* Allocate memory for temporary array(s) */ + a_t = (lapack_complex_double*) + LAPACKE_malloc( sizeof(lapack_complex_double) * lda_t * MAX(1,n) ); + if( a_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_0; + } + b_t = (lapack_complex_double*) + LAPACKE_malloc( sizeof(lapack_complex_double) * + ldb_t * MAX(1,nrhs) ); + if( b_t == NULL ) { + info = LAPACK_TRANSPOSE_MEMORY_ERROR; + goto exit_level_1; + } + /* Transpose input matrices */ + LAPACKE_zge_trans( matrix_layout, m, n, a, lda, a_t, lda_t ); + LAPACKE_zge_trans( matrix_layout, MAX(m,n), nrhs, b, ldb, b_t, ldb_t ); + /* Call LAPACK function and adjust info */ + LAPACK_zgetsls( &trans, &m, &n, &nrhs, a_t, &lda_t, b_t, &ldb_t, work, + &lwork, &info ); + if( info < 0 ) { + info = info - 1; + } + /* Transpose output matrices */ + LAPACKE_zge_trans( LAPACK_COL_MAJOR, m, n, a_t, lda_t, a, lda ); + LAPACKE_zge_trans( LAPACK_COL_MAJOR, MAX(m,n), nrhs, b_t, ldb_t, b, + ldb ); + /* Release memory and exit */ + LAPACKE_free( b_t ); +exit_level_1: + LAPACKE_free( a_t ); +exit_level_0: + if( info == LAPACK_TRANSPOSE_MEMORY_ERROR ) { + LAPACKE_xerbla( "LAPACKE_zgetsls_work", info ); + } + } else { + info = -1; + LAPACKE_xerbla( "LAPACKE_zgetsls_work", info ); + } + return info; +} diff --git a/SRC/cgelq.f b/SRC/cgelq.f index c6c962d7..497851f5 100644 --- a/SRC/cgelq.f +++ b/SRC/cgelq.f @@ -2,14 +2,14 @@ * Definition: * =========== * -* SUBROUTINE CGELQ( M, N, A, LDA, WORK1, LWORK1, WORK2, LWORK2, -* INFO) +* SUBROUTINE CGELQ( M, N, A, LDA, T, TSIZE, WORK, LWORK, +* INFO ) * * .. Scalar Arguments .. -* INTEGER INFO, LDA, M, N, LWORK1, LWORK2 +* INTEGER INFO, LDA, M, N, TSIZE, LWORK * .. * .. Array Arguments .. -* COMPLEX A( LDA, * ), WORK1( * ), WORK2( * ) +* COMPLEX A( LDA, * ), T( * ), WORK( * ) * .. * * @@ -17,11 +17,7 @@ * ============= *> *> \verbatim -*> -*> CGELQ computes an LQ factorization of an M-by-N matrix A, -*> using CLASWLQ when A is short and wide -*> (N sufficiently greater than M), and otherwise CGELQT: -*> A = L * Q . +*> CGELQ computes a LQ factorization of an M-by-N matrix A. *> \endverbatim * * Arguments: @@ -46,8 +42,8 @@ *> On exit, the elements on and below the diagonal of the array *> contain the M-by-min(M,N) lower trapezoidal matrix L *> (L is lower triangular if M <= N); -*> the elements above the diagonal are the rows of -*> blocked V representing Q (see Further Details). +*> the elements above the diagonal are used to store part of the +*> data structure to represent Q. *> \endverbatim *> *> \param[in] LDA @@ -56,47 +52,50 @@ *> The leading dimension of the array A. LDA >= max(1,M). *> \endverbatim *> -*> \param[out] WORK1 +*> \param[out] T *> \verbatim -*> WORK1 is COMPLEX array, dimension (MAX(1,LWORK1)) -*> WORK1 contains part of the data structure used to store Q. -*> WORK1(1): algorithm type = 1, to indicate output from -*> CLASWLQ or CGELQT -*> WORK1(2): optimum size of WORK1 -*> WORK1(3): minimum size of WORK1 -*> WORK1(4): horizontal block size -*> WORK1(5): vertical block size -*> WORK1(6:LWORK1): data structure needed for Q, computed by -*> CLASWLQ or CGELQT +*> T is COMPLEX array, dimension (MAX(5,TSIZE)) +*> On exit, if INFO = 0, T(1) returns optimal (or either minimal +*> or optimal, if query is assumed) TSIZE. See TSIZE for details. +*> Remaining T contains part of the data structure used to represent Q. +*> If one wants to apply or construct Q, then one needs to keep T +*> (in addition to A) and pass it to further subroutines. *> \endverbatim *> -*> \param[in] LWORK1 +*> \param[in] TSIZE *> \verbatim -*> LWORK1 is INTEGER -*> The dimension of the array WORK1. -*> If LWORK1 = -1, then a query is assumed. In this case the -*> routine calculates the optimal size of WORK1 and -*> returns this value in WORK1(2), and calculates the minimum -*> size of WORK1 and returns this value in WORK1(3). -*> No error message related to LWORK1 is issued by XERBLA when -*> LWORK1 = -1. +*> TSIZE is INTEGER +*> If TSIZE >= 5, the dimension of the array T. +*> If TSIZE = -1 or -2, then a workspace query is assumed. The routine +*> only calculates the sizes of the T and WORK arrays, returns these +*> values as the first entries of the T and WORK arrays, and no error +*> message related to T or WORK is issued by XERBLA. +*> If TSIZE = -1, the routine calculates optimal size of T for the +*> optimum performance and returns this value in T(1). +*> If TSIZE = -2, the routine calculates minimal size of T and +*> returns this value in T(1). *> \endverbatim *> -*> \param[out] WORK2 +*> \param[out] WORK *> \verbatim -*> (workspace) COMPLEX array, dimension (MAX(1,LWORK2)) -*> +*> (workspace) COMPLEX array, dimension (MAX(1,LWORK)) +*> On exit, if INFO = 0, WORK(1) contains optimal (or either minimal +*> or optimal, if query was assumed) LWORK. +*> See LWORK for details. *> \endverbatim -*> \param[in] LWORK2 +*> +*> \param[in] LWORK *> \verbatim -*> LWORK2 is INTEGER -*> The dimension of the array WORK2. -*> If LWORK2 = -1, then a query is assumed. In this case the -*> routine calculates the optimal size of WORK2 and -*> returns this value in WORK2(1), and calculates the minimum -*> size of WORK2 and returns this value in WORK2(2). -*> No error message related to LWORK2 is issued by XERBLA when -*> LWORK2 = -1. +*> LWORK is INTEGER +*> The dimension of the array WORK. +*> If LWORK = -1 or -2, then a workspace query is assumed. The routine +*> only calculates the sizes of the T and WORK arrays, returns these +*> values as the first entries of the T and WORK arrays, and no error +*> message related to T or WORK is issued by XERBLA. +*> If LWORK = -1, the routine calculates optimal size of WORK for the +*> optimal performance and returns this value in WORK(1). +*> If LWORK = -2, the routine calculates minimal size of WORK and +*> returns this value in WORK(1). *> \endverbatim *> *> \param[out] INFO @@ -114,105 +113,137 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \par Further Details: -* ===================== +*> \par Further Details +* ==================== *> *> \verbatim +*> +*> The goal of the interface is to give maximum freedom to the developers for +*> creating any LQ factorization algorithm they wish. The triangular +*> (trapezoidal) L has to be stored in the lower part of A. The lower part of A +*> and the array T can be used to store any relevant information for applying or +*> constructing the Q factor. The WORK array can safely be discarded after exit. +*> +*> Caution: One should not expect the sizes of T and WORK to be the same from one +*> LAPACK implementation to the other, or even from one execution to the other. +*> A workspace query (for T and WORK) is needed at each execution. However, +*> for a given execution, the size of T and WORK are fixed and will not change +*> from one query to the next. +*> +*> \endverbatim +*> +*> \par Further Details particular to this LAPACK implementation: +* ============================================================== +*> +*> \verbatim +*> +*> These details are particular for this LAPACK implementation. Users should not +*> take them for granted. These details may change in the future, and are unlikely not +*> true for another LAPACK implementation. These details are relevant if one wants +*> to try to understand the code. They are not part of the interface. +*> +*> In this version, +*> +*> T(2): row block size (MB) +*> T(3): column block size (NB) +*> T(6:TSIZE): data structure needed for Q, computed by +*> CLASWLQ or CGELQT +*> *> Depending on the matrix dimensions M and N, and row and column -*> block sizes MB and NB returned by ILAENV, GELQ will use either -*> LASWLQ(if the matrix is short-and-wide) or GELQT to compute -*> the LQ decomposition. -*> The output of LASWLQ or GELQT representing Q is stored in A and in -*> array WORK1(6:LWORK1) for later use. -*> WORK1(2:5) contains the matrix dimensions M,N and block sizes MB, NB -*> which are needed to interpret A and WORK1(6:LWORK1) for later use. -*> WORK1(1)=1 indicates that the code needed to take WORK1(2:5) and -*> decide whether LASWLQ or GELQT was used is the same as used below in -*> GELQ. For a detailed description of A and WORK1(6:LWORK1), see -*> Further Details in LASWLQ or GELQT. +*> block sizes MB and NB returned by ILAENV, CGELQ will use either +*> CLASWLQ (if the matrix is short-and-wide) or CGELQT to compute +*> the LQ factorization. *> \endverbatim *> * ===================================================================== - SUBROUTINE CGELQ( M, N, A, LDA, WORK1, LWORK1, WORK2, LWORK2, - $ INFO) + SUBROUTINE CGELQ( M, N, A, LDA, T, TSIZE, WORK, LWORK, + $ INFO ) * -* -- LAPACK computational routine (version 3.5.0) -- +* -- LAPACK computational routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd. -- -* November 2013 +* November 2016 * * .. Scalar Arguments .. - INTEGER INFO, LDA, M, N, LWORK1, LWORK2 + INTEGER INFO, LDA, M, N, TSIZE, LWORK * .. * .. Array Arguments .. - COMPLEX A( LDA, * ), WORK1( * ), WORK2( * ) + COMPLEX A( LDA, * ), T( * ), WORK( * ) * .. * * ===================================================================== * * .. * .. Local Scalars .. - LOGICAL LQUERY, LMINWS - INTEGER MB, NB, I, II, KK, MINLW1, NBLCKS + LOGICAL LQUERY, LMINWS, MINT, MINW + INTEGER MB, NB, MINTSZ, NBLCKS * .. -* .. EXTERNAL FUNCTIONS .. +* .. External Functions .. LOGICAL LSAME EXTERNAL LSAME -* .. EXTERNAL SUBROUTINES .. +* .. +* .. External Subroutines .. EXTERNAL CGELQT, CLASWLQ, XERBLA -* .. INTRINSIC FUNCTIONS .. +* .. +* .. Intrinsic Functions .. INTRINSIC MAX, MIN, MOD * .. -* .. EXTERNAL FUNCTIONS .. +* .. External Functions .. INTEGER ILAENV EXTERNAL ILAENV * .. -* .. EXECUTABLE STATEMENTS .. +* .. Executable Statements .. * -* TEST THE INPUT ARGUMENTS +* Test the input arguments * INFO = 0 * - LQUERY = ( LWORK1.EQ.-1 .OR. LWORK2.EQ.-1 ) + LQUERY = ( TSIZE.EQ.-1 .OR. TSIZE.EQ.-2 .OR. + $ LWORK.EQ.-1 .OR. LWORK.EQ.-2 ) +* + MINT = .FALSE. + MINW = .FALSE. + IF( TSIZE.EQ.-2 .OR. LWORK.EQ.-2 ) THEN + IF( TSIZE.NE.-1 ) MINT = .TRUE. + IF( LWORK.NE.-1 ) MINW = .TRUE. + END IF * * Determine the block size * - IF ( MIN(M,N).GT.0 ) THEN - MB = ILAENV( 1, 'CGELQ ', ' ', M, N, 1, -1) - NB = ILAENV( 1, 'CGELQ ', ' ', M, N, 2, -1) + IF( MIN( M, N ).GT.0 ) THEN + MB = ILAENV( 1, 'CGELQ ', ' ', M, N, 1, -1 ) + NB = ILAENV( 1, 'CGELQ ', ' ', M, N, 2, -1 ) ELSE MB = 1 NB = N END IF - IF( MB.GT.MIN(M,N).OR.MB.LT.1) MB = 1 - IF( NB.GT.N.OR.NB.LE.M) NB = N - MINLW1 = M + 5 - IF ((NB.GT.M).AND.(N.GT.M)) THEN - IF(MOD(N-M, NB-M).EQ.0) THEN - NBLCKS = (N-M)/(NB-M) + IF( MB.GT.MIN( M, N ) .OR. MB.LT.1 ) MB = 1 + IF( NB.GT.N .OR. NB.LE.M ) NB = N + MINTSZ = M + 5 + IF( NB.GT.M .AND. N.GT.M ) THEN + IF( MOD( N - M, NB - M ).EQ.0 ) THEN + NBLCKS = ( N - M ) / ( NB - M ) ELSE - NBLCKS = (N-M)/(NB-M) + 1 + NBLCKS = ( N - M ) / ( NB - M ) + 1 END IF ELSE NBLCKS = 1 END IF -* Determine if the workspace size satisfies minimum size +* +* Determine if the workspace size satisfies minimal size * LMINWS = .FALSE. - IF((LWORK1.LT.MAX(1,MB*M*NBLCKS+5) - $ .OR.(LWORK2.LT.MB*M)).AND.(LWORK2.GE.M).AND.(LWORK1.GE.M+5) - $ .AND.(.NOT.LQUERY)) THEN - IF (LWORK1.LT.MAX(1,MB*M*NBLCKS+5)) THEN - LMINWS = .TRUE. - MB = 1 + IF( ( TSIZE.LT.MAX( 1, MB*M*NBLCKS + 5 ) .OR. LWORK.LT.MB*M ) + $ .AND. ( LWORK.GE.M ) .AND. ( TSIZE.GE.MINTSZ ) + $ .AND. ( .NOT.LQUERY ) ) THEN + IF( TSIZE.LT.MAX( 1, MB*M*NBLCKS + 5 ) ) THEN + LMINWS = .TRUE. + MB = 1 + NB = N END IF - IF (LWORK1.LT.MAX(1,M*NBLCKS+5)) THEN - LMINWS = .TRUE. - NB = N - END IF - IF (LWORK2.LT.MB*M) THEN - LMINWS = .TRUE. - MB = 1 + IF( LWORK.LT.MB*M ) THEN + LMINWS = .TRUE. + MB = 1 END IF END IF * @@ -222,44 +253,52 @@ INFO = -2 ELSE IF( LDA.LT.MAX( 1, M ) ) THEN INFO = -4 - ELSE IF( LWORK1.LT.MAX( 1, MB*M*NBLCKS+5 ) - $ .AND.(.NOT.LQUERY).AND. (.NOT.LMINWS)) THEN + ELSE IF( TSIZE.LT.MAX( 1, MB*M*NBLCKS + 5 ) + $ .AND. ( .NOT.LQUERY ) .AND. ( .NOT.LMINWS ) ) THEN INFO = -6 - ELSE IF( (LWORK2.LT.MAX(1,M*MB)).AND.(.NOT.LQUERY) - $ .AND.(.NOT.LMINWS) ) THEN + ELSE IF( ( LWORK.LT.MAX( 1, M*MB ) ) .AND .( .NOT.LQUERY ) + $ .AND. ( .NOT.LMINWS ) ) THEN INFO = -8 END IF * - IF( INFO.EQ.0) THEN - WORK1(1) = 1 - WORK1(2) = MB*M*NBLCKS+5 - WORK1(3) = MINLW1 - WORK1(4) = MB - WORK1(5) = NB - WORK2(1) = MB * M - WORK2(2) = M + IF( INFO.EQ.0 ) THEN + IF( MINT ) THEN + T( 1 ) = MINTSZ + ELSE + T( 1 ) = MB*M*NBLCKS + 5 + END IF + T( 2 ) = MB + T( 3 ) = NB + IF( MINW ) THEN + WORK( 1 ) = MAX( 1, N ) + ELSE + WORK( 1 ) = MAX( 1, MB*M ) + END IF END IF IF( INFO.NE.0 ) THEN CALL XERBLA( 'CGELQ', -INFO ) RETURN - ELSE IF (LQUERY) THEN - RETURN + ELSE IF( LQUERY ) THEN + RETURN END IF * * Quick return if possible * - IF( MIN(M,N).EQ.0 ) THEN - RETURN + IF( MIN( M, N ).EQ.0 ) THEN + RETURN END IF * * The LQ Decomposition * - IF((N.LE.M).OR.(NB.LE.M).OR.(NB.GE.N)) THEN - CALL CGELQT( M, N, MB, A, LDA, WORK1(6), MB, WORK2, INFO) + IF( ( N.LE.M ) .OR. ( NB.LE.M ) .OR. ( NB.GE.N ) ) THEN + CALL CGELQT( M, N, MB, A, LDA, T( 6 ), MB, WORK, INFO ) ELSE - CALL CLASWLQ( M, N, MB, NB, A, LDA, WORK1(6), MB, WORK2, - $ LWORK2, INFO) + CALL CLASWLQ( M, N, MB, NB, A, LDA, T( 6 ), MB, WORK, + $ LWORK, INFO ) END IF +* + WORK( 1 ) = MAX( 1, MB*M ) +* RETURN * * End of CGELQ diff --git a/SRC/cgemlq.f b/SRC/cgemlq.f index 1a551ca3..59df3ddf 100644 --- a/SRC/cgemlq.f +++ b/SRC/cgemlq.f @@ -2,17 +2,18 @@ * Definition: * =========== * -* SUBROUTINE CGEMLQ( SIDE, TRANS, M, N, K, A, LDA, WORK1, -* $ LWORK1, C, LDC, WORK2, LWORK2, INFO ) +* SUBROUTINE CGEMLQ( SIDE, TRANS, M, N, K, A, LDA, T, +* $ TSIZE, C, LDC, WORK, LWORK, INFO ) * * * .. Scalar Arguments .. -* CHARACTER SIDE, TRANS -* INTEGER INFO, LDA, M, N, K, MB, NB, LWORK1, LWORK2, LDC +* CHARACTER SIDE, TRANS +* INTEGER INFO, LDA, M, N, K, LDT, TSIZE, LWORK, LDC * .. * .. Array Arguments .. -* COMPLEX A( LDA, * ), WORK1( * ), C(LDC, * ), -* $ WORK2( * ) +* COMPLEX A( LDA, * ), T( * ), C(LDC, * ), WORK( * ) +* .. +* *> \par Purpose: * ============= *> @@ -20,27 +21,32 @@ *> *> CGEMLQ overwrites the general real M-by-N matrix C with *> +*> SIDE = 'L' SIDE = 'R' +*> TRANS = 'N': Q * C C * Q +*> TRANS = 'C': Q**H * C C * Q**H +*> where Q is a complex unitary matrix defined as the product +*> of blocked elementary reflectors computed by short wide +*> LQ factorization (CGELQ) *> -*> SIDE = 'L' SIDE = 'R' -*> TRANS = 'N': Q * C C * Q -*> TRANS = 'T': Q**T * C C * Q**T -*> where Q is a complex orthogonal matrix defined as the product -*> of blocked elementary reflectors computed by short wide LQ -*> factorization (DGELQ) *> \endverbatim * * Arguments: * ========== * *> \param[in] SIDE +*> \verbatim *> SIDE is CHARACTER*1 *> = 'L': apply Q or Q**T from the Left; *> = 'R': apply Q or Q**T from the Right. +*> \endverbatim *> *> \param[in] TRANS +*> \verbatim *> TRANS is CHARACTER*1 *> = 'N': No transpose, apply Q; *> = 'T': Transpose, apply Q**T. +*> \endverbatim +*> *> \param[in] M *> \verbatim *> M is INTEGER @@ -50,7 +56,7 @@ *> \param[in] N *> \verbatim *> N is INTEGER -*> The number of columns of the matrix C. N >= M. +*> The number of columns of the matrix C. N >= 0. *> \endverbatim *> *> \param[in] K @@ -58,61 +64,64 @@ *> K is INTEGER *> The number of elementary reflectors whose product defines *> the matrix Q. -*> M >= K >= 0; -*> +*> If SIDE = 'L', M >= K >= 0; +*> if SIDE = 'R', N >= K >= 0. *> \endverbatim *> -*> \param[in,out] A +*> \param[in] A *> \verbatim -*> A is COMPLEX array, dimension (LDA,K) -*> The i-th row must contain the vector which defines the blocked -*> elementary reflector H(i), for i = 1,2,...,k, as returned by -*> DLASWLQ in the first k rows of its array argument A. +*> A is COMPLEX array, dimension +*> (LDA,M) if SIDE = 'L', +*> (LDA,N) if SIDE = 'R' +*> Part of the data structure to represent Q as returned by CGELQ. *> \endverbatim *> *> \param[in] LDA *> \verbatim *> LDA is INTEGER -*> The leading dimension of the array A. -*> If SIDE = 'L', LDA >= max(1,M); -*> if SIDE = 'R', LDA >= max(1,N). +*> The leading dimension of the array A. LDA >= max(1,K). *> \endverbatim *> -*> \param[in] WORK1 +*> \param[in] T *> \verbatim -*> WORK1 is COMPLEX array, dimension (MAX(1,LWORK1)) is -*> returned by GEQR. +*> T is COMPLEX array, dimension (MAX(5,TSIZE)). +*> Part of the data structure to represent Q as returned by CGELQ. *> \endverbatim *> -*> \param[in] LWORK1 +*> \param[in] TSIZE *> \verbatim -*> LWORK1 is INTEGER -*> The dimension of the array WORK1. +*> TSIZE is INTEGER +*> The dimension of the array T. TSIZE >= 5. *> \endverbatim *> *> \param[in,out] C +*> \verbatim *> C is COMPLEX array, dimension (LDC,N) *> On entry, the M-by-N matrix C. *> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +*> \endverbatim +*> *> \param[in] LDC +*> \verbatim *> LDC is INTEGER *> The leading dimension of the array C. LDC >= max(1,M). +*> \endverbatim *> -*> \param[out] WORK2 +*> \param[out] WORK *> \verbatim -*> (workspace) COMPLEX array, dimension (MAX(1,LWORK2)) -*> +*> (workspace) COMPLEX array, dimension (MAX(1,LWORK)) *> \endverbatim -*> \param[in] LWORK2 -*> \verbatim -*> LWORK2 is INTEGER -*> The dimension of the array WORK2. -*> If LWORK2 = -1, then a workspace query is assumed; the routine -*> only calculates the optimal size of the WORK2 array, returns -*> this value as the third entry of the WORK2 array (WORK2(1)), -*> and no error message related to LWORK2 is issued by XERBLA. *> +*> \param[in] LWORK +*> \verbatim +*> LWORK is INTEGER +*> The dimension of the array WORK. +*> If LWORK = -1, then a workspace query is assumed. The routine +*> only calculates the size of the WORK array, returns this +*> value as WORK(1), and no error message related to WORK +*> is issued by XERBLA. *> \endverbatim +*> *> \param[out] INFO *> \verbatim *> INFO is INTEGER @@ -128,53 +137,63 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \par Further Details: -* ===================== +*> \par Further Details +* ==================== *> *> \verbatim +*> +*> These details are particular for this LAPACK implementation. Users should not +*> take them for granted. These details may change in the future, and are unlikely not +*> true for another LAPACK implementation. These details are relevant if one wants +*> to try to understand the code. They are not part of the interface. +*> +*> In this version, +*> +*> T(2): row block size (MB) +*> T(3): column block size (NB) +*> T(6:TSIZE): data structure needed for Q, computed by +*> CLASWQR or CGELQT +*> *> Depending on the matrix dimensions M and N, and row and column -*> block sizes MB and NB returned by ILAENV, GELQ will use either -*> LASWLQ(if the matrix is short-and-wide) or GELQT to compute -*> the LQ decomposition. -*> The output of LASWLQ or GELQT representing Q is stored in A and in -*> array WORK1(6:LWORK1) for later use. -*> WORK1(2:5) contains the matrix dimensions M,N and block sizes MB, NB -*> which are needed to interpret A and WORK1(6:LWORK1) for later use. -*> WORK1(1)=1 indicates that the code needed to take WORK1(2:5) and -*> decide whether LASWLQ or GELQT was used is the same as used below in -*> GELQ. For a detailed description of A and WORK1(6:LWORK1), see -*> Further Details in LASWLQ or GELQT. +*> block sizes MB and NB returned by ILAENV, CGELQ will use either +*> CLASWLQ (if the matrix is wide-and-short) or CGELQT to compute +*> the LQ factorization. +*> This version of CGEMLQ will use either CLAMSWLQ or CGEMLQT to +*> multiply matrix Q by another matrix. +*> Further Details in CLAMSWLQ or CGEMLQT. *> \endverbatim *> * ===================================================================== - SUBROUTINE CGEMLQ( SIDE, TRANS, M, N, K, A, LDA, WORK1, LWORK1, - $ C, LDC, WORK2, LWORK2, INFO ) + SUBROUTINE CGEMLQ( SIDE, TRANS, M, N, K, A, LDA, T, TSIZE, + $ C, LDC, WORK, LWORK, INFO ) * -* -- LAPACK computational routine (version 3.5.0) -- +* -- LAPACK computational routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- -* November 2013 +* November 2016 * * .. Scalar Arguments .. - CHARACTER SIDE, TRANS - INTEGER INFO, LDA, M, N, K, LWORK1, LWORK2, LDC + CHARACTER SIDE, TRANS + INTEGER INFO, LDA, M, N, K, TSIZE, LWORK, LDC * .. * .. Array Arguments .. - COMPLEX A( LDA, * ), C( LDC, * ), WORK1( * ), WORK2( * ) + COMPLEX A( LDA, * ), T( * ), C( LDC, * ), WORK( * ) * .. * * ===================================================================== * * .. * .. Local Scalars .. - LOGICAL LEFT, RIGHT, TRAN, NOTRAN, LQUERY - INTEGER I, II, KK, MB, NB, LW, NBLCKS, MN + LOGICAL LEFT, RIGHT, TRAN, NOTRAN, LQUERY + INTEGER MB, NB, LW, NBLCKS, MN * .. * .. External Functions .. LOGICAL LSAME EXTERNAL LSAME +* .. * .. External Subroutines .. EXTERNAL CLAMSWLQ, CGEMLQT, XERBLA +* .. * .. Intrinsic Functions .. INTRINSIC INT, MAX, MIN, MOD * .. @@ -182,26 +201,27 @@ * * Test the input arguments * - LQUERY = LWORK2.LT.0 + LQUERY = LWORK.EQ.-1 NOTRAN = LSAME( TRANS, 'N' ) TRAN = LSAME( TRANS, 'C' ) LEFT = LSAME( SIDE, 'L' ) RIGHT = LSAME( SIDE, 'R' ) * - MB = INT(WORK1(4)) - NB = INT(WORK1(5)) - IF (LEFT) THEN + MB = INT( T( 2 ) ) + NB = INT( T( 3 ) ) + IF( LEFT ) THEN LW = N * MB MN = M ELSE LW = M * MB MN = N END IF - IF ((NB.GT.K).AND.(MN.GT.K)) THEN - IF(MOD(MN-K, NB-K).EQ.0) THEN - NBLCKS = (MN-K)/(NB-K) +* + IF( ( NB.GT.K ) .AND. ( MN.GT.K ) ) THEN + IF( MOD( MN - K, NB - K ) .EQ. 0 ) THEN + NBLCKS = ( MN - K ) / ( NB - K ) ELSE - NBLCKS = (MN-K)/(NB-K) + 1 + NBLCKS = ( MN - K ) / ( NB - K ) + 1 END IF ELSE NBLCKS = 1 @@ -209,51 +229,53 @@ * INFO = 0 IF( .NOT.LEFT .AND. .NOT.RIGHT ) THEN - INFO = -1 + INFO = -1 ELSE IF( .NOT.TRAN .AND. .NOT.NOTRAN ) THEN - INFO = -2 + INFO = -2 ELSE IF( M.LT.0 ) THEN INFO = -3 - ELSE IF( N.LT.0) THEN + ELSE IF( N.LT.0 ) THEN INFO = -4 - ELSE IF( K.LT.0 ) THEN + ELSE IF( K.LT.0 .OR. K.GT.MN ) THEN INFO = -5 ELSE IF( LDA.LT.MAX( 1, K ) ) THEN INFO = -7 - ELSE IF( LWORK1.LT.MAX( 1, MB*K*NBLCKS+5 )) THEN + ELSE IF( TSIZE.LT.5 ) THEN INFO = -9 ELSE IF( LDC.LT.MAX( 1, M ) ) THEN - INFO = -11 - ELSE IF(( LWORK2.LT.MAX(1,LW)).AND.(.NOT.LQUERY)) THEN + INFO = -11 + ELSE IF( ( LWORK.LT.MAX( 1, LW ) ) .AND. ( .NOT.LQUERY ) ) THEN INFO = -13 END IF * - IF( INFO.EQ.0) THEN - WORK2(1) = LW + IF( INFO.EQ.0 ) THEN + WORK( 1 ) = REAL( LW ) END IF +* IF( INFO.NE.0 ) THEN CALL XERBLA( 'CGEMLQ', -INFO ) RETURN - ELSE IF (LQUERY) THEN + ELSE IF( LQUERY ) THEN RETURN END IF * * Quick return if possible * - IF( MIN(M,N,K).EQ.0 ) THEN + IF( MIN( M, N, K ).EQ.0 ) THEN RETURN END IF * - IF((LEFT.AND.M.LE.K).OR.(RIGHT.AND.N.LE.K).OR.(NB.LE.K).OR. - $ (NB.GE.MAX(M,N,K))) THEN + IF( ( LEFT .AND. M.LE.K ) .OR. ( RIGHT .AND. N.LE.K ) + $ .OR. ( NB.LE.K ) .OR. ( NB.GE.MAX( M, N, K ) ) ) THEN CALL CGEMLQT( SIDE, TRANS, M, N, K, MB, A, LDA, - $ WORK1(6), MB, C, LDC, WORK2, INFO) + $ T( 6 ), MB, C, LDC, WORK, INFO ) ELSE - CALL CLAMSWLQ( SIDE, TRANS, M, N, K, MB, NB, A, LDA, WORK1(6), - $ MB, C, LDC, WORK2, LWORK2, INFO ) + CALL CLAMSWLQ( SIDE, TRANS, M, N, K, MB, NB, A, LDA, T( 6 ), + $ MB, C, LDC, WORK, LWORK, INFO ) END IF * - WORK2(1) = LW + WORK( 1 ) = REAL( LW ) +* RETURN * * End of CGEMLQ diff --git a/SRC/cgemqr.f b/SRC/cgemqr.f index 51d38b85..a5420553 100644 --- a/SRC/cgemqr.f +++ b/SRC/cgemqr.f @@ -2,45 +2,52 @@ * Definition: * =========== * -* SUBROUTINE CGEMQR( SIDE, TRANS, M, N, K, A, LDA, WORK1, -* $ LWORK1, C, LDC, WORK2, LWORK2, INFO ) +* SUBROUTINE CGEMQR( SIDE, TRANS, M, N, K, A, LDA, T, +* $ TSIZE, C, LDC, WORK, LWORK, INFO ) * * * .. Scalar Arguments .. -* CHARACTER SIDE, TRANS -* INTEGER INFO, LDA, M, N, K, LDT, LWORK1, LWORK2, LDC +* CHARACTER SIDE, TRANS +* INTEGER INFO, LDA, M, N, K, LDT, TSIZE, LWORK, LDC * .. * .. Array Arguments .. -* COMPLEX A( LDA, * ), WORK1( * ), C(LDC, * ), -* $ WORK2( * ) +* COMPLEX A( LDA, * ), T( * ), C( LDC, * ), WORK( * ) +* .. +* *> \par Purpose: * ============= *> *> \verbatim *> -*> CGEMQR overwrites the general real M-by-N matrix C with -*> +*> CGEMQR overwrites the general real M-by-N matrix C with *> *> SIDE = 'L' SIDE = 'R' *> TRANS = 'N': Q * C C * Q -*> TRANS = 'T': Q**T * C C * Q**T -*> where Q is a complex orthogonal matrix defined as the product -*> of blocked elementary reflectors computed by tall skinny -*> QR factorization (CGEQR) +*> TRANS = 'T': Q**H * C C * Q**H +*> +*> where Q is a complex unitary matrix defined as the product +*> of blocked elementary reflectors computed by tall skinny +*> QR factorization (CGEQR) +*> *> \endverbatim * * Arguments: * ========== * *> \param[in] SIDE +*> \verbatim *> SIDE is CHARACTER*1 *> = 'L': apply Q or Q**T from the Left; *> = 'R': apply Q or Q**T from the Right. +*> \endverbatim *> *> \param[in] TRANS +*> \verbatim *> TRANS is CHARACTER*1 *> = 'N': No transpose, apply Q; *> = 'T': Transpose, apply Q**T. +*> \endverbatim +*> *> \param[in] M *> \verbatim *> M is INTEGER @@ -50,7 +57,7 @@ *> \param[in] N *> \verbatim *> N is INTEGER -*> The number of columns of the matrix C. M >= N >= 0. +*> The number of columns of the matrix C. N >= 0. *> \endverbatim *> *> \param[in] K @@ -58,17 +65,14 @@ *> K is INTEGER *> The number of elementary reflectors whose product defines *> the matrix Q. -*> N >= K >= 0; -*> +*> If SIDE = 'L', M >= K >= 0; +*> if SIDE = 'R', N >= K >= 0. *> \endverbatim *> -*> \param[in,out] A +*> \param[in] A *> \verbatim *> A is COMPLEX array, dimension (LDA,K) -*> The i-th column must contain the vector which defines the -*> blockedelementary reflector H(i), for i = 1,2,...,k, as -*> returned by DGETSQR in the first k columns of -*> its array argument A. +*> Part of the data structure to represent Q as returned by CGEQR. *> \endverbatim *> *> \param[in] LDA @@ -79,42 +83,46 @@ *> if SIDE = 'R', LDA >= max(1,N). *> \endverbatim *> -*> \param[in] WORK1 +*> \param[in] T *> \verbatim -*> WORK1 is COMPLEX array, dimension (MAX(1,LWORK1)) as -*> it is returned by GEQR. +*> T is COMPLEX array, dimension (MAX(5,TSIZE)). +*> Part of the data structure to represent Q as returned by CGEQR. *> \endverbatim *> -*> \param[in] LWORK1 +*> \param[in] TSIZE *> \verbatim -*> LWORK1 is INTEGER -*> The dimension of the array WORK1. +*> TSIZE is INTEGER +*> The dimension of the array T. TSIZE >= 5. *> \endverbatim *> *> \param[in,out] C +*> \verbatim *> C is COMPLEX array, dimension (LDC,N) *> On entry, the M-by-N matrix C. *> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +*> \endverbatim *> *> \param[in] LDC +*> \verbatim *> LDC is INTEGER *> The leading dimension of the array C. LDC >= max(1,M). +*> \endverbatim *> -*> \param[out] WORK2 +*> \param[out] WORK *> \verbatim -*> (workspace) COMPLEX array, dimension (MAX(1,LWORK2)) -*> +*> (workspace) COMPLEX array, dimension (MAX(1,LWORK)) *> \endverbatim -*> \param[in] LWORK2 -*> \verbatim -*> LWORK2 is INTEGER -*> The dimension of the array WORK2. -*> If LWORK2 = -1, then a workspace query is assumed; the routine -*> only calculates the optimal size of the WORK2 array, returns -*> this value as the third entry of the WORK2 array (WORK2(1)), -*> and no error message related to LWORK2 is issued by XERBLA. *> +*> \param[in] LWORK +*> \verbatim +*> LWORK is INTEGER +*> The dimension of the array WORK. +*> If LWORK = -1, then a workspace query is assumed. The routine +*> only calculates the size of the WORK array, returns this +*> value as WORK(1), and no error message related to WORK +*> is issued by XERBLA. *> \endverbatim +*> *> \param[out] INFO *> \verbatim *> INFO is INTEGER @@ -130,54 +138,64 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \par Further Details: -* ===================== +*> \par Further Details +* ==================== *> *> \verbatim +*> +*> These details are particular for this LAPACK implementation. Users should not +*> take them for granted. These details may change in the future, and are unlikely not +*> true for another LAPACK implementation. These details are relevant if one wants +*> to try to understand the code. They are not part of the interface. +*> +*> In this version, +*> +*> T(2): row block size (MB) +*> T(3): column block size (NB) +*> T(6:TSIZE): data structure needed for Q, computed by +*> CLATSQR or CGEQRT +*> *> Depending on the matrix dimensions M and N, and row and column -*> block sizes MB and NB returned by ILAENV, GEQR will use either -*> LATSQR (if the matrix is tall-and-skinny) or GEQRT to compute -*> the QR decomposition. -*> The output of LATSQR or GEQRT representing Q is stored in A and in -*> array WORK1(6:LWORK1) for later use. -*> WORK1(2:5) contains the matrix dimensions M,N and block sizes MB,NB -*> which are needed to interpret A and WORK1(6:LWORK1) for later use. -*> WORK1(1)=1 indicates that the code needed to take WORK1(2:5) and -*> decide whether LATSQR or GEQRT was used is the same as used below in -*> GEQR. For a detailed description of A and WORK1(6:LWORK1), see -*> Further Details in LATSQR or GEQRT. +*> block sizes MB and NB returned by ILAENV, CGEQR will use either +*> CLATSQR (if the matrix is tall-and-skinny) or CGEQRT to compute +*> the QR factorization. +*> This version of CGEMQR will use either CLAMTSQR or CGEMQRT to +*> multiply matrix Q by another matrix. +*> Further Details in CLAMTSQR or CGEMQRT. +*> *> \endverbatim *> * ===================================================================== - SUBROUTINE CGEMQR( SIDE, TRANS, M, N, K, A, LDA, WORK1, LWORK1, - $ C, LDC, WORK2, LWORK2, INFO ) + SUBROUTINE CGEMQR( SIDE, TRANS, M, N, K, A, LDA, T, TSIZE, + $ C, LDC, WORK, LWORK, INFO ) * -* -- LAPACK computational routine (version 3.5.0) -- +* -- LAPACK computational routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- -* November 2013 +* November 2016 * * .. Scalar Arguments .. - CHARACTER SIDE, TRANS - INTEGER INFO, LDA, M, N, K, LWORK1, LWORK2, LDC + CHARACTER SIDE, TRANS + INTEGER INFO, LDA, M, N, K, TSIZE, LWORK, LDC * .. * .. Array Arguments .. - COMPLEX A( LDA, * ), WORK1( * ), C(LDC, * ), - $ WORK2( * ) + COMPLEX A( LDA, * ), T( * ), C( LDC, * ), WORK( * ) * .. * * ===================================================================== * * .. * .. Local Scalars .. - LOGICAL LEFT, RIGHT, TRAN, NOTRAN, LQUERY - INTEGER MB, NB, I, II, KK, LW, NBLCKS, MN + LOGICAL LEFT, RIGHT, TRAN, NOTRAN, LQUERY + INTEGER MB, NB, LW, NBLCKS, MN * .. * .. External Functions .. LOGICAL LSAME EXTERNAL LSAME +* .. * .. External Subroutines .. EXTERNAL CGEMQRT, CLAMTSQR, XERBLA +* .. * .. Intrinsic Functions .. INTRINSIC INT, MAX, MIN, MOD * .. @@ -185,82 +203,81 @@ * * Test the input arguments * - LQUERY = LWORK2.LT.0 + LQUERY = LWORK.EQ.-1 NOTRAN = LSAME( TRANS, 'N' ) TRAN = LSAME( TRANS, 'C' ) LEFT = LSAME( SIDE, 'L' ) RIGHT = LSAME( SIDE, 'R' ) * - MB = INT(WORK1(4)) - NB = INT(WORK1(5)) - IF(LEFT) THEN + MB = INT( T( 2 ) ) + NB = INT( T( 3 ) ) + IF( LEFT ) THEN LW = N * NB MN = M - ELSE IF(RIGHT) THEN + ELSE LW = MB * NB MN = N END IF * - IF ((MB.GT.K).AND.(MN.GT.K)) THEN - IF(MOD(MN-K, MB-K).EQ.0) THEN - NBLCKS = (MN-K)/(MB-K) - ELSE - NBLCKS = (MN-K)/(MB-K) + 1 - END IF + IF( ( MB.GT.K ) .AND. ( MN.GT.K ) ) THEN + IF( MOD( MN - K, MB - K ).EQ.0 ) THEN + NBLCKS = ( MN - K ) / ( MB - K ) + ELSE + NBLCKS = ( MN - K ) / ( MB - K ) + 1 + END IF ELSE NBLCKS = 1 END IF * INFO = 0 IF( .NOT.LEFT .AND. .NOT.RIGHT ) THEN - INFO = -1 + INFO = -1 ELSE IF( .NOT.TRAN .AND. .NOT.NOTRAN ) THEN - INFO = -2 + INFO = -2 ELSE IF( M.LT.0 ) THEN INFO = -3 ELSE IF( N.LT.0 ) THEN INFO = -4 - ELSE IF( K.LT.0 ) THEN + ELSE IF( K.LT.0 .OR. K.GT.MN ) THEN INFO = -5 - ELSE IF( LDA.LT.MAX( 1, K ) ) THEN + ELSE IF( LDA.LT.MAX( 1, MN ) ) THEN INFO = -7 - ELSE IF( LWORK1.LT.MAX( 1, NB*K*NBLCKS+5 )) THEN + ELSE IF( TSIZE.LT.5 ) THEN INFO = -9 ELSE IF( LDC.LT.MAX( 1, M ) ) THEN - INFO = -11 - ELSE IF(( LWORK2.LT.MAX(1,LW)).AND.(.NOT.LQUERY)) THEN + INFO = -11 + ELSE IF( ( LWORK.LT.MAX( 1, LW ) ) .AND. ( .NOT.LQUERY ) ) THEN INFO = -13 END IF * -* Determine the block size if it is tall skinny or short and wide -* - IF( INFO.EQ.0) THEN - WORK2(1) = LW + IF( INFO.EQ.0 ) THEN + WORK( 1 ) = LW END IF * IF( INFO.NE.0 ) THEN CALL XERBLA( 'CGEMQR', -INFO ) RETURN - ELSE IF (LQUERY) THEN - RETURN + ELSE IF( LQUERY ) THEN + RETURN END IF * * Quick return if possible * - IF( MIN(M,N,K).EQ.0 ) THEN + IF( MIN( M, N, K ).EQ.0 ) THEN RETURN END IF * - IF((LEFT.AND.M.LE.K).OR.(RIGHT.AND.N.LE.K).OR.(MB.LE.K).OR. - $ (MB.GE.MAX(M,N,K))) THEN - CALL CGEMQRT( SIDE, TRANS, M, N, K, NB, A, LDA, - $ WORK1(6), NB, C, LDC, WORK2, INFO) + IF( ( LEFT .AND. M.LE.K ) .OR. ( RIGHT .AND. N.LE.K ) + $ .OR. ( MB.LE.K ) .OR. ( MB.GE.MAX( M, N, K ) ) ) THEN + CALL CGEMQRT( SIDE, TRANS, M, N, K, NB, A, LDA, T( 6 ), + $ NB, C, LDC, WORK, INFO ) ELSE - CALL CLAMTSQR( SIDE, TRANS, M, N, K, MB, NB, A, LDA, WORK1(6), - $ NB, C, LDC, WORK2, LWORK2, INFO ) + CALL CLAMTSQR( SIDE, TRANS, M, N, K, MB, NB, A, LDA, T( 6 ), + $ NB, C, LDC, WORK, LWORK, INFO ) END IF * - WORK2(1) = LW + WORK( 1 ) = LW +* RETURN * * End of CGEMQR diff --git a/SRC/cgeqr.f b/SRC/cgeqr.f index 330fda5c..e336a916 100644 --- a/SRC/cgeqr.f +++ b/SRC/cgeqr.f @@ -2,14 +2,14 @@ * Definition: * =========== * -* SUBROUTINE CGEQR( M, N, A, LDA, WORK1, LWORK1, WORK2, LWORK2, -* INFO) +* SUBROUTINE CGEQR( M, N, A, LDA, T, TSIZE, WORK, LWORK, +* INFO ) * * .. Scalar Arguments .. -* INTEGER INFO, LDA, M, N, LWORK1, LWORK2 +* INTEGER INFO, LDA, M, N, TSIZE, LWORK * .. * .. Array Arguments .. -* COMPLEX A( LDA, * ), WORK1( * ), WORK2( * ) +* COMPLEX A( LDA, * ), T( * ), WORK( * ) * .. * * @@ -17,11 +17,7 @@ * ============= *> *> \verbatim -*> -*> CGEQR computes a QR factorization of an M-by-N matrix A, -*> using CLATSQR when A is tall and skinny -*> (M sufficiently greater than N), and otherwise CGEQRT: -*> A = Q * R . +*> CGEQR computes a QR factorization of an M-by-N matrix A. *> \endverbatim * * Arguments: @@ -46,7 +42,8 @@ *> On exit, the elements on and above the diagonal of the array *> contain the min(M,N)-by-N upper trapezoidal matrix R *> (R is upper triangular if M >= N); -*> the elements below the diagonal represent Q (see Further Details). +*> the elements below the diagonal are used to store part of the +*> data structure to represent Q. *> \endverbatim *> *> \param[in] LDA @@ -55,47 +52,50 @@ *> The leading dimension of the array A. LDA >= max(1,M). *> \endverbatim *> -*> \param[out] WORK1 +*> \param[out] T *> \verbatim -*> WORK1 is COMPLEX array, dimension (MAX(1,LWORK1)) -*> WORK1 contains part of the data structure used to store Q. -*> WORK1(1): algorithm type = 1, to indicate output from -*> CLATSQR or CGEQRT -*> WORK1(2): optimum size of WORK1 -*> WORK1(3): minimum size of WORK1 -*> WORK1(4): row block size -*> WORK1(5): column block size -*> WORK1(6:LWORK1): data structure needed for Q, computed by -*> CLATSQR or CGEQRT +*> T is COMPLEX array, dimension (MAX(5,TSIZE)) +*> On exit, if INFO = 0, T(1) returns optimal (or either minimal +*> or optimal, if query is assumed) TSIZE. See TSIZE for details. +*> Remaining T contains part of the data structure used to represent Q. +*> If one wants to apply or construct Q, then one needs to keep T +*> (in addition to A) and pass it to further subroutines. *> \endverbatim *> -*> \param[in] LWORK1 +*> \param[in] TSIZE *> \verbatim -*> LWORK1 is INTEGER -*> The dimension of the array WORK1. -*> If LWORK1 = -1, then a query is assumed. In this case the -*> routine calculates the optimal size of WORK1 and -*> returns this value in WORK1(2), and calculates the minimum -*> size of WORK1 and returns this value in WORK1(3). -*> No error message related to LWORK1 is issued by XERBLA when -*> LWORK1 = -1. +*> TSIZE is INTEGER +*> If TSIZE >= 5, the dimension of the array T. +*> If TSIZE = -1 or -2, then a workspace query is assumed. The routine +*> only calculates the sizes of the T and WORK arrays, returns these +*> values as the first entries of the T and WORK arrays, and no error +*> message related to T or WORK is issued by XERBLA. +*> If TSIZE = -1, the routine calculates optimal size of T for the +*> optimum performance and returns this value in T(1). +*> If TSIZE = -2, the routine calculates minimal size of T and +*> returns this value in T(1). *> \endverbatim *> -*> \param[out] WORK2 +*> \param[out] WORK *> \verbatim -*> (workspace) COMPLEX array, dimension (MAX(1,LWORK2)) +*> (workspace) COMPLEX array, dimension (MAX(1,LWORK)) +*> On exit, if INFO = 0, WORK(1) contains optimal (or either minimal +*> or optimal, if query was assumed) LWORK. +*> See LWORK for details. *> \endverbatim *> -*> \param[in] LWORK2 +*> \param[in] LWORK *> \verbatim -*> LWORK2 is INTEGER -*> The dimension of the array WORK2. -*> If LWORK2 = -1, then a query is assumed. In this case the -*> routine calculates the optimal size of WORK2 and -*> returns this value in WORK2(1), and calculates the minimum -*> size of WORK2 and returns this value in WORK2(2). -*> No error message related to LWORK2 is issued by XERBLA when -*> LWORK2 = -1. +*> LWORK is INTEGER +*> The dimension of the array WORK. +*> If LWORK = -1 or -2, then a workspace query is assumed. The routine +*> only calculates the sizes of the T and WORK arrays, returns these +*> values as the first entries of the T and WORK arrays, and no error +*> message related to T or WORK is issued by XERBLA. +*> If LWORK = -1, the routine calculates optimal size of WORK for the +*> optimal performance and returns this value in WORK(1). +*> If LWORK = -2, the routine calculates minimal size of WORK and +*> returns this value in WORK(1). *> \endverbatim *> *> \param[out] INFO @@ -113,106 +113,138 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \par Further Details: -* ===================== +*> \par Further Details +* ==================== +*> +*> \verbatim +*> +*> The goal of the interface is to give maximum freedom to the developers for +*> creating any QR factorization algorithm they wish. The triangular +*> (trapezoidal) R has to be stored in the upper part of A. The lower part of A +*> and the array T can be used to store any relevant information for applying or +*> constructing the Q factor. The WORK array can safely be discarded after exit. +*> +*> Caution: One should not expect the sizes of T and WORK to be the same from one +*> LAPACK implementation to the other, or even from one execution to the other. +*> A workspace query (for T and WORK) is needed at each execution. However, +*> for a given execution, the size of T and WORK are fixed and will not change +*> from one query to the next. +*> +*> \endverbatim +*> +*> \par Further Details particular to this LAPACK implementation: +* ============================================================== *> *> \verbatim +*> +*> These details are particular for this LAPACK implementation. Users should not +*> take them for granted. These details may change in the future, and are unlikely not +*> true for another LAPACK implementation. These details are relevant if one wants +*> to try to understand the code. They are not part of the interface. +*> +*> In this version, +*> +*> T(2): row block size (MB) +*> T(3): column block size (NB) +*> T(6:TSIZE): data structure needed for Q, computed by +*> CLATSQR or CGEQRT +*> *> Depending on the matrix dimensions M and N, and row and column -*> block sizes MB and NB returned by ILAENV, GEQR will use either -*> LATSQR (if the matrix is tall-and-skinny) or GEQRT to compute -*> the QR decomposition. -*> The output of LATSQR or GEQRT representing Q is stored in A and in -*> array WORK1(6:LWORK1) for later use. -*> WORK1(2:5) contains the matrix dimensions M,N and block sizes MB,NB -*> which are needed to interpret A and WORK1(6:LWORK1) for later use. -*> WORK1(1)=1 indicates that the code needed to take WORK1(2:5) and -*> decide whether LATSQR or GEQRT was used is the same as used below in -*> GEQR. For a detailed description of A and WORK1(6:LWORK1), see -*> Further Details in LATSQR or GEQRT. +*> block sizes MB and NB returned by ILAENV, CGEQR will use either +*> CLATSQR (if the matrix is tall-and-skinny) or CGEQRT to compute +*> the QR factorization. +*> *> \endverbatim *> * ===================================================================== - SUBROUTINE CGEQR( M, N, A, LDA, WORK1, LWORK1, WORK2, LWORK2, - $ INFO) + SUBROUTINE CGEQR( M, N, A, LDA, T, TSIZE, WORK, LWORK, + $ INFO ) * -* -- LAPACK computational routine (version 3.5.0) -- +* -- LAPACK computational routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd. -- -* November 2013 +* November 2016 * * .. Scalar Arguments .. - INTEGER INFO, LDA, M, N, LWORK1, LWORK2 + INTEGER INFO, LDA, M, N, TSIZE, LWORK * .. * .. Array Arguments .. - COMPLEX A( LDA, * ), WORK1( * ), WORK2( * ) + COMPLEX A( LDA, * ), T( * ), WORK( * ) * .. * * ===================================================================== * * .. * .. Local Scalars .. - LOGICAL LQUERY, LMINWS - INTEGER MB, NB, I, II, KK, MINLW1, NBLCKS + LOGICAL LQUERY, LMINWS, MINT, MINW + INTEGER MB, NB, MINTSZ, NBLCKS * .. -* .. EXTERNAL FUNCTIONS .. +* .. External Functions .. LOGICAL LSAME EXTERNAL LSAME -* .. EXTERNAL SUBROUTINES .. +* .. +* .. External Subroutines .. EXTERNAL CLATSQR, CGEQRT, XERBLA -* .. INTRINSIC FUNCTIONS .. +* .. +* .. Intrinsic Functions .. INTRINSIC MAX, MIN, MOD * .. -* .. EXTERNAL FUNCTIONS .. +* .. External Functions .. INTEGER ILAENV EXTERNAL ILAENV * .. -* .. EXECUTABLE STATEMENTS .. +* .. Executable Statements .. * -* TEST THE INPUT ARGUMENTS +* Test the input arguments * INFO = 0 * - LQUERY = ( LWORK1.EQ.-1 .OR. LWORK2.EQ.-1 ) + LQUERY = ( TSIZE.EQ.-1 .OR. TSIZE.EQ.-2 .OR. + $ LWORK.EQ.-1 .OR. LWORK.EQ.-2 ) +* + MINT = .FALSE. + MINW = .FALSE. + IF( TSIZE.EQ.-2 .OR. LWORK.EQ.-2 ) THEN + IF( TSIZE.NE.-1 ) MINT = .TRUE. + IF( LWORK.NE.-1 ) MINW = .TRUE. + END IF * * Determine the block size * - IF ( MIN(M,N).GT.0 ) THEN - MB = ILAENV( 1, 'CGEQR ', ' ', M, N, 1, -1) - NB = ILAENV( 1, 'CGEQR ', ' ', M, N, 2, -1) + IF( MIN( M, N ).GT.0 ) THEN + MB = ILAENV( 1, 'CGEQR ', ' ', M, N, 1, -1 ) + NB = ILAENV( 1, 'CGEQR ', ' ', M, N, 2, -1 ) ELSE MB = M NB = 1 END IF - IF( MB.GT.M.OR.MB.LE.N) MB = M - IF( NB.GT.MIN(M,N).OR.NB.LT.1) NB = 1 - MINLW1 = N + 5 - IF ((MB.GT.N).AND.(M.GT.N)) THEN - IF(MOD(M-N, MB-N).EQ.0) THEN - NBLCKS = (M-N)/(MB-N) + IF( MB.GT.M .OR. MB.LE.N ) MB = M + IF( NB.GT.MIN( M, N ) .OR. NB.LT.1 ) NB = 1 + MINTSZ = N + 5 + IF( MB.GT.N .AND. M.GT.N ) THEN + IF( MOD( M - N, MB - N ).EQ.0 ) THEN + NBLCKS = ( M - N ) / ( MB - N ) ELSE - NBLCKS = (M-N)/(MB-N) + 1 + NBLCKS = ( M - N ) / ( MB - N ) + 1 END IF ELSE NBLCKS = 1 END IF * -* Determine if the workspace size satisfies minimum size +* Determine if the workspace size satisfies minimal size * LMINWS = .FALSE. - IF((LWORK1.LT.MAX(1, NB*N*NBLCKS+5) - $ .OR.(LWORK2.LT.NB*N)).AND.(LWORK2.GE.N).AND.(LWORK1.GT.N+5) - $ .AND.(.NOT.LQUERY)) THEN - IF (LWORK1.LT.MAX(1, NB * N * NBLCKS+5)) THEN - LMINWS = .TRUE. - NB = 1 - END IF - IF (LWORK1.LT.MAX(1, N * NBLCKS+5)) THEN - LMINWS = .TRUE. - MB = M + IF( ( TSIZE.LT.MAX( 1, NB*N*NBLCKS + 5 ) .OR. LWORK.LT.NB*N ) + $ .AND. ( LWORK.GE.N ) .AND. ( TSIZE.GE.MINTSZ ) + $ .AND. ( .NOT.LQUERY ) ) THEN + IF( TSIZE.LT.MAX( 1, NB*N*NBLCKS + 5 ) ) THEN + LMINWS = .TRUE. + NB = 1 + MB = M END IF - IF (LWORK2.LT.NB*N) THEN - LMINWS = .TRUE. - NB = 1 + IF( LWORK.LT.NB*N ) THEN + LMINWS = .TRUE. + NB = 1 END IF END IF * @@ -222,45 +254,52 @@ INFO = -2 ELSE IF( LDA.LT.MAX( 1, M ) ) THEN INFO = -4 - ELSE IF( LWORK1.LT.MAX( 1, NB * N * NBLCKS + 5 ) - $ .AND.(.NOT.LQUERY).AND.(.NOT.LMINWS)) THEN + ELSE IF( TSIZE.LT.MAX( 1, NB*N*NBLCKS + 5 ) + $ .AND. ( .NOT.LQUERY ) .AND. ( .NOT.LMINWS ) ) THEN INFO = -6 - ELSE IF( (LWORK2.LT.MAX(1,N*NB)).AND.(.NOT.LQUERY) - $ .AND.(.NOT.LMINWS)) THEN + ELSE IF( ( LWORK.LT.MAX( 1, N*NB ) ) .AND. ( .NOT.LQUERY ) + $ .AND. ( .NOT.LMINWS ) ) THEN INFO = -8 END IF * - IF( INFO.EQ.0) THEN - WORK1(1) = 1 - WORK1(2) = NB * N * NBLCKS + 5 - WORK1(3) = MINLW1 - WORK1(4) = MB - WORK1(5) = NB - WORK2(1) = NB * N - WORK2(2) = N + IF( INFO.EQ.0 ) THEN + IF( MINT ) THEN + T( 1 ) = MINTSZ + ELSE + T( 1 ) = NB*N*NBLCKS + 5 + END IF + T( 2 ) = MB + T( 3 ) = NB + IF( MINW ) THEN + WORK( 1 ) = MAX( 1, N ) + ELSE + WORK( 1 ) = MAX( 1, NB*N ) + END IF END IF IF( INFO.NE.0 ) THEN CALL XERBLA( 'CGEQR', -INFO ) RETURN - ELSE IF (LQUERY) THEN - RETURN + ELSE IF( LQUERY ) THEN + RETURN END IF * * Quick return if possible * - IF( MIN(M,N).EQ.0 ) THEN - RETURN + IF( MIN( M, N ).EQ.0 ) THEN + RETURN END IF * * The QR Decomposition * - IF((M.LE.N).OR.(MB.LE.N).OR.(MB.GE.M)) THEN - CALL CGEQRT( M, N, NB, A, LDA, WORK1(6), NB, WORK2, INFO) - RETURN + IF( ( M.LE.N ) .OR. ( MB.LE.N ) .OR. ( MB.GE.M ) ) THEN + CALL CGEQRT( M, N, NB, A, LDA, T( 6 ), NB, WORK, INFO ) ELSE - CALL CLATSQR( M, N, MB, NB, A, LDA, WORK1(6), NB, WORK2, - $ LWORK2, INFO) + CALL CLATSQR( M, N, MB, NB, A, LDA, T( 6 ), NB, WORK, + $ LWORK, INFO ) END IF +* + WORK( 1 ) = MAX( 1, NB*N ) +* RETURN * * End of CGEQR diff --git a/SRC/cgetsls.f b/SRC/cgetsls.f index af5bd2cb..1ba3045e 100644 --- a/SRC/cgetsls.f +++ b/SRC/cgetsls.f @@ -1,16 +1,15 @@ * Definition: * =========== * -* SUBROUTINE CGETSLS( TRANS, M, N, NRHS, A, LDA, B, LDB -* $ , WORK, LWORK, INFO ) - +* SUBROUTINE CGETSLS( TRANS, M, N, NRHS, A, LDA, B, LDB, +* $ WORK, LWORK, INFO ) * * .. Scalar Arguments .. * CHARACTER TRANS * INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS * .. * .. Array Arguments .. -* COMPLEX A( LDA, * ), B( LDB, * ), WORK( * ) +* COMPLEX A( LDA, * ), B( LDB, * ), WORK( * ) * .. * * @@ -19,10 +18,11 @@ *> *> \verbatim *> -*> CGETSLS solves overdetermined or underdetermined real linear systems -*> involving an M-by-N matrix A, or its transpose, using a tall skinny -*> QR or short wide LQfactorization of A. It is assumed that A has -*> full rank. +*> CGETSLS solves overdetermined or underdetermined complex linear systems +*> involving an M-by-N matrix A, using a tall skinny QR or short wide LQ +*> factorization of A. It is assumed that A has full rank. +*> +*> *> *> The following options are provided: *> @@ -80,10 +80,8 @@ *> A is COMPLEX array, dimension (LDA,N) *> On entry, the M-by-N matrix A. *> On exit, -*> if M >= N, A is overwritten by details of its QR -*> factorization as returned by DGEQRF; -*> if M < N, A is overwritten by details of its LQ -*> factorization as returned by DGELQF. +*> A is overwritten by details of its QR or LQ +*> factorization as returned by CGEQR or CGELQ. *> \endverbatim *> *> \param[in] LDA @@ -97,21 +95,17 @@ *> B is COMPLEX array, dimension (LDB,NRHS) *> On entry, the matrix B of right hand side vectors, stored *> columnwise; B is M-by-NRHS if TRANS = 'N', or N-by-NRHS -*> if TRANS = 'T'. +*> if TRANS = 'C'. *> On exit, if INFO = 0, B is overwritten by the solution *> vectors, stored columnwise: *> if TRANS = 'N' and m >= n, rows 1 to n of B contain the least -*> squares solution vectors; the residual sum of squares for the -*> solution in each column is given by the sum of squares of -*> elements N+1 to M in that column; +*> squares solution vectors. *> if TRANS = 'N' and m < n, rows 1 to N of B contain the *> minimum norm solution vectors; -*> if TRANS = 'T' and m >= n, rows 1 to M of B contain the +*> if TRANS = 'C' and m >= n, rows 1 to M of B contain the *> minimum norm solution vectors; -*> if TRANS = 'T' and m < n, rows 1 to M of B contain the -*> least squares solution vectors; the residual sum of squares -*> for the solution in each column is given by the sum of -*> squares of elements M+1 to N in that column. +*> if TRANS = 'C' and m < n, rows 1 to M of B contain the +*> least squares solution vectors. *> \endverbatim *> *> \param[in] LDB @@ -122,23 +116,21 @@ *> *> \param[out] WORK *> \verbatim -*> WORK is COMPLEX array, dimension (MAX(1,LWORK)) -*> On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +*> (workspace) COMPLEX array, dimension (MAX(1,LWORK)) +*> On exit, if INFO = 0, WORK(1) contains optimal (or either minimal +*> or optimal, if query was assumed) LWORK. +*> See LWORK for details. *> \endverbatim *> *> \param[in] LWORK *> \verbatim *> LWORK is INTEGER *> The dimension of the array WORK. -*> LWORK >= max( 1, MN + max( MN, NRHS ) ). -*> For optimal performance, -*> LWORK >= max( 1, MN + max( MN, NRHS )*NB ). -*> where MN = min(M,N) and NB is the optimum block size. -*> -*> If LWORK = -1, then a workspace query is assumed; the routine -*> only calculates the optimal size of the WORK array, returns -*> this value as the first entry of the WORK array, and no error -*> message related to LWORK is issued by XERBLA. +*> If LWORK = -1 or -2, then a workspace query is assumed. +*> If LWORK = -1, the routine calculates optimal size of WORK for the +*> optimal performance and returns this value in WORK(1). +*> If LWORK = -2, the routine calculates minimal size of WORK and +*> returns this value in WORK(1). *> \endverbatim *> *> \param[out] INFO @@ -160,20 +152,22 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \date November 2011 +*> \date November 2016 +* +*> \ingroup complexGEsolve * * ===================================================================== - SUBROUTINE CGETSLS( TRANS, M, N, NRHS, A, LDA, B, LDB - $ , WORK, LWORK, INFO ) + SUBROUTINE CGETSLS( TRANS, M, N, NRHS, A, LDA, B, LDB, + $ WORK, LWORK, INFO ) * -* -- LAPACK driver routine (version 3.4.0) -- +* -- LAPACK driver routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- -* November 2011 +* November 2016 * * .. Scalar Arguments .. CHARACTER TRANS - INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, MB + INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS * .. * .. Array Arguments .. COMPLEX A( LDA, * ), B( LDB, * ), WORK( * ) @@ -183,17 +177,18 @@ * ===================================================================== * * .. Parameters .. - REAL ZERO, ONE + REAL ZERO, ONE PARAMETER ( ZERO = 0.0E0, ONE = 1.0E0 ) - COMPLEX CZERO + COMPLEX CZERO PARAMETER ( CZERO = ( 0.0E+0, 0.0E+0 ) ) * .. * .. Local Scalars .. LOGICAL LQUERY, TRAN - INTEGER I, IASCL, IBSCL, J, MINMN, MAXMN, BROW, LW, - $ SCLLEN, MNK, WSIZEO, WSIZEM, LW1, LW2, - $ INFO2, NB + INTEGER I, IASCL, IBSCL, J, MINMN, MAXMN, BROW, + $ SCLLEN, MNK, TSZO, TSZM, LWO, LWM, LW1, LW2, + $ WSIZEO, WSIZEM, INFO2 REAL ANRM, BIGNUM, BNRM, SMLNUM + COMPLEX TQ( 5 ), WORKQ * .. * .. External Functions .. LOGICAL LSAME @@ -206,19 +201,19 @@ $ CTRTRS, XERBLA, CGELQ, CGEMLQ * .. * .. Intrinsic Functions .. - INTRINSIC REAL, MAX, MIN + INTRINSIC REAL, MAX, MIN, INT * .. * .. Executable Statements .. * * Test the input arguments. * - INFO=0 + INFO = 0 MINMN = MIN( M, N ) MAXMN = MAX( M, N ) - MNK = MAX(MINMN,NRHS) + MNK = MAX( MINMN, NRHS ) TRAN = LSAME( TRANS, 'C' ) * - LQUERY = ( LWORK.EQ.-1 ) + LQUERY = ( LWORK.EQ.-1 .OR. LWORK.EQ.-2 ) IF( .NOT.( LSAME( TRANS, 'N' ) .OR. $ LSAME( TRANS, 'C' ) ) ) THEN INFO = -1 @@ -234,60 +229,71 @@ INFO = -8 END IF * - IF( INFO.EQ.0) THEN + IF( INFO.EQ.0 ) THEN * * Determine the block size and minimum LWORK * - IF ( M.GE.N ) THEN - CALL CGEQR( M, N, A, LDA, WORK(1), -1, WORK(6), -1, - $ INFO2) - MB = INT(WORK(4)) - NB = INT(WORK(5)) - LW = INT(WORK(6)) - CALL CGEMQR( 'L', TRANS, M, NRHS, N, A, LDA, WORK(1), - $ INT(WORK(2)), B, LDB, WORK(6), -1 , INFO2 ) - WSIZEO = INT(WORK(2))+MAX(LW,INT(WORK(6))) - WSIZEM = INT(WORK(3))+MAX(LW,INT(WORK(6))) - ELSE - CALL CGELQ( M, N, A, LDA, WORK(1), -1, WORK(6), -1, - $ INFO2) - MB = INT(WORK(4)) - NB = INT(WORK(5)) - LW = INT(WORK(6)) - CALL CGEMLQ( 'L', TRANS, N, NRHS, M, A, LDA, WORK(1), - $ INT(WORK(2)), B, LDB, WORK(6), -1 , INFO2 ) - WSIZEO = INT(WORK(2))+MAX(LW,INT(WORK(6))) - WSIZEM = INT(WORK(3))+MAX(LW,INT(WORK(6))) - END IF + IF( M.GE.N ) THEN + CALL CGEQR( M, N, A, LDA, TQ, -1, WORKQ, -1, INFO2 ) + TSZO = INT( TQ( 1 ) ) + LWO = INT( WORKQ ) + CALL CGEMQR( 'L', TRANS, M, NRHS, N, A, LDA, TQ, + $ TSZO, B, LDB, WORKQ, -1, INFO2 ) + LWO = MAX( LWO, INT( WORKQ ) ) + CALL CGEQR( M, N, A, LDA, TQ, -2, WORKQ, -2, INFO2 ) + TSZM = INT( TQ( 1 ) ) + LWM = INT( WORKQ ) + CALL CGEMQR( 'L', TRANS, M, NRHS, N, A, LDA, TQ, + $ TSZM, B, LDB, WORKQ, -1, INFO2 ) + LWM = MAX( LWM, INT( WORKQ ) ) + WSIZEO = TSZO + LWO + WSIZEM = TSZM + LWM + ELSE + CALL CGELQ( M, N, A, LDA, TQ, -1, WORKQ, -1, INFO2 ) + TSZO = INT( TQ( 1 ) ) + LWO = INT( WORKQ ) + CALL CGEMLQ( 'L', TRANS, N, NRHS, M, A, LDA, TQ, + $ TSZO, B, LDB, WORKQ, -1, INFO2 ) + LWO = MAX( LWO, INT( WORKQ ) ) + CALL CGELQ( M, N, A, LDA, TQ, -2, WORKQ, -2, INFO2 ) + TSZM = INT( TQ( 1 ) ) + LWM = INT( WORKQ ) + CALL CGEMLQ( 'L', TRANS, N, NRHS, M, A, LDA, TQ, + $ TSZO, B, LDB, WORKQ, -1, INFO2 ) + LWM = MAX( LWM, INT( WORKQ ) ) + WSIZEO = TSZO + LWO + WSIZEM = TSZM + LWM + END IF * - IF((LWORK.LT.WSIZEO).AND.(.NOT.LQUERY)) THEN - INFO=-10 + IF( ( LWORK.LT.WSIZEM ).AND.( .NOT.LQUERY ) ) THEN + INFO = -10 END IF +* END IF * IF( INFO.NE.0 ) THEN - CALL XERBLA( 'DGETSLS', -INFO ) + CALL XERBLA( 'CGETSLS', -INFO ) WORK( 1 ) = REAL( WSIZEO ) - WORK( 2 ) = REAL( WSIZEM ) RETURN - ELSE IF (LQUERY) THEN - WORK( 1 ) = REAL( WSIZEO ) - WORK( 2 ) = REAL( WSIZEM ) + END IF + IF( LQUERY ) THEN + IF( LWORK.EQ.-1 ) WORK( 1 ) = REAL( WSIZEO ) + IF( LWORK.EQ.-2 ) WORK( 1 ) = REAL( WSIZEM ) RETURN END IF - IF(LWORK.LT.WSIZEO) THEN - LW1=INT(WORK(3)) - LW2=MAX(LW,INT(WORK(6))) + IF( LWORK.LT.WSIZEO ) THEN + LW1 = TSZM + LW2 = LWM ELSE - LW1=INT(WORK(2)) - LW2=MAX(LW,INT(WORK(6))) + LW1 = TSZO + LW2 = LWO END IF * * Quick return if possible * IF( MIN( M, N, NRHS ).EQ.0 ) THEN CALL CLASET( 'FULL', MAX( M, N ), NRHS, CZERO, CZERO, - $ B, LDB ) + $ B, LDB ) RETURN END IF * @@ -343,26 +349,27 @@ IBSCL = 2 END IF * - IF ( M.GE.N) THEN + IF ( M.GE.N ) THEN * * compute QR factorization of A * - CALL CGEQR( M, N, A, LDA, WORK(LW2+1), LW1 - $ , WORK(1), LW2, INFO ) - IF (.NOT.TRAN) THEN + CALL CGEQR( M, N, A, LDA, WORK( LW2+1 ), LW1, + $ WORK( 1 ), LW2, INFO ) + IF ( .NOT.TRAN ) THEN * * Least-Squares Problem min || A * X - B || * * B(1:M,1:NRHS) := Q**T * B(1:M,1:NRHS) * CALL CGEMQR( 'L' , 'C', M, NRHS, N, A, LDA, - $ WORK(LW2+1), LW1, B, LDB, WORK(1), LW2, INFO ) + $ WORK( LW2+1 ), LW1, B, LDB, WORK( 1 ), LW2, + $ INFO ) * * B(1:N,1:NRHS) := inv(R) * B(1:N,1:NRHS) * CALL CTRTRS( 'U', 'N', 'N', N, NRHS, - $ A, LDA, B, LDB, INFO ) - IF(INFO.GT.0) THEN + $ A, LDA, B, LDB, INFO ) + IF( INFO.GT.0 ) THEN RETURN END IF SCLLEN = N @@ -390,7 +397,7 @@ * B(1:M,1:NRHS) := Q(1:N,:) * B(1:N,1:NRHS) * CALL CGEMQR( 'L', 'N', M, NRHS, N, A, LDA, - $ WORK( LW2+1), LW1, B, LDB, WORK( 1 ), LW2, + $ WORK( LW2+1 ), LW1, B, LDB, WORK( 1 ), LW2, $ INFO ) * SCLLEN = M @@ -401,8 +408,8 @@ * * Compute LQ factorization of A * - CALL CGELQ( M, N, A, LDA, WORK(LW2+1), LW1 - $ , WORK(1), LW2, INFO ) + CALL CGELQ( M, N, A, LDA, WORK( LW2+1 ), LW1, + $ WORK( 1 ), LW2, INFO ) * * workspace at least M, optimally M*NB. * @@ -430,7 +437,7 @@ * B(1:N,1:NRHS) := Q(1:N,:)**T * B(1:M,1:NRHS) * CALL CGEMLQ( 'L', 'C', N, NRHS, M, A, LDA, - $ WORK( LW2+1), LW1, B, LDB, WORK( 1 ), LW2, + $ WORK( LW2+1 ), LW1, B, LDB, WORK( 1 ), LW2, $ INFO ) * * workspace at least NRHS, optimally NRHS*NB @@ -444,7 +451,7 @@ * B(1:N,1:NRHS) := Q * B(1:N,1:NRHS) * CALL CGEMLQ( 'L', 'N', N, NRHS, M, A, LDA, - $ WORK( LW2+1), LW1, B, LDB, WORK( 1 ), LW2, + $ WORK( LW2+1 ), LW1, B, LDB, WORK( 1 ), LW2, $ INFO ) * * workspace at least NRHS, optimally NRHS*NB @@ -468,24 +475,23 @@ * IF( IASCL.EQ.1 ) THEN CALL CLASCL( 'G', 0, 0, ANRM, SMLNUM, SCLLEN, NRHS, B, LDB, - $ INFO ) + $ INFO ) ELSE IF( IASCL.EQ.2 ) THEN CALL CLASCL( 'G', 0, 0, ANRM, BIGNUM, SCLLEN, NRHS, B, LDB, - $ INFO ) + $ INFO ) END IF IF( IBSCL.EQ.1 ) THEN - CALL CLASCL( 'G', 0, 0, SMLNUM, BNRM, SCLLEN, NRHS, B, LDB, - $ INFO ) + CALL CLASCL( 'G', 0, 0, SMLNUM, BNRM, SCLLEN, NRHS, B, LDB, + $ INFO ) ELSE IF( IBSCL.EQ.2 ) THEN - CALL CLASCL( 'G', 0, 0, BIGNUM, BNRM, SCLLEN, NRHS, B, LDB, - $ INFO ) + CALL CLASCL( 'G', 0, 0, BIGNUM, BNRM, SCLLEN, NRHS, B, LDB, + $ INFO ) END IF * 50 CONTINUE - WORK( 1 ) = REAL( WSIZEO ) - WORK( 2 ) = REAL( WSIZEM ) + WORK( 1 ) = REAL( TSZO + LWO ) RETURN * -* End of CGETSLS +* End of ZGETSLS * END diff --git a/SRC/clamswlq.f b/SRC/clamswlq.f index 9e3338e2..f89d417b 100644 --- a/SRC/clamswlq.f +++ b/SRC/clamswlq.f @@ -33,14 +33,19 @@ * ========== * *> \param[in] SIDE +*> \verbatim *> SIDE is CHARACTER*1 *> = 'L': apply Q or Q**T from the Left; *> = 'R': apply Q or Q**T from the Right. +*> \endverbatim *> *> \param[in] TRANS +*> \verbatim *> TRANS is CHARACTER*1 *> = 'N': No transpose, apply Q; *> = 'T': Transpose, apply Q**T. +*> \endverbatim +*> *> \param[in] M *> \verbatim *> M is INTEGER @@ -115,18 +120,23 @@ *> \endverbatim *> *> \param[in,out] C +*> \verbatim *> C is COMPLEX array, dimension (LDC,N) *> On entry, the M-by-N matrix C. *> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +*> \endverbatim +*> *> \param[in] LDC +*> \verbatim *> LDC is INTEGER *> The leading dimension of the array C. LDC >= max(1,M). +*> \endverbatim *> *> \param[out] WORK *> \verbatim *> (workspace) COMPLEX array, dimension (MAX(1,LWORK)) -*> *> \endverbatim +*> *> \param[in] LWORK *> \verbatim *> LWORK is INTEGER @@ -137,8 +147,8 @@ *> only calculates the optimal size of the WORK array, returns *> this value as the first entry of the WORK array, and no error *> message related to LWORK is issued by XERBLA. -*> *> \endverbatim +*> *> \param[out] INFO *> \verbatim *> INFO is INTEGER diff --git a/SRC/clamtsqr.f b/SRC/clamtsqr.f index 387e1fe1..aa2740f0 100644 --- a/SRC/clamtsqr.f +++ b/SRC/clamtsqr.f @@ -33,14 +33,19 @@ * ========== * *> \param[in] SIDE +*> \verbatim *> SIDE is CHARACTER*1 *> = 'L': apply Q or Q**T from the Left; *> = 'R': apply Q or Q**T from the Right. +*> \endverbatim *> *> \param[in] TRANS +*> \verbatim *> TRANS is CHARACTER*1 *> = 'N': No transpose, apply Q; *> = 'C': Conjugate Transpose, apply Q**C. +*> \endverbatim +*> *> \param[in] M *> \verbatim *> M is INTEGER @@ -109,12 +114,17 @@ *> \endverbatim *> *> \param[in,out] C +*> \verbatim *> C is COMPLEX array, dimension (LDC,N) *> On entry, the M-by-N matrix C. *> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +*> \endverbatim +*> *> \param[in] LDC +*> \verbatim *> LDC is INTEGER *> The leading dimension of the array C. LDC >= max(1,M). +*> \endverbatim *> *> \param[out] WORK *> \verbatim @@ -247,14 +257,13 @@ ELSE IF(( LWORK.LT.MAX(1,LW)).AND.(.NOT.LQUERY)) THEN INFO = -15 END IF - IF( INFO.EQ.0) THEN * * Determine the block size if it is tall skinny or short and wide * IF( INFO.EQ.0) THEN WORK(1) = LW END IF - END IF +* IF( INFO.NE.0 ) THEN CALL XERBLA( 'CLAMTSQR', -INFO ) RETURN @@ -354,10 +363,10 @@ * * Multiply Q to the current block of C (1:M,I:I+MB) * - CTR = CTR - 1 - CALL CTPMQRT('R','C',M , MB-K, K, 0,NB, A(I,1), LDA, - $ T(1,CTR*K+1), LDT, C(1,1), LDC, - $ C(1,I), LDC, WORK, INFO ) + CTR = CTR - 1 + CALL CTPMQRT('R','C',M , MB-K, K, 0,NB, A(I,1), LDA, + $ T(1,CTR*K+1), LDT, C(1,1), LDC, + $ C(1,I), LDC, WORK, INFO ) END DO * * Multiply Q to the first block of C (1:M,1:MB) @@ -397,11 +406,7 @@ * END IF * - IF(LEFT) THEN - WORK(1)= N * NB - ELSE IF(RIGHT) THEN - WORK(1)= MB * NB - END IF + WORK(1) = LW RETURN * * End of CLAMTSQR diff --git a/SRC/dgelq.f b/SRC/dgelq.f index d73f7454..a9af9006 100644 --- a/SRC/dgelq.f +++ b/SRC/dgelq.f @@ -2,14 +2,14 @@ * Definition: * =========== * -* SUBROUTINE DGELQ( M, N, A, LDA, WORK1, LWORK1, WORK2, LWORK2, -* INFO) +* SUBROUTINE DGELQ( M, N, A, LDA, T, TSIZE, WORK, LWORK, +* INFO ) * * .. Scalar Arguments .. -* INTEGER INFO, LDA, M, N, LWORK1, LWORK2 +* INTEGER INFO, LDA, M, N, TSIZE, LWORK * .. * .. Array Arguments .. -* DOUBLE PRECISION A( LDA, * ), WORK1( * ), WORK2( * ) +* DOUBLE PRECISION A( LDA, * ), T( * ), WORK( * ) * .. * * @@ -17,11 +17,7 @@ * ============= *> *> \verbatim -*> -*> DGELQ computes an LQ factorization of an M-by-N matrix A, -*> using DLASWLQ when A is short and wide -*> (N sufficiently greater than M), and otherwise DGELQT: -*> A = L * Q . +*> DGELQ computes a LQ factorization of an M-by-N matrix A. *> \endverbatim * * Arguments: @@ -46,8 +42,8 @@ *> On exit, the elements on and below the diagonal of the array *> contain the M-by-min(M,N) lower trapezoidal matrix L *> (L is lower triangular if M <= N); -*> the elements above the diagonal are the rows of -*> blocked V representing Q (see Further Details). +*> the elements above the diagonal are used to store part of the +*> data structure to represent Q. *> \endverbatim *> *> \param[in] LDA @@ -56,47 +52,50 @@ *> The leading dimension of the array A. LDA >= max(1,M). *> \endverbatim *> -*> \param[out] WORK1 +*> \param[out] T *> \verbatim -*> WORK1 is DOUBLE PRECISION array, dimension (MAX(1,LWORK1)) -*> WORK1 contains part of the data structure used to store Q. -*> WORK1(1): algorithm type = 1, to indicate output from -*> DLASWLQ or DGELQT -*> WORK1(2): optimum size of WORK1 -*> WORK1(3): minimum size of WORK1 -*> WORK1(4): horizontal block size -*> WORK1(5): vertical block size -*> WORK1(6:LWORK1): data structure needed for Q, computed by -*> DLASWLQ or DGELQT +*> T is DOUBLE PRECISION array, dimension (MAX(5,TSIZE)) +*> On exit, if INFO = 0, T(1) returns optimal (or either minimal +*> or optimal, if query is assumed) TSIZE. See TSIZE for details. +*> Remaining T contains part of the data structure used to represent Q. +*> If one wants to apply or construct Q, then one needs to keep T +*> (in addition to A) and pass it to further subroutines. *> \endverbatim *> -*> \param[in] LWORK1 +*> \param[in] TSIZE *> \verbatim -*> LWORK1 is INTEGER -*> The dimension of the array WORK1. -*> If LWORK1 = -1, then a query is assumed. In this case the -*> routine calculates the optimal size of WORK1 and -*> returns this value in WORK1(2), and calculates the minimum -*> size of WORK1 and returns this value in WORK1(3). -*> No error message related to LWORK1 is issued by XERBLA when -*> LWORK1 = -1. +*> TSIZE is INTEGER +*> If TSIZE >= 5, the dimension of the array T. +*> If TSIZE = -1 or -2, then a workspace query is assumed. The routine +*> only calculates the sizes of the T and WORK arrays, returns these +*> values as the first entries of the T and WORK arrays, and no error +*> message related to T or WORK is issued by XERBLA. +*> If TSIZE = -1, the routine calculates optimal size of T for the +*> optimum performance and returns this value in T(1). +*> If TSIZE = -2, the routine calculates minimal size of T and +*> returns this value in T(1). *> \endverbatim *> -*> \param[out] WORK2 +*> \param[out] WORK *> \verbatim -*> (workspace) DOUBLE PRECISION array, dimension (MAX(1,LWORK2)) -*> +*> (workspace) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +*> On exit, if INFO = 0, WORK(1) contains optimal (or either minimal +*> or optimal, if query was assumed) LWORK. +*> See LWORK for details. *> \endverbatim -*> \param[in] LWORK2 +*> +*> \param[in] LWORK *> \verbatim -*> LWORK2 is INTEGER -*> The dimension of the array WORK2. -*> If LWORK2 = -1, then a query is assumed. In this case the -*> routine calculates the optimal size of WORK2 and -*> returns this value in WORK2(1), and calculates the minimum -*> size of WORK2 and returns this value in WORK2(2). -*> No error message related to LWORK2 is issued by XERBLA when -*> LWORK2 = -1. +*> LWORK is INTEGER +*> The dimension of the array WORK. +*> If LWORK = -1 or -2, then a workspace query is assumed. The routine +*> only calculates the sizes of the T and WORK arrays, returns these +*> values as the first entries of the T and WORK arrays, and no error +*> message related to T or WORK is issued by XERBLA. +*> If LWORK = -1, the routine calculates optimal size of WORK for the +*> optimal performance and returns this value in WORK(1). +*> If LWORK = -2, the routine calculates minimal size of WORK and +*> returns this value in WORK(1). *> \endverbatim *> *> \param[out] INFO @@ -114,105 +113,135 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \par Further Details: -* ===================== +*> \par Further Details +* ==================== *> *> \verbatim -*> Depending on the matrix dimensions M and N, and row and column -*> block sizes MB and NB returned by ILAENV, GELQ will use either -*> LASWLQ(if the matrix is short-and-wide) or GELQT to compute -*> the LQ decomposition. -*> The output of LASWLQ or GELQT representing Q is stored in A and in -*> array WORK1(6:LWORK1) for later use. -*> WORK1(2:5) contains the matrix dimensions M,N and block sizes MB, NB -*> which are needed to interpret A and WORK1(6:LWORK1) for later use. -*> WORK1(1)=1 indicates that the code needed to take WORK1(2:5) and -*> decide whether LASWLQ or GELQT was used is the same as used below in -*> GELQ. For a detailed description of A and WORK1(6:LWORK1), see -*> Further Details in LASWLQ or GELQT. +*> +*> The goal of the interface is to give maximum freedom to the developers for +*> creating any LQ factorization algorithm they wish. The triangular +*> (trapezoidal) L has to be stored in the lower part of A. The lower part of A +*> and the array T can be used to store any relevant information for applying or +*> constructing the Q factor. The WORK array can safely be discarded after exit. +*> +*> Caution: One should not expect the sizes of T and WORK to be the same from one +*> LAPACK implementation to the other, or even from one execution to the other. +*> A workspace query (for T and WORK) is needed at each execution. However, +*> for a given execution, the size of T and WORK are fixed and will not change +*> from one query to the next. +*> *> \endverbatim *> +*> \par Further Details particular to this LAPACK implementation: +* ============================================================== +*> +*> \verbatim +*> +*> These details are particular for this LAPACK implementation. Users should not +*> take them for granted. These details may change in the future, and are unlikely not +*> true for another LAPACK implementation. These details are relevant if one wants +*> to try to understand the code. They are not part of the interface. +*> +*> In this version, +*> +*> T(2): row block size (MB) +*> T(3): column block size (NB) +*> T(6:TSIZE): data structure needed for Q, computed by +*> DLASWLQ or DGELQT +*> +*> Depending on the matrix dimensions M and N, and row and column +*> block sizes MB and NB returned by ILAENV, DGELQ will use either +*> DLASWLQ (if the matrix is short-and-wide) or DGELQT to compute +*> the LQ factorization. +*> \endverbatim *> * ===================================================================== - SUBROUTINE DGELQ( M, N, A, LDA, WORK1, LWORK1, WORK2, LWORK2, - $ INFO) + SUBROUTINE DGELQ( M, N, A, LDA, T, TSIZE, WORK, LWORK, + $ INFO ) * -* -- LAPACK computational routine (version 3.5.0) -- +* -- LAPACK computational routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd. -- -* November 2013 +* November 2016 * * .. Scalar Arguments .. - INTEGER INFO, LDA, M, N, LWORK1, LWORK2 + INTEGER INFO, LDA, M, N, TSIZE, LWORK * .. * .. Array Arguments .. - DOUBLE PRECISION A( LDA, * ), WORK1( * ), WORK2( * ) + DOUBLE PRECISION A( LDA, * ), T( * ), WORK( * ) * .. * * ===================================================================== * * .. * .. Local Scalars .. - LOGICAL LQUERY, LMINWS - INTEGER MB, NB, I, II, KK, MINLW1, NBLCKS + LOGICAL LQUERY, LMINWS, MINT, MINW + INTEGER MB, NB, MINTSZ, NBLCKS * .. -* .. EXTERNAL FUNCTIONS .. +* .. External Functions .. LOGICAL LSAME EXTERNAL LSAME -* .. EXTERNAL SUBROUTINES .. +* .. +* .. External Subroutines .. EXTERNAL DGELQT, DLASWLQ, XERBLA -* .. INTRINSIC FUNCTIONS .. +* .. +* .. Intrinsic Functions .. INTRINSIC MAX, MIN, MOD * .. -* .. EXTERNAL FUNCTIONS .. +* .. External Functions .. INTEGER ILAENV EXTERNAL ILAENV * .. -* .. EXECUTABLE STATEMENTS .. +* .. Executable Statements .. * -* TEST THE INPUT ARGUMENTS +* Test the input arguments * INFO = 0 * - LQUERY = ( LWORK1.EQ.-1 .OR. LWORK2.EQ.-1 ) + LQUERY = ( TSIZE.EQ.-1 .OR. TSIZE.EQ.-2 .OR. + $ LWORK.EQ.-1 .OR. LWORK.EQ.-2 ) +* + MINT = .FALSE. + MINW = .FALSE. + IF( TSIZE.EQ.-2 .OR. LWORK.EQ.-2 ) THEN + IF( TSIZE.NE.-1 ) MINT = .TRUE. + IF( LWORK.NE.-1 ) MINW = .TRUE. + END IF * * Determine the block size * - IF ( MIN(M,N).GT.0 ) THEN - MB = ILAENV( 1, 'DGELQ ', ' ', M, N, 1, -1) - NB = ILAENV( 1, 'DGELQ ', ' ', M, N, 2, -1) + IF( MIN( M, N ).GT.0 ) THEN + MB = ILAENV( 1, 'DGELQ ', ' ', M, N, 1, -1 ) + NB = ILAENV( 1, 'DGELQ ', ' ', M, N, 2, -1 ) ELSE MB = 1 NB = N END IF - IF( MB.GT.MIN(M,N).OR.MB.LT.1) MB = 1 - IF( NB.GT.N.OR.NB.LE.M) NB = N - MINLW1 = M + 5 - IF ((NB.GT.M).AND.(N.GT.M)) THEN - IF(MOD(N-M, NB-M).EQ.0) THEN - NBLCKS = (N-M)/(NB-M) + IF( MB.GT.MIN( M, N ) .OR. MB.LT.1 ) MB = 1 + IF( NB.GT.N .OR. NB.LE.M ) NB = N + MINTSZ = M + 5 + IF ( NB.GT.M .AND. N.GT.M ) THEN + IF( MOD( N - M, NB - M ).EQ.0 ) THEN + NBLCKS = ( N - M ) / ( NB - M ) ELSE - NBLCKS = (N-M)/(NB-M) + 1 + NBLCKS = ( N - M ) / ( NB - M ) + 1 END IF ELSE NBLCKS = 1 END IF * -* Determine if the workspace size satisfies minimum size +* Determine if the workspace size satisfies minimal size * LMINWS = .FALSE. - IF((LWORK1.LT.MAX(1,MB*M*NBLCKS+5) - $ .OR.(LWORK2.LT.MB*M)).AND.(LWORK2.GE.M).AND.(LWORK1.GE.M+5) - $ .AND.(.NOT.LQUERY)) THEN - IF (LWORK1.LT.MAX(1,MB*M*NBLCKS+5)) THEN + IF( ( TSIZE.LT.MAX( 1, MB*M*NBLCKS + 5 ) .OR. LWORK.LT.MB*M ) + $ .AND. ( LWORK.GE.M ) .AND. ( TSIZE.GE.MINTSZ ) + $ .AND. ( .NOT.LQUERY ) ) THEN + IF( TSIZE.LT.MAX( 1, MB*M*NBLCKS + 5 ) ) THEN LMINWS = .TRUE. MB = 1 - END IF - IF (LWORK1.LT.MAX(1,M*NBLCKS+5)) THEN - LMINWS = .TRUE. NB = N END IF - IF (LWORK2.LT.MB*M) THEN + IF( LWORK.LT.MB*M ) THEN LMINWS = .TRUE. MB = 1 END IF @@ -224,44 +253,52 @@ INFO = -2 ELSE IF( LDA.LT.MAX( 1, M ) ) THEN INFO = -4 - ELSE IF( LWORK1.LT.MAX( 1, MB*M*NBLCKS+5 ) - $ .AND.(.NOT.LQUERY).AND. (.NOT.LMINWS)) THEN + ELSE IF( TSIZE.LT.MAX( 1, MB*M*NBLCKS + 5 ) + $ .AND. ( .NOT.LQUERY ) .AND. ( .NOT.LMINWS ) ) THEN INFO = -6 - ELSE IF( (LWORK2.LT.MAX(1,M*MB)).AND.(.NOT.LQUERY) - $ .AND.(.NOT.LMINWS) ) THEN + ELSE IF( ( LWORK.LT.MAX( 1, M*MB ) ) .AND .( .NOT.LQUERY ) + $ .AND. ( .NOT.LMINWS ) ) THEN INFO = -8 END IF * - IF( INFO.EQ.0) THEN - WORK1(1) = 1 - WORK1(2) = MB*M*NBLCKS+5 - WORK1(3) = MINLW1 - WORK1(4) = MB - WORK1(5) = NB - WORK2(1) = MB * M - WORK2(2) = M + IF( INFO.EQ.0 ) THEN + IF( MINT ) THEN + T( 1 ) = MINTSZ + ELSE + T( 1 ) = MB*M*NBLCKS + 5 + END IF + T( 2 ) = MB + T( 3 ) = NB + IF( MINW ) THEN + WORK( 1 ) = MAX( 1, N ) + ELSE + WORK( 1 ) = MAX( 1, MB*M ) + END IF END IF IF( INFO.NE.0 ) THEN CALL XERBLA( 'DGELQ', -INFO ) RETURN - ELSE IF (LQUERY) THEN - RETURN + ELSE IF( LQUERY ) THEN + RETURN END IF * * Quick return if possible * - IF( MIN(M,N).EQ.0 ) THEN - RETURN + IF( MIN( M, N ).EQ.0 ) THEN + RETURN END IF * * The LQ Decomposition * - IF((N.LE.M).OR.(NB.LE.M).OR.(NB.GE.N)) THEN - CALL DGELQT( M, N, MB, A, LDA, WORK1(6), MB, WORK2, INFO) + IF( ( N.LE.M ) .OR. ( NB.LE.M ) .OR. ( NB.GE.N ) ) THEN + CALL DGELQT( M, N, MB, A, LDA, T( 6 ), MB, WORK, INFO ) ELSE - CALL DLASWLQ( M, N, MB, NB, A, LDA, WORK1(6), MB, WORK2, - $ LWORK2, INFO) + CALL DLASWLQ( M, N, MB, NB, A, LDA, T( 6 ), MB, WORK, + $ LWORK, INFO ) END IF +* + WORK( 1 ) = MAX( 1, MB*M ) +* RETURN * * End of DGELQ diff --git a/SRC/dgemlq.f b/SRC/dgemlq.f index 7bdf97a1..203ca7ec 100644 --- a/SRC/dgemlq.f +++ b/SRC/dgemlq.f @@ -2,17 +2,18 @@ * Definition: * =========== * -* SUBROUTINE DGEMLQ( SIDE, TRANS, M, N, K, A, LDA, WORK1, -* $ LWORK1, C, LDC, WORK2, LWORK2, INFO ) +* SUBROUTINE DGEMLQ( SIDE, TRANS, M, N, K, A, LDA, T, +* $ TSIZE, C, LDC, WORK, LWORK, INFO ) * * * .. Scalar Arguments .. -* CHARACTER SIDE, TRANS -* INTEGER INFO, LDA, M, N, K, MB, NB, LWORK1, LWORK2, LDC +* CHARACTER SIDE, TRANS +* INTEGER INFO, LDA, M, N, K, LDT, TSIZE, LWORK, LDC * .. * .. Array Arguments .. -* DOUBLE A( LDA, * ), WORK1( * ), C(LDC, * ), -* $ WORK2( * ) +* DOUBLE PRECISION A( LDA, * ), T( * ), C(LDC, * ), WORK( * ) +* .. +* *> \par Purpose: * ============= *> @@ -20,27 +21,32 @@ *> *> DGEMLQ overwrites the general real M-by-N matrix C with *> -*> *> SIDE = 'L' SIDE = 'R' *> TRANS = 'N': Q * C C * Q *> TRANS = 'T': Q**T * C C * Q**T *> where Q is a real orthogonal matrix defined as the product *> of blocked elementary reflectors computed by short wide LQ *> factorization (DGELQ) +*> *> \endverbatim * * Arguments: * ========== * *> \param[in] SIDE +*> \verbatim *> SIDE is CHARACTER*1 *> = 'L': apply Q or Q**T from the Left; *> = 'R': apply Q or Q**T from the Right. +*> \endverbatim *> *> \param[in] TRANS +*> \verbatim *> TRANS is CHARACTER*1 *> = 'N': No transpose, apply Q; *> = 'T': Transpose, apply Q**T. +*> \endverbatim +*> *> \param[in] M *> \verbatim *> M is INTEGER @@ -50,7 +56,7 @@ *> \param[in] N *> \verbatim *> N is INTEGER -*> The number of columns of the matrix C. N >= M. +*> The number of columns of the matrix C. N >= 0. *> \endverbatim *> *> \param[in] K @@ -58,61 +64,65 @@ *> K is INTEGER *> The number of elementary reflectors whose product defines *> the matrix Q. -*> M >= K >= 0; +*> If SIDE = 'L', M >= K >= 0; +*> if SIDE = 'R', N >= K >= 0. *> *> \endverbatim *> -*> \param[in,out] A +*> \param[in] A *> \verbatim -*> A is DOUBLE PRECISION array, dimension (LDA,K) -*> The i-th row must contain the vector which defines the blocked -*> elementary reflector H(i), for i = 1,2,...,k, as returned by -*> DLASWLQ in the first k rows of its array argument A. +*> A is DOUBLE PRECISION array, dimension +*> (LDA,M) if SIDE = 'L', +*> (LDA,N) if SIDE = 'R' +*> Part of the data structure to represent Q as returned by DGELQ. *> \endverbatim *> *> \param[in] LDA *> \verbatim *> LDA is INTEGER -*> The leading dimension of the array A. -*> If SIDE = 'L', LDA >= max(1,M); -*> if SIDE = 'R', LDA >= max(1,N). +*> The leading dimension of the array A. LDA >= max(1,K). *> \endverbatim *> -*> \param[in] WORK1 +*> \param[in] T *> \verbatim -*> WORK1 is DOUBLE PRECISION array, dimension (MAX(1,LWORK1)) is -*> returned by GEQR. +*> T is DOUBLE PRECISION array, dimension (MAX(5,TSIZE)). +*> Part of the data structure to represent Q as returned by DGELQ. *> \endverbatim *> -*> \param[in] LWORK1 +*> \param[in] TSIZE *> \verbatim -*> LWORK1 is INTEGER -*> The dimension of the array WORK1. +*> TSIZE is INTEGER +*> The dimension of the array T. TSIZE >= 5. *> \endverbatim *> *> \param[in,out] C +*> \verbatim *> C is DOUBLE PRECISION array, dimension (LDC,N) *> On entry, the M-by-N matrix C. *> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +*> \endverbatim +*> *> \param[in] LDC +*> \verbatim *> LDC is INTEGER *> The leading dimension of the array C. LDC >= max(1,M). +*> \endverbatim *> -*> \param[out] WORK2 +*> \param[out] WORK *> \verbatim -*> (workspace) DOUBLE PRECISION array, dimension (MAX(1,LWORK2)) -*> +*> (workspace) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) *> \endverbatim -*> \param[in] LWORK2 -*> \verbatim -*> LWORK2 is INTEGER -*> The dimension of the array WORK2. -*> If LWORK2 = -1, then a workspace query is assumed; the routine -*> only calculates the optimal size of the WORK2 array, returns -*> this value as the third entry of the WORK2 array (WORK2(1)), -*> and no error message related to LWORK2 is issued by XERBLA. *> +*> \param[in] LWORK +*> \verbatim +*> LWORK is INTEGER +*> The dimension of the array WORK. +*> If LWORK = -1, then a workspace query is assumed. The routine +*> only calculates the size of the WORK array, returns this +*> value as WORK(1), and no error message related to WORK +*> is issued by XERBLA. *> \endverbatim +*> *> \param[out] INFO *> \verbatim *> INFO is INTEGER @@ -128,53 +138,63 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \par Further Details: -* ===================== +*> \par Further Details +* ==================== *> *> \verbatim +*> +*> These details are particular for this LAPACK implementation. Users should not +*> take them for granted. These details may change in the future, and are unlikely not +*> true for another LAPACK implementation. These details are relevant if one wants +*> to try to understand the code. They are not part of the interface. +*> +*> In this version, +*> +*> T(2): row block size (MB) +*> T(3): column block size (NB) +*> T(6:TSIZE): data structure needed for Q, computed by +*> DLASWLQ or DGELQT +*> *> Depending on the matrix dimensions M and N, and row and column -*> block sizes MB and NB returned by ILAENV, GELQ will use either -*> LASWLQ(if the matrix is short-and-wide) or GELQT to compute -*> the LQ decomposition. -*> The output of LASWLQ or GELQT representing Q is stored in A and in -*> array WORK1(6:LWORK1) for later use. -*> WORK1(2:5) contains the matrix dimensions M,N and block sizes MB, NB -*> which are needed to interpret A and WORK1(6:LWORK1) for later use. -*> WORK1(1)=1 indicates that the code needed to take WORK1(2:5) and -*> decide whether LASWLQ or GELQT was used is the same as used below in -*> GELQ. For a detailed description of A and WORK1(6:LWORK1), see -*> Further Details in LASWLQ or GELQT. +*> block sizes MB and NB returned by ILAENV, DGELQ will use either +*> DLASWLQ (if the matrix is wide-and-short) or DGELQT to compute +*> the LQ factorization. +*> This version of DGEMLQ will use either DLAMSWLQ or DGEMLQT to +*> multiply matrix Q by another matrix. +*> Further Details in DLAMSWLQ or DGEMLQT. *> \endverbatim *> * ===================================================================== - SUBROUTINE DGEMLQ( SIDE, TRANS, M, N, K, A, LDA, WORK1, LWORK1, - $ C, LDC, WORK2, LWORK2, INFO ) + SUBROUTINE DGEMLQ( SIDE, TRANS, M, N, K, A, LDA, T, TSIZE, + $ C, LDC, WORK, LWORK, INFO ) * -* -- LAPACK computational routine (version 3.5.0) -- +* -- LAPACK computational routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- -* November 2013 +* November 2016 * * .. Scalar Arguments .. - CHARACTER SIDE, TRANS - INTEGER INFO, LDA, M, N, K, LWORK1, LWORK2, LDC + CHARACTER SIDE, TRANS + INTEGER INFO, LDA, M, N, K, TSIZE, LWORK, LDC * .. * .. Array Arguments .. - DOUBLE PRECISION A( LDA, * ), C( LDC, * ), WORK1( * ), WORK2( * ) + DOUBLE PRECISION A( LDA, * ), T( * ), C( LDC, * ), WORK( * ) * .. * * ===================================================================== * * .. * .. Local Scalars .. - LOGICAL LEFT, RIGHT, TRAN, NOTRAN, LQUERY - INTEGER I, II, KK, MB, NB, LW, NBLCKS, MN + LOGICAL LEFT, RIGHT, TRAN, NOTRAN, LQUERY + INTEGER MB, NB, LW, NBLCKS, MN * .. * .. External Functions .. LOGICAL LSAME EXTERNAL LSAME +* .. * .. External Subroutines .. - EXTERNAL DTPMLQT, DGEMLQT, XERBLA + EXTERNAL DLAMSWLQ, DGEMLQT, XERBLA +* .. * .. Intrinsic Functions .. INTRINSIC INT, MAX, MIN, MOD * .. @@ -182,26 +202,27 @@ * * Test the input arguments * - LQUERY = (LWORK2.LT.0) + LQUERY = LWORK.EQ.-1 NOTRAN = LSAME( TRANS, 'N' ) TRAN = LSAME( TRANS, 'T' ) LEFT = LSAME( SIDE, 'L' ) RIGHT = LSAME( SIDE, 'R' ) * - MB = INT(WORK1(4)) - NB = INT(WORK1(5)) - IF (LEFT) THEN + MB = INT( T( 2 ) ) + NB = INT( T( 3 ) ) + IF( LEFT ) THEN LW = N * MB MN = M ELSE LW = M * MB MN = N END IF - IF ((NB.GT.K).AND.(MN.GT.K)) THEN - IF(MOD(MN-K, NB-K).EQ.0) THEN - NBLCKS = (MN-K)/(NB-K) +* + IF( ( NB.GT.K ) .AND. ( MN.GT.K ) ) THEN + IF( MOD( MN - K, NB - K ) .EQ. 0 ) THEN + NBLCKS = ( MN - K ) / ( NB - K ) ELSE - NBLCKS = (MN-K)/(NB-K) + 1 + NBLCKS = ( MN - K ) / ( NB - K ) + 1 END IF ELSE NBLCKS = 1 @@ -209,51 +230,52 @@ * INFO = 0 IF( .NOT.LEFT .AND. .NOT.RIGHT ) THEN - INFO = -1 + INFO = -1 ELSE IF( .NOT.TRAN .AND. .NOT.NOTRAN ) THEN - INFO = -2 + INFO = -2 ELSE IF( M.LT.0 ) THEN INFO = -3 - ELSE IF( N.LT.0) THEN + ELSE IF( N.LT.0 ) THEN INFO = -4 - ELSE IF( K.LT.0 ) THEN + ELSE IF( K.LT.0 .OR. K.GT.MN ) THEN INFO = -5 ELSE IF( LDA.LT.MAX( 1, K ) ) THEN INFO = -7 - ELSE IF( LWORK1.LT.MAX( 1, MB*K*NBLCKS+5 )) THEN + ELSE IF( TSIZE.LT.5 ) THEN INFO = -9 ELSE IF( LDC.LT.MAX( 1, M ) ) THEN - INFO = -11 - ELSE IF(( LWORK2.LT.MAX(1,LW)).AND.(.NOT.LQUERY)) THEN + INFO = -11 + ELSE IF( ( LWORK.LT.MAX( 1, LW ) ) .AND. ( .NOT.LQUERY ) ) THEN INFO = -13 END IF * - IF( INFO.EQ.0) THEN - WORK2(1) = LW + IF( INFO.EQ.0 ) THEN + WORK( 1 ) = LW END IF +* IF( INFO.NE.0 ) THEN CALL XERBLA( 'DGEMLQ', -INFO ) RETURN - ELSE IF (LQUERY) THEN + ELSE IF( LQUERY ) THEN RETURN END IF * * Quick return if possible * - IF( MIN(M,N,K).EQ.0 ) THEN + IF( MIN( M, N, K ).EQ.0 ) THEN RETURN END IF * - IF((LEFT.AND.M.LE.K).OR.(RIGHT.AND.N.LE.K).OR.(NB.LE.K).OR. - $ (NB.GE.MAX(M,N,K))) THEN + IF( ( LEFT .AND. M.LE.K ) .OR. ( RIGHT .AND. N.LE.K ) + $ .OR. ( NB.LE.K ) .OR. ( NB.GE.MAX( M, N, K ) ) ) THEN CALL DGEMLQT( SIDE, TRANS, M, N, K, MB, A, LDA, - $ WORK1(6), MB, C, LDC, WORK2, INFO) + $ T( 6 ), MB, C, LDC, WORK, INFO ) ELSE - CALL DLAMSWLQ( SIDE, TRANS, M, N, K, MB, NB, A, LDA, WORK1(6), - $ MB, C, LDC, WORK2, LWORK2, INFO ) + CALL DLAMSWLQ( SIDE, TRANS, M, N, K, MB, NB, A, LDA, T( 6 ), + $ MB, C, LDC, WORK, LWORK, INFO ) END IF * - WORK2(1) = LW + WORK( 1 ) = LW * RETURN * diff --git a/SRC/dgemqr.f b/SRC/dgemqr.f index f47e6a87..6032be6d 100644 --- a/SRC/dgemqr.f +++ b/SRC/dgemqr.f @@ -2,48 +2,52 @@ * Definition: * =========== * -* SUBROUTINE DGEMQR( SIDE, TRANS, M, N, K, A, LDA, WORK1, -* $ LWORK1, C, LDC, WORK2, LWORK2, INFO ) +* SUBROUTINE DGEMQR( SIDE, TRANS, M, N, K, A, LDA, T, +* $ TSIZE, C, LDC, WORK, LWORK, INFO ) * * * .. Scalar Arguments .. -* CHARACTER SIDE, TRANS -* INTEGER INFO, LDA, M, N, K, LDT, LWORK1, LWORK2, LDC +* CHARACTER SIDE, TRANS +* INTEGER INFO, LDA, M, N, K, LDT, TSIZE, LWORK, LDC * .. * .. Array Arguments .. -* DOUBLE PRECISION A( LDA, * ), WORK1( * ), C(LDC, * ), -* $ WORK2( * ) -* .. -* +* DOUBLE PRECISION A( LDA, * ), T( * ), C( LDC, * ), WORK( * ) +* .. * *> \par Purpose: * ============= *> *> \verbatim *> -*> DGEMQR overwrites the general real M-by-N matrix C with -*> +*> DGEMQR overwrites the general real M-by-N matrix C with *> *> SIDE = 'L' SIDE = 'R' *> TRANS = 'N': Q * C C * Q *> TRANS = 'T': Q**T * C C * Q**T -*> where Q is a real orthogonal matrix defined as the product -*> of blocked elementary reflectors computed by tall skinny -*> QR factorization (DGEQR) +*> +*> where Q is a real orthogonal matrix defined as the product +*> of blocked elementary reflectors computed by tall skinny +*> QR factorization (DGEQR) +*> *> \endverbatim * * Arguments: * ========== * *> \param[in] SIDE +*> \verbatim *> SIDE is CHARACTER*1 *> = 'L': apply Q or Q**T from the Left; *> = 'R': apply Q or Q**T from the Right. +*> \endverbatim *> *> \param[in] TRANS +*> \verbatim *> TRANS is CHARACTER*1 *> = 'N': No transpose, apply Q; *> = 'T': Transpose, apply Q**T. +*> \endverbatim +*> *> \param[in] M *> \verbatim *> M is INTEGER @@ -53,7 +57,7 @@ *> \param[in] N *> \verbatim *> N is INTEGER -*> The number of columns of the matrix C. M >= N >= 0. +*> The number of columns of the matrix C. N >= 0. *> \endverbatim *> *> \param[in] K @@ -61,17 +65,14 @@ *> K is INTEGER *> The number of elementary reflectors whose product defines *> the matrix Q. -*> N >= K >= 0; -*> +*> If SIDE = 'L', M >= K >= 0; +*> if SIDE = 'R', N >= K >= 0. *> \endverbatim *> -*> \param[in,out] A +*> \param[in] A *> \verbatim *> A is DOUBLE PRECISION array, dimension (LDA,K) -*> The i-th column must contain the vector which defines the -*> blockedelementary reflector H(i), for i = 1,2,...,k, as -*> returned by DGETSQR in the first k columns of -*> its array argument A. +*> Part of the data structure to represent Q as returned by DGEQR. *> \endverbatim *> *> \param[in] LDA @@ -82,42 +83,46 @@ *> if SIDE = 'R', LDA >= max(1,N). *> \endverbatim *> -*> \param[in] WORK1 +*> \param[in] T *> \verbatim -*> WORK1 is DOUBLE PRECISION array, dimension (MAX(1,LWORK1)) as -*> it is returned by GEQR. +*> T is DOUBLE PRECISION array, dimension (MAX(5,TSIZE)). +*> Part of the data structure to represent Q as returned by DGEQR. *> \endverbatim *> -*> \param[in] LWORK1 +*> \param[in] TSIZE *> \verbatim -*> LWORK1 is INTEGER -*> The dimension of the array WORK1. +*> TSIZE is INTEGER +*> The dimension of the array T. TSIZE >= 5. *> \endverbatim *> *> \param[in,out] C +*> \verbatim *> C is DOUBLE PRECISION array, dimension (LDC,N) *> On entry, the M-by-N matrix C. *> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +*> \endverbatim *> *> \param[in] LDC +*> \verbatim *> LDC is INTEGER *> The leading dimension of the array C. LDC >= max(1,M). +*> \endverbatim *> -*> \param[out] WORK2 +*> \param[out] WORK *> \verbatim -*> (workspace) DOUBLE PRECISION array, dimension (MAX(1,LWORK2)) -*> +*> (workspace) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) *> \endverbatim -*> \param[in] LWORK2 -*> \verbatim -*> LWORK2 is INTEGER -*> The dimension of the array WORK2. -*> If LWORK2 = -1, then a workspace query is assumed; the routine -*> only calculates the optimal size of the WORK2 array, returns -*> this value as the third entry of the WORK2 array (WORK2(1)), -*> and no error message related to LWORK2 is issued by XERBLA. *> +*> \param[in] LWORK +*> \verbatim +*> LWORK is INTEGER +*> The dimension of the array WORK. +*> If LWORK = -1, then a workspace query is assumed. The routine +*> only calculates the size of the WORK array, returns this +*> value as WORK(1), and no error message related to WORK +*> is issued by XERBLA. *> \endverbatim +*> *> \param[out] INFO *> \verbatim *> INFO is INTEGER @@ -133,54 +138,64 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \par Further Details: -* ===================== +*> \par Further Details +* ==================== *> *> \verbatim +*> +*> These details are particular for this LAPACK implementation. Users should not +*> take them for granted. These details may change in the future, and are unlikely not +*> true for another LAPACK implementation. These details are relevant if one wants +*> to try to understand the code. They are not part of the interface. +*> +*> In this version, +*> +*> T(2): row block size (MB) +*> T(3): column block size (NB) +*> T(6:TSIZE): data structure needed for Q, computed by +*> DLATSQR or DGEQRT +*> *> Depending on the matrix dimensions M and N, and row and column -*> block sizes MB and NB returned by ILAENV, GEQR will use either -*> LATSQR (if the matrix is tall-and-skinny) or GEQRT to compute -*> the QR decomposition. -*> The output of LATSQR or GEQRT representing Q is stored in A and in -*> array WORK1(6:LWORK1) for later use. -*> WORK1(2:5) contains the matrix dimensions M,N and block sizes MB,NB -*> which are needed to interpret A and WORK1(6:LWORK1) for later use. -*> WORK1(1)=1 indicates that the code needed to take WORK1(2:5) and -*> decide whether LATSQR or GEQRT was used is the same as used below in -*> GEQR. For a detailed description of A and WORK1(6:LWORK1), see -*> Further Details in LATSQR or GEQRT. +*> block sizes MB and NB returned by ILAENV, DGEQR will use either +*> DLATSQR (if the matrix is tall-and-skinny) or DGEQRT to compute +*> the QR factorization. +*> This version of DGEMQR will use either DLAMTSQR or DGEMQRT to +*> multiply matrix Q by another matrix. +*> Further Details in DLATMSQR or DGEMQRT. +*> *> \endverbatim *> * ===================================================================== - SUBROUTINE DGEMQR( SIDE, TRANS, M, N, K, A, LDA, WORK1, LWORK1, - $ C, LDC, WORK2, LWORK2, INFO ) + SUBROUTINE DGEMQR( SIDE, TRANS, M, N, K, A, LDA, T, TSIZE, + $ C, LDC, WORK, LWORK, INFO ) * -* -- LAPACK computational routine (version 3.5.0) -- +* -- LAPACK computational routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- -* November 2013 +* November 2016 * * .. Scalar Arguments .. - CHARACTER SIDE, TRANS - INTEGER INFO, LDA, M, N, K, LWORK1, LWORK2, LDC + CHARACTER SIDE, TRANS + INTEGER INFO, LDA, M, N, K, TSIZE, LWORK, LDC * .. * .. Array Arguments .. - DOUBLE PRECISION A( LDA, * ), WORK1( * ), C(LDC, * ), - $ WORK2( * ) + DOUBLE PRECISION A( LDA, * ), T( * ), C( LDC, * ), WORK( * ) * .. * * ===================================================================== * * .. * .. Local Scalars .. - LOGICAL LEFT, RIGHT, TRAN, NOTRAN, LQUERY - INTEGER MB, NB, I, II, KK, LW, NBLCKS, MN + LOGICAL LEFT, RIGHT, TRAN, NOTRAN, LQUERY + INTEGER MB, NB, LW, NBLCKS, MN * .. * .. External Functions .. LOGICAL LSAME EXTERNAL LSAME +* .. * .. External Subroutines .. - EXTERNAL DGEMQRT, DTPMQRT, XERBLA + EXTERNAL DGEMQRT, DLAMTSQR, XERBLA +* .. * .. Intrinsic Functions .. INTRINSIC INT, MAX, MIN, MOD * .. @@ -188,82 +203,80 @@ * * Test the input arguments * - LQUERY = LWORK2.LT.0 + LQUERY = LWORK.EQ.-1 NOTRAN = LSAME( TRANS, 'N' ) TRAN = LSAME( TRANS, 'T' ) LEFT = LSAME( SIDE, 'L' ) RIGHT = LSAME( SIDE, 'R' ) * - MB = INT(WORK1(4)) - NB = INT(WORK1(5)) - IF(LEFT) THEN + MB = INT( T( 2 ) ) + NB = INT( T( 3 ) ) + IF( LEFT ) THEN LW = N * NB MN = M - ELSE IF(RIGHT) THEN + ELSE LW = MB * NB MN = N END IF * - IF ((MB.GT.K).AND.(MN.GT.K)) THEN - IF(MOD(MN-K, MB-K).EQ.0) THEN - NBLCKS = (MN-K)/(MB-K) - ELSE - NBLCKS = (MN-K)/(MB-K) + 1 - END IF + IF( ( MB.GT.K ) .AND. ( MN.GT.K ) ) THEN + IF( MOD( MN - K, MB - K ).EQ.0 ) THEN + NBLCKS = ( MN - K ) / ( MB - K ) + ELSE + NBLCKS = ( MN - K ) / ( MB - K ) + 1 + END IF ELSE NBLCKS = 1 END IF * INFO = 0 IF( .NOT.LEFT .AND. .NOT.RIGHT ) THEN - INFO = -1 + INFO = -1 ELSE IF( .NOT.TRAN .AND. .NOT.NOTRAN ) THEN - INFO = -2 + INFO = -2 ELSE IF( M.LT.0 ) THEN INFO = -3 ELSE IF( N.LT.0 ) THEN INFO = -4 - ELSE IF( K.LT.0 ) THEN + ELSE IF( K.LT.0 .OR. K.GT.MN ) THEN INFO = -5 - ELSE IF( LDA.LT.MAX( 1, K ) ) THEN + ELSE IF( LDA.LT.MAX( 1, MN ) ) THEN INFO = -7 - ELSE IF( LWORK1.LT.MAX( 1, NB*K*NBLCKS+5 )) THEN + ELSE IF( TSIZE.LT.5 ) THEN INFO = -9 - ELSE IF( LDC.LT.MAX( 1, M ).AND.MIN(M,N,K).NE.0 ) THEN - INFO = -11 - ELSE IF(( LWORK2.LT.MAX(1,LW)).AND.(.NOT.LQUERY)) THEN + ELSE IF( LDC.LT.MAX( 1, M ) ) THEN + INFO = -11 + ELSE IF( ( LWORK.LT.MAX( 1, LW ) ) .AND. ( .NOT.LQUERY ) ) THEN INFO = -13 END IF * -* Determine the block size if it is tall skinny or short and wide -* - IF( INFO.EQ.0) THEN - WORK2(1) = LW + IF( INFO.EQ.0 ) THEN + WORK( 1 ) = LW END IF * IF( INFO.NE.0 ) THEN CALL XERBLA( 'DGEMQR', -INFO ) RETURN - ELSE IF (LQUERY) THEN - RETURN + ELSE IF( LQUERY ) THEN + RETURN END IF * * Quick return if possible * - IF( MIN(M,N,K).EQ.0 ) THEN + IF( MIN( M, N, K ).EQ.0 ) THEN RETURN END IF * - IF((LEFT.AND.M.LE.K).OR.(RIGHT.AND.N.LE.K).OR.(MB.LE.K).OR. - $ (MB.GE.MAX(M,N,K))) THEN - CALL DGEMQRT( SIDE, TRANS, M, N, K, NB, A, LDA, - $ WORK1(6), NB, C, LDC, WORK2, INFO) + IF( ( LEFT .AND. M.LE.K ) .OR. ( RIGHT .AND. N.LE.K ) + $ .OR. ( MB.LE.K ) .OR. ( MB.GE.MAX( M, N, K ) ) ) THEN + CALL DGEMQRT( SIDE, TRANS, M, N, K, NB, A, LDA, T( 6 ), + $ NB, C, LDC, WORK, INFO ) ELSE - CALL DLAMTSQR( SIDE, TRANS, M, N, K, MB, NB, A, LDA, WORK1(6), - $ NB, C, LDC, WORK2, LWORK2, INFO ) + CALL DLAMTSQR( SIDE, TRANS, M, N, K, MB, NB, A, LDA, T( 6 ), + $ NB, C, LDC, WORK, LWORK, INFO ) END IF * - WORK2(1) = LW + WORK( 1 ) = LW * RETURN * diff --git a/SRC/dgeqr.f b/SRC/dgeqr.f index da0fc4ad..5212c69e 100644 --- a/SRC/dgeqr.f +++ b/SRC/dgeqr.f @@ -2,14 +2,14 @@ * Definition: * =========== * -* SUBROUTINE DGEQR( M, N, A, LDA, WORK1, LWORK1, WORK2, LWORK2, -* INFO) +* SUBROUTINE DGEQR( M, N, A, LDA, T, TSIZE, WORK, LWORK, +* INFO ) * * .. Scalar Arguments .. -* INTEGER INFO, LDA, M, N, LWORK1, LWORK2 +* INTEGER INFO, LDA, M, N, TSIZE, LWORK * .. * .. Array Arguments .. -* DOUBLE PRECISION A( LDA, * ), WORK1( * ), WORK2( * ) +* DOUBLE PRECISION A( LDA, * ), T( * ), WORK( * ) * .. * * @@ -17,11 +17,7 @@ * ============= *> *> \verbatim -*> -*> DGEQR computes a QR factorization of an M-by-N matrix A, -*> using DLATSQR when A is tall and skinny -*> (M sufficiently greater than N), and otherwise DGEQRT: -*> A = Q * R . +*> DGEQR computes a QR factorization of an M-by-N matrix A. *> \endverbatim * * Arguments: @@ -46,7 +42,8 @@ *> On exit, the elements on and above the diagonal of the array *> contain the min(M,N)-by-N upper trapezoidal matrix R *> (R is upper triangular if M >= N); -*> the elements below the diagonal represent Q (see Further Details). +*> the elements below the diagonal are used to store part of the +*> data structure to represent Q. *> \endverbatim *> *> \param[in] LDA @@ -55,47 +52,50 @@ *> The leading dimension of the array A. LDA >= max(1,M). *> \endverbatim *> -*> \param[out] WORK1 +*> \param[out] T *> \verbatim -*> WORK1 is DOUBLE PRECISION array, dimension (MAX(1,LWORK1)) -*> WORK1 contains part of the data structure used to store Q. -*> WORK1(1): algorithm type = 1, to indicate output from -*> DLATSQR or DGEQRT -*> WORK1(2): optimum size of WORK1 -*> WORK1(3): minimum size of WORK1 -*> WORK1(4): row block size -*> WORK1(5): column block size -*> WORK1(6:LWORK1): data structure needed for Q, computed by -*> DLATSQR or DGEQRT +*> T is DOUBLE PRECISION array, dimension (MAX(5,TSIZE)) +*> On exit, if INFO = 0, T(1) returns optimal (or either minimal +*> or optimal, if query is assumed) TSIZE. See TSIZE for details. +*> Remaining T contains part of the data structure used to represent Q. +*> If one wants to apply or construct Q, then one needs to keep T +*> (in addition to A) and pass it to further subroutines. *> \endverbatim *> -*> \param[in] LWORK1 +*> \param[in] TSIZE *> \verbatim -*> LWORK1 is INTEGER -*> The dimension of the array WORK1. -*> If LWORK1 = -1, then a query is assumed. In this case the -*> routine calculates the optimal size of WORK1 and -*> returns this value in WORK1(2), and calculates the minimum -*> size of WORK1 and returns this value in WORK1(3). -*> No error message related to LWORK1 is issued by XERBLA when -*> LWORK1 = -1. +*> TSIZE is INTEGER +*> If TSIZE >= 5, the dimension of the array T. +*> If TSIZE = -1 or -2, then a workspace query is assumed. The routine +*> only calculates the sizes of the T and WORK arrays, returns these +*> values as the first entries of the T and WORK arrays, and no error +*> message related to T or WORK is issued by XERBLA. +*> If TSIZE = -1, the routine calculates optimal size of T for the +*> optimum performance and returns this value in T(1). +*> If TSIZE = -2, the routine calculates minimal size of T and +*> returns this value in T(1). *> \endverbatim *> -*> \param[out] WORK2 +*> \param[out] WORK *> \verbatim -*> (workspace) DOUBLE PRECISION array, dimension (MAX(1,LWORK2)) +*> (workspace) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +*> On exit, if INFO = 0, WORK(1) contains optimal (or either minimal +*> or optimal, if query was assumed) LWORK. +*> See LWORK for details. *> \endverbatim *> -*> \param[in] LWORK2 +*> \param[in] LWORK *> \verbatim -*> LWORK2 is INTEGER -*> The dimension of the array WORK2. -*> If LWORK2 = -1, then a query is assumed. In this case the -*> routine calculates the optimal size of WORK2 and -*> returns this value in WORK2(1), and calculates the minimum -*> size of WORK2 and returns this value in WORK2(2). -*> No error message related to LWORK2 is issued by XERBLA when -*> LWORK2 = -1. +*> LWORK is INTEGER +*> The dimension of the array WORK. +*> If LWORK = -1 or -2, then a workspace query is assumed. The routine +*> only calculates the sizes of the T and WORK arrays, returns these +*> values as the first entries of the T and WORK arrays, and no error +*> message related to T or WORK is issued by XERBLA. +*> If LWORK = -1, the routine calculates optimal size of WORK for the +*> optimal performance and returns this value in WORK(1). +*> If LWORK = -2, the routine calculates minimal size of WORK and +*> returns this value in WORK(1). *> \endverbatim *> *> \param[out] INFO @@ -113,106 +113,138 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \par Further Details: -* ===================== +*> \par Further Details +* ==================== *> *> \verbatim +*> +*> The goal of the interface is to give maximum freedom to the developers for +*> creating any QR factorization algorithm they wish. The triangular +*> (trapezoidal) R has to be stored in the upper part of A. The lower part of A +*> and the array T can be used to store any relevant information for applying or +*> constructing the Q factor. The WORK array can safely be discarded after exit. +*> +*> Caution: One should not expect the sizes of T and WORK to be the same from one +*> LAPACK implementation to the other, or even from one execution to the other. +*> A workspace query (for T and WORK) is needed at each execution. However, +*> for a given execution, the size of T and WORK are fixed and will not change +*> from one query to the next. +*> +*> \endverbatim +*> +*> \par Further Details particular to this LAPACK implementation: +* ============================================================== +*> +*> \verbatim +*> +*> These details are particular for this LAPACK implementation. Users should not +*> take them for granted. These details may change in the future, and are unlikely not +*> true for another LAPACK implementation. These details are relevant if one wants +*> to try to understand the code. They are not part of the interface. +*> +*> In this version, +*> +*> T(2): row block size (MB) +*> T(3): column block size (NB) +*> T(6:TSIZE): data structure needed for Q, computed by +*> DLATSQR or DGEQRT +*> *> Depending on the matrix dimensions M and N, and row and column -*> block sizes MB and NB returned by ILAENV, GEQR will use either -*> LATSQR (if the matrix is tall-and-skinny) or GEQRT to compute -*> the QR decomposition. -*> The output of LATSQR or GEQRT representing Q is stored in A and in -*> array WORK1(6:LWORK1) for later use. -*> WORK1(2:5) contains the matrix dimensions M,N and block sizes MB,NB -*> which are needed to interpret A and WORK1(6:LWORK1) for later use. -*> WORK1(1)=1 indicates that the code needed to take WORK1(2:5) and -*> decide whether LATSQR or GEQRT was used is the same as used below in -*> GEQR. For a detailed description of A and WORK1(6:LWORK1), see -*> Further Details in LATSQR or GEQRT. +*> block sizes MB and NB returned by ILAENV, DGEQR will use either +*> DLATSQR (if the matrix is tall-and-skinny) or DGEQRT to compute +*> the QR factorization. +*> *> \endverbatim *> * ===================================================================== - SUBROUTINE DGEQR( M, N, A, LDA, WORK1, LWORK1, WORK2, LWORK2, - $ INFO) + SUBROUTINE DGEQR( M, N, A, LDA, T, TSIZE, WORK, LWORK, + $ INFO ) * -* -- LAPACK computational routine (version 3.5.0) -- +* -- LAPACK computational routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd. -- -* November 2013 +* November 2016 * * .. Scalar Arguments .. - INTEGER INFO, LDA, M, N, LWORK1, LWORK2 + INTEGER INFO, LDA, M, N, TSIZE, LWORK * .. * .. Array Arguments .. - DOUBLE PRECISION A( LDA, * ), WORK1( * ), WORK2( * ) + DOUBLE PRECISION A( LDA, * ), T( * ), WORK( * ) * .. * * ===================================================================== * * .. * .. Local Scalars .. - LOGICAL LQUERY, LMINWS - INTEGER MB, NB, I, II, KK, MINLW1, NBLCKS + LOGICAL LQUERY, LMINWS, MINT, MINW + INTEGER MB, NB, MINTSZ, NBLCKS * .. -* .. EXTERNAL FUNCTIONS .. +* .. External Functions .. LOGICAL LSAME EXTERNAL LSAME -* .. EXTERNAL SUBROUTINES .. +* .. +* .. External Subroutines .. EXTERNAL DLATSQR, DGEQRT, XERBLA -* .. INTRINSIC FUNCTIONS .. +* .. +* .. Intrinsic Functions .. INTRINSIC MAX, MIN, MOD * .. -* .. EXTERNAL FUNCTIONS .. +* .. External Functions .. INTEGER ILAENV EXTERNAL ILAENV * .. -* .. EXECUTABLE STATEMENTS .. +* .. Executable Statements .. * -* TEST THE INPUT ARGUMENTS +* Test the input arguments * INFO = 0 * - LQUERY = ( LWORK1.EQ.-1 .OR. LWORK2.EQ.-1 ) + LQUERY = ( TSIZE.EQ.-1 .OR. TSIZE.EQ.-2 .OR. + $ LWORK.EQ.-1 .OR. LWORK.EQ.-2 ) +* + MINT = .FALSE. + MINW = .FALSE. + IF( TSIZE.EQ.-2 .OR. LWORK.EQ.-2 ) THEN + IF( TSIZE.NE.-1 ) MINT = .TRUE. + IF( LWORK.NE.-1 ) MINW = .TRUE. + END IF * * Determine the block size * - IF ( MIN(M,N).GT.0 ) THEN - MB = ILAENV( 1, 'DGEQR ', ' ', M, N, 1, -1) - NB = ILAENV( 1, 'DGEQR ', ' ', M, N, 2, -1) + IF( MIN( M, N ).GT.0 ) THEN + MB = ILAENV( 1, 'DGEQR ', ' ', M, N, 1, -1 ) + NB = ILAENV( 1, 'DGEQR ', ' ', M, N, 2, -1 ) ELSE MB = M NB = 1 END IF - IF( MB.GT.M.OR.MB.LE.N) MB = M - IF( NB.GT.MIN(M,N).OR.NB.LT.1) NB = 1 - MINLW1 = N + 5 - IF ((MB.GT.N).AND.(M.GT.N)) THEN - IF(MOD(M-N, MB-N).EQ.0) THEN - NBLCKS = (M-N)/(MB-N) + IF( MB.GT.M .OR. MB.LE.N ) MB = M + IF( NB.GT.MIN( M, N ) .OR. NB.LT.1 ) NB = 1 + MINTSZ = N + 5 + IF( MB.GT.N .AND. M.GT.N ) THEN + IF( MOD( M - N, MB - N ).EQ.0 ) THEN + NBLCKS = ( M - N ) / ( MB - N ) ELSE - NBLCKS = (M-N)/(MB-N) + 1 + NBLCKS = ( M - N ) / ( MB - N ) + 1 END IF ELSE NBLCKS = 1 END IF * -* Determine if the workspace size satisfies minimum size +* Determine if the workspace size satisfies minimal size * LMINWS = .FALSE. - IF((LWORK1.LT.MAX(1, NB*N*NBLCKS+5) - $ .OR.(LWORK2.LT.NB*N)).AND.(LWORK2.GE.N).AND.(LWORK1.GT.N+5) - $ .AND.(.NOT.LQUERY)) THEN - IF (LWORK1.LT.MAX(1, NB * N * NBLCKS+5)) THEN - LMINWS = .TRUE. - NB = 1 + IF( ( TSIZE.LT.MAX( 1, NB*N*NBLCKS + 5 ) .OR. LWORK.LT.NB*N ) + $ .AND. ( LWORK.GE.N ) .AND. ( TSIZE.GE.MINTSZ ) + $ .AND. ( .NOT.LQUERY ) ) THEN + IF( TSIZE.LT.MAX( 1, NB*N*NBLCKS + 5 ) ) THEN + LMINWS = .TRUE. + NB = 1 + MB = M END IF - IF (LWORK1.LT.MAX(1, N * NBLCKS+5)) THEN - LMINWS = .TRUE. - MB = M - END IF - IF (LWORK2.LT.NB*N) THEN - LMINWS = .TRUE. - NB = 1 + IF( LWORK.LT.NB*N ) THEN + LMINWS = .TRUE. + NB = 1 END IF END IF * @@ -222,44 +254,52 @@ INFO = -2 ELSE IF( LDA.LT.MAX( 1, M ) ) THEN INFO = -4 - ELSE IF( LWORK1.LT.MAX( 1, NB * N * NBLCKS + 5 ) - $ .AND.(.NOT.LQUERY).AND.(.NOT.LMINWS)) THEN + ELSE IF( TSIZE.LT.MAX( 1, NB*N*NBLCKS + 5 ) + $ .AND. ( .NOT.LQUERY ) .AND. ( .NOT.LMINWS ) ) THEN INFO = -6 - ELSE IF( (LWORK2.LT.MAX(1,N*NB)).AND.(.NOT.LQUERY) - $ .AND.(.NOT.LMINWS)) THEN + ELSE IF( ( LWORK.LT.MAX( 1, N*NB ) ) .AND. ( .NOT.LQUERY ) + $ .AND. ( .NOT.LMINWS ) ) THEN INFO = -8 END IF - - IF( INFO.EQ.0) THEN - WORK1(1) = 1 - WORK1(2) = NB * N * NBLCKS + 5 - WORK1(3) = MINLW1 - WORK1(4) = MB - WORK1(5) = NB - WORK2(1) = NB * N - WORK2(2) = N +* + IF( INFO.EQ.0 ) THEN + IF( MINT ) THEN + T( 1 ) = MINTSZ + ELSE + T( 1 ) = NB*N*NBLCKS + 5 + END IF + T( 2 ) = MB + T( 3 ) = NB + IF( MINW ) THEN + WORK( 1 ) = MAX( 1, N ) + ELSE + WORK( 1 ) = MAX( 1, NB*N ) + END IF END IF IF( INFO.NE.0 ) THEN CALL XERBLA( 'DGEQR', -INFO ) RETURN - ELSE IF (LQUERY) THEN - RETURN + ELSE IF( LQUERY ) THEN + RETURN END IF * * Quick return if possible * - IF( MIN(M,N).EQ.0 ) THEN - RETURN + IF( MIN( M, N ).EQ.0 ) THEN + RETURN END IF * * The QR Decomposition * - IF((M.LE.N).OR.(MB.LE.N).OR.(MB.GE.M)) THEN - CALL DGEQRT( M, N, NB, A, LDA, WORK1(6), NB, WORK2, INFO) + IF( ( M.LE.N ) .OR. ( MB.LE.N ) .OR. ( MB.GE.M ) ) THEN + CALL DGEQRT( M, N, NB, A, LDA, T( 6 ), NB, WORK, INFO ) ELSE - CALL DLATSQR( M, N, MB, NB, A, LDA, WORK1(6), NB, WORK2, - $ LWORK2, INFO) + CALL DLATSQR( M, N, MB, NB, A, LDA, T( 6 ), NB, WORK, + $ LWORK, INFO ) END IF +* + WORK( 1 ) = MAX( 1, NB*N ) +* RETURN * * End of DGEQR diff --git a/SRC/dgetsls.f b/SRC/dgetsls.f index f2a7b3a7..13a8fd19 100644 --- a/SRC/dgetsls.f +++ b/SRC/dgetsls.f @@ -29,16 +29,21 @@ *> 1. If TRANS = 'N' and m >= n: find the least squares solution of *> an overdetermined system, i.e., solve the least squares problem *> minimize || B - A*X ||. - +*> *> 2. If TRANS = 'N' and m < n: find the minimum norm solution of *> an underdetermined system A * X = B. - +*> *> 3. If TRANS = 'T' and m >= n: find the minimum norm solution of *> an undetermined system A**T * X = B. - +*> *> 4. If TRANS = 'T' and m < n: find the least squares solution of *> an overdetermined system, i.e., solve the least squares problem *> minimize || B - A**T * X ||. +*> +*> Several right hand side vectors b and solution vectors x can be +*> handled in a single call; they are stored as the columns of the +*> M-by-NRHS right hand side matrix B and the N-by-NRHS solution +*> matrix X. *> \endverbatim * * Arguments: @@ -76,7 +81,7 @@ *> On entry, the M-by-N matrix A. *> On exit, *> A is overwritten by details of its QR or LQ -*> factorization as returned by DGETSQR. +*> factorization as returned by DGEQR or DGELQ. *> \endverbatim *> *> \param[in] LDA @@ -111,18 +116,21 @@ *> *> \param[out] WORK *> \verbatim -*> WORK is DOUBLE PRECISION array, dimension (MAX(12,LWORK)) -*> On exit, if INFO = 0, WORK(1) returns the optimal LWORK, -*> and WORK(2) returns the minimum LWORK. +*> (workspace) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +*> On exit, if INFO = 0, WORK(1) contains optimal (or either minimal +*> or optimal, if query was assumed) LWORK. +*> See LWORK for details. *> \endverbatim *> *> \param[in] LWORK *> \verbatim *> LWORK is INTEGER *> The dimension of the array WORK. -*> IF LWORK=-1, workspace query is assumed, and -*> WORK(1) returns the optimal LWORK, -*> and WORK(2) returns the minimum LWORK. +*> If LWORK = -1 or -2, then a workspace query is assumed. +*> If LWORK = -1, the routine calculates optimal size of WORK for the +*> optimal performance and returns this value in WORK(1). +*> If LWORK = -2, the routine calculates minimal size of WORK and +*> returns this value in WORK(1). *> \endverbatim *> *> \param[out] INFO @@ -144,18 +152,18 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \date November 2011 +*> \date November 2016 * *> \ingroup doubleGEsolve * * ===================================================================== SUBROUTINE DGETSLS( TRANS, M, N, NRHS, A, LDA, B, LDB, - $ WORK, LWORK, INFO ) + $ WORK, LWORK, INFO ) * -* -- LAPACK driver routine (version 3.4.0) -- +* -- LAPACK driver routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- -* November 2011 +* November 2016 * * .. Scalar Arguments .. CHARACTER TRANS @@ -174,10 +182,10 @@ * .. * .. Local Scalars .. LOGICAL LQUERY, TRAN - INTEGER I, IASCL, IBSCL, J, MINMN, MAXMN, BROW, LW, - $ SCLLEN, MNK, WSIZEO, WSIZEM, LW1, LW2, - $ INFO2 - DOUBLE PRECISION ANRM, BIGNUM, BNRM, SMLNUM + INTEGER I, IASCL, IBSCL, J, MINMN, MAXMN, BROW, + $ SCLLEN, MNK, TSZO, TSZM, LWO, LWM, LW1, LW2, + $ WSIZEO, WSIZEM, INFO2 + DOUBLE PRECISION ANRM, BIGNUM, BNRM, SMLNUM, TQ( 5 ), WORKQ * .. * .. External Functions .. LOGICAL LSAME @@ -190,19 +198,19 @@ $ DTRTRS, XERBLA, DGELQ, DGEMLQ * .. * .. Intrinsic Functions .. - INTRINSIC DBLE, MAX, MIN + INTRINSIC DBLE, MAX, MIN, INT * .. * .. Executable Statements .. * * Test the input arguments. * - INFO=0 + INFO = 0 MINMN = MIN( M, N ) MAXMN = MAX( M, N ) - MNK = MAX(MINMN,NRHS) + MNK = MAX( MINMN, NRHS ) TRAN = LSAME( TRANS, 'T' ) * - LQUERY = ( LWORK.EQ.-1 ) + LQUERY = ( LWORK.EQ.-1 .OR. LWORK.EQ.-2 ) IF( .NOT.( LSAME( TRANS, 'N' ) .OR. $ LSAME( TRANS, 'T' ) ) ) THEN INFO = -1 @@ -218,56 +226,71 @@ INFO = -8 END IF * - IF( INFO.EQ.0) THEN + IF( INFO.EQ.0 ) THEN * * Determine the block size and minimum LWORK * - IF ( M.GE.N ) THEN - CALL DGEQR( M, N, A, LDA, WORK(1), -1, WORK(6), -1, - $ INFO2) - LW = INT(WORK(6)) - CALL DGEMQR( 'L', TRANS, M, NRHS, N, A, LDA, WORK(1), - $ INT(WORK(2)), B, LDB, WORK(6), -1 , INFO2 ) - WSIZEO = INT(WORK(2))+MAX(LW,INT(WORK(6))) - WSIZEM = INT(WORK(3))+MAX(LW,INT(WORK(6))) + IF( M.GE.N ) THEN + CALL DGEQR( M, N, A, LDA, TQ, -1, WORKQ, -1, INFO2 ) + TSZO = INT( TQ( 1 ) ) + LWO = INT( WORKQ ) + CALL DGEMQR( 'L', TRANS, M, NRHS, N, A, LDA, TQ, + $ TSZO, B, LDB, WORKQ, -1, INFO2 ) + LWO = MAX( LWO, INT( WORKQ ) ) + CALL DGEQR( M, N, A, LDA, TQ, -2, WORKQ, -2, INFO2 ) + TSZM = INT( TQ( 1 ) ) + LWM = INT( WORKQ ) + CALL DGEMQR( 'L', TRANS, M, NRHS, N, A, LDA, TQ, + $ TSZM, B, LDB, WORKQ, -1, INFO2 ) + LWM = MAX( LWM, INT( WORKQ ) ) + WSIZEO = TSZO + LWO + WSIZEM = TSZM + LWM ELSE - CALL DGELQ( M, N, A, LDA, WORK(1), -1, WORK(6), -1, - $ INFO2) - LW = INT(WORK(6)) - CALL DGEMLQ( 'L', TRANS, N, NRHS, M, A, LDA, WORK(1), - $ INT(WORK(2)), B, LDB, WORK(6), -1 , INFO2 ) - WSIZEO = INT(WORK(2))+MAX(LW,INT(WORK(6))) - WSIZEM = INT(WORK(3))+MAX(LW,INT(WORK(6))) + CALL DGELQ( M, N, A, LDA, TQ, -1, WORKQ, -1, INFO2 ) + TSZO = INT( TQ( 1 ) ) + LWO = INT( WORKQ ) + CALL DGEMLQ( 'L', TRANS, N, NRHS, M, A, LDA, TQ, + $ TSZO, B, LDB, WORKQ, -1, INFO2 ) + LWO = MAX( LWO, INT( WORKQ ) ) + CALL DGELQ( M, N, A, LDA, TQ, -2, WORKQ, -2, INFO2 ) + TSZM = INT( TQ( 1 ) ) + LWM = INT( WORKQ ) + CALL DGEMLQ( 'L', TRANS, N, NRHS, M, A, LDA, TQ, + $ TSZO, B, LDB, WORKQ, -1, INFO2 ) + LWM = MAX( LWM, INT( WORKQ ) ) + WSIZEO = TSZO + LWO + WSIZEM = TSZM + LWM END IF * - IF((LWORK.LT.WSIZEO).AND.(.NOT.LQUERY)) THEN - INFO=-10 + IF( ( LWORK.LT.WSIZEM ).AND.( .NOT.LQUERY ) ) THEN + INFO = -10 END IF +* END IF * IF( INFO.NE.0 ) THEN CALL XERBLA( 'DGETSLS', -INFO ) WORK( 1 ) = DBLE( WSIZEO ) - WORK( 2 ) = DBLE( WSIZEM ) RETURN - ELSE IF (LQUERY) THEN - WORK( 1 ) = DBLE( WSIZEO ) - WORK( 2 ) = DBLE( WSIZEM ) + END IF + IF( LQUERY ) THEN + IF( LWORK.EQ.-1 ) WORK( 1 ) = REAL( WSIZEO ) + IF( LWORK.EQ.-2 ) WORK( 1 ) = REAL( WSIZEM ) RETURN END IF - IF(LWORK.LT.WSIZEO) THEN - LW1=INT(WORK(3)) - LW2=MAX(LW,INT(WORK(6))) + IF( LWORK.LT.WSIZEO ) THEN + LW1 = TSZM + LW2 = LWM ELSE - LW1=INT(WORK(2)) - LW2=MAX(LW,INT(WORK(6))) + LW1 = TSZO + LW2 = LWO END IF * * Quick return if possible * IF( MIN( M, N, NRHS ).EQ.0 ) THEN CALL DLASET( 'FULL', MAX( M, N ), NRHS, ZERO, ZERO, - $ B, LDB ) + $ B, LDB ) RETURN END IF * @@ -323,26 +346,27 @@ IBSCL = 2 END IF * - IF ( M.GE.N) THEN + IF ( M.GE.N ) THEN * * compute QR factorization of A * - CALL DGEQR( M, N, A, LDA, WORK(LW2+1), LW1, - $ WORK(1), LW2, INFO ) - IF (.NOT.TRAN) THEN + CALL DGEQR( M, N, A, LDA, WORK( LW2+1 ), LW1, + $ WORK( 1 ), LW2, INFO ) + IF ( .NOT.TRAN ) THEN * * Least-Squares Problem min || A * X - B || * * B(1:M,1:NRHS) := Q**T * B(1:M,1:NRHS) * CALL DGEMQR( 'L' , 'T', M, NRHS, N, A, LDA, - $ WORK(LW2+1), LW1, B, LDB, WORK(1), LW2, INFO ) + $ WORK( LW2+1 ), LW1, B, LDB, WORK( 1 ), LW2, + $ INFO ) * * B(1:N,1:NRHS) := inv(R) * B(1:N,1:NRHS) * CALL DTRTRS( 'U', 'N', 'N', N, NRHS, - $ A, LDA, B, LDB, INFO ) - IF(INFO.GT.0) THEN + $ A, LDA, B, LDB, INFO ) + IF( INFO.GT.0 ) THEN RETURN END IF SCLLEN = N @@ -370,7 +394,7 @@ * B(1:M,1:NRHS) := Q(1:N,:) * B(1:N,1:NRHS) * CALL DGEMQR( 'L', 'N', M, NRHS, N, A, LDA, - $ WORK( LW2+1), LW1, B, LDB, WORK( 1 ), LW2, + $ WORK( LW2+1 ), LW1, B, LDB, WORK( 1 ), LW2, $ INFO ) * SCLLEN = M @@ -381,8 +405,8 @@ * * Compute LQ factorization of A * - CALL DGELQ( M, N, A, LDA, WORK(LW2+1), LW1, - $ WORK(1), LW2, INFO ) + CALL DGELQ( M, N, A, LDA, WORK( LW2+1 ), LW1, + $ WORK( 1 ), LW2, INFO ) * * workspace at least M, optimally M*NB. * @@ -410,7 +434,7 @@ * B(1:N,1:NRHS) := Q(1:N,:)**T * B(1:M,1:NRHS) * CALL DGEMLQ( 'L', 'T', N, NRHS, M, A, LDA, - $ WORK( LW2+1), LW1, B, LDB, WORK( 1 ), LW2, + $ WORK( LW2+1 ), LW1, B, LDB, WORK( 1 ), LW2, $ INFO ) * * workspace at least NRHS, optimally NRHS*NB @@ -424,7 +448,7 @@ * B(1:N,1:NRHS) := Q * B(1:N,1:NRHS) * CALL DGEMLQ( 'L', 'N', N, NRHS, M, A, LDA, - $ WORK( LW2+1), LW1, B, LDB, WORK( 1 ), LW2, + $ WORK( LW2+1 ), LW1, B, LDB, WORK( 1 ), LW2, $ INFO ) * * workspace at least NRHS, optimally NRHS*NB @@ -448,22 +472,21 @@ * IF( IASCL.EQ.1 ) THEN CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, SCLLEN, NRHS, B, LDB, - $ INFO ) + $ INFO ) ELSE IF( IASCL.EQ.2 ) THEN CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, SCLLEN, NRHS, B, LDB, - $ INFO ) + $ INFO ) END IF IF( IBSCL.EQ.1 ) THEN - CALL DLASCL( 'G', 0, 0, SMLNUM, BNRM, SCLLEN, NRHS, B, LDB, - $ INFO ) + CALL DLASCL( 'G', 0, 0, SMLNUM, BNRM, SCLLEN, NRHS, B, LDB, + $ INFO ) ELSE IF( IBSCL.EQ.2 ) THEN - CALL DLASCL( 'G', 0, 0, BIGNUM, BNRM, SCLLEN, NRHS, B, LDB, - $ INFO ) + CALL DLASCL( 'G', 0, 0, BIGNUM, BNRM, SCLLEN, NRHS, B, LDB, + $ INFO ) END IF * 50 CONTINUE - WORK( 1 ) = DBLE( WSIZEO ) - WORK( 2 ) = DBLE( WSIZEM ) + WORK( 1 ) = DBLE( TSZO + LWO ) RETURN * * End of DGETSLS diff --git a/SRC/dlamswlq.f b/SRC/dlamswlq.f index 3bf0e798..6eed0389 100644 --- a/SRC/dlamswlq.f +++ b/SRC/dlamswlq.f @@ -33,14 +33,19 @@ * ========== * *> \param[in] SIDE +*> \verbatim *> SIDE is CHARACTER*1 *> = 'L': apply Q or Q**T from the Left; *> = 'R': apply Q or Q**T from the Right. +*> \endverbatim *> *> \param[in] TRANS +*> \verbatim *> TRANS is CHARACTER*1 *> = 'N': No transpose, apply Q; *> = 'T': Transpose, apply Q**T. +*> \endverbatim +*> *> \param[in] M *> \verbatim *> M is INTEGER @@ -115,18 +120,23 @@ *> \endverbatim *> *> \param[in,out] C +*> \verbatim *> C is DOUBLE PRECISION array, dimension (LDC,N) *> On entry, the M-by-N matrix C. *> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +*> \endverbatim +*> *> \param[in] LDC +*> \verbatim *> LDC is INTEGER *> The leading dimension of the array C. LDC >= max(1,M). +*> \endverbatim *> *> \param[out] WORK *> \verbatim *> (workspace) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) -*> *> \endverbatim +*> *> \param[in] LWORK *> \verbatim *> LWORK is INTEGER @@ -137,8 +147,8 @@ *> only calculates the optimal size of the WORK array, returns *> this value as the first entry of the WORK array, and no error *> message related to LWORK is issued by XERBLA. -*> *> \endverbatim +*> *> \param[out] INFO *> \verbatim *> INFO is INTEGER diff --git a/SRC/dlamtsqr.f b/SRC/dlamtsqr.f index a4f5a025..59d4ae55 100644 --- a/SRC/dlamtsqr.f +++ b/SRC/dlamtsqr.f @@ -33,14 +33,19 @@ * ========== * *> \param[in] SIDE +*> \verbatim *> SIDE is CHARACTER*1 *> = 'L': apply Q or Q**T from the Left; *> = 'R': apply Q or Q**T from the Right. +*> \endverbatim *> *> \param[in] TRANS +*> \verbatim *> TRANS is CHARACTER*1 *> = 'N': No transpose, apply Q; *> = 'T': Transpose, apply Q**T. +*> \endverbatim +*> *> \param[in] M *> \verbatim *> M is INTEGER @@ -109,12 +114,17 @@ *> \endverbatim *> *> \param[in,out] C +*> \verbatim *> C is DOUBLE PRECISION array, dimension (LDC,N) *> On entry, the M-by-N matrix C. *> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +*> \endverbatim +*> *> \param[in] LDC +*> \verbatim *> LDC is INTEGER *> The leading dimension of the array C. LDC >= max(1,M). +*> \endverbatim *> *> \param[out] WORK *> \verbatim @@ -253,6 +263,7 @@ IF( INFO.EQ.0) THEN WORK(1) = LW END IF +* IF( INFO.NE.0 ) THEN CALL XERBLA( 'DLAMTSQR', -INFO ) RETURN @@ -352,8 +363,8 @@ * * Multiply Q to the current block of C (1:M,I:I+MB) * - CTR = CTR - 1 - CALL DTPMQRT('R','T',M , MB-K, K, 0,NB, A(I,1), LDA, + CTR = CTR - 1 + CALL DTPMQRT('R','T',M , MB-K, K, 0,NB, A(I,1), LDA, $ T(1,CTR*K+1), LDT, C(1,1), LDC, $ C(1,I), LDC, WORK, INFO ) * diff --git a/SRC/sgelq.f b/SRC/sgelq.f index 8a759834..1ae47d15 100644 --- a/SRC/sgelq.f +++ b/SRC/sgelq.f @@ -2,14 +2,14 @@ * Definition: * =========== * -* SUBROUTINE SGELQ( M, N, A, LDA, WORK1, LWORK1, WORK2, LWORK2, -* INFO) +* SUBROUTINE SGELQ( M, N, A, LDA, T, TSIZE, WORK, LWORK, +* INFO ) * * .. Scalar Arguments .. -* INTEGER INFO, LDA, M, N, LWORK1, LWORK2 +* INTEGER INFO, LDA, M, N, TSIZE, LWORK * .. * .. Array Arguments .. -* REAL A( LDA, * ), WORK1( * ), WORK2( * ) +* REAL A( LDA, * ), T( * ), WORK( * ) * .. * * @@ -17,11 +17,7 @@ * ============= *> *> \verbatim -*> -*> SGELQ computes an LQ factorization of an M-by-N matrix A, -*> using SLASWLQ when A is short and wide -*> (N sufficiently greater than M), and otherwise SGELQT: -*> A = L * Q . +*> SGELQ computes a LQ factorization of an M-by-N matrix A. *> \endverbatim * * Arguments: @@ -46,8 +42,8 @@ *> On exit, the elements on and below the diagonal of the array *> contain the M-by-min(M,N) lower trapezoidal matrix L *> (L is lower triangular if M <= N); -*> the elements above the diagonal are the rows of -*> blocked V representing Q (see Further Details). +*> the elements above the diagonal are used to store part of the +*> data structure to represent Q. *> \endverbatim *> *> \param[in] LDA @@ -56,47 +52,50 @@ *> The leading dimension of the array A. LDA >= max(1,M). *> \endverbatim *> -*> \param[out] WORK1 +*> \param[out] T *> \verbatim -*> WORK1 is REAL array, dimension (MAX(1,LWORK1)) -*> WORK1 contains part of the data structure used to store Q. -*> WORK1(1): algorithm type = 1, to indicate output from -*> SLASWLQ or SGELQT -*> WORK1(2): optimum size of WORK1 -*> WORK1(3): minimum size of WORK1 -*> WORK1(4): horizontal block size -*> WORK1(5): vertical block size -*> WORK1(6:LWORK1): data structure needed for Q, computed by -*> SLASWLQ or SGELQT +*> T is REAL array, dimension (MAX(5,TSIZE)) +*> On exit, if INFO = 0, T(1) returns optimal (or either minimal +*> or optimal, if query is assumed) TSIZE. See TSIZE for details. +*> Remaining T contains part of the data structure used to represent Q. +*> If one wants to apply or construct Q, then one needs to keep T +*> (in addition to A) and pass it to further subroutines. *> \endverbatim *> -*> \param[in] LWORK1 +*> \param[in] TSIZE *> \verbatim -*> LWORK1 is INTEGER -*> The dimension of the array WORK1. -*> If LWORK1 = -1, then a query is assumed. In this case the -*> routine calculates the optimal size of WORK1 and -*> returns this value in WORK1(2), and calculates the minimum -*> size of WORK1 and returns this value in WORK1(3). -*> No error message related to LWORK1 is issued by XERBLA when -*> LWORK1 = -1. +*> TSIZE is INTEGER +*> If TSIZE >= 5, the dimension of the array T. +*> If TSIZE = -1 or -2, then a workspace query is assumed. The routine +*> only calculates the sizes of the T and WORK arrays, returns these +*> values as the first entries of the T and WORK arrays, and no error +*> message related to T or WORK is issued by XERBLA. +*> If TSIZE = -1, the routine calculates optimal size of T for the +*> optimum performance and returns this value in T(1). +*> If TSIZE = -2, the routine calculates minimal size of T and +*> returns this value in T(1). *> \endverbatim *> -*> \param[out] WORK2 +*> \param[out] WORK *> \verbatim -*> (workspace) REAL array, dimension (MAX(1,LWORK2)) -*> +*> (workspace) REAL array, dimension (MAX(1,LWORK)) +*> On exit, if INFO = 0, WORK(1) contains optimal (or either minimal +*> or optimal, if query was assumed) LWORK. +*> See LWORK for details. *> \endverbatim -*> \param[in] LWORK2 +*> +*> \param[in] LWORK *> \verbatim -*> LWORK2 is INTEGER -*> The dimension of the array WORK2. -*> If LWORK2 = -1, then a query is assumed. In this case the -*> routine calculates the optimal size of WORK2 and -*> returns this value in WORK2(1), and calculates the minimum -*> size of WORK2 and returns this value in WORK2(2). -*> No error message related to LWORK2 is issued by XERBLA when -*> LWORK2 = -1. +*> LWORK is INTEGER +*> The dimension of the array WORK. +*> If LWORK = -1 or -2, then a workspace query is assumed. The routine +*> only calculates the sizes of the T and WORK arrays, returns these +*> values as the first entries of the T and WORK arrays, and no error +*> message related to T or WORK is issued by XERBLA. +*> If LWORK = -1, the routine calculates optimal size of WORK for the +*> optimal performance and returns this value in WORK(1). +*> If LWORK = -2, the routine calculates minimal size of WORK and +*> returns this value in WORK(1). *> \endverbatim *> *> \param[out] INFO @@ -114,107 +113,137 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \par Further Details: -* ===================== +*> \par Further Details +* ==================== *> *> \verbatim -*> Depending on the matrix dimensions M and N, and row and column -*> block sizes MB and NB returned by ILAENV, GELQ will use either -*> LASWLQ(if the matrix is short-and-wide) or GELQT to compute -*> the LQ decomposition. -*> The output of LASWLQ or GELQT representing Q is stored in A and in -*> array WORK1(6:LWORK1) for later use. -*> WORK1(2:5) contains the matrix dimensions M,N and block sizes MB, NB -*> which are needed to interpret A and WORK1(6:LWORK1) for later use. -*> WORK1(1)=1 indicates that the code needed to take WORK1(2:5) and -*> decide whether LASWLQ or GELQT was used is the same as used below in -*> GELQ. For a detailed description of A and WORK1(6:LWORK1), see -*> Further Details in LASWLQ or GELQT. +*> +*> The goal of the interface is to give maximum freedom to the developers for +*> creating any LQ factorization algorithm they wish. The triangular +*> (trapezoidal) L has to be stored in the lower part of A. The lower part of A +*> and the array T can be used to store any relevant information for applying or +*> constructing the Q factor. The WORK array can safely be discarded after exit. +*> +*> Caution: One should not expect the sizes of T and WORK to be the same from one +*> LAPACK implementation to the other, or even from one execution to the other. +*> A workspace query (for T and WORK) is needed at each execution. However, +*> for a given execution, the size of T and WORK are fixed and will not change +*> from one query to the next. +*> *> \endverbatim *> +*> \par Further Details particular to this LAPACK implementation: +* ============================================================== +*> +*> \verbatim +*> +*> These details are particular for this LAPACK implementation. Users should not +*> take them for granted. These details may change in the future, and are unlikely not +*> true for another LAPACK implementation. These details are relevant if one wants +*> to try to understand the code. They are not part of the interface. +*> +*> In this version, +*> +*> T(2): row block size (MB) +*> T(3): column block size (NB) +*> T(6:TSIZE): data structure needed for Q, computed by +*> SLASWLQ or SGELQT +*> +*> Depending on the matrix dimensions M and N, and row and column +*> block sizes MB and NB returned by ILAENV, SGELQ will use either +*> SLASWLQ (if the matrix is short-and-wide) or SGELQT to compute +*> the LQ factorization. +*> \endverbatim *> * ===================================================================== - SUBROUTINE SGELQ( M, N, A, LDA, WORK1, LWORK1, WORK2, LWORK2, - $ INFO) + SUBROUTINE SGELQ( M, N, A, LDA, T, TSIZE, WORK, LWORK, + $ INFO ) * -* -- LAPACK computational routine (version 3.5.0) -- +* -- LAPACK computational routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd. -- -* November 2013 +* November 2016 * * .. Scalar Arguments .. - INTEGER INFO, LDA, M, N, LWORK1, LWORK2 + INTEGER INFO, LDA, M, N, TSIZE, LWORK * .. * .. Array Arguments .. - REAL A( LDA, * ), WORK1( * ), WORK2( * ) + REAL A( LDA, * ), T( * ), WORK( * ) * .. * * ===================================================================== * * .. * .. Local Scalars .. - LOGICAL LQUERY, LMINWS - INTEGER MB, NB, I, II, KK, MINLW1, NBLCKS + LOGICAL LQUERY, LMINWS, MINT, MINW + INTEGER MB, NB, MINTSZ, NBLCKS * .. -* .. EXTERNAL FUNCTIONS .. +* .. External Functions .. LOGICAL LSAME EXTERNAL LSAME -* .. EXTERNAL SUBROUTINES .. +* .. +* .. External Subroutines .. EXTERNAL SGELQT, SLASWLQ, XERBLA -* .. INTRINSIC FUNCTIONS .. +* .. +* .. Intrinsic Functions .. INTRINSIC MAX, MIN, MOD * .. -* .. EXTERNAL FUNCTIONS .. +* .. External Functions .. INTEGER ILAENV EXTERNAL ILAENV * .. -* .. EXECUTABLE STATEMENTS .. +* .. Executable statements .. * -* TEST THE INPUT ARGUMENTS +* Test the input arguments * INFO = 0 * - LQUERY = ( LWORK1.EQ.-1 .OR. LWORK2.EQ.-1 ) + LQUERY = ( TSIZE.EQ.-1 .OR. TSIZE.EQ.-2 .OR. + $ LWORK.EQ.-1 .OR. LWORK.EQ.-2 ) +* + MINT = .FALSE. + MINW = .FALSE. + IF( TSIZE.EQ.-2 .OR. LWORK.EQ.-2 ) THEN + IF( TSIZE.NE.-1 ) MINT = .TRUE. + IF( LWORK.NE.-1 ) MINW = .TRUE. + END IF * * Determine the block size * - IF ( MIN(M,N).GT.0 ) THEN - MB = ILAENV( 1, 'SGELQ ', ' ', M, N, 1, -1) - NB = ILAENV( 1, 'SGELQ ', ' ', M, N, 2, -1) + IF( MIN( M, N ).GT.0 ) THEN + MB = ILAENV( 1, 'SGELQ ', ' ', M, N, 1, -1 ) + NB = ILAENV( 1, 'SGELQ ', ' ', M, N, 2, -1 ) ELSE MB = 1 NB = N END IF - IF( MB.GT.MIN(M,N).OR.MB.LT.1) MB = 1 - IF( NB.GT.N.OR.NB.LE.M) NB = N - MINLW1 = M + 5 - IF ((NB.GT.M).AND.(N.GT.M)) THEN - IF(MOD(N-M, NB-M).EQ.0) THEN - NBLCKS = (N-M)/(NB-M) + IF( MB.GT.MIN( M, N ) .OR. MB.LT.1 ) MB = 1 + IF( NB.GT.N .OR. NB.LE.M ) NB = N + MINTSZ = M + 5 + IF ( NB.GT.M .AND. N.GT.M ) THEN + IF( MOD( N - M, NB - M ).EQ.0 ) THEN + NBLCKS = ( N - M ) / ( NB - M ) ELSE - NBLCKS = (N-M)/(NB-M) + 1 + NBLCKS = ( N - M ) / ( NB - M ) + 1 END IF ELSE NBLCKS = 1 END IF * -* Determine if the workspace size satisfies minimum size +* Determine if the workspace size satisfies minimal size * LMINWS = .FALSE. - IF((LWORK1.LT.MAX(1,MB*M*NBLCKS+5) - $ .OR.(LWORK2.LT.MB*M)).AND.(LWORK2.GE.M).AND.(LWORK1.GE.M+5) - $ .AND.(.NOT.LQUERY)) THEN - IF (LWORK1.LT.MAX(1,MB*M*NBLCKS+5)) THEN - LMINWS = .TRUE. - MB = 1 - END IF - IF (LWORK1.LT.MAX(1,M*NBLCKS+5)) THEN - LMINWS = .TRUE. - NB = N + IF( ( TSIZE.LT.MAX( 1, MB*M*NBLCKS + 5 ) .OR. LWORK.LT.MB*M ) + $ .AND. ( LWORK.GE.M ) .AND. ( TSIZE.GE.MINTSZ ) + $ .AND. ( .NOT.LQUERY ) ) THEN + IF( TSIZE.LT.MAX( 1, MB*M*NBLCKS + 5 ) ) THEN + LMINWS = .TRUE. + MB = 1 + NB = N END IF - IF (LWORK2.LT.MB*M) THEN - LMINWS = .TRUE. - MB = 1 + IF( LWORK.LT.MB*M ) THEN + LMINWS = .TRUE. + MB = 1 END IF END IF * @@ -224,44 +253,51 @@ INFO = -2 ELSE IF( LDA.LT.MAX( 1, M ) ) THEN INFO = -4 - ELSE IF( LWORK1.LT.MAX( 1, MB*M*NBLCKS+5 ) - $ .AND.(.NOT.LQUERY).AND. (.NOT.LMINWS)) THEN + ELSE IF( TSIZE.LT.MAX( 1, MB*M*NBLCKS + 5 ) + $ .AND. ( .NOT.LQUERY ) .AND. ( .NOT.LMINWS ) ) THEN INFO = -6 - ELSE IF( (LWORK2.LT.MAX(1,M*MB)).AND.(.NOT.LQUERY) - $ .AND.(.NOT.LMINWS) ) THEN + ELSE IF( ( LWORK.LT.MAX( 1, M*MB ) ) .AND .( .NOT.LQUERY ) + $ .AND. ( .NOT.LMINWS ) ) THEN INFO = -8 END IF * - IF( INFO.EQ.0) THEN - WORK1(1) = 1 - WORK1(2) = MB*M*NBLCKS+5 - WORK1(3) = MINLW1 - WORK1(4) = MB - WORK1(5) = NB - WORK2(1) = MB * M - WORK2(2) = M + IF( INFO.EQ.0 ) THEN + IF( MINT ) THEN + T( 1 ) = MINTSZ + ELSE + T( 1 ) = MB*M*NBLCKS + 5 + END IF + T( 2 ) = MB + T( 3 ) = NB + IF( MINW ) THEN + WORK( 1 ) = MAX( 1, N ) + ELSE + WORK( 1 ) = MAX( 1, MB*M ) + END IF END IF IF( INFO.NE.0 ) THEN CALL XERBLA( 'SGELQ', -INFO ) RETURN - ELSE IF (LQUERY) THEN - RETURN + ELSE IF( LQUERY ) THEN + RETURN END IF * * Quick return if possible * - IF( MIN(M,N).EQ.0 ) THEN - RETURN + IF( MIN( M, N ).EQ.0 ) THEN + RETURN END IF * * The LQ Decomposition * - IF((N.LE.M).OR.(NB.LE.M).OR.(NB.GE.N)) THEN - CALL SGELQT( M, N, MB, A, LDA, WORK1(6), MB, WORK2, INFO) + IF( ( N.LE.M ) .OR. ( NB.LE.M ) .OR. ( NB.GE.N ) ) THEN + CALL SGELQT( M, N, MB, A, LDA, T( 6 ), MB, WORK, INFO ) ELSE - CALL SLASWLQ( M, N, MB, NB, A, LDA, WORK1(6), MB, WORK2, - $ LWORK2, INFO) + CALL SLASWLQ( M, N, MB, NB, A, LDA, T( 6 ), MB, WORK, + $ LWORK, INFO ) END IF +* + WORK( 1 ) = MAX( 1, MB*M ) RETURN * * End of SGELQ diff --git a/SRC/sgemlq.f b/SRC/sgemlq.f index 14a37a4d..42306ae4 100644 --- a/SRC/sgemlq.f +++ b/SRC/sgemlq.f @@ -2,45 +2,51 @@ * Definition: * =========== * -* SUBROUTINE SGEMLQ( SIDE, TRANS, M, N, K, A, LDA, WORK1, -* $ LWORK1, C, LDC, WORK2, LWORK2, INFO ) +* SUBROUTINE SGEMLQ( SIDE, TRANS, M, N, K, A, LDA, T, +* $ TSIZE, C, LDC, WORK, LWORK, INFO ) * * * .. Scalar Arguments .. -* CHARACTER SIDE, TRANS -* INTEGER INFO, LDA, M, N, K, MB, NB, LWORK1, LWORK2, LDC +* CHARACTER SIDE, TRANS +* INTEGER INFO, LDA, M, N, K, LDT, TSIZE, LWORK, LDC * .. * .. Array Arguments .. -* REAL A( LDA, * ), WORK1( * ), C(LDC, * ), -* $ WORK2( * ) +* REAL A( LDA, * ), T( * ), C(LDC, * ), WORK( * ) +* .. +* *> \par Purpose: * ============= *> *> \verbatim *> -*> DGEMLQ overwrites the general real M-by-N matrix C with -*> +*> SGEMLQ overwrites the general real M-by-N matrix C with *> *> SIDE = 'L' SIDE = 'R' *> TRANS = 'N': Q * C C * Q *> TRANS = 'T': Q**T * C C * Q**T *> where Q is a real orthogonal matrix defined as the product *> of blocked elementary reflectors computed by short wide LQ -*> factorization (DGELQ) +*> factorization (SGELQ) +*> *> \endverbatim * * Arguments: * ========== * *> \param[in] SIDE +*> \verbatim *> SIDE is CHARACTER*1 *> = 'L': apply Q or Q**T from the Left; *> = 'R': apply Q or Q**T from the Right. +*> \endverbatim *> *> \param[in] TRANS +*> \verbatim *> TRANS is CHARACTER*1 *> = 'N': No transpose, apply Q; *> = 'T': Transpose, apply Q**T. +*> \endverbatim +*> *> \param[in] M *> \verbatim *> M is INTEGER @@ -50,7 +56,7 @@ *> \param[in] N *> \verbatim *> N is INTEGER -*> The number of columns of the matrix C. N >= M. +*> The number of columns of the matrix C. N >= 0. *> \endverbatim *> *> \param[in] K @@ -58,61 +64,64 @@ *> K is INTEGER *> The number of elementary reflectors whose product defines *> the matrix Q. -*> M >= K >= 0; -*> +*> If SIDE = 'L', M >= K >= 0; +*> if SIDE = 'R', N >= K >= 0. *> \endverbatim *> -*> \param[in,out] A +*> \param[in] A *> \verbatim -*> A is REAL array, dimension (LDA,K) -*> The i-th row must contain the vector which defines the blocked -*> elementary reflector H(i), for i = 1,2,...,k, as returned by -*> DLASWLQ in the first k rows of its array argument A. +*> A is REAL array, dimension +*> (LDA,M) if SIDE = 'L', +*> (LDA,N) if SIDE = 'R' +*> Part of the data structure to represent Q as returned by DGELQ. *> \endverbatim *> *> \param[in] LDA *> \verbatim *> LDA is INTEGER -*> The leading dimension of the array A. -*> If SIDE = 'L', LDA >= max(1,M); -*> if SIDE = 'R', LDA >= max(1,N). +*> The leading dimension of the array A. LDA >= max(1,K). *> \endverbatim *> -*> \param[in] WORK1 +*> \param[in] T *> \verbatim -*> WORK1 is REAL array, dimension (MAX(1,LWORK1)) is -*> returned by GEQR. +*> T is REAL array, dimension (MAX(5,TSIZE)). +*> Part of the data structure to represent Q as returned by SGELQ. *> \endverbatim *> -*> \param[in] LWORK1 +*> \param[in] TSIZE *> \verbatim -*> LWORK1 is INTEGER -*> The dimension of the array WORK1. +*> TSIZE is INTEGER +*> The dimension of the array T. TSIZE >= 5. *> \endverbatim *> *> \param[in,out] C +*> \verbatim *> C is REAL array, dimension (LDC,N) *> On entry, the M-by-N matrix C. *> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +*> \endverbatim +*> *> \param[in] LDC +*> \verbatim *> LDC is INTEGER *> The leading dimension of the array C. LDC >= max(1,M). +*> \endverbatim *> -*> \param[out] WORK2 +*> \param[out] WORK *> \verbatim -*> (workspace) REAL array, dimension (MAX(1,LWORK2)) -*> +*> (workspace) REAL array, dimension (MAX(1,LWORK)) *> \endverbatim -*> \param[in] LWORK2 -*> \verbatim -*> LWORK2 is INTEGER -*> The dimension of the array WORK2. -*> If LWORK2 = -1, then a workspace query is assumed; the routine -*> only calculates the optimal size of the WORK2 array, returns -*> this value as the third entry of the WORK2 array (WORK2(1)), -*> and no error message related to LWORK2 is issued by XERBLA. *> +*> \param[in] LWORK +*> \verbatim +*> LWORK is INTEGER +*> The dimension of the array WORK. +*> If LWORK = -1, then a workspace query is assumed. The routine +*> only calculates the size of the WORK array, returns this +*> value as WORK(1), and no error message related to WORK +*> is issued by XERBLA. *> \endverbatim +*> *> \param[out] INFO *> \verbatim *> INFO is INTEGER @@ -128,53 +137,63 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \par Further Details: -* ===================== +*> \par Further Details +* ==================== *> *> \verbatim +*> +*> These details are particular for this LAPACK implementation. Users should not +*> take them for granted. These details may change in the future, and are unlikely not +*> true for another LAPACK implementation. These details are relevant if one wants +*> to try to understand the code. They are not part of the interface. +*> +*> In this version, +*> +*> T(2): row block size (MB) +*> T(3): column block size (NB) +*> T(6:TSIZE): data structure needed for Q, computed by +*> SLASWLQ or SGELQT +*> *> Depending on the matrix dimensions M and N, and row and column -*> block sizes MB and NB returned by ILAENV, GELQ will use either -*> LASWLQ(if the matrix is short-and-wide) or GELQT to compute -*> the LQ decomposition. -*> The output of LASWLQ or GELQT representing Q is stored in A and in -*> array WORK1(6:LWORK1) for later use. -*> WORK1(2:5) contains the matrix dimensions M,N and block sizes MB, NB -*> which are needed to interpret A and WORK1(6:LWORK1) for later use. -*> WORK1(1)=1 indicates that the code needed to take WORK1(2:5) and -*> decide whether LASWLQ or GELQT was used is the same as used below in -*> GELQ. For a detailed description of A and WORK1(6:LWORK1), see -*> Further Details in LASWLQ or GELQT. +*> block sizes MB and NB returned by ILAENV, SGELQ will use either +*> SLASWLQ (if the matrix is wide-and-short) or SGELQT to compute +*> the LQ factorization. +*> This version of SGEMLQ will use either SLAMSWLQ or SGEMLQT to +*> multiply matrix Q by another matrix. +*> Further Details in SLAMSWLQ or SGEMLQT. *> \endverbatim *> * ===================================================================== - SUBROUTINE SGEMLQ( SIDE, TRANS, M, N, K, A, LDA, WORK1, LWORK1, - $ C, LDC, WORK2, LWORK2, INFO ) + SUBROUTINE SGEMLQ( SIDE, TRANS, M, N, K, A, LDA, T, TSIZE, + $ C, LDC, WORK, LWORK, INFO ) * -* -- LAPACK computational routine (version 3.5.0) -- +* -- LAPACK computational routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- -* November 2013 +* November 2016 * * .. Scalar Arguments .. - CHARACTER SIDE, TRANS - INTEGER INFO, LDA, M, N, K, LWORK1, LWORK2, LDC + CHARACTER SIDE, TRANS + INTEGER INFO, LDA, M, N, K, TSIZE, LWORK, LDC * .. * .. Array Arguments .. - REAL A( LDA, * ), C( LDC, * ), WORK1( * ), WORK2( * ) + REAL A( LDA, * ), T( * ), C( LDC, * ), WORK( * ) * .. * * ===================================================================== * * .. * .. Local Scalars .. - LOGICAL LEFT, RIGHT, TRAN, NOTRAN, LQUERY - INTEGER I, II, KK, MB, NB, LW, NBLCKS, MN + LOGICAL LEFT, RIGHT, TRAN, NOTRAN, LQUERY + INTEGER MB, NB, LW, NBLCKS, MN * .. * .. External Functions .. LOGICAL LSAME EXTERNAL LSAME +* .. * .. External Subroutines .. - EXTERNAL STPMLQT, SGEMLQT, XERBLA + EXTERNAL SLAMSWLQ, SGEMLQT, XERBLA +* .. * .. Intrinsic Functions .. INTRINSIC INT, MAX, MIN, MOD * .. @@ -182,26 +201,27 @@ * * Test the input arguments * - LQUERY = LWORK2.LT.0 + LQUERY = LWORK.EQ.-1 NOTRAN = LSAME( TRANS, 'N' ) TRAN = LSAME( TRANS, 'T' ) LEFT = LSAME( SIDE, 'L' ) RIGHT = LSAME( SIDE, 'R' ) * - MB = INT(WORK1(4)) - NB = INT(WORK1(5)) - IF (LEFT) THEN + MB = INT( T( 2 ) ) + NB = INT( T( 3 ) ) + IF( LEFT ) THEN LW = N * MB MN = M ELSE LW = M * MB MN = N END IF - IF ((NB.GT.K).AND.(MN.GT.K)) THEN - IF(MOD(MN-K, NB-K).EQ.0) THEN - NBLCKS = (MN-K)/(NB-K) +* + IF( ( NB.GT.K ) .AND. ( MN.GT.K ) ) THEN + IF( MOD( MN - K, NB - K ) .EQ. 0 ) THEN + NBLCKS = ( MN - K ) / ( NB - K ) ELSE - NBLCKS = (MN-K)/(NB-K) + 1 + NBLCKS = ( MN - K ) / ( NB - K ) + 1 END IF ELSE NBLCKS = 1 @@ -209,51 +229,53 @@ * INFO = 0 IF( .NOT.LEFT .AND. .NOT.RIGHT ) THEN - INFO = -1 + INFO = -1 ELSE IF( .NOT.TRAN .AND. .NOT.NOTRAN ) THEN - INFO = -2 + INFO = -2 ELSE IF( M.LT.0 ) THEN INFO = -3 - ELSE IF( N.LT.0) THEN + ELSE IF( N.LT.0 ) THEN INFO = -4 - ELSE IF( K.LT.0 ) THEN + ELSE IF( K.LT.0 .OR. K.GT.MN ) THEN INFO = -5 ELSE IF( LDA.LT.MAX( 1, K ) ) THEN INFO = -7 - ELSE IF( LWORK1.LT.MAX( 1, MB*K*NBLCKS+5 )) THEN + ELSE IF( TSIZE.LT.5 ) THEN INFO = -9 ELSE IF( LDC.LT.MAX( 1, M ) ) THEN - INFO = -11 - ELSE IF(( LWORK2.LT.MAX(1,LW)).AND.(.NOT.LQUERY)) THEN + INFO = -11 + ELSE IF( ( LWORK.LT.MAX( 1, LW ) ) .AND. ( .NOT.LQUERY ) ) THEN INFO = -13 END IF * - IF( INFO.EQ.0) THEN - WORK2(1) = LW + IF( INFO.EQ.0 ) THEN + WORK( 1 ) = REAL( LW ) END IF +* IF( INFO.NE.0 ) THEN CALL XERBLA( 'SGEMLQ', -INFO ) RETURN - ELSE IF (LQUERY) THEN + ELSE IF( LQUERY ) THEN RETURN END IF * * Quick return if possible * - IF( MIN(M,N,K).EQ.0 ) THEN + IF( MIN( M, N, K ).EQ.0 ) THEN RETURN END IF * - IF((LEFT.AND.M.LE.K).OR.(RIGHT.AND.N.LE.K).OR.(NB.LE.K).OR. - $ (NB.GE.MAX(M,N,K))) THEN + IF( ( LEFT .AND. M.LE.K ) .OR. ( RIGHT .AND. N.LE.K ) + $ .OR. ( NB.LE.K ) .OR. ( NB.GE.MAX( M, N, K ) ) ) THEN CALL SGEMLQT( SIDE, TRANS, M, N, K, MB, A, LDA, - $ WORK1(6), MB, C, LDC, WORK2, INFO) + $ T( 6 ), MB, C, LDC, WORK, INFO ) ELSE - CALL SLAMSWLQ( SIDE, TRANS, M, N, K, MB, NB, A, LDA, WORK1(6), - $ MB, C, LDC, WORK2, LWORK2, INFO ) + CALL SLAMSWLQ( SIDE, TRANS, M, N, K, MB, NB, A, LDA, T( 6 ), + $ MB, C, LDC, WORK, LWORK, INFO ) END IF * - WORK2(1) = LW + WORK( 1 ) = REAL( LW ) +* RETURN * * End of SGEMLQ diff --git a/SRC/sgemqr.f b/SRC/sgemqr.f index cda7990c..6bf3a1bd 100644 --- a/SRC/sgemqr.f +++ b/SRC/sgemqr.f @@ -2,45 +2,52 @@ * Definition: * =========== * -* SUBROUTINE SGEMQR( SIDE, TRANS, M, N, K, A, LDA, WORK1, -* $ LWORK1, C, LDC, WORK2, LWORK2, INFO ) +* SUBROUTINE SGEMQR( SIDE, TRANS, M, N, K, A, LDA, T, +* $ TSIZE, C, LDC, WORK, LWORK, INFO ) * * * .. Scalar Arguments .. -* CHARACTER SIDE, TRANS -* INTEGER INFO, LDA, M, N, K, LDT, LWORK1, LWORK2, LDC +* CHARACTER SIDE, TRANS +* INTEGER INFO, LDA, M, N, K, LDT, TSIZE, LWORK, LDC * .. * .. Array Arguments .. -* REAL A( LDA, * ), WORK1( * ), C(LDC, * ), -* $ WORK2( * ) +* REAL A( LDA, * ), T( * ), C( LDC, * ), WORK( * ) +* .. +* *> \par Purpose: * ============= *> *> \verbatim *> -*> SGEMQR overwrites the general real M-by-N matrix C with -*> +*> SGEMQR overwrites the general real M-by-N matrix C with *> *> SIDE = 'L' SIDE = 'R' -*> TRANS = 'N': Q * C C * Q -*> TRANS = 'T': Q**T * C C * Q**T -*> where Q is a real orthogonal matrix defined as the product -*> of blocked elementary reflectors computed by tall skinny -*> QR factorization (DGEQR) +*> TRANS = 'N': Q * C C * Q +*> TRANS = 'T': Q**T * C C * Q**T +*> +*> where Q is a real orthogonal matrix defined as the product +*> of blocked elementary reflectors computed by tall skinny +*> QR factorization (SGEQR) +*> *> \endverbatim * * Arguments: * ========== * *> \param[in] SIDE +*> \verbatim *> SIDE is CHARACTER*1 *> = 'L': apply Q or Q**T from the Left; *> = 'R': apply Q or Q**T from the Right. +*> \endverbatim *> *> \param[in] TRANS +*> \verbatim *> TRANS is CHARACTER*1 *> = 'N': No transpose, apply Q; *> = 'T': Transpose, apply Q**T. +*> \endverbatim +*> *> \param[in] M *> \verbatim *> M is INTEGER @@ -50,7 +57,7 @@ *> \param[in] N *> \verbatim *> N is INTEGER -*> The number of columns of the matrix C. M >= N >= 0. +*> The number of columns of the matrix C. N >= 0. *> \endverbatim *> *> \param[in] K @@ -58,17 +65,14 @@ *> K is INTEGER *> The number of elementary reflectors whose product defines *> the matrix Q. -*> N >= K >= 0; -*> +*> If SIDE = 'L', M >= K >= 0; +*> if SIDE = 'R', N >= K >= 0. *> \endverbatim *> -*> \param[in,out] A +*> \param[in] A *> \verbatim *> A is REAL array, dimension (LDA,K) -*> The i-th column must contain the vector which defines the -*> blockedelementary reflector H(i), for i = 1,2,...,k, as -*> returned by DGETSQR in the first k columns of -*> its array argument A. +*> Part of the data structure to represent Q as returned by SGEQR. *> \endverbatim *> *> \param[in] LDA @@ -79,42 +83,46 @@ *> if SIDE = 'R', LDA >= max(1,N). *> \endverbatim *> -*> \param[in] WORK1 +*> \param[in] T *> \verbatim -*> WORK1 is REAL array, dimension (MAX(1,LWORK1)) as -*> it is returned by GEQR. +*> T is REAL array, dimension (MAX(5,TSIZE)). +*> Part of the data structure to represent Q as returned by SGEQR. *> \endverbatim *> -*> \param[in] LWORK1 +*> \param[in] TSIZE *> \verbatim -*> LWORK1 is INTEGER -*> The dimension of the array WORK1. +*> TSIZE is INTEGER +*> The dimension of the array T. TSIZE >= 5. *> \endverbatim *> *> \param[in,out] C +*> \verbatim *> C is REAL array, dimension (LDC,N) *> On entry, the M-by-N matrix C. *> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +*> \endverbatim *> *> \param[in] LDC +*> \verbatim *> LDC is INTEGER *> The leading dimension of the array C. LDC >= max(1,M). +*> \endverbatim *> -*> \param[out] WORK2 +*> \param[out] WORK *> \verbatim -*> (workspace) REAL array, dimension (MAX(1,LWORK2)) -*> +*> (workspace) REAL array, dimension (MAX(1,LWORK)) *> \endverbatim -*> \param[in] LWORK2 -*> \verbatim -*> LWORK2 is INTEGER -*> The dimension of the array WORK2. -*> If LWORK2 = -1, then a workspace query is assumed; the routine -*> only calculates the optimal size of the WORK2 array, returns -*> this value as the third entry of the WORK2 array (WORK2(1)), -*> and no error message related to LWORK2 is issued by XERBLA. *> +*> \param[in] LWORK +*> \verbatim +*> LWORK is INTEGER +*> The dimension of the array WORK. +*> If LWORK = -1, then a workspace query is assumed. The routine +*> only calculates the size of the WORK array, returns this +*> value as WORK(1), and no error message related to WORK +*> is issued by XERBLA. *> \endverbatim +*> *> \param[out] INFO *> \verbatim *> INFO is INTEGER @@ -130,54 +138,64 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \par Further Details: -* ===================== +*> \par Further Details +* ==================== *> *> \verbatim +*> +*> These details are particular for this LAPACK implementation. Users should not +*> take them for granted. These details may change in the future, and are unlikely not +*> true for another LAPACK implementation. These details are relevant if one wants +*> to try to understand the code. They are not part of the interface. +*> +*> In this version, +*> +*> T(2): row block size (MB) +*> T(3): column block size (NB) +*> T(6:TSIZE): data structure needed for Q, computed by +*> SLATSQR or SGEQRT +*> *> Depending on the matrix dimensions M and N, and row and column -*> block sizes MB and NB returned by ILAENV, GEQR will use either -*> LATSQR (if the matrix is tall-and-skinny) or GEQRT to compute -*> the QR decomposition. -*> The output of LATSQR or GEQRT representing Q is stored in A and in -*> array WORK1(6:LWORK1) for later use. -*> WORK1(2:5) contains the matrix dimensions M,N and block sizes MB,NB -*> which are needed to interpret A and WORK1(6:LWORK1) for later use. -*> WORK1(1)=1 indicates that the code needed to take WORK1(2:5) and -*> decide whether LATSQR or GEQRT was used is the same as used below in -*> GEQR. For a detailed description of A and WORK1(6:LWORK1), see -*> Further Details in LATSQR or GEQRT. +*> block sizes MB and NB returned by ILAENV, SGEQR will use either +*> SLATSQR (if the matrix is tall-and-skinny) or SGEQRT to compute +*> the QR factorization. +*> This version of SGEMQR will use either SLAMTSQR or SGEMQRT to +*> multiply matrix Q by another matrix. +*> Further Details in SLAMTSQR or SGEMQRT. +*> *> \endverbatim *> * ===================================================================== - SUBROUTINE SGEMQR( SIDE, TRANS, M, N, K, A, LDA, WORK1, LWORK1, - $ C, LDC, WORK2, LWORK2, INFO ) + SUBROUTINE SGEMQR( SIDE, TRANS, M, N, K, A, LDA, T, TSIZE, + $ C, LDC, WORK, LWORK, INFO ) * -* -- LAPACK computational routine (version 3.5.0) -- +* -- LAPACK computational routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- -* November 2013 +* November 2016 * * .. Scalar Arguments .. - CHARACTER SIDE, TRANS - INTEGER INFO, LDA, M, N, K, LWORK1, LWORK2, LDC + CHARACTER SIDE, TRANS + INTEGER INFO, LDA, M, N, K, TSIZE, LWORK, LDC * .. * .. Array Arguments .. - REAL A( LDA, * ), WORK1( * ), C(LDC, * ), - $ WORK2( * ) + REAL A( LDA, * ), T( * ), C( LDC, * ), WORK( * ) * .. * * ===================================================================== * * .. * .. Local Scalars .. - LOGICAL LEFT, RIGHT, TRAN, NOTRAN, LQUERY - INTEGER MB, NB, I, II, KK, LW, NBLCKS, MN + LOGICAL LEFT, RIGHT, TRAN, NOTRAN, LQUERY + INTEGER MB, NB, LW, NBLCKS, MN * .. * .. External Functions .. LOGICAL LSAME EXTERNAL LSAME +* .. * .. External Subroutines .. - EXTERNAL SGEMQRT, STPMQRT, XERBLA + EXTERNAL SGEMQRT, SLAMTSQR, XERBLA +* .. * .. Intrinsic Functions .. INTRINSIC INT, MAX, MIN, MOD * .. @@ -185,82 +203,80 @@ * * Test the input arguments * - LQUERY = LWORK2.LT.0 + LQUERY = LWORK.EQ.-1 NOTRAN = LSAME( TRANS, 'N' ) TRAN = LSAME( TRANS, 'T' ) LEFT = LSAME( SIDE, 'L' ) RIGHT = LSAME( SIDE, 'R' ) * - MB = INT(WORK1(4)) - NB = INT(WORK1(5)) - IF(LEFT) THEN + MB = INT( T( 2 ) ) + NB = INT( T( 3 ) ) + IF( LEFT ) THEN LW = N * NB MN = M - ELSE IF(RIGHT) THEN + ELSE LW = MB * NB MN = N END IF * - IF ((MB.GT.K).AND.(MN.GT.K)) THEN - IF(MOD(MN-K, MB-K).EQ.0) THEN - NBLCKS = (MN-K)/(MB-K) - ELSE - NBLCKS = (MN-K)/(MB-K) + 1 - END IF + IF( ( MB.GT.K ) .AND. ( MN.GT.K ) ) THEN + IF( MOD( MN - K, MB - K ).EQ.0 ) THEN + NBLCKS = ( MN - K ) / ( MB - K ) + ELSE + NBLCKS = ( MN - K ) / ( MB - K ) + 1 + END IF ELSE NBLCKS = 1 END IF * INFO = 0 IF( .NOT.LEFT .AND. .NOT.RIGHT ) THEN - INFO = -1 + INFO = -1 ELSE IF( .NOT.TRAN .AND. .NOT.NOTRAN ) THEN - INFO = -2 + INFO = -2 ELSE IF( M.LT.0 ) THEN INFO = -3 ELSE IF( N.LT.0 ) THEN INFO = -4 - ELSE IF( K.LT.0 ) THEN + ELSE IF( K.LT.0 .OR. K.GT.MN ) THEN INFO = -5 - ELSE IF( LDA.LT.MAX( 1, K ) ) THEN + ELSE IF( LDA.LT.MAX( 1, MN ) ) THEN INFO = -7 - ELSE IF( LWORK1.LT.MAX( 1, NB*K*NBLCKS+5 )) THEN + ELSE IF( TSIZE.LT.5 ) THEN INFO = -9 - ELSE IF( LDC.LT.MAX( 1, M ).AND.MIN(M,N,K).NE.0 ) THEN - INFO = -11 - ELSE IF(( LWORK2.LT.MAX(1,LW)).AND.(.NOT.LQUERY)) THEN + ELSE IF( LDC.LT.MAX( 1, M ) ) THEN + INFO = -11 + ELSE IF( ( LWORK.LT.MAX( 1, LW ) ) .AND. ( .NOT.LQUERY ) ) THEN INFO = -13 END IF * -* Determine the block size if it is tall skinny or short and wide -* - IF( INFO.EQ.0) THEN - WORK2(1) = LW + IF( INFO.EQ.0 ) THEN + WORK( 1 ) = LW END IF * IF( INFO.NE.0 ) THEN CALL XERBLA( 'SGEMQR', -INFO ) RETURN - ELSE IF (LQUERY) THEN - RETURN + ELSE IF( LQUERY ) THEN + RETURN END IF * * Quick return if possible * - IF( MIN(M,N,K).EQ.0 ) THEN + IF( MIN( M, N, K ).EQ.0 ) THEN RETURN END IF * - IF((LEFT.AND.M.LE.K).OR.(RIGHT.AND.N.LE.K).OR.(MB.LE.K).OR. - $ (MB.GE.MAX(M,N,K))) THEN - CALL SGEMQRT( SIDE, TRANS, M, N, K, NB, A, LDA, - $ WORK1(6), NB, C, LDC, WORK2, INFO) + IF( ( LEFT .AND. M.LE.K ) .OR. ( RIGHT .AND. N.LE.K ) + $ .OR. ( MB.LE.K ) .OR. ( MB.GE.MAX( M, N, K ) ) ) THEN + CALL SGEMQRT( SIDE, TRANS, M, N, K, NB, A, LDA, T( 6 ), + $ NB, C, LDC, WORK, INFO ) ELSE - CALL SLAMTSQR( SIDE, TRANS, M, N, K, MB, NB, A, LDA, WORK1(6), - $ NB, C, LDC, WORK2, LWORK2, INFO ) + CALL SLAMTSQR( SIDE, TRANS, M, N, K, MB, NB, A, LDA, T( 6 ), + $ NB, C, LDC, WORK, LWORK, INFO ) END IF * - WORK2(1) = LW + WORK( 1 ) = LW * RETURN * diff --git a/SRC/sgeqr.f b/SRC/sgeqr.f index 41e04622..3f561a45 100644 --- a/SRC/sgeqr.f +++ b/SRC/sgeqr.f @@ -2,14 +2,14 @@ * Definition: * =========== * -* SUBROUTINE SGEQR( M, N, A, LDA, WORK1, LWORK1, WORK2, LWORK2, -* INFO) +* SUBROUTINE SGEQR( M, N, A, LDA, T, TSIZE, WORK, LWORK, +* INFO ) * * .. Scalar Arguments .. -* INTEGER INFO, LDA, M, N, LWORK1, LWORK2 +* INTEGER INFO, LDA, M, N, TSIZE, LWORK * .. * .. Array Arguments .. -* REAL A( LDA, * ), WORK1( * ), WORK2( * ) +* REAL A( LDA, * ), T( * ), WORK( * ) * .. * * @@ -17,11 +17,7 @@ * ============= *> *> \verbatim -*> -*> SGEQR computes a QR factorization of an M-by-N matrix A, -*> using SLATSQR when A is tall and skinny -*> (M sufficiently greater than N), and otherwise SGEQRT: -*> A = Q * R . +*> SGEQR computes a QR factorization of an M-by-N matrix A. *> \endverbatim * * Arguments: @@ -46,7 +42,8 @@ *> On exit, the elements on and above the diagonal of the array *> contain the min(M,N)-by-N upper trapezoidal matrix R *> (R is upper triangular if M >= N); -*> the elements below the diagonal represent Q (see Further Details). +*> the elements below the diagonal are used to store part of the +*> data structure to represent Q. *> \endverbatim *> *> \param[in] LDA @@ -55,47 +52,50 @@ *> The leading dimension of the array A. LDA >= max(1,M). *> \endverbatim *> -*> \param[out] WORK1 +*> \param[out] T *> \verbatim -*> WORK1 is REAL array, dimension (MAX(1,LWORK1)) -*> WORK1 contains part of the data structure used to store Q. -*> WORK1(1): algorithm type = 1, to indicate output from -*> DLATSQR or DGEQRT -*> WORK1(2): optimum size of WORK1 -*> WORK1(3): minimum size of WORK1 -*> WORK1(4): row block size -*> WORK1(5): column block size -*> WORK1(6:LWORK1): data structure needed for Q, computed by -*> SLATSQR or SGEQRT +*> T is REAL array, dimension (MAX(5,TSIZE)) +*> On exit, if INFO = 0, T(1) returns optimal (or either minimal +*> or optimal, if query is assumed) TSIZE. See TSIZE for details. +*> Remaining T contains part of the data structure used to represent Q. +*> If one wants to apply or construct Q, then one needs to keep T +*> (in addition to A) and pass it to further subroutines. *> \endverbatim *> -*> \param[in] LWORK1 +*> \param[in] TSIZE *> \verbatim -*> LWORK1 is INTEGER -*> The dimension of the array WORK1. -*> If LWORK1 = -1, then a query is assumed. In this case the -*> routine calculates the optimal size of WORK1 and -*> returns this value in WORK1(2), and calculates the minimum -*> size of WORK1 and returns this value in WORK1(3). -*> No error message related to LWORK1 is issued by XERBLA when -*> LWORK1 = -1. +*> TSIZE is INTEGER +*> If TSIZE >= 5, the dimension of the array T. +*> If TSIZE = -1 or -2, then a workspace query is assumed. The routine +*> only calculates the sizes of the T and WORK arrays, returns these +*> values as the first entries of the T and WORK arrays, and no error +*> message related to T or WORK is issued by XERBLA. +*> If TSIZE = -1, the routine calculates optimal size of T for the +*> optimum performance and returns this value in T(1). +*> If TSIZE = -2, the routine calculates minimal size of T and +*> returns this value in T(1). *> \endverbatim *> -*> \param[out] WORK2 +*> \param[out] WORK *> \verbatim -*> (workspace) REAL array, dimension (MAX(1,LWORK2)) +*> (workspace) REAL array, dimension (MAX(1,LWORK)) +*> On exit, if INFO = 0, WORK(1) contains optimal (or either minimal +*> or optimal, if query was assumed) LWORK. +*> See LWORK for details. *> \endverbatim *> -*> \param[in] LWORK2 +*> \param[in] LWORK *> \verbatim -*> LWORK2 is INTEGER -*> The dimension of the array WORK2. -*> If LWORK2 = -1, then a query is assumed. In this case the -*> routine calculates the optimal size of WORK2 and -*> returns this value in WORK2(1), and calculates the minimum -*> size of WORK2 and returns this value in WORK2(2). -*> No error message related to LWORK2 is issued by XERBLA when -*> LWORK2 = -1. +*> LWORK is INTEGER +*> The dimension of the array WORK. +*> If LWORK = -1 or -2, then a workspace query is assumed. The routine +*> only calculates the sizes of the T and WORK arrays, returns these +*> values as the first entries of the T and WORK arrays, and no error +*> message related to T or WORK is issued by XERBLA. +*> If LWORK = -1, the routine calculates optimal size of WORK for the +*> optimal performance and returns this value in WORK(1). +*> If LWORK = -2, the routine calculates minimal size of WORK and +*> returns this value in WORK(1). *> \endverbatim *> *> \param[out] INFO @@ -113,106 +113,138 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \par Further Details: -* ===================== +*> \par Further Details +* ==================== *> *> \verbatim +*> +*> The goal of the interface is to give maximum freedom to the developers for +*> creating any QR factorization algorithm they wish. The triangular +*> (trapezoidal) R has to be stored in the upper part of A. The lower part of A +*> and the array T can be used to store any relevant information for applying or +*> constructing the Q factor. The WORK array can safely be discarded after exit. +*> +*> Caution: One should not expect the sizes of T and WORK to be the same from one +*> LAPACK implementation to the other, or even from one execution to the other. +*> A workspace query (for T and WORK) is needed at each execution. However, +*> for a given execution, the size of T and WORK are fixed and will not change +*> from one query to the next. +*> +*> \endverbatim +*> +*> \par Further Details particular to this LAPACK implementation: +* ============================================================== +*> +*> \verbatim +*> +*> These details are particular for this LAPACK implementation. Users should not +*> take them for granted. These details may change in the future, and are unlikely not +*> true for another LAPACK implementation. These details are relevant if one wants +*> to try to understand the code. They are not part of the interface. +*> +*> In this version, +*> +*> T(2): row block size (MB) +*> T(3): column block size (NB) +*> T(6:TSIZE): data structure needed for Q, computed by +*> SLATSQR or SGEQRT +*> *> Depending on the matrix dimensions M and N, and row and column -*> block sizes MB and NB returned by ILAENV, GEQR will use either -*> LATSQR (if the matrix is tall-and-skinny) or GEQRT to compute -*> the QR decomposition. -*> The output of LATSQR or GEQRT representing Q is stored in A and in -*> array WORK1(6:LWORK1) for later use. -*> WORK1(2:5) contains the matrix dimensions M,N and block sizes MB,NB -*> which are needed to interpret A and WORK1(6:LWORK1) for later use. -*> WORK1(1)=1 indicates that the code needed to take WORK1(2:5) and -*> decide whether LATSQR or GEQRT was used is the same as used below in -*> GEQR. For a detailed description of A and WORK1(6:LWORK1), see -*> Further Details in LATSQR or GEQRT. +*> block sizes MB and NB returned by ILAENV, SGEQR will use either +*> SLATSQR (if the matrix is tall-and-skinny) or SGEQRT to compute +*> the QR factorization. +*> *> \endverbatim *> * ===================================================================== - SUBROUTINE SGEQR( M, N, A, LDA, WORK1, LWORK1, WORK2, LWORK2, - $ INFO) + SUBROUTINE SGEQR( M, N, A, LDA, T, TSIZE, WORK, LWORK, + $ INFO ) * -* -- LAPACK computational routine (version 3.5.0) -- +* -- LAPACK computational routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd. -- -* November 2013 +* November 2016 * * .. Scalar Arguments .. - INTEGER INFO, LDA, M, N, LWORK1, LWORK2 + INTEGER INFO, LDA, M, N, TSIZE, LWORK * .. * .. Array Arguments .. - REAL A( LDA, * ), WORK1( * ), WORK2( * ) + REAL A( LDA, * ), T( * ), WORK( * ) * .. * * ===================================================================== * * .. * .. Local Scalars .. - LOGICAL LQUERY, LMINWS - INTEGER MB, NB, I, II, KK, MINLW1, NBLCKS + LOGICAL LQUERY, LMINWS, MINT, MINW + INTEGER MB, NB, MINTSZ, NBLCKS * .. -* .. EXTERNAL FUNCTIONS .. +* .. External Functions .. LOGICAL LSAME EXTERNAL LSAME -* .. EXTERNAL SUBROUTINES .. +* .. +* .. External Subroutines .. EXTERNAL SLATSQR, SGEQRT, XERBLA -* .. INTRINSIC FUNCTIONS .. +* .. +* .. Intrinsic Functions .. INTRINSIC MAX, MIN, MOD * .. -* .. EXTERNAL FUNCTIONS .. +* .. External Functions .. INTEGER ILAENV EXTERNAL ILAENV * .. -* .. EXECUTABLE STATEMENTS .. +* .. Executable statements .. * -* TEST THE INPUT ARGUMENTS +* Test the input arguments * INFO = 0 * - LQUERY = ( LWORK1.EQ.-1 .OR. LWORK2.EQ.-1 ) + LQUERY = ( TSIZE.EQ.-1 .OR. TSIZE.EQ.-2 .OR. + $ LWORK.EQ.-1 .OR. LWORK.EQ.-2 ) +* + MINT = .FALSE. + MINW = .FALSE. + IF( TSIZE.EQ.-2 .OR. LWORK.EQ.-2 ) THEN + IF( TSIZE.NE.-1 ) MINT = .TRUE. + IF( LWORK.NE.-1 ) MINW = .TRUE. + END IF * * Determine the block size * - IF ( MIN(M,N).GT.0 ) THEN - MB = ILAENV( 1, 'SGEQR ', ' ', M, N, 1, -1) - NB = ILAENV( 1, 'SGEQR ', ' ', M, N, 2, -1) + IF( MIN( M, N ).GT.0 ) THEN + MB = ILAENV( 1, 'SGEQR ', ' ', M, N, 1, -1 ) + NB = ILAENV( 1, 'SGEQR ', ' ', M, N, 2, -1 ) ELSE MB = M NB = 1 END IF - IF( MB.GT.M.OR.MB.LE.N) MB = M - IF( NB.GT.MIN(M,N).OR.NB.LT.1) NB = 1 - MINLW1 = N + 5 - IF ((MB.GT.N).AND.(M.GT.N)) THEN - IF(MOD(M-N, MB-N).EQ.0) THEN - NBLCKS = (M-N)/(MB-N) + IF( MB.GT.M .OR. MB.LE.N ) MB = M + IF( NB.GT.MIN( M, N ) .OR. NB.LT.1 ) NB = 1 + MINTSZ = N + 5 + IF ( MB.GT.N .AND. M.GT.N ) THEN + IF( MOD( M - N, MB - N ).EQ.0 ) THEN + NBLCKS = ( M - N ) / ( MB - N ) ELSE - NBLCKS = (M-N)/(MB-N) + 1 + NBLCKS = ( M - N ) / ( MB - N ) + 1 END IF ELSE NBLCKS = 1 END IF * -* Determine if the workspace size satisfies minimum size +* Determine if the workspace size satisfies minimal size * LMINWS = .FALSE. - IF((LWORK1.LT.MAX(1, NB*N*NBLCKS+5) - $ .OR.(LWORK2.LT.NB*N)).AND.(LWORK2.GE.N).AND.(LWORK1.GT.N+5) - $ .AND.(.NOT.LQUERY)) THEN - IF (LWORK1.LT.MAX(1, NB * N * NBLCKS+5)) THEN - LMINWS = .TRUE. - NB = 1 + IF( ( TSIZE.LT.MAX( 1, NB*N*NBLCKS + 5 ) .OR. LWORK.LT.NB*N ) + $ .AND. ( LWORK.GE.N ) .AND. ( TSIZE.GE.MINTSZ ) + $ .AND. ( .NOT.LQUERY ) ) THEN + IF( TSIZE.LT.MAX( 1, NB*N*NBLCKS + 5 ) ) THEN + LMINWS = .TRUE. + NB = 1 + MB = M END IF - IF (LWORK1.LT.MAX(1, N * NBLCKS+5)) THEN - LMINWS = .TRUE. - MB = M - END IF - IF (LWORK2.LT.NB*N) THEN - LMINWS = .TRUE. - NB = 1 + IF( LWORK.LT.NB*N ) THEN + LMINWS = .TRUE. + NB = 1 END IF END IF * @@ -222,44 +254,52 @@ INFO = -2 ELSE IF( LDA.LT.MAX( 1, M ) ) THEN INFO = -4 - ELSE IF( LWORK1.LT.MAX( 1, NB * N * NBLCKS + 5 ) - $ .AND.(.NOT.LQUERY).AND.(.NOT.LMINWS)) THEN + ELSE IF( TSIZE.LT.MAX( 1, NB*N*NBLCKS + 5 ) + $ .AND. ( .NOT.LQUERY ) .AND. ( .NOT.LMINWS ) ) THEN INFO = -6 - ELSE IF( (LWORK2.LT.MAX(1,N*NB)).AND.(.NOT.LQUERY) - $ .AND.(.NOT.LMINWS)) THEN + ELSE IF( ( LWORK.LT.MAX( 1, N*NB ) ) .AND. ( .NOT.LQUERY ) + $ .AND. ( .NOT.LMINWS ) ) THEN INFO = -8 END IF - - IF( INFO.EQ.0) THEN - WORK1(1) = 1 - WORK1(2) = NB * N * NBLCKS + 5 - WORK1(3) = MINLW1 - WORK1(4) = MB - WORK1(5) = NB - WORK2(1) = NB * N - WORK2(2) = N +* + IF( INFO.EQ.0 ) THEN + IF( MINT ) THEN + T( 1 ) = MINTSZ + ELSE + T( 1 ) = NB*N*NBLCKS + 5 + END IF + T( 2 ) = MB + T( 3 ) = NB + IF( MINW ) THEN + WORK( 1 ) = MAX( 1, N ) + ELSE + WORK( 1 ) = MAX( 1, NB*N ) + END IF END IF IF( INFO.NE.0 ) THEN CALL XERBLA( 'SGEQR', -INFO ) RETURN - ELSE IF (LQUERY) THEN - RETURN + ELSE IF( LQUERY ) THEN + RETURN END IF * * Quick return if possible * - IF( MIN(M,N).EQ.0 ) THEN - RETURN + IF( MIN( M, N ).EQ.0 ) THEN + RETURN END IF * * The QR Decomposition * - IF((M.LE.N).OR.(MB.LE.N).OR.(MB.GE.M)) THEN - CALL SGEQRT( M, N, NB, A, LDA, WORK1(6), NB, WORK2, INFO) + IF( ( M.LE.N ) .OR. ( MB.LE.N ) .OR. ( MB.GE.M ) ) THEN + CALL SGEQRT( M, N, NB, A, LDA, T( 6 ), NB, WORK, INFO ) ELSE - CALL SLATSQR( M, N, MB, NB, A, LDA, WORK1(6), NB, WORK2, - $ LWORK2, INFO) + CALL SLATSQR( M, N, MB, NB, A, LDA, T( 6 ), NB, WORK, + $ LWORK, INFO ) END IF +* + WORK( 1 ) = MAX( 1, NB*N ) +* RETURN * * End of SGEQR diff --git a/SRC/sgetsls.f b/SRC/sgetsls.f index b7bcd0f0..1dbfb305 100644 --- a/SRC/sgetsls.f +++ b/SRC/sgetsls.f @@ -1,16 +1,15 @@ * Definition: * =========== * -* SUBROUTINE SGETSLS( TRANS, M, N, NRHS, A, LDA, B, LDB -* $ , WORK, LWORK, INFO ) - +* SUBROUTINE SGETSLS( TRANS, M, N, NRHS, A, LDA, B, LDB, +* $ WORK, LWORK, INFO ) * * .. Scalar Arguments .. * CHARACTER TRANS * INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS * .. * .. Array Arguments .. -* REAL A( LDA, * ), B( LDB, * ), WORK( * ) +* REAL A( LDA, * ), B( LDB, * ), WORK( * ) * .. * * @@ -30,16 +29,21 @@ *> 1. If TRANS = 'N' and m >= n: find the least squares solution of *> an overdetermined system, i.e., solve the least squares problem *> minimize || B - A*X ||. - +*> *> 2. If TRANS = 'N' and m < n: find the minimum norm solution of *> an underdetermined system A * X = B. - +*> *> 3. If TRANS = 'T' and m >= n: find the minimum norm solution of *> an undetermined system A**T * X = B. - +*> *> 4. If TRANS = 'T' and m < n: find the least squares solution of *> an overdetermined system, i.e., solve the least squares problem *> minimize || B - A**T * X ||. +*> +*> Several right hand side vectors b and solution vectors x can be +*> handled in a single call; they are stored as the columns of the +*> M-by-NRHS right hand side matrix B and the N-by-NRHS solution +*> matrix X. *> \endverbatim * * Arguments: @@ -77,7 +81,7 @@ *> On entry, the M-by-N matrix A. *> On exit, *> A is overwritten by details of its QR or LQ -*> factorization as returned by DGETSQR. +*> factorization as returned by SGEQR or SGELQ. *> \endverbatim *> *> \param[in] LDA @@ -112,18 +116,21 @@ *> *> \param[out] WORK *> \verbatim -*> WORK is REAL array, dimension (MAX(1,LWORK)) -*> On exit, if INFO = 0, WORK(1) returns the optimal LWORK, -*> and WORK(2) returns the minimum LWORK. +*> (workspace) REAL array, dimension (MAX(1,LWORK)) +*> On exit, if INFO = 0, WORK(1) contains optimal (or either minimal +*> or optimal, if query was assumed) LWORK. +*> See LWORK for details. *> \endverbatim *> *> \param[in] LWORK *> \verbatim *> LWORK is INTEGER *> The dimension of the array WORK. -*> IF LWORK=-1, workspace query is assumed, and -*> WORK(1) returns the optimal LWORK, -*> and WORK(2) returns the minimum LWORK. +*> If LWORK = -1 or -2, then a workspace query is assumed. +*> If LWORK = -1, the routine calculates optimal size of WORK for the +*> optimal performance and returns this value in WORK(1). +*> If LWORK = -2, the routine calculates minimal size of WORK and +*> returns this value in WORK(1). *> \endverbatim *> *> \param[out] INFO @@ -145,22 +152,22 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \date November 2011 +*> \date November 2016 * *> \ingroup doubleGEsolve * * ===================================================================== - SUBROUTINE SGETSLS( TRANS, M, N, NRHS, A, LDA, B, LDB - $ , WORK, LWORK, INFO ) + SUBROUTINE SGETSLS( TRANS, M, N, NRHS, A, LDA, B, LDB, + $ WORK, LWORK, INFO ) * -* -- LAPACK driver routine (version 3.4.0) -- +* -- LAPACK driver routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- -* November 2011 +* November 2016 * * .. Scalar Arguments .. CHARACTER TRANS - INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, MB + INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS * .. * .. Array Arguments .. REAL A( LDA, * ), B( LDB, * ), WORK( * ) @@ -175,10 +182,10 @@ * .. * .. Local Scalars .. LOGICAL LQUERY, TRAN - INTEGER I, IASCL, IBSCL, J, MINMN, MAXMN, BROW, LW, - $ SCLLEN, MNK, WSIZEO, WSIZEM, LW1, LW2, INFO2, - $ NB - REAL ANRM, BIGNUM, BNRM, SMLNUM + INTEGER I, IASCL, IBSCL, J, MINMN, MAXMN, BROW, + $ SCLLEN, MNK, TSZO, TSZM, LWO, LWM, LW1, LW2, + $ WSIZEO, WSIZEM, INFO2 + REAL ANRM, BIGNUM, BNRM, SMLNUM, TQ( 5 ), WORKQ * .. * .. External Functions .. LOGICAL LSAME @@ -191,19 +198,19 @@ $ STRTRS, XERBLA, SGELQ, SGEMLQ * .. * .. Intrinsic Functions .. - INTRINSIC REAL, MAX, MIN + INTRINSIC REAL, MAX, MIN, INT * .. * .. Executable Statements .. * * Test the input arguments. * - INFO=0 + INFO = 0 MINMN = MIN( M, N ) MAXMN = MAX( M, N ) - MNK = MAX(MINMN,NRHS) + MNK = MAX( MINMN, NRHS ) TRAN = LSAME( TRANS, 'T' ) * - LQUERY = ( LWORK.EQ.-1 ) + LQUERY = ( LWORK.EQ.-1 .OR. LWORK.EQ.-2 ) IF( .NOT.( LSAME( TRANS, 'N' ) .OR. $ LSAME( TRANS, 'T' ) ) ) THEN INFO = -1 @@ -219,60 +226,71 @@ INFO = -8 END IF * - IF( INFO.EQ.0) THEN + IF( INFO.EQ.0 ) THEN * * Determine the block size and minimum LWORK * - IF ( M.GE.N ) THEN - CALL SGEQR( M, N, A, LDA, WORK(1), -1, WORK(6), -1, - $ INFO2) - MB = INT(WORK(4)) - NB = INT(WORK(5)) - LW = INT(WORK(6)) - CALL SGEMQR( 'L', TRANS, M, NRHS, N, A, LDA, WORK(1), - $ INT(WORK(2)), B, LDB, WORK(6), -1 , INFO2 ) - WSIZEO = INT(WORK(2))+MAX(LW,INT(WORK(6))) - WSIZEM = INT(WORK(3))+MAX(LW,INT(WORK(6))) + IF( M.GE.N ) THEN + CALL SGEQR( M, N, A, LDA, TQ, -1, WORKQ, -1, INFO2 ) + TSZO = INT( TQ( 1 ) ) + LWO = INT( WORKQ ) + CALL SGEMQR( 'L', TRANS, M, NRHS, N, A, LDA, TQ, + $ TSZO, B, LDB, WORKQ, -1, INFO2 ) + LWO = MAX( LWO, INT( WORKQ ) ) + CALL SGEQR( M, N, A, LDA, TQ, -2, WORKQ, -2, INFO2 ) + TSZM = INT( TQ( 1 ) ) + LWM = INT( WORKQ ) + CALL SGEMQR( 'L', TRANS, M, NRHS, N, A, LDA, TQ, + $ TSZM, B, LDB, WORKQ, -1, INFO2 ) + LWM = MAX( LWM, INT( WORKQ ) ) + WSIZEO = TSZO + LWO + WSIZEM = TSZM + LWM ELSE - CALL SGELQ( M, N, A, LDA, WORK(1), -1, WORK(6), -1, - $ INFO2) - MB = INT(WORK(4)) - NB = INT(WORK(5)) - LW = INT(WORK(6)) - CALL SGEMLQ( 'L', TRANS, N, NRHS, M, A, LDA, WORK(1), - $ INT(WORK(2)), B, LDB, WORK(6), -1 , INFO2 ) - WSIZEO = INT(WORK(2))+MAX(LW,INT(WORK(6))) - WSIZEM = INT(WORK(3))+MAX(LW,INT(WORK(6))) + CALL SGELQ( M, N, A, LDA, TQ, -1, WORKQ, -1, INFO2 ) + TSZO = INT( TQ( 1 ) ) + LWO = INT( WORKQ ) + CALL SGEMLQ( 'L', TRANS, N, NRHS, M, A, LDA, TQ, + $ TSZO, B, LDB, WORKQ, -1, INFO2 ) + LWO = MAX( LWO, INT( WORKQ ) ) + CALL SGELQ( M, N, A, LDA, TQ, -2, WORKQ, -2, INFO2 ) + TSZM = INT( TQ( 1 ) ) + LWM = INT( WORKQ ) + CALL SGEMLQ( 'L', TRANS, N, NRHS, M, A, LDA, TQ, + $ TSZO, B, LDB, WORKQ, -1, INFO2 ) + LWM = MAX( LWM, INT( WORKQ ) ) + WSIZEO = TSZO + LWO + WSIZEM = TSZM + LWM END IF * - IF((LWORK.LT.WSIZEO).AND.(.NOT.LQUERY)) THEN - INFO=-10 + IF( ( LWORK.LT.WSIZEM ).AND.( .NOT.LQUERY ) ) THEN + INFO = -10 END IF +* END IF * IF( INFO.NE.0 ) THEN CALL XERBLA( 'SGETSLS', -INFO ) WORK( 1 ) = REAL( WSIZEO ) - WORK( 2 ) = REAL( WSIZEM ) RETURN - ELSE IF (LQUERY) THEN - WORK( 1 ) = REAL( WSIZEO ) - WORK( 2 ) = REAL( WSIZEM ) + END IF + IF( LQUERY ) THEN + IF( LWORK.EQ.-1 ) WORK( 1 ) = REAL( WSIZEO ) + IF( LWORK.EQ.-2 ) WORK( 1 ) = REAL( WSIZEM ) RETURN END IF - IF(LWORK.LT.WSIZEO) THEN - LW1=INT(WORK(3)) - LW2=MAX(LW,INT(WORK(6))) + IF( LWORK.LT.WSIZEO ) THEN + LW1 = TSZM + LW2 = LWM ELSE - LW1=INT(WORK(2)) - LW2=MAX(LW,INT(WORK(6))) + LW1 = TSZO + LW2 = LWO END IF * * Quick return if possible * IF( MIN( M, N, NRHS ).EQ.0 ) THEN CALL SLASET( 'FULL', MAX( M, N ), NRHS, ZERO, ZERO, - $ B, LDB ) + $ B, LDB ) RETURN END IF * @@ -328,26 +346,27 @@ IBSCL = 2 END IF * - IF ( M.GE.N) THEN + IF ( M.GE.N ) THEN * * compute QR factorization of A * - CALL SGEQR( M, N, A, LDA, WORK(LW2+1), LW1 - $ , WORK(1), LW2, INFO ) - IF (.NOT.TRAN) THEN + CALL SGEQR( M, N, A, LDA, WORK( LW2+1 ), LW1, + $ WORK( 1 ), LW2, INFO ) + IF ( .NOT.TRAN ) THEN * * Least-Squares Problem min || A * X - B || * * B(1:M,1:NRHS) := Q**T * B(1:M,1:NRHS) * CALL SGEMQR( 'L' , 'T', M, NRHS, N, A, LDA, - $ WORK(LW2+1), LW1, B, LDB, WORK(1), LW2, INFO ) + $ WORK( LW2+1 ), LW1, B, LDB, WORK( 1 ), LW2, + $ INFO ) * * B(1:N,1:NRHS) := inv(R) * B(1:N,1:NRHS) * CALL STRTRS( 'U', 'N', 'N', N, NRHS, - $ A, LDA, B, LDB, INFO ) - IF(INFO.GT.0) THEN + $ A, LDA, B, LDB, INFO ) + IF( INFO.GT.0 ) THEN RETURN END IF SCLLEN = N @@ -375,7 +394,7 @@ * B(1:M,1:NRHS) := Q(1:N,:) * B(1:N,1:NRHS) * CALL SGEMQR( 'L', 'N', M, NRHS, N, A, LDA, - $ WORK( LW2+1), LW1, B, LDB, WORK( 1 ), LW2, + $ WORK( LW2+1 ), LW1, B, LDB, WORK( 1 ), LW2, $ INFO ) * SCLLEN = M @@ -386,8 +405,8 @@ * * Compute LQ factorization of A * - CALL SGELQ( M, N, A, LDA, WORK(LW2+1), LW1 - $ , WORK(1), LW2, INFO ) + CALL SGELQ( M, N, A, LDA, WORK( LW2+1 ), LW1, + $ WORK( 1 ), LW2, INFO ) * * workspace at least M, optimally M*NB. * @@ -415,7 +434,7 @@ * B(1:N,1:NRHS) := Q(1:N,:)**T * B(1:M,1:NRHS) * CALL SGEMLQ( 'L', 'T', N, NRHS, M, A, LDA, - $ WORK( LW2+1), LW1, B, LDB, WORK( 1 ), LW2, + $ WORK( LW2+1 ), LW1, B, LDB, WORK( 1 ), LW2, $ INFO ) * * workspace at least NRHS, optimally NRHS*NB @@ -429,7 +448,7 @@ * B(1:N,1:NRHS) := Q * B(1:N,1:NRHS) * CALL SGEMLQ( 'L', 'N', N, NRHS, M, A, LDA, - $ WORK( LW2+1), LW1, B, LDB, WORK( 1 ), LW2, + $ WORK( LW2+1 ), LW1, B, LDB, WORK( 1 ), LW2, $ INFO ) * * workspace at least NRHS, optimally NRHS*NB @@ -453,22 +472,21 @@ * IF( IASCL.EQ.1 ) THEN CALL SLASCL( 'G', 0, 0, ANRM, SMLNUM, SCLLEN, NRHS, B, LDB, - $ INFO ) + $ INFO ) ELSE IF( IASCL.EQ.2 ) THEN CALL SLASCL( 'G', 0, 0, ANRM, BIGNUM, SCLLEN, NRHS, B, LDB, - $ INFO ) + $ INFO ) END IF IF( IBSCL.EQ.1 ) THEN - CALL SLASCL( 'G', 0, 0, SMLNUM, BNRM, SCLLEN, NRHS, B, LDB, - $ INFO ) + CALL SLASCL( 'G', 0, 0, SMLNUM, BNRM, SCLLEN, NRHS, B, LDB, + $ INFO ) ELSE IF( IBSCL.EQ.2 ) THEN - CALL SLASCL( 'G', 0, 0, BIGNUM, BNRM, SCLLEN, NRHS, B, LDB, - $ INFO ) + CALL SLASCL( 'G', 0, 0, BIGNUM, BNRM, SCLLEN, NRHS, B, LDB, + $ INFO ) END IF * 50 CONTINUE - WORK( 1 ) = REAL( WSIZEO ) - WORK( 2 ) = REAL( WSIZEM ) + WORK( 1 ) = REAL( TSZO + LWO ) RETURN * * End of SGETSLS diff --git a/SRC/slamswlq.f b/SRC/slamswlq.f index f8719139..fc30556b 100644 --- a/SRC/slamswlq.f +++ b/SRC/slamswlq.f @@ -33,14 +33,19 @@ * ========== * *> \param[in] SIDE +*> \verbatim *> SIDE is CHARACTER*1 *> = 'L': apply Q or Q**T from the Left; *> = 'R': apply Q or Q**T from the Right. +*> \endverbatim *> *> \param[in] TRANS +*> \verbatim *> TRANS is CHARACTER*1 *> = 'N': No transpose, apply Q; *> = 'T': Transpose, apply Q**T. +*> \endverbatim +*> *> \param[in] M *> \verbatim *> M is INTEGER @@ -115,18 +120,23 @@ *> \endverbatim *> *> \param[in,out] C +*> \verbatim *> C is REAL array, dimension (LDC,N) *> On entry, the M-by-N matrix C. *> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +*> \endverbatim +*> *> \param[in] LDC +*> \verbatim *> LDC is INTEGER *> The leading dimension of the array C. LDC >= max(1,M). +*> \endverbatim *> *> \param[out] WORK *> \verbatim *> (workspace) REAL array, dimension (MAX(1,LWORK)) -*> *> \endverbatim +*> *> \param[in] LWORK *> \verbatim *> LWORK is INTEGER @@ -137,8 +147,8 @@ *> only calculates the optimal size of the WORK array, returns *> this value as the first entry of the WORK array, and no error *> message related to LWORK is issued by XERBLA. -*> *> \endverbatim +*> *> \param[out] INFO *> \verbatim *> INFO is INTEGER diff --git a/SRC/slamtsqr.f b/SRC/slamtsqr.f index 69d6c327..f3e176db 100644 --- a/SRC/slamtsqr.f +++ b/SRC/slamtsqr.f @@ -33,14 +33,19 @@ * ========== * *> \param[in] SIDE +*> \verbatim *> SIDE is CHARACTER*1 *> = 'L': apply Q or Q**T from the Left; *> = 'R': apply Q or Q**T from the Right. +*> \endverbatim *> *> \param[in] TRANS +*> \verbatim *> TRANS is CHARACTER*1 *> = 'N': No transpose, apply Q; *> = 'T': Transpose, apply Q**T. +*> \endverbatim +*> *> \param[in] M *> \verbatim *> M is INTEGER @@ -109,12 +114,17 @@ *> \endverbatim *> *> \param[in,out] C +*> \verbatim *> C is REAL array, dimension (LDC,N) *> On entry, the M-by-N matrix C. *> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +*> \endverbatim +*> *> \param[in] LDC +*> \verbatim *> LDC is INTEGER *> The leading dimension of the array C. LDC >= max(1,M). +*> \endverbatim *> *> \param[out] WORK *> \verbatim @@ -247,14 +257,13 @@ ELSE IF(( LWORK.LT.MAX(1,LW)).AND.(.NOT.LQUERY)) THEN INFO = -15 END IF - IF( INFO.EQ.0) THEN * * Determine the block size if it is tall skinny or short and wide * IF( INFO.EQ.0) THEN WORK(1) = LW END IF - END IF +* IF( INFO.NE.0 ) THEN CALL XERBLA( 'SLAMTSQR', -INFO ) RETURN @@ -354,10 +363,11 @@ * * Multiply Q to the current block of C (1:M,I:I+MB) * - CTR = CTR - 1 - CALL STPMQRT('R','T',M , MB-K, K, 0,NB, A(I,1), LDA, + CTR = CTR - 1 + CALL STPMQRT('R','T',M , MB-K, K, 0,NB, A(I,1), LDA, $ T(1, CTR * K + 1), LDT, C(1,1), LDC, $ C(1,I), LDC, WORK, INFO ) +* END DO * * Multiply Q to the first block of C (1:M,1:MB) diff --git a/SRC/zgelq.f b/SRC/zgelq.f index 33125b3d..73d54771 100644 --- a/SRC/zgelq.f +++ b/SRC/zgelq.f @@ -2,14 +2,14 @@ * Definition: * =========== * -* SUBROUTINE CGELQ( M, N, A, LDA, WORK1, LWORK1, WORK2, LWORK2, -* INFO) +* SUBROUTINE ZGELQ( M, N, A, LDA, T, TSIZE, WORK, LWORK, +* INFO ) * * .. Scalar Arguments .. -* INTEGER INFO, LDA, M, N, LWORK1, LWORK2 +* INTEGER INFO, LDA, M, N, TSIZE, LWORK * .. * .. Array Arguments .. -* COMPLEX*16 A( LDA, * ), WORK1( * ), WORK2( * ) +* COMPLEX*16 A( LDA, * ), T( * ), WORK( * ) * .. * * @@ -17,11 +17,7 @@ * ============= *> *> \verbatim -*> -*> ZGELQ computes an LQ factorization of an M-by-N matrix A, -*> using ZLASWLQ when A is short and wide -*> (N sufficiently greater than M), and otherwise ZGELQT: -*> A = L * Q . +*> ZGELQ computes a LQ factorization of an M-by-N matrix A. *> \endverbatim * * Arguments: @@ -46,8 +42,8 @@ *> On exit, the elements on and below the diagonal of the array *> contain the M-by-min(M,N) lower trapezoidal matrix L *> (L is lower triangular if M <= N); -*> the elements above the diagonal are the rows of -*> blocked V representing Q (see Further Details). +*> the elements above the diagonal are used to store part of the +*> data structure to represent Q. *> \endverbatim *> *> \param[in] LDA @@ -56,47 +52,50 @@ *> The leading dimension of the array A. LDA >= max(1,M). *> \endverbatim *> -*> \param[out] WORK1 +*> \param[out] T *> \verbatim -*> WORK1 is COMPLEX*16 array, dimension (MAX(1,LWORK1)) -*> WORK1 contains part of the data structure used to store Q. -*> WORK1(1): algorithm type = 1, to indicate output from -*> ZLASWLQ or ZGELQT -*> WORK1(2): optimum size of WORK1 -*> WORK1(3): minimum size of WORK1 -*> WORK1(4): horizontal block size -*> WORK1(5): vertical block size -*> WORK1(6:LWORK1): data structure needed for Q, computed by -*> ZLASWLQ or ZGELQT +*> T is COMPLEX*16 array, dimension (MAX(5,TSIZE)) +*> On exit, if INFO = 0, T(1) returns optimal (or either minimal +*> or optimal, if query is assumed) TSIZE. See TSIZE for details. +*> Remaining T contains part of the data structure used to represent Q. +*> If one wants to apply or construct Q, then one needs to keep T +*> (in addition to A) and pass it to further subroutines. *> \endverbatim *> -*> \param[in] LWORK1 +*> \param[in] TSIZE *> \verbatim -*> LWORK1 is INTEGER -*> The dimension of the array WORK1. -*> If LWORK1 = -1, then a query is assumed. In this case the -*> routine calculates the optimal size of WORK1 and -*> returns this value in WORK1(2), and calculates the minimum -*> size of WORK1 and returns this value in WORK1(3). -*> No error message related to LWORK1 is issued by XERBLA when -*> LWORK1 = -1. +*> TSIZE is INTEGER +*> If TSIZE >= 5, the dimension of the array T. +*> If TSIZE = -1 or -2, then a workspace query is assumed. The routine +*> only calculates the sizes of the T and WORK arrays, returns these +*> values as the first entries of the T and WORK arrays, and no error +*> message related to T or WORK is issued by XERBLA. +*> If TSIZE = -1, the routine calculates optimal size of T for the +*> optimum performance and returns this value in T(1). +*> If TSIZE = -2, the routine calculates minimal size of T and +*> returns this value in T(1). *> \endverbatim *> -*> \param[out] WORK2 +*> \param[out] WORK *> \verbatim -*> (workspace) COMPLEX*16 array, dimension (MAX(1,LWORK2)) -*> +*> (workspace) COMPLEX*16 array, dimension (MAX(1,LWORK)) +*> On exit, if INFO = 0, WORK(1) contains optimal (or either minimal +*> or optimal, if query was assumed) LWORK. +*> See LWORK for details. *> \endverbatim -*> \param[in] LWORK2 +*> +*> \param[in] LWORK *> \verbatim -*> LWORK2 is INTEGER -*> The dimension of the array WORK2. -*> If LWORK2 = -1, then a query is assumed. In this case the -*> routine calculates the optimal size of WORK2 and -*> returns this value in WORK2(1), and calculates the minimum -*> size of WORK2 and returns this value in WORK2(2). -*> No error message related to LWORK2 is issued by XERBLA when -*> LWORK2 = -1. +*> LWORK is INTEGER +*> The dimension of the array WORK. +*> If LWORK = -1 or -2, then a workspace query is assumed. The routine +*> only calculates the sizes of the T and WORK arrays, returns these +*> values as the first entries of the T and WORK arrays, and no error +*> message related to T or WORK is issued by XERBLA. +*> If LWORK = -1, the routine calculates optimal size of WORK for the +*> optimal performance and returns this value in WORK(1). +*> If LWORK = -2, the routine calculates minimal size of WORK and +*> returns this value in WORK(1). *> \endverbatim *> *> \param[out] INFO @@ -114,104 +113,135 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \par Further Details: -* ===================== +*> \par Further Details +* ==================== *> *> \verbatim +*> +*> The goal of the interface is to give maximum freedom to the developers for +*> creating any LQ factorization algorithm they wish. The triangular +*> (trapezoidal) L has to be stored in the lower part of A. The lower part of A +*> and the array T can be used to store any relevant information for applying or +*> constructing the Q factor. The WORK array can safely be discarded after exit. +*> +*> Caution: One should not expect the sizes of T and WORK to be the same from one +*> LAPACK implementation to the other, or even from one execution to the other. +*> A workspace query (for T and WORK) is needed at each execution. However, +*> for a given execution, the size of T and WORK are fixed and will not change +*> from one query to the next. +*> +*> \endverbatim +*> +*> \par Further Details particular to this LAPACK implementation: +* ============================================================== +*> +*> \verbatim +*> +*> These details are particular for this LAPACK implementation. Users should not +*> take them for granted. These details may change in the future, and are unlikely not +*> true for another LAPACK implementation. These details are relevant if one wants +*> to try to understand the code. They are not part of the interface. +*> +*> In this version, +*> +*> T(2): row block size (MB) +*> T(3): column block size (NB) +*> T(6:TSIZE): data structure needed for Q, computed by +*> ZLASWLQ or ZGELQT +*> *> Depending on the matrix dimensions M and N, and row and column -*> block sizes MB and NB returned by ILAENV, GELQ will use either -*> LASWLQ(if the matrix is short-and-wide) or GELQT to compute -*> the LQ decomposition. -*> The output of LASWLQ or GELQT representing Q is stored in A and in -*> array WORK1(6:LWORK1) for later use. -*> WORK1(2:5) contains the matrix dimensions M,N and block sizes MB, NB -*> which are needed to interpret A and WORK1(6:LWORK1) for later use. -*> WORK1(1)=1 indicates that the code needed to take WORK1(2:5) and -*> decide whether LASWLQ or GELQT was used is the same as used below in -*> GELQ. For a detailed description of A and WORK1(6:LWORK1), see -*> Further Details in LASWLQ or GELQT. +*> block sizes MB and NB returned by ILAENV, ZGELQ will use either +*> ZLASWLQ (if the matrix is short-and-wide) or ZGELQT to compute +*> the LQ factorization. *> \endverbatim *> * ===================================================================== - SUBROUTINE ZGELQ( M, N, A, LDA, WORK1, LWORK1, WORK2, LWORK2, - $ INFO) + SUBROUTINE ZGELQ( M, N, A, LDA, T, TSIZE, WORK, LWORK, + $ INFO ) * -* -- LAPACK computational routine (version 3.5.0) -- +* -- LAPACK computational routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd. -- -* November 2013 +* November 2016 * * .. Scalar Arguments .. - INTEGER INFO, LDA, M, N, LWORK1, LWORK2 + INTEGER INFO, LDA, M, N, TSIZE, LWORK * .. * .. Array Arguments .. - COMPLEX*16 A( LDA, * ), WORK1( * ), WORK2( * ) + COMPLEX*16 A( LDA, * ), T( * ), WORK( * ) * .. * * ===================================================================== * * .. * .. Local Scalars .. - LOGICAL LQUERY, LMINWS - INTEGER MB, NB, I, II, KK, MINLW1, NBLCKS + LOGICAL LQUERY, LMINWS, MINT, MINW + INTEGER MB, NB, MINTSZ, NBLCKS * .. -* .. EXTERNAL FUNCTIONS .. +* .. External Functions .. LOGICAL LSAME EXTERNAL LSAME -* .. EXTERNAL SUBROUTINES .. +* .. +* .. External Subroutines .. EXTERNAL ZGELQT, ZLASWLQ, XERBLA -* .. INTRINSIC FUNCTIONS .. +* .. +* .. Intrinsic Functions .. INTRINSIC MAX, MIN, MOD * .. -* .. EXTERNAL FUNCTIONS .. +* .. External Functions .. INTEGER ILAENV EXTERNAL ILAENV * .. -* .. EXECUTABLE STATEMENTS .. +* .. Executable Statements .. * -* TEST THE INPUT ARGUMENTS +* Test the input arguments * INFO = 0 * - LQUERY = ( LWORK1.EQ.-1 .OR. LWORK2.EQ.-1 ) + LQUERY = ( TSIZE.EQ.-1 .OR. TSIZE.EQ.-2 .OR. + $ LWORK.EQ.-1 .OR. LWORK.EQ.-2 ) +* + MINT = .FALSE. + MINW = .FALSE. + IF( TSIZE.EQ.-2 .OR. LWORK.EQ.-2 ) THEN + IF( TSIZE.NE.-1 ) MINT = .TRUE. + IF( LWORK.NE.-1 ) MINW = .TRUE. + END IF * * Determine the block size * - IF ( MIN(M,N).GT.0 ) THEN - MB = ILAENV( 1, 'ZGELQ ', ' ', M, N, 1, -1) - NB = ILAENV( 1, 'ZGELQ ', ' ', M, N, 2, -1) + IF( MIN( M, N ).GT.0 ) THEN + MB = ILAENV( 1, 'ZGELQ ', ' ', M, N, 1, -1 ) + NB = ILAENV( 1, 'ZGELQ ', ' ', M, N, 2, -1 ) ELSE MB = 1 NB = N END IF - IF( MB.GT.MIN(M,N).OR.MB.LT.1) MB = 1 - IF( NB.GT.N.OR.NB.LE.M) NB = N - MINLW1 = M + 5 - IF ((NB.GT.M).AND.(N.GT.M)) THEN - IF(MOD(N-M, NB-M).EQ.0) THEN - NBLCKS = (N-M)/(NB-M) + IF( MB.GT.MIN( M, N ) .OR. MB.LT.1 ) MB = 1 + IF( NB.GT.N .OR. NB.LE.M ) NB = N + MINTSZ = M + 5 + IF ( NB.GT.M .AND. N.GT.M ) THEN + IF( MOD( N - M, NB - M ).EQ.0 ) THEN + NBLCKS = ( N - M ) / ( NB - M ) ELSE - NBLCKS = (N-M)/(NB-M) + 1 + NBLCKS = ( N - M ) / ( NB - M ) + 1 END IF ELSE NBLCKS = 1 END IF * -* Determine if the workspace size satisfies minimum size +* Determine if the workspace size satisfies minimal size * LMINWS = .FALSE. - IF((LWORK1.LT.MAX(1,MB*M*NBLCKS+5) - $ .OR.(LWORK2.LT.MB*M)).AND.(LWORK2.GE.M).AND.(LWORK1.GE.M+5) - $ .AND.(.NOT.LQUERY)) THEN - IF (LWORK1.LT.MAX(1,MB*M*NBLCKS+5)) THEN + IF( ( TSIZE.LT.MAX( 1, MB*M*NBLCKS + 5 ) .OR. LWORK.LT.MB*M ) + $ .AND. ( LWORK.GE.M ) .AND. ( TSIZE.GE.MINTSZ ) + $ .AND. ( .NOT.LQUERY ) ) THEN + IF( TSIZE.LT.MAX( 1, MB*M*NBLCKS + 5 ) ) THEN LMINWS = .TRUE. MB = 1 - END IF - IF (LWORK1.LT.MAX(1,M*NBLCKS+5)) THEN - LMINWS = .TRUE. NB = N END IF - IF (LWORK2.LT.MB*M) THEN + IF( LWORK.LT.MB*M ) THEN LMINWS = .TRUE. MB = 1 END IF @@ -223,44 +253,52 @@ INFO = -2 ELSE IF( LDA.LT.MAX( 1, M ) ) THEN INFO = -4 - ELSE IF( LWORK1.LT.MAX( 1, MB*M*NBLCKS+5 ) - $ .AND.(.NOT.LQUERY).AND. (.NOT.LMINWS)) THEN + ELSE IF( TSIZE.LT.MAX( 1, MB*M*NBLCKS + 5 ) + $ .AND. ( .NOT.LQUERY ) .AND. ( .NOT.LMINWS ) ) THEN INFO = -6 - ELSE IF( (LWORK2.LT.MAX(1,M*MB)).AND.(.NOT.LQUERY) - $ .AND.(.NOT.LMINWS) ) THEN + ELSE IF( ( LWORK.LT.MAX( 1, M*MB ) ) .AND .( .NOT.LQUERY ) + $ .AND. ( .NOT.LMINWS ) ) THEN INFO = -8 END IF * - IF( INFO.EQ.0) THEN - WORK1(1) = 1 - WORK1(2) = MB*M*NBLCKS+5 - WORK1(3) = MINLW1 - WORK1(4) = MB - WORK1(5) = NB - WORK2(1) = MB * M - WORK2(2) = M + IF( INFO.EQ.0 ) THEN + IF( MINT ) THEN + T( 1 ) = MINTSZ + ELSE + T( 1 ) = MB*M*NBLCKS + 5 + END IF + T( 2 ) = MB + T( 3 ) = NB + IF( MINW ) THEN + WORK( 1 ) = MAX( 1, N ) + ELSE + WORK( 1 ) = MAX( 1, MB*M ) + END IF END IF IF( INFO.NE.0 ) THEN CALL XERBLA( 'ZGELQ', -INFO ) RETURN - ELSE IF (LQUERY) THEN - RETURN + ELSE IF( LQUERY ) THEN + RETURN END IF * * Quick return if possible * - IF( MIN(M,N).EQ.0 ) THEN - RETURN + IF( MIN( M, N ).EQ.0 ) THEN + RETURN END IF * * The LQ Decomposition * - IF((N.LE.M).OR.(NB.LE.M).OR.(NB.GE.N)) THEN - CALL ZGELQT( M, N, MB, A, LDA, WORK1(6), MB, WORK2, INFO) + IF( ( N.LE.M ) .OR. ( NB.LE.M ) .OR. ( NB.GE.N ) ) THEN + CALL ZGELQT( M, N, MB, A, LDA, T( 6 ), MB, WORK, INFO ) ELSE - CALL ZLASWLQ( M, N, MB, NB, A, LDA, WORK1(6), MB, WORK2, - $ LWORK2, INFO) + CALL ZLASWLQ( M, N, MB, NB, A, LDA, T( 6 ), MB, WORK, + $ LWORK, INFO ) END IF +* + WORK( 1 ) = MAX( 1, MB*M ) +* RETURN * * End of ZGELQ diff --git a/SRC/zgemlq.f b/SRC/zgemlq.f index 10d3a5e4..5602d872 100644 --- a/SRC/zgemlq.f +++ b/SRC/zgemlq.f @@ -2,17 +2,16 @@ * Definition: * =========== * -* SUBROUTINE ZGEMLQ( SIDE, TRANS, M, N, K, A, LDA, WORK1, -* $ LWORK1, C, LDC, WORK2, LWORK2, INFO ) +* SUBROUTINE ZGEMLQ( SIDE, TRANS, M, N, K, A, LDA, T, +* $ TSIZE, C, LDC, WORK, LWORK, INFO ) * * * .. Scalar Arguments .. -* CHARACTER SIDE, TRANS -* INTEGER INFO, LDA, M, N, K, MB, NB, LWORK1, LWORK2, LDC +* CHARACTER SIDE, TRANS +* INTEGER INFO, LDA, M, N, K, LDT, TSIZE, LWORK, LDC * .. * .. Array Arguments .. -* COMPLEX*16 A( LDA, * ), WORK1( * ), C(LDC, * ), -* $ WORK2( * ) +* COMPLEX*16 A( LDA, * ), T( * ), C(LDC, * ), WORK( * ) *> \par Purpose: * ============= *> @@ -20,27 +19,32 @@ *> *> ZGEMLQ overwrites the general real M-by-N matrix C with *> +*> SIDE = 'L' SIDE = 'R' +*> TRANS = 'N': Q * C C * Q +*> TRANS = 'C': Q**H * C C * Q**H +*> where Q is a complex unitary matrix defined as the product +*> of blocked elementary reflectors computed by short wide +*> LQ factorization (ZGELQ) *> -*> SIDE = 'L' SIDE = 'R' -*> TRANS = 'N': Q * C C * Q -*> TRANS = 'T': Q**T * C C * Q**T -*> where Q is a complex orthogonal matrix defined as the product -*> of blocked elementary reflectors computed by short wide LQ -*> factorization (DGELQ) *> \endverbatim * * Arguments: * ========== * *> \param[in] SIDE +*> \verbatim *> SIDE is CHARACTER*1 *> = 'L': apply Q or Q**T from the Left; *> = 'R': apply Q or Q**T from the Right. +*> \endverbatim *> *> \param[in] TRANS +*> \verbatim *> TRANS is CHARACTER*1 *> = 'N': No transpose, apply Q; *> = 'T': Transpose, apply Q**T. +*> \endverbatim +*> *> \param[in] M *> \verbatim *> M is INTEGER @@ -50,7 +54,7 @@ *> \param[in] N *> \verbatim *> N is INTEGER -*> The number of columns of the matrix C. N >= M. +*> The number of columns of the matrix C. N >= 0. *> \endverbatim *> *> \param[in] K @@ -58,61 +62,65 @@ *> K is INTEGER *> The number of elementary reflectors whose product defines *> the matrix Q. -*> M >= K >= 0; +*> If SIDE = 'L', M >= K >= 0; +*> if SIDE = 'R', N >= K >= 0. *> *> \endverbatim *> -*> \param[in,out] A +*> \param[in] A *> \verbatim -*> A is COMPLEX*16 array, dimension (LDA,K) -*> The i-th row must contain the vector which defines the blocked -*> elementary reflector H(i), for i = 1,2,...,k, as returned by -*> DLASWLQ in the first k rows of its array argument A. +*> A is COMPLEX*16 array, dimension +*> (LDA,M) if SIDE = 'L', +*> (LDA,N) if SIDE = 'R' +*> Part of the data structure to represent Q as returned by ZGELQ. *> \endverbatim *> *> \param[in] LDA *> \verbatim *> LDA is INTEGER -*> The leading dimension of the array A. -*> If SIDE = 'L', LDA >= max(1,M); -*> if SIDE = 'R', LDA >= max(1,N). +*> The leading dimension of the array A. LDA >= max(1,K). *> \endverbatim *> -*> \param[in] WORK1 +*> \param[in] T *> \verbatim -*> WORK1 is COMPLEX*16 array, dimension (MAX(1,LWORK1)) is -*> returned by GEQR. +*> T is COMPLEX*16 array, dimension (MAX(5,TSIZE)). +*> Part of the data structure to represent Q as returned by ZGELQ. *> \endverbatim *> -*> \param[in] LWORK1 +*> \param[in] TSIZE *> \verbatim -*> LWORK1 is INTEGER -*> The dimension of the array WORK1. +*> TSIZE is INTEGER +*> The dimension of the array T. TSIZE >= 5. *> \endverbatim *> *> \param[in,out] C +*> \verbatim *> C is COMPLEX*16 array, dimension (LDC,N) *> On entry, the M-by-N matrix C. *> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +*> \endverbatim +*> *> \param[in] LDC +*> \verbatim *> LDC is INTEGER *> The leading dimension of the array C. LDC >= max(1,M). +*> \endverbatim *> -*> \param[out] WORK2 +*> \param[out] WORK *> \verbatim -*> (workspace) COMPLEX*16 array, dimension (MAX(1,LWORK2)) -*> +*> (workspace) COMPLEX*16 array, dimension (MAX(1,LWORK)) *> \endverbatim -*> \param[in] LWORK2 -*> \verbatim -*> LWORK2 is INTEGER -*> The dimension of the array WORK2. -*> If LWORK2 = -1, then a workspace query is assumed; the routine -*> only calculates the optimal size of the WORK2 array, returns -*> this value as the third entry of the WORK2 array (WORK2(1)), -*> and no error message related to LWORK2 is issued by XERBLA. *> +*> \param[in] LWORK +*> \verbatim +*> LWORK is INTEGER +*> The dimension of the array WORK. +*> If LWORK = -1, then a workspace query is assumed. The routine +*> only calculates the size of the WORK array, returns this +*> value as WORK(1), and no error message related to WORK +*> is issued by XERBLA. *> \endverbatim +*> *> \param[out] INFO *> \verbatim *> INFO is INTEGER @@ -128,53 +136,63 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \par Further Details: -* ===================== +*> \par Further Details +* ==================== *> *> \verbatim +*> +*> These details are particular for this LAPACK implementation. Users should not +*> take them for granted. These details may change in the future, and are unlikely not +*> true for another LAPACK implementation. These details are relevant if one wants +*> to try to understand the code. They are not part of the interface. +*> +*> In this version, +*> +*> T(2): row block size (MB) +*> T(3): column block size (NB) +*> T(6:TSIZE): data structure needed for Q, computed by +*> ZLASWLQ or ZGELQT +*> *> Depending on the matrix dimensions M and N, and row and column -*> block sizes MB and NB returned by ILAENV, GELQ will use either -*> LASWLQ(if the matrix is short-and-wide) or GELQT to compute -*> the LQ decomposition. -*> The output of LASWLQ or GELQT representing Q is stored in A and in -*> array WORK1(6:LWORK1) for later use. -*> WORK1(2:5) contains the matrix dimensions M,N and block sizes MB, NB -*> which are needed to interpret A and WORK1(6:LWORK1) for later use. -*> WORK1(1)=1 indicates that the code needed to take WORK1(2:5) and -*> decide whether LASWLQ or GELQT was used is the same as used below in -*> GELQ. For a detailed description of A and WORK1(6:LWORK1), see -*> Further Details in LASWLQ or GELQT. +*> block sizes MB and NB returned by ILAENV, ZGELQ will use either +*> ZLASWLQ (if the matrix is wide-and-short) or ZGELQT to compute +*> the LQ factorization. +*> This version of ZGEMLQ will use either ZLAMSWLQ or ZGEMLQT to +*> multiply matrix Q by another matrix. +*> Further Details in ZLAMSWLQ or ZGEMLQT. *> \endverbatim *> * ===================================================================== - SUBROUTINE ZGEMLQ( SIDE, TRANS, M, N, K, A, LDA, WORK1, LWORK1, - $ C, LDC, WORK2, LWORK2, INFO ) + SUBROUTINE ZGEMLQ( SIDE, TRANS, M, N, K, A, LDA, T, TSIZE, + $ C, LDC, WORK, LWORK, INFO ) * -* -- LAPACK computational routine (version 3.5.0) -- +* -- LAPACK computational routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- -* November 2013 +* November 2016 * * .. Scalar Arguments .. - CHARACTER SIDE, TRANS - INTEGER INFO, LDA, M, N, K, LWORK1, LWORK2, LDC + CHARACTER SIDE, TRANS + INTEGER INFO, LDA, M, N, K, TSIZE, LWORK, LDC * .. * .. Array Arguments .. - COMPLEX*16 A( LDA, * ), C( LDC, * ), WORK1( * ), WORK2( * ) + COMPLEX*16 A( LDA, * ), T( * ), C( LDC, * ), WORK( * ) * .. * * ===================================================================== * * .. * .. Local Scalars .. - LOGICAL LEFT, RIGHT, TRAN, NOTRAN, LQUERY - INTEGER I, II, KK, MB, NB, LW, NBLCKS, MN + LOGICAL LEFT, RIGHT, TRAN, NOTRAN, LQUERY + INTEGER MB, NB, LW, NBLCKS, MN * .. * .. External Functions .. LOGICAL LSAME EXTERNAL LSAME +* .. * .. External Subroutines .. EXTERNAL ZLAMSWLQ, ZGEMLQT, XERBLA +* .. * .. Intrinsic Functions .. INTRINSIC INT, MAX, MIN, MOD * .. @@ -182,26 +200,27 @@ * * Test the input arguments * - LQUERY = LWORK2.LT.0 + LQUERY = LWORK.EQ.-1 NOTRAN = LSAME( TRANS, 'N' ) TRAN = LSAME( TRANS, 'C' ) LEFT = LSAME( SIDE, 'L' ) RIGHT = LSAME( SIDE, 'R' ) * - MB = INT(WORK1(4)) - NB = INT(WORK1(5)) - IF (LEFT) THEN + MB = INT( T( 2 ) ) + NB = INT( T( 3 ) ) + IF( LEFT ) THEN LW = N * MB MN = M ELSE LW = M * MB MN = N END IF - IF ((NB.GT.K).AND.(MN.GT.K)) THEN - IF(MOD(MN-K, NB-K).EQ.0) THEN - NBLCKS = (MN-K)/(NB-K) +* + IF( ( NB.GT.K ) .AND. ( MN.GT.K ) ) THEN + IF( MOD( MN - K, NB - K ) .EQ. 0 ) THEN + NBLCKS = ( MN - K ) / ( NB - K ) ELSE - NBLCKS = (MN-K)/(NB-K) + 1 + NBLCKS = ( MN - K ) / ( NB - K ) + 1 END IF ELSE NBLCKS = 1 @@ -209,51 +228,53 @@ * INFO = 0 IF( .NOT.LEFT .AND. .NOT.RIGHT ) THEN - INFO = -1 + INFO = -1 ELSE IF( .NOT.TRAN .AND. .NOT.NOTRAN ) THEN - INFO = -2 + INFO = -2 ELSE IF( M.LT.0 ) THEN INFO = -3 - ELSE IF( N.LT.0) THEN + ELSE IF( N.LT.0 ) THEN INFO = -4 - ELSE IF( K.LT.0 ) THEN + ELSE IF( K.LT.0 .OR. K.GT.MN ) THEN INFO = -5 ELSE IF( LDA.LT.MAX( 1, K ) ) THEN INFO = -7 - ELSE IF( LWORK1.LT.MAX( 1, MB*K*NBLCKS+5 )) THEN + ELSE IF( TSIZE.LT.5 ) THEN INFO = -9 ELSE IF( LDC.LT.MAX( 1, M ) ) THEN - INFO = -11 - ELSE IF(( LWORK2.LT.MAX(1,LW)).AND.(.NOT.LQUERY)) THEN + INFO = -11 + ELSE IF( ( LWORK.LT.MAX( 1, LW ) ) .AND. ( .NOT.LQUERY ) ) THEN INFO = -13 END IF * - IF( INFO.EQ.0) THEN - WORK2(1) = LW + IF( INFO.EQ.0 ) THEN + WORK( 1 ) = LW END IF +* IF( INFO.NE.0 ) THEN CALL XERBLA( 'ZGEMLQ', -INFO ) RETURN - ELSE IF (LQUERY) THEN + ELSE IF( LQUERY ) THEN RETURN END IF * * Quick return if possible * - IF( MIN(M,N,K).EQ.0 ) THEN + IF( MIN( M, N, K ).EQ.0 ) THEN RETURN END IF * - IF((LEFT.AND.M.LE.K).OR.(RIGHT.AND.N.LE.K).OR.(NB.LE.K).OR. - $ (NB.GE.MAX(M,N,K))) THEN + IF( ( LEFT .AND. M.LE.K ) .OR. ( RIGHT .AND. N.LE.K ) + $ .OR. ( NB.LE.K ) .OR. ( NB.GE.MAX( M, N, K ) ) ) THEN CALL ZGEMLQT( SIDE, TRANS, M, N, K, MB, A, LDA, - $ WORK1(6), MB, C, LDC, WORK2, INFO) + $ T( 6 ), MB, C, LDC, WORK, INFO ) ELSE - CALL ZLAMSWLQ( SIDE, TRANS, M, N, K, MB, NB, A, LDA, WORK1(6), - $ MB, C, LDC, WORK2, LWORK2, INFO ) + CALL ZLAMSWLQ( SIDE, TRANS, M, N, K, MB, NB, A, LDA, T( 6 ), + $ MB, C, LDC, WORK, LWORK, INFO ) END IF * - WORK2(1) = LW + WORK( 1 ) = LW +* RETURN * * End of ZGEMLQ diff --git a/SRC/zgemqr.f b/SRC/zgemqr.f index 3141067f..ed67b45f 100644 --- a/SRC/zgemqr.f +++ b/SRC/zgemqr.f @@ -2,45 +2,52 @@ * Definition: * =========== * -* SUBROUTINE ZGEMQR( SIDE, TRANS, M, N, K, A, LDA, WORK1, -* $ LWORK1, C, LDC, WORK2, LWORK2, INFO ) +* SUBROUTINE ZGEMQR( SIDE, TRANS, M, N, K, A, LDA, T, +* $ TSIZE, C, LDC, WORK, LWORK, INFO ) * * * .. Scalar Arguments .. -* CHARACTER SIDE, TRANS -* INTEGER INFO, LDA, M, N, K, LDT, LWORK1, LWORK2, LDC +* CHARACTER SIDE, TRANS +* INTEGER INFO, LDA, M, N, K, LDT, TSIZE, LWORK, LDC * .. * .. Array Arguments .. -* COMPLEX*16 A( LDA, * ), WORK1( * ), C(LDC, * ), -* $ WORK2( * ) +* COMPLEX*16 A( LDA, * ), T( * ), C( LDC, * ), WORK( * ) +* .. +* *> \par Purpose: * ============= *> *> \verbatim *> -*> ZGEMQR overwrites the general real M-by-N matrix C with -*> +*> ZGEMQR overwrites the general real M-by-N matrix C with *> *> SIDE = 'L' SIDE = 'R' *> TRANS = 'N': Q * C C * Q -*> TRANS = 'T': Q**T * C C * Q**T -*> where Q is a complex orthogonal matrix defined as the product -*> of blocked elementary reflectors computed by tall skinny -*> QR factorization (ZGEQR) +*> TRANS = 'T': Q**H * C C * Q**H +*> +*> where Q is a complex unitary matrix defined as the product +*> of blocked elementary reflectors computed by tall skinny +*> QR factorization (ZGEQR) +*> *> \endverbatim * * Arguments: * ========== * *> \param[in] SIDE +*> \verbatim *> SIDE is CHARACTER*1 *> = 'L': apply Q or Q**T from the Left; *> = 'R': apply Q or Q**T from the Right. +*> \endverbatim *> *> \param[in] TRANS +*> \verbatim *> TRANS is CHARACTER*1 *> = 'N': No transpose, apply Q; *> = 'T': Transpose, apply Q**T. +*> \endverbatim +*> *> \param[in] M *> \verbatim *> M is INTEGER @@ -50,7 +57,7 @@ *> \param[in] N *> \verbatim *> N is INTEGER -*> The number of columns of the matrix C. M >= N >= 0. +*> The number of columns of the matrix C. N >= 0. *> \endverbatim *> *> \param[in] K @@ -58,17 +65,14 @@ *> K is INTEGER *> The number of elementary reflectors whose product defines *> the matrix Q. -*> N >= K >= 0; -*> +*> If SIDE = 'L', M >= K >= 0; +*> if SIDE = 'R', N >= K >= 0. *> \endverbatim *> -*> \param[in,out] A +*> \param[in] A *> \verbatim *> A is COMPLEX*16 array, dimension (LDA,K) -*> The i-th column must contain the vector which defines the -*> blockedelementary reflector H(i), for i = 1,2,...,k, as -*> returned by DGETSQR in the first k columns of -*> its array argument A. +*> Part of the data structure to represent Q as returned by ZGEQR. *> \endverbatim *> *> \param[in] LDA @@ -79,42 +83,46 @@ *> if SIDE = 'R', LDA >= max(1,N). *> \endverbatim *> -*> \param[in] WORK1 +*> \param[in] T *> \verbatim -*> WORK1 is COMPLEX*16 array, dimension (MAX(1,LWORK1)) as -*> it is returned by GEQR. +*> T is COMPLEX*16 array, dimension (MAX(5,TSIZE)). +*> Part of the data structure to represent Q as returned by ZGEQR. *> \endverbatim *> -*> \param[in] LWORK1 +*> \param[in] TSIZE *> \verbatim -*> LWORK1 is INTEGER -*> The dimension of the array WORK1. +*> TSIZE is INTEGER +*> The dimension of the array T. TSIZE >= 5. *> \endverbatim *> *> \param[in,out] C +*> \verbatim *> C is COMPLEX*16 array, dimension (LDC,N) *> On entry, the M-by-N matrix C. *> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +*> \endverbatim *> *> \param[in] LDC +*> \verbatim *> LDC is INTEGER *> The leading dimension of the array C. LDC >= max(1,M). +*> \endverbatim *> -*> \param[out] WORK2 +*> \param[out] WORK *> \verbatim -*> (workspace) COMPLEX*16 array, dimension (MAX(1,LWORK2)) -*> +*> (workspace) COMPLEX*16 array, dimension (MAX(1,LWORK)) *> \endverbatim -*> \param[in] LWORK2 -*> \verbatim -*> LWORK2 is INTEGER -*> The dimension of the array WORK2. -*> If LWORK2 = -1, then a workspace query is assumed; the routine -*> only calculates the optimal size of the WORK2 array, returns -*> this value as the third entry of the WORK2 array (WORK2(1)), -*> and no error message related to LWORK2 is issued by XERBLA. *> +*> \param[in] LWORK +*> \verbatim +*> LWORK is INTEGER +*> The dimension of the array WORK. +*> If LWORK = -1, then a workspace query is assumed. The routine +*> only calculates the size of the WORK array, returns this +*> value as WORK(1), and no error message related to WORK +*> is issued by XERBLA. *> \endverbatim +*> *> \param[out] INFO *> \verbatim *> INFO is INTEGER @@ -130,54 +138,64 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \par Further Details: -* ===================== +*> \par Further Details +* ==================== *> *> \verbatim +*> +*> These details are particular for this LAPACK implementation. Users should not +*> take them for granted. These details may change in the future, and are unlikely not +*> true for another LAPACK implementation. These details are relevant if one wants +*> to try to understand the code. They are not part of the interface. +*> +*> In this version, +*> +*> T(2): row block size (MB) +*> T(3): column block size (NB) +*> T(6:TSIZE): data structure needed for Q, computed by +*> ZLATSQR or ZGEQRT +*> *> Depending on the matrix dimensions M and N, and row and column -*> block sizes MB and NB returned by ILAENV, GEQR will use either -*> LATSQR (if the matrix is tall-and-skinny) or GEQRT to compute -*> the QR decomposition. -*> The output of LATSQR or GEQRT representing Q is stored in A and in -*> array WORK1(6:LWORK1) for later use. -*> WORK1(2:5) contains the matrix dimensions M,N and block sizes MB,NB -*> which are needed to interpret A and WORK1(6:LWORK1) for later use. -*> WORK1(1)=1 indicates that the code needed to take WORK1(2:5) and -*> decide whether LATSQR or GEQRT was used is the same as used below in -*> GEQR. For a detailed description of A and WORK1(6:LWORK1), see -*> Further Details in LATSQR or GEQRT. +*> block sizes MB and NB returned by ILAENV, ZGEQR will use either +*> ZLATSQR (if the matrix is tall-and-skinny) or ZGEQRT to compute +*> the QR factorization. +*> This version of ZGEMQR will use either ZLAMTSQR or ZGEMQRT to +*> multiply matrix Q by another matrix. +*> Further Details in ZLAMTSQR or ZGEMQRT. +*> *> \endverbatim *> * ===================================================================== - SUBROUTINE ZGEMQR( SIDE, TRANS, M, N, K, A, LDA, WORK1, LWORK1, - $ C, LDC, WORK2, LWORK2, INFO ) + SUBROUTINE ZGEMQR( SIDE, TRANS, M, N, K, A, LDA, T, TSIZE, + $ C, LDC, WORK, LWORK, INFO ) * -* -- LAPACK computational routine (version 3.5.0) -- +* -- LAPACK computational routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- -* November 2013 +* November 2016 * * .. Scalar Arguments .. - CHARACTER SIDE, TRANS - INTEGER INFO, LDA, M, N, K, LWORK1, LWORK2, LDC + CHARACTER SIDE, TRANS + INTEGER INFO, LDA, M, N, K, TSIZE, LWORK, LDC * .. * .. Array Arguments .. - COMPLEX*16 A( LDA, * ), WORK1( * ), C(LDC, * ), - $ WORK2( * ) + COMPLEX*16 A( LDA, * ), T( * ), C( LDC, * ), WORK( * ) * .. * * ===================================================================== * * .. * .. Local Scalars .. - LOGICAL LEFT, RIGHT, TRAN, NOTRAN, LQUERY - INTEGER MB, NB, I, II, KK, LW, NBLCKS, MN + LOGICAL LEFT, RIGHT, TRAN, NOTRAN, LQUERY + INTEGER MB, NB, LW, NBLCKS, MN * .. * .. External Functions .. LOGICAL LSAME EXTERNAL LSAME +* .. * .. External Subroutines .. EXTERNAL ZGEMQRT, ZLAMTSQR, XERBLA +* .. * .. Intrinsic Functions .. INTRINSIC INT, MAX, MIN, MOD * .. @@ -185,84 +203,83 @@ * * Test the input arguments * - LQUERY = LWORK2.LT.0 + LQUERY = LWORK.EQ.-1 NOTRAN = LSAME( TRANS, 'N' ) TRAN = LSAME( TRANS, 'C' ) LEFT = LSAME( SIDE, 'L' ) RIGHT = LSAME( SIDE, 'R' ) * - MB = INT(WORK1(4)) - NB = INT(WORK1(5)) - IF(LEFT) THEN + MB = INT( T( 2 ) ) + NB = INT( T( 3 ) ) + IF( LEFT ) THEN LW = N * NB MN = M - ELSE IF(RIGHT) THEN + ELSE LW = MB * NB MN = N END IF * - IF ((MB.GT.K).AND.(MN.GT.K)) THEN - IF(MOD(MN-K, MB-K).EQ.0) THEN - NBLCKS = (MN-K)/(MB-K) - ELSE - NBLCKS = (MN-K)/(MB-K) + 1 - END IF + IF( ( MB.GT.K ) .AND. ( MN.GT.K ) ) THEN + IF( MOD( MN - K, MB - K ).EQ.0 ) THEN + NBLCKS = ( MN - K ) / ( MB - K ) + ELSE + NBLCKS = ( MN - K ) / ( MB - K ) + 1 + END IF ELSE NBLCKS = 1 END IF * INFO = 0 IF( .NOT.LEFT .AND. .NOT.RIGHT ) THEN - INFO = -1 + INFO = -1 ELSE IF( .NOT.TRAN .AND. .NOT.NOTRAN ) THEN - INFO = -2 + INFO = -2 ELSE IF( M.LT.0 ) THEN INFO = -3 ELSE IF( N.LT.0 ) THEN INFO = -4 - ELSE IF( K.LT.0 ) THEN + ELSE IF( K.LT.0 .OR. K.GT.MN ) THEN INFO = -5 - ELSE IF( LDA.LT.MAX( 1, K ) ) THEN + ELSE IF( LDA.LT.MAX( 1, MN ) ) THEN INFO = -7 - ELSE IF( LWORK1.LT.MAX( 1, NB*K*NBLCKS+5 )) THEN + ELSE IF( TSIZE.LT.5 ) THEN INFO = -9 ELSE IF( LDC.LT.MAX( 1, M ) ) THEN - INFO = -11 - ELSE IF(( LWORK2.LT.MAX(1,LW)).AND.(.NOT.LQUERY)) THEN + INFO = -11 + ELSE IF( ( LWORK.LT.MAX( 1, LW ) ) .AND. ( .NOT.LQUERY ) ) THEN INFO = -13 END IF * -* Determine the block size if it is tall skinny or short and wide -* - IF( INFO.EQ.0) THEN - WORK2(1) = LW + IF( INFO.EQ.0 ) THEN + WORK( 1 ) = LW END IF * IF( INFO.NE.0 ) THEN CALL XERBLA( 'ZGEMQR', -INFO ) RETURN - ELSE IF (LQUERY) THEN - RETURN + ELSE IF( LQUERY ) THEN + RETURN END IF * * Quick return if possible * - IF( MIN(M,N,K).EQ.0 ) THEN + IF( MIN( M, N, K ).EQ.0 ) THEN RETURN END IF * - IF((LEFT.AND.M.LE.K).OR.(RIGHT.AND.N.LE.K).OR.(MB.LE.K).OR. - $ (MB.GE.MAX(M,N,K))) THEN - CALL ZGEMQRT( SIDE, TRANS, M, N, K, NB, A, LDA, - $ WORK1(6), NB, C, LDC, WORK2, INFO) + IF( ( LEFT .AND. M.LE.K ) .OR. ( RIGHT .AND. N.LE.K ) + $ .OR. ( MB.LE.K ) .OR. ( MB.GE.MAX( M, N, K ) ) ) THEN + CALL ZGEMQRT( SIDE, TRANS, M, N, K, NB, A, LDA, T( 6 ), + $ NB, C, LDC, WORK, INFO ) ELSE - CALL ZLAMTSQR( SIDE, TRANS, M, N, K, MB, NB, A, LDA, WORK1(6), - $ NB, C, LDC, WORK2, LWORK2, INFO ) + CALL ZLAMTSQR( SIDE, TRANS, M, N, K, MB, NB, A, LDA, T( 6 ), + $ NB, C, LDC, WORK, LWORK, INFO ) END IF * - WORK2(1) = LW + WORK( 1 ) = LW +* RETURN * -* End of DGEMQR +* End of ZGEMQR * END diff --git a/SRC/zgeqr.f b/SRC/zgeqr.f index 10fab97f..a38e47b5 100644 --- a/SRC/zgeqr.f +++ b/SRC/zgeqr.f @@ -2,14 +2,14 @@ * Definition: * =========== * -* SUBROUTINE ZGEQR( M, N, A, LDA, WORK1, LWORK1, WORK2, LWORK2, -* INFO) +* SUBROUTINE ZGEQR( M, N, A, LDA, T, TSIZE, WORK, LWORK, +* INFO ) * * .. Scalar Arguments .. -* INTEGER INFO, LDA, M, N, LWORK1, LWORK2 +* INTEGER INFO, LDA, M, N, TSIZE, LWORK * .. * .. Array Arguments .. -* COMPLEX*16 A( LDA, * ), WORK1( * ), WORK2( * ) +* COMPLEX*16 A( LDA, * ), T( * ), WORK( * ) * .. * * @@ -17,11 +17,7 @@ * ============= *> *> \verbatim -*> -*> ZGEQR computes a QR factorization of an M-by-N matrix A, -*> using ZLATSQR when A is tall and skinny -*> (M sufficiently greater than N), and otherwise ZGEQRT: -*> A = Q * R . +*> ZGEQR computes a QR factorization of an M-by-N matrix A. *> \endverbatim * * Arguments: @@ -46,7 +42,8 @@ *> On exit, the elements on and above the diagonal of the array *> contain the min(M,N)-by-N upper trapezoidal matrix R *> (R is upper triangular if M >= N); -*> the elements below the diagonal represent Q (see Further Details). +*> the elements below the diagonal are used to store part of the +*> data structure to represent Q. *> \endverbatim *> *> \param[in] LDA @@ -55,47 +52,50 @@ *> The leading dimension of the array A. LDA >= max(1,M). *> \endverbatim *> -*> \param[out] WORK1 +*> \param[out] T *> \verbatim -*> WORK1 is COMPLEX*16 array, dimension (MAX(1,LWORK1)) -*> WORK1 contains part of the data structure used to store Q. -*> WORK1(1): algorithm type = 1, to indicate output from -*> ZLATSQR or ZGEQRT -*> WORK1(2): optimum size of WORK1 -*> WORK1(3): minimum size of WORK1 -*> WORK1(4): row block size -*> WORK1(5): column block size -*> WORK1(6:LWORK1): data structure needed for Q, computed by -*> CLATSQR or CGEQRT +*> T is COMPLEX*16 array, dimension (MAX(5,TSIZE)) +*> On exit, if INFO = 0, T(1) returns optimal (or either minimal +*> or optimal, if query is assumed) TSIZE. See TSIZE for details. +*> Remaining T contains part of the data structure used to represent Q. +*> If one wants to apply or construct Q, then one needs to keep T +*> (in addition to A) and pass it to further subroutines. *> \endverbatim *> -*> \param[in] LWORK1 +*> \param[in] TSIZE *> \verbatim -*> LWORK1 is INTEGER -*> The dimension of the array WORK1. -*> If LWORK1 = -1, then a query is assumed. In this case the -*> routine calculates the optimal size of WORK1 and -*> returns this value in WORK1(2), and calculates the minimum -*> size of WORK1 and returns this value in WORK1(3). -*> No error message related to LWORK1 is issued by XERBLA when -*> LWORK1 = -1. +*> TSIZE is INTEGER +*> If TSIZE >= 5, the dimension of the array T. +*> If TSIZE = -1 or -2, then a workspace query is assumed. The routine +*> only calculates the sizes of the T and WORK arrays, returns these +*> values as the first entries of the T and WORK arrays, and no error +*> message related to T or WORK is issued by XERBLA. +*> If TSIZE = -1, the routine calculates optimal size of T for the +*> optimum performance and returns this value in T(1). +*> If TSIZE = -2, the routine calculates minimal size of T and +*> returns this value in T(1). *> \endverbatim *> -*> \param[out] WORK2 +*> \param[out] WORK *> \verbatim -*> (workspace) COMPLEX*16 array, dimension (MAX(1,LWORK2)) +*> (workspace) COMPLEX*16 array, dimension (MAX(1,LWORK)) +*> On exit, if INFO = 0, WORK(1) contains optimal (or either minimal +*> or optimal, if query was assumed) LWORK. +*> See LWORK for details. *> \endverbatim *> -*> \param[in] LWORK2 +*> \param[in] LWORK *> \verbatim -*> LWORK2 is INTEGER -*> The dimension of the array WORK2. -*> If LWORK2 = -1, then a query is assumed. In this case the -*> routine calculates the optimal size of WORK2 and -*> returns this value in WORK2(1), and calculates the minimum -*> size of WORK2 and returns this value in WORK2(2). -*> No error message related to LWORK2 is issued by XERBLA when -*> LWORK2 = -1. +*> LWORK is INTEGER +*> The dimension of the array WORK. +*> If LWORK = -1 or -2, then a workspace query is assumed. The routine +*> only calculates the sizes of the T and WORK arrays, returns these +*> values as the first entries of the T and WORK arrays, and no error +*> message related to T or WORK is issued by XERBLA. +*> If LWORK = -1, the routine calculates optimal size of WORK for the +*> optimal performance and returns this value in WORK(1). +*> If LWORK = -2, the routine calculates minimal size of WORK and +*> returns this value in WORK(1). *> \endverbatim *> *> \param[out] INFO @@ -113,106 +113,138 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \par Further Details: -* ===================== +*> \par Further Details +* ==================== +*> +*> \verbatim +*> +*> The goal of the interface is to give maximum freedom to the developers for +*> creating any QR factorization algorithm they wish. The triangular +*> (trapezoidal) R has to be stored in the upper part of A. The lower part of A +*> and the array T can be used to store any relevant information for applying or +*> constructing the Q factor. The WORK array can safely be discarded after exit. +*> +*> Caution: One should not expect the sizes of T and WORK to be the same from one +*> LAPACK implementation to the other, or even from one execution to the other. +*> A workspace query (for T and WORK) is needed at each execution. However, +*> for a given execution, the size of T and WORK are fixed and will not change +*> from one query to the next. +*> +*> \endverbatim +*> +*> \par Further Details particular to this LAPACK implementation: +* ============================================================== *> *> \verbatim +*> +*> These details are particular for this LAPACK implementation. Users should not +*> take them for granted. These details may change in the future, and are unlikely not +*> true for another LAPACK implementation. These details are relevant if one wants +*> to try to understand the code. They are not part of the interface. +*> +*> In this version, +*> +*> T(2): row block size (MB) +*> T(3): column block size (NB) +*> T(6:TSIZE): data structure needed for Q, computed by +*> ZLATSQR or ZGEQRT +*> *> Depending on the matrix dimensions M and N, and row and column -*> block sizes MB and NB returned by ILAENV, GEQR will use either -*> LATSQR (if the matrix is tall-and-skinny) or GEQRT to compute -*> the QR decomposition. -*> The output of LATSQR or GEQRT representing Q is stored in A and in -*> array WORK1(6:LWORK1) for later use. -*> WORK1(2:5) contains the matrix dimensions M,N and block sizes MB,NB -*> which are needed to interpret A and WORK1(6:LWORK1) for later use. -*> WORK1(1)=1 indicates that the code needed to take WORK1(2:5) and -*> decide whether LATSQR or GEQRT was used is the same as used below in -*> GEQR. For a detailed description of A and WORK1(6:LWORK1), see -*> Further Details in LATSQR or GEQRT. +*> block sizes MB and NB returned by ILAENV, ZGEQR will use either +*> ZLATSQR (if the matrix is tall-and-skinny) or ZGEQRT to compute +*> the QR factorization. +*> *> \endverbatim *> * ===================================================================== - SUBROUTINE ZGEQR( M, N, A, LDA, WORK1, LWORK1, WORK2, LWORK2, - $ INFO) + SUBROUTINE ZGEQR( M, N, A, LDA, T, TSIZE, WORK, LWORK, + $ INFO ) * -* -- LAPACK computational routine (version 3.5.0) -- +* -- LAPACK computational routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd. -- -* November 2013 +* November 2016 * * .. Scalar Arguments .. - INTEGER INFO, LDA, M, N, LWORK1, LWORK2 + INTEGER INFO, LDA, M, N, TSIZE, LWORK * .. * .. Array Arguments .. - COMPLEX*16 A( LDA, * ), WORK1( * ), WORK2( * ) + COMPLEX*16 A( LDA, * ), T( * ), WORK( * ) * .. * * ===================================================================== * * .. * .. Local Scalars .. - LOGICAL LQUERY, LMINWS - INTEGER MB, NB, I, II, KK, MINLW1, NBLCKS + LOGICAL LQUERY, LMINWS, MINT, MINW + INTEGER MB, NB, MINTSZ, NBLCKS * .. -* .. EXTERNAL FUNCTIONS .. +* .. External Functions .. LOGICAL LSAME EXTERNAL LSAME -* .. EXTERNAL SUBROUTINES .. - EXTERNAL ZLATSQR, ZGEQRT, XERBLA -* .. INTRINSIC FUNCTIONS .. +* .. +* .. External Subroutines .. + EXTERNAL ZLATSQR, ZGEQRT, XERBLA +* .. +* .. Intrinsic Functions .. INTRINSIC MAX, MIN, MOD * .. -* .. EXTERNAL FUNCTIONS .. +* .. External Functions .. INTEGER ILAENV EXTERNAL ILAENV * .. -* .. EXECUTABLE STATEMENTS .. +* .. Executable Statements .. * -* TEST THE INPUT ARGUMENTS +* Test the input arguments * INFO = 0 * - LQUERY = ( LWORK1.EQ.-1 .OR. LWORK2.EQ.-1 ) + LQUERY = ( TSIZE.EQ.-1 .OR. TSIZE.EQ.-2 .OR. + $ LWORK.EQ.-1 .OR. LWORK.EQ.-2 ) +* + MINT = .FALSE. + MINW = .FALSE. + IF( TSIZE.EQ.-2 .OR. LWORK.EQ.-2 ) THEN + IF( TSIZE.NE.-1 ) MINT = .TRUE. + IF( LWORK.NE.-1 ) MINW = .TRUE. + END IF * * Determine the block size * - IF ( MIN(M,N).GT.0 ) THEN - MB = ILAENV( 1, 'ZGEQR ', ' ', M, N, 1, -1) - NB = ILAENV( 1, 'ZGEQR ', ' ', M, N, 2, -1) + IF( MIN ( M, N ).GT.0 ) THEN + MB = ILAENV( 1, 'ZGEQR ', ' ', M, N, 1, -1 ) + NB = ILAENV( 1, 'ZGEQR ', ' ', M, N, 2, -1 ) ELSE MB = M NB = 1 END IF - IF( MB.GT.M.OR.MB.LE.N) MB = M - IF( NB.GT.MIN(M,N).OR.NB.LT.1) NB = 1 - MINLW1 = N + 5 - IF ((MB.GT.N).AND.(M.GT.N)) THEN - IF(MOD(M-N, MB-N).EQ.0) THEN - NBLCKS = (M-N)/(MB-N) + IF( MB.GT.M .OR. MB.LE.N ) MB = M + IF( NB.GT.MIN( M, N ) .OR. NB.LT.1 ) NB = 1 + MINTSZ = N + 5 + IF( MB.GT.N .AND. M.GT.N ) THEN + IF( MOD( M - N, MB - N ).EQ.0 ) THEN + NBLCKS = ( M - N ) / ( MB - N ) ELSE - NBLCKS = (M-N)/(MB-N) + 1 + NBLCKS = ( M - N ) / ( MB - N ) + 1 END IF ELSE NBLCKS = 1 END IF * -* Determine if the workspace size satisfies minimum size +* Determine if the workspace size satisfies minimal size * LMINWS = .FALSE. - IF((LWORK1.LT.MAX(1, NB*N*NBLCKS+5) - $ .OR.(LWORK2.LT.NB*N)).AND.(LWORK2.GE.N).AND.(LWORK1.GT.N+5) - $ .AND.(.NOT.LQUERY)) THEN - IF (LWORK1.LT.MAX(1, NB * N * NBLCKS+5)) THEN - LMINWS = .TRUE. - NB = 1 - END IF - IF (LWORK1.LT.MAX(1, N * NBLCKS+5)) THEN - LMINWS = .TRUE. - MB = M + IF( ( TSIZE.LT.MAX( 1, NB*N*NBLCKS + 5 ) .OR. LWORK.LT.NB*N ) + $ .AND. ( LWORK.GE.N ) .AND. ( TSIZE.GE.MINTSZ ) + $ .AND. ( .NOT.LQUERY ) ) THEN + IF( TSIZE.LT.MAX( 1, NB*N*NBLCKS + 5 ) ) THEN + LMINWS = .TRUE. + NB = 1 + MB = M END IF - IF (LWORK2.LT.NB*N) THEN - LMINWS = .TRUE. - NB = 1 + IF( LWORK.LT.NB*N ) THEN + LMINWS = .TRUE. + NB = 1 END IF END IF * @@ -222,44 +254,52 @@ INFO = -2 ELSE IF( LDA.LT.MAX( 1, M ) ) THEN INFO = -4 - ELSE IF( LWORK1.LT.MAX( 1, NB * N * NBLCKS + 5 ) - $ .AND.(.NOT.LQUERY).AND.(.NOT.LMINWS)) THEN + ELSE IF( TSIZE.LT.MAX( 1, NB*N*NBLCKS + 5 ) + $ .AND. ( .NOT.LQUERY ) .AND. ( .NOT.LMINWS ) ) THEN INFO = -6 - ELSE IF( (LWORK2.LT.MAX(1,N*NB)).AND.(.NOT.LQUERY) - $ .AND.(.NOT.LMINWS)) THEN + ELSE IF( ( LWORK.LT.MAX( 1, N*NB ) ) .AND. ( .NOT.LQUERY ) + $ .AND. ( .NOT.LMINWS ) ) THEN INFO = -8 END IF - - IF( INFO.EQ.0) THEN - WORK1(1) = 1 - WORK1(2) = NB * N * NBLCKS + 5 - WORK1(3) = MINLW1 - WORK1(4) = MB - WORK1(5) = NB - WORK2(1) = NB * N - WORK2(2) = N +* + IF( INFO.EQ.0 ) THEN + IF( MINT ) THEN + T( 1 ) = MINTSZ + ELSE + T( 1 ) = NB*N*NBLCKS + 5 + END IF + T( 2 ) = MB + T( 3 ) = NB + IF( MINW ) THEN + WORK( 1 ) = MAX( 1, N ) + ELSE + WORK( 1 ) = MAX( 1, NB*N ) + END IF END IF IF( INFO.NE.0 ) THEN CALL XERBLA( 'ZGEQR', -INFO ) RETURN - ELSE IF (LQUERY) THEN - RETURN + ELSE IF( LQUERY ) THEN + RETURN END IF * * Quick return if possible * - IF( MIN(M,N).EQ.0 ) THEN - RETURN + IF( MIN( M, N ).EQ.0 ) THEN + RETURN END IF * * The QR Decomposition * - IF((M.LE.N).OR.(MB.LE.N).OR.(MB.GE.M)) THEN - CALL ZGEQRT( M, N, NB, A, LDA, WORK1(6), NB, WORK2, INFO) + IF( ( M.LE.N ) .OR. ( MB.LE.N ) .OR. ( MB.GE.M ) ) THEN + CALL ZGEQRT( M, N, NB, A, LDA, T( 6 ), NB, WORK, INFO ) ELSE - CALL ZLATSQR( M, N, MB, NB, A, LDA, WORK1(6), NB, WORK2, - $ LWORK2, INFO) + CALL ZLATSQR( M, N, MB, NB, A, LDA, T( 6 ), NB, WORK, + $ LWORK, INFO ) END IF +* + WORK( 1 ) = MAX( 1, NB*N ) +* RETURN * * End of ZGEQR diff --git a/SRC/zgetsls.f b/SRC/zgetsls.f index d61b88c3..6dc6a843 100644 --- a/SRC/zgetsls.f +++ b/SRC/zgetsls.f @@ -1,16 +1,15 @@ * Definition: * =========== * -* SUBROUTINE ZGETSLS( TRANS, M, N, NRHS, A, LDA, B, LDB -* $ , WORK, LWORK, INFO ) - +* SUBROUTINE ZGETSLS( TRANS, M, N, NRHS, A, LDA, B, LDB, +* $ WORK, LWORK, INFO ) * * .. Scalar Arguments .. * CHARACTER TRANS * INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS * .. * .. Array Arguments .. -* COMPLEX*16 A( LDA, * ), B( LDB, * ), WORK( * ) +* COMPLEX*16 A( LDA, * ), B( LDB, * ), WORK( * ) * .. * * @@ -19,10 +18,11 @@ *> *> \verbatim *> -*> ZGETSLS solves overdetermined or underdetermined real linear systems -*> involving an M-by-N matrix A, or its transpose, using a tall skinny -*> QR or short wide LQfactorization of A. It is assumed that A has -*> full rank. +*> ZGETSLS solves overdetermined or underdetermined complex linear systems +*> involving an M-by-N matrix A, using a tall skinny QR or short wide LQ +*> factorization of A. It is assumed that A has full rank. +*> +*> *> *> The following options are provided: *> @@ -80,10 +80,8 @@ *> A is COMPLEX*16 array, dimension (LDA,N) *> On entry, the M-by-N matrix A. *> On exit, -*> if M >= N, A is overwritten by details of its QR -*> factorization as returned by DGEQRF; -*> if M < N, A is overwritten by details of its LQ -*> factorization as returned by DGELQF. +*> A is overwritten by details of its QR or LQ +*> factorization as returned by ZGEQR or ZGELQ. *> \endverbatim *> *> \param[in] LDA @@ -97,21 +95,17 @@ *> B is COMPLEX*16 array, dimension (LDB,NRHS) *> On entry, the matrix B of right hand side vectors, stored *> columnwise; B is M-by-NRHS if TRANS = 'N', or N-by-NRHS -*> if TRANS = 'T'. +*> if TRANS = 'C'. *> On exit, if INFO = 0, B is overwritten by the solution *> vectors, stored columnwise: *> if TRANS = 'N' and m >= n, rows 1 to n of B contain the least -*> squares solution vectors; the residual sum of squares for the -*> solution in each column is given by the sum of squares of -*> elements N+1 to M in that column; +*> squares solution vectors. *> if TRANS = 'N' and m < n, rows 1 to N of B contain the *> minimum norm solution vectors; -*> if TRANS = 'T' and m >= n, rows 1 to M of B contain the +*> if TRANS = 'C' and m >= n, rows 1 to M of B contain the *> minimum norm solution vectors; -*> if TRANS = 'T' and m < n, rows 1 to M of B contain the -*> least squares solution vectors; the residual sum of squares -*> for the solution in each column is given by the sum of -*> squares of elements M+1 to N in that column. +*> if TRANS = 'C' and m < n, rows 1 to M of B contain the +*> least squares solution vectors. *> \endverbatim *> *> \param[in] LDB @@ -122,23 +116,21 @@ *> *> \param[out] WORK *> \verbatim -*> WORK is COMPLEX*16 array, dimension (MAX(1,LWORK)) -*> On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +*> (workspace) COMPLEX*16 array, dimension (MAX(1,LWORK)) +*> On exit, if INFO = 0, WORK(1) contains optimal (or either minimal +*> or optimal, if query was assumed) LWORK. +*> See LWORK for details. *> \endverbatim *> *> \param[in] LWORK *> \verbatim *> LWORK is INTEGER *> The dimension of the array WORK. -*> LWORK >= max( 1, MN + max( MN, NRHS ) ). -*> For optimal performance, -*> LWORK >= max( 1, MN + max( MN, NRHS )*NB ). -*> where MN = min(M,N) and NB is the optimum block size. -*> -*> If LWORK = -1, then a workspace query is assumed; the routine -*> only calculates the optimal size of the WORK array, returns -*> this value as the first entry of the WORK array, and no error -*> message related to LWORK is issued by XERBLA. +*> If LWORK = -1 or -2, then a workspace query is assumed. +*> If LWORK = -1, the routine calculates optimal size of WORK for the +*> optimal performance and returns this value in WORK(1). +*> If LWORK = -2, the routine calculates minimal size of WORK and +*> returns this value in WORK(1). *> \endverbatim *> *> \param[out] INFO @@ -160,23 +152,25 @@ *> \author Univ. of Colorado Denver *> \author NAG Ltd. * -*> \date November 2011 +*> \date November 2016 +* +*> \ingroup complex16GEsolve * * ===================================================================== - SUBROUTINE ZGETSLS( TRANS, M, N, NRHS, A, LDA, B, LDB - $ , WORK, LWORK, INFO ) + SUBROUTINE ZGETSLS( TRANS, M, N, NRHS, A, LDA, B, LDB, + $ WORK, LWORK, INFO ) * -* -- LAPACK driver routine (version 3.4.0) -- +* -- LAPACK driver routine (version 3.7.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- -* November 2011 +* November 2016 * * .. Scalar Arguments .. CHARACTER TRANS - INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, MB, NB + INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS * .. * .. Array Arguments .. - COMPLEX*16 A( LDA, * ), B( LDB, * ), WORK( * ) + COMPLEX*16 A( LDA, * ), B( LDB, * ), WORK( * ) * * .. * @@ -190,9 +184,11 @@ * .. * .. Local Scalars .. LOGICAL LQUERY, TRAN - INTEGER I, IASCL, IBSCL, J, MINMN, MAXMN, BROW, LW, - $ SCLLEN, MNK, WSIZEO, WSIZEM, LW1, LW2, INFO2 + INTEGER I, IASCL, IBSCL, J, MINMN, MAXMN, BROW, + $ SCLLEN, MNK, TSZO, TSZM, LWO, LWM, LW1, LW2, + $ WSIZEO, WSIZEM, INFO2 DOUBLE PRECISION ANRM, BIGNUM, BNRM, SMLNUM + COMPLEX*16 TQ( 5 ), WORKQ * .. * .. External Functions .. LOGICAL LSAME @@ -205,19 +201,19 @@ $ ZTRTRS, XERBLA, ZGELQ, ZGEMLQ * .. * .. Intrinsic Functions .. - INTRINSIC DBLE, MAX, MIN + INTRINSIC DBLE, MAX, MIN, INT * .. * .. Executable Statements .. * * Test the input arguments. * - INFO=0 + INFO = 0 MINMN = MIN( M, N ) MAXMN = MAX( M, N ) - MNK = MAX(MINMN,NRHS) + MNK = MAX( MINMN, NRHS ) TRAN = LSAME( TRANS, 'C' ) * - LQUERY = ( LWORK.EQ.-1 ) + LQUERY = ( LWORK.EQ.-1 .OR. LWORK.EQ.-2 ) IF( .NOT.( LSAME( TRANS, 'N' ) .OR. $ LSAME( TRANS, 'C' ) ) ) THEN INFO = -1 @@ -233,60 +229,71 @@ INFO = -8 END IF * - IF( INFO.EQ.0) THEN + IF( INFO.EQ.0 ) THEN * * Determine the block size and minimum LWORK * - IF ( M.GE.N ) THEN - CALL ZGEQR( M, N, A, LDA, WORK(1), -1, WORK(6), -1, - $ INFO2) - MB = INT(WORK(4)) - NB = INT(WORK(5)) - LW = INT(WORK(6)) - CALL ZGEMQR( 'L', TRANS, M, NRHS, N, A, LDA, WORK(1), - $ INT(WORK(2)), B, LDB, WORK(6), -1 , INFO2 ) - WSIZEO = INT(WORK(2))+MAX(LW,INT(WORK(6))) - WSIZEM = INT(WORK(3))+MAX(LW,INT(WORK(6))) - ELSE - CALL ZGELQ( M, N, A, LDA, WORK(1), -1, WORK(6), -1, - $ INFO2) - MB = INT(WORK(4)) - NB = INT(WORK(5)) - LW = INT(WORK(6)) - CALL ZGEMLQ( 'L', TRANS, N, NRHS, M, A, LDA, WORK(1), - $ INT(WORK(2)), B, LDB, WORK(6), -1 , INFO2 ) - WSIZEO = INT(WORK(2))+MAX(LW,INT(WORK(6))) - WSIZEM = INT(WORK(3))+MAX(LW,INT(WORK(6))) - END IF + IF( M.GE.N ) THEN + CALL ZGEQR( M, N, A, LDA, TQ, -1, WORKQ, -1, INFO2 ) + TSZO = INT( TQ( 1 ) ) + LWO = INT( WORKQ ) + CALL ZGEMQR( 'L', TRANS, M, NRHS, N, A, LDA, TQ, + $ TSZO, B, LDB, WORKQ, -1, INFO2 ) + LWO = MAX( LWO, INT( WORKQ ) ) + CALL ZGEQR( M, N, A, LDA, TQ, -2, WORKQ, -2, INFO2 ) + TSZM = INT( TQ( 1 ) ) + LWM = INT( WORKQ ) + CALL ZGEMQR( 'L', TRANS, M, NRHS, N, A, LDA, TQ, + $ TSZM, B, LDB, WORKQ, -1, INFO2 ) + LWM = MAX( LWM, INT( WORKQ ) ) + WSIZEO = TSZO + LWO + WSIZEM = TSZM + LWM + ELSE + CALL ZGELQ( M, N, A, LDA, TQ, -1, WORKQ, -1, INFO2 ) + TSZO = INT( TQ( 1 ) ) + LWO = INT( WORKQ ) + CALL ZGEMLQ( 'L', TRANS, N, NRHS, M, A, LDA, TQ, + $ TSZO, B, LDB, WORKQ, -1, INFO2 ) + LWO = MAX( LWO, INT( WORKQ ) ) + CALL ZGELQ( M, N, A, LDA, TQ, -2, WORKQ, -2, INFO2 ) + TSZM = INT( TQ( 1 ) ) + LWM = INT( WORKQ ) + CALL ZGEMLQ( 'L', TRANS, N, NRHS, M, A, LDA, TQ, + $ TSZO, B, LDB, WORKQ, -1, INFO2 ) + LWM = MAX( LWM, INT( WORKQ ) ) + WSIZEO = TSZO + LWO + WSIZEM = TSZM + LWM + END IF * - IF((LWORK.LT.WSIZEO).AND.(.NOT.LQUERY)) THEN - INFO=-10 + IF( ( LWORK.LT.WSIZEM ).AND.( .NOT.LQUERY ) ) THEN + INFO = -10 END IF +* END IF * IF( INFO.NE.0 ) THEN CALL XERBLA( 'ZGETSLS', -INFO ) WORK( 1 ) = DBLE( WSIZEO ) - WORK( 2 ) = DBLE( WSIZEM ) RETURN - ELSE IF (LQUERY) THEN - WORK( 1 ) = DBLE( WSIZEO ) - WORK( 2 ) = DBLE( WSIZEM ) + END IF + IF( LQUERY ) THEN + IF( LWORK.EQ.-1 ) WORK( 1 ) = REAL( WSIZEO ) + IF( LWORK.EQ.-2 ) WORK( 1 ) = REAL( WSIZEM ) RETURN END IF - IF(LWORK.LT.WSIZEO) THEN - LW1=INT(WORK(3)) - LW2=MAX(LW,INT(WORK(6))) + IF( LWORK.LT.WSIZEO ) THEN + LW1 = TSZM + LW2 = LWM ELSE - LW1=INT(WORK(2)) - LW2=MAX(LW,INT(WORK(6))) + LW1 = TSZO + LW2 = LWO END IF * * Quick return if possible * IF( MIN( M, N, NRHS ).EQ.0 ) THEN CALL ZLASET( 'FULL', MAX( M, N ), NRHS, CZERO, CZERO, - $ B, LDB ) + $ B, LDB ) RETURN END IF * @@ -342,26 +349,27 @@ IBSCL = 2 END IF * - IF ( M.GE.N) THEN + IF ( M.GE.N ) THEN * * compute QR factorization of A * - CALL ZGEQR( M, N, A, LDA, WORK(LW2+1), LW1 - $ , WORK(1), LW2, INFO ) - IF (.NOT.TRAN) THEN + CALL ZGEQR( M, N, A, LDA, WORK( LW2+1 ), LW1, + $ WORK( 1 ), LW2, INFO ) + IF ( .NOT.TRAN ) THEN * * Least-Squares Problem min || A * X - B || * * B(1:M,1:NRHS) := Q**T * B(1:M,1:NRHS) * CALL ZGEMQR( 'L' , 'C', M, NRHS, N, A, LDA, - $ WORK(LW2+1), LW1, B, LDB, WORK(1), LW2, INFO ) + $ WORK( LW2+1 ), LW1, B, LDB, WORK( 1 ), LW2, + $ INFO ) * * B(1:N,1:NRHS) := inv(R) * B(1:N,1:NRHS) * CALL ZTRTRS( 'U', 'N', 'N', N, NRHS, - $ A, LDA, B, LDB, INFO ) - IF(INFO.GT.0) THEN + $ A, LDA, B, LDB, INFO ) + IF( INFO.GT.0 ) THEN RETURN END IF SCLLEN = N @@ -389,7 +397,7 @@ * B(1:M,1:NRHS) := Q(1:N,:) * B(1:N,1:NRHS) * CALL ZGEMQR( 'L', 'N', M, NRHS, N, A, LDA, - $ WORK( LW2+1), LW1, B, LDB, WORK( 1 ), LW2, + $ WORK( LW2+1 ), LW1, B, LDB, WORK( 1 ), LW2, $ INFO ) * SCLLEN = M @@ -400,8 +408,8 @@ * * Compute LQ factorization of A * - CALL ZGELQ( M, N, A, LDA, WORK(LW2+1), LW1 - $ , WORK(1), LW2, INFO ) + CALL ZGELQ( M, N, A, LDA, WORK( LW2+1 ), LW1, + $ WORK( 1 ), LW2, INFO ) * * workspace at least M, optimally M*NB. * @@ -429,7 +437,7 @@ * B(1:N,1:NRHS) := Q(1:N,:)**T * B(1:M,1:NRHS) * CALL ZGEMLQ( 'L', 'C', N, NRHS, M, A, LDA, - $ WORK( LW2+1), LW1, B, LDB, WORK( 1 ), LW2, + $ WORK( LW2+1 ), LW1, B, LDB, WORK( 1 ), LW2, $ INFO ) * * workspace at least NRHS, optimally NRHS*NB @@ -443,7 +451,7 @@ * B(1:N,1:NRHS) := Q * B(1:N,1:NRHS) * CALL ZGEMLQ( 'L', 'N', N, NRHS, M, A, LDA, - $ WORK( LW2+1), LW1, B, LDB, WORK( 1 ), LW2, + $ WORK( LW2+1 ), LW1, B, LDB, WORK( 1 ), LW2, $ INFO ) * * workspace at least NRHS, optimally NRHS*NB @@ -467,22 +475,21 @@ * IF( IASCL.EQ.1 ) THEN CALL ZLASCL( 'G', 0, 0, ANRM, SMLNUM, SCLLEN, NRHS, B, LDB, - $ INFO ) + $ INFO ) ELSE IF( IASCL.EQ.2 ) THEN CALL ZLASCL( 'G', 0, 0, ANRM, BIGNUM, SCLLEN, NRHS, B, LDB, - $ INFO ) + $ NFO ) END IF IF( IBSCL.EQ.1 ) THEN - CALL ZLASCL( 'G', 0, 0, SMLNUM, BNRM, SCLLEN, NRHS, B, LDB, - $ INFO ) + CALL ZLASCL( 'G', 0, 0, SMLNUM, BNRM, SCLLEN, NRHS, B, LDB, + $ INFO ) ELSE IF( IBSCL.EQ.2 ) THEN - CALL ZLASCL( 'G', 0, 0, BIGNUM, BNRM, SCLLEN, NRHS, B, LDB, - $ INFO ) + CALL ZLASCL( 'G', 0, 0, BIGNUM, BNRM, SCLLEN, NRHS, B, LDB, + $ INFO ) END IF * 50 CONTINUE - WORK( 1 ) = DBLE( WSIZEO ) - WORK( 2 ) = DBLE( WSIZEM ) + WORK( 1 ) = DBLE( TSZO + LWO ) RETURN * * End of ZGETSLS diff --git a/SRC/zlamswlq.f b/SRC/zlamswlq.f index 365530c3..a0268d86 100644 --- a/SRC/zlamswlq.f +++ b/SRC/zlamswlq.f @@ -33,14 +33,19 @@ * ========== * *> \param[in] SIDE +*> \verbatim *> SIDE is CHARACTER*1 *> = 'L': apply Q or Q**T from the Left; *> = 'R': apply Q or Q**T from the Right. +*> \endverbatim *> *> \param[in] TRANS +*> \verbatim *> TRANS is CHARACTER*1 *> = 'N': No transpose, apply Q; *> = 'T': Transpose, apply Q**T. +*> \endverbatim +*> *> \param[in] M *> \verbatim *> M is INTEGER @@ -115,18 +120,23 @@ *> \endverbatim *> *> \param[in,out] C +*> \verbatim *> C is COMPLEX*16 array, dimension (LDC,N) *> On entry, the M-by-N matrix C. *> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +*> \endverbatim +*> *> \param[in] LDC +*> \verbatim *> LDC is INTEGER *> The leading dimension of the array C. LDC >= max(1,M). +*> \endverbatim *> *> \param[out] WORK *> \verbatim *> (workspace) COMPLEX*16 array, dimension (MAX(1,LWORK)) -*> *> \endverbatim +*> *> \param[in] LWORK *> \verbatim *> LWORK is INTEGER @@ -137,8 +147,8 @@ *> only calculates the optimal size of the WORK array, returns *> this value as the first entry of the WORK array, and no error *> message related to LWORK is issued by XERBLA. -*> *> \endverbatim +*> *> \param[out] INFO *> \verbatim *> INFO is INTEGER diff --git a/SRC/zlamtsqr.f b/SRC/zlamtsqr.f index 7195f9e1..103049c2 100644 --- a/SRC/zlamtsqr.f +++ b/SRC/zlamtsqr.f @@ -33,14 +33,19 @@ * ========== * *> \param[in] SIDE +*> \verbatim *> SIDE is CHARACTER*1 *> = 'L': apply Q or Q**T from the Left; *> = 'R': apply Q or Q**T from the Right. +*> \endverbatim *> *> \param[in] TRANS +*> \verbatim *> TRANS is CHARACTER*1 *> = 'N': No transpose, apply Q; *> = 'C': Conjugate Transpose, apply Q**C. +*> \endverbatim +*> *> \param[in] M *> \verbatim *> M is INTEGER @@ -109,12 +114,17 @@ *> \endverbatim *> *> \param[in,out] C +*> \verbatim *> C is COMPLEX*16 array, dimension (LDC,N) *> On entry, the M-by-N matrix C. *> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +*> \endverbatim +*> *> \param[in] LDC +*> \verbatim *> LDC is INTEGER *> The leading dimension of the array C. LDC >= max(1,M). +*> \endverbatim *> *> \param[out] WORK *> \verbatim @@ -310,9 +320,9 @@ * KK = MOD((M-K),(MB-K)) II=M-KK+1 + CTR = 1 CALL ZGEMQRT('L','C',MB , N, K, NB, A(1,1), LDA, T $ ,LDT ,C(1,1), LDC, WORK, INFO ) - CTR = 1 * DO I=MB+1,II-MB+K,(MB-K) * @@ -350,11 +360,11 @@ END IF * DO I=II-(MB-K),MB+1,-(MB-K) - CTR = CTR - 1 * * Multiply Q to the current block of C (1:M,I:I+MB) * - CALL ZTPMQRT('R','C',M , MB-K, K, 0,NB, A(I,1), LDA, + CTR = CTR - 1 + CALL ZTPMQRT('R','C',M , MB-K, K, 0,NB, A(I,1), LDA, $ T(1, CTR * K + 1), LDT, C(1,1), LDC, $ C(1,I), LDC, WORK, INFO ) @@ -371,9 +381,9 @@ * KK = MOD((N-K),(MB-K)) II=N-KK+1 + CTR = 1 CALL ZGEMQRT('R','N', M, MB , K, NB, A(1,1), LDA, T $ ,LDT ,C(1,1), LDC, WORK, INFO ) - CTR = 1 * DO I=MB+1,II-MB+K,(MB-K) * diff --git a/TESTING/LIN/cchkaa.f b/TESTING/LIN/cchkaa.f index f2ef59f1..5881043f 100644 --- a/TESTING/LIN/cchkaa.f +++ b/TESTING/LIN/cchkaa.f @@ -1047,8 +1047,7 @@ CALL CDRVLS( DOTYPE, NM, MVAL, NN, NVAL, NNS, NSVAL, NNB, $ NBVAL, NXVAL, THRESH, TSTERR, A( 1, 1 ), $ A( 1, 2 ), A( 1, 3 ), A( 1, 4 ), A( 1, 5 ), - $ S( 1 ), S( NMAX+1 ), WORK, RWORK, IWORK, - $ NOUT ) + $ S( 1 ), S( NMAX+1 ), NOUT ) ELSE WRITE( NOUT, FMT = 9989 )PATH END IF diff --git a/TESTING/LIN/cdrvls.f b/TESTING/LIN/cdrvls.f index ededde5a..49c99354 100644 --- a/TESTING/LIN/cdrvls.f +++ b/TESTING/LIN/cdrvls.f @@ -10,8 +10,7 @@ * * SUBROUTINE CDRVLS( DOTYPE, NM, MVAL, NN, NVAL, NNS, NSVAL, NNB, * NBVAL, NXVAL, THRESH, TSTERR, A, COPYA, B, -* COPYB, C, S, COPYS, WORK, RWORK, IWORK, -* NOUT ) +* COPYB, C, S, COPYS, NOUT ) * * .. Scalar Arguments .. * LOGICAL TSTERR @@ -20,11 +19,10 @@ * .. * .. Array Arguments .. * LOGICAL DOTYPE( * ) -* INTEGER IWORK( * ), MVAL( * ), NBVAL( * ), NSVAL( * ), +* INTEGER MVAL( * ), NBVAL( * ), NSVAL( * ), * $ NVAL( * ), NXVAL( * ) -* REAL COPYS( * ), RWORK( * ), S( * ) -* COMPLEX A( * ), B( * ), C( * ), COPYA( * ), COPYB( * ), -* $ WORK( * ) +* REAL COPYS( * ), S( * ) +* COMPLEX A( * ), B( * ), C( * ), COPYA( * ), COPYB( * ) * .. * * @@ -33,7 +31,7 @@ *> *> \verbatim *> -*> CDRVLS tests the least squares driver routines CGELS, CGELSS, CGELSY +*> CDRVLS tests the least squares driver routines CGELS, CGETSLS, CGELSS, CGELSY *> and CGELSD. *> \endverbatim * @@ -171,22 +169,6 @@ *> (min(MMAX,NMAX)) *> \endverbatim *> -*> \param[out] WORK -*> \verbatim -*> WORK is COMPLEX array, dimension -*> (MMAX*NMAX + 4*NMAX + MMAX). -*> \endverbatim -*> -*> \param[out] RWORK -*> \verbatim -*> RWORK is REAL array, dimension (5*NMAX-1) -*> \endverbatim -*> -*> \param[out] IWORK -*> \verbatim -*> IWORK is INTEGER array, dimension (15*NMAX) -*> \endverbatim -*> *> \param[in] NOUT *> \verbatim *> NOUT is INTEGER @@ -208,8 +190,7 @@ * ===================================================================== SUBROUTINE CDRVLS( DOTYPE, NM, MVAL, NN, NVAL, NNS, NSVAL, NNB, $ NBVAL, NXVAL, THRESH, TSTERR, A, COPYA, B, - $ COPYB, C, S, COPYS, WORK, RWORK, IWORK, - $ NOUT ) + $ COPYB, C, S, COPYS, NOUT ) * * -- LAPACK test routine (version 3.6.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- @@ -223,11 +204,10 @@ * .. * .. Array Arguments .. LOGICAL DOTYPE( * ) - INTEGER IWORK( * ), MVAL( * ), NBVAL( * ), NSVAL( * ), + INTEGER MVAL( * ), NBVAL( * ), NSVAL( * ), $ NVAL( * ), NXVAL( * ) - REAL COPYS( * ), RWORK( * ), S( * ) - COMPLEX A( * ), B( * ), C( * ), COPYA( * ), COPYB( * ), - $ WORK( * ) + REAL COPYS( * ), S( * ) + COMPLEX A( * ), B( * ), C( * ), COPYA( * ), COPYB( * ) * .. * * ===================================================================== @@ -249,12 +229,22 @@ INTEGER CRANK, I, IM, IMB, IN, INB, INFO, INS, IRANK, $ ISCALE, ITRAN, ITYPE, J, K, LDA, LDB, LDWORK, $ LWLSY, LWORK, M, MNMIN, N, NB, NCOLS, NERRS, - $ NFAIL, NRHS, NROWS, NRUN, RANK, MB, LWTS + $ NFAIL, NRHS, NROWS, NRUN, RANK, MB, + $ MMAX, NMAX, NSMAX, LIWORK, LRWORK, + $ LWORK_CGELS, LWORK_CGETSLS, LWORK_CGELSS, + $ LWORK_CGELSY, LWORK_CGELSD, + $ LRWORK_CGELSY, LRWORK_CGELSS, LRWORK_CGELSD REAL EPS, NORMA, NORMB, RCOND * .. * .. Local Arrays .. - INTEGER ISEED( 4 ), ISEEDY( 4 ) - REAL RESULT( NTESTS ) + INTEGER ISEED( 4 ), ISEEDY( 4 ), IWORKQUERY + REAL RESULT( NTESTS ), RWORKQUERY + COMPLEX WORKQUERY +* .. +* .. Allocatable Arrays .. + COMPLEX, ALLOCATABLE :: WORK (:) + REAL, ALLOCATABLE :: RWORK (:) + INTEGER, ALLOCATABLE :: IWORK (:) * .. * .. External Functions .. REAL CQRT12, CQRT14, CQRT17, SASUM, SLAMCH @@ -267,7 +257,7 @@ $ SAXPY, XLAENV * .. * .. Intrinsic Functions .. - INTRINSIC MAX, MIN, REAL, SQRT + INTRINSIC MAX, MIN, INT, REAL, SQRT * .. * .. Scalars in Common .. LOGICAL LERR, OK @@ -311,6 +301,77 @@ $ CALL ALAHD( NOUT, PATH ) INFOT = 0 * +* Compute maximal workspace needed for all routines +* + NMAX = 0 + MMAX = 0 + NSMAX = 0 + DO I = 1, NM + IF ( MVAL( I ).GT.MMAX ) THEN + MMAX = MVAL( I ) + END IF + ENDDO + DO I = 1, NN + IF ( NVAL( I ).GT.NMAX ) THEN + NMAX = NVAL( I ) + END IF + ENDDO + DO I = 1, NNS + IF ( NSVAL( I ).GT.NSMAX ) THEN + NSMAX = NSVAL( I ) + END IF + ENDDO + M = MMAX + N = NMAX + NRHS = NSMAX + LDA = MAX( 1, M ) + LDB = MAX( 1, M, N ) + MNMIN = MAX( MIN( M, N ), 1 ) +* +* Compute workspace needed for routines +* CQRT14, CQRT17 (two side cases), CQRT15 and CQRT12 +* + LWORK = MAX( ( M+N )*NRHS, + $ ( N+NRHS )*( M+2 ), ( M+NRHS )*( N+2 ), + $ MAX( M+MNMIN, NRHS*MNMIN,2*N+M ), + $ MAX( M*N+4*MNMIN+MAX(M,N), M*N+2*MNMIN+4*N ) ) +* +* Compute workspace needed for CGELS + CALL CGELS( 'N', M, N, NRHS, A, LDA, B, LDB, + $ WORKQUERY, -1, INFO ) + LWORK_CGELS = INT( WORKQUERY ) +* Compute workspace needed for CGETSLS + CALL CGETSLS( 'N', M, N, NRHS, A, LDA, B, LDB, + $ WORKQUERY, -1, INFO ) + LWORK_CGETSLS = INT( WORKQUERY ) +* Compute workspace needed for CGELSY + CALL CGELSY( M, N, NRHS, A, LDA, B, LDB, IWORKQUERY, + $ RCOND, CRANK, WORKQUERY, -1, RWORK, INFO ) + LWORK_CGELSY = INT( WORKQUERY ) + LRWORK_CGELSY = 2*N +* Compute workspace needed for CGELSS + CALL CGELSS( M, N, NRHS, A, LDA, B, LDB, S, + $ RCOND, CRANK, WORKQUERY, -1, RWORK, INFO ) + LWORK_CGELSS = INT( WORKQUERY ) + LRWORK_CGELSS = 5*MNMIN +* Compute workspace needed for CGELSD + CALL CGELSD( M, N, NRHS, A, LDA, B, LDB, S, RCOND, CRANK, + $ WORKQUERY, -1, RWORKQUERY, IWORKQUERY, INFO ) + LWORK_CGELSD = INT( WORKQUERY ) + LRWORK_CGELSD = INT( RWORKQUERY ) +* Compute LIWORK workspace needed for CGELSY and CGELSD + LIWORK = MAX( 1, N, IWORKQUERY ) +* Compute LRWORK workspace needed for CGELSY, CGELSS and CGELSD + LRWORK = MAX( 1, LRWORK_CGELSY, LRWORK_CGELSS, LRWORK_CGELSD ) +* Compute LWORK workspace needed for all functions + LWORK = MAX( 1, LWORK, LWORK_CGELS, LWORK_CGETSLS, LWORK_CGELSY, + $ LWORK_CGELSS, LWORK_CGELSD ) + LWLSY = LWORK +* + ALLOCATE( WORK( LWORK ) ) + ALLOCATE( IWORK( LIWORK ) ) + ALLOCATE( RWORK( LRWORK ) ) +* DO 140 IM = 1, NM M = MVAL( IM ) LDA = MAX( 1, M ) @@ -320,16 +381,9 @@ MNMIN = MAX(MIN( M, N ),1) LDB = MAX( 1, M, N ) MB = (MNMIN+1) - IF(MNMIN.NE.MB) THEN - LWTS = (((LDB-MB)/(MB-MNMIN))*MNMIN+MNMIN*2)*MB+5 - ELSE - LWTS = 2*MNMIN+5 - END IF * DO 120 INS = 1, NNS NRHS = NSVAL( INS ) - LWORK = MAX( 1, ( M+NRHS )*( N+2 ), ( N+NRHS )*( M+2 ), - $ M*N+4*MNMIN+MAX( M, N ), 2*N+M, LWTS ) * DO 110 IRANK = 1, 2 DO 100 ISCALE = 1, 3 @@ -580,12 +634,6 @@ IWORK( J ) = 0 70 CONTINUE * -* Set LWLSY to the adequate value. -* - LWLSY = MNMIN + MAX( 2*MNMIN, NB*( N+1 ), - $ MNMIN+NB*NRHS ) - LWLSY = MAX( 1, LWLSY ) -* SRNAMT = 'CGELSY' CALL CGELSY( M, N, NRHS, A, LDA, B, LDB, IWORK, $ RCOND, CRANK, WORK, LWLSY, RWORK, @@ -776,6 +824,10 @@ 9997 FORMAT( ' TRANS=''', A1,' M=', I5, ', N=', I5, ', NRHS=', I4, $ ', MB=', I4,', NB=', I4,', type', I2, $ ', test(', I2, ')=', G12.5 ) +* + DEALLOCATE( WORK ) + DEALLOCATE( RWORK ) + DEALLOCATE( IWORK ) RETURN * * End of CDRVLS diff --git a/TESTING/LIN/cerrtsqr.f b/TESTING/LIN/cerrtsqr.f index b8b42dcc..399fcc41 100644 --- a/TESTING/LIN/cerrtsqr.f +++ b/TESTING/LIN/cerrtsqr.f @@ -161,13 +161,13 @@ CALL CGEMQR( 'L', 'N', 2, 1, 0, A, 0, TAU, 1, C, 1, W, 1,INFO) CALL CHKXER( 'CGEMQR', INFOT, NOUT, LERR, OK ) INFOT = 9 - CALL CGEMQR( 'R', 'N', 2, 2, 1, A, 1, TAU, 0, C, 1, W, 1,INFO) + CALL CGEMQR( 'R', 'N', 2, 2, 1, A, 2, TAU, 0, C, 1, W, 1,INFO) CALL CHKXER( 'CGEMQR', INFOT, NOUT, LERR, OK ) INFOT = 9 - CALL CGEMQR( 'L', 'N', 2, 2, 1, A, 1, TAU, 0, C, 1, W, 1,INFO) + CALL CGEMQR( 'L', 'N', 2, 2, 1, A, 2, TAU, 0, C, 1, W, 1,INFO) CALL CHKXER( 'CGEMQR', INFOT, NOUT, LERR, OK ) INFOT = 11 - CALL CGEMQR( 'L', 'N', 2, 1, 1, A, 1, TAU, 6, C, 0, W, 1,INFO) + CALL CGEMQR( 'L', 'N', 2, 1, 1, A, 2, TAU, 6, C, 0, W, 1,INFO) CALL CHKXER( 'CGEMQR', INFOT, NOUT, LERR, OK ) INFOT = 13 CALL CGEMQR( 'L', 'N', 2, 2, 1, A, 2, TAU, 6, C, 2, W, 0,INFO) diff --git a/TESTING/LIN/ctsqr01.f b/TESTING/LIN/ctsqr01.f index a437386b..6fbeb837 100644 --- a/TESTING/LIN/ctsqr01.f +++ b/TESTING/LIN/ctsqr01.f @@ -109,11 +109,12 @@ * .. * .. Local Scalars .. LOGICAL TESTZEROS, TS - INTEGER INFO, J, K, L, LWORK, LT ,MNB + INTEGER INFO, J, K, L, LWORK, TSIZE, MNB REAL ANORM, EPS, RESID, CNORM, DNORM * .. * .. Local Arrays .. INTEGER ISEED( 4 ) + COMPLEX TQUERY( 5 ), WORKQUERY * .. * .. External Functions .. REAL SLAMCH, CLANGE, CLANSY @@ -145,17 +146,11 @@ L = MAX(M,N,1) MNB = MAX ( MB, NB) LWORK = MAX(3,L)*MNB - IF((K.GE.MNB).OR.(MNB.GE.L))THEN - LT=MAX(1,L)*MNB+5 - ELSE - LT=MAX(1,(L-K)/(MNB-K)+1)*L*MNB+5 - END IF - * * Dynamically allocate local arrays * ALLOCATE ( A(M,N), AF(M,N), Q(L,L), R(M,L), RWORK(L), - $ WORK(LWORK), T(LT), C(M,N), CF(M,N), + $ C(M,N), CF(M,N), $ D(N,M), DF(N,M), LQ(L,N) ) * * Put random numbers into A and copy to AF @@ -176,14 +171,34 @@ * * Factor the matrix A in the array AF. * + CALL CGEQR( M, N, AF, M, TQUERY, -1, WORKQUERY, -1, INFO ) + TSIZE = INT( TQUERY( 1 ) ) + LWORK = INT( WORKQUERY ) + CALL CGEMQR( 'L', 'N', M, M, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL CGEMQR( 'L', 'N', M, N, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL CGEMQR( 'L', 'C', M, N, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL CGEMQR( 'R', 'N', N, M, K, AF, M, TQUERY, TSIZE, DF, N, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL CGEMQR( 'R', 'C', N, M, K, AF, M, TQUERY, TSIZE, DF, N, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + ALLOCATE ( T( TSIZE ) ) + ALLOCATE ( WORK( LWORK ) ) srnamt = 'CGEQR' - CALL CGEQR( M, N, AF, M, T, LT, WORK, LWORK, INFO ) + CALL CGEQR( M, N, AF, M, T, TSIZE, WORK, LWORK, INFO ) * * Generate the m-by-m matrix Q * CALL CLASET( 'Full', M, M, CZERO, ONE, Q, M ) srnamt = 'CGEMQR' - CALL CGEMQR( 'L', 'N', M, M, K, AF, M, T, LT, Q, M, + CALL CGEMQR( 'L', 'N', M, M, K, AF, M, T, TSIZE, Q, M, $ WORK, LWORK, INFO ) * * Copy R @@ -220,7 +235,7 @@ * Apply Q to C as Q*C * srnamt = 'CGEMQR' - CALL CGEMQR( 'L', 'N', M, N, K, AF, M, T, LT, CF, M, + CALL CGEMQR( 'L', 'N', M, N, K, AF, M, T, TSIZE, CF, M, $ WORK, LWORK, INFO) * * Compute |Q*C - Q*C| / |C| @@ -240,7 +255,7 @@ * Apply Q to C as QT*C * srnamt = 'CGEMQR' - CALL CGEMQR( 'L', 'C', M, N, K, AF, M, T, LT, CF, M, + CALL CGEMQR( 'L', 'C', M, N, K, AF, M, T, TSIZE, CF, M, $ WORK, LWORK, INFO) * * Compute |QT*C - QT*C| / |C| @@ -264,7 +279,7 @@ * Apply Q to D as D*Q * srnamt = 'CGEMQR' - CALL CGEMQR( 'R', 'N', N, M, K, AF, M, T, LT, DF, N, + CALL CGEMQR( 'R', 'N', N, M, K, AF, M, T, TSIZE, DF, N, $ WORK, LWORK, INFO) * * Compute |D*Q - D*Q| / |D| @@ -283,7 +298,7 @@ * * Apply Q to D as D*QT * - CALL CGEMQR( 'R', 'C', N, M, K, AF, M, T, LT, DF, N, + CALL CGEMQR( 'R', 'C', N, M, K, AF, M, T, TSIZE, DF, N, $ WORK, LWORK, INFO) * * Compute |D*QT - D*QT| / |D| @@ -299,15 +314,35 @@ * Short and wide * ELSE + CALL CGELQ( M, N, AF, M, TQUERY, -1, WORKQUERY, -1, INFO ) + TSIZE = INT( TQUERY( 1 ) ) + LWORK = INT( WORKQUERY ) + CALL CGEMLQ( 'R', 'N', N, N, K, AF, M, TQUERY, TSIZE, Q, N, + $ WORKQUERY, -1, INFO ) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL CGEMLQ( 'L', 'N', N, M, K, AF, M, TQUERY, TSIZE, DF, N, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL CGEMLQ( 'L', 'C', N, M, K, AF, M, TQUERY, TSIZE, DF, N, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL CGEMLQ( 'R', 'N', M, N, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL CGEMLQ( 'R', 'C', M, N, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + ALLOCATE ( T( TSIZE ) ) + ALLOCATE ( WORK( LWORK ) ) srnamt = 'CGELQ' - CALL CGELQ( M, N, AF, M, T, LT, WORK, LWORK, INFO ) + CALL CGELQ( M, N, AF, M, T, TSIZE, WORK, LWORK, INFO ) * * * Generate the n-by-n matrix Q * CALL CLASET( 'Full', N, N, CZERO, ONE, Q, N ) srnamt = 'CGEMLQ' - CALL CGEMLQ( 'R', 'N', N, N, K, AF, M, T, LT, Q, N, + CALL CGEMLQ( 'R', 'N', N, N, K, AF, M, T, TSIZE, Q, N, $ WORK, LWORK, INFO ) * * Copy R @@ -343,7 +378,7 @@ * * Apply Q to C as Q*C * - CALL CGEMLQ( 'L', 'N', N, M, K, AF, M, T, LT, DF, N, + CALL CGEMLQ( 'L', 'N', N, M, K, AF, M, T, TSIZE, DF, N, $ WORK, LWORK, INFO) * * Compute |Q*D - Q*D| / |D| @@ -362,7 +397,7 @@ * * Apply Q to D as QT*D * - CALL CGEMLQ( 'L', 'C', N, M, K, AF, M, T, LT, DF, N, + CALL CGEMLQ( 'L', 'C', N, M, K, AF, M, T, TSIZE, DF, N, $ WORK, LWORK, INFO) * * Compute |QT*D - QT*D| / |D| @@ -385,7 +420,7 @@ * * Apply Q to C as C*Q * - CALL CGEMLQ( 'R', 'N', M, N, K, AF, M, T, LT, CF, M, + CALL CGEMLQ( 'R', 'N', M, N, K, AF, M, T, TSIZE, CF, M, $ WORK, LWORK, INFO) * * Compute |C*Q - C*Q| / |C| @@ -404,7 +439,7 @@ * * Apply Q to D as D*QT * - CALL CGEMLQ( 'R', 'C', M, N, K, AF, M, T, LT, CF, M, + CALL CGEMLQ( 'R', 'C', M, N, K, AF, M, T, TSIZE, CF, M, $ WORK, LWORK, INFO) * * Compute |C*QT - C*QT| / |C| diff --git a/TESTING/LIN/dchkaa.f b/TESTING/LIN/dchkaa.f index 5d122d38..707517d2 100644 --- a/TESTING/LIN/dchkaa.f +++ b/TESTING/LIN/dchkaa.f @@ -907,7 +907,7 @@ CALL DDRVLS( DOTYPE, NM, MVAL, NN, NVAL, NNS, NSVAL, NNB, $ NBVAL, NXVAL, THRESH, TSTERR, A( 1, 1 ), $ A( 1, 2 ), B( 1, 1 ), B( 1, 2 ), B( 1, 3 ), - $ RWORK, RWORK( NMAX+1 ), WORK, IWORK, NOUT ) + $ RWORK, RWORK( NMAX+1 ), NOUT ) ELSE WRITE( NOUT, FMT = 9988 )PATH END IF diff --git a/TESTING/LIN/ddrvls.f b/TESTING/LIN/ddrvls.f index d11f910e..74b0c336 100644 --- a/TESTING/LIN/ddrvls.f +++ b/TESTING/LIN/ddrvls.f @@ -10,7 +10,7 @@ * * SUBROUTINE DDRVLS( DOTYPE, NM, MVAL, NN, NVAL, NNS, NSVAL, NNB, * NBVAL, NXVAL, THRESH, TSTERR, A, COPYA, B, -* COPYB, C, S, COPYS, WORK, IWORK, NOUT ) +* COPYB, C, S, COPYS, NOUT ) * * .. Scalar Arguments .. * LOGICAL TSTERR @@ -19,10 +19,10 @@ * .. * .. Array Arguments .. * LOGICAL DOTYPE( * ) -* INTEGER IWORK( * ), MVAL( * ), NBVAL( * ), NSVAL( * ), +* INTEGER MVAL( * ), NBVAL( * ), NSVAL( * ), * $ NVAL( * ), NXVAL( * ) * DOUBLE PRECISION A( * ), B( * ), C( * ), COPYA( * ), COPYB( * ), -* $ COPYS( * ), S( * ), WORK( * ) +* $ COPYS( * ), S( * ) * .. * * @@ -169,17 +169,6 @@ *> (min(MMAX,NMAX)) *> \endverbatim *> -*> \param[out] WORK -*> \verbatim -*> WORK is DOUBLE PRECISION array, -*> dimension (MMAX*NMAX + 4*NMAX + MMAX). -*> \endverbatim -*> -*> \param[out] IWORK -*> \verbatim -*> IWORK is INTEGER array, dimension (15*NMAX) -*> \endverbatim -*> *> \param[in] NOUT *> \verbatim *> NOUT is INTEGER @@ -201,7 +190,7 @@ * ===================================================================== SUBROUTINE DDRVLS( DOTYPE, NM, MVAL, NN, NVAL, NNS, NSVAL, NNB, $ NBVAL, NXVAL, THRESH, TSTERR, A, COPYA, B, - $ COPYB, C, S, COPYS, WORK, IWORK, NOUT ) + $ COPYB, C, S, COPYS, NOUT ) * * -- LAPACK test routine (version 3.6.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- @@ -215,10 +204,10 @@ * .. * .. Array Arguments .. LOGICAL DOTYPE( * ) - INTEGER IWORK( * ), MVAL( * ), NBVAL( * ), NSVAL( * ), + INTEGER MVAL( * ), NBVAL( * ), NSVAL( * ), $ NVAL( * ), NXVAL( * ) DOUBLE PRECISION A( * ), B( * ), C( * ), COPYA( * ), COPYB( * ), - $ COPYS( * ), S( * ), WORK( * ) + $ COPYS( * ), S( * ) * .. * * ===================================================================== @@ -237,12 +226,19 @@ INTEGER CRANK, I, IM, IMB, IN, INB, INFO, INS, IRANK, $ ISCALE, ITRAN, ITYPE, J, K, LDA, LDB, LDWORK, $ LWLSY, LWORK, M, MNMIN, N, NB, NCOLS, NERRS, - $ NFAIL, NLVL, NRHS, NROWS, NRUN, RANK, MB, LWTS + $ NFAIL, NRHS, NROWS, NRUN, RANK, MB, + $ MMAX, NMAX, NSMAX, LIWORK, + $ LWORK_DGELS, LWORK_DGETSLS, LWORK_DGELSS, + $ LWORK_DGELSY, LWORK_DGELSD DOUBLE PRECISION EPS, NORMA, NORMB, RCOND * .. * .. Local Arrays .. - INTEGER ISEED( 4 ), ISEEDY( 4 ) - DOUBLE PRECISION RESULT( NTESTS ) + INTEGER ISEED( 4 ), ISEEDY( 4 ), IWORKQUERY + DOUBLE PRECISION RESULT( NTESTS ), WORKQUERY +* .. +* .. Allocatable Arrays .. + DOUBLE PRECISION, ALLOCATABLE :: WORK (:) + INTEGER, ALLOCATABLE :: IWORK (:) * .. * .. External Functions .. DOUBLE PRECISION DASUM, DLAMCH, DQRT12, DQRT14, DQRT17 @@ -302,6 +298,71 @@ CALL XLAENV( 2, 2 ) CALL XLAENV( 9, SMLSIZ ) * +* Compute maximal workspace needed for all routines +* + NMAX = 0 + MMAX = 0 + NSMAX = 0 + DO I = 1, NM + IF ( MVAL( I ).GT.MMAX ) THEN + MMAX = MVAL( I ) + END IF + ENDDO + DO I = 1, NN + IF ( NVAL( I ).GT.NMAX ) THEN + NMAX = NVAL( I ) + END IF + ENDDO + DO I = 1, NNS + IF ( NSVAL( I ).GT.NSMAX ) THEN + NSMAX = NSVAL( I ) + END IF + ENDDO + M = MMAX + N = NMAX + NRHS = NSMAX + LDA = MAX( 1, M ) + LDB = MAX( 1, M, N ) + MNMIN = MAX( MIN( M, N ), 1 ) +* +* Compute workspace needed for routines +* DQRT14, DQRT17 (two side cases), DQRT15 and DQRT12 +* + LWORK = MAX( ( M+N )*NRHS, + $ ( N+NRHS )*( M+2 ), ( M+NRHS )*( N+2 ), + $ MAX( M+MNMIN, NRHS*MNMIN,2*N+M ), + $ MAX( M*N+4*MNMIN+MAX(M,N), M*N+2*MNMIN+4*N ) ) +* +* Compute workspace needed for DGELS + CALL DGELS( 'N', M, N, NRHS, A, LDA, B, LDB, + $ WORKQUERY, -1, INFO ) + LWORK_DGELS = INT ( WORKQUERY ) +* Compute workspace needed for DGETSLS + CALL DGETSLS( 'N', M, N, NRHS, A, LDA, B, LDB, + $ WORKQUERY, -1, INFO ) + LWORK_DGETSLS = INT( WORKQUERY ) +* Compute workspace needed for DGELSY + CALL DGELSY( M, N, NRHS, A, LDA, B, LDB, IWORKQUERY, + $ RCOND, CRANK, WORKQUERY, -1, INFO ) + LWORK_DGELSY = INT( WORKQUERY ) +* Compute workspace needed for DGELSS + CALL DGELSS( M, N, NRHS, A, LDA, B, LDB, S, + $ RCOND, CRANK, WORKQUERY, -1 , INFO ) + LWORK_DGELSS = INT( WORKQUERY ) +* Compute workspace needed for DGELSD + CALL DGELSD( M, N, NRHS, A, LDA, B, LDB, S, + $ RCOND, CRANK, WORKQUERY, -1, IWORKQUERY, INFO ) + LWORK_DGELSD = INT( WORKQUERY ) +* Compute LIWORK workspace needed for DGELSY and DGELSD + LIWORK = MAX( 1, N, IWORKQUERY ) +* Compute LWORK workspace needed for all functions + LWORK = MAX( 1, LWORK, LWORK_DGELS, LWORK_DGETSLS, LWORK_DGELSY, + $ LWORK_DGELSS, LWORK_DGELSD ) + LWLSY = LWORK +* + ALLOCATE( WORK( LWORK ) ) + ALLOCATE( IWORK( LIWORK ) ) +* DO 150 IM = 1, NM M = MVAL( IM ) LDA = MAX( 1, M ) @@ -311,20 +372,9 @@ MNMIN = MAX(MIN( M, N ),1) LDB = MAX( 1, M, N ) MB = (MNMIN+1) - IF(MNMIN.NE.MB) THEN - LWTS = (((LDB-MB)/(MB-MNMIN))*MNMIN+MNMIN*2)*MB+5 - ELSE - LWTS = 2*MNMIN+5 - END IF * DO 130 INS = 1, NNS NRHS = NSVAL( INS ) - NLVL = MAX( INT( LOG( MAX( ONE, DBLE( MNMIN ) ) / - $ DBLE( SMLSIZ+1 ) ) / LOG( TWO ) ) + 1, 0 ) - LWORK = MAX( 1, ( M+NRHS )*( N+2 ), ( N+NRHS )*( M+2 ), - $ M*N+4*MNMIN+MAX( M, N ), 12*MNMIN+2*MNMIN*SMLSIZ+ - $ 8*MNMIN*NLVL+MNMIN*NRHS+(SMLSIZ+1)**2,LWTS) - $ * DO 120 IRANK = 1, 2 DO 110 ISCALE = 1, 3 @@ -570,11 +620,6 @@ IWORK( J ) = 0 70 CONTINUE * -* Set LWLSY to the adequate value. -* - LWLSY = MAX( 1, MNMIN+2*N+NB*( N+1 ), - $ 2*MNMIN+NB*NRHS ) -* CALL DLACPY( 'Full', M, N, COPYA, LDA, A, LDA ) CALL DLACPY( 'Full', M, NRHS, COPYB, LDB, B, $ LDB ) @@ -768,6 +813,9 @@ 9997 FORMAT( ' TRANS=''', A1,' M=', I5, ', N=', I5, ', NRHS=', I4, $ ', MB=', I4,', NB=', I4,', type', I2, $ ', test(', I2, ')=', G12.5 ) +* + DEALLOCATE( WORK ) + DEALLOCATE( IWORK ) RETURN * * End of DDRVLS diff --git a/TESTING/LIN/derrtsqr.f b/TESTING/LIN/derrtsqr.f index 4a5ad5e6..a83ed1fb 100644 --- a/TESTING/LIN/derrtsqr.f +++ b/TESTING/LIN/derrtsqr.f @@ -161,13 +161,13 @@ CALL DGEMQR( 'L', 'N', 2, 1, 0, A, 0, TAU, 1, C, 1, W, 1,INFO) CALL CHKXER( 'DGEMQR', INFOT, NOUT, LERR, OK ) INFOT = 9 - CALL DGEMQR( 'R', 'N', 2, 2, 1, A, 1, TAU, 0, C, 1, W, 1,INFO) + CALL DGEMQR( 'R', 'N', 2, 2, 1, A, 2, TAU, 0, C, 1, W, 1,INFO) CALL CHKXER( 'DGEMQR', INFOT, NOUT, LERR, OK ) INFOT = 9 - CALL DGEMQR( 'L', 'N', 2, 2, 1, A, 1, TAU, 0, C, 1, W, 1,INFO) + CALL DGEMQR( 'L', 'N', 2, 2, 1, A, 2, TAU, 0, C, 1, W, 1,INFO) CALL CHKXER( 'DGEMQR', INFOT, NOUT, LERR, OK ) INFOT = 11 - CALL DGEMQR( 'L', 'N', 2, 1, 1, A, 1, TAU, 6, C, 0, W, 1,INFO) + CALL DGEMQR( 'L', 'N', 2, 1, 1, A, 2, TAU, 6, C, 0, W, 1,INFO) CALL CHKXER( 'DGEMQR', INFOT, NOUT, LERR, OK ) INFOT = 13 CALL DGEMQR( 'L', 'N', 2, 2, 1, A, 2, TAU, 6, C, 2, W, 0,INFO) diff --git a/TESTING/LIN/dtsqr01.f b/TESTING/LIN/dtsqr01.f index a9ac1635..d8f34cba 100644 --- a/TESTING/LIN/dtsqr01.f +++ b/TESTING/LIN/dtsqr01.f @@ -110,11 +110,12 @@ * .. * .. Local Scalars .. LOGICAL TESTZEROS, TS - INTEGER INFO, J, K, L, LWORK, LT ,MNB + INTEGER INFO, J, K, L, LWORK, TSIZE, MNB DOUBLE PRECISION ANORM, EPS, RESID, CNORM, DNORM * .. * .. Local Arrays .. INTEGER ISEED( 4 ) + DOUBLE PRECISION TQUERY( 5 ), WORKQUERY * .. * .. External Functions .. DOUBLE PRECISION DLAMCH, DLANGE, DLANSY @@ -146,17 +147,11 @@ L = MAX(M,N,1) MNB = MAX ( MB, NB) LWORK = MAX(3,L)*MNB - IF((K.GE.MNB).OR.(MNB.GE.L))THEN - LT=MAX(1,L)*MNB+5 - ELSE - LT=MAX(1,(L-K)/(MNB-K)+1)*L*MNB+5 - END IF - * * Dynamically allocate local arrays * ALLOCATE ( A(M,N), AF(M,N), Q(L,L), R(M,L), RWORK(L), - $ WORK(LWORK), T(LT), C(M,N), CF(M,N), + $ C(M,N), CF(M,N), $ D(N,M), DF(N,M), LQ(L,N) ) * * Put random numbers into A and copy to AF @@ -177,14 +172,34 @@ * * Factor the matrix A in the array AF. * + CALL DGEQR( M, N, AF, M, TQUERY, -1, WORKQUERY, -1, INFO ) + TSIZE = INT( TQUERY( 1 ) ) + LWORK = INT( WORKQUERY ) + CALL DGEMQR( 'L', 'N', M, M, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL DGEMQR( 'L', 'N', M, N, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL DGEMQR( 'L', 'T', M, N, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL DGEMQR( 'R', 'N', N, M, K, AF, M, TQUERY, TSIZE, DF, N, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL DGEMQR( 'R', 'T', N, M, K, AF, M, TQUERY, TSIZE, DF, N, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + ALLOCATE ( T( TSIZE ) ) + ALLOCATE ( WORK( LWORK ) ) srnamt = 'DGEQR' - CALL DGEQR( M, N, AF, M, T, LT, WORK, LWORK, INFO ) + CALL DGEQR( M, N, AF, M, T, TSIZE, WORK, LWORK, INFO ) * * Generate the m-by-m matrix Q * CALL DLASET( 'Full', M, M, ZERO, ONE, Q, M ) srnamt = 'DGEMQR' - CALL DGEMQR( 'L', 'N', M, M, K, AF, M, T, LT, Q, M, + CALL DGEMQR( 'L', 'N', M, M, K, AF, M, T, TSIZE, Q, M, $ WORK, LWORK, INFO ) * * Copy R @@ -221,7 +236,7 @@ * Apply Q to C as Q*C * srnamt = 'DGEMQR' - CALL DGEMQR( 'L', 'N', M, N, K, AF, M, T, LT, CF, M, + CALL DGEMQR( 'L', 'N', M, N, K, AF, M, T, TSIZE, CF, M, $ WORK, LWORK, INFO) * * Compute |Q*C - Q*C| / |C| @@ -241,7 +256,7 @@ * Apply Q to C as QT*C * srnamt = 'DGEMQR' - CALL DGEMQR( 'L', 'T', M, N, K, AF, M, T, LT, CF, M, + CALL DGEMQR( 'L', 'T', M, N, K, AF, M, T, TSIZE, CF, M, $ WORK, LWORK, INFO) * * Compute |QT*C - QT*C| / |C| @@ -265,7 +280,7 @@ * Apply Q to D as D*Q * srnamt = 'DGEMQR' - CALL DGEMQR( 'R', 'N', N, M, K, AF, M, T, LT, DF, N, + CALL DGEMQR( 'R', 'N', N, M, K, AF, M, T, TSIZE, DF, N, $ WORK, LWORK, INFO) * * Compute |D*Q - D*Q| / |D| @@ -284,7 +299,7 @@ * * Apply Q to D as D*QT * - CALL DGEMQR( 'R', 'T', N, M, K, AF, M, T, LT, DF, N, + CALL DGEMQR( 'R', 'T', N, M, K, AF, M, T, TSIZE, DF, N, $ WORK, LWORK, INFO) * * Compute |D*QT - D*QT| / |D| @@ -300,15 +315,35 @@ * Short and wide * ELSE + CALL DGELQ( M, N, AF, M, TQUERY, -1, WORKQUERY, -1, INFO ) + TSIZE = INT( TQUERY( 1 ) ) + LWORK = INT( WORKQUERY ) + CALL DGEMLQ( 'R', 'N', N, N, K, AF, M, TQUERY, TSIZE, Q, N, + $ WORKQUERY, -1, INFO ) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL DGEMLQ( 'L', 'N', N, M, K, AF, M, TQUERY, TSIZE, DF, N, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL DGEMLQ( 'L', 'T', N, M, K, AF, M, TQUERY, TSIZE, DF, N, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL DGEMLQ( 'R', 'N', M, N, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL DGEMLQ( 'R', 'T', M, N, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + ALLOCATE ( T( TSIZE ) ) + ALLOCATE ( WORK( LWORK ) ) srnamt = 'DGELQ' - CALL DGELQ( M, N, AF, M, T, LT, WORK, LWORK, INFO ) + CALL DGELQ( M, N, AF, M, T, TSIZE, WORK, LWORK, INFO ) * * * Generate the n-by-n matrix Q * CALL DLASET( 'Full', N, N, ZERO, ONE, Q, N ) srnamt = 'DGEMLQ' - CALL DGEMLQ( 'R', 'N', N, N, K, AF, M, T, LT, Q, N, + CALL DGEMLQ( 'R', 'N', N, N, K, AF, M, T, TSIZE, Q, N, $ WORK, LWORK, INFO ) * * Copy R @@ -344,7 +379,7 @@ * * Apply Q to C as Q*C * - CALL DGEMLQ( 'L', 'N', N, M, K, AF, M, T, LT, DF, N, + CALL DGEMLQ( 'L', 'N', N, M, K, AF, M, T, TSIZE, DF, N, $ WORK, LWORK, INFO) * * Compute |Q*D - Q*D| / |D| @@ -363,7 +398,7 @@ * * Apply Q to D as QT*D * - CALL DGEMLQ( 'L', 'T', N, M, K, AF, M, T, LT, DF, N, + CALL DGEMLQ( 'L', 'T', N, M, K, AF, M, T, TSIZE, DF, N, $ WORK, LWORK, INFO) * * Compute |QT*D - QT*D| / |D| @@ -386,7 +421,7 @@ * * Apply Q to C as C*Q * - CALL DGEMLQ( 'R', 'N', M, N, K, AF, M, T, LT, CF, M, + CALL DGEMLQ( 'R', 'N', M, N, K, AF, M, T, TSIZE, CF, M, $ WORK, LWORK, INFO) * * Compute |C*Q - C*Q| / |C| @@ -405,7 +440,7 @@ * * Apply Q to D as D*QT * - CALL DGEMLQ( 'R', 'T', M, N, K, AF, M, T, LT, CF, M, + CALL DGEMLQ( 'R', 'T', M, N, K, AF, M, T, TSIZE, CF, M, $ WORK, LWORK, INFO) * * Compute |C*QT - C*QT| / |C| diff --git a/TESTING/LIN/schkaa.f b/TESTING/LIN/schkaa.f index 675e32f1..410379b3 100644 --- a/TESTING/LIN/schkaa.f +++ b/TESTING/LIN/schkaa.f @@ -904,7 +904,7 @@ CALL SDRVLS( DOTYPE, NM, MVAL, NN, NVAL, NNS, NSVAL, NNB, $ NBVAL, NXVAL, THRESH, TSTERR, A( 1, 1 ), $ A( 1, 2 ), B( 1, 1 ), B( 1, 2 ), B( 1, 3 ), - $ RWORK, RWORK( NMAX+1 ), WORK, IWORK, NOUT ) + $ RWORK, RWORK( NMAX+1 ), NOUT ) ELSE WRITE( NOUT, FMT = 9988 )PATH END IF diff --git a/TESTING/LIN/sdrvls.f b/TESTING/LIN/sdrvls.f index 03598937..d6a55708 100644 --- a/TESTING/LIN/sdrvls.f +++ b/TESTING/LIN/sdrvls.f @@ -10,7 +10,7 @@ * * SUBROUTINE SDRVLS( DOTYPE, NM, MVAL, NN, NVAL, NNS, NSVAL, NNB, * NBVAL, NXVAL, THRESH, TSTERR, A, COPYA, B, -* COPYB, C, S, COPYS, WORK, IWORK, NOUT ) +* COPYB, C, S, COPYS, NOUT ) * * .. Scalar Arguments .. * LOGICAL TSTERR @@ -19,10 +19,10 @@ * .. * .. Array Arguments .. * LOGICAL DOTYPE( * ) -* INTEGER IWORK( * ), MVAL( * ), NBVAL( * ), NSVAL( * ), +* INTEGER MVAL( * ), NBVAL( * ), NSVAL( * ), * $ NVAL( * ), NXVAL( * ) * REAL A( * ), B( * ), C( * ), COPYA( * ), COPYB( * ), -* $ COPYS( * ), S( * ), WORK( * ) +* $ COPYS( * ), S( * ) * .. * * @@ -169,17 +169,6 @@ *> (min(MMAX,NMAX)) *> \endverbatim *> -*> \param[out] WORK -*> \verbatim -*> WORK is REAL array, -*> dimension (MMAX*NMAX + 4*NMAX + MMAX). -*> \endverbatim -*> -*> \param[out] IWORK -*> \verbatim -*> IWORK is INTEGER array, dimension (15*NMAX) -*> \endverbatim -*> *> \param[in] NOUT *> \verbatim *> NOUT is INTEGER @@ -201,7 +190,7 @@ * ===================================================================== SUBROUTINE SDRVLS( DOTYPE, NM, MVAL, NN, NVAL, NNS, NSVAL, NNB, $ NBVAL, NXVAL, THRESH, TSTERR, A, COPYA, B, - $ COPYB, C, S, COPYS, WORK, IWORK, NOUT ) + $ COPYB, C, S, COPYS, NOUT ) * * -- LAPACK test routine (version 3.6.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- @@ -215,10 +204,10 @@ * .. * .. Array Arguments .. LOGICAL DOTYPE( * ) - INTEGER IWORK( * ), MVAL( * ), NBVAL( * ), NSVAL( * ), + INTEGER MVAL( * ), NBVAL( * ), NSVAL( * ), $ NVAL( * ), NXVAL( * ) REAL A( * ), B( * ), C( * ), COPYA( * ), COPYB( * ), - $ COPYS( * ), S( * ), WORK( * ) + $ COPYS( * ), S( * ) * .. * * ===================================================================== @@ -237,12 +226,19 @@ INTEGER CRANK, I, IM, IMB, IN, INB, INFO, INS, IRANK, $ ISCALE, ITRAN, ITYPE, J, K, LDA, LDB, LDWORK, $ LWLSY, LWORK, M, MNMIN, N, NB, NCOLS, NERRS, - $ NFAIL, NLVL, NRHS, NROWS, NRUN, RANK, MB, LWTS + $ NFAIL, NRHS, NROWS, NRUN, RANK, MB, + $ MMAX, NMAX, NSMAX, LIWORK, + $ LWORK_SGELS, LWORK_SGETSLS, LWORK_SGELSS, + $ LWORK_SGELSY, LWORK_SGELSD REAL EPS, NORMA, NORMB, RCOND * .. * .. Local Arrays .. - INTEGER ISEED( 4 ), ISEEDY( 4 ) - REAL RESULT( NTESTS ) + INTEGER ISEED( 4 ), ISEEDY( 4 ), IWORKQUERY + REAL RESULT( NTESTS ), WORKQUERY +* .. +* .. Allocatable Arrays .. + REAL, ALLOCATABLE :: WORK (:) + INTEGER, ALLOCATABLE :: IWORK (:) * .. * .. External Functions .. REAL SASUM, SLAMCH, SQRT12, SQRT14, SQRT17 @@ -302,6 +298,71 @@ CALL XLAENV( 2, 2 ) CALL XLAENV( 9, SMLSIZ ) * +* Compute maximal workspace needed for all routines +* + NMAX = 0 + MMAX = 0 + NSMAX = 0 + DO I = 1, NM + IF ( MVAL( I ).GT.MMAX ) THEN + MMAX = MVAL( I ) + END IF + ENDDO + DO I = 1, NN + IF ( NVAL( I ).GT.NMAX ) THEN + NMAX = NVAL( I ) + END IF + ENDDO + DO I = 1, NNS + IF ( NSVAL( I ).GT.NSMAX ) THEN + NSMAX = NSVAL( I ) + END IF + ENDDO + M = MMAX + N = NMAX + NRHS = NSMAX + LDA = MAX( 1, M ) + LDB = MAX( 1, M, N ) + MNMIN = MAX( MIN( M, N ), 1 ) +* +* Compute workspace needed for routines +* SQRT14, SQRT17 (two side cases), SQRT15 and SQRT12 +* + LWORK = MAX( ( M+N )*NRHS, + $ ( N+NRHS )*( M+2 ), ( M+NRHS )*( N+2 ), + $ MAX( M+MNMIN, NRHS*MNMIN,2*N+M ), + $ MAX( M*N+4*MNMIN+MAX(M,N), M*N+2*MNMIN+4*N ) ) +* +* Compute workspace needed for SGELS + CALL SGELS( 'N', M, N, NRHS, A, LDA, B, LDB, + $ WORKQUERY, -1, INFO ) + LWORK_SGELS = INT ( WORKQUERY ) +* Compute workspace needed for SGETSLS + CALL SGETSLS( 'N', M, N, NRHS, A, LDA, B, LDB, + $ WORKQUERY, -1, INFO ) + LWORK_SGETSLS = INT( WORKQUERY ) +* Compute workspace needed for SGELSY + CALL SGELSY( M, N, NRHS, A, LDA, B, LDB, IWORKQUERY, + $ RCOND, CRANK, WORKQUERY, -1, INFO ) + LWORK_SGELSY = INT( WORKQUERY ) +* Compute workspace needed for SGELSS + CALL SGELSS( M, N, NRHS, A, LDA, B, LDB, S, + $ RCOND, CRANK, WORKQUERY, -1 , INFO ) + LWORK_SGELSS = INT( WORKQUERY ) +* Compute workspace needed for SGELSD + CALL SGELSD( M, N, NRHS, A, LDA, B, LDB, S, + $ RCOND, CRANK, WORKQUERY, -1, IWORKQUERY, INFO ) + LWORK_SGELSD = INT( WORKQUERY ) +* Compute LIWORK workspace needed for SGELSY and SGELSD + LIWORK = MAX( 1, N, IWORKQUERY ) +* Compute LWORK workspace needed for all functions + LWORK = MAX( 1, LWORK, LWORK_SGELS, LWORK_SGETSLS, LWORK_SGELSY, + $ LWORK_SGELSS, LWORK_SGELSD ) + LWLSY = LWORK +* + ALLOCATE( WORK( LWORK ) ) + ALLOCATE( IWORK( LIWORK ) ) +* DO 150 IM = 1, NM M = MVAL( IM ) LDA = MAX( 1, M ) @@ -311,20 +372,9 @@ MNMIN = MAX(MIN( M, N ),1) LDB = MAX( 1, M, N ) MB = (MNMIN+1) - IF(MNMIN.NE.MB) THEN - LWTS = (((LDB-MB)/(MB-MNMIN))*MNMIN+MNMIN*2)*MB+5 - ELSE - LWTS = 2*MNMIN+5 - END IF * DO 130 INS = 1, NNS NRHS = NSVAL( INS ) - NLVL = MAX( INT( LOG( MAX( ONE, REAL( MNMIN ) ) / - $ REAL( SMLSIZ+1 ) ) / LOG( TWO ) ) + 1, 0 ) - LWORK = MAX( 1, ( M+NRHS )*( N+2 ), ( N+NRHS )*( M+2 ), - $ M*N+4*MNMIN+MAX( M, N ), 12*MNMIN+2*MNMIN*SMLSIZ+ - $ 8*MNMIN*NLVL+MNMIN*NRHS+(SMLSIZ+1)**2,LWTS) - $ * DO 120 IRANK = 1, 2 DO 110 ISCALE = 1, 3 @@ -570,11 +620,6 @@ IWORK( J ) = 0 70 CONTINUE * -* Set LWLSY to the adequate value. -* - LWLSY = MAX( 1, MNMIN+2*N+NB*( N+1 ), - $ 2*MNMIN+NB*NRHS ) -* CALL SLACPY( 'Full', M, N, COPYA, LDA, A, LDA ) CALL SLACPY( 'Full', M, NRHS, COPYB, LDB, B, $ LDB ) @@ -768,6 +813,9 @@ 9997 FORMAT( ' TRANS=''', A1,' M=', I5, ', N=', I5, ', NRHS=', I4, $ ', MB=', I4,', NB=', I4,', type', I2, $ ', test(', I2, ')=', G12.5 ) +* + DEALLOCATE( WORK ) + DEALLOCATE( IWORK ) RETURN * * End of SDRVLS diff --git a/TESTING/LIN/serrtsqr.f b/TESTING/LIN/serrtsqr.f index eddadbee..cb7c3266 100644 --- a/TESTING/LIN/serrtsqr.f +++ b/TESTING/LIN/serrtsqr.f @@ -161,13 +161,13 @@ CALL SGEMQR( 'L', 'N', 2, 1, 0, A, 0, TAU, 1, C, 1, W, 1,INFO) CALL CHKXER( 'SGEMQR', INFOT, NOUT, LERR, OK ) INFOT = 9 - CALL SGEMQR( 'R', 'N', 2, 2, 1, A, 1, TAU, 0, C, 1, W, 1,INFO) + CALL SGEMQR( 'R', 'N', 2, 2, 1, A, 2, TAU, 0, C, 1, W, 1,INFO) CALL CHKXER( 'SGEMQR', INFOT, NOUT, LERR, OK ) INFOT = 9 - CALL SGEMQR( 'L', 'N', 2, 2, 1, A, 1, TAU, 0, C, 1, W, 1,INFO) + CALL SGEMQR( 'L', 'N', 2, 2, 1, A, 2, TAU, 0, C, 1, W, 1,INFO) CALL CHKXER( 'SGEMQR', INFOT, NOUT, LERR, OK ) INFOT = 11 - CALL SGEMQR( 'L', 'N', 2, 1, 1, A, 1, TAU, 6, C, 0, W, 1,INFO) + CALL SGEMQR( 'L', 'N', 2, 1, 1, A, 2, TAU, 6, C, 0, W, 1,INFO) CALL CHKXER( 'SGEMQR', INFOT, NOUT, LERR, OK ) INFOT = 13 CALL SGEMQR( 'L', 'N', 2, 2, 1, A, 2, TAU, 6, C, 2, W, 0,INFO) diff --git a/TESTING/LIN/stsqr01.f b/TESTING/LIN/stsqr01.f index 4cebfc88..3e4e3d09 100644 --- a/TESTING/LIN/stsqr01.f +++ b/TESTING/LIN/stsqr01.f @@ -110,11 +110,12 @@ * .. * .. Local Scalars .. LOGICAL TESTZEROS, TS - INTEGER INFO, J, K, L, LWORK, LT ,MNB + INTEGER INFO, J, K, L, LWORK, TSIZE, MNB REAL ANORM, EPS, RESID, CNORM, DNORM * .. * .. Local Arrays .. INTEGER ISEED( 4 ) + REAL TQUERY( 5 ), WORKQUERY * .. * .. External Functions .. REAL SLAMCH, SLANGE, SLANSY @@ -146,17 +147,11 @@ L = MAX(M,N,1) MNB = MAX ( MB, NB) LWORK = MAX(3,L)*MNB - IF((K.GE.MNB).OR.(MNB.GE.L))THEN - LT=MAX(1,L)*MNB+5 - ELSE - LT=MAX(1,(L-K)/(MNB-K)+1)*L*MNB+5 - END IF - * * Dynamically allocate local arrays * ALLOCATE ( A(M,N), AF(M,N), Q(L,L), R(M,L), RWORK(L), - $ WORK(LWORK), T(LT), C(M,N), CF(M,N), + $ C(M,N), CF(M,N), $ D(N,M), DF(N,M), LQ(L,N) ) * * Put random numbers into A and copy to AF @@ -177,14 +172,34 @@ * * Factor the matrix A in the array AF. * + CALL SGEQR( M, N, AF, M, TQUERY, -1, WORKQUERY, -1, INFO ) + TSIZE = INT( TQUERY( 1 ) ) + LWORK = INT( WORKQUERY ) + CALL SGEMQR( 'L', 'N', M, M, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL SGEMQR( 'L', 'N', M, N, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL SGEMQR( 'L', 'T', M, N, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL SGEMQR( 'R', 'N', N, M, K, AF, M, TQUERY, TSIZE, DF, N, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL SGEMQR( 'R', 'T', N, M, K, AF, M, TQUERY, TSIZE, DF, N, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + ALLOCATE ( T( TSIZE ) ) + ALLOCATE ( WORK( LWORK ) ) srnamt = 'SGEQR' - CALL SGEQR( M, N, AF, M, T, LT, WORK, LWORK, INFO ) + CALL SGEQR( M, N, AF, M, T, TSIZE, WORK, LWORK, INFO ) * * Generate the m-by-m matrix Q * CALL SLASET( 'Full', M, M, ZERO, ONE, Q, M ) srnamt = 'SGEMQR' - CALL SGEMQR( 'L', 'N', M, M, K, AF, M, T, LT, Q, M, + CALL SGEMQR( 'L', 'N', M, M, K, AF, M, T, TSIZE, Q, M, $ WORK, LWORK, INFO ) * * Copy R @@ -221,7 +236,7 @@ * Apply Q to C as Q*C * srnamt = 'DGEQR' - CALL SGEMQR( 'L', 'N', M, N, K, AF, M, T, LT, CF, M, + CALL SGEMQR( 'L', 'N', M, N, K, AF, M, T, TSIZE, CF, M, $ WORK, LWORK, INFO) * * Compute |Q*C - Q*C| / |C| @@ -241,7 +256,7 @@ * Apply Q to C as QT*C * srnamt = 'DGEQR' - CALL SGEMQR( 'L', 'T', M, N, K, AF, M, T, LT, CF, M, + CALL SGEMQR( 'L', 'T', M, N, K, AF, M, T, TSIZE, CF, M, $ WORK, LWORK, INFO) * * Compute |QT*C - QT*C| / |C| @@ -265,7 +280,7 @@ * Apply Q to D as D*Q * srnamt = 'DGEQR' - CALL SGEMQR( 'R', 'N', N, M, K, AF, M, T, LT, DF, N, + CALL SGEMQR( 'R', 'N', N, M, K, AF, M, T, TSIZE, DF, N, $ WORK, LWORK, INFO) * * Compute |D*Q - D*Q| / |D| @@ -284,7 +299,7 @@ * * Apply Q to D as D*QT * - CALL SGEMQR( 'R', 'T', N, M, K, AF, M, T, LT, DF, N, + CALL SGEMQR( 'R', 'T', N, M, K, AF, M, T, TSIZE, DF, N, $ WORK, LWORK, INFO) * * Compute |D*QT - D*QT| / |D| @@ -300,15 +315,35 @@ * Short and wide * ELSE + CALL SGELQ( M, N, AF, M, TQUERY, -1, WORKQUERY, -1, INFO ) + TSIZE = INT( TQUERY( 1 ) ) + LWORK = INT( WORKQUERY ) + CALL SGEMLQ( 'R', 'N', N, N, K, AF, M, TQUERY, TSIZE, Q, N, + $ WORKQUERY, -1, INFO ) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL SGEMLQ( 'L', 'N', N, M, K, AF, M, TQUERY, TSIZE, DF, N, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL SGEMLQ( 'L', 'T', N, M, K, AF, M, TQUERY, TSIZE, DF, N, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL SGEMLQ( 'R', 'N', M, N, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL SGEMLQ( 'R', 'T', M, N, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + ALLOCATE ( T( TSIZE ) ) + ALLOCATE ( WORK( LWORK ) ) srnamt = 'SGELQ' - CALL SGELQ( M, N, AF, M, T, LT, WORK, LWORK, INFO ) + CALL SGELQ( M, N, AF, M, T, TSIZE, WORK, LWORK, INFO ) * * * Generate the n-by-n matrix Q * CALL SLASET( 'Full', N, N, ZERO, ONE, Q, N ) - srnamt = 'SGEMQR' - CALL SGEMLQ( 'R', 'N', N, N, K, AF, M, T, LT, Q, N, + srnamt = 'SGEMLQ' + CALL SGEMLQ( 'R', 'N', N, N, K, AF, M, T, TSIZE, Q, N, $ WORK, LWORK, INFO ) * * Copy R @@ -344,7 +379,7 @@ * * Apply Q to C as Q*C * - CALL SGEMLQ( 'L', 'N', N, M, K, AF, M, T, LT, DF, N, + CALL SGEMLQ( 'L', 'N', N, M, K, AF, M, T, TSIZE, DF, N, $ WORK, LWORK, INFO) * * Compute |Q*D - Q*D| / |D| @@ -363,7 +398,7 @@ * * Apply Q to D as QT*D * - CALL SGEMLQ( 'L', 'T', N, M, K, AF, M, T, LT, DF, N, + CALL SGEMLQ( 'L', 'T', N, M, K, AF, M, T, TSIZE, DF, N, $ WORK, LWORK, INFO) * * Compute |QT*D - QT*D| / |D| @@ -386,7 +421,7 @@ * * Apply Q to C as C*Q * - CALL SGEMLQ( 'R', 'N', M, N, K, AF, M, T, LT, CF, M, + CALL SGEMLQ( 'R', 'N', M, N, K, AF, M, T, TSIZE, CF, M, $ WORK, LWORK, INFO) * * Compute |C*Q - C*Q| / |C| @@ -405,7 +440,7 @@ * * Apply Q to D as D*QT * - CALL SGEMLQ( 'R', 'T', M, N, K, AF, M, T, LT, CF, M, + CALL SGEMLQ( 'R', 'T', M, N, K, AF, M, T, TSIZE, CF, M, $ WORK, LWORK, INFO) * * Compute |C*QT - C*QT| / |C| diff --git a/TESTING/LIN/zchkaa.f b/TESTING/LIN/zchkaa.f index 818f1e63..5a41ab32 100644 --- a/TESTING/LIN/zchkaa.f +++ b/TESTING/LIN/zchkaa.f @@ -1049,8 +1049,7 @@ CALL ZDRVLS( DOTYPE, NM, MVAL, NN, NVAL, NNS, NSVAL, NNB, $ NBVAL, NXVAL, THRESH, TSTERR, A( 1, 1 ), $ A( 1, 2 ), A( 1, 3 ), A( 1, 4 ), A( 1, 5 ), - $ S( 1 ), S( NMAX+1 ), WORK, RWORK, IWORK, - $ NOUT ) + $ S( 1 ), S( NMAX+1 ), NOUT ) ELSE WRITE( NOUT, FMT = 9989 )PATH END IF diff --git a/TESTING/LIN/zdrvls.f b/TESTING/LIN/zdrvls.f index fe63b540..13a9263e 100644 --- a/TESTING/LIN/zdrvls.f +++ b/TESTING/LIN/zdrvls.f @@ -10,7 +10,7 @@ * * SUBROUTINE ZDRVLS( DOTYPE, NM, MVAL, NN, NVAL, NNS, NSVAL, NNB, * NBVAL, NXVAL, THRESH, TSTERR, A, COPYA, B, -* COPYB, C, S, COPYS, WORK, RWORK, IWORK, NOUT ) +* COPYB, C, S, COPYS, NOUT ) * * .. Scalar Arguments .. * LOGICAL TSTERR @@ -19,11 +19,10 @@ * .. * .. Array Arguments .. * LOGICAL DOTYPE( * ) -* INTEGER IWORK( * ), MVAL( * ), NBVAL( * ), NSVAL( * ), +* INTEGER MVAL( * ), NBVAL( * ), NSVAL( * ), * $ NVAL( * ), NXVAL( * ) -* DOUBLE PRECISION COPYS( * ), RWORK( * ), S( * ) -* COMPLEX*16 A( * ), B( * ), C( * ), COPYA( * ), COPYB( * ), -* $ WORK( * ) +* DOUBLE PRECISION COPYS( * ), S( * ) +* COMPLEX*16 A( * ), B( * ), C( * ), COPYA( * ), COPYB( * ) * .. * * @@ -32,8 +31,8 @@ *> *> \verbatim *> -*> ZDRVLS tests the least squares driver routines ZGELS, CGELSS, ZGELSY -*> and CGELSD. +*> ZDRVLS tests the least squares driver routines ZGELS, ZGETSLS, ZGELSS, ZGELSY +*> and ZGELSD. *> \endverbatim * * Arguments: @@ -170,22 +169,6 @@ *> (min(MMAX,NMAX)) *> \endverbatim *> -*> \param[out] WORK -*> \verbatim -*> WORK is COMPLEX*16 array, dimension -*> (MMAX*NMAX + 4*NMAX + MMAX). -*> \endverbatim -*> -*> \param[out] RWORK -*> \verbatim -*> RWORK is DOUBLE PRECISION array, dimension (5*NMAX-1) -*> \endverbatim -*> -*> \param[out] IWORK -*> \verbatim -*> IWORK is INTEGER array, dimension (15*NMAX) -*> \endverbatim -*> *> \param[in] NOUT *> \verbatim *> NOUT is INTEGER @@ -207,7 +190,7 @@ * ===================================================================== SUBROUTINE ZDRVLS( DOTYPE, NM, MVAL, NN, NVAL, NNS, NSVAL, NNB, $ NBVAL, NXVAL, THRESH, TSTERR, A, COPYA, B, - $ COPYB, C, S, COPYS, WORK, RWORK, IWORK, NOUT ) + $ COPYB, C, S, COPYS, NOUT ) * * -- LAPACK test routine (version 3.6.0) -- * -- LAPACK is a software package provided by Univ. of Tennessee, -- @@ -221,11 +204,10 @@ * .. * .. Array Arguments .. LOGICAL DOTYPE( * ) - INTEGER IWORK( * ), MVAL( * ), NBVAL( * ), NSVAL( * ), + INTEGER MVAL( * ), NBVAL( * ), NSVAL( * ), $ NVAL( * ), NXVAL( * ) - DOUBLE PRECISION COPYS( * ), RWORK( * ), S( * ) - COMPLEX*16 A( * ), B( * ), C( * ), COPYA( * ), COPYB( * ), - $ WORK( * ) + DOUBLE PRECISION COPYS( * ), S( * ) + COMPLEX*16 A( * ), B( * ), C( * ), COPYA( * ), COPYB( * ) * .. * * ===================================================================== @@ -247,12 +229,22 @@ INTEGER CRANK, I, IM, IMB, IN, INB, INFO, INS, IRANK, $ ISCALE, ITRAN, ITYPE, J, K, LDA, LDB, LDWORK, $ LWLSY, LWORK, M, MNMIN, N, NB, NCOLS, NERRS, - $ NFAIL, NRHS, NROWS, NRUN, RANK, MB, LWTS + $ NFAIL, NRHS, NROWS, NRUN, RANK, MB, + $ MMAX, NMAX, NSMAX, LIWORK, LRWORK, + $ LWORK_ZGELS, LWORK_ZGETSLS, LWORK_ZGELSS, + $ LWORK_ZGELSY, LWORK_ZGELSD, + $ LRWORK_ZGELSY, LRWORK_ZGELSS, LRWORK_ZGELSD DOUBLE PRECISION EPS, NORMA, NORMB, RCOND * .. * .. Local Arrays .. - INTEGER ISEED( 4 ), ISEEDY( 4 ) - DOUBLE PRECISION RESULT( NTESTS ) + INTEGER ISEED( 4 ), ISEEDY( 4 ), IWORKQUERY + DOUBLE PRECISION RESULT( NTESTS ), RWORKQUERY + COMPLEX*16 WORKQUERY +* .. +* .. Allocatable Arrays .. + COMPLEX*16, ALLOCATABLE :: WORK (:) + DOUBLE PRECISION, ALLOCATABLE :: RWORK (:) + INTEGER, ALLOCATABLE :: IWORK (:) * .. * .. External Functions .. DOUBLE PRECISION DASUM, DLAMCH, ZQRT12, ZQRT14, ZQRT17 @@ -265,7 +257,7 @@ $ ZQRT16, ZGETSLS * .. * .. Intrinsic Functions .. - INTRINSIC DBLE, MAX, MIN, SQRT + INTRINSIC DBLE, MAX, MIN, INT, SQRT * .. * .. Scalars in Common .. LOGICAL LERR, OK @@ -309,6 +301,77 @@ $ CALL ALAHD( NOUT, PATH ) INFOT = 0 * +* Compute maximal workspace needed for all routines +* + NMAX = 0 + MMAX = 0 + NSMAX = 0 + DO I = 1, NM + IF ( MVAL( I ).GT.MMAX ) THEN + MMAX = MVAL( I ) + END IF + ENDDO + DO I = 1, NN + IF ( NVAL( I ).GT.NMAX ) THEN + NMAX = NVAL( I ) + END IF + ENDDO + DO I = 1, NNS + IF ( NSVAL( I ).GT.NSMAX ) THEN + NSMAX = NSVAL( I ) + END IF + ENDDO + M = MMAX + N = NMAX + NRHS = NSMAX + LDA = MAX( 1, M ) + LDB = MAX( 1, M, N ) + MNMIN = MAX( MIN( M, N ), 1 ) +* +* Compute workspace needed for routines +* ZQRT14, ZQRT17 (two side cases), ZQRT15 and ZQRT12 +* + LWORK = MAX( ( M+N )*NRHS, + $ ( N+NRHS )*( M+2 ), ( M+NRHS )*( N+2 ), + $ MAX( M+MNMIN, NRHS*MNMIN,2*N+M ), + $ MAX( M*N+4*MNMIN+MAX(M,N), M*N+2*MNMIN+4*N ) ) +* +* Compute workspace needed for ZGELS + CALL ZGELS( 'N', M, N, NRHS, A, LDA, B, LDB, + $ WORKQUERY, -1, INFO ) + LWORK_ZGELS = INT ( WORKQUERY ) +* Compute workspace needed for ZGETSLS + CALL ZGETSLS( 'N', M, N, NRHS, A, LDA, B, LDB, + $ WORKQUERY, -1, INFO ) + LWORK_ZGETSLS = INT( WORKQUERY ) +* Compute workspace needed for ZGELSY + CALL ZGELSY( M, N, NRHS, A, LDA, B, LDB, IWORKQUERY, + $ RCOND, CRANK, WORKQUERY, -1, RWORK, INFO ) + LWORK_ZGELSY = INT( WORKQUERY ) + LRWORK_ZGELSY = 2*N +* Compute workspace needed for ZGELSS + CALL ZGELSS( M, N, NRHS, A, LDA, B, LDB, S, + $ RCOND, CRANK, WORKQUERY, -1 , RWORK, INFO ) + LWORK_ZGELSS = INT( WORKQUERY ) + LRWORK_ZGELSS = 5*MNMIN +* Compute workspace needed for ZGELSD + CALL ZGELSD( M, N, NRHS, A, LDA, B, LDB, S, RCOND, CRANK, + $ WORKQUERY, -1, RWORKQUERY, IWORKQUERY, INFO ) + LWORK_ZGELSD = INT( WORKQUERY ) + LRWORK_ZGELSD = INT( RWORKQUERY ) +* Compute LIWORK workspace needed for ZGELSY and ZGELSD + LIWORK = MAX( 1, N, IWORKQUERY ) +* Compute LRWORK workspace needed for ZGELSY, ZGELSS and ZGELSD + LRWORK = MAX( 1, LRWORK_ZGELSY, LRWORK_ZGELSS, LRWORK_ZGELSD ) +* Compute LWORK workspace needed for all functions + LWORK = MAX( 1, LWORK, LWORK_ZGELS, LWORK_ZGETSLS, LWORK_ZGELSY, + $ LWORK_ZGELSS, LWORK_ZGELSD ) + LWLSY = LWORK +* + ALLOCATE( WORK( LWORK ) ) + ALLOCATE( IWORK( LIWORK ) ) + ALLOCATE( RWORK( LRWORK ) ) +* DO 140 IM = 1, NM M = MVAL( IM ) LDA = MAX( 1, M ) @@ -318,16 +381,9 @@ MNMIN = MAX(MIN( M, N ),1) LDB = MAX( 1, M, N ) MB = (MNMIN+1) - IF(MNMIN.NE.MB) THEN - LWTS = (((LDB-MB)/(MB-MNMIN))*MNMIN+LDB*2)*MB+5 - ELSE - LWTS = 2*MNMIN+5 - END IF * DO 120 INS = 1, NNS NRHS = NSVAL( INS ) - LWORK = MAX( 1, ( M+NRHS )*( N+2 ), ( N+NRHS )*( M+2 ), - $ M*N+4*MNMIN+MAX( M, N ), 2*N+M, LWTS ) * DO 110 IRANK = 1, 2 DO 100 ISCALE = 1, 3 @@ -578,12 +634,6 @@ IWORK( J ) = 0 70 CONTINUE * -* Set LWLSY to the adequate value. -* - LWLSY = MNMIN + MAX( 2*MNMIN, NB*( N+1 ), - $ MNMIN+NB*NRHS ) - LWLSY = MAX( 1, LWLSY ) -* SRNAMT = 'ZGELSY' CALL ZGELSY( M, N, NRHS, A, LDA, B, LDB, IWORK, $ RCOND, CRANK, WORK, LWLSY, RWORK, @@ -774,6 +824,10 @@ 9997 FORMAT( ' TRANS=''', A1,' M=', I5, ', N=', I5, ', NRHS=', I4, $ ', MB=', I4,', NB=', I4,', type', I2, $ ', test(', I2, ')=', G12.5 ) +* + DEALLOCATE( WORK ) + DEALLOCATE( IWORK ) + DEALLOCATE( RWORK ) RETURN * * End of ZDRVLS diff --git a/TESTING/LIN/zerrtsqr.f b/TESTING/LIN/zerrtsqr.f index 3aa3e4a5..5550e219 100644 --- a/TESTING/LIN/zerrtsqr.f +++ b/TESTING/LIN/zerrtsqr.f @@ -161,13 +161,13 @@ CALL ZGEMQR( 'L', 'N', 2, 1, 0, A, 0, TAU, 1, C, 1, W, 1,INFO) CALL CHKXER( 'ZGEMQR', INFOT, NOUT, LERR, OK ) INFOT = 9 - CALL ZGEMQR( 'R', 'N', 2, 2, 1, A, 1, TAU, 0, C, 1, W, 1,INFO) + CALL ZGEMQR( 'R', 'N', 2, 2, 1, A, 2, TAU, 0, C, 1, W, 1,INFO) CALL CHKXER( 'ZGEMQR', INFOT, NOUT, LERR, OK ) INFOT = 9 - CALL ZGEMQR( 'L', 'N', 2, 2, 1, A, 1, TAU, 0, C, 1, W, 1,INFO) + CALL ZGEMQR( 'L', 'N', 2, 2, 1, A, 2, TAU, 0, C, 1, W, 1,INFO) CALL CHKXER( 'ZGEMQR', INFOT, NOUT, LERR, OK ) INFOT = 11 - CALL ZGEMQR( 'L', 'N', 2, 1, 1, A, 1, TAU, 6, C, 0, W, 1,INFO) + CALL ZGEMQR( 'L', 'N', 2, 1, 1, A, 2, TAU, 6, C, 0, W, 1,INFO) CALL CHKXER( 'ZGEMQR', INFOT, NOUT, LERR, OK ) INFOT = 13 CALL ZGEMQR( 'L', 'N', 2, 2, 1, A, 2, TAU, 6, C, 2, W, 0,INFO) diff --git a/TESTING/LIN/ztsqr01.f b/TESTING/LIN/ztsqr01.f index 38ace9c8..acc027e0 100644 --- a/TESTING/LIN/ztsqr01.f +++ b/TESTING/LIN/ztsqr01.f @@ -109,11 +109,12 @@ * .. * .. Local Scalars .. LOGICAL TESTZEROS, TS - INTEGER INFO, J, K, L, LWORK, LT ,MNB + INTEGER INFO, J, K, L, LWORK, TSIZE, MNB DOUBLE PRECISION ANORM, EPS, RESID, CNORM, DNORM * .. * .. Local Arrays .. INTEGER ISEED( 4 ) + COMPLEX*16 TQUERY( 5 ), WORKQUERY * .. * .. External Functions .. DOUBLE PRECISION DLAMCH, ZLANGE, ZLANSY @@ -145,17 +146,11 @@ L = MAX(M,N,1) MNB = MAX ( MB, NB) LWORK = MAX(3,L)*MNB - IF((K.GE.MNB).OR.(MNB.GE.L))THEN - LT=MAX(1,L)*MNB+5 - ELSE - LT=MAX(1,(L-K)/(MNB-K)+1)*L*MNB+5 - END IF - * * Dynamically allocate local arrays * ALLOCATE ( A(M,N), AF(M,N), Q(L,L), R(M,L), RWORK(L), - $ WORK(LWORK), T(LT), C(M,N), CF(M,N), + $ C(M,N), CF(M,N), $ D(N,M), DF(N,M), LQ(L,N) ) * * Put random numbers into A and copy to AF @@ -176,14 +171,34 @@ * * Factor the matrix A in the array AF. * + CALL ZGEQR( M, N, AF, M, TQUERY, -1, WORKQUERY, -1, INFO ) + TSIZE = INT( TQUERY( 1 ) ) + LWORK = INT( WORKQUERY ) + CALL ZGEMQR( 'L', 'N', M, M, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL ZGEMQR( 'L', 'N', M, N, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL ZGEMQR( 'L', 'C', M, N, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL ZGEMQR( 'R', 'N', N, M, K, AF, M, TQUERY, TSIZE, DF, N, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL ZGEMQR( 'R', 'C', N, M, K, AF, M, TQUERY, TSIZE, DF, N, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + ALLOCATE ( T( TSIZE ) ) + ALLOCATE ( WORK( LWORK ) ) srnamt = 'ZGEQR' - CALL ZGEQR( M, N, AF, M, T, LT, WORK, LWORK, INFO ) + CALL ZGEQR( M, N, AF, M, T, TSIZE, WORK, LWORK, INFO ) * * Generate the m-by-m matrix Q * CALL ZLASET( 'Full', M, M, CZERO, ONE, Q, M ) srnamt = 'ZGEMQR' - CALL ZGEMQR( 'L', 'N', M, M, K, AF, M, T, LT, Q, M, + CALL ZGEMQR( 'L', 'N', M, M, K, AF, M, T, TSIZE, Q, M, $ WORK, LWORK, INFO ) * * Copy R @@ -220,7 +235,7 @@ * Apply Q to C as Q*C * srnamt = 'ZGEMQR' - CALL ZGEMQR( 'L', 'N', M, N, K, AF, M, T, LT, CF, M, + CALL ZGEMQR( 'L', 'N', M, N, K, AF, M, T, TSIZE, CF, M, $ WORK, LWORK, INFO) * * Compute |Q*C - Q*C| / |C| @@ -240,7 +255,7 @@ * Apply Q to C as QT*C * srnamt = 'ZGEMQR' - CALL ZGEMQR( 'L', 'C', M, N, K, AF, M, T, LT, CF, M, + CALL ZGEMQR( 'L', 'C', M, N, K, AF, M, T, TSIZE, CF, M, $ WORK, LWORK, INFO) * * Compute |QT*C - QT*C| / |C| @@ -264,7 +279,7 @@ * Apply Q to D as D*Q * srnamt = 'ZGEMQR' - CALL ZGEMQR( 'R', 'N', N, M, K, AF, M, T, LT, DF, N, + CALL ZGEMQR( 'R', 'N', N, M, K, AF, M, T, TSIZE, DF, N, $ WORK, LWORK, INFO) * * Compute |D*Q - D*Q| / |D| @@ -283,7 +298,7 @@ * * Apply Q to D as D*QT * - CALL ZGEMQR( 'R', 'C', N, M, K, AF, M, T, LT, DF, N, + CALL ZGEMQR( 'R', 'C', N, M, K, AF, M, T, TSIZE, DF, N, $ WORK, LWORK, INFO) * * Compute |D*QT - D*QT| / |D| @@ -299,15 +314,35 @@ * Short and wide * ELSE + CALL ZGELQ( M, N, AF, M, TQUERY, -1, WORKQUERY, -1, INFO ) + TSIZE = INT( TQUERY( 1 ) ) + LWORK = INT( WORKQUERY ) + CALL ZGEMLQ( 'R', 'N', N, N, K, AF, M, TQUERY, TSIZE, Q, N, + $ WORKQUERY, -1, INFO ) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL ZGEMLQ( 'L', 'N', N, M, K, AF, M, TQUERY, TSIZE, DF, N, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL ZGEMLQ( 'L', 'C', N, M, K, AF, M, TQUERY, TSIZE, DF, N, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL ZGEMLQ( 'R', 'N', M, N, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + CALL ZGEMLQ( 'R', 'C', M, N, K, AF, M, TQUERY, TSIZE, CF, M, + $ WORKQUERY, -1, INFO) + LWORK = MAX( LWORK, INT( WORKQUERY ) ) + ALLOCATE ( T( TSIZE ) ) + ALLOCATE ( WORK( LWORK ) ) srnamt = 'ZGELQ' - CALL ZGELQ( M, N, AF, M, T, LT, WORK, LWORK, INFO ) + CALL ZGELQ( M, N, AF, M, T, TSIZE, WORK, LWORK, INFO ) * * * Generate the n-by-n matrix Q * CALL ZLASET( 'Full', N, N, CZERO, ONE, Q, N ) srnamt = 'ZGEMLQ' - CALL ZGEMLQ( 'R', 'N', N, N, K, AF, M, T, LT, Q, N, + CALL ZGEMLQ( 'R', 'N', N, N, K, AF, M, T, TSIZE, Q, N, $ WORK, LWORK, INFO ) * * Copy R @@ -343,7 +378,7 @@ * * Apply Q to C as Q*C * - CALL ZGEMLQ( 'L', 'N', N, M, K, AF, M, T, LT, DF, N, + CALL ZGEMLQ( 'L', 'N', N, M, K, AF, M, T, TSIZE, DF, N, $ WORK, LWORK, INFO) * * Compute |Q*D - Q*D| / |D| @@ -362,7 +397,7 @@ * * Apply Q to D as QT*D * - CALL ZGEMLQ( 'L', 'C', N, M, K, AF, M, T, LT, DF, N, + CALL ZGEMLQ( 'L', 'C', N, M, K, AF, M, T, TSIZE, DF, N, $ WORK, LWORK, INFO) * * Compute |QT*D - QT*D| / |D| @@ -385,7 +420,7 @@ * * Apply Q to C as C*Q * - CALL ZGEMLQ( 'R', 'N', M, N, K, AF, M, T, LT, CF, M, + CALL ZGEMLQ( 'R', 'N', M, N, K, AF, M, T, TSIZE, CF, M, $ WORK, LWORK, INFO) * * Compute |C*Q - C*Q| / |C| @@ -404,7 +439,7 @@ * * Apply Q to D as D*QT * - CALL ZGEMLQ( 'R', 'C', M, N, K, AF, M, T, LT, CF, M, + CALL ZGEMLQ( 'R', 'C', M, N, K, AF, M, T, TSIZE, CF, M, $ WORK, LWORK, INFO) * * Compute |C*QT - C*QT| / |C| |