10 #if !defined(SG14_FIXED_POINT_OPERATORS_H) 11 #define SG14_FIXED_POINT_OPERATORS_H 1 13 #include "fixed_point_arithmetic.h" 22 template<
class RhsRep,
int RhsExponent>
23 constexpr
auto operator-(
const fixed_point<RhsRep, RhsExponent>& rhs)
24 -> fixed_point<decltype(-rhs.data()), RhsExponent>
26 using result_type = fixed_point<decltype(-rhs.data()), RhsExponent>;
27 return result_type::from_data(-rhs.data());
32 class LhsRep,
int LhsExponent,
33 class RhsRep,
int RhsExponent>
34 constexpr
auto operator+(
35 const fixed_point<LhsRep, LhsExponent>& lhs,
36 const fixed_point<RhsRep, RhsExponent>& rhs)
37 -> decltype(_impl::fp::operate<_impl::fp::arithmetic_operator_tag>(lhs, rhs, _impl::add_tag))
39 return _impl::fp::operate<_impl::fp::arithmetic_operator_tag>(lhs, rhs, _impl::add_tag);
44 class LhsRep,
int LhsExponent,
45 class RhsRep,
int RhsExponent>
46 constexpr
auto operator-(
47 const fixed_point<LhsRep, LhsExponent>& lhs,
48 const fixed_point<RhsRep, RhsExponent>& rhs)
49 -> decltype(_impl::fp::operate<_impl::fp::arithmetic_operator_tag>(lhs, rhs, _impl::subtract_tag))
51 return _impl::fp::operate<_impl::fp::arithmetic_operator_tag>(lhs, rhs, _impl::subtract_tag);
56 class LhsRep,
int LhsExponent,
57 class RhsRep,
int RhsExponent>
58 constexpr
auto operator*(
59 const fixed_point<LhsRep, LhsExponent>& lhs,
60 const fixed_point<RhsRep, RhsExponent>& rhs)
61 -> decltype(_impl::fp::operate<_impl::fp::arithmetic_operator_tag>(lhs, rhs, _impl::multiply_tag))
63 return _impl::fp::operate<_impl::fp::arithmetic_operator_tag>(lhs, rhs, _impl::multiply_tag);
67 template<
class LhsRep,
int LhsExponent,
class RhsRep,
int RhsExponent>
68 constexpr
auto operator/(
69 const fixed_point<LhsRep, LhsExponent>& lhs,
70 const fixed_point<RhsRep, RhsExponent>& rhs)
71 -> decltype(_impl::fp::operate<_impl::fp::division_arithmetic_operator_tag>(lhs, rhs, _impl::divide_tag))
73 return _impl::fp::operate<_impl::fp::division_arithmetic_operator_tag>(lhs, rhs, _impl::divide_tag);
81 namespace _fixed_point_operators_impl {
82 template<
class Lhs,
class Rhs>
83 constexpr
bool is_heterogeneous() {
84 return (!std::is_same<Lhs, Rhs>::value) &&
85 (_impl::is_fixed_point<Lhs>::value || _impl::is_fixed_point<Rhs>::value);
91 class Operator,
class Lhs,
class Rhs,
92 class = _impl::enable_if_t<Operator::is_comparison && sg14::_fixed_point_operators_impl::is_heterogeneous<Lhs, Rhs>()>>
93 constexpr
auto operate(
const Lhs& lhs,
const Rhs& rhs, Operator op)
94 -> decltype(op(
static_cast<_impl::common_type_t<Lhs, Rhs>
>(lhs),
static_cast<_impl::common_type_t<Lhs, Rhs>
>(rhs)))
96 return op(
static_cast<_impl::common_type_t<Lhs, Rhs>
>(lhs),
static_cast<_impl::common_type_t<Lhs, Rhs>
>(rhs));
99 template<
class Operator,
class Rep,
int Exponent,
class = _impl::enable_if_t<Operator::is_comparison>>
100 constexpr
auto operate(
const fixed_point<Rep, Exponent>& lhs,
const fixed_point<Rep, Exponent>& rhs, Operator op)
101 -> decltype(op(lhs.data(), rhs.data()))
103 return op(lhs.data(), rhs.data());
112 class LhsRep,
int LhsExponent,
114 typename = _impl::enable_if_t<std::numeric_limits<RhsInteger>::is_integer>>
115 constexpr
auto operator+(
const fixed_point<LhsRep, LhsExponent>& lhs,
const RhsInteger& rhs)
116 -> decltype(lhs + fixed_point<RhsInteger, 0>{rhs})
118 return lhs + fixed_point<RhsInteger, 0>{rhs};
122 class LhsRep,
int LhsExponent,
124 typename = _impl::enable_if_t<std::numeric_limits<RhsInteger>::is_integer>>
125 constexpr
auto operator-(
const fixed_point<LhsRep, LhsExponent>& lhs,
const RhsInteger& rhs)
126 -> decltype(lhs - fixed_point<RhsInteger, 0>{rhs})
128 return lhs - fixed_point<RhsInteger, 0>{rhs};
132 class LhsRep,
int LhsExponent,
134 typename = _impl::enable_if_t<std::numeric_limits<RhsInteger>::is_integer>>
135 constexpr
auto operator*(
const fixed_point<LhsRep, LhsExponent>& lhs,
const RhsInteger& rhs)
136 -> decltype(lhs*fixed_point<RhsInteger>(rhs))
138 return lhs*fixed_point<RhsInteger>(rhs);
142 class LhsRep,
int LhsExponent,
144 typename = _impl::enable_if_t<std::numeric_limits<RhsInteger>::is_integer>>
145 constexpr
auto operator/(
const fixed_point<LhsRep, LhsExponent>& lhs,
const RhsInteger& rhs)
146 -> decltype(lhs/fixed_point<RhsInteger>{rhs})
148 return lhs/fixed_point<RhsInteger>{rhs};
154 class RhsRep,
int RhsExponent,
155 typename = _impl::enable_if_t<std::numeric_limits<LhsInteger>::is_integer>>
156 constexpr
auto operator+(
const LhsInteger& lhs,
const fixed_point<RhsRep, RhsExponent>& rhs)
157 -> decltype(fixed_point<LhsInteger, 0>{lhs} + rhs)
159 return fixed_point<LhsInteger, 0>{lhs} + rhs;
164 class RhsRep,
int RhsExponent,
165 typename = _impl::enable_if_t<std::numeric_limits<LhsInteger>::is_integer>>
166 constexpr
auto operator-(
const LhsInteger& lhs,
const fixed_point<RhsRep, RhsExponent>& rhs)
167 -> decltype(fixed_point<LhsInteger>{lhs}-rhs)
169 return fixed_point<LhsInteger>{lhs}-rhs;
174 class RhsRep,
int RhsExponent,
175 typename = _impl::enable_if_t<std::numeric_limits<LhsInteger>::is_integer>>
176 constexpr
auto operator*(
const LhsInteger& lhs,
const fixed_point<RhsRep, RhsExponent>& rhs)
177 -> decltype(fixed_point<LhsInteger>{lhs}*rhs)
179 return fixed_point<LhsInteger>{lhs}*rhs;
184 class RhsRep,
int RhsExponent,
185 typename = _impl::enable_if_t<std::numeric_limits<LhsInteger>::is_integer>>
186 constexpr
auto operator/(
const LhsInteger& lhs,
const fixed_point<RhsRep, RhsExponent>& rhs)
187 -> decltype(fixed_point<LhsInteger>{lhs}/rhs)
189 return fixed_point<LhsInteger>{lhs}/rhs;
193 template<class LhsRep, int LhsExponent, class RhsFloat, typename = _impl::enable_if_t<std::is_floating_point<RhsFloat>::value>>
194 constexpr
auto operator+(
const fixed_point<LhsRep, LhsExponent>& lhs,
const RhsFloat& rhs)-> _impl::common_type_t<fixed_point<LhsRep, LhsExponent>, RhsFloat>
196 using result_type = _impl::common_type_t<fixed_point<LhsRep, LhsExponent>, RhsFloat>;
197 return static_cast<result_type
>(lhs)+static_cast<result_type>(rhs);
200 template<class LhsRep, int LhsExponent, class RhsFloat, typename = _impl::enable_if_t <std::is_floating_point<RhsFloat>::value>>
201 constexpr
auto operator-(
const fixed_point<LhsRep, LhsExponent>& lhs,
const RhsFloat& rhs)-> _impl::common_type_t<fixed_point<LhsRep, LhsExponent>, RhsFloat>
203 using result_type = _impl::common_type_t<fixed_point<LhsRep, LhsExponent>, RhsFloat>;
204 return static_cast<result_type
>(lhs)-static_cast<result_type>(rhs);
207 template<
class LhsRep,
int LhsExponent,
class RhsFloat>
208 constexpr
auto operator*(
209 const fixed_point<LhsRep, LhsExponent>& lhs,
211 -> _impl::common_type_t<
212 fixed_point<LhsRep, LhsExponent>,
213 _impl::enable_if_t<std::is_floating_point<RhsFloat>::value, RhsFloat>>
215 using result_type = _impl::common_type_t<fixed_point<LhsRep, LhsExponent>, RhsFloat>;
216 return static_cast<result_type
>(lhs)*rhs;
219 template<
class LhsRep,
int LhsExponent,
class RhsFloat>
220 constexpr
auto operator/(
221 const fixed_point<LhsRep, LhsExponent>& lhs,
223 -> _impl::common_type_t<
224 fixed_point<LhsRep, LhsExponent>,
225 _impl::enable_if_t<std::is_floating_point<RhsFloat>::value, RhsFloat>>
227 using result_type = _impl::common_type_t<fixed_point<LhsRep, LhsExponent>, RhsFloat>;
228 return static_cast<result_type
>(lhs)/rhs;
232 template<class LhsFloat, class RhsRep, int RhsExponent, typename = _impl::enable_if_t <std::is_floating_point<LhsFloat>::value>>
233 constexpr
auto operator+(
const LhsFloat& lhs,
const fixed_point<RhsRep, RhsExponent>& rhs)-> _impl::common_type_t<LhsFloat, fixed_point<RhsRep, RhsExponent>>
235 using result_type = _impl::common_type_t<LhsFloat, fixed_point<RhsRep, RhsExponent>>;
236 return static_cast<result_type
>(lhs)+static_cast<result_type>(rhs);
239 template<class LhsFloat, class RhsRep, int RhsExponent, typename = _impl::enable_if_t <std::is_floating_point<LhsFloat>::value>>
240 constexpr
auto operator-(
const LhsFloat& lhs,
const fixed_point<RhsRep, RhsExponent>& rhs)-> _impl::common_type_t<LhsFloat, fixed_point<RhsRep, RhsExponent>>
242 using result_type = _impl::common_type_t<LhsFloat, fixed_point<RhsRep, RhsExponent>>;
243 return static_cast<result_type
>(lhs)-static_cast<result_type>(rhs);
246 template<
class LhsFloat,
class RhsRep,
int RhsExponent>
247 constexpr
auto operator*(
249 const fixed_point<RhsRep, RhsExponent>& rhs)
250 -> _impl::common_type_t <_impl::enable_if_t<std::is_floating_point<LhsFloat>::value, LhsFloat>, fixed_point<RhsRep, RhsExponent>>
252 using result_type = _impl::common_type_t<fixed_point<RhsRep, RhsExponent>, LhsFloat>;
253 return lhs*
static_cast<result_type
>(rhs);
256 template<
class LhsFloat,
class RhsRep,
int RhsExponent>
257 constexpr
auto operator/(
259 const fixed_point<RhsRep, RhsExponent>& rhs)
260 -> _impl::common_type_t <_impl::enable_if_t<std::is_floating_point<LhsFloat>::value, LhsFloat>, fixed_point<RhsRep, RhsExponent>>
262 using result_type = _impl::common_type_t<fixed_point<RhsRep, RhsExponent>, LhsFloat>;
264 static_cast<result_type
>(rhs);
271 template<
class LhsRep,
int LhsExponent,
class Rhs>
272 constexpr
auto operator<<(const fixed_point<LhsRep, LhsExponent>& lhs,
const Rhs& rhs)
273 -> decltype(_impl::from_rep<fixed_point<decltype(lhs.data() << rhs), LhsExponent>>(lhs.data() << rhs))
275 return _impl::from_rep<fixed_point<decltype(lhs.data() << rhs), LhsExponent>>(lhs.data() << rhs);
278 template<
class LhsRep,
int LhsExponent,
class Rhs>
279 constexpr
auto operator>>(
const fixed_point<LhsRep, LhsExponent>& lhs,
const Rhs& rhs)
280 -> decltype(_impl::from_rep<fixed_point<decltype(lhs.data() >> rhs), LhsExponent>>(lhs.data() >> rhs))
282 return _impl::from_rep<fixed_point<decltype(lhs.data() >> rhs), LhsExponent>>(lhs.data() >> rhs);
286 template<
class LhsRep,
int LhsExponent,
class RhsIntegral, RhsIntegral RhsValue>
287 constexpr fixed_point<LhsRep, LhsExponent+RhsValue>
288 operator<<(const fixed_point<LhsRep, LhsExponent>& lhs, const_integer<RhsIntegral, RhsValue>)
293 template<
class LhsRep,
int LhsExponent,
class RhsIntegral, RhsIntegral RhsValue>
294 constexpr fixed_point<LhsRep, LhsExponent-RhsValue>
295 operator>>(
const fixed_point<LhsRep, LhsExponent>& lhs, const_integer<RhsIntegral, RhsValue>)
301 template<
class LhsRep,
int LhsExponent,
class RhsIntegral, RhsIntegral RhsValue>
302 constexpr fixed_point<LhsRep, LhsExponent+RhsValue>
303 operator<<(const fixed_point<LhsRep, LhsExponent>& lhs, std::integral_constant<RhsIntegral, RhsValue>)
308 template<
class LhsRep,
int LhsExponent,
class RhsIntegral, RhsIntegral RhsValue>
309 constexpr fixed_point<LhsRep, LhsExponent-RhsValue>
310 operator>>(
const fixed_point<LhsRep, LhsExponent>& lhs, std::integral_constant<RhsIntegral, RhsValue>)
316 #endif // SG14_FIXED_POINT_OPERATORS_H static constexpr fixed_point from_data(rep const &r)
creates an instance given the underlying representation value
Definition: fixed_point_type.h:190
study group 14 of the C++ working group
Definition: const_integer.h:22