Clover icon

Coverage Report

  1. Project Clover database Thu Nov 7 2024 13:01:17 GMT
  2. Package jalview.math

File Matrix.java

 

Coverage histogram

../../img/srcFileCovDistChart4.png
48% 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.4093137440.9%
 

Contributing tests

This file is covered by 38 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  22 toggle protected Matrix(int rowCount, int colCount)
67    {
68  22 rows = rowCount;
69  22 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  82 toggle public Matrix(double[][] values)
91    {
92  82 this.rows = values.length;
93  82 this.cols = this.rows == 0 ? 0 : values[0].length;
94   
95    /*
96    * make a copy of the values array, for immutability
97    */
98  82 this.value = new double[rows][];
99  82 int i = 0;
100  82 for (double[] row : values)
101    {
102  1350 if (row != null)
103    {
104  1350 value[i] = new double[row.length];
105  1350 System.arraycopy(row, 0, value[i], 0, row.length);
106    }
107  1350 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  10 toggle @Override
175    public MatrixI preMultiply(MatrixI in)
176    {
177  10 if (in.width() != rows)
178    {
179  2 throw new IllegalArgumentException("Can't pre-multiply " + this.rows
180    + " rows by " + in.width() + " columns");
181    }
182  8 double[][] tmp = new double[in.height()][this.cols];
183   
184  22 for (int i = 0; i < in.height(); i++)
185    {
186  48 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  86 for (int k = 0; k < in.width(); k++)
193    {
194  52 if (!Double.isNaN(in.getValue(i, k))
195    && !Double.isNaN(this.value[k][j]))
196    {
197  52 tmp[i][j] += (in.getValue(i, k) * this.value[k][j]);
198    }
199    }
200    }
201    }
202   
203  8 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  6 toggle @Override
230    public MatrixI postMultiply(MatrixI in)
231    {
232  6 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  6 return in.preMultiply(this);
238    }
239   
 
240  10 toggle @Override
241    public MatrixI copy()
242    {
243  10 double[][] newmat = new double[rows][cols];
244   
245  62 for (int i = 0; i < rows; i++)
246    {
247  52 System.arraycopy(value[i], 0, newmat[i], 0, value[i].length);
248    }
249   
250  10 Matrix m = new Matrix(newmat);
251  10 if (this.d != null)
252    {
253  2 m.d = Arrays.copyOf(this.d, this.d.length);
254    }
255  10 if (this.e != null)
256    {
257  2 m.e = Arrays.copyOf(this.e, this.e.length);
258    }
259   
260  10 return m;
261    }
262   
263    /**
264    * DOCUMENT ME!
265    */
 
266  9 toggle @Override
267    public void tred()
268    {
269  9 int n = rows;
270  9 int k;
271  9 int j;
272  9 int i;
273   
274  9 double scale;
275  9 double hh;
276  9 double h;
277  9 double g;
278  9 double f;
279   
280  9 this.d = new double[rows];
281  9 this.e = new double[rows];
282   
283  87 for (i = n; i >= 2; i--)
284    {
285  78 final int l = i - 1;
286  78 h = 0.0;
287  78 scale = 0.0;
288   
289  78 if (l > 1)
290    {
291  465 for (k = 1; k <= l; k++)
292    {
293  396 double v = Math.abs(getValue(i - 1, k - 1));
294  396 scale += v;
295    }
296   
297  69 if (scale == 0.0)
298    {
299  0 e[i - 1] = getValue(i - 1, l - 1);
300    }
301    else
302    {
303  465 for (k = 1; k <= l; k++)
304    {
305  396 double v = divideValue(i - 1, k - 1, scale);
306  396 h += v * v;
307    }
308   
309  69 f = getValue(i - 1, l - 1);
310   
311  69 if (f > 0)
312    {
313  26 g = -1.0 * Math.sqrt(h);
314    }
315    else
316    {
317  43 g = Math.sqrt(h);
318    }
319   
320  69 e[i - 1] = scale * g;
321  69 h -= (f * g);
322  69 setValue(i - 1, l - 1, f - g);
323  69 f = 0.0;
324   
325  465 for (j = 1; j <= l; j++)
326    {
327  396 double val = getValue(i - 1, j - 1) / h;
328  396 setValue(j - 1, i - 1, val);
329  396 g = 0.0;
330   
331  2007 for (k = 1; k <= j; k++)
332    {
333  1611 g += (getValue(j - 1, k - 1) * getValue(i - 1, k - 1));
334    }
335   
336  1611 for (k = j + 1; k <= l; k++)
337    {
338  1215 g += (getValue(k - 1, j - 1) * getValue(i - 1, k - 1));
339    }
340   
341  396 e[j - 1] = g / h;
342  396 f += (e[j - 1] * getValue(i - 1, j - 1));
343    }
344   
345  69 hh = f / (h + h);
346   
347  465 for (j = 1; j <= l; j++)
348    {
349  396 f = getValue(i - 1, j - 1);
350  396 g = e[j - 1] - (hh * f);
351  396 e[j - 1] = g;
352   
353  2007 for (k = 1; k <= j; k++)
354    {
355  1611 double val = (f * e[k - 1]) + (g * getValue(i - 1, k - 1));
356  1611 addValue(j - 1, k - 1, -val);
357    }
358    }
359    }
360    }
361    else
362    {
363  9 e[i - 1] = getValue(i - 1, l - 1);
364    }
365   
366  78 d[i - 1] = h;
367    }
368   
369  9 d[0] = 0.0;
370  9 e[0] = 0.0;
371   
372  96 for (i = 1; i <= n; i++)
373    {
374  87 final int l = i - 1;
375   
376  87 if (d[i - 1] != 0.0)
377    {
378  465 for (j = 1; j <= l; j++)
379    {
380  396 g = 0.0;
381   
382  3222 for (k = 1; k <= l; k++)
383    {
384  2826 g += (getValue(i - 1, k - 1) * getValue(k - 1, j - 1));
385    }
386   
387  3222 for (k = 1; k <= l; k++)
388    {
389  2826 addValue(k - 1, j - 1, -(g * getValue(k - 1, i - 1)));
390    }
391    }
392    }
393   
394  87 d[i - 1] = getValue(i - 1, i - 1);
395  87 setValue(i - 1, i - 1, 1.0);
396   
397  492 for (j = 1; j <= l; j++)
398    {
399  405 setValue(j - 1, i - 1, 0.0);
400  405 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  3005 toggle protected double addValue(int i, int j, double f)
413    {
414  3005 double v = value[i][j] + f;
415  3005 value[i][j] = v;
416  3005 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  250 toggle protected double divideValue(int i, int j, double divisor)
429    {
430  250 if (divisor == 0d)
431    {
432  0 return getValue(i, j);
433    }
434  250 double v = value[i][j];
435  250 v = v / divisor;
436  250 value[i][j] = v;
437  250 return v;
438    }
439   
440    /**
441    * DOCUMENT ME!
442    */
 
443  3 toggle @Override
444    public void tqli() throws Exception
445    {
446  3 int n = rows;
447   
448  3 int m;
449  3 int l;
450  3 int iter;
451  3 int i;
452  3 int k;
453  3 double s;
454  3 double r;
455  3 double p;
456   
457  3 double g;
458  3 double f;
459  3 double dd;
460  3 double c;
461  3 double b;
462   
463  27 for (i = 2; i <= n; i++)
464    {
465  24 e[i - 2] = e[i - 1];
466    }
467   
468  3 e[n - 1] = 0.0;
469   
470  30 for (l = 1; l <= n; l++)
471    {
472  27 iter = 0;
473   
474  27 do
475    {
476  371 for (m = l; m <= (n - 1); m++)
477    {
478  325 dd = Math.abs(d[m - 1]) + Math.abs(d[m]);
479   
480  325 if ((Math.abs(e[m - 1]) + dd) == dd)
481    {
482  27 break;
483    }
484    }
485   
486  73 if (m != l)
487    {
488  46 iter++;
489   
490  46 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  46 g = (d[l] - d[l - 1]) / (2.0 * e[l - 1]);
502  46 r = Math.sqrt((g * g) + 1.0);
503  46 g = d[m - 1] - d[l - 1] + (e[l - 1] / (g + sign(r, g)));
504  46 c = 1.0;
505  46 s = c;
506  46 p = 0.0;
507   
508  344 for (i = m - 1; i >= l; i--)
509    {
510  298 f = s * e[i - 1];
511  298 b = c * e[i - 1];
512   
513  298 if (Math.abs(f) >= Math.abs(g))
514    {
515  34 c = g / f;
516  34 r = Math.sqrt((c * c) + 1.0);
517  34 e[i] = f * r;
518  34 s = 1.0 / r;
519  34 c *= s;
520    }
521    else
522    {
523  264 s = f / g;
524  264 r = Math.sqrt((s * s) + 1.0);
525  264 e[i] = g * r;
526  264 c = 1.0 / r;
527  264 s *= c;
528    }
529   
530  298 g = d[i] - p;
531  298 r = ((d[i - 1] - g) * s) + (2.0 * c * b);
532  298 p = s * r;
533  298 d[i] = g + p;
534  298 g = (c * r) - b;
535   
536  4228 for (k = 1; k <= n; k++)
537    {
538  3930 f = getValue(k - 1, i);
539  3930 setValue(k - 1, i, (s * getValue(k - 1, i - 1)) + (c * f));
540  3930 setValue(k - 1, i - 1,
541    (c * getValue(k - 1, i - 1)) - (s * f));
542    }
543    }
544   
545  46 d[l - 1] = d[l - 1] - p;
546  46 e[l - 1] = g;
547  46 e[m - 1] = 0.0;
548    }
549  73 } while (m != l);
550    }
551    }
552   
 
553  71178 toggle @Override
554    public double getValue(int i, int j)
555    {
556  71178 return value[i][j];
557    }
558   
 
559  19083 toggle @Override
560    public void setValue(int i, int j, double val)
561    {
562  19083 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  46 toggle static double sign(double a, double b)
825    {
826  46 if (b < 0)
827    {
828  12 return -Math.abs(a);
829    }
830    else
831    {
832  34 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  72 toggle @Override
901    public double[] getD()
902    {
903  72 return d;
904    }
905   
 
906  27 toggle @Override
907    public double[] getE()
908    {
909  27 return e;
910    }
911   
 
912  346 toggle @Override
913    public int height()
914    {
915  346 return rows;
916    }
917   
 
918  2450 toggle @Override
919    public int width()
920    {
921  2450 return cols;
922    }
923   
 
924  26 toggle @Override
925    public double[] getRow(int i)
926    {
927  26 double[] row = new double[cols];
928  26 System.arraycopy(value[i], 0, row, 0, cols);
929  26 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  13 toggle double[] findMinMax()
939    {
940  13 if (value == null)
941    {
942  0 return null;
943    }
944  13 double min = Double.MAX_VALUE;
945  13 double max = -Double.MAX_VALUE;
946  13 boolean empty = true;
947  13 for (double[] row : value)
948    {
949  1023 if (row != null)
950    {
951  1023 for (double x : row)
952    {
953  1000054 empty = false;
954  1000054 if (x > max)
955    {
956  40 max = x;
957    }
958  1000054 if (x < min)
959    {
960  38 min = x;
961    }
962    }
963    }
964    }
965  13 return empty ? null : new double[] { min, max };
966    }
967   
968    /**
969    * {@inheritDoc}
970    */
 
971  10 toggle @Override
972    public void reverseRange(boolean maxToZero)
973    {
974  10 if (value == null)
975    {
976  0 return;
977    }
978  10 double[] minMax = findMinMax();
979  10 if (minMax == null)
980    {
981  0 return; // empty matrix
982    }
983  10 double subtractFrom = maxToZero ? minMax[1] : minMax[0] + minMax[1];
984   
985  10 for (double[] row : value)
986    {
987  20 if (row != null)
988    {
989  20 int j = 0;
990  20 for (double x : row)
991    {
992  48 row[j] = subtractFrom - x;
993  48 j++;
994    }
995    }
996    }
997    }
998   
999    /**
1000    * Multiplies every entry in the matrix by the given value.
1001    *
1002    * @param
1003    */
 
1004  1 toggle @Override
1005    public void multiply(double by)
1006    {
1007  1 for (double[] row : value)
1008    {
1009  2 if (row != null)
1010    {
1011  8 for (int i = 0; i < row.length; i++)
1012    {
1013  6 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  2 toggle @Override
1041    public void setD(double[] v)
1042    {
1043  2 d = v;
1044    }
1045   
 
1046  2 toggle @Override
1047    public void setE(double[] v)
1048    {
1049  2 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  12 toggle @Override
1069    public boolean equals(MatrixI m2, double delta)
1070    {
1071  12 if (m2 == null || this.height() != m2.height()
1072    || this.width() != m2.width())
1073    {
1074  2 return false;
1075    }
1076  27 for (int i = 0; i < this.height(); i++)
1077    {
1078  66 for (int j = 0; j < this.width(); j++)
1079    {
1080  49 double diff = this.getValue(i, j) - m2.getValue(i, j);
1081  49 if (Math.abs(diff) > delta)
1082    {
1083  3 return false;
1084    }
1085    }
1086    }
1087  7 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    }