27 #ifndef INCG_PHI_CORE_FLOATING_POINT_HPP 28 #define INCG_PHI_CORE_FLOATING_POINT_HPP 30 #include "phi/phi_config.hpp" 32 #if PHI_HAS_EXTENSION_PRAGMA_ONCE() 36 #include "phi/algorithm/swap.hpp" 37 #include "phi/compiler_support/constexpr.hpp" 38 #include "phi/compiler_support/inline.hpp" 39 #include "phi/compiler_support/nodiscard.hpp" 40 #include "phi/compiler_support/noexcept.hpp" 41 #include "phi/compiler_support/standard_library.hpp" 42 #include "phi/compiler_support/warning.hpp" 43 #include "phi/core/boolean.hpp" 44 #include "phi/type_traits/conditional.hpp" 45 #include "phi/type_traits/enable_if.hpp" 46 #include "phi/type_traits/integral_constant.hpp" 47 #include "phi/type_traits/is_unsafe_floating_point.hpp" 52 DETAIL_PHI_BEGIN_NAMESPACE()
54 template <typename FloatT>
61 template <
typename FromT,
typename ToT>
62 struct is_safe_floating_point_conversion
64 is_unsafe_floating_point<ToT>::value &&
65 sizeof(FromT) <= sizeof(ToT)>
68 template <typename FromT, typename ToT>
69 using enable_safe_floating_point_conversion =
70 enable_if_t<is_safe_floating_point_conversion<FromT, ToT>::value>;
72 template <typename FromT, typename ToT>
73 using fallback_safe_floating_point_conversion =
74 enable_if_t<!is_safe_floating_point_conversion<FromT, ToT>::value>;
77 template <typename LhsT, typename RhsT>
78 struct is_safe_floating_point_comparison
79 : public integral_constant<bool,
80 is_safe_floating_point_conversion<LhsT, RhsT>::value ||
81 is_safe_floating_point_conversion<RhsT, LhsT>::value>
84 template <typename LhsT, typename RhsT>
85 using enable_safe_floating_point_comparison =
86 enable_if_t<is_safe_floating_point_comparison<LhsT, RhsT>::value>;
88 template <typename LhsT, typename RhsT>
89 using fallback_safe_floating_point_comparison =
90 enable_if_t<!is_safe_floating_point_comparison<LhsT, RhsT>::value>;
93 template <typename LhsT, typename RhsT>
94 struct is_safe_floating_point_operation
95 : public integral_constant<bool, is_unsafe_floating_point<LhsT>::value &&
96 is_unsafe_floating_point<RhsT>::value>
99 template <typename LhsT, typename RhsT>
100 using floating_point_result_t =
101 floating_point<enable_if_t<is_safe_floating_point_operation<LhsT, RhsT>::value,
102 conditional_t<sizeof(LhsT) < sizeof(RhsT), RhsT, LhsT>>>;
106 template <typename FloatT>
109 static_assert(is_unsafe_floating_point<FloatT>::value,
110 "[phi::floating_point] must be a floating point type");
113 using this_type = floating_point<FloatT>;
114 using value_type = FloatT;
115 using limits_type = std::numeric_limits<FloatT>;
117 floating_point() = delete;
119 template <typename TypeT,
120 typename = detail::enable_safe_floating_point_conversion<TypeT, FloatT>>
121 PHI_ALWAYS_INLINE PHI_CONSTEXPR floating_point(const TypeT& val) PHI_NOEXCEPT
122 : m_Value(static_cast<FloatT>(val))
125 template <typename TypeT,
126 typename = detail::enable_safe_floating_point_conversion<TypeT, FloatT>>
127 PHI_ALWAYS_INLINE PHI_CONSTEXPR floating_point(const floating_point<TypeT>& val) PHI_NOEXCEPT
128 : m_Value(static_cast<FloatT>(static_cast<TypeT>(val)))
131 template <typename TypeT,
132 typename = detail::fallback_safe_floating_point_conversion<TypeT, FloatT>>
133 floating_point(TypeT) = delete;
137 template <typename TypeT,
138 typename = detail::enable_safe_floating_point_conversion<TypeT, FloatT>>
139 PHI_ALWAYS_INLINE floating_point& operator=(const TypeT& val) PHI_NOEXCEPT
145 PHI_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdouble-promotion")
147 template <typename TypeT,
148 typename = detail::enable_safe_floating_point_conversion<TypeT, FloatT>>
149 PHI_ALWAYS_INLINE floating_point& operator=(const floating_point<TypeT>& val) PHI_NOEXCEPT
151 m_Value = static_cast<TypeT>(val);
155 PHI_CLANG_SUPPRESS_WARNING_POP()
157 template <typename TypeT,
158 typename = detail::fallback_safe_floating_point_conversion<TypeT, FloatT>>
159 floating_point& operator=(TypeT) = delete;
163 PHI_ALWAYS_INLINE explicit PHI_CONSTEXPR operator FloatT() const PHI_NOEXCEPT
168 PHI_NODISCARD PHI_ALWAYS_INLINE PHI_CONSTEXPR FloatT unsafe() const PHI_NOEXCEPT
173 PHI_EXTENDED_CONSTEXPR void swap(floating_point<FloatT>& other) PHI_NOEXCEPT
175 phi::swap(m_Value, other.m_Value);
180 PHI_ALWAYS_INLINE PHI_CONSTEXPR floating_point operator+() const PHI_NOEXCEPT
185 PHI_ALWAYS_INLINE PHI_CONSTEXPR floating_point operator-() const PHI_NOEXCEPT
192 template <typename TypeT,
193 typename = detail::enable_safe_floating_point_conversion<TypeT, FloatT>>
194 PHI_ALWAYS_INLINE floating_point& operator+=(const floating_point<TypeT>& other) PHI_NOEXCEPT
196 m_Value += static_cast<TypeT>(other);
200 template <typename TypeT,
201 typename = detail::enable_safe_floating_point_conversion<TypeT, FloatT>>
202 PHI_ALWAYS_INLINE floating_point& operator+=(const TypeT& other) PHI_NOEXCEPT
204 return *this += floating_point<TypeT>(other);
207 template <typename TypeT,
208 typename = detail::fallback_safe_floating_point_conversion<TypeT, FloatT>>
209 floating_point& operator+=(floating_point<TypeT>) = delete;
211 template <typename TypeT,
212 typename = detail::fallback_safe_floating_point_conversion<TypeT, FloatT>>
213 floating_point& operator+=(TypeT) = delete;
215 template <typename TypeT,
216 typename = detail::enable_safe_floating_point_conversion<TypeT, FloatT>>
217 PHI_ALWAYS_INLINE floating_point& operator-=(const floating_point<TypeT>& other) PHI_NOEXCEPT
219 m_Value -= static_cast<TypeT>(other);
223 template <typename TypeT,
224 typename = detail::enable_safe_floating_point_conversion<TypeT, FloatT>>
225 PHI_ALWAYS_INLINE floating_point& operator-=(const TypeT& other) PHI_NOEXCEPT
227 return *this -= floating_point<TypeT>(other);
230 template <typename TypeT,
231 typename = detail::fallback_safe_floating_point_conversion<TypeT, FloatT>>
232 floating_point& operator-=(floating_point<TypeT>) = delete;
234 template <typename TypeT,
235 typename = detail::fallback_safe_floating_point_conversion<TypeT, FloatT>>
236 floating_point& operator-=(TypeT) = delete;
238 template <typename TypeT,
239 typename = detail::enable_safe_floating_point_conversion<TypeT, FloatT>>
240 PHI_ALWAYS_INLINE floating_point& operator*=(const floating_point<TypeT>& other) PHI_NOEXCEPT
242 m_Value *= static_cast<TypeT>(other);
246 template <typename TypeT,
247 typename = detail::enable_safe_floating_point_conversion<TypeT, FloatT>>
248 PHI_ALWAYS_INLINE floating_point& operator*=(const TypeT& other) PHI_NOEXCEPT
250 return *this *= floating_point<TypeT>(other);
253 template <typename TypeT,
254 typename = detail::fallback_safe_floating_point_conversion<TypeT, FloatT>>
255 floating_point& operator*=(floating_point<TypeT>) = delete;
257 template <typename TypeT,
258 typename = detail::fallback_safe_floating_point_conversion<TypeT, FloatT>>
259 floating_point& operator*=(TypeT) = delete;
261 template <typename TypeT,
262 typename = detail::enable_safe_floating_point_conversion<TypeT, FloatT>>
263 PHI_ALWAYS_INLINE floating_point& operator/=(const floating_point<TypeT>& other) PHI_NOEXCEPT
265 m_Value /= static_cast<TypeT>(other);
269 template <typename TypeT,
270 typename = detail::enable_safe_floating_point_conversion<TypeT, FloatT>>
271 PHI_ALWAYS_INLINE floating_point& operator/=(const TypeT& other) PHI_NOEXCEPT
273 return *this /= floating_point<TypeT>(other);
276 template <typename TypeT,
277 typename = detail::fallback_safe_floating_point_conversion<TypeT, FloatT>>
278 floating_point& operator/=(floating_point<TypeT>) = delete;
280 template <typename TypeT,
281 typename = detail::fallback_safe_floating_point_conversion<TypeT, FloatT>>
282 floating_point& operator/=(TypeT) = delete;
284 template <typename TypeT,
285 typename = detail::enable_safe_floating_point_conversion<TypeT, FloatT>>
286 PHI_ALWAYS_INLINE floating_point& operator%=(const floating_point<TypeT>& other) PHI_NOEXCEPT
288 m_Value = std::fmod(m_Value, static_cast<TypeT>(other));
292 template <typename TypeT,
293 typename = detail::enable_safe_floating_point_conversion<TypeT, FloatT>>
294 PHI_ALWAYS_INLINE floating_point& operator%=(const TypeT& other) PHI_NOEXCEPT
296 return *this %= floating_point<TypeT>(other);
299 template <typename TypeT,
300 typename = detail::fallback_safe_floating_point_conversion<TypeT, FloatT>>
301 floating_point& operator%=(floating_point<TypeT>) = delete;
303 template <typename TypeT,
304 typename = detail::fallback_safe_floating_point_conversion<TypeT, FloatT>>
305 floating_point& operator%=(TypeT) = delete;
313 template <typename LhsT, typename RhsT,
314 typename = detail::enable_safe_floating_point_comparison<LhsT, RhsT>>
315 PHI_ALWAYS_INLINE PHI_CONSTEXPR boolean operator<(const floating_point<LhsT>& lhs,
316 const floating_point<RhsT>& rhs) PHI_NOEXCEPT
318 return static_cast<LhsT>(lhs) < static_cast<RhsT>(rhs);
321 template <typename LhsT, typename RhsT,
322 typename = detail::enable_safe_floating_point_conversion<LhsT, RhsT>>
323 PHI_ALWAYS_INLINE PHI_CONSTEXPR boolean operator<(const LhsT& lhs,
324 const floating_point<RhsT>& rhs) PHI_NOEXCEPT
326 return floating_point<LhsT>(lhs) < rhs;
329 template <typename LhsT, typename RhsT,
330 typename = detail::enable_safe_floating_point_comparison<LhsT, RhsT>>
331 PHI_ALWAYS_INLINE PHI_CONSTEXPR boolean operator<(const floating_point<LhsT>& lhs,
332 const RhsT& rhs) PHI_NOEXCEPT
334 return lhs < floating_point<RhsT>(rhs);
337 template <typename LhsT, typename RhsT,
338 typename = detail::fallback_safe_floating_point_comparison<LhsT, RhsT>>
339 PHI_CONSTEXPR boolean operator<(floating_point<LhsT>, floating_point<RhsT>) = delete;
341 template <typename LhsT, typename RhsT,
342 typename = detail::fallback_safe_floating_point_comparison<LhsT, RhsT>>
343 PHI_CONSTEXPR boolean operator<(LhsT, floating_point<RhsT>) = delete;
345 template <typename LhsT, typename RhsT,
346 typename = detail::fallback_safe_floating_point_comparison<LhsT, RhsT>>
347 PHI_CONSTEXPR boolean operator<(floating_point<LhsT>, RhsT) = delete;
349 template <typename LhsT, typename RhsT,
350 typename = detail::enable_safe_floating_point_comparison<LhsT, RhsT>>
351 PHI_ALWAYS_INLINE PHI_CONSTEXPR boolean operator<=(const floating_point<LhsT>& lhs,
352 const floating_point<RhsT>& rhs) PHI_NOEXCEPT
354 return static_cast<LhsT>(lhs) <= static_cast<RhsT>(rhs);
357 template <typename LhsT, typename RhsT,
358 typename = detail::enable_safe_floating_point_conversion<LhsT, RhsT>>
359 PHI_ALWAYS_INLINE PHI_CONSTEXPR boolean operator<=(const LhsT& lhs,
360 const floating_point<RhsT>& rhs) PHI_NOEXCEPT
362 return floating_point<LhsT>(lhs) <= rhs;
365 template <typename LhsT, typename RhsT,
366 typename = detail::enable_safe_floating_point_comparison<LhsT, RhsT>>
367 PHI_ALWAYS_INLINE PHI_CONSTEXPR boolean operator<=(const floating_point<LhsT>& lhs,
368 const RhsT& rhs) PHI_NOEXCEPT
370 return lhs <= floating_point<RhsT>(rhs);
373 template <typename LhsT, typename RhsT,
374 typename = detail::fallback_safe_floating_point_comparison<LhsT, RhsT>>
375 PHI_CONSTEXPR boolean operator<=(floating_point<LhsT>, floating_point<RhsT>) = delete;
377 template <typename LhsT, typename RhsT,
378 typename = detail::fallback_safe_floating_point_comparison<LhsT, RhsT>>
379 PHI_CONSTEXPR boolean operator<=(LhsT, floating_point<RhsT>) = delete;
381 template <typename LhsT, typename RhsT,
382 typename = detail::fallback_safe_floating_point_comparison<LhsT, RhsT>>
383 PHI_CONSTEXPR boolean operator<=(floating_point<LhsT>, RhsT) = delete;
385 PHI_CLANG_SUPPRESS_WARNING_PUSH()
386 PHI_CLANG_SUPPRESS_WARNING("-Wdouble-promotion")
388 template <typename LhsT, typename RhsT,
389 typename = detail::enable_safe_floating_point_comparison<LhsT, RhsT>>
390 PHI_ALWAYS_INLINE PHI_CONSTEXPR boolean operator>(const floating_point<LhsT>& lhs,
391 const floating_point<RhsT>& rhs) PHI_NOEXCEPT
393 return static_cast<LhsT>(lhs) > static_cast<RhsT>(rhs);
396 PHI_CLANG_SUPPRESS_WARNING_POP()
398 template <typename LhsT, typename RhsT,
399 typename = detail::enable_safe_floating_point_conversion<LhsT, RhsT>>
400 PHI_ALWAYS_INLINE PHI_CONSTEXPR boolean operator>(const LhsT& lhs,
401 const floating_point<RhsT>& rhs) PHI_NOEXCEPT
403 return floating_point<LhsT>(lhs) > rhs;
406 template <typename LhsT, typename RhsT,
407 typename = detail::enable_safe_floating_point_comparison<LhsT, RhsT>>
408 PHI_ALWAYS_INLINE PHI_CONSTEXPR boolean operator>(const floating_point<LhsT>& lhs,
409 const RhsT& rhs) PHI_NOEXCEPT
411 return lhs > floating_point<RhsT>(rhs);
414 template <typename LhsT, typename RhsT,
415 typename = detail::fallback_safe_floating_point_comparison<LhsT, RhsT>>
416 PHI_CONSTEXPR boolean operator>(floating_point<LhsT>, floating_point<RhsT>) = delete;
418 template <typename LhsT, typename RhsT,
419 typename = detail::fallback_safe_floating_point_comparison<LhsT, RhsT>>
420 PHI_CONSTEXPR boolean operator>(LhsT, floating_point<RhsT>) = delete;
422 template <typename LhsT, typename RhsT,
423 typename = detail::fallback_safe_floating_point_comparison<LhsT, RhsT>>
424 PHI_CONSTEXPR boolean operator>(floating_point<LhsT>, RhsT) = delete;
426 PHI_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdouble-promotion")
428 template <typename LhsT, typename RhsT,
429 typename = detail::enable_safe_floating_point_comparison<LhsT, RhsT>>
430 PHI_ALWAYS_INLINE PHI_CONSTEXPR boolean operator>=(const floating_point<LhsT>& lhs,
431 const floating_point<RhsT>& rhs) PHI_NOEXCEPT
433 return static_cast<LhsT>(lhs) >= static_cast<RhsT>(rhs);
436 PHI_GCC_SUPPRESS_WARNING_POP()
438 template <typename LhsT, typename RhsT,
439 typename = detail::enable_safe_floating_point_conversion<LhsT, RhsT>>
440 PHI_ALWAYS_INLINE PHI_CONSTEXPR boolean operator>=(const LhsT& lhs,
441 const floating_point<RhsT>& rhs) PHI_NOEXCEPT
443 return floating_point<LhsT>(lhs) >= rhs;
446 template <typename LhsT, typename RhsT,
447 typename = detail::enable_safe_floating_point_comparison<LhsT, RhsT>>
448 PHI_ALWAYS_INLINE PHI_CONSTEXPR boolean operator>=(const floating_point<LhsT>& lhs,
449 const RhsT& rhs) PHI_NOEXCEPT
451 return lhs >= floating_point<RhsT>(rhs);
454 template <typename LhsT, typename RhsT,
455 typename = detail::fallback_safe_floating_point_comparison<LhsT, RhsT>>
456 PHI_CONSTEXPR boolean operator>=(floating_point<LhsT>, floating_point<RhsT>) = delete;
458 template <typename LhsT, typename RhsT,
459 typename = detail::fallback_safe_floating_point_comparison<LhsT, RhsT>>
460 PHI_CONSTEXPR boolean operator>=(LhsT, floating_point<RhsT>) = delete;
462 template <typename LhsT, typename RhsT,
463 typename = detail::fallback_safe_floating_point_comparison<LhsT, RhsT>>
464 PHI_CONSTEXPR boolean operator>=(floating_point<LhsT>, RhsT) = delete;
468 template <typename LhsT, typename RhsT>
469 PHI_ALWAYS_INLINE PHI_CONSTEXPR auto operator+(const floating_point<LhsT>& lhs,
470 const floating_point<RhsT>& rhs)
471 PHI_NOEXCEPT->detail::floating_point_result_t<LhsT, RhsT>
473 return static_cast<LhsT>(lhs) + static_cast<RhsT>(rhs);
476 template <typename LhsT, typename RhsT>
477 PHI_ALWAYS_INLINE PHI_CONSTEXPR auto operator+(const LhsT& lhs, const floating_point<RhsT>& rhs)
478 PHI_NOEXCEPT->detail::floating_point_result_t<LhsT, RhsT>
483 template <
typename LhsT,
typename RhsT>
484 PHI_ALWAYS_INLINE PHI_CONSTEXPR
auto operator+(
const floating_point<LhsT>& lhs,
const RhsT& rhs)
485 PHI_NOEXCEPT->detail::floating_point_result_t<LhsT, RhsT>
490 template <
typename LhsT,
typename RhsT>
493 PHI_NOEXCEPT->detail::floating_point_result_t<LhsT, RhsT>
495 return static_cast<LhsT
>(lhs) - static_cast<RhsT>(rhs);
498 template <
typename LhsT,
typename RhsT>
499 PHI_ALWAYS_INLINE PHI_CONSTEXPR
auto operator-(
const LhsT& lhs,
const floating_point<RhsT>& rhs)
500 PHI_NOEXCEPT->detail::floating_point_result_t<LhsT, RhsT>
505 template <
typename LhsT,
typename RhsT>
506 PHI_ALWAYS_INLINE PHI_CONSTEXPR
auto operator-(
const floating_point<LhsT>& lhs,
const RhsT& rhs)
507 PHI_NOEXCEPT->detail::floating_point_result_t<LhsT, RhsT>
512 template <
typename LhsT,
typename RhsT>
515 PHI_NOEXCEPT->detail::floating_point_result_t<LhsT, RhsT>
517 return static_cast<LhsT
>(lhs) * static_cast<RhsT>(rhs);
520 template <
typename LhsT,
typename RhsT>
521 PHI_ALWAYS_INLINE PHI_CONSTEXPR
auto operator*(
const LhsT& lhs,
const floating_point<RhsT>& rhs)
522 PHI_NOEXCEPT->detail::floating_point_result_t<LhsT, RhsT>
527 template <
typename LhsT,
typename RhsT>
528 PHI_ALWAYS_INLINE PHI_CONSTEXPR
auto operator*(
const floating_point<LhsT>& lhs,
const RhsT& rhs)
529 PHI_NOEXCEPT->detail::floating_point_result_t<LhsT, RhsT>
534 template <
typename LhsT,
typename RhsT>
537 PHI_NOEXCEPT->detail::floating_point_result_t<LhsT, RhsT>
539 return static_cast<LhsT
>(lhs) / static_cast<RhsT>(rhs);
542 template <
typename LhsT,
typename RhsT>
543 PHI_ALWAYS_INLINE PHI_CONSTEXPR
auto operator/(
const LhsT& lhs,
const floating_point<RhsT>& rhs)
544 PHI_NOEXCEPT->detail::floating_point_result_t<LhsT, RhsT>
549 template <
typename LhsT,
typename RhsT>
550 PHI_ALWAYS_INLINE PHI_CONSTEXPR
auto operator/(
const floating_point<LhsT>& lhs,
const RhsT& rhs)
551 PHI_NOEXCEPT->detail::floating_point_result_t<LhsT, RhsT>
556 template <
typename LhsT,
typename RhsT>
559 PHI_NOEXCEPT->detail::floating_point_result_t<LhsT, RhsT>
561 return std::fmod(static_cast<LhsT>(lhs), static_cast<RhsT>(rhs));
564 template <
typename LhsT,
typename RhsT>
565 PHI_ALWAYS_INLINE PHI_CONSTEXPR
auto operator%(
const LhsT& lhs,
const floating_point<RhsT>& rhs)
566 PHI_NOEXCEPT->detail::floating_point_result_t<LhsT, RhsT>
571 template <
typename LhsT,
typename RhsT>
572 PHI_ALWAYS_INLINE PHI_CONSTEXPR
auto operator%(
const floating_point<LhsT>& lhs,
const RhsT& rhs)
573 PHI_NOEXCEPT->detail::floating_point_result_t<LhsT, RhsT>
580 template <
typename CharT,
class CharTraitsT,
typename FloatT>
581 std::basic_istream<CharT, CharTraitsT>& operator>>(std::basic_istream<CharT, CharTraitsT>& stream,
584 FloatT val{FloatT(0.0)};
590 template <
typename CharT,
class CharTraitsT,
typename FloatT>
591 std::basic_ostream<CharT, CharTraitsT>& operator<<(std::basic_ostream<CharT, CharTraitsT>& stream,
594 return stream << static_cast<FloatT>(float_value);
597 template <
typename FloatT>
604 DETAIL_PHI_END_NAMESPACE()
606 DETAIL_PHI_BEGIN_STD_NAMESPACE()
608 template <
typename FloatT>
611 phi::size_t operator()(
const phi::floating_point<FloatT>& value)
const PHI_NOEXCEPT
613 return std::hash<FloatT>()(static_cast<FloatT>(value));
617 template <
typename FloatT>
618 struct numeric_limits<
phi::floating_point<FloatT>> : std::numeric_limits<FloatT>
621 DETAIL_PHI_END_STD_NAMESPACE()
623 #endif // INCG_PHI_CORE_FLOATING_POINT_HPP Definition: integral_constant.hpp:19
Definition: floating_point.hpp:55
Definition: common_type.test.cpp:195