summaryrefslogtreecommitdiffstats
path: root/src/libs/lprof/cmsmatn.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/lprof/cmsmatn.cpp')
-rw-r--r--src/libs/lprof/cmsmatn.cpp323
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
+
+