| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | //====================================================================================================================== | ||
| 2 | /* | ||
| 3 | POLYFLOAT - Extended precision floating points | ||
| 4 | Copyright : POLYFLOAT Contributors & Maintainers | ||
| 5 | SPDX-License-Identifier: BSL-1.0 | ||
| 6 | */ | ||
| 7 | //====================================================================================================================== | ||
| 8 | #pragma once | ||
| 9 | |||
| 10 | #include <polyfloat/details/callable.hpp> | ||
| 11 | #include <polyfloat/types/concepts.hpp> | ||
| 12 | #include <polyfloat/types/traits.hpp> | ||
| 13 | #include <type_traits> | ||
| 14 | #include <polyfloat/module/core/is_nan.hpp> | ||
| 15 | #include <polyfloat/module/core/is_minf.hpp> | ||
| 16 | #include <polyfloat/module/core/is_pinf.hpp> | ||
| 17 | |||
| 18 | namespace plf | ||
| 19 | { | ||
| 20 | |||
| 21 | template<typename Options> struct exp2n_t : eve::callable<exp2n_t, Options, raw_option, pedantic_option> | ||
| 22 | { | ||
| 23 | 66 | template<concepts::polyfloat_like Z> POLYFLOAT_ABI constexpr Z operator()(Z n) const noexcept | |
| 24 | { | ||
| 25 | 66 | return POLYFLOAT_CALL(n); | |
| 26 | } | ||
| 27 | |||
| 28 | template<eve::integral_value N, concepts::polyfloat_like Target> | ||
| 29 | 112 | POLYFLOAT_ABI constexpr Target operator()(N n, eve::as<Target>) const noexcept | |
| 30 | { | ||
| 31 | 112 | return POLYFLOAT_CALL(n, eve::as<Target>()); | |
| 32 | } | ||
| 33 | |||
| 34 | 178 | POLYFLOAT_CALLABLE_OBJECT(exp2n_t, exp2n_); | |
| 35 | }; | ||
| 36 | //====================================================================================================================== | ||
| 37 | //! @addtogroup core | ||
| 38 | //! @{ | ||
| 39 | //! @var exp2n | ||
| 40 | //! @brief return \f$2^n\f$ where n is flint or integral. | ||
| 41 | //! | ||
| 42 | //! @groupheader{Header file} | ||
| 43 | //! | ||
| 44 | //! @code | ||
| 45 | //! #include <polyfloat/core.hpp> | ||
| 46 | //! @endcode | ||
| 47 | //! | ||
| 48 | //! @groupheader{Callable Signatures} | ||
| 49 | //! | ||
| 50 | //! @code | ||
| 51 | //! namespace polyfloat | ||
| 52 | //! { | ||
| 53 | //! template<polyfloat::concepts::polyfloat_like T> constexpr auto exp2n(T n) noexcept; //1 | ||
| 54 | //! template<eve::integral_value I, polyfloat::concepts::polyfloat_like U> constexpr auto exp2n(I n, eve::as<U>) noexcept;//2 | ||
| 55 | //! } | ||
| 56 | //! @endcode | ||
| 57 | //! | ||
| 58 | //! **Parameters** | ||
| 59 | //! | ||
| 60 | //! `n`: flint exponent (if it is not flint it is truncated before use). | ||
| 61 | //! | ||
| 62 | //! **Template Parameter** | ||
| 63 | //! | ||
| 64 | //! * `U`: target type to convert to. | ||
| 65 | //! | ||
| 66 | //! **Return value** | ||
| 67 | //! | ||
| 68 | //! Returns \f$2^\tilda{n}\f$. where \f$\tilda{n}\f$ is the truncature of \f$n\f$n in the type of N | ||
| 69 | //! if N inot integral and in the type of the target otherwise. This is faster than the general exp2 | ||
| 70 | //! and does not uses math module. | ||
| 71 | //! | ||
| 72 | //! * If n is a flint polyfloat or standard floating the same type is returned | ||
| 73 | //! * If n is integral you have to choose a target | ||
| 74 | //! | ||
| 75 | //! @note Mind the fact that n greater than maxexponent or less than than minexponent of the target; will | ||
| 76 | //! repectively return inf and zero values, unless 'eve::raw' options is used and then | ||
| 77 | //! in these cases the result undefined and is UB for non-finite values. | ||
| 78 | //! | ||
| 79 | //! @groupheader{Example} | ||
| 80 | //! | ||
| 81 | //! @godbolt{doc/core/exp2n.cpp} | ||
| 82 | //====================================================================================================================== | ||
| 83 | |||
| 84 | inline constexpr auto exp2n = eve::functor<exp2n_t>; | ||
| 85 | //====================================================================================================================== | ||
| 86 | //! @} | ||
| 87 | //====================================================================================================================== | ||
| 88 | } | ||
| 89 | |||
| 90 | namespace plf::_ | ||
| 91 | { | ||
| 92 | template<eve::integral_value N, typename Z, eve::callable_options O> | ||
| 93 | 112 | constexpr auto exp2n_(POLYFLOAT_DELAY(), O const&, N const& n, eve::as<Z>) noexcept | |
| 94 | { | ||
| 95 | using c_t = as_component_type_t<Z>; | ||
| 96 | using e_t = eve::element_type_t<Z>; | ||
| 97 | using u_t = eve::underlying_type_t<e_t>; | ||
| 98 | 112 | auto bits = (n + eve::maxexponent(eve::as<u_t>())) << eve::nbmantissabits(eve::as<u_t>()); | |
| 99 | 112 | auto r = eve::bit_cast(bits, eve::as(c_t())); | |
| 100 | 20 | if constexpr (O::contains(eve::raw)) return Z(r); | |
| 101 | else | ||
| 102 | { | ||
| 103 | 92 | auto test1 = eve::minexponent(eve::as<u_t>()) > n; | |
| 104 | 92 | auto test2 = eve::maxexponent(eve::as<u_t>()) < n; | |
| 105 | 92 | return Z(eve::if_else(test1, eve::zero, eve::if_else(test2, eve::inf(eve::as<u_t>()), r))); | |
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | template<typename N, eve::callable_options O> | ||
| 110 | 66 | constexpr auto exp2n_(POLYFLOAT_DELAY(), O const& o, N n) noexcept | |
| 111 | requires(!eve::integral_value<N>) | ||
| 112 | { | ||
| 113 | using u_t = eve::underlying_type_t<N>; | ||
| 114 | using i_t = eve::as_integer_t<u_t, signed>; | ||
| 115 | 66 | auto test = plf::is_not_finite(n); | |
| 116 | 66 | auto nann = plf::is_nan(n); | |
| 117 | if constexpr (!O::contains(eve::raw)) | ||
| 118 | { | ||
| 119 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 20 times.
|
46 | if (eve::any(test)) |
| 120 | { | ||
| 121 | 6 | n = plf::if_else(plf::is_pinf(n), N(eve::maxexponentp1(eve::as<u_t>())), | |
| 122 | 6 | plf::if_else(plf::is_minf(n), N(-eve::maxexponentp1(eve::as<u_t>())), | |
| 123 | 12 | plf::if_else(nann, plf::zero(eve::as(n)), n))); | |
| 124 | } | ||
| 125 | } | ||
| 126 | 66 | auto in = eve::convert(plf::hi(n), eve::as<i_t>()); | |
| 127 | 66 | auto r = exp2n[o](in, eve::as<N>()); | |
| 128 | 20 | if constexpr (O::contains(eve::raw)) return r; | |
| 129 | 46 | else return plf::if_else(nann, nan(as<N>()), exp2n[o](in, eve::as<N>())); | |
| 130 | } | ||
| 131 | } | ||
| 132 |