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

📄 jacobi.c

📁 该文件为c++的数学函数库!是一个非常有用的编程工具.它含有各种数学函数,为科学计算、工程应用等程序编写提供方便!
💻 C
字号:
/* eigen/jacobi.c *  * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman *  * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. *  * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* Author:  G. Jungman *//* Simple linear algebra operations, operating directly * on the gsl_vector and gsl_matrix objects. These are * meant for "generic" and "small" systems. Anyone * interested in large systems will want to use more * sophisticated methods, presumably involving native * BLAS operations, specialized data representations, * or other optimizations. */#include <config.h>#include <stdlib.h>#include <string.h>#include <gsl/gsl_math.h>#include <gsl/gsl_vector.h>#include <gsl/gsl_matrix.h>#include <gsl/gsl_eigen.h>#define REAL doubleinline static voidjac_rotate(gsl_matrix * a,           unsigned int i, unsigned int j, unsigned int k, unsigned int l,           double * g, double * h,           double s, double tau){  *g = gsl_matrix_get(a, i, j);  *h = gsl_matrix_get(a, k, l);  gsl_matrix_set(a, i, j, (*g) - s*((*h) + (*g)*tau));  gsl_matrix_set(a, k, l, (*h) + s*((*g) - (*h)*tau));}intgsl_eigen_jacobi(gsl_matrix * a,                         gsl_vector * eval,                         gsl_matrix * evec,                         unsigned int max_rot,                          unsigned int * nrot){  if(a->size1 != a->size2) {     GSL_ERROR ("eigenproblem requires square matrix", GSL_ENOTSQR);  }  else if(a->size1 != evec->size1 || a->size1 != evec->size2) {     GSL_ERROR ("eigenvector matrix must match input matrix", GSL_EBADLEN);  }  else if(a->size1 != eval->size) {    GSL_ERROR ("eigenvalue vector must match input matrix", GSL_EBADLEN);  }  else {    const unsigned int n = a->size1;    unsigned int i, j, iq, ip;    double t, s;    REAL * b = (REAL *) malloc(n * sizeof(REAL));    REAL * z = (REAL *) malloc(n * sizeof(REAL));    if(b == 0 || z == 0) {      if(b != 0) free(b);      if(z != 0) free(z);      GSL_ERROR ("could not allocate memory for workspace", GSL_ENOMEM);    }    /* Set eigenvectors to coordinate basis. */    for(ip=0; ip<n; ip++) {      for(iq=0; iq<n; iq++) {        gsl_matrix_set(evec, ip, iq, 0.0);      }      gsl_matrix_set(evec, ip, ip, 1.0);    }    /* Initialize eigenvalues and workspace. */    for(ip=0; ip<n; ip++) {      REAL a_ipip = gsl_matrix_get(a, ip, ip);      z[ip] = 0.0;      b[ip] = a_ipip;      gsl_vector_set(eval, ip, a_ipip);    }    *nrot = 0;    for(i=1; i<=max_rot; i++) {      REAL thresh;      REAL tau;      REAL g, h, c;      REAL sm = 0.0;      for(ip=0; ip<n-1; ip++) {        for(iq=ip+1; iq<n; iq++) {          sm += fabs(gsl_matrix_get(a, ip, iq));        }      }      if(sm == 0.0) {        free(z);        free(b);        return GSL_SUCCESS;      }      if(i < 4)        thresh = 0.2*sm/(n*n);      else        thresh = 0.0;      for(ip=0; ip<n-1; ip++) {        for(iq=ip+1; iq<n; iq++) {          const REAL d_ip = gsl_vector_get(eval, ip);          const REAL d_iq = gsl_vector_get(eval, iq);          const REAL a_ipiq = gsl_matrix_get(a, ip, iq);          g = 100.0 * fabs(a_ipiq);          if(   i > 4             && fabs(d_ip)+g == fabs(d_ip)             && fabs(d_iq)+g == fabs(d_iq)             ) {            gsl_matrix_set(a, ip, iq, 0.0);          }          else if(fabs(a_ipiq) > thresh) {            h = d_iq - d_ip;            if(fabs(h) + g == fabs(h)) {              t = a_ipiq/h;            }            else {              REAL theta = 0.5*h/a_ipiq;              t = 1.0/(fabs(theta) + sqrt(1.0 + theta*theta));              if(theta < 0.0) t = -t;            }            c   = 1.0/sqrt(1.0+t*t);            s   = t*c;            tau = s/(1.0+c);            h   = t * a_ipiq;            z[ip] -= h;            z[iq] += h;            gsl_vector_set(eval, ip, d_ip - h);            gsl_vector_set(eval, iq, d_iq + h);            gsl_matrix_set(a, ip, iq, 0.0);            for(j=0; j<ip; j++){              jac_rotate(a, j, ip, j, iq, &g, &h, s, tau);            }            for(j=ip+1; j<iq; j++){              jac_rotate(a, ip, j, j, iq, &g, &h, s, tau);            }            for(j=iq+1; j<n; j++){              jac_rotate(a, ip, j, iq, j, &g, &h, s, tau);            }            for (j=0; j<n; j++){              jac_rotate(evec, j, ip, j, iq, &g, &h, s, tau);            }            ++(*nrot);          }        }      }      for (ip=0; ip<n; ip++) {        b[ip] += z[ip];        z[ip]  = 0.0;        gsl_vector_set(eval, ip, b[ip]);      }      /* continue iteration */    }    return GSL_EMAXITER;  }}intgsl_eigen_invert_jacobi(const gsl_matrix * a,                             gsl_matrix * ainv,                             unsigned int max_rot){  if(a->size1 != a->size2 || ainv->size1 != ainv->size2) {    return GSL_ENOTSQR;  }  else if(a->size1 != ainv->size2) {    return GSL_EBADLEN;  }  else {    const unsigned int n = a->size1;    unsigned int nrot;    unsigned int i,j,k,l;    /* This is annoying because I do not want     * the error handling in these functions.     * But there are no "impl"-like versions     * of these allocators... sigh.     */    gsl_vector * eval = gsl_vector_alloc(n);    gsl_matrix * evec = gsl_matrix_alloc(n, n);    gsl_matrix * inv_diag = gsl_matrix_alloc(n, n);    if(eval == 0 || evec == 0 || inv_diag == 0) {      if(eval != 0) gsl_vector_free(eval);      if(evec != 0) gsl_matrix_free(evec);      if(inv_diag != 0) gsl_matrix_free(inv_diag);      return GSL_ENOMEM;    }    memcpy(ainv->data, a->data, n*n*sizeof(REAL));    gsl_eigen_jacobi(ainv, eval, evec, max_rot, &nrot);    for(i=0; i<n; i++) {      if(fabs(gsl_vector_get(eval, i)) < 100.0 * GSL_DBL_EPSILON) {        /* apparent singularity */        gsl_vector_free(eval);        gsl_matrix_free(evec);        gsl_matrix_free(inv_diag);        return GSL_ESING;      }    }    /* Invert the diagonalized matrix. */    for(i=0; i<n; i++) {      for(j=0; j<n; j++) {        gsl_matrix_set(inv_diag, i, j, 0.0);      }      gsl_matrix_set(inv_diag, i, i, 1.0/gsl_vector_get(eval, i));    }    for(i=0; i<n; i++) {      for(j=0; j<n; j++) {        gsl_matrix_set(ainv, i, j, 0.0);        for(k=0; k<n; k++) {          for(l=0; l<n; l++) {            REAL ainv_ij = gsl_matrix_get(ainv, i, j);            REAL evec_il = gsl_matrix_get(evec, i, l);            REAL evec_jk = gsl_matrix_get(evec, j, k);            REAL inv_diag_lk = gsl_matrix_get(inv_diag, l, k);            REAL delta = evec_il * inv_diag_lk * evec_jk;            gsl_matrix_set(ainv, i, j, ainv_ij + delta);          }        }      }    }    gsl_vector_free(eval);    gsl_matrix_free(evec);    gsl_matrix_free(inv_diag);    return GSL_SUCCESS;  }}

⌨️ 快捷键说明

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