File indexing completed on 2025-01-19 03:55:05
0001 /*****************************************************************************/ 0002 // Copyright 2006-2019 Adobe Systems Incorporated 0003 // All Rights Reserved. 0004 // 0005 // NOTICE: Adobe permits you to use, modify, and distribute this file in 0006 // accordance with the terms of the Adobe license agreement accompanying it. 0007 /*****************************************************************************/ 0008 0009 #include "dng_matrix.h" 0010 0011 #include "dng_assertions.h" 0012 #include "dng_exceptions.h" 0013 #include "dng_utils.h" 0014 0015 /*****************************************************************************/ 0016 0017 dng_matrix::dng_matrix () 0018 0019 : fRows (0) 0020 , fCols (0) 0021 0022 { 0023 0024 } 0025 0026 /*****************************************************************************/ 0027 0028 dng_matrix::dng_matrix (uint32 rows, 0029 uint32 cols) 0030 0031 : fRows (0) 0032 , fCols (0) 0033 0034 { 0035 0036 if (rows < 1 || rows > kMaxColorPlanes || 0037 cols < 1 || cols > kMaxColorPlanes) 0038 { 0039 0040 ThrowProgramError (); 0041 0042 } 0043 0044 fRows = rows; 0045 fCols = cols; 0046 0047 for (uint32 row = 0; row < fRows; row++) 0048 for (uint32 col = 0; col < fCols; col++) 0049 { 0050 0051 fData [row] [col] = 0.0; 0052 0053 } 0054 0055 } 0056 0057 /*****************************************************************************/ 0058 0059 dng_matrix::dng_matrix (const dng_matrix &m) 0060 0061 : fRows (m.fRows) 0062 , fCols (m.fCols) 0063 0064 { 0065 0066 for (uint32 row = 0; row < fRows; row++) 0067 for (uint32 col = 0; col < fCols; col++) 0068 { 0069 0070 fData [row] [col] = m.fData [row] [col]; 0071 0072 } 0073 0074 } 0075 0076 /*****************************************************************************/ 0077 0078 void dng_matrix::Clear () 0079 { 0080 0081 fRows = 0; 0082 fCols = 0; 0083 0084 } 0085 0086 /*****************************************************************************/ 0087 0088 void dng_matrix::SetIdentity (uint32 count) 0089 { 0090 0091 *this = dng_matrix (count, count); 0092 0093 for (uint32 j = 0; j < count; j++) 0094 { 0095 0096 fData [j] [j] = 1.0; 0097 0098 } 0099 0100 } 0101 0102 /******************************************************************************/ 0103 0104 bool dng_matrix::operator== (const dng_matrix &m) const 0105 { 0106 0107 if (Rows () != m.Rows () || 0108 Cols () != m.Cols ()) 0109 { 0110 0111 return false; 0112 0113 } 0114 0115 for (uint32 j = 0; j < Rows (); j++) 0116 for (uint32 k = 0; k < Cols (); k++) 0117 { 0118 0119 if (fData [j] [k] != m.fData [j] [k]) 0120 { 0121 0122 return false; 0123 0124 } 0125 0126 } 0127 0128 return true; 0129 0130 } 0131 0132 /******************************************************************************/ 0133 0134 bool dng_matrix::IsDiagonal () const 0135 { 0136 0137 if (IsEmpty ()) 0138 { 0139 return false; 0140 } 0141 0142 if (Rows () != Cols ()) 0143 { 0144 return false; 0145 } 0146 0147 for (uint32 j = 0; j < Rows (); j++) 0148 for (uint32 k = 0; k < Cols (); k++) 0149 { 0150 0151 if (j != k) 0152 { 0153 0154 if (fData [j] [k] != 0.0) 0155 { 0156 return false; 0157 } 0158 0159 } 0160 0161 } 0162 0163 return true; 0164 0165 } 0166 0167 /******************************************************************************/ 0168 0169 bool dng_matrix::IsIdentity () const 0170 { 0171 0172 if (IsDiagonal ()) 0173 { 0174 0175 for (uint32 j = 0; j < Rows (); j++) 0176 { 0177 0178 if (fData [j] [j] != 1.0) 0179 { 0180 return false; 0181 } 0182 0183 } 0184 0185 return true; 0186 0187 } 0188 0189 return false; 0190 0191 } 0192 0193 /******************************************************************************/ 0194 0195 real64 dng_matrix::MaxEntry () const 0196 { 0197 0198 if (IsEmpty ()) 0199 { 0200 0201 return 0.0; 0202 0203 } 0204 0205 real64 m = fData [0] [0]; 0206 0207 for (uint32 j = 0; j < Rows (); j++) 0208 for (uint32 k = 0; k < Cols (); k++) 0209 { 0210 0211 m = Max_real64 (m, fData [j] [k]); 0212 0213 } 0214 0215 return m; 0216 0217 } 0218 0219 /******************************************************************************/ 0220 0221 real64 dng_matrix::MinEntry () const 0222 { 0223 0224 if (IsEmpty ()) 0225 { 0226 0227 return 0.0; 0228 0229 } 0230 0231 real64 m = fData [0] [0]; 0232 0233 for (uint32 j = 0; j < Rows (); j++) 0234 for (uint32 k = 0; k < Cols (); k++) 0235 { 0236 0237 m = Min_real64 (m, fData [j] [k]); 0238 0239 } 0240 0241 return m; 0242 0243 } 0244 0245 /*****************************************************************************/ 0246 0247 void dng_matrix::Scale (real64 factor) 0248 { 0249 0250 for (uint32 j = 0; j < Rows (); j++) 0251 for (uint32 k = 0; k < Cols (); k++) 0252 { 0253 0254 fData [j] [k] *= factor; 0255 0256 } 0257 0258 } 0259 0260 /*****************************************************************************/ 0261 0262 void dng_matrix::Round (real64 factor) 0263 { 0264 0265 real64 invFactor = 1.0 / factor; 0266 0267 for (uint32 j = 0; j < Rows (); j++) 0268 for (uint32 k = 0; k < Cols (); k++) 0269 { 0270 0271 fData [j] [k] = Round_int32 (fData [j] [k] * factor) * invFactor; 0272 0273 } 0274 0275 } 0276 0277 /*****************************************************************************/ 0278 0279 void dng_matrix::SafeRound (real64 factor) 0280 { 0281 0282 real64 invFactor = 1.0 / factor; 0283 0284 for (uint32 j = 0; j < Rows (); j++) 0285 { 0286 0287 // Round each row to the specified accuracy, but make sure the 0288 // a rounding does not affect the total of the elements in a row 0289 // more than necessary. 0290 0291 real64 error = 0.0; 0292 0293 for (uint32 k = 0; k < Cols (); k++) 0294 { 0295 0296 fData [j] [k] += error; 0297 0298 real64 rounded = Round_int32 (fData [j] [k] * factor) * invFactor; 0299 0300 error = fData [j] [k] - rounded; 0301 0302 fData [j] [k] = rounded; 0303 0304 } 0305 0306 } 0307 0308 } 0309 0310 /*****************************************************************************/ 0311 0312 bool dng_matrix::AlmostEqual (const dng_matrix &m, 0313 real64 slop) const 0314 { 0315 0316 if (Rows () != m.Rows () || 0317 Cols () != m.Cols ()) 0318 { 0319 return false; 0320 } 0321 0322 for (uint32 j = 0; j < Rows (); j++) 0323 { 0324 0325 for (uint32 k = 0; k < Cols (); k++) 0326 { 0327 0328 if (Abs_real64 (fData [j] [k] - m [j] [k]) > slop) 0329 { 0330 return false; 0331 } 0332 0333 } 0334 0335 } 0336 0337 return true; 0338 0339 } 0340 0341 /*****************************************************************************/ 0342 0343 bool dng_matrix::AlmostIdentity (real64 slop) const 0344 { 0345 0346 dng_matrix m; 0347 0348 m.SetIdentity (Rows ()); 0349 0350 return AlmostEqual (m, slop); 0351 0352 } 0353 0354 /*****************************************************************************/ 0355 0356 dng_matrix_3by3::dng_matrix_3by3 () 0357 0358 : dng_matrix (3, 3) 0359 0360 { 0361 } 0362 0363 /*****************************************************************************/ 0364 0365 dng_matrix_3by3::dng_matrix_3by3 (const dng_matrix &m) 0366 0367 : dng_matrix (m) 0368 0369 { 0370 0371 if (Rows () != 3 || 0372 Cols () != 3) 0373 { 0374 0375 ThrowMatrixMath (); 0376 0377 } 0378 0379 } 0380 0381 /*****************************************************************************/ 0382 0383 dng_matrix_3by3::dng_matrix_3by3 (real64 a00, real64 a01, real64 a02, 0384 real64 a10, real64 a11, real64 a12, 0385 real64 a20, real64 a21, real64 a22) 0386 0387 0388 : dng_matrix (3, 3) 0389 0390 { 0391 0392 fData [0] [0] = a00; 0393 fData [0] [1] = a01; 0394 fData [0] [2] = a02; 0395 0396 fData [1] [0] = a10; 0397 fData [1] [1] = a11; 0398 fData [1] [2] = a12; 0399 0400 fData [2] [0] = a20; 0401 fData [2] [1] = a21; 0402 fData [2] [2] = a22; 0403 0404 } 0405 0406 /*****************************************************************************/ 0407 0408 dng_matrix_3by3::dng_matrix_3by3 (real64 a00, real64 a11, real64 a22) 0409 0410 : dng_matrix (3, 3) 0411 0412 { 0413 0414 fData [0] [0] = a00; 0415 fData [1] [1] = a11; 0416 fData [2] [2] = a22; 0417 0418 } 0419 0420 /*****************************************************************************/ 0421 0422 dng_matrix_4by3::dng_matrix_4by3 () 0423 0424 : dng_matrix (4, 3) 0425 0426 { 0427 } 0428 0429 /*****************************************************************************/ 0430 0431 dng_matrix_4by3::dng_matrix_4by3 (const dng_matrix &m) 0432 0433 : dng_matrix (m) 0434 0435 { 0436 0437 if (Rows () != 4 || 0438 Cols () != 3) 0439 { 0440 0441 ThrowMatrixMath (); 0442 0443 } 0444 0445 } 0446 0447 /*****************************************************************************/ 0448 0449 dng_matrix_4by3::dng_matrix_4by3 (real64 a00, real64 a01, real64 a02, 0450 real64 a10, real64 a11, real64 a12, 0451 real64 a20, real64 a21, real64 a22, 0452 real64 a30, real64 a31, real64 a32) 0453 0454 0455 : dng_matrix (4, 3) 0456 0457 { 0458 0459 fData [0] [0] = a00; 0460 fData [0] [1] = a01; 0461 fData [0] [2] = a02; 0462 0463 fData [1] [0] = a10; 0464 fData [1] [1] = a11; 0465 fData [1] [2] = a12; 0466 0467 fData [2] [0] = a20; 0468 fData [2] [1] = a21; 0469 fData [2] [2] = a22; 0470 0471 fData [3] [0] = a30; 0472 fData [3] [1] = a31; 0473 fData [3] [2] = a32; 0474 0475 } 0476 0477 /*****************************************************************************/ 0478 0479 dng_matrix_4by4::dng_matrix_4by4 () 0480 0481 : dng_matrix (4, 4) 0482 0483 { 0484 0485 } 0486 0487 /*****************************************************************************/ 0488 0489 dng_matrix_4by4::dng_matrix_4by4 (const dng_matrix &m) 0490 0491 : dng_matrix (m) 0492 0493 { 0494 0495 // Input must be either 3x3 or 4x4. 0496 0497 const bool is3by3 = (m.Rows () == 3 && 0498 m.Cols () == 3); 0499 0500 const bool is4by4 = (m.Rows () == 4 && 0501 m.Cols () == 4); 0502 0503 if (!is3by3 && !is4by4) 0504 { 0505 0506 ThrowMatrixMath (); 0507 0508 } 0509 0510 // For 3x3 case, pad to 4x4 (equivalent 4x4 matrix). 0511 0512 if (is3by3) 0513 { 0514 0515 fRows = 4; 0516 fCols = 4; 0517 0518 fData [0] [3] = 0.0; 0519 fData [1] [3] = 0.0; 0520 fData [2] [3] = 0.0; 0521 0522 fData [3] [0] = 0.0; 0523 fData [3] [1] = 0.0; 0524 fData [3] [2] = 0.0; 0525 0526 fData [3] [3] = 1.0; 0527 0528 } 0529 0530 } 0531 0532 /*****************************************************************************/ 0533 0534 dng_matrix_4by4::dng_matrix_4by4 (real64 a00, real64 a01, real64 a02, real64 a03, 0535 real64 a10, real64 a11, real64 a12, real64 a13, 0536 real64 a20, real64 a21, real64 a22, real64 a23, 0537 real64 a30, real64 a31, real64 a32, real64 a33) 0538 0539 : dng_matrix (4, 4) 0540 0541 { 0542 0543 fData [0] [0] = a00; 0544 fData [0] [1] = a01; 0545 fData [0] [2] = a02; 0546 fData [0] [3] = a03; 0547 0548 fData [1] [0] = a10; 0549 fData [1] [1] = a11; 0550 fData [1] [2] = a12; 0551 fData [1] [3] = a13; 0552 0553 fData [2] [0] = a20; 0554 fData [2] [1] = a21; 0555 fData [2] [2] = a22; 0556 fData [2] [3] = a23; 0557 0558 fData [3] [0] = a30; 0559 fData [3] [1] = a31; 0560 fData [3] [2] = a32; 0561 fData [3] [3] = a33; 0562 0563 } 0564 0565 /*****************************************************************************/ 0566 0567 dng_matrix_4by4::dng_matrix_4by4 (real64 a00, 0568 real64 a11, 0569 real64 a22, 0570 real64 a33) 0571 0572 : dng_matrix (4, 4) 0573 0574 { 0575 0576 fData [0] [0] = a00; 0577 fData [1] [1] = a11; 0578 fData [2] [2] = a22; 0579 fData [3] [3] = a33; 0580 0581 } 0582 0583 /*****************************************************************************/ 0584 0585 dng_vector::dng_vector () 0586 0587 : fCount (0) 0588 0589 { 0590 0591 } 0592 0593 /*****************************************************************************/ 0594 0595 dng_vector::dng_vector (uint32 count) 0596 0597 : fCount (0) 0598 0599 { 0600 0601 if (count < 1 || count > kMaxColorPlanes) 0602 { 0603 0604 ThrowProgramError (); 0605 0606 } 0607 0608 fCount = count; 0609 0610 for (uint32 index = 0; index < fCount; index++) 0611 { 0612 0613 fData [index] = 0.0; 0614 0615 } 0616 0617 } 0618 0619 /*****************************************************************************/ 0620 0621 dng_vector::dng_vector (const dng_vector &v) 0622 0623 : fCount (v.fCount) 0624 0625 { 0626 0627 for (uint32 index = 0; index < fCount; index++) 0628 { 0629 0630 fData [index] = v.fData [index]; 0631 0632 } 0633 0634 } 0635 0636 /*****************************************************************************/ 0637 0638 void dng_vector::Clear () 0639 { 0640 0641 fCount = 0; 0642 0643 } 0644 0645 /*****************************************************************************/ 0646 0647 void dng_vector::SetIdentity (uint32 count) 0648 { 0649 0650 *this = dng_vector (count); 0651 0652 for (uint32 j = 0; j < count; j++) 0653 { 0654 0655 fData [j] = 1.0; 0656 0657 } 0658 0659 } 0660 0661 /******************************************************************************/ 0662 0663 bool dng_vector::operator== (const dng_vector &v) const 0664 { 0665 0666 if (Count () != v.Count ()) 0667 { 0668 0669 return false; 0670 0671 } 0672 0673 for (uint32 j = 0; j < Count (); j++) 0674 { 0675 0676 if (fData [j] != v.fData [j]) 0677 { 0678 0679 return false; 0680 0681 } 0682 0683 } 0684 0685 return true; 0686 0687 } 0688 0689 /******************************************************************************/ 0690 0691 real64 dng_vector::MaxEntry () const 0692 { 0693 0694 if (IsEmpty ()) 0695 { 0696 0697 return 0.0; 0698 0699 } 0700 0701 real64 m = fData [0]; 0702 0703 for (uint32 j = 0; j < Count (); j++) 0704 { 0705 0706 m = Max_real64 (m, fData [j]); 0707 0708 } 0709 0710 return m; 0711 0712 } 0713 0714 /******************************************************************************/ 0715 0716 real64 dng_vector::MinEntry () const 0717 { 0718 0719 if (IsEmpty ()) 0720 { 0721 0722 return 0.0; 0723 0724 } 0725 0726 real64 m = fData [0]; 0727 0728 for (uint32 j = 0; j < Count (); j++) 0729 { 0730 0731 m = Min_real64 (m, fData [j]); 0732 0733 } 0734 0735 return m; 0736 0737 } 0738 0739 /*****************************************************************************/ 0740 0741 void dng_vector::Scale (real64 factor) 0742 { 0743 0744 for (uint32 j = 0; j < Count (); j++) 0745 { 0746 0747 fData [j] *= factor; 0748 0749 } 0750 0751 } 0752 0753 /*****************************************************************************/ 0754 0755 void dng_vector::Round (real64 factor) 0756 { 0757 0758 real64 invFactor = 1.0 / factor; 0759 0760 for (uint32 j = 0; j < Count (); j++) 0761 { 0762 0763 fData [j] = Round_int32 (fData [j] * factor) * invFactor; 0764 0765 } 0766 0767 } 0768 0769 /*****************************************************************************/ 0770 0771 dng_matrix dng_vector::AsDiagonal () const 0772 { 0773 0774 dng_matrix M (Count (), Count ()); 0775 0776 for (uint32 j = 0; j < Count (); j++) 0777 { 0778 0779 M [j] [j] = fData [j]; 0780 0781 } 0782 0783 return M; 0784 0785 } 0786 0787 /*****************************************************************************/ 0788 0789 dng_matrix dng_vector::AsColumn () const 0790 { 0791 0792 dng_matrix M (Count (), 1); 0793 0794 for (uint32 j = 0; j < Count (); j++) 0795 { 0796 0797 M [j] [0] = fData [j]; 0798 0799 } 0800 0801 return M; 0802 0803 } 0804 0805 /******************************************************************************/ 0806 0807 dng_vector_3::dng_vector_3 () 0808 0809 : dng_vector (3) 0810 0811 { 0812 } 0813 0814 /******************************************************************************/ 0815 0816 dng_vector_3::dng_vector_3 (const dng_vector &v) 0817 0818 : dng_vector (v) 0819 0820 { 0821 0822 if (Count () != 3) 0823 { 0824 0825 ThrowMatrixMath (); 0826 0827 } 0828 0829 } 0830 0831 /******************************************************************************/ 0832 0833 dng_vector_3::dng_vector_3 (real64 a0, 0834 real64 a1, 0835 real64 a2) 0836 0837 : dng_vector (3) 0838 0839 { 0840 0841 fData [0] = a0; 0842 fData [1] = a1; 0843 fData [2] = a2; 0844 0845 } 0846 0847 /******************************************************************************/ 0848 0849 dng_vector_4::dng_vector_4 () 0850 0851 : dng_vector (4) 0852 0853 { 0854 } 0855 0856 /******************************************************************************/ 0857 0858 dng_vector_4::dng_vector_4 (const dng_vector &v) 0859 0860 : dng_vector (v) 0861 0862 { 0863 0864 if (Count () != 4) 0865 { 0866 0867 ThrowMatrixMath (); 0868 0869 } 0870 0871 } 0872 0873 /******************************************************************************/ 0874 0875 dng_vector_4::dng_vector_4 (real64 a0, 0876 real64 a1, 0877 real64 a2, 0878 real64 a3) 0879 0880 : dng_vector (4) 0881 0882 { 0883 0884 fData [0] = a0; 0885 fData [1] = a1; 0886 fData [2] = a2; 0887 fData [3] = a3; 0888 0889 } 0890 0891 /******************************************************************************/ 0892 0893 dng_matrix operator* (const dng_matrix &A, 0894 const dng_matrix &B) 0895 { 0896 0897 if (A.Cols () != B.Rows ()) 0898 { 0899 0900 ThrowMatrixMath (); 0901 0902 } 0903 0904 dng_matrix C (A.Rows (), B.Cols ()); 0905 0906 for (uint32 j = 0; j < C.Rows (); j++) 0907 for (uint32 k = 0; k < C.Cols (); k++) 0908 { 0909 0910 C [j] [k] = 0.0; 0911 0912 for (uint32 m = 0; m < A.Cols (); m++) 0913 { 0914 0915 real64 aa = A [j] [m]; 0916 0917 real64 bb = B [m] [k]; 0918 0919 C [j] [k] += aa * bb; 0920 0921 } 0922 0923 } 0924 0925 return C; 0926 0927 } 0928 0929 /******************************************************************************/ 0930 0931 dng_vector operator* (const dng_matrix &A, 0932 const dng_vector &B) 0933 { 0934 0935 if (A.Cols () != B.Count ()) 0936 { 0937 0938 ThrowMatrixMath (); 0939 0940 } 0941 0942 dng_vector C (A.Rows ()); 0943 0944 for (uint32 j = 0; j < C.Count (); j++) 0945 { 0946 0947 C [j] = 0.0; 0948 0949 for (uint32 m = 0; m < A.Cols (); m++) 0950 { 0951 0952 real64 aa = A [j] [m]; 0953 0954 real64 bb = B [m]; 0955 0956 C [j] += aa * bb; 0957 0958 } 0959 0960 } 0961 0962 return C; 0963 0964 } 0965 0966 /******************************************************************************/ 0967 0968 dng_matrix operator* (real64 scale, 0969 const dng_matrix &A) 0970 { 0971 0972 dng_matrix B (A); 0973 0974 B.Scale (scale); 0975 0976 return B; 0977 0978 } 0979 0980 /******************************************************************************/ 0981 0982 dng_vector operator* (real64 scale, 0983 const dng_vector &A) 0984 { 0985 0986 dng_vector B (A); 0987 0988 B.Scale (scale); 0989 0990 return B; 0991 0992 } 0993 0994 /******************************************************************************/ 0995 0996 dng_matrix operator+ (const dng_matrix &A, 0997 const dng_matrix &B) 0998 { 0999 1000 if (A.Cols () != B.Cols () || 1001 A.Rows () != B.Rows ()) 1002 { 1003 1004 ThrowMatrixMath (); 1005 1006 } 1007 1008 dng_matrix C (A); 1009 1010 for (uint32 j = 0; j < C.Rows (); j++) 1011 for (uint32 k = 0; k < C.Cols (); k++) 1012 { 1013 1014 C [j] [k] += B [j] [k]; 1015 1016 } 1017 1018 return C; 1019 1020 } 1021 1022 /******************************************************************************/ 1023 1024 dng_vector operator- (const dng_vector &a, 1025 const dng_vector &b) 1026 { 1027 1028 uint32 count = a.Count (); 1029 1030 DNG_REQUIRE (count == b.Count (), 1031 "Mismatch count in Dot"); 1032 1033 if (!count) 1034 { 1035 return dng_vector (); 1036 } 1037 1038 dng_vector result (count); 1039 1040 for (uint32 i = 0; i < count; i++) 1041 { 1042 1043 result [i] = a [i] - b [i]; 1044 1045 } 1046 1047 return result; 1048 1049 } 1050 1051 /******************************************************************************/ 1052 1053 const real64 kNearZero = 1.0E-10; 1054 1055 /******************************************************************************/ 1056 1057 // Work around bug #1294195, which may be a hardware problem on a specific machine. 1058 // This pragma turns on "improved" floating-point consistency. 1059 #ifdef _MSC_VER 1060 #pragma optimize ("p", on) 1061 #endif 1062 1063 static dng_matrix Invert3by3 (const dng_matrix &A) 1064 { 1065 1066 real64 a00 = A [0] [0]; 1067 real64 a01 = A [0] [1]; 1068 real64 a02 = A [0] [2]; 1069 real64 a10 = A [1] [0]; 1070 real64 a11 = A [1] [1]; 1071 real64 a12 = A [1] [2]; 1072 real64 a20 = A [2] [0]; 1073 real64 a21 = A [2] [1]; 1074 real64 a22 = A [2] [2]; 1075 1076 real64 temp [3] [3]; 1077 1078 temp [0] [0] = a11 * a22 - a21 * a12; 1079 temp [0] [1] = a21 * a02 - a01 * a22; 1080 temp [0] [2] = a01 * a12 - a11 * a02; 1081 temp [1] [0] = a20 * a12 - a10 * a22; 1082 temp [1] [1] = a00 * a22 - a20 * a02; 1083 temp [1] [2] = a10 * a02 - a00 * a12; 1084 temp [2] [0] = a10 * a21 - a20 * a11; 1085 temp [2] [1] = a20 * a01 - a00 * a21; 1086 temp [2] [2] = a00 * a11 - a10 * a01; 1087 1088 real64 det = (a00 * temp [0] [0] + 1089 a01 * temp [1] [0] + 1090 a02 * temp [2] [0]); 1091 1092 if (Abs_real64 (det) < kNearZero) 1093 { 1094 1095 ThrowMatrixMath (); 1096 1097 } 1098 1099 dng_matrix B (3, 3); 1100 1101 for (uint32 j = 0; j < 3; j++) 1102 for (uint32 k = 0; k < 3; k++) 1103 { 1104 1105 B [j] [k] = temp [j] [k] / det; 1106 1107 } 1108 1109 return B; 1110 1111 } 1112 1113 // Reset floating-point optimization. See comment above. 1114 #ifdef _MSC_VER 1115 #pragma optimize ("p", off) 1116 #endif 1117 1118 /******************************************************************************/ 1119 1120 static dng_matrix InvertNbyN (const dng_matrix &A) 1121 { 1122 1123 uint32 i; 1124 uint32 j; 1125 uint32 k; 1126 1127 const uint32 n = A.Rows (); 1128 1129 const uint32 augmented_cols = 2 * n; 1130 1131 real64 temp [kMaxColorPlanes] [kMaxColorPlanes * 2]; 1132 1133 memset (temp, 0, sizeof (temp)); 1134 1135 for (i = 0; i < n; i++) 1136 for (j = 0; j < n; j++) 1137 { 1138 1139 temp [i] [j ] = A [i] [j]; 1140 1141 temp [i] [j + n] = (i == j ? 1.0 : 0.0); 1142 1143 } 1144 1145 for (i = 0; i < n; i++) 1146 { 1147 1148 // Find row iMax with largest absolute entry in column i. 1149 1150 uint32 iMax = i; 1151 real64 vMax = -1.0; 1152 1153 for (k = i; k < n; k++) 1154 { 1155 1156 real64 v = Abs_real64 (A [k] [i]); 1157 1158 if (v > vMax) 1159 { 1160 vMax = v; 1161 iMax = k; 1162 } 1163 1164 } 1165 1166 real64 alpha = temp [iMax] [i]; 1167 1168 if (Abs_real64 (alpha) < kNearZero) 1169 { 1170 1171 ThrowMatrixMath (); 1172 1173 } 1174 1175 // Swap rows i and iMax, column by column. 1176 1177 if (i != iMax) 1178 { 1179 1180 for (j = 0; j < augmented_cols; j++) 1181 { 1182 1183 std::swap (temp [i ] [j], 1184 temp [iMax] [j]); 1185 1186 } 1187 1188 } 1189 1190 for (j = 0; j < augmented_cols; j++) 1191 { 1192 1193 temp [i] [j] /= alpha; 1194 1195 } 1196 1197 for (k = 0; k < n; k++) 1198 { 1199 1200 if (i != k) 1201 { 1202 1203 real64 beta = temp [k] [i]; 1204 1205 for (j = 0; j < augmented_cols; j++) 1206 { 1207 1208 temp [k] [j] -= beta * temp [i] [j]; 1209 1210 } 1211 1212 } 1213 1214 } 1215 1216 } 1217 1218 dng_matrix B (n, n); 1219 1220 for (i = 0; i < n; i++) 1221 for (j = 0; j < n; j++) 1222 { 1223 1224 B [i] [j] = temp [i] [j + n]; 1225 1226 } 1227 1228 return B; 1229 1230 } 1231 1232 /******************************************************************************/ 1233 1234 dng_matrix Transpose (const dng_matrix &A) 1235 { 1236 1237 dng_matrix B (A.Cols (), A.Rows ()); 1238 1239 for (uint32 j = 0; j < B.Rows (); j++) 1240 for (uint32 k = 0; k < B.Cols (); k++) 1241 { 1242 1243 B [j] [k] = A [k] [j]; 1244 1245 } 1246 1247 return B; 1248 1249 } 1250 1251 /******************************************************************************/ 1252 1253 dng_matrix Invert (const dng_matrix &A) 1254 { 1255 1256 if (A.Rows () < 2 || A.Cols () < 2) 1257 { 1258 1259 ThrowMatrixMath (); 1260 1261 } 1262 1263 if (A.Rows () == A.Cols ()) 1264 { 1265 1266 if (A.Rows () == 3) 1267 { 1268 1269 return Invert3by3 (A); 1270 1271 } 1272 1273 return InvertNbyN (A); 1274 1275 } 1276 1277 else 1278 { 1279 1280 // Compute the pseudo inverse. 1281 1282 dng_matrix B = Transpose (A); 1283 1284 return Invert (B * A) * B; 1285 1286 } 1287 1288 } 1289 1290 /******************************************************************************/ 1291 1292 dng_matrix Invert (const dng_matrix &A, 1293 const dng_matrix &hint) 1294 { 1295 1296 if (A.Rows () == A .Cols () || 1297 A.Rows () != hint.Cols () || 1298 A.Cols () != hint.Rows ()) 1299 { 1300 1301 return Invert (A); 1302 1303 } 1304 1305 else 1306 { 1307 1308 // Use the specified hint matrix. 1309 1310 return Invert (hint * A) * hint; 1311 1312 } 1313 1314 } 1315 1316 /*****************************************************************************/ 1317 1318 real64 Dot (const dng_vector &a, 1319 const dng_vector &b) 1320 { 1321 1322 DNG_REQUIRE (a.Count () == b.Count (), 1323 "Cannot take dot product between vectors of different size."); 1324 1325 // DNG_REQUIRE (a.Count () > 0, 1326 // "Cannot take dot product with an empty vector."); 1327 1328 real64 sum = 0.0; 1329 1330 for (uint32 j = 0; j < a.Count (); j++) 1331 { 1332 1333 sum += (a [j] * b [j]); 1334 1335 } 1336 1337 return sum; 1338 1339 } 1340 1341 /*****************************************************************************/ 1342 1343 real64 Distance (const dng_vector &a, 1344 const dng_vector &b) 1345 { 1346 1347 dng_vector c = a - b; 1348 1349 return sqrt (Dot (c, c)); 1350 1351 } 1352 1353 /*****************************************************************************/