kopia lustrzana https://github.com/Dsplib/libdspl-2.0
added pseudoinverion of matrix
Changes to be committed: modified: dspl/src/matrix.c new file: examples/src/matrix_pinv_test.c modified: include/dspl.c modified: include/dspl.hpull/6/merge
rodzic
f848c84fac
commit
b810cb1e22
|
@ -20,6 +20,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <float.h>
|
||||||
#include "dspl.h"
|
#include "dspl.h"
|
||||||
#include "dspl_internal.h"
|
#include "dspl_internal.h"
|
||||||
#include "blas.h"
|
#include "blas.h"
|
||||||
|
@ -235,50 +236,116 @@ int DSPL_API matrix_mul(double* a, int na, int ma,
|
||||||
#ifdef DOXYGEN_RUSSIAN
|
#ifdef DOXYGEN_RUSSIAN
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
int DSPL_API matrix_svd(double* a, int n, int m,
|
int DSPL_API matrix_pinv(double* a, int n, int m, double* tol,
|
||||||
double* u, double* s, double* vt, int* info)
|
double* inv, int* info)
|
||||||
{
|
{
|
||||||
char jobz = 'A';
|
int err, mn, i, j;
|
||||||
double* work = NULL;
|
double eps;
|
||||||
int* iwork = NULL;
|
|
||||||
int lwork, mn, mx, err;
|
|
||||||
int pi;
|
double* u = NULL;
|
||||||
|
double* vt = NULL;
|
||||||
|
double* v = NULL;
|
||||||
|
double* ut = NULL;
|
||||||
|
double* s = NULL;
|
||||||
|
|
||||||
if(!a || !u || !s || !vt)
|
|
||||||
return ERROR_PTR;
|
|
||||||
if(n < 1 || m < 1)
|
|
||||||
return ERROR_SIZE;
|
|
||||||
|
|
||||||
|
|
||||||
if(n > m)
|
mn = (m > n) ? n : m;
|
||||||
|
|
||||||
|
u = (double*) malloc(n*n*sizeof(double));
|
||||||
|
if(!u)
|
||||||
{
|
{
|
||||||
mn = m;
|
err = ERROR_MALLOC;
|
||||||
mx = n;
|
goto exit_label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vt = (double*) malloc(m*m*sizeof(double));
|
||||||
|
if(!vt)
|
||||||
|
{
|
||||||
|
err = ERROR_MALLOC;
|
||||||
|
goto exit_label;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = (double*) malloc(mn*sizeof(double));
|
||||||
|
if(!s)
|
||||||
|
{
|
||||||
|
err = ERROR_MALLOC;
|
||||||
|
goto exit_label;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = matrix_svd(a, n, m, u, s, vt, info);
|
||||||
|
if(err != RES_OK)
|
||||||
|
goto exit_label;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(tol)
|
||||||
|
eps = *tol;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mn = n;
|
double smax;
|
||||||
mx = m;
|
double mx = (n > m) ? (double)n : (double)m;
|
||||||
|
err = minmax(s, mn, NULL, &smax);
|
||||||
|
eps = DBL_EPSILON * mx * smax;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = RES_OK;
|
for(i = 0; i < mn; i++)
|
||||||
|
if(s[i] > eps)
|
||||||
|
s[i] = 1.0 / s[i];
|
||||||
|
else
|
||||||
|
s[i] = 0.0;
|
||||||
|
|
||||||
|
v = (double*) malloc(m*m*sizeof(double));
|
||||||
|
if(!v)
|
||||||
|
{
|
||||||
|
err = ERROR_MALLOC;
|
||||||
|
goto exit_label;
|
||||||
|
}
|
||||||
|
err = matrix_transpose(vt, m, m, v);
|
||||||
|
if(err != RES_OK)
|
||||||
|
goto exit_label;
|
||||||
|
|
||||||
lwork = 4 * mn * mn + 6 * mn + mx;
|
ut = (double*) malloc(n*n*sizeof(double));
|
||||||
work = (double*) malloc(lwork*sizeof(double));
|
if(!ut)
|
||||||
iwork = (int*) malloc(8*mn*sizeof(int));
|
{
|
||||||
dgesdd_(&jobz, &n, &m, a, &n, s, u, &n, vt, &m, work, &lwork, iwork, &pi);
|
err = ERROR_MALLOC;
|
||||||
|
goto exit_label;
|
||||||
|
}
|
||||||
|
err = matrix_transpose(u, n, n, ut);
|
||||||
|
if(err != RES_OK)
|
||||||
|
goto exit_label;
|
||||||
|
|
||||||
|
for(i = 0; i < mn; i++)
|
||||||
|
for(j = 0; j < m; j++)
|
||||||
|
v[j + i*m] *= s[i];
|
||||||
|
|
||||||
|
if(mn < m)
|
||||||
|
memset(v+ mn*m, 0, (m-mn)*sizeof(double));
|
||||||
|
|
||||||
|
err = matrix_mul(v, m, n, ut, n, n, inv);
|
||||||
|
|
||||||
|
exit_label:
|
||||||
|
if(u)
|
||||||
|
free(u);
|
||||||
|
if(vt)
|
||||||
|
free(vt);
|
||||||
|
if(s)
|
||||||
|
free(s);
|
||||||
|
if(v)
|
||||||
|
free(v);
|
||||||
|
if(ut)
|
||||||
|
free(ut);
|
||||||
|
|
||||||
if(info)
|
|
||||||
*info = pi;
|
|
||||||
if(pi)
|
|
||||||
err = ERROR_LAPACK;
|
|
||||||
if(work)
|
|
||||||
free(work);
|
|
||||||
if(iwork)
|
|
||||||
free(iwork);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DOXYGEN_ENGLISH
|
#ifdef DOXYGEN_ENGLISH
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -357,6 +424,55 @@ int DSPL_API matrix_print_cmplx(complex_t* a, int n, int m,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DOXYGEN_ENGLISH
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#ifdef DOXYGEN_RUSSIAN
|
||||||
|
|
||||||
|
#endif
|
||||||
|
int DSPL_API matrix_svd(double* a, int n, int m,
|
||||||
|
double* u, double* s, double* vt, int* info)
|
||||||
|
{
|
||||||
|
char jobz = 'A';
|
||||||
|
double* work = NULL;
|
||||||
|
int* iwork = NULL;
|
||||||
|
int lwork, mn, mx, err;
|
||||||
|
int pi;
|
||||||
|
|
||||||
|
if(!a || !u || !s || !vt)
|
||||||
|
return ERROR_PTR;
|
||||||
|
if(n < 1 || m < 1)
|
||||||
|
return ERROR_SIZE;
|
||||||
|
|
||||||
|
if(n > m)
|
||||||
|
{
|
||||||
|
mn = m;
|
||||||
|
mx = n;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mn = n;
|
||||||
|
mx = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = RES_OK;
|
||||||
|
|
||||||
|
lwork = 4 * mn * mn + 6 * mn + mx;
|
||||||
|
work = (double*) malloc(lwork*sizeof(double));
|
||||||
|
iwork = (int*) malloc(8*mn*sizeof(int));
|
||||||
|
dgesdd_(&jobz, &n, &m, a, &n, s, u, &n, vt, &m, work, &lwork, iwork, &pi);
|
||||||
|
|
||||||
|
if(info)
|
||||||
|
*info = pi;
|
||||||
|
|
||||||
|
if(pi)
|
||||||
|
err = ERROR_LAPACK;
|
||||||
|
if(work)
|
||||||
|
free(work);
|
||||||
|
if(iwork)
|
||||||
|
free(iwork);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef DOXYGEN_ENGLISH
|
#ifdef DOXYGEN_ENGLISH
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "dspl.h"
|
||||||
|
|
||||||
|
#define N 2
|
||||||
|
#define M 6
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
void* handle; /* DSPL handle */
|
||||||
|
handle = dspl_load(); /* Load DSPL function */
|
||||||
|
|
||||||
|
/* Matrix
|
||||||
|
A = [ 1 2 2;
|
||||||
|
2 4 5;
|
||||||
|
2 0 1;
|
||||||
|
2 -1 0;];
|
||||||
|
in array a by columns
|
||||||
|
*/
|
||||||
|
double a[N*M] = { 1, 2, 2, 5, 2, 4, 4, -1, 0, 0, 3, -2};
|
||||||
|
double inv[M*N]; /* left orthogonal matrix U */
|
||||||
|
|
||||||
|
|
||||||
|
int err, info, mn;
|
||||||
|
|
||||||
|
/* print input matrix */
|
||||||
|
matrix_print(a, N, M, "A", "%8.2f");
|
||||||
|
|
||||||
|
/* SVD decomposition A = U*S*V^T */
|
||||||
|
/*-----------------------------------------------------*/
|
||||||
|
err = matrix_pinv(a, N, M, NULL, inv, &info);
|
||||||
|
if(err != RES_OK)
|
||||||
|
printf("err = %.8x info = %d\n", err, info);
|
||||||
|
|
||||||
|
/* Print SVD decomposition */
|
||||||
|
matrix_print(inv, M, N, "inv(A)", "%8.8f");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
dspl_free(handle); /* free dspl handle */
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -137,6 +137,7 @@ p_matrix_eig_cmplx matrix_eig_cmplx ;
|
||||||
p_matrix_eye matrix_eye ;
|
p_matrix_eye matrix_eye ;
|
||||||
p_matrix_eye_cmplx matrix_eye_cmplx ;
|
p_matrix_eye_cmplx matrix_eye_cmplx ;
|
||||||
p_matrix_mul matrix_mul ;
|
p_matrix_mul matrix_mul ;
|
||||||
|
p_matrix_pinv matrix_pinv ;
|
||||||
p_matrix_print matrix_print ;
|
p_matrix_print matrix_print ;
|
||||||
p_matrix_print_cmplx matrix_print_cmplx ;
|
p_matrix_print_cmplx matrix_print_cmplx ;
|
||||||
p_matrix_svd matrix_svd ;
|
p_matrix_svd matrix_svd ;
|
||||||
|
@ -350,6 +351,7 @@ void* dspl_load()
|
||||||
LOAD_FUNC(matrix_eye);
|
LOAD_FUNC(matrix_eye);
|
||||||
LOAD_FUNC(matrix_eye_cmplx);
|
LOAD_FUNC(matrix_eye_cmplx);
|
||||||
LOAD_FUNC(matrix_mul);
|
LOAD_FUNC(matrix_mul);
|
||||||
|
LOAD_FUNC(matrix_pinv);
|
||||||
LOAD_FUNC(matrix_print);
|
LOAD_FUNC(matrix_print);
|
||||||
LOAD_FUNC(matrix_print_cmplx);
|
LOAD_FUNC(matrix_print_cmplx);
|
||||||
LOAD_FUNC(matrix_svd);
|
LOAD_FUNC(matrix_svd);
|
||||||
|
|
|
@ -1216,6 +1216,13 @@ DECLARE_FUNC(int, matrix_mul, double* a
|
||||||
COMMA int mb
|
COMMA int mb
|
||||||
COMMA double* c);
|
COMMA double* c);
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
DECLARE_FUNC(int, matrix_pinv, double* a
|
||||||
|
COMMA int n
|
||||||
|
COMMA int m
|
||||||
|
COMMA double* tol
|
||||||
|
COMMA double* inv
|
||||||
|
COMMA int* info);
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
DECLARE_FUNC(int, matrix_print, double* a
|
DECLARE_FUNC(int, matrix_print, double* a
|
||||||
COMMA int n
|
COMMA int n
|
||||||
COMMA int m
|
COMMA int m
|
||||||
|
|
Ładowanie…
Reference in New Issue