Eigen  5.0.1
 
Loading...
Searching...
No Matches
MathFunctions.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2007 Julien Pommier
5// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
6//
7// This Source Code Form is subject to the terms of the Mozilla
8// Public License v. 2.0. If a copy of the MPL was not distributed
9// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10// SPDX-License-Identifier: MPL-2.0
11
12/* The sin and cos functions of this file come from
13 * Julien Pommier's sse math library: http://gruntthepeon.free.fr/ssemath/
14 */
15
16#ifndef EIGEN_MATH_FUNCTIONS_SSE_H
17#define EIGEN_MATH_FUNCTIONS_SSE_H
18
19// IWYU pragma: private
20#include "../../InternalHeaderCheck.h"
21
22namespace Eigen {
23
24namespace internal {
25
26EIGEN_INSTANTIATE_GENERIC_MATH_FUNCS_FLOAT(Packet4f)
27EIGEN_INSTANTIATE_GENERIC_MATH_FUNCS_DOUBLE(Packet2d)
28
29// Notice that for newer processors, it is counterproductive to use Newton
30// iteration for square root. In particular, Skylake and Zen2 processors
31// have approximately doubled throughput of the _mm_sqrt_ps instruction
32// compared to their predecessors.
33template <>
34EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet4f psqrt<Packet4f>(const Packet4f& x) {
35 return _mm_sqrt_ps(x);
36}
37template <>
38EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet2d psqrt<Packet2d>(const Packet2d& x) {
39 return _mm_sqrt_pd(x);
40}
41template <>
42EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet16b psqrt<Packet16b>(const Packet16b& x) {
43 return x;
44}
45
46#if EIGEN_FAST_MATH
47// Even on Skylake, using Newton iteration is a win for reciprocal square root.
48template <>
49EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet4f prsqrt<Packet4f>(const Packet4f& x) {
50 return generic_rsqrt_newton_step<Packet4f, /*Steps=*/1>::run(x, _mm_rsqrt_ps(x));
51}
52
53#ifdef EIGEN_VECTORIZE_FMA
54// Trying to speed up reciprocal using Newton-Raphson is counterproductive
55// unless FMA is available. Without FMA pdiv(pset1<Packet>(Scalar(1),a)) is
56// 30% faster.
57template <>
58EIGEN_STRONG_INLINE Packet4f preciprocal<Packet4f>(const Packet4f& x) {
59#ifdef EIGEN_VECTORIZE_AVX
60 // generic_reciprocal_newton_step, with its NaN-or-zero test as a single compare: r == 0 or unordered.
61 const Packet4f one = pset1<Packet4f>(1.0f);
62 const Packet4f r0 = _mm_rcp_ps(x);
63 const Packet4f refined = pmadd(r0, pnmadd(x, r0, one), r0);
64 const Packet4f redo = _mm_cmp_ps(refined, _mm_setzero_ps(), _CMP_EQ_UQ);
65 return predux_any(redo) ? pselect(redo, pdiv(one, x), refined) : refined;
66#else
67 return generic_reciprocal_newton_step<Packet4f, /*Steps=*/1>::run(x, _mm_rcp_ps(x));
68#endif
69}
70#endif
71
72#endif
73
74} // end namespace internal
75
76namespace numext {
77
78template <>
79EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float sqrt(const float& x) {
80 return internal::pfirst(internal::Packet4f(_mm_sqrt_ss(_mm_set_ss(x))));
81}
82
83template <>
84EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double sqrt(const double& x) {
85#if EIGEN_COMP_GNUC_STRICT
86 // This works around a GCC bug generating poor code for _mm_sqrt_pd
87 // See https://gitlab.com/libeigen/eigen/commit/8dca9f97e38970
88 return internal::pfirst(internal::Packet2d(__builtin_ia32_sqrtsd(_mm_set_sd(x))));
89#else
90 return internal::pfirst(internal::Packet2d(_mm_sqrt_pd(_mm_set_sd(x))));
91#endif
92}
93
94} // namespace numext
95
96} // end namespace Eigen
97
98#endif // EIGEN_MATH_FUNCTIONS_SSE_H