1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2008-2016 Gael Guennebaud <gael.guennebaud (at) inria.fr> 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 // Copied from unsupported/Eigen/CXX11/src/Tensor/TensorFunctors.h 18 // TODO: remove or update after upstream 19 /** \internal 20 * \brief Template functor to compute the sigmoid of a scalar 21 * \sa class CwiseUnaryOp, ArrayBase::sigmoid() 22 */ 23 template <typename T> 24 struct scalar_sigmoid_op { 25 EIGEN_EMPTY_STRUCT_CTOR(scalar_sigmoid_op) 26 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T operator()(const T& x) const { 27 const T one = T(1); 28 return one / (one + numext::exp(-x)); 29 } 30 31 template <typename Packet> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 32 Packet packetOp(const Packet& x) const { 33 const Packet one = pset1<Packet>(T(1)); 34 return pdiv(one, padd(one, pexp(pnegate(x)))); 35 } 36 }; 37 38 template <typename T> 39 struct functor_traits<scalar_sigmoid_op<T> > { 40 enum { 41 Cost = NumTraits<T>::AddCost * 2 + NumTraits<T>::MulCost * 6, 42 PacketAccess = packet_traits<T>::HasAdd && packet_traits<T>::HasDiv && 43 packet_traits<T>::HasNegate && packet_traits<T>::HasExp 44 }; 45 }; 46 47 48 /** \internal 49 * \brief Template functor to compute the opposite of a scalar 50 * 51 * \sa class CwiseUnaryOp, MatrixBase::operator- 52 */ 53 template<typename Scalar> struct scalar_opposite_op { 54 EIGEN_EMPTY_STRUCT_CTOR(scalar_opposite_op) 55 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return -a; } 56 template<typename Packet> 57 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const 58 { return internal::pnegate(a); } 59 }; 60 template<typename Scalar> 61 struct functor_traits<scalar_opposite_op<Scalar> > 62 { enum { 63 Cost = NumTraits<Scalar>::AddCost, 64 PacketAccess = packet_traits<Scalar>::HasNegate }; 65 }; 66 67 /** \internal 68 * \brief Template functor to compute the absolute value of a scalar 69 * 70 * \sa class CwiseUnaryOp, Cwise::abs 71 */ 72 template<typename Scalar> struct scalar_abs_op { 73 EIGEN_EMPTY_STRUCT_CTOR(scalar_abs_op) 74 typedef typename NumTraits<Scalar>::Real result_type; 75 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return numext::abs(a); } 76 template<typename Packet> 77 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const 78 { return internal::pabs(a); } 79 }; 80 template<typename Scalar> 81 struct functor_traits<scalar_abs_op<Scalar> > 82 { 83 enum { 84 Cost = NumTraits<Scalar>::AddCost, 85 PacketAccess = packet_traits<Scalar>::HasAbs 86 }; 87 }; 88 89 /** \internal 90 * \brief Template functor to compute the score of a scalar, to chose a pivot 91 * 92 * \sa class CwiseUnaryOp 93 */ 94 template<typename Scalar> struct scalar_score_coeff_op : scalar_abs_op<Scalar> 95 { 96 typedef void Score_is_abs; 97 }; 98 template<typename Scalar> 99 struct functor_traits<scalar_score_coeff_op<Scalar> > : functor_traits<scalar_abs_op<Scalar> > {}; 100 101 /* Avoid recomputing abs when we know the score and they are the same. Not a true Eigen functor. */ 102 template<typename Scalar, typename=void> struct abs_knowing_score 103 { 104 EIGEN_EMPTY_STRUCT_CTOR(abs_knowing_score) 105 typedef typename NumTraits<Scalar>::Real result_type; 106 template<typename Score> 107 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a, const Score&) const { return numext::abs(a); } 108 }; 109 template<typename Scalar> struct abs_knowing_score<Scalar, typename scalar_score_coeff_op<Scalar>::Score_is_abs> 110 { 111 EIGEN_EMPTY_STRUCT_CTOR(abs_knowing_score) 112 typedef typename NumTraits<Scalar>::Real result_type; 113 template<typename Scal> 114 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const Scal&, const result_type& a) const { return a; } 115 }; 116 117 /** \internal 118 * \brief Template functor to compute the squared absolute value of a scalar 119 * 120 * \sa class CwiseUnaryOp, Cwise::abs2 121 */ 122 template<typename Scalar> struct scalar_abs2_op { 123 EIGEN_EMPTY_STRUCT_CTOR(scalar_abs2_op) 124 typedef typename NumTraits<Scalar>::Real result_type; 125 EIGEN_DEVICE_FUNC 126 EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return numext::abs2(a); } 127 template<typename Packet> 128 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const 129 { return internal::pmul(a,a); } 130 }; 131 template<typename Scalar> 132 struct functor_traits<scalar_abs2_op<Scalar> > 133 { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasAbs2 }; }; 134 135 /** \internal 136 * \brief Template functor to compute the conjugate of a complex value 137 * 138 * \sa class CwiseUnaryOp, MatrixBase::conjugate() 139 */ 140 template<typename Scalar> struct scalar_conjugate_op { 141 EIGEN_EMPTY_STRUCT_CTOR(scalar_conjugate_op) 142 EIGEN_DEVICE_FUNC 143 EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { using numext::conj; return conj(a); } 144 template<typename Packet> 145 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const { return internal::pconj(a); } 146 }; 147 template<typename Scalar> 148 struct functor_traits<scalar_conjugate_op<Scalar> > 149 { 150 enum { 151 Cost = NumTraits<Scalar>::IsComplex ? NumTraits<Scalar>::AddCost : 0, 152 PacketAccess = packet_traits<Scalar>::HasConj 153 }; 154 }; 155 156 /** \internal 157 * \brief Template functor to compute the phase angle of a complex 158 * 159 * \sa class CwiseUnaryOp, Cwise::arg 160 */ 161 template<typename Scalar> struct scalar_arg_op { 162 EIGEN_EMPTY_STRUCT_CTOR(scalar_arg_op) 163 typedef typename NumTraits<Scalar>::Real result_type; 164 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { using numext::arg; return arg(a); } 165 template<typename Packet> 166 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const 167 { return internal::parg(a); } 168 }; 169 template<typename Scalar> 170 struct functor_traits<scalar_arg_op<Scalar> > 171 { 172 enum { 173 Cost = NumTraits<Scalar>::IsComplex ? 5 * NumTraits<Scalar>::MulCost : NumTraits<Scalar>::AddCost, 174 PacketAccess = packet_traits<Scalar>::HasArg 175 }; 176 }; 177 /** \internal 178 * \brief Template functor to cast a scalar to another type 179 * 180 * \sa class CwiseUnaryOp, MatrixBase::cast() 181 */ 182 template<typename Scalar, typename NewType> 183 struct scalar_cast_op { 184 EIGEN_EMPTY_STRUCT_CTOR(scalar_cast_op) 185 typedef NewType result_type; 186 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const NewType operator() (const Scalar& a) const { return cast<Scalar, NewType>(a); } 187 }; 188 template<typename Scalar, typename NewType> 189 struct functor_traits<scalar_cast_op<Scalar,NewType> > 190 { enum { Cost = is_same<Scalar, NewType>::value ? 0 : NumTraits<NewType>::AddCost, PacketAccess = false }; }; 191 192 /** \internal 193 * \brief Template functor to extract the real part of a complex 194 * 195 * \sa class CwiseUnaryOp, MatrixBase::real() 196 */ 197 template<typename Scalar> 198 struct scalar_real_op { 199 EIGEN_EMPTY_STRUCT_CTOR(scalar_real_op) 200 typedef typename NumTraits<Scalar>::Real result_type; 201 EIGEN_DEVICE_FUNC 202 EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return numext::real(a); } 203 }; 204 template<typename Scalar> 205 struct functor_traits<scalar_real_op<Scalar> > 206 { enum { Cost = 0, PacketAccess = false }; }; 207 208 /** \internal 209 * \brief Template functor to extract the imaginary part of a complex 210 * 211 * \sa class CwiseUnaryOp, MatrixBase::imag() 212 */ 213 template<typename Scalar> 214 struct scalar_imag_op { 215 EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_op) 216 typedef typename NumTraits<Scalar>::Real result_type; 217 EIGEN_DEVICE_FUNC 218 EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return numext::imag(a); } 219 }; 220 template<typename Scalar> 221 struct functor_traits<scalar_imag_op<Scalar> > 222 { enum { Cost = 0, PacketAccess = false }; }; 223 224 /** \internal 225 * \brief Template functor to extract the real part of a complex as a reference 226 * 227 * \sa class CwiseUnaryOp, MatrixBase::real() 228 */ 229 template<typename Scalar> 230 struct scalar_real_ref_op { 231 EIGEN_EMPTY_STRUCT_CTOR(scalar_real_ref_op) 232 typedef typename NumTraits<Scalar>::Real result_type; 233 EIGEN_DEVICE_FUNC 234 EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return numext::real_ref(*const_cast<Scalar*>(&a)); } 235 }; 236 template<typename Scalar> 237 struct functor_traits<scalar_real_ref_op<Scalar> > 238 { enum { Cost = 0, PacketAccess = false }; }; 239 240 /** \internal 241 * \brief Template functor to extract the imaginary part of a complex as a reference 242 * 243 * \sa class CwiseUnaryOp, MatrixBase::imag() 244 */ 245 template<typename Scalar> 246 struct scalar_imag_ref_op { 247 EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_ref_op) 248 typedef typename NumTraits<Scalar>::Real result_type; 249 EIGEN_DEVICE_FUNC 250 EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return numext::imag_ref(*const_cast<Scalar*>(&a)); } 251 }; 252 template<typename Scalar> 253 struct functor_traits<scalar_imag_ref_op<Scalar> > 254 { enum { Cost = 0, PacketAccess = false }; }; 255 256 /** \internal 257 * 258 * \brief Template functor to compute the exponential of a scalar 259 * 260 * \sa class CwiseUnaryOp, Cwise::exp() 261 */ 262 template<typename Scalar> struct scalar_exp_op { 263 EIGEN_EMPTY_STRUCT_CTOR(scalar_exp_op) 264 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::exp(a); } 265 template <typename Packet> 266 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pexp(a); } 267 }; 268 template <typename Scalar> 269 struct functor_traits<scalar_exp_op<Scalar> > { 270 enum { 271 PacketAccess = packet_traits<Scalar>::HasExp, 272 // The following numbers are based on the AVX implementation. 273 #ifdef EIGEN_VECTORIZE_FMA 274 // Haswell can issue 2 add/mul/madd per cycle. 275 Cost = 276 (sizeof(Scalar) == 4 277 // float: 8 pmadd, 4 pmul, 2 padd/psub, 6 other 278 ? (8 * NumTraits<Scalar>::AddCost + 6 * NumTraits<Scalar>::MulCost) 279 // double: 7 pmadd, 5 pmul, 3 padd/psub, 1 div, 13 other 280 : (14 * NumTraits<Scalar>::AddCost + 281 6 * NumTraits<Scalar>::MulCost + 282 scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value)) 283 #else 284 Cost = 285 (sizeof(Scalar) == 4 286 // float: 7 pmadd, 6 pmul, 4 padd/psub, 10 other 287 ? (21 * NumTraits<Scalar>::AddCost + 13 * NumTraits<Scalar>::MulCost) 288 // double: 7 pmadd, 5 pmul, 3 padd/psub, 1 div, 13 other 289 : (23 * NumTraits<Scalar>::AddCost + 290 12 * NumTraits<Scalar>::MulCost + 291 scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value)) 292 #endif 293 }; 294 }; 295 296 /** \internal 297 * 298 * \brief Template functor to compute the logarithm of a scalar 299 * 300 * \sa class CwiseUnaryOp, ArrayBase::log() 301 */ 302 template<typename Scalar> struct scalar_log_op { 303 EIGEN_EMPTY_STRUCT_CTOR(scalar_log_op) 304 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::log(a); } 305 template <typename Packet> 306 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::plog(a); } 307 }; 308 template <typename Scalar> 309 struct functor_traits<scalar_log_op<Scalar> > { 310 enum { 311 PacketAccess = packet_traits<Scalar>::HasLog, 312 Cost = 313 (PacketAccess 314 // The following numbers are based on the AVX implementation. 315 #ifdef EIGEN_VECTORIZE_FMA 316 // 8 pmadd, 6 pmul, 8 padd/psub, 16 other, can issue 2 add/mul/madd per cycle. 317 ? (20 * NumTraits<Scalar>::AddCost + 7 * NumTraits<Scalar>::MulCost) 318 #else 319 // 8 pmadd, 6 pmul, 8 padd/psub, 20 other 320 ? (36 * NumTraits<Scalar>::AddCost + 14 * NumTraits<Scalar>::MulCost) 321 #endif 322 // Measured cost of std::log. 323 : sizeof(Scalar)==4 ? 40 : 85) 324 }; 325 }; 326 327 /** \internal 328 * 329 * \brief Template functor to compute the logarithm of 1 plus a scalar value 330 * 331 * \sa class CwiseUnaryOp, ArrayBase::log1p() 332 */ 333 template<typename Scalar> struct scalar_log1p_op { 334 EIGEN_EMPTY_STRUCT_CTOR(scalar_log1p_op) 335 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::log1p(a); } 336 template <typename Packet> 337 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::plog1p(a); } 338 }; 339 template <typename Scalar> 340 struct functor_traits<scalar_log1p_op<Scalar> > { 341 enum { 342 PacketAccess = packet_traits<Scalar>::HasLog1p, 343 Cost = functor_traits<scalar_log_op<Scalar> >::Cost // TODO measure cost of log1p 344 }; 345 }; 346 347 /** \internal 348 * 349 * \brief Template functor to compute the base-10 logarithm of a scalar 350 * 351 * \sa class CwiseUnaryOp, Cwise::log10() 352 */ 353 template<typename Scalar> struct scalar_log10_op { 354 EIGEN_EMPTY_STRUCT_CTOR(scalar_log10_op) 355 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { EIGEN_USING_STD_MATH(log10) return log10(a); } 356 template <typename Packet> 357 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::plog10(a); } 358 }; 359 template<typename Scalar> 360 struct functor_traits<scalar_log10_op<Scalar> > 361 { enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasLog10 }; }; 362 363 /** \internal 364 * \brief Template functor to compute the square root of a scalar 365 * \sa class CwiseUnaryOp, Cwise::sqrt() 366 */ 367 template<typename Scalar> struct scalar_sqrt_op { 368 EIGEN_EMPTY_STRUCT_CTOR(scalar_sqrt_op) 369 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::sqrt(a); } 370 template <typename Packet> 371 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psqrt(a); } 372 }; 373 template <typename Scalar> 374 struct functor_traits<scalar_sqrt_op<Scalar> > { 375 enum { 376 #if EIGEN_FAST_MATH 377 // The following numbers are based on the AVX implementation. 378 Cost = (sizeof(Scalar) == 8 ? 28 379 // 4 pmul, 1 pmadd, 3 other 380 : (3 * NumTraits<Scalar>::AddCost + 381 5 * NumTraits<Scalar>::MulCost)), 382 #else 383 // The following numbers are based on min VSQRT throughput on Haswell. 384 Cost = (sizeof(Scalar) == 8 ? 28 : 14), 385 #endif 386 PacketAccess = packet_traits<Scalar>::HasSqrt 387 }; 388 }; 389 390 /** \internal 391 * \brief Template functor to compute the reciprocal square root of a scalar 392 * \sa class CwiseUnaryOp, Cwise::rsqrt() 393 */ 394 template<typename Scalar> struct scalar_rsqrt_op { 395 EIGEN_EMPTY_STRUCT_CTOR(scalar_rsqrt_op) 396 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return Scalar(1)/numext::sqrt(a); } 397 template <typename Packet> 398 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::prsqrt(a); } 399 }; 400 401 template<typename Scalar> 402 struct functor_traits<scalar_rsqrt_op<Scalar> > 403 { enum { 404 Cost = 5 * NumTraits<Scalar>::MulCost, 405 PacketAccess = packet_traits<Scalar>::HasRsqrt 406 }; 407 }; 408 409 /** \internal 410 * \brief Template functor to compute the cosine of a scalar 411 * \sa class CwiseUnaryOp, ArrayBase::cos() 412 */ 413 template<typename Scalar> struct scalar_cos_op { 414 EIGEN_EMPTY_STRUCT_CTOR(scalar_cos_op) 415 EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return numext::cos(a); } 416 template <typename Packet> 417 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pcos(a); } 418 }; 419 template<typename Scalar> 420 struct functor_traits<scalar_cos_op<Scalar> > 421 { 422 enum { 423 Cost = 5 * NumTraits<Scalar>::MulCost, 424 PacketAccess = packet_traits<Scalar>::HasCos 425 }; 426 }; 427 428 /** \internal 429 * \brief Template functor to compute the sine of a scalar 430 * \sa class CwiseUnaryOp, ArrayBase::sin() 431 */ 432 template<typename Scalar> struct scalar_sin_op { 433 EIGEN_EMPTY_STRUCT_CTOR(scalar_sin_op) 434 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::sin(a); } 435 template <typename Packet> 436 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psin(a); } 437 }; 438 template<typename Scalar> 439 struct functor_traits<scalar_sin_op<Scalar> > 440 { 441 enum { 442 Cost = 5 * NumTraits<Scalar>::MulCost, 443 PacketAccess = packet_traits<Scalar>::HasSin 444 }; 445 }; 446 447 448 /** \internal 449 * \brief Template functor to compute the tan of a scalar 450 * \sa class CwiseUnaryOp, ArrayBase::tan() 451 */ 452 template<typename Scalar> struct scalar_tan_op { 453 EIGEN_EMPTY_STRUCT_CTOR(scalar_tan_op) 454 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::tan(a); } 455 template <typename Packet> 456 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::ptan(a); } 457 }; 458 template<typename Scalar> 459 struct functor_traits<scalar_tan_op<Scalar> > 460 { 461 enum { 462 Cost = 5 * NumTraits<Scalar>::MulCost, 463 PacketAccess = packet_traits<Scalar>::HasTan 464 }; 465 }; 466 467 /** \internal 468 * \brief Template functor to compute the arc cosine of a scalar 469 * \sa class CwiseUnaryOp, ArrayBase::acos() 470 */ 471 template<typename Scalar> struct scalar_acos_op { 472 EIGEN_EMPTY_STRUCT_CTOR(scalar_acos_op) 473 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::acos(a); } 474 template <typename Packet> 475 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pacos(a); } 476 }; 477 template<typename Scalar> 478 struct functor_traits<scalar_acos_op<Scalar> > 479 { 480 enum { 481 Cost = 5 * NumTraits<Scalar>::MulCost, 482 PacketAccess = packet_traits<Scalar>::HasACos 483 }; 484 }; 485 486 /** \internal 487 * \brief Template functor to compute the arc sine of a scalar 488 * \sa class CwiseUnaryOp, ArrayBase::asin() 489 */ 490 template<typename Scalar> struct scalar_asin_op { 491 EIGEN_EMPTY_STRUCT_CTOR(scalar_asin_op) 492 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::asin(a); } 493 template <typename Packet> 494 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pasin(a); } 495 }; 496 template<typename Scalar> 497 struct functor_traits<scalar_asin_op<Scalar> > 498 { 499 enum { 500 Cost = 5 * NumTraits<Scalar>::MulCost, 501 PacketAccess = packet_traits<Scalar>::HasASin 502 }; 503 }; 504 505 506 /** \internal 507 * \brief Template functor to compute the atan of a scalar 508 * \sa class CwiseUnaryOp, ArrayBase::atan() 509 */ 510 template<typename Scalar> struct scalar_atan_op { 511 EIGEN_EMPTY_STRUCT_CTOR(scalar_atan_op) 512 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::atan(a); } 513 template <typename Packet> 514 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::patan(a); } 515 }; 516 template<typename Scalar> 517 struct functor_traits<scalar_atan_op<Scalar> > 518 { 519 enum { 520 Cost = 5 * NumTraits<Scalar>::MulCost, 521 PacketAccess = packet_traits<Scalar>::HasATan 522 }; 523 }; 524 525 /** \internal 526 * \brief Template functor to compute the tanh of a scalar 527 * \sa class CwiseUnaryOp, ArrayBase::tanh() 528 */ 529 template <typename Scalar> 530 struct scalar_tanh_op { 531 EIGEN_EMPTY_STRUCT_CTOR(scalar_tanh_op) 532 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::tanh(a); } 533 template <typename Packet> 534 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& x) const { return ptanh(x); } 535 }; 536 537 template <typename Scalar> 538 struct functor_traits<scalar_tanh_op<Scalar> > { 539 enum { 540 PacketAccess = packet_traits<Scalar>::HasTanh, 541 Cost = ( (EIGEN_FAST_MATH && is_same<Scalar,float>::value) 542 // The following numbers are based on the AVX implementation, 543 #ifdef EIGEN_VECTORIZE_FMA 544 // Haswell can issue 2 add/mul/madd per cycle. 545 // 9 pmadd, 2 pmul, 1 div, 2 other 546 ? (2 * NumTraits<Scalar>::AddCost + 547 6 * NumTraits<Scalar>::MulCost + 548 scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value) 549 #else 550 ? (11 * NumTraits<Scalar>::AddCost + 551 11 * NumTraits<Scalar>::MulCost + 552 scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value) 553 #endif 554 // This number assumes a naive implementation of tanh 555 : (6 * NumTraits<Scalar>::AddCost + 556 3 * NumTraits<Scalar>::MulCost + 557 2 * scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value + 558 functor_traits<scalar_exp_op<Scalar> >::Cost)) 559 }; 560 }; 561 562 /** \internal 563 * \brief Template functor to compute the sinh of a scalar 564 * \sa class CwiseUnaryOp, ArrayBase::sinh() 565 */ 566 template<typename Scalar> struct scalar_sinh_op { 567 EIGEN_EMPTY_STRUCT_CTOR(scalar_sinh_op) 568 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::sinh(a); } 569 template <typename Packet> 570 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psinh(a); } 571 }; 572 template<typename Scalar> 573 struct functor_traits<scalar_sinh_op<Scalar> > 574 { 575 enum { 576 Cost = 5 * NumTraits<Scalar>::MulCost, 577 PacketAccess = packet_traits<Scalar>::HasSinh 578 }; 579 }; 580 581 /** \internal 582 * \brief Template functor to compute the cosh of a scalar 583 * \sa class CwiseUnaryOp, ArrayBase::cosh() 584 */ 585 template<typename Scalar> struct scalar_cosh_op { 586 EIGEN_EMPTY_STRUCT_CTOR(scalar_cosh_op) 587 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::cosh(a); } 588 template <typename Packet> 589 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pcosh(a); } 590 }; 591 template<typename Scalar> 592 struct functor_traits<scalar_cosh_op<Scalar> > 593 { 594 enum { 595 Cost = 5 * NumTraits<Scalar>::MulCost, 596 PacketAccess = packet_traits<Scalar>::HasCosh 597 }; 598 }; 599 600 /** \internal 601 * \brief Template functor to compute the inverse of a scalar 602 * \sa class CwiseUnaryOp, Cwise::inverse() 603 */ 604 template<typename Scalar> 605 struct scalar_inverse_op { 606 EIGEN_EMPTY_STRUCT_CTOR(scalar_inverse_op) 607 EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return Scalar(1)/a; } 608 template<typename Packet> 609 EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const 610 { return internal::pdiv(pset1<Packet>(Scalar(1)),a); } 611 }; 612 template<typename Scalar> 613 struct functor_traits<scalar_inverse_op<Scalar> > 614 { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasDiv }; }; 615 616 /** \internal 617 * \brief Template functor to compute the square of a scalar 618 * \sa class CwiseUnaryOp, Cwise::square() 619 */ 620 template<typename Scalar> 621 struct scalar_square_op { 622 EIGEN_EMPTY_STRUCT_CTOR(scalar_square_op) 623 EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return a*a; } 624 template<typename Packet> 625 EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const 626 { return internal::pmul(a,a); } 627 }; 628 template<typename Scalar> 629 struct functor_traits<scalar_square_op<Scalar> > 630 { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; }; 631 632 /** \internal 633 * \brief Template functor to compute the cube of a scalar 634 * \sa class CwiseUnaryOp, Cwise::cube() 635 */ 636 template<typename Scalar> 637 struct scalar_cube_op { 638 EIGEN_EMPTY_STRUCT_CTOR(scalar_cube_op) 639 EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return a*a*a; } 640 template<typename Packet> 641 EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const 642 { return internal::pmul(a,pmul(a,a)); } 643 }; 644 template<typename Scalar> 645 struct functor_traits<scalar_cube_op<Scalar> > 646 { enum { Cost = 2*NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; }; 647 648 /** \internal 649 * \brief Template functor to compute the rounded value of a scalar 650 * \sa class CwiseUnaryOp, ArrayBase::round() 651 */ 652 template<typename Scalar> struct scalar_round_op { 653 EIGEN_EMPTY_STRUCT_CTOR(scalar_round_op) 654 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return numext::round(a); } 655 template <typename Packet> 656 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pround(a); } 657 }; 658 template<typename Scalar> 659 struct functor_traits<scalar_round_op<Scalar> > 660 { 661 enum { 662 Cost = NumTraits<Scalar>::MulCost, 663 PacketAccess = packet_traits<Scalar>::HasRound 664 }; 665 }; 666 667 /** \internal 668 * \brief Template functor to compute the floor of a scalar 669 * \sa class CwiseUnaryOp, ArrayBase::floor() 670 */ 671 template<typename Scalar> struct scalar_floor_op { 672 EIGEN_EMPTY_STRUCT_CTOR(scalar_floor_op) 673 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return numext::floor(a); } 674 template <typename Packet> 675 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pfloor(a); } 676 }; 677 template<typename Scalar> 678 struct functor_traits<scalar_floor_op<Scalar> > 679 { 680 enum { 681 Cost = NumTraits<Scalar>::MulCost, 682 PacketAccess = packet_traits<Scalar>::HasFloor 683 }; 684 }; 685 686 /** \internal 687 * \brief Template functor to compute the ceil of a scalar 688 * \sa class CwiseUnaryOp, ArrayBase::ceil() 689 */ 690 template<typename Scalar> struct scalar_ceil_op { 691 EIGEN_EMPTY_STRUCT_CTOR(scalar_ceil_op) 692 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return numext::ceil(a); } 693 template <typename Packet> 694 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pceil(a); } 695 }; 696 template<typename Scalar> 697 struct functor_traits<scalar_ceil_op<Scalar> > 698 { 699 enum { 700 Cost = NumTraits<Scalar>::MulCost, 701 PacketAccess = packet_traits<Scalar>::HasCeil 702 }; 703 }; 704 705 /** \internal 706 * \brief Template functor to compute whether a scalar is NaN 707 * \sa class CwiseUnaryOp, ArrayBase::isnan() 708 */ 709 template<typename Scalar> struct scalar_isnan_op { 710 EIGEN_EMPTY_STRUCT_CTOR(scalar_isnan_op) 711 typedef bool result_type; 712 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return (numext::isnan)(a); } 713 }; 714 template<typename Scalar> 715 struct functor_traits<scalar_isnan_op<Scalar> > 716 { 717 enum { 718 Cost = NumTraits<Scalar>::MulCost, 719 PacketAccess = false 720 }; 721 }; 722 723 /** \internal 724 * \brief Template functor to check whether a scalar is +/-inf 725 * \sa class CwiseUnaryOp, ArrayBase::isinf() 726 */ 727 template<typename Scalar> struct scalar_isinf_op { 728 EIGEN_EMPTY_STRUCT_CTOR(scalar_isinf_op) 729 typedef bool result_type; 730 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return (numext::isinf)(a); } 731 }; 732 template<typename Scalar> 733 struct functor_traits<scalar_isinf_op<Scalar> > 734 { 735 enum { 736 Cost = NumTraits<Scalar>::MulCost, 737 PacketAccess = false 738 }; 739 }; 740 741 /** \internal 742 * \brief Template functor to check whether a scalar has a finite value 743 * \sa class CwiseUnaryOp, ArrayBase::isfinite() 744 */ 745 template<typename Scalar> struct scalar_isfinite_op { 746 EIGEN_EMPTY_STRUCT_CTOR(scalar_isfinite_op) 747 typedef bool result_type; 748 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return (numext::isfinite)(a); } 749 }; 750 template<typename Scalar> 751 struct functor_traits<scalar_isfinite_op<Scalar> > 752 { 753 enum { 754 Cost = NumTraits<Scalar>::MulCost, 755 PacketAccess = false 756 }; 757 }; 758 759 /** \internal 760 * \brief Template functor to compute the logical not of a boolean 761 * 762 * \sa class CwiseUnaryOp, ArrayBase::operator! 763 */ 764 template<typename Scalar> struct scalar_boolean_not_op { 765 EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_not_op) 766 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a) const { return !a; } 767 }; 768 template<typename Scalar> 769 struct functor_traits<scalar_boolean_not_op<Scalar> > { 770 enum { 771 Cost = NumTraits<bool>::AddCost, 772 PacketAccess = false 773 }; 774 }; 775 776 /** \internal 777 * \brief Template functor to compute the signum of a scalar 778 * \sa class CwiseUnaryOp, Cwise::sign() 779 */ 780 template<typename Scalar,bool iscpx=(NumTraits<Scalar>::IsComplex!=0) > struct scalar_sign_op; 781 template<typename Scalar> 782 struct scalar_sign_op<Scalar,false> { 783 EIGEN_EMPTY_STRUCT_CTOR(scalar_sign_op) 784 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const 785 { 786 return Scalar( (a>Scalar(0)) - (a<Scalar(0)) ); 787 } 788 //TODO 789 //template <typename Packet> 790 //EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psign(a); } 791 }; 792 template<typename Scalar> 793 struct scalar_sign_op<Scalar,true> { 794 EIGEN_EMPTY_STRUCT_CTOR(scalar_sign_op) 795 EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const 796 { 797 typedef typename NumTraits<Scalar>::Real real_type; 798 real_type aa = numext::abs(a); 799 if (aa==real_type(0)) 800 return Scalar(0); 801 aa = real_type(1)/aa; 802 return Scalar(real(a)*aa, imag(a)*aa ); 803 } 804 //TODO 805 //template <typename Packet> 806 //EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psign(a); } 807 }; 808 template<typename Scalar> 809 struct functor_traits<scalar_sign_op<Scalar> > 810 { enum { 811 Cost = 812 NumTraits<Scalar>::IsComplex 813 ? ( 8*NumTraits<Scalar>::MulCost ) // roughly 814 : ( 3*NumTraits<Scalar>::AddCost), 815 PacketAccess = packet_traits<Scalar>::HasSign 816 }; 817 }; 818 819 } // end namespace internal 820 821 } // end namespace Eigen 822 823 #endif // EIGEN_FUNCTORS_H 824