All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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