60 const GUM_SCALAR& number,
61 const int64_t& den_max,
62 const GUM_SCALAR& zero) {
63 bool isNegative = (number < 0) ?
true :
false;
64 GUM_SCALAR pnumber = (isNegative) ? -number : number;
66 if (std::abs(pnumber - GUM_SCALAR(1.)) < zero) {
67 numerator = (isNegative) ? -1 : 1;
70 }
else if (pnumber < zero) {
76 int64_t a(0), b(1), c(1), d(1);
79 while (b <= den_max && d <= den_max) {
81 if (c > std::numeric_limits< int64_t >::max() - a
82 || d > std::numeric_limits< int64_t >::max() - b)
84 mediant = (GUM_SCALAR)(a + c) / (GUM_SCALAR)(b + d);
86 if (std::fabs(pnumber - mediant) < zero) {
87 if (b + d <= den_max) {
88 numerator = (isNegative) ? -(a + c) : (a + c);
92 numerator = (isNegative) ? -c : c;
96 numerator = (isNegative) ? -a : a;
100 }
else if (pnumber > mediant) {
110 numerator = (isNegative) ? -c : c;
114 numerator = (isNegative) ? -a : a;
122 int64_t& denominator,
123 const GUM_SCALAR& number,
124 const double& zero) {
125 const GUM_SCALAR pnumber = (number > 0) ? number : -number;
128 GUM_SCALAR rnumber = pnumber;
131 std::vector< uint64_t > p({0, 1});
132 std::vector< uint64_t > q({1, 0});
135 std::vector< uint64_t > a;
137 uint64_t p_tmp, q_tmp;
140 double delta, delta_tmp;
148 a.push_back(std::lrint(std::floor(rnumber)));
149 p.push_back(a.back() * p.back() + p[p.size() - 2]);
150 q.push_back(a.back() * q.back() + q[q.size() - 2]);
152 delta = std::fabs(pnumber - (GUM_SCALAR)p.back() / q.back());
155 numerator = (int64_t)p.back();
156 if (number < 0) numerator = -numerator;
157 denominator = q.back();
161 if (std::abs(rnumber - a.back()) < 1e-6)
break;
163 rnumber = GUM_SCALAR(1.) / (rnumber - a.back());
166 if (a.size() < 2)
return;
171 Idx i =
Idx(p.size() - 2);
177 p_tmp = n * p[i] + p[i - 1];
178 q_tmp = n * q[i] + q[i - 1];
180 delta = std::fabs(pnumber - ((
double)p[i]) / q[i]);
181 delta_tmp = std::fabs(pnumber - ((
double)p_tmp) / q_tmp);
184 numerator = (int64_t)p[i];
185 if (number < 0) numerator = -numerator;
190 if (delta_tmp < zero) {
191 numerator = (int64_t)p_tmp;
192 if (number < 0) numerator = -numerator;
200 for (n = (a[i - 1] + 2) / 2; n < a[i - 1]; ++n) {
201 p_tmp = n * p[i] + p[i - 1];
202 q_tmp = n * q[i] + q[i - 1];
204 delta_tmp = std::fabs(pnumber - ((
double)p_tmp) / q_tmp);
206 if (delta_tmp < zero) {
207 numerator = (int64_t)p_tmp;
208 if (number < 0) numerator = -numerator;
219 int64_t& denominator,
220 const GUM_SCALAR& number,
221 const int64_t& den_max) {
222 const GUM_SCALAR pnumber = (number > 0) ? number : -number;
224 const uint64_t denMax = (uint64_t)den_max;
227 GUM_SCALAR rnumber = pnumber;
230 std::vector< uint64_t > p({0, 1});
231 std::vector< uint64_t > q({1, 0});
234 std::vector< uint64_t > a;
236 uint64_t p_tmp, q_tmp;
239 double delta, delta_tmp;
243 a.push_back(std::lrint(std::floor(rnumber)));
245 p_tmp = a.back() * p.back() + p[p.size() - 2];
246 q_tmp = a.back() * q.back() + q[q.size() - 2];
248 if (q_tmp > denMax || p_tmp > denMax)
break;
253 if (std::fabs(rnumber - a.back()) < 1e-6)
break;
255 rnumber = GUM_SCALAR(1.) / (rnumber - a.back());
258 if (a.size() < 2 || q.back() == denMax || p.back() == denMax) {
259 numerator = p.back();
260 if (number < 0) numerator = -numerator;
261 denominator = q.back();
268 Idx i =
Idx(p.size() - 1);
273 for (n = a[i - 1] - 1; n >= (a[i - 1] + 2) / 2; --n) {
274 p_tmp = n * p[i] + p[i - 1];
275 q_tmp = n * q[i] + q[i - 1];
277 if (q_tmp > denMax || p_tmp > denMax)
continue;
279 numerator = (int64_t)p_tmp;
280 if (number < 0) numerator = -numerator;
287 p_tmp = n * p[i] + p[i - 1];
288 q_tmp = n * q[i] + q[i - 1];
290 delta_tmp = std::fabs(pnumber - ((
double)p_tmp) / q_tmp);
291 delta = std::fabs(pnumber - ((
double)p[i]) / q[i]);
293 if (delta_tmp < delta && q_tmp <= denMax && p_tmp <= denMax) {
294 numerator = (int64_t)p_tmp;
295 if (number < 0) numerator = -numerator;
298 numerator = (int64_t)p[i];
299 if (number < 0) numerator = -numerator;
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 continuedFracFirst(int64_t &numerator, int64_t &denominator, const GUM_SCALAR &number, const double &zero=1e-6)
Find the first 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...