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 PlusScalar {
041            public static final PlusScalarCalculation<Matrix, Matrix> MATRIX = new PlusScalarMatrix();
042    
043            public static final PlusScalarCalculation<DenseMatrix, DenseMatrix> DENSEMATRIX = new PlusScalarDenseMatrix();
044    
045            public static final PlusScalarCalculation<DenseMatrix2D, DenseMatrix2D> DENSEMATRIX2D = new PlusScalarDenseMatrix2D();
046    
047            public static final PlusScalarCalculation<DenseDoubleMatrix2D, DenseDoubleMatrix2D> DENSEDOUBLEMATRIX2D = new PlusScalarDenseDoubleMatrix2D();
048    
049            public static final PlusScalarCalculation<SparseMatrix, SparseMatrix> SPARSEMATRIX = new PlusScalarSparseMatrix();
050    }
051    
052    class PlusScalarMatrix implements PlusScalarCalculation<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                            PlusScalar.DENSEMATRIX.calc((DenseMatrix) source, value, (DenseMatrix) target);
057                    } else if (source instanceof SparseMatrix && target instanceof SparseMatrix) {
058                            PlusScalar.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.plus(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                            PlusScalar.DENSEMATRIX.calc((DenseMatrix) source, value, (DenseMatrix) target);
072                    } else if (source instanceof SparseMatrix && target instanceof SparseMatrix) {
073                            PlusScalar.SPARSEMATRIX.calc((SparseMatrix) source, value, (SparseMatrix) target);
074                    } else {
075                            calc(source, new BigDecimal(value, MathUtil.getDefaultMathContext()), target);
076                    }
077            }
078    };
079    
080    class PlusScalarDenseMatrix implements PlusScalarCalculation<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                            PlusScalar.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.plus(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                            PlusScalar.DENSEMATRIX2D.calc((DenseMatrix2D) source, value, (DenseMatrix2D) target);
099                    } else {
100                            calc(source, new BigDecimal(value, MathUtil.getDefaultMathContext()), target);
101                    }
102            }
103    };
104    
105    class PlusScalarSparseMatrix implements PlusScalarCalculation<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.plus(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 PlusScalarDenseMatrix2D implements PlusScalarCalculation<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                            PlusScalar.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.plus(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                            PlusScalar.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 PlusScalarDenseDoubleMatrix2D implements
153                    PlusScalarCalculation<DenseDoubleMatrix2D, DenseDoubleMatrix2D> {
154    
155            public final void calc(final DenseDoubleMatrix2D source, final BigDecimal value,
156                            final DenseDoubleMatrix2D target) {
157                    calc(source, value.doubleValue(), target);
158            }
159    
160            public final void calc(final DenseDoubleMatrix2D source, final double value,
161                            final DenseDoubleMatrix2D target) {
162                    if (source instanceof HasColumnMajorDoubleArray1D
163                                    && target instanceof HasColumnMajorDoubleArray1D) {
164                            calc(((HasColumnMajorDoubleArray1D) source).getColumnMajorDoubleArray1D(), value,
165                                            ((HasColumnMajorDoubleArray1D) target).getColumnMajorDoubleArray1D());
166                    } else if (source instanceof HasRowMajorDoubleArray2D
167                                    && target instanceof HasRowMajorDoubleArray2D) {
168                            calc(((HasRowMajorDoubleArray2D) source).getRowMajorDoubleArray2D(), value,
169                                            ((HasRowMajorDoubleArray2D) target).getRowMajorDoubleArray2D());
170                    } else {
171                            VerifyUtil.assertSameSize(source, target);
172                            for (int r = (int) source.getRowCount(); --r != -1;) {
173                                    for (int c = (int) source.getColumnCount(); --c != -1;) {
174                                            target.setDouble(source.getDouble(r, c) + value, r, c);
175                                    }
176                            }
177                    }
178            }
179    
180            private final void calc(final double[][] source, final double value, final double[][] target) {
181                    VerifyUtil.assertSameSize(source, target);
182                    if (UJMPSettings.getNumberOfThreads() > 1 && source.length >= 100
183                                    && source[0].length >= 100) {
184                            new PForEquidistant(0, source.length - 1) {
185                                    public void step(int i) {
186                                            double[] tsource = source[i];
187                                            double[] ttarget = target[i];
188                                            for (int c = source[0].length; --c != -1;) {
189                                                    ttarget[c] = tsource[c] + value;
190                                            }
191                                    }
192                            };
193                    } else {
194                            double[] tsource = null;
195                            double[] ttarget = null;
196                            for (int r = source.length; --r != -1;) {
197                                    tsource = source[r];
198                                    ttarget = target[r];
199                                    for (int c = source[0].length; --c != -1;) {
200                                            ttarget[c] = tsource[c] + value;
201                                    }
202                            }
203                    }
204            }
205    
206            private final void calc(final double[] source, final double value, final double[] target) {
207                    VerifyUtil.assertSameSize(source, target);
208                    final int length = source.length;
209                    for (int i = 0; i < length; i++) {
210                            target[i] = source[i] + value;
211                    }
212            }
213    };