
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%%  Fp_polynomial.tex       LiDIA documentation
%%
%%  This file contains the documentation of the class Fp_polynomial
%%
%%  Copyright   (c)   1996   by  LiDIA-Group 
%%
%%  Authors: Thomas Pfahler
%%

\begin{lidia_man}
\markright{\BF{Fp\_polynomial}}

\NAME
	\BF{Fp\_polynomial}  \DOTFILL  polynomials over finite prime fields 


\ABSTRACT
		\BF{Fp\_polynomial} is a class for doing very fast polynomial computation
		modulo a prime \MATH{p > 2}. A variable of type \BF{Fp\_polynomial} can hold
		polynomials of arbitrary length. Each polynomial has its own modulus p,
		which is of type \BF{bigint}.


\DESCRIPTION

	A variable \MATH{f} of type \BF{Fp\_polynomial} is internally represented as
	a coefficient array with entries of type \BF{bigint}. The zero polynomial is a zero 
	length array; otherwise, \MATH{f[0]} is the constant-term, and \MATH{f[f.degree()]} 
	is the leading coefficient, which is always non-zero (except for \MATH{f = 0}).
	Furthermore, every \BF{Fp\_polynomial} carries a pointer to its modulus,
	thus allowing to use polynomials over different prime fields at the same time.
	This modulus 
	%is initialized with zero and (therefore)
	must be set explicitely if \MATH{f} is not the result of an arithmetical
	operation.\\
	For multiplication and division, we have implemented a very efficient 
	FFT-arithmetic.
	

\CONS

\fcode{ct}{Fp\_polynomial}{}{
	initializes a zero polynomial.}

\fcode{ct}{Fp\_polynomial}{const Fp\_polynomial \& f}{
    initializes with a copy of the polynomial \MATH{f}.}

\fcode{dt}{\MATH{\sim}Fp\_polynomial}{}{}



\ASGN

	Let \MATH{f} be of type \BF{Fp\_polynomial}.
	
	The operator \TT{=} is overloaded. For efficiency reasons, the following
	functions are also implemented:

\fcode{void }{f.assign\_zero}{}{
	sets \MATH{f} to zero polynomial.\\
	If \MATH{f.modulus() = 0}, the lidia\_error\_handler is invoked.}

\fcode{void }{f.assign\_one}{}{
	sets \MATH{f} to polynomial \MATH{1 \CDOT x^0}.\\
	If \MATH{f.modulus() = 0}, the lidia\_error\_handler is invoked.}

\fcode{void }{f.assign\_x}{}{
	sets \MATH{f} to polynomial \MATH{1 \CDOT x^1+0 \CDOT x^0}.\\
	If \MATH{f.modulus() = 0}, the lidia\_error\_handler is invoked.}

\fcode{void }{f.assign}{const Fp\_polynomial \& g}{
	\MATH{f = g}.}

\fcode{void }{f.assign}{const bigint \& a}{
	\MATH{f = a \CDOT x^0}.
	If \MATH{f.modulus() = 0}, the lidia\_error\_handler is invoked.}

\fcode{void }{f.assign}{const base\_vector\TEMPL{bigint} \& v\k const bigint \& p}{
    \MATH{f \equiv \SUM{i=0}{v.size()-1}{v[i] \CDOT x^{i}} \pmod{p}}.\\
	\MATH{p} must be prime; otherwise, the behaviour of this class
	is undefined.
	If \MATH{p \LT\; 2}, the lidia\_error\_handler is invoked.
	Leading zeros will be automatically removed.}


\BASIC
	
	Let \MATH{f} be of type \BF{Fp\_polynomial}.

\fcode{void }{f.set\_modulus}{const bigint  \& p}{
%	sets \MATH{f} to zero polynomial modulo \MATH{p}.
	sets the modulus for polynomial \MATH{f} to \MATH{p}.
	\MATH{p} must \MATH{\GE\; 2} and prime.\\
	The primality of \MATH{p} is not tested, but be aware that
	the behavoir of this class is not defined if \MATH{p} is not a prime.\\
	\MATH{f} is set to zero.}

\cfcode{const bigint \& }{f.modulus}{}{
	returns the modulus of \MATH{f}.\\
	If \MATH{f} has not been assigned a modulus yet (explicitely by 
	\MATH{f.set\_modulus()} or implicitely by an operation), the value
	zero is returned.}

\fcode{void }{f.set\_max\_degree}{lidia\_size\_t n}{
	pre-allocates space for coefficients up to degree \MATH{n}. \\
	This has no effect if \MATH{n < f.degree()} or if sufficient space was 
	already allocated.\\
	The value of \MATH{f} is always unchanged.}

\fcode{void }{f.remove\_leading\_zeros}{}{
	removes leading zeros.\\
	Afterwards, if \MATH{f} is not the zero polynomial, \MATH{f.lead\_coeff() \;\NEQ\; 0}.\\
	If \MATH{f.modulus() = 0}, the lidia\_error\_handler is invoked.}

\fcode{void }{f.make\_monic}{}{
	divides \MATH{f} by its leading coefficient; afterwards, \MATH{f.lead\_coeff = 1}.\\
	If \MATH{f = 0} or \MATH{f.modulus() = 0}, the lidia\_error\_handler is invoked.}

\fcode{void }{f.kill}{}{
	deallocates the polynomial's coefficients and sets \MATH{f} to zero.\\
	\MATH{f.modulus()} is set to zero.}



\ACCS

	Let \MATH{f} be of type \BF{Fp\_polynomial}.\\
	All returned coefficients lie in the interval
	\MATH{[ 0,\ldots, f.modulus()-1 ]}.

\cfcode{lidia\_size\_t }{f.degree}{}{
	returns the degree of \MATH{f}.
	The zero polynomial has degree \MATH{-1}.}

\fcode{bigint \& }{f.operator[]}{lidia\_size\_t i}{
	returns a reference to the coefficient of \MATH{x^{i}} of \MATH{f}.
	\MATH{i} must be non-negative.\\
	IMPORTANT NOTE: Assignments to coefficients via this operator are only 
	possible by the following functions:
	\begin{itemize}
	\item operator=(const bigint \&)
	\item bigint::assign\_zero()
	\item bigint::assign\_one()
	\item bigint::assign(const bigint \&)
	\end{itemize}
	Any other assignment (e.g. \TT{square(f[0], a)}) will only cause
	compiler warnings, but your program will not run
	correctly.\\
	The degree of \MATH{f} is adapted automatically after any assignment.\\
	Read access is always possible.}

%	WARNING: If you assign a value to a coefficient via this function,
%    you have to guarantee that the value of the coefficient lies in the
%	interval \MATH{[ 0,\ldots,|f.modulus()|-1 ]}. Otherwise, the behaviour of
%	the polynomial \MATH{f} may not be defined. 
%	Use the function f.remove\_leading\_zeros() to get rid of leading zeros.}

\cfcode{const bigint \& }{f.operator[]}{lidia\_size\_t i}{
	returns a constant reference to the coefficient of \MATH{x^{i}} of \MATH{f}.
	\MATH{i} must be non-negative. If \MATH{i} exceeds the degree of \MATH{f}, 
	a reference to a bigint of value zero is returned.}

\cfcode{bigint \& }{f.lead\_coeff}{}{
	returns \MATH{f[f.degree()]}, i.e. the leading coefficient of \MATH{f};\\
	returns zero if \MATH{f} is the zero polynomial.}

\cfcode{bigint \& }{f.const\_term}{}{
	returns \MATH{f[0]}, i.e. the constant term of \MATH{f};
	returns zero if \MATH{f} is zero polynomial.}

	To avoid copying, coefficient access can also be performed by
	the following functions:

\cfcode{void }{f.get\_coefficient}{bigint \& a \k int i}{
	\MATH{a = c_{i}}, where \MATH{f = \SUM{k=0}{f.degree()}{c_{k} \CDOT x^{k}}}.
	\MATH{a = 0}, if \MATH{i > f.degree()}.\\
	The lidia\_error\_handler is invoked if \MATH{i < 0}.}

\fcode{void }{p.set\_coefficient}{const bigint \& a, lidia\_size\_t i}{
	sets coefficient of \MATH{x^{i}} to \MATH{a \pmod{f.modulus()}}; 
	if \MATH{i > f.degree()}, all coefficients \MATH{c_j} of \MATH{x^j}
	with \MATH{j = f.degree()+1, \LDOTS, i-1} are set to zero;
	the degree of \MATH{f} is adapted automatically.\\
	The lidia\_error\_handler is invoked if \MATH{i < 0}.}

\fcode{void }{f.set\_coefficient}{lidia\_size\_t i}{
    = \MATH{f.set\_coefficient(1,i)}\\
	sets coefficient of \MATH{x^{i}} to \MATH{1};
	if \MATH{i > f.degree()}, all coefficients \MATH{c_j} of \MATH{x^j}
	with \linebreak
	\MATH{j = f.degree()+1, \LDOTS, i-1} are set to zero;
	the degree of \MATH{f} is adapted automatically.\\
	The lidia\_error\_handler is invoked if \MATH{i < 0}.}



\ARTH

	All arithmetical operations are done modulo the modulus assigned to each 
	polynomial. Input variables of type \BF{bigint} are automatically reduced.
	In principal, the lidia\_error\_handler is invoked if the moduli of the 
	``const'' arguments
	are not the same. The ``resulting'' polynomial receives the modulus of the 
	``input'' polynomials.

	The following operators are overloaded and can be used in exactly the same way
	as for machine types in C (e.g.~int) :

	\begin{center}
	\TT{(unary) -}\\
	\TT{(binary) +, -, *, /, \%}\\
	\TT{(binary with assignment) +=,  -=,  *=,  /=, \%=}
	\end{center}

	Let \MATH{f} be of type \BF{Fp\_polynomial}.

	To avoid copying, these operations can also be performed by
	the following functions:

\fcode{void }{f.negate}{}{
	\MATH{f = -f}.}
\fcode{void }{negate}{Fp\_polynomial \& g\k const Fp\_polynomial \& f}{
	\MATH{g = -f}.}

\fcode{void }{add}{Fp\_polynomial \& f\k const Fp\_polynomial \& g\k const Fp\_polynomial \& h}{
	\MATH{f = g + h}.}
\fcode{void }{add}{Fp\_polynomial \& f\k const Fp\_polynomial \& g\k const bigint \& a}{
	\MATH{f = g + a \pmod{p}}, where \MATH{p = g.modulus()}.}
\fcode{void }{add}{Fp\_polynomial \& f\k const bigint \& a\k const Fp\_polynomial \& g}{
	\MATH{f = g + a \pmod{p}}, where \MATH{p = g.modulus()}.}

\fcode{void }{subtract}{Fp\_polynomial \& f\k const Fp\_polynomial \& g\k const Fp\_polynomial \& h}{
	\MATH{f = g - h}.}
\fcode{void }{subtract}{Fp\_polynomial \& f\k const Fp\_polynomial \& g\k const bigint \&a}{
	\MATH{f = g - a \pmod{p}}, where \MATH{p = g.modulus()}.}
\fcode{void }{subtract}{Fp\_polynomial \& f\k const bigint \& a\k const Fp\_polynomial \& g}{
	\MATH{f = a - g \pmod{p}}, where \MATH{p = g.modulus()}.}


\fcode{void }{multiply}{Fp\_polynomial \& f\k const Fp\_polynomial \& g\k const Fp\_polynomial \& h}{
	\MATH{f = g \CDOT h}.}
\fcode{void }{multiply}{Fp\_polynomial \& f\k const Fp\_polynomial \& g\k const bigint \& a}{
	\MATH{f = g \CDOT a \pmod{p}}, where \MATH{p = g.modulus()}.}
\fcode{void }{multiply}{Fp\_polynomial \& f\k const bigint \& a\k const Fp\_polynomial \& g}{
	\MATH{f = g \CDOT a \pmod{p}}, where \MATH{p = g.modulus()}.}

\fcode{void }{square}{Fp\_polynomial \& f\k const Fp\_polynomial \& g}{
	\MATH{f = g^2}.}

\fcode{void }{divide}{Fp\_polynomial \& q\k const Fp\_polynomial \& f\k const Fp\_polynomial \& g}{
	\MATH{q = f/g}.}
\fcode{void }{divide}{Fp\_polynomial \& q\k const Fp\_polynomial \& f\k const bigint \& a}{
	\MATH{q = f/a \pmod{p}}, where \MATH{p = f.modulus()}.}
	
\fcode{void }{remainder}{Fp\_polynomial \& r\k const Fp\_polynomial \& f\k const Fp\_polynomial \& g}{
	\MATH{r \equiv f \pmod{g} }.}
\fcode{void }{div\_rem}{Fp\_polynomial \& q\k const Fp\_polynomial \& r\k const Fp\_polynomial \& f\k const Fp\_polynomial \& g}{
	\MATH{f = q \CDOT g + r}, where \MATH{0 \;\LE\; r.degree() < g.degree()}.}

\fcode{void }{invert}{Fp\_polynomial \& f\k const Fp\_polynomial \& g\k lidia\_size\_t m}{
	\MATH{f \equiv g^{-1} \pmod{x^{m}}}. \\
	The constant term of \MATH{g} must be non-zero, otherwise the 
	lidia\_error\_handler is invoked.}


\STITLE{Greatest Common Divisor}

\fcode{void }{gcd}{Fp\_polynomial \& d\k const Fp\_polynomial \& f\k const Fp\_polynomial \& g}{
	\MATH{d = gcd(f, g)}.}
\fcode{Fp\_polynomial }{gcd}{const Fp\_polynomial \& f\k const Fp\_polynomial \& g}{
	returns \MATH{gcd(f, g)}.}

\fcode{void }{xgcd}{Fp\_polynomial \& d\k Fp\_polynomial \& s\k Fp\_polynomial \& t\k const Fp\_polynomial \& f\k const Fp\_polynomial \& g}{
	\MATH{d = gcd(f, g) = s \CDOT f + t \CDOT g}.}


\STITLE{Modular Arithmetic without pre-conditioning}

\fcode{void }{multiply\_mod}{Fp\_polynomial \& g\k const Fp\_polynomial \& a\k const Fp\_polynomial \& b\k const Fp\_polynomial \& f}{
	\MATH{g \equiv a \CDOT b \pmod{f}}.}

\fcode{void }{square\_mod}{Fp\_polynomial \& g\k const Fp\_polynomial \& a\k const Fp\_polynomial \& f}{
	\MATH{g \equiv a^2 \pmod{f}}.}

\fcode{void }{multiply\_by\_x\_mod}{Fp\_polynomial \& g\k const Fp\_polynomial \& a\k const Fp\_polynomial \& f}{
	\MATH{g \equiv a \CDOT x \pmod{f}}.}

\fcode{void }{invert\_mod}{Fp\_polynomial \& g\k const Fp\_polynomial \& a\k const Fp\_polynomial \& f}{
	\MATH{g \equiv a^{-1} \pmod{f}}. \\
	The lidia\_error\_handler is invoked if \MATH{a} is not invertible.}

\fcode{bool }{invert\_mod\_status}{Fp\_polynomial \& g\k const Fp\_polynomial \& a\k const Fp\_polynomial \& f}{
	returns \TRUE\ and sets \MATH{g \equiv a^{-1} \pmod{f}} if \MATH{gcd(a, f) = 1}; \\
	otherwise returns \FALSE\ and sets \MATH{g = gcd(a, f)}.}

\fcode{void }{power\_mod}{Fp\_polynomial \& g\k const Fp\_polynomial \& a\k const bigint \& e\k const Fp\_polynomial \& f}{
	\MATH{g \equiv a^e \pmod{f}}.\\
	The polynomial \MATH{f} and the exponent \MATH{e} may not alias an output.}

\fcode{void }{power\_x\_mod}{Fp\_polynomial \& g\k const bigint \& e\k const Fp\_polynomial \& f}{
	\MATH{g \equiv x^e \pmod{f}}.\\
	The polynomial \MATH{f} and the exponent \MATH{e} may not alias an output.}

\fcode{void }{power\_x\_plus\_a\_mod}{Fp\_polynomial \& g\k const bigint \& a\k const bigint \& e\k const Fp\_polynomial \& f}{
	\MATH{g \equiv (x + a)^e \pmod{f}}.\\
	The polynomial \MATH{f} and the exponent \MATH{e} may not alias an output.}



\COMP

	The  binary operators \TT{==}, \TT{!=} are overloaded and can be used in
	exactly the same way as for machine types in C (e.g.~int).

	Let \MATH{f} be an instance of type \BF{Fp\_polynomial}.


\cfcode{bool }{f.is\_zero}{}{
	returns \TRUE\  if \MATH{f} is the zero polynomial; \FALSE\  otherwise.}

\cfcode{bool }{f.is\_one}{}{
	returns \TRUE\  if \MATH{f} is a constant polynomial and the constant coefficient
	equals \MATH{1}; \FALSE\  otherwise.}

\cfcode{bool }{f.is\_x}{}{
	returns \TRUE\  if \MATH{f} is a polynomial of degree \MATH{1}, the leading coefficient
	equals \MATH{1} and the constant coefficient equals \MATH{0}; \FALSE\  otherwise.}

\cfcode{bool }{f.is\_monic}{}{
  	returns \TRUE\  if \MATH{f} is a monic polynomial, i.e. if \MATH{f} is not
	the zero polynomial and \MATH{f.lead\_coeff() = 1}.}


\HIGH

	Let \MATH{f} be an instance of type \BF{Fp\_polynomial}.

\fcode{void }{shift\_left}{Fp\_polynomial \& f\k const Fp\_polynomial \& g\k lidia\_size\_t n}{
	\MATH{f = g \CDOT x^{n}}.}

\fcode{void }{shift\_right}{Fp\_polynomial \& f\k const Fp\_polynomial \& g\k lidia\_size\_t n}{
	\MATH{f = g / x^{n}}.}

\fcode{void }{trunc}{Fp\_polynomial \& f\k const Fp\_polynomial \& g\k lidia\_size\_t n}{
	\MATH{f \equiv g \pmod{x^{n}}}.}

\fcode{void }{derive}{Fp\_polynomial \& f\k const Fp\_polynomial \& g}{
	\MATH{f = g'}\ , i.e. the derivative of \MATH{g}.}

\fcode{void }{f.randomize}{lidia\_size\_t n}{
	\MATH{f} is assigned a random polynomial of degree \MATH{n} 
	modulo \MATH{f.modulus()}.\\
	If \MATH{f.modulus() = 0}, the lidia\_error\_handler is invoked.}

\fcode{void }{randomize}{Fp\_polynomial \& f\k const bigint \& p\k lidia\_size\_t n}{
	\MATH{f} is assigned a random polynomial modulo \MATH{p}
	of degree \MATH{n}.}

\cfcode{bigint }{f.operator()}{const bigint \& a}{
	returns \MATH{\SUM{i=0}{f.degree()}c_{i} \CDOT a^{i} \pmod{p}}, where
	\MATH{f = \SUM{i=0}{f.degree()}c_{i} \CDOT x^{i}} and \MATH{p = f.modulus()}.\\
	If \MATH{f.modulus() = 0}, the lidia\_error\_handler is invoked.}


\fcode{void }{build\_from\_roots}{const base\_vector\TEMPL{bigint} \& v}{
  	computes the polynomial \MATH{\PROD{i=0}{v.size()-1}{(x - a[i])} \pmod{f.modulus()}}.\\
	The lidia\_error\_handler is invoked if \MATH{f.modulus() = 0}.}

\fcode{void }{cyclic\_reduce}{Fp\_polynomial \& f\k const Fp\_polynomial \& g\k lidia\_size\_t m}{
  	\MATH{f \equiv g  \pmod{x^{m}-1}}.}

\fcode{void }{add\_multiple}{Fp\_polynomial \& f\k const Fp\_polynomial \& g\k const bigint \& s\k lidia\_size\_t n\k const Fp\_polynomial \& h}{
	\MATH{f = g + s \CDOT x^n \CDOT h \pmod{p}}, where \MATH{p = g.modulus()}.}

\fcode{bool }{prob\_irred\_test}{const Fp\_polynomial \& f\k lidia\_size\_t iter=1}{
  	performs a fast, probabilistic irreducibility test. The test can err only
	if \MATH{f} is reducible modulo \MATH{f.modulus()}, and the error
	probability is bounded by \MATH{(f.modulus())^{-iter}}.}

\fcode{bool }{det\_irred\_test}{const Fp\_polynomial \& f}{
	performs a recursive deterministic irreducibility test.}

\fcode{void }{build\_irred}{Fp\_polynomial \& f\k cnost bigint \& p\k lidia\_size\_t n}{
	\MATH{f =} a monic irreducible polynomial modulo \MATH{p} of degree 
	\MATH{n}.}

\fcode{void }{build\_random\_irred}{Fp\_polynomial \& f\k const Fp\_polynomial \& g}{
	constructs a random monic irreducible polynomial \MATH{f} of degree
	\MATH{g.degree()} over \MATH{\Z/p\Z}, where \MATH{p = g.modulus()}.
	Assumes \MATH{g} to be a monic irreducible polynomial (otherwise, the
	behaviour of this function is undefined).}

\fcode{base\_vector\TEMPL{bigint} }{find\_roots}{const Fp\_polynomial \& f}{
        returns the list of roots of \MATH{f}.\\
        Assumes that \MATH{f} is monic and has \MATH{f.degree()} distinct
        roots; otherwise the behaviour of this function is undefined.}

\fcode{bigint }{find\_root}{const Fp\_polynomial \& f}{
        same as \MATH{find\_roots}, but returns only a single root of
        \MATH{f}.}


\fcode{void }{swap}{Fp\_polynomial \& f\k Fp\_polynomial \& g}{
    swaps the values of \MATH{f} and \MATH{g}.}


\IO

	The \BF{istream}  operator  \TT{>>}  and  the \BF{ostream}  operator \TT{<<}
	are overloaded.\\
	Let \MATH{f = \SUM{i=0}{n}{c_{i} \CDOT x^{i}} \pmod{p}} where \MATH{n}
	denotes the degree and \MATH{p} the modulus of the polynomial \MATH{f}.
	
	We support two different I/O-formats:
	\begin{itemize}
	\item
	The more simple format is 
%	\MATH{[ c_{0} c_{1} \LDOTS c_{n-1} ] {\rm mod} p}''
	\begin{verbatim} [ c_0 c_1 ... c_n ] mod p \end{verbatim}
	with integers c\_i, p. All numbers will be reduced modulo
	\MATH{p} at input; leading zeros will be removed.

	\item
	The more comfortable format (especially for sparse polynomials) is
%	``\MATH{c_n{\rm *x^n + \LDOTS + }c_2{\rm *x^2 + }c_1{\rm *x + }c_0 {\rm mod} p}'' 
	\begin{verbatim} c_n * x^n + ... + c_2 * x^2 + c_1 * x + c_0 mod p \end{verbatim}
	At output, zero coefficients are omitted, as well as you may omit them at input. 
	Even \begin{verbatim} -x -x^2 +3*x^2 -17 +2 mod 5 \end{verbatim}
	will be accepted.
	\end{itemize}
	Both formats may be used as input - they are distiguished automatically by the 
	first character of the input, being `[' or not `['.
	The \BF{ostream}  operator \TT{<<} always uses the first format.
	The second output format can be obtained using the member function
\cfcode{void}{f.pretty\_print}{ostream \& os}{}

\medskip

\SEEALSO

	\BF{bigint}, \BF{polynomial\TEMPL{T}}

\NOTES

	If you want to do many computations modulo some fixed \BF{Fp\_polynomial}
	\MATH{f}, use class \BF{poly\_modulus}.

\WARNINGS

	Assignments to coefficients of polynomials
	via \TT{operator[](lidia\_size\_t)} (without \TT{const})
	are only possible by the following functions:
	\begin{itemize}
	\item \TT{operator=(const bigint \&)}
	\item \TT{bigint::assign\_zero()}
	\item \TT{bigint::assign\_one()}
	\item \TT{bigint::assign(const bigint \&)}
	\end{itemize}
	Any other assignment (e.g. \TT{square(f[0], a)}) will only cause
	compiler warnings, but your program will not run
	correctly.\\
	Read access is always possible.
	

\EXAMPLES
\begin{verbatim}
    #include <LiDIA/Fp_polynomial.h>

    main()
    {
        Fp_polynomial f, g, h;

        cout << "Please enter f : "; cin >> f;
        cout << "Please enter g : "; cin >> g;

        h = f * g;

        cout << "f * g   =  ";
        h.pretty_print();
        cout << "\n";
    }
\end{verbatim}

example:

\begin{verbatim}
    Please enter f : 14*x^4 - 43*x^3 + 1  mod 97
    Please enter g : -x^3 + x - 2  mod 97

    f * g  =  83*x^7 + 43*x^6 + 14*x^5 + 26*x^4 + 85*x^3 + x + 95 mod 97
\end{verbatim}

\AUTHOR
	Victor Shoup (original author) \\
	Thomas Pfahler

\end{lidia_man}
