/* * Concept profile generation tool suite * Copyright (C) 2015 Biosemantics Group, Erasmus University Medical Center, * Rotterdam, The Netherlands * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> */ package org.erasmusmc.math.vector; import java.io.Serializable; import java.util.Comparator; import java.util.Iterator; import org.erasmusmc.collections.SortedListMap; import org.erasmusmc.math.space.Space; public class SparseVector<D> extends Vector<D> implements Serializable { private static final long serialVersionUID = 7973211925353447858L; public Space<D> space; public SortedListMap<D, Double> values; public SparseVector(Space<D> space) { this.space = space; values = new SortedListMap<D, Double>(new SparseVectorKeyComparator()); } public SparseVector(){ values = new SortedListMap<D, Double>(new SparseVectorKeyComparator()); } public SparseVector(Vector<D> vector) { space = vector.getSpace(); values = new SortedListMap<D, Double>(new SparseVectorKeyComparator()); set(vector); } public void set(D index, double value) { if (value != 0d) values.put(index, value); else values.remove(index); } public double get(D index) { Double value = values.get(index); if (value != null) return value; else return 0; } public void set(Vector<D> vector) { values.clear(); VectorCursor<D> cursor = vector.getNonzeroCursor(); while (cursor.isValid()) { set(cursor.dimension(), cursor.get()); cursor.next(); } } public Space<D> getSpace() { return space; } public void setSpace(Space<D> space) { this.space = space; } public String toString() { return "Sparse vector"; } public VectorCursor<D> getCursor() { return new SparseVectorCursor(); } public VectorCursor<D> getNonzeroCursor() { return new SparseVectorNonzeroCursor(); } public VectorSlaveCursor<D> getSlaveCursor() { return new SparseVectorSlaveCursor(); } public int getStoredValueCount() { return values.size(); } protected class SparseVectorHandle implements VectorHandle<D> { D dimension; public D dimension() { return dimension; } public int index() { return space.indexOfObject(dimension); } public double get() { Double value = values.get(dimension); if (value != null) return value; else return 0; } public void set(double value) { if (value != 0d) values.put(dimension, value); else values.remove(dimension); } } protected class SparseVectorSlaveCursor extends SparseVectorHandle implements VectorSlaveCursor<D> { public void synchronize(VectorHandle<D> vectorHandle) { dimension = vectorHandle.dimension(); } } protected class SparseVectorCursor extends SparseVectorHandle implements VectorCursor<D> { protected Iterator<D> iterator; public SparseVectorCursor() { iterator = space.iterator(); next(); } public boolean isValid() { return dimension != null; } public void next() { if (iterator.hasNext()) dimension = iterator.next(); else dimension = null; } } protected class SparseVectorNonzeroCursor extends SparseVectorHandle implements VectorCursor<D>, Serializable { private static final long serialVersionUID = 2287253547250643918L; protected Iterator<D> iterator; public SparseVectorNonzeroCursor() { iterator = values.keyIterator(); next(); } public boolean isValid() { return dimension != null; } public void next() { if (iterator.hasNext()) dimension = iterator.next(); else dimension = null; } } protected class SparseVectorKeyComparator implements Serializable, Comparator<D> { private static final long serialVersionUID = 1481833931150717597L; public int compare(D o1, D o2) { return space.indexOfObject(o1) - space.indexOfObject(o2); } } }