package rltoys.algorithms.representations.traces;

import rltoys.math.vector.MutableVector;
import rltoys.math.vector.RealVector;
import rltoys.math.vector.SparseVector;
import rltoys.math.vector.VectorEntry;
import rltoys.math.vector.implementations.SVector;

/**
 * Accumulating traces with an absolute value on each element
 */
public class AMaxTraces extends ATraces {
  private static final long serialVersionUID = 8063854269195146376L;
  final private double maximumValue;

  public AMaxTraces() {
    this(1);
  }

  public AMaxTraces(double maximumValue) {
    this(maximumValue, DefaultPrototype);
  }

  public AMaxTraces(double maximumValue, MutableVector prototype) {
    this(maximumValue, DefaultPrototype, -1, 0);
  }

  public AMaxTraces(double maximumValue, MutableVector prototype, int targetSize, double targetTolerance) {
    this(0, targetSize, targetTolerance, maximumValue, DefaultPrototype);
    assert prototype instanceof SparseVector;
  }

  protected AMaxTraces(int size, int targetSize, double targetTolerance, double maximumValue, MutableVector prototype) {
    super(size, targetSize, targetTolerance, prototype);
    this.maximumValue = maximumValue;
  }

  @Override
  public AMaxTraces newTraces(int size) {
    return new AMaxTraces(size, targetSize, targetTolerance, maximumValue, prototype);
  }

  private void addToSelfAsSVector(RealVector phi) {
    SVector svector = (SVector) vector;
    int thisPosition = 0;
    for (VectorEntry entry : phi) {
      int otherIndex = entry.index();
      int search = svector.searchFrom(thisPosition, otherIndex);
      int position = search;
      if (position < 0) {
        position = SVector.notFoundToPosition(search);
        svector.insertElementAtPosition(position, otherIndex, adjustValue(entry.value()));
      } else
        svector.values[position] = adjustValue(entry.value() + svector.values[position]);
      thisPosition = position + 1;
    }
  }

  @Override
  protected void addToSelf(RealVector phi) {
    if (phi instanceof SVector) {
      addToSelfAsSVector(phi);
      return;
    }
    for (VectorEntry entry : phi) {
      int index = entry.index();
      double value = adjustValue(vector.getEntry(index) + entry.value());
      vector.setEntry(index, value);
    }
  }

  private double adjustValue(double value) {
    if (Math.abs(value) <= maximumValue)
      return value;
    return Math.signum(value) * maximumValue;
  }
}

@@ -597,32 +597,191 @@
 rototype);%0A  %7D%0A%0A
+  public AMaxTraces(double maximumValue, int targetSize, double targetTolerance) %7B%0A    this(maximumValue, DefaultPrototype, targetSize, targetTolerance);%0A  %7D%0A%0A
   public AMaxTra
@@ -1488,23 +1488,37 @@
 %0A  %7D%0A%0A  
-priva
+@Override%0A  protec
 te
+d
  void ad
@@ -1524,25 +1524,16 @@
 ddToSelf
-AsSVector
 (RealVec
@@ -1551,422 +1551,166 @@
     
-SVector svector = (SVector) vector;%0A    int thisPosition = 0
+super.addToSelf(phi)
 ;%0A    
+i
 f
-or
  (
-V
+v
 ector
-Entry entry : phi) %7B%0A      int otherIndex = entry.index();%0A      int search = svector.searchFrom(thisPosition, otherIndex);%0A      int position = search;%0A      if (position %3C 0) %7B%0A        position = SVector.notFoundToPosition(search);%0A        svector.insertElementAtPosition(position, otherIndex, adjustValue(entry.value()));%0A      %7D else
+ instanceof SVector) %7B%0A      SVector svector = (SVector) vector;%0A      for (int i = 0; i %3C svector.nonZeroElements(); i++)
 %0A   
@@ -1729,24 +1729,17 @@
 .values%5B
-position
+i
 %5D = adju
@@ -1750,216 +1750,25 @@
 lue(
-entry.value() + svector.values%5Bposition%5D);%0A      thisPosition = position + 1;%0A    %7D%0A  %7D%0A%0A  @Override%0A  protected void addToSelf(RealVector phi) %7B%0A    if (phi instanceof SVector) %7B%0A      addToSelfAsSVector(phi
+svector.values%5Bi%5D
 );%0A 

Optimize AMaxTraces