code: // Copyright (c) 2016 - Patrick Schäfer (patrick.schaefer@hu-berlin.de)
  // Distributed under the GLP 3.0 (See accompanying file LICENSE)
  
  //modified by @shifaz 2018
  
  package dotnet54.classifiers.tschief.splitters.boss;
  
  /**
   * SFA lower bounding distance of the Euclidean distance as published in
   * Schäfer, P., Högqvist, M.: SFA: a symbolic fourier approximation and
   * index for similarity search in high dimensional datasets.
   * In: EDBT, ACM (2012) *
   */
  public class SFADistance {
    private SFA sfa;
  
    public SFADistance(SFA transform) {
      this.sfa = transform;
    }
  
    /**
     * The SFA-distance lower bounds the Euclidean Distance
     */
    public double getDistance(short[] wordsTs, short[] wordsQuery, double[] dftQuery, boolean normed, double minValue) {
      double distance = 0.0;
  
      // mean (DC) value
      int i = 0;
      if (!normed) {
        distance = dist(
            wordsTs[0],
            wordsQuery[0],
            dftQuery[0],
            0);
        distance *= distance;
        i += 2;
      }
  
      // remaining Fourier values (real and imaginary parts)
      for (; i < wordsTs.length; i++) {
  
        double value = dist(
            wordsTs[i],
            wordsQuery[i],
            dftQuery[i],
            i);
  
        distance += 2 * value * value;
  
        // pruning if distance threshold is exceeded
        if (distance > minValue) {
          return distance;
        }
      }
  
      return distance;
    }
  
    /**
     * Distance between a symbol and a Fourier value based on bins
     */
    public double dist(short c1Value, short c2Value, double realC2, int dim) {
      if (c1Value == c2Value) {
        return 0;
      }
      return (c1Value > c2Value) ?
          (this.sfa).bins[dim][c1Value - 1] - realC2 :
          realC2 - (this.sfa).bins[dim][c1Value];
    }
  }
  