Clover icon

jalviewX

  1. Project Clover database Wed Oct 31 2018 15:13:58 GMT
  2. Package jalview.math

File Matrix.java

 

Coverage histogram

../../img/srcFileCovDistChart6.png
35% of files have more coverage

Code metrics

168
353
28
1
998
682
112
0.32
12.61
28
4

Classes

Class Line # Actions
Matrix 31 353 112 249
0.546448154.6%
 

Contributing tests

This file is covered by 29 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   
28    /**
29    * A class to model rectangular matrices of double values and operations on them
30    */
 
31    public class Matrix implements MatrixI
32    {
33    /*
34    * the cell values in row-major order
35    */
36    private double[][] value;
37   
38    /*
39    * the number of rows
40    */
41    protected int rows;
42   
43    /*
44    * the number of columns
45    */
46    protected int cols;
47   
48    protected double[] d; // Diagonal
49   
50    protected double[] e; // off diagonal
51   
52    /**
53    * maximum number of iterations for tqli
54    *
55    */
56    private static final int maxIter = 45; // fudge - add 15 iterations, just in
57    // case
58   
59    /**
60    * Default constructor
61    */
 
62  22 toggle public Matrix()
63    {
64   
65    }
66   
67    /**
68    * Creates a new Matrix object containing a copy of the supplied array values.
69    * For example
70    *
71    * <pre>
72    * new Matrix(new double[][] {{2, 3, 4}, {5, 6, 7})
73    * constructs
74    * (2 3 4)
75    * (5 6 7)
76    * </pre>
77    *
78    * Note that ragged arrays (with not all rows, or columns, of the same
79    * length), are not supported by this class. They can be constructed, but
80    * results of operations on them are undefined and may throw exceptions.
81    *
82    * @param values
83    * the matrix values in row-major order
84    */
 
85  47 toggle public Matrix(double[][] values)
86    {
87  47 this.rows = values.length;
88  47 this.cols = this.rows == 0 ? 0 : values[0].length;
89   
90    /*
91    * make a copy of the values array, for immutability
92    */
93  47 this.value = new double[rows][];
94  47 int i = 0;
95  47 for (double[] row : values)
96    {
97  1131 if (row != null)
98    {
99  1131 value[i] = new double[row.length];
100  1131 System.arraycopy(row, 0, value[i], 0, row.length);
101    }
102  1131 i++;
103    }
104    }
105   
106    /**
107    * Returns a new matrix which is the transpose of this one
108    *
109    * @return
110    */
 
111  0 toggle @Override
112    public MatrixI transpose()
113    {
114  0 double[][] out = new double[cols][rows];
115   
116  0 for (int i = 0; i < cols; i++)
117    {
118  0 for (int j = 0; j < rows; j++)
119    {
120  0 out[i][j] = value[j][i];
121    }
122    }
123   
124  0 return new Matrix(out);
125    }
126   
127    /**
128    * DOCUMENT ME!
129    *
130    * @param ps
131    * DOCUMENT ME!
132    * @param format
133    */
 
134  0 toggle @Override
135    public void print(PrintStream ps, String format)
136    {
137  0 for (int i = 0; i < rows; i++)
138    {
139  0 for (int j = 0; j < cols; j++)
140    {
141  0 Format.print(ps, format, getValue(i, j));
142    }
143   
144  0 ps.println();
145    }
146    }
147   
148    /**
149    * Returns a new matrix which is the result of premultiplying this matrix by
150    * the supplied argument. If this of size AxB (A rows and B columns), and the
151    * argument is CxA (C rows and A columns), the result is of size CxB.
152    *
153    * @param in
154    *
155    * @return
156    * @throws IllegalArgumentException
157    * if the number of columns in the pre-multiplier is not equal to
158    * the number of rows in the multiplicand (this)
159    */
 
160  10 toggle @Override
161    public MatrixI preMultiply(MatrixI in)
162    {
163  10 if (in.width() != rows)
164    {
165  2 throw new IllegalArgumentException("Can't pre-multiply " + this.rows
166    + " rows by " + in.width() + " columns");
167    }
168  8 double[][] tmp = new double[in.height()][this.cols];
169   
170  22 for (int i = 0; i < in.height(); i++)
171    {
172  48 for (int j = 0; j < this.cols; j++)
173    {
174    /*
175    * result[i][j] is the vector product of
176    * in.row[i] and this.column[j]
177    */
178  86 for (int k = 0; k < in.width(); k++)
179    {
180  52 tmp[i][j] += (in.getValue(i, k) * this.value[k][j]);
181    }
182    }
183    }
184   
185  8 return new Matrix(tmp);
186    }
187   
188    /**
189    *
190    * @param in
191    *
192    * @return
193    */
 
194  0 toggle public double[] vectorPostMultiply(double[] in)
195    {
196  0 double[] out = new double[in.length];
197   
198  0 for (int i = 0; i < in.length; i++)
199    {
200  0 out[i] = 0.0;
201   
202  0 for (int k = 0; k < in.length; k++)
203    {
204  0 out[i] += (value[i][k] * in[k]);
205    }
206    }
207   
208  0 return out;
209    }
210   
211    /**
212    * Returns a new matrix which is the result of postmultiplying this matrix by
213    * the supplied argument. If this of size AxB (A rows and B columns), and the
214    * argument is BxC (B rows and C columns), the result is of size AxC.
215    * <p>
216    * This method simply returns the result of in.preMultiply(this)
217    *
218    * @param in
219    *
220    * @return
221    * @throws IllegalArgumentException
222    * if the number of rows in the post-multiplier is not equal to the
223    * number of columns in the multiplicand (this)
224    * @see #preMultiply(Matrix)
225    */
 
226  6 toggle @Override
227    public MatrixI postMultiply(MatrixI in)
228    {
229  6 if (in.height() != this.cols)
230    {
231  0 throw new IllegalArgumentException("Can't post-multiply " + this.cols
232    + " columns by " + in.height() + " rows");
233    }
234  6 return in.preMultiply(this);
235    }
236   
237    /**
238    * Answers a new matrix with a copy of the values in this one
239    *
240    * @return
241    */
 
242  1 toggle @Override
243    public MatrixI copy()
244    {
245  1 double[][] newmat = new double[rows][cols];
246   
247  6 for (int i = 0; i < rows; i++)
248    {
249  5 System.arraycopy(value[i], 0, newmat[i], 0, value[i].length);
250    }
251   
252  1 return new Matrix(newmat);
253    }
254   
255    /**
256    * DOCUMENT ME!
257    */
 
258  8 toggle @Override
259    public void tred()
260    {
261  8 int n = rows;
262  8 int k;
263  8 int j;
264  8 int i;
265   
266  8 double scale;
267  8 double hh;
268  8 double h;
269  8 double g;
270  8 double f;
271   
272  8 this.d = new double[rows];
273  8 this.e = new double[rows];
274   
275  72 for (i = n; i >= 2; i--)
276    {
277  64 final int l = i - 1;
278  64 h = 0.0;
279  64 scale = 0.0;
280   
281  64 if (l > 1)
282    {
283  348 for (k = 1; k <= l; k++)
284    {
285  292 double v = Math.abs(getValue(i - 1, k - 1));
286  292 scale += v;
287    }
288   
289  56 if (scale == 0.0)
290    {
291  0 e[i - 1] = getValue(i - 1, l - 1);
292    }
293    else
294    {
295  348 for (k = 1; k <= l; k++)
296    {
297  292 double v = divideValue(i - 1, k - 1, scale);
298  292 h += v * v;
299    }
300   
301  56 f = getValue(i - 1, l - 1);
302   
303  56 if (f > 0)
304    {
305  20 g = -1.0 * Math.sqrt(h);
306    }
307    else
308    {
309  36 g = Math.sqrt(h);
310    }
311   
312  56 e[i - 1] = scale * g;
313  56 h -= (f * g);
314  56 setValue(i - 1, l - 1, f - g);
315  56 f = 0.0;
316   
317  348 for (j = 1; j <= l; j++)
318    {
319  292 double val = getValue(i - 1, j - 1) / h;
320  292 setValue(j - 1, i - 1, val);
321  292 g = 0.0;
322   
323  1344 for (k = 1; k <= j; k++)
324    {
325  1052 g += (getValue(j - 1, k - 1) * getValue(i - 1, k - 1));
326    }
327   
328  1052 for (k = j + 1; k <= l; k++)
329    {
330  760 g += (getValue(k - 1, j - 1) * getValue(i - 1, k - 1));
331    }
332   
333  292 e[j - 1] = g / h;
334  292 f += (e[j - 1] * getValue(i - 1, j - 1));
335    }
336   
337  56 hh = f / (h + h);
338   
339  348 for (j = 1; j <= l; j++)
340    {
341  292 f = getValue(i - 1, j - 1);
342  292 g = e[j - 1] - (hh * f);
343  292 e[j - 1] = g;
344   
345  1344 for (k = 1; k <= j; k++)
346    {
347  1052 double val = (f * e[k - 1]) + (g * getValue(i - 1, k - 1));
348  1052 addValue(j - 1, k - 1, -val);
349    }
350    }
351    }
352    }
353    else
354    {
355  8 e[i - 1] = getValue(i - 1, l - 1);
356    }
357   
358  64 d[i - 1] = h;
359    }
360   
361  8 d[0] = 0.0;
362  8 e[0] = 0.0;
363   
364  80 for (i = 1; i <= n; i++)
365    {
366  72 final int l = i - 1;
367   
368  72 if (d[i - 1] != 0.0)
369    {
370  348 for (j = 1; j <= l; j++)
371    {
372  292 g = 0.0;
373   
374  2104 for (k = 1; k <= l; k++)
375    {
376  1812 g += (getValue(i - 1, k - 1) * getValue(k - 1, j - 1));
377    }
378   
379  2104 for (k = 1; k <= l; k++)
380    {
381  1812 addValue(k - 1, j - 1, -(g * getValue(k - 1, i - 1)));
382    }
383    }
384    }
385   
386  72 d[i - 1] = getValue(i - 1, i - 1);
387  72 setValue(i - 1, i - 1, 1.0);
388   
389  372 for (j = 1; j <= l; j++)
390    {
391  300 setValue(j - 1, i - 1, 0.0);
392  300 setValue(i - 1, j - 1, 0.0);
393    }
394    }
395    }
396   
397    /**
398    * Adds f to the value at [i, j] and returns the new value
399    *
400    * @param i
401    * @param j
402    * @param f
403    */
 
404  1432 toggle protected double addValue(int i, int j, double f)
405    {
406  1432 double v = value[i][j] + f;
407  1432 value[i][j] = v;
408  1432 return v;
409    }
410   
411    /**
412    * Divides the value at [i, j] by divisor and returns the new value. If d is
413    * zero, returns the unchanged value.
414    *
415    * @param i
416    * @param j
417    * @param divisor
418    * @return
419    */
 
420  146 toggle protected double divideValue(int i, int j, double divisor)
421    {
422  146 if (divisor == 0d)
423    {
424  0 return getValue(i, j);
425    }
426  146 double v = value[i][j];
427  146 v = v / divisor;
428  146 value[i][j] = v;
429  146 return v;
430    }
431   
432    /**
433    * DOCUMENT ME!
434    */
 
435  2 toggle @Override
436    public void tqli() throws Exception
437    {
438  2 int n = rows;
439   
440  2 int m;
441  2 int l;
442  2 int iter;
443  2 int i;
444  2 int k;
445  2 double s;
446  2 double r;
447  2 double p;
448   
449  2 double g;
450  2 double f;
451  2 double dd;
452  2 double c;
453  2 double b;
454   
455  12 for (i = 2; i <= n; i++)
456    {
457  10 e[i - 2] = e[i - 1];
458    }
459   
460  2 e[n - 1] = 0.0;
461   
462  14 for (l = 1; l <= n; l++)
463    {
464  12 iter = 0;
465   
466  12 do
467    {
468  92 for (m = l; m <= (n - 1); m++)
469    {
470  70 dd = Math.abs(d[m - 1]) + Math.abs(d[m]);
471   
472  70 if ((Math.abs(e[m - 1]) + dd) == dd)
473    {
474  10 break;
475    }
476    }
477   
478  32 if (m != l)
479    {
480  20 iter++;
481   
482  20 if (iter == maxIter)
483    {
484  0 throw new Exception(MessageManager.formatMessage(
485    "exception.matrix_too_many_iteration", new String[]
486    { "tqli", Integer.valueOf(maxIter).toString() }));
487    }
488    else
489    {
490    // System.out.println("Iteration " + iter);
491    }
492   
493  20 g = (d[l] - d[l - 1]) / (2.0 * e[l - 1]);
494  20 r = Math.sqrt((g * g) + 1.0);
495  20 g = d[m - 1] - d[l - 1] + (e[l - 1] / (g + sign(r, g)));
496  20 c = 1.0;
497  20 s = c;
498  20 p = 0.0;
499   
500  80 for (i = m - 1; i >= l; i--)
501    {
502  60 f = s * e[i - 1];
503  60 b = c * e[i - 1];
504   
505  60 if (Math.abs(f) >= Math.abs(g))
506    {
507  14 c = g / f;
508  14 r = Math.sqrt((c * c) + 1.0);
509  14 e[i] = f * r;
510  14 s = 1.0 / r;
511  14 c *= s;
512    }
513    else
514    {
515  46 s = f / g;
516  46 r = Math.sqrt((s * s) + 1.0);
517  46 e[i] = g * r;
518  46 c = 1.0 / r;
519  46 s *= c;
520    }
521   
522  60 g = d[i] - p;
523  60 r = ((d[i - 1] - g) * s) + (2.0 * c * b);
524  60 p = s * r;
525  60 d[i] = g + p;
526  60 g = (c * r) - b;
527   
528  420 for (k = 1; k <= n; k++)
529    {
530  360 f = getValue(k - 1, i);
531  360 setValue(k - 1, i, (s * getValue(k - 1, i - 1)) + (c * f));
532  360 setValue(k - 1, i - 1,
533    (c * getValue(k - 1, i - 1)) - (s * f));
534    }
535    }
536   
537  20 d[l - 1] = d[l - 1] - p;
538  20 e[l - 1] = g;
539  20 e[m - 1] = 0.0;
540    }
541  32 } while (m != l);
542    }
543    }
544   
 
545  7093 toggle @Override
546    public double getValue(int i, int j)
547    {
548  7093 return value[i][j];
549    }
550   
 
551  870 toggle @Override
552    public void setValue(int i, int j, double val)
553    {
554  870 value[i][j] = val;
555    }
556   
557    /**
558    * DOCUMENT ME!
559    */
 
560  0 toggle public void tred2()
561    {
562  0 int n = rows;
563  0 int l;
564  0 int k;
565  0 int j;
566  0 int i;
567   
568  0 double scale;
569  0 double hh;
570  0 double h;
571  0 double g;
572  0 double f;
573   
574  0 this.d = new double[rows];
575  0 this.e = new double[rows];
576   
577  0 for (i = n - 1; i >= 1; i--)
578    {
579  0 l = i - 1;
580  0 h = 0.0;
581  0 scale = 0.0;
582   
583  0 if (l > 0)
584    {
585  0 for (k = 0; k < l; k++)
586    {
587  0 scale += Math.abs(value[i][k]);
588    }
589   
590  0 if (scale == 0.0)
591    {
592  0 e[i] = value[i][l];
593    }
594    else
595    {
596  0 for (k = 0; k < l; k++)
597    {
598  0 value[i][k] /= scale;
599  0 h += (value[i][k] * value[i][k]);
600    }
601   
602  0 f = value[i][l];
603   
604  0 if (f > 0)
605    {
606  0 g = -1.0 * Math.sqrt(h);
607    }
608    else
609    {
610  0 g = Math.sqrt(h);
611    }
612   
613  0 e[i] = scale * g;
614  0 h -= (f * g);
615  0 value[i][l] = f - g;
616  0 f = 0.0;
617   
618  0 for (j = 0; j < l; j++)
619    {
620  0 value[j][i] = value[i][j] / h;
621  0 g = 0.0;
622   
623  0 for (k = 0; k < j; k++)
624    {
625  0 g += (value[j][k] * value[i][k]);
626    }
627   
628  0 for (k = j; k < l; k++)
629    {
630  0 g += (value[k][j] * value[i][k]);
631    }
632   
633  0 e[j] = g / h;
634  0 f += (e[j] * value[i][j]);
635    }
636   
637  0 hh = f / (h + h);
638   
639  0 for (j = 0; j < l; j++)
640    {
641  0 f = value[i][j];
642  0 g = e[j] - (hh * f);
643  0 e[j] = g;
644   
645  0 for (k = 0; k < j; k++)
646    {
647  0 value[j][k] -= ((f * e[k]) + (g * value[i][k]));
648    }
649    }
650    }
651    }
652    else
653    {
654  0 e[i] = value[i][l];
655    }
656   
657  0 d[i] = h;
658    }
659   
660  0 d[0] = 0.0;
661  0 e[0] = 0.0;
662   
663  0 for (i = 0; i < n; i++)
664    {
665  0 l = i - 1;
666   
667  0 if (d[i] != 0.0)
668    {
669  0 for (j = 0; j < l; j++)
670    {
671  0 g = 0.0;
672   
673  0 for (k = 0; k < l; k++)
674    {
675  0 g += (value[i][k] * value[k][j]);
676    }
677   
678  0 for (k = 0; k < l; k++)
679    {
680  0 value[k][j] -= (g * value[k][i]);
681    }
682    }
683    }
684   
685  0 d[i] = value[i][i];
686  0 value[i][i] = 1.0;
687   
688  0 for (j = 0; j < l; j++)
689    {
690  0 value[j][i] = 0.0;
691  0 value[i][j] = 0.0;
692    }
693    }
694    }
695   
696    /**
697    * DOCUMENT ME!
698    */
 
699  0 toggle public void tqli2() throws Exception
700    {
701  0 int n = rows;
702   
703  0 int m;
704  0 int l;
705  0 int iter;
706  0 int i;
707  0 int k;
708  0 double s;
709  0 double r;
710  0 double p;
711  0 ;
712   
713  0 double g;
714  0 double f;
715  0 double dd;
716  0 double c;
717  0 double b;
718   
719  0 for (i = 2; i <= n; i++)
720    {
721  0 e[i - 2] = e[i - 1];
722    }
723   
724  0 e[n - 1] = 0.0;
725   
726  0 for (l = 1; l <= n; l++)
727    {
728  0 iter = 0;
729   
730  0 do
731    {
732  0 for (m = l; m <= (n - 1); m++)
733    {
734  0 dd = Math.abs(d[m - 1]) + Math.abs(d[m]);
735   
736  0 if ((Math.abs(e[m - 1]) + dd) == dd)
737    {
738  0 break;
739    }
740    }
741   
742  0 if (m != l)
743    {
744  0 iter++;
745   
746  0 if (iter == maxIter)
747    {
748  0 throw new Exception(MessageManager.formatMessage(
749    "exception.matrix_too_many_iteration", new String[]
750    { "tqli2", Integer.valueOf(maxIter).toString() }));
751    }
752    else
753    {
754    // System.out.println("Iteration " + iter);
755    }
756   
757  0 g = (d[l] - d[l - 1]) / (2.0 * e[l - 1]);
758  0 r = Math.sqrt((g * g) + 1.0);
759  0 g = d[m - 1] - d[l - 1] + (e[l - 1] / (g + sign(r, g)));
760  0 c = 1.0;
761  0 s = c;
762  0 p = 0.0;
763   
764  0 for (i = m - 1; i >= l; i--)
765    {
766  0 f = s * e[i - 1];
767  0 b = c * e[i - 1];
768   
769  0 if (Math.abs(f) >= Math.abs(g))
770    {
771  0 c = g / f;
772  0 r = Math.sqrt((c * c) + 1.0);
773  0 e[i] = f * r;
774  0 s = 1.0 / r;
775  0 c *= s;
776    }
777    else
778    {
779  0 s = f / g;
780  0 r = Math.sqrt((s * s) + 1.0);
781  0 e[i] = g * r;
782  0 c = 1.0 / r;
783  0 s *= c;
784    }
785   
786  0 g = d[i] - p;
787  0 r = ((d[i - 1] - g) * s) + (2.0 * c * b);
788  0 p = s * r;
789  0 d[i] = g + p;
790  0 g = (c * r) - b;
791   
792  0 for (k = 1; k <= n; k++)
793    {
794  0 f = value[k - 1][i];
795  0 value[k - 1][i] = (s * value[k - 1][i - 1]) + (c * f);
796  0 value[k - 1][i - 1] = (c * value[k - 1][i - 1]) - (s * f);
797    }
798    }
799   
800  0 d[l - 1] = d[l - 1] - p;
801  0 e[l - 1] = g;
802  0 e[m - 1] = 0.0;
803    }
804  0 } while (m != l);
805    }
806    }
807   
808    /**
809    * Answers the first argument with the sign of the second argument
810    *
811    * @param a
812    * @param b
813    *
814    * @return
815    */
 
816  20 toggle static double sign(double a, double b)
817    {
818  20 if (b < 0)
819    {
820  2 return -Math.abs(a);
821    }
822    else
823    {
824  18 return Math.abs(a);
825    }
826    }
827   
828    /**
829    * Returns an array containing the values in the specified column
830    *
831    * @param col
832    *
833    * @return
834    */
 
835  0 toggle public double[] getColumn(int col)
836    {
837  0 double[] out = new double[rows];
838   
839  0 for (int i = 0; i < rows; i++)
840    {
841  0 out[i] = value[i][col];
842    }
843   
844  0 return out;
845    }
846   
847    /**
848    * DOCUMENT ME!
849    *
850    * @param ps
851    * DOCUMENT ME!
852    * @param format
853    */
 
854  0 toggle @Override
855    public void printD(PrintStream ps, String format)
856    {
857  0 for (int j = 0; j < rows; j++)
858    {
859  0 Format.print(ps, format, d[j]);
860    }
861    }
862   
863    /**
864    * DOCUMENT ME!
865    *
866    * @param ps
867    * DOCUMENT ME!
868    * @param format
869    * TODO
870    */
 
871  0 toggle @Override
872    public void printE(PrintStream ps, String format)
873    {
874  0 for (int j = 0; j < rows; j++)
875    {
876  0 Format.print(ps, format, e[j]);
877    }
878    }
879   
 
880  22 toggle @Override
881    public double[] getD()
882    {
883  22 return d;
884    }
885   
 
886  22 toggle @Override
887    public double[] getE()
888    {
889  22 return e;
890    }
891   
 
892  227 toggle @Override
893    public int height()
894    {
895  227 return rows;
896    }
897   
 
898  921 toggle @Override
899    public int width()
900    {
901  921 return cols;
902    }
903   
 
904  26 toggle @Override
905    public double[] getRow(int i)
906    {
907  26 double[] row = new double[cols];
908  26 System.arraycopy(value[i], 0, row, 0, cols);
909  26 return row;
910    }
911   
912    /**
913    * Returns a length 2 array of {minValue, maxValue} of all values in the
914    * matrix. Returns null if the matrix is null or empty.
915    *
916    * @return
917    */
 
918  7 toggle double[] findMinMax()
919    {
920  7 if (value == null)
921    {
922  0 return null;
923    }
924  7 double min = Double.MAX_VALUE;
925  7 double max = -Double.MAX_VALUE;
926  7 boolean empty = true;
927  7 for (double[] row : value)
928    {
929  1011 if (row != null)
930    {
931  1011 for (double x : row)
932    {
933  1000030 empty = false;
934  1000030 if (x > max)
935    {
936  35 max = x;
937    }
938  1000030 if (x < min)
939    {
940  33 min = x;
941    }
942    }
943    }
944    }
945  7 return empty ? null : new double[] { min, max };
946    }
947   
948    /**
949    * {@inheritDoc}
950    */
 
951  4 toggle @Override
952    public void reverseRange(boolean maxToZero)
953    {
954  4 if (value == null)
955    {
956  0 return;
957    }
958  4 double[] minMax = findMinMax();
959  4 if (minMax == null)
960    {
961  0 return; // empty matrix
962    }
963  4 double subtractFrom = maxToZero ? minMax[1] : minMax[0] + minMax[1];
964   
965  4 for (double[] row : value)
966    {
967  8 if (row != null)
968    {
969  8 int j = 0;
970  8 for (double x : row)
971    {
972  24 row[j] = subtractFrom - x;
973  24 j++;
974    }
975    }
976    }
977    }
978   
979    /**
980    * Multiplies every entry in the matrix by the given value.
981    *
982    * @param
983    */
 
984  1 toggle @Override
985    public void multiply(double by)
986    {
987  1 for (double[] row : value)
988    {
989  2 if (row != null)
990    {
991  8 for (int i = 0; i < row.length; i++)
992    {
993  6 row[i] *= by;
994    }
995    }
996    }
997    }
998    }