19 #include <cudf/detail/utilities/assert.cuh>
20 #include <cudf/fixed_point/temporary.hpp>
23 #include <cuda/std/limits>
24 #include <cuda/std/type_traits>
25 #include <cuda/std/utility>
54 enum class Radix : int32_t { BASE_2 = 2, BASE_10 = 10 };
65 return cuda::std::is_same_v<T, int32_t> ||
66 cuda::std::is_same_v<T, int64_t> ||
67 cuda::std::is_same_v<T, __int128_t>;
87 return scale_type{
min(
static_cast<int>(a),
static_cast<int>(b))};
89 return std::min(a, b);
101 template <
typename Rep,
104 typename cuda::std::enable_if_t<(cuda::std::is_same_v<int32_t, T> &&
105 cuda::std::is_integral_v<Rep>)>* =
nullptr>
108 cudf_assert(exponent >= 0 &&
"integer exponentiation with negative exponent is not possible.");
110 if constexpr (Base == numeric::Radix::BASE_2) {
return static_cast<Rep
>(1) << exponent; }
116 if (exponent == 0) {
return static_cast<Rep
>(1); }
117 auto extra =
static_cast<Rep
>(1);
118 auto square =
static_cast<Rep
>(Base);
119 while (exponent > 1) {
120 if (exponent & 1) { extra *= square; }
124 return square * extra;
138 template <
typename Rep, Radix Rad,
typename T>
141 return val / ipow<Rep, Rad>(
static_cast<int32_t
>(scale));
155 template <
typename Rep, Radix Rad,
typename T>
158 return val * ipow<Rep, Rad>(
static_cast<int32_t
>(-scale));
174 template <
typename Rep, Radix Rad,
typename T>
177 if (scale == 0) {
return val; }
178 if (scale > 0) {
return right_shift<Rep, Rad>(val, scale); }
179 return left_shift<Rep, Rad>(val, scale);
202 template <
typename Rep,
203 typename cuda::std::enable_if_t<is_supported_representation_type<Rep>()>* =
nullptr>
225 template <
typename Rep, Radix Rad>
232 static constexpr
auto rad = Rad;
242 template <
typename T,
243 typename cuda::std::enable_if_t<cuda::std::is_integral_v<T> &&
244 is_supported_representation_type<Rep>()>* =
nullptr>
248 : _value{detail::shift<Rep, Rad>(static_cast<Rep>(value), scale)}, _scale{scale}
258 : _value{s.value}, _scale{s.scale}
269 template <
typename T,
typename cuda::std::enable_if_t<cuda::std::is_
integral_v<T>>* =
nullptr>
271 : _value{static_cast<Rep>(value)}, _scale{
scale_type{0}}
287 template <
typename U,
typename cuda::std::enable_if_t<cuda::std::is_
integral_v<U>>* =
nullptr>
293 auto const value = cuda::std::common_type_t<U, Rep>(_value);
294 return static_cast<U
>(detail::shift<Rep, Rad>(value,
scale_type{-_scale}));
328 return static_cast<bool>(_value);
339 template <
typename Rep1, Radix Rad1>
354 template <
typename Rep1, Radix Rad1>
369 template <
typename Rep1, Radix Rad1>
384 template <
typename Rep1, Radix Rad1>
415 template <
typename Rep1, Radix Rad1>
432 template <
typename Rep1, Radix Rad1>
447 template <
typename Rep1, Radix Rad1>
462 template <
typename Rep1, Radix Rad1>
479 template <
typename Rep1, Radix Rad1>
496 template <
typename Rep1, Radix Rad1>
513 template <
typename Rep1, Radix Rad1>
530 template <
typename Rep1, Radix Rad1>
547 template <
typename Rep1, Radix Rad1>
564 template <
typename Rep1, Radix Rad1>
581 template <
typename Rep1, Radix Rad1>
596 if (scale == _scale) {
return *
this; }
597 Rep
const value = detail::shift<Rep, Rad>(_value,
scale_type{scale - _scale});
604 explicit operator std::string()
const
607 auto const av = detail::abs(_value);
608 Rep
const n = detail::exp10<Rep>(-_scale);
609 Rep
const f = av % n;
610 auto const num_zeros =
611 std::max(0, (-_scale -
static_cast<int32_t
>(detail::to_string(f).size())));
612 auto const zeros = std::string(num_zeros,
'0');
613 auto const sign = _value < 0 ? std::string(
"-") : std::string();
614 return sign + detail::to_string(av / n) + std::string(
".") + zeros +
615 detail::to_string(av % n);
617 auto const zeros = std::string(_scale,
'0');
618 return detail::to_string(_value) + zeros;
631 template <
typename Rep,
typename T>
634 return rhs > 0 ? lhs > cuda::std::numeric_limits<Rep>::max() - rhs
635 : lhs < cuda::std::numeric_limits<Rep>::min() - rhs;
646 template <
typename Rep,
typename T>
649 return rhs > 0 ? lhs < cuda::std::numeric_limits<Rep>::min() + rhs
650 : lhs > cuda::std::numeric_limits<Rep>::max() + rhs;
661 template <
typename Rep,
typename T>
664 return lhs == cuda::std::numeric_limits<Rep>::min() && rhs == -1;
675 template <
typename Rep,
typename T>
678 auto const min = cuda::std::numeric_limits<Rep>::min();
679 auto const max = cuda::std::numeric_limits<Rep>::max();
680 if (rhs > 0) {
return lhs > max / rhs || lhs < min / rhs; }
681 if (rhs < -1) {
return lhs > min / rhs || lhs < max / rhs; }
682 return rhs == -1 && lhs == min;
686 template <
typename Rep1, Radix Rad1>
690 auto const scale = detail::min(lhs._scale, rhs._scale);
693 #if defined(__CUDACC_DEBUG__)
695 assert(!addition_overflow<Rep1>(lhs.
rescaled(scale)._value, rhs.
rescaled(scale)._value) &&
696 "fixed_point overflow");
704 template <
typename Rep1, Radix Rad1>
708 auto const scale = detail::min(lhs._scale, rhs._scale);
711 #if defined(__CUDACC_DEBUG__)
713 assert(!subtraction_overflow<Rep1>(lhs.
rescaled(scale)._value, rhs.
rescaled(scale)._value) &&
714 "fixed_point overflow");
722 template <
typename Rep1, Radix Rad1>
726 #if defined(__CUDACC_DEBUG__)
728 assert(!multiplication_overflow<Rep1>(lhs._value, rhs._value) &&
"fixed_point overflow");
737 template <
typename Rep1, Radix Rad1>
741 #if defined(__CUDACC_DEBUG__)
743 assert(!division_overflow<Rep1>(lhs._value, rhs._value) &&
"fixed_point overflow");
752 template <
typename Rep1, Radix Rad1>
756 auto const scale = detail::min(lhs._scale, rhs._scale);
761 template <
typename Rep1, Radix Rad1>
765 auto const scale = detail::min(lhs._scale, rhs._scale);
770 template <
typename Rep1, Radix Rad1>
774 auto const scale = detail::min(lhs._scale, rhs._scale);
779 template <
typename Rep1, Radix Rad1>
783 auto const scale = detail::min(lhs._scale, rhs._scale);
788 template <
typename Rep1, Radix Rad1>
792 auto const scale = detail::min(lhs._scale, rhs._scale);
797 template <
typename Rep1, Radix Rad1>
801 auto const scale = detail::min(lhs._scale, rhs._scale);
806 template <
typename Rep1, Radix Rad1>
810 auto const scale = detail::min(lhs._scale, rhs._scale);
811 auto const remainder = lhs.
rescaled(scale)._value % rhs.
rescaled(scale)._value;
CUDF_HOST_DEVICE fixed_point(scaled_integer< Rep > s)
不执行移位操作的构造函数(假定值已被移位)
CUDF_HOST_DEVICE fixed_point< Rep, Rad > rescaled(scale_type scale) const
创建具有新刻度的 fixed_point 数的方法
CUDF_HOST_DEVICE rep value() const
返回 fixed_point 数底层值的方法。
CUDF_HOST_DEVICE fixed_point< Rep1, Rad1 > & operator*=(fixed_point< Rep1, Rad1 > const &rhs)
operator *=
CUDF_HOST_DEVICE scale_type scale() const
返回 fixed_point 数刻度的方法。
CUDF_HOST_DEVICE fixed_point(T const &value)
“无刻度”构造函数,使用指定值和零刻度构造 fixed_point 数
CUDF_HOST_DEVICE fixed_point< Rep1, Rad1 > & operator-=(fixed_point< Rep1, Rad1 > const &rhs)
operator -=
CUDF_HOST_DEVICE fixed_point< Rep1, Rad1 > & operator+=(fixed_point< Rep1, Rad1 > const &rhs)
operator +=
CUDF_HOST_DEVICE fixed_point()
默认构造函数,构造值为零、刻度为零的 fixed_point 数。
CUDF_HOST_DEVICE fixed_point< Rep1, Rad1 > & operator/=(fixed_point< Rep1, Rad1 > const &rhs)
operator /=
CUDF_HOST_DEVICE fixed_point(T const &value, scale_type const &scale)
构造函数,将执行移位以适当存储值(从整数类型)
CUDF_HOST_DEVICE fixed_point< Rep, Rad > & operator++()
operator ++ (后置自增)
constexpr CUDF_HOST_DEVICE scale_type min(scale_type const &a, scale_type const &b)
返回给定刻度中较小的一个。
constexpr CUDF_HOST_DEVICE T left_shift(T const &val, scale_type const &scale)
对 val 执行 scale “次” 左移的函数
constexpr CUDF_HOST_DEVICE Rep ipow(T exponent)
用于通过平方进行整数幂运算的函数。
constexpr CUDF_HOST_DEVICE T right_shift(T const &val, scale_type const &scale)
对 val 执行 scale “次” 右移的函数
Radix
构造 fixed_point 时使用的作用域枚举器
CUDF_HOST_DEVICE fixed_point< Rep1, Rad1 > operator-(fixed_point< Rep1, Rad1 > const &lhs, fixed_point< Rep1, Rad1 > const &rhs)
CUDF_HOST_DEVICE bool operator>=(fixed_point< Rep1, Rad1 > const &lhs, fixed_point< Rep1, Rad1 > const &rhs)
CUDF_HOST_DEVICE bool operator<=(fixed_point< Rep1, Rad1 > const &lhs, fixed_point< Rep1, Rad1 > const &rhs)
CUDF_HOST_DEVICE bool operator==(fixed_point< Rep1, Rad1 > const &lhs, fixed_point< Rep1, Rad1 > const &rhs)
CUDF_HOST_DEVICE fixed_point< Rep1, Rad1 > operator%(fixed_point< Rep1, Rad1 > const &lhs, fixed_point< Rep1, Rad1 > const &rhs)
CUDF_HOST_DEVICE auto division_overflow(T lhs, T rhs)
用于识别除法中的整数溢出的函数。
CUDF_HOST_DEVICE fixed_point< Rep1, Rad1 > operator/(fixed_point< Rep1, Rad1 > const &lhs, fixed_point< Rep1, Rad1 > const &rhs)
scale_type
fixed_point 的刻度类型。
CUDF_HOST_DEVICE fixed_point< Rep1, Rad1 > operator*(fixed_point< Rep1, Rad1 > const &lhs, fixed_point< Rep1, Rad1 > const &rhs)
CUDF_HOST_DEVICE bool operator>(fixed_point< Rep1, Rad1 > const &lhs, fixed_point< Rep1, Rad1 > const &rhs)
CUDF_HOST_DEVICE auto addition_overflow(T lhs, T rhs)
用于识别加法中的整数溢出的函数。
CUDF_HOST_DEVICE fixed_point< Rep1, Rad1 > operator+(fixed_point< Rep1, Rad1 > const &lhs, fixed_point< Rep1, Rad1 > const &rhs)
CUDF_HOST_DEVICE auto multiplication_overflow(T lhs, T rhs)
用于识别乘法中的整数溢出的函数。
constexpr CUDF_HOST_DEVICE auto is_supported_representation_type()
如果 fixed_point 支持表示类型,则返回 true
CUDF_HOST_DEVICE bool operator!=(fixed_point< Rep1, Rad1 > const &lhs, fixed_point< Rep1, Rad1 > const &rhs)
CUDF_HOST_DEVICE auto subtraction_overflow(T lhs, T rhs)
用于识别减法中的整数溢出的函数。
CUDF_HOST_DEVICE bool operator<(fixed_point< Rep1, Rad1 > const &lhs, fixed_point< Rep1, Rad1 > const &rhs)
用于在值已移位时构造 fixed_point 的辅助结构体。
Rep value
fixed_point 数的值。
CUDF_HOST_DEVICE scaled_integer(Rep v, scale_type s)
scaled_integer 的构造函数
#define CUDF_HOST_DEVICE
指示函数或方法可在主机和设备上使用。