aboutsummaryrefslogtreecommitdiff
path: root/src/mathfunc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mathfunc.cpp')
-rw-r--r--src/mathfunc.cpp123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/mathfunc.cpp b/src/mathfunc.cpp
index 9a4bb8b..3b70102 100644
--- a/src/mathfunc.cpp
+++ b/src/mathfunc.cpp
@@ -29,15 +29,25 @@
#include <stdio.h>
#include <stdlib.h>
#include <string>
+#include <tuple>
#include <vector>
#include "Eigen/Dense"
+
+#include "gsl/gsl_version.h"
+
+#if GSL_MAJOR_VERSION < 2
+#pragma message "GSL version " GSL_VERSION
+#endif
+
#include "gsl/gsl_blas.h"
#include "gsl/gsl_cdf.h"
#include "gsl/gsl_linalg.h"
#include "gsl/gsl_matrix.h"
#include "gsl/gsl_vector.h"
+#include "gsl/gsl_eigen.h"
+#include "debug.h"
#include "eigenlib.h"
#include "lapack.h"
#include "mathfunc.h"
@@ -45,6 +55,14 @@
using namespace std;
using namespace Eigen;
+bool has_nan(const vector<double> v) {
+ for (const auto& e: v) {
+ if (std::isnan(e))
+ return true;
+ }
+ return false;
+}
+
// calculate variance of a vector
double VectorVar(const gsl_vector *v) {
double d, m = 0.0, m2 = 0.0;
@@ -187,6 +205,111 @@ double ScaleMatrix(gsl_matrix *G) {
return d;
}
+bool isMatrixSymmetric(const gsl_matrix *G) {
+ enforce(G->size1 == G->size2);
+ auto m = G->data;
+ // upper triangle
+ auto size = G->size1;
+ for(auto c = 0; c < size; c++) {
+ for(auto r = 0; r < c; r++) {
+ int x1 = c, y1 = r, x2 = r, y2 = c;
+ auto idx1 = y1*size+x1, idx2 = y2*size+x2;
+ // printf("(%d,%d %f - %d,%d %f)",x1,y1,m[idx1],x2,y2,m[idx2]);
+ if(m[idx1] != m[idx2]) {
+ cout << "Mismatch coordinates (" << c << "," << r << ")" << m[idx1] << ":" << m[idx2] << "!" << endl;
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool isMatrixPositiveDefinite(const gsl_matrix *G) {
+ enforce(G->size1 == G->size2);
+ auto G2 = gsl_matrix_alloc(G->size1, G->size2);
+ enforce_gsl(gsl_matrix_memcpy(G2,G));
+ auto handler = gsl_set_error_handler_off();
+#if GSL_MAJOR_VERSION >= 2
+ auto s = gsl_linalg_cholesky_decomp1(G2);
+#else
+ auto s = gsl_linalg_cholesky_decomp(G2);
+#endif
+ gsl_set_error_handler(handler);
+ gsl_matrix_free(G2);
+ return (s == GSL_SUCCESS);
+}
+
+gsl_vector *getEigenValues(const gsl_matrix *G) {
+ enforce(G->size1 == G->size2);
+ auto G2 = gsl_matrix_alloc(G->size1, G->size2);
+ enforce_gsl(gsl_matrix_memcpy(G2,G));
+ auto eworkspace = gsl_eigen_symm_alloc(G->size1);
+ enforce(eworkspace);
+ gsl_vector *eigenvalues = gsl_vector_alloc(G->size1);
+ enforce_gsl(gsl_eigen_symm(G2, eigenvalues, eworkspace));
+ gsl_eigen_symm_free(eworkspace);
+ gsl_matrix_free(G2);
+ return eigenvalues;
+}
+
+// Check whether eigen values are larger than *min*
+// by default 1E-5.
+// Returns success, eigen min, eigen max
+
+tuple<double, double> abs_minmax(const gsl_vector *v) {
+ auto min = std::abs(v->data[0]);
+ auto max = std::abs(v->data[0]);
+ for (auto i=0; i<v->size; i++) {
+ auto value = std::abs(v->data[i]);
+ if (value < min)
+ min = value;
+ if (value > max)
+ max = value;
+ }
+ return std::make_tuple(min, max);
+}
+
+bool has_negative_values(const gsl_vector *v) {
+ for (auto i=0; i<v->size; i++) {
+ if (v->data[i] < 0.0) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool checkMatrixEigen(const gsl_matrix *G, double min) {
+ auto eigenvalues = getEigenValues(G);
+ bool ret_valid = true;
+
+ if (has_negative_values(eigenvalues))
+ ret_valid = false;
+
+ auto t = abs_minmax(eigenvalues);
+ auto absmin = get<0>(t);
+ if (absmin < min)
+ ret_valid = false;
+ gsl_vector_free(eigenvalues);
+ return ret_valid;
+}
+
+bool isMatrixIllConditioned(const gsl_matrix *G, double max_ratio) {
+ bool ret_valid = true;
+ auto eigenvalues = getEigenValues(G);
+
+ auto t = abs_minmax(eigenvalues);
+ auto absmin = get<0>(t);
+ auto absmax = get<1>(t);
+ if (absmax/absmin > max_ratio) {
+ #if !NDEBUG
+ cerr << "**** DEBUG: Eigenvalues Min " << absmin << " Max " << absmax << " Ratio " << absmax/absmin << endl;
+ #endif
+ ret_valid = false;
+ }
+ gsl_vector_free(eigenvalues);
+ return ret_valid;
+}
+
double SumVector(const gsl_vector *v) {
double sum = 0;
for (int i = 0; i < v->size; i++ ) {