using namespace std;
int
factorial(
int
n){
int
fc
=
1
;
for
(
int
i
=
1
;i<
=
n;
+
+
i) fc
*
=
i;
return
fc;
}
int
combo(
int
n,
int
m){
return
factorial(n)
/
(factorial(m)
*
factorial(n
-
m));
}
fmpz
*
*
gen_poly(
int
degree){
fmpz_mod_ctx ctx;
fmpz n
=
1LL
<<
32
;
fmpz_mod_ctx_init(&ctx, &n);
fmpz_mod_poly_struct f, g;
fmpz_mod_poly_init(&f, &ctx);
fmpz_mod_poly_init(&g, &ctx);
fmpz m
=
degree;
fmpz
*
a
=
new fmpz[m
+
1
];
fmpz
*
b
=
new fmpz[m
+
1
];
fmpz a1_inv;
fmpz
*
A
=
new fmpz[m
+
1
];
fmpz
*
A_sum
=
new fmpz[m
+
1
];
a[
0
]
=
rand(), a[
1
]
=
rand() |
1
;
for
(
int
i
=
2
;i <
=
m;i
+
+
){
a[i]
=
(rand() >>
16
) <<
16
;
}
/
/
Calculate a1_inv
fmpz_mod_inv(&a1_inv, a
+
1
, &ctx);
/
/
Calculate A
fmpz_mod_pow_ui(A
+
m, &a1_inv, m, &ctx);
fmpz_mod_neg(A
+
m, A
+
m, &ctx);
fmpz_mod_mul(A
+
m, A
+
m, a
+
m, &ctx);
for
(
int
k
=
m
-
1
; k >
=
0
;k
-
-
){
fmpz
sum
=
0
;
for
(
int
j
=
k
+
1
;j <
=
m;j
+
+
){
fmpz tmp;
fmpz_mod_pow_ui(&tmp, a, j
-
k, &ctx);
fmpz_mod_mul(&tmp, &tmp, A
+
j, &ctx);
fmpz_mod_mul_ui(&tmp, &tmp, combo(j, k), &ctx);
fmpz_mod_add(&
sum
, &
sum
, &tmp, &ctx);
}
fmpz_mod_pow_ui(A
+
k, &a1_inv, k, &ctx);
fmpz_mod_mul(A
+
k, A
+
k, a
+
k, &ctx);
fmpz_mod_neg(A
+
k, A
+
k, &ctx);
fmpz_mod_sub(A
+
k, A
+
k, &
sum
, &ctx);
A_sum[k]
=
sum
;
}
/
/
Calculate bm
fmpz_mod_pow_ui(b
+
m, &a1_inv, m
+
1
, &ctx);
fmpz_mod_neg(b
+
m, b
+
m, &ctx);
fmpz_mod_mul(b
+
m, b
+
m, a
+
m, &ctx);
/
/
Calculate bk
for
(
int
k
=
2
;k < m;k
+
+
){
fmpz_mod_pow_ui(b
+
k, &a1_inv, k
+
1
, &ctx);
fmpz_mod_mul(b
+
k, b
+
k, a
+
k, &ctx);
fmpz_mod_neg(b
+
k, b
+
k, &ctx);
fmpz tmp;
fmpz_mod_mul(&tmp, &a1_inv, A_sum
+
k, &ctx);
fmpz_mod_sub(b
+
k, b
+
k, &tmp, &ctx);
}
/
/
Calculate b1
fmpz
sum
=
0
;
for
(
int
j
=
2
;j <
=
m;j
+
+
){
fmpz tmp;
fmpz_mod_pow_ui(&tmp, a, j
-
1
, &ctx);
fmpz_mod_mul(&tmp, &tmp, A
+
j, &ctx);
fmpz_mod_mul_ui(&tmp, &tmp, j, &ctx);
fmpz_mod_add(&
sum
, &
sum
, &tmp, &ctx);
}
fmpz_mod_mul(&
sum
, &
sum
, &a1_inv, &ctx);
fmpz_mod_sub(b
+
1
, &a1_inv, &
sum
, &ctx);
/
/
Calculate b0
b[
0
]
=
0
;
for
(
int
j
=
1
;j <
=
m;j
+
+
){
fmpz tmp;
fmpz_mod_pow_ui(&tmp, a, j, &ctx);
fmpz_mod_mul(&tmp, &tmp, b
+
j, &ctx);
fmpz_mod_add(b, b, &tmp, &ctx);
}
fmpz_mod_neg(b, b, &ctx);
fmpz
*
*
coeff
=
new fmpz
*
[
2
];
coeff[
0
]
=
a, coeff[
1
]
=
b;
delete[] A;
delete[] A_sum;
return
coeff;
}
int
main(){
int
degree
=
10
;
srand(time(NULL));
fmpz
*
*
coeff
=
gen_poly(degree);
fmpz_mod_ctx ctx;
fmpz n
=
1LL
<<
32
;
fmpz_mod_ctx_init(&ctx, &n);
fmpz_mod_poly_struct f, g, res;
fmpz_mod_poly_init(&f, &ctx);
fmpz_mod_poly_init(&g, &ctx);
fmpz_mod_poly_init(&res, &ctx);
for
(
int
i
=
0
;i <
=
degree;i
+
+
){
fmpz_mod_poly_set_coeff_ui(&f, i, coeff[
0
][i], &ctx);
fmpz_mod_poly_set_coeff_ui(&g, i, coeff[
1
][i], &ctx);
}
fmpz_mod_poly_compose(&res, &g, &f, &ctx);
flint_printf(
"f(x) = "
); fmpz_mod_poly_print_pretty(&f,
"x"
, &ctx); flint_printf(
"\n"
);
flint_printf(
"g(x) = "
); fmpz_mod_poly_print_pretty(&g,
"x"
, &ctx); flint_printf(
"\n"
);
flint_printf(
"g(f(x)) = "
); fmpz_mod_poly_print_pretty(&res,
"x"
, &ctx); flint_printf(
"\n"
);
}