1use std::ops::{Add, AddAssign, Mul, Neg};
2
3pub struct FracApproxIter<I, F> {
4 lower: Fraction<I>,
5 upper: Fraction<I>,
6 bound: Option<I>,
7 pred: F,
8}
9
10impl<I: SbInt, F: Fn(I, I) -> bool> FracApproxIter<I, F> {
11 fn new(pred: F, bound: Option<I>) -> Self {
12 let (lower, upper) = if !I::SIGNED {
13 (I::lowest_frac(), I::highest_frac())
14 } else if pred(I::ZERO, I::ONE) {
15 (I::zero_frac(), I::highest_frac())
16 } else {
17 (I::lowest_frac(), I::zero_frac())
18 };
19 let (lower, upper) = (lower.into(), upper.into());
20 Self { lower, upper, bound, pred }
21 }
22
23 fn iter_return(&mut self, q: I, tf: bool) -> (ApproxFrac<I>, I) {
24 (ApproxFrac::from(((self.lower, self.upper), tf)), q)
25 }
26}
27
28impl<I: SbInt, F: Fn(I, I) -> bool> Iterator for FracApproxIter<I, F> {
29 type Item = (ApproxFrac<I>, I);
30 fn next(&mut self) -> Option<Self::Item> {
31 let Self { lower, upper, bound, pred } = self;
32 let pred = |fr: Fraction<I>| {
33 let (lower, upper) = fr.into();
34 pred(lower, upper)
35 };
36 let mediant = *lower + *upper;
37
38 if mediant.is_deeper(*bound) {
39 return None;
40 }
41
42 let tf = pred(mediant);
43 let (from, to) = if tf { (*lower, *upper) } else { (*upper, *lower) };
44
45 let mut lo = I::ONE;
46 let mut hi = lo + I::ONE;
47 while pred(from + to * hi) == tf {
48 lo += lo;
49 hi += hi;
50 if (from + to * lo).is_deeper(*bound) {
51 let bound =
52 if let Some(bound) = *bound { bound } else { continue };
53 let steps = bound.steps(from.into_inner(), to.into_inner());
54 if steps == I::ZERO {
55 return None;
56 }
57 let front = from + to * steps;
58 *(if tf { lower } else { upper }) = front;
59 return Some(self.iter_return(steps, tf));
60 }
61 }
62
63 while lo.lt1(hi) {
64 let mid = lo.avg(hi);
65 let tmp = from + to * mid;
66 let cur = !tmp.is_deeper(*bound) && pred(tmp) == tf;
67 *(if cur { &mut lo } else { &mut hi }) = mid;
68 }
69
70 *(if tf { lower } else { upper }) = from + to * lo;
71 Some(self.iter_return(lo, tf))
72 }
73}
74
75pub enum ApproxFrac<I> {
76 Lower((I, I)),
77 Upper((I, I)),
78}
79use ApproxFrac::{Lower, Upper};
80
81impl<I: std::fmt::Display> std::fmt::Debug for ApproxFrac<I> {
82 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 let (name, (num, den)) = match self {
84 Lower(x) => ("Lower", x),
85 Upper(x) => ("Upper", x),
86 };
87 fmt.debug_tuple(name).field(&format!("{}/{}", num, den)).finish()
88 }
89}
90
91impl<I> ApproxFrac<I> {
92 pub fn into_inner(self) -> (I, I) {
93 match self {
94 Lower(x) | Upper(x) => x,
95 }
96 }
97}
98
99impl<I: SbInt> From<((Fraction<I>, Fraction<I>), bool)> for ApproxFrac<I> {
100 fn from(((lower, upper), tf): ((Fraction<I>, Fraction<I>), bool)) -> Self {
101 if tf { Lower(lower.into()) } else { Upper(upper.into()) }
102 }
103}
104
105pub trait FracApprox<I, F> {
106 fn frac_approx_iter(self) -> FracApproxIter<I, F>;
107 fn frac_approx_iter_bound(self, bound: I) -> FracApproxIter<I, F>;
108 fn frac_approx_bound(self, bound: I) -> [(I, I); 2];
109}
110
111impl<I: SbInt, F: Fn(I, I) -> bool> FracApprox<I, F> for F {
112 fn frac_approx_iter(self) -> FracApproxIter<I, F> {
113 FracApproxIter::new(self, None)
114 }
115 fn frac_approx_iter_bound(self, bound: I) -> FracApproxIter<I, F> {
116 FracApproxIter::new(self, Some(bound))
117 }
118 fn frac_approx_bound(self, bound: I) -> [(I, I); 2] {
119 let mut lo = I::lowest_frac();
120 let mut hi = I::highest_frac();
121 for x in FracApproxIter::new(self, Some(bound)) {
122 match x {
123 (Lower(f), _) => lo = f,
124 (Upper(f), _) => hi = f,
125 }
126 }
127 [lo, hi]
128 }
129}
130
131pub trait SbInt:
132 Copy
133 + Eq
134 + PartialOrd<Self>
135 + AddAssign<Self>
136 + Add<Self, Output = Self>
137 + Mul<Self, Output = Self>
138 + std::fmt::Display
139 + std::fmt::Debug
140{
141 const ZERO: Self;
142 const ONE: Self;
143 const SIGNED: bool;
144 fn lt1(self, other: Self) -> bool;
145 fn avg(self, other: Self) -> Self;
146 fn abs(self) -> Self;
147 fn neg(self) -> Self;
148 fn steps(self, from: (Self, Self), to: (Self, Self)) -> Self;
149 fn lowest_frac() -> (Self, Self);
150 fn highest_frac() -> (Self, Self);
151 fn zero_frac() -> (Self, Self);
152}
153
154#[derive(Clone, Copy, Eq, PartialEq, std::fmt::Debug)]
155struct Fraction<I>(I, I);
156
157impl<I: SbInt> From<(I, I)> for Fraction<I> {
158 fn from((num, den): (I, I)) -> Self { Self(num, den) }
159}
160
161impl<I: SbInt> From<Fraction<I>> for (I, I) {
162 fn from(frac: Fraction<I>) -> Self { (frac.0, frac.1) }
163}
164
165impl<I: SbInt> Neg for Fraction<I> {
166 type Output = Self;
167 fn neg(self) -> Self { self.neg() }
168}
169
170impl<I: SbInt> Mul<I> for Fraction<I> {
171 type Output = Self;
172 fn mul(self, a: I) -> Self { Self(self.0 * a, self.1 * a) }
173}
174
175impl<I: SbInt> Add<Fraction<I>> for Fraction<I> {
176 type Output = Self;
177 fn add(self, other: Self) -> Self {
178 Self(self.0 + other.0, self.1 + other.1)
180 }
181}
182
183impl<I: SbInt> Fraction<I> {
184 fn is_deeper(self, bound: Option<I>) -> bool {
185 bound.into_iter().any(|b| self.1 > b)
186 }
187 fn neg(self) -> Self { Self(self.0.neg(), self.1) }
188 fn into_inner(self) -> (I, I) { (self.0, self.1) }
189}
190
191macro_rules! impl_uint {
192 ( $($ty:ty)* ) => { $(
193 impl SbInt for $ty {
194 const ZERO: $ty = 0;
195 const ONE: $ty = 1;
196 const SIGNED: bool = false;
197 fn lt1(self, other: Self) -> bool { self + 1 < other }
198 fn avg(self, other: Self) -> Self {
199 self + (other - self) / 2
200 }
201 fn abs(self) -> Self { self }
202 fn neg(self) -> Self { self.wrapping_neg() } fn steps(self, from: (Self, Self), to: (Self, Self)) -> Self {
204 if to.0 == 0 {
205 (self - from.1) / to.1
206 } else if to.1 == 0 {
207 (self - from.0) / to.0
208 } else {
209 ((self - from.0) / to.0).min((self - from.1) / to.1)
210 }
211 }
212 fn lowest_frac() -> (Self, Self) { (0, 1) }
213 fn highest_frac() -> (Self, Self) { (1, 0) }
214 fn zero_frac() -> (Self, Self) { (0, 1) }
215 }
216 )* }
217}
218
219impl_uint! { u8 u16 u32 u64 u128 usize }
220
221macro_rules! impl_int {
222 ( $($ty:ty)* ) => { $(
223 impl SbInt for $ty {
224 const ZERO: $ty = 0;
225 const ONE: $ty = 1;
226 const SIGNED: bool = true;
227 fn lt1(self, other: Self) -> bool { self + 1 < other }
228 fn avg(self, other: Self) -> Self {
229 self + (other - self) / 2
230 }
231 fn abs(self) -> Self { self.abs() }
232 fn neg(self) -> Self { -self}
233 fn steps(self, from: (Self, Self), to: (Self, Self)) -> Self {
234 if to.0 == 0 {
235 (self - from.1) / to.1
236 } else if to.1 == 0 {
237 (self - from.0) / to.0
238 } else {
239 ((self - from.0) / to.0).min((self - from.1) / to.1)
240 }
241 }
242 fn lowest_frac() -> (Self, Self) { (-1, 0) }
243 fn highest_frac() -> (Self, Self) { (1, 0) }
244 fn zero_frac() -> (Self, Self) { (0, 1) }
245 }
246 )* }
247}
248
249impl_int! { i8 i16 i32 i64 i128 isize }
250
251#[test]
252fn sanity_check() {
253 let sqrt2 = |p: i128, q| p * p <= 2 * q * q;
254 for ap in sqrt2.frac_approx_iter().take(30) {
255 eprintln!("{ap:?}");
256 }
257
258 eprintln!("{:?}", sqrt2.frac_approx_bound(10000));
259
260 let frac = |p: i128, q| 113 * p <= 355 * q;
261 for ap in frac.frac_approx_iter_bound(113) {
262 eprintln!("{ap:?}");
263 }
264
265 const PI_INT: u128 = 3;
266 const PI_FRAC: &str = "141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647";
267 let pi = |p: u128, q| {
268 if p / q != PI_INT {
270 return p / q < PI_INT;
271 }
272 let mut r = p % q * 10;
273 for d in PI_FRAC.bytes().map(|b| (b - b'0') as u128) {
274 if r / q != d {
275 return r / q < d;
276 }
277 r = r % q * 10;
278 }
279 true
280 };
281 for ap in pi.frac_approx_iter_bound(10_u128.pow(18)) {
282 eprintln!("{ap:?}");
283 }
284}