// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2016 Benoit Steiner // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_PACKET_MATH_HALF_CUDA_H #define EIGEN_PACKET_MATH_HALF_CUDA_H namespace Eigen { namespace internal { #if defined(EIGEN_HAS_CUDA_FP16) // Make sure this is only available when targeting a GPU: we don't want to // introduce conflicts between these packet_traits definitions and the ones // we'll use on the host side (SSE, AVX, ...) #if defined(__CUDACC__) && defined(EIGEN_USE_GPU) #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530 __device__ half operator + (const half& a, const half& b) { return __hadd(a, b); } __device__ half operator * (const half& a, const half& b) { return __hmul(a, b); } __device__ half operator - (const half& a, const half& b) { return __hsub(a, b); } __device__ half operator / (const half& a, const half& b) { float num = __half2float(a); float denom = __half2float(b); return __float2half(num / denom); } __device__ half operator - (const half& a) { return __hneg(a); } __device__ half operator += (half& a, const half& b) { a = __hadd(a, b); return a; } __device__ half operator *= (half& a, const half& b) { a = __hmul(a, b); return a; } __device__ half operator -= (half& a, const half& b) { a = __hsub(a, b); return a; } __device__ half operator /= (half& a, const half& b) { a = a / b; return a; } template<> struct is_arithmetic { enum { value = true }; }; template<> struct packet_traits : default_packet_traits { typedef half2 type; typedef half2 half; enum { Vectorizable = 1, AlignedOnScalar = 1, size=2, HasHalfPacket = 0, HasDiv = 1, HasLog = 1, HasExp = 1, HasSqrt = 1, HasRsqrt = 1, HasLGamma = 1, HasDiGamma = 1, HasErf = 1, HasErfc = 1, HasBlend = 0, }; }; template<> struct unpacket_traits { typedef half type; enum {size=2, alignment=Aligned16}; typedef half2 half; }; template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pset1(const half& from) { return __half2half2(from); } template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 plset(const half& a) { return __halves2half2(a, __hadd(a, __float2half(1))); } template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 padd(const half2& a, const half2& b) { return __hadd2(a, b); } template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 psub(const half2& a, const half2& b) { return __hsub2(a, b); } template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pnegate(const half2& a) { return __hneg2(a); } template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pconj(const half2& a) { return a; } template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmul(const half2& a, const half2& b) { return __hmul2(a, b); } template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmadd(const half2& a, const half2& b, const half2& c) { return __hfma2(a, b, c); } template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pdiv(const half2& a, const half2& b) { float a1 = __low2float(a); float a2 = __high2float(a); float b1 = __low2float(b); float b2 = __high2float(b); float r1 = a1 / b1; float r2 = a2 / b2; return __floats2half2_rn(r1, r2); } template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmin(const half2& a, const half2& b) { float a1 = __low2float(a); float a2 = __high2float(a); float b1 = __low2float(b); float b2 = __high2float(b); half r1 = a1 < b1 ? __low2half(a) : __low2half(b); half r2 = a2 < b2 ? __high2half(a) : __high2half(b); return __halves2half2(r1, r2); } template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmax(const half2& a, const half2& b) { float a1 = __low2float(a); float a2 = __high2float(a); float b1 = __low2float(b); float b2 = __high2float(b); half r1 = a1 > b1 ? __low2half(a) : __low2half(b); half r2 = a2 > b2 ? __high2half(a) : __high2half(b); return __halves2half2(r1, r2); } template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pload(const half* from) { return *reinterpret_cast(from); } template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 ploadu(const half* from) { return __halves2half2(from[0], from[1]); } template<> EIGEN_STRONG_INLINE half2 ploaddup(const half* from) { return __halves2half2(from[0], from[0]); } template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstore(half* to, const half2& from) { *reinterpret_cast(to) = from; } template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstoreu(half* to, const half2& from) { to[0] = __low2half(from); to[1] = __high2half(from); } template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE half2 ploadt_ro(const half* from) { return __ldg((const half2*)from); } template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE half2 ploadt_ro(const half* from) { return __halves2half2(__ldg(from+0), __ldg(from+1)); } template<> EIGEN_DEVICE_FUNC inline half2 pgather(const half* from, Index stride) { return __halves2half2(from[0*stride], from[1*stride]); } template<> EIGEN_DEVICE_FUNC inline void pscatter(half* to, const half2& from, Index stride) { to[stride*0] = __low2half(from); to[stride*1] = __high2half(from); } template<> EIGEN_DEVICE_FUNC inline half pfirst(const half2& a) { return __low2half(a); } template<> EIGEN_DEVICE_FUNC inline half predux(const half2& a) { return __hadd(__low2half(a), __high2half(a)); } template<> EIGEN_DEVICE_FUNC inline half predux_max(const half2& a) { half first = __low2half(a); half second = __high2half(a); return __hgt(first, second) ? first : second; } template<> EIGEN_DEVICE_FUNC inline half predux_min(const half2& a) { half first = __low2half(a); half second = __high2half(a); return __hlt(first, second) ? first : second; } template<> EIGEN_DEVICE_FUNC inline half predux_mul(const half2& a) { return __hmul(__low2half(a), __high2half(a)); } template<> EIGEN_DEVICE_FUNC inline half2 pabs(const half2& a) { assert(false && "tbd"); return half2(); } EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock& kernel) { assert(false && "tbd"); // half tmp = kernel.packet[0].y; // kernel.packet[0].y = kernel.packet[1].x; // kernel.packet[1].x = tmp; } #endif #endif #endif } // end namespace internal } // end namespace Eigen #endif // EIGEN_PACKET_MATH_HALF_CUDA_H