1use std::{
11 fmt,
12 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign},
13 sync::Arc,
14};
15type Q = rug::Rational;
16type Z = rug::Integer;
17
18#[derive(Debug, Clone, PartialEq, Eq)]
19struct QuadraticField {
20 a: Q,
21 b: Q,
22 d: Arc<Z>,
23}
24impl fmt::Display for QuadraticField {
25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
26 write!(f, "{}+{}√{}", self.a, self.b, self.d)
27 }
28}
29#[auto_impl_ops::auto_ops]
30impl AddAssign<&QuadraticField> for QuadraticField {
31 fn add_assign(&mut self, other: &Self) {
32 assert_eq!(self.d, other.d);
33 self.a += &other.a;
34 self.b += &other.b;
35 }
36}
37#[auto_impl_ops::auto_ops]
38impl SubAssign<&QuadraticField> for QuadraticField {
39 fn sub_assign(&mut self, other: &Self) {
40 assert_eq!(self.d, other.d);
41 self.a -= &other.a;
42 self.b -= &other.b;
43 }
44}
45#[auto_impl_ops::auto_ops]
46impl SubAssign<&Z> for QuadraticField {
47 fn sub_assign(&mut self, other: &Z) {
48 self.a -= other;
49 }
50}
51#[auto_impl_ops::auto_ops]
52impl MulAssign<&QuadraticField> for QuadraticField {
53 fn mul_assign(&mut self, other: &Self) {
54 assert_eq!(self.d, other.d);
55 let new_a = Q::from(&self.a * &other.a) + Q::from(&self.b * &other.b) * &*self.d;
56 self.b = Q::from(&self.a * &other.b) + Q::from(&self.b * &other.a);
57 self.a = new_a;
58 }
59}
60#[auto_impl_ops::auto_ops]
61impl DivAssign<&QuadraticField> for QuadraticField {
62 fn div_assign(&mut self, other: &Self) {
63 assert_eq!(self.d, other.d);
64 let denom = Q::from(other.a.square_ref()) - Q::from(other.b.square_ref()) * &*self.d;
65 let new_a = (Q::from(&self.a * &other.a) - Q::from(&self.b * &other.b) * &*self.d) / &denom;
66 self.b = (Q::from(&self.b * &other.a) - Q::from(&self.a * &other.b)) / denom;
67 self.a = new_a;
68 }
69}
70impl QuadraticField {
71 fn from_integer(v: Z, d: Arc<Z>) -> Self {
72 Self {
73 a: Q::from(v),
74 b: Q::ZERO.clone(),
75 d,
76 }
77 }
78 fn one(d: Arc<Z>) -> Self {
79 Self::from_integer(Z::ONE.clone(), d)
80 }
81 fn recip(&self) -> Self {
82 QuadraticField::one(Arc::clone(&self.d)) / self
83 }
84 fn floor(&self) -> Z {
85 let d = Z::from(self.d.sqrt_ref());
86 let mut left = &self.a + Q::from(&self.b * &d);
87 let mut right = &self.a + Q::from(&self.b * (d + 1));
88 if right < left {
89 std::mem::swap(&mut left, &mut right);
90 }
91 let offset = Q::from(self.b.square_ref()) * &*self.d;
92 while Q::from(left.floor_ref()) != Q::from(right.floor_ref()) {
93 let mid = Q::from(&left + &right) / 2;
94 let y = Q::from(&mid - &self.a).square() - &offset;
95 if y <= *Q::ZERO {
96 left = mid;
97 } else {
98 right = mid;
99 }
100 }
101 left.floor().numer().clone()
102 }
103}
104
105pub fn continued_fraction_of_sqrt(d: Z) -> Vec<Z> {
116 let sd = Z::from(d.sqrt_ref());
117 if Z::from(sd.square_ref()) == d {
118 return vec![sd];
119 }
120 let d = Arc::new(d);
121 let mut v = QuadraticField {
122 a: Q::ZERO.clone(),
123 b: Q::ONE.clone(),
124 d: Arc::clone(&d),
125 };
126 let int = v.floor();
127 v = (v - &int).recip();
128 let v0 = v.clone();
129 let mut a = vec![int];
130 loop {
131 let int = v.floor();
132 v = (v - &int).recip();
133 a.push(int);
134 if v == v0 {
135 return a;
136 }
137 }
138}
139
140#[derive(Debug, Clone, PartialEq, Eq)]
142pub enum Solution {
143 Negative(Z, Z),
145 Positive(Z, Z),
147}
148
149pub fn solve_pell(d: Z) -> Solution {
161 let a = continued_fraction_of_sqrt(d.clone());
162 let mut p_old = Z::ONE.clone();
163 let mut q_old = Z::ZERO;
164 let mut p_now = a[0].clone();
165 let mut q_now = Z::ONE.clone();
166 let z = Q::from(p_now.square_ref()) - Q::from(q_now.square_ref()) * &d;
169 if z == -Z::ONE.clone() {
170 return Solution::Negative(p_now, q_now);
171 } else if z == *Z::ONE {
172 return Solution::Positive(p_now, q_now);
173 }
174 for a in a.iter().skip(1) {
175 let p_new = a * &p_now + p_old;
176 let q_new = a * &q_now + q_old;
177 p_old = p_now;
178 q_old = q_now;
179 p_now = p_new;
180 q_now = q_new;
181 let z = Q::from(p_now.square_ref()) - Q::from(q_now.square_ref()) * &d;
183 if z == -Z::ONE.clone() {
184 return Solution::Negative(p_now, q_now);
185 } else if z == *Z::ONE {
186 return Solution::Positive(p_now, q_now);
187 }
188 }
189 unreachable!()
190}
191
192#[cfg(test)]
193mod tests {
194 use super::*;
195
196 #[test]
197 fn test() {
198 let d = Arc::new(Z::from(3));
199 let q = QuadraticField {
200 a: Q::ZERO.clone(),
201 b: Q::ONE.clone(),
202 d: Arc::clone(&d),
203 };
204 let a = q.floor();
205 assert_eq!(&a, Z::ONE);
206 let q = (q - a).recip();
207 let r = QuadraticField {
208 a: Q::from_f64(0.5).unwrap(),
209 b: Q::from_f64(0.5).unwrap(),
210 d: Arc::clone(&d),
211 };
212 assert_eq!(q, r);
213 }
214 fn to_z(v: &[i32]) -> Vec<Z> {
215 v.iter().map(|x| Z::from(*x)).collect()
216 }
217 #[test]
219 fn test_continued_fraction_of_sqrt2() {
220 let v = continued_fraction_of_sqrt(Z::from(2));
221 assert_eq!(v, to_z(&[1, 2]));
222 }
223 #[test]
224 fn test_continued_fraction_of_sqrt3() {
225 let v = continued_fraction_of_sqrt(Z::from(3));
226 assert_eq!(v, to_z(&[1, 1, 2]));
227 }
228 #[test]
229 fn test_continued_fraction_of_sqrt5() {
230 let v = continued_fraction_of_sqrt(Z::from(5));
231 assert_eq!(v, to_z(&[2, 4]));
232 }
233 #[test]
234 fn test_continued_fraction_of_sqrt6() {
235 let v = continued_fraction_of_sqrt(Z::from(6));
236 assert_eq!(v, to_z(&[2, 2, 4]));
237 }
238 #[test]
239 fn test_continued_fraction_of_sqrt7() {
240 let v = continued_fraction_of_sqrt(Z::from(7));
241 assert_eq!(v, to_z(&[2, 1, 1, 1, 4]));
242 }
243 #[test]
244 fn test_continued_fraction_of_sqrt8() {
245 let v = continued_fraction_of_sqrt(Z::from(8));
246 assert_eq!(v, to_z(&[2, 1, 4]));
247 }
248 #[test]
249 fn test_continued_fraction_of_sqrt10() {
250 let v = continued_fraction_of_sqrt(Z::from(10));
251 assert_eq!(v, to_z(&[3, 6]));
252 }
253 #[test]
254 fn test_continued_fraction_of_sqrt11() {
255 let v = continued_fraction_of_sqrt(Z::from(11));
256 assert_eq!(v, to_z(&[3, 3, 6]));
257 }
258 #[test]
259 fn test_continued_fraction_of_sqrt12() {
260 let v = continued_fraction_of_sqrt(Z::from(12));
261 assert_eq!(v, to_z(&[3, 2, 6]));
262 }
263 #[test]
264 fn test_continued_fraction_of_sqrt13() {
265 let v = continued_fraction_of_sqrt(Z::from(13));
266 assert_eq!(v, to_z(&[3, 1, 1, 1, 1, 6]));
267 }
268 #[test]
269 fn test_continued_fraction_of_sqrt31() {
270 let v = continued_fraction_of_sqrt(Z::from(31));
271 assert_eq!(v, to_z(&[5, 1, 1, 3, 5, 3, 1, 1, 10]));
272 }
273 #[test]
274 fn test_continued_fraction_of_sqrt94() {
275 let v = continued_fraction_of_sqrt(Z::from(94));
276 assert_eq!(
277 v,
278 to_z(&[9, 1, 2, 3, 1, 1, 5, 1, 8, 1, 5, 1, 1, 3, 2, 1, 18])
279 );
280 }
281 #[test]
282 fn test_continued_fraction_of_sqrt338() {
283 let v = continued_fraction_of_sqrt(Z::from(338));
284 assert_eq!(v, to_z(&[18, 2, 1, 1, 2, 36]));
285 }
286 #[test]
287 fn test_solve_pell() {
288 let v = solve_pell(Z::from(653));
289 assert_eq!(
290 v,
291 Solution::Negative(Z::from(2291286382u64), Z::from(89664965))
292 );
293 }
294 #[test]
295 fn test_solve_pell2() {
296 let v = solve_pell(Z::from(115));
297 assert_eq!(v, Solution::Positive(Z::from(1126), Z::from(105)));
298 }
299}