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