/** * Build a vector with known the sparseness (for advanced use only). * * @param field Field to which the elements belong. * @param dimension Size of the vector. * @param expectedSize Expected number of non-zero entries. */ public SparseFieldVector(Field<T> field, int dimension, int expectedSize) { this.field = field; virtualSize = dimension; entries = new OpenIntToFieldHashMap<T>(field,expectedSize); }
/** * Build an empty map with specified size. * @param field field to which the elements belong * @param expectedSize expected number of elements in the map * @param missingEntries value to return when a missing entry is fetched */ public OpenIntToFieldHashMap(final Field<T> field,final int expectedSize, final T missingEntries) { this.field = field; final int capacity = computeCapacity(expectedSize); keys = new int[capacity]; values = buildArray(capacity); states = new byte[capacity]; this.missingEntries = missingEntries; mask = capacity - 1; }
/** * Put a value associated with a key in the map. * @param key key to which value is associated * @param value value to put in the map * @return previous value associated with the key */ public T put(final int key, final T value) { int index = findInsertionIndex(key); T previous = missingEntries; boolean newMapping = true; if (index < 0) { index = changeIndexSign(index); previous = values[index]; newMapping = false; } keys[index] = key; states[index] = FULL; values[index] = value; if (newMapping) { ++size; if (shouldGrowTable()) { growTable(); } ++count; } return previous; }
/** * Remove the value associated with a key. * @param key key to which the value is associated * @return removed value */ public T remove(final int key) { final int hash = hashOf(key); int index = hash & mask; if (containsKey(key, index)) { return doRemove(index); } if (states[index] == FREE) { return missingEntries; } int j = index; for (int perturb = perturb(hash); states[index] != FREE; perturb >>= PERTURB_SHIFT) { j = probe(perturb, j); index = j & mask; if (containsKey(key, index)) { return doRemove(index); } } return missingEntries; }
/** {@inheritDoc} */ @Override public void multiplyEntry(int row, int column, T factor) { checkRowIndex(row); checkColumnIndex(column); final int key = computeKey(row, column); final T value = entries.get(key).multiply(factor); if (getField().getZero().equals(value)) { entries.remove(key); } else { entries.put(key, value); } }
/** * Optimized method to add sparse vectors. * * @param v Vector to add. * @return {@code this + v}. * @throws DimensionMismatchException if {@code v} is not the same size as * {@code this}. */ public FieldVector<T> add(SparseFieldVector<T> v) throws DimensionMismatchException { checkVectorDimensions(v.getDimension()); SparseFieldVector<T> res = (SparseFieldVector<T>)copy(); OpenIntToFieldHashMap<T>.Iterator iter = v.getEntries().iterator(); while (iter.hasNext()) { iter.advance(); int key = iter.key(); T value = iter.value(); if (entries.containsKey(key)) { res.setEntry(key, entries.get(key).add(value)); } else { res.setEntry(key, value); } } return res; }
final int hash = hashOf(key); int index = hash & mask; if (states[index] == FREE) { return index; } else if (states[index] == FULL && keys[index] == key) { return changeIndexSign(index); int perturb = perturb(hash); int j = index; if (states[index] == FULL) { while (true) { j = probe(perturb, j); index = j & mask; perturb >>= PERTURB_SHIFT; return changeIndexSign(index); j = probe(perturb, j); index = j & mask; return firstRemoved; } else if (states[index] == FULL && keys[index] == key) { return changeIndexSign(index);
/** * Create from a Field array. * Only non-zero entries will be stored. * * @param field Field to which the elements belong. * @param values Set of values to create from. * @exception NullArgumentException if values is null */ public SparseFieldVector(Field<T> field, T[] values) throws NullArgumentException { MathUtils.checkNotNull(values); this.field = field; virtualSize = values.length; entries = new OpenIntToFieldHashMap<T>(field); for (int key = 0; key < values.length; key++) { T value = values[key]; entries.put(key, value); } }
/** {@inheritDoc} */ public FieldVector<T> subtract(FieldVector<T> v) throws DimensionMismatchException { if (v instanceof SparseFieldVector<?>) { return subtract((SparseFieldVector<T>)v); } else { final int n = v.getDimension(); checkVectorDimensions(n); SparseFieldVector<T> res = new SparseFieldVector<T>(this); for (int i = 0; i < n; i++) { if (entries.containsKey(i)) { res.setEntry(i, entries.get(i).subtract(v.getEntry(i))); } else { res.setEntry(i, field.getZero().subtract(v.getEntry(i))); } } return res; } }
/** * Grow the tables. */ private void growTable() { final int oldLength = states.length; final int[] oldKeys = keys; final T[] oldValues = values; final byte[] oldStates = states; final int newLength = RESIZE_MULTIPLIER * oldLength; final int[] newKeys = new int[newLength]; final T[] newValues = buildArray(newLength); final byte[] newStates = new byte[newLength]; final int newMask = newLength - 1; for (int i = 0; i < oldLength; ++i) { if (oldStates[i] == FULL) { final int key = oldKeys[i]; final int index = findInsertionIndex(newKeys, newStates, key, newMask); newKeys[index] = key; newValues[index] = oldValues[i]; newStates[index] = FULL; } } mask = newMask; keys = newKeys; values = newValues; states = newStates; }
/** {@inheritDoc} */ public T getEntry(int index) throws OutOfRangeException { checkIndex(index); return entries.get(index); }
/** * Find the index at which a key should be inserted * @param key key to lookup * @return index at which key should be inserted */ private int findInsertionIndex(final int key) { return findInsertionIndex(keys, states, key, mask); }
/** * Copy constructor. * @param source map to copy */ public OpenIntToFieldHashMap(final OpenIntToFieldHashMap<T> source) { field = source.field; final int length = source.keys.length; keys = new int[length]; System.arraycopy(source.keys, 0, keys, 0, length); values = buildArray(length); System.arraycopy(source.values, 0, values, 0, length); states = new byte[length]; System.arraycopy(source.states, 0, states, 0, length); missingEntries = source.missingEntries; size = source.size; mask = source.mask; count = source.count; }
/** * Get the stored value associated with the given key * @param key key associated with the data * @return data associated with the key */ public T get(final int key) { final int hash = hashOf(key); int index = hash & mask; if (containsKey(key, index)) { return values[index]; } if (states[index] == FREE) { return missingEntries; } int j = index; for (int perturb = perturb(hash); states[index] != FREE; perturb >>= PERTURB_SHIFT) { j = probe(perturb, j); index = j & mask; if (containsKey(key, index)) { return values[index]; } } return missingEntries; }
/** {@inheritDoc} */ @Override public void addToEntry(int row, int column, T increment) { checkRowIndex(row); checkColumnIndex(column); final int key = computeKey(row, column); final T value = entries.get(key).add(increment); if (getField().getZero().equals(value)) { entries.remove(key); } else { entries.put(key, value); } }
/** * Optimized method to compute {@code this} minus {@code v}. * @param v vector to be subtracted * @return {@code this - v} * @throws DimensionMismatchException if {@code v} is not the same size as * {@code this}. */ public SparseFieldVector<T> subtract(SparseFieldVector<T> v) throws DimensionMismatchException { checkVectorDimensions(v.getDimension()); SparseFieldVector<T> res = (SparseFieldVector<T>)copy(); OpenIntToFieldHashMap<T>.Iterator iter = v.getEntries().iterator(); while (iter.hasNext()) { iter.advance(); int key = iter.key(); if (entries.containsKey(key)) { res.setEntry(key, entries.get(key).subtract(iter.value())); } else { res.setEntry(key, field.getZero().subtract(iter.value())); } } return res; }
final int hash = hashOf(key); int index = hash & mask; if (states[index] == FREE) { return index; } else if (states[index] == FULL && keys[index] == key) { return changeIndexSign(index); int perturb = perturb(hash); int j = index; if (states[index] == FULL) { while (true) { j = probe(perturb, j); index = j & mask; perturb >>= PERTURB_SHIFT; return changeIndexSign(index); j = probe(perturb, j); index = j & mask; return firstRemoved; } else if (states[index] == FULL && keys[index] == key) { return changeIndexSign(index);
/** * Create from a Field array. * Only non-zero entries will be stored. * * @param field Field to which the elements belong. * @param values Set of values to create from. * @exception NullArgumentException if values is null */ public SparseFieldVector(Field<T> field, T[] values) throws NullArgumentException { MathUtils.checkNotNull(values); this.field = field; virtualSize = values.length; entries = new OpenIntToFieldHashMap<T>(field); for (int key = 0; key < values.length; key++) { T value = values[key]; entries.put(key, value); } }
/** {@inheritDoc} */ public FieldVector<T> subtract(FieldVector<T> v) throws DimensionMismatchException { if (v instanceof SparseFieldVector<?>) { return subtract((SparseFieldVector<T>)v); } else { final int n = v.getDimension(); checkVectorDimensions(n); SparseFieldVector<T> res = new SparseFieldVector<T>(this); for (int i = 0; i < n; i++) { if (entries.containsKey(i)) { res.setEntry(i, entries.get(i).subtract(v.getEntry(i))); } else { res.setEntry(i, field.getZero().subtract(v.getEntry(i))); } } return res; } }
/** * Grow the tables. */ private void growTable() { final int oldLength = states.length; final int[] oldKeys = keys; final T[] oldValues = values; final byte[] oldStates = states; final int newLength = RESIZE_MULTIPLIER * oldLength; final int[] newKeys = new int[newLength]; final T[] newValues = buildArray(newLength); final byte[] newStates = new byte[newLength]; final int newMask = newLength - 1; for (int i = 0; i < oldLength; ++i) { if (oldStates[i] == FULL) { final int key = oldKeys[i]; final int index = findInsertionIndex(newKeys, newStates, key, newMask); newKeys[index] = key; newValues[index] = oldValues[i]; newStates[index] = FULL; } } mask = newMask; keys = newKeys; values = newValues; states = newStates; }