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.genericmatrix.impl;
025    
026    import java.util.HashMap;
027    import java.util.Map;
028    
029    import org.ujmp.core.Coordinates;
030    import org.ujmp.core.Matrix;
031    import org.ujmp.core.enums.ValueType;
032    import org.ujmp.core.exceptions.MatrixException;
033    import org.ujmp.core.genericmatrix.stub.AbstractSparseGenericMatrix;
034    import org.ujmp.core.util.CoordinateSetToLongWrapper;
035    import org.ujmp.core.util.MathUtil;
036    import org.ujmp.core.util.VerifyUtil;
037    
038    public class DefaultSparseGenericMatrix<A> extends AbstractSparseGenericMatrix<A> {
039            private static final long serialVersionUID = -7139128532871448340L;
040    
041            private final Map<Coordinates, A> values = new HashMap<Coordinates, A>();
042    
043            private long[] size;
044    
045            private int maximumNumberOfEntries = -1;
046    
047            public DefaultSparseGenericMatrix(Matrix m) throws MatrixException {
048                    this(m, -1);
049            }
050    
051            public DefaultSparseGenericMatrix(Matrix m, int maximumNumberOfEntries) throws MatrixException {
052                    this(m.getSize());
053                    this.maximumNumberOfEntries = maximumNumberOfEntries;
054                    for (long[] c : m.availableCoordinates()) {
055                            setObject(m.getAsObject(c), c);
056                    }
057            }
058    
059            public DefaultSparseGenericMatrix(long... size) {
060                    VerifyUtil.assertTrue(size.length > 1, "matrix must have at least two dimensions");
061                    this.size = Coordinates.copyOf(size);
062            }
063    
064            public DefaultSparseGenericMatrix(int maximumNumberOfEntries, long... size) {
065                    this(size);
066                    this.maximumNumberOfEntries = maximumNumberOfEntries;
067            }
068    
069            public long[] getSize() {
070                    return size;
071            }
072    
073            public void setSize(long... size) {
074                    this.size = size;
075            }
076    
077            public A getObject(long... coordinates) {
078                    return values.get(new Coordinates(coordinates));
079            }
080    
081            public long getValueCount() {
082                    return values.size();
083            }
084    
085            @SuppressWarnings("unchecked")
086            public void setObject(Object value, long... coordinates) {
087                    while (maximumNumberOfEntries > 0 && values.size() > maximumNumberOfEntries) {
088                            values.remove(values.keySet().iterator().next());
089                    }
090                    if (Coordinates.isSmallerThan(coordinates, size)) {
091                            if (MathUtil.isNull(value)) {
092                                    values.remove(new Coordinates(coordinates));
093                            } else {
094                                    values.put(new Coordinates(coordinates), (A) value);
095                            }
096                    }
097            }
098    
099            public Iterable<long[]> availableCoordinates() {
100                    return new CoordinateSetToLongWrapper(values.keySet());
101            }
102    
103            public boolean contains(long... coordinates) {
104                    return values.containsKey(new Coordinates(coordinates));
105            }
106    
107            public double getAsDouble(long... coordinates) throws MatrixException {
108                    return MathUtil.getDouble(getObject(coordinates));
109            }
110    
111            public void setAsDouble(double value, long... coordinates) throws MatrixException {
112                    setObject(value, coordinates);
113            }
114    
115            public ValueType getValueType() {
116                    return ValueType.OBJECT;
117            }
118    
119            public final StorageType getStorageType() {
120                    return StorageType.SPARSE;
121            }
122    
123    }