genv.c

来自「math library from gnu」· C语言 代码 · 共 924 行 · 第 1/2 页

C
924
字号
              scale = GSL_MIN(scale,                        1.0 / (GSL_DBL_MIN *                               GSL_MAX(1.0,                                 GSL_MAX(fabs(acoef), fabs(bcoefr)))));              if (lsa)                acoef = ascale * (scale * sbeta);              else                acoef *= scale;              if (lsb)                bcoefr = bscale * (scale * salfar);              else                bcoefr *= scale;            }          acoefa = fabs(acoef);          bcoefa = fabs(bcoefr);          /* first component is 1 */          gsl_vector_set(w->work3, je, 1.0);          xmax = 1.0;          /* compute contribution from column je of A and B to sum */          for (i = 0; i < je; ++i)            {              gsl_vector_set(w->work3, i,                bcoefr*gsl_matrix_get(T, i, je) -                acoef * gsl_matrix_get(S, i, je));            }        }      else        {          gsl_matrix_const_view vs =            gsl_matrix_const_submatrix(S, je - 1, je - 1, 2, 2);          gsl_matrix_const_view vt =            gsl_matrix_const_submatrix(T, je - 1, je - 1, 2, 2);          /* complex eigenvalue */          gsl_schur_gen_eigvals(&vs.matrix,                                &vt.matrix,                                &bcoefr,                                &temp2,                                &bcoefi,                                &acoef,                                &temp);          if (bcoefi == 0.0)            {              GSL_ERROR("gsl_schur_gen_eigvals failed on complex block", GSL_FAILURE);            }          /* scale to avoid over/underflow */          acoefa = fabs(acoef);          bcoefa = fabs(bcoefr) + fabs(bcoefi);          scale = 1.0;          if (acoefa*GSL_DBL_EPSILON < GSL_DBL_MIN && acoefa >= GSL_DBL_MIN)            scale = (GSL_DBL_MIN / GSL_DBL_EPSILON) / acoefa;          if (bcoefa*GSL_DBL_EPSILON < GSL_DBL_MIN && bcoefa >= GSL_DBL_MIN)            scale = GSL_MAX(scale, (GSL_DBL_MIN/GSL_DBL_EPSILON) / bcoefa);          if (GSL_DBL_MIN*acoefa > ascale)            scale = ascale / (GSL_DBL_MIN * acoefa);          if (GSL_DBL_MIN*bcoefa > bscale)            scale = GSL_MIN(scale, bscale / (GSL_DBL_MIN*bcoefa));          if (scale != 1.0)            {              acoef *= scale;              acoefa = fabs(acoef);              bcoefr *= scale;              bcoefi *= scale;              bcoefa = fabs(bcoefr) + fabs(bcoefi);            }          /* compute first two components of eigenvector */          temp = acoef * gsl_matrix_get(S, je, je - 1);          temp2r = acoef * gsl_matrix_get(S, je, je) -                   bcoefr * gsl_matrix_get(T, je, je);          temp2i = -bcoefi * gsl_matrix_get(T, je, je);          if (fabs(temp) >= fabs(temp2r) + fabs(temp2i))            {              gsl_vector_set(w->work3, je, 1.0);              gsl_vector_set(w->work4, je, 0.0);              gsl_vector_set(w->work3, je - 1, -temp2r / temp);              gsl_vector_set(w->work4, je - 1, -temp2i / temp);            }          else            {              gsl_vector_set(w->work3, je - 1, 1.0);              gsl_vector_set(w->work4, je - 1, 0.0);              temp = acoef * gsl_matrix_get(S, je - 1, je);              gsl_vector_set(w->work3, je,                (bcoefr*gsl_matrix_get(T, je - 1, je - 1) -                 acoef*gsl_matrix_get(S, je - 1, je - 1)) / temp);              gsl_vector_set(w->work4, je,                bcoefi*gsl_matrix_get(T, je - 1, je - 1) / temp);            }          xmax = GSL_MAX(fabs(gsl_vector_get(w->work3, je)) +                         fabs(gsl_vector_get(w->work4, je)),                         fabs(gsl_vector_get(w->work3, je - 1)) +                         fabs(gsl_vector_get(w->work4, je - 1)));          /* compute contribution from column je and je - 1 */          creala = acoef * gsl_vector_get(w->work3, je - 1);          cimaga = acoef * gsl_vector_get(w->work4, je - 1);          crealb = bcoefr * gsl_vector_get(w->work3, je - 1) -                   bcoefi * gsl_vector_get(w->work4, je - 1);          cimagb = bcoefi * gsl_vector_get(w->work3, je - 1) +                   bcoefr * gsl_vector_get(w->work4, je - 1);          cre2a = acoef * gsl_vector_get(w->work3, je);          cim2a = acoef * gsl_vector_get(w->work4, je);          cre2b = bcoefr * gsl_vector_get(w->work3, je) -                  bcoefi * gsl_vector_get(w->work4, je);          cim2b = bcoefi * gsl_vector_get(w->work3, je) +                  bcoefr * gsl_vector_get(w->work4, je);          for (i = 0; i < je - 1; ++i)            {              gsl_vector_set(w->work3, i,                -creala * gsl_matrix_get(S, i, je - 1) +                crealb * gsl_matrix_get(T, i, je - 1) -                cre2a * gsl_matrix_get(S, i, je) +                cre2b * gsl_matrix_get(T, i, je));              gsl_vector_set(w->work4, i,                -cimaga * gsl_matrix_get(S, i, je - 1) +                cimagb * gsl_matrix_get(T, i, je - 1) -                cim2a * gsl_matrix_get(S, i, je) +                cim2b * gsl_matrix_get(T, i, je));            }        }      dmin = GSL_MAX(GSL_DBL_MIN,               GSL_MAX(GSL_DBL_EPSILON*acoefa*anorm,                       GSL_DBL_EPSILON*bcoefa*bnorm));      /* triangular solve of (a A - b B) x = 0 */      il2by2 = 0;      for (is = (int) je - (int) nw; is >= 0; --is)        {          j = (size_t) is;          if (!il2by2 && j > 0)            {              if (gsl_matrix_get(S, j, j - 1) != 0.0)                {                  il2by2 = 1;                  continue;                }            }          bdiag[0] = gsl_matrix_get(T, j, j);          if (il2by2)            {              na = 2;              bdiag[1] = gsl_matrix_get(T, j + 1, j + 1);            }          else            na = 1;          if (nw == 1)            {              gsl_matrix_const_view sv =                gsl_matrix_const_submatrix(S, j, j, na, na);              gsl_vector_view xv, bv;              bv = gsl_vector_subvector(w->work3, j, na);              /*               * the loop below expects the solution in the first column               * of sum, so set stride to 2               */              xv = gsl_vector_view_array_with_stride(sum, 2, na);              gsl_schur_solve_equation(acoef,                                       &sv.matrix,                                       bcoefr,                                       bdiag[0],                                       bdiag[1],                                       &bv.vector,                                       &xv.vector,                                       &scale,                                       &temp,                                       dmin);            }          else            {              double bdat[4];              gsl_matrix_const_view sv =                gsl_matrix_const_submatrix(S, j, j, na, na);              gsl_vector_complex_view xv =                gsl_vector_complex_view_array(sum, na);              gsl_vector_complex_view bv =                gsl_vector_complex_view_array(bdat, na);              gsl_complex z;              bdat[0] = gsl_vector_get(w->work3, j);              bdat[1] = gsl_vector_get(w->work4, j);              if (na == 2)                {                  bdat[2] = gsl_vector_get(w->work3, j + 1);                  bdat[3] = gsl_vector_get(w->work4, j + 1);                }              GSL_SET_COMPLEX(&z, bcoefr, bcoefi);              gsl_schur_solve_equation_z(acoef,                                         &sv.matrix,                                         &z,                                         bdiag[0],                                         bdiag[1],                                         &bv.vector,                                         &xv.vector,                                         &scale,                                         &temp,                                         dmin);            }          if (scale < 1.0)            {              for (jr = 0; jr <= je; ++jr)                {                  gsl_vector_set(w->work3, jr,                    scale * gsl_vector_get(w->work3, jr));                  if (nw == 2)                    {                      gsl_vector_set(w->work4, jr,                        scale * gsl_vector_get(w->work4, jr));                    }                }            }          xmax = GSL_MAX(scale * xmax, temp);          for (jr = 0; jr < na; ++jr)            {              gsl_vector_set(w->work3, j + jr, sum[jr*na]);              if (nw == 2)                gsl_vector_set(w->work4, j + jr, sum[jr*na + 1]);            }          if (j > 0)            {              xscale = 1.0 / GSL_MAX(1.0, xmax);              temp = acoefa * gsl_vector_get(w->work1, j) +                     bcoefa * gsl_vector_get(w->work2, j);              if (il2by2)                {                  temp = GSL_MAX(temp,                           acoefa * gsl_vector_get(w->work1, j + 1) +                           bcoefa * gsl_vector_get(w->work2, j + 1));                }              temp = GSL_MAX(temp, GSL_MAX(acoefa, bcoefa));              if (temp > bignum * xscale)                {                  for (jr = 0; jr <= je; ++jr)                    {                      gsl_vector_set(w->work3, jr,                        xscale * gsl_vector_get(w->work3, jr));                      if (nw == 2)                        {                          gsl_vector_set(w->work4, jr,                            xscale * gsl_vector_get(w->work4, jr));                        }                    }                  xmax *= xscale;                }              for (ja = 0; ja < na; ++ja)                {                  if (complex_pair)                    {                      creala = acoef * gsl_vector_get(w->work3, j + ja);                      cimaga = acoef * gsl_vector_get(w->work4, j + ja);                      crealb = bcoefr * gsl_vector_get(w->work3, j + ja) -                               bcoefi * gsl_vector_get(w->work4, j + ja);                      cimagb = bcoefi * gsl_vector_get(w->work3, j + ja) +                               bcoefr * gsl_vector_get(w->work4, j + ja);                      for (jr = 0; jr <= j - 1; ++jr)                        {                          gsl_vector_set(w->work3, jr,                            gsl_vector_get(w->work3, jr) -                            creala * gsl_matrix_get(S, jr, j + ja) +                            crealb * gsl_matrix_get(T, jr, j + ja));                          gsl_vector_set(w->work4, jr,                            gsl_vector_get(w->work4, jr) -                            cimaga * gsl_matrix_get(S, jr, j + ja) +                            cimagb * gsl_matrix_get(T, jr, j + ja));                        }                    }                  else                    {                      creala = acoef * gsl_vector_get(w->work3, j + ja);                      crealb = bcoefr * gsl_vector_get(w->work3, j + ja);                      for (jr = 0; jr <= j - 1; ++jr)                        {                          gsl_vector_set(w->work3, jr,                            gsl_vector_get(w->work3, jr) -                            creala * gsl_matrix_get(S, jr, j + ja) +                            crealb * gsl_matrix_get(T, jr, j + ja));                        }                    } /* if (!complex_pair) */                } /* for (ja = 0; ja < na; ++ja) */            } /* if (j > 0) */          il2by2 = 0;        } /* for (i = 0; i < je - nw; ++i) */      for (jr = 0; jr < N; ++jr)        {          gsl_vector_set(w->work5, jr,            gsl_vector_get(w->work3, 0) * gsl_matrix_get(Z, jr, 0));          if (nw == 2)            {              gsl_vector_set(w->work6, jr,                gsl_vector_get(w->work4, 0) * gsl_matrix_get(Z, jr, 0));            }        }      for (jc = 1; jc <= je; ++jc)        {          for (jr = 0; jr < N; ++jr)            {              gsl_vector_set(w->work5, jr,                gsl_vector_get(w->work5, jr) +                gsl_vector_get(w->work3, jc) * gsl_matrix_get(Z, jr, jc));              if (nw == 2)                {                  gsl_vector_set(w->work6, jr,                    gsl_vector_get(w->work6, jr) +                    gsl_vector_get(w->work4, jc) * gsl_matrix_get(Z, jr, jc));                }            }        }      /* store the eigenvector */      if (complex_pair)        {          ecol = gsl_matrix_complex_column(evec, je - 1);          re = gsl_vector_complex_real(&ecol.vector);          im = gsl_vector_complex_imag(&ecol.vector);          ecol = gsl_matrix_complex_column(evec, je);          re2 = gsl_vector_complex_real(&ecol.vector);          im2 = gsl_vector_complex_imag(&ecol.vector);        }      else        {          ecol = gsl_matrix_complex_column(evec, je);          re = gsl_vector_complex_real(&ecol.vector);          im = gsl_vector_complex_imag(&ecol.vector);        }      for (jr = 0; jr < N; ++jr)        {          gsl_vector_set(&re.vector, jr, gsl_vector_get(w->work5, jr));          if (complex_pair)            {              gsl_vector_set(&im.vector, jr, gsl_vector_get(w->work6, jr));              gsl_vector_set(&re2.vector, jr, gsl_vector_get(w->work5, jr));              gsl_vector_set(&im2.vector, jr, -gsl_vector_get(w->work6, jr));            }          else            {              gsl_vector_set(&im.vector, jr, 0.0);            }        }      /* scale eigenvector */      xmax = 0.0;      if (complex_pair)        {          for (j = 0; j < N; ++j)            {              xmax = GSL_MAX(xmax,                             fabs(gsl_vector_get(&re.vector, j)) +                             fabs(gsl_vector_get(&im.vector, j)));            }        }      else        {          for (j = 0; j < N; ++j)            {              xmax = GSL_MAX(xmax, fabs(gsl_vector_get(&re.vector, j)));            }        }      if (xmax > GSL_DBL_MIN)        {          xscale = 1.0 / xmax;          for (j = 0; j < N; ++j)            {              gsl_vector_set(&re.vector, j,                             gsl_vector_get(&re.vector, j) * xscale);              if (complex_pair)                {                  gsl_vector_set(&im.vector, j,                                 gsl_vector_get(&im.vector, j) * xscale);                  gsl_vector_set(&re2.vector, j,                                 gsl_vector_get(&re2.vector, j) * xscale);                  gsl_vector_set(&im2.vector, j,                                 gsl_vector_get(&im2.vector, j) * xscale);                }            }        }    } /* for (k = 0; k < N; ++k) */  return GSL_SUCCESS;} /* genv_get_right_eigenvectors() *//*genv_normalize_eigenvectors()  Normalize eigenvectors so that their Euclidean norm is 1Inputs: alpha - eigenvalue numerators        evec  - eigenvectors*/static voidgenv_normalize_eigenvectors(gsl_vector_complex *alpha,                            gsl_matrix_complex *evec){  const size_t N = evec->size1;  size_t i;     /* looping */  gsl_complex ai;  gsl_vector_complex_view vi;  gsl_vector_view re, im;  double scale; /* scaling factor */  for (i = 0; i < N; ++i)    {      ai = gsl_vector_complex_get(alpha, i);      vi = gsl_matrix_complex_column(evec, i);      re = gsl_vector_complex_real(&vi.vector);      if (GSL_IMAG(ai) == 0.0)        {          scale = 1.0 / gsl_blas_dnrm2(&re.vector);          gsl_blas_dscal(scale, &re.vector);        }      else if (GSL_IMAG(ai) > 0.0)        {          im = gsl_vector_complex_imag(&vi.vector);          scale = 1.0 / gsl_hypot(gsl_blas_dnrm2(&re.vector),                                  gsl_blas_dnrm2(&im.vector));          gsl_blas_zdscal(scale, &vi.vector);          vi = gsl_matrix_complex_column(evec, i + 1);          gsl_blas_zdscal(scale, &vi.vector);        }    }} /* genv_normalize_eigenvectors() */

⌨️ 快捷键说明

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