16cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi/*
26cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * Copyright (C) 2013 The Android Open Source Project
36cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *
46cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
56cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * you may not use this file except in compliance with the License.
66cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * You may obtain a copy of the License at
76cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *
86cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
96cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *
106cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
116cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
126cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * See the License for the specific language governing permissions and
146cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * limitations under the License.
156cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi */
166cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
176cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#ifndef LE_FX_ENGINE_DSP_CORE_INTERPOLATOR_BASE_INL_H_
186cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#define LE_FX_ENGINE_DSP_CORE_INTERPOLATOR_BASE_INL_H_
196cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
206cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#include "dsp/core/basic.h"
216cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
226cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi//#define LOG_NDEBUG 0
236cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#include <cutils/log.h>
246cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
256cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
266cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivinamespace le_fx {
276cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
286cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivinamespace sigmod {
296cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
306cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm>
316cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel TriviInterpolatorBase<T, Algorithm>::InterpolatorBase() {
326cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  status_ = false;
336cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  cached_index_ = 0;
346cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  x_data_ = NULL;
356cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  y_data_ = NULL;
366cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  data_length_ = 0;
376cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  own_x_data_ = false;
386cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  x_start_offset_ = 0.0;
396cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  last_element_index_ = -1;
406cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  x_inverse_sampling_interval_ = 0.0;
416cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  state_ = NULL;
426cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}
436cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
446cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm>
456cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel TriviInterpolatorBase<T, Algorithm>::~InterpolatorBase() {
466cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  delete [] state_;
476cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  if (own_x_data_) {
486cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    delete [] x_data_;
496cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  }
506cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}
516cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
526cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm>
536cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivibool InterpolatorBase<T, Algorithm>::Initialize(const vector<T> &x_data,
546cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                                                const vector<T> &y_data) {
556cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#ifndef NDEBUG
566cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  if (x_data.size() != y_data.size()) {
576cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    LoggerError("InterpolatorBase::Initialize: xData size (%d) != yData size"
586cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                  " (%d)", x_data.size(), y_data.size());
596cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  }
606cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#endif
616cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  return Initialize(&x_data[0], &y_data[0], x_data.size());
626cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}
636cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
646cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm>
656cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivibool InterpolatorBase<T, Algorithm>::Initialize(double x_start_offset,
666cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                                                double x_sampling_interval,
676cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                                                const vector<T> &y_data) {
686cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  return Initialize(x_start_offset,
696cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                    x_sampling_interval,
706cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                    &y_data[0],
716cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                    y_data.size());
726cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}
736cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
746cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm>
756cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivibool InterpolatorBase<T, Algorithm>::Initialize(double x_start_offset,
766cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                                                double x_sampling_interval,
776cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                                                const T *y_data,
786cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                                                int data_length) {
796cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // Constructs and populate x-axis data: `x_data_`
806cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  T *x_data_tmp = new T[data_length];
816cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  float time_offset = x_start_offset;
826cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  for (int n = 0; n < data_length; n++) {
836cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    x_data_tmp[n] = time_offset;
846cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    time_offset += x_sampling_interval;
856cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  }
866cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  Initialize(x_data_tmp, y_data, data_length);
876cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // Sets-up the regularly sampled interpolation mode
886cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  x_start_offset_ = x_start_offset;
896cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  x_inverse_sampling_interval_ = 1.0 / x_sampling_interval;
906cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  own_x_data_ = true;
916cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  return status_;
926cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}
936cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
946cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
956cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm>
966cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivibool InterpolatorBase<T, Algorithm>::Initialize(
976cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    const T *x_data, const T *y_data, int data_length) {
986cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // Default settings
996cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  cached_index_ = 0;
1006cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  data_length_ = 0;
1016cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  x_start_offset_ = 0;
1026cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  x_inverse_sampling_interval_ = 0;
1036cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  state_ = NULL;
1046cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // Input data is externally owned
1056cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  own_x_data_ = false;
1066cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  x_data_ = x_data;
1076cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  y_data_ = y_data;
1086cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  data_length_ = data_length;
1096cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  last_element_index_ = data_length - 1;
1106cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // Check input data sanity
1116cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  for (int n = 0; n < last_element_index_; ++n) {
1126cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    if (x_data_[n + 1] <= x_data_[n]) {
1136cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      ALOGE("InterpolatorBase::Initialize: xData are not ordered or "
1146cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi              "contain equal values (X[%d] <= X[%d]) (%.5e <= %.5e)",
1156cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi              n + 1, n, x_data_[n + 1], x_data_[n]);
1166cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      status_ = false;
1176cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      return false;
1186cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    }
1196cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  }
1206cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // Pre-compute internal state by calling the corresponding function of the
1216cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // derived class.
1226cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  status_ = static_cast<Algorithm*>(this)->SetInternalState();
1236cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  return status_;
1246cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}
1256cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
1266cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm>
1276cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel TriviT InterpolatorBase<T, Algorithm>::Interpolate(T x) {
1286cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#ifndef NDEBUG
1296cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  if (cached_index_ < 0 || cached_index_ > data_length_ - 2) {
1306cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    LoggerError("InterpolatorBase:Interpolate: CachedIndex_ out of bounds "
1316cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                  "[0, %d, %d]", cached_index_, data_length_ - 2);
1326cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  }
1336cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#endif
1346cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // Search for the containing interval
1356cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  if (x <= x_data_[cached_index_]) {
1366cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    if (cached_index_ <= 0) {
1376cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      cached_index_ = 0;
1386cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      return y_data_[0];
1396cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    }
1406cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    if (x >= x_data_[cached_index_ - 1]) {
1416cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      cached_index_--;  // Fast descending
1426cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    } else {
1436cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      if (x <= x_data_[0]) {
1446cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi        cached_index_ = 0;
1456cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi        return y_data_[0];
1466cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      }
1476cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      cached_index_ = SearchIndex(x_data_, x, 0, cached_index_);
1486cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    }
1496cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  } else {
1506cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    if (cached_index_ >= last_element_index_) {
1516cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      cached_index_ = last_element_index_;
1526cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      return y_data_[last_element_index_];
1536cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    }
1546cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    if (x > x_data_[cached_index_ + 1]) {
1556cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      if (cached_index_ + 2 > last_element_index_) {
1566cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi        cached_index_ = last_element_index_ - 1;
1576cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi        return y_data_[last_element_index_];
1586cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      }
1596cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      if (x <= x_data_[cached_index_ + 2]) {
1606cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi        cached_index_++;  // Fast ascending
1616cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      } else {
1626cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi        if (x >= x_data_[last_element_index_]) {
1636cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi          cached_index_ = last_element_index_ - 1;
1646cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi          return y_data_[last_element_index_];
1656cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi        }
1666cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi        cached_index_ = SearchIndex(
1676cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi            x_data_, x, cached_index_, last_element_index_);
1686cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      }
1696cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    }
1706cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  }
1716cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // Compute interpolated value by calling the corresponding function of the
1726cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // derived class.
1736cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  return static_cast<Algorithm*>(this)->MethodSpecificInterpolation(x);
1746cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}
1756cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
1766cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}  // namespace sigmod
1776cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
1786cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}  // namespace le_fx
1796cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
1806cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#endif  // LE_FX_ENGINE_DSP_CORE_INTERPOLATOR_BASE_INL_H_
181