1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use crate::prelude::*;
use poly::*;
#[inline]
#[cfg_attr(feature = "use_attributes", unsafe_hacspec)]
pub(crate) fn extended_euclid_internal<T: Integer + Copy>(
x: &[T],
y: &[T],
n: T,
) -> Result<Vec<T>, &'static str> {
let (yd, _) = leading_coefficient(y);
let (xd, _) = leading_coefficient(x);
debug_assert!(yd >= xd);
debug_assert!(yd > 0);
let mut f = make_fixed_length(y, yd + 1);
f.reverse();
let mut g = make_fixed_length(x, yd);
g.reverse();
let (delta, f, _g, v) = divstepsx(2 * yd - 1, 2 * yd - 1, &f, &g, n);
if delta != 0 {
return Err("Could not invert the polynomial");
}
let t = monomial(f[0].inv(n), 2 * yd - 2 - v.1);
let mut rr = poly_mul(&t, &v.0, n);
rr = make_fixed_length(&rr, yd);
rr.reverse();
Ok(rr)
}
fn divstepsx<T: Integer + Copy>(
nn: usize,
t: usize,
fin: &[T],
gin: &[T],
n: T,
) -> (i128, Vec<T>, Vec<T>, (Vec<T>, usize)) {
debug_assert!(t >= nn);
let mut f = fin.to_vec();
let mut g = gin.to_vec();
let mut delta = 1;
let mut u = (vec![T::ONE(); 1], 0);
let mut v = (vec![T::ZERO(); 1], 0);
let mut q = (vec![T::ZERO(); 1], 0);
let mut r = (vec![T::ONE(); 1], 0);
for i in 0..nn {
u.0 = make_fixed_length(&u.0, t);
v.0 = make_fixed_length(&v.0, t);
q.0 = make_fixed_length(&q.0, t);
r.0 = make_fixed_length(&r.0, t);
f = make_fixed_length(&f, nn - i);
g = make_fixed_length(&g, nn - i);
if delta > 0 && !g[0].equal(T::ZERO()) {
delta = -delta;
core::mem::swap(&mut f, &mut g);
core::mem::swap(&mut q, &mut u);
core::mem::swap(&mut r, &mut v);
}
delta = delta + 1;
let f0 = monomial(f[0], 0);
let g0 = monomial(g[0], 0);
let t0 = poly_mul(&f0, &g, n);
let t1 = poly_mul(&g0, &f, n);
g = poly_sub(&t0, &t1, n);
g = poly_divx(&g);
let t0 = poly_mul(&f0, &q.0, n);
let t1 = poly_mul(&g0, &u.0, n);
q = quot_sub(&t0, q.1, &t1, u.1, n);
q.1 += 1;
let t0 = poly_mul(&f0, &r.0, n);
let t1 = poly_mul(&g0, &v.0, n);
r = quot_sub(&t0, r.1, &t1, v.1, n);
r.1 += 1;
}
(delta, f, g, v)
}
fn poly_divx<T: Numeric + Copy>(v: &[T]) -> Vec<T> {
let mut out = vec![T::default(); v.len() - 1];
for (a, &b) in out.iter_mut().zip(v.iter().skip(1)) {
*a = b;
}
out
}
fn quot_sub<T: Integer + Copy>(an: &[T], ad: usize, bn: &[T], bd: usize, n: T) -> (Vec<T>, usize) {
let cd = core::cmp::max(ad, bd);
let x = monomial(T::ONE(), 1);
let mut a = an.to_vec();
let mut b = bn.to_vec();
for _ in 0..cd - ad {
a = poly_mul(&a, &x, n);
}
for _ in 0..cd - bd {
b = poly_mul(&b, &x, n);
}
(poly_sub(&a, &b, n), cd)
}