5eaa7c33c2f67251b0eced94cece02ebcd1bc677
[jalview.git] / src / jalview / math / Matrix.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.math;
22
23 import jalview.util.Format;
24 import jalview.util.MessageManager;
25
26 import java.io.PrintStream;
27 import java.lang.Math;
28 import java.util.Arrays;
29
30 /**
31  * A class to model rectangular matrices of double values and operations on them
32  */
33 public class Matrix implements MatrixI
34 {
35   /*
36    * maximum number of iterations for tqli
37    */
38   private static final int MAX_ITER = 45;
39   // fudge - add 15 iterations, just in case
40
41   /*
42    * the number of rows
43    */
44   final protected int rows;
45
46   /*
47    * the number of columns
48    */
49   final protected int cols;
50
51   /*
52    * the cell values in row-major order
53    */
54   private double[][] value;
55
56   protected double[] d; // Diagonal
57
58   protected double[] e; // off diagonal
59
60   /**
61    * Constructor given number of rows and columns
62    * 
63    * @param colCount
64    * @param rowCount
65    */
66   protected Matrix(int rowCount, int colCount)
67   {
68     rows = rowCount;
69     cols = colCount;
70   }
71
72   /**
73    * Creates a new Matrix object containing a copy of the supplied array values.
74    * For example
75    * 
76    * <pre>
77    *   new Matrix(new double[][] {{2, 3, 4}, {5, 6, 7})
78    * constructs
79    *   (2 3 4)
80    *   (5 6 7)
81    * </pre>
82    * 
83    * Note that ragged arrays (with not all rows, or columns, of the same
84    * length), are not supported by this class. They can be constructed, but
85    * results of operations on them are undefined and may throw exceptions.
86    * 
87    * @param values
88    *          the matrix values in row-major order
89    */
90   public Matrix(double[][] values)
91   {
92     this.rows = values.length;
93     this.cols = this.rows == 0 ? 0 : values[0].length;
94
95     /*
96      * make a copy of the values array, for immutability
97      */
98     this.value = new double[rows][];
99     int i = 0;
100     for (double[] row : values)
101     {
102       if (row != null)
103       {
104         value[i] = new double[row.length];
105         System.arraycopy(row, 0, value[i], 0, row.length);
106       }
107       i++;
108     }
109   }
110
111   public Matrix(float[][] values)
112   {
113     this.rows = values.length;
114     this.cols = this.rows == 0 ? 0 : values[0].length;
115
116     /*
117      * make a copy of the values array, for immutability
118      */
119     this.value = new double[rows][];
120     int i = 0;
121     for (float[] row : values)
122     {
123       if (row != null)
124       {
125         value[i] = new double[row.length];
126         int j = 0;
127         for (float oldValue : row)
128         {
129           value[i][j] = oldValue;
130           j++;
131         }
132       }
133       i++;
134     }
135   }
136
137   @Override
138   public MatrixI transpose()
139   {
140     double[][] out = new double[cols][rows];
141
142     for (int i = 0; i < cols; i++)
143     {
144       for (int j = 0; j < rows; j++)
145       {
146         out[i][j] = value[j][i];
147       }
148     }
149
150     return new Matrix(out);
151   }
152
153   /**
154    * DOCUMENT ME!
155    * 
156    * @param ps
157    *          DOCUMENT ME!
158    * @param format
159    */
160   @Override
161   public void print(PrintStream ps, String format)
162   {
163     for (int i = 0; i < rows; i++)
164     {
165       for (int j = 0; j < cols; j++)
166       {
167         Format.print(ps, format, getValue(i, j));
168       }
169
170       ps.println();
171     }
172   }
173
174   @Override
175   public MatrixI preMultiply(MatrixI in)
176   {
177     if (in.width() != rows)
178     {
179       throw new IllegalArgumentException("Can't pre-multiply " + this.rows
180               + " rows by " + in.width() + " columns");
181     }
182     double[][] tmp = new double[in.height()][this.cols];
183
184     for (int i = 0; i < in.height(); i++)
185     {
186       for (int j = 0; j < this.cols; j++)
187       {
188         /*
189          * result[i][j] is the vector product of 
190          * in.row[i] and this.column[j]
191          */
192         for (int k = 0; k < in.width(); k++)
193         {
194           tmp[i][j] += (in.getValue(i, k) * this.value[k][j]);
195         }
196       }
197     }
198
199     return new Matrix(tmp);
200   }
201
202   /**
203    * 
204    * @param in
205    * 
206    * @return
207    */
208   public double[] vectorPostMultiply(double[] in)
209   {
210     double[] out = new double[in.length];
211
212     for (int i = 0; i < in.length; i++)
213     {
214       out[i] = 0.0;
215
216       for (int k = 0; k < in.length; k++)
217       {
218         out[i] += (value[i][k] * in[k]);
219       }
220     }
221
222     return out;
223   }
224
225   @Override
226   public MatrixI postMultiply(MatrixI in)
227   {
228     if (in.height() != this.cols)
229     {
230       throw new IllegalArgumentException("Can't post-multiply " + this.cols
231               + " columns by " + in.height() + " rows");
232     }
233     return in.preMultiply(this);
234   }
235
236   @Override
237   public MatrixI copy()
238   {
239     double[][] newmat = new double[rows][cols];
240
241     for (int i = 0; i < rows; i++)
242     {
243       System.arraycopy(value[i], 0, newmat[i], 0, value[i].length);
244     }
245
246     Matrix m = new Matrix(newmat);
247     if (this.d != null)
248     {
249       m.d = Arrays.copyOf(this.d, this.d.length);
250     }
251     if (this.e != null)
252     {
253       m.e = Arrays.copyOf(this.e, this.e.length);
254     }
255
256     return m;
257   }
258
259   /**
260    * DOCUMENT ME!
261    */
262   @Override
263   public void tred()
264   {
265     int n = rows;
266     int k;
267     int j;
268     int i;
269
270     double scale;
271     double hh;
272     double h;
273     double g;
274     double f;
275
276     this.d = new double[rows];
277     this.e = new double[rows];
278
279     for (i = n; i >= 2; i--)
280     {
281       final int l = i - 1;
282       h = 0.0;
283       scale = 0.0;
284
285       if (l > 1)
286       {
287         for (k = 1; k <= l; k++)
288         {
289           double v = Math.abs(getValue(i - 1, k - 1));
290           scale += v;
291         }
292
293         if (scale == 0.0)
294         {
295           e[i - 1] = getValue(i - 1, l - 1);
296         }
297         else
298         {
299           for (k = 1; k <= l; k++)
300           {
301             double v = divideValue(i - 1, k - 1, scale);
302             h += v * v;
303           }
304
305           f = getValue(i - 1, l - 1);
306
307           if (f > 0)
308           {
309             g = -1.0 * Math.sqrt(h);
310           }
311           else
312           {
313             g = Math.sqrt(h);
314           }
315
316           e[i - 1] = scale * g;
317           h -= (f * g);
318           setValue(i - 1, l - 1, f - g);
319           f = 0.0;
320
321           for (j = 1; j <= l; j++)
322           {
323             double val = getValue(i - 1, j - 1) / h;
324             setValue(j - 1, i - 1, val);
325             g = 0.0;
326
327             for (k = 1; k <= j; k++)
328             {
329               g += (getValue(j - 1, k - 1) * getValue(i - 1, k - 1));
330             }
331
332             for (k = j + 1; k <= l; k++)
333             {
334               g += (getValue(k - 1, j - 1) * getValue(i - 1, k - 1));
335             }
336
337             e[j - 1] = g / h;
338             f += (e[j - 1] * getValue(i - 1, j - 1));
339           }
340
341           hh = f / (h + h);
342
343           for (j = 1; j <= l; j++)
344           {
345             f = getValue(i - 1, j - 1);
346             g = e[j - 1] - (hh * f);
347             e[j - 1] = g;
348
349             for (k = 1; k <= j; k++)
350             {
351               double val = (f * e[k - 1]) + (g * getValue(i - 1, k - 1));
352               addValue(j - 1, k - 1, -val);
353             }
354           }
355         }
356       }
357       else
358       {
359         e[i - 1] = getValue(i - 1, l - 1);
360       }
361
362       d[i - 1] = h;
363     }
364
365     d[0] = 0.0;
366     e[0] = 0.0;
367
368     for (i = 1; i <= n; i++)
369     {
370       final int l = i - 1;
371
372       if (d[i - 1] != 0.0)
373       {
374         for (j = 1; j <= l; j++)
375         {
376           g = 0.0;
377
378           for (k = 1; k <= l; k++)
379           {
380             g += (getValue(i - 1, k - 1) * getValue(k - 1, j - 1));
381           }
382
383           for (k = 1; k <= l; k++)
384           {
385             addValue(k - 1, j - 1, -(g * getValue(k - 1, i - 1)));
386           }
387         }
388       }
389
390       d[i - 1] = getValue(i - 1, i - 1);
391       setValue(i - 1, i - 1, 1.0);
392
393       for (j = 1; j <= l; j++)
394       {
395         setValue(j - 1, i - 1, 0.0);
396         setValue(i - 1, j - 1, 0.0);
397       }
398     }
399   }
400
401   /**
402    * Adds f to the value at [i, j] and returns the new value
403    * 
404    * @param i
405    * @param j
406    * @param f
407    */
408   protected double addValue(int i, int j, double f)
409   {
410     double v = value[i][j] + f;
411     value[i][j] = v;
412     return v;
413   }
414
415   /**
416    * Divides the value at [i, j] by divisor and returns the new value. If d is
417    * zero, returns the unchanged value.
418    * 
419    * @param i
420    * @param j
421    * @param divisor
422    * @return
423    */
424   protected double divideValue(int i, int j, double divisor)
425   {
426     if (divisor == 0d)
427     {
428       return getValue(i, j);
429     }
430     double v = value[i][j];
431     v = v / divisor;
432     value[i][j] = v;
433     return v;
434   }
435
436   /**
437    * DOCUMENT ME!
438    */
439   @Override
440   public void tqli() throws Exception
441   {
442     int n = rows;
443
444     int m;
445     int l;
446     int iter;
447     int i;
448     int k;
449     double s;
450     double r;
451     double p;
452
453     double g;
454     double f;
455     double dd;
456     double c;
457     double b;
458
459     for (i = 2; i <= n; i++)
460     {
461       e[i - 2] = e[i - 1];
462     }
463
464     e[n - 1] = 0.0;
465
466     for (l = 1; l <= n; l++)
467     {
468       iter = 0;
469
470       do
471       {
472         for (m = l; m <= (n - 1); m++)
473         {
474           dd = Math.abs(d[m - 1]) + Math.abs(d[m]);
475
476           if ((Math.abs(e[m - 1]) + dd) == dd)
477           {
478             break;
479           }
480         }
481
482         if (m != l)
483         {
484           iter++;
485
486           if (iter == MAX_ITER)
487           {
488             throw new Exception(MessageManager.formatMessage(
489                     "exception.matrix_too_many_iteration", new String[]
490                     { "tqli", Integer.valueOf(MAX_ITER).toString() }));
491           }
492           else
493           {
494             // System.out.println("Iteration " + iter);
495           }
496
497           g = (d[l] - d[l - 1]) / (2.0 * e[l - 1]);
498           r = Math.sqrt((g * g) + 1.0);
499           g = d[m - 1] - d[l - 1] + (e[l - 1] / (g + sign(r, g)));
500           c = 1.0;
501           s = c;
502           p = 0.0;
503
504           for (i = m - 1; i >= l; i--)
505           {
506             f = s * e[i - 1];
507             b = c * e[i - 1];
508
509             if (Math.abs(f) >= Math.abs(g))
510             {
511               c = g / f;
512               r = Math.sqrt((c * c) + 1.0);
513               e[i] = f * r;
514               s = 1.0 / r;
515               c *= s;
516             }
517             else
518             {
519               s = f / g;
520               r = Math.sqrt((s * s) + 1.0);
521               e[i] = g * r;
522               c = 1.0 / r;
523               s *= c;
524             }
525
526             g = d[i] - p;
527             r = ((d[i - 1] - g) * s) + (2.0 * c * b);
528             p = s * r;
529             d[i] = g + p;
530             g = (c * r) - b;
531
532             for (k = 1; k <= n; k++)
533             {
534               f = getValue(k - 1, i);
535               setValue(k - 1, i, (s * getValue(k - 1, i - 1)) + (c * f));
536               setValue(k - 1, i - 1,
537                       (c * getValue(k - 1, i - 1)) - (s * f));
538             }
539           }
540
541           d[l - 1] = d[l - 1] - p;
542           e[l - 1] = g;
543           e[m - 1] = 0.0;
544         }
545       } while (m != l);
546     }
547   }
548
549   @Override
550   public double getValue(int i, int j)
551   {
552     return value[i][j];
553   }
554
555   @Override
556   public void setValue(int i, int j, double val)
557   {
558     value[i][j] = val;
559   }
560
561   /**
562    * DOCUMENT ME!
563    */
564   public void tred2()
565   {
566     int n = rows;
567     int l;
568     int k;
569     int j;
570     int i;
571
572     double scale;
573     double hh;
574     double h;
575     double g;
576     double f;
577
578     this.d = new double[rows];
579     this.e = new double[rows];
580
581     for (i = n - 1; i >= 1; i--)
582     {
583       l = i - 1;
584       h = 0.0;
585       scale = 0.0;
586
587       if (l > 0)
588       {
589         for (k = 0; k < l; k++)
590         {
591           scale += Math.abs(value[i][k]);
592         }
593
594         if (scale == 0.0)
595         {
596           e[i] = value[i][l];
597         }
598         else
599         {
600           for (k = 0; k < l; k++)
601           {
602             value[i][k] /= scale;
603             h += (value[i][k] * value[i][k]);
604           }
605
606           f = value[i][l];
607
608           if (f > 0)
609           {
610             g = -1.0 * Math.sqrt(h);
611           }
612           else
613           {
614             g = Math.sqrt(h);
615           }
616
617           e[i] = scale * g;
618           h -= (f * g);
619           value[i][l] = f - g;
620           f = 0.0;
621
622           for (j = 0; j < l; j++)
623           {
624             value[j][i] = value[i][j] / h;
625             g = 0.0;
626
627             for (k = 0; k < j; k++)
628             {
629               g += (value[j][k] * value[i][k]);
630             }
631
632             for (k = j; k < l; k++)
633             {
634               g += (value[k][j] * value[i][k]);
635             }
636
637             e[j] = g / h;
638             f += (e[j] * value[i][j]);
639           }
640
641           hh = f / (h + h);
642
643           for (j = 0; j < l; j++)
644           {
645             f = value[i][j];
646             g = e[j] - (hh * f);
647             e[j] = g;
648
649             for (k = 0; k < j; k++)
650             {
651               value[j][k] -= ((f * e[k]) + (g * value[i][k]));
652             }
653           }
654         }
655       }
656       else
657       {
658         e[i] = value[i][l];
659       }
660
661       d[i] = h;
662     }
663
664     d[0] = 0.0;
665     e[0] = 0.0;
666
667     for (i = 0; i < n; i++)
668     {
669       l = i - 1;
670
671       if (d[i] != 0.0)
672       {
673         for (j = 0; j < l; j++)
674         {
675           g = 0.0;
676
677           for (k = 0; k < l; k++)
678           {
679             g += (value[i][k] * value[k][j]);
680           }
681
682           for (k = 0; k < l; k++)
683           {
684             value[k][j] -= (g * value[k][i]);
685           }
686         }
687       }
688
689       d[i] = value[i][i];
690       value[i][i] = 1.0;
691
692       for (j = 0; j < l; j++)
693       {
694         value[j][i] = 0.0;
695         value[i][j] = 0.0;
696       }
697     }
698   }
699
700   /**
701    * DOCUMENT ME!
702    */
703   public void tqli2() throws Exception
704   {
705     int n = rows;
706
707     int m;
708     int l;
709     int iter;
710     int i;
711     int k;
712     double s;
713     double r;
714     double p;
715     ;
716
717     double g;
718     double f;
719     double dd;
720     double c;
721     double b;
722
723     for (i = 2; i <= n; i++)
724     {
725       e[i - 2] = e[i - 1];
726     }
727
728     e[n - 1] = 0.0;
729
730     for (l = 1; l <= n; l++)
731     {
732       iter = 0;
733
734       do
735       {
736         for (m = l; m <= (n - 1); m++)
737         {
738           dd = Math.abs(d[m - 1]) + Math.abs(d[m]);
739
740           if ((Math.abs(e[m - 1]) + dd) == dd)
741           {
742             break;
743           }
744         }
745
746         if (m != l)
747         {
748           iter++;
749
750           if (iter == MAX_ITER)
751           {
752             throw new Exception(MessageManager.formatMessage(
753                     "exception.matrix_too_many_iteration", new String[]
754                     { "tqli2", Integer.valueOf(MAX_ITER).toString() }));
755           }
756           else
757           {
758             // System.out.println("Iteration " + iter);
759           }
760
761           g = (d[l] - d[l - 1]) / (2.0 * e[l - 1]);
762           r = Math.sqrt((g * g) + 1.0);
763           g = d[m - 1] - d[l - 1] + (e[l - 1] / (g + sign(r, g)));
764           c = 1.0;
765           s = c;
766           p = 0.0;
767
768           for (i = m - 1; i >= l; i--)
769           {
770             f = s * e[i - 1];
771             b = c * e[i - 1];
772
773             if (Math.abs(f) >= Math.abs(g))
774             {
775               c = g / f;
776               r = Math.sqrt((c * c) + 1.0);
777               e[i] = f * r;
778               s = 1.0 / r;
779               c *= s;
780             }
781             else
782             {
783               s = f / g;
784               r = Math.sqrt((s * s) + 1.0);
785               e[i] = g * r;
786               c = 1.0 / r;
787               s *= c;
788             }
789
790             g = d[i] - p;
791             r = ((d[i - 1] - g) * s) + (2.0 * c * b);
792             p = s * r;
793             d[i] = g + p;
794             g = (c * r) - b;
795
796             for (k = 1; k <= n; k++)
797             {
798               f = value[k - 1][i];
799               value[k - 1][i] = (s * value[k - 1][i - 1]) + (c * f);
800               value[k - 1][i - 1] = (c * value[k - 1][i - 1]) - (s * f);
801             }
802           }
803
804           d[l - 1] = d[l - 1] - p;
805           e[l - 1] = g;
806           e[m - 1] = 0.0;
807         }
808       } while (m != l);
809     }
810   }
811
812   /**
813    * Answers the first argument with the sign of the second argument
814    * 
815    * @param a
816    * @param b
817    * 
818    * @return
819    */
820   static double sign(double a, double b)
821   {
822     if (b < 0)
823     {
824       return -Math.abs(a);
825     }
826     else
827     {
828       return Math.abs(a);
829     }
830   }
831
832   /**
833    * Returns an array containing the values in the specified column
834    * 
835    * @param col
836    * 
837    * @return
838    */
839   public double[] getColumn(int col)
840   {
841     double[] out = new double[rows];
842
843     for (int i = 0; i < rows; i++)
844     {
845       out[i] = value[i][col];
846     }
847
848     return out;
849   }
850
851   /**
852    * DOCUMENT ME!
853    * 
854    * @param ps
855    *          DOCUMENT ME!
856    * @param format
857    */
858   @Override
859   public void printD(PrintStream ps, String format)
860   {
861     for (int j = 0; j < rows; j++)
862     {
863       Format.print(ps, format, d[j]);
864     }
865   }
866
867   /**
868    * DOCUMENT ME!
869    * 
870    * @param ps
871    *          DOCUMENT ME!
872    * @param format
873    *          TODO
874    */
875   @Override
876   public void printE(PrintStream ps, String format)
877   {
878     for (int j = 0; j < rows; j++)
879     {
880       Format.print(ps, format, e[j]);
881     }
882   }
883
884   @Override
885   public double[] getD()
886   {
887     return d;
888   }
889
890   @Override
891   public double[] getE()
892   {
893     return e;
894   }
895
896   @Override
897   public int height()
898   {
899     return rows;
900   }
901
902   @Override
903   public int width()
904   {
905     return cols;
906   }
907
908   @Override
909   public double[] getRow(int i)
910   {
911     double[] row = new double[cols];
912     System.arraycopy(value[i], 0, row, 0, cols);
913     return row;
914   }
915
916   /**
917    * Returns a length 2 array of {minValue, maxValue} of all values in the
918    * matrix. Returns null if the matrix is null or empty.
919    * 
920    * @return
921    */
922   double[] findMinMax()
923   {
924     if (value == null)
925     {
926       return null;
927     }
928     double min = Double.MAX_VALUE;
929     double max = -Double.MAX_VALUE;
930     boolean empty = true;
931     for (double[] row : value)
932     {
933       if (row != null)
934       {
935         for (double x : row)
936         {
937           empty = false;
938           if (x > max)
939           {
940             max = x;
941           }
942           if (x < min)
943           {
944             min = x;
945           }
946         }
947       }
948     }
949     return empty ? null : new double[] { min, max };
950   }
951
952   /**
953    * {@inheritDoc}
954    */
955   @Override
956   public void reverseRange(boolean maxToZero)
957   {
958     if (value == null)
959     {
960       return;
961     }
962     double[] minMax = findMinMax();
963     if (minMax == null)
964     {
965       return; // empty matrix
966     }
967     double subtractFrom = maxToZero ? minMax[1] : minMax[0] + minMax[1];
968
969     for (double[] row : value)
970     {
971       if (row != null)
972       {
973         int j = 0;
974         for (double x : row)
975         {
976           row[j] = subtractFrom - x;
977           j++;
978         }
979       }
980     }
981   }
982
983   /**
984    * Multiplies every entry in the matrix by the given value.
985    * 
986    * @param
987    */
988   @Override
989   public void multiply(double by)
990   {
991     for (double[] row : value)
992     {
993       if (row != null)
994       {
995         for (int i = 0; i < row.length; i++)
996         {
997           row[i] *= by;
998         }
999       }
1000     }
1001   }
1002
1003   @Override
1004   public void setD(double[] v)
1005   {
1006     d = v;
1007   }
1008
1009   @Override
1010   public void setE(double[] v)
1011   {
1012     e = v;
1013   }
1014
1015   public double getTotal()
1016   {
1017     double d = 0d;
1018     for (int i = 0; i < this.height(); i++)
1019     {
1020       for (int j = 0; j < this.width(); j++)
1021       {
1022         d += value[i][j];
1023       }
1024     }
1025     return d;
1026   }
1027
1028   /**
1029    * {@inheritDoc}
1030    */
1031   @Override
1032   public boolean equals(MatrixI m2, double delta)
1033   {
1034     if (m2 == null || this.height() != m2.height()
1035             || this.width() != m2.width())
1036     {
1037       return false;
1038     }
1039     for (int i = 0; i < this.height(); i++)
1040     {
1041       for (int j = 0; j < this.width(); j++)
1042       {
1043         double diff = this.getValue(i, j) - m2.getValue(i, j);
1044         if (Math.abs(diff) > delta)
1045         {
1046           return false;
1047         }
1048       }
1049     }
1050     return true;
1051   }
1052
1053   /**
1054    * Returns a copy in which  every value in the matrix is its absolute
1055    * 
1056    */
1057   @Override
1058   public MatrixI absolute()
1059   {
1060     MatrixI copy = this.copy();
1061     for (int i = 0; i < copy.width(); i++)
1062     {
1063       double[] row = copy.getRow(i);
1064       if (row != null)
1065       {
1066         for (int j = 0; j < row.length; j++)
1067         {
1068           row[j] = Math.abs(row[j]);
1069         }
1070       }
1071     }
1072     return copy;
1073   }
1074
1075   /**
1076    * Returns the mean of each row
1077    * 
1078    */
1079   @Override
1080   public double[] meanRow()
1081   {
1082     double[] mean = new double[rows];
1083     int i = 0;
1084     for (double[] row : value)
1085     {
1086       if (row != null)
1087       {
1088         mean[i++] = MiscMath.mean(row);
1089       }
1090     }
1091     return mean;
1092   }
1093
1094   /**
1095    * Returns the mean of each column
1096    * 
1097    */
1098   @Override
1099   public double[] meanCol()
1100   {
1101     double[] mean = new double[cols];
1102     for (int j = 0; j < cols; j++)
1103     {
1104       double[] column = getColumn(j);
1105       if (column != null)
1106       {
1107         mean[j] = MiscMath.mean(column);
1108       }
1109     }
1110     return mean;
1111   }
1112
1113   /**
1114   * fills up a diagonal matrix with its transposed copy
1115   * !other side should be filled with 0
1116   *
1117   * TODO check on which side it was diagonal and only do calculations for the other side
1118   */
1119   @Override
1120   public void fillDiagonal()
1121   {
1122     int n = this.rows;
1123     int m = this.cols;
1124     MatrixI copy = this.transpose();
1125     for (int i = 0; i < n; i++)
1126     {
1127       for (int j = 0; j < m; j++)
1128       {
1129         if (i != j)
1130         {
1131           this.addValue(i, j, copy.getValue(i,j));
1132         }
1133       }
1134     }
1135   }
1136
1137   /**
1138   * counts the number of Double.NaN in the matrix
1139   *
1140   * @return
1141   */
1142   @Override
1143   public int countNaN()
1144   {
1145     int NaN = 0;
1146     for (int i = 0; i < this.rows; i++)
1147     {
1148       for (int j = 0; j < this.cols; j++)
1149       {
1150         if (Double.isNaN(this.getValue(i,j)))
1151         {
1152           NaN++;
1153         }
1154       }
1155     }
1156     return NaN;
1157   }
1158
1159 }