1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2008-2016 Gael Guennebaud <[email protected]> 5 // 6 // This Source Code Form is subject to the terms of the Mozilla 7 // Public License v. 2.0. If a copy of the MPL was not distributed 8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 10 #ifndef EIGEN_UNARY_FUNCTORS_H 11 #define EIGEN_UNARY_FUNCTORS_H 12 13 namespace Eigen { 14 15 namespace internal { 16 17 /** \internal 18 * \brief Template functor to compute the opposite of a scalar 19 * 20 * \sa class CwiseUnaryOp, MatrixBase::operator- 21 */ 22 template<typename Scalar> struct scalar_opposite_op { EIGEN_EMPTY_STRUCT_CTORscalar_opposite_op23 EIGEN_EMPTY_STRUCT_CTOR(scalar_opposite_op) 24 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return -a; } 25 template<typename Packet> packetOpscalar_opposite_op26 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const 27 { return internal::pnegate(a); } 28 }; 29 template<typename Scalar> 30 struct functor_traits<scalar_opposite_op<Scalar> > 31 { enum { 32 Cost = NumTraits<Scalar>::AddCost, 33 PacketAccess = packet_traits<Scalar>::HasNegate }; 34 }; 35 36 /** \internal 37 * \brief Template functor to compute the absolute value of a scalar 38 * 39 * \sa class CwiseUnaryOp, Cwise::abs 40 */ 41 template<typename Scalar> struct scalar_abs_op { 42 EIGEN_EMPTY_STRUCT_CTOR(scalar_abs_op) 43 typedef typename NumTraits<Scalar>::Real result_type; 44 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return numext::abs(a); } 45 template<typename Packet> 46 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const 47 { return internal::pabs(a); } 48 }; 49 template<typename Scalar> 50 struct functor_traits<scalar_abs_op<Scalar> > 51 { 52 enum { 53 Cost = NumTraits<Scalar>::AddCost, 54 PacketAccess = packet_traits<Scalar>::HasAbs 55 }; 56 }; 57 58 /** \internal 59 * \brief Template functor to compute the score of a scalar, to chose a pivot 60 * 61 * \sa class CwiseUnaryOp 62 */ 63 template<typename Scalar> struct scalar_score_coeff_op : scalar_abs_op<Scalar> 64 { 65 typedef void Score_is_abs; 66 }; 67 template<typename Scalar> 68 struct functor_traits<scalar_score_coeff_op<Scalar> > : functor_traits<scalar_abs_op<Scalar> > {}; 69 70 /* Avoid recomputing abs when we know the score and they are the same. Not a true Eigen functor. */ 71 template<typename Scalar, typename=void> struct abs_knowing_score 72 { 73 EIGEN_EMPTY_STRUCT_CTOR(abs_knowing_score) 74 typedef typename NumTraits<Scalar>::Real result_type; 75 template<typename Score> 76 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a, const Score&) const { return numext::abs(a); } 77 }; 78 template<typename Scalar> struct abs_knowing_score<Scalar, typename scalar_score_coeff_op<Scalar>::Score_is_abs> 79 { 80 EIGEN_EMPTY_STRUCT_CTOR(abs_knowing_score) 81 typedef typename NumTraits<Scalar>::Real result_type; 82 template<typename Scal> 83 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const Scal&, const result_type& a) const { return a; } 84 }; 85 86 /** \internal 87 * \brief Template functor to compute the squared absolute value of a scalar 88 * 89 * \sa class CwiseUnaryOp, Cwise::abs2 90 */ 91 template<typename Scalar> struct scalar_abs2_op { 92 EIGEN_EMPTY_STRUCT_CTOR(scalar_abs2_op) 93 typedef typename NumTraits<Scalar>::Real result_type; 94 EIGEN_DEVICE_FUNC 95 EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return numext::abs2(a); } 96 template<typename Packet> 97 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const 98 { return internal::pmul(a,a); } 99 }; 100 template<typename Scalar> 101 struct functor_traits<scalar_abs2_op<Scalar> > 102 { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasAbs2 }; }; 103 104 /** \internal 105 * \brief Template functor to compute the conjugate of a complex value 106 * 107 * \sa class CwiseUnaryOp, MatrixBase::conjugate() 108 */ 109 template<typename Scalar> struct scalar_conjugate_op { 110 EIGEN_EMPTY_STRUCT_CTOR(scalar_conjugate_op) 111 EIGEN_DEVICE_FUNC 112 EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return numext::conj(a); } 113 template<typename Packet> 114 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const { return internal::pconj(a); } 115 }; 116 template<typename Scalar> 117 struct functor_traits<scalar_conjugate_op<Scalar> > 118 { 119 enum { 120 Cost = 0, 121 // Yes the cost is zero even for complexes because in most cases for which 122 // the cost is used, conjugation turns to be a no-op. Some examples: 123 // cost(a*conj(b)) == cost(a*b) 124 // cost(a+conj(b)) == cost(a+b) 125 // <etc. 126 // If we don't set it to zero, then: 127 // A.conjugate().lazyProduct(B.conjugate()) 128 // will bake its operands. We definitely don't want that! 129 PacketAccess = packet_traits<Scalar>::HasConj 130 }; 131 }; 132 133 /** \internal 134 * \brief Template functor to compute the phase angle of a complex 135 * 136 * \sa class CwiseUnaryOp, Cwise::arg 137 */ 138 template<typename Scalar> struct scalar_arg_op { 139 EIGEN_EMPTY_STRUCT_CTOR(scalar_arg_op) 140 typedef typename NumTraits<Scalar>::Real result_type; 141 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return numext::arg(a); } 142 template<typename Packet> 143 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const 144 { return internal::parg(a); } 145 }; 146 template<typename Scalar> 147 struct functor_traits<scalar_arg_op<Scalar> > 148 { 149 enum { 150 Cost = NumTraits<Scalar>::IsComplex ? 5 * NumTraits<Scalar>::MulCost : NumTraits<Scalar>::AddCost, 151 PacketAccess = packet_traits<Scalar>::HasArg 152 }; 153 }; 154 /** \internal 155 * \brief Template functor to cast a scalar to another type 156 * 157 * \sa class CwiseUnaryOp, MatrixBase::cast() 158 */ 159 template<typename Scalar, typename NewType> 160 struct scalar_cast_op { 161 EIGEN_EMPTY_STRUCT_CTOR(scalar_cast_op) 162 typedef NewType result_type; 163 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const NewType operator() (const Scalar& a) const { return cast<Scalar, NewType>(a); } 164 }; 165 template<typename Scalar, typename NewType> 166 struct functor_traits<scalar_cast_op<Scalar,NewType> > 167 { enum { Cost = is_same<Scalar, NewType>::value ? 0 : NumTraits<NewType>::AddCost, PacketAccess = false }; }; 168 169 /** \internal 170 * \brief Template functor to arithmetically shift a scalar right by a number of bits 171 * 172 * \sa class CwiseUnaryOp, MatrixBase::shift_right() 173 */ 174 template<typename Scalar, int N> 175 struct scalar_shift_right_op { 176 EIGEN_EMPTY_STRUCT_CTOR(scalar_shift_right_op) 177 178 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const 179 { return a >> N; } 180 template<typename Packet> 181 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const 182 { return internal::parithmetic_shift_right<N>(a); } 183 }; 184 template<typename Scalar, int N> 185 struct functor_traits<scalar_shift_right_op<Scalar,N> > 186 { enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasShift }; }; 187 188 /** \internal 189 * \brief Template functor to logically shift a scalar left by a number of bits 190 * 191 * \sa class CwiseUnaryOp, MatrixBase::shift_left() 192 */ 193 template<typename Scalar, int N> 194 struct scalar_shift_left_op { 195 EIGEN_EMPTY_STRUCT_CTOR(scalar_shift_left_op) 196 197 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const 198 { return a << N; } 199 template<typename Packet> 200 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const 201 { return internal::plogical_shift_left<N>(a); } 202 }; 203 template<typename Scalar, int N> 204 struct functor_traits<scalar_shift_left_op<Scalar,N> > 205 { enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasShift }; }; 206 207 /** \internal 208 * \brief Template functor to extract the real part of a complex 209 * 210 * \sa class CwiseUnaryOp, MatrixBase::real() 211 */ 212 template<typename Scalar> 213 struct scalar_real_op { 214 EIGEN_EMPTY_STRUCT_CTOR(scalar_real_op) 215 typedef typename NumTraits<Scalar>::Real result_type; 216 EIGEN_DEVICE_FUNC 217 EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return numext::real(a); } 218 }; 219 template<typename Scalar> 220 struct functor_traits<scalar_real_op<Scalar> > 221 { enum { Cost = 0, PacketAccess = false }; }; 222 223 /** \internal 224 * \brief Template functor to extract the imaginary part of a complex 225 * 226 * \sa class CwiseUnaryOp, MatrixBase::imag() 227 */ 228 template<typename Scalar> 229 struct scalar_imag_op { 230 EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_op) 231 typedef typename NumTraits<Scalar>::Real result_type; 232 EIGEN_DEVICE_FUNC 233 EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return numext::imag(a); } 234 }; 235 template<typename Scalar> 236 struct functor_traits<scalar_imag_op<Scalar> > 237 { enum { Cost = 0, PacketAccess = false }; }; 238 239 /** \internal 240 * \brief Template functor to extract the real part of a complex as a reference 241 * 242 * \sa class CwiseUnaryOp, MatrixBase::real() 243 */ 244 template<typename Scalar> 245 struct scalar_real_ref_op { 246 EIGEN_EMPTY_STRUCT_CTOR(scalar_real_ref_op) 247 typedef typename NumTraits<Scalar>::Real result_type; 248 EIGEN_DEVICE_FUNC 249 EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return numext::real_ref(*const_cast<Scalar*>(&a)); } 250 }; 251 template<typename Scalar> 252 struct functor_traits<scalar_real_ref_op<Scalar> > 253 { enum { Cost = 0, PacketAccess = false }; }; 254 255 /** \internal 256 * \brief Template functor to extract the imaginary part of a complex as a reference 257 * 258 * \sa class CwiseUnaryOp, MatrixBase::imag() 259 */ 260 template<typename Scalar> 261 struct scalar_imag_ref_op { 262 EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_ref_op) 263 typedef typename NumTraits<Scalar>::Real result_type; 264 EIGEN_DEVICE_FUNC 265 EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return numext::imag_ref(*const_cast<Scalar*>(&a)); } 266 }; 267 template<typename Scalar> 268 struct functor_traits<scalar_imag_ref_op<Scalar> > 269 { enum { Cost = 0, PacketAccess = false }; }; 270 271 /** \internal 272 * 273 * \brief Template functor to compute the exponential of a scalar 274 * 275 * \sa class CwiseUnaryOp, Cwise::exp() 276 */ 277 template<typename Scalar> struct scalar_exp_op { 278 EIGEN_EMPTY_STRUCT_CTOR(scalar_exp_op) 279 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::exp(a); } 280 template <typename Packet> 281 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pexp(a); } 282 }; 283 template <typename Scalar> 284 struct functor_traits<scalar_exp_op<Scalar> > { 285 enum { 286 PacketAccess = packet_traits<Scalar>::HasExp, 287 // The following numbers are based on the AVX implementation. 288 #ifdef EIGEN_VECTORIZE_FMA 289 // Haswell can issue 2 add/mul/madd per cycle. 290 Cost = 291 (sizeof(Scalar) == 4 292 // float: 8 pmadd, 4 pmul, 2 padd/psub, 6 other 293 ? (8 * NumTraits<Scalar>::AddCost + 6 * NumTraits<Scalar>::MulCost) 294 // double: 7 pmadd, 5 pmul, 3 padd/psub, 1 div, 13 other 295 : (14 * NumTraits<Scalar>::AddCost + 296 6 * NumTraits<Scalar>::MulCost + 297 scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value)) 298 #else 299 Cost = 300 (sizeof(Scalar) == 4 301 // float: 7 pmadd, 6 pmul, 4 padd/psub, 10 other 302 ? (21 * NumTraits<Scalar>::AddCost + 13 * NumTraits<Scalar>::MulCost) 303 // double: 7 pmadd, 5 pmul, 3 padd/psub, 1 div, 13 other 304 : (23 * NumTraits<Scalar>::AddCost + 305 12 * NumTraits<Scalar>::MulCost + 306 scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value)) 307 #endif 308 }; 309 }; 310 311 /** \internal 312 * 313 * \brief Template functor to compute the exponential of a scalar - 1. 314 * 315 * \sa class CwiseUnaryOp, ArrayBase::expm1() 316 */ 317 template<typename Scalar> struct scalar_expm1_op { 318 EIGEN_EMPTY_STRUCT_CTOR(scalar_expm1_op) 319 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::expm1(a); } 320 template <typename Packet> 321 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pexpm1(a); } 322 }; 323 template <typename Scalar> 324 struct functor_traits<scalar_expm1_op<Scalar> > { 325 enum { 326 PacketAccess = packet_traits<Scalar>::HasExpm1, 327 Cost = functor_traits<scalar_exp_op<Scalar> >::Cost // TODO measure cost of expm1 328 }; 329 }; 330 331 /** \internal 332 * 333 * \brief Template functor to compute the logarithm of a scalar 334 * 335 * \sa class CwiseUnaryOp, ArrayBase::log() 336 */ 337 template<typename Scalar> struct scalar_log_op { 338 EIGEN_EMPTY_STRUCT_CTOR(scalar_log_op) 339 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::log(a); } 340 template <typename Packet> 341 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::plog(a); } 342 }; 343 template <typename Scalar> 344 struct functor_traits<scalar_log_op<Scalar> > { 345 enum { 346 PacketAccess = packet_traits<Scalar>::HasLog, 347 Cost = 348 (PacketAccess 349 // The following numbers are based on the AVX implementation. 350 #ifdef EIGEN_VECTORIZE_FMA 351 // 8 pmadd, 6 pmul, 8 padd/psub, 16 other, can issue 2 add/mul/madd per cycle. 352 ? (20 * NumTraits<Scalar>::AddCost + 7 * NumTraits<Scalar>::MulCost) 353 #else 354 // 8 pmadd, 6 pmul, 8 padd/psub, 20 other 355 ? (36 * NumTraits<Scalar>::AddCost + 14 * NumTraits<Scalar>::MulCost) 356 #endif 357 // Measured cost of std::log. 358 : sizeof(Scalar)==4 ? 40 : 85) 359 }; 360 }; 361 362 /** \internal 363 * 364 * \brief Template functor to compute the logarithm of 1 plus a scalar value 365 * 366 * \sa class CwiseUnaryOp, ArrayBase::log1p() 367 */ 368 template<typename Scalar> struct scalar_log1p_op { 369 EIGEN_EMPTY_STRUCT_CTOR(scalar_log1p_op) 370 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::log1p(a); } 371 template <typename Packet> 372 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::plog1p(a); } 373 }; 374 template <typename Scalar> 375 struct functor_traits<scalar_log1p_op<Scalar> > { 376 enum { 377 PacketAccess = packet_traits<Scalar>::HasLog1p, 378 Cost = functor_traits<scalar_log_op<Scalar> >::Cost // TODO measure cost of log1p 379 }; 380 }; 381 382 /** \internal 383 * 384 * \brief Template functor to compute the base-10 logarithm of a scalar 385 * 386 * \sa class CwiseUnaryOp, Cwise::log10() 387 */ 388 template<typename Scalar> struct scalar_log10_op { 389 EIGEN_EMPTY_STRUCT_CTOR(scalar_log10_op) 390 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { EIGEN_USING_STD(log10) return log10(a); } 391 template <typename Packet> 392 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::plog10(a); } 393 }; 394 template<typename Scalar> 395 struct functor_traits<scalar_log10_op<Scalar> > 396 { enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasLog10 }; }; 397 398 /** \internal 399 * 400 * \brief Template functor to compute the base-2 logarithm of a scalar 401 * 402 * \sa class CwiseUnaryOp, Cwise::log2() 403 */ 404 template<typename Scalar> struct scalar_log2_op { 405 EIGEN_EMPTY_STRUCT_CTOR(scalar_log2_op) 406 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return Scalar(EIGEN_LOG2E) * numext::log(a); } 407 template <typename Packet> 408 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::plog2(a); } 409 }; 410 template<typename Scalar> 411 struct functor_traits<scalar_log2_op<Scalar> > 412 { enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasLog }; }; 413 414 /** \internal 415 * \brief Template functor to compute the square root of a scalar 416 * \sa class CwiseUnaryOp, Cwise::sqrt() 417 */ 418 template<typename Scalar> struct scalar_sqrt_op { 419 EIGEN_EMPTY_STRUCT_CTOR(scalar_sqrt_op) 420 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::sqrt(a); } 421 template <typename Packet> 422 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psqrt(a); } 423 }; 424 template <typename Scalar> 425 struct functor_traits<scalar_sqrt_op<Scalar> > { 426 enum { 427 #if EIGEN_FAST_MATH 428 // The following numbers are based on the AVX implementation. 429 Cost = (sizeof(Scalar) == 8 ? 28 430 // 4 pmul, 1 pmadd, 3 other 431 : (3 * NumTraits<Scalar>::AddCost + 432 5 * NumTraits<Scalar>::MulCost)), 433 #else 434 // The following numbers are based on min VSQRT throughput on Haswell. 435 Cost = (sizeof(Scalar) == 8 ? 28 : 14), 436 #endif 437 PacketAccess = packet_traits<Scalar>::HasSqrt 438 }; 439 }; 440 441 // Boolean specialization to eliminate -Wimplicit-conversion-floating-point-to-bool warnings. 442 template<> struct scalar_sqrt_op<bool> { 443 EIGEN_EMPTY_STRUCT_CTOR(scalar_sqrt_op) 444 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline bool operator() (const bool& a) const { return a; } 445 template <typename Packet> 446 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return a; } 447 }; 448 template <> 449 struct functor_traits<scalar_sqrt_op<bool> > { 450 enum { Cost = 1, PacketAccess = packet_traits<bool>::Vectorizable }; 451 }; 452 453 /** \internal 454 * \brief Template functor to compute the reciprocal square root of a scalar 455 * \sa class CwiseUnaryOp, Cwise::rsqrt() 456 */ 457 template<typename Scalar> struct scalar_rsqrt_op { 458 EIGEN_EMPTY_STRUCT_CTOR(scalar_rsqrt_op) 459 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::rsqrt(a); } 460 template <typename Packet> 461 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::prsqrt(a); } 462 }; 463 464 template<typename Scalar> 465 struct functor_traits<scalar_rsqrt_op<Scalar> > 466 { enum { 467 Cost = 5 * NumTraits<Scalar>::MulCost, 468 PacketAccess = packet_traits<Scalar>::HasRsqrt 469 }; 470 }; 471 472 /** \internal 473 * \brief Template functor to compute the cosine of a scalar 474 * \sa class CwiseUnaryOp, ArrayBase::cos() 475 */ 476 template<typename Scalar> struct scalar_cos_op { 477 EIGEN_EMPTY_STRUCT_CTOR(scalar_cos_op) 478 EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return numext::cos(a); } 479 template <typename Packet> 480 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pcos(a); } 481 }; 482 template<typename Scalar> 483 struct functor_traits<scalar_cos_op<Scalar> > 484 { 485 enum { 486 Cost = 5 * NumTraits<Scalar>::MulCost, 487 PacketAccess = packet_traits<Scalar>::HasCos 488 }; 489 }; 490 491 /** \internal 492 * \brief Template functor to compute the sine of a scalar 493 * \sa class CwiseUnaryOp, ArrayBase::sin() 494 */ 495 template<typename Scalar> struct scalar_sin_op { 496 EIGEN_EMPTY_STRUCT_CTOR(scalar_sin_op) 497 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::sin(a); } 498 template <typename Packet> 499 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psin(a); } 500 }; 501 template<typename Scalar> 502 struct functor_traits<scalar_sin_op<Scalar> > 503 { 504 enum { 505 Cost = 5 * NumTraits<Scalar>::MulCost, 506 PacketAccess = packet_traits<Scalar>::HasSin 507 }; 508 }; 509 510 511 /** \internal 512 * \brief Template functor to compute the tan of a scalar 513 * \sa class CwiseUnaryOp, ArrayBase::tan() 514 */ 515 template<typename Scalar> struct scalar_tan_op { 516 EIGEN_EMPTY_STRUCT_CTOR(scalar_tan_op) 517 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::tan(a); } 518 template <typename Packet> 519 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::ptan(a); } 520 }; 521 template<typename Scalar> 522 struct functor_traits<scalar_tan_op<Scalar> > 523 { 524 enum { 525 Cost = 5 * NumTraits<Scalar>::MulCost, 526 PacketAccess = packet_traits<Scalar>::HasTan 527 }; 528 }; 529 530 /** \internal 531 * \brief Template functor to compute the arc cosine of a scalar 532 * \sa class CwiseUnaryOp, ArrayBase::acos() 533 */ 534 template<typename Scalar> struct scalar_acos_op { 535 EIGEN_EMPTY_STRUCT_CTOR(scalar_acos_op) 536 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::acos(a); } 537 template <typename Packet> 538 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pacos(a); } 539 }; 540 template<typename Scalar> 541 struct functor_traits<scalar_acos_op<Scalar> > 542 { 543 enum { 544 Cost = 5 * NumTraits<Scalar>::MulCost, 545 PacketAccess = packet_traits<Scalar>::HasACos 546 }; 547 }; 548 549 /** \internal 550 * \brief Template functor to compute the arc sine of a scalar 551 * \sa class CwiseUnaryOp, ArrayBase::asin() 552 */ 553 template<typename Scalar> struct scalar_asin_op { 554 EIGEN_EMPTY_STRUCT_CTOR(scalar_asin_op) 555 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::asin(a); } 556 template <typename Packet> 557 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pasin(a); } 558 }; 559 template<typename Scalar> 560 struct functor_traits<scalar_asin_op<Scalar> > 561 { 562 enum { 563 Cost = 5 * NumTraits<Scalar>::MulCost, 564 PacketAccess = packet_traits<Scalar>::HasASin 565 }; 566 }; 567 568 569 /** \internal 570 * \brief Template functor to compute the atan of a scalar 571 * \sa class CwiseUnaryOp, ArrayBase::atan() 572 */ 573 template<typename Scalar> struct scalar_atan_op { 574 EIGEN_EMPTY_STRUCT_CTOR(scalar_atan_op) 575 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::atan(a); } 576 template <typename Packet> 577 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::patan(a); } 578 }; 579 template<typename Scalar> 580 struct functor_traits<scalar_atan_op<Scalar> > 581 { 582 enum { 583 Cost = 5 * NumTraits<Scalar>::MulCost, 584 PacketAccess = packet_traits<Scalar>::HasATan 585 }; 586 }; 587 588 /** \internal 589 * \brief Template functor to compute the tanh of a scalar 590 * \sa class CwiseUnaryOp, ArrayBase::tanh() 591 */ 592 template <typename Scalar> 593 struct scalar_tanh_op { 594 EIGEN_EMPTY_STRUCT_CTOR(scalar_tanh_op) 595 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::tanh(a); } 596 template <typename Packet> 597 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& x) const { return ptanh(x); } 598 }; 599 600 template <typename Scalar> 601 struct functor_traits<scalar_tanh_op<Scalar> > { 602 enum { 603 PacketAccess = packet_traits<Scalar>::HasTanh, 604 Cost = ( (EIGEN_FAST_MATH && is_same<Scalar,float>::value) 605 // The following numbers are based on the AVX implementation, 606 #ifdef EIGEN_VECTORIZE_FMA 607 // Haswell can issue 2 add/mul/madd per cycle. 608 // 9 pmadd, 2 pmul, 1 div, 2 other 609 ? (2 * NumTraits<Scalar>::AddCost + 610 6 * NumTraits<Scalar>::MulCost + 611 scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value) 612 #else 613 ? (11 * NumTraits<Scalar>::AddCost + 614 11 * NumTraits<Scalar>::MulCost + 615 scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value) 616 #endif 617 // This number assumes a naive implementation of tanh 618 : (6 * NumTraits<Scalar>::AddCost + 619 3 * NumTraits<Scalar>::MulCost + 620 2 * scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value + 621 functor_traits<scalar_exp_op<Scalar> >::Cost)) 622 }; 623 }; 624 625 #if EIGEN_HAS_CXX11_MATH 626 /** \internal 627 * \brief Template functor to compute the atanh of a scalar 628 * \sa class CwiseUnaryOp, ArrayBase::atanh() 629 */ 630 template <typename Scalar> 631 struct scalar_atanh_op { 632 EIGEN_EMPTY_STRUCT_CTOR(scalar_atanh_op) 633 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::atanh(a); } 634 }; 635 636 template <typename Scalar> 637 struct functor_traits<scalar_atanh_op<Scalar> > { 638 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; 639 }; 640 #endif 641 642 /** \internal 643 * \brief Template functor to compute the sinh of a scalar 644 * \sa class CwiseUnaryOp, ArrayBase::sinh() 645 */ 646 template<typename Scalar> struct scalar_sinh_op { 647 EIGEN_EMPTY_STRUCT_CTOR(scalar_sinh_op) 648 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::sinh(a); } 649 template <typename Packet> 650 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psinh(a); } 651 }; 652 template<typename Scalar> 653 struct functor_traits<scalar_sinh_op<Scalar> > 654 { 655 enum { 656 Cost = 5 * NumTraits<Scalar>::MulCost, 657 PacketAccess = packet_traits<Scalar>::HasSinh 658 }; 659 }; 660 661 #if EIGEN_HAS_CXX11_MATH 662 /** \internal 663 * \brief Template functor to compute the asinh of a scalar 664 * \sa class CwiseUnaryOp, ArrayBase::asinh() 665 */ 666 template <typename Scalar> 667 struct scalar_asinh_op { 668 EIGEN_EMPTY_STRUCT_CTOR(scalar_asinh_op) 669 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::asinh(a); } 670 }; 671 672 template <typename Scalar> 673 struct functor_traits<scalar_asinh_op<Scalar> > { 674 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; 675 }; 676 #endif 677 678 /** \internal 679 * \brief Template functor to compute the cosh of a scalar 680 * \sa class CwiseUnaryOp, ArrayBase::cosh() 681 */ 682 template<typename Scalar> struct scalar_cosh_op { 683 EIGEN_EMPTY_STRUCT_CTOR(scalar_cosh_op) 684 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::cosh(a); } 685 template <typename Packet> 686 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pcosh(a); } 687 }; 688 template<typename Scalar> 689 struct functor_traits<scalar_cosh_op<Scalar> > 690 { 691 enum { 692 Cost = 5 * NumTraits<Scalar>::MulCost, 693 PacketAccess = packet_traits<Scalar>::HasCosh 694 }; 695 }; 696 697 #if EIGEN_HAS_CXX11_MATH 698 /** \internal 699 * \brief Template functor to compute the acosh of a scalar 700 * \sa class CwiseUnaryOp, ArrayBase::acosh() 701 */ 702 template <typename Scalar> 703 struct scalar_acosh_op { 704 EIGEN_EMPTY_STRUCT_CTOR(scalar_acosh_op) 705 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::acosh(a); } 706 }; 707 708 template <typename Scalar> 709 struct functor_traits<scalar_acosh_op<Scalar> > { 710 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; 711 }; 712 #endif 713 714 /** \internal 715 * \brief Template functor to compute the inverse of a scalar 716 * \sa class CwiseUnaryOp, Cwise::inverse() 717 */ 718 template<typename Scalar> 719 struct scalar_inverse_op { 720 EIGEN_EMPTY_STRUCT_CTOR(scalar_inverse_op) 721 EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return Scalar(1)/a; } 722 template<typename Packet> 723 EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const 724 { return internal::pdiv(pset1<Packet>(Scalar(1)),a); } 725 }; 726 template <typename Scalar> 727 struct functor_traits<scalar_inverse_op<Scalar> > { 728 enum { 729 PacketAccess = packet_traits<Scalar>::HasDiv, 730 Cost = scalar_div_cost<Scalar, PacketAccess>::value 731 }; 732 }; 733 734 /** \internal 735 * \brief Template functor to compute the square of a scalar 736 * \sa class CwiseUnaryOp, Cwise::square() 737 */ 738 template<typename Scalar> 739 struct scalar_square_op { 740 EIGEN_EMPTY_STRUCT_CTOR(scalar_square_op) 741 EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return a*a; } 742 template<typename Packet> 743 EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const 744 { return internal::pmul(a,a); } 745 }; 746 template<typename Scalar> 747 struct functor_traits<scalar_square_op<Scalar> > 748 { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; }; 749 750 // Boolean specialization to avoid -Wint-in-bool-context warnings on GCC. 751 template<> 752 struct scalar_square_op<bool> { 753 EIGEN_EMPTY_STRUCT_CTOR(scalar_square_op) 754 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline bool operator() (const bool& a) const { return a; } 755 template<typename Packet> 756 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const 757 { return a; } 758 }; 759 template<> 760 struct functor_traits<scalar_square_op<bool> > 761 { enum { Cost = 0, PacketAccess = packet_traits<bool>::Vectorizable }; }; 762 763 /** \internal 764 * \brief Template functor to compute the cube of a scalar 765 * \sa class CwiseUnaryOp, Cwise::cube() 766 */ 767 template<typename Scalar> 768 struct scalar_cube_op { 769 EIGEN_EMPTY_STRUCT_CTOR(scalar_cube_op) 770 EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return a*a*a; } 771 template<typename Packet> 772 EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const 773 { return internal::pmul(a,pmul(a,a)); } 774 }; 775 template<typename Scalar> 776 struct functor_traits<scalar_cube_op<Scalar> > 777 { enum { Cost = 2*NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; }; 778 779 // Boolean specialization to avoid -Wint-in-bool-context warnings on GCC. 780 template<> 781 struct scalar_cube_op<bool> { 782 EIGEN_EMPTY_STRUCT_CTOR(scalar_cube_op) 783 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline bool operator() (const bool& a) const { return a; } 784 template<typename Packet> 785 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const 786 { return a; } 787 }; 788 template<> 789 struct functor_traits<scalar_cube_op<bool> > 790 { enum { Cost = 0, PacketAccess = packet_traits<bool>::Vectorizable }; }; 791 792 /** \internal 793 * \brief Template functor to compute the rounded value of a scalar 794 * \sa class CwiseUnaryOp, ArrayBase::round() 795 */ 796 template<typename Scalar> struct scalar_round_op { 797 EIGEN_EMPTY_STRUCT_CTOR(scalar_round_op) 798 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return numext::round(a); } 799 template <typename Packet> 800 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pround(a); } 801 }; 802 template<typename Scalar> 803 struct functor_traits<scalar_round_op<Scalar> > 804 { 805 enum { 806 Cost = NumTraits<Scalar>::MulCost, 807 PacketAccess = packet_traits<Scalar>::HasRound 808 }; 809 }; 810 811 /** \internal 812 * \brief Template functor to compute the floor of a scalar 813 * \sa class CwiseUnaryOp, ArrayBase::floor() 814 */ 815 template<typename Scalar> struct scalar_floor_op { 816 EIGEN_EMPTY_STRUCT_CTOR(scalar_floor_op) 817 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return numext::floor(a); } 818 template <typename Packet> 819 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pfloor(a); } 820 }; 821 template<typename Scalar> 822 struct functor_traits<scalar_floor_op<Scalar> > 823 { 824 enum { 825 Cost = NumTraits<Scalar>::MulCost, 826 PacketAccess = packet_traits<Scalar>::HasFloor 827 }; 828 }; 829 830 /** \internal 831 * \brief Template functor to compute the rounded (with current rounding mode) value of a scalar 832 * \sa class CwiseUnaryOp, ArrayBase::rint() 833 */ 834 template<typename Scalar> struct scalar_rint_op { 835 EIGEN_EMPTY_STRUCT_CTOR(scalar_rint_op) 836 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return numext::rint(a); } 837 template <typename Packet> 838 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::print(a); } 839 }; 840 template<typename Scalar> 841 struct functor_traits<scalar_rint_op<Scalar> > 842 { 843 enum { 844 Cost = NumTraits<Scalar>::MulCost, 845 PacketAccess = packet_traits<Scalar>::HasRint 846 }; 847 }; 848 849 /** \internal 850 * \brief Template functor to compute the ceil of a scalar 851 * \sa class CwiseUnaryOp, ArrayBase::ceil() 852 */ 853 template<typename Scalar> struct scalar_ceil_op { 854 EIGEN_EMPTY_STRUCT_CTOR(scalar_ceil_op) 855 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return numext::ceil(a); } 856 template <typename Packet> 857 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pceil(a); } 858 }; 859 template<typename Scalar> 860 struct functor_traits<scalar_ceil_op<Scalar> > 861 { 862 enum { 863 Cost = NumTraits<Scalar>::MulCost, 864 PacketAccess = packet_traits<Scalar>::HasCeil 865 }; 866 }; 867 868 /** \internal 869 * \brief Template functor to compute whether a scalar is NaN 870 * \sa class CwiseUnaryOp, ArrayBase::isnan() 871 */ 872 template<typename Scalar> struct scalar_isnan_op { 873 EIGEN_EMPTY_STRUCT_CTOR(scalar_isnan_op) 874 typedef bool result_type; 875 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { 876 #if defined(SYCL_DEVICE_ONLY) 877 return numext::isnan(a); 878 #else 879 return (numext::isnan)(a); 880 #endif 881 } 882 }; 883 template<typename Scalar> 884 struct functor_traits<scalar_isnan_op<Scalar> > 885 { 886 enum { 887 Cost = NumTraits<Scalar>::MulCost, 888 PacketAccess = false 889 }; 890 }; 891 892 /** \internal 893 * \brief Template functor to check whether a scalar is +/-inf 894 * \sa class CwiseUnaryOp, ArrayBase::isinf() 895 */ 896 template<typename Scalar> struct scalar_isinf_op { 897 EIGEN_EMPTY_STRUCT_CTOR(scalar_isinf_op) 898 typedef bool result_type; 899 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { 900 #if defined(SYCL_DEVICE_ONLY) 901 return numext::isinf(a); 902 #else 903 return (numext::isinf)(a); 904 #endif 905 } 906 }; 907 template<typename Scalar> 908 struct functor_traits<scalar_isinf_op<Scalar> > 909 { 910 enum { 911 Cost = NumTraits<Scalar>::MulCost, 912 PacketAccess = false 913 }; 914 }; 915 916 /** \internal 917 * \brief Template functor to check whether a scalar has a finite value 918 * \sa class CwiseUnaryOp, ArrayBase::isfinite() 919 */ 920 template<typename Scalar> struct scalar_isfinite_op { 921 EIGEN_EMPTY_STRUCT_CTOR(scalar_isfinite_op) 922 typedef bool result_type; 923 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { 924 #if defined(SYCL_DEVICE_ONLY) 925 return numext::isfinite(a); 926 #else 927 return (numext::isfinite)(a); 928 #endif 929 } 930 }; 931 template<typename Scalar> 932 struct functor_traits<scalar_isfinite_op<Scalar> > 933 { 934 enum { 935 Cost = NumTraits<Scalar>::MulCost, 936 PacketAccess = false 937 }; 938 }; 939 940 /** \internal 941 * \brief Template functor to compute the logical not of a boolean 942 * 943 * \sa class CwiseUnaryOp, ArrayBase::operator! 944 */ 945 template<typename Scalar> struct scalar_boolean_not_op { 946 EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_not_op) 947 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a) const { return !a; } 948 }; 949 template<typename Scalar> 950 struct functor_traits<scalar_boolean_not_op<Scalar> > { 951 enum { 952 Cost = NumTraits<bool>::AddCost, 953 PacketAccess = false 954 }; 955 }; 956 957 /** \internal 958 * \brief Template functor to compute the signum of a scalar 959 * \sa class CwiseUnaryOp, Cwise::sign() 960 */ 961 template<typename Scalar,bool is_complex=(NumTraits<Scalar>::IsComplex!=0), bool is_integer=(NumTraits<Scalar>::IsInteger!=0) > struct scalar_sign_op; 962 template<typename Scalar> 963 struct scalar_sign_op<Scalar, false, true> { 964 EIGEN_EMPTY_STRUCT_CTOR(scalar_sign_op) 965 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const 966 { 967 return Scalar( (a>Scalar(0)) - (a<Scalar(0)) ); 968 } 969 //TODO 970 //template <typename Packet> 971 //EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psign(a); } 972 }; 973 974 template<typename Scalar> 975 struct scalar_sign_op<Scalar, false, false> { 976 EIGEN_EMPTY_STRUCT_CTOR(scalar_sign_op) 977 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const 978 { 979 return (numext::isnan)(a) ? a : Scalar( (a>Scalar(0)) - (a<Scalar(0)) ); 980 } 981 //TODO 982 //template <typename Packet> 983 //EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psign(a); } 984 }; 985 986 template<typename Scalar, bool is_integer> 987 struct scalar_sign_op<Scalar,true, is_integer> { 988 EIGEN_EMPTY_STRUCT_CTOR(scalar_sign_op) 989 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const 990 { 991 typedef typename NumTraits<Scalar>::Real real_type; 992 real_type aa = numext::abs(a); 993 if (aa==real_type(0)) 994 return Scalar(0); 995 aa = real_type(1)/aa; 996 return Scalar(a.real()*aa, a.imag()*aa ); 997 } 998 //TODO 999 //template <typename Packet> 1000 //EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psign(a); } 1001 }; 1002 template<typename Scalar> 1003 struct functor_traits<scalar_sign_op<Scalar> > 1004 { enum { 1005 Cost = 1006 NumTraits<Scalar>::IsComplex 1007 ? ( 8*NumTraits<Scalar>::MulCost ) // roughly 1008 : ( 3*NumTraits<Scalar>::AddCost), 1009 PacketAccess = packet_traits<Scalar>::HasSign 1010 }; 1011 }; 1012 1013 /** \internal 1014 * \brief Template functor to compute the logistic function of a scalar 1015 * \sa class CwiseUnaryOp, ArrayBase::logistic() 1016 */ 1017 template <typename T> 1018 struct scalar_logistic_op { 1019 EIGEN_EMPTY_STRUCT_CTOR(scalar_logistic_op) 1020 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T operator()(const T& x) const { 1021 return packetOp(x); 1022 } 1023 1024 template <typename Packet> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 1025 Packet packetOp(const Packet& x) const { 1026 const Packet one = pset1<Packet>(T(1)); 1027 return pdiv(one, padd(one, pexp(pnegate(x)))); 1028 } 1029 }; 1030 1031 #ifndef EIGEN_GPU_COMPILE_PHASE 1032 /** \internal 1033 * \brief Template specialization of the logistic function for float. 1034 * 1035 * Uses just a 9/10-degree rational interpolant which 1036 * interpolates 1/(1+exp(-x)) - 0.5 up to a couple of ulps in the range 1037 * [-9, 18]. Below -9 we use the more accurate approximation 1038 * 1/(1+exp(-x)) ~= exp(x), and above 18 the logistic function is 1 withing 1039 * one ulp. The shifted logistic is interpolated because it was easier to 1040 * make the fit converge. 1041 * 1042 */ 1043 template <> 1044 struct scalar_logistic_op<float> { 1045 EIGEN_EMPTY_STRUCT_CTOR(scalar_logistic_op) 1046 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float operator()(const float& x) const { 1047 return packetOp(x); 1048 } 1049 1050 template <typename Packet> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 1051 Packet packetOp(const Packet& _x) const { 1052 const Packet cutoff_lower = pset1<Packet>(-9.f); 1053 const Packet lt_mask = pcmp_lt<Packet>(_x, cutoff_lower); 1054 const bool any_small = predux_any(lt_mask); 1055 1056 // The upper cut-off is the smallest x for which the rational approximation evaluates to 1. 1057 // Choosing this value saves us a few instructions clamping the results at the end. 1058 #ifdef EIGEN_VECTORIZE_FMA 1059 const Packet cutoff_upper = pset1<Packet>(15.7243833541870117f); 1060 #else 1061 const Packet cutoff_upper = pset1<Packet>(15.6437711715698242f); 1062 #endif 1063 const Packet x = pmin(_x, cutoff_upper); 1064 1065 // The monomial coefficients of the numerator polynomial (odd). 1066 const Packet alpha_1 = pset1<Packet>(2.48287947061529e-01f); 1067 const Packet alpha_3 = pset1<Packet>(8.51377133304701e-03f); 1068 const Packet alpha_5 = pset1<Packet>(6.08574864600143e-05f); 1069 const Packet alpha_7 = pset1<Packet>(1.15627324459942e-07f); 1070 const Packet alpha_9 = pset1<Packet>(4.37031012579801e-11f); 1071 1072 // The monomial coefficients of the denominator polynomial (even). 1073 const Packet beta_0 = pset1<Packet>(9.93151921023180e-01f); 1074 const Packet beta_2 = pset1<Packet>(1.16817656904453e-01f); 1075 const Packet beta_4 = pset1<Packet>(1.70198817374094e-03f); 1076 const Packet beta_6 = pset1<Packet>(6.29106785017040e-06f); 1077 const Packet beta_8 = pset1<Packet>(5.76102136993427e-09f); 1078 const Packet beta_10 = pset1<Packet>(6.10247389755681e-13f); 1079 1080 // Since the polynomials are odd/even, we need x^2. 1081 const Packet x2 = pmul(x, x); 1082 1083 // Evaluate the numerator polynomial p. 1084 Packet p = pmadd(x2, alpha_9, alpha_7); 1085 p = pmadd(x2, p, alpha_5); 1086 p = pmadd(x2, p, alpha_3); 1087 p = pmadd(x2, p, alpha_1); 1088 p = pmul(x, p); 1089 1090 // Evaluate the denominator polynomial q. 1091 Packet q = pmadd(x2, beta_10, beta_8); 1092 q = pmadd(x2, q, beta_6); 1093 q = pmadd(x2, q, beta_4); 1094 q = pmadd(x2, q, beta_2); 1095 q = pmadd(x2, q, beta_0); 1096 // Divide the numerator by the denominator and shift it up. 1097 const Packet logistic = padd(pdiv(p, q), pset1<Packet>(0.5f)); 1098 if (EIGEN_PREDICT_FALSE(any_small)) { 1099 const Packet exponential = pexp(_x); 1100 return pselect(lt_mask, exponential, logistic); 1101 } else { 1102 return logistic; 1103 } 1104 } 1105 }; 1106 #endif // #ifndef EIGEN_GPU_COMPILE_PHASE 1107 1108 template <typename T> 1109 struct functor_traits<scalar_logistic_op<T> > { 1110 enum { 1111 // The cost estimate for float here here is for the common(?) case where 1112 // all arguments are greater than -9. 1113 Cost = scalar_div_cost<T, packet_traits<T>::HasDiv>::value + 1114 (internal::is_same<T, float>::value 1115 ? NumTraits<T>::AddCost * 15 + NumTraits<T>::MulCost * 11 1116 : NumTraits<T>::AddCost * 2 + 1117 functor_traits<scalar_exp_op<T> >::Cost), 1118 PacketAccess = 1119 packet_traits<T>::HasAdd && packet_traits<T>::HasDiv && 1120 (internal::is_same<T, float>::value 1121 ? packet_traits<T>::HasMul && packet_traits<T>::HasMax && 1122 packet_traits<T>::HasMin 1123 : packet_traits<T>::HasNegate && packet_traits<T>::HasExp) 1124 }; 1125 }; 1126 1127 } // end namespace internal 1128 1129 } // end namespace Eigen 1130 1131 #endif // EIGEN_FUNCTORS_H 1132