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