/*
 * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
 *     Yves Roos (yroos@lifl.fr) and others.
 *
 * Licensed under the Apache License, Version 2.0 (the License);
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package rationals.algebra;

import java.util.Arrays;

/**
 * Matrix representation of an automaton.
 * <p>
 * The elements of a the matrix are {@see SemiRing}objects.
 * 
 * @author nono
 * @version $Id: Matrix.java 6 2006-08-30 08:56:44Z oqube $
 */
public final class Matrix implements SemiRing {

    /* matrices for transitions, initial and terminal states */
    protected final SemiRing[][] matrix;

    private int line;
    
    private int col;
    

    public Matrix(int ns) {
        this.line = this.col = ns;
        this.matrix = new SemiRing[ns][ns];
    }

    /**
     * @param matrix
     */
    public Matrix(Matrix matrix) {
        this(matrix.line);
        for (int i = 0; i < line; i++) 
            for (int j = 0; j < col; j++) 
                this.matrix[i][j] = matrix.matrix[i][j];
        
    }

    /**
     * @param l
     * @param c
     */
    public Matrix(int l, int c) {
        this.line = l;
        this.col = c;
        matrix = new SemiRing[l][c];
    }

    /**
     * Returns the n <sup>th </sup> power of this matrix.
     * 
     * @param n
     *            the power. Must be positive or null.
     * @param res
     *            matrix where the result should be stored. Must be same size as
     *            this matrix with all elements initialized with null.
     * @return the result Matrix object with transition matrix equals the n
     *         <sup>th </sup> power of this matrix's transition.
     */
    public Matrix power(int n, Matrix res) {
        int l = line;
        if(line != col)
            throw new IllegalStateException("Cannot compute power of a non square matrix");
        SemiRing[][] tmp = new SemiRing[l][l];
        for (int i = 0; i < l; i++)
            Arrays.fill(tmp[i], matrix[0][0].zero());
        for (int k = 0; k <n; k++) {
            for (int i = 0; i < l; i++) {
                for (int j = 0; j < l; j++) {
                    for (int m = 0; m < l; m++) {
                        if (k==0)
                            tmp[i][j] = tmp[i][j].plus(matrix[i][m]
                                    .mult(matrix[m][j]));
                        else
                            tmp[i][j] = tmp[i][j].plus(res.matrix[i][m]
                                    .mult(matrix[m][j]));
                    }
                }
            }
            /* copy to res */
            for (int i = 0; i < l; i++)
                System.arraycopy(tmp[i],0,res.matrix[i],0,l);
        }
        return res;
    }


    /**
     * Returns the star of this matrix.
     * 
     * @return
     */
    public Matrix star() {
        return null;
    }

    public int getLine() {
        return line;
    }
    
    public String toString() {
        final String ln = System.getProperty("line.separator");
        StringBuffer sb = new StringBuffer();
        int n = matrix.length;
        for (int i = 0; i < line; i++) {
            sb.append("[ ");
            for (int j = 0; j < col; j++) {
                String s = matrix[i][j].toString();
                sb.append(s).append(' ');
            }
            sb.append("]").append(ln);
        }
        return sb.toString();
    }

    /* (non-Javadoc)
     * @see rationals.algebra.SemiRing#plus(rationals.algebra.SemiRing)
     */
    public SemiRing plus(SemiRing s2) {
        if(s2 == null)
            throw new IllegalArgumentException("Null argument");
        Matrix o = (Matrix)s2; // maybe ClassCastException
        if(col != o.col || line != o.line)
            throw new IllegalArgumentException("Incompatible matrices dimensions : cannot add non square matrices");
        int l = line;
        int c = col;
        Matrix res = Matrix.zero(l,c,matrix[0][0]);
        for(int i=0;i<l;i++) 
            for(int j=0;j<c;j++)
                res.matrix[i][j] = matrix[i][j].plus(o.matrix[i][j]);
        return res;               
    }

    /* (non-Javadoc)
     * @see rationals.algebra.SemiRing#mult(rationals.algebra.SemiRing)
     */
    public SemiRing mult(SemiRing s2) {
        if(s2 == null)
            throw new IllegalArgumentException("Null argument");
        Matrix o = (Matrix)s2; // maybe ClassCastException
        if(col != o.line)
            throw new IllegalArgumentException("Incompatible matrices dimensions");
        int l = line; // lines
        int c = o.col;  // cols
        int m = col;
        Matrix res = Matrix.zero(l,c,matrix[0][0]);
        for(int i=0;i<l;i++) {
            for(int j=0;j<c;j++)
                for(int k=0;k<m;k++){
                   if(k ==0)
                       res.matrix[i][j] = matrix[i][k].mult(o.matrix[k][j]);
                   else
                       res.matrix[i][j] = res.matrix[i][j].plus(matrix[i][k].mult(o.matrix[k][j]));
                }
        }
        return res;
    }

    /* (non-Javadoc)
     * @see rationals.algebra.SemiRing#one()
     */
    public SemiRing one() {
        if(line != col)
            throw new IllegalStateException("Cannot get unit matrix on non-square matrices");
        return one(line,matrix[0][0]);
    }

    /* (non-Javadoc)
     * @see rationals.algebra.SemiRing#zero()
     */
    public SemiRing zero() {
        return zero(line,col,matrix[0][0]);
    }
    
    public int getCol() {
        return col;
    }
    
    /**
     * Factory method for creating Matrix instances with coefficients
     * in a certain SemiRing.
     * 
     * @param sr a SemiRing instance. Used to get one and zero.
     * @return a new zero matrix.
     */
    public static Matrix zero(int line,int col,SemiRing sr) {
        Matrix m = new Matrix(line,col);
        for(int i=0;i<line;i++)
            for(int j=0;j<col;j++)
                m.matrix[i][j] = sr.zero();
        return m;
    }
    
    /**
     * Factory method for creating unit Matrix instances with coefficients
     * in a certain SemiRing.
     * 
     * @param sr a SemiRing instance. Used to get one and zero.
     * @return a new unit square matrix.
     */
    public static Matrix one(int dim,SemiRing sr) {
        Matrix m = new Matrix(dim);
        for(int i=0;i<dim;i++)
            for(int j=0;j<dim;j++)
                m.matrix[i][j] = (i == j) ? sr.one() : sr.zero();
        return m;
    }
    
    
}

@@ -836,24 +836,8 @@
  * %0A
- * @author nono%0A
  * @
@@ -3485,39 +3485,8 @@
 ();%0A
-        int n = matrix.length;%0A
     

Remove unused variable.