7 #if !defined(CNL_IMPL_FRACTION_MAKE_FRACTION_H)
8 #define CNL_IMPL_FRACTION_MAKE_FRACTION_H
10 #include "../cnl_assert.h"
11 #include "../numbers/set_signedness.h"
12 #include "definition.h"
16 #include <type_traits>
22 template<
typename Numerator,
typename Denominator>
23 [[nodiscard]] constexpr
auto make_fraction(
24 Numerator
const& n, Denominator
const& d)
26 return fraction<Numerator, Denominator>{n, d};
30 template<
typename Numerator>
31 [[nodiscard]] constexpr
auto make_fraction(Numerator
const& n)
33 return fraction<Numerator, Numerator>{n, 1};
38 typename Numerator,
typename Denominator = Numerator,
39 std::floating_point FloatingPoint =
float>
45 "This function only supports cnl::fraction<T, T> and not cnl::fraction<T1, "
48 using int_t = Numerator;
50 numbers::signedness_v<int_t>,
51 "This function only supports cnl::fraction of signed integers.");
53 using uint_t = numbers::set_signedness_t<int_t, false>;
55 if (d < FloatingPoint{}) {
59 auto left{fraction<int_t>(int_t(d), 1)};
60 auto right{fraction<int_t>{int_t(
left.numerator + 1), 1}};
61 if (FloatingPoint(left) == d) {
64 if (FloatingPoint(right) == d) {
70 auto const mid{fraction<uint_t>(
72 uint_t(
left.denominator +
right.denominator))};
73 CNL_ASSERT(int_t(mid.numerator) >= 0);
74 CNL_ASSERT(int_t(mid.denominator) >= 0);
76 auto fn = [mid, d](
int& fars, fraction<int_t>& f,
int& nears, fraction<int_t>& n) {
83 d * FloatingPoint(f.denominator) - FloatingPoint(f.numerator)};
85 FloatingPoint(n.numerator) - d * FloatingPoint(n.denominator)};
86 auto const n0{dividend / divisor};
90 ((FloatingPoint(f.denominator) + FloatingPoint(n.denominator) * n0)
92 ? int_t(FloatingPoint(
95 / FloatingPoint(n.denominator))
98 ((FloatingPoint(f.numerator) + FloatingPoint(n.numerator * n1))
100 ? int_t(FloatingPoint(
103 / FloatingPoint(n.numerator))
108 f.numerator = int_t(f.numerator + n2 * n.numerator);
109 f.denominator = int_t(f.denominator + n2 * n.denominator);
110 return FloatingPoint(f) == d;
113 auto mid_q{FloatingPoint(mid)};
115 if (fn(lefts, left, rights, right)) {
118 }
else if (mid_q > d) {
119 if (fn(rights, right, lefts, left)) {
130 #endif // CNL_IMPL_FRACTION_MAKE_FRACTION_H