diff options
Diffstat (limited to 'src/libs/lprof/cmsmatn.cpp')
-rw-r--r-- | src/libs/lprof/cmsmatn.cpp | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/src/libs/lprof/cmsmatn.cpp b/src/libs/lprof/cmsmatn.cpp new file mode 100644 index 00000000..bca52717 --- /dev/null +++ b/src/libs/lprof/cmsmatn.cpp @@ -0,0 +1,323 @@ +/* */ +/* Little cms - profiler construction set */ +/* Copyright (C) 1998-2001 Marti Maria <marti@littlecms.com> */ +/* */ +/* THIS SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY */ +/* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. */ +/* */ +/* IN NO EVENT SHALL MARTI MARIA BE LIABLE FOR ANY SPECIAL, INCIDENTAL, */ +/* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, */ +/* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, */ +/* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF */ +/* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE */ +/* OF THIS SOFTWARE. */ +/* */ +/* This file is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but */ +/* WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +/* */ +/* As a special exception to the GNU General Public License, if you */ +/* distribute this file as part of a program that contains a */ +/* configuration script generated by Autoconf, you may include it under */ +/* the same distribution terms that you use for the rest of that program. */ +/* */ +/* Version 1.09a */ + + +#include "lcmsprf.h" + + +LPMATN cdecl MATNalloc(int Rows, int Cols); +void cdecl MATNfree (LPMATN mat); +LPMATN cdecl MATNmult(LPMATN a1, LPMATN a2); +double cdecl MATNcross(LPMATN a); +void cdecl MATNscalar (LPMATN a, double scl, LPMATN b); +LPMATN cdecl MATNtranspose (LPMATN a); +BOOL cdecl MATNsolve(LPMATN a, LPMATN b); + + +/* ------------------------------------------------------------ Implementation */ + +/* Free matrix */ + +void MATNfree(LPMATN mat) +{ + int i; + + if (mat == NULL) return; + + for (i = 0; i < mat->Rows; i++) + { + if (mat -> Values[i] != NULL) + free (mat->Values[i]); + } + + free(mat->Values); + free(mat); +} + + +/* Allocate (and Zero) a new matrix */ + +LPMATN MATNalloc(int Rows, int Cols) +{ + int i; + + LPMATN mat = (LPMATN) malloc (sizeof (MATN)); + if (mat == NULL) return mat; + + ZeroMemory(mat, sizeof(MATN)); + + mat->Rows = Rows; + mat->Cols = Cols; + mat->Values = (double**) malloc(Rows * sizeof (double*)); + + if (mat->Values == NULL) { + free(mat); + return NULL; + } + + ZeroMemory(mat -> Values, Rows * sizeof (double*)); + + for (i = 0; i < Rows; i++) + { + mat-> Values [i] = (double*) malloc(Cols * sizeof (double)); + if (mat -> Values[i] == NULL) { + MATNfree(mat); + return NULL; + } + + } + + return mat; +} + +#define DO_SWAP(a, b, tmp) { tmp = (a); (a) = (b); (b) = tmp; } + +/* Gauss-Jordan elimination. There is also a more */ +/* exahustive non-singular matrix checking part. */ + +BOOL MATNsolve(LPMATN a, LPMATN b) +{ + BOOL status; + int n = a->Rows; + int i, iCol=0, iRow=0, j, k; + double fMax, fAbs, fSave, fInf, temp; + int* aiColIndex; + int* aiRowIndex=0; + int* aiPivoted=0; + + + if (a->Rows != a->Cols) return false; + + status = false; + if((aiColIndex = (int*) malloc(n * sizeof(int))) == NULL) + goto GotError; + + if((aiRowIndex = (int*) malloc(n * sizeof(int))) == NULL) + goto GotError; + + if((aiPivoted = (int*) malloc(n * sizeof(int))) == NULL) + goto GotError; + + ZeroMemory(aiPivoted, n * sizeof(int)); + + + for(i = 0; i < n; i++) { + + /* search matrix (excluding pivoted rows) for maximum absolute entry */ + + fMax = 0.0; + for (j = 0; j < n; j++) + if (aiPivoted[j] != 1) + for (k = 0; k < n; k++) + { + fAbs = fabs(a->Values[j][k]); + if (fAbs >= fMax) { + + fMax = fAbs; + iRow = j; + iCol = k; + } + else + if (aiPivoted[k] > 1) { + + status = false; + goto GotError; + } + } + + aiPivoted[iCol]++; + + /* swap rows so that A[iCol][iCol] contains the pivot entry */ + + if (iRow != iCol) { + + for(j = 0; j < n; j++) + DO_SWAP(a->Values[iRow][j], a->Values[iCol][j], temp) + + DO_SWAP(b->Values[iRow][0], b->Values[iCol][0], temp) + } + + /* keep track of the permutations of the rows */ + + aiRowIndex[i] = iRow; + aiColIndex[i] = iCol; + + if (a->Values[iCol][iCol] == 0.0) + { + status = false; + goto GotError; + } + + /* scale the row so that the pivot entry is 1 */ + + fInf = 1.0 / a->Values[iCol][iCol]; + a->Values[iCol][iCol] = 1.0; + + for(j = 0; j < n; j++) + a->Values[iCol][j] *= fInf; + + b->Values[iCol][0] *= fInf; + + /* zero out the pivot column locations in the other rows */ + + for(j = 0; j < n; j++) + if (j != iCol) { + + fSave = a->Values[j][iCol]; + a->Values[j][iCol] = 0.0; + + for(k = 0; k < n; k++) + a->Values[j][k] -= a->Values[iCol][k] * fSave; + + b->Values[j][0] -= b->Values[iCol][0] * fSave; + } + } + + /* reorder rows so that A[][] stores the inverse of the original matrix */ + + for(i = n - 1; i >= 0; i--) { + + if(aiRowIndex[i] != aiColIndex[i]) + for(j = 0; j < n; j++) + DO_SWAP(a->Values[j][aiRowIndex[i]], a->Values[j][aiColIndex[i]], temp) + } + + status = true; + +GotError: + if(aiColIndex) free(aiColIndex); + if(aiRowIndex) free(aiRowIndex); + if(aiPivoted) free(aiPivoted); + return status; + +} + +#undef DO_SWAP + + +LPMATN MATNmult(LPMATN a1, LPMATN a2) +{ + int i, j, k; + LPMATN b; + + if (a1->Cols != a2->Rows) + return NULL; + + b = MATNalloc (a1->Rows, a2->Cols); + if (b == NULL) + return NULL; + + for (i = 0; i < b->Rows; i++) { + + for (j = 0; j < b->Cols; j++) { + + b->Values[i][j] = 0.0; + + for (k = 0; k < a1->Cols; k++) { + + b->Values[i][j] += a1->Values[i][k] * a2->Values[k][j]; + } + } + } + + return b; +} + + +double MATNcross(LPMATN a) +{ + int i; + double prod = 0.0; + + for (i = 0; i < a->Rows; i++) { + + prod += a->Values[i][0]*a->Values[i][0]; + } + return prod; +} + + +void MATNscalar(LPMATN a, double scl, LPMATN b) +{ + int i, j; + + if (a->Rows != b->Rows || a->Cols != b->Cols) + return; + + for (i = 0; i < a->Rows; i++) { + + for (j = 0; j < a->Cols; j++) + b->Values[i][j] = a->Values[i][j] * scl; + } +} + + +LPMATN MATNtranspose(LPMATN a) +{ + LPMATN b = MATNalloc(a->Cols, a->Rows); + if (b != NULL) { + + int i, j; + + for (i = 0; i < a->Rows; i++) + { + for (j = 0; j < a->Cols; j++) + b->Values[j][i] = a->Values [i][j]; + } + } + return b; +} + + + +/* Used for debug purposes */ +#ifdef DEBUG +void MATNprintf(char* name, LPMATN mat) +{ + int i, j; + + printf ("%s:\n", name); + for (i= 0; i < mat->Rows; i++) { + + printf ("%3d", i); + for (j = 0; j < mat->Cols; j++) + printf (" %.5f", mat->Values[i][j]); + printf ("\n"); + } +} +#endif + + |