/src/dng_sdk/source/dng_matrix.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /*****************************************************************************/ |
2 | | // Copyright 2006-2008 Adobe Systems Incorporated |
3 | | // All Rights Reserved. |
4 | | // |
5 | | // NOTICE: Adobe permits you to use, modify, and distribute this file in |
6 | | // accordance with the terms of the Adobe license agreement accompanying it. |
7 | | /*****************************************************************************/ |
8 | | |
9 | | /* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_matrix.cpp#1 $ */ |
10 | | /* $DateTime: 2012/05/30 13:28:51 $ */ |
11 | | /* $Change: 832332 $ */ |
12 | | /* $Author: tknoll $ */ |
13 | | |
14 | | /*****************************************************************************/ |
15 | | |
16 | | #include "dng_matrix.h" |
17 | | |
18 | | #include "dng_exceptions.h" |
19 | | #include "dng_utils.h" |
20 | | |
21 | | /*****************************************************************************/ |
22 | | |
23 | | dng_matrix::dng_matrix () |
24 | | |
25 | 51.7M | : fRows (0) |
26 | 51.7M | , fCols (0) |
27 | | |
28 | 51.7M | { |
29 | | |
30 | 51.7M | } |
31 | | |
32 | | /*****************************************************************************/ |
33 | | |
34 | | dng_matrix::dng_matrix (uint32 rows, |
35 | | uint32 cols) |
36 | | |
37 | 363k | : fRows (0) |
38 | 363k | , fCols (0) |
39 | | |
40 | 363k | { |
41 | | |
42 | 363k | if (rows < 1 || rows > kMaxColorPlanes || |
43 | 363k | cols < 1 || cols > kMaxColorPlanes) |
44 | 0 | { |
45 | | |
46 | 0 | ThrowProgramError (); |
47 | | |
48 | 0 | } |
49 | | |
50 | 363k | fRows = rows; |
51 | 363k | fCols = cols; |
52 | | |
53 | 1.43M | for (uint32 row = 0; row < fRows; row++) |
54 | 4.49M | for (uint32 col = 0; col < fCols; col++) |
55 | 3.42M | { |
56 | | |
57 | 3.42M | fData [row] [col] = 0.0; |
58 | | |
59 | 3.42M | } |
60 | | |
61 | 363k | } |
62 | | |
63 | | /*****************************************************************************/ |
64 | | |
65 | | dng_matrix::dng_matrix (const dng_matrix &m) |
66 | | |
67 | 2.46M | : fRows (m.fRows) |
68 | 2.46M | , fCols (m.fCols) |
69 | | |
70 | 2.46M | { |
71 | | |
72 | 3.07M | for (uint32 row = 0; row < fRows; row++) |
73 | 2.85M | for (uint32 col = 0; col < fCols; col++) |
74 | 2.24M | { |
75 | | |
76 | 2.24M | fData [row] [col] = m.fData [row] [col]; |
77 | | |
78 | 2.24M | } |
79 | | |
80 | 2.46M | } |
81 | | |
82 | | /*****************************************************************************/ |
83 | | |
84 | | void dng_matrix::Clear () |
85 | 3.23k | { |
86 | | |
87 | 3.23k | fRows = 0; |
88 | 3.23k | fCols = 0; |
89 | | |
90 | 3.23k | } |
91 | | |
92 | | /*****************************************************************************/ |
93 | | |
94 | | void dng_matrix::SetIdentity (uint32 count) |
95 | 2.35k | { |
96 | | |
97 | 2.35k | *this = dng_matrix (count, count); |
98 | | |
99 | 9.76k | for (uint32 j = 0; j < count; j++) |
100 | 7.40k | { |
101 | | |
102 | 7.40k | fData [j] [j] = 1.0; |
103 | | |
104 | 7.40k | } |
105 | | |
106 | 2.35k | } |
107 | | |
108 | | /******************************************************************************/ |
109 | | |
110 | | bool dng_matrix::operator== (const dng_matrix &m) const |
111 | 455k | { |
112 | | |
113 | 455k | if (Rows () != m.Rows () || |
114 | 455k | Cols () != m.Cols ()) |
115 | 14.4k | { |
116 | | |
117 | 14.4k | return false; |
118 | | |
119 | 14.4k | } |
120 | | |
121 | 729k | for (uint32 j = 0; j < Rows (); j++) |
122 | 1.16M | for (uint32 k = 0; k < Cols (); k++) |
123 | 874k | { |
124 | | |
125 | 874k | if (fData [j] [k] != m.fData [j] [k]) |
126 | 8.75k | { |
127 | | |
128 | 8.75k | return false; |
129 | | |
130 | 8.75k | } |
131 | | |
132 | 874k | } |
133 | | |
134 | 432k | return true; |
135 | | |
136 | 441k | } |
137 | | |
138 | | /******************************************************************************/ |
139 | | |
140 | | bool dng_matrix::IsDiagonal () const |
141 | 0 | { |
142 | | |
143 | 0 | if (IsEmpty ()) |
144 | 0 | { |
145 | 0 | return false; |
146 | 0 | } |
147 | | |
148 | 0 | if (Rows () != Cols ()) |
149 | 0 | { |
150 | 0 | return false; |
151 | 0 | } |
152 | | |
153 | 0 | for (uint32 j = 0; j < Rows (); j++) |
154 | 0 | for (uint32 k = 0; k < Cols (); k++) |
155 | 0 | { |
156 | | |
157 | 0 | if (j != k) |
158 | 0 | { |
159 | | |
160 | 0 | if (fData [j] [k] != 0.0) |
161 | 0 | { |
162 | 0 | return false; |
163 | 0 | } |
164 | | |
165 | 0 | } |
166 | | |
167 | 0 | } |
168 | | |
169 | 0 | return true; |
170 | | |
171 | 0 | } |
172 | | |
173 | | /******************************************************************************/ |
174 | | |
175 | | real64 dng_matrix::MaxEntry () const |
176 | 0 | { |
177 | | |
178 | 0 | if (IsEmpty ()) |
179 | 0 | { |
180 | | |
181 | 0 | return 0.0; |
182 | | |
183 | 0 | } |
184 | | |
185 | 0 | real64 m = fData [0] [0]; |
186 | | |
187 | 0 | for (uint32 j = 0; j < Rows (); j++) |
188 | 0 | for (uint32 k = 0; k < Cols (); k++) |
189 | 0 | { |
190 | | |
191 | 0 | m = Max_real64 (m, fData [j] [k]); |
192 | | |
193 | 0 | } |
194 | | |
195 | 0 | return m; |
196 | | |
197 | 0 | } |
198 | | |
199 | | /******************************************************************************/ |
200 | | |
201 | | real64 dng_matrix::MinEntry () const |
202 | 0 | { |
203 | | |
204 | 0 | if (IsEmpty ()) |
205 | 0 | { |
206 | | |
207 | 0 | return 0.0; |
208 | | |
209 | 0 | } |
210 | | |
211 | 0 | real64 m = fData [0] [0]; |
212 | | |
213 | 0 | for (uint32 j = 0; j < Rows (); j++) |
214 | 0 | for (uint32 k = 0; k < Cols (); k++) |
215 | 0 | { |
216 | | |
217 | 0 | m = Min_real64 (m, fData [j] [k]); |
218 | | |
219 | 0 | } |
220 | | |
221 | 0 | return m; |
222 | | |
223 | 0 | } |
224 | | |
225 | | /*****************************************************************************/ |
226 | | |
227 | | void dng_matrix::Scale (real64 factor) |
228 | 48.7k | { |
229 | | |
230 | 194k | for (uint32 j = 0; j < Rows (); j++) |
231 | 583k | for (uint32 k = 0; k < Cols (); k++) |
232 | 437k | { |
233 | | |
234 | 437k | fData [j] [k] *= factor; |
235 | | |
236 | 437k | } |
237 | | |
238 | 48.7k | } |
239 | | |
240 | | /*****************************************************************************/ |
241 | | |
242 | | void dng_matrix::Round (real64 factor) |
243 | 72.0k | { |
244 | | |
245 | 72.0k | real64 invFactor = 1.0 / factor; |
246 | | |
247 | 280k | for (uint32 j = 0; j < Rows (); j++) |
248 | 831k | for (uint32 k = 0; k < Cols (); k++) |
249 | 622k | { |
250 | | |
251 | 622k | fData [j] [k] = Round_int32 (fData [j] [k] * factor) * invFactor; |
252 | | |
253 | 622k | } |
254 | | |
255 | 72.0k | } |
256 | | |
257 | | /*****************************************************************************/ |
258 | | |
259 | | void dng_matrix::SafeRound (real64 factor) |
260 | 0 | { |
261 | | |
262 | 0 | real64 invFactor = 1.0 / factor; |
263 | | |
264 | 0 | for (uint32 j = 0; j < Rows (); j++) |
265 | 0 | { |
266 | | |
267 | | // Round each row to the specified accuracy, but make sure the |
268 | | // a rounding does not affect the total of the elements in a row |
269 | | // more than necessary. |
270 | | |
271 | 0 | real64 error = 0.0; |
272 | | |
273 | 0 | for (uint32 k = 0; k < Cols (); k++) |
274 | 0 | { |
275 | | |
276 | 0 | fData [j] [k] += error; |
277 | | |
278 | 0 | real64 rounded = Round_int32 (fData [j] [k] * factor) * invFactor; |
279 | | |
280 | 0 | error = fData [j] [k] - rounded; |
281 | | |
282 | 0 | fData [j] [k] = rounded; |
283 | | |
284 | 0 | } |
285 | | |
286 | 0 | } |
287 | | |
288 | 0 | } |
289 | | |
290 | | /*****************************************************************************/ |
291 | | |
292 | | dng_matrix_3by3::dng_matrix_3by3 () |
293 | | |
294 | 1.17k | : dng_matrix (3, 3) |
295 | | |
296 | 1.17k | { |
297 | 1.17k | } |
298 | | |
299 | | /*****************************************************************************/ |
300 | | |
301 | | dng_matrix_3by3::dng_matrix_3by3 (const dng_matrix &m) |
302 | | |
303 | 1.17k | : dng_matrix (m) |
304 | | |
305 | 1.17k | { |
306 | | |
307 | 1.17k | if (Rows () != 3 || |
308 | 1.17k | Cols () != 3) |
309 | 0 | { |
310 | | |
311 | 0 | ThrowMatrixMath (); |
312 | | |
313 | 0 | } |
314 | | |
315 | 1.17k | } |
316 | | |
317 | | /*****************************************************************************/ |
318 | | |
319 | | dng_matrix_3by3::dng_matrix_3by3 (real64 a00, real64 a01, real64 a02, |
320 | | real64 a10, real64 a11, real64 a12, |
321 | | real64 a20, real64 a21, real64 a22) |
322 | | |
323 | | |
324 | 1.18k | : dng_matrix (3, 3) |
325 | | |
326 | 1.18k | { |
327 | | |
328 | 1.18k | fData [0] [0] = a00; |
329 | 1.18k | fData [0] [1] = a01; |
330 | 1.18k | fData [0] [2] = a02; |
331 | | |
332 | 1.18k | fData [1] [0] = a10; |
333 | 1.18k | fData [1] [1] = a11; |
334 | 1.18k | fData [1] [2] = a12; |
335 | | |
336 | 1.18k | fData [2] [0] = a20; |
337 | 1.18k | fData [2] [1] = a21; |
338 | 1.18k | fData [2] [2] = a22; |
339 | | |
340 | 1.18k | } |
341 | | |
342 | | /*****************************************************************************/ |
343 | | |
344 | | dng_matrix_3by3::dng_matrix_3by3 (real64 a00, real64 a11, real64 a22) |
345 | | |
346 | 0 | : dng_matrix (3, 3) |
347 | | |
348 | 0 | { |
349 | | |
350 | 0 | fData [0] [0] = a00; |
351 | 0 | fData [1] [1] = a11; |
352 | 0 | fData [2] [2] = a22; |
353 | | |
354 | 0 | } |
355 | | |
356 | | /*****************************************************************************/ |
357 | | |
358 | | dng_matrix_4by3::dng_matrix_4by3 () |
359 | | |
360 | 0 | : dng_matrix (4, 3) |
361 | | |
362 | 0 | { |
363 | 0 | } |
364 | | |
365 | | /*****************************************************************************/ |
366 | | |
367 | | dng_matrix_4by3::dng_matrix_4by3 (const dng_matrix &m) |
368 | | |
369 | 0 | : dng_matrix (m) |
370 | | |
371 | 0 | { |
372 | | |
373 | 0 | if (Rows () != 4 || |
374 | 0 | Cols () != 3) |
375 | 0 | { |
376 | | |
377 | 0 | ThrowMatrixMath (); |
378 | | |
379 | 0 | } |
380 | | |
381 | 0 | } |
382 | | |
383 | | /*****************************************************************************/ |
384 | | |
385 | | dng_matrix_4by3::dng_matrix_4by3 (real64 a00, real64 a01, real64 a02, |
386 | | real64 a10, real64 a11, real64 a12, |
387 | | real64 a20, real64 a21, real64 a22, |
388 | | real64 a30, real64 a31, real64 a32) |
389 | | |
390 | | |
391 | 0 | : dng_matrix (4, 3) |
392 | | |
393 | 0 | { |
394 | | |
395 | 0 | fData [0] [0] = a00; |
396 | 0 | fData [0] [1] = a01; |
397 | 0 | fData [0] [2] = a02; |
398 | | |
399 | 0 | fData [1] [0] = a10; |
400 | 0 | fData [1] [1] = a11; |
401 | 0 | fData [1] [2] = a12; |
402 | | |
403 | 0 | fData [2] [0] = a20; |
404 | 0 | fData [2] [1] = a21; |
405 | 0 | fData [2] [2] = a22; |
406 | | |
407 | 0 | fData [3] [0] = a30; |
408 | 0 | fData [3] [1] = a31; |
409 | 0 | fData [3] [2] = a32; |
410 | | |
411 | 0 | } |
412 | | |
413 | | /*****************************************************************************/ |
414 | | |
415 | | dng_vector::dng_vector () |
416 | | |
417 | 383k | : fCount (0) |
418 | | |
419 | 383k | { |
420 | | |
421 | 383k | } |
422 | | |
423 | | /*****************************************************************************/ |
424 | | |
425 | | dng_vector::dng_vector (uint32 count) |
426 | | |
427 | 171k | : fCount (0) |
428 | | |
429 | 171k | { |
430 | | |
431 | 171k | if (count < 1 || count > kMaxColorPlanes) |
432 | 0 | { |
433 | | |
434 | 0 | ThrowProgramError (); |
435 | | |
436 | 0 | } |
437 | | |
438 | 171k | fCount = count; |
439 | | |
440 | 686k | for (uint32 index = 0; index < fCount; index++) |
441 | 514k | { |
442 | | |
443 | 514k | fData [index] = 0.0; |
444 | | |
445 | 514k | } |
446 | | |
447 | 171k | } |
448 | | |
449 | | /*****************************************************************************/ |
450 | | |
451 | | dng_vector::dng_vector (const dng_vector &v) |
452 | | |
453 | 8.54k | : fCount (v.fCount) |
454 | | |
455 | 8.54k | { |
456 | | |
457 | 34.1k | for (uint32 index = 0; index < fCount; index++) |
458 | 25.6k | { |
459 | | |
460 | 25.6k | fData [index] = v.fData [index]; |
461 | | |
462 | 25.6k | } |
463 | | |
464 | 8.54k | } |
465 | | |
466 | | /*****************************************************************************/ |
467 | | |
468 | | void dng_vector::Clear () |
469 | 5.54k | { |
470 | | |
471 | 5.54k | fCount = 0; |
472 | | |
473 | 5.54k | } |
474 | | |
475 | | /*****************************************************************************/ |
476 | | |
477 | | void dng_vector::SetIdentity (uint32 count) |
478 | 6.00k | { |
479 | | |
480 | 6.00k | *this = dng_vector (count); |
481 | | |
482 | 24.0k | for (uint32 j = 0; j < count; j++) |
483 | 18.0k | { |
484 | | |
485 | 18.0k | fData [j] = 1.0; |
486 | | |
487 | 18.0k | } |
488 | | |
489 | 6.00k | } |
490 | | |
491 | | /******************************************************************************/ |
492 | | |
493 | | bool dng_vector::operator== (const dng_vector &v) const |
494 | 0 | { |
495 | | |
496 | 0 | if (Count () != v.Count ()) |
497 | 0 | { |
498 | | |
499 | 0 | return false; |
500 | | |
501 | 0 | } |
502 | | |
503 | 0 | for (uint32 j = 0; j < Count (); j++) |
504 | 0 | { |
505 | | |
506 | 0 | if (fData [j] != v.fData [j]) |
507 | 0 | { |
508 | | |
509 | 0 | return false; |
510 | | |
511 | 0 | } |
512 | | |
513 | 0 | } |
514 | | |
515 | 0 | return true; |
516 | | |
517 | 0 | } |
518 | | |
519 | | /******************************************************************************/ |
520 | | |
521 | | real64 dng_vector::MaxEntry () const |
522 | 65.2k | { |
523 | | |
524 | 65.2k | if (IsEmpty ()) |
525 | 0 | { |
526 | | |
527 | 0 | return 0.0; |
528 | | |
529 | 0 | } |
530 | | |
531 | 65.2k | real64 m = fData [0]; |
532 | | |
533 | 259k | for (uint32 j = 0; j < Count (); j++) |
534 | 193k | { |
535 | | |
536 | 193k | m = Max_real64 (m, fData [j]); |
537 | | |
538 | 193k | } |
539 | | |
540 | 65.2k | return m; |
541 | | |
542 | 65.2k | } |
543 | | |
544 | | /******************************************************************************/ |
545 | | |
546 | | real64 dng_vector::MinEntry () const |
547 | 6.20k | { |
548 | | |
549 | 6.20k | if (IsEmpty ()) |
550 | 0 | { |
551 | | |
552 | 0 | return 0.0; |
553 | | |
554 | 0 | } |
555 | | |
556 | 6.20k | real64 m = fData [0]; |
557 | | |
558 | 24.7k | for (uint32 j = 0; j < Count (); j++) |
559 | 18.5k | { |
560 | | |
561 | 18.5k | m = Min_real64 (m, fData [j]); |
562 | | |
563 | 18.5k | } |
564 | | |
565 | 6.20k | return m; |
566 | | |
567 | 6.20k | } |
568 | | |
569 | | /*****************************************************************************/ |
570 | | |
571 | | void dng_vector::Scale (real64 factor) |
572 | 4.49k | { |
573 | | |
574 | 17.8k | for (uint32 j = 0; j < Count (); j++) |
575 | 13.3k | { |
576 | | |
577 | 13.3k | fData [j] *= factor; |
578 | | |
579 | 13.3k | } |
580 | | |
581 | 4.49k | } |
582 | | |
583 | | /*****************************************************************************/ |
584 | | |
585 | | void dng_vector::Round (real64 factor) |
586 | 4.49k | { |
587 | | |
588 | 4.49k | real64 invFactor = 1.0 / factor; |
589 | | |
590 | 17.8k | for (uint32 j = 0; j < Count (); j++) |
591 | 13.3k | { |
592 | | |
593 | 13.3k | fData [j] = Round_int32 (fData [j] * factor) * invFactor; |
594 | | |
595 | 13.3k | } |
596 | | |
597 | 4.49k | } |
598 | | |
599 | | /*****************************************************************************/ |
600 | | |
601 | | dng_matrix dng_vector::AsDiagonal () const |
602 | 6.65k | { |
603 | | |
604 | 6.65k | dng_matrix M (Count (), Count ()); |
605 | | |
606 | 26.5k | for (uint32 j = 0; j < Count (); j++) |
607 | 19.8k | { |
608 | | |
609 | 19.8k | M [j] [j] = fData [j]; |
610 | | |
611 | 19.8k | } |
612 | | |
613 | 6.65k | return M; |
614 | | |
615 | 6.65k | } |
616 | | |
617 | | /*****************************************************************************/ |
618 | | |
619 | | dng_matrix dng_vector::AsColumn () const |
620 | 3 | { |
621 | | |
622 | 3 | dng_matrix M (Count (), 1); |
623 | | |
624 | 12 | for (uint32 j = 0; j < Count (); j++) |
625 | 9 | { |
626 | | |
627 | 9 | M [j] [0] = fData [j]; |
628 | | |
629 | 9 | } |
630 | | |
631 | 3 | return M; |
632 | | |
633 | 3 | } |
634 | | |
635 | | /******************************************************************************/ |
636 | | |
637 | | dng_vector_3::dng_vector_3 () |
638 | | |
639 | 0 | : dng_vector (3) |
640 | | |
641 | 0 | { |
642 | 0 | } |
643 | | |
644 | | /******************************************************************************/ |
645 | | |
646 | | dng_vector_3::dng_vector_3 (const dng_vector &v) |
647 | | |
648 | 2.54k | : dng_vector (v) |
649 | | |
650 | 2.54k | { |
651 | | |
652 | 2.54k | if (Count () != 3) |
653 | 0 | { |
654 | | |
655 | 0 | ThrowMatrixMath (); |
656 | | |
657 | 0 | } |
658 | | |
659 | 2.54k | } |
660 | | |
661 | | /******************************************************************************/ |
662 | | |
663 | | dng_vector_3::dng_vector_3 (real64 a0, |
664 | | real64 a1, |
665 | | real64 a2) |
666 | | |
667 | 73.3k | : dng_vector (3) |
668 | | |
669 | 73.3k | { |
670 | | |
671 | 73.3k | fData [0] = a0; |
672 | 73.3k | fData [1] = a1; |
673 | 73.3k | fData [2] = a2; |
674 | | |
675 | 73.3k | } |
676 | | |
677 | | /******************************************************************************/ |
678 | | |
679 | | dng_vector_4::dng_vector_4 () |
680 | | |
681 | 0 | : dng_vector (4) |
682 | | |
683 | 0 | { |
684 | 0 | } |
685 | | |
686 | | /******************************************************************************/ |
687 | | |
688 | | dng_vector_4::dng_vector_4 (const dng_vector &v) |
689 | | |
690 | 0 | : dng_vector (v) |
691 | | |
692 | 0 | { |
693 | | |
694 | 0 | if (Count () != 4) |
695 | 0 | { |
696 | | |
697 | 0 | ThrowMatrixMath (); |
698 | | |
699 | 0 | } |
700 | | |
701 | 0 | } |
702 | | |
703 | | /******************************************************************************/ |
704 | | |
705 | | dng_vector_4::dng_vector_4 (real64 a0, |
706 | | real64 a1, |
707 | | real64 a2, |
708 | | real64 a3) |
709 | | |
710 | 0 | : dng_vector (4) |
711 | | |
712 | 0 | { |
713 | | |
714 | 0 | fData [0] = a0; |
715 | 0 | fData [1] = a1; |
716 | 0 | fData [2] = a2; |
717 | 0 | fData [3] = a3; |
718 | | |
719 | 0 | } |
720 | | |
721 | | /******************************************************************************/ |
722 | | |
723 | | dng_matrix operator* (const dng_matrix &A, |
724 | | const dng_matrix &B) |
725 | 23.6k | { |
726 | | |
727 | 23.6k | if (A.Cols () != B.Rows ()) |
728 | 0 | { |
729 | | |
730 | 0 | ThrowMatrixMath (); |
731 | | |
732 | 0 | } |
733 | | |
734 | 23.6k | dng_matrix C (A.Rows (), B.Cols ()); |
735 | | |
736 | 85.4k | for (uint32 j = 0; j < C.Rows (); j++) |
737 | 239k | for (uint32 k = 0; k < C.Cols (); k++) |
738 | 177k | { |
739 | | |
740 | 177k | C [j] [k] = 0.0; |
741 | | |
742 | 684k | for (uint32 m = 0; m < A.Cols (); m++) |
743 | 507k | { |
744 | | |
745 | 507k | real64 aa = A [j] [m]; |
746 | | |
747 | 507k | real64 bb = B [m] [k]; |
748 | | |
749 | 507k | C [j] [k] += aa * bb; |
750 | | |
751 | 507k | } |
752 | | |
753 | 177k | } |
754 | | |
755 | 23.6k | return C; |
756 | | |
757 | 23.6k | } |
758 | | |
759 | | /******************************************************************************/ |
760 | | |
761 | | dng_vector operator* (const dng_matrix &A, |
762 | | const dng_vector &B) |
763 | 73.5k | { |
764 | | |
765 | 73.5k | if (A.Cols () != B.Count ()) |
766 | 0 | { |
767 | | |
768 | 0 | ThrowMatrixMath (); |
769 | | |
770 | 0 | } |
771 | | |
772 | 73.5k | dng_vector C (A.Rows ()); |
773 | | |
774 | 292k | for (uint32 j = 0; j < C.Count (); j++) |
775 | 218k | { |
776 | | |
777 | 218k | C [j] = 0.0; |
778 | | |
779 | 875k | for (uint32 m = 0; m < A.Cols (); m++) |
780 | 656k | { |
781 | | |
782 | 656k | real64 aa = A [j] [m]; |
783 | | |
784 | 656k | real64 bb = B [m]; |
785 | | |
786 | 656k | C [j] += aa * bb; |
787 | | |
788 | 656k | } |
789 | | |
790 | 218k | } |
791 | | |
792 | 73.5k | return C; |
793 | | |
794 | 73.5k | } |
795 | | |
796 | | /******************************************************************************/ |
797 | | |
798 | | dng_matrix operator* (real64 scale, |
799 | | const dng_matrix &A) |
800 | 1.20k | { |
801 | | |
802 | 1.20k | dng_matrix B (A); |
803 | | |
804 | 1.20k | B.Scale (scale); |
805 | | |
806 | 1.20k | return B; |
807 | | |
808 | 1.20k | } |
809 | | |
810 | | /******************************************************************************/ |
811 | | |
812 | | dng_vector operator* (real64 scale, |
813 | | const dng_vector &A) |
814 | 0 | { |
815 | | |
816 | 0 | dng_vector B (A); |
817 | | |
818 | 0 | B.Scale (scale); |
819 | | |
820 | 0 | return B; |
821 | | |
822 | 0 | } |
823 | | |
824 | | /******************************************************************************/ |
825 | | |
826 | | dng_matrix operator+ (const dng_matrix &A, |
827 | | const dng_matrix &B) |
828 | 16 | { |
829 | | |
830 | 16 | if (A.Cols () != B.Cols () || |
831 | 16 | A.Rows () != B.Rows ()) |
832 | 0 | { |
833 | | |
834 | 0 | ThrowMatrixMath (); |
835 | | |
836 | 0 | } |
837 | | |
838 | 16 | dng_matrix C (A); |
839 | | |
840 | 64 | for (uint32 j = 0; j < C.Rows (); j++) |
841 | 192 | for (uint32 k = 0; k < C.Cols (); k++) |
842 | 144 | { |
843 | | |
844 | 144 | C [j] [k] += B [j] [k]; |
845 | | |
846 | 144 | } |
847 | | |
848 | 16 | return C; |
849 | | |
850 | 16 | } |
851 | | |
852 | | /******************************************************************************/ |
853 | | |
854 | | const real64 kNearZero = 1.0E-10; |
855 | | |
856 | | /******************************************************************************/ |
857 | | |
858 | | // Work around bug #1294195, which may be a hardware problem on a specific machine. |
859 | | // This pragma turns on "improved" floating-point consistency. |
860 | | #ifdef _MSC_VER |
861 | | #pragma optimize ("p", on) |
862 | | #endif |
863 | | |
864 | | static dng_matrix Invert3by3 (const dng_matrix &A) |
865 | 48.5k | { |
866 | | |
867 | 48.5k | real64 a00 = A [0] [0]; |
868 | 48.5k | real64 a01 = A [0] [1]; |
869 | 48.5k | real64 a02 = A [0] [2]; |
870 | 48.5k | real64 a10 = A [1] [0]; |
871 | 48.5k | real64 a11 = A [1] [1]; |
872 | 48.5k | real64 a12 = A [1] [2]; |
873 | 48.5k | real64 a20 = A [2] [0]; |
874 | 48.5k | real64 a21 = A [2] [1]; |
875 | 48.5k | real64 a22 = A [2] [2]; |
876 | | |
877 | 48.5k | real64 temp [3] [3]; |
878 | | |
879 | 48.5k | temp [0] [0] = a11 * a22 - a21 * a12; |
880 | 48.5k | temp [0] [1] = a21 * a02 - a01 * a22; |
881 | 48.5k | temp [0] [2] = a01 * a12 - a11 * a02; |
882 | 48.5k | temp [1] [0] = a20 * a12 - a10 * a22; |
883 | 48.5k | temp [1] [1] = a00 * a22 - a20 * a02; |
884 | 48.5k | temp [1] [2] = a10 * a02 - a00 * a12; |
885 | 48.5k | temp [2] [0] = a10 * a21 - a20 * a11; |
886 | 48.5k | temp [2] [1] = a20 * a01 - a00 * a21; |
887 | 48.5k | temp [2] [2] = a00 * a11 - a10 * a01; |
888 | | |
889 | 48.5k | real64 det = (a00 * temp [0] [0] + |
890 | 48.5k | a01 * temp [1] [0] + |
891 | 48.5k | a02 * temp [2] [0]); |
892 | | |
893 | 48.5k | if (Abs_real64 (det) < kNearZero) |
894 | 3.93k | { |
895 | | |
896 | 3.93k | ThrowMatrixMath (); |
897 | | |
898 | 3.93k | } |
899 | | |
900 | 48.5k | dng_matrix B (3, 3); |
901 | | |
902 | 182k | for (uint32 j = 0; j < 3; j++) |
903 | 535k | for (uint32 k = 0; k < 3; k++) |
904 | 401k | { |
905 | | |
906 | 401k | B [j] [k] = temp [j] [k] / det; |
907 | | |
908 | 401k | } |
909 | | |
910 | 48.5k | return B; |
911 | | |
912 | 48.5k | } |
913 | | |
914 | | // Reset floating-point optimization. See comment above. |
915 | | #ifdef _MSC_VER |
916 | | #pragma optimize ("p", off) |
917 | | #endif |
918 | | |
919 | | /******************************************************************************/ |
920 | | |
921 | | static dng_matrix InvertNbyN (const dng_matrix &A) |
922 | 248 | { |
923 | | |
924 | 248 | uint32 i; |
925 | 248 | uint32 j; |
926 | 248 | uint32 k; |
927 | | |
928 | 248 | uint32 n = A.Rows (); |
929 | | |
930 | 248 | real64 temp [kMaxColorPlanes] [kMaxColorPlanes * 2]; |
931 | | |
932 | 962 | for (i = 0; i < n; i++) |
933 | 3.01k | for (j = 0; j < n; j++) |
934 | 2.30k | { |
935 | | |
936 | 2.30k | temp [i] [j ] = A [i] [j]; |
937 | | |
938 | 2.30k | temp [i] [j + n] = (i == j ? 1.0 : 0.0); |
939 | | |
940 | 2.30k | } |
941 | | |
942 | 891 | for (i = 0; i < n; i++) |
943 | 643 | { |
944 | | |
945 | 643 | real64 alpha = temp [i] [i]; |
946 | | |
947 | 643 | if (Abs_real64 (alpha) < kNearZero) |
948 | 58 | { |
949 | | |
950 | 58 | ThrowMatrixMath (); |
951 | | |
952 | 58 | } |
953 | | |
954 | 4.31k | for (j = 0; j < n * 2; j++) |
955 | 3.66k | { |
956 | | |
957 | 3.66k | temp [i] [j] /= alpha; |
958 | | |
959 | 3.66k | } |
960 | | |
961 | 2.47k | for (k = 0; k < n; k++) |
962 | 1.83k | { |
963 | | |
964 | 1.83k | if (i != k) |
965 | 1.24k | { |
966 | | |
967 | 1.24k | real64 beta = temp [k] [i]; |
968 | | |
969 | 10.2k | for (j = 0; j < n * 2; j++) |
970 | 8.98k | { |
971 | | |
972 | 8.98k | temp [k] [j] -= beta * temp [i] [j]; |
973 | | |
974 | 8.98k | } |
975 | | |
976 | 1.24k | } |
977 | | |
978 | 1.83k | } |
979 | | |
980 | 643 | } |
981 | | |
982 | 248 | dng_matrix B (n, n); |
983 | | |
984 | 760 | for (i = 0; i < n; i++) |
985 | 2.06k | for (j = 0; j < n; j++) |
986 | 1.55k | { |
987 | | |
988 | 1.55k | B [i] [j] = temp [i] [j + n]; |
989 | | |
990 | 1.55k | } |
991 | | |
992 | 248 | return B; |
993 | | |
994 | 248 | } |
995 | | |
996 | | /******************************************************************************/ |
997 | | |
998 | | dng_matrix Transpose (const dng_matrix &A) |
999 | 3.96k | { |
1000 | | |
1001 | 3.96k | dng_matrix B (A.Cols (), A.Rows ()); |
1002 | | |
1003 | 15.8k | for (uint32 j = 0; j < B.Rows (); j++) |
1004 | 37.9k | for (uint32 k = 0; k < B.Cols (); k++) |
1005 | 26.0k | { |
1006 | | |
1007 | 26.0k | B [j] [k] = A [k] [j]; |
1008 | | |
1009 | 26.0k | } |
1010 | | |
1011 | 3.96k | return B; |
1012 | | |
1013 | 3.96k | } |
1014 | | |
1015 | | /******************************************************************************/ |
1016 | | |
1017 | | dng_matrix Invert (const dng_matrix &A) |
1018 | 52.7k | { |
1019 | | |
1020 | 52.7k | if (A.Rows () < 2 || A.Cols () < 2) |
1021 | 0 | { |
1022 | | |
1023 | 0 | ThrowMatrixMath (); |
1024 | | |
1025 | 0 | } |
1026 | | |
1027 | 52.7k | if (A.Rows () == A.Cols ()) |
1028 | 48.7k | { |
1029 | | |
1030 | 48.7k | if (A.Rows () == 3) |
1031 | 48.5k | { |
1032 | | |
1033 | 48.5k | return Invert3by3 (A); |
1034 | | |
1035 | 48.5k | } |
1036 | | |
1037 | 248 | return InvertNbyN (A); |
1038 | | |
1039 | 48.7k | } |
1040 | | |
1041 | 3.96k | else |
1042 | 3.96k | { |
1043 | | |
1044 | | // Compute the pseudo inverse. |
1045 | | |
1046 | 3.96k | dng_matrix B = Transpose (A); |
1047 | | |
1048 | 3.96k | return Invert (B * A) * B; |
1049 | | |
1050 | 3.96k | } |
1051 | | |
1052 | 52.7k | } |
1053 | | |
1054 | | /******************************************************************************/ |
1055 | | |
1056 | | dng_matrix Invert (const dng_matrix &A, |
1057 | | const dng_matrix &hint) |
1058 | 2.40k | { |
1059 | | |
1060 | 2.40k | if (A.Rows () == A .Cols () || |
1061 | 2.40k | A.Rows () != hint.Cols () || |
1062 | 2.40k | A.Cols () != hint.Rows ()) |
1063 | 2.37k | { |
1064 | | |
1065 | 2.37k | return Invert (A); |
1066 | | |
1067 | 2.37k | } |
1068 | | |
1069 | 33 | else |
1070 | 33 | { |
1071 | | |
1072 | | // Use the specified hint matrix. |
1073 | | |
1074 | 33 | return Invert (hint * A) * hint; |
1075 | | |
1076 | 33 | } |
1077 | | |
1078 | 2.40k | } |
1079 | | |
1080 | | /*****************************************************************************/ |