Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef LE_FX_ENGINE_DSP_CORE_INTERPOLATOR_BASE_INL_H_
     18 #define LE_FX_ENGINE_DSP_CORE_INTERPOLATOR_BASE_INL_H_
     19 
     20 #include "dsp/core/basic.h"
     21 
     22 //#define LOG_NDEBUG 0
     23 #include <cutils/log.h>
     24 
     25 
     26 namespace le_fx {
     27 
     28 namespace sigmod {
     29 
     30 template <typename T, class Algorithm>
     31 InterpolatorBase<T, Algorithm>::InterpolatorBase() {
     32   status_ = false;
     33   cached_index_ = 0;
     34   x_data_ = NULL;
     35   y_data_ = NULL;
     36   data_length_ = 0;
     37   own_x_data_ = false;
     38   x_start_offset_ = 0.0;
     39   last_element_index_ = -1;
     40   x_inverse_sampling_interval_ = 0.0;
     41   state_ = NULL;
     42 }
     43 
     44 template <typename T, class Algorithm>
     45 InterpolatorBase<T, Algorithm>::~InterpolatorBase() {
     46   delete [] state_;
     47   if (own_x_data_) {
     48     delete [] x_data_;
     49   }
     50 }
     51 
     52 template <typename T, class Algorithm>
     53 bool InterpolatorBase<T, Algorithm>::Initialize(const vector<T> &x_data,
     54                                                 const vector<T> &y_data) {
     55 #ifndef NDEBUG
     56   if (x_data.size() != y_data.size()) {
     57     LoggerError("InterpolatorBase::Initialize: xData size (%d) != yData size"
     58                   " (%d)", x_data.size(), y_data.size());
     59   }
     60 #endif
     61   return Initialize(&x_data[0], &y_data[0], x_data.size());
     62 }
     63 
     64 template <typename T, class Algorithm>
     65 bool InterpolatorBase<T, Algorithm>::Initialize(double x_start_offset,
     66                                                 double x_sampling_interval,
     67                                                 const vector<T> &y_data) {
     68   return Initialize(x_start_offset,
     69                     x_sampling_interval,
     70                     &y_data[0],
     71                     y_data.size());
     72 }
     73 
     74 template <typename T, class Algorithm>
     75 bool InterpolatorBase<T, Algorithm>::Initialize(double x_start_offset,
     76                                                 double x_sampling_interval,
     77                                                 const T *y_data,
     78                                                 int data_length) {
     79   // Constructs and populate x-axis data: `x_data_`
     80   T *x_data_tmp = new T[data_length];
     81   float time_offset = x_start_offset;
     82   for (int n = 0; n < data_length; n++) {
     83     x_data_tmp[n] = time_offset;
     84     time_offset += x_sampling_interval;
     85   }
     86   Initialize(x_data_tmp, y_data, data_length);
     87   // Sets-up the regularly sampled interpolation mode
     88   x_start_offset_ = x_start_offset;
     89   x_inverse_sampling_interval_ = 1.0 / x_sampling_interval;
     90   own_x_data_ = true;
     91   return status_;
     92 }
     93 
     94 
     95 template <typename T, class Algorithm>
     96 bool InterpolatorBase<T, Algorithm>::Initialize(
     97     const T *x_data, const T *y_data, int data_length) {
     98   // Default settings
     99   cached_index_ = 0;
    100   data_length_ = 0;
    101   x_start_offset_ = 0;
    102   x_inverse_sampling_interval_ = 0;
    103   state_ = NULL;
    104   // Input data is externally owned
    105   own_x_data_ = false;
    106   x_data_ = x_data;
    107   y_data_ = y_data;
    108   data_length_ = data_length;
    109   last_element_index_ = data_length - 1;
    110   // Check input data sanity
    111   for (int n = 0; n < last_element_index_; ++n) {
    112     if (x_data_[n + 1] <= x_data_[n]) {
    113       ALOGE("InterpolatorBase::Initialize: xData are not ordered or "
    114               "contain equal values (X[%d] <= X[%d]) (%.5e <= %.5e)",
    115               n + 1, n, x_data_[n + 1], x_data_[n]);
    116       status_ = false;
    117       return false;
    118     }
    119   }
    120   // Pre-compute internal state by calling the corresponding function of the
    121   // derived class.
    122   status_ = static_cast<Algorithm*>(this)->SetInternalState();
    123   return status_;
    124 }
    125 
    126 template <typename T, class Algorithm>
    127 T InterpolatorBase<T, Algorithm>::Interpolate(T x) {
    128 #ifndef NDEBUG
    129   if (cached_index_ < 0 || cached_index_ > data_length_ - 2) {
    130     LoggerError("InterpolatorBase:Interpolate: CachedIndex_ out of bounds "
    131                   "[0, %d, %d]", cached_index_, data_length_ - 2);
    132   }
    133 #endif
    134   // Search for the containing interval
    135   if (x <= x_data_[cached_index_]) {
    136     if (cached_index_ <= 0) {
    137       cached_index_ = 0;
    138       return y_data_[0];
    139     }
    140     if (x >= x_data_[cached_index_ - 1]) {
    141       cached_index_--;  // Fast descending
    142     } else {
    143       if (x <= x_data_[0]) {
    144         cached_index_ = 0;
    145         return y_data_[0];
    146       }
    147       cached_index_ = SearchIndex(x_data_, x, 0, cached_index_);
    148     }
    149   } else {
    150     if (cached_index_ >= last_element_index_) {
    151       cached_index_ = last_element_index_;
    152       return y_data_[last_element_index_];
    153     }
    154     if (x > x_data_[cached_index_ + 1]) {
    155       if (cached_index_ + 2 > last_element_index_) {
    156         cached_index_ = last_element_index_ - 1;
    157         return y_data_[last_element_index_];
    158       }
    159       if (x <= x_data_[cached_index_ + 2]) {
    160         cached_index_++;  // Fast ascending
    161       } else {
    162         if (x >= x_data_[last_element_index_]) {
    163           cached_index_ = last_element_index_ - 1;
    164           return y_data_[last_element_index_];
    165         }
    166         cached_index_ = SearchIndex(
    167             x_data_, x, cached_index_, last_element_index_);
    168       }
    169     }
    170   }
    171   // Compute interpolated value by calling the corresponding function of the
    172   // derived class.
    173   return static_cast<Algorithm*>(this)->MethodSpecificInterpolation(x);
    174 }
    175 
    176 }  // namespace sigmod
    177 
    178 }  // namespace le_fx
    179 
    180 #endif  // LE_FX_ENGINE_DSP_CORE_INTERPOLATOR_BASE_INL_H_
    181