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.doublematrix.impl; 025 026 import org.ujmp.core.Matrix; 027 import org.ujmp.core.doublematrix.stub.AbstractDenseDoubleMatrix2D; 028 import org.ujmp.core.exceptions.MatrixException; 029 import org.ujmp.core.util.MathUtil; 030 031 public class MortonDenseDoubleMartrix2D extends AbstractDenseDoubleMatrix2D { 032 private static final long serialVersionUID = -1951357825977485935L; 033 034 public static final int ONES0 = 0xaaaaaaaa; 035 036 public static final int ONES1 = 0x55555555; 037 038 public static final int ONES0P1 = ONES0 + 1; 039 040 public static final int ONES1P1 = ONES1 + 1; 041 042 public static final int[] TABLE0 = new int[32767]; 043 044 public static final int[] TABLE1 = new int[32767]; 045 046 private double[] values = null; 047 048 private long[] size = null; 049 050 private int rows = 0; 051 052 private int cols = 0; 053 054 static { 055 init(); 056 } 057 058 public MortonDenseDoubleMartrix2D(Matrix m) throws MatrixException { 059 this.rows = (int) m.getRowCount(); 060 this.cols = (int) m.getColumnCount(); 061 this.size = new long[] { rows, cols }; 062 int length = (int) Math.pow(Math.pow(2, Math.ceil(MathUtil.log2(Math.max(rows, cols)))), 2); 063 if (m instanceof MortonDenseDoubleMartrix2D) { 064 double[] v = ((MortonDenseDoubleMartrix2D) m).values; 065 this.values = new double[length]; 066 System.arraycopy(v, 0, this.values, 0, v.length); 067 } else { 068 this.values = new double[length]; 069 for (long[] c : m.allCoordinates()) { 070 setDouble(m.getAsDouble(c), c); 071 } 072 } 073 } 074 075 public MortonDenseDoubleMartrix2D(long... size) { 076 this.rows = (int) size[ROW]; 077 this.cols = (int) size[COLUMN]; 078 this.size = new long[] { rows, cols }; 079 int length = (int) Math.pow(Math.pow(2, Math.ceil(MathUtil.log2(Math.max(rows, cols)))), 2); 080 this.values = new double[length]; 081 } 082 083 public MortonDenseDoubleMartrix2D(double[] v, int rows, int cols) { 084 this.rows = rows; 085 this.cols = cols; 086 this.size = new long[] { rows, cols }; 087 this.values = v; 088 } 089 090 public final long[] getSize() { 091 return size; 092 } 093 094 public final long getRowCount() { 095 return rows; 096 } 097 098 public final long getColumnCount() { 099 return cols; 100 } 101 102 public final double getDouble(long row, long column) { 103 return values[TABLE1[(int) row] + TABLE0[(int) column]]; 104 } 105 106 public final double getAsDouble(long row, long column) { 107 return values[TABLE1[(int) row] + TABLE0[(int) column]]; 108 } 109 110 public final double getAsDouble(int row, int column) { 111 return values[TABLE1[row] + TABLE0[column]]; 112 } 113 114 public final void setDouble(double value, long row, long column) { 115 values[TABLE1[(int) row] + TABLE0[(int) column]] = value; 116 } 117 118 public final void setAsDouble(double value, long row, long column) { 119 values[TABLE1[(int) row] + TABLE0[(int) column]] = value; 120 } 121 122 public final double getDouble(int row, int column) { 123 return values[TABLE1[row] + TABLE0[column]]; 124 } 125 126 public final void setDouble(double value, int row, int column) { 127 values[TABLE1[row] + TABLE0[column]] = value; 128 } 129 130 public final void setAsDouble(double value, int row, int column) { 131 values[TABLE1[row] + TABLE0[column]] = value; 132 } 133 134 public final Matrix copy() throws MatrixException { 135 double[] result = new double[values.length]; 136 System.arraycopy(values, 0, result, 0, values.length); 137 Matrix m = new MortonDenseDoubleMartrix2D(result, rows, cols); 138 if (getAnnotation() != null) { 139 m.setAnnotation(getAnnotation().clone()); 140 } 141 return m; 142 } 143 144 public Matrix mtimes(Matrix m2) { 145 if (m2 instanceof MortonDenseDoubleMartrix2D) { 146 final MortonDenseDoubleMartrix2D ret = new MortonDenseDoubleMartrix2D(getRowCount(), m2 147 .getColumnCount()); 148 final double[] c = ret.values; 149 final double[] b = ((MortonDenseDoubleMartrix2D) m2).values; 150 final int retcols = ret.cols; 151 final int table1rows = TABLE1[rows]; 152 final int table0cols = TABLE0[cols]; 153 final int table0retcols = TABLE0[retcols]; 154 155 for (int i = 0; i < table1rows; i = i + ONES1P1 & ONES0) { 156 for (int k0 = 0; k0 < table0cols; k0 = k0 + ONES0P1 & ONES1) { 157 final int k1 = k0 << 1; 158 final double r = values[i + k0]; 159 for (int j = 0; j < table0retcols; j = j + ONES0P1 & ONES1) { 160 c[i + j] += r * b[k1 + j]; 161 } 162 } 163 } 164 165 return ret; 166 } else { 167 return super.mtimes(m2); 168 } 169 } 170 171 public static final void init() { 172 int v = 0; 173 int length = TABLE0.length; 174 for (int i = 0; i < length; i++) { 175 TABLE0[i] = v; 176 v = (v + ONES0P1) & ONES1; 177 } 178 179 v = 0; 180 length = TABLE1.length; 181 for (int i = 0; i < length; i++) { 182 TABLE1[i] = v; 183 v = (v + ONES1P1) & ONES0; 184 } 185 } 186 187 }