/* 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;
}
}