// // Lol Engine - Sample math program: Chebyshev polynomials // // Copyright: (c) 2005-2011 Sam Hocevar // This program is free software; you can redistribute it and/or // modify it under the terms of the Do What The Fuck You Want To // Public License, Version 2, as published by Sam Hocevar. See // http://sam.zoy.org/projects/COPYING.WTFPL for more details. // #if !defined __REMEZ_MATRIX_H__ #define __REMEZ_MATRIX_H__ template struct Matrix { inline Matrix() {} Matrix(real x) { for (int j = 0; j < N; j++) for (int i = 0; i < N; i++) if (i == j) m[i][j] = x; else m[i][j] = 0; } /* Naive matrix inversion */ Matrix inv() const { Matrix a = *this, b((real)1.0); /* Inversion method: iterate through all columns and make sure * all the terms are 1 on the diagonal and 0 everywhere else */ for (int i = 0; i < N; i++) { /* If the expected coefficient is zero, add one of * the other lines. The first we meet will do. */ if ((double)a.m[i][i] == 0.0) { for (int j = i + 1; j < N; j++) { if ((double)a.m[i][j] == 0.0) continue; /* Add row j to row i */ for (int n = 0; n < N; n++) { a.m[n][i] += a.m[n][j]; b.m[n][i] += b.m[n][j]; } break; } } /* Now we know the diagonal term is non-zero. Get its inverse * and use that to nullify all other terms in the column */ real x = (real)1.0 / a.m[i][i]; for (int j = 0; j < N; j++) { if (j == i) continue; real mul = x * a.m[i][j]; for (int n = 0; n < N; n++) { a.m[n][j] -= mul * a.m[n][i]; b.m[n][j] -= mul * b.m[n][i]; } } /* Finally, ensure the diagonal term is 1 */ for (int n = 0; n < N; n++) { a.m[n][i] *= x; b.m[n][i] *= x; } } return b; } void print() const { using std::printf; for (int j = 0; j < N; j++) { for (int i = 0; i < N; i++) printf("%9.5f ", (double)m[j][i]); printf("\n"); } } real m[N][N]; }; #endif /* __REMEZ_MATRIX_H__ */