Coverage Report

Created: 2025-07-23 06:38

/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
/*****************************************************************************/