Commit 191bfe69 authored by Uwe Schulzweida's avatar Uwe Schulzweida
Browse files

eigen_solution_of_symmetric_matrix(): changed type parameter covar to Varray2D<double> &.

parent e9e9c0b5
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#include "cdo_options.h" #include "cdo_options.h"
#include "cdo_vlist.h" #include "cdo_vlist.h"
#include "dmemory.h"
#include "process_int.h" #include "process_int.h"
#include "param_conversion.h" #include "param_conversion.h"
#include <mpim_grid.h> #include <mpim_grid.h>
...@@ -49,21 +48,21 @@ ...@@ -49,21 +48,21 @@
static void static void
scale_eigvec_grid(Varray<double> &out, int tsID, size_t npack, const std::vector<size_t> &pack, const Varray<double> &weight, scale_eigvec_grid(Varray<double> &out, int tsID, size_t npack, const std::vector<size_t> &pack, const Varray<double> &weight,
double **covar, double sum_w) Varray2D<double> &covar, double sum_w)
{ {
for (size_t i = 0; i < npack; ++i) out[pack[i]] = covar[tsID][i] / std::sqrt(weight[pack[i]] / sum_w); for (size_t i = 0; i < npack; ++i) out[pack[i]] = covar[tsID][i] / std::sqrt(weight[pack[i]] / sum_w);
} }
static void static void
scale_eigvec_time(Varray<double> &out, int tsID, int nts, size_t npack, const std::vector<size_t> &pack, const Varray<double> &weight, scale_eigvec_time(Varray<double> &out, int tsID, int nts, size_t npack, const std::vector<size_t> &pack, const Varray<double> &weight,
double **covar, const Varray2D<double> &data, double missval, double sum_w) const Varray2D<double> &covar, const Varray2D<double> &data, double missval, double sum_w)
{ {
#ifdef _OPENMP #ifdef _OPENMP
#pragma omp parallel for default(none) shared(npack, nts, tsID, pack, data, covar, out) #pragma omp parallel for default(none) shared(npack, nts, tsID, pack, data, covar, out)
#endif #endif
for (size_t i = 0; i < npack; ++i) for (size_t i = 0; i < npack; ++i)
{ {
double sum = 0; double sum = 0.0;
for (int j = 0; j < nts; ++j) sum += data[j][i] * covar[tsID][j]; for (int j = 0; j < nts; ++j) sum += data[j][i] * covar[tsID][j];
out[pack[i]] = sum; out[pack[i]] = sum;
...@@ -77,7 +76,7 @@ scale_eigvec_time(Varray<double> &out, int tsID, int nts, size_t npack, const st ...@@ -77,7 +76,7 @@ scale_eigvec_time(Varray<double> &out, int tsID, int nts, size_t npack, const st
*/ */
// Normalizing // Normalizing
double sum = 0; double sum = 0.0;
#ifdef _OPENMP #ifdef _OPENMP
#pragma omp parallel for default(none) reduction(+ : sum) shared(out, weight, pack, npack) #pragma omp parallel for default(none) reduction(+ : sum) shared(out, weight, pack, npack)
...@@ -88,7 +87,7 @@ scale_eigvec_time(Varray<double> &out, int tsID, int nts, size_t npack, const st ...@@ -88,7 +87,7 @@ scale_eigvec_time(Varray<double> &out, int tsID, int nts, size_t npack, const st
sum += weight[pack[i]] * out[pack[i]] * out[pack[i]]; sum += weight[pack[i]] * out[pack[i]] * out[pack[i]];
} }
if (sum > 0) if (sum > 0.0)
{ {
sum = std::sqrt(sum / sum_w); sum = std::sqrt(sum / sum_w);
#ifdef _OPENMP #ifdef _OPENMP
...@@ -129,8 +128,7 @@ EOFs(void *process) ...@@ -129,8 +128,7 @@ EOFs(void *process)
bool init; bool init;
bool first_call; bool first_call;
Varray<double> eig_val; Varray<double> eig_val;
double *covar_array; Varray2D<double> covar;
double **covar;
Varray2D<double> data; Varray2D<double> data;
}; };
...@@ -273,8 +271,6 @@ EOFs(void *process) ...@@ -273,8 +271,6 @@ EOFs(void *process)
{ {
eofdata[varID][levelID].init = false; eofdata[varID][levelID].init = false;
eofdata[varID][levelID].first_call = true; eofdata[varID][levelID].first_call = true;
eofdata[varID][levelID].covar_array = nullptr;
eofdata[varID][levelID].covar = nullptr;
if (time_space) eofdata[varID][levelID].data.resize(nts); if (time_space) eofdata[varID][levelID].data.resize(nts);
} }
...@@ -282,8 +278,7 @@ EOFs(void *process) ...@@ -282,8 +278,7 @@ EOFs(void *process)
if (Options::cdoVerbose) cdoPrint("Allocated eigenvalue/eigenvector structures with nts=%d gridsize=%zu", nts, gridsizemax); if (Options::cdoVerbose) cdoPrint("Allocated eigenvalue/eigenvector structures with nts=%d gridsize=%zu", nts, gridsizemax);
double **covar = nullptr; double sum_w = 1.0;
double sum_w = 1.;
int tsID = 0; int tsID = 0;
...@@ -315,7 +310,7 @@ EOFs(void *process) ...@@ -315,7 +310,7 @@ EOFs(void *process)
if (weight_mode == WEIGHT_ON) if (weight_mode == WEIGHT_ON)
{ {
sum_w = 0; sum_w = 0.0;
for (size_t i = 0; i < npack; i++) sum_w += weight[pack[i]]; for (size_t i = 0; i < npack; i++) sum_w += weight[pack[i]];
} }
} }
...@@ -337,20 +332,11 @@ EOFs(void *process) ...@@ -337,20 +332,11 @@ EOFs(void *process)
{ {
if (!eofdata[varID][levelID].init) if (!eofdata[varID][levelID].init)
{ {
n = npack; eofdata[varID][levelID].covar.resize(npack);
double *covar_array = (double *) Malloc(npack * npack * sizeof(double)); for (size_t i = 0; i < npack; ++i) eofdata[varID][levelID].covar[i].resize(npack, 0.0);
covar = (double **) Malloc(npack * sizeof(double *));
for (size_t i = 0; i < npack; ++i) covar[i] = covar_array + npack * i;
for (size_t i = 0; i < npack; ++i)
for (size_t j = 0; j < npack; ++j) covar[i][j] = 0;
eofdata[varID][levelID].covar_array = covar_array;
eofdata[varID][levelID].covar = covar;
}
else
{
covar = eofdata[varID][levelID].covar;
} }
auto &covar = eofdata[varID][levelID].covar;
#ifdef _OPENMP #ifdef _OPENMP
#pragma omp parallel for default(shared) #pragma omp parallel for default(shared)
#endif #endif
...@@ -375,9 +361,9 @@ EOFs(void *process) ...@@ -375,9 +361,9 @@ EOFs(void *process)
if (tsID == 1) cdoAbort("File consists of only one timestep!"); if (tsID == 1) cdoAbort("File consists of only one timestep!");
/* write files with eigenvalues (ID3) and eigenvectors (ID2) */ // write files with eigenvalues (ID3) and eigenvectors (ID2)
/* eigenvalues */ // eigenvalues
const auto streamID2 = cdoOpenWrite(1); const auto streamID2 = cdoOpenWrite(1);
const auto vlistID2 = vlistDuplicate(vlistID1); const auto vlistID2 = vlistDuplicate(vlistID1);
...@@ -389,12 +375,12 @@ EOFs(void *process) ...@@ -389,12 +375,12 @@ EOFs(void *process)
const auto gridID2 = gridCreate(GRID_LONLAT, 1); const auto gridID2 = gridCreate(GRID_LONLAT, 1);
gridDefXsize(gridID2, 1); gridDefXsize(gridID2, 1);
gridDefYsize(gridID2, 1); gridDefYsize(gridID2, 1);
double xvals = 0, yvals = 0; double xvals = 0.0, yvals = 0.0;
gridDefXvals(gridID2, &xvals); gridDefXvals(gridID2, &xvals);
gridDefYvals(gridID2, &yvals); gridDefYvals(gridID2, &yvals);
for (int i = 0; i < ngrids; i++) vlistChangeGridIndex(vlistID2, i, gridID2); for (int i = 0; i < ngrids; i++) vlistChangeGridIndex(vlistID2, i, gridID2);
/* eigenvectors */ // eigenvectors
const auto streamID3 = cdoOpenWrite(2); const auto streamID3 = cdoOpenWrite(2);
const auto vlistID3 = vlistDuplicate(vlistID1); const auto vlistID3 = vlistDuplicate(vlistID1);
...@@ -441,6 +427,7 @@ EOFs(void *process) ...@@ -441,6 +427,7 @@ EOFs(void *process)
for (levelID = 0; levelID < nlevs; levelID++) for (levelID = 0; levelID < nlevs; levelID++)
{ {
const auto &data = eofdata[varID][levelID].data; const auto &data = eofdata[varID][levelID].data;
auto &covar = eofdata[varID][levelID].covar;
if (eofdata[varID][levelID].first_call) if (eofdata[varID][levelID].first_call)
{ {
...@@ -456,8 +443,6 @@ EOFs(void *process) ...@@ -456,8 +443,6 @@ EOFs(void *process)
{ {
if (npack) eofdata[varID][levelID].eig_val.resize(npack); if (npack) eofdata[varID][levelID].eig_val.resize(npack);
covar = eofdata[varID][levelID].covar;
for (size_t ipack = 0; ipack < npack; ++ipack) for (size_t ipack = 0; ipack < npack; ++ipack)
{ {
const size_t i = pack[ipack]; const size_t i = pack[ipack];
...@@ -481,13 +466,10 @@ EOFs(void *process) ...@@ -481,13 +466,10 @@ EOFs(void *process)
{ {
if (Options::cdoVerbose) cdoPrint("allocating covar with %i x %i elements | npack=%zu", nts, nts, npack); if (Options::cdoVerbose) cdoPrint("allocating covar with %i x %i elements | npack=%zu", nts, nts, npack);
double *covar_array = (double *) Malloc(nts * nts * sizeof(double)); covar.resize(nts);
covar = (double **) Malloc(nts * sizeof(double *)); for (int i = 0; i < nts; ++i) covar[i].resize(nts);
for (int i = 0; i < nts; ++i) covar[i] = covar_array + nts * i;
eofdata[varID][levelID].eig_val.resize(nts); eofdata[varID][levelID].eig_val.resize(nts);
eofdata[varID][levelID].covar_array = covar_array;
eofdata[varID][levelID].covar = covar;
#ifdef _OPENMP #ifdef _OPENMP
#pragma omp parallel for default(shared) schedule(dynamic) #pragma omp parallel for default(shared) schedule(dynamic)
...@@ -499,7 +481,7 @@ EOFs(void *process) ...@@ -499,7 +481,7 @@ EOFs(void *process)
for (int j2 = j1; j2 < nts; j2++) for (int j2 = j1; j2 < nts; j2++)
{ {
const auto &df2p = data[j2]; const auto &df2p = data[j2];
double sum = 0; double sum = 0.0;
for (size_t i = 0; i < npack; i++) sum += weight[pack[i]] * df1p[i] * df2p[i]; for (size_t i = 0; i < npack; i++) sum += weight[pack[i]] * df1p[i] * df2p[i];
covar[j1][j2] = sum / sum_w / nts; covar[j1][j2] = sum / sum_w / nts;
} }
...@@ -510,7 +492,7 @@ EOFs(void *process) ...@@ -510,7 +492,7 @@ EOFs(void *process)
if (Options::Timer) timer_stop(timer_cov); if (Options::Timer) timer_stop(timer_cov);
/* SOLVE THE EIGEN PROBLEM */ // SOLVE THE EIGEN PROBLEM
if (Options::Timer) timer_start(timer_eig); if (Options::Timer) timer_start(timer_eig);
auto &eig_val = eofdata[varID][levelID].eig_val; auto &eig_val = eofdata[varID][levelID].eig_val;
...@@ -521,16 +503,12 @@ EOFs(void *process) ...@@ -521,16 +503,12 @@ EOFs(void *process)
cdo::eigen_solution_of_symmetric_matrix(covar, eig_val, n, __func__); cdo::eigen_solution_of_symmetric_matrix(covar, eig_val, n, __func__);
if (Options::Timer) timer_stop(timer_eig); if (Options::Timer) timer_stop(timer_eig);
/* NOW: covar contains the eigenvectors, eig_val the eigenvalues */ // NOW: covar contains the eigenvectors, eig_val the eigenvalues
for (size_t i = 0; i < gridsize; ++i) out[i] = missval; for (size_t i = 0; i < gridsize; ++i) out[i] = missval;
// for ( int i = 0; i < n; i++ ) eig_val[i] *= sum_w; // for ( int i = 0; i < n; i++ ) eig_val[i] *= sum_w;
} // first_call } // first_call
else
{
covar = eofdata[varID][levelID].covar;
}
if (tsID < n_eig) if (tsID < n_eig)
{ {
...@@ -554,15 +532,6 @@ EOFs(void *process) ...@@ -554,15 +532,6 @@ EOFs(void *process)
} // loop nvars } // loop nvars
} }
for (varID = 0; varID < nvars; varID++)
{
for (levelID = 0; levelID < varList1[varID].nlevels; levelID++)
{
if (eofdata[varID][levelID].covar_array) Free(eofdata[varID][levelID].covar_array);
if (eofdata[varID][levelID].covar) Free(eofdata[varID][levelID].covar);
}
}
cdoStreamClose(streamID3); cdoStreamClose(streamID3);
cdoStreamClose(streamID2); cdoStreamClose(streamID2);
cdoStreamClose(streamID1); cdoStreamClose(streamID1);
......
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#include "cdo_options.h" #include "cdo_options.h"
#include "cdo_vlist.h" #include "cdo_vlist.h"
#include "dmemory.h"
#include "process_int.h" #include "process_int.h"
#include "param_conversion.h" #include "param_conversion.h"
#include <mpim_grid.h> #include <mpim_grid.h>
...@@ -68,7 +67,6 @@ EOF3d(void *process) ...@@ -68,7 +67,6 @@ EOF3d(void *process)
int calendar = CALENDAR_STANDARD; int calendar = CALENDAR_STANDARD;
double sum_w; double sum_w;
double **cov = nullptr; // TODO: covariance matrix / eigenvectors after solving
if (Options::Timer) if (Options::Timer)
{ {
...@@ -279,9 +277,9 @@ EOF3d(void *process) ...@@ -279,9 +277,9 @@ EOF3d(void *process)
continue; continue;
} }
cov = (double **) Malloc(nts * sizeof(double *));
for (int j1 = 0; j1 < nts; j1++) cov[j1] = (double *) Malloc(nts * sizeof(double));
Varray<double> eigv(n); Varray<double> eigv(n);
Varray2D<double> covar(nts);
for (int j1 = 0; j1 < nts; j1++) covar[j1].resize(nts);
if (Options::cdoVerbose) if (Options::cdoVerbose)
{ {
...@@ -300,13 +298,13 @@ EOF3d(void *process) ...@@ -300,13 +298,13 @@ EOF3d(void *process)
double *df2p = datafields[varID][j2].data(); double *df2p = datafields[varID][j2].data();
double sum = 0.0; double sum = 0.0;
for (size_t i = 0; i < npack; i++) sum += weight[pack[i] % gridsizemax] * df1p[pack[i]] * df2p[pack[i]]; for (size_t i = 0; i < npack; i++) sum += weight[pack[i] % gridsizemax] * df1p[pack[i]] * df2p[pack[i]];
cov[j2][j1] = cov[j1][j2] = sum / sum_w / nts; covar[j2][j1] = covar[j1][j2] = sum / sum_w / nts;
} }
} }
if (Options::cdoVerbose) cdoPrint("calculated cov-matrix"); if (Options::cdoVerbose) cdoPrint("calculated cov-matrix");
/* SOLVE THE EIGEN PROBLEM */ // SOLVE THE EIGEN PROBLEM
if (Options::Timer) timer_stop(timer_cov); if (Options::Timer) timer_stop(timer_cov);
if (Options::Timer) timer_start(timer_eig); if (Options::Timer) timer_start(timer_eig);
...@@ -314,10 +312,10 @@ EOF3d(void *process) ...@@ -314,10 +312,10 @@ EOF3d(void *process)
if (Options::cdoVerbose) cdoPrint("Processed correlation matrix for var %2i | npack: %zu", varID, n); if (Options::cdoVerbose) cdoPrint("Processed correlation matrix for var %2i | npack: %zu", varID, n);
if (eigen_mode == JACOBI) if (eigen_mode == JACOBI)
cdo::parallel_eigen_solution_of_symmetric_matrix(cov, eigv, n, __func__); cdo::parallel_eigen_solution_of_symmetric_matrix(covar, eigv, n, __func__);
else else
cdo::eigen_solution_of_symmetric_matrix(cov, eigv, n, __func__); cdo::eigen_solution_of_symmetric_matrix(covar, eigv, n, __func__);
// NOW: cov contains the eigenvectors, eigv the eigenvalues // NOW: covar contains the eigenvectors, eigv the eigenvalues
if (Options::cdoVerbose) cdoPrint("Processed SVD decomposition for var %d from %d x %d matrix", varID, n, n); if (Options::cdoVerbose) cdoPrint("Processed SVD decomposition for var %d from %d x %d matrix", varID, n, n);
...@@ -330,12 +328,12 @@ EOF3d(void *process) ...@@ -330,12 +328,12 @@ EOF3d(void *process)
double *eigenvec = eigenvectors[varID][eofID].data(); double *eigenvec = eigenvectors[varID][eofID].data();
#ifdef _OPENMP #ifdef _OPENMP
#pragma omp parallel for default(none) shared(varID, nts, eofID, npack, pack, cov, datafields, eigenvec) #pragma omp parallel for default(none) shared(varID, nts, eofID, npack, pack, covar, datafields, eigenvec)
#endif #endif
for (size_t i = 0; i < npack; i++) for (size_t i = 0; i < npack; i++)
{ {
double sum = 0.0; double sum = 0.0;
for (int j = 0; j < nts; j++) sum += datafields[varID][j][pack[i]] * cov[eofID][j]; for (int j = 0; j < nts; j++) sum += datafields[varID][j][pack[i]] * covar[eofID][j];
eigenvec[pack[i]] = sum; eigenvec[pack[i]] = sum;
} }
...@@ -364,9 +362,6 @@ EOF3d(void *process) ...@@ -364,9 +362,6 @@ EOF3d(void *process)
for (size_t i = 0; i < npack; i++) eigenvec[pack[i]] = missval; for (size_t i = 0; i < npack; i++) eigenvec[pack[i]] = missval;
} }
} // for ( eofID = 0; eofID < n_eig; eofID++ ) } // for ( eofID = 0; eofID < n_eig; eofID++ )
for (int i = 0; i < n; i++)
if (cov[i]) Free(cov[i]);
} // for ( varID = 0; varID < nvars; varID++ ) } // for ( varID = 0; varID < nvars; varID++ )
// write files with eigenvalues (ID3) and eigenvectors (ID2) // write files with eigenvalues (ID3) and eigenvectors (ID2)
...@@ -383,7 +378,7 @@ EOF3d(void *process) ...@@ -383,7 +378,7 @@ EOF3d(void *process)
const auto gridID2 = gridCreate(GRID_LONLAT, 1); const auto gridID2 = gridCreate(GRID_LONLAT, 1);
gridDefXsize(gridID2, 1); gridDefXsize(gridID2, 1);
gridDefYsize(gridID2, 1); gridDefYsize(gridID2, 1);
double xvals = 0, yvals = 0; double xvals = 0.0, yvals = 0.0;
gridDefXvals(gridID2, &xvals); gridDefXvals(gridID2, &xvals);
gridDefYvals(gridID2, &yvals); gridDefYvals(gridID2, &yvals);
...@@ -399,7 +394,7 @@ EOF3d(void *process) ...@@ -399,7 +394,7 @@ EOF3d(void *process)
const auto nzaxis = vlistNzaxis(vlistID2); const auto nzaxis = vlistNzaxis(vlistID2);
for (int i = 0; i < nzaxis; i++) vlistChangeZaxisIndex(vlistID2, i, zaxisID2); for (int i = 0; i < nzaxis; i++) vlistChangeZaxisIndex(vlistID2, i, zaxisID2);
/* eigenvectors */ // eigenvectors
const auto streamID3 = cdoOpenWrite(2); const auto streamID3 = cdoOpenWrite(2);
const auto vlistID3 = vlistDuplicate(vlistID1); const auto vlistID3 = vlistDuplicate(vlistID1);
......
...@@ -55,18 +55,18 @@ static int n_finished; ...@@ -55,18 +55,18 @@ static int n_finished;
namespace cdo namespace cdo
{ {
void static void
heap_sort(Varray<double> &eig_val, double **a, int n) heap_sort(Varray<double> &eig_val, Varray2D<double> &a, long n)
{ {
int j_next; long j_next;
// First part of heap sort: // First part of heap sort:
for (int i = n / 2 - 1; i >= 0; i--) for (long i = n / 2 - 1; i >= 0; i--)
{ {
for (int j = i; 2 * j + 1 < n; j = j_next) for (long j = i; 2 * j + 1 < n; j = j_next)
{ {
int k1 = 2 * j + 1; auto k1 = 2 * j + 1;
int k2 = 2 * j + 2; auto k2 = 2 * j + 2;
j_next = j; j_next = j;
if (eig_val[k1] < eig_val[j_next]) j_next = k1; if (eig_val[k1] < eig_val[j_next]) j_next = k1;
if (k2 < n && eig_val[k2] < eig_val[j_next]) j_next = k2; if (k2 < n && eig_val[k2] < eig_val[j_next]) j_next = k2;
...@@ -76,14 +76,14 @@ heap_sort(Varray<double> &eig_val, double **a, int n) ...@@ -76,14 +76,14 @@ heap_sort(Varray<double> &eig_val, double **a, int n)
} }
} }
// Second part of head sort: // Second part of head sort:
for (int i = n - 1; i > 0; i--) for (long i = n - 1; i > 0; i--)
{ {
std::swap(eig_val[0], eig_val[i]); std::swap(eig_val[0], eig_val[i]);
std::swap(a[0], a[i]); std::swap(a[0], a[i]);
for (int j = 0; 2 * j + 1 < i; j = j_next) for (long j = 0; 2 * j + 1 < i; j = j_next)
{ {
int k1 = 2 * j + 1; auto k1 = 2 * j + 1;
int k2 = 2 * j + 2; auto k2 = 2 * j + 2;
j_next = j; j_next = j;
if (eig_val[k1] < eig_val[j_next]) j_next = k1; if (eig_val[k1] < eig_val[j_next]) j_next = k1;
if (k2 < i && eig_val[k2] < eig_val[j_next]) j_next = k2; if (k2 < i && eig_val[k2] < eig_val[j_next]) j_next = k2;
...@@ -95,9 +95,9 @@ heap_sort(Varray<double> &eig_val, double **a, int n) ...@@ -95,9 +95,9 @@ heap_sort(Varray<double> &eig_val, double **a, int n)
} }
static void static void
make_symmetric_matrix_triangular(double **a, int n, Varray<double> &d, Varray<double> &e) make_symmetric_matrix_triangular(Varray2D<double> &a, long n, Varray<double> &d, Varray<double> &e)
{ {
int i, j, k; long i, j, k;
double f, g, h, hh, scale; double f, g, h, hh, scale;
for (i = n - 1; i >= 1; i--) for (i = n - 1; i >= 1; i--)
...@@ -172,13 +172,13 @@ pythagoras(double a, double b) ...@@ -172,13 +172,13 @@ pythagoras(double a, double b)
{ {
auto sqr = abs_b / abs_a; auto sqr = abs_b / abs_a;
sqr *= sqr; sqr *= sqr;
return abs_a * std::sqrt(1 + sqr); return abs_a * std::sqrt(1.0 + sqr);
} }
else if (abs_b > abs_a) else if (abs_b > abs_a)
{ {
auto sqr = abs_a / abs_b; auto sqr = abs_a / abs_b;
sqr *= sqr; sqr *= sqr;
return abs_b * std::sqrt(1 + sqr); return abs_b * std::sqrt(1.0 + sqr);
} }
else else
return M_SQRT2 * abs_a; return M_SQRT2 * abs_a;
...@@ -187,15 +187,15 @@ pythagoras(double a, double b) ...@@ -187,15 +187,15 @@ pythagoras(double a, double b)
#define MAX_ITER 1000 #define MAX_ITER 1000
static void static void
eigen_solution_of_triangular_matrix(Varray<double> &d, Varray<double> &e, int n, double **a, const char *prompt) eigen_solution_of_triangular_matrix(Varray<double> &d, Varray<double> &e, long n, Varray2D<double> &a, const char *prompt)
{ {
constexpr double eps = 1.e-6; constexpr double eps = 1.e-6;
int i, k, l, m, iter; long i, k, l, m, iter;
double b, c, f, g, p, r, s; double b, c, f, g, p, r, s;
for (i = 1; i < n; i++) e[i - 1] = e[i]; for (i = 1; i < n; i++) e[i - 1] = e[i];
e[n - 1] = 0; e[n - 1] = 0.0;
for (l = 0; l < n; l++) for (l = 0; l < n; l++)
{ {
iter = 0; iter = 0;
...@@ -214,7 +214,7 @@ eigen_solution_of_triangular_matrix(Varray<double> &d, Varray<double> &e, int n, ...@@ -214,7 +214,7 @@ eigen_solution_of_triangular_matrix(Varray<double> &d, Varray<double> &e, int n,
fprintf(stderr, "%s: ERROR! Too many iterations while determining the eigensolution!\n", prompt); fprintf(stderr, "%s: ERROR! Too many iterations while determining the eigensolution!\n", prompt);
exit(1); exit(1);
} }
g = (d[l + 1] - d[l]) / (2 * e[l]); g = (d[l + 1] - d[l]) / (2.0 * e[l]);
r = pythagoras(g, 1); r = pythagoras(g, 1);
g = d[m] - d[l] + e[l] / (g + (std::fabs(g) > 0 ? (g >= 0 ? std::fabs(r) : -std::fabs(r)) : r)); g = d[m] - d[l] + e[l] / (g + (std::fabs(g) > 0 ? (g >= 0 ? std::fabs(r) : -std::fabs(r)) : r));
s = c = 1;