GCC Code Coverage Report


Directory: include/polyfloat/
File: include/polyfloat/module/core/exp2n.hpp
Date: 2026-11-09 15:28:50
Exec Total Coverage
Lines: 23 23 100.0%
Functions: 78 78 100.0%
Branches: 2 2 100.0%

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