\subsection{remez}
\label{labremez}
\noindent Name: \textbf{remez}\\
\phantom{aaa}computes the minimax of a function on an interval.\\[0.2cm]
\noindent Library names:\\
\verb|   sollya_obj_t sollya_lib_remez(sollya_obj_t, sollya_obj_t, sollya_obj_t, ...)|\\
\verb|   sollya_obj_t sollya_lib_v_remez(sollya_obj_t, sollya_obj_t, sollya_obj_t,|\\
\verb|                                   va_list)|\\[0.2cm]
\noindent Usage: 
\begin{center}
\textbf{remez}(\emph{f}, \emph{n}, \emph{range}, \emph{w}, \emph{quality}, \emph{bounds}) : (\textsf{function}, \textsf{integer}, \textsf{range}, \textsf{function}, \textsf{constant}, \textsf{range}) $\rightarrow$ \textsf{function}\\
\textbf{remez}(\emph{f}, \emph{L}, \emph{range}, \emph{w}, \emph{quality}, \emph{bounds}) : (\textsf{function}, \textsf{list}, \textsf{range}, \textsf{function}, \textsf{constant}, \textsf{range}) $\rightarrow$ \textsf{function}\\
\end{center}
Parameters: 
\begin{itemize}
\item \emph{f} is the function to be approximated
\item \emph{n} is the degree of the polynomial that must approximate \emph{f}
\item \emph{L} is a list of integers or a list of functions and indicates the basis for the approximation of \emph{f}
\item \emph{range} is the interval where the function must be approximated
\item \emph{w} (optional) is a weight function. Default is 1.
\item \emph{quality} (optional) is a parameter that controls the quality of the returned polynomial \emph{p}, with respect to the exact minimax $p^\star$. Default is 1e-5.
\item \emph{bounds} (optional) is a parameter that allows the user to make the algorithm stop earlier, whenever a given accuracy is reached or a given accuracy is proved unreachable. Default is $[0,\,+\infty]$.
\end{itemize}
\noindent Description: \begin{itemize}

\item \textbf{remez} computes an approximation of the function $f$ with respect to
   the weight function $w$ on the interval \emph{range}. More precisely, it
   searches $p$ such that $\|pw-f\|_{\infty}$ is
   (almost) minimal among all $p$ of a certain form. The norm is
   the infinity norm, e.g. $\|g\|_{\infty} = \max \{|g(x)|, x \in \mathrm{range}\}.$

\item If $w=1$ (the default case), it consists in searching the best
   polynomial approximation of $f$ with respect to the absolute error.
   If $f=1$ and $w$ is of the form $1/g$, it consists in
   searching the best polynomial approximation of $g$ with respect to the
   relative error.

\item If $n$ is given, $p$ is searched among the polynomials with degree not
   greater than $n$.
   If \emph{L} is given and is a list of integers, $p$ is searched as a linear
   combination of monomials $X^k$ where $k$ belongs to \emph{L}.
   In the case when \emph{L} is a list of integers, it may contain ellipses but
   cannot be end-elliptic.
   If \emph{L} is given and is a list of functions $g_k$, $p$ is searched as a
   linear combination of the $g_k$. In that case \emph{L} cannot contain ellipses.
   It is the user responsibility to check that the $g_k$ are linearly independent
   over the interval \emph{range}. Moreover, the functions $w\cdot g_k$ must be at least
   twice differentiable over \emph{range}. If these conditions are not fulfilled, the
   algorithm might fail or even silently return a result as if it successfully
   found the minimax, though the returned $p$ is not optimal.

\item The polynomial is obtained by a convergent iteration called Remez'
   algorithm (and an extension of this algorithm, due to Stiefel).
   The algorithm computes a sequence $p_1,\dots ,p_k,\dots$
   such that $e_k = \|p_k w-f\|_{\infty}$ converges towards
   the optimal value $e$. The algorithm is stopped when the relative error
   between $e_k$ and $e$ is less than \emph{quality}.
   \\
   For this reason, the returned polynomial usually has dyadic coefficients.
   However, one should not rely on that property. Especially, a noticeable
   exception to that statement is when we manage to detect that $f/w$ exactly
   simplifies to a polynomial of the required degree, in which case we return it
   as it is without further rounding.

\item The optional argument \emph{bounds} is an interval $[\varepsilon_\ell,\,\varepsilon_u]$
   with the following behavior:\begin{itemize}
     \item if, during the algorithm, we manage to prove that $\varepsilon_u$ is
       unreachable, we stop the algorithm returning the last computed
       polynomial.
     \item if, during the algorithm, we obtain a polynomial with an error smaller
       than $\varepsilon_\ell$, we stop the algorithm returning that polynomial.
     \item otherwise we loop until we find an optimal polynomial with the required
       quality, as usual.\end{itemize}
   Examples of use:\\
     $[0,\,+\infty]$ (compute the optimal polynomial with the required quality)\\
     $[\varepsilon_u]$ (stops as soon as a polynomial achieving $\varepsilon_u$ is
                   obtained or as soon as such a polynomial is proved not to
                   exist).\\
     $[0,\,\varepsilon_u]$ (finds the optimal polynomial, but provided that its error
                      is smaller than $\varepsilon_u$).\\
     $[\varepsilon_\ell,\,+\infty]$ (stops as soon as a polynomial achieving
                             $\varepsilon_\ell$ is obtained. If such a polynomial
                             does not exist, returns the optimal polynomial).
\end{itemize}
\noindent Example 1: 
\begin{center}\begin{minipage}{15cm}\begin{Verbatim}[frame=single]
> p = remez(exp(x),5,[0;1]);
> degree(p);
5
> dirtyinfnorm(p-exp(x),[0;1]);
1.1295698151096148707171193829266077607222634589363e-6
\end{Verbatim}
\end{minipage}\end{center}
\noindent Example 2: 
\begin{center}\begin{minipage}{15cm}\begin{Verbatim}[frame=single]
> p = remez(1,[|0,2,4,6,8|],[0,Pi/4],1/cos(x));
> canonical=on!;
> p;
0.99999999994393732180959690352543887130348096061124 - 0.49999999571556857768772
053063721544670949467222259 * x^2 + 4.166661323347363300994105948057027587011322
0089059e-2 * x^4 - 1.3886529147145693651355523880319714051047635695061e-3 * x^6 
+ 2.4372679177224179934800328511009205218114284220126e-5 * x^8
\end{Verbatim}
\end{minipage}\end{center}
\noindent Example 3: 
\begin{center}\begin{minipage}{15cm}\begin{Verbatim}[frame=single]
> p1 = remez(exp(x),5,[0;1],default,1e-5);
> p2 = remez(exp(x),5,[0;1],default,1e-10);
> p3 = remez(exp(x),5,[0;1],default,1e-15);
> dirtyinfnorm(p1-exp(x),[0;1]);
1.1295698151096148707171193829266077607222634589363e-6
> dirtyinfnorm(p2-exp(x),[0;1]);
1.12956980227478675612619255125474525171079325793124e-6
> dirtyinfnorm(p3-exp(x),[0;1]);
1.12956980227478675612619255125474525171079325793124e-6
\end{Verbatim}
\end{minipage}\end{center}
\noindent Example 4: 
\begin{center}\begin{minipage}{15cm}\begin{Verbatim}[frame=single]
> L = [|exp(x), sin(x), cos(x)-1, sin(x^3)|];
> g = (2^x-1)/x;
> p1 = remez(g, L, [-1/16;1/16]);
> p2 = remez(g, 3, [-1/16;1/16]);
> dirtyinfnorm(p1 - g, [-1/16;1/16]);
9.8841323829271038137685646777951687620288462194746e-8
> dirtyinfnorm(p2 - g, [-1/16;1/16]);
2.54337800593461418356437401152248866818783932027105e-9
\end{Verbatim}
\end{minipage}\end{center}
\noindent Example 5: 
\begin{center}\begin{minipage}{15cm}\begin{Verbatim}[frame=single]
> f = sin(x);
> I = [-3b-5;-1b-1074];
> time(popt = remez(1, [|1, 3, 4, 5, 7, 8, 9|], I, 1/f));
0.18153754500000000000000000000000000000951234855126
> time(p1 = remez(1, [|1, 3, 4, 5, 7, 8, 9|], I, 1/f, default, [0, 1b-73]));
0.13429872799999999999999999999999999998420186148156
> time(p2 = remez(1, [|1, 3, 4, 5, 7, 8, 9|], I, 1/f, default, [3b-72, +@Inf@]))
;
0.15097598299999999999999999999999999997436992893015
> dirtyinfnorm(popt/f-1, I);
2.06750931454112835098093903810531156576504665659064e-22
> dirtyinfnorm(p1/f-1, I);
2.49711266837493110470637913808914046704452778960875e-22
> dirtyinfnorm(p2/f-1, I);
5.4567247553615435246376977231253834265248756996947e-22
> 1b-73;
1.05879118406787542383540312584955245256423950195312e-22
> 3b-72;
6.3527471044072525430124187550973147153854370117187e-22
\end{Verbatim}
\end{minipage}\end{center}
See also: \textbf{dirtyinfnorm} (\ref{labdirtyinfnorm}), \textbf{infnorm} (\ref{labinfnorm}), \textbf{fpminimax} (\ref{labfpminimax}), \textbf{guessdegree} (\ref{labguessdegree}), \textbf{taylorform} (\ref{labtaylorform}), \textbf{taylor} (\ref{labtaylor}), \textbf{interpolate} (\ref{labinterpolate})
