-
Notifications
You must be signed in to change notification settings - Fork 226
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
simple_continued_fraction: added public functions to access and modify the coefficients #971
base: develop
Are you sure you want to change the base?
Conversation
Why make the coefficients mutable? |
Mutability simply allows further operations with continued fractions, not only constructing them from floats. Modifying particular coefficients should not turn the object into an inconsistent state.
Consistency can be easily preserved within If these comments are OK with you, I can update the pull request ... |
Also, I can update the code in order to fix some of the tests that failed. But not all of them, for example in cases where |
The current usage is consistent with Mathworld's definition. Are there more authoritative sources which exclude the integer part from the definition?
The goal of this class is to convert a floating point number into its best continued fraction approximation. Therefore, unless we change the purpose of the class, it does not make sense to allow it to be mutable. |
5090fd1
to
345f53e
Compare
I only found sources where either "Mathworld's definition" is used, or the coefficients b_i have no specific name.
I believe that this is enough for many use cases, but definitely not for all use cases, and it would be pitty if one would have to implement brand new class for this, where construction from floats is supposed to be necessary too. Thus, I updated the merge request s.t. it is quite conservative, with quite minimal modifications. There is still one issue though. Since both const and non-const I also added |
IIRC, I was reading Khinchin's book when I wrote this class. I'll take a look at it and see whether I messed up and used a different definition. In either case, the documentation can be made more clear.
Is this necessary? They should've been created by the compiler-or better explicitly deleted.
I confess I do not see a good reason to allow non-const modifications. |
cd9961d
to
0101051
Compare
Consider the following example, where I want to compute best rational approximation within an interval: using boost::math::tools::simple_continued_fraction;
const RealT lhs = ...;
const RealT rhs = ...;
const auto cont_frac1 = simple_continued_fraction(lhs);
const auto cont_frac2 = simple_continued_fraction(rhs);
auto& coefs1 = cont_frac1.partial_denominators();
auto& coefs2 = cont_frac2.partial_denominators();
const size_t max_size = min(coefs1.size(), coefs2.size());
simple_continued_fraction cont_frac;
auto& coefs = cont_frac.partial_denominators();
coefs.reserve(max_size);
for (size_t i = 0; i < max_size; ++i) {
const auto c1 = coefs1[i];
const auto c2 = coefs2[i];
if (c1 == c2) {
coefs.push_back(c1);
continue;
}
coefs.push_back(min(c1, c2) + 1);
break;
}
return cont_frac; It is not possible to construct such |
0101051
to
1f3a079
Compare
4937338
to
c4c4592
Compare
simple_continued_fraction(Real x) : x_{x} { | ||
typedef Z int_type; | ||
|
||
simple_continued_fraction(std::vector<Z> data) : b_{std::move(data)} { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
simple_continued_fraction(std::vector<Z> data) : b_{std::move(data)} { | |
simple_continued_fraction(std::vector<Z>&& data) : b_{data} { |
As written this makes a copy of the data vector and then moves it into b_
. I expect you want to take an r-value reference instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
simple_continued_fraction(std::vector<Z>)
can be used both with std::vector<Z>&&
and const std::vector<Z>&
arguments, whereas simple_continued_fraction(std::vector<Z>&&)
cannot be used with const std::vector<Z>&
. In the case of std::vector<Z>&&
argument, there should no significant difference (std::vector<Z>
can require one more call to move constructor, which is negligible).
More importantly, I'm pretty sure that your suggestion simple_continued_fraction(std::vector<Z>&& data) : b_{data}
will call copy constructor on data
, because you pass it as an lvalue, not as an rvalue.
// Can be used with `boost::rational` from <boost/rational.hpp> | ||
template <typename Rational, typename Real, typename Z = std::int64_t> | ||
inline Rational to_rational(const simple_continued_fraction<Real, Z>& scf) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this work with other rational types (e.g. mpq_t
)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume that mpq_t
cannot be used since it is C-style struct which requires to call mpq_init
etc.
The function can be used with any type T
that supports typename T::int_type
, T(typename T::int_type)
(just integer part) and T(typename T::int_type, typename T::int_type)
(numerator and denominator).
I assume C++20 is not supported so I do not use concepts or such.
Is this being superseded by #975? |
partial_denominators
, because IMO the name is misleading - front element represents integer part, and is not denominator. It may confuse the user that the function returns sth. where the integer part is omitted.x_
because I consider it useless - it is only necessary in the constructor, and also it would be difficult to make it consistent with the new mutable member function..x_.backend()
. But if the precision is somehow needed, only precision should be stored, not the original value.Partially solves #970, but I did not handle documentation.
I also implemented conversion (non-member) function to
boost::rational
, but I am not sure where to place it, because it needs to include bothsimple_continued_fraction.hpp
andrational.hpp
.