
org.nuiton.math.matrix.MatrixNDImpl Maven / Gradle / Ivy
The newest version!
/*
* #%L
* Nuiton Matrix :: API
* %%
* Copyright (C) 2004 - 2010 CodeLutin
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
package org.nuiton.math.matrix;
import java.lang.ref.Reference;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* MatrixNDImpl.
*
* Created: 29 oct. 2004
*
* @author Benjamin Poussin <[email protected]>
* @version $Revision$
*
* Mise a jour: $Date$
* par : $Author$
*/
public class MatrixNDImpl extends AbstractMatrixND { // MatrixNDImpl
/** serialVersionUID. */
private static final long serialVersionUID = 1L;
/** to use log facility, just put in your code: log.info(\"...\"); */
private static Log log = LogFactory.getLog(MatrixNDImpl.class);
public static List> allMat = new LinkedList>();
protected BasicMatrix matrix = null;
@Override
public long getNumberOfAssignedValue() {
return matrix.getNumberOfAssignedValue();
}
// /**
// * Used for statistic on matrix usage
// * @throws Throwable
// */
// @Override
// protected void finalize() throws Throwable {
// if (matrix != null && matrix.getInternalVector() != null) {
// Vector v = matrix.getInternalVector();
// String name = getName();
// String[] dimName = getDimensionNames();
// log.fatal("Stat: " + v.getInfo() + " for " + name + "(" + Arrays.toString(dimName) + ")");
// }
// super.finalize();
// }
//
// {
// allMat.add(new WeakReference(this));
// }
// static {
// Runtime.getRuntime().addShutdownHook(new Thread(){
//
// @Override
// public void run() {
// for (Reference r : allMat) {
// MatrixNDImpl m = r.get();
// if (m != null) {
// try {
// m.finalize();
// } catch (Throwable ex) {
// // just info in finalize, exception is not important
// }
// }
// }
// log.fatal("Stat: " + allMat.size() + " matrice creee");
// }
//
// });
// }
protected MatrixNDImpl(MatrixFactory factory, int[] dim) {
super(factory, dim);
matrix = new BasicMatrix(factory, dim);
}
protected MatrixNDImpl(MatrixFactory factory, List>[] semantics) {
super(factory, semantics);
matrix = new BasicMatrix(factory, dim);
}
protected MatrixNDImpl(MatrixFactory factory, String name, int[] dim) {
super(factory, name, dim);
matrix = new BasicMatrix(factory, dim);
}
protected MatrixNDImpl(MatrixFactory factory, String name, int[] dim,
String[] dimNames) {
super(factory, name, dim, dimNames);
matrix = new BasicMatrix(factory, dim);
}
protected MatrixNDImpl(MatrixFactory factory, String name, int[] dim,
String[] dimNames, Vector data) {
super(factory, name, dim, dimNames);
matrix = new BasicMatrix(factory, data, dim);
}
protected MatrixNDImpl(MatrixFactory factory, String name,
List>[] semantics) {
super(factory, name, semantics);
matrix = new BasicMatrix(factory, dim);
}
protected MatrixNDImpl(MatrixFactory factory, String name,
List>[] semantics, String[] dimNames) {
super(factory, name, semantics, dimNames);
matrix = new BasicMatrix(factory, dim);
}
protected MatrixNDImpl(MatrixFactory factory, String name,
List>[] semantics, String[] dimNames, Vector data) {
super(factory, name, semantics, dimNames);
matrix = new BasicMatrix(factory, data, dim);
}
protected MatrixNDImpl(MatrixFactory factory, MatrixND matrix) {
super(factory, matrix.getName(), matrix.getSemantics(), matrix
.getDimensionNames());
this.matrix = new BasicMatrix(factory, dim);
this.paste(matrix);
}
protected MatrixNDImpl(MatrixFactory factory, MatrixND matrix, Vector data) {
super(factory, matrix.getName(), matrix.getSemantics(), matrix
.getDimensionNames());
this.matrix = new BasicMatrix(factory, data, dim);
this.paste(matrix);
}
public BasicMatrix getInternalMatrix() {
return matrix;
}
@Override
public boolean equalsValues(MatrixND mat) {
boolean result;
if (mat instanceof MatrixNDImpl) {
result = matrix.equals(((MatrixNDImpl) mat).matrix);
} else {
result = super.equalsValues(mat);
}
return result;
}
@Override
public MatrixIterator iterator() {
return new MatrixIteratorImpl(matrix.iterator(), getSemantics());
}
@Override
public MatrixIterator iteratorNotZero() {
return new MatrixIteratorImpl(matrix.iteratorNotZero(), getSemantics());
}
@Override
public double getValue(int[] coordinates) {
return matrix.getValue(coordinates);
}
@Override
public void setValue(int[] coordinates, double d) {
matrix.setValue(coordinates, d);
}
@Override
@Deprecated
public double getMaxOccurence() {
return getMaxOccurrence();
}
@Override
public double getMaxOccurrence() {
return matrix.getMaxOccurrence();
}
@Override
public String toString() {
return getName() + " " + matrix.toString();
}
// Un peu d'optimisation pour les matrices entieres (pas de sub matrix)
/**
* Si le vector utilise par la BasicMatix supporte la method map, on
* l'utilise pour gagner du temps
*/
@Override
public MatrixND map(MapFunction f) {
if (matrix.data.isImplementedMap()) {
matrix.data.map(f);
} else {
super.map(f);
}
return this;
}
/**
* Si on peut on utilise le paste du vector de BasicMatix, sinon on utilise
* la methode de AbstractMatrixND.
*/
@Override
public MatrixND paste(int[] origin, MatrixND mat) {
// permet de savoir si l'origin est bien le point 0 de la matrice
boolean origin0 = true;
for (int i = 0; i < origin.length && origin0; i++) {
origin0 = origin0 && origin[i] == 0;
}
if (origin0
&& mat instanceof MatrixNDImpl
&& Arrays.equals(mat.getDim(), this.getDim())
&& matrix.data
.isImplementedPaste(((MatrixNDImpl) mat).matrix.data)) {
matrix.data.paste(((MatrixNDImpl) mat).matrix.data);
} else {
super.paste(origin, mat);
}
return this;
}
@Override
public MatrixND pasteSemantics(MatrixND mat) {
boolean pasteDone = false;
// optimisation si on a les memes semantics
if (mat instanceof MatrixNDImpl) {
MatrixNDImpl mImpl = (MatrixNDImpl) mat;
if (MatrixHelper.sameSemantics(semantics, mImpl.semantics)) {
if (matrix.data.isImplementedPaste(mImpl.matrix.data)) {
matrix.data.paste(mImpl.matrix.data);
pasteDone = true;
}
}
}
if (!pasteDone) {
super.pasteSemantics(mat);
}
return this;
}
@Override
public MatrixND add(MatrixND m) {
if (m instanceof MatrixNDImpl
&& matrix.data.isImplementedAdd(((MatrixNDImpl) m).matrix.data)) {
matrix.data.add(((MatrixNDImpl) m).matrix.data);
} else {
super.add(m);
}
return this;
}
/**
* Modifie la matrice actuelle en lui soustrayant les valeurs de la matrice
* passé en parametre. La matrice passé en parametre doit avoir le meme
* nombre de dimension, et chacune de ses dimensions doit avoir un nombre
* d'element au moins egal a cette matrice.
*/
@Override
public MatrixND minus(MatrixND m) {
if (m instanceof MatrixNDImpl
&& matrix.data
.isImplementedMinus(((MatrixNDImpl) m).matrix.data)) {
matrix.data.minus(((MatrixNDImpl) m).matrix.data);
} else {
super.minus(m);
}
return this;
}
private boolean useLegacySumOverDim(Vector data) {
return ((data instanceof LazyVector &&
(((LazyVector) data).backend instanceof LegacyDoubleSparseHashVector
|| ((LazyVector) data).backend instanceof LegacyDoubleBigVector))
|| data instanceof LegacyDoubleSparseHashVector || data instanceof LegacyDoubleBigVector);
}
@Override
public MatrixND sumOverDim(int d) {
Vector data = this.matrix.data;
// Si la matrice utilise LegacyDoubleSparseHashVector ou LegacyDoubleBigVector pour stocker ses données,
// alors on utilise l'ancien algorithme sumOverDim
if (useLegacySumOverDim(data)) {
return super.sumOverDim(d);
}
// s'il n'y a rien à sommer, on retourne une copie
if (dim[d] <= 1) {
return copy();
}
// copie des sémantiques
List>[] sems = new List>[dim.length];
System.arraycopy(semantics, 0, sems, 0, dim.length);
sems[d] = Collections.singletonList(0);
MatrixNDImpl result = new MatrixNDImpl(factory, name, sems, dimNames);
// linearFactor[d]
long linearFactorDim = Arrays.stream(dim, d + 1, dim.length).reduce(1, (a, b) -> a * b);
// linearFactor[d-1]
long linearFactorDimMinusOne = linearFactorDim * dim[d];
Vector resultData = result.matrix.data;
data.forEachNotZero((pos, val) -> {
// on calcule la coordonnee linéaire dans la matrice résultat,
// puis on fait l'addition directement dans le Vector sous-jacent (cela evite la conversion de coordonnees)
long chunk = pos / linearFactorDimMinusOne;
long destPos = (linearFactorDimMinusOne * chunk + pos % linearFactorDim) % linearFactorDimMinusOne + chunk * linearFactorDim;
double currentVal = resultData.getValue(destPos);
resultData.setValue(destPos, currentVal + val);
});
return result;
}
} // MatrixNDImpl
© 2015 - 2025 Weber Informatics LLC | Privacy Policy