/** * Copyright 2014, Emory University * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package edu.emory.clir.clearnlp.util; import edu.emory.clir.clearnlp.classification.vector.SparseFeatureVector; /** * @since 3.0.0 * @author Jinho D. Choi ({@code jinho.choi@emory.edu}) */ public class MathUtils { static public double DOUBLE_NEGATIVE_MIN = 4.9E-324; private MathUtils() {} static public double average(double... array) { double sum = 0; for (double d : array) sum += d; return sum / array.length; } static public double variance(double... array) { double avg = average(array), sum = 0; for (double d : array) sum += sq(d - avg); return sum / (array.length - 1); } static public double stdev(double... array) { return Math.sqrt(variance(array)); } static public int ceil(double d) { return (int)Math.ceil(d); } static public double divide(int numerator, int denominator) { return (double)numerator / denominator; } static public double divide(long numerator, long denominator) { return (double)numerator / denominator; } static public double accuracy(int correct, int total) { return 100d * correct / total; } static public double reciprocal(int number) { return divide(1, number); } /** @param exponent non-negative integer. */ static public double pow(double base, int exponent) { if (exponent == 0) return 1; if (exponent == 1) return base; if (exponent == -1) return 1/base; boolean negative; if (exponent < 0) { negative = true; exponent = -exponent; } else negative = false; double mod = (exponent%2 == 0) ? 1 : base; double p = base; exponent /= 2; while (exponent > 0) { p = p * p; exponent /= 2; } mod *= p; return negative ? 1/mod : mod; } static public long sq(long l) { return l * l; } static public double sq(double d) { return d * d; } static public double sq(float f) { return f * f; } static public int signum(double d) { return (int)Math.signum(d); } static public double getF1(double precision, double recall) { return (precision + recall == 0) ? 0 : 2 * (precision * recall) / (precision + recall); } static public double getAccuracy(int correct, int total) { return 100d * correct / total; } static public double sum(double[] vector) { double sum = 0; for (double d : vector) sum += d; return sum; } static public double sum(float[] vector) { double sum = 0; for (double d : vector) sum += d; return sum; } static public double sumOfSquares(double[] vector) { double sum = 0; for (double d : vector) sum += sq(d); return sum; } static public void multiply(float[] array, int multiplier) { int i, size = array.length; for (i=0; i<size; i++) array[i] *= multiplier; } /** @param n a positive integer. */ static public boolean isPrimeNumber(long n) { if (n < 2) return false; if (n == 2 || n == 3) return true; if (n%2 == 0 || n%3 == 0) return false; long i, sqrt = (long)Math.sqrt(n) + 1; for (i=6; i<=sqrt; i+=6) { if (n%(i-1) == 0 || n%(i+1) == 0) return false; } return true; } /** * @param n inclusive. * @return the next prime number if exists; otherwise, {@code -1}. */ static public long nextPrimeNumber(long n) { while (true) { if (n >= Long.MAX_VALUE) return -1; if (isPrimeNumber(n)) return n; n++; } } /** * @param a either a positive or negative integer. * @param b a positive integer. */ static public int divisor(int a, int b) { return (a < 0) ? ((a % b) + b) % b : a % b; } static public double getCosineSimilarity(SparseFeatureVector v1, SparseFeatureVector v2) { int i1, i2, idx1 = 0, idx2 = 0, len1 = v1.size(), len2 = v2.size(); double d1, d2, num = 0, den1 = 0, den2 = 0; while (idx1 < len1 && idx2 < len2) { i1 = v1.getIndex(idx1); i2 = v2.getIndex(idx2); d1 = v1.getWeight(idx1); d2 = v2.getWeight(idx2); den1 += MathUtils.sq(d1); den2 += MathUtils.sq(d2); if (i1 < i2) idx1++; else if (i1 > i2) idx2++; else { num += d1 * d2; idx1++; idx2++; } } for (; idx1<len1; idx1++) den1 += MathUtils.sq(v1.getWeight(idx1)); for (; idx2<len2; idx2++) den2 += MathUtils.sq(v2.getWeight(idx2)); return num / (Math.sqrt(den1) * Math.sqrt(den2)); } }