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    }