Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Crayon鑫
Paddle
提交
b9aeb681
P
Paddle
项目概览
Crayon鑫
/
Paddle
与 Fork 源项目一致
Fork自
PaddlePaddle / Paddle
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Paddle
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
b9aeb681
编写于
7月 03, 2020
作者:
Z
Zhang Ting
提交者:
GitHub
7月 03, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
remove EIGEN_MAX_CPP_VER=11, test=develop (#25309)
上级
8de89e67
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
1946 addition
and
7 deletion
+1946
-7
cmake/configure.cmake
cmake/configure.cmake
+0
-4
cmake/external/eigen.cmake
cmake/external/eigen.cmake
+8
-3
patches/eigen/MathFunctions.h
patches/eigen/MathFunctions.h
+1938
-0
未找到文件。
cmake/configure.cmake
浏览文件 @
b9aeb681
...
...
@@ -70,10 +70,6 @@ endif()
if
(
WITH_GPU
)
add_definitions
(
-DPADDLE_WITH_CUDA
)
add_definitions
(
-DEIGEN_USE_GPU
)
# The compiler fully support const expressions since c++14,
# but Eigen use some const expressions such as std::max and std::min, which are not supported in c++11
# use following definition to set EIGEN_HAS_CONSTEXPR=0 to avoid compilation error in c++11
add_definitions
(
-DEIGEN_MAX_CPP_VER=11
)
FIND_PACKAGE
(
CUDA REQUIRED
)
...
...
cmake/external/eigen.cmake
浏览文件 @
b9aeb681
...
...
@@ -49,9 +49,14 @@ elseif(LINUX)
# refer to: https://gitlab.com/libeigen/eigen/-/blob/4da2c6b1974827b1999bab652a3d4703e1992d26/Eigen/src/Core/arch/SSE/PacketMath.h#L33-60
# add -fabi-version=4 could avoid above error, but will cause "double free corruption" when compile with gcc8
# so use following patch to solve compilation error with different version of gcc.
file
(
TO_NATIVE_PATH
${
PADDLE_SOURCE_DIR
}
/patches/eigen/Geometry_SSE.h native_src
)
file
(
TO_NATIVE_PATH
${
EIGEN_SOURCE_DIR
}
/Eigen/src/Geometry/arch/Geometry_SSE.h native_dst
)
set
(
EIGEN_PATCH_COMMAND cp
${
native_src
}
${
native_dst
}
)
file
(
TO_NATIVE_PATH
${
PADDLE_SOURCE_DIR
}
/patches/eigen/Geometry_SSE.h native_src1
)
file
(
TO_NATIVE_PATH
${
EIGEN_SOURCE_DIR
}
/Eigen/src/Geometry/arch/Geometry_SSE.h native_dst1
)
# The compiler fully support const expressions since c++14,
# but Eigen use some const expressions such as std::max and std::min, which are not supported in c++11
# add patch to avoid compilation error in c++11
file
(
TO_NATIVE_PATH
${
PADDLE_SOURCE_DIR
}
/patches/eigen/MathFunctions.h native_src2
)
file
(
TO_NATIVE_PATH
${
EIGEN_SOURCE_DIR
}
/Eigen/src/Core/MathFunctions.h native_dst2
)
set
(
EIGEN_PATCH_COMMAND cp
${
native_src1
}
${
native_dst1
}
&& cp
${
native_src2
}
${
native_dst2
}
)
endif
()
set
(
EIGEN_INCLUDE_DIR
${
EIGEN_SOURCE_DIR
}
)
...
...
patches/eigen/MathFunctions.h
0 → 100644
浏览文件 @
b9aeb681
// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_MATHFUNCTIONS_H
#define EIGEN_MATHFUNCTIONS_H
// source: http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html
// TODO this should better be moved to NumTraits
#define EIGEN_PI \
3.141592653589793238462643383279502884197169399375105820974944592307816406L
namespace
Eigen
{
// On WINCE, std::abs is defined for int only, so let's defined our own
// overloads:
// This issue has been confirmed with MSVC 2008 only, but the issue might exist
// for more recent versions too.
#if EIGEN_OS_WINCE && EIGEN_COMP_MSVC && EIGEN_COMP_MSVC <= 1500
long
abs
(
long
x
)
{
return
(
labs
(
x
));
}
double
abs
(
double
x
)
{
return
(
fabs
(
x
));
}
float
abs
(
float
x
)
{
return
(
fabsf
(
x
));
}
long
double
abs
(
long
double
x
)
{
return
(
fabsl
(
x
));
}
#endif
namespace
internal
{
/** \internal \class global_math_functions_filtering_base
*
* What it does:
* Defines a typedef 'type' as follows:
* - if type T has a member typedef
* Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl, then
* global_math_functions_filtering_base<T>::type is a typedef for it.
* - otherwise, global_math_functions_filtering_base<T>::type is a typedef for
* T.
*
* How it's used:
* To allow to defined the global math functions (like sin...) in certain
* cases, like the Array expressions.
* When you do sin(array1+array2), the object array1+array2 has a complicated
* expression type, all what you want to know
* is that it inherits ArrayBase. So we implement a partial specialization of
* sin_impl for ArrayBase<Derived>.
* So we must make sure to use sin_impl<ArrayBase<Derived> > and not
* sin_impl<Derived>, otherwise our partial specialization
* won't be used. How does sin know that? That's exactly what
* global_math_functions_filtering_base tells it.
*
* How it's implemented:
* SFINAE in the style of enable_if. Highly susceptible of breaking compilers.
* With GCC, it sure does work, but if you replace
* the typename dummy by an integer template parameter, it doesn't work
* anymore!
*/
template
<
typename
T
,
typename
dummy
=
void
>
struct
global_math_functions_filtering_base
{
typedef
T
type
;
};
template
<
typename
T
>
struct
always_void
{
typedef
void
type
;
};
template
<
typename
T
>
struct
global_math_functions_filtering_base
<
T
,
typename
always_void
<
typename
T
::
Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl
>::
type
>
{
typedef
typename
T
::
Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl
type
;
};
#define EIGEN_MATHFUNC_IMPL(func, scalar) \
Eigen::internal::func##_impl< \
typename Eigen::internal::global_math_functions_filtering_base< \
scalar>::type>
#define EIGEN_MATHFUNC_RETVAL(func, scalar) \
typename Eigen::internal::func##_retval< \
typename Eigen::internal::global_math_functions_filtering_base< \
scalar>::type>::type
/****************************************************************************
* Implementation of real *
****************************************************************************/
template
<
typename
Scalar
,
bool
IsComplex
=
NumTraits
<
Scalar
>
::
IsComplex
>
struct
real_default_impl
{
typedef
typename
NumTraits
<
Scalar
>::
Real
RealScalar
;
EIGEN_DEVICE_FUNC
static
inline
RealScalar
run
(
const
Scalar
&
x
)
{
return
x
;
}
};
template
<
typename
Scalar
>
struct
real_default_impl
<
Scalar
,
true
>
{
typedef
typename
NumTraits
<
Scalar
>::
Real
RealScalar
;
EIGEN_DEVICE_FUNC
static
inline
RealScalar
run
(
const
Scalar
&
x
)
{
using
std
::
real
;
return
real
(
x
);
}
};
template
<
typename
Scalar
>
struct
real_impl
:
real_default_impl
<
Scalar
>
{};
#if defined(EIGEN_GPU_COMPILE_PHASE)
template
<
typename
T
>
struct
real_impl
<
std
::
complex
<
T
>>
{
typedef
T
RealScalar
;
EIGEN_DEVICE_FUNC
static
inline
T
run
(
const
std
::
complex
<
T
>&
x
)
{
return
x
.
real
();
}
};
#endif
template
<
typename
Scalar
>
struct
real_retval
{
typedef
typename
NumTraits
<
Scalar
>::
Real
type
;
};
/****************************************************************************
* Implementation of imag *
****************************************************************************/
template
<
typename
Scalar
,
bool
IsComplex
=
NumTraits
<
Scalar
>
::
IsComplex
>
struct
imag_default_impl
{
typedef
typename
NumTraits
<
Scalar
>::
Real
RealScalar
;
EIGEN_DEVICE_FUNC
static
inline
RealScalar
run
(
const
Scalar
&
)
{
return
RealScalar
(
0
);
}
};
template
<
typename
Scalar
>
struct
imag_default_impl
<
Scalar
,
true
>
{
typedef
typename
NumTraits
<
Scalar
>::
Real
RealScalar
;
EIGEN_DEVICE_FUNC
static
inline
RealScalar
run
(
const
Scalar
&
x
)
{
using
std
::
imag
;
return
imag
(
x
);
}
};
template
<
typename
Scalar
>
struct
imag_impl
:
imag_default_impl
<
Scalar
>
{};
#if defined(EIGEN_GPU_COMPILE_PHASE)
template
<
typename
T
>
struct
imag_impl
<
std
::
complex
<
T
>>
{
typedef
T
RealScalar
;
EIGEN_DEVICE_FUNC
static
inline
T
run
(
const
std
::
complex
<
T
>&
x
)
{
return
x
.
imag
();
}
};
#endif
template
<
typename
Scalar
>
struct
imag_retval
{
typedef
typename
NumTraits
<
Scalar
>::
Real
type
;
};
/****************************************************************************
* Implementation of real_ref *
****************************************************************************/
template
<
typename
Scalar
>
struct
real_ref_impl
{
typedef
typename
NumTraits
<
Scalar
>::
Real
RealScalar
;
EIGEN_DEVICE_FUNC
static
inline
RealScalar
&
run
(
Scalar
&
x
)
{
return
reinterpret_cast
<
RealScalar
*>
(
&
x
)[
0
];
}
EIGEN_DEVICE_FUNC
static
inline
const
RealScalar
&
run
(
const
Scalar
&
x
)
{
return
reinterpret_cast
<
const
RealScalar
*>
(
&
x
)[
0
];
}
};
template
<
typename
Scalar
>
struct
real_ref_retval
{
typedef
typename
NumTraits
<
Scalar
>::
Real
&
type
;
};
/****************************************************************************
* Implementation of imag_ref *
****************************************************************************/
template
<
typename
Scalar
,
bool
IsComplex
>
struct
imag_ref_default_impl
{
typedef
typename
NumTraits
<
Scalar
>::
Real
RealScalar
;
EIGEN_DEVICE_FUNC
static
inline
RealScalar
&
run
(
Scalar
&
x
)
{
return
reinterpret_cast
<
RealScalar
*>
(
&
x
)[
1
];
}
EIGEN_DEVICE_FUNC
static
inline
const
RealScalar
&
run
(
const
Scalar
&
x
)
{
return
reinterpret_cast
<
RealScalar
*>
(
&
x
)[
1
];
}
};
template
<
typename
Scalar
>
struct
imag_ref_default_impl
<
Scalar
,
false
>
{
EIGEN_DEVICE_FUNC
static
inline
Scalar
run
(
Scalar
&
)
{
return
Scalar
(
0
);
}
EIGEN_DEVICE_FUNC
static
inline
const
Scalar
run
(
const
Scalar
&
)
{
return
Scalar
(
0
);
}
};
template
<
typename
Scalar
>
struct
imag_ref_impl
:
imag_ref_default_impl
<
Scalar
,
NumTraits
<
Scalar
>::
IsComplex
>
{};
template
<
typename
Scalar
>
struct
imag_ref_retval
{
typedef
typename
NumTraits
<
Scalar
>::
Real
&
type
;
};
/****************************************************************************
* Implementation of conj *
****************************************************************************/
template
<
typename
Scalar
,
bool
IsComplex
=
NumTraits
<
Scalar
>
::
IsComplex
>
struct
conj_default_impl
{
EIGEN_DEVICE_FUNC
static
inline
Scalar
run
(
const
Scalar
&
x
)
{
return
x
;
}
};
template
<
typename
Scalar
>
struct
conj_default_impl
<
Scalar
,
true
>
{
EIGEN_DEVICE_FUNC
static
inline
Scalar
run
(
const
Scalar
&
x
)
{
using
std
::
conj
;
return
conj
(
x
);
}
};
template
<
typename
Scalar
>
struct
conj_impl
:
conj_default_impl
<
Scalar
>
{};
#if defined(EIGEN_GPU_COMPILE_PHASE)
template
<
typename
T
>
struct
conj_impl
<
std
::
complex
<
T
>>
{
EIGEN_DEVICE_FUNC
static
inline
std
::
complex
<
T
>
run
(
const
std
::
complex
<
T
>&
x
)
{
return
std
::
complex
<
T
>
(
x
.
real
(),
-
x
.
imag
());
}
};
#endif
template
<
typename
Scalar
>
struct
conj_retval
{
typedef
Scalar
type
;
};
/****************************************************************************
* Implementation of abs2 *
****************************************************************************/
template
<
typename
Scalar
,
bool
IsComplex
>
struct
abs2_impl_default
{
typedef
typename
NumTraits
<
Scalar
>::
Real
RealScalar
;
EIGEN_DEVICE_FUNC
static
inline
RealScalar
run
(
const
Scalar
&
x
)
{
return
x
*
x
;
}
};
template
<
typename
Scalar
>
struct
abs2_impl_default
<
Scalar
,
true
>
// IsComplex
{
typedef
typename
NumTraits
<
Scalar
>::
Real
RealScalar
;
EIGEN_DEVICE_FUNC
static
inline
RealScalar
run
(
const
Scalar
&
x
)
{
return
x
.
real
()
*
x
.
real
()
+
x
.
imag
()
*
x
.
imag
();
}
};
template
<
typename
Scalar
>
struct
abs2_impl
{
typedef
typename
NumTraits
<
Scalar
>::
Real
RealScalar
;
EIGEN_DEVICE_FUNC
static
inline
RealScalar
run
(
const
Scalar
&
x
)
{
return
abs2_impl_default
<
Scalar
,
NumTraits
<
Scalar
>::
IsComplex
>::
run
(
x
);
}
};
template
<
typename
Scalar
>
struct
abs2_retval
{
typedef
typename
NumTraits
<
Scalar
>::
Real
type
;
};
/****************************************************************************
* Implementation of norm1 *
****************************************************************************/
template
<
typename
Scalar
,
bool
IsComplex
>
struct
norm1_default_impl
;
template
<
typename
Scalar
>
struct
norm1_default_impl
<
Scalar
,
true
>
{
typedef
typename
NumTraits
<
Scalar
>::
Real
RealScalar
;
EIGEN_DEVICE_FUNC
static
inline
RealScalar
run
(
const
Scalar
&
x
)
{
EIGEN_USING_STD_MATH
(
abs
);
return
abs
(
x
.
real
())
+
abs
(
x
.
imag
());
}
};
template
<
typename
Scalar
>
struct
norm1_default_impl
<
Scalar
,
false
>
{
EIGEN_DEVICE_FUNC
static
inline
Scalar
run
(
const
Scalar
&
x
)
{
EIGEN_USING_STD_MATH
(
abs
);
return
abs
(
x
);
}
};
template
<
typename
Scalar
>
struct
norm1_impl
:
norm1_default_impl
<
Scalar
,
NumTraits
<
Scalar
>::
IsComplex
>
{};
template
<
typename
Scalar
>
struct
norm1_retval
{
typedef
typename
NumTraits
<
Scalar
>::
Real
type
;
};
/****************************************************************************
* Implementation of hypot *
****************************************************************************/
template
<
typename
Scalar
>
struct
hypot_impl
;
template
<
typename
Scalar
>
struct
hypot_retval
{
typedef
typename
NumTraits
<
Scalar
>::
Real
type
;
};
/****************************************************************************
* Implementation of cast *
****************************************************************************/
template
<
typename
OldType
,
typename
NewType
>
struct
cast_impl
{
EIGEN_DEVICE_FUNC
static
inline
NewType
run
(
const
OldType
&
x
)
{
return
static_cast
<
NewType
>
(
x
);
}
};
// here, for once, we're plainly returning NewType: we don't want cast to do
// weird things.
template
<
typename
OldType
,
typename
NewType
>
EIGEN_DEVICE_FUNC
inline
NewType
cast
(
const
OldType
&
x
)
{
return
cast_impl
<
OldType
,
NewType
>::
run
(
x
);
}
/****************************************************************************
* Implementation of round *
****************************************************************************/
#if EIGEN_HAS_CXX11_MATH
template
<
typename
Scalar
>
struct
round_impl
{
EIGEN_DEVICE_FUNC
static
inline
Scalar
run
(
const
Scalar
&
x
)
{
EIGEN_STATIC_ASSERT
((
!
NumTraits
<
Scalar
>::
IsComplex
),
NUMERIC_TYPE_MUST_BE_REAL
)
EIGEN_USING_STD_MATH
(
round
);
return
round
(
x
);
}
};
#else
template
<
typename
Scalar
>
struct
round_impl
{
EIGEN_DEVICE_FUNC
static
inline
Scalar
run
(
const
Scalar
&
x
)
{
EIGEN_STATIC_ASSERT
((
!
NumTraits
<
Scalar
>::
IsComplex
),
NUMERIC_TYPE_MUST_BE_REAL
)
EIGEN_USING_STD_MATH
(
floor
);
EIGEN_USING_STD_MATH
(
ceil
);
return
(
x
>
Scalar
(
0
))
?
floor
(
x
+
Scalar
(
0.5
))
:
ceil
(
x
-
Scalar
(
0.5
));
}
};
#endif
template
<
typename
Scalar
>
struct
round_retval
{
typedef
Scalar
type
;
};
/****************************************************************************
* Implementation of rint *
****************************************************************************/
template
<
typename
Scalar
>
struct
rint_impl
{
EIGEN_DEVICE_FUNC
static
inline
Scalar
run
(
const
Scalar
&
x
)
{
EIGEN_STATIC_ASSERT
((
!
NumTraits
<
Scalar
>::
IsComplex
),
NUMERIC_TYPE_MUST_BE_REAL
)
#if EIGEN_HAS_CXX11_MATH
EIGEN_USING_STD_MATH
(
rint
);
#endif
return
rint
(
x
);
}
};
#if !EIGEN_HAS_CXX11_MATH
template
<
>
struct
rint_impl
<
double
>
{
EIGEN_DEVICE_FUNC
static
inline
double
run
(
const
double
&
x
)
{
return
::
rint
(
x
);
}
};
template
<
>
struct
rint_impl
<
float
>
{
EIGEN_DEVICE_FUNC
static
inline
float
run
(
const
float
&
x
)
{
return
::
rintf
(
x
);
}
};
#endif
template
<
typename
Scalar
>
struct
rint_retval
{
typedef
Scalar
type
;
};
/****************************************************************************
* Implementation of arg *
****************************************************************************/
#if EIGEN_HAS_CXX11_MATH
template
<
typename
Scalar
>
struct
arg_impl
{
EIGEN_DEVICE_FUNC
static
inline
Scalar
run
(
const
Scalar
&
x
)
{
#if defined(EIGEN_HIP_DEVICE_COMPILE)
// HIP does not seem to have a native device side implementation for the
// math routine "arg"
using
std
::
arg
;
#else
EIGEN_USING_STD_MATH
(
arg
);
#endif
return
arg
(
x
);
}
};
#else
template
<
typename
Scalar
,
bool
IsComplex
=
NumTraits
<
Scalar
>
::
IsComplex
>
struct
arg_default_impl
{
typedef
typename
NumTraits
<
Scalar
>::
Real
RealScalar
;
EIGEN_DEVICE_FUNC
static
inline
RealScalar
run
(
const
Scalar
&
x
)
{
return
(
x
<
Scalar
(
0
))
?
Scalar
(
EIGEN_PI
)
:
Scalar
(
0
);
}
};
template
<
typename
Scalar
>
struct
arg_default_impl
<
Scalar
,
true
>
{
typedef
typename
NumTraits
<
Scalar
>::
Real
RealScalar
;
EIGEN_DEVICE_FUNC
static
inline
RealScalar
run
(
const
Scalar
&
x
)
{
EIGEN_USING_STD_MATH
(
arg
);
return
arg
(
x
);
}
};
template
<
typename
Scalar
>
struct
arg_impl
:
arg_default_impl
<
Scalar
>
{};
#endif
template
<
typename
Scalar
>
struct
arg_retval
{
typedef
typename
NumTraits
<
Scalar
>::
Real
type
;
};
/****************************************************************************
* Implementation of expm1 *
****************************************************************************/
// This implementation is based on GSL Math's expm1.
namespace
std_fallback
{
// fallback expm1 implementation in case there is no expm1(Scalar) function in
// namespace of Scalar,
// or that there is no suitable std::expm1 function available. Implementation
// attributed to Kahan. See: http://www.plunk.org/~hatch/rightway.php.
template
<
typename
Scalar
>
EIGEN_DEVICE_FUNC
inline
Scalar
expm1
(
const
Scalar
&
x
)
{
EIGEN_STATIC_ASSERT_NON_INTEGER
(
Scalar
)
typedef
typename
NumTraits
<
Scalar
>::
Real
RealScalar
;
EIGEN_USING_STD_MATH
(
exp
);
Scalar
u
=
exp
(
x
);
if
(
numext
::
equal_strict
(
u
,
Scalar
(
1
)))
{
return
x
;
}
Scalar
um1
=
u
-
RealScalar
(
1
);
if
(
numext
::
equal_strict
(
um1
,
Scalar
(
-
1
)))
{
return
RealScalar
(
-
1
);
}
EIGEN_USING_STD_MATH
(
log
);
Scalar
logu
=
log
(
u
);
return
numext
::
equal_strict
(
u
,
logu
)
?
u
:
(
u
-
RealScalar
(
1
))
*
x
/
logu
;
}
}
template
<
typename
Scalar
>
struct
expm1_impl
{
EIGEN_DEVICE_FUNC
static
inline
Scalar
run
(
const
Scalar
&
x
)
{
EIGEN_STATIC_ASSERT_NON_INTEGER
(
Scalar
)
#if EIGEN_HAS_CXX11_MATH
using
std
::
expm1
;
#else
using
std_fallback
::
expm1
;
#endif
return
expm1
(
x
);
}
};
// Specialization for complex types that are not supported by std::expm1.
template
<
typename
RealScalar
>
struct
expm1_impl
<
std
::
complex
<
RealScalar
>>
{
EIGEN_DEVICE_FUNC
static
inline
std
::
complex
<
RealScalar
>
run
(
const
std
::
complex
<
RealScalar
>&
x
)
{
EIGEN_STATIC_ASSERT_NON_INTEGER
(
RealScalar
)
RealScalar
xr
=
x
.
real
();
RealScalar
xi
=
x
.
imag
();
// expm1(z) = exp(z) - 1
// = exp(x + i * y) - 1
// = exp(x) * (cos(y) + i * sin(y)) - 1
// = exp(x) * cos(y) - 1 + i * exp(x) * sin(y)
// Imag(expm1(z)) = exp(x) * sin(y)
// Real(expm1(z)) = exp(x) * cos(y) - 1
// = exp(x) * cos(y) - 1.
// = expm1(x) + exp(x) * (cos(y) - 1)
// = expm1(x) + exp(x) * (2 * sin(y / 2) ** 2)
// TODO better use numext::expm1 and numext::sin (but that would require
// forward declarations or moving this specialization down).
RealScalar
erm1
=
expm1_impl
<
RealScalar
>::
run
(
xr
);
RealScalar
er
=
erm1
+
RealScalar
(
1.
);
EIGEN_USING_STD_MATH
(
sin
);
RealScalar
sin2
=
sin
(
xi
/
RealScalar
(
2.
));
sin2
=
sin2
*
sin2
;
RealScalar
s
=
sin
(
xi
);
RealScalar
real_part
=
erm1
-
RealScalar
(
2.
)
*
er
*
sin2
;
return
std
::
complex
<
RealScalar
>
(
real_part
,
er
*
s
);
}
};
template
<
typename
Scalar
>
struct
expm1_retval
{
typedef
Scalar
type
;
};
/****************************************************************************
* Implementation of log1p *
****************************************************************************/
namespace
std_fallback
{
// fallback log1p implementation in case there is no log1p(Scalar) function in
// namespace of Scalar,
// or that there is no suitable std::log1p function available
template
<
typename
Scalar
>
EIGEN_DEVICE_FUNC
inline
Scalar
log1p
(
const
Scalar
&
x
)
{
EIGEN_STATIC_ASSERT_NON_INTEGER
(
Scalar
)
typedef
typename
NumTraits
<
Scalar
>::
Real
RealScalar
;
EIGEN_USING_STD_MATH
(
log
);
Scalar
x1p
=
RealScalar
(
1
)
+
x
;
Scalar
log_1p
=
log
(
x1p
);
const
bool
is_small
=
numext
::
equal_strict
(
x1p
,
Scalar
(
1
));
const
bool
is_inf
=
numext
::
equal_strict
(
x1p
,
log_1p
);
return
(
is_small
||
is_inf
)
?
x
:
x
*
(
log_1p
/
(
x1p
-
RealScalar
(
1
)));
}
}
template
<
typename
Scalar
>
struct
log1p_impl
{
EIGEN_DEVICE_FUNC
static
inline
Scalar
run
(
const
Scalar
&
x
)
{
EIGEN_STATIC_ASSERT_NON_INTEGER
(
Scalar
)
#if EIGEN_HAS_CXX11_MATH
using
std
::
log1p
;
#else
using
std_fallback
::
log1p
;
#endif
return
log1p
(
x
);
}
};
// Specialization for complex types that are not supported by std::log1p.
template
<
typename
RealScalar
>
struct
log1p_impl
<
std
::
complex
<
RealScalar
>>
{
EIGEN_DEVICE_FUNC
static
inline
std
::
complex
<
RealScalar
>
run
(
const
std
::
complex
<
RealScalar
>&
x
)
{
EIGEN_STATIC_ASSERT_NON_INTEGER
(
RealScalar
)
return
std_fallback
::
log1p
(
x
);
}
};
template
<
typename
Scalar
>
struct
log1p_retval
{
typedef
Scalar
type
;
};
/****************************************************************************
* Implementation of pow *
****************************************************************************/
template
<
typename
ScalarX
,
typename
ScalarY
,
bool
IsInteger
=
NumTraits
<
ScalarX
>
::
IsInteger
&&
NumTraits
<
ScalarY
>::
IsInteger
>
struct
pow_impl
{
// typedef Scalar retval;
typedef
typename
ScalarBinaryOpTraits
<
ScalarX
,
ScalarY
,
internal
::
scalar_pow_op
<
ScalarX
,
ScalarY
>>::
ReturnType
result_type
;
static
EIGEN_DEVICE_FUNC
inline
result_type
run
(
const
ScalarX
&
x
,
const
ScalarY
&
y
)
{
EIGEN_USING_STD_MATH
(
pow
);
return
pow
(
x
,
y
);
}
};
template
<
typename
ScalarX
,
typename
ScalarY
>
struct
pow_impl
<
ScalarX
,
ScalarY
,
true
>
{
typedef
ScalarX
result_type
;
static
EIGEN_DEVICE_FUNC
inline
ScalarX
run
(
ScalarX
x
,
ScalarY
y
)
{
ScalarX
res
(
1
);
eigen_assert
(
!
NumTraits
<
ScalarY
>::
IsSigned
||
y
>=
0
);
if
(
y
&
1
)
res
*=
x
;
y
>>=
1
;
while
(
y
)
{
x
*=
x
;
if
(
y
&
1
)
res
*=
x
;
y
>>=
1
;
}
return
res
;
}
};
/****************************************************************************
* Implementation of random *
****************************************************************************/
template
<
typename
Scalar
,
bool
IsComplex
,
bool
IsInteger
>
struct
random_default_impl
{};
template
<
typename
Scalar
>
struct
random_impl
:
random_default_impl
<
Scalar
,
NumTraits
<
Scalar
>::
IsComplex
,
NumTraits
<
Scalar
>::
IsInteger
>
{};
template
<
typename
Scalar
>
struct
random_retval
{
typedef
Scalar
type
;
};
template
<
typename
Scalar
>
inline
EIGEN_MATHFUNC_RETVAL
(
random
,
Scalar
)
random
(
const
Scalar
&
x
,
const
Scalar
&
y
);
template
<
typename
Scalar
>
inline
EIGEN_MATHFUNC_RETVAL
(
random
,
Scalar
)
random
();
template
<
typename
Scalar
>
struct
random_default_impl
<
Scalar
,
false
,
false
>
{
static
inline
Scalar
run
(
const
Scalar
&
x
,
const
Scalar
&
y
)
{
return
x
+
(
y
-
x
)
*
Scalar
(
std
::
rand
())
/
Scalar
(
RAND_MAX
);
}
static
inline
Scalar
run
()
{
return
run
(
Scalar
(
NumTraits
<
Scalar
>::
IsSigned
?
-
1
:
0
),
Scalar
(
1
));
}
};
enum
{
meta_floor_log2_terminate
,
meta_floor_log2_move_up
,
meta_floor_log2_move_down
,
meta_floor_log2_bogus
};
template
<
unsigned
int
n
,
int
lower
,
int
upper
>
struct
meta_floor_log2_selector
{
enum
{
middle
=
(
lower
+
upper
)
/
2
,
value
=
(
upper
<=
lower
+
1
)
?
int
(
meta_floor_log2_terminate
)
:
(
n
<
(
1
<<
middle
))
?
int
(
meta_floor_log2_move_down
)
:
(
n
==
0
)
?
int
(
meta_floor_log2_bogus
)
:
int
(
meta_floor_log2_move_up
)
};
};
template
<
unsigned
int
n
,
int
lower
=
0
,
int
upper
=
sizeof
(
unsigned
int
)
*
CHAR_BIT
-
1
,
int
selector
=
meta_floor_log2_selector
<
n
,
lower
,
upper
>
::
value
>
struct
meta_floor_log2
{};
template
<
unsigned
int
n
,
int
lower
,
int
upper
>
struct
meta_floor_log2
<
n
,
lower
,
upper
,
meta_floor_log2_move_down
>
{
enum
{
value
=
meta_floor_log2
<
n
,
lower
,
meta_floor_log2_selector
<
n
,
lower
,
upper
>::
middle
>::
value
};
};
template
<
unsigned
int
n
,
int
lower
,
int
upper
>
struct
meta_floor_log2
<
n
,
lower
,
upper
,
meta_floor_log2_move_up
>
{
enum
{
value
=
meta_floor_log2
<
n
,
meta_floor_log2_selector
<
n
,
lower
,
upper
>::
middle
,
upper
>::
value
};
};
template
<
unsigned
int
n
,
int
lower
,
int
upper
>
struct
meta_floor_log2
<
n
,
lower
,
upper
,
meta_floor_log2_terminate
>
{
enum
{
value
=
(
n
>=
((
unsigned
int
)(
1
)
<<
(
lower
+
1
)))
?
lower
+
1
:
lower
};
};
template
<
unsigned
int
n
,
int
lower
,
int
upper
>
struct
meta_floor_log2
<
n
,
lower
,
upper
,
meta_floor_log2_bogus
>
{
// no value, error at compile time
};
template
<
typename
Scalar
>
struct
random_default_impl
<
Scalar
,
false
,
true
>
{
static
inline
Scalar
run
(
const
Scalar
&
x
,
const
Scalar
&
y
)
{
if
(
y
<=
x
)
return
x
;
// ScalarU is the unsigned counterpart of Scalar, possibly Scalar itself.
typedef
typename
make_unsigned
<
Scalar
>::
type
ScalarU
;
// ScalarX is the widest of ScalarU and unsigned int.
// We'll deal only with ScalarX and unsigned int below thus avoiding signed
// types and arithmetic and signed overflows (which are undefined behavior).
typedef
typename
conditional
<
(
ScalarU
(
-
1
)
>
unsigned
(
-
1
)),
ScalarU
,
unsigned
>::
type
ScalarX
;
// The following difference doesn't overflow, provided our integer types are
// two's
// complement and have the same number of padding bits in signed and
// unsigned variants.
// This is the case in most modern implementations of C++.
ScalarX
range
=
ScalarX
(
y
)
-
ScalarX
(
x
);
ScalarX
offset
=
0
;
ScalarX
divisor
=
1
;
ScalarX
multiplier
=
1
;
const
unsigned
rand_max
=
RAND_MAX
;
if
(
range
<=
rand_max
)
divisor
=
(
rand_max
+
1
)
/
(
range
+
1
);
else
multiplier
=
1
+
range
/
(
rand_max
+
1
);
// Rejection sampling.
do
{
offset
=
(
unsigned
(
std
::
rand
())
*
multiplier
)
/
divisor
;
}
while
(
offset
>
range
);
return
Scalar
(
ScalarX
(
x
)
+
offset
);
}
static
inline
Scalar
run
()
{
#ifdef EIGEN_MAKING_DOCS
return
run
(
Scalar
(
NumTraits
<
Scalar
>::
IsSigned
?
-
10
:
0
),
Scalar
(
10
));
#else
enum
{
rand_bits
=
meta_floor_log2
<
(
unsigned
int
)(
RAND_MAX
)
+
1
>::
value
,
scalar_bits
=
sizeof
(
Scalar
)
*
CHAR_BIT
,
shift
=
EIGEN_PLAIN_ENUM_MAX
(
0
,
int
(
rand_bits
)
-
int
(
scalar_bits
)),
offset
=
NumTraits
<
Scalar
>::
IsSigned
?
(
1
<<
(
EIGEN_PLAIN_ENUM_MIN
(
rand_bits
,
scalar_bits
)
-
1
))
:
0
};
return
Scalar
((
std
::
rand
()
>>
shift
)
-
offset
);
#endif
}
};
template
<
typename
Scalar
>
struct
random_default_impl
<
Scalar
,
true
,
false
>
{
static
inline
Scalar
run
(
const
Scalar
&
x
,
const
Scalar
&
y
)
{
return
Scalar
(
random
(
x
.
real
(),
y
.
real
()),
random
(
x
.
imag
(),
y
.
imag
()));
}
static
inline
Scalar
run
()
{
typedef
typename
NumTraits
<
Scalar
>::
Real
RealScalar
;
return
Scalar
(
random
<
RealScalar
>
(),
random
<
RealScalar
>
());
}
};
template
<
typename
Scalar
>
inline
EIGEN_MATHFUNC_RETVAL
(
random
,
Scalar
)
random
(
const
Scalar
&
x
,
const
Scalar
&
y
)
{
return
EIGEN_MATHFUNC_IMPL
(
random
,
Scalar
)
::
run
(
x
,
y
);
}
template
<
typename
Scalar
>
inline
EIGEN_MATHFUNC_RETVAL
(
random
,
Scalar
)
random
()
{
return
EIGEN_MATHFUNC_IMPL
(
random
,
Scalar
)
::
run
();
}
// Implementation of is* functions
// std::is* do not work with fast-math and gcc, std::is* are available on MSVC
// 2013 and newer, as well as in clang.
#if (EIGEN_HAS_CXX11_MATH && \
!(EIGEN_COMP_GNUC_STRICT && __FINITE_MATH_ONLY__)) || \
(EIGEN_COMP_MSVC >= 1800) || (EIGEN_COMP_CLANG)
#define EIGEN_USE_STD_FPCLASSIFY 1
#else
#define EIGEN_USE_STD_FPCLASSIFY 0
#endif
template
<
typename
T
>
EIGEN_DEVICE_FUNC
typename
internal
::
enable_if
<
internal
::
is_integral
<
T
>::
value
,
bool
>::
type
isnan_impl
(
const
T
&
)
{
return
false
;
}
template
<
typename
T
>
EIGEN_DEVICE_FUNC
typename
internal
::
enable_if
<
internal
::
is_integral
<
T
>::
value
,
bool
>::
type
isinf_impl
(
const
T
&
)
{
return
false
;
}
template
<
typename
T
>
EIGEN_DEVICE_FUNC
typename
internal
::
enable_if
<
internal
::
is_integral
<
T
>::
value
,
bool
>::
type
isfinite_impl
(
const
T
&
)
{
return
true
;
}
template
<
typename
T
>
EIGEN_DEVICE_FUNC
typename
internal
::
enable_if
<
(
!
internal
::
is_integral
<
T
>::
value
)
&&
(
!
NumTraits
<
T
>::
IsComplex
),
bool
>::
type
isfinite_impl
(
const
T
&
x
)
{
#if defined(EIGEN_GPU_COMPILE_PHASE)
return
(
::
isfinite
)(
x
);
#elif EIGEN_USE_STD_FPCLASSIFY
using
std
::
isfinite
;
return
isfinite
EIGEN_NOT_A_MACRO
(
x
);
#else
return
x
<=
NumTraits
<
T
>::
highest
()
&&
x
>=
NumTraits
<
T
>::
lowest
();
#endif
}
template
<
typename
T
>
EIGEN_DEVICE_FUNC
typename
internal
::
enable_if
<
(
!
internal
::
is_integral
<
T
>::
value
)
&&
(
!
NumTraits
<
T
>::
IsComplex
),
bool
>::
type
isinf_impl
(
const
T
&
x
)
{
#if defined(EIGEN_GPU_COMPILE_PHASE)
return
(
::
isinf
)(
x
);
#elif EIGEN_USE_STD_FPCLASSIFY
using
std
::
isinf
;
return
isinf
EIGEN_NOT_A_MACRO
(
x
);
#else
return
x
>
NumTraits
<
T
>::
highest
()
||
x
<
NumTraits
<
T
>::
lowest
();
#endif
}
template
<
typename
T
>
EIGEN_DEVICE_FUNC
typename
internal
::
enable_if
<
(
!
internal
::
is_integral
<
T
>::
value
)
&&
(
!
NumTraits
<
T
>::
IsComplex
),
bool
>::
type
isnan_impl
(
const
T
&
x
)
{
#if defined(EIGEN_GPU_COMPILE_PHASE)
return
(
::
isnan
)(
x
);
#elif EIGEN_USE_STD_FPCLASSIFY
using
std
::
isnan
;
return
isnan
EIGEN_NOT_A_MACRO
(
x
);
#else
return
x
!=
x
;
#endif
}
#if (!EIGEN_USE_STD_FPCLASSIFY)
#if EIGEN_COMP_MSVC
template
<
typename
T
>
EIGEN_DEVICE_FUNC
bool
isinf_msvc_helper
(
T
x
)
{
return
_fpclass
(
x
)
==
_FPCLASS_NINF
||
_fpclass
(
x
)
==
_FPCLASS_PINF
;
}
// MSVC defines a _isnan builtin function, but for double only
EIGEN_DEVICE_FUNC
inline
bool
isnan_impl
(
const
long
double
&
x
)
{
return
_isnan
(
x
)
!=
0
;
}
EIGEN_DEVICE_FUNC
inline
bool
isnan_impl
(
const
double
&
x
)
{
return
_isnan
(
x
)
!=
0
;
}
EIGEN_DEVICE_FUNC
inline
bool
isnan_impl
(
const
float
&
x
)
{
return
_isnan
(
x
)
!=
0
;
}
EIGEN_DEVICE_FUNC
inline
bool
isinf_impl
(
const
long
double
&
x
)
{
return
isinf_msvc_helper
(
x
);
}
EIGEN_DEVICE_FUNC
inline
bool
isinf_impl
(
const
double
&
x
)
{
return
isinf_msvc_helper
(
x
);
}
EIGEN_DEVICE_FUNC
inline
bool
isinf_impl
(
const
float
&
x
)
{
return
isinf_msvc_helper
(
x
);
}
#elif (defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ && EIGEN_COMP_GNUC)
#if EIGEN_GNUC_AT_LEAST(5, 0)
#define EIGEN_TMP_NOOPT_ATTRIB \
EIGEN_DEVICE_FUNC inline __attribute__((optimize("no-finite-math-only")))
#else
// NOTE the inline qualifier and noinline attribute are both needed: the former
// is to avoid linking issue (duplicate symbol),
// while the second prevent too aggressive optimizations in fast-math mode:
#define EIGEN_TMP_NOOPT_ATTRIB \
EIGEN_DEVICE_FUNC inline \
__attribute__((noinline, optimize("no-finite-math-only")))
#endif
template
<
>
EIGEN_TMP_NOOPT_ATTRIB
bool
isnan_impl
(
const
long
double
&
x
)
{
return
__builtin_isnan
(
x
);
}
template
<
>
EIGEN_TMP_NOOPT_ATTRIB
bool
isnan_impl
(
const
double
&
x
)
{
return
__builtin_isnan
(
x
);
}
template
<
>
EIGEN_TMP_NOOPT_ATTRIB
bool
isnan_impl
(
const
float
&
x
)
{
return
__builtin_isnan
(
x
);
}
template
<
>
EIGEN_TMP_NOOPT_ATTRIB
bool
isinf_impl
(
const
double
&
x
)
{
return
__builtin_isinf
(
x
);
}
template
<
>
EIGEN_TMP_NOOPT_ATTRIB
bool
isinf_impl
(
const
float
&
x
)
{
return
__builtin_isinf
(
x
);
}
template
<
>
EIGEN_TMP_NOOPT_ATTRIB
bool
isinf_impl
(
const
long
double
&
x
)
{
return
__builtin_isinf
(
x
);
}
#undef EIGEN_TMP_NOOPT_ATTRIB
#endif
#endif
// The following overload are defined at the end of this file
template
<
typename
T
>
EIGEN_DEVICE_FUNC
bool
isfinite_impl
(
const
std
::
complex
<
T
>&
x
);
template
<
typename
T
>
EIGEN_DEVICE_FUNC
bool
isnan_impl
(
const
std
::
complex
<
T
>&
x
);
template
<
typename
T
>
EIGEN_DEVICE_FUNC
bool
isinf_impl
(
const
std
::
complex
<
T
>&
x
);
template
<
typename
T
>
T
generic_fast_tanh_float
(
const
T
&
a_x
);
}
// end namespace internal
/****************************************************************************
* Generic math functions *
****************************************************************************/
namespace
numext
{
#if (!defined(EIGEN_GPUCC))
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
mini
(
const
T
&
x
,
const
T
&
y
)
{
EIGEN_USING_STD_MATH
(
min
);
return
min
EIGEN_NOT_A_MACRO
(
x
,
y
);
}
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
maxi
(
const
T
&
x
,
const
T
&
y
)
{
EIGEN_USING_STD_MATH
(
max
);
return
max
EIGEN_NOT_A_MACRO
(
x
,
y
);
}
#else
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
mini
(
const
T
&
x
,
const
T
&
y
)
{
return
y
<
x
?
y
:
x
;
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
mini
(
const
float
&
x
,
const
float
&
y
)
{
return
fminf
(
x
,
y
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
mini
(
const
double
&
x
,
const
double
&
y
)
{
return
fmin
(
x
,
y
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
long
double
mini
(
const
long
double
&
x
,
const
long
double
&
y
)
{
#if defined(EIGEN_HIPCC)
// no "fminl" on HIP yet
return
(
x
<
y
)
?
x
:
y
;
#else
return
fminl
(
x
,
y
);
#endif
}
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
maxi
(
const
T
&
x
,
const
T
&
y
)
{
return
x
<
y
?
y
:
x
;
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
maxi
(
const
float
&
x
,
const
float
&
y
)
{
return
fmaxf
(
x
,
y
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
maxi
(
const
double
&
x
,
const
double
&
y
)
{
return
fmax
(
x
,
y
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
long
double
maxi
(
const
long
double
&
x
,
const
long
double
&
y
)
{
#if defined(EIGEN_HIPCC)
// no "fmaxl" on HIP yet
return
(
x
>
y
)
?
x
:
y
;
#else
return
fmaxl
(
x
,
y
);
#endif
}
#endif
#if defined(SYCL_DEVICE_ONLY)
#define SYCL_SPECIALIZE_SIGNED_INTEGER_TYPES_BINARY(NAME, FUNC) \
SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_char) \
SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_short) \
SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_int) \
SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_long)
#define SYCL_SPECIALIZE_SIGNED_INTEGER_TYPES_UNARY(NAME, FUNC) \
SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_char) \
SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_short) \
SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_int) \
SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_long)
#define SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_BINARY(NAME, FUNC) \
SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_uchar) \
SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_ushort) \
SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_uint) \
SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_ulong)
#define SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_UNARY(NAME, FUNC) \
SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_uchar) \
SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_ushort) \
SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_uint) \
SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_ulong)
#define SYCL_SPECIALIZE_INTEGER_TYPES_BINARY(NAME, FUNC) \
SYCL_SPECIALIZE_SIGNED_INTEGER_TYPES_BINARY(NAME, FUNC) \
SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_BINARY(NAME, FUNC)
#define SYCL_SPECIALIZE_INTEGER_TYPES_UNARY(NAME, FUNC) \
SYCL_SPECIALIZE_SIGNED_INTEGER_TYPES_UNARY(NAME, FUNC) \
SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_UNARY(NAME, FUNC)
#define SYCL_SPECIALIZE_FLOATING_TYPES_BINARY(NAME, FUNC) \
SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_float) \
SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_double)
#define SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(NAME, FUNC) \
SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_float) \
SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_double)
#define SYCL_SPECIALIZE_FLOATING_TYPES_UNARY_FUNC_RET_TYPE( \
NAME, FUNC, RET_TYPE) \
SYCL_SPECIALIZE_GEN_UNARY_FUNC(NAME, FUNC, RET_TYPE, cl::sycl::cl_float) \
SYCL_SPECIALIZE_GEN_UNARY_FUNC(NAME, FUNC, RET_TYPE, cl::sycl::cl_double)
#define SYCL_SPECIALIZE_GEN_UNARY_FUNC(NAME, FUNC, RET_TYPE, ARG_TYPE) \
template <> \
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE RET_TYPE NAME(const ARG_TYPE& x) { \
return cl::sycl::FUNC(x); \
}
#define SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, TYPE) \
SYCL_SPECIALIZE_GEN_UNARY_FUNC(NAME, FUNC, TYPE, TYPE)
#define SYCL_SPECIALIZE_GEN1_BINARY_FUNC( \
NAME, FUNC, RET_TYPE, ARG_TYPE1, ARG_TYPE2) \
template <> \
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE RET_TYPE NAME(const ARG_TYPE1& x, \
const ARG_TYPE2& y) { \
return cl::sycl::FUNC(x, y); \
}
#define SYCL_SPECIALIZE_GEN2_BINARY_FUNC(NAME, FUNC, RET_TYPE, ARG_TYPE) \
SYCL_SPECIALIZE_GEN1_BINARY_FUNC(NAME, FUNC, RET_TYPE, ARG_TYPE, ARG_TYPE)
#define SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, TYPE) \
SYCL_SPECIALIZE_GEN2_BINARY_FUNC(NAME, FUNC, TYPE, TYPE)
SYCL_SPECIALIZE_INTEGER_TYPES_BINARY
(
mini
,
min
)
SYCL_SPECIALIZE_FLOATING_TYPES_BINARY
(
mini
,
fmin
)
SYCL_SPECIALIZE_INTEGER_TYPES_BINARY
(
maxi
,
max
)
SYCL_SPECIALIZE_FLOATING_TYPES_BINARY
(
maxi
,
fmax
)
#endif
template
<
typename
Scalar
>
EIGEN_DEVICE_FUNC
inline
EIGEN_MATHFUNC_RETVAL
(
real
,
Scalar
)
real
(
const
Scalar
&
x
)
{
return
EIGEN_MATHFUNC_IMPL
(
real
,
Scalar
)
::
run
(
x
);
}
template
<
typename
Scalar
>
EIGEN_DEVICE_FUNC
inline
typename
internal
::
add_const_on_value_type
<
EIGEN_MATHFUNC_RETVAL
(
real_ref
,
Scalar
)
>::
type
real_ref
(
const
Scalar
&
x
)
{
return
internal
::
real_ref_impl
<
Scalar
>::
run
(
x
);
}
template
<
typename
Scalar
>
EIGEN_DEVICE_FUNC
inline
EIGEN_MATHFUNC_RETVAL
(
real_ref
,
Scalar
)
real_ref
(
Scalar
&
x
)
{
return
EIGEN_MATHFUNC_IMPL
(
real_ref
,
Scalar
)
::
run
(
x
);
}
template
<
typename
Scalar
>
EIGEN_DEVICE_FUNC
inline
EIGEN_MATHFUNC_RETVAL
(
imag
,
Scalar
)
imag
(
const
Scalar
&
x
)
{
return
EIGEN_MATHFUNC_IMPL
(
imag
,
Scalar
)
::
run
(
x
);
}
template
<
typename
Scalar
>
EIGEN_DEVICE_FUNC
inline
EIGEN_MATHFUNC_RETVAL
(
arg
,
Scalar
)
arg
(
const
Scalar
&
x
)
{
return
EIGEN_MATHFUNC_IMPL
(
arg
,
Scalar
)
::
run
(
x
);
}
template
<
typename
Scalar
>
EIGEN_DEVICE_FUNC
inline
typename
internal
::
add_const_on_value_type
<
EIGEN_MATHFUNC_RETVAL
(
imag_ref
,
Scalar
)
>::
type
imag_ref
(
const
Scalar
&
x
)
{
return
internal
::
imag_ref_impl
<
Scalar
>::
run
(
x
);
}
template
<
typename
Scalar
>
EIGEN_DEVICE_FUNC
inline
EIGEN_MATHFUNC_RETVAL
(
imag_ref
,
Scalar
)
imag_ref
(
Scalar
&
x
)
{
return
EIGEN_MATHFUNC_IMPL
(
imag_ref
,
Scalar
)
::
run
(
x
);
}
template
<
typename
Scalar
>
EIGEN_DEVICE_FUNC
inline
EIGEN_MATHFUNC_RETVAL
(
conj
,
Scalar
)
conj
(
const
Scalar
&
x
)
{
return
EIGEN_MATHFUNC_IMPL
(
conj
,
Scalar
)
::
run
(
x
);
}
template
<
typename
Scalar
>
EIGEN_DEVICE_FUNC
inline
EIGEN_MATHFUNC_RETVAL
(
abs2
,
Scalar
)
abs2
(
const
Scalar
&
x
)
{
return
EIGEN_MATHFUNC_IMPL
(
abs2
,
Scalar
)
::
run
(
x
);
}
EIGEN_DEVICE_FUNC
inline
bool
abs2
(
bool
x
)
{
return
x
;
}
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
absdiff
(
const
T
&
x
,
const
T
&
y
)
{
return
x
>
y
?
x
-
y
:
y
-
x
;
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
absdiff
(
const
float
&
x
,
const
float
&
y
)
{
return
fabsf
(
x
-
y
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
absdiff
(
const
double
&
x
,
const
double
&
y
)
{
return
fabs
(
x
-
y
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
long
double
absdiff
(
const
long
double
&
x
,
const
long
double
&
y
)
{
#if defined(EIGEN_HIPCC)
// no "fabsl" on HIP yet
return
(
x
>
y
)
?
x
:
y
;
#else
return
fabsl
(
x
-
y
);
#endif
}
template
<
typename
Scalar
>
EIGEN_DEVICE_FUNC
inline
EIGEN_MATHFUNC_RETVAL
(
norm1
,
Scalar
)
norm1
(
const
Scalar
&
x
)
{
return
EIGEN_MATHFUNC_IMPL
(
norm1
,
Scalar
)
::
run
(
x
);
}
template
<
typename
Scalar
>
EIGEN_DEVICE_FUNC
inline
EIGEN_MATHFUNC_RETVAL
(
hypot
,
Scalar
)
hypot
(
const
Scalar
&
x
,
const
Scalar
&
y
)
{
return
EIGEN_MATHFUNC_IMPL
(
hypot
,
Scalar
)
::
run
(
x
,
y
);
}
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_BINARY
(
hypot
,
hypot
)
#endif
template
<
typename
Scalar
>
EIGEN_DEVICE_FUNC
inline
EIGEN_MATHFUNC_RETVAL
(
log1p
,
Scalar
)
log1p
(
const
Scalar
&
x
)
{
return
EIGEN_MATHFUNC_IMPL
(
log1p
,
Scalar
)
::
run
(
x
);
}
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
log1p
,
log1p
)
#endif
#if defined(EIGEN_GPUCC)
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
log1p
(
const
float
&
x
)
{
return
::
log1pf
(
x
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
log1p
(
const
double
&
x
)
{
return
::
log1p
(
x
);
}
#endif
template
<
typename
ScalarX
,
typename
ScalarY
>
EIGEN_DEVICE_FUNC
inline
typename
internal
::
pow_impl
<
ScalarX
,
ScalarY
>::
result_type
pow
(
const
ScalarX
&
x
,
const
ScalarY
&
y
)
{
return
internal
::
pow_impl
<
ScalarX
,
ScalarY
>::
run
(
x
,
y
);
}
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_BINARY
(
pow
,
pow
)
#endif
template
<
typename
T
>
EIGEN_DEVICE_FUNC
bool
(
isnan
)(
const
T
&
x
)
{
return
internal
::
isnan_impl
(
x
);
}
template
<
typename
T
>
EIGEN_DEVICE_FUNC
bool
(
isinf
)(
const
T
&
x
)
{
return
internal
::
isinf_impl
(
x
);
}
template
<
typename
T
>
EIGEN_DEVICE_FUNC
bool
(
isfinite
)(
const
T
&
x
)
{
return
internal
::
isfinite_impl
(
x
);
}
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY_FUNC_RET_TYPE
(
isnan
,
isnan
,
bool
)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY_FUNC_RET_TYPE
(
isinf
,
isinf
,
bool
)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY_FUNC_RET_TYPE
(
isfinite
,
isfinite
,
bool
)
#endif
template
<
typename
Scalar
>
EIGEN_DEVICE_FUNC
inline
EIGEN_MATHFUNC_RETVAL
(
rint
,
Scalar
)
rint
(
const
Scalar
&
x
)
{
return
EIGEN_MATHFUNC_IMPL
(
rint
,
Scalar
)
::
run
(
x
);
}
template
<
typename
Scalar
>
EIGEN_DEVICE_FUNC
inline
EIGEN_MATHFUNC_RETVAL
(
round
,
Scalar
)
round
(
const
Scalar
&
x
)
{
return
EIGEN_MATHFUNC_IMPL
(
round
,
Scalar
)
::
run
(
x
);
}
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
round
,
round
)
#endif
template
<
typename
T
>
EIGEN_DEVICE_FUNC
T
(
floor
)(
const
T
&
x
)
{
EIGEN_USING_STD_MATH
(
floor
);
return
floor
(
x
);
}
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
floor
,
floor
)
#endif
#if defined(EIGEN_GPUCC)
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
floor
(
const
float
&
x
)
{
return
::
floorf
(
x
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
floor
(
const
double
&
x
)
{
return
::
floor
(
x
);
}
#endif
template
<
typename
T
>
EIGEN_DEVICE_FUNC
T
(
ceil
)(
const
T
&
x
)
{
EIGEN_USING_STD_MATH
(
ceil
);
return
ceil
(
x
);
}
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
ceil
,
ceil
)
#endif
#if defined(EIGEN_GPUCC)
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
ceil
(
const
float
&
x
)
{
return
::
ceilf
(
x
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
ceil
(
const
double
&
x
)
{
return
::
ceil
(
x
);
}
#endif
/** Log base 2 for 32 bits positive integers.
* Conveniently returns 0 for x==0. */
inline
int
log2
(
int
x
)
{
eigen_assert
(
x
>=
0
);
unsigned
int
v
(
x
);
static
const
int
table
[
32
]
=
{
0
,
9
,
1
,
10
,
13
,
21
,
2
,
29
,
11
,
14
,
16
,
18
,
22
,
25
,
3
,
30
,
8
,
12
,
20
,
28
,
15
,
17
,
24
,
7
,
19
,
27
,
23
,
6
,
26
,
5
,
4
,
31
};
v
|=
v
>>
1
;
v
|=
v
>>
2
;
v
|=
v
>>
4
;
v
|=
v
>>
8
;
v
|=
v
>>
16
;
return
table
[(
v
*
0x07C4ACDDU
)
>>
27
];
}
/** \returns the square root of \a x.
*
* It is essentially equivalent to
* \code using std::sqrt; return sqrt(x); \endcode
* but slightly faster for float/double and some compilers (e.g., gcc), thanks
* to
* specializations when SSE is enabled.
*
* It's usage is justified in performance critical functions, like
* norm/normalize.
*/
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
sqrt
(
const
T
&
x
)
{
EIGEN_USING_STD_MATH
(
sqrt
);
return
sqrt
(
x
);
}
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
sqrt
,
sqrt
)
#endif
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
log
(
const
T
&
x
)
{
EIGEN_USING_STD_MATH
(
log
);
return
log
(
x
);
}
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
log
,
log
)
#endif
#if defined(EIGEN_GPUCC)
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
log
(
const
float
&
x
)
{
return
::
logf
(
x
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
log
(
const
double
&
x
)
{
return
::
log
(
x
);
}
#endif
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
typename
internal
::
enable_if
<
NumTraits
<
T
>::
IsSigned
||
NumTraits
<
T
>::
IsComplex
,
typename
NumTraits
<
T
>::
Real
>::
type
abs
(
const
T
&
x
)
{
EIGEN_USING_STD_MATH
(
abs
);
return
abs
(
x
);
}
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
typename
internal
::
enable_if
<!
(
NumTraits
<
T
>::
IsSigned
||
NumTraits
<
T
>::
IsComplex
),
typename
NumTraits
<
T
>::
Real
>::
type
abs
(
const
T
&
x
)
{
return
x
;
}
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_INTEGER_TYPES_UNARY
(
abs
,
abs
)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
abs
,
fabs
)
#endif
#if defined(EIGEN_GPUCC)
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
abs
(
const
float
&
x
)
{
return
::
fabsf
(
x
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
abs
(
const
double
&
x
)
{
return
::
fabs
(
x
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
abs
(
const
std
::
complex
<
float
>&
x
)
{
return
::
hypotf
(
x
.
real
(),
x
.
imag
());
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
abs
(
const
std
::
complex
<
double
>&
x
)
{
return
::
hypot
(
x
.
real
(),
x
.
imag
());
}
#endif
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
exp
(
const
T
&
x
)
{
EIGEN_USING_STD_MATH
(
exp
);
return
exp
(
x
);
}
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
exp
,
exp
)
#endif
#if defined(EIGEN_GPUCC)
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
exp
(
const
float
&
x
)
{
return
::
expf
(
x
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
exp
(
const
double
&
x
)
{
return
::
exp
(
x
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
std
::
complex
<
float
>
exp
(
const
std
::
complex
<
float
>&
x
)
{
float
com
=
::
expf
(
x
.
real
());
float
res_real
=
com
*
::
cosf
(
x
.
imag
());
float
res_imag
=
com
*
::
sinf
(
x
.
imag
());
return
std
::
complex
<
float
>
(
res_real
,
res_imag
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
std
::
complex
<
double
>
exp
(
const
std
::
complex
<
double
>&
x
)
{
double
com
=
::
exp
(
x
.
real
());
double
res_real
=
com
*
::
cos
(
x
.
imag
());
double
res_imag
=
com
*
::
sin
(
x
.
imag
());
return
std
::
complex
<
double
>
(
res_real
,
res_imag
);
}
#endif
template
<
typename
Scalar
>
EIGEN_DEVICE_FUNC
inline
EIGEN_MATHFUNC_RETVAL
(
expm1
,
Scalar
)
expm1
(
const
Scalar
&
x
)
{
return
EIGEN_MATHFUNC_IMPL
(
expm1
,
Scalar
)
::
run
(
x
);
}
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
expm1
,
expm1
)
#endif
#if defined(EIGEN_GPUCC)
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
expm1
(
const
float
&
x
)
{
return
::
expm1f
(
x
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
expm1
(
const
double
&
x
)
{
return
::
expm1
(
x
);
}
#endif
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
cos
(
const
T
&
x
)
{
EIGEN_USING_STD_MATH
(
cos
);
return
cos
(
x
);
}
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
cos
,
cos
)
#endif
#if defined(EIGEN_GPUCC)
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
cos
(
const
float
&
x
)
{
return
::
cosf
(
x
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
cos
(
const
double
&
x
)
{
return
::
cos
(
x
);
}
#endif
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
sin
(
const
T
&
x
)
{
EIGEN_USING_STD_MATH
(
sin
);
return
sin
(
x
);
}
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
sin
,
sin
)
#endif
#if defined(EIGEN_GPUCC)
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
sin
(
const
float
&
x
)
{
return
::
sinf
(
x
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
sin
(
const
double
&
x
)
{
return
::
sin
(
x
);
}
#endif
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
tan
(
const
T
&
x
)
{
EIGEN_USING_STD_MATH
(
tan
);
return
tan
(
x
);
}
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
tan
,
tan
)
#endif
#if defined(EIGEN_GPUCC)
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
tan
(
const
float
&
x
)
{
return
::
tanf
(
x
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
tan
(
const
double
&
x
)
{
return
::
tan
(
x
);
}
#endif
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
acos
(
const
T
&
x
)
{
EIGEN_USING_STD_MATH
(
acos
);
return
acos
(
x
);
}
#if EIGEN_HAS_CXX11_MATH
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
acosh
(
const
T
&
x
)
{
EIGEN_USING_STD_MATH
(
acosh
);
return
acosh
(
x
);
}
#endif
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
acos
,
acos
)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
acosh
,
acosh
)
#endif
#if defined(EIGEN_GPUCC)
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
acos
(
const
float
&
x
)
{
return
::
acosf
(
x
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
acos
(
const
double
&
x
)
{
return
::
acos
(
x
);
}
#endif
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
asin
(
const
T
&
x
)
{
EIGEN_USING_STD_MATH
(
asin
);
return
asin
(
x
);
}
#if EIGEN_HAS_CXX11_MATH
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
asinh
(
const
T
&
x
)
{
EIGEN_USING_STD_MATH
(
asinh
);
return
asinh
(
x
);
}
#endif
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
asin
,
asin
)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
asinh
,
asinh
)
#endif
#if defined(EIGEN_GPUCC)
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
asin
(
const
float
&
x
)
{
return
::
asinf
(
x
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
asin
(
const
double
&
x
)
{
return
::
asin
(
x
);
}
#endif
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
atan
(
const
T
&
x
)
{
EIGEN_USING_STD_MATH
(
atan
);
return
atan
(
x
);
}
#if EIGEN_HAS_CXX11_MATH
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
atanh
(
const
T
&
x
)
{
EIGEN_USING_STD_MATH
(
atanh
);
return
atanh
(
x
);
}
#endif
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
atan
,
atan
)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
atanh
,
atanh
)
#endif
#if defined(EIGEN_GPUCC)
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
atan
(
const
float
&
x
)
{
return
::
atanf
(
x
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
atan
(
const
double
&
x
)
{
return
::
atan
(
x
);
}
#endif
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
cosh
(
const
T
&
x
)
{
EIGEN_USING_STD_MATH
(
cosh
);
return
cosh
(
x
);
}
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
cosh
,
cosh
)
#endif
#if defined(EIGEN_GPUCC)
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
cosh
(
const
float
&
x
)
{
return
::
coshf
(
x
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
cosh
(
const
double
&
x
)
{
return
::
cosh
(
x
);
}
#endif
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
sinh
(
const
T
&
x
)
{
EIGEN_USING_STD_MATH
(
sinh
);
return
sinh
(
x
);
}
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
sinh
,
sinh
)
#endif
#if defined(EIGEN_GPUCC)
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
sinh
(
const
float
&
x
)
{
return
::
sinhf
(
x
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
sinh
(
const
double
&
x
)
{
return
::
sinh
(
x
);
}
#endif
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
tanh
(
const
T
&
x
)
{
EIGEN_USING_STD_MATH
(
tanh
);
return
tanh
(
x
);
}
#if (!defined(EIGEN_GPUCC)) && EIGEN_FAST_MATH && !defined(SYCL_DEVICE_ONLY)
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
tanh
(
float
x
)
{
return
internal
::
generic_fast_tanh_float
(
x
);
}
#endif
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
(
tanh
,
tanh
)
#endif
#if defined(EIGEN_GPUCC)
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
tanh
(
const
float
&
x
)
{
return
::
tanhf
(
x
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
tanh
(
const
double
&
x
)
{
return
::
tanh
(
x
);
}
#endif
template
<
typename
T
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
T
fmod
(
const
T
&
a
,
const
T
&
b
)
{
EIGEN_USING_STD_MATH
(
fmod
);
return
fmod
(
a
,
b
);
}
#if defined(SYCL_DEVICE_ONLY)
SYCL_SPECIALIZE_FLOATING_TYPES_BINARY
(
fmod
,
fmod
)
#endif
#if defined(EIGEN_GPUCC)
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
float
fmod
(
const
float
&
a
,
const
float
&
b
)
{
return
::
fmodf
(
a
,
b
);
}
template
<
>
EIGEN_DEVICE_FUNC
EIGEN_ALWAYS_INLINE
double
fmod
(
const
double
&
a
,
const
double
&
b
)
{
return
::
fmod
(
a
,
b
);
}
#endif
#if defined(SYCL_DEVICE_ONLY)
#undef SYCL_SPECIALIZE_SIGNED_INTEGER_TYPES_BINARY
#undef SYCL_SPECIALIZE_SIGNED_INTEGER_TYPES_UNARY
#undef SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_BINARY
#undef SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_UNARY
#undef SYCL_SPECIALIZE_INTEGER_TYPES_BINARY
#undef SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_UNARY
#undef SYCL_SPECIALIZE_FLOATING_TYPES_BINARY
#undef SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
#undef SYCL_SPECIALIZE_FLOATING_TYPES_UNARY_FUNC_RET_TYPE
#undef SYCL_SPECIALIZE_GEN_UNARY_FUNC
#undef SYCL_SPECIALIZE_UNARY_FUNC
#undef SYCL_SPECIALIZE_GEN1_BINARY_FUNC
#undef SYCL_SPECIALIZE_GEN2_BINARY_FUNC
#undef SYCL_SPECIALIZE_BINARY_FUNC
#endif
}
// end namespace numext
namespace
internal
{
template
<
typename
T
>
EIGEN_DEVICE_FUNC
bool
isfinite_impl
(
const
std
::
complex
<
T
>&
x
)
{
return
(
numext
::
isfinite
)(
numext
::
real
(
x
))
&&
(
numext
::
isfinite
)(
numext
::
imag
(
x
));
}
template
<
typename
T
>
EIGEN_DEVICE_FUNC
bool
isnan_impl
(
const
std
::
complex
<
T
>&
x
)
{
return
(
numext
::
isnan
)(
numext
::
real
(
x
))
||
(
numext
::
isnan
)(
numext
::
imag
(
x
));
}
template
<
typename
T
>
EIGEN_DEVICE_FUNC
bool
isinf_impl
(
const
std
::
complex
<
T
>&
x
)
{
return
((
numext
::
isinf
)(
numext
::
real
(
x
))
||
(
numext
::
isinf
)(
numext
::
imag
(
x
)))
&&
(
!
(
numext
::
isnan
)(
x
));
}
/****************************************************************************
* Implementation of fuzzy comparisons *
****************************************************************************/
template
<
typename
Scalar
,
bool
IsComplex
,
bool
IsInteger
>
struct
scalar_fuzzy_default_impl
{};
template
<
typename
Scalar
>
struct
scalar_fuzzy_default_impl
<
Scalar
,
false
,
false
>
{
typedef
typename
NumTraits
<
Scalar
>::
Real
RealScalar
;
template
<
typename
OtherScalar
>
EIGEN_DEVICE_FUNC
static
inline
bool
isMuchSmallerThan
(
const
Scalar
&
x
,
const
OtherScalar
&
y
,
const
RealScalar
&
prec
)
{
return
numext
::
abs
(
x
)
<=
numext
::
abs
(
y
)
*
prec
;
}
EIGEN_DEVICE_FUNC
static
inline
bool
isApprox
(
const
Scalar
&
x
,
const
Scalar
&
y
,
const
RealScalar
&
prec
)
{
return
numext
::
abs
(
x
-
y
)
<=
numext
::
mini
(
numext
::
abs
(
x
),
numext
::
abs
(
y
))
*
prec
;
}
EIGEN_DEVICE_FUNC
static
inline
bool
isApproxOrLessThan
(
const
Scalar
&
x
,
const
Scalar
&
y
,
const
RealScalar
&
prec
)
{
return
x
<=
y
||
isApprox
(
x
,
y
,
prec
);
}
};
template
<
typename
Scalar
>
struct
scalar_fuzzy_default_impl
<
Scalar
,
false
,
true
>
{
typedef
typename
NumTraits
<
Scalar
>::
Real
RealScalar
;
template
<
typename
OtherScalar
>
EIGEN_DEVICE_FUNC
static
inline
bool
isMuchSmallerThan
(
const
Scalar
&
x
,
const
Scalar
&
,
const
RealScalar
&
)
{
return
x
==
Scalar
(
0
);
}
EIGEN_DEVICE_FUNC
static
inline
bool
isApprox
(
const
Scalar
&
x
,
const
Scalar
&
y
,
const
RealScalar
&
)
{
return
x
==
y
;
}
EIGEN_DEVICE_FUNC
static
inline
bool
isApproxOrLessThan
(
const
Scalar
&
x
,
const
Scalar
&
y
,
const
RealScalar
&
)
{
return
x
<=
y
;
}
};
template
<
typename
Scalar
>
struct
scalar_fuzzy_default_impl
<
Scalar
,
true
,
false
>
{
typedef
typename
NumTraits
<
Scalar
>::
Real
RealScalar
;
template
<
typename
OtherScalar
>
EIGEN_DEVICE_FUNC
static
inline
bool
isMuchSmallerThan
(
const
Scalar
&
x
,
const
OtherScalar
&
y
,
const
RealScalar
&
prec
)
{
return
numext
::
abs2
(
x
)
<=
numext
::
abs2
(
y
)
*
prec
*
prec
;
}
EIGEN_DEVICE_FUNC
static
inline
bool
isApprox
(
const
Scalar
&
x
,
const
Scalar
&
y
,
const
RealScalar
&
prec
)
{
return
numext
::
abs2
(
x
-
y
)
<=
numext
::
mini
(
numext
::
abs2
(
x
),
numext
::
abs2
(
y
))
*
prec
*
prec
;
}
};
template
<
typename
Scalar
>
struct
scalar_fuzzy_impl
:
scalar_fuzzy_default_impl
<
Scalar
,
NumTraits
<
Scalar
>::
IsComplex
,
NumTraits
<
Scalar
>::
IsInteger
>
{};
template
<
typename
Scalar
,
typename
OtherScalar
>
EIGEN_DEVICE_FUNC
inline
bool
isMuchSmallerThan
(
const
Scalar
&
x
,
const
OtherScalar
&
y
,
const
typename
NumTraits
<
Scalar
>::
Real
&
precision
=
NumTraits
<
Scalar
>::
dummy_precision
())
{
return
scalar_fuzzy_impl
<
Scalar
>::
template
isMuchSmallerThan
<
OtherScalar
>(
x
,
y
,
precision
);
}
template
<
typename
Scalar
>
EIGEN_DEVICE_FUNC
inline
bool
isApprox
(
const
Scalar
&
x
,
const
Scalar
&
y
,
const
typename
NumTraits
<
Scalar
>::
Real
&
precision
=
NumTraits
<
Scalar
>::
dummy_precision
())
{
return
scalar_fuzzy_impl
<
Scalar
>::
isApprox
(
x
,
y
,
precision
);
}
template
<
typename
Scalar
>
EIGEN_DEVICE_FUNC
inline
bool
isApproxOrLessThan
(
const
Scalar
&
x
,
const
Scalar
&
y
,
const
typename
NumTraits
<
Scalar
>::
Real
&
precision
=
NumTraits
<
Scalar
>::
dummy_precision
())
{
return
scalar_fuzzy_impl
<
Scalar
>::
isApproxOrLessThan
(
x
,
y
,
precision
);
}
/******************************************
*** The special case of the bool type ***
******************************************/
template
<
>
struct
random_impl
<
bool
>
{
static
inline
bool
run
()
{
return
random
<
int
>
(
0
,
1
)
==
0
?
false
:
true
;
}
};
template
<
>
struct
scalar_fuzzy_impl
<
bool
>
{
typedef
bool
RealScalar
;
template
<
typename
OtherScalar
>
EIGEN_DEVICE_FUNC
static
inline
bool
isMuchSmallerThan
(
const
bool
&
x
,
const
bool
&
,
const
bool
&
)
{
return
!
x
;
}
EIGEN_DEVICE_FUNC
static
inline
bool
isApprox
(
bool
x
,
bool
y
,
bool
)
{
return
x
==
y
;
}
EIGEN_DEVICE_FUNC
static
inline
bool
isApproxOrLessThan
(
const
bool
&
x
,
const
bool
&
y
,
const
bool
&
)
{
return
(
!
x
)
||
y
;
}
};
}
// end namespace internal
}
// end namespace Eigen
#endif // EIGEN_MATHFUNCTIONS_H
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录