summaryrefslogtreecommitdiff
path: root/numlib/svdtest.c
diff options
context:
space:
mode:
Diffstat (limited to 'numlib/svdtest.c')
-rw-r--r--numlib/svdtest.c214
1 files changed, 214 insertions, 0 deletions
diff --git a/numlib/svdtest.c b/numlib/svdtest.c
new file mode 100644
index 0000000..100120d
--- /dev/null
+++ b/numlib/svdtest.c
@@ -0,0 +1,214 @@
+
+/* SVD test */
+/* Verify that the SVD solver does what it is supposed to. */
+/*
+ * Copyright 2000 Graeme W. Gill
+ * All rights reserved.
+ *
+ * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
+ * see the License.txt file for licencing details.
+ */
+
+/* We assume two device dependent variables, and one objective function value */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <math.h>
+#include <time.h>
+#if defined(__IBMC__)
+#include <float.h>
+#endif
+
+#include "numlib.h"
+
+int main(void) {
+ int its;
+ int i,j,x;
+ double **a; /* A[0..M-1][0..N-1] input */
+ double **u; /* U[0..M-1][0..N-1] output */
+ double *w; /* W[0..N-1] output */
+ double **v; /* V[0..N-1][0..N-1] output */
+ double **a2; /* A[0..M-1][0..N-1] check on a */
+ double **t; /* A[0..M-1][0..N-1] temp */
+ int m,n;
+
+#if defined(__IBMC__)
+ _control87(EM_UNDERFLOW, EM_UNDERFLOW);
+ _control87(EM_OVERFLOW, EM_OVERFLOW);
+#endif
+
+ printf("Test SVD\n");
+
+ for (its = 400; its > 0; its--) {
+ int bad;
+ int bad0;
+
+ m = i_rand(1,30); /* Number of equations */
+ n = i_rand(1,30); /* Number of unknowns */
+
+ a = dmatrix(0,m-1, 0,n-1);
+ t = dmatrix(0,m-1, 0,n-1);
+ a2 = dmatrix(0,m-1, 0,n-1);
+ u = dmatrix(0,m-1, 0,n-1);
+ w = dvector(0,n-1);
+ v = dmatrix(0,n-1, 0,n-1);
+
+ printf("Testing %d by %d\n",m,n);
+
+ /* Create A matrix */
+ for (j = 0; j < m; j++)
+ for (i = 0; i < n; i++)
+ a[j][i] = d_rand(-10.0, 10.0);
+
+ /* Setup u */
+ for (j = 0; j < m; j++)
+ for (i = 0; i < n; i++)
+ u[j][i] = a[j][i];
+
+ /* decompose A into U, W and V */
+ svdecomp(u, w, v, m, n);
+
+ /* Check results by computing a2 = U.W.Vt */
+ for (j = 0; j < m; j++) { /* U.W */
+ for (i = 0; i < n; i++) {
+ t[j][i] = 0.0;
+ for (x = 0; x < n; x++) {
+ if (x == i)
+ t[j][i] += u[j][x] * w[x];
+ }
+ }
+ }
+ for (j = 0; j < m; j++) { /* .Vt */
+ for (i = 0; i < n; i++) {
+ a2[j][i] = 0.0;
+ for (x = 0; x < n; x++) {
+ a2[j][i] += t[j][x] * v[i][x];
+ }
+ }
+ }
+
+ /* Now check */
+ bad = 0;
+ for (j = 0; j < m; j++)
+ for (i = 0; i < n; i++) {
+ double tt;
+ tt = a2[j][i] - a[j][i];
+ tt = fabs(tt);
+ if (tt > 0.0000001) {
+ bad = 1;
+ }
+ }
+ if (bad)
+ printf("A == U.W.Vt Check failed!\n");
+
+
+ /* Check that U and Ut are inverses */
+ bad = bad0 = 0;
+ for (j = 0; j < n; j++) {
+ for (i = 0; i < n; i++) {
+ double t2, tt = 0.0;
+ for (x = 0; x < m; x++) {
+ tt += u[x][j] * u[x][i];
+ }
+ t2 = tt;
+ if (i == j)
+ tt -= 1.0;
+ tt = fabs(tt);
+ if (tt > 0.0000001) {
+ if (i == j && fabs(t2) < 0.0000001)
+ bad0++; /* Unexpected zero diagonal */
+ else {
+ bad = 1;
+ printf("Possible U error at %d %d = %f \n",j,i,tt);
+ }
+ }
+ }
+ }
+ /* Expect n-m diagnals to be 0 instead of 1 if m < n */
+ if (bad || (m >= n && bad0) || (m < n && bad0 != n-m))
+ printf("U,Ut == 1 Check failed!\n");
+
+ /* Check that V and Vt are inverses */
+ bad = 0;
+ for (j = 0; j < n; j++) {
+ for (i = 0; i < n; i++) {
+ double tt = 0.0;
+ for (x = 0; x < n; x++) {
+ tt += v[j][x] * v[i][x];
+ }
+ if (i == j)
+ tt -= 1.0;
+ tt = fabs(tt);
+ if (tt > 0.0000001) {
+ bad = 1;
+ printf("V Error at %d %d = %f \n",j,i,tt);
+ }
+ }
+ if (bad)
+ printf("V,Vt == 1 Check failed!\n");
+ }
+
+#ifdef NEVER
+ printf("A = %f %f %f\n %f %f %f\n %f %f %f\n\n",
+ a[0][0], a[0][1], a[0][2], a[1][0], a[1][1], a[1][2], a[2][0], a[2][1], a[2][2]);
+
+ printf("u = %f %f %f\n %f %f %f\n %f %f %f\n\n",
+ u[0][0], u[0][1], u[0][2], u[1][0], u[1][1], u[1][2], u[2][0], u[2][1], u[2][2]);
+
+ printf("w = %f %f %f\n\n", w[0],w[1],w[2]);
+
+ printf("V = %f %f %f\n %f %f %f\n %f %f %f\n\n",
+ v[0][0], v[0][1], v[0][2], v[1][0], v[1][1], v[1][2], v[2][0], v[2][1], v[2][2]);;
+
+ printf("A2 = %f %f %f\n %f %f %f\n %f %f %f\n\n",
+ a2[0][0], a2[0][1], a2[0][2], a2[1][0], a2[1][1],
+ a2[1][2], a2[2][0], a2[2][1], a2[2][2]);
+#endif
+
+ free_dmatrix(a, 0,m-1, 0,n-1);
+ free_dmatrix(t, 0,m-1, 0,n-1);
+ free_dmatrix(a2, 0,m-1, 0,n-1);
+ free_dmatrix(u, 0,m-1, 0,n-1);
+ free_dvector(w, 0,n-1);
+ free_dmatrix(v, 0,n-1, 0,n-1);
+ }
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+