summaryrefslogtreecommitdiff
path: root/gpr/source/lib/dng_sdk/dng_matrix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gpr/source/lib/dng_sdk/dng_matrix.cpp')
-rw-r--r--gpr/source/lib/dng_sdk/dng_matrix.cpp1080
1 files changed, 1080 insertions, 0 deletions
diff --git a/gpr/source/lib/dng_sdk/dng_matrix.cpp b/gpr/source/lib/dng_sdk/dng_matrix.cpp
new file mode 100644
index 0000000..b96f80b
--- /dev/null
+++ b/gpr/source/lib/dng_sdk/dng_matrix.cpp
@@ -0,0 +1,1080 @@
+/*****************************************************************************/
+// Copyright 2006-2008 Adobe Systems Incorporated
+// All Rights Reserved.
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in
+// accordance with the terms of the Adobe license agreement accompanying it.
+/*****************************************************************************/
+
+/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_matrix.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_matrix.h"
+
+#include "dng_exceptions.h"
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+dng_matrix::dng_matrix ()
+
+ : fRows (0)
+ , fCols (0)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_matrix::dng_matrix (uint32 rows,
+ uint32 cols)
+
+ : fRows (0)
+ , fCols (0)
+
+ {
+
+ if (rows < 1 || rows > kMaxColorPlanes ||
+ cols < 1 || cols > kMaxColorPlanes)
+ {
+
+ ThrowProgramError ();
+
+ }
+
+ fRows = rows;
+ fCols = cols;
+
+ for (uint32 row = 0; row < fRows; row++)
+ for (uint32 col = 0; col < fCols; col++)
+ {
+
+ fData [row] [col] = 0.0;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_matrix::dng_matrix (const dng_matrix &m)
+
+ : fRows (m.fRows)
+ , fCols (m.fCols)
+
+ {
+
+ for (uint32 row = 0; row < fRows; row++)
+ for (uint32 col = 0; col < fCols; col++)
+ {
+
+ fData [row] [col] = m.fData [row] [col];
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_matrix::Clear ()
+ {
+
+ fRows = 0;
+ fCols = 0;
+
+ }
+
+/*****************************************************************************/
+
+void dng_matrix::SetIdentity (uint32 count)
+ {
+
+ *this = dng_matrix (count, count);
+
+ for (uint32 j = 0; j < count; j++)
+ {
+
+ fData [j] [j] = 1.0;
+
+ }
+
+ }
+
+/******************************************************************************/
+
+bool dng_matrix::operator== (const dng_matrix &m) const
+ {
+
+ if (Rows () != m.Rows () ||
+ Cols () != m.Cols ())
+ {
+
+ return false;
+
+ }
+
+ for (uint32 j = 0; j < Rows (); j++)
+ for (uint32 k = 0; k < Cols (); k++)
+ {
+
+ if (fData [j] [k] != m.fData [j] [k])
+ {
+
+ return false;
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/******************************************************************************/
+
+bool dng_matrix::IsDiagonal () const
+ {
+
+ if (IsEmpty ())
+ {
+ return false;
+ }
+
+ if (Rows () != Cols ())
+ {
+ return false;
+ }
+
+ for (uint32 j = 0; j < Rows (); j++)
+ for (uint32 k = 0; k < Cols (); k++)
+ {
+
+ if (j != k)
+ {
+
+ if (fData [j] [k] != 0.0)
+ {
+ return false;
+ }
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/******************************************************************************/
+
+real64 dng_matrix::MaxEntry () const
+ {
+
+ if (IsEmpty ())
+ {
+
+ return 0.0;
+
+ }
+
+ real64 m = fData [0] [0];
+
+ for (uint32 j = 0; j < Rows (); j++)
+ for (uint32 k = 0; k < Cols (); k++)
+ {
+
+ m = Max_real64 (m, fData [j] [k]);
+
+ }
+
+ return m;
+
+ }
+
+/******************************************************************************/
+
+real64 dng_matrix::MinEntry () const
+ {
+
+ if (IsEmpty ())
+ {
+
+ return 0.0;
+
+ }
+
+ real64 m = fData [0] [0];
+
+ for (uint32 j = 0; j < Rows (); j++)
+ for (uint32 k = 0; k < Cols (); k++)
+ {
+
+ m = Min_real64 (m, fData [j] [k]);
+
+ }
+
+ return m;
+
+ }
+
+/*****************************************************************************/
+
+void dng_matrix::Scale (real64 factor)
+ {
+
+ for (uint32 j = 0; j < Rows (); j++)
+ for (uint32 k = 0; k < Cols (); k++)
+ {
+
+ fData [j] [k] *= factor;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_matrix::Round (real64 factor)
+ {
+
+ real64 invFactor = 1.0 / factor;
+
+ for (uint32 j = 0; j < Rows (); j++)
+ for (uint32 k = 0; k < Cols (); k++)
+ {
+
+ fData [j] [k] = Round_int32 (fData [j] [k] * factor) * invFactor;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_matrix::SafeRound (real64 factor)
+ {
+
+ real64 invFactor = 1.0 / factor;
+
+ for (uint32 j = 0; j < Rows (); j++)
+ {
+
+ // Round each row to the specified accuracy, but make sure the
+ // a rounding does not affect the total of the elements in a row
+ // more than necessary.
+
+ real64 error = 0.0;
+
+ for (uint32 k = 0; k < Cols (); k++)
+ {
+
+ fData [j] [k] += error;
+
+ real64 rounded = Round_int32 (fData [j] [k] * factor) * invFactor;
+
+ error = fData [j] [k] - rounded;
+
+ fData [j] [k] = rounded;
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_matrix_3by3::dng_matrix_3by3 ()
+
+ : dng_matrix (3, 3)
+
+ {
+ }
+
+/*****************************************************************************/
+
+dng_matrix_3by3::dng_matrix_3by3 (const dng_matrix &m)
+
+ : dng_matrix (m)
+
+ {
+
+ if (Rows () != 3 ||
+ Cols () != 3)
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_matrix_3by3::dng_matrix_3by3 (real64 a00, real64 a01, real64 a02,
+ real64 a10, real64 a11, real64 a12,
+ real64 a20, real64 a21, real64 a22)
+
+
+ : dng_matrix (3, 3)
+
+ {
+
+ fData [0] [0] = a00;
+ fData [0] [1] = a01;
+ fData [0] [2] = a02;
+
+ fData [1] [0] = a10;
+ fData [1] [1] = a11;
+ fData [1] [2] = a12;
+
+ fData [2] [0] = a20;
+ fData [2] [1] = a21;
+ fData [2] [2] = a22;
+
+ }
+
+/*****************************************************************************/
+
+dng_matrix_3by3::dng_matrix_3by3 (real64 a00, real64 a11, real64 a22)
+
+ : dng_matrix (3, 3)
+
+ {
+
+ fData [0] [0] = a00;
+ fData [1] [1] = a11;
+ fData [2] [2] = a22;
+
+ }
+
+/*****************************************************************************/
+
+dng_matrix_4by3::dng_matrix_4by3 ()
+
+ : dng_matrix (4, 3)
+
+ {
+ }
+
+/*****************************************************************************/
+
+dng_matrix_4by3::dng_matrix_4by3 (const dng_matrix &m)
+
+ : dng_matrix (m)
+
+ {
+
+ if (Rows () != 4 ||
+ Cols () != 3)
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_matrix_4by3::dng_matrix_4by3 (real64 a00, real64 a01, real64 a02,
+ real64 a10, real64 a11, real64 a12,
+ real64 a20, real64 a21, real64 a22,
+ real64 a30, real64 a31, real64 a32)
+
+
+ : dng_matrix (4, 3)
+
+ {
+
+ fData [0] [0] = a00;
+ fData [0] [1] = a01;
+ fData [0] [2] = a02;
+
+ fData [1] [0] = a10;
+ fData [1] [1] = a11;
+ fData [1] [2] = a12;
+
+ fData [2] [0] = a20;
+ fData [2] [1] = a21;
+ fData [2] [2] = a22;
+
+ fData [3] [0] = a30;
+ fData [3] [1] = a31;
+ fData [3] [2] = a32;
+
+ }
+
+/*****************************************************************************/
+
+dng_vector::dng_vector ()
+
+ : fCount (0)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_vector::dng_vector (uint32 count)
+
+ : fCount (0)
+
+ {
+
+ if (count < 1 || count > kMaxColorPlanes)
+ {
+
+ ThrowProgramError ();
+
+ }
+
+ fCount = count;
+
+ for (uint32 index = 0; index < fCount; index++)
+ {
+
+ fData [index] = 0.0;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_vector::dng_vector (const dng_vector &v)
+
+ : fCount (v.fCount)
+
+ {
+
+ for (uint32 index = 0; index < fCount; index++)
+ {
+
+ fData [index] = v.fData [index];
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_vector::Clear ()
+ {
+
+ fCount = 0;
+
+ }
+
+/*****************************************************************************/
+
+void dng_vector::SetIdentity (uint32 count)
+ {
+
+ *this = dng_vector (count);
+
+ for (uint32 j = 0; j < count; j++)
+ {
+
+ fData [j] = 1.0;
+
+ }
+
+ }
+
+/******************************************************************************/
+
+bool dng_vector::operator== (const dng_vector &v) const
+ {
+
+ if (Count () != v.Count ())
+ {
+
+ return false;
+
+ }
+
+ for (uint32 j = 0; j < Count (); j++)
+ {
+
+ if (fData [j] != v.fData [j])
+ {
+
+ return false;
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/******************************************************************************/
+
+real64 dng_vector::MaxEntry () const
+ {
+
+ if (IsEmpty ())
+ {
+
+ return 0.0;
+
+ }
+
+ real64 m = fData [0];
+
+ for (uint32 j = 0; j < Count (); j++)
+ {
+
+ m = Max_real64 (m, fData [j]);
+
+ }
+
+ return m;
+
+ }
+
+/******************************************************************************/
+
+real64 dng_vector::MinEntry () const
+ {
+
+ if (IsEmpty ())
+ {
+
+ return 0.0;
+
+ }
+
+ real64 m = fData [0];
+
+ for (uint32 j = 0; j < Count (); j++)
+ {
+
+ m = Min_real64 (m, fData [j]);
+
+ }
+
+ return m;
+
+ }
+
+/*****************************************************************************/
+
+void dng_vector::Scale (real64 factor)
+ {
+
+ for (uint32 j = 0; j < Count (); j++)
+ {
+
+ fData [j] *= factor;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_vector::Round (real64 factor)
+ {
+
+ real64 invFactor = 1.0 / factor;
+
+ for (uint32 j = 0; j < Count (); j++)
+ {
+
+ fData [j] = Round_int32 (fData [j] * factor) * invFactor;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_matrix dng_vector::AsDiagonal () const
+ {
+
+ dng_matrix M (Count (), Count ());
+
+ for (uint32 j = 0; j < Count (); j++)
+ {
+
+ M [j] [j] = fData [j];
+
+ }
+
+ return M;
+
+ }
+
+/*****************************************************************************/
+
+dng_matrix dng_vector::AsColumn () const
+ {
+
+ dng_matrix M (Count (), 1);
+
+ for (uint32 j = 0; j < Count (); j++)
+ {
+
+ M [j] [0] = fData [j];
+
+ }
+
+ return M;
+
+ }
+
+/******************************************************************************/
+
+dng_vector_3::dng_vector_3 ()
+
+ : dng_vector (3)
+
+ {
+ }
+
+/******************************************************************************/
+
+dng_vector_3::dng_vector_3 (const dng_vector &v)
+
+ : dng_vector (v)
+
+ {
+
+ if (Count () != 3)
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ }
+
+/******************************************************************************/
+
+dng_vector_3::dng_vector_3 (real64 a0,
+ real64 a1,
+ real64 a2)
+
+ : dng_vector (3)
+
+ {
+
+ fData [0] = a0;
+ fData [1] = a1;
+ fData [2] = a2;
+
+ }
+
+/******************************************************************************/
+
+dng_vector_4::dng_vector_4 ()
+
+ : dng_vector (4)
+
+ {
+ }
+
+/******************************************************************************/
+
+dng_vector_4::dng_vector_4 (const dng_vector &v)
+
+ : dng_vector (v)
+
+ {
+
+ if (Count () != 4)
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ }
+
+/******************************************************************************/
+
+dng_vector_4::dng_vector_4 (real64 a0,
+ real64 a1,
+ real64 a2,
+ real64 a3)
+
+ : dng_vector (4)
+
+ {
+
+ fData [0] = a0;
+ fData [1] = a1;
+ fData [2] = a2;
+ fData [3] = a3;
+
+ }
+
+/******************************************************************************/
+
+dng_matrix operator* (const dng_matrix &A,
+ const dng_matrix &B)
+ {
+
+ if (A.Cols () != B.Rows ())
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ dng_matrix C (A.Rows (), B.Cols ());
+
+ for (uint32 j = 0; j < C.Rows (); j++)
+ for (uint32 k = 0; k < C.Cols (); k++)
+ {
+
+ C [j] [k] = 0.0;
+
+ for (uint32 m = 0; m < A.Cols (); m++)
+ {
+
+ real64 aa = A [j] [m];
+
+ real64 bb = B [m] [k];
+
+ C [j] [k] += aa * bb;
+
+ }
+
+ }
+
+ return C;
+
+ }
+
+/******************************************************************************/
+
+dng_vector operator* (const dng_matrix &A,
+ const dng_vector &B)
+ {
+
+ if (A.Cols () != B.Count ())
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ dng_vector C (A.Rows ());
+
+ for (uint32 j = 0; j < C.Count (); j++)
+ {
+
+ C [j] = 0.0;
+
+ for (uint32 m = 0; m < A.Cols (); m++)
+ {
+
+ real64 aa = A [j] [m];
+
+ real64 bb = B [m];
+
+ C [j] += aa * bb;
+
+ }
+
+ }
+
+ return C;
+
+ }
+
+/******************************************************************************/
+
+dng_matrix operator* (real64 scale,
+ const dng_matrix &A)
+ {
+
+ dng_matrix B (A);
+
+ B.Scale (scale);
+
+ return B;
+
+ }
+
+/******************************************************************************/
+
+dng_vector operator* (real64 scale,
+ const dng_vector &A)
+ {
+
+ dng_vector B (A);
+
+ B.Scale (scale);
+
+ return B;
+
+ }
+
+/******************************************************************************/
+
+dng_matrix operator+ (const dng_matrix &A,
+ const dng_matrix &B)
+ {
+
+ if (A.Cols () != B.Cols () ||
+ A.Rows () != B.Rows ())
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ dng_matrix C (A);
+
+ for (uint32 j = 0; j < C.Rows (); j++)
+ for (uint32 k = 0; k < C.Cols (); k++)
+ {
+
+ C [j] [k] += B [j] [k];
+
+ }
+
+ return C;
+
+ }
+
+/******************************************************************************/
+
+const real64 kNearZero = 1.0E-10;
+
+/******************************************************************************/
+
+// Work around bug #1294195, which may be a hardware problem on a specific machine.
+// This pragma turns on "improved" floating-point consistency.
+#ifdef _MSC_VER
+#pragma optimize ("p", on)
+#endif
+
+static dng_matrix Invert3by3 (const dng_matrix &A)
+ {
+
+ real64 a00 = A [0] [0];
+ real64 a01 = A [0] [1];
+ real64 a02 = A [0] [2];
+ real64 a10 = A [1] [0];
+ real64 a11 = A [1] [1];
+ real64 a12 = A [1] [2];
+ real64 a20 = A [2] [0];
+ real64 a21 = A [2] [1];
+ real64 a22 = A [2] [2];
+
+ real64 temp [3] [3];
+
+ temp [0] [0] = a11 * a22 - a21 * a12;
+ temp [0] [1] = a21 * a02 - a01 * a22;
+ temp [0] [2] = a01 * a12 - a11 * a02;
+ temp [1] [0] = a20 * a12 - a10 * a22;
+ temp [1] [1] = a00 * a22 - a20 * a02;
+ temp [1] [2] = a10 * a02 - a00 * a12;
+ temp [2] [0] = a10 * a21 - a20 * a11;
+ temp [2] [1] = a20 * a01 - a00 * a21;
+ temp [2] [2] = a00 * a11 - a10 * a01;
+
+ real64 det = (a00 * temp [0] [0] +
+ a01 * temp [1] [0] +
+ a02 * temp [2] [0]);
+
+ if (Abs_real64 (det) < kNearZero)
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ dng_matrix B (3, 3);
+
+ for (uint32 j = 0; j < 3; j++)
+ for (uint32 k = 0; k < 3; k++)
+ {
+
+ B [j] [k] = temp [j] [k] / det;
+
+ }
+
+ return B;
+
+ }
+
+// Reset floating-point optimization. See comment above.
+#ifdef _MSC_VER
+#pragma optimize ("p", off)
+#endif
+
+/******************************************************************************/
+
+static dng_matrix InvertNbyN (const dng_matrix &A)
+ {
+
+ uint32 i;
+ uint32 j;
+ uint32 k;
+
+ uint32 n = A.Rows ();
+
+ real64 temp [kMaxColorPlanes] [kMaxColorPlanes * 2];
+
+ for (i = 0; i < n; i++)
+ for (j = 0; j < n; j++)
+ {
+
+ temp [i] [j ] = A [i] [j];
+
+ temp [i] [j + n] = (i == j ? 1.0 : 0.0);
+
+ }
+
+ for (i = 0; i < n; i++)
+ {
+
+ real64 alpha = temp [i] [i];
+
+ if (Abs_real64 (alpha) < kNearZero)
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ for (j = 0; j < n * 2; j++)
+ {
+
+ temp [i] [j] /= alpha;
+
+ }
+
+ for (k = 0; k < n; k++)
+ {
+
+ if (i != k)
+ {
+
+ real64 beta = temp [k] [i];
+
+ for (j = 0; j < n * 2; j++)
+ {
+
+ temp [k] [j] -= beta * temp [i] [j];
+
+ }
+
+ }
+
+ }
+
+ }
+
+ dng_matrix B (n, n);
+
+ for (i = 0; i < n; i++)
+ for (j = 0; j < n; j++)
+ {
+
+ B [i] [j] = temp [i] [j + n];
+
+ }
+
+ return B;
+
+ }
+
+/******************************************************************************/
+
+dng_matrix Transpose (const dng_matrix &A)
+ {
+
+ dng_matrix B (A.Cols (), A.Rows ());
+
+ for (uint32 j = 0; j < B.Rows (); j++)
+ for (uint32 k = 0; k < B.Cols (); k++)
+ {
+
+ B [j] [k] = A [k] [j];
+
+ }
+
+ return B;
+
+ }
+
+/******************************************************************************/
+
+dng_matrix Invert (const dng_matrix &A)
+ {
+
+ if (A.Rows () < 2 || A.Cols () < 2)
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ if (A.Rows () == A.Cols ())
+ {
+
+ if (A.Rows () == 3)
+ {
+
+ return Invert3by3 (A);
+
+ }
+
+ return InvertNbyN (A);
+
+ }
+
+ else
+ {
+
+ // Compute the pseudo inverse.
+
+ dng_matrix B = Transpose (A);
+
+ return Invert (B * A) * B;
+
+ }
+
+ }
+
+/******************************************************************************/
+
+dng_matrix Invert (const dng_matrix &A,
+ const dng_matrix &hint)
+ {
+
+ if (A.Rows () == A .Cols () ||
+ A.Rows () != hint.Cols () ||
+ A.Cols () != hint.Rows ())
+ {
+
+ return Invert (A);
+
+ }
+
+ else
+ {
+
+ // Use the specified hint matrix.
+
+ return Invert (hint * A) * hint;
+
+ }
+
+ }
+
+/*****************************************************************************/