1use crate::extended::{ExtendedInt, Infinity};
32use num::{BigInt, FromPrimitive, One, Zero};
33use std::iter::Peekable;
34
35pub struct State {
37 a: BigInt,
38 b: BigInt,
39 c: BigInt,
40 d: BigInt,
41}
42
43pub mod input {
44 use super::State;
45 use crate::{
46 extended::{ExtendedInt, ExtendedRational, Infinity},
47 rational::Rational,
48 };
49 use num::BigInt;
50 use std::iter::Peekable;
51
52 pub trait Input {
54 type Domain: Infinity;
55 fn peek_domain(&mut self) -> Self::Domain;
56 fn update_state(&mut self, state: &State) -> State;
57 }
58
59 pub struct Regular<I>(pub I);
61 impl<I> Input for Regular<Peekable<I>>
62 where
63 I: Iterator<Item = BigInt>,
64 {
65 type Domain = ExtendedInt;
66
67 fn peek_domain(&mut self) -> Self::Domain {
68 ExtendedInt::from(self.0.peek().cloned())
69 }
70
71 fn update_state(&mut self, state: &State) -> State {
72 let State { a, b, c, d } = state;
73 match &ExtendedInt::from(self.0.next()) {
74 ExtendedInt::Infinity => State {
75 a: a.clone(),
76 b: a.clone(),
77 c: c.clone(),
78 d: c.clone(),
79 },
80 ExtendedInt::Finite(p) => State {
81 a: b + a * p,
82 b: a.clone(),
83 c: d + c * p,
84 d: c.clone(),
85 },
86 }
87 }
88 }
89
90 pub struct Generalized<I>(pub I);
94 impl<I> Input for Generalized<Peekable<I>>
95 where
96 I: Iterator<Item = Rational>,
97 {
98 type Domain = ExtendedRational;
99
100 fn peek_domain(&mut self) -> Self::Domain {
101 ExtendedRational::from(self.0.peek().cloned())
102 }
103
104 fn update_state(&mut self, state: &State) -> State {
105 let State { a, b, c, d } = state;
106 match &ExtendedRational::from(self.0.next()) {
107 ExtendedRational::Finite(Rational(num, den)) => State {
108 a: a * num + b * den,
109 b: a.clone(),
110 c: c * num + d * den,
111 d: c.clone(),
112 },
113 _ => unimplemented!("Only infinite general continued fractions are supported"),
114 }
115 }
116 }
117}
118
119pub mod output {
120 use num::{BigInt, Zero};
121
122 use crate::extended::Infinity;
123
124 use super::State;
125
126 pub trait Output {
128 type Range;
129 type Term;
130
131 fn is_done<D: Infinity>(&self, state: &State, domain: &D) -> bool;
132 fn well_defined_range<D: Infinity>(&self, state: &State, domain: &D)
133 -> Option<Self::Range>;
134 fn update_state(&self, state: &State, range: &Self::Range) -> State;
135 fn emit(&self, range: &Self::Range) -> Self::Term;
136 }
137
138 pub struct Regular;
140 impl Output for Regular {
141 type Range = BigInt;
142 type Term = BigInt;
143
144 fn is_done<D: Infinity>(&self, state: &State, domain: &D) -> bool {
145 if domain.is_infinite() {
146 state.c.is_zero()
147 } else {
148 state.c.is_zero() && state.d.is_zero()
149 }
150 }
151
152 fn well_defined_range<D: Infinity>(
153 &self,
154 state: &State,
155 domain: &D,
156 ) -> Option<Self::Range> {
157 state.factor_integer(domain)
158 }
159
160 fn update_state(&self, state: &State, r: &Self::Range) -> State {
161 let State { a, b, c, d } = state;
162 State {
163 a: c.clone(),
164 b: d.clone(),
165 c: a - c * r,
166 d: b - d * r,
167 }
168 }
169
170 fn emit(&self, r: &Self::Range) -> Self::Term {
171 r.clone()
172 }
173 }
174
175 pub struct Decimal;
177 impl Output for Decimal {
178 type Range = BigInt;
179 type Term = BigInt;
180
181 fn is_done<D: Infinity>(&self, state: &State, domain: &D) -> bool {
182 if domain.is_infinite() {
183 state.a.is_zero() } else {
185 state.a.is_zero() && state.b.is_zero()
186 }
187 }
188
189 fn well_defined_range<D: Infinity>(
190 &self,
191 state: &State,
192 domain: &D,
193 ) -> Option<Self::Range> {
194 state.factor_integer(domain)
195 }
196
197 fn update_state(&self, state: &State, r: &Self::Range) -> State {
198 let State { a, b, c, d } = state;
199 State {
200 a: (a - c * r) * BigInt::from(10),
201 b: (b - d * r) * BigInt::from(10),
202 c: c.clone(),
203 d: d.clone(),
204 }
205 }
206
207 fn emit(&self, r: &Self::Range) -> Self::Term {
208 r.clone()
209 }
210 }
211}
212
213impl State {
214 pub fn identity() -> State {
215 State {
216 a: BigInt::one(),
217 b: BigInt::zero(),
218 c: BigInt::zero(),
219 d: BigInt::one(),
220 }
221 }
222
223 pub fn from_i8(a: i8, b: i8, c: i8, d: i8) -> State {
224 State {
225 a: BigInt::from_i8(a).unwrap(),
226 b: BigInt::from_i8(b).unwrap(),
227 c: BigInt::from_i8(c).unwrap(),
228 d: BigInt::from_i8(d).unwrap(),
229 }
230 }
231
232 pub fn factor_integer<D: Infinity>(&self, domain: &D) -> Option<BigInt> {
233 let State { a, b, c, d } = self;
234
235 if domain.is_infinite() {
236 let ac = ExtendedInt::divide_ints(a, c);
237 match ac {
238 ExtendedInt::Finite(x) => Some(x),
239 _ => None,
240 }
241 } else {
242 let ac = ExtendedInt::divide_ints(a, c);
243 if matches!(ac, ExtendedInt::Infinity) {
244 return None;
245 }
246
247 let bd = ExtendedInt::divide_ints(b, d);
248 if matches!(bd, ExtendedInt::Infinity) {
249 return None;
250 }
251
252 match (ac, bd) {
253 (ExtendedInt::Finite(x), ExtendedInt::Finite(y)) if x.eq(&y) => Some(x),
254 _ => None,
255 }
256 }
257 }
258}
259
260pub struct Solver<I, O> {
262 state: State,
263 input: I,
264 output: O,
265}
266
267impl<I, O> Solver<I, O>
268where
269 I: input::Input,
270 O: output::Output,
271{
272 pub fn identity(input: I, output: O) -> Self {
273 Self {
274 state: State::identity(),
275 input,
276 output,
277 }
278 }
279}
280
281impl<I, O> Iterator for Solver<I, O>
282where
283 I: input::Input,
284 O: output::Output,
285{
286 type Item = O::Term;
287
288 fn next(&mut self) -> Option<Self::Item> {
289 loop {
290 let domain = self.input.peek_domain();
291 if self.output.is_done(&self.state, &domain) {
292 return None;
293 }
294
295 let range = self.output.well_defined_range(&self.state, &domain);
296 if let Some(r) = range {
297 self.state = self.output.update_state(&self.state, &r);
298 return Some(self.output.emit(&r));
299 } else if !domain.is_infinite() {
300 self.state = self.input.update_state(&self.state);
301 } else {
302 return None;
305 }
306 }
307 }
308}
309
310pub type DecimalSolver<I> = Solver<input::Regular<Peekable<I>>, output::Decimal>;
312
313pub type GeneralizedSolver<I> = Solver<input::Generalized<Peekable<I>>, output::Regular>;
316
317#[cfg(test)]
318mod tests {
319 use crate::{consts, terms};
320 use num::ToPrimitive;
321
322 #[test]
323 fn it_emits_phi_as_decimal() {
324 let terms::Decimal(iter) = terms::Decimal::from(terms::Regular::from(consts::Phi));
325 assert!(iter
326 .take(10)
327 .map(|i| i.to_i32().unwrap())
328 .eq([1, 6, 1, 8, 0, 3, 3, 9, 8, 8]));
329 }
330
331 #[test]
332 fn it_emits_pi_as_decimal() {
333 let terms::Decimal(iter) = terms::Decimal::from(terms::Regular::from(consts::Pi));
334 assert!(iter
335 .take(11)
336 .map(|i| i.to_i32().unwrap())
337 .eq([3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]));
338 }
339
340 #[test]
341 fn it_emits_pi_as_regular_continued_fraction() {
342 let terms::Regular(iter) = terms::Regular::from(consts::Pi);
343 assert!(iter
344 .take(13)
345 .map(|i| i.to_i32().unwrap())
346 .eq([3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14]));
347 }
348}