6 // sin 1 from Taylor series
7 static void *sin1_expansion(cf_t cf
) {
8 mpz_t p0
, q0
; // p0/q0 = last convergent
9 mpz_t p1
, q1
; // p1/q1 = convergent
10 mpq_t r0
; // lower bound for sin 1
11 mpq_t r1
; // upper bound for sin 1
12 mpz_t t0
, t1
, t2
; // Temporary variables.
15 mpq_init(r0
); mpq_init(r1
);
16 mpz_init(p0
); mpz_init(p1
); mpz_init(q0
); mpz_init(q1
);
17 mpz_init(t0
); mpz_init(t1
); mpz_init(t2
);
20 // Zero causes all sorts of problems.
21 // Output it and forget about it.
24 // Initialize convergents.
28 // sin 1 = 1 - 1/6 + ...
32 int k
= 1; // Number of Taylor series terms we've computed,
33 // numbered from 0, unlike continued fraction terms.
34 int i
= 2; // Number of convergent we're computing.
36 void increase_limit() {
38 mpz_mul_ui(mpq_numref(r1
), mpq_numref(r0
), (2 * k
) * (2 * k
+ 1));
39 mpz_mul_ui(mpq_denref(r1
), mpq_denref(r0
), (2 * k
) * (2 * k
+ 1));
40 mpz_add_ui(mpq_numref(r1
), mpq_numref(r1
), 1);
42 mpz_mul_ui(mpq_numref(r0
), mpq_numref(r1
), (2 * k
) * (2 * k
+ 1));
43 mpz_mul_ui(mpq_denref(r0
), mpq_denref(r1
), (2 * k
) * (2 * k
+ 1));
44 mpz_sub_ui(mpq_numref(r0
), mpq_numref(r0
), 1);
49 // Find largest x such that (p1 x + p0)/(q1 x + q0)
50 // <= r0 for odd i, and >= r1 for even i
51 // => x < (q0 num(r) - p0 den(r))/(p1 den(r) - q1 num(r))
52 // for the appropriate r.
53 mpq_ptr r
= i
& 1 ? r0
: r1
;
54 mpz_mul(t0
, q0
, mpq_numref(r
));
55 mpz_mul(t1
, p0
, mpq_denref(r
));
57 mpz_mul(t0
, p1
, mpq_denref(r
));
58 mpz_mul(t1
, q1
, mpq_numref(r
));
60 mpz_fdiv_q(t0
, t2
, t1
);
62 // Then x is the next convergent provided substituting x + 1 overshoots
63 // the other bound. (If not, we need better bounds to decide.)
67 mpz_add_ui(t1
, t0
, 1);
68 mpz_set(mpq_numref(tq0
), p0
);
69 mpz_addmul(mpq_numref(tq0
), p1
, t1
);
70 mpz_set(mpq_denref(tq0
), q0
);
71 mpz_addmul(mpq_denref(tq0
), q1
, t1
);
73 if (mpq_cmp(tq0
, r1
) > 0) break;
74 // Check (p1(x+1) + p0)/(q1(x+1) + q0) > r1
76 if (mpq_cmp(tq0
, r0
) < 0) break;
77 // Check (p1(x+1) + p0)/(q1(x+1) + q0) < r0
84 mpz_addmul(p0
, p1
, t0
);
85 mpz_addmul(q0
, q1
, t0
);
90 mpq_clear(r0
); mpq_clear(r1
);
91 mpz_clear(p0
); mpz_clear(p1
); mpz_clear(q0
); mpz_clear(q1
);
92 mpz_clear(t0
); mpz_clear(t1
); mpz_clear(t2
);
97 int main(int argc
, char *argv
[]) {
98 cf_t x
= cf_new_const(sin1_expansion
);
99 cf_t conv
= cf_new_convergent(x
);
102 for (int i
= 0; i
< 20; i
++) {
103 cf_get(z
, conv
); gmp_printf("%d: %Zd/", i
, z
);
104 cf_get(z
, conv
); gmp_printf("%Zd\n", z
);