33 template <
typename GUM_SCALAR >
36 const GUM_SCALAR& number,
37 const int64_t& den_max,
38 const GUM_SCALAR& zero) {
39 bool isNegative = (number < 0) ?
true :
false;
40 GUM_SCALAR pnumber = (isNegative) ? -number : number;
42 if (std::abs(pnumber - GUM_SCALAR(1.)) < zero) {
43 numerator = (isNegative) ? -1 : 1;
46 }
else if (pnumber < zero) {
52 int64_t a(0), b(1), c(1), d(1);
55 while (b <= den_max && d <= den_max) {
56 mediant = (GUM_SCALAR)(a + c) / (GUM_SCALAR)(b + d);
58 if (std::fabs(pnumber - mediant) < zero) {
59 if (b + d <= den_max) {
60 numerator = (isNegative) ? -(a + c) : (a + c);
64 numerator = (isNegative) ? -c : c;
68 numerator = (isNegative) ? -a : a;
72 }
else if (pnumber > mediant) {
82 numerator = (isNegative) ? -c : c;
86 numerator = (isNegative) ? -a : a;
92 template <
typename GUM_SCALAR >
95 const GUM_SCALAR& number,
97 const GUM_SCALAR pnumber = (number > 0) ? number : -number;
100 GUM_SCALAR rnumber = pnumber;
103 std::vector< uint64_t > p({0, 1});
104 std::vector< uint64_t > q({1, 0});
107 std::vector< uint64_t > a;
109 uint64_t p_tmp, q_tmp;
112 double delta, delta_tmp;
120 a.push_back(std::lrint(std::floor(rnumber)));
121 p.push_back(a.back() * p.back() + p[p.size() - 2]);
122 q.push_back(a.back() * q.back() + q[q.size() - 2]);
124 delta = std::fabs(pnumber - (GUM_SCALAR)p.back() / q.back());
127 numerator = (int64_t)p.back();
128 if (number < 0) numerator = -numerator;
129 denominator = q.back();
133 if (std::abs(rnumber - a.back()) < 1e-6)
break;
135 rnumber = GUM_SCALAR(1.) / (rnumber - a.back());
138 if (a.size() < 2)
return;
143 Idx i =
Idx(p.size() - 2);
149 p_tmp = n * p[i] + p[i - 1];
150 q_tmp = n * q[i] + q[i - 1];
152 delta = std::fabs(pnumber - ((
double)p[i]) / q[i]);
153 delta_tmp = std::fabs(pnumber - ((
double)p_tmp) / q_tmp);
156 numerator = (int64_t)p[i];
157 if (number < 0) numerator = -numerator;
162 if (delta_tmp < zero) {
163 numerator = (int64_t)p_tmp;
164 if (number < 0) numerator = -numerator;
172 for (n = (a[i - 1] + 2) / 2; n < a[i - 1]; ++n) {
173 p_tmp = n * p[i] + p[i - 1];
174 q_tmp = n * q[i] + q[i - 1];
176 delta_tmp = std::fabs(pnumber - ((
double)p_tmp) / q_tmp);
178 if (delta_tmp < zero) {
179 numerator = (int64_t)p_tmp;
180 if (number < 0) numerator = -numerator;
189 template <
typename GUM_SCALAR >
191 int64_t& denominator,
192 const GUM_SCALAR& number,
193 const int64_t& den_max) {
194 const GUM_SCALAR pnumber = (number > 0) ? number : -number;
196 const uint64_t denMax =
200 GUM_SCALAR rnumber = pnumber;
203 std::vector< uint64_t > p({0, 1});
204 std::vector< uint64_t > q({1, 0});
207 std::vector< uint64_t > a;
209 uint64_t p_tmp, q_tmp;
212 double delta, delta_tmp;
216 a.push_back(std::lrint(std::floor(rnumber)));
218 p_tmp = a.back() * p.back() + p[p.size() - 2];
219 q_tmp = a.back() * q.back() + q[q.size() - 2];
221 if (q_tmp > denMax || p_tmp > denMax)
break;
226 if (std::fabs(rnumber - a.back()) < 1e-6)
break;
228 rnumber = GUM_SCALAR(1.) / (rnumber - a.back());
231 if (a.size() < 2 || q.back() == denMax || p.back() == denMax) {
232 numerator = p.back();
233 if (number < 0) numerator = -numerator;
234 denominator = q.back();
241 Idx i =
Idx(p.size() - 1);
246 for (n = a[i - 1] - 1; n >= (a[i - 1] + 2) / 2; --n) {
247 p_tmp = n * p[i] + p[i - 1];
248 q_tmp = n * q[i] + q[i - 1];
250 if (q_tmp > denMax || p_tmp > denMax)
continue;
252 numerator = (int64_t)p_tmp;
253 if (number < 0) numerator = -numerator;
260 p_tmp = n * p[i] + p[i - 1];
261 q_tmp = n * q[i] + q[i - 1];
263 delta_tmp = std::fabs(pnumber - ((
double)p_tmp) / q_tmp);
264 delta = std::fabs(pnumber - ((
double)p[i]) / q[i]);
266 if (delta_tmp < delta && q_tmp <= denMax && p_tmp <= denMax) {
267 numerator = (int64_t)p_tmp;
268 if (number < 0) numerator = -numerator;
271 numerator = (int64_t)p[i];
272 if (number < 0) numerator = -numerator;
gum is the global namespace for all aGrUM entities
static void continuedFracBest(int64_t &numerator, int64_t &denominator, const GUM_SCALAR &number, const int64_t &den_max=1000000)
Find the best rational approximation.
static void farey(int64_t &numerator, int64_t &denominator, const GUM_SCALAR &number, const int64_t &den_max=1000000L, const GUM_SCALAR &zero=1e-6)
Find the rational close enough to a given ( decimal ) number in [-1,1] and whose denominator is not h...
static void continuedFracFirst(int64_t &numerator, int64_t &denominator, const GUM_SCALAR &number, const double &zero=1e-6)
Find the first best rational approximation.
Class template used to approximate decimal numbers by rationals.
Size Idx
Type for indexes.