% ┌                                                ┐
% │     AUTHOR: Janis Hutz<info@janishutz.com>     │
% └                                                ┘

\newpage
\subsubsection{Zero-Padding-Auswertung}
Ein trigonometrisches Polynom $p_{N - 1}(t)$ kann effizient an den äquidistanten Punkten $\frac{k}{M}$ mit $M > N$ ausgewertet werden, für $k = 0, \ldots, M - 1$.
Dazu muss das Polynom $p_{N - 1} \in \mathcal{T}_N \subseteq \mathcal{T}_M$ in der trigonometrischen Basis $\mathcal{T}_M$ neugeschrieben werden,
in dem man \bi{Zero-Padding} verwendet, also Nullen im Koeffizientenvektor an den Stellen höheren Frequenzen einfügt.

\innumpy Dieses Verfahren lässt sich in Python leicht via \verb|slices| umsetzen:
\rmvspace
\begin{code}{python}
def zero_pad(v: np.ndarray, N: int):
    """Apply zero-padding to size N to a vector v """
    n = v.size
    if (N < n): raise ValueError(f"ERROR: Zeropadding for N smaller than vector length: {N} < {n}")
    
    u = np.zeros(N, dtype=complex)
    u[:n//2] = v[:n//2]
    u[N-n//2:] = v[n//2:]
    return u


def eval_trig_poly(y: np.ndarray, N: int):
    """ Evaluate trig poly generated using y on N points """
    n = y.size
    if (n % 2 != 0): raise ValueError(f"ERROR: y must be of even length, len(y)={n}")
    
    coeffs = np.fft.fft(y) * 1/n
    coeffs = zero_pad(coeffs, N)
    return np.fft.ifft(coeffs) * N
\end{code}

\subsubsection{Ableitungen mit Zero-Padding}
Mit dem Trick aus Bemerkung 3.2.13 lassen sich auch direkt die Ableitungen berechnen.

\innumpy Geht dies direkt durch leichte Modifikation der obigen Funktionen:

\begin{code}{python}
def eval_trig_poly_d1(y: np.ndarray, N: int):
    """ Evaluates first der. of trig poly generated using y on N points """
    n = y.size
    if (n % 2 != 0): raise ValueError(f"ERROR: y must be of even length, len(y)={n}")
    
    coeffs = np.fft.fft(y) * 1/n
    
    for i in range(0, n//2):
        coeffs[i] *= (2.0j * np.pi * i)
    for i in range(n//2, n):
        coeffs[i] *= (2.0j * np.pi * (i - n))
    
    coeffs = zero_pad(coeffs, N)
    return np.fft.ifft(coeffs) * N
\end{code}

