28 #ifndef YB_INC_ystdex_rational_hpp_
29 #define YB_INC_ystdex_rational_hpp_ 1
44 template<
typename _type, std::uintmax_t _vNum = 1, std::uintmax_t _vDen = 1,
45 bool _bIsFloat = is_floating_point<_type>::value>
48 template<
typename _type, std::u
intmax_t _vNum, std::u
intmax_t _vDen>
61 template<
typename _type, std::u
intmax_t _vNum, std::u
intmax_t _vDen>
64 static yconstexpr _type value = std::numeric_limits<_type>::max();
82 template<
typename _type>
84 : integral_constant<bool, is_floating_point<_type>::value>
98 template<
typename _type>
102 _type>::value << 1>::type, is_signed<_type>::value>
::type;
136 template<
typename _tBase = std::int32_t,
137 size_t _vInt = std::numeric_limits<_tBase>::digits - 6U,
138 size_t _vFrac = std::numeric_limits<_tBase>::digits - _vInt>
141 static_assert(is_integral<_tBase>::value,
"Non-integral type found.");
142 static_assert(_vInt <
size_t(std::numeric_limits<_tBase>::digits),
143 "No sufficient fractional bits found.");
144 static_assert(_vInt + _vFrac ==
size_t(std::numeric_limits<_tBase>::digits),
145 "Wrong total bits found.");
147 template<
typename _OtherBase,
size_t _vOtherInt,
size_t _vOtherFrac>
149 friend class std::numeric_limits<
fixed_point<_tBase, _vInt, _vFrac>>;
179 template<
typename _tInt>
185 template<
typename _tFloat>
193 template<
typename _tFirst,
typename _tSecond>
196 && !is_same<_tSecond, raw_tag>::value, _tFirst*> = {})
199 template<
typename _tFirst,
typename _tSecond>
202 ::
value && !is_same<_tSecond, raw_tag>::value, _tFirst*> = {})
208 template<
size_t _vOtherInt,
size_t _vOtherFrac>
214 template<
size_t _vOtherInt,
size_t _vOtherFrac>
220 template<
typename _tOtherBase,
size_t _vOtherInt,
size_t _vOtherFrac>
226 template<
typename _tOtherBase,
size_t _vOtherInt,
size_t _vOtherFrac>
232 template<
typename _tOtherBase,
size_t _vOtherInt,
size_t _vOtherFrac>
298 value = mul<frac_bit_n + is_signed<base_type>::value>(
value,
299 f.
value, integral_constant<bool, is_signed<
327 template<
typename _type,
330 operator _type()
const
332 return this->cast<_type>();
344 template<
typename _type>
351 template<
typename _type>
358 template<
size_t _vShiftBits>
362 return mul_signed<_vShiftBits>(
365 template<
size_t _vShiftBits>
376 template<
size_t _vShiftBits>
380 return tmp < 0 ? -(-tmp >> _vShiftBits) : tmp >> _vShiftBits;
409 return x.
value < 0 ? -x : x;
434 #define YB_FIX_POINT_TMPL_HEAD_2 \
435 template<typename _tBase1, size_t _vInt1, size_t _vFrac1, \
436 typename _tBase2, size_t _vInt2, size_t _vFrac2>
437 #define YB_FIX_POINT_TMPL_OP_2_PARAMS_BODY(_op) \
439 operator _op(const fixed_point<_tBase1, _vInt1, _vFrac1> x, \
440 const fixed_point<_tBase2, _vInt2, _vFrac2>& y) \
442 using result_type = common_type_t<fixed_point<_tBase1, _vInt1, \
443 _vFrac1>, fixed_point<_tBase2, _vInt2, _vFrac2>>; \
445 return result_type(x) _op result_type(y); \
454 #define YB_FIX_POINT_ARITHMETIC_2(_op) \
456 YB_FIX_POINT_TMPL_HEAD_2 \
457 yconstfn common_type_t<fixed_point<_tBase1, _vInt1, _vFrac1>, \
458 fixed_point<_tBase2, _vInt2, _vFrac2>> \
459 YB_FIX_POINT_TMPL_OP_2_PARAMS_BODY(_op)
466 #undef YB_FIX_POINT_ARITHMETIC_2
475 #define YB_FIX_POINT_RATIONAL_2(_op) \
477 YB_FIX_POINT_TMPL_HEAD_2 \
479 YB_FIX_POINT_TMPL_OP_2_PARAMS_BODY(_op)
488 #undef YB_FIX_POINT_RATIONAL_2
491 #undef YB_FIX_POINT_TMPL_HEAD_2
492 #undef YB_FIX_POINT_TMPL_OP_2_PARAMS_BODY
500 template<
typename _tBase,
size_t _vInt,
size_t _vFrac>
510 template<
typename _tBase,
size_t _vInt,
size_t _vFrac>
525 template<
typename _tBase1,
size_t _vInt1,
size_t _vFrac1,
typename _tBase2,
526 size_t _vInt2,
size_t _vFrac2>
527 struct common_type<ystdex::fixed_point<_tBase1, _vInt1, _vFrac1>,
533 static yconstexpr size_t int_size = _vInt1 < _vInt2 ? _vInt2 : _vInt1;
537 std::numeric_limits<common_base_type>::digits - int_size>;
545 template<
typename _tBase, ystdex::
size_t _vInt, ystdex::
size_t _vFrac>
546 class numeric_limits<ystdex::fixed_point<_tBase, _vInt, _vFrac>>
558 return fp_type(std::numeric_limits<base_type>::min(),
565 return fp_type(std::numeric_limits<base_type>::max(),
578 static yconstexpr bool is_signed = numeric_limits<base_type>::is_signed;
603 static yconstexpr float_denorm_style has_denorm = denorm_absent;
632 static yconstexpr bool is_modulo = numeric_limits<base_type>::is_modulo;
634 static yconstexpr bool traps = numeric_limits<base_type>::traps;
636 static yconstexpr float_round_style round_style = round_toward_zero;
fixed_point & operator-=(const fixed_point &f)
bool operator==(const fixed_point &f) const
static const size_t frac_bit_n
小数部分二进制位数。
fixed_point(_tFloat val, enable_if_t< is_floating_point< _tFloat >::value, _tFloat * >={})
fixed_point(const fixed_point< base_type, _vOtherInt, _vOtherFrac > &f, enable_if_t<(_vOtherInt< int_bit_n), base_type * >={})
fixed_point & operator/=(const fixed_point &f)
friend fixed_point ceil(fixed_point x)
static const size_t digit_bit_n
非符号位的二进制位数。
bool operator<(const fixed_point &f) const
static fp_type denorm_min()
ystdex::common_type_t< _tBase1, _tBase2 > common_base_type
static base_type mul(base_type x, base_type y, false_type)
fixed_point & operator--()
fixed_point & operator+=(const fixed_point &f)
fixed_point & operator++()
#define YB_FIX_POINT_RATIONAL_2(_op)
不同模板参数的二元关系操作符。
fixed_point(_tFirst x, _tSecond y, enable_if_t< is_integral< _tFirst >::value &&!is_same< _tSecond, raw_tag >::value, _tFirst * >={})
fixed_point & operator>>=(size_t s)
friend fixed_point round(fixed_point x)
typename fp_type::base_type base_type
enable_if_t< is_floating_point< _type >::value, _type > cast() const
fixed_point(const fixed_point< base_type, _vOtherInt, _vOtherFrac > &f, enable_if_t<(int_bit_n< _vOtherInt), base_type * >={})
#define ynothrow
YSLib 无异常抛出保证:若支持 noexcept 关键字, 指定特定的 noexcept 异常规范。
取指定整数类型和条件表达式对应的有符号或无符号整数类型。
fixed_point(base_type v, raw_tag)
enable_if_t< is_integral< _type >::value, _type > cast() const
fixed_point(_tFirst x, _tSecond y, enable_if_t< is_floating_point< _tFirst >::value &&!is_same< _tSecond, raw_tag >::value, _tFirst * >={})
#define YB_FIX_POINT_ARITHMETIC_2(_op)
不同模板参数的二元算术操作符。
friend fixed_point fabs(fixed_point x)
#define yconstfn
指定编译时常量函数。
static base_type mul(base_type x, base_type y, true_type)
typename make_signed_c< typename make_width_int< integer_width< _type >::value<< 1 >::type, is_signed< _type >::value >::type type
fixed_point & operator<<=(size_t s)
friend fixed_point floor(fixed_point x)
static fp_type signaling_NaN()
fixed_point(const fixed_point< _tOtherBase, _vOtherInt, _vOtherFrac > &f, enable_if_t<(_vOtherFrac< frac_bit_n), base_type * >={})
#define yconstexpr
指定编译时常量表达式。
static fp_type infinity()
fixed_point(const fixed_point< _tOtherBase, _vOtherInt, _vOtherFrac > &f, enable_if_t<(frac_bit_n< _vOtherFrac), base_type * >={})
empty_base<> raw_tag
直接构造类型(直接构造重载用)。
fixed_point(const fixed_point< _tOtherBase, _vOtherInt, _vOtherFrac > &f, enable_if_t<(frac_bit_n==_vOtherFrac), base_type * >={})
fixed_point & operator*=(const fixed_point &f)
static fp_type quiet_NaN()
static const size_t int_bit_n
整数部分二进制位数。
fixed_point(_tInt val, enable_if_t< is_integral< _tInt >::value, _tInt * >={})
typename enable_if< _bCond, _type >::type enable_if_t
static base_type mul_signed(typename fixed_multiplicative< base_type >::type tmp)
static fixed_point identity()
取单位元。
fixed_point operator-() const
typename common_type< _types...>::type common_type_t
static base_type base_element()
取 base_type 表达的单位元。
static fp_type round_error()