Analoog aan de ontbinding van een reële functie in een Fourier-cosinus reeks, kan een rij van reële getallen $$x$$ ontbonden worden in een stel basisvectoren, waarvan de componenten van cosinusfuncties afkomstig zijn. Beschouw de reële $$N \times N$$ matrix $$C$$, gedefinieerd via:
$$ C_{nk} = \cos[k(n+\frac{1}{2})\frac{\pi}{N}] $$
met $$k = 0 ... N-1$$, $$n = 0 ... N-1$$. De kolommen van deze matrix vormen de basisvectoren waarin we een rijvector $$x$$, bestaande uit $$N$$ reële getallen, zullen ontbinden.

Beschouw de reële getallen $$X_k$$ gegeven door ($$0 \le k \lt N$$):
$$ X_k = \sum_{n=0}^{N-1} x_n \cos[k(n+\frac{1}{2})\frac{\pi}{N}] $$
of in matrixgedaante (waarbij de rijvector $$X$$ de componenten $$X_k$$ bevat):
$$ X = x C $$
Men kan aantonen dat (voor $$0 \le n \lt N$$) :
$$ x_n = \frac{X_0}{N} + \frac{2}{N}\sum_{k=1}^{N-1}X_k \cos[k(n+\frac{1}{2})\frac{\pi}{N}] $$
De afbeelding die de vector $$x$$ afbeeldt op de vector $$X$$ wordt de "discrete cosinustransformatie" genoemd, en wordt veel gebruikt bij het verwerken van geluiden en beelden. Bovenstaande uitdrukking maakt het bovendien ook mogelijk om gegeven de vector $$X$$ het origineel $$x$$ terug te vinden (en wordt dus de "inverse discrete cosinustransformatie" genoemd).

Schrijf de functie basisvectoren() met als enig argument een geheel getal $$N > 0$$. Het resultaat is een NumPy-tabel met $$N$$ rijen en $$N$$ kolommen die de matrix $$C$$ (definitie zie hoger) voorstelt, als resultaat oplevert.

Schrijf de functie dct_tf() met als enig argument een NumPy-rij met $$N$$ componenten. Het resultaat van de functie is het beeld van dit argument dat je bekomt via de discrete cosinustransformatie. Het resultaat is een NumPy-rij bestaande uit $$N$$ componenten.

Schrijf de functie dct_itf() met twee argumenten, namelijk:

Bereken de inverse discrete cosinustransformatie van $$X$$ waarbij $$N$$ basisvectoren gebruikt worden, en waarbij je $$X_k = 0$$ neemt voor $$K \le k < N$$.

LET OP : het is NIET toegelaten om in deze oefening gebruik te maken van lijsten. De oplossing mag enkel gebruik maken van NumPy-rijen of tabellen.

Merk op dat je resultaat, ten behoeve van de evaluatie in Dodona, afgebroken wordt op 4 decimalen (de functie format_p() en uit het format_l() verbeterscript zorgt hiervoor). Je resultaat wordt ook omgezet naar een lijst, maar let erop dat het resultaat van je functie WEL DEGELIJK een NumPy-tabel MOET zijn.

Voorbeeld

print(basisvectoren(4))
#[[ 1.          0.92387953  0.70710678  0.38268343]
# [ 1.          0.38268343 -0.70710678 -0.92387953]
# [ 1.         -0.38268343 -0.70710678  0.92387953]
# [ 1.         -0.92387953  0.70710678 -0.38268343]]
Voor
x = [10 10 10 10  0  0  0  0 10 10 10 10  0  0  0  0]
tf = dct_tf(x)
#[  8.00000000e+01   2.11296494e+01  -4.44089210e-15   4.15835515e+01
#   1.06581410e-14  -2.56070245e+01   6.66133815e-16  -3.26464334e+00
#  -7.10542736e-15   2.67922355e+00  -1.86517468e-14   1.36872398e+01
#  -2.66453526e-14  -1.26142324e+01   5.88418203e-14  -2.08108882e+00]
itf = dct_itf(tf, 16)
#[  1.00000000e+01   1.00000000e+01   1.00000000e+01   1.00000000e+01
#   1.04044927e-14  -1.82235671e-14   1.25468903e-14  -1.91825540e-14
#   1.00000000e+01   1.00000000e+01   1.00000000e+01   1.00000000e+01
#  -1.00952955e-14  -4.41817496e-15   1.51469966e-14  -4.66237620e-15]
itf_15 = dct_itf(tf[:15], 16)
#[ 10.0254978    9.92448648  10.12262731   9.8349714    
#  0.20108793   -0.22941956   0.24893473  -0.25888348  
#  10.25888348   9.75106527  10.22941956   9.79891207   
#  0.1650286   -0.12262731   0.07551352   -0.0254978 ]
>