Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
MiscMath | 33 | 102 | 50 |
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 | ||
25 | import java.lang.Math; | |
26 | import java.util.Arrays; | |
27 | ||
28 | /** | |
29 | * A collection of miscellaneous mathematical operations | |
30 | * | |
31 | * @AUTHOR MorellThomas | |
32 | */ | |
33 | public class MiscMath | |
34 | { | |
35 | /** | |
36 | * prints an array | |
37 | * | |
38 | * @param m | |
39 | * ~ array | |
40 | */ | |
41 | 0 | public static void print(double[] m, String format) |
42 | { | |
43 | 0 | System.out.print("[ "); |
44 | 0 | for (double a : m) |
45 | { | |
46 | 0 | Format.print(System.out, format + " ", a); |
47 | } | |
48 | 0 | System.out.println("]"); |
49 | } | |
50 | ||
51 | /** | |
52 | * calculates the mean of an array | |
53 | * | |
54 | * @param m | |
55 | * ~ array | |
56 | * @return | |
57 | */ | |
58 | 0 | public static double mean(double[] m) |
59 | { | |
60 | 0 | double sum = 0; |
61 | 0 | int nanCount = 0; |
62 | 0 | for (int i = 0; i < m.length; i++) |
63 | { | |
64 | 0 | if (!Double.isNaN(m[i])) // ignore NaN values in the array |
65 | { | |
66 | 0 | sum += m[i]; |
67 | } | |
68 | else | |
69 | { | |
70 | 0 | nanCount++; |
71 | } | |
72 | } | |
73 | 0 | return sum / (double) (m.length - nanCount); |
74 | } | |
75 | ||
76 | /** | |
77 | * calculates the sum of an array | |
78 | * | |
79 | * @param m | |
80 | * ~ array | |
81 | * @return | |
82 | */ | |
83 | 0 | public static double sum(double[] m) |
84 | { | |
85 | 0 | double sum = 0; |
86 | 0 | for (int i = 0; i < m.length; i++) |
87 | { | |
88 | 0 | if (!Double.isNaN(m[i])) // ignore NaN values in the array |
89 | { | |
90 | 0 | sum += m[i]; |
91 | } | |
92 | } | |
93 | 0 | return sum; |
94 | } | |
95 | ||
96 | /** | |
97 | * calculates the square root of each element in an array | |
98 | * | |
99 | * @param m | |
100 | * ~ array | |
101 | * | |
102 | * @return TODO make general with function passed -> apply function to each | |
103 | * element | |
104 | */ | |
105 | 0 | public static double[] sqrt(double[] m) |
106 | { | |
107 | 0 | double[] sqrts = new double[m.length]; |
108 | 0 | for (int i = 0; i < m.length; i++) |
109 | { | |
110 | 0 | sqrts[i] = Math.sqrt(m[i]); |
111 | } | |
112 | 0 | return sqrts; |
113 | } | |
114 | ||
115 | /** | |
116 | * calculate element wise multiplication of two arrays with the same length | |
117 | * | |
118 | * @param a | |
119 | * ~ array | |
120 | * @param b | |
121 | * ~ array | |
122 | * | |
123 | * @return | |
124 | */ | |
125 | 0 | public static double[] elementwiseMultiply(byte[] a, double[] b) |
126 | throws RuntimeException | |
127 | { | |
128 | 0 | if (a.length != b.length) // throw exception if the arrays do not have the |
129 | // same length | |
130 | { | |
131 | 0 | throw new SameLengthException(a.length, b.length); |
132 | } | |
133 | 0 | double[] result = new double[a.length]; |
134 | 0 | for (int i = 0; i < a.length; i++) |
135 | { | |
136 | 0 | result[i] = a[i] * b[i]; |
137 | } | |
138 | 0 | return result; |
139 | } | |
140 | ||
141 | 0 | public static double[] elementwiseMultiply(double[] a, double[] b) |
142 | throws RuntimeException | |
143 | { | |
144 | 0 | if (a.length != b.length) // throw exception if the arrays do not have the |
145 | // same length | |
146 | { | |
147 | 0 | throw new SameLengthException(a.length, b.length); |
148 | } | |
149 | 0 | double[] result = new double[a.length]; |
150 | 0 | for (int i = 0; i < a.length; i++) |
151 | { | |
152 | 0 | result[i] = a[i] * b[i]; |
153 | } | |
154 | 0 | return result; |
155 | } | |
156 | ||
157 | 0 | public static byte[] elementwiseMultiply(byte[] a, byte[] b) |
158 | throws RuntimeException | |
159 | { | |
160 | 0 | if (a.length != b.length) // throw exception if the arrays do not have the |
161 | // same length | |
162 | { | |
163 | 0 | throw new SameLengthException(a.length, b.length); |
164 | } | |
165 | 0 | byte[] result = new byte[a.length]; |
166 | 0 | for (int i = 0; i < a.length; i++) |
167 | { | |
168 | 0 | result[i] = (byte) (a[i] * b[i]); |
169 | } | |
170 | 0 | return result; |
171 | } | |
172 | ||
173 | 0 | public static double[] elementwiseMultiply(double[] a, double b) |
174 | { | |
175 | 0 | double[] result = new double[a.length]; |
176 | 0 | for (int i = 0; i < a.length; i++) |
177 | { | |
178 | 0 | result[i] = a[i] * b; |
179 | } | |
180 | 0 | return result; |
181 | } | |
182 | ||
183 | /** | |
184 | * calculate element wise division of two arrays ~ a / b | |
185 | * | |
186 | * @param a | |
187 | * ~ array | |
188 | * @param b | |
189 | * ~ array | |
190 | * | |
191 | * @return | |
192 | */ | |
193 | 0 | public static double[] elementwiseDivide(double[] a, double[] b) |
194 | throws RuntimeException | |
195 | { | |
196 | 0 | if (a.length != b.length) // throw exception if the arrays do not have the |
197 | // same length | |
198 | { | |
199 | 0 | throw new SameLengthException(a.length, b.length); |
200 | } | |
201 | 0 | double[] result = new double[a.length]; |
202 | 0 | for (int i = 0; i < a.length; i++) |
203 | { | |
204 | 0 | result[i] = a[i] / b[i]; |
205 | } | |
206 | 0 | return result; |
207 | } | |
208 | ||
209 | /** | |
210 | * calculate element wise addition of two arrays | |
211 | * | |
212 | * @param a | |
213 | * ~ array | |
214 | * @param b | |
215 | * ~ array | |
216 | * | |
217 | * @return | |
218 | */ | |
219 | 0 | public static double[] elementwiseAdd(double[] a, double[] b) |
220 | throws RuntimeException | |
221 | { | |
222 | 0 | if (a.length != b.length) // throw exception if the arrays do not have the |
223 | // same length | |
224 | { | |
225 | 0 | throw new SameLengthException(a.length, b.length); |
226 | } | |
227 | 0 | double[] result = new double[a.length]; |
228 | ||
229 | 0 | for (int i = 0; i < a.length; i++) |
230 | { | |
231 | 0 | result[i] += a[i] + b[i]; |
232 | } | |
233 | 0 | return result; |
234 | } | |
235 | ||
236 | 0 | public static double[] elementwiseAdd(double[] a, double b) |
237 | { | |
238 | 0 | double[] result = new double[a.length]; |
239 | 0 | for (int i = 0; i < a.length; i++) |
240 | { | |
241 | 0 | result[i] = a[i] + b; |
242 | } | |
243 | 0 | return result; |
244 | } | |
245 | ||
246 | /** | |
247 | * returns true if two arrays are element wise within a tolerance | |
248 | * | |
249 | * @param a | |
250 | * ~ array | |
251 | * @param b | |
252 | * ~ array | |
253 | * @param rtol | |
254 | * ~ relative tolerance | |
255 | * @param atol | |
256 | * ~ absolute tolerance | |
257 | * @param equalNAN | |
258 | * ~ whether NaN at the same position return true | |
259 | * | |
260 | * @return | |
261 | */ | |
262 | 0 | public static boolean allClose(double[] a, double[] b, double rtol, |
263 | double atol, boolean equalNAN) | |
264 | { | |
265 | 0 | boolean areEqual = true; |
266 | 0 | for (int i = 0; i < a.length; i++) |
267 | { | |
268 | 0 | if (equalNAN && (Double.isNaN(a[i]) && Double.isNaN(b[i]))) // if equalNAN |
269 | // == true -> | |
270 | // skip the | |
271 | // NaN pair | |
272 | { | |
273 | 0 | continue; |
274 | } | |
275 | 0 | if (Math.abs(a[i] - b[i]) > (atol + rtol * Math.abs(b[i]))) // check for |
276 | // the | |
277 | // similarity | |
278 | // condition | |
279 | // -> if not | |
280 | // met -> | |
281 | // break and | |
282 | // return | |
283 | // false | |
284 | { | |
285 | 0 | areEqual = false; |
286 | 0 | break; |
287 | } | |
288 | } | |
289 | 0 | return areEqual; |
290 | } | |
291 | ||
292 | /** | |
293 | * returns the index of the maximum and the maximum value of an array | |
294 | * | |
295 | * @param a | |
296 | * ~ array | |
297 | * | |
298 | * @return | |
299 | */ | |
300 | 2 | public static int[] findMax(int[] a) |
301 | { | |
302 | 2 | int max = 0; |
303 | 2 | int maxIndex = 0; |
304 | 6 | for (int i = 0; i < a.length; i++) |
305 | { | |
306 | 4 | if (a[i] > max) |
307 | { | |
308 | 2 | max = a[i]; |
309 | 2 | maxIndex = i; |
310 | } | |
311 | } | |
312 | 2 | return new int[] { maxIndex, max }; |
313 | } | |
314 | ||
315 | /** | |
316 | * returns the dot product of two arrays | |
317 | * | |
318 | * @param a | |
319 | * ~ array a | |
320 | * @param b | |
321 | * ~ array b | |
322 | * | |
323 | * @return | |
324 | */ | |
325 | 0 | public static double dot(double[] a, double[] b) |
326 | { | |
327 | 0 | if (a.length != b.length) |
328 | { | |
329 | 0 | throw new IllegalArgumentException( |
330 | String.format("Vectors do not have the same length (%d, %d)!", | |
331 | a.length, b.length)); | |
332 | } | |
333 | ||
334 | 0 | double aibi = 0; |
335 | 0 | for (int i = 0; i < a.length; i++) |
336 | { | |
337 | 0 | aibi += a[i] * b[i]; |
338 | } | |
339 | 0 | return aibi; |
340 | } | |
341 | ||
342 | /** | |
343 | * returns the euklidian norm of the vector | |
344 | * | |
345 | * @param v | |
346 | * ~ vector | |
347 | * | |
348 | * @return | |
349 | */ | |
350 | 0 | public static double norm(double[] v) |
351 | { | |
352 | 0 | double result = 0; |
353 | 0 | for (double i : v) |
354 | { | |
355 | 0 | result += Math.pow(i, 2); |
356 | } | |
357 | 0 | return Math.sqrt(result); |
358 | } | |
359 | ||
360 | /** | |
361 | * returns the number of NaN in the vector | |
362 | * | |
363 | * @param v | |
364 | * ~ vector | |
365 | * | |
366 | * @return | |
367 | */ | |
368 | 0 | public static int countNaN(double[] v) |
369 | { | |
370 | 0 | int cnt = 0; |
371 | 0 | for (double i : v) |
372 | { | |
373 | 0 | if (Double.isNaN(i)) |
374 | { | |
375 | 0 | cnt++; |
376 | } | |
377 | } | |
378 | 0 | return cnt; |
379 | } | |
380 | ||
381 | /** | |
382 | * recursively calculates the permutations of total n items with r items per | |
383 | * combination according to n!/(n-r)! by only multiplying the relevant terms | |
384 | * | |
385 | * @param n | |
386 | * @param r | |
387 | * | |
388 | * @return permutations | |
389 | */ | |
390 | 0 | public static long permutations(int n, int r) |
391 | { | |
392 | 0 | if (n < r) |
393 | 0 | return permutations(r, n); |
394 | ||
395 | 0 | long result = 1l; |
396 | 0 | for (int i = 0; i < r; i++) |
397 | { | |
398 | 0 | result *= (n - i); |
399 | } | |
400 | 0 | return result; |
401 | } | |
402 | ||
403 | /** | |
404 | * calculate all unique combinations of n elements into r sized groups | |
405 | * | |
406 | * @param n | |
407 | * @param r | |
408 | * | |
409 | * @return | |
410 | */ | |
411 | 0 | public static int combinations(int n, int r) |
412 | { | |
413 | 0 | int result = 1; |
414 | 0 | for (int i = 0; i < r; i++) |
415 | { | |
416 | 0 | result *= (n - 1); |
417 | } | |
418 | 0 | return (int) (result / MiscMath.factorial(r)); |
419 | } | |
420 | ||
421 | /** | |
422 | * calculate the factorial of n (n >= 0) | |
423 | * | |
424 | * @param n | |
425 | * | |
426 | * @return | |
427 | */ | |
428 | 0 | public static int factorial(int n) |
429 | { | |
430 | 0 | int result = 1; |
431 | 0 | for (int i = 0; i < n; i++) |
432 | { | |
433 | 0 | result *= (n - i); |
434 | } | |
435 | 0 | return result; |
436 | } | |
437 | ||
438 | } |