⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 svd.cpp

📁 本程序将独立分量分析技术和数字水印技术有机地结合在一起
💻 CPP
字号:
#include <math.h>
#include <stdio.h>
#include <malloc.h>
/* svd-奇异值分解子程序(SVD) 
 * 把m×n矩阵a分解成udv,这里u,v分别为其左正交和右正交矩阵,d是奇异值对角矩阵
 * 参数说明:
 *   a : 所要分解的m×n矩阵a, 返回左正交矩阵u
 *   m : 矩阵a的行
 *   n : 矩阵a的列
 *   d : 返回矩阵a的向量
 *   v : 返回矩阵a的右正交矩阵
*/

#define SIGN(a, b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
#define MAX(x,y) ((x)>(y)?(x):(y))
 
static double PYTHAG(double a, double b)
{
    double at = fabs(a), bt = fabs(b), ct, result;

    if (at > bt)       { ct = bt / at; result = at * sqrt(1.0 + ct * ct); }
    else if (bt > 0.0) { ct = at / bt; result = bt * sqrt(1.0 + ct * ct); }
    else result = 0.0;
    return(result);
}


int svd(float *a, int m, int n, float *d, float *v)
{
    int flag, i, its, j, jj, k, l, nm;
    double c, f, h, s, x, y, z;
    double anorm = 0.0, g = 0.0, scale = 0.0;
    double *rv1;
  
    if (m < n) 
    {
        fprintf(stderr, "#rows must be > #cols \n");
        return(0);
    }
  
    rv1 = (double *)malloc((unsigned int) n*sizeof(double));

/* Householder reduction to bidiagonal form */
    for (i = 0; i < n; i++) 
    {
        /* left-hand reduction */
        l = i + 1;
        rv1[i] = scale * g;
        g = s = scale = 0.0;
        if (i < m) 
        {
            for (k = i; k < m; k++) 
				scale += fabs((double)a[k*m+i]);
            if (scale) 
            {
                for (k = i; k < m; k++) 
                {
                    a[k*m+i] = (float)((double)a[k*m+i]/scale);
                    s += ((double)a[k*m+i] * (double)a[k*m+i]);
                }
                f = (double)a[i*n+i];
                g = -SIGN(sqrt(s), f);
                h = f * g - s;
                a[i*n+i] = (float)(f - g);
                if (i != n - 1) 
                {
                    for (j = l; j < n; j++) 
                    {
                        for (s = 0.0, k = i; k < m; k++) 
							s += ((double)a[k*m+i] * (double)a[k*m+j]);

                        f = s / h;
                        for (k = i; k < m; k++) 
							a[k*m+j] += (float)(f * (double)a[k*m+i]);
                    }
                }
                for (k = i; k < m; k++) 
					a[k*m+i] = (float)((double)a[k*m+i]*scale);
            }
        }
        d[i] = (float)(scale * g);
    
        /* right-hand reduction */
        g = s = scale = 0.0;
        if (i < m && i != n - 1) 
        {
            for (k = l; k < n; k++) 
				scale += fabs((double)a[i*n+k]);
            if (scale) 
            {
                for (k = l; k < n; k++) 
                {
                    a[i*n+k] = (float)((double)a[i*n+k]/scale);
					s += ((double)a[i*n+k] * (double)a[i*n+k]);

                }
				f = (double)a[i*n+l];
                g = -SIGN(sqrt(s), f);
                h = f * g - s;
                a[i*n+l] = (float)(f - g);
                for (k = l; k < n; k++) 
                    rv1[k] = (double)a[i*n+k] / h;
                if (i != m - 1) 
                {
                    for (j = l; j < m; j++) 
                    {
                        for (s = 0.0, k = l; k < n; k++) 
                            s += ((double)a[j*m+k] * (double)a[i*n+k]);
                        for (k = l; k < n; k++) 
                            a[j*m+k] += (float)(s * rv1[k]);
                    }
                }
                for (k = l; k < n; k++) 
                    a[i*n+k] = (float)((double)a[i*n+k]*scale);
            }
        }
        anorm = MAX(anorm, (fabs((double)d[i]) + fabs(rv1[i])));
    }
  
    /* accumulate the right-hand transformation */
    for (i = n - 1; i >= 0; i--) 
    {
        if (i < n - 1) 
        {
            if (g) 
            {
                for (j = l; j < n; j++)
                    v[j*n+i] = (float)(((double)a[i*n+j] / (double)a[i*n+l]) / g);
                    /* double division to avoid underflow */
                for (j = l; j < n; j++) 
                {
                    for (s = 0.0, k = l; k < n; k++) 
                        s += ((double)a[i*n+k] * (double)v[k*n+j]);
                    for (k = l; k < n; k++) 
                        v[k*n+j] += (float)(s * (double)v[k*n+i]);
                }
            }
            for (j = l; j < n; j++) 
                v[i*n+j] = v[j*n+i] = 0.0;
        }
        v[i*n+i] = 1.0;
        g = rv1[i];
        l = i;
    }
  
    /* accumulate the left-hand transformation */
    for (i = n - 1; i >= 0; i--) 
    {
        l = i + 1;
        g = (double)d[i];
        if (i < n - 1) 
            for (j = l; j < n; j++) 
                a[i*n+j] = 0.0;
			
        if (g) 
        {
            g = 1.0 / g;
            if (i != n - 1) 
            {
                for (j = l; j < n; j++) 
                {
                    for (s = 0.0, k = l; k < m; k++) 
                        s += ((double)a[k*m+i] * (double)a[k*m+j]);
					
                    f = (s / (double)a[i*n+i]) * g;
			
                    for (k = i; k < m; k++) 
						a[k*m+j] += (float)(f * (double)a[k*m+i]);
                       
                }
            }
            for (j = i; j < m; j++) 
				a[j*m+i] = (float)((double)a[j*m+i]*g);
              
        }
        else 
        {
            for (j = i; j < m; j++) 
				a[j*m+i] = 0.0;

        }
		++a[i*n+i];

    }

    /* diagonalize the bidiagonal form */
    for (k = n - 1; k >= 0; k--) 
    {                             /* loop over singular values */
        for (its = 0; its < 30; its++) 
        {                         /* loop over allowed iterations */
            flag = 1;
            for (l = k; l >= 0; l--) 
            {                     /* test for splitting */
                nm = l - 1;
                if (fabs(rv1[l]) + anorm == anorm) 
                {
                    flag = 0;
                    break;
                }
                if (fabs((double)d[nm]) + anorm == anorm) 
                    break;
            }
            if (flag) 
            {
                c = 0.0;
                s = 1.0;
                for (i = l; i <= k; i++) 
                {
                    f = s * rv1[i];
                    if (fabs(f) + anorm != anorm) 
                    {
                        g = (double)d[i];
                        h = PYTHAG(f, g);
                        d[i] = (float)h; 
                        h = 1.0 / h;
                        c = g * h;
                        s = (- f * h);
                        for (j = 0; j < m; j++) 
                        {
							y = (double)a[j*m+nm];
                            z = (double)a[j*m+i];
                            a[j*m+nm] = (float)(y * c + z * s);
                            a[j*m+i] = (float)(z * c - y * s);
                        }
                    }
                }
            }
            z = (double)d[k];
            if (l == k) 
            {                  /* convergence */
                if (z < 0.0) 
                {              /* make singular value nonnegative */
                    d[k] = (float)(-z);
                    for (j = 0; j < n; j++) 
                        v[j*n+k] = (-v[j*n+k]);
                }
                break;
            }
            if (its >= 30) {
                free((void*) rv1);
                fprintf(stderr, "No convergence after 30,000! iterations \n");
                return(0);
            }
    
            /* shift from bottom 2 x 2 minor */
            x = (double)d[l];
            nm = k - 1;
            y = (double)d[nm];
            g = rv1[nm];
            h = rv1[k];
            f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y);
            g = PYTHAG(f, 1.0);
            f = ((x - z) * (x + z) + h * ((y / (f + SIGN(g, f))) - h)) / x;
          
            /* next QR transformation */
            c = s = 1.0;
            for (j = l; j <= nm; j++) 
            {
                i = j + 1;
                g = rv1[i];
                y = (double)d[i];
                h = s * g;
                g = c * g;
                z = PYTHAG(f, h);
                rv1[j] = z;
                c = f / z;
                s = h / z;
                f = x * c + g * s;
                g = g * c - x * s;
                h = y * s;
                y = y * c;
                for (jj = 0; jj < n; jj++) 
                {   

                    x = (double)v[jj*n+j];
                    z = (double)v[jj*n+i];
                    v[jj*n+j] = (float)(x * c + z * s);
                    v[jj*n+i] = (float)(z * c - x * s);
                }
                z = PYTHAG(f, h);
                d[j] = (float)z;
                if (z) 
                {
                    z = 1.0 / z;
                    c = f * z;
                    s = h * z;
                }
                f = (c * g) + (s * y);
                x = (c * y) - (s * g);
                for (jj = 0; jj < m; jj++) 
                {   
                    y = (double)a[jj*n+j];
                    z = (double)a[jj*n+i];
                    a[jj*n+j] = (float)(y * c + z * s);
                    a[jj*n+i] = (float)(z * c - y * s);
                }
            }
            rv1[l] = 0.0;
            rv1[k] = f;
            d[k] = (float)x;
        }
    }
    free((void*) rv1);
    return(1);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -