---
title: ?gesdd
description: "计算矩形矩阵的奇异值分解，可以用来计算左和右奇异向量，使用分治算法。"
url: https://www.hikunpeng.com/document/detail/zh/hpchistory/hpckit/develop2400/kunpengaccel_kml_0711.html
sourcePath: /source/zh/hpchistory/hpckit/develop2400/kunpengaccel_kml_0711.html
indexId: cc1818e1f530a39cc9f9ad66c89674ca40211d84b677e57b8bc7c93e22c4063167
---
# ?gesdd

计算矩形矩阵的奇异值分解，可以用来计算左和右奇异向量，使用分治算法。

#### 接口定义

C Interface：

void sgesdd_(const char *jobz, const int *m, const int *n, float *a, const int *lda, float *s, float *u, const int *ldu, float *vt, const int *ldvt, float *work, const int *lwork, int *iwork, int *info);

void dgesdd_(const char *jobz, const int *m, const int *n, double *a, const int *lda, double *s, double *u, const int *ldu, double *vt, const int *ldvt, double *work, const int *lwork, int *iwork, int *info);

void cgesdd_(const char *jobz, const int *m, const int *n, float _Complex *a, const int *lda, float *s, float _Complex *u, const int *ldu, float _Complex *vt, const int *ldvt, float _Complex *work, const int *lwork, float *rwork, int *iwork, int *info);

void zgesdd_(const char *jobz, const int *m, const int *n, double _Complex *a, const int *lda, double *s, double _Complex *u, const int *ldu, double _Complex *vt, const int *ldvt, double _Complex *work, const int *lwork, double *rwork, int *iwork, int *info);

Fortran Interface：

SGESDD(JOBZ, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK, IWORK, INFO)

DGESDD(JOBZ, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK, IWORK, INFO)

CGESDD(JOBZ, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK, RWORK, IWORK, INFO)

ZGESDD(JOBZ, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK, RWORK, IWORK, INFO)


#### 参数

| 参数 | 类型 | 说明 | 输入/输出 |
| --- | --- | --- | --- |
| jobz | 字符型 | 'N'：只计算特征值不返回U和Vt。 'S'：返回前min(M,N)列U和前min(M,N)行Vt。 'O'：如果M>=N，前N列U重写在矩阵A上，所有Vt行都返回在数组Vt上。 'A'：所有M列U和所有N行Vt都返回在数据U和Vt上。 | 输入 |
| m | 整数型 | 矩阵的维度，m≥0。 | 输入 |
| n | 整数型 | 矩阵的维度，m≥0。 | 输入 |
| a | 在sgesdd中为单精度浮点型数组 在dgesdd中为双精度浮点型数组 在cgesdd中为单精度复数型数组 在zgesdd中为双精度复数型数组 | 大小为M\*N 进入时：M\*N的矩阵。 退出时： 如果jobz='O'，M>=N时，A被U的前N列覆盖（左奇异值向量，按列存储）；如果jobz!='O'，销毁A。 | 输入，输出 |
| lda | 整数型 | 矩阵A的前导维度，lda>=max(1,M)。 | 输入 |
| s | 在sstedc中为单精度浮点型数组 在dstedc中为双精度浮点型数组 在cstedc中为单精度浮点型数组 在zstedc中为双精度浮点型数组 | 大小为min(M,N)。 矩阵A的奇异值，降序排列。 | 输出 |
| u | 在sgesdd中为单精度浮点型数组 在dgesdd中为双精度浮点型数组 在cgesdd中为单精度复数型数组 在zgesdd中为双精度复数型数组 | 二维数组，大小为LDU\*UCOL。 如果jobz='A'或'O'并且M<N，UCOL=M，u中存储M\*M的正交矩阵。 如果jobz='S'，UCOL=min(M,N)，u中存储前min(M,N)列的U，左奇异值向量，按列存储。 如果jobz='O'并且M>=N，或者jobz='N', 该参数无意义。 | 输出 |
| ldu | 整数型 | 矩阵u的前导维度，ldu>=1。 如果jobz='S'或'A'，或者jobz='O'并且M<N，LDU>=M。 | 输入 |
| vt | 在sgesdd中为单精度浮点型数组 在dgesdd中为双精度浮点型数组 在cgesdd中为单精度复数型数组 在zgesdd中为双精度复数型数组 | 二维数组，大小为LDVT\*N。 如果jobz='A'或'O'并且M<N，UCOL=M，存储M\*M的正交矩阵。 如果jobz='S'， 存储前min(M,N)列的vt，右奇异值向量，按行存储。 如果jobz='O'并且M>=N，或者jobz='N', 该参数无意义。 | 输出 |
| ldvt | 整数型 | 矩阵vt的前导维度，ldvt>=1。 如果jobz='A'或'O'并且M<N，LDU>=N。 如果jobz='S'，ldvt>=min(M,N)。 | 输入 |
| work | 在sgesdd中为单精度浮点型数组 在dgesdd中为双精度浮点型数组 在cgesdd中为单精度复数型数组 在zgesdd中为双精度复数型数组 | 数组维度为max(1,LWORK)。 退出时，如果info=0，第一个元素返回合适的lwork。 | 输出 |
| lwork | 整数型 | 矩阵work的维度，lwork>=1。如果lwork=1，默认为查询状态，在work第一个元素中返回合适的大小，并且不检查其它work的参数。 如果JOBZ ='N'，则LWORK >= 3\*mn + max( mx, 7\*mn )。 如果JOBZ ='O'，则LWORK >= 3\*mn + max( mx, 5\*mn\*mn + 4\*mn )。 如果JOBZ ='S'，则LWORK >= 4\*mn\*mn + 7\*mn。 如果JOBZ ='A'，则LWORK >= 4\*mn\*mn + 6\*mn + mx。 | 输入 |
| iwork | 整数型数组 | 数组维度为8\*min(M,N)。 | 输出 |
| info | 整数型 | 等于0：表示成功。 小于0：info=\-i，表示第i个参数非法。 大于0：计算出错。 | 输出 |


#### 依赖

#include "klapack.h"


#### 示例

C Interface：

```
const char jobz = 'A';
const int m = 5;
const int n = 5;
const int lda = 5;
const int ldu = 5;
const int ldvt = 5;

double a[] = {72.1673, 66.1857, 64.7644, 28.0199, 91.4151,
              6.5180,  62.8483, 72.4323, 46.5760, 8.6928,
              28.9821, 42.1828, 18.6437, 99.8612, 35.6972,
              67.9812, 5.0880,  85.5035, 79.2945, 54.5920,
              28.6869, 49.7512, 7.5186,  28.6929, 84.6041};

double *s = (double*)malloc(m * sizeof(double));
double *u = (double*)malloc(ldu*m * sizeof(double));
double *vt = (double*)malloc(ldvt*n * sizeof(double));
double *iwork = (double*)malloc(8 * m * sizeof(double));

double qwork;
int lwork = -1;
int info = 0;

dgesdd_(&jobz, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, &qwork, &lwork, iwork, &info);
if (info != 0) {
    printf("Error, info = %d\n", info);
    return info;
}

lwork = (int)qwork;
double *work = (double*)malloc(lwork * sizeof(double));

dgesdd_(&jobz, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, iwork, &info);
if (info != 0) {
    printf("Error, info = %d\n", info);
    return info;
}

* output:
* s:
* 254.071516      87.547400       67.835073       64.370735       14.897476
* u:
* -0.395825       -0.377874       -0.458327       -0.488090       -0.502234       -0.155273       -0.217110       0.348128        0.628260        -0.642534       * -0.312281       0.362918        -0.694714       0.528618        0.093312        -0.399962       0.761762        0.321232        -0.289476       -0.269743       * -0.749482       -0.313183       0.287969        0.061841        0.503430
* vt:
* -0.562230       -0.504441       -0.297298       0.148954        -0.564680       -0.340949       0.391046        -0.060652       0.818829        0.238069        * -0.403926       0.372759        0.728616      -0.186514        -0.363629       -0.527964       0.375181        -0.468379       -0.520847       0.299721        * -0.354610       -0.559386       0.397083        -0.035531       0.634351
```

Fortran Interface：

```
CHARACTER :: jobz = "A"
PARAMETER (m = 5)
PARAMETER (n = 5)
PARAMETER (lda = 5)
PARAMETER (ldu = 5)
PARAMETER (ldvt = 5)
INTEGER :: info = 0
REAL(8) :: a(lad, n)
REAL(8) :: s(m)
REAL(8) :: u(ldu, m)
REAL(8) :: vt(ldvt, n)
REAL(8) :: iwork(8, m)
REAL(8), ALLOCATABLE :: work(:)
INTEGER :: lwork = -1
REAL(8) :: qwork
DATA a / 72.1673, 66.1857, 64.7644, 28.0199, 91.4151,
6.5180,  62.8483, 72.4323, 46.5760, 8.6928,
28.9821, 42.1828, 18.6437, 99.8612, 35.6972,
67.9812, 5.0880,  85.5035, 79.2945, 54.5920,
28.6869, 49.7512, 7.5186,  28.6929, 84.6041/
EXTERNAL DGESDD
CALL DGESDD(jobu, jobvt, m, n, a, lda, s, u, ldu, vt, ldvt, qwork, lwork, iwork, info);
lwork = (int)qwork;
work = (double *)malloc(sizeof(double) * lwork);
CALL DGESDD(jobu, jobvt, m, n, a, lda, s, u, ldu, vt, ldvt, work, lwork, iwork, info);
*
* Output:
* s:
* 254.071516      87.547400       67.835073       64.370735       14.897476
* u:
* -0.395825       -0.377874       -0.458327       -0.488090       -0.502234       -0.155273       -0.217110       0.348128        0.628260        -0.642534       * -0.312281       0.362918        -0.694714       0.528618        0.093312        -0.399962       0.761762        0.321232        -0.289476       -0.269743       * -0.749482       -0.313183       0.287969        0.061841        0.503430
* vt:
* -0.562230       -0.504441       -0.297298       0.148954        -0.564680       -0.340949       0.391046        -0.060652       0.818829        0.238069        * -0.403926       0.372759        0.728616      -0.186514        -0.363629       -0.527964       0.375181        -0.468379       -0.520847       0.299721        * -0.354610       -0.559386       0.397083        -0.035531       0.634351
```
