001    /*
002     * Copyright (C) 2008-2010 by Holger Arndt
003     *
004     * This file is part of the Universal Java Matrix Package (UJMP).
005     * See the NOTICE file distributed with this work for additional
006     * information regarding copyright ownership and licensing.
007     *
008     * UJMP is free software; you can redistribute it and/or modify
009     * it under the terms of the GNU Lesser General Public License as
010     * published by the Free Software Foundation; either version 2
011     * of the License, or (at your option) any later version.
012     *
013     * UJMP is distributed in the hope that it will be useful,
014     * but WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016     * GNU Lesser General Public License for more details.
017     *
018     * You should have received a copy of the GNU Lesser General Public
019     * License along with UJMP; if not, write to the
020     * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
021     * Boston, MA  02110-1301  USA
022     */
023    
024    package org.ujmp.core.util;
025    
026    import java.io.File;
027    import java.io.IOException;
028    import java.io.Serializable;
029    import java.math.BigDecimal;
030    import java.math.BigInteger;
031    import java.math.MathContext;
032    import java.security.MessageDigest;
033    import java.security.NoSuchAlgorithmException;
034    import java.text.DateFormat;
035    import java.util.ArrayList;
036    import java.util.Collection;
037    import java.util.Collections;
038    import java.util.Date;
039    import java.util.List;
040    import java.util.Locale;
041    import java.util.Random;
042    
043    import org.ujmp.core.Matrix;
044    import org.ujmp.core.MatrixFactory;
045    import org.ujmp.core.util.io.IntelligentFileReader;
046    
047    public abstract class MathUtil {
048    
049            private static List<DateFormat> dateFormats = null;
050    
051            private static final double ROOT2PI = Math.sqrt(2 * Math.PI);
052    
053            private static final double LOG10 = Math.log(10.0);
054    
055            private static final double LOG2 = Math.log(2.0);
056    
057            private static final double COFGAMMALN[] = { 76.18009172947146, -86.50532032941677,
058                            24.01409824083091, -1.231739572450155, 0.1208650973866179e-2, -0.5395239384953e-5 };
059    
060            private static long seed = System.nanoTime();
061    
062            private static Random random = new Random();
063    
064            static {
065                    try {
066                            random.setSeed(seed);
067                            dateFormats = new ArrayList<DateFormat>();
068                            dateFormats.add(DateFormat.getDateInstance(DateFormat.SHORT, Locale.US));
069                            dateFormats.add(DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.US));
070                            dateFormats.add(DateFormat.getDateInstance(DateFormat.LONG, Locale.US));
071                            dateFormats.add(DateFormat.getDateInstance(DateFormat.SHORT, Locale.GERMAN));
072                            dateFormats.add(DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.GERMAN));
073                            dateFormats.add(DateFormat.getDateInstance(DateFormat.LONG, Locale.GERMAN));
074                            dateFormats.add(DateFormat.getTimeInstance(DateFormat.SHORT, Locale.US));
075                            dateFormats.add(DateFormat.getTimeInstance(DateFormat.MEDIUM, Locale.US));
076                            dateFormats.add(DateFormat.getTimeInstance(DateFormat.LONG, Locale.US));
077                            dateFormats.add(DateFormat.getTimeInstance(DateFormat.SHORT, Locale.GERMAN));
078                            dateFormats.add(DateFormat.getTimeInstance(DateFormat.MEDIUM, Locale.GERMAN));
079                            dateFormats.add(DateFormat.getTimeInstance(DateFormat.LONG, Locale.GERMAN));
080                    } catch (Throwable t) {
081                    }
082            }
083    
084            public static MathContext getDefaultMathContext() {
085                    return UJMPSettings.getDefaultMathContext();
086            }
087    
088            public static String md5(String text) throws NoSuchAlgorithmException {
089                    return md5(text.getBytes());
090            }
091    
092            public static String md5(byte[] data) throws NoSuchAlgorithmException {
093                    MessageDigest mdAlgorithm;
094                    StringBuilder hexString = new StringBuilder();
095    
096                    mdAlgorithm = MessageDigest.getInstance("MD5");
097                    mdAlgorithm.update(data);
098                    byte[] digest = mdAlgorithm.digest();
099    
100                    for (int i = 0; i < digest.length; i++) {
101                            String text = Integer.toHexString(0xFF & digest[i]);
102    
103                            if (text.length() < 2) {
104                                    text = "0" + text;
105                            }
106    
107                            hexString.append(text);
108                    }
109                    hexString.trimToSize();
110                    return hexString.toString();
111            }
112    
113            public static String md5(File file) throws NoSuchAlgorithmException {
114                    return md5(IntelligentFileReader.readBytes(file));
115            }
116    
117            public static String md5(Serializable o) throws NoSuchAlgorithmException, IOException {
118                    return md5(SerializationUtil.serialize(o));
119            }
120    
121            public static final Random getRandom() {
122                    return random;
123            }
124    
125            public static final boolean xor(boolean b1, boolean b2) {
126                    if (b1 == false && b2 == false) {
127                            return false;
128                    } else if (b1 == false && b2 == true) {
129                            return true;
130                    } else if (b1 == true && b2 == false) {
131                            return true;
132                    } else {
133                            return false;
134                    }
135            }
136    
137            public static double[] logToProbs(double[] logs) {
138                    double[] probs = new double[logs.length];
139                    double sum = 0.0;
140                    for (int i = 0; i < probs.length; i++) {
141                            probs[i] = Math.exp(logs[i]);
142                            sum += probs[i];
143                    }
144                    for (int i = 0; i < probs.length; i++) {
145                            probs[i] = probs[i] / sum;
146                    }
147                    return probs;
148            }
149    
150            public static final long getSeed() {
151                    return seed;
152            }
153    
154            public static final double round(double value, int decimals) {
155                    return Math.round(value * Math.pow(10, decimals)) / Math.pow(10, decimals);
156    
157            }
158    
159            public static void setSeed(long seed) {
160                    MathUtil.seed = seed;
161                    random.setSeed(seed);
162            }
163    
164            public static final double log2(final double d) {
165                    return Math.log(d) / LOG2;
166            }
167    
168            public static final double log10(final double d) {
169                    return Math.log(d) / LOG10;
170            }
171    
172            public static int hash(int h) {
173                    // This function ensures that hashCodes that differ only by
174                    // constant multiples at each bit position have a bounded
175                    // number of collisions (approximately 8 at default load factor).
176                    h ^= (h >>> 20) ^ (h >>> 12);
177                    return h ^ (h >>> 7) ^ (h >>> 4);
178            }
179    
180            public static final double gauss(double mean, double sigma, double x) {
181                    return Math.exp(-0.5 * Math.pow((x - mean) / sigma, 2.0)) / (sigma * ROOT2PI);
182            }
183    
184            public static final double artanh(double x) {
185                    return 0.5 * Math.log((1 + x) / (1 - x));
186            }
187    
188            public static final double nextGaussian(double mean, double sigma) {
189                    return sigma <= 0.0 ? 0.0 : sigma * random.nextGaussian() + mean;
190            }
191    
192            public static final double nextUniform(double min, double max) {
193                    if (min == max) {
194                            max += Double.MIN_VALUE;
195                    }
196                    double r = random.nextDouble();
197                    while (r <= 0.0) {
198                            r = random.nextDouble();
199                    }
200    
201                    return min + r * (max - min);
202            }
203    
204            /**
205             * Returns a random value in the desired interval
206             * 
207             * @param min
208             *            minimum value (inclusive)
209             * @param max
210             *            maximum value (inclusive)
211             * @return a random value
212             */
213            public static final int nextInteger(int min, int max) {
214                    if (min == max) {
215                            return min;
216                    }
217                    double r = random.nextDouble();
218                    return (int) ((r * max) + ((1.0 - r) * min) + r);
219            }
220    
221            public static boolean isEventHappening(double probability) {
222                    return nextUniform(0.0, 1.0) < probability;
223            }
224    
225            public static boolean nextBoolean() {
226                    return nextGaussian(0.0, 1.0) > 0;
227            }
228    
229            public static double nextDouble() {
230                    return random.nextDouble();
231            }
232    
233            public static final double ignoreNaN(final double v) {
234                    return Double.isNaN(v) || (v == Double.POSITIVE_INFINITY)
235                                    || (v == Double.NEGATIVE_INFINITY) ? 0.0 : v;
236            }
237    
238            public static final boolean isNaNOrInfinite(final double v) {
239                    return Double.isNaN(v) || (v == Double.POSITIVE_INFINITY)
240                                    || (v == Double.NEGATIVE_INFINITY);
241            }
242    
243            public static final boolean isNaNOrInfinite(final Object o) {
244                    return Double.valueOf(Double.NaN).equals(o)
245                                    || Double.valueOf(Double.POSITIVE_INFINITY).equals(o)
246                                    || Double.valueOf(Double.NEGATIVE_INFINITY).equals(o);
247            }
248    
249            public static final Matrix getMatrix(Object o) {
250                    if (o == null) {
251                            return MatrixFactory.EMPTYMATRIX;
252                    }
253                    if (o instanceof Matrix) {
254                            Matrix m = (Matrix) o;
255                            if (m.isScalar() && m.getAsObject(0, 0) instanceof Matrix) {
256                                    return getMatrix(m.getAsObject(0, 0));
257                            } else {
258                                    return m;
259                            }
260                    } else {
261                            return MatrixFactory.linkToValue(o);
262                    }
263            }
264    
265            public static final Date getDate(Object o) {
266                    if (o == null) {
267                            return null;
268                    }
269                    if (o instanceof Date) {
270                            return (Date) o;
271                    }
272                    if (o instanceof Long) {
273                            return new Date((Long) o);
274                    }
275                    if (o instanceof String) {
276                            for (DateFormat df : dateFormats) {
277                                    try {
278                                            return df.parse((String) o);
279                                    } catch (Exception e) {
280                                    }
281                            }
282                    }
283                    return new Date(getLong(o));
284            }
285    
286            public static final double getDouble(Object o) {
287                    if (o == null) {
288                            return 0.0;
289                    } else if (o instanceof Double) {
290                            return (Double) o;
291                    } else if (o instanceof Date) {
292                            return ((Date) o).getTime();
293                    } else if (o instanceof Matrix) {
294                            return ((Matrix) o).doubleValue();
295                    } else {
296                            if ("true".equalsIgnoreCase(o.toString())) {
297                                    return 1.0;
298                            }
299                            if ("false".equalsIgnoreCase(o.toString())) {
300                                    return 0.0;
301                            }
302                            try {
303                                    return Double.parseDouble(o.toString());
304                            } catch (Exception e) {
305                            }
306                    }
307                    return Double.NaN;
308            }
309    
310            /** sqrt(a^2 + b^2) without under/overflow. **/
311            public static final double hypot(double a, double b) {
312                    double r;
313                    if (Math.abs(a) > Math.abs(b)) {
314                            r = b / a;
315                            r = Math.abs(a) * Math.sqrt(1.0 + r * r);
316                    } else if (b != 0) {
317                            r = a / b;
318                            r = Math.abs(b) * Math.sqrt(1.0 + r * r);
319                    } else {
320                            r = 0.0;
321                    }
322                    return r;
323            }
324    
325            public static long[] collectionToLong(Collection<? extends Number> numbers) {
326                    long[] ret = new long[numbers.size()];
327                    int i = 0;
328                    for (Number n : numbers) {
329                            ret[i++] = n.longValue();
330                    }
331                    return ret;
332            }
333    
334            public static double[] collectionToDouble(Collection<? extends Number> numbers) {
335                    double[] ret = new double[numbers.size()];
336                    int i = 0;
337                    for (Number n : numbers) {
338                            ret[i++] = n.doubleValue();
339                    }
340                    return ret;
341            }
342    
343            public static int[] collectionToInt(Collection<? extends Number> numbers) {
344                    int[] ret = new int[numbers.size()];
345                    int i = 0;
346                    for (Number n : numbers) {
347                            ret[i++] = n.intValue();
348                    }
349                    return ret;
350            }
351    
352            public static List<Long> toLongList(long[] numbers) {
353                    List<Long> ret = new ArrayList<Long>(numbers.length);
354                    for (int i = 0; i < numbers.length; i++) {
355                            ret.add(numbers[i]);
356                    }
357                    return ret;
358            }
359    
360            public static List<Long> toLongList(int[] numbers) {
361                    List<Long> ret = new ArrayList<Long>(numbers.length);
362                    for (int i = 0; i < numbers.length; i++) {
363                            ret.add((long) numbers[i]);
364                    }
365                    return ret;
366            }
367    
368            public static List<Double> toDoubleList(double[] numbers) {
369                    List<Double> ret = new ArrayList<Double>(numbers.length);
370                    for (int i = 0; i < numbers.length; i++) {
371                            ret.add(numbers[i]);
372                    }
373                    return ret;
374            }
375    
376            public static List<Double> toDoubleList(int[] numbers) {
377                    List<Double> ret = new ArrayList<Double>(numbers.length);
378                    for (int i = 0; i < numbers.length; i++) {
379                            ret.add((double) numbers[i]);
380                    }
381                    return ret;
382            }
383    
384            public static List<Double> toDoubleList(long[] numbers) {
385                    List<Double> ret = new ArrayList<Double>(numbers.length);
386                    for (int i = 0; i < numbers.length; i++) {
387                            ret.add((double) numbers[i]);
388                    }
389                    return ret;
390            }
391    
392            public static double[] toDoubleArray(int... intArray) {
393                    int nmb = intArray.length;
394                    double[] ret = new double[nmb];
395                    for (int i = 0; i < nmb; i++)
396                            ret[i] = intArray[i];
397                    return ret;
398            }
399    
400            public static double[][] toDoubleArray(int[]... intArray) {
401                    int rows = intArray.length;
402                    if (rows <= 0)
403                            return new double[0][0];
404                    int cols = intArray[0].length;
405                    double[][] ret = new double[rows][cols];
406                    for (int i = rows - 1; i >= 0; i--) {
407                            for (int j = cols - 1; j >= 0; j--) {
408                                    ret[i][j] = intArray[i][j];
409                            }
410                    }
411                    return ret;
412            }
413    
414            public static List<Long> sequenceListLong(long start, long end) {
415                    return sequenceListLong(start, end, 1);
416            }
417    
418            public static List<Long> sequenceListLong(long start, long end, long stepsize) {
419                    List<Long> list = new ArrayList<Long>();
420    
421                    if (start < end) {
422                            stepsize = Math.abs(stepsize);
423                            for (long l = start; l <= end; l += stepsize) {
424                                    list.add(l);
425                            }
426                    } else {
427                            stepsize = -Math.abs(stepsize);
428                            for (long l = start; l >= end; l += stepsize) {
429                                    list.add(l);
430                            }
431                    }
432                    return list;
433            }
434    
435            public static List<Double> sequenceListDouble(double start, double end) {
436                    return sequenceListDouble(start, end, 1);
437            }
438    
439            public static List<Double> sequenceListDouble(double start, double end, double stepsize) {
440                    List<Double> list = new ArrayList<Double>();
441    
442                    if (start < end) {
443                            stepsize = Math.abs(stepsize);
444                            for (double l = start; l <= end; l += stepsize) {
445                                    list.add(l);
446                            }
447                    } else {
448                            stepsize = -Math.abs(stepsize);
449                            for (double l = start; l >= end; l += stepsize) {
450                                    list.add(l);
451                            }
452                    }
453                    return list;
454            }
455    
456            public static List<Integer> sequenceListInt(int start, int end) {
457                    List<Integer> list = new ArrayList<Integer>();
458    
459                    if (start < end) {
460                            for (int l = start; l <= end; l++) {
461                                    list.add(l);
462                            }
463                    } else {
464                            for (int l = start; l >= end; l--) {
465                                    list.add(l);
466                            }
467                    }
468                    return list;
469            }
470    
471            public static long[] sequenceLong(long start, long end) {
472                    return collectionToLong(sequenceListLong(start, end));
473            }
474    
475            public static long[] sequenceLong(long start, long end, long stepsize) {
476                    return collectionToLong(sequenceListLong(start, end, stepsize));
477            }
478    
479            public static double[] sequenceDouble(double start, double end) {
480                    return collectionToDouble(sequenceListDouble(start, end));
481            }
482    
483            public static double[] sequenceDouble(double start, double end, double stepsize) {
484                    return collectionToDouble(sequenceListDouble(start, end, stepsize));
485            }
486    
487            public static int[] sequenceInt(int start, int end) {
488                    return collectionToInt(sequenceListInt(start, end));
489            }
490    
491            public static List<Long> randPerm(long start, long end) {
492                    List<Long> list = sequenceListLong(start, end);
493                    Collections.shuffle(list);
494                    return list;
495            }
496    
497            public static boolean equals(Object o1, Object o2) {
498                    if ((o1 instanceof Number) || (o2 instanceof Number)) {
499                            return getDouble(o1) == getDouble(o2);
500                    } else if ((o1 instanceof String) || (o2 instanceof String)) {
501                            return UJMPFormat.getSingleLineInstance().format(o1).equals(
502                                            UJMPFormat.getSingleLineInstance().format(o2));
503                    } else if ((o1 instanceof Boolean) || (o2 instanceof Boolean)) {
504                            return ((Boolean) o1).equals(o2);
505                    } else {
506                            return false;
507                    }
508            }
509    
510            public static double sensitivity(double tp, double fn) {
511                    double r = tp / (tp + fn);
512                    return MathUtil.isNaNOrInfinite(r) ? 0.0 : r;
513            }
514    
515            public static double specificity(double tn, double fp) {
516                    double r = tn / (tn + fp);
517                    return MathUtil.isNaNOrInfinite(r) ? 0.0 : r;
518            }
519    
520            public static double positivePredictiveValue(double tp, double fp) {
521                    double r = tp / (tp + fp);
522                    return MathUtil.isNaNOrInfinite(r) ? 0.0 : r;
523            }
524    
525            public static double negativePredictiveValue(double tn, double fn) {
526                    double r = tn / (tn + fn);
527                    return MathUtil.isNaNOrInfinite(r) ? 0.0 : r;
528            }
529    
530            public static double falsePositiveRate(double fp, double tn) {
531                    double r = fp / (fp + tn);
532                    return MathUtil.isNaNOrInfinite(r) ? 0.0 : r;
533            }
534    
535            public static double falseNegativeRate(double fn, double tp) {
536                    double r = fn / (fn + tp);
537                    return MathUtil.isNaNOrInfinite(r) ? 0.0 : r;
538            }
539    
540            public static double recall(double tp, double fn) {
541                    double r = tp / (tp + fn);
542                    return MathUtil.isNaNOrInfinite(r) ? 0.0 : r;
543            }
544    
545            public static double precision(double tp, double fp) {
546                    double r = tp / (tp + fp);
547                    return MathUtil.isNaNOrInfinite(r) ? 0.0 : r;
548            }
549    
550            public static double fallout(double tn, double fp) {
551                    double r = tn / (fp + tn);
552                    return MathUtil.isNaNOrInfinite(r) ? 0.0 : r;
553            }
554    
555            public static double trueNegativeRate(double tn, double fp) {
556                    double r = tn / (fp + tn);
557                    return MathUtil.isNaNOrInfinite(r) ? 0.0 : r;
558            }
559    
560            public static double f1Measure(double precision, double recall) {
561                    double r = (2.0 * precision * recall) / (precision + recall);
562                    return MathUtil.isNaNOrInfinite(r) ? 0.0 : r;
563            }
564    
565            public static double fBetaMeasure(double beta, double precision, double recall) {
566                    double r = ((1 + beta * beta) * precision * recall) / (beta * beta * precision + recall);
567                    return MathUtil.isNaNOrInfinite(r) ? 0.0 : r;
568            }
569    
570            public static Object getPreferredObject(Object o) {
571                    if (o == null) {
572                            return null;
573                    }
574                    if (o instanceof Number) {
575                            return o;
576                    }
577                    if (o instanceof String) {
578                            Double d = getDouble(o);
579                            if (isNaNOrInfinite(d)) {
580                                    return o;
581                            }
582                            return d;
583                    }
584                    return o;
585            }
586    
587            public static boolean getBoolean(Object o) {
588                    if (o == null) {
589                            return false;
590                    }
591                    if (o instanceof Boolean) {
592                            return (Boolean) o;
593                    }
594                    if (o instanceof Number) {
595                            return ((Number) o).doubleValue() != 0;
596                    }
597                    if (o instanceof Matrix) {
598                            return ((Matrix) o).booleanValue();
599                    }
600                    if (o instanceof String) {
601                            try {
602                                    return Boolean.parseBoolean(((String) o));
603                            } catch (Exception e) {
604                            }
605                    }
606                    return false;
607            }
608    
609            public static byte getByte(Object o) {
610                    if (o == null) {
611                            return 0;
612                    }
613                    if (o instanceof Byte) {
614                            return (Byte) o;
615                    }
616                    if (o instanceof Number) {
617                            return ((Number) o).byteValue();
618                    }
619                    if (o instanceof Matrix) {
620                            return ((Matrix) o).byteValue();
621                    }
622                    if (o instanceof String) {
623                            try {
624                                    return Byte.parseByte(((String) o));
625                            } catch (Exception e) {
626                            }
627                    }
628                    return 0;
629            }
630    
631            public static BigInteger getBigInteger(Object o) {
632                    if (o == null) {
633                            return BigInteger.ZERO;
634                    }
635                    if (o instanceof BigInteger) {
636                            return (BigInteger) o;
637                    }
638                    if (o instanceof Number) {
639                            if (MathUtil.isNaNOrInfinite(o)) {
640                                    throw new IllegalArgumentException("NaN, Inf and -Inf not allowed for BigInteger");
641                            } else {
642                                    return BigInteger.valueOf(((Number) o).longValue());
643                            }
644                    }
645                    if (o instanceof Matrix) {
646                            return ((Matrix) o).bigIntegerValue();
647                    }
648                    if (o instanceof String) {
649                            return new BigInteger((String) o);
650                    }
651                    return BigInteger.ZERO;
652            }
653    
654            public static BigDecimal getBigDecimal(Object o) {
655                    if (o == null) {
656                            return BigDecimal.ZERO;
657                    }
658                    if (o instanceof BigDecimal) {
659                            return (BigDecimal) o;
660                    }
661                    if (o instanceof Number) {
662                            double val = ((Number) o).doubleValue();
663                            if (MathUtil.isNaNOrInfinite(val)) {
664                                    return null;
665                            } else if (val == 0) {
666                                    return BigDecimal.ZERO;
667                            } else if (val == 1) {
668                                    return BigDecimal.ONE;
669                            } else if (val == 10) {
670                                    return BigDecimal.TEN;
671                            } else {
672                                    return BigDecimal.valueOf(val);
673                            }
674                    }
675                    if (o instanceof Matrix) {
676                            return ((Matrix) o).bigDecimalValue();
677                    }
678                    if (o instanceof String) {
679                            try {
680                                    return new BigDecimal((String) o);
681                            } catch (Exception e) {
682                                    return BigDecimal.ZERO;
683                            }
684                    }
685                    return BigDecimal.ZERO;
686            }
687    
688            public static char getChar(Object o) {
689                    if (o == null) {
690                            return 0;
691                    }
692                    if (o instanceof Character) {
693                            return (Character) o;
694                    }
695                    if (o instanceof Number) {
696                            return (char) ((Number) o).byteValue();
697                    }
698                    if (o instanceof Matrix) {
699                            return ((Matrix) o).charValue();
700                    }
701                    if (o instanceof String) {
702                            try {
703                                    return (char) Byte.parseByte(((String) o));
704                            } catch (Exception e) {
705                            }
706                    }
707                    return 0;
708            }
709    
710            public static float getFloat(Object o) {
711                    if (o == null) {
712                            return 0;
713                    }
714                    if (o instanceof Float) {
715                            return (Float) o;
716                    }
717                    if (o instanceof Number) {
718                            return ((Number) o).floatValue();
719                    }
720                    if (o instanceof Matrix) {
721                            return ((Matrix) o).floatValue();
722                    }
723                    if (o instanceof String) {
724                            try {
725                                    return Float.parseFloat(((String) o));
726                            } catch (Exception e) {
727                            }
728                    }
729                    return 0;
730            }
731    
732            public static Object getObject(Object o) {
733                    if (o == null) {
734                            return null;
735                    }
736                    if (o instanceof Matrix) {
737                            Matrix m = (Matrix) o;
738                            if (m.getValueCount() == 1) {
739                                    return m.getAsObject(0, 0);
740                            }
741                    }
742                    return o;
743            }
744    
745            public static int getInt(Object o) {
746                    if (o == null) {
747                            return 0;
748                    }
749                    if (o instanceof Integer) {
750                            return (Integer) o;
751                    }
752                    if (o instanceof Number) {
753                            return ((Number) o).intValue();
754                    }
755                    if (o instanceof Matrix) {
756                            return ((Matrix) o).intValue();
757                    }
758                    if (o instanceof String) {
759                            try {
760                                    return Integer.parseInt(((String) o));
761                            } catch (Exception e) {
762                            }
763                    }
764                    return 0;
765            }
766    
767            public static long getLong(Object o) {
768                    if (o == null) {
769                            return 0;
770                    }
771                    if (o instanceof Long) {
772                            return (Long) o;
773                    }
774                    if (o instanceof Number) {
775                            return ((Number) o).longValue();
776                    }
777                    if (o instanceof Matrix) {
778                            return ((Matrix) o).longValue();
779                    }
780                    if (o instanceof String) {
781                            try {
782                                    return Long.parseLong(((String) o));
783                            } catch (Exception e) {
784                            }
785                    }
786                    return 0;
787            }
788    
789            public static short getShort(Object o) {
790                    if (o == null) {
791                            return 0;
792                    }
793                    if (o instanceof Short) {
794                            return (Short) o;
795                    }
796                    if (o instanceof Number) {
797                            return ((Number) o).shortValue();
798                    }
799                    if (o instanceof Matrix) {
800                            return ((Matrix) o).shortValue();
801                    }
802                    if (o instanceof String) {
803                            try {
804                                    return Short.parseShort(((String) o));
805                            } catch (Exception e) {
806                            }
807                    }
808                    return 0;
809            }
810    
811            public static int[] toIntArray(long... coordinates) {
812                    int[] result = new int[coordinates.length];
813                    for (int i = coordinates.length; --i != -1;) {
814                            result[i] = (int) coordinates[i];
815                    }
816                    return result;
817            }
818    
819            public static long[] toLongArray(int... coordinates) {
820                    long[] result = new long[coordinates.length];
821                    for (int i = coordinates.length; --i != -1;) {
822                            result[i] = coordinates[i];
823                    }
824                    return result;
825            }
826    
827            public static boolean isNull(Object value) {
828                    if (value == null) {
829                            return true;
830                    }
831                    if (value instanceof Number) {
832                            if (((Number) value).doubleValue() == 0.0) {
833                                    return true;
834                            }
835                    }
836                    return false;
837            }
838    
839            public static double norminv(double p, double mu, double sigma) {
840                    if (sigma <= 0) {
841                            return Double.NaN;
842                    }
843    
844                    if (MathUtil.isNaNOrInfinite(p)) {
845                            return Double.NaN;
846                    }
847    
848                    if (p == 1) {
849                            return Double.POSITIVE_INFINITY;
850                    }
851    
852                    if (p == 0) {
853                            return Double.NEGATIVE_INFINITY;
854                    }
855    
856                    if (p < 0 || p > 1) {
857                            return Double.NaN;
858                    }
859    
860                    double r, val;
861                    double p_ = p;
862                    double q = p_ - 0.5;
863    
864                    if (Math.abs(q) <= .425) {
865                            r = .180625 - q * q;
866                            val = q
867                                            * (((((((r * 2509.0809287301226727 + 33430.575583588128105) * r + 67265.770927008700853)
868                                                            * r + 45921.953931549871457)
869                                                            * r + 13731.693765509461125)
870                                                            * r + 1971.5909503065514427)
871                                                            * r + 133.14166789178437745)
872                                                            * r + 3.387132872796366608)
873                                            / (((((((r * 5226.495278852854561 + 28729.085735721942674) * r + 39307.89580009271061)
874                                                            * r + 21213.794301586595867)
875                                                            * r + 5394.1960214247511077)
876                                                            * r + 687.1870074920579083)
877                                                            * r + 42.313330701600911252)
878                                                            * r + 1.);
879                    } else {
880                            if (q > 0) {
881                                    r = 1 - p;
882                            } else {
883                                    r = p_;
884                            }
885    
886                            r = Math.sqrt(-Math.log(r));
887    
888                            if (r <= 5.) {
889                                    r += -1.6;
890                                    val = (((((((r * 7.7454501427834140764e-4 + 0.0227238449892691845833) * r + 0.24178072517745061177)
891                                                    * r + 1.27045825245236838258)
892                                                    * r + 3.64784832476320460504)
893                                                    * r + 5.7694972214606914055)
894                                                    * r + 4.6303378461565452959)
895                                                    * r + 1.42343711074968357734)
896                                                    / (((((((r * 1.05075007164441684324e-9 + 5.475938084995344946e-4) * r + 0.0151986665636164571966)
897                                                                    * r + 0.14810397642748007459)
898                                                                    * r + 0.68976733498510000455)
899                                                                    * r + 1.6763848301838038494)
900                                                                    * r + 2.05319162663775882187)
901                                                                    * r + 1.0);
902                            } else {
903                                    r += -5.;
904                                    val = (((((((r * 2.01033439929228813265e-7 + 2.71155556874348757815e-5) * r + 0.0012426609473880784386)
905                                                    * r + 0.026532189526576123093)
906                                                    * r + 0.29656057182850489123)
907                                                    * r + 1.7848265399172913358)
908                                                    * r + 5.4637849111641143699)
909                                                    * r + 6.6579046435011037772)
910                                                    / (((((((r * 2.04426310338993978564e-15 + 1.4215117583164458887e-7) * r + 1.8463183175100546818e-5)
911                                                                    * r + 7.868691311456132591e-4)
912                                                                    * r + 0.0148753612908506148525)
913                                                                    * r + 0.13692988092273580531)
914                                                                    * r + 0.59983220655588793769)
915                                                                    * r + 1.0);
916                            }
917    
918                            if (q < 0.0) {
919                                    val = -val;
920                            }
921    
922                    }
923                    return mu + sigma * val;
924            }
925    
926            public static double f1measure(double tp, double tn, double fp, double fn) {
927                    double precision = precision(tp, fp);
928                    double recall = recall(tp, fn);
929                    return f1Measure(precision, recall);
930            }
931    
932            public static final long factorial(int n) {
933                    long r = 1;
934                    for (int i = 2; i <= n; i++) {
935                            r *= i;
936                    }
937                    return r;
938            }
939    
940            public static final BigInteger factorialBig(int n) {
941                    BigInteger r = BigInteger.ONE;
942                    for (int i = 2; i <= n; i++) {
943                            r = r.multiply(BigInteger.valueOf(i));
944                    }
945                    return r;
946            }
947    
948            public static final long binomialCoefficient(int n, int k) {
949                    if (k > n || k < 0) {
950                            return 0;
951                    } else {
952                            return factorial(n) / factorial(k) / factorial(n - k);
953                    }
954            }
955    
956            public static final BigInteger binomialCoefficientBig(int n, int k) {
957                    if (k > n || k < 0) {
958                            return BigInteger.ZERO;
959                    } else {
960                            return factorialBig(n).divide(factorialBig(k)).divide(factorialBig(n - k));
961                    }
962            }
963    
964            public static final boolean greater(BigInteger i1, BigInteger i2) {
965                    return i1.subtract(i2).signum() > 0;
966            }
967    
968            public static final boolean smaller(BigInteger i1, BigInteger i2) {
969                    return i1.subtract(i2).signum() < 0;
970            }
971    
972            public static int max(int[] values) {
973                    int max = -Integer.MAX_VALUE;
974                    for (int i = values.length - 1; i != -1; i--) {
975                            max = values[i] > max ? values[i] : max;
976                    }
977                    return max;
978            }
979    
980            public static int min(int[] values) {
981                    int min = Integer.MAX_VALUE;
982                    for (int i = values.length - 1; i != -1; i--) {
983                            min = values[i] < min ? values[i] : min;
984                    }
985                    return min;
986            }
987    
988            public static final BigDecimal plus(BigDecimal v1, BigDecimal v2) {
989                    if (v1 != null && v2 != null) {
990                            return v1.add(v2, getDefaultMathContext());
991                    } else {
992                            return null;
993                    }
994            }
995    
996            public static final BigDecimal minus(BigDecimal v1, BigDecimal v2) {
997                    if (v1 != null && v2 != null) {
998                            return v1.subtract(v2, getDefaultMathContext());
999                    } else {
1000                            return null;
1001                    }
1002            }
1003    
1004            public static final BigDecimal times(BigDecimal v1, BigDecimal v2) {
1005                    if (v1 != null && v2 != null) {
1006                            return v1.multiply(v2, getDefaultMathContext());
1007                    } else {
1008                            return null;
1009                    }
1010            }
1011    
1012            public static final BigDecimal divide(BigDecimal v1, BigDecimal v2) {
1013                    if (BigDecimal.ZERO.equals(v2)) {
1014                            return null;
1015                    } else if (v1 != null && v2 != null) {
1016                            return v1.divide(v2, getDefaultMathContext());
1017                    } else {
1018                            return null;
1019                    }
1020            }
1021    
1022            public static boolean isGreater(BigDecimal v1, BigDecimal v2) {
1023                    return v1.compareTo(v2) > 0;
1024            }
1025    
1026            public static boolean isSmaller(BigDecimal v1, BigDecimal v2) {
1027                    return v1.compareTo(v2) < 0;
1028            }
1029    
1030            public static boolean isEqual(BigDecimal v1, BigDecimal v2) {
1031                    return v1.compareTo(v2) == 0;
1032            }
1033    
1034            // Compute square root of large numbers using Heron's method
1035            // adapted from http://www.merriampark.com/bigsqrt.htm
1036            public static final BigDecimal sqrt(BigDecimal n) {
1037                    if (n.compareTo(BigDecimal.ZERO) <= 0) {
1038                            throw new IllegalArgumentException();
1039                    }
1040    
1041                    final BigDecimal TWO = new BigDecimal("2");
1042                    BigDecimal error;
1043                    BigDecimal lastGuess = BigDecimal.ZERO;
1044                    BigDecimal guess = BigDecimal.ONE.movePointRight(n.toBigInteger().toString().length() / 2);
1045                    int maxIterations = 50;
1046                    int iterations = 0;
1047                    boolean more = true;
1048                    while (more) {
1049                            lastGuess = guess;
1050                            guess = n.divide(guess, UJMPSettings.getDefaultMathContext());
1051                            guess = guess.add(lastGuess);
1052                            guess = guess.divide(TWO, UJMPSettings.getDefaultMathContext());
1053                            error = n.subtract(guess.multiply(guess));
1054                            if (++iterations >= maxIterations) {
1055                                    more = false;
1056                            } else if (lastGuess.equals(guess)) {
1057                                    more = error.abs().compareTo(BigDecimal.ONE) >= 0;
1058                            }
1059                    }
1060                    return guess;
1061            }
1062    
1063            /**
1064             * from numerical recipes in c (p. 214)
1065             */
1066            public static final double gammaln(double x) {
1067                    double ser = 1.00000000090015;
1068                    double y = x;
1069                    double tmp = x + 5.5;
1070                    tmp -= (x + 0.5) * Math.log(tmp);
1071                    for (int j = 0; j < +5; j++) {
1072                            ser += COFGAMMALN[j] / ++y;
1073                    }
1074                    return -tmp + Math.log(ser * 2.5066282751072975 / x);
1075            }
1076    
1077            public static final long pos2IndexRowMajor(long[] size, long[] pos) {
1078                    long sum = 0;
1079                    long prod = 1;
1080                    final int length = pos.length;
1081                    for (int k = length - 1; k >= 0; k--) {
1082                            sum += prod * pos[k];
1083                            prod *= size[k];
1084                    }
1085                    return sum;
1086            }
1087    
1088            public static final long pos2IndexColumnMajor(long[] size, long[] pos) {
1089                    long sum = 0;
1090                    long prod = 1;
1091                    final int length = pos.length;
1092                    for (int k = 0; k < length; k++) {
1093                            sum += prod * pos[k];
1094                            prod *= size[k];
1095                    }
1096                    return sum;
1097            }
1098    
1099            public static final long[] index2PosRowMajor(long[] size, long index) {
1100                    final long[] pos = new long[size.length];
1101                    long res = index;
1102                    for (int k = size.length; --k != -1;) {
1103                            pos[k] = res % size[k];
1104                            res /= size[k];
1105                    }
1106                    return pos;
1107            }
1108    
1109            public static final long[] index2PosColumnMajor(long[] size, long index) {
1110                    final int length = size.length;
1111                    final long[] pos = new long[length];
1112                    long res = index;
1113                    for (int k = 0; k < length; k++) {
1114                            pos[k] = res % size[k];
1115                            res /= size[k];
1116                    }
1117                    return pos;
1118            }
1119    
1120    }