/* Copyright (C) 2002 Univ. of Massachusetts Amherst, Computer Science Dept. This file is part of "MALLET" (MAchine Learning for LanguagE Toolkit). http://www.cs.umass.edu/~mccallum/mallet This software is provided under the terms of the Common Public License, version 1.0, as published by http://www.opensource.org. For further information, see the file `LICENSE' included with this distribution. */ /** @author Andrew McCallum <a href="mailto:mccallum@cs.umass.edu">mccallum@cs.umass.edu</a> */ package edu.nd.nina.types; import edu.nd.nina.util.MathUtil; public abstract class DenseMatrix implements Matrix { double[] values; protected boolean hasInfinite; // if true, at least one value = -Inf or +Inf public abstract int getNumDimensions(); public abstract int getDimensions(int[] sizes); public abstract double value(int[] indices); public abstract void setValue(int[] indices, double value); public abstract ConstantMatrix cloneMatrix(); public abstract int singleIndex(int[] indices); public abstract void singleToIndices(int i, int[] indices); public double singleValue(int i) { return values[i]; } public void setSingleValue(int i, double value) { values[i] = value; } public void incrementSingleValue(int i, double delta) { values[i] += delta; } public void setValueAtLocation(int loc, double value) { // indices == locations setSingleValue(loc, value); } public int singleSize() { return values.length; } public int numLocations() { return values.length; } public int location(int index) { return index; } public double valueAtLocation(int location) { return values[location]; } // Returns a "singleIndex" public int indexAtLocation(int location) { return location; } public void setAll(double v) { for (int i = 0; i < values.length; i++) values[i] = v; } public void set(ConstantMatrix m) { if (m instanceof DenseMatrix) { assert (m.singleSize() == values.length); System.arraycopy(((DenseMatrix) m).values, 0, values, 0, values.length); } else for (int i = m.numLocations() - 1; i >= 0; i--) values[m.indexAtLocation(i)] = m.valueAtLocation(i); } public void setWithAddend(ConstantMatrix m, double addend) { if (m instanceof DenseMatrix) { assert (m.singleSize() == values.length); for (int i = 0; i < values.length; i++) values[i] = ((DenseMatrix) m).values[i] + addend; } else for (int i = m.numLocations() - 1; i >= 0; i--) values[m.indexAtLocation(i)] = m.valueAtLocation(i) + addend; } public void setWithFactor(ConstantMatrix m, double factor) { if (m instanceof DenseMatrix) { assert (m.singleSize() == values.length); for (int i = 0; i < values.length; i++) values[i] = ((DenseMatrix) m).values[i] * factor; } else for (int i = m.numLocations() - 1; i >= 0; i--) values[m.indexAtLocation(i)] = m.valueAtLocation(i) * factor; } public void plusEquals(double v) { for (int i = 0; i < values.length; i++) values[i] += v; } public void plusEquals(ConstantMatrix m) { if (m instanceof DenseMatrix) { assert (m.singleSize() == values.length); for (int i = 0; i < values.length; i++) { // added by Culotta - 12.10.0 to enforce INF - INF = 0 if (Double.isInfinite(values[i]) && Double.isInfinite(m.valueAtLocation(i))) { double newValue = m.valueAtLocation(i); // make sure they're opposite signed if ((newValue * values[i]) < 0) { values[i] = 0.0; // inf - inf = 0 } else values[i] += newValue; } else values[i] += m.valueAtLocation(i); } } else for (int i = m.numLocations() - 1; i >= 0; i--) { // added by Culotta - 12.10.02 to enforce INF - INF = 0 if (Double.isInfinite(values[m.indexAtLocation(i)]) && Double.isInfinite(((DenseMatrix) m).values[i])) { double newValue = m.valueAtLocation(i); // make sure they're oppisite signed if ((newValue * values[m.indexAtLocation(i)]) < 0) { values[m.indexAtLocation(i)] = 0.0; } else values[m.indexAtLocation(i)] += newValue; } else values[m.indexAtLocation(i)] += m.valueAtLocation(i); } } public void plusEquals(ConstantMatrix m, double factor) { if (m instanceof DenseMatrix) { assert (m.singleSize() == values.length); for (int i = 0; i < values.length; i++) { // added by Culotta - 12.10.0 to enforce INF - INF = 0 if (Double.isInfinite(values[i]) && Double.isInfinite(m.valueAtLocation(i))) { double newValue = factor * (m.valueAtLocation(i)); // make sure they're opposite signed if ((newValue * values[i]) < 0) { values[i] = 0.0; // inf - inf = 0 } else values[i] += newValue; } else values[i] += (m.valueAtLocation(i) * factor); } } else for (int i = m.numLocations() - 1; i >= 0; i--) { // added by Culotta - 12.10.02 to enforce INF - INF = 0 if (Double.isInfinite(values[m.indexAtLocation(i)]) && Double.isInfinite(m.valueAtLocation(i))) { double newValue = factor * m.valueAtLocation(i); // make sure they're oppisite signed if ((newValue * values[m.indexAtLocation(i)]) < 0) { values[m.indexAtLocation(i)] = 0.0; } else values[m.indexAtLocation(i)] += newValue; } else values[m.indexAtLocation(i)] += m.valueAtLocation(i) * factor; } } public void equalsPlus(double factor, ConstantMatrix m) { if (m instanceof DenseMatrix) { assert (m.singleSize() == values.length); for (int i = 0; i < values.length; i++) { // added by Culotta - 12.10.0 to enforce INF - INF = 0 if (Double.isInfinite(values[i]) && Double.isInfinite(((DenseMatrix) m).values[i])) { double lhs = factor * values[i]; double rhs = ((DenseMatrix) m).values[i]; // make sure they're opposite signed if ((lhs * rhs) < 0) { values[i] = 0.0; // inf - inf = 0 } else values[i] = lhs + rhs; } else values[i] = factor * values[i] + ((DenseMatrix) m).values[i]; } } else for (int i = m.numLocations() - 1; i >= 0; i--) { // added by Culotta - 12.10.02 to enforce INF - INF = 0 if (Double.isInfinite(values[m.indexAtLocation(i)]) && Double.isInfinite(((DenseMatrix) m).values[i])) { double lhs = factor * values[m.indexAtLocation(i)]; double rhs = m.valueAtLocation(i); // make sure they're oppisite signed if ((lhs * rhs) < 0) { values[m.indexAtLocation(i)] = 0.0; } else values[m.indexAtLocation(i)] = lhs + rhs; } else values[m.indexAtLocation(i)] = factor * values[m.indexAtLocation(i)] + m.valueAtLocation(i); } } public void timesEquals(double factor) { for (int i = 0; i < values.length; i++) values[i] *= factor; } public void elementwiseTimesEquals(ConstantMatrix m) { if (m instanceof DenseMatrix) { assert (m.singleSize() == values.length); for (int i = 0; i < values.length; i++) values[i] *= ((DenseMatrix) m).values[i]; } else for (int i = m.numLocations() - 1; i >= 0; i--) values[m.indexAtLocation(i)] *= m.valueAtLocation(i); } public void elementwiseTimesEquals(ConstantMatrix m, double factor) { if (m instanceof DenseMatrix) { assert (m.singleSize() == values.length); for (int i = 0; i < values.length; i++) values[i] *= ((DenseMatrix) m).values[i] * factor; } else for (int i = m.numLocations() - 1; i >= 0; i--) values[m.indexAtLocation(i)] *= m.valueAtLocation(i) * factor; } public void divideEquals(double factor) { for (int i = 0; i < values.length; i++) values[i] /= factor; } public void elementwiseDivideEquals(ConstantMatrix m) { if (m instanceof DenseMatrix) { assert (m.singleSize() == values.length); for (int i = 0; i < values.length; i++) values[i] /= ((DenseMatrix) m).values[i]; } else for (int i = m.numLocations() - 1; i >= 0; i--) values[m.indexAtLocation(i)] /= m.valueAtLocation(i); } public void elementwiseDivideEquals(ConstantMatrix m, double factor) { if (m instanceof DenseMatrix) { assert (m.singleSize() == values.length); for (int i = 0; i < values.length; i++) values[i] /= ((DenseMatrix) m).values[i] * factor; } else for (int i = m.numLocations() - 1; i >= 0; i--) values[m.indexAtLocation(i)] /= m.valueAtLocation(i) * factor; } // xxx Perhaps make a special efficient case for binary vectors public double dotProduct(ConstantMatrix m) { double ret = 0; if (m instanceof DenseMatrix) { assert (m.singleSize() == values.length); for (int i = 0; i < values.length; i++) ret += values[i] * ((DenseMatrix) m).values[i]; } else { for (int i = m.numLocations() - 1; i >= 0; i--) if (m.indexAtLocation(i) < values.length)// fix problem ret += values[m.indexAtLocation(i)] * m.valueAtLocation(i); else { // System.out.println(m.indexAtLocation(i) + ":" + // values.length); // throw new // ArrayIndexOutOfBoundsException(m.indexAtLocation(i)); } } return ret; } public double absNorm() { double ret = 0; for (int i = 0; i < values.length; i++) ret += Math.abs(values[i]); return ret; } public double oneNorm() { double ret = 0; for (int i = 0; i < values.length; i++) ret += values[i]; return ret; } public double twoNorm() { double ret = 0; for (int i = 0; i < values.length; i++) ret += values[i] * values[i]; return Math.sqrt(ret); } public double infinityNorm() { double max = Double.NEGATIVE_INFINITY; for (int i = 0; i < values.length; i++) if (Math.abs(values[i]) > max) max = Math.abs(values[i]); return max; } public double oneNormalize() { double norm = oneNorm(); for (int i = 0; i < values.length; i++) values[i] /= norm; return norm; } public double twoNormalize() { double norm = twoNorm(); for (int i = 0; i < values.length; i++) values[i] /= norm; return norm; } public double absNormalize() { double norm = absNorm(); if (norm > 0) for (int i = 0; i < values.length; i++) values[i] /= norm; return norm; } public double infinityNormalize() { double norm = infinityNorm(); for (int i = 0; i < values.length; i++) values[i] /= norm; return norm; } public void print() { for (int i = 0; i < values.length; i++) System.out.println("DenseMatrix[" + i + "] = " + values[i]); } public boolean isNaN() { for (int i = 0; i < values.length; i++) if (Double.isNaN(values[i])) return true; return false; } public final void substitute(double oldValue, double newValue) { for (int i = values.length - 1; i >= 0; i--) if (values[i] == oldValue) values[i] = newValue; } public static void plusEquals(double[] accumulator, double[] addend) { assert (accumulator.length == addend.length); for (int i = 0; i < addend.length; i++) accumulator[i] += addend[i]; } public static void plusEquals(double[] accumulator, double[] addend, double factor) { assert (accumulator.length == addend.length); for (int i = 0; i < addend.length; i++) accumulator[i] += factor * addend[i]; } public static void timesEquals(double[] accumulator, double[] product) { assert (accumulator.length == product.length); for (int i = 0; i < product.length; i++) accumulator[i] *= product[i]; } public static double infinityNorm(double[] vector) { double max = Double.NEGATIVE_INFINITY; for (int i = 0; i < vector.length; i++) if (Math.abs(vector[i]) > max) max = Math.abs(vector[i]); return max; } // This should probably be generalized. public boolean almostEquals(ConstantMatrix m2) { if (getNumDimensions() != m2.getNumDimensions()) { return false; } if (numLocations() != m2.numLocations()) { return false; } int[] dims1 = new int[getNumDimensions()]; int[] dims2 = new int[getNumDimensions()]; getDimensions(dims1); m2.getDimensions(dims2); for (int i = 0; i < dims1.length; i++) { if (dims1[i] != dims2[i]) { return false; } } for (int i = 0; i < numLocations(); i++) { if (!MathUtil.almostEquals(valueAtLocation(i), m2.valueAtLocation(i))) { return false; } } return true; } }