/*
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef COBALT_MATH_LINEAR_INTERPOLATOR_H_
#define COBALT_MATH_LINEAR_INTERPOLATOR_H_

#include <iterator>
#include <utility>
#include <vector>

#include "base/logging.h"
#include "starboard/types.h"

namespace cobalt {
namespace math {

// LinearInterpolator effectively generates outputs based on a table. This can
// be used for function approximation (ie. sine) or arbitrary functions that
// need specific values at specific inputs, and interpolated values otherwise.
// KeyT and ValueT can be any builtin integer and float point type.
// It's recommended that double types are used unless speed is required, then
// use other types.
//
// Performance:
//  This table increases the computation on the order of O(n) of the number
//  of interpolation points. However in practice the number of interpolation
//  points is small enough (<20) where this linear search is faster than binary
//  lookup.
//
// Discontinuous values:
//  This table supports discontinuous values. To enable this feature, insert a
//  pair of duplicate keys, each with a different value. See example below.
//
// Example (continuous):
//  LinearInterpolator<float, float> interp;
//  interp.Add(0, 0);
//  interp.Add(1, 2);
//  EXPECT_FLOAT_EQ(0.f, interp.Map(0.0f));
//  EXPECT_FLOAT_EQ(1.f, interp.Map(0.5f));
//  EXPECT_FLOAT_EQ(2.f, interp.Map(1.0f));
//
// Example (discontinuous):
//  LinearInterpolator<double, float> interp;
//  interp.Add(0, 0);
//  interp.Add(1, 1);  // Discontinuity at input = 1.
//  interp.Add(1, 3);
//  interp.Add(2, 4);
//  static const double kErrorThreshold = .1f;
//  static const double kEpsilon = std::numeric_limits<double>::epsilon()*4.0;
//  EXPECT_NEAR(1.0, interp.Map(1.f - kEpsilon), kErrorThreshold);
//  EXPECT_FLOAT_EQ(3, interp.Map(1.f));
//  EXPECT_NEAR(3.0, interp.Map(1.f + kEpsilon), kErrorThreshold);
template <typename KeyT, typename ValueT>
class LinearInterpolator {
 public:
  ValueT Map(const KeyT& key) const {
    return Interp(key);
  }

  // Adds a key to the table. For a continuous piecewise line-curve each key
  // added must be greater in value than the last key added.
  // If duplicate keys are entered sequentially then this will introduce
  // a discontinuity - a big jump in the returned value from Map() when the
  // input crosses the discontinuity point.
  void Add(const KeyT& key, const ValueT& val) {
    if (!table_.empty()) {
      DCHECK_LE(table_.back().first, key) << "Keys are not in order.";
    }
    table_.push_back(std::pair<KeyT, ValueT>(key, val));
  }
  void Clear() {
    table_.clear();
  }

 private:
  ValueT Interp(const KeyT& k) const {
    if (table_.empty()) {
      return ValueT(0);
    }

    // Contains the indices which reference keys before and after the key.
    std::pair<size_t, size_t> indices = SelectInterpPoints(k);

    // Singular value, no interpolation needed.
    if (indices.first == indices.second) {
      return table_[indices.first].second;
    }

    // Perform the interpolation with the given key & value lines.
    const std::pair<KeyT, ValueT>& curr = table_[indices.first];
    const std::pair<KeyT, ValueT>& next = table_[indices.second];

    // Duplicate keys, select the second value. This prevents
    // LinearInterpolation() from dividing by 0 for duplicate keys.
    if (curr.first == next.first) {
      return next.second;
    }

    return LinearInterpolation(k, curr.first, next.first,
                               curr.second, next.second);
  }

  // Linearly walk through the table looking for a pair of interpolation
  // points. Linear walking must be used because this table uses duplicate
  // keys generate discontinuous outputs.
  std::pair<size_t, size_t> SelectInterpPoints(const KeyT& k) const {
    DCHECK(!table_.empty());
    if (k < table_[0].first) {
      return std::pair<size_t, size_t>(0, 0);
    }

    for (size_t i = 0; i < table_.size() - 1; ++i) {
      const std::pair<KeyT, ValueT>& curr = table_[i];
      const std::pair<KeyT, ValueT>& next = table_[i+1];

      if (curr.first <= k && k < next.first) {
        return std::pair<size_t, size_t>(i, i+1);
      }
    }

    return std::pair<size_t, size_t>(table_.size() - 1, table_.size() - 1);
  }

  // Maps a value in the range [x1, x2] to the range [y1, y2].
  static const ValueT LinearInterpolation(const KeyT& t,
                                          const KeyT& x1, const KeyT& x2,
                                          const ValueT& y1, const ValueT& y2) {
    ValueT return_val =
        static_cast<ValueT>((t - x1) * (y2 - y1) / (x2 - x1) + y1);
    return return_val;
  }

  typedef std::vector<std::pair<KeyT, ValueT> > VectorType;
  VectorType table_;
};

}  // namespace math
}  // namespace cobalt

#endif  // COBALT_MATH_LINEAR_INTERPOLATOR_H_
