GCC Code Coverage Report


Directory: include/polyfloat/
File: include/polyfloat/module/core/rat.hpp
Date: 2026-11-09 15:28:50
Exec Total Coverage
Lines: 34 34 100.0%
Functions: 37 37 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/minus.hpp>
15 #include <polyfloat/module/core/is_negative.hpp>
16
17 namespace plf
18 {
19
20 template<typename Options> struct rat_t : plf::callable<rat_t, eve::rat_t, Options, raw_option, pedantic_option>
21 {
22 18 template<concepts::polyfloat_like Z> POLYFLOAT_ABI constexpr eve::zipped<Z, Z> operator()(Z z) const noexcept
23 {
24 18 return POLYFLOAT_CALL(z);
25 }
26
27 template<concepts::polyfloat_like Z0, concepts::polyfloat_like Z1>
28 16 POLYFLOAT_ABI constexpr eve::zipped<as_polyfloat_like_t<Z0, Z1>, as_polyfloat_like_t<Z0, Z1>> operator()(
29 Z0 z0, Z1 tol) const noexcept
30 {
31 16 return POLYFLOAT_CALL(z0, tol);
32 }
33
34 32 POLYFLOAT_CALLABLE_OBJECT(rat_t, rat_);
35 };
36 //======================================================================================================================
37 //! @addtogroup core
38 //! @{
39 //! @var rat
40 //! @brief return the ratolute value.
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 //! constexpr auto rat(floating_value auto x) noexcept;
54 //! constexpr auto rat(floating_value auto x, floating_value auto tol) noexcept;
55 //! }
56 //! @endcode
57 //!
58 //! **Parameters**
59 //!
60 //!
61 //! * `x` : [argument](@ref eve::value).
62 //! * `tol`: [floating value](@ref eve::value). By default `tol`
63 //! is equal to `10*eps(as(x))*eve::abs(x)`.
64 //!
65 //! **Return value**
66 //!
67 //! Returns the ratolute value of z.
68 //!
69 //! @groupheader{Example}
70 //!
71 //! @godbolt{doc/core/rat.cpp}
72 //======================================================================================================================
73
74 inline constexpr auto rat = eve::functor<rat_t>;
75 //======================================================================================================================
76 //! @}
77 //======================================================================================================================
78 }
79
80 namespace plf::_
81 {
82 16 template<typename Z, eve::callable_options O> constexpr auto rat_(POLYFLOAT_DELAY(), O const&, Z const& x) noexcept
83 {
84 16 return rat(x, 10 * hi(plf::eps(eve::as(x)) * plf::abs(x)));
85 }
86
87 template<typename Z0, typename Z1, eve::callable_options O>
88 16 constexpr auto rat_(POLYFLOAT_DELAY(), O const&, Z0 const& xx, Z1 const& tol) noexcept
89 {
90 using r_t = as_polyfloat_like_t<Z0, Z1>;
91 8 auto cvt = [](auto a) { return plf::convert(a, eve::as<eve::element_type_t<r_t>>()); };
92 16 r_t x = cvt(xx);
93 16 auto is_inf = is_infinite(x);
94 16 auto y = plf::if_else(is_inf, eve::zero, x);
95 16 auto n = plf::nearest(y);
96 16 auto d = plf::one(as(y));
97 16 auto frac = y - n;
98 16 auto lastn = plf::one(as(y));
99 16 auto lastd = plf::zero(as(y));
100
101 72 while (true)
102 {
103 88 auto notdone = plf::is_nez(y) && (plf::abs(y - n / d) >= tol);
104
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 36 times.
88 if (eve::none(notdone)) break;
105 72 auto flip = plf::rec[notdone][pedantic](frac);
106 72 auto step = plf::if_else(notdone, plf::nearest(flip), zero);
107 72 frac = flip - step;
108 72 auto savedn = n;
109 72 auto savedd = d;
110 72 n = plf::fma[notdone](n, step, lastn);
111 72 d = plf::fma[notdone](d, step, lastd);
112 72 lastn = savedn;
113 72 lastd = savedd;
114 }
115 16 n *= plf::sign(d);
116 16 d = plf::abs(d);
117 16 n = plf::if_else(is_inf, plf::sign(x), n);
118 16 d = plf::if_else(is_inf, eve::zero, d);
119 16 return eve::zip(n, d);
120 }
121 }
122