// Path: src/main/java/sssj/io/Vector.java
// public class Vector { // entries are returned in the same order they are added
//   public static final Vector EMPTY_VECTOR = new Vector(Long.MIN_VALUE);
//   protected Int2DoubleLinkedOpenHashMap data = new Int2DoubleLinkedOpenHashMap();
//   protected long timestamp;
//   protected double maxValue;
//   protected double sumValues;
// 
//   public Vector() {
//     this(0);
//   }
// 
//   public Vector(long timestamp) {
//     this.timestamp = timestamp;
//     this.maxValue = 0;
//     this.sumValues = 0;
//   }
// 
//   /**
//    * Copy constructor. The values are deep copied.
//    * 
//    * @param other the vector to copy
//    */
//   public Vector(Vector other) {
//     this.timestamp = other.timestamp;
//     this.maxValue = other.maxValue;
//     this.sumValues = other.sumValues;
//     data.putAll(other.data);
//   }
// 
//   public double put(int k, double v) {
//     this.maxValue = Math.max(maxValue, v);
//     this.sumValues += v;
//     return data.put(k, v);
//   }
// 
//   public double get(int k) {
//     return data.get(k);
//   }
// 
//   public FastSortedEntrySet int2DoubleEntrySet() {
//     return data.int2DoubleEntrySet();
//   }
// 
//   public int size() {
//     return data.size();
//   }
// 
//   public double maxValue() {
//     return maxValue;
//   }
//   
//   public double sumValues() {
//     return sumValues;
//   }
// 
//   public long timestamp() {
//     return timestamp;
//   }
// 
//   public void setTimestamp(long timestamp) {
//     this.timestamp = timestamp;
//   }
// 
//   @Override
//   public String toString() {
//     return timestamp + "\t" + super.toString();
//   }
// 
//   @Override
//   public int hashCode() {
//     final int prime = 31;
//     int result = 1;
//     result = prime * result + ((data == null) ? 0 : data.hashCode());
//     result = prime * result + (int) (timestamp ^ (timestamp >>> 32));
//     return result;
//   }
// 
//   @Override
//   public boolean equals(Object obj) {
//     if (this == obj)
//       return true;
//     if (obj == null)
//       return false;
//     if (!(obj instanceof Vector))
//       return false;
//     Vector other = (Vector) obj;
//     if (data == null) {
//       if (other.data != null)
//         return false;
//     } else if (!data.equals(other.data))
//       return false;
//     if (timestamp != other.timestamp)
//       return false;
//     return true;
//   }
// 
//   public double magnitude() {
//     double magnitude = 0;
//     for (double d : data.values())
//       magnitude += d * d;
//     magnitude = Math.sqrt(magnitude);
//     return magnitude;
//   }
// 
//   public void read(ByteBuffer in) throws IOException {
//     data.clear();
//     int numElements = in.getInt();
//     this.setTimestamp(in.getLong());
//     for (int i = 0; i < numElements; i++) {
//       int dim = in.getInt();
//       double val = in.getDouble();
//       this.put(dim, val);
//     }
//   }
// 
//   public void write(ByteBuffer out) throws IOException {
//     out.putInt(this.size());
//     out.putLong(this.timestamp());
//     for (Int2DoubleMap.Entry e : this.int2DoubleEntrySet()) {
//       out.putInt(e.getIntKey());
//       out.putDouble(e.getDoubleValue());
//     }
//   }
// 
//   public void read(DataInput in) throws IOException {
//     data.clear();
//     int numElements = in.readInt();
//     this.setTimestamp(in.readLong());
//     for (int i = 0; i < numElements; i++) {
//       int dim = in.readInt();
//       double val = in.readDouble();
//       this.put(dim, val);
//     }
//   }
// 
//   public void write(DataOutput out) throws IOException {
//     out.writeInt(this.size());
//     out.writeLong(this.timestamp());
//     for (Int2DoubleMap.Entry e : this.int2DoubleEntrySet()) {
//       out.writeInt(e.getIntKey());
//       out.writeDouble(e.getDoubleValue());
//     }
//   }
// 
//   public static Vector l2normalize(Vector v) {
//     Vector result;
//     double magnitude = v.magnitude();
//     if (Double.compare(1.0, magnitude) != 0) {
//       result = new Vector(v.timestamp());
//       for (Int2DoubleMap.Entry e : v.int2DoubleEntrySet())
//         result.put(e.getIntKey(), e.getDoubleValue() / magnitude);
//     } else {
//       result = v;
//     }
//     return result;
//   }
// 
//   public static double similarity(Vector query, Vector target) {
//     double result = 0;
//     for (Int2DoubleMap.Entry e : query.int2DoubleEntrySet()) {
//       result += e.getDoubleValue() * target.get(e.getIntKey());
//     }
//     return result;
//   }
// }


import java.util.ArrayDeque;
import java.util.Iterator;
import java.util.Queue;
import sssj.io.Vector;
import com.google.common.base.Preconditions;
package sssj.index.minibatch.component;




/**
 * A buffer for Vectors. The buffer keeps the order of the vectors as they are added, and optionally maintains the maximum vector. Assumes vectors are added in
 * increasing order of timestamp.
 */
public class VectorWindow {
  private MaxVector max1 = new MaxVector();
  private MaxVector max2 = new MaxVector();
// Path: src/main/java/sssj/io/Vector.java
// public class Vector { // entries are returned in the same order they are added
//   public static final Vector EMPTY_VECTOR = new Vector(Long.MIN_VALUE);
//   protected Int2DoubleLinkedOpenHashMap data = new Int2DoubleLinkedOpenHashMap();
//   protected long timestamp;
//   protected double maxValue;
//   protected double sumValues;
// 
//   public Vector() {
//     this(0);
//   }
// 
//   public Vector(long timestamp) {
//     this.timestamp = timestamp;
//     this.maxValue = 0;
//     this.sumValues = 0;
//   }
// 
//   /**
//    * Copy constructor. The values are deep copied.
//    * 
//    * @param other the vector to copy
//    */
//   public Vector(Vector other) {
//     this.timestamp = other.timestamp;
//     this.maxValue = other.maxValue;
//     this.sumValues = other.sumValues;
//     data.putAll(other.data);
//   }
// 
//   public double put(int k, double v) {
//     this.maxValue = Math.max(maxValue, v);
//     this.sumValues += v;
//     return data.put(k, v);
//   }
// 
//   public double get(int k) {
//     return data.get(k);
//   }
// 
//   public FastSortedEntrySet int2DoubleEntrySet() {
//     return data.int2DoubleEntrySet();
//   }
// 
//   public int size() {
//     return data.size();
//   }
// 
//   public double maxValue() {
//     return maxValue;
//   }
//   
//   public double sumValues() {
//     return sumValues;
//   }
// 
//   public long timestamp() {
//     return timestamp;
//   }
// 
//   public void setTimestamp(long timestamp) {
//     this.timestamp = timestamp;
//   }
// 
//   @Override
//   public String toString() {
//     return timestamp + "\t" + super.toString();
//   }
// 
//   @Override
//   public int hashCode() {
//     final int prime = 31;
//     int result = 1;
//     result = prime * result + ((data == null) ? 0 : data.hashCode());
//     result = prime * result + (int) (timestamp ^ (timestamp >>> 32));
//     return result;
//   }
// 
//   @Override
//   public boolean equals(Object obj) {
//     if (this == obj)
//       return true;
//     if (obj == null)
//       return false;
//     if (!(obj instanceof Vector))
//       return false;
//     Vector other = (Vector) obj;
//     if (data == null) {
//       if (other.data != null)
//         return false;
//     } else if (!data.equals(other.data))
//       return false;
//     if (timestamp != other.timestamp)
//       return false;
//     return true;
//   }
// 
//   public double magnitude() {
//     double magnitude = 0;
//     for (double d : data.values())
//       magnitude += d * d;
//     magnitude = Math.sqrt(magnitude);
//     return magnitude;
//   }
// 
//   public void read(ByteBuffer in) throws IOException {
//     data.clear();
//     int numElements = in.getInt();
//     this.setTimestamp(in.getLong());
//     for (int i = 0; i < numElements; i++) {
//       int dim = in.getInt();
//       double val = in.getDouble();
//       this.put(dim, val);
//     }
//   }
// 
//   public void write(ByteBuffer out) throws IOException {
//     out.putInt(this.size());
//     out.putLong(this.timestamp());
//     for (Int2DoubleMap.Entry e : this.int2DoubleEntrySet()) {
//       out.putInt(e.getIntKey());
//       out.putDouble(e.getDoubleValue());
//     }
//   }
// 
//   public void read(DataInput in) throws IOException {
//     data.clear();
//     int numElements = in.readInt();
//     this.setTimestamp(in.readLong());
//     for (int i = 0; i < numElements; i++) {
//       int dim = in.readInt();
//       double val = in.readDouble();
//       this.put(dim, val);
//     }
//   }
// 
//   public void write(DataOutput out) throws IOException {
//     out.writeInt(this.size());
//     out.writeLong(this.timestamp());
//     for (Int2DoubleMap.Entry e : this.int2DoubleEntrySet()) {
//       out.writeInt(e.getIntKey());
//       out.writeDouble(e.getDoubleValue());
//     }
//   }
// 
//   public static Vector l2normalize(Vector v) {
//     Vector result;
//     double magnitude = v.magnitude();
//     if (Double.compare(1.0, magnitude) != 0) {
//       result = new Vector(v.timestamp());
//       for (Int2DoubleMap.Entry e : v.int2DoubleEntrySet())
//         result.put(e.getIntKey(), e.getDoubleValue() / magnitude);
//     } else {
//       result = v;
//     }
//     return result;
//   }
// 
//   public static double similarity(Vector query, Vector target) {
//     double result = 0;
//     for (Int2DoubleMap.Entry e : query.int2DoubleEntrySet()) {
//       result += e.getDoubleValue() * target.get(e.getIntKey());
//     }
//     return result;
//   }
// }


// Path: src/main/java/sssj/index/minibatch/component/VectorWindow.java
import java.util.ArrayDeque;
import java.util.Iterator;
import java.util.Queue;
import sssj.io.Vector;
import com.google.common.base.Preconditions;

package sssj.index.minibatch.component;




/**
 * A buffer for Vectors. The buffer keeps the order of the vectors as they are added, and optionally maintains the maximum vector. Assumes vectors are added in
 * increasing order of timestamp.
 */
public class VectorWindow {
  private MaxVector max1 = new MaxVector();
  private MaxVector max2 = new MaxVector();
  private Queue<Vector> q1 = new ArrayDeque<>();