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

org.nuiton.math.matrix.BasicMatrix Maven / Gradle / Ivy

The newest version!
/* *##% NuitonMatrix
 * Copyright (C) 2004 - 2009 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
 * . ##%*/

package org.nuiton.math.matrix;

import java.util.Arrays;
import java.util.NoSuchElementException;

import org.nuiton.i18n.I18n;

/**
 * Objet matrice qui ne permet que le stockage de double dans un matrice à
 * autant de dimension que l'on souhaite.
 * 
 * Created: 27 oct. 2004
 *
 * @author Benjamin Poussin 
 * @version $Revision: 179 $
 *
 * Mise a jour: $Date: 2009-10-08 15:23:44 +0200 (jeu., 08 oct. 2009) $
 * par : $Author: echatellier $
 */
public class BasicMatrix { // BasicMatrix

    /** La factory */
    protected MatrixFactory factory = null;
    /** Les dimensions de la matrice */
    protected int[] dimensions = null;
    /** La matrice en représentation linéaire */
    protected Vector data = null;

    /**
     * tableau de facteur permettant de convertir les coordonnées dans la
     * matrice en un indice dans la représentation linéaire de la matrice
     */
    protected int[] linearFactor = null;

    /**
     * Crée une nouvelle matrice ayant les dimensions demandées.
     * 
     * @param factory factory
     * @param dimensions dimensions
     */
    public BasicMatrix(MatrixFactory factory, int[] dimensions) {
        this.factory = factory;
        checkDim(dimensions);

        // copie des dimensions pour que personne à l'extérieur de l'objet
        // ne puisse les modifiers par la suite
        this.dimensions = new int[dimensions.length];
        System.arraycopy(dimensions, 0, this.dimensions, 0, dimensions.length);

        // calcul du linearFactor
        linearFactor = new int[dimensions.length];
        linearFactor[linearFactor.length - 1] = 1;
        for (int i = linearFactor.length - 2; i >= 0; i--) {
            linearFactor[i] = linearFactor[i + 1] * dimensions[i + 1];
        }

        // creation de la matrice lineaire
        data = factory.createVector(linearFactor[0] * dimensions[0]);
    }

    /**
     * Retourne la valeur la plus courrement rencontrer dans la matrice. si
     * plusieurs valeurs ont le même nombre d'occurence la plus petite valeur
     * est retourné.
     * 
     * @return la valeur la plus nombreuse dans la matrice, ou la plus petite si
     *         plusieurs valeur se retourve le même nombre de fois
     */
    public double getMaxOccurence() {
        return data.getMaxOccurence();
    }

    /**
     * Retourne le nombre de dimension de la matrice
     * 
     * @return le nombre de dimension de la matrice;
     */
    public int getNbDim() {
        return dimensions.length;
    }

    /**
     * Retourne la taille d'une dimension
     * 
     * @param dim la dimension dont on souhaite la taille
     * @return la taille d'une dimension
     */
    public int getDim(int dim) {
        checkDim(dim);
        return dimensions[dim];
    }

    /**
     * Retourne un tableau representant les dimensions de la matrice. Le tableau
     * retourné n'est pas une copie, il ne faut donc pas le modifier
     * 
     * @return le tableau des dimensions.
     */
    public int[] getDim() {
        return dimensions;
    }

    /**
     * Retourne un element de la matrice
     * 
     * @param pos la position de l'element à retourner
     * @return un element de la matrice
     */
    public double getValue(int[] pos) {
        int indice = coordonatesToLinear(pos);
        return data.getValue(indice);
    }

    /**
     * Modifie un élement de la matrice
     * 
     * @param pos la position de l'element à modifier
     * @param value la nouvelle valeur à mettre dans la matrice
     */
    public void setValue(int[] pos, double value) {
        int indice = coordonatesToLinear(pos);
        data.setValue(indice, value);
    }

    /**
     * Retourne un objet Inc pret a etre utilisé pour boucler sur tous les
     * element de la matrice.
     * 
     * @return un objet Inc pret à être utilisé
     */
    public BasicMatrixIterator iterator() {
        return new BasicMatrixIteratorImpl(this);
    }

    /**
     * Permet de faire un traitement sur chaque valeur de la matrice
     * 
     * @param f la fonction a appliquer à chaque élement de la matrice
     */
    public void map(MapFunction f) {
        if (data.isImplementedMap()) {
            data.map(f);
        } else {
            for (int i = 0; i < data.size(); i++) {
                double result = f.apply(data.getValue(i));
                data.setValue(i, result);
            }
        }
    }

    /**
     * Permet de convertir les coordonnées d'un élément en un indice dans la
     * représentation linéraire de la matrice.
     * 
     * @param coordonates les coordonnées à lineariser
     * @return un indice réprésentant les coordonnées de façon linéaire
     */
    protected int coordonatesToLinear(int[] coordonates) {
        checkPos(coordonates);

        int result = 0;
        for (int i = 0; i < linearFactor.length; i++) {
            result += coordonates[i] * linearFactor[i];
        }
        return result;
    }

    /**
     * Convertie une coordonnée lineaire en coordonnées spaciales
     * 
     * @param pos la coordonnée linéaire
     * @return les coordonnées spaciales de l'élément
     */
    protected int[] linearToCoordinates(int pos) {
        int[] result = new int[linearFactor.length];

        for (int i = 0; i < result.length; i++) {
            result[i] = pos / linearFactor[i];
            pos -= result[i] * linearFactor[i];
        }
        return result;
    }

    /**
     * Permet de vérifier que les dimensions de la nouvelle matrice sont
     * corrects
     * 
     * @param dim les dimensions de la nouvelle matrice
     * @throws IllegalArgumentException si une dimension n'est pas valide
     */
    protected void checkDim(int[] dim) {
        for (int i = 0; i < dim.length; i++) {
            if (dim[i] <= 0) {
                throw new IllegalArgumentException(I18n._(
                        "nuitonmatrix.invalid.size", Integer.valueOf(i), Integer
                                .valueOf(dim[i])));
            }
        }
    }

    /**
     * Permet de vérifier qu'une dimension demandé existe bien dans la matrice
     * 
     * @param dim la position de la dimension que l'on souhaite
     * @throws IndexOutOfBoundsException si la dimension demandée n'existe pas
     */
    protected void checkDim(int dim) {
        if (dim < 0 || dim >= getNbDim()) {
            throw new IndexOutOfBoundsException(I18n._(
                    "nuitonmatrix.invalid.size", dim, getNbDim()));
        }
    }

    /**
     * Verifie que les coordonnées demandé appartiennent bien à la matrice
     * 
     * @param pos les coordonnées souhaitées dans la matrice
     * @throws NoSuchElementException si les coordonnées ne correspondent pas à
     *             un élement de la matrice
     */
    protected void checkPos(int[] pos) {
        int[] dim = getDim();
        boolean result = dim.length == pos.length;
        for (int i = 0; result && i < dim.length; i++) {
            result = (0 <= pos[i]) && (pos[i] < dim[i]);
        }
        if (!result) {
            throw new NoSuchElementException(I18n._(
                    "nuitonmatrix.invalid.element", Arrays.toString(pos), Arrays
                            .toString(dim)));
        }
    }

    @Override
    public String toString() {
        StringBuffer result = new StringBuffer();
        if (getNbDim() == 1) {
            result.append("matrix1D [");
            for (int i = 0; i < data.size(); i++) {
                result.append(data.getValue(i) + ",");
            }
            result.append("]");
        } else if (getNbDim() == 2) {
            DimensionHelper dimHelper = new DimensionHelper();
            result.append("matrix2D [");
            for (int y = 0; y < getDim(1); y++) {
                result.append("\n");
                for (int x = 0; x < getDim(0); x++) {
                    result.append(getValue(dimHelper.get(x, y)) + ",");
                }
            }
            result.append("]");
        } else {
            result.append("dimensions = [\n");
            for (int i = 0; i < dimensions.length; i++) {
                result.append(dimensions[i] + ",");
            }
            result.append("\n]\nmatrice = [\n");
            for (int i = 0; i < data.size(); i++) {
                result.append(data.getValue(i) + ",");
            }
            result.append("\n]\nlinearFactor = [\n");
            for (int i = 0; i < linearFactor.length; i++) {
                result.append(linearFactor[i] + ",");
            }
            result.append("\n]\n");
        }
        return result.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (o instanceof BasicMatrix) {
            BasicMatrix other = (BasicMatrix) o;
            return this == o
                    || (Arrays.equals(this.dimensions, other.dimensions) && this.data
                            .equals(other.data));
        }
        return false;
    }

    protected class BasicMatrixIteratorImpl implements BasicMatrixIterator { // MatrixIteratorImpl

        protected BasicMatrix matrix = null;
        protected int pos = -1;

        /**
         * @param matrix la matrice sur lequel l'iterator doit travailler
         */
        public BasicMatrixIteratorImpl(BasicMatrix matrix) {
            this.matrix = matrix;
            pos = -1;
        }

        @Override
        public boolean hasNext() {
            return pos + 1 < matrix.data.size();
        }

        @Override
        public boolean next() {
            boolean result = false;
            if (hasNext()) {
                pos++;
                return true;
            }
            return result;
        }

        @Override
        public double getValue() {
            return matrix.data.getValue(pos);
        }

        @Override
        public void setValue(double value) {
            matrix.data.setValue(pos, value);
        }

        @Override
        public int[] getCoordinates() {
            return matrix.linearToCoordinates(pos);
        }

    } // BasicMatrixIteratorImpl

} // BasicMatrix





© 2015 - 2024 Weber Informatics LLC | Privacy Policy