1*99a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2*99a2dd95SBruce Richardson * Copyright(c) 2010-2014 Intel Corporation
3*99a2dd95SBruce Richardson */
4*99a2dd95SBruce Richardson
5*99a2dd95SBruce Richardson #include <stdlib.h>
6*99a2dd95SBruce Richardson
7*99a2dd95SBruce Richardson #include "rte_approx.h"
8*99a2dd95SBruce Richardson
9*99a2dd95SBruce Richardson /*
10*99a2dd95SBruce Richardson * Based on paper "Approximating Rational Numbers by Fractions" by Michal
11*99a2dd95SBruce Richardson * Forisek forisek@dcs.fmph.uniba.sk
12*99a2dd95SBruce Richardson *
13*99a2dd95SBruce Richardson * Given a rational number alpha with 0 < alpha < 1 and a precision d, the goal
14*99a2dd95SBruce Richardson * is to find positive integers p, q such that alpha - d < p/q < alpha + d, and
15*99a2dd95SBruce Richardson * q is minimal.
16*99a2dd95SBruce Richardson *
17*99a2dd95SBruce Richardson * http://people.ksp.sk/~misof/publications/2007approx.pdf
18*99a2dd95SBruce Richardson */
19*99a2dd95SBruce Richardson
20*99a2dd95SBruce Richardson /* fraction comparison: compare (a/b) and (c/d) */
21*99a2dd95SBruce Richardson static inline uint32_t
less(uint32_t a,uint32_t b,uint32_t c,uint32_t d)22*99a2dd95SBruce Richardson less(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
23*99a2dd95SBruce Richardson {
24*99a2dd95SBruce Richardson return a*d < b*c;
25*99a2dd95SBruce Richardson }
26*99a2dd95SBruce Richardson
27*99a2dd95SBruce Richardson static inline uint32_t
less_or_equal(uint32_t a,uint32_t b,uint32_t c,uint32_t d)28*99a2dd95SBruce Richardson less_or_equal(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
29*99a2dd95SBruce Richardson {
30*99a2dd95SBruce Richardson return a*d <= b*c;
31*99a2dd95SBruce Richardson }
32*99a2dd95SBruce Richardson
33*99a2dd95SBruce Richardson /* check whether a/b is a valid approximation */
34*99a2dd95SBruce Richardson static inline uint32_t
matches(uint32_t a,uint32_t b,uint32_t alpha_num,uint32_t d_num,uint32_t denum)35*99a2dd95SBruce Richardson matches(uint32_t a, uint32_t b,
36*99a2dd95SBruce Richardson uint32_t alpha_num, uint32_t d_num, uint32_t denum)
37*99a2dd95SBruce Richardson {
38*99a2dd95SBruce Richardson if (less_or_equal(a, b, alpha_num - d_num, denum))
39*99a2dd95SBruce Richardson return 0;
40*99a2dd95SBruce Richardson
41*99a2dd95SBruce Richardson if (less(a ,b, alpha_num + d_num, denum))
42*99a2dd95SBruce Richardson return 1;
43*99a2dd95SBruce Richardson
44*99a2dd95SBruce Richardson return 0;
45*99a2dd95SBruce Richardson }
46*99a2dd95SBruce Richardson
47*99a2dd95SBruce Richardson static inline void
find_exact_solution_left(uint32_t p_a,uint32_t q_a,uint32_t p_b,uint32_t q_b,uint32_t alpha_num,uint32_t d_num,uint32_t denum,uint32_t * p,uint32_t * q)48*99a2dd95SBruce Richardson find_exact_solution_left(uint32_t p_a, uint32_t q_a, uint32_t p_b, uint32_t q_b,
49*99a2dd95SBruce Richardson uint32_t alpha_num, uint32_t d_num, uint32_t denum, uint32_t *p, uint32_t *q)
50*99a2dd95SBruce Richardson {
51*99a2dd95SBruce Richardson uint32_t k_num = denum * p_b - (alpha_num + d_num) * q_b;
52*99a2dd95SBruce Richardson uint32_t k_denum = (alpha_num + d_num) * q_a - denum * p_a;
53*99a2dd95SBruce Richardson uint32_t k = (k_num / k_denum) + 1;
54*99a2dd95SBruce Richardson
55*99a2dd95SBruce Richardson *p = p_b + k * p_a;
56*99a2dd95SBruce Richardson *q = q_b + k * q_a;
57*99a2dd95SBruce Richardson }
58*99a2dd95SBruce Richardson
59*99a2dd95SBruce Richardson static inline void
find_exact_solution_right(uint32_t p_a,uint32_t q_a,uint32_t p_b,uint32_t q_b,uint32_t alpha_num,uint32_t d_num,uint32_t denum,uint32_t * p,uint32_t * q)60*99a2dd95SBruce Richardson find_exact_solution_right(uint32_t p_a, uint32_t q_a, uint32_t p_b, uint32_t q_b,
61*99a2dd95SBruce Richardson uint32_t alpha_num, uint32_t d_num, uint32_t denum, uint32_t *p, uint32_t *q)
62*99a2dd95SBruce Richardson {
63*99a2dd95SBruce Richardson uint32_t k_num = - denum * p_b + (alpha_num - d_num) * q_b;
64*99a2dd95SBruce Richardson uint32_t k_denum = - (alpha_num - d_num) * q_a + denum * p_a;
65*99a2dd95SBruce Richardson uint32_t k = (k_num / k_denum) + 1;
66*99a2dd95SBruce Richardson
67*99a2dd95SBruce Richardson *p = p_b + k * p_a;
68*99a2dd95SBruce Richardson *q = q_b + k * q_a;
69*99a2dd95SBruce Richardson }
70*99a2dd95SBruce Richardson
71*99a2dd95SBruce Richardson static int
find_best_rational_approximation(uint32_t alpha_num,uint32_t d_num,uint32_t denum,uint32_t * p,uint32_t * q)72*99a2dd95SBruce Richardson find_best_rational_approximation(uint32_t alpha_num, uint32_t d_num, uint32_t denum, uint32_t *p, uint32_t *q)
73*99a2dd95SBruce Richardson {
74*99a2dd95SBruce Richardson uint32_t p_a, q_a, p_b, q_b;
75*99a2dd95SBruce Richardson
76*99a2dd95SBruce Richardson /* check assumptions on the inputs */
77*99a2dd95SBruce Richardson if (!((0 < d_num) && (d_num < alpha_num) && (alpha_num < denum) && (d_num + alpha_num < denum))) {
78*99a2dd95SBruce Richardson return -1;
79*99a2dd95SBruce Richardson }
80*99a2dd95SBruce Richardson
81*99a2dd95SBruce Richardson /* set initial bounds for the search */
82*99a2dd95SBruce Richardson p_a = 0;
83*99a2dd95SBruce Richardson q_a = 1;
84*99a2dd95SBruce Richardson p_b = 1;
85*99a2dd95SBruce Richardson q_b = 1;
86*99a2dd95SBruce Richardson
87*99a2dd95SBruce Richardson while (1) {
88*99a2dd95SBruce Richardson uint32_t new_p_a, new_q_a, new_p_b, new_q_b;
89*99a2dd95SBruce Richardson uint32_t x_num, x_denum, x;
90*99a2dd95SBruce Richardson int aa, bb;
91*99a2dd95SBruce Richardson
92*99a2dd95SBruce Richardson /* compute the number of steps to the left */
93*99a2dd95SBruce Richardson x_num = denum * p_b - alpha_num * q_b;
94*99a2dd95SBruce Richardson x_denum = - denum * p_a + alpha_num * q_a;
95*99a2dd95SBruce Richardson x = (x_num + x_denum - 1) / x_denum; /* x = ceil(x_num / x_denum) */
96*99a2dd95SBruce Richardson
97*99a2dd95SBruce Richardson /* check whether we have a valid approximation */
98*99a2dd95SBruce Richardson aa = matches(p_b + x * p_a, q_b + x * q_a, alpha_num, d_num, denum);
99*99a2dd95SBruce Richardson bb = matches(p_b + (x-1) * p_a, q_b + (x - 1) * q_a, alpha_num, d_num, denum);
100*99a2dd95SBruce Richardson if (aa || bb) {
101*99a2dd95SBruce Richardson find_exact_solution_left(p_a, q_a, p_b, q_b, alpha_num, d_num, denum, p, q);
102*99a2dd95SBruce Richardson return 0;
103*99a2dd95SBruce Richardson }
104*99a2dd95SBruce Richardson
105*99a2dd95SBruce Richardson /* update the interval */
106*99a2dd95SBruce Richardson new_p_a = p_b + (x - 1) * p_a ;
107*99a2dd95SBruce Richardson new_q_a = q_b + (x - 1) * q_a;
108*99a2dd95SBruce Richardson new_p_b = p_b + x * p_a ;
109*99a2dd95SBruce Richardson new_q_b = q_b + x * q_a;
110*99a2dd95SBruce Richardson
111*99a2dd95SBruce Richardson p_a = new_p_a ;
112*99a2dd95SBruce Richardson q_a = new_q_a;
113*99a2dd95SBruce Richardson p_b = new_p_b ;
114*99a2dd95SBruce Richardson q_b = new_q_b;
115*99a2dd95SBruce Richardson
116*99a2dd95SBruce Richardson /* compute the number of steps to the right */
117*99a2dd95SBruce Richardson x_num = alpha_num * q_b - denum * p_b;
118*99a2dd95SBruce Richardson x_denum = - alpha_num * q_a + denum * p_a;
119*99a2dd95SBruce Richardson x = (x_num + x_denum - 1) / x_denum; /* x = ceil(x_num / x_denum) */
120*99a2dd95SBruce Richardson
121*99a2dd95SBruce Richardson /* check whether we have a valid approximation */
122*99a2dd95SBruce Richardson aa = matches(p_b + x * p_a, q_b + x * q_a, alpha_num, d_num, denum);
123*99a2dd95SBruce Richardson bb = matches(p_b + (x - 1) * p_a, q_b + (x - 1) * q_a, alpha_num, d_num, denum);
124*99a2dd95SBruce Richardson if (aa || bb) {
125*99a2dd95SBruce Richardson find_exact_solution_right(p_a, q_a, p_b, q_b, alpha_num, d_num, denum, p, q);
126*99a2dd95SBruce Richardson return 0;
127*99a2dd95SBruce Richardson }
128*99a2dd95SBruce Richardson
129*99a2dd95SBruce Richardson /* update the interval */
130*99a2dd95SBruce Richardson new_p_a = p_b + (x - 1) * p_a;
131*99a2dd95SBruce Richardson new_q_a = q_b + (x - 1) * q_a;
132*99a2dd95SBruce Richardson new_p_b = p_b + x * p_a;
133*99a2dd95SBruce Richardson new_q_b = q_b + x * q_a;
134*99a2dd95SBruce Richardson
135*99a2dd95SBruce Richardson p_a = new_p_a;
136*99a2dd95SBruce Richardson q_a = new_q_a;
137*99a2dd95SBruce Richardson p_b = new_p_b;
138*99a2dd95SBruce Richardson q_b = new_q_b;
139*99a2dd95SBruce Richardson }
140*99a2dd95SBruce Richardson }
141*99a2dd95SBruce Richardson
rte_approx(double alpha,double d,uint32_t * p,uint32_t * q)142*99a2dd95SBruce Richardson int rte_approx(double alpha, double d, uint32_t *p, uint32_t *q)
143*99a2dd95SBruce Richardson {
144*99a2dd95SBruce Richardson uint32_t alpha_num, d_num, denum;
145*99a2dd95SBruce Richardson
146*99a2dd95SBruce Richardson /* Check input arguments */
147*99a2dd95SBruce Richardson if (!((0.0 < d) && (d < alpha) && (alpha < 1.0))) {
148*99a2dd95SBruce Richardson return -1;
149*99a2dd95SBruce Richardson }
150*99a2dd95SBruce Richardson
151*99a2dd95SBruce Richardson if ((p == NULL) || (q == NULL)) {
152*99a2dd95SBruce Richardson return -2;
153*99a2dd95SBruce Richardson }
154*99a2dd95SBruce Richardson
155*99a2dd95SBruce Richardson /* Compute alpha_num, d_num and denum */
156*99a2dd95SBruce Richardson denum = 1;
157*99a2dd95SBruce Richardson while (d < 1) {
158*99a2dd95SBruce Richardson alpha *= 10;
159*99a2dd95SBruce Richardson d *= 10;
160*99a2dd95SBruce Richardson denum *= 10;
161*99a2dd95SBruce Richardson }
162*99a2dd95SBruce Richardson alpha_num = (uint32_t) alpha;
163*99a2dd95SBruce Richardson d_num = (uint32_t) d;
164*99a2dd95SBruce Richardson
165*99a2dd95SBruce Richardson /* Perform approximation */
166*99a2dd95SBruce Richardson return find_best_rational_approximation(alpha_num, d_num, denum, p, q);
167*99a2dd95SBruce Richardson }
168*99a2dd95SBruce Richardson
169*99a2dd95SBruce Richardson /* fraction comparison (64 bit version): compare (a/b) and (c/d) */
170*99a2dd95SBruce Richardson static inline uint64_t
less_64(uint64_t a,uint64_t b,uint64_t c,uint64_t d)171*99a2dd95SBruce Richardson less_64(uint64_t a, uint64_t b, uint64_t c, uint64_t d)
172*99a2dd95SBruce Richardson {
173*99a2dd95SBruce Richardson return a*d < b*c;
174*99a2dd95SBruce Richardson }
175*99a2dd95SBruce Richardson
176*99a2dd95SBruce Richardson static inline uint64_t
less_or_equal_64(uint64_t a,uint64_t b,uint64_t c,uint64_t d)177*99a2dd95SBruce Richardson less_or_equal_64(uint64_t a, uint64_t b, uint64_t c, uint64_t d)
178*99a2dd95SBruce Richardson {
179*99a2dd95SBruce Richardson return a*d <= b*c;
180*99a2dd95SBruce Richardson }
181*99a2dd95SBruce Richardson
182*99a2dd95SBruce Richardson /* check whether a/b is a valid approximation (64 bit version) */
183*99a2dd95SBruce Richardson static inline uint64_t
matches_64(uint64_t a,uint64_t b,uint64_t alpha_num,uint64_t d_num,uint64_t denum)184*99a2dd95SBruce Richardson matches_64(uint64_t a, uint64_t b,
185*99a2dd95SBruce Richardson uint64_t alpha_num, uint64_t d_num, uint64_t denum)
186*99a2dd95SBruce Richardson {
187*99a2dd95SBruce Richardson if (less_or_equal_64(a, b, alpha_num - d_num, denum))
188*99a2dd95SBruce Richardson return 0;
189*99a2dd95SBruce Richardson
190*99a2dd95SBruce Richardson if (less_64(a, b, alpha_num + d_num, denum))
191*99a2dd95SBruce Richardson return 1;
192*99a2dd95SBruce Richardson
193*99a2dd95SBruce Richardson return 0;
194*99a2dd95SBruce Richardson }
195*99a2dd95SBruce Richardson
196*99a2dd95SBruce Richardson static inline void
find_exact_solution_left_64(uint64_t p_a,uint64_t q_a,uint64_t p_b,uint64_t q_b,uint64_t alpha_num,uint64_t d_num,uint64_t denum,uint64_t * p,uint64_t * q)197*99a2dd95SBruce Richardson find_exact_solution_left_64(uint64_t p_a, uint64_t q_a, uint64_t p_b, uint64_t q_b,
198*99a2dd95SBruce Richardson uint64_t alpha_num, uint64_t d_num, uint64_t denum, uint64_t *p, uint64_t *q)
199*99a2dd95SBruce Richardson {
200*99a2dd95SBruce Richardson uint64_t k_num = denum * p_b - (alpha_num + d_num) * q_b;
201*99a2dd95SBruce Richardson uint64_t k_denum = (alpha_num + d_num) * q_a - denum * p_a;
202*99a2dd95SBruce Richardson uint64_t k = (k_num / k_denum) + 1;
203*99a2dd95SBruce Richardson
204*99a2dd95SBruce Richardson *p = p_b + k * p_a;
205*99a2dd95SBruce Richardson *q = q_b + k * q_a;
206*99a2dd95SBruce Richardson }
207*99a2dd95SBruce Richardson
208*99a2dd95SBruce Richardson static inline void
find_exact_solution_right_64(uint64_t p_a,uint64_t q_a,uint64_t p_b,uint64_t q_b,uint64_t alpha_num,uint64_t d_num,uint64_t denum,uint64_t * p,uint64_t * q)209*99a2dd95SBruce Richardson find_exact_solution_right_64(uint64_t p_a, uint64_t q_a, uint64_t p_b, uint64_t q_b,
210*99a2dd95SBruce Richardson uint64_t alpha_num, uint64_t d_num, uint64_t denum, uint64_t *p, uint64_t *q)
211*99a2dd95SBruce Richardson {
212*99a2dd95SBruce Richardson uint64_t k_num = -denum * p_b + (alpha_num - d_num) * q_b;
213*99a2dd95SBruce Richardson uint64_t k_denum = -(alpha_num - d_num) * q_a + denum * p_a;
214*99a2dd95SBruce Richardson uint64_t k = (k_num / k_denum) + 1;
215*99a2dd95SBruce Richardson
216*99a2dd95SBruce Richardson *p = p_b + k * p_a;
217*99a2dd95SBruce Richardson *q = q_b + k * q_a;
218*99a2dd95SBruce Richardson }
219*99a2dd95SBruce Richardson
220*99a2dd95SBruce Richardson static int
find_best_rational_approximation_64(uint64_t alpha_num,uint64_t d_num,uint64_t denum,uint64_t * p,uint64_t * q)221*99a2dd95SBruce Richardson find_best_rational_approximation_64(uint64_t alpha_num, uint64_t d_num,
222*99a2dd95SBruce Richardson uint64_t denum, uint64_t *p, uint64_t *q)
223*99a2dd95SBruce Richardson {
224*99a2dd95SBruce Richardson uint64_t p_a, q_a, p_b, q_b;
225*99a2dd95SBruce Richardson
226*99a2dd95SBruce Richardson /* check assumptions on the inputs */
227*99a2dd95SBruce Richardson if (!((d_num > 0) && (d_num < alpha_num) &&
228*99a2dd95SBruce Richardson (alpha_num < denum) && (d_num + alpha_num < denum))) {
229*99a2dd95SBruce Richardson return -1;
230*99a2dd95SBruce Richardson }
231*99a2dd95SBruce Richardson
232*99a2dd95SBruce Richardson /* set initial bounds for the search */
233*99a2dd95SBruce Richardson p_a = 0;
234*99a2dd95SBruce Richardson q_a = 1;
235*99a2dd95SBruce Richardson p_b = 1;
236*99a2dd95SBruce Richardson q_b = 1;
237*99a2dd95SBruce Richardson
238*99a2dd95SBruce Richardson while (1) {
239*99a2dd95SBruce Richardson uint64_t new_p_a, new_q_a, new_p_b, new_q_b;
240*99a2dd95SBruce Richardson uint64_t x_num, x_denum, x;
241*99a2dd95SBruce Richardson int aa, bb;
242*99a2dd95SBruce Richardson
243*99a2dd95SBruce Richardson /* compute the number of steps to the left */
244*99a2dd95SBruce Richardson x_num = denum * p_b - alpha_num * q_b;
245*99a2dd95SBruce Richardson x_denum = -denum * p_a + alpha_num * q_a;
246*99a2dd95SBruce Richardson x = (x_num + x_denum - 1) / x_denum; /* x = ceil(x_num / x_denum) */
247*99a2dd95SBruce Richardson
248*99a2dd95SBruce Richardson /* check whether we have a valid approximation */
249*99a2dd95SBruce Richardson aa = matches_64(p_b + x * p_a, q_b + x * q_a, alpha_num, d_num, denum);
250*99a2dd95SBruce Richardson bb = matches_64(p_b + (x-1) * p_a, q_b + (x - 1) * q_a,
251*99a2dd95SBruce Richardson alpha_num, d_num, denum);
252*99a2dd95SBruce Richardson if (aa || bb) {
253*99a2dd95SBruce Richardson find_exact_solution_left_64(p_a, q_a, p_b, q_b,
254*99a2dd95SBruce Richardson alpha_num, d_num, denum, p, q);
255*99a2dd95SBruce Richardson return 0;
256*99a2dd95SBruce Richardson }
257*99a2dd95SBruce Richardson
258*99a2dd95SBruce Richardson /* update the interval */
259*99a2dd95SBruce Richardson new_p_a = p_b + (x - 1) * p_a;
260*99a2dd95SBruce Richardson new_q_a = q_b + (x - 1) * q_a;
261*99a2dd95SBruce Richardson new_p_b = p_b + x * p_a;
262*99a2dd95SBruce Richardson new_q_b = q_b + x * q_a;
263*99a2dd95SBruce Richardson
264*99a2dd95SBruce Richardson p_a = new_p_a;
265*99a2dd95SBruce Richardson q_a = new_q_a;
266*99a2dd95SBruce Richardson p_b = new_p_b;
267*99a2dd95SBruce Richardson q_b = new_q_b;
268*99a2dd95SBruce Richardson
269*99a2dd95SBruce Richardson /* compute the number of steps to the right */
270*99a2dd95SBruce Richardson x_num = alpha_num * q_b - denum * p_b;
271*99a2dd95SBruce Richardson x_denum = -alpha_num * q_a + denum * p_a;
272*99a2dd95SBruce Richardson x = (x_num + x_denum - 1) / x_denum; /* x = ceil(x_num / x_denum) */
273*99a2dd95SBruce Richardson
274*99a2dd95SBruce Richardson /* check whether we have a valid approximation */
275*99a2dd95SBruce Richardson aa = matches_64(p_b + x * p_a, q_b + x * q_a, alpha_num, d_num, denum);
276*99a2dd95SBruce Richardson bb = matches_64(p_b + (x - 1) * p_a, q_b + (x - 1) * q_a,
277*99a2dd95SBruce Richardson alpha_num, d_num, denum);
278*99a2dd95SBruce Richardson if (aa || bb) {
279*99a2dd95SBruce Richardson find_exact_solution_right_64(p_a, q_a, p_b, q_b,
280*99a2dd95SBruce Richardson alpha_num, d_num, denum, p, q);
281*99a2dd95SBruce Richardson return 0;
282*99a2dd95SBruce Richardson }
283*99a2dd95SBruce Richardson
284*99a2dd95SBruce Richardson /* update the interval */
285*99a2dd95SBruce Richardson new_p_a = p_b + (x - 1) * p_a;
286*99a2dd95SBruce Richardson new_q_a = q_b + (x - 1) * q_a;
287*99a2dd95SBruce Richardson new_p_b = p_b + x * p_a;
288*99a2dd95SBruce Richardson new_q_b = q_b + x * q_a;
289*99a2dd95SBruce Richardson
290*99a2dd95SBruce Richardson p_a = new_p_a;
291*99a2dd95SBruce Richardson q_a = new_q_a;
292*99a2dd95SBruce Richardson p_b = new_p_b;
293*99a2dd95SBruce Richardson q_b = new_q_b;
294*99a2dd95SBruce Richardson }
295*99a2dd95SBruce Richardson }
296*99a2dd95SBruce Richardson
rte_approx_64(double alpha,double d,uint64_t * p,uint64_t * q)297*99a2dd95SBruce Richardson int rte_approx_64(double alpha, double d, uint64_t *p, uint64_t *q)
298*99a2dd95SBruce Richardson {
299*99a2dd95SBruce Richardson uint64_t alpha_num, d_num, denum;
300*99a2dd95SBruce Richardson
301*99a2dd95SBruce Richardson /* Check input arguments */
302*99a2dd95SBruce Richardson if (!((0.0 < d) && (d < alpha) && (alpha < 1.0)))
303*99a2dd95SBruce Richardson return -1;
304*99a2dd95SBruce Richardson
305*99a2dd95SBruce Richardson if ((p == NULL) || (q == NULL))
306*99a2dd95SBruce Richardson return -2;
307*99a2dd95SBruce Richardson
308*99a2dd95SBruce Richardson /* Compute alpha_num, d_num and denum */
309*99a2dd95SBruce Richardson denum = 1;
310*99a2dd95SBruce Richardson while (d < 1) {
311*99a2dd95SBruce Richardson alpha *= 10;
312*99a2dd95SBruce Richardson d *= 10;
313*99a2dd95SBruce Richardson denum *= 10;
314*99a2dd95SBruce Richardson }
315*99a2dd95SBruce Richardson alpha_num = (uint64_t) alpha;
316*99a2dd95SBruce Richardson d_num = (uint64_t) d;
317*99a2dd95SBruce Richardson
318*99a2dd95SBruce Richardson /* Perform approximation */
319*99a2dd95SBruce Richardson return find_best_rational_approximation_64(alpha_num, d_num, denum, p, q);
320*99a2dd95SBruce Richardson }
321