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 MinusScalar {
041            public static final MinusScalarCalculation<Matrix, Matrix> MATRIX = new MinusScalarMatrix();
042    
043            public static final MinusScalarCalculation<DenseMatrix, DenseMatrix> DENSEMATRIX = new MinusScalarDenseMatrix();
044    
045            public static final MinusScalarCalculation<DenseMatrix2D, DenseMatrix2D> DENSEMATRIX2D = new MinusScalarDenseMatrix2D();
046    
047            public static final MinusScalarCalculation<DenseDoubleMatrix2D, DenseDoubleMatrix2D> DENSEDOUBLEMATRIX2D = new MinusScalarDenseDoubleMatrix2D();
048    
049            public static final MinusScalarCalculation<SparseMatrix, SparseMatrix> SPARSEMATRIX = new MinusScalarSparseMatrix();
050    }
051    
052    class MinusScalarMatrix implements MinusScalarCalculation<Matrix, Matrix> {
053    
054            public final void calc(final Matrix source, final BigDecimal value, final Matrix target) {
055                    if (source instanceof DenseMatrix && target instanceof DenseMatrix) {
056                            MinusScalar.DENSEMATRIX.calc((DenseMatrix) source, value, (DenseMatrix) target);
057                    } else if (source instanceof SparseMatrix && target instanceof SparseMatrix) {
058                            MinusScalar.SPARSEMATRIX.calc((SparseMatrix) source, value, (SparseMatrix) target);
059                    } else {
060                            VerifyUtil.assertSameSize(source, target);
061                            for (long[] c : source.allCoordinates()) {
062                                    BigDecimal svalue = source.getAsBigDecimal(c);
063                                    BigDecimal result = MathUtil.minus(svalue, value);
064                                    target.setAsBigDecimal(result, c);
065                            }
066                    }
067            }
068    
069            public final void calc(final Matrix source, final double value, final Matrix target) {
070                    if (source instanceof DenseMatrix && target instanceof DenseMatrix) {
071                            MinusScalar.DENSEMATRIX.calc((DenseMatrix) source, value, (DenseMatrix) target);
072                    } else if (source instanceof SparseMatrix && target instanceof SparseMatrix) {
073                            MinusScalar.SPARSEMATRIX.calc((SparseMatrix) source, value, (SparseMatrix) target);
074                    } else {
075                            calc(source, new BigDecimal(value, MathUtil.getDefaultMathContext()), target);
076                    }
077            }
078    };
079    
080    class MinusScalarDenseMatrix implements MinusScalarCalculation<DenseMatrix, DenseMatrix> {
081    
082            public final void calc(final DenseMatrix source, final BigDecimal value,
083                            final DenseMatrix target) {
084                    if (source instanceof DenseMatrix2D && target instanceof DenseMatrix2D) {
085                            MinusScalar.DENSEMATRIX2D.calc((DenseMatrix2D) source, value, (DenseMatrix2D) target);
086                    } else {
087                            VerifyUtil.assertSameSize(source, target);
088                            for (long[] c : source.allCoordinates()) {
089                                    BigDecimal svalue = source.getAsBigDecimal(c);
090                                    BigDecimal result = MathUtil.minus(svalue, value);
091                                    target.setAsBigDecimal(result, c);
092                            }
093                    }
094            }
095    
096            public final void calc(final DenseMatrix source, final double value, final DenseMatrix target) {
097                    if (source instanceof DenseMatrix2D && target instanceof DenseMatrix2D) {
098                            MinusScalar.DENSEMATRIX2D.calc((DenseMatrix2D) source, value, (DenseMatrix2D) target);
099                    } else {
100                            calc(source, new BigDecimal(value, MathUtil.getDefaultMathContext()), target);
101                    }
102            }
103    };
104    
105    class MinusScalarSparseMatrix implements MinusScalarCalculation<SparseMatrix, SparseMatrix> {
106    
107            public final void calc(final SparseMatrix source, final BigDecimal value,
108                            final SparseMatrix target) {
109                    VerifyUtil.assertSameSize(source, target);
110                    for (long[] c : source.availableCoordinates()) {
111                            BigDecimal svalue = source.getAsBigDecimal(c);
112                            BigDecimal result = MathUtil.minus(svalue, value);
113                            target.setAsBigDecimal(result, c);
114                    }
115            }
116    
117            public final void calc(SparseMatrix source, double value, SparseMatrix target) {
118                    calc(source, new BigDecimal(value, MathUtil.getDefaultMathContext()), target);
119            }
120    };
121    
122    class MinusScalarDenseMatrix2D implements MinusScalarCalculation<DenseMatrix2D, DenseMatrix2D> {
123    
124            public final void calc(final DenseMatrix2D source, final BigDecimal value,
125                            final DenseMatrix2D target) {
126                    if (source instanceof DenseDoubleMatrix2D && target instanceof DenseDoubleMatrix2D) {
127                            MinusScalar.DENSEDOUBLEMATRIX2D.calc((DenseDoubleMatrix2D) source, value,
128                                            (DenseDoubleMatrix2D) target);
129                    } else {
130                            VerifyUtil.assertSameSize(source, target);
131                            for (int r = (int) source.getRowCount(); --r != -1;) {
132                                    for (int c = (int) source.getColumnCount(); --c != -1;) {
133                                            BigDecimal svalue = source.getAsBigDecimal(r, c);
134                                            BigDecimal result = MathUtil.minus(svalue, value);
135                                            target.setAsBigDecimal(result, r, c);
136                                    }
137                            }
138                    }
139            }
140    
141            public final void calc(final DenseMatrix2D source, final double value,
142                            final DenseMatrix2D target) {
143                    if (source instanceof DenseDoubleMatrix2D && target instanceof DenseDoubleMatrix2D) {
144                            MinusScalar.DENSEDOUBLEMATRIX2D.calc((DenseDoubleMatrix2D) source, value,
145                                            (DenseDoubleMatrix2D) target);
146                    } else {
147                            calc(source, new BigDecimal(value, MathUtil.getDefaultMathContext()), target);
148                    }
149            }
150    };
151    
152    class MinusScalarDenseDoubleMatrix2D implements
153                    MinusScalarCalculation<DenseDoubleMatrix2D, DenseDoubleMatrix2D> {
154    
155            public final void calc(DenseDoubleMatrix2D source, BigDecimal value, DenseDoubleMatrix2D target) {
156                    calc(source, value.doubleValue(), target);
157            }
158    
159            public final void calc(final DenseDoubleMatrix2D source, final double value,
160                            final DenseDoubleMatrix2D target) {
161                    if (source instanceof HasColumnMajorDoubleArray1D
162                                    && target instanceof HasColumnMajorDoubleArray1D) {
163                            calc(((HasColumnMajorDoubleArray1D) source).getColumnMajorDoubleArray1D(), value,
164                                            ((HasColumnMajorDoubleArray1D) target).getColumnMajorDoubleArray1D());
165                    } else if (source instanceof HasRowMajorDoubleArray2D
166                                    && target instanceof HasRowMajorDoubleArray2D) {
167                            calc(((HasRowMajorDoubleArray2D) source).getRowMajorDoubleArray2D(), value,
168                                            ((HasRowMajorDoubleArray2D) target).getRowMajorDoubleArray2D());
169                    } else {
170                            VerifyUtil.assertSameSize(source, target);
171                            for (int r = (int) source.getRowCount(); --r != -1;) {
172                                    for (int c = (int) source.getColumnCount(); --c != -1;) {
173                                            target.setDouble(source.getDouble(r, c) - value, r, c);
174                                    }
175                            }
176                    }
177            }
178    
179            private final void calc(final double[][] source, final double value, final double[][] target) {
180                    VerifyUtil.assertSameSize(source, target);
181                    if (UJMPSettings.getNumberOfThreads() > 1 && source.length >= 100
182                                    && source[0].length >= 100) {
183                            new PForEquidistant(0, source.length - 1) {
184                                    public void step(int i) {
185                                            double[] tsource = source[i];
186                                            double[] ttarget = target[i];
187                                            for (int c = source[0].length; --c != -1;) {
188                                                    ttarget[c] = tsource[c] - value;
189                                            }
190                                    }
191                            };
192                    } else {
193                            double[] tsource = null;
194                            double[] ttarget = null;
195                            for (int r = source.length; --r != -1;) {
196                                    tsource = source[r];
197                                    ttarget = target[r];
198                                    for (int c = source[0].length; --c != -1;) {
199                                            ttarget[c] = tsource[c] - value;
200                                    }
201                            }
202                    }
203            }
204    
205            private final void calc(final double[] source, final double value, final double[] target) {
206                    VerifyUtil.assertSameSize(source, target);
207                    final int length = source.length;
208                    for (int i = 0; i < length; i++) {
209                            target[i] = source[i] - value;
210                    }
211            }
212    };