001    /*
002     * Copyright (C) 2008-2010 by Holger Arndt
003     *
004     * This file is part of the Universal Java Matrix Package (UJMP).
005     * See the NOTICE file distributed with this work for additional
006     * information regarding copyright ownership and licensing.
007     *
008     * UJMP is free software; you can redistribute it and/or modify
009     * it under the terms of the GNU Lesser General Public License as
010     * published by the Free Software Foundation; either version 2
011     * of the License, or (at your option) any later version.
012     *
013     * UJMP is distributed in the hope that it will be useful,
014     * but WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016     * GNU Lesser General Public License for more details.
017     *
018     * You should have received a copy of the GNU Lesser General Public
019     * License along with UJMP; if not, write to the
020     * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
021     * Boston, MA  02110-1301  USA
022     */
023    
024    package org.ujmp.core.calculation;
025    
026    import java.math.BigDecimal;
027    
028    import org.ujmp.core.Matrix;
029    import org.ujmp.core.doublematrix.DenseDoubleMatrix2D;
030    import org.ujmp.core.interfaces.HasColumnMajorDoubleArray1D;
031    import org.ujmp.core.interfaces.HasRowMajorDoubleArray2D;
032    import org.ujmp.core.matrix.DenseMatrix;
033    import org.ujmp.core.matrix.DenseMatrix2D;
034    import org.ujmp.core.matrix.SparseMatrix;
035    import org.ujmp.core.util.MathUtil;
036    import org.ujmp.core.util.UJMPSettings;
037    import org.ujmp.core.util.VerifyUtil;
038    import org.ujmp.core.util.concurrent.PForEquidistant;
039    
040    public class MinusMatrix {
041            public static final MinusMatrixCalculation<Matrix, Matrix, Matrix> MATRIX = new MinusMatrixMatrix();
042    
043            public static final MinusMatrixCalculation<DenseMatrix, DenseMatrix, DenseMatrix> DENSEMATRIX = new MinusMatrixDenseMatrix();
044    
045            public static final MinusMatrixCalculation<DenseMatrix2D, DenseMatrix2D, DenseMatrix2D> DENSEMATRIX2D = new MinusMatrixDenseMatrix2D();
046    
047            public static final MinusMatrixCalculation<DenseDoubleMatrix2D, DenseDoubleMatrix2D, DenseDoubleMatrix2D> DENSEDOUBLEMATRIX2D = new MinusMatrixDenseDoubleMatrix2D();
048    
049            public static final MinusMatrixCalculation<SparseMatrix, SparseMatrix, SparseMatrix> SPARSEMATRIX = new MinusMatrixSparseMatrix();
050    }
051    
052    class MinusMatrixMatrix implements MinusMatrixCalculation<Matrix, Matrix, Matrix> {
053    
054            public final void calc(final Matrix source1, final Matrix source2, final Matrix target) {
055                    if (source1 instanceof DenseMatrix && source2 instanceof DenseMatrix
056                                    && target instanceof DenseMatrix) {
057                            MinusMatrix.DENSEMATRIX.calc((DenseMatrix) source1, (DenseMatrix) source2,
058                                            (DenseMatrix) target);
059                    } else if (source1 instanceof SparseMatrix && source2 instanceof SparseMatrix
060                                    && target instanceof SparseMatrix) {
061                            MinusMatrix.SPARSEMATRIX.calc((SparseMatrix) source1, (SparseMatrix) source2,
062                                            (SparseMatrix) target);
063                    } else {
064                            VerifyUtil.assertSameSize(source1, source2, target);
065                            for (long[] c : source1.allCoordinates()) {
066                                    BigDecimal v1 = source1.getAsBigDecimal(c);
067                                    BigDecimal v2 = source2.getAsBigDecimal(c);
068                                    BigDecimal result = MathUtil.minus(v1, v2);
069                                    target.setAsBigDecimal(result, c);
070                            }
071                    }
072            }
073    };
074    
075    class MinusMatrixDenseMatrix implements
076                    MinusMatrixCalculation<DenseMatrix, DenseMatrix, DenseMatrix> {
077    
078            public final void calc(final DenseMatrix source1, final DenseMatrix source2,
079                            final DenseMatrix target) {
080                    if (source1 instanceof DenseMatrix2D && source2 instanceof DenseMatrix2D
081                                    && target instanceof DenseMatrix2D) {
082                            MinusMatrix.DENSEMATRIX2D.calc((DenseMatrix2D) source1, (DenseMatrix2D) source2,
083                                            (DenseMatrix2D) target);
084                    } else {
085                            VerifyUtil.assertSameSize(source1, source2, target);
086                            for (long[] c : source1.allCoordinates()) {
087                                    BigDecimal v1 = source1.getAsBigDecimal(c);
088                                    BigDecimal v2 = source2.getAsBigDecimal(c);
089                                    BigDecimal result = MathUtil.minus(v1, v2);
090                                    target.setAsBigDecimal(result, c);
091                            }
092                    }
093            }
094    };
095    
096    class MinusMatrixSparseMatrix implements
097                    MinusMatrixCalculation<SparseMatrix, SparseMatrix, SparseMatrix> {
098    
099            public final void calc(final SparseMatrix source1, final SparseMatrix source2,
100                            final SparseMatrix target) {
101                    VerifyUtil.assertSameSize(source1, source2, target);
102                    // copy all elements in source1 to target
103                    for (long[] c : source1.availableCoordinates()) {
104                            BigDecimal svalue = source1.getAsBigDecimal(c);
105                            target.setAsBigDecimal(svalue, c);
106                    }
107                    // calculate difference with source2
108                    for (long[] c : source2.availableCoordinates()) {
109                            BigDecimal v1 = target.getAsBigDecimal(c);
110                            BigDecimal v2 = source2.getAsBigDecimal(c);
111                            BigDecimal result = MathUtil.minus(v1, v2);
112                            target.setAsBigDecimal(result, c);
113                    }
114            }
115    
116    };
117    
118    class MinusMatrixDenseMatrix2D implements
119                    MinusMatrixCalculation<DenseMatrix2D, DenseMatrix2D, DenseMatrix2D> {
120    
121            public final void calc(final DenseMatrix2D source1, final DenseMatrix2D source2,
122                            final DenseMatrix2D target) {
123                    if (source1 instanceof DenseDoubleMatrix2D && source2 instanceof DenseDoubleMatrix2D
124                                    && target instanceof DenseDoubleMatrix2D) {
125                            MinusMatrix.DENSEDOUBLEMATRIX2D.calc((DenseDoubleMatrix2D) source1,
126                                            (DenseDoubleMatrix2D) source2, (DenseDoubleMatrix2D) target);
127                    } else {
128                            VerifyUtil.assertSameSize(source1, source2, target);
129                            for (int r = (int) source1.getRowCount(); --r != -1;) {
130                                    for (int c = (int) source1.getColumnCount(); --c != -1;) {
131                                            BigDecimal v1 = source1.getAsBigDecimal(r, c);
132                                            BigDecimal v2 = source2.getAsBigDecimal(r, c);
133                                            BigDecimal result = MathUtil.minus(v1, v2);
134                                            target.setAsBigDecimal(result, r, c);
135                                    }
136                            }
137                    }
138            }
139    };
140    
141    class MinusMatrixDenseDoubleMatrix2D implements
142                    MinusMatrixCalculation<DenseDoubleMatrix2D, DenseDoubleMatrix2D, DenseDoubleMatrix2D> {
143    
144            public final void calc(final DenseDoubleMatrix2D source1, final DenseDoubleMatrix2D source2,
145                            final DenseDoubleMatrix2D target) {
146                    if (source1 instanceof HasColumnMajorDoubleArray1D
147                                    && source2 instanceof HasColumnMajorDoubleArray1D
148                                    && target instanceof HasColumnMajorDoubleArray1D) {
149                            calc(((HasColumnMajorDoubleArray1D) source1).getColumnMajorDoubleArray1D(),
150                                            ((HasColumnMajorDoubleArray1D) source2).getColumnMajorDoubleArray1D(),
151                                            ((HasColumnMajorDoubleArray1D) target).getColumnMajorDoubleArray1D());
152                    } else if (source1 instanceof HasRowMajorDoubleArray2D
153                                    && source2 instanceof HasRowMajorDoubleArray2D
154                                    && target instanceof HasRowMajorDoubleArray2D) {
155                            calc(((HasRowMajorDoubleArray2D) source1).getRowMajorDoubleArray2D(),
156                                            ((HasRowMajorDoubleArray2D) source2).getRowMajorDoubleArray2D(),
157                                            ((HasRowMajorDoubleArray2D) target).getRowMajorDoubleArray2D());
158                    } else {
159                            VerifyUtil.assertSameSize(source1, source2, target);
160                            for (int r = (int) source1.getRowCount(); --r != -1;) {
161                                    for (int c = (int) source1.getColumnCount(); --c != -1;) {
162                                            target.setDouble(source1.getDouble(r, c) - source2.getDouble(r, c), r, c);
163                                    }
164                            }
165                    }
166            }
167    
168            private final void calc(final double[][] source1, final double[][] source2,
169                            final double[][] target) {
170                    VerifyUtil.assertSameSize(source1, source2, target);
171                    if (UJMPSettings.getNumberOfThreads() > 1 && source1.length >= 100
172                                    && source1[0].length >= 100) {
173                            new PForEquidistant(0, source1.length - 1) {
174                                    public void step(int i) {
175                                            double[] v1 = source1[i];
176                                            double[] v2 = source2[i];
177                                            double[] t = target[i];
178                                            for (int c = source1[0].length; --c != -1;) {
179                                                    t[c] = v1[c] - v2[c];
180                                            }
181                                    }
182                            };
183                    } else {
184                            double[] v1 = null;
185                            double[] v2 = null;
186                            double[] t = null;
187                            for (int r = source1.length; --r != -1;) {
188                                    v1 = source1[r];
189                                    v2 = source2[r];
190                                    t = target[r];
191                                    for (int c = source1[0].length; --c != -1;) {
192                                            t[c] = v1[c] - v2[c];
193                                    }
194                            }
195                    }
196            }
197    
198            private final void calc(final double[] source1, final double[] source2, final double[] target) {
199                    VerifyUtil.assertSameSize(source1, source2, target);
200                    final int length = source1.length;
201                    for (int i = 0; i < length; i++) {
202                            target[i] = source1[i] - source2[i];
203                    }
204            }
205    
206    };