@Override public void mutablePairwiseDivide(Vec b) { if (this.length() != b.length()) throw new ArithmeticException("Vectors must have the same length"); clearCaches(); for (int i = 0; i < used; i++) values[i] /= b.get(indexes[i]); // zeros stay zero }
@Override public void mutableMultiply(double c) { clearCaches(); if (c == 0.0) { zeroOut(); return; } for (int i = 0; i < used; i++) values[i] *= c; }
@Override public void mutableAdd(double c) { if (c == 0.0) return; clearCaches(); /* This NOT the most efficient way to implement this. * But adding a constant to every value in a sparce * vector defeats its purpos. */ for (int i = 0; i < length(); i++) this.set(i, get(i) + c); }
@Override public void set(int index, double val) { if (index > length() - 1 || index < 0) throw new IndexOutOfBoundsException(index + " does not fit in [0," + length + ")"); clearCaches(); int insertLocation = Arrays.binarySearch(indexes, 0, used, index); if (insertLocation >= 0) { if (val != 0) // set it values[insertLocation] = val; else // shift used count and everyone over { removeNonZero(insertLocation); } } else if (val != 0) // dont insert 0s, that is stupid insertValue(insertLocation, index, val); }
@Override public void mutableDivide(double c) { clearCaches(); if (c == 0 && used != length) throw new ArithmeticException("Division by zero would occur"); for (int i = 0; i < used; i++) values[i] /= c; }
@Override public void mutableAdd(double c, Vec v) { clearCaches(); if (c == 0.0) return; if (v instanceof SparseVector) { SparseVector b = (SparseVector) v; int p1 = 0, p2 = 0; while (p1 < used && p2 < b.used) { int a1 = indexes[p1], a2 = b.indexes[p2]; if (a1 == a2) { values[p1] += c * b.values[p2]; p1++; p2++; } else if (a1 > a2) { // 0 + some value is that value, set it this.set(a2, c * b.values[p2]); /* * p2 must be increment becase were moving to the next value * * p1 must be be incremented becase a2 was less thenn the current index. * So the inseration occured before p1, so for indexes[p1] to == a1, * p1 must be incremented * */ p1++; p2++; } else // a1 < a2, thats adding 0 to this vector, nothing to do. { p1++; } } // One of them is now empty. // If b is not empty, we must add b to this. If b is empty, we would be adding zeros to this // [so we do nothing] while (p2 < b.used) this.set(b.indexes[p2], c * b.values[p2++]); // TODO Can be done more efficently } else if (v.isSparse()) { if (v.nnz() == 0) return; int p1 = 0; Iterator<IndexValue> iter = v.getNonZeroIterator(); IndexValue iv = iter.next(); while (p1 < used && iv != null) { int a1 = indexes[p1]; int a2 = iv.getIndex(); if (a1 == a2) { values[p1++] += c * iv.getValue(); if (iter.hasNext()) iv = iter.next(); else break; } else if (a1 > a2) { this.set(a2, c * iv.getValue()); p1++; if (iter.hasNext()) iv = iter.next(); else break; } else p1++; } } else { // Else it is dense for (int i = 0; i < length(); i++) this.set(i, this.get(i) + c * v.get(i)); } }