12b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// This file is part of Eigen, a lightweight C++ template library
22b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// for linear algebra.
32b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang//
42b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// This Source Code Form is subject to the terms of the Mozilla
52b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// Public License v. 2.0. If a copy of the MPL was not distributed
62b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
72b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
82b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang/* The sin, cos, exp, and log functions of this file come from
92b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * Julien Pommier's sse math library: http://gruntthepeon.free.fr/ssemath/
102b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang */
112b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
122b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#ifndef EIGEN_MATH_FUNCTIONS_NEON_H
132b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#define EIGEN_MATH_FUNCTIONS_NEON_H
142b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
152b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangnamespace Eigen {
162b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
172b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangnamespace internal {
182b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
192b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangtemplate<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
202b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao WangPacket4f pexp<Packet4f>(const Packet4f& _x)
212b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang{
222b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Packet4f x = _x;
232b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Packet4f tmp, fx;
242b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
252b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  _EIGEN_DECLARE_CONST_Packet4f(1 , 1.0f);
262b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  _EIGEN_DECLARE_CONST_Packet4f(half, 0.5f);
272b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  _EIGEN_DECLARE_CONST_Packet4i(0x7f, 0x7f);
282b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  _EIGEN_DECLARE_CONST_Packet4f(exp_hi,  88.3762626647950f);
292b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  _EIGEN_DECLARE_CONST_Packet4f(exp_lo, -88.3762626647949f);
302b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  _EIGEN_DECLARE_CONST_Packet4f(cephes_LOG2EF, 1.44269504088896341f);
312b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  _EIGEN_DECLARE_CONST_Packet4f(cephes_exp_C1, 0.693359375f);
322b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  _EIGEN_DECLARE_CONST_Packet4f(cephes_exp_C2, -2.12194440e-4f);
332b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  _EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p0, 1.9875691500E-4f);
342b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  _EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p1, 1.3981999507E-3f);
352b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  _EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p2, 8.3334519073E-3f);
362b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  _EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p3, 4.1665795894E-2f);
372b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  _EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p4, 1.6666665459E-1f);
382b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  _EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p5, 5.0000001201E-1f);
392b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
402b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  x = vminq_f32(x, p4f_exp_hi);
412b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  x = vmaxq_f32(x, p4f_exp_lo);
422b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
432b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  /* express exp(x) as exp(g + n*log(2)) */
442b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  fx = vmlaq_f32(p4f_half, x, p4f_cephes_LOG2EF);
452b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
462b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  /* perform a floorf */
472b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  tmp = vcvtq_f32_s32(vcvtq_s32_f32(fx));
482b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
492b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  /* if greater, substract 1 */
502b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Packet4ui mask = vcgtq_f32(tmp, fx);
512b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  mask = vandq_u32(mask, vreinterpretq_u32_f32(p4f_1));
522b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
532b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  fx = vsubq_f32(tmp, vreinterpretq_f32_u32(mask));
542b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
552b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  tmp = vmulq_f32(fx, p4f_cephes_exp_C1);
562b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Packet4f z = vmulq_f32(fx, p4f_cephes_exp_C2);
572b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  x = vsubq_f32(x, tmp);
582b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  x = vsubq_f32(x, z);
592b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
602b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Packet4f y = vmulq_f32(p4f_cephes_exp_p0, x);
612b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  z = vmulq_f32(x, x);
622b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  y = vaddq_f32(y, p4f_cephes_exp_p1);
632b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  y = vmulq_f32(y, x);
642b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  y = vaddq_f32(y, p4f_cephes_exp_p2);
652b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  y = vmulq_f32(y, x);
662b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  y = vaddq_f32(y, p4f_cephes_exp_p3);
672b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  y = vmulq_f32(y, x);
682b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  y = vaddq_f32(y, p4f_cephes_exp_p4);
692b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  y = vmulq_f32(y, x);
702b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  y = vaddq_f32(y, p4f_cephes_exp_p5);
712b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
722b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  y = vmulq_f32(y, z);
732b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  y = vaddq_f32(y, x);
742b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  y = vaddq_f32(y, p4f_1);
752b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
762b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  /* build 2^n */
772b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  int32x4_t mm;
782b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  mm = vcvtq_s32_f32(fx);
792b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  mm = vaddq_s32(mm, p4i_0x7f);
802b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  mm = vshlq_n_s32(mm, 23);
812b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Packet4f pow2n = vreinterpretq_f32_s32(mm);
822b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
832b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  y = vmulq_f32(y, pow2n);
842b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  return y;
852b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang}
862b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
872b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang} // end namespace internal
882b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
892b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang} // end namespace Eigen
902b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
912b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#endif // EIGEN_MATH_FUNCTIONS_NEON_H
92