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_COMMON_CORE_MATH_H_
186cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#define LE_FX_ENGINE_COMMON_CORE_MATH_H_
196cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
206cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#include <math.h>
216cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#include <algorithm>
226cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviusing ::std::min;
236cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviusing ::std::max;
246cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviusing ::std::fill;
256cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviusing ::std::fill_n;using ::std::lower_bound;
266cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#include <cmath>
276cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#include <math.h>
286cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi//using ::std::fpclassify;
296cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
306cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#include "common/core/os.h"
316cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#include "common/core/types.h"
326cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
336cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivinamespace le_fx {
346cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivinamespace math {
356cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
366cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// A fast approximation to log2(.)
376cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviinline float fast_log2(float val) {
386cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  int* const exp_ptr = reinterpret_cast <int *> (&val);
396cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  int x = *exp_ptr;
406cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  const int log_2 = ((x >> 23) & 255) - 128;
416cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  x &= ~(255 << 23);
426cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  x += 127 << 23;
436cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  *exp_ptr = x;
446cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  val = ((-1.0f / 3) * val + 2) * val - 2.0f / 3;
456cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  return static_cast<float>(val + log_2);
466cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}
476cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
486cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// A fast approximation to log(.)
496cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviinline float fast_log(float val) {
506cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  return fast_log2(val) *
516cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      0.693147180559945286226763982995180413126945495605468750f;
526cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}
536cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
546cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// An approximation of the exp(.) function using a 5-th order Taylor expansion.
556cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// It's pretty accurate between +-0.1 and accurate to 10e-3 between +-1
566cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T>
576cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviinline T ExpApproximationViaTaylorExpansionOrder5(T x) {
586cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  const T x2 = x * x;
596cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  const T x3 = x2 * x;
606cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  const T x4 = x2 * x2;
616cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  const T x5 = x3 * x2;
626cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  return 1.0f + x + 0.5f * x2 +
636cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      0.16666666666666665741480812812369549646973609924316406250f * x3 +
646cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      0.0416666666666666643537020320309238741174340248107910156250f * x4 +
656cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      0.008333333333333333217685101601546193705871701240539550781250f * x5;
666cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}
676cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
686cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}  // namespace math
696cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}  // namespace le_fx
706cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
716cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// Math functions missing in Android NDK:
726cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#if defined(LE_FX_OS_ANDROID)
736cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
746cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivinamespace std {
756cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
766cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi//
776cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// Round to the nearest integer: We need this implementation
786cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// since std::round is missing on android.
796cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi//
806cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T>
816cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviinline T round(const T &x) {
826cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  return static_cast<T>(std::floor(static_cast<double>(x) + 0.5));
836cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}
846cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
856cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}  // namespace std
866cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
876cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#endif  // LE_FX_OS_ANDROID
886cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
896cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#endif  // LE_FX_ENGINE_COMMON_CORE_MATH_H_
90