+/** Calculates the bound for the modulus.
+ * See [Mig].
+ */
+static inline cl_I calc_bound(const ex& a, const ex& x, int maxdeg)
+{
+ cl_I maxcoeff = 0;
+ cl_R coeff = 0;
+ for ( int i=a.degree(x); i>=a.ldegree(x); --i ) {
+ cl_I aa = abs(the<cl_I>(ex_to<numeric>(a.coeff(x, i)).to_cl_N()));
+ if ( aa > maxcoeff ) maxcoeff = aa;
+ coeff = coeff + square(aa);
+ }
+ cl_I coeffnorm = ceiling1(the<cl_R>(cln::sqrt(coeff)));
+ cl_I B = coeffnorm * expt_pos(cl_I(2), cl_I(maxdeg));
+ return ( B > maxcoeff ) ? B : maxcoeff;
+}
+
+/** Calculates the bound for the modulus.
+ * See [Mig].
+ */
+static inline cl_I calc_bound(const upoly& a, int maxdeg)
+{
+ cl_I maxcoeff = 0;
+ cl_R coeff = 0;
+ for ( int i=degree(a); i>=0; --i ) {
+ cl_I aa = abs(a[i]);
+ if ( aa > maxcoeff ) maxcoeff = aa;
+ coeff = coeff + square(aa);
+ }
+ cl_I coeffnorm = ceiling1(the<cl_R>(cln::sqrt(coeff)));
+ cl_I B = coeffnorm * expt_pos(cl_I(2), cl_I(maxdeg));
+ return ( B > maxcoeff ) ? B : maxcoeff;
+}
+
+/** Hensel lifting as used by factor_univariate().
+ *
+ * The implementation follows the algorithm in chapter 6 of [GCL].
+ *
+ * @param[in] a_ primitive univariate polynomials
+ * @param[in] p prime number that does not divide lcoeff(a)
+ * @param[in] u1_ modular factor of a (mod p)
+ * @param[in] w1_ modular factor of a (mod p), relatively prime to u1_,
+ * fulfilling u1_*w1_ == a mod p
+ * @param[out] u lifted factor
+ * @param[out] w lifted factor, u*w = a
+ */