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; }
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 Interpolate(double t1, double t2, double t, const dng_matrix &m1, const dng_matrix &m2) { double r1, r2, r; double t0; double g; int inv; int i, j; if(m1.IsEmpty()) return m2; if(m2.IsEmpty()) return m1; if((m1.Rows() != m2.Rows()) || (m1.Cols() != m2.Cols())) { ThrowMatrixMath("Interpolate of matrices of differerent sizes"); } if(t1 <= 1.0) return m2; if(t2 <= 1.0) return m1; inv=0; if(t2 < t1) { t0=t2; t2=t1; t1=t0; inv=1; } if(t <= t1) { if(inv) return m2; else return m1; } if(t >= t2) { if(inv) return m1; else return m2; } r1=1.0/t1; r2=1.0/t2; r=1.0/t; g=(r2-r)/(r2-r1); if(inv) g=1.0-g; dng_matrix m(m1.Rows(), m1.Cols()); for(i=0; i<m.Rows(); i++) { for(j=0; j<m.Cols(); j++) { m[i][j]=m1[i][j]*g+m2[i][j]*(1.0-g); } } m.Round(10000); return m; }
dng_vector_4::dng_vector_4 (const dng_vector &v) : dng_vector (v) { if (Count () != 4) { ThrowMatrixMath (); } }
dng_vector_3::dng_vector_3 (const dng_vector &v) : dng_vector (v) { if (Count () != 3) { ThrowMatrixMath (); } }
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; }
dng_matrix_4by3::dng_matrix_4by3 (const dng_matrix &m) : dng_matrix (m) { if (Rows () != 4 || Cols () != 3) { ThrowMatrixMath (); } }
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; } }
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; }