Clover icon

Coverage Report

  1. Project Clover database Mon Nov 18 2024 09:38:20 GMT
  2. Package jalview.math

File Matrix.java

 

Coverage histogram

../../img/srcFileCovDistChart1.png
51% of files have more coverage

Code metrics

264
501
51
1
1,475
1,046
190
0.38
9.82
51
3.73

Classes

Class Line # Actions
Matrix 33 501 190
0.0196078442%
 

Contributing tests

This file is covered by 2 tests. .

Source view

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  0 toggle protected Matrix(int rowCount, int colCount)
67    {
68  0 rows = rowCount;
69  0 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  2 toggle public Matrix(double[][] values)
91    {
92  2 this.rows = values.length;
93  2 this.cols = this.rows == 0 ? 0 : values[0].length;
94   
95    /*
96    * make a copy of the values array, for immutability
97    */
98  2 this.value = new double[rows][];
99  2 int i = 0;
100  2 for (double[] row : values)
101    {
102  64 if (row != null)
103    {
104  64 value[i] = new double[row.length];
105  64 System.arraycopy(row, 0, value[i], 0, row.length);
106    }
107  64 i++;
108    }
109    }
110   
 
111  0 toggle public Matrix(float[][] values)
112    {
113  0 this.rows = values.length;
114  0 this.cols = this.rows == 0 ? 0 : values[0].length;
115   
116    /*
117    * make a copy of the values array, for immutability
118    */
119  0 this.value = new double[rows][];
120  0 int i = 0;
121  0 for (float[] row : values)
122    {
123  0 if (row != null)
124    {
125  0 value[i] = new double[row.length];
126  0 int j = 0;
127  0 for (float oldValue : row)
128    {
129  0 value[i][j] = oldValue;
130  0 j++;
131    }
132    }
133  0 i++;
134    }
135    }
136   
 
137  0 toggle @Override
138    public MatrixI transpose()
139    {
140  0 double[][] out = new double[cols][rows];
141   
142  0 for (int i = 0; i < cols; i++)
143    {
144  0 for (int j = 0; j < rows; j++)
145    {
146  0 out[i][j] = value[j][i];
147    }
148    }
149   
150  0 return new Matrix(out);
151    }
152   
153    /**
154    * DOCUMENT ME!
155    *
156    * @param ps
157    * DOCUMENT ME!
158    * @param format
159    */
 
160  0 toggle @Override
161    public void print(PrintStream ps, String format)
162    {
163  0 for (int i = 0; i < rows; i++)
164    {
165  0 for (int j = 0; j < cols; j++)
166    {
167  0 Format.print(ps, format, getValue(i, j));
168    }
169   
170  0 ps.println();
171    }
172    }
173   
 
174  0 toggle @Override
175    public MatrixI preMultiply(MatrixI in)
176    {
177  0 if (in.width() != rows)
178    {
179  0 throw new IllegalArgumentException("Can't pre-multiply " + this.rows
180    + " rows by " + in.width() + " columns");
181    }
182  0 double[][] tmp = new double[in.height()][this.cols];
183   
184  0 for (int i = 0; i < in.height(); i++)
185    {
186  0 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  0 for (int k = 0; k < in.width(); k++)
193    {
194  0 if (!Double.isNaN(in.getValue(i, k))
195    && !Double.isNaN(this.value[k][j]))
196    {
197  0 tmp[i][j] += (in.getValue(i, k) * this.value[k][j]);
198    }
199    }
200    }
201    }
202   
203  0 return new Matrix(tmp);
204    }
205   
206    /**
207    *
208    * @param in
209    *
210    * @return
211    */
 
212  0 toggle public double[] vectorPostMultiply(double[] in)
213    {
214  0 double[] out = new double[in.length];
215   
216  0 for (int i = 0; i < in.length; i++)
217    {
218  0 out[i] = 0.0;
219   
220  0 for (int k = 0; k < in.length; k++)
221    {
222  0 out[i] += (value[i][k] * in[k]);
223    }
224    }
225   
226  0 return out;
227    }
228   
 
229  0 toggle @Override
230    public MatrixI postMultiply(MatrixI in)
231    {
232  0 if (in.height() != this.cols)
233    {
234  0 throw new IllegalArgumentException("Can't post-multiply " + this.cols
235    + " columns by " + in.height() + " rows");
236    }
237  0 return in.preMultiply(this);
238    }
239   
 
240  0 toggle @Override
241    public MatrixI copy()
242    {
243  0 double[][] newmat = new double[rows][cols];
244   
245  0 for (int i = 0; i < rows; i++)
246    {
247  0 System.arraycopy(value[i], 0, newmat[i], 0, value[i].length);
248    }
249   
250  0 Matrix m = new Matrix(newmat);
251  0 if (this.d != null)
252    {
253  0 m.d = Arrays.copyOf(this.d, this.d.length);
254    }
255  0 if (this.e != null)
256    {
257  0 m.e = Arrays.copyOf(this.e, this.e.length);
258    }
259   
260  0 return m;
261    }
262   
263    /**
264    * DOCUMENT ME!
265    */
 
266  0 toggle @Override
267    public void tred()
268    {
269  0 int n = rows;
270  0 int k;
271  0 int j;
272  0 int i;
273   
274  0 double scale;
275  0 double hh;
276  0 double h;
277  0 double g;
278  0 double f;
279   
280  0 this.d = new double[rows];
281  0 this.e = new double[rows];
282   
283  0 for (i = n; i >= 2; i--)
284    {
285  0 final int l = i - 1;
286  0 h = 0.0;
287  0 scale = 0.0;
288   
289  0 if (l > 1)
290    {
291  0 for (k = 1; k <= l; k++)
292    {
293  0 double v = Math.abs(getValue(i - 1, k - 1));
294  0 scale += v;
295    }
296   
297  0 if (scale == 0.0)
298    {
299  0 e[i - 1] = getValue(i - 1, l - 1);
300    }
301    else
302    {
303  0 for (k = 1; k <= l; k++)
304    {
305  0 double v = divideValue(i - 1, k - 1, scale);
306  0 h += v * v;
307    }
308   
309  0 f = getValue(i - 1, l - 1);
310   
311  0 if (f > 0)
312    {
313  0 g = -1.0 * Math.sqrt(h);
314    }
315    else
316    {
317  0 g = Math.sqrt(h);
318    }
319   
320  0 e[i - 1] = scale * g;
321  0 h -= (f * g);
322  0 setValue(i - 1, l - 1, f - g);
323  0 f = 0.0;
324   
325  0 for (j = 1; j <= l; j++)
326    {
327  0 double val = getValue(i - 1, j - 1) / h;
328  0 setValue(j - 1, i - 1, val);
329  0 g = 0.0;
330   
331  0 for (k = 1; k <= j; k++)
332    {
333  0 g += (getValue(j - 1, k - 1) * getValue(i - 1, k - 1));
334    }
335   
336  0 for (k = j + 1; k <= l; k++)
337    {
338  0 g += (getValue(k - 1, j - 1) * getValue(i - 1, k - 1));
339    }
340   
341  0 e[j - 1] = g / h;
342  0 f += (e[j - 1] * getValue(i - 1, j - 1));
343    }
344   
345  0 hh = f / (h + h);
346   
347  0 for (j = 1; j <= l; j++)
348    {
349  0 f = getValue(i - 1, j - 1);
350  0 g = e[j - 1] - (hh * f);
351  0 e[j - 1] = g;
352   
353  0 for (k = 1; k <= j; k++)
354    {
355  0 double val = (f * e[k - 1]) + (g * getValue(i - 1, k - 1));
356  0 addValue(j - 1, k - 1, -val);
357    }
358    }
359    }
360    }
361    else
362    {
363  0 e[i - 1] = getValue(i - 1, l - 1);
364    }
365   
366  0 d[i - 1] = h;
367    }
368   
369  0 d[0] = 0.0;
370  0 e[0] = 0.0;
371   
372  0 for (i = 1; i <= n; i++)
373    {
374  0 final int l = i - 1;
375   
376  0 if (d[i - 1] != 0.0)
377    {
378  0 for (j = 1; j <= l; j++)
379    {
380  0 g = 0.0;
381   
382  0 for (k = 1; k <= l; k++)
383    {
384  0 g += (getValue(i - 1, k - 1) * getValue(k - 1, j - 1));
385    }
386   
387  0 for (k = 1; k <= l; k++)
388    {
389  0 addValue(k - 1, j - 1, -(g * getValue(k - 1, i - 1)));
390    }
391    }
392    }
393   
394  0 d[i - 1] = getValue(i - 1, i - 1);
395  0 setValue(i - 1, i - 1, 1.0);
396   
397  0 for (j = 1; j <= l; j++)
398    {
399  0 setValue(j - 1, i - 1, 0.0);
400  0 setValue(i - 1, j - 1, 0.0);
401    }
402    }
403    }
404   
405    /**
406    * Adds f to the value at [i, j] and returns the new value
407    *
408    * @param i
409    * @param j
410    * @param f
411    */
 
412  0 toggle protected double addValue(int i, int j, double f)
413    {
414  0 double v = value[i][j] + f;
415  0 value[i][j] = v;
416  0 return v;
417    }
418   
419    /**
420    * Divides the value at [i, j] by divisor and returns the new value. If d is
421    * zero, returns the unchanged value.
422    *
423    * @param i
424    * @param j
425    * @param divisor
426    * @return
427    */
 
428  0 toggle protected double divideValue(int i, int j, double divisor)
429    {
430  0 if (divisor == 0d)
431    {
432  0 return getValue(i, j);
433    }
434  0 double v = value[i][j];
435  0 v = v / divisor;
436  0 value[i][j] = v;
437  0 return v;
438    }
439   
440    /**
441    * DOCUMENT ME!
442    */
 
443  0 toggle @Override
444    public void tqli() throws Exception
445    {
446  0 int n = rows;
447   
448  0 int m;
449  0 int l;
450  0 int iter;
451  0 int i;
452  0 int k;
453  0 double s;
454  0 double r;
455  0 double p;
456   
457  0 double g;
458  0 double f;
459  0 double dd;
460  0 double c;
461  0 double b;
462   
463  0 for (i = 2; i <= n; i++)
464    {
465  0 e[i - 2] = e[i - 1];
466    }
467   
468  0 e[n - 1] = 0.0;
469   
470  0 for (l = 1; l <= n; l++)
471    {
472  0 iter = 0;
473   
474  0 do
475    {
476  0 for (m = l; m <= (n - 1); m++)
477    {
478  0 dd = Math.abs(d[m - 1]) + Math.abs(d[m]);
479   
480  0 if ((Math.abs(e[m - 1]) + dd) == dd)
481    {
482  0 break;
483    }
484    }
485   
486  0 if (m != l)
487    {
488  0 iter++;
489   
490  0 if (iter == MAX_ITER)
491    {
492  0 throw new Exception(MessageManager.formatMessage(
493    "exception.matrix_too_many_iteration", new String[]
494    { "tqli", Integer.valueOf(MAX_ITER).toString() }));
495    }
496    else
497    {
498    // jalview.bin.Console.outPrintln("Iteration " + iter);
499    }
500   
501  0 g = (d[l] - d[l - 1]) / (2.0 * e[l - 1]);
502  0 r = Math.sqrt((g * g) + 1.0);
503  0 g = d[m - 1] - d[l - 1] + (e[l - 1] / (g + sign(r, g)));
504  0 c = 1.0;
505  0 s = c;
506  0 p = 0.0;
507   
508  0 for (i = m - 1; i >= l; i--)
509    {
510  0 f = s * e[i - 1];
511  0 b = c * e[i - 1];
512   
513  0 if (Math.abs(f) >= Math.abs(g))
514    {
515  0 c = g / f;
516  0 r = Math.sqrt((c * c) + 1.0);
517  0 e[i] = f * r;
518  0 s = 1.0 / r;
519  0 c *= s;
520    }
521    else
522    {
523  0 s = f / g;
524  0 r = Math.sqrt((s * s) + 1.0);
525  0 e[i] = g * r;
526  0 c = 1.0 / r;
527  0 s *= c;
528    }
529   
530  0 g = d[i] - p;
531  0 r = ((d[i - 1] - g) * s) + (2.0 * c * b);
532  0 p = s * r;
533  0 d[i] = g + p;
534  0 g = (c * r) - b;
535   
536  0 for (k = 1; k <= n; k++)
537    {
538  0 f = getValue(k - 1, i);
539  0 setValue(k - 1, i, (s * getValue(k - 1, i - 1)) + (c * f));
540  0 setValue(k - 1, i - 1,
541    (c * getValue(k - 1, i - 1)) - (s * f));
542    }
543    }
544   
545  0 d[l - 1] = d[l - 1] - p;
546  0 e[l - 1] = g;
547  0 e[m - 1] = 0.0;
548    }
549  0 } while (m != l);
550    }
551    }
552   
 
553  44582 toggle @Override
554    public double getValue(int i, int j)
555    {
556  44582 return value[i][j];
557    }
558   
 
559  10390 toggle @Override
560    public void setValue(int i, int j, double val)
561    {
562  10390 value[i][j] = val;
563    }
564   
565    /**
566    * DOCUMENT ME!
567    */
 
568  0 toggle public void tred2()
569    {
570  0 int n = rows;
571  0 int l;
572  0 int k;
573  0 int j;
574  0 int i;
575   
576  0 double scale;
577  0 double hh;
578  0 double h;
579  0 double g;
580  0 double f;
581   
582  0 this.d = new double[rows];
583  0 this.e = new double[rows];
584   
585  0 for (i = n - 1; i >= 1; i--)
586    {
587  0 l = i - 1;
588  0 h = 0.0;
589  0 scale = 0.0;
590   
591  0 if (l > 0)
592    {
593  0 for (k = 0; k < l; k++)
594    {
595  0 scale += Math.abs(value[i][k]);
596    }
597   
598  0 if (scale == 0.0)
599    {
600  0 e[i] = value[i][l];
601    }
602    else
603    {
604  0 for (k = 0; k < l; k++)
605    {
606  0 value[i][k] /= scale;
607  0 h += (value[i][k] * value[i][k]);
608    }
609   
610  0 f = value[i][l];
611   
612  0 if (f > 0)
613    {
614  0 g = -1.0 * Math.sqrt(h);
615    }
616    else
617    {
618  0 g = Math.sqrt(h);
619    }
620   
621  0 e[i] = scale * g;
622  0 h -= (f * g);
623  0 value[i][l] = f - g;
624  0 f = 0.0;
625   
626  0 for (j = 0; j < l; j++)
627    {
628  0 value[j][i] = value[i][j] / h;
629  0 g = 0.0;
630   
631  0 for (k = 0; k < j; k++)
632    {
633  0 g += (value[j][k] * value[i][k]);
634    }
635   
636  0 for (k = j; k < l; k++)
637    {
638  0 g += (value[k][j] * value[i][k]);
639    }
640   
641  0 e[j] = g / h;
642  0 f += (e[j] * value[i][j]);
643    }
644   
645  0 hh = f / (h + h);
646   
647  0 for (j = 0; j < l; j++)
648    {
649  0 f = value[i][j];
650  0 g = e[j] - (hh * f);
651  0 e[j] = g;
652   
653  0 for (k = 0; k < j; k++)
654    {
655  0 value[j][k] -= ((f * e[k]) + (g * value[i][k]));
656    }
657    }
658    }
659    }
660    else
661    {
662  0 e[i] = value[i][l];
663    }
664   
665  0 d[i] = h;
666    }
667   
668  0 d[0] = 0.0;
669  0 e[0] = 0.0;
670   
671  0 for (i = 0; i < n; i++)
672    {
673  0 l = i - 1;
674   
675  0 if (d[i] != 0.0)
676    {
677  0 for (j = 0; j < l; j++)
678    {
679  0 g = 0.0;
680   
681  0 for (k = 0; k < l; k++)
682    {
683  0 g += (value[i][k] * value[k][j]);
684    }
685   
686  0 for (k = 0; k < l; k++)
687    {
688  0 value[k][j] -= (g * value[k][i]);
689    }
690    }
691    }
692   
693  0 d[i] = value[i][i];
694  0 value[i][i] = 1.0;
695   
696  0 for (j = 0; j < l; j++)
697    {
698  0 value[j][i] = 0.0;
699  0 value[i][j] = 0.0;
700    }
701    }
702    }
703   
704    /**
705    * DOCUMENT ME!
706    */
 
707  0 toggle public void tqli2() throws Exception
708    {
709  0 int n = rows;
710   
711  0 int m;
712  0 int l;
713  0 int iter;
714  0 int i;
715  0 int k;
716  0 double s;
717  0 double r;
718  0 double p;
719  0 ;
720   
721  0 double g;
722  0 double f;
723  0 double dd;
724  0 double c;
725  0 double b;
726   
727  0 for (i = 2; i <= n; i++)
728    {
729  0 e[i - 2] = e[i - 1];
730    }
731   
732  0 e[n - 1] = 0.0;
733   
734  0 for (l = 1; l <= n; l++)
735    {
736  0 iter = 0;
737   
738  0 do
739    {
740  0 for (m = l; m <= (n - 1); m++)
741    {
742  0 dd = Math.abs(d[m - 1]) + Math.abs(d[m]);
743   
744  0 if ((Math.abs(e[m - 1]) + dd) == dd)
745    {
746  0 break;
747    }
748    }
749   
750  0 if (m != l)
751    {
752  0 iter++;
753   
754  0 if (iter == MAX_ITER)
755    {
756  0 throw new Exception(MessageManager.formatMessage(
757    "exception.matrix_too_many_iteration", new String[]
758    { "tqli2", Integer.valueOf(MAX_ITER).toString() }));
759    }
760    else
761    {
762    // jalview.bin.Console.outPrintln("Iteration " + iter);
763    }
764   
765  0 g = (d[l] - d[l - 1]) / (2.0 * e[l - 1]);
766  0 r = Math.sqrt((g * g) + 1.0);
767  0 g = d[m - 1] - d[l - 1] + (e[l - 1] / (g + sign(r, g)));
768  0 c = 1.0;
769  0 s = c;
770  0 p = 0.0;
771   
772  0 for (i = m - 1; i >= l; i--)
773    {
774  0 f = s * e[i - 1];
775  0 b = c * e[i - 1];
776   
777  0 if (Math.abs(f) >= Math.abs(g))
778    {
779  0 c = g / f;
780  0 r = Math.sqrt((c * c) + 1.0);
781  0 e[i] = f * r;
782  0 s = 1.0 / r;
783  0 c *= s;
784    }
785    else
786    {
787  0 s = f / g;
788  0 r = Math.sqrt((s * s) + 1.0);
789  0 e[i] = g * r;
790  0 c = 1.0 / r;
791  0 s *= c;
792    }
793   
794  0 g = d[i] - p;
795  0 r = ((d[i - 1] - g) * s) + (2.0 * c * b);
796  0 p = s * r;
797  0 d[i] = g + p;
798  0 g = (c * r) - b;
799   
800  0 for (k = 1; k <= n; k++)
801    {
802  0 f = value[k - 1][i];
803  0 value[k - 1][i] = (s * value[k - 1][i - 1]) + (c * f);
804  0 value[k - 1][i - 1] = (c * value[k - 1][i - 1]) - (s * f);
805    }
806    }
807   
808  0 d[l - 1] = d[l - 1] - p;
809  0 e[l - 1] = g;
810  0 e[m - 1] = 0.0;
811    }
812  0 } while (m != l);
813    }
814    }
815   
816    /**
817    * Answers the first argument with the sign of the second argument
818    *
819    * @param a
820    * @param b
821    *
822    * @return
823    */
 
824  0 toggle static double sign(double a, double b)
825    {
826  0 if (b < 0)
827    {
828  0 return -Math.abs(a);
829    }
830    else
831    {
832  0 return Math.abs(a);
833    }
834    }
835   
836    /**
837    * returns the matrix as a double[][] array
838    *
839    * @return
840    */
 
841  0 toggle @Override
842    public double[][] asArray()
843    {
844  0 return value;
845    }
846   
847    /**
848    * Returns an array containing the values in the specified column
849    *
850    * @param col
851    *
852    * @return
853    */
 
854  0 toggle @Override
855    public double[] getColumn(int col)
856    {
857  0 double[] out = new double[rows];
858   
859  0 for (int i = 0; i < rows; i++)
860    {
861  0 out[i] = value[i][col];
862    }
863   
864  0 return out;
865    }
866   
867    /**
868    * DOCUMENT ME!
869    *
870    * @param ps
871    * DOCUMENT ME!
872    * @param format
873    */
 
874  0 toggle @Override
875    public void printD(PrintStream ps, String format)
876    {
877  0 for (int j = 0; j < d.length; j++)
878    {
879  0 Format.print(ps, format, d[j]);
880    }
881    }
882   
883    /**
884    * DOCUMENT ME!
885    *
886    * @param ps
887    * DOCUMENT ME!
888    * @param format
889    * TODO
890    */
 
891  0 toggle @Override
892    public void printE(PrintStream ps, String format)
893    {
894  0 for (int j = 0; j < rows; j++)
895    {
896  0 Format.print(ps, format, e[j]);
897    }
898    }
899   
 
900  0 toggle @Override
901    public double[] getD()
902    {
903  0 return d;
904    }
905   
 
906  0 toggle @Override
907    public double[] getE()
908    {
909  0 return e;
910    }
911   
 
912  0 toggle @Override
913    public int height()
914    {
915  0 return rows;
916    }
917   
 
918  0 toggle @Override
919    public int width()
920    {
921  0 return cols;
922    }
923   
 
924  0 toggle @Override
925    public double[] getRow(int i)
926    {
927  0 double[] row = new double[cols];
928  0 System.arraycopy(value[i], 0, row, 0, cols);
929  0 return row;
930    }
931   
932    /**
933    * Returns a length 2 array of {minValue, maxValue} of all values in the
934    * matrix. Returns null if the matrix is null or empty.
935    *
936    * @return
937    */
 
938  0 toggle double[] findMinMax()
939    {
940  0 if (value == null)
941    {
942  0 return null;
943    }
944  0 double min = Double.MAX_VALUE;
945  0 double max = -Double.MAX_VALUE;
946  0 boolean empty = true;
947  0 for (double[] row : value)
948    {
949  0 if (row != null)
950    {
951  0 for (double x : row)
952    {
953  0 empty = false;
954  0 if (x > max)
955    {
956  0 max = x;
957    }
958  0 if (x < min)
959    {
960  0 min = x;
961    }
962    }
963    }
964    }
965  0 return empty ? null : new double[] { min, max };
966    }
967   
968    /**
969    * {@inheritDoc}
970    */
 
971  0 toggle @Override
972    public void reverseRange(boolean maxToZero)
973    {
974  0 if (value == null)
975    {
976  0 return;
977    }
978  0 double[] minMax = findMinMax();
979  0 if (minMax == null)
980    {
981  0 return; // empty matrix
982    }
983  0 double subtractFrom = maxToZero ? minMax[1] : minMax[0] + minMax[1];
984   
985  0 for (double[] row : value)
986    {
987  0 if (row != null)
988    {
989  0 int j = 0;
990  0 for (double x : row)
991    {
992  0 row[j] = subtractFrom - x;
993  0 j++;
994    }
995    }
996    }
997    }
998   
999    /**
1000    * Multiplies every entry in the matrix by the given value.
1001    *
1002    * @param
1003    */
 
1004  0 toggle @Override
1005    public void multiply(double by)
1006    {
1007  0 for (double[] row : value)
1008    {
1009  0 if (row != null)
1010    {
1011  0 for (int i = 0; i < row.length; i++)
1012    {
1013  0 row[i] *= by;
1014    }
1015    }
1016    }
1017    }
1018   
1019    /**
1020    * Add d to all entries of this matrix
1021    *
1022    * @param d
1023    * ~ value to add
1024    */
 
1025  0 toggle @Override
1026    public void add(double d)
1027    {
1028  0 for (double[] row : value)
1029    {
1030  0 if (row != null)
1031    {
1032  0 for (int i = 0; i < row.length; i++)
1033    {
1034  0 row[i] += d;
1035    }
1036    }
1037    }
1038    }
1039   
 
1040  0 toggle @Override
1041    public void setD(double[] v)
1042    {
1043  0 d = v;
1044    }
1045   
 
1046  0 toggle @Override
1047    public void setE(double[] v)
1048    {
1049  0 e = v;
1050    }
1051   
 
1052  0 toggle public double getTotal()
1053    {
1054  0 double d = 0d;
1055  0 for (int i = 0; i < this.height(); i++)
1056    {
1057  0 for (int j = 0; j < this.width(); j++)
1058    {
1059  0 d += value[i][j];
1060    }
1061    }
1062  0 return d;
1063    }
1064   
1065    /**
1066    * {@inheritDoc}
1067    */
 
1068  0 toggle @Override
1069    public boolean equals(MatrixI m2, double delta)
1070    {
1071  0 if (m2 == null || this.height() != m2.height()
1072    || this.width() != m2.width())
1073    {
1074  0 return false;
1075    }
1076  0 for (int i = 0; i < this.height(); i++)
1077    {
1078  0 for (int j = 0; j < this.width(); j++)
1079    {
1080  0 double diff = this.getValue(i, j) - m2.getValue(i, j);
1081  0 if (Math.abs(diff) > delta)
1082    {
1083  0 return false;
1084    }
1085    }
1086    }
1087  0 return true;
1088    }
1089   
1090    /**
1091    * Returns a copy in which every value in the matrix is its absolute
1092    *
1093    * @return
1094    */
 
1095  0 toggle @Override
1096    public MatrixI absolute()
1097    {
1098  0 MatrixI copy = this.copy();
1099  0 for (int i = 0; i < copy.width(); i++)
1100    {
1101  0 double[] row = copy.getRow(i);
1102  0 if (row != null)
1103    {
1104  0 for (int j = 0; j < row.length; j++)
1105    {
1106  0 row[j] = Math.abs(row[j]);
1107    }
1108    }
1109    }
1110  0 return copy;
1111    }
1112   
1113    /**
1114    * Returns the mean of each row
1115    *
1116    * @return
1117    */
 
1118  0 toggle @Override
1119    public double[] meanRow()
1120    {
1121  0 double[] mean = new double[rows];
1122  0 int i = 0;
1123  0 for (double[] row : value)
1124    {
1125  0 if (row != null)
1126    {
1127  0 mean[i++] = MiscMath.mean(row);
1128    }
1129    }
1130  0 return mean;
1131    }
1132   
1133    /**
1134    * Returns the mean of each column
1135    *
1136    * @return
1137    */
 
1138  0 toggle @Override
1139    public double[] meanCol()
1140    {
1141  0 double[] mean = new double[cols];
1142  0 for (int j = 0; j < cols; j++)
1143    {
1144  0 double[] column = getColumn(j);
1145  0 if (column != null)
1146    {
1147  0 mean[j] = MiscMath.mean(column);
1148    }
1149    }
1150  0 return mean;
1151    }
1152   
1153    /**
1154    * return a flattened matrix containing the sum of each column
1155    *
1156    * @return
1157    */
 
1158  0 toggle @Override
1159    public double[] sumCol()
1160    {
1161  0 double[] sum = new double[cols];
1162  0 for (int j = 0; j < cols; j++)
1163    {
1164  0 double[] column = getColumn(j);
1165  0 if (column != null)
1166    {
1167  0 sum[j] = MiscMath.sum(column);
1168    }
1169    }
1170  0 return sum;
1171    }
1172   
1173    /**
1174    * returns the mean value of the complete matrix
1175    *
1176    * @return
1177    */
 
1178  0 toggle @Override
1179    public double mean()
1180    {
1181  0 double sum = 0;
1182  0 int nanCount = 0;
1183  0 for (double[] row : value)
1184    {
1185  0 for (double col : row)
1186    {
1187  0 if (!Double.isNaN(col))
1188    {
1189  0 sum += col;
1190    }
1191    else
1192    {
1193  0 nanCount++;
1194    }
1195    }
1196    }
1197  0 return sum / (double) (this.rows * this.cols - nanCount);
1198    }
1199   
1200    /**
1201    * fills up a diagonal matrix with its transposed copy !other side should be
1202    * filled with 0 !keeps Double.NaN found in either side
1203    *
1204    * TODO check on which side it was diagonal and only do calculations for the
1205    * other side
1206    */
 
1207  0 toggle @Override
1208    public void fillDiagonal()
1209    {
1210  0 int n = this.rows;
1211  0 int m = this.cols;
1212  0 MatrixI copy = this.transpose(); // goes through each element in the matrix
1213    // and
1214  0 for (int i = 0; i < n; i++) // adds the value in the transposed copy to the
1215    // original value
1216    {
1217  0 for (int j = 0; j < m; j++)
1218    {
1219  0 if (i != j)
1220    {
1221  0 this.addValue(i, j, copy.getValue(i, j));
1222    }
1223    }
1224    }
1225    }
1226   
1227    /**
1228    * counts the number of Double.NaN in the matrix
1229    *
1230    * @return
1231    */
 
1232  0 toggle @Override
1233    public int countNaN()
1234    {
1235  0 int NaN = 0;
1236  0 for (int i = 0; i < this.rows; i++)
1237    {
1238  0 for (int j = 0; j < this.cols; j++)
1239    {
1240  0 if (Double.isNaN(this.getValue(i, j)))
1241    {
1242  0 NaN++;
1243    }
1244    }
1245    }
1246  0 return NaN;
1247    }
1248   
1249    /**
1250    * performs an element-wise addition of this matrix by another matrix ~ this -
1251    * m
1252    *
1253    * @param m
1254    * ~ other matrix
1255    *
1256    * @return
1257    */
 
1258  0 toggle @Override
1259    public MatrixI add(MatrixI m)
1260    {
1261  0 if (m.width() != cols || m.height() != rows)
1262    {
1263  0 throw new IllegalArgumentException(
1264    "Can't add a " + m.height() + "x" + m.width() + " to a "
1265    + this.rows + "x" + this.cols + " matrix");
1266    }
1267  0 double[][] tmp = new double[this.rows][this.cols];
1268  0 for (int i = 0; i < this.rows; i++)
1269    {
1270  0 for (int j = 0; j < this.cols; j++)
1271    {
1272  0 tmp[i][j] = this.getValue(i, j) + m.getValue(i, j);
1273    }
1274    }
1275  0 return new Matrix(tmp);
1276    }
1277   
1278    /**
1279    * performs an element-wise subtraction of this matrix by another matrix ~
1280    * this - m
1281    *
1282    * @param m
1283    * ~ other matrix
1284    *
1285    * @return
1286    */
 
1287  0 toggle @Override
1288    public MatrixI subtract(MatrixI m)
1289    {
1290  0 if (m.width() != cols || m.height() != rows)
1291    {
1292  0 throw new IllegalArgumentException("Can't subtract a " + m.height()
1293    + "x" + m.width() + " from a " + this.rows + "x" + this.cols
1294    + " matrix");
1295    }
1296  0 double[][] tmp = new double[this.rows][this.cols];
1297  0 for (int i = 0; i < this.rows; i++)
1298    {
1299  0 for (int j = 0; j < this.cols; j++)
1300    {
1301  0 tmp[i][j] = this.getValue(i, j) - m.getValue(i, j);
1302    }
1303    }
1304  0 return new Matrix(tmp);
1305    }
1306   
1307    /**
1308    * performs an element-wise multiplication of this matrix by another matrix ~
1309    * this * m
1310    *
1311    * @param m
1312    * ~ other matrix
1313    *
1314    * @return
1315    */
 
1316  0 toggle @Override
1317    public MatrixI elementwiseMultiply(MatrixI m)
1318    {
1319  0 if (m.width() != cols || m.height() != rows)
1320    {
1321  0 throw new IllegalArgumentException(
1322    "Can't multiply a " + this.rows + "x" + this.cols + " by a "
1323    + m.height() + "x" + m.width() + " matrix");
1324    }
1325  0 double[][] tmp = new double[this.rows][this.cols];
1326  0 for (int i = 0; i < this.rows; i++)
1327    {
1328  0 for (int j = 0; j < this.cols; j++)
1329    {
1330  0 tmp[i][j] = this.getValue(i, j) * m.getValue(i, j);
1331    }
1332    }
1333  0 return new Matrix(tmp);
1334    }
1335   
1336    /**
1337    * performs an element-wise division of this matrix by another matrix ~ this /
1338    * m
1339    *
1340    * @param m
1341    * ~ other matrix
1342    *
1343    * @return
1344    */
 
1345  0 toggle @Override
1346    public MatrixI elementwiseDivide(MatrixI m)
1347    {
1348  0 if (m.width() != cols || m.height() != rows)
1349    {
1350  0 throw new IllegalArgumentException(
1351    "Can't divide a " + this.rows + "x" + this.cols + " by a "
1352    + m.height() + "x" + m.width() + " matrix");
1353    }
1354  0 double[][] tmp = new double[this.rows][this.cols];
1355  0 for (int i = 0; i < this.rows; i++)
1356    {
1357  0 for (int j = 0; j < this.cols; j++)
1358    {
1359  0 tmp[i][j] = this.getValue(i, j) / m.getValue(i, j);
1360    }
1361    }
1362  0 return new Matrix(tmp);
1363    }
1364   
1365    /**
1366    * calculate the root-mean-square for tow matrices
1367    *
1368    * @param m
1369    * ~ other matrix
1370    *
1371    * @return
1372    */
 
1373  0 toggle @Override
1374    public double rmsd(MatrixI m)
1375    {
1376  0 MatrixI squaredDeviates = this.subtract(m);
1377  0 squaredDeviates = squaredDeviates.preMultiply(squaredDeviates);
1378  0 return Math.sqrt(squaredDeviates.mean());
1379    }
1380   
1381    /**
1382    * calculates the Frobenius norm of this matrix
1383    *
1384    * @return
1385    */
 
1386  0 toggle @Override
1387    public double norm()
1388    {
1389  0 double result = 0;
1390  0 for (double[] row : value)
1391    {
1392  0 for (double val : row)
1393    {
1394  0 result += Math.pow(val, 2);
1395    }
1396    }
1397  0 return Math.sqrt(result);
1398    }
1399   
1400    /**
1401    * returns the sum of all values in this matrix
1402    *
1403    * @return
1404    */
 
1405  0 toggle @Override
1406    public double sum()
1407    {
1408  0 double sum = 0;
1409  0 for (double[] row : value)
1410    {
1411  0 for (double val : row)
1412    {
1413  0 sum += (Double.isNaN(val)) ? 0.0 : val;
1414    }
1415    }
1416  0 return sum;
1417    }
1418   
1419    /**
1420    * returns the sum-product of this matrix with vector v
1421    *
1422    * @param v
1423    * ~ vector
1424    *
1425    * @return
1426    */
 
1427  0 toggle @Override
1428    public double[] sumProduct(double[] v)
1429    {
1430  0 if (v.length != cols)
1431    {
1432  0 throw new IllegalArgumentException(
1433    "Vector and matrix do not have the same dimension! ("
1434    + v.length + " != " + cols + ")");
1435    }
1436  0 double[] result = new double[rows];
1437  0 for (int i = 0; i < rows; i++)
1438    {
1439  0 double[] row = value[i];
1440  0 double sum = 0;
1441  0 for (int j = 0; j < row.length; j++)
1442    {
1443  0 sum += row[j] * v[j];
1444    }
1445  0 result[i] = sum;
1446    }
1447  0 return result;
1448    }
1449   
1450    /**
1451    * mirrors columns of the matrix
1452    *
1453    * @return
1454    */
 
1455  0 toggle @Override
1456    public MatrixI mirrorCol()
1457    {
1458  0 double[][] result = new double[rows][cols];
1459  0 for (int i = 0; i < rows; i++)
1460    {
1461  0 int k = cols - 1; // reverse col
1462  0 for (int j = 0; j < cols; j++)
1463    {
1464  0 result[i][k--] = this.getValue(i, j);
1465    }
1466    }
1467  0 MatrixI resultMatrix = new Matrix(result);
1468  0 if (d != null)
1469  0 resultMatrix.setD(d);
1470  0 if (e != null)
1471  0 resultMatrix.setE(e);
1472   
1473  0 return resultMatrix;
1474    }
1475    }