/**
  * Construct a new vector from a key set and value array.
  *
  * @param ks The key set. Used as-is, and will be modified. Pass a clone, usually.
  * @param vs The value array.
  */
 @SuppressWarnings("PMD.ArrayIsStoredDirectly")
 SparseVector(LongKeyDomain ks, double[] vs) {
   assert vs.length >= ks.domainSize();
   keys = ks;
   keys.acquire();
   values = vs;
 }
 /**
  * Construct a new vector from the contents of a map. The key domain is the key set of the map.
  * Therefore, no new keys can be added to this vector.
  *
  * @param keyValueMap A map providing the values for the vector.
  */
 SparseVector(Long2DoubleMap keyValueMap) {
   keys = LongKeyDomain.fromCollection(keyValueMap.keySet(), true);
   final int len = keys.domainSize();
   values = new double[len];
   for (int i = 0; i < len; i++) {
     values[i] = keyValueMap.get(keys.getKey(i));
   }
 }
  /**
   * Check whether an entry is set.
   *
   * @param entry The entry.
   * @return {@code true} if the entry is set in this vector.
   * @throws IllegalArgumentException if the entry is not from this vector or another vector sharing
   *     the same key domain. Only vectors and their side channels share key domains for the
   *     purposes of this check.
   */
  public boolean isSet(VectorEntry entry) {
    final SparseVector evec = entry.getVector();
    final int eind = entry.getIndex();

    if (evec == null) {
      throw new IllegalArgumentException("entry is not associated with a vector");
    } else if (!keys.isCompatibleWith(evec.keys)) {
      throw new IllegalArgumentException("entry does not have safe key domain");
    }
    assert entry.getKey() == keys.getKey(eind);
    return keys.indexIsActive(eind);
  }
  /**
   * Get the value for the entry's key.
   *
   * @param entry A {@code VectorEntry} with the key to look up
   * @return the key's value
   * @throws IllegalArgumentException if the entry is unset, or if it is not from this vector or
   *     another vector sharing the same key domain. Only vectors and their side channels share key
   *     domains for the purposes of this check.
   */
  public double get(VectorEntry entry) {
    final SparseVector evec = entry.getVector();
    final int eind = entry.getIndex();

    if (evec == null) {
      throw new IllegalArgumentException("entry is not associated with a vector");
    } else if (!evec.keys.isCompatibleWith(keys)) {
      throw new IllegalArgumentException("entry does not have safe key domain");
    }
    assert entry.getKey() == keys.getKey(eind);
    if (keys.indexIsActive(eind)) {
      return values[eind];
    } else {
      throw new IllegalArgumentException("Key " + entry.getKey() + " is not set");
    }
  }
 /**
  * Get the value for {@var key}.
  *
  * @param key the key to look up
  * @param dft The value to return if the key is not in the vector
  * @return the value (or {@var dft} if the key is not set to a value)
  */
 public double get(long key, double dft) {
   final int idx = keys.getIndexIfActive(key);
   if (idx >= 0) {
     return values[idx];
   } else {
     return dft;
   }
 }
 /**
  * Get the value for {@var key}.
  *
  * @param key the key to look up; the key must be in the key set.
  * @return the key's value
  * @throws IllegalArgumentException if {@var key} is not in the key set.
  */
 public double get(long key) {
   final int idx = keys.getIndexIfActive(key);
   if (idx >= 0) {
     return values[idx];
   } else {
     throw new IllegalArgumentException("Key " + key + " is not in the key set");
   }
 }
 /**
  * Get the collection of values of this vector.
  *
  * @return The collection of all values in this vector.
  */
 public DoubleCollection values() {
   DoubleArrayList lst = new DoubleArrayList(size());
   IntIterator iter = keys.activeIndexIterator(false);
   while (iter.hasNext()) {
     int idx = iter.nextInt();
     lst.add(values[idx]);
   }
   return lst;
 }
 /**
  * Fast iterator over entries (it can reuse entry objects).
  *
  * @param state The state of entries to iterate.
  * @return a fast iterator over all key/value pairs
  * @see it.unimi.dsi.fastutil.longs.Long2DoubleMap.FastEntrySet#fastIterator()
  *     Long2DoubleMap.FastEntrySet.fastIterator()
  * @since 0.11
  */
 public Iterator<VectorEntry> fastIterator(VectorEntry.State state) {
   IntIterator iter;
   switch (state) {
     case SET:
       iter = keys.activeIndexIterator(isMutable());
       break;
     case UNSET:
       {
         iter = keys.clone().invert().activeIndexIterator(false);
         break;
       }
     case EITHER:
       {
         iter = IntIterators.fromTo(0, keys.domainSize());
         break;
       }
     default: // should be impossible
       throw new IllegalArgumentException("invalid entry state");
   }
   return new FastIterImpl(iter, state);
 }
 /**
  * Construct a new sparse vector with a particular domain. Allocates the value storage.
  *
  * @param ks The key set. Used as-is, and will be modified. Pass a clone, usually.
  */
 SparseVector(LongKeyDomain ks) {
   this(ks, new double[ks.domainSize()]);
   ks.setAllActive(false);
 }
 /**
  * Get the size of this vector (the number of keys).
  *
  * @return The number of keys in the vector. This is at most the size of the key domain.
  */
 public int size() {
   return keys.size();
 }
 /**
  * Get the set of unset keys. This is \(D \\ S\), where \(D\) is the key domain and \(S\) the key
  * set.
  */
 public LongSortedSet unsetKeySet() {
   return keys.clone().invert().activeSetView();
 }
 /**
  * Get the set of keys of this vector. It is a subset of the key domain. The keys will be in
  * sorted order.
  *
  * @return The set of keys used in this vector.
  */
 public LongSortedSet keySet() {
   return keys.activeSetView();
 }
 /**
  * Get the key domain for this vector. All keys used are in this set. The keys will be in sorted
  * order.
  *
  * @return The key domain for this vector.
  */
 public LongSortedSet keyDomain() {
   return keys.domain();
 }
 /**
  * Query whether the vector contains an entry for the key in question.
  *
  * @param key The key to search for.
  * @return {@code true} if the key exists.
  */
 public boolean containsKey(long key) {
   return keys.keyIsActive(key);
 }