// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com> // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
/** \internal * * \class TensorIntDiv * \ingroup CXX11_Tensor_Module * * \brief Fast integer division by a constant. * * See the paper from Granlund and Montgomery for explanation. * (at https://doi.org/10.1145/773473.178249) * * \sa Tensor
*/
namespace internal {
namespace {
// Note: result is undefined if val == 0 template <typename T>
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE typename internal::enable_if<sizeof(T)==4,int>::type count_leading_zeros(const T val)
{ #ifdef EIGEN_GPU_COMPILE_PHASE return __clz(val); #elifdefined(SYCL_DEVICE_ONLY) return cl::sycl::clz(val); #elif EIGEN_COMP_MSVC unsignedlong index;
_BitScanReverse(&index, val); return31 - index; #else
EIGEN_STATIC_ASSERT(sizeof(unsignedlonglong) == 8, YOU_MADE_A_PROGRAMMING_MISTAKE); return __builtin_clz(static_cast<uint32_t>(val)); #endif
}
template <typename T>
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE typename internal::enable_if<sizeof(T)==8,int>::type count_leading_zeros(const T val)
{ #ifdef EIGEN_GPU_COMPILE_PHASE return __clzll(val); #elifdefined(SYCL_DEVICE_ONLY) returnstatic_cast<int>(cl::sycl::clz(val)); #elif EIGEN_COMP_MSVC && EIGEN_ARCH_x86_64 unsignedlong index;
_BitScanReverse64(&index, val); return63 - index; #elif EIGEN_COMP_MSVC // MSVC's _BitScanReverse64 is not available for 32bits builds. unsignedint lo = (unsignedint)(val&0xffffffff); unsignedint hi = (unsignedint)((val>>32)&0xffffffff); int n; if(hi==0)
n = 32 + count_leading_zeros<unsignedint>(lo); else
n = count_leading_zeros<unsignedint>(hi); return n; #else
EIGEN_STATIC_ASSERT(sizeof(unsignedlonglong) == 8, YOU_MADE_A_PROGRAMMING_MISTAKE); return __builtin_clzll(static_cast<uint64_t>(val)); #endif
}
// Must have 0 < divider < 2^31. This is relaxed to // 0 < divider < 2^63 when using 64-bit indices on platforms that support // the __uint128_t type.
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorIntDivisor(const T divider) { constint N = DividerTraits<T>::N;
eigen_assert(static_cast<typename UnsignedTraits<T>::type>(divider) < NumTraits<UnsignedType>::highest()/2);
eigen_assert(divider > 0);
// fast ln2 constint leading_zeros = count_leading_zeros(static_cast<UnsignedType>(divider)); int log_div = N - leading_zeros; // if divider is a power of two then log_div is 1 more than it should be. if ((static_cast<typename UnsignedTraits<T>::type>(1) << (log_div-1)) == static_cast<typenameUnsignedTraits<T>::type>(divider))
log_div--;
// Must have 0 <= numerator. On platforms that don't support the __uint128_t // type numerator should also be less than 2^32-1.
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T divide(const T numerator) const {
eigen_assert(static_cast<typename UnsignedTraits<T>::type>(numerator) < NumTraits<UnsignedType>::highest()/2); //eigen_assert(numerator >= 0); // this is implicitly asserted by the line above
// Optimized version for signed 32 bit integers. // Derived from Hacker's Delight. // Only works for divisors strictly greater than one template <> class TensorIntDivisor<int32_t, true> { public:
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorIntDivisor() {
magic = 0;
shift = 0;
} // Must have 2 <= divider
EIGEN_DEVICE_FUNC TensorIntDivisor(int32_t divider) {
eigen_assert(divider >= 2);
calcMagic(divider);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.