1. Citra masukan ground truth dan normalisasi

Pada citra grayscale, setiap piksel memiliki satu nilai intensitas yang menunjukkan tingkat kecerahan. Apabila nilai intensitas telah dinormalisasi ke rentang \([0,1]\), maka nilai 0 menunjukkan piksel paling gelap (hitam), nilai 1 menunjukkan piksel paling terang (putih), sedangkan nilai di antara 0 dan 1 menunjukkan gradasi abu-abu. Semakin mendekati 0, piksel semakin gelap; semakin mendekati 1, piksel semakin terang.
Dalam ilustrasi ini, matriks citra awal masih menggunakan skala intensitas 0-255. Oleh karena itu, nilai 0 merepresentasikan hitam, nilai 255 merepresentasikan putih, dan nilai seperti 64, 128, atau 192 menunjukkan tingkat abu-abu yang berbeda. Dimensi matriks adalah \(5\times5\).

a. Citra Masukan

\[ \mathbf{I}=\begin{bmatrix} 0 & 64 & 192 & 160 & 32\\ 0 & 80 & 208 & 176 & 40\\ 0 & 80 & 208 & 176 & 40\\ 0 & 72 & 192 & 160 & 32\\ 8 & 48 & 144 & 112 & 24 \end{bmatrix} \]

b. Ground truth biner

\[ \mathbf{M}=\begin{bmatrix} 0 & 0 & 1 & 1 & 0\\ 0 & 1 & 1 & 1 & 0\\ 0 & 1 & 1 & 1 & 0\\ 0 & 0 & 1 & 1 & 0\\ 0 & 0 & 0 & 0 & 0 \end{bmatrix} \]

Ground truth \(\mathbf{M}\) berada di awal sebagai target evaluasi dimana nilai 0 merupakan latar belakang dan 1 merupakan wilayah lesi, bukan masukan encoder.

c. Normalisasi kanal

  • Normalisasi pretrained ImageNet diterapkan per kanal:

\[ \mathbf{X}_R=\frac{I_R/255-0.485}{0.229},\qquad \mathbf{X}_G=\frac{I_G/255-0.456}{0.224},\qquad \mathbf{X}_B=\frac{I_B/255-0.406}{0.225}. \]

  • Contoh:

\[ \begin{aligned} \mathbf{X}_{1,3}&=\frac{(192/255-0.485)}{0.229}\\ &=1.17 \end{aligned} \]

Pada ilustrasi ini menggunakan 1 kanal jadi setiap elemen dihitung dengan \(X_{i,j}=(I_{i,j}/255-0.485)/0.229\). Aturan yang sama diterapkan pada seluruh elemen matriks berikut.

\[ \mathbf{X}_{\mathrm{norm}}=\begin{bmatrix} -2.12 & -1.02 & 1.17 & 0.62 & -1.57\\ -2.12 & -0.75 & 1.44 & 0.90 & -1.43\\ -2.12 & -0.75 & 1.44 & 0.90 & -1.43\\ -2.12 & -0.88 & 1.17 & 0.62 & -1.57\\ -1.98 & -1.30 & 0.35 & -0.20 & -1.71 \end{bmatrix}. \]

2. Representasi Lokal

Pada ilustrasi ini, matriks \(\mathbf{X}\) berukuran \(5\times5\) merepresentasikan satu kanal dari feature map masukan blok \(\mathbf{F}^{(0)}\) yang telah dinormalisasi. Pembentukan representasi lokal diawali dengan operasi depthwise convolution menggunakan kernel \(3\times3\), stride \(1\), dan zero padding sebesar \(1\) pada setiap sisi. Hasilnya kemudian diproses melalui fungsi aktivasi Swish. Selanjutnya, proyeksi pointwise convolution \(1\times1\) diterapkan pada feature map lokal yang dihasilkan.

a. Depthwise Convolution

Matriks feature map masukan yang digunakan adalah:

\[ \mathbf{X} = \begin{bmatrix} -2.12 & -1.02 & 1.17 & 0.62 & -1.57\\ -2.12 & -0.75 & 1.44 & 0.90 & -1.43\\ -2.12 & -0.75 & 1.44 & 0.90 & -1.43\\ -2.12 & -0.88 & 1.17 & 0.62 & -1.57\\ -1.98 & -1.30 & 0.35 & -0.20 & -1.71 \end{bmatrix}. \]

  • Penambahan Zero Padding:

Sebelum operasi depthwise convolution dilakukan, satu lapisan nilai nol ditambahkan pada keempat sisi matriks masukan, yaitu sisi atas, bawah, kiri, dan kanan. Penambahan zero padding bertujuan mempertahankan ukuran spasial feature map setelah operasi konvolusi.

Ukuran keluaran dihitung menggunakan:

\[ o = \left\lfloor \frac{i+2p-k}{s} \right\rfloor+1, \]

dengan \(i\) menyatakan ukuran spasial masukan, \(p\) merupakan jumlah padding pada setiap sisi, \(k\) merupakan ukuran kernel, dan \(s\) merupakan stride.

Pada ilustrasi ini digunakan \(i=5\), \(p=1\), \(k=3\), dan \(s=1\), sehingga:

\[ \begin{aligned} o &= \left\lfloor \frac{5+2(1)-3}{1} \right\rfloor+1\\ &= \left\lfloor \frac{4}{1} \right\rfloor+1\\ &=5. \end{aligned} \]

Dengan demikian, ukuran spasial keluaran tetap \(5\times5\). Penambahan zero padding mengubah ukuran matriks masukan sementara dari \(5\times5\) menjadi \(7\times7\).

Matriks setelah penambahan zero padding adalah:

\[ \mathbf{X}_{\mathrm{pad}} = \begin{bmatrix} 0.00 & 0.00 & 0.00 & 0.00 & 0.00 & 0.00 & 0.00\\ 0.00 & -2.12 & -1.02 & 1.17 & 0.62 & -1.57 & 0.00\\ 0.00 & -2.12 & -0.75 & 1.44 & 0.90 & -1.43 & 0.00\\ 0.00 & -2.12 & -0.75 & 1.44 & 0.90 & -1.43 & 0.00\\ 0.00 & -2.12 & -0.88 & 1.17 & 0.62 & -1.57 & 0.00\\ 0.00 & -1.98 & -1.30 & 0.35 & -0.20 & -1.71 & 0.00\\ 0.00 & 0.00 & 0.00 & 0.00 & 0.00 & 0.00 & 0.00 \end{bmatrix}. \]

  • Filter Kernel:

Pada ilustrasi ini, matriks bobot kernel depthwise convolution ditetapkan sebagai:

\[ \mathbf{W}_{\mathrm{dw}} = \begin{bmatrix} 0.00 & 0.10 & 0.00\\ 0.10 & 0.60 & 0.10\\ 0.00 & 0.10 & 0.00 \end{bmatrix}. \]

Kernel tersebut memiliki bobot pusat sebesar \(0.60\), empat bobot sebesar \(0.10\) pada posisi atas, bawah, kiri, dan kanan, serta empat bobot sudut bernilai \(0.00\).

Setiap hasil konvolusi diperoleh melalui perkalian sembilan elemen pada area feature map dengan sembilan bobot kernel yang bersesuaian, kemudian seluruh hasil perkalian dijumlahkan.

  • Rumus:

Operasi depthwise convolution untuk satu kanal masukan dinyatakan sebagai:

\[ F_{\mathrm{dw},k,l} = \sum_{u=1}^{3} \sum_{v=1}^{3} W_{\mathrm{dw},u,v} X_{\mathrm{pad},k+u-1,l+v-1}, \]

dengan \(k,l=1,2,\ldots,5\), sedangkan \(u\) dan \(v\) merupakan indeks baris dan kolom kernel.

Pada setiap posisi, kernel mencakup area berukuran \(3\times3\). Karena stride bernilai \(1\), kernel bergeser satu kolom ke kanan untuk menghitung elemen berikutnya pada baris keluaran yang sama. Setelah mencapai posisi terakhir pada baris tersebut, kernel kembali ke sisi kiri dan bergeser satu baris ke bawah.

  • Contoh Perhitungan Konvolusi:

1. Perhitungan elemen pada posisi \((1,1)\)

Untuk menghasilkan elemen pertama dari feature map keluaran, kernel ditempatkan pada area \(3\times3\) di pojok kiri atas matriks yang telah diberi zero padding.

Area feature map yang diproses adalah:

\[ \begin{bmatrix} 0.00 & 0.00 & 0.00\\ 0.00 & -2.12 & -1.02\\ 0.00 & -2.12 & -0.75 \end{bmatrix}. \]

Area tersebut dikalikan secara elemen demi elemen dengan bobot kernel \(\mathbf{W}_{\mathrm{dw}}\), kemudian seluruh hasil perkalian dijumlahkan sebagai berikut:

\[ \begin{aligned} F_{\mathrm{dw},1,1} ={}& (0.00)(0.00) +(0.00)(0.10) +(0.00)(0.00)\\ &+(0.00)(0.10) +(-2.12)(0.60) +(-1.02)(0.10)\\ &+(0.00)(0.00) +(-2.12)(0.10) +(-0.75)(0.00)\\ ={}& -1.272-0.102-0.212\\ ={}&-1.586. \end{aligned} \]

Hasil perkalian berdasarkan nilai masukan yang ditampilkan adalah \(-1.586\). Pada matriks ilustrasi yang telah disusun sebelumnya, elemen ini tercatat sebesar \(-1.58\). Nilai tersebut dipertahankan sementara dan akan divalidasi kembali bersama seluruh tahapan perhitungan.

2. Perhitungan elemen pada posisi \((2,2)\)

Untuk menghitung elemen pada posisi \((2,2)\), kernel ditempatkan pada area yang dimulai dari baris kedua dan kolom kedua matriks setelah padding. Posisi ini berada satu baris di bawah dan satu kolom di kanan dibandingkan posisi awal.

Area feature map yang diproses adalah:

\[ \begin{bmatrix} -2.12 & -1.02 & 1.17\\ -2.12 & -0.75 & 1.44\\ -2.12 & -0.75 & 1.44 \end{bmatrix}. \]

Perhitungan konvolusi dilakukan menggunakan bobot kernel yang sama:

\[ \begin{aligned} F_{\mathrm{dw},2,2} ={}& (-2.12)(0.00) +(-1.02)(0.10) +(1.17)(0.00)\\ &+(-2.12)(0.10) +(-0.75)(0.60) +(1.44)(0.10)\\ &+(-2.12)(0.00) +(-0.75)(0.10) +(1.44)(0.00)\\ ={}& -0.102-0.212-0.450\\ &+0.144-0.075\\ ={}&-0.695. \end{aligned} \]

Hasil perkalian berdasarkan nilai masukan yang ditampilkan adalah \(-0.695\). Pada matriks ilustrasi sebelumnya, elemen ini tercatat sebesar \(-0.69\). Nilai tersebut juga dipertahankan sementara hingga proses validasi numerik dilakukan.

Prosedur yang sama diterapkan pada seluruh posisi kernel. Pada setiap posisi, elemen-elemen dalam area konvolusi dikalikan dengan bobot kernel yang bersesuaian, kemudian seluruh hasil perkalian dijumlahkan untuk membentuk satu elemen feature map keluaran.

Matriks hasil depthwise convolution yang digunakan sementara dalam ilustrasi ini adalah:

\[ \mathbf{F}_{\mathrm{dw}} = \begin{bmatrix} -1.58 & -0.78 & 0.81 & 0.42 & -1.02\\ -1.77 & -0.69 & 1.14 & 0.69 & -1.07\\ -1.77 & -0.68 & 1.14 & 0.69 & -1.07\\ -1.77 & -0.83 & 0.85 & 0.40 & -1.19\\ -1.53 & -1.03 & 0.18 & -0.19 & -1.20 \end{bmatrix}. \]

Matriks tersebut mempertahankan nilai pada ilustrasi sebelumnya dan akan diperiksa kembali melalui perhitungan numerik untuk memastikan konsistensi seluruh tahapan.

  • Fungsi Aktivasi Swish:

Setelah operasi depthwise convolution, fungsi aktivasi Swish diterapkan secara elemen demi elemen pada feature map yang dihasilkan.

Rumus fungsi aktivasi Swish adalah:

\[ \begin{aligned} L_{i,j} &= \operatorname{Swish} \left( F_{\mathrm{dw},i,j} \right)\\ &= \frac{F_{\mathrm{dw},i,j}} {1+e^{-F_{\mathrm{dw},i,j}}}. \end{aligned} \]

  • Contoh Perhitungan:

Untuk elemen pada posisi \((1,1)\), nilai yang digunakan sesuai dengan matriks hasil depthwise convolution pada ilustrasi sebelumnya, yaitu \(-1.58\).

\[ \begin{aligned} L_{1,1} &=\operatorname{Swish}(-1.58)\\ &=\frac{-1.58}{1+e^{-(-1.58)}}\\ &=\frac{-1.58}{1+e^{1.58}}\\ &=\frac{-1.58}{1+4.85}\\ &=\frac{-1.58}{5.85}\\ &=-0.27. \end{aligned} \]

Berdasarkan penerapan fungsi aktivasi Swish pada matriks ilustrasi sebelumnya, diperoleh:

\[ \mathbf{L} = \begin{bmatrix} -0.27 & -0.25 & 0.56 & 0.26 & -0.27\\ -0.26 & -0.23 & 0.87 & 0.46 & -0.27\\ -0.26 & -0.23 & 0.87 & 0.46 & -0.27\\ -0.26 & -0.25 & 0.60 & 0.24 & -0.28\\ -0.27 & -0.27 & 0.10 & -0.09 & -0.28 \end{bmatrix}. \]

Matriks \(\mathbf{L}\) merupakan representasi lokal setelah penerapan fungsi aktivasi Swish dan digunakan sebagai masukan pada tahap proyeksi pointwise convolution berikutnya. Nilai matriks ini dipertahankan sesuai ilustrasi sebelumnya hingga dilakukan validasi numerik secara menyeluruh.

b. Proyeksi Pointwise Convolution dan Tokenisasi

Feature map lokal \(\mathbf{L}\) memiliki dimensi \(5\times5\times1\). Selanjutnya, pointwise convolution \(1\times1\) diterapkan secara independen pada setiap posisi spasial. Berbeda dengan depthwise convolution \(3\times3\), operasi ini tidak melibatkan piksel tetangga, tetapi memproyeksikan satu kanal masukan menjadi dua kanal keluaran.

Proyeksi tersebut menghasilkan vektor fitur berdimensi dua pada setiap posisi spasial yang selanjutnya digunakan sebagai embedding token untuk masukan Transformer. Jumlah dua kanal digunakan sebagai penyederhanaan ilustrasi perhitungan manual agar pembentukan token serta operasi Query, Key, dan Value dapat ditunjukkan secara eksplisit. Pada implementasi MobileViTv3-v1-S sebenarnya, jumlah kanal ditentukan berdasarkan konfigurasi arsitektur.

  • Bobot pointwise convolution:

Pada ilustrasi ini, matriks bobot pointwise convolution ditetapkan sebagai:

\[ \mathbf{W}_{\mathrm{pw}}^{(\mathrm{tok})} = \begin{bmatrix} 1.00 & -0.50 \end{bmatrix}. \]

Matriks bobot \(\mathbf{W}_{\mathrm{pw}}^{(\mathrm{tok})}\) berdimensi \(1\times2\), sehingga setiap nilai pada feature map lokal diproyeksikan menjadi vektor dengan dua elemen.

  • Rumus:

Untuk setiap posisi spasial \((i,j)\), elemen ke-\(n\) dari token ke-\(t\) dihitung menggunakan:

\[ T_{t,n} = \sum_{m=1}^{C_L} W_{\mathrm{pw},m,n}^{(\mathrm{tok})} L_{i,j,m}, \qquad t=5(i-1)+j. \]

Pada ilustrasi ini, \(C_L=1\) dan \(n=1,2\). Dengan demikian, persamaan tersebut dapat disederhanakan menjadi:

\[ \mathbf{T}_t = L_{i,j} \mathbf{W}_{\mathrm{pw}}^{(\mathrm{tok})}. \]

Dengan bobot yang digunakan, kanal keluaran pertama mempertahankan nilai aktivasi lokal, sedangkan kanal kedua bernilai \(-0.50\) kali aktivasi lokal. Hasil proyeksi membentuk feature map berdimensi \(25\times2\).

  • Contoh perhitungan pada posisi \((1,1)\):

Diketahui \(L_{1,1}=-0.27\), sehingga:

\[ \begin{aligned} \mathbf{T}_1 &= L_{1,1} \mathbf{W}_{\mathrm{pw}}^{(\mathrm{tok})}\\ &= (-0.27) \begin{bmatrix} 1.00 & -0.50 \end{bmatrix}\\ &= \begin{bmatrix} (-0.27)(1.00) & (-0.27)(-0.50) \end{bmatrix}\\ &= \begin{bmatrix} -0.27 & 0.135 \end{bmatrix}\\ &= \begin{bmatrix} -0.27 & 0.14 \end{bmatrix}. \end{aligned} \]

Posisi spasial \((1,1)\) merupakan token pertama berdasarkan:

\[ t=5(1-1)+1=1. \]

  • Tokenisasi:

Setelah proyeksi pointwise convolution, vektor dua kanal pada setiap posisi spasial disusun menjadi urutan token menggunakan urutan raster, yaitu dari kiri ke kanan dan dari atas ke bawah. Indeks token ditentukan oleh:

\[ t=5(i-1)+j. \]

Sebagai contoh, posisi spasial \((1,1)\), \((1,3)\), \((2,1)\), dan \((5,5)\) masing-masing berkorespondensi dengan token ke-1, ke-3, ke-6, dan ke-25.

Setiap vektor token dinyatakan sebagai:

\[ \begin{aligned} \mathbf{T}_t &= L_{i,j,1} \mathbf{W}_{\mathrm{pw}}^{(\mathrm{tok})}\\ &= \begin{bmatrix} L_{i,j,1} & -0.50L_{i,j,1} \end{bmatrix}. \end{aligned} \]

Vektor token \(\mathbf{T}_t\) berdimensi \(1\times2\). Dengan menyusun seluruh 25 vektor token berdasarkan urutan raster, diperoleh matriks \(\mathbf{T}\) berdimensi \(25\times2\):

\[ \mathbf{T} = \begin{bmatrix} -0.27 & 0.13\\ -0.25 & 0.12\\ 0.56 & -0.28\\ 0.26 & -0.13\\ -0.27 & 0.14\\ -0.26 & 0.13\\ -0.23 & 0.12\\ 0.87 & -0.43\\ 0.46 & -0.23\\ -0.27 & 0.14\\ -0.26 & 0.13\\ -0.23 & 0.11\\ 0.87 & -0.43\\ 0.46 & -0.23\\ -0.27 & 0.14\\ -0.26 & 0.13\\ -0.25 & 0.13\\ 0.60 & -0.30\\ 0.24 & -0.12\\ -0.28 & 0.14\\ -0.27 & 0.14\\ -0.27 & 0.14\\ 0.10 & -0.05\\ -0.09 & 0.04\\ -0.28 & 0.14 \end{bmatrix}. \]

3. Transformer MobileViTv3-v1-S (Self-Attention)

a. Normalisasi Token

Sebelum memasuki mekanisme self-attention, setiap token pada matriks \(\mathbf{T}\) dinormalisasi menggunakan Layer Normalization (LN). Normalisasi dilakukan secara independen pada setiap token, sehingga rata-rata dan varians dihitung berdasarkan dua elemen fitur pada token yang sama.

  • Rumus:

Untuk token ke-\(t\), rata-rata dan varians dihitung sebagai:

\[ \mu_t = \frac{1}{2}\sum_{k=1}^{2}T_{t,k}, \qquad \sigma_t^2 = \frac{1}{2}\sum_{k=1}^{2}(T_{t,k}-\mu_t)^2. \]

Selanjutnya, elemen ke-\(k\) pada token ke-\(t\) dinormalisasi menggunakan:

\[ [\operatorname{LN}(\mathbf{T})]_{t,k} = \frac{T_{t,k}-\mu_t} {\sqrt{\sigma_t^2+\varepsilon}}, \qquad \varepsilon=10^{-5}. \]

Matriks token \(\mathbf{T}\) berdimensi \(25\times2\), sehingga matriks hasil normalisasi \(\operatorname{LN}(\mathbf{T})\) juga berdimensi \(25\times2\).

  • Contoh perhitungan untuk token pertama:

Diketahui vektor token pertama adalah:

\[ \mathbf{T}_1 = \begin{bmatrix} -0.27 & 0.13 \end{bmatrix}. \]

Rata-rata token pertama dihitung sebagai:

\[ \begin{aligned} \mu_1 &=\frac{T_{1,1}+T_{1,2}}{2}\\ &=\frac{-0.27+0.13}{2}\\ &=\frac{-0.14}{2}\\ &=-0.07. \end{aligned} \]

Varians token pertama diperoleh:

\[ \begin{aligned} \sigma_1^2 &=\frac{(T_{1,1}-\mu_1)^2+(T_{1,2}-\mu_1)^2}{2}\\ &=\frac{(-0.27-(-0.07))^2+(0.13-(-0.07))^2}{2}\\ &=\frac{(-0.20)^2+(0.20)^2}{2}\\ &=\frac{0.04+0.04}{2}\\ &=0.04. \end{aligned} \]

Selanjutnya, elemen pertama token dinormalisasi sebagai:

\[ \begin{aligned} \left[\mathrm{LN}(\mathbf{T})\right]_{1,1} &= \frac{T_{1,1}-\mu_1}{\sqrt{\sigma_1^2+\varepsilon}}\\ &= \frac{-0.27-(-0.07)}{\sqrt{0.04+10^{-5}}}\\ &= \frac{-0.20}{\sqrt{0.04+10^{-5}}}\\ &= \frac{-0.20}{0.20}\\ &= -1.00 \end{aligned} \]

Dengan perhitungan yang sama, elemen kedua token pertama diperoleh:

\[ [\operatorname{LN}(\mathbf{T})]_{1,2} =1.00. \]

Dengan demikian, hasil normalisasi token pertama adalah:

\[ [\operatorname{LN}(\mathbf{T})]_{1} = \begin{bmatrix} -1.00 & 1.00 \end{bmatrix}. \]

Proses normalisasi yang sama diterapkan pada seluruh token, sehingga diperoleh matriks token ternormalisasi berukuran \(25\times2\) sebagai berikut:

\[ \operatorname{LN}(\mathbf{T}) = \begin{bmatrix} -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00 \end{bmatrix}. \]

b. Proyeksi Query

Setelah token dinormalisasi, setiap token diproyeksikan menjadi Query (Q). Query merepresentasikan informasi yang dicari oleh setiap token ketika menghitung hubungan dengan token-token lain melalui mekanisme self-attention.

  • Bobot Query:

Pada ilustrasi ini, matriks bobot proyeksi Query ditetapkan sebagai:

\[ \mathbf{W}_Q = 0.50\mathbf{I} = \begin{bmatrix} 0.50 & 0.00\\ 0.00 & 0.50 \end{bmatrix}, \]

dengan \(\mathbf{I}\) merupakan matriks identitas berukuran \(2\times2\). Bobot tersebut mengalikan setiap elemen token ternormalisasi dengan \(0.50\), tanpa mencampurkan informasi antara kedua kanal fitur.

  • Rumus:

Proyeksi Query dirumuskan sebagai:

\[ \mathbf{Q} = \operatorname{LN}(\mathbf{T})\mathbf{W}_Q. \]

Untuk token ke-\(t\), persamaan tersebut dapat dituliskan sebagai:

\[ \begin{aligned} \mathbf{Q}_t &= [\operatorname{LN}(\mathbf{T})]_{t}\mathbf{W}_Q\\ &= \begin{bmatrix} [\operatorname{LN}(\mathbf{T})]_{t,1} & [\operatorname{LN}(\mathbf{T})]_{t,2} \end{bmatrix} \begin{bmatrix} 0.50 & 0.00\\ 0.00 & 0.50 \end{bmatrix}. \end{aligned} \]

Matriks hasil normalisasi \(\operatorname{LN}(\mathbf{T})\) berukuran \(25\times2\), sedangkan matriks bobot \(\mathbf{W}_Q\) berukuran \(2\times2\). Dengan demikian, matriks Query \(\mathbf{Q}\) berukuran \(25\times2\).

  • Contoh perhitungan untuk token pertama:

Berdasarkan tahap normalisasi token sebelumnya, hasil normalisasi token pertama yang ditampilkan dengan dua angka desimal adalah:

\[ [\operatorname{LN}(\mathbf{T})]_{1} = \begin{bmatrix} -1.00 & 1.00 \end{bmatrix}. \]

Selanjutnya, Query untuk token pertama dihitung sebagai:

\[ \begin{aligned} \mathbf{Q}_1 &= [\operatorname{LN}(\mathbf{T})]_{1}\mathbf{W}_Q\\ &= \begin{bmatrix} -1.00 & 1.00 \end{bmatrix} \begin{bmatrix} 0.50 & 0.00\\ 0.00 & 0.50 \end{bmatrix}\\ &= \begin{bmatrix} (-1.00)(0.50)+(1.00)(0.00) & (-1.00)(0.00)+(1.00)(0.50) \end{bmatrix}\\ &= \begin{bmatrix} -0.50 & 0.50 \end{bmatrix}. \end{aligned} \]

Dengan demikian, elemen Query untuk token pertama adalah:

\[ Q_{1,1}=-0.50, \qquad Q_{1,2}=0.50. \]

Proses proyeksi yang sama diterapkan pada seluruh token. Dengan menampilkan hasil hingga dua angka desimal, diperoleh matriks Query berukuran \(25\times2\) sebagai berikut:

\[ \mathbf{Q} = \begin{bmatrix} -0.50 & 0.50\\ -0.50 & 0.50\\ 0.50 & -0.50\\ 0.50 & -0.50\\ -0.50 & 0.50\\ -0.50 & 0.50\\ -0.50 & 0.50\\ 0.50 & -0.50\\ 0.50 & -0.50\\ -0.50 & 0.50\\ -0.50 & 0.50\\ -0.50 & 0.50\\ 0.50 & -0.50\\ 0.50 & -0.50\\ -0.50 & 0.50\\ -0.50 & 0.50\\ -0.50 & 0.50\\ 0.50 & -0.50\\ 0.50 & -0.50\\ -0.50 & 0.50\\ -0.50 & 0.50\\ -0.50 & 0.50\\ 0.50 & -0.50\\ -0.50 & 0.50\\ -0.50 & 0.50 \end{bmatrix}. \]

c. Proyeksi Key

Setelah token dinormalisasi, setiap token juga diproyeksikan menjadi Key (K). Pada mekanisme self-attention, Key berfungsi sebagai representasi pembanding. Setiap Query dibandingkan dengan seluruh Key untuk menentukan tingkat keterkaitan antartoken.

  • Bobot Key:

Pada ilustrasi ini, matriks bobot proyeksi Key ditetapkan sebagai:

\[ \mathbf{W}_K = \begin{bmatrix} 0.40 & 0.00\\ 0.00 & 0.60 \end{bmatrix}. \]

Bobot tersebut memberikan skala yang berbeda pada komponen pertama dan kedua dari setiap token ternormalisasi, tanpa mencampurkan informasi antara kedua komponen fitur.

  • Rumus:

Proyeksi Key dirumuskan sebagai:

\[ \mathbf{K} = \operatorname{LN}(\mathbf{T})\mathbf{W}_K. \]

Untuk token ke-\(t\), persamaan tersebut dapat dituliskan sebagai:

\[ \begin{aligned} \mathbf{K}_t &= [\operatorname{LN}(\mathbf{T})]_{t}\mathbf{W}_K\\ &= \begin{bmatrix} [\operatorname{LN}(\mathbf{T})]_{t,1} & [\operatorname{LN}(\mathbf{T})]_{t,2} \end{bmatrix} \begin{bmatrix} 0.40 & 0.00\\ 0.00 & 0.60 \end{bmatrix}. \end{aligned} \]

Matriks hasil normalisasi \(\operatorname{LN}(\mathbf{T})\) berukuran \(25\times2\), sedangkan matriks bobot \(\mathbf{W}_K\) berukuran \(2\times2\). Dengan demikian, matriks Key \(\mathbf{K}\) berukuran \(25\times2\).

  • Contoh perhitungan untuk token pertama:

Berdasarkan tahap normalisasi token sebelumnya, hasil normalisasi token pertama yang ditampilkan dengan dua angka desimal adalah:

\[ [\operatorname{LN}(\mathbf{T})]_{1} = \begin{bmatrix} -1.00 & 1.00 \end{bmatrix}. \]

Selanjutnya, Key untuk token pertama dihitung sebagai:

\[ \begin{aligned} \mathbf{K}_1 &= [\operatorname{LN}(\mathbf{T})]_{1}\mathbf{W}_K\\ &= \begin{bmatrix} -1.00 & 1.00 \end{bmatrix} \begin{bmatrix} 0.40 & 0.00\\ 0.00 & 0.60 \end{bmatrix}\\ &= \begin{bmatrix} (-1.00)(0.40)+(1.00)(0.00) & (-1.00)(0.00)+(1.00)(0.60) \end{bmatrix}\\ &= \begin{bmatrix} -0.40 & 0.60 \end{bmatrix}. \end{aligned} \]

Dengan demikian, elemen Key untuk token pertama adalah:

\[ K_{1,1}=-0.40, \qquad K_{1,2}=0.60. \]

Pada ilustrasi ini, matriks bobot \(\mathbf{W}_K\) ditetapkan berbeda dari matriks bobot \(\mathbf{W}_Q\) untuk menunjukkan bahwa Query dan Key dihasilkan melalui proyeksi yang berbeda. Pada implementasi Transformer sebenarnya, kedua matriks bobot tersebut merupakan parameter yang dipelajari secara terpisah selama proses pelatihan.

Proses proyeksi yang sama diterapkan pada seluruh token. Dengan menampilkan hasil hingga dua angka desimal, diperoleh matriks Key berukuran \(25\times2\) sebagai berikut:

\[ \mathbf{K} = \begin{bmatrix} -0.40 & 0.60\\ -0.40 & 0.60\\ 0.40 & -0.60\\ 0.40 & -0.60\\ -0.40 & 0.60\\ -0.40 & 0.60\\ -0.40 & 0.60\\ 0.40 & -0.60\\ 0.40 & -0.60\\ -0.40 & 0.60\\ -0.40 & 0.60\\ -0.40 & 0.60\\ 0.40 & -0.60\\ 0.40 & -0.60\\ -0.40 & 0.60\\ -0.40 & 0.60\\ -0.40 & 0.60\\ 0.40 & -0.60\\ 0.40 & -0.60\\ -0.40 & 0.60\\ -0.40 & 0.60\\ -0.40 & 0.60\\ 0.40 & -0.60\\ -0.40 & 0.60\\ -0.40 & 0.60 \end{bmatrix}. \]

d. Proyeksi Value

Setelah token dinormalisasi, setiap token juga diproyeksikan menjadi Value (V). Pada mekanisme self-attention, Value memuat informasi fitur yang akan diagregasikan dari seluruh token berdasarkan bobot attention yang dihitung melalui interaksi antara Query dan Key.

  • Bobot Value:

Pada ilustrasi ini, matriks bobot proyeksi Value ditetapkan sebagai matriks identitas:

\[ \mathbf{W}_V = \mathbf{I} = \begin{bmatrix} 1.00 & 0.00\\ 0.00 & 1.00 \end{bmatrix}. \]

Matriks identitas tidak mengubah nilai maupun mencampurkan kedua elemen fitur token. Oleh karena itu, pada ilustrasi ini matriks Value memiliki nilai yang sama dengan matriks token yang telah dinormalisasi.

  • Rumus:

Proyeksi Value dirumuskan sebagai:

\[ \mathbf{V} = \operatorname{LN}(\mathbf{T})\mathbf{W}_V = \operatorname{LN}(\mathbf{T})\mathbf{I} = \operatorname{LN}(\mathbf{T}). \]

Untuk token ke-\(t\), persamaan tersebut dapat dituliskan sebagai:

\[ \begin{aligned} \mathbf{V}_t &= [\operatorname{LN}(\mathbf{T})]_{t}\mathbf{W}_V\\ &= \begin{bmatrix} [\operatorname{LN}(\mathbf{T})]_{t,1} & [\operatorname{LN}(\mathbf{T})]_{t,2} \end{bmatrix} \begin{bmatrix} 1.00 & 0.00\\ 0.00 & 1.00 \end{bmatrix}. \end{aligned} \]

Matriks hasil normalisasi \(\operatorname{LN}(\mathbf{T})\) berukuran \(25\times2\), sedangkan matriks bobot \(\mathbf{W}_V\) berukuran \(2\times2\). Dengan demikian, matriks Value \(\mathbf{V}\) berukuran \(25\times2\).

  • Contoh perhitungan untuk token pertama:

Berdasarkan tahap normalisasi token sebelumnya, hasil normalisasi token pertama yang ditampilkan dengan dua angka desimal adalah:

\[ [\operatorname{LN}(\mathbf{T})]_{1} = \begin{bmatrix} -1.00 & 1.00 \end{bmatrix}. \]

Selanjutnya, Value untuk token pertama dihitung sebagai:

\[ \begin{aligned} \mathbf{V}_1 &= [\operatorname{LN}(\mathbf{T})]_{1}\mathbf{W}_V\\ &= \begin{bmatrix} -1.00 & 1.00 \end{bmatrix} \begin{bmatrix} 1.00 & 0.00\\ 0.00 & 1.00 \end{bmatrix}\\ &= \begin{bmatrix} (-1.00)(1.00)+(1.00)(0.00) & (-1.00)(0.00)+(1.00)(1.00) \end{bmatrix}\\ &= \begin{bmatrix} -1.00 & 1.00 \end{bmatrix}. \end{aligned} \]

Dengan demikian, elemen Value untuk token pertama adalah:

\[ V_{1,1}=-1.00, \qquad V_{1,2}=1.00. \]

Karena \(\mathbf{W}_V=\mathbf{I}\), setiap baris pada matriks \(\mathbf{V}\) memiliki nilai yang sama dengan baris yang bersesuaian pada matriks \(\operatorname{LN}(\mathbf{T})\). Pada implementasi Transformer sebenarnya, matriks bobot \(\mathbf{W}_V\) merupakan parameter yang dipelajari selama pelatihan dan tidak harus berbentuk matriks identitas.

Proses proyeksi yang sama diterapkan pada seluruh token. Dengan menampilkan hasil hingga dua angka desimal, diperoleh matriks Value berukuran \(25\times2\) sebagai berikut:

\[ \mathbf{V} = \begin{bmatrix} -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00 \end{bmatrix}. \]

e. Scaled Dot-Product Attention

Setelah matriks Query \(\mathbf{Q}\) dan matriks Key \(\mathbf{K}\) diperoleh, tingkat keterkaitan antartoken dihitung menggunakan scaled dot-product attention. Perhitungan ini menghasilkan matriks skor perhatian \(\mathbf{S}\). Elemen \(S_{t,u}\) menyatakan skor kesesuaian antara Query token ke-\(t\) dan Key token ke-\(u\). Semakin besar skor yang diperoleh, semakin tinggi tingkat kesesuaian kedua representasi tersebut.

  • Rumus:

Mengacu pada Persamaan (2.9), matriks skor perhatian dirumuskan sebagai:

\[ \mathbf{S} = \frac{\mathbf{Q}\mathbf{K}^{\top}}{\sqrt{d_k}}. \]

Pada ilustrasi ini, setiap Key memiliki dua komponen fitur, sehingga:

\[ d_k=2. \]

Untuk pasangan token ke-\(t\) dan ke-\(u\), skor perhatian dihitung menggunakan:

\[ S_{t,u} = \frac{\mathbf{Q}_t\mathbf{K}_u^{\top}}{\sqrt{2}}. \]

Matriks \(\mathbf{Q}\) dan \(\mathbf{K}\) masing-masing berukuran \(25\times2\), sedangkan matriks \(\mathbf{K}^{\top}\) berukuran \(2\times25\). Dengan demikian, matriks skor perhatian \(\mathbf{S}\) berukuran \(25\times25\). Setiap baris merepresentasikan token Query, sedangkan setiap kolom merepresentasikan token Key.

  • Contoh perhitungan skor perhatian token pertama:

Berdasarkan hasil proyeksi sebelumnya, diperoleh Query dan Key token pertama:

\[ \mathbf{Q}_1 = \begin{bmatrix} -0.50 & 0.50 \end{bmatrix}, \qquad \mathbf{K}_1 = \begin{bmatrix} -0.40 & 0.60 \end{bmatrix}. \]

Skor perhatian token pertama terhadap dirinya sendiri dihitung sebagai:

\[ \begin{aligned} S_{1,1} &= \frac{\mathbf{Q}_1\mathbf{K}_1^{\top}}{\sqrt{2}}\\ &= \frac{ \begin{bmatrix} -0.50 & 0.50 \end{bmatrix} \begin{bmatrix} -0.40\\ 0.60 \end{bmatrix} }{\sqrt{2}}\\ &= \frac{(-0.50)(-0.40)+(0.50)(0.60)}{\sqrt{2}}\\ &= \frac{0.20+0.30}{\sqrt{2}}\\ &= \frac{0.50}{\sqrt{2}}\\ &=0.35. \end{aligned} \]

Sebagai pembanding, Key token ketiga adalah:

\[ \mathbf{K}_3 = \begin{bmatrix} 0.40 & -0.60 \end{bmatrix}. \]

Skor perhatian Query token pertama terhadap Key token ketiga dihitung sebagai:

\[ \begin{aligned} S_{1,3} &= \frac{\mathbf{Q}_1\mathbf{K}_3^{\top}}{\sqrt{2}}\\ &= \frac{ \begin{bmatrix} -0.50 & 0.50 \end{bmatrix} \begin{bmatrix} 0.40\\ -0.60 \end{bmatrix} }{\sqrt{2}}\\ &= \frac{(-0.50)(0.40)+(0.50)(-0.60)}{\sqrt{2}}\\ &= \frac{-0.20-0.30}{\sqrt{2}}\\ &= \frac{-0.50}{\sqrt{2}}\\ &=-0.35. \end{aligned} \]

Proses yang sama diterapkan pada seluruh pasangan token. Dengan menampilkan hasil hingga dua angka desimal, diperoleh matriks skor perhatian \(\mathbf{S}\) berukuran \(25\times25\) sebagai berikut:

\[ mathbf{S} =\begin{bmatrix} 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & 0.35 & 0.35\\ 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & 0.35 & 0.35\\ -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & -0.35 & -0.35\\ -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & -0.35 & -0.35\\ 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & 0.35 & 0.35\\ 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & 0.35 & 0.35\\ 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & 0.35 & 0.35\\ -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & -0.35 & -0.35\\ -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & -0.35 & -0.35\\ 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & 0.35 & 0.35\\ 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & 0.35 & 0.35\\ 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & 0.35 & 0.35\\ -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & -0.35 & -0.35\\ -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & -0.35 & -0.35\\ 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & 0.35 & 0.35\\ 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & 0.35 & 0.35\\ 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & 0.35 & 0.35\\ -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & -0.35 & -0.35\\ -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & -0.35 & -0.35\\ 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & 0.35 & 0.35\\ 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & 0.35 & 0.35\\ 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & 0.35 & 0.35\\ -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & 0.35 & -0.35 & -0.35 & -0.35 & 0.35 & -0.35 & -0.35\\ 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & 0.35 & 0.35\\ 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & -0.35 & 0.35 & 0.35 & 0.35 & -0.35 & 0.35 & 0.35 \end{bmatrix}. \]

Nilai positif menunjukkan bahwa pola Query dan Key kedua token cenderung serupa, sedangkan nilai negatif menunjukkan pola yang berlawanan. Matriks \(\mathbf{S}\) selanjutnya dinormalisasi menggunakan fungsi softmax pada setiap baris untuk menghasilkan matriks bobot perhatian \(\mathbf{A}\).

f. Softmax Attention

Matriks skor \(S\) selanjutnya diubah menjadi bobot attention menggunakan fungsi softmax per baris. Dengan demikian, setiap baris pada matriks \(A\) memiliki jumlah nilai sebesar satu.

  • Rumus:

\[ A_{t,u} = \frac{e^{S_{t,u}}} {\sum_{r=1}^{25}e^{S_{t,r}}}. \]

Matriks \(A\) memiliki dimensi \(25\times25\), sama seperti matriks skor \(S\).

  • Contoh perhitungan untuk \(A_{1,1}\):

Pada baris pertama matriks \(S\), terdapat 16 skor bernilai \(0.35\) dan 9 skor bernilai \(-0.35\). Oleh karena itu,

\[ \begin{aligned} A_{1,1} &= \frac{e^{0.35}} {16e^{0.35}+9e^{-0.35}}\\ &= \frac{1.42} {16(1.42)+9(0.70)}\\ &= \frac{1.42}{22.72+6.30}\\ &= \frac{1.42}{29.02}\\ &=0.05. \end{aligned} \]

Nilai \(0.05\) menunjukkan bahwa token pertama memberi bobot perhatian lebih besar kepada token yang memiliki pola Query–Key serupa, yaitu token dengan skor \(0.35\).

Aturan yang sama diterapkan pada seluruh baris, sehingga diperoleh matriks bobot attention \(A\) berikut. \[ A=\begin{bmatrix} 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.05 & 0.05\\ 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.05 & 0.05\\ 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.03 & 0.03\\ 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.03 & 0.03\\ 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.05 & 0.05\\ 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.05 & 0.05\\ 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.05 & 0.05\\ 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.03 & 0.03\\ 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.03 & 0.03\\ 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.05 & 0.05\\ 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.05 & 0.05\\ 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.05 & 0.05\\ 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.03 & 0.03\\ 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.03 & 0.03\\ 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.05 & 0.05\\ 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.05 & 0.05\\ 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.05 & 0.05\\ 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.03 & 0.03\\ 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.03 & 0.03\\ 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.05 & 0.05\\ 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.05 & 0.05\\ 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.05 & 0.05\\ 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.06 & 0.03 & 0.03 & 0.03 & 0.06 & 0.03 & 0.03\\ 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.05 & 0.05\\ 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.02 & 0.05 & 0.05 & 0.05 & 0.02 & 0.05 & 0.05 \end{bmatrix}. \]

g. Agregasi Value Berbobot Attention

Matriks bobot attention \(\mathbf{A}\) digunakan untuk menggabungkan seluruh Value \(\mathbf{V}\). Setiap baris hasil \(\mathbf{A}\mathbf{V}\) adalah jumlah berbobot dari seluruh token Value.

Pada ilustrasi perhitungan ini, mekanisme self-attention disederhanakan menggunakan satu attention head. Oleh karena itu, operasi concatenation pada Persamaan (2.14) tidak menggabungkan beberapa keluaran head dan menghasilkan keluaran yang sama dengan head tunggal tersebut. Matriks proyeksi keluaran \(\mathbf W^O\) ditetapkan sebagai matriks identitas, sehingga proses proyeksi keluaran tidak mengubah nilai hasil agregasi Value. Dengan demikian, keluaran attention pada ilustrasi ini diperoleh dari perkalian matriks bobot perhatian \(\mathbf A\) dan matriks Value \(\mathbf V\).

  • Rumus:

\[ \mathbf{O}_{\mathrm{att}}=\mathbf{A}\mathbf{V}. \]

Pada ilustrasi ini, karena bobot keluaran \(\mathbf{W}^{O}=\mathbf{I}\), maka:

\[ \mathbf{O}_{\mathrm{att}} = \mathbf{A}\mathbf{V}\mathbf{W}^{O} = \mathbf{A}\mathbf{V}. \]

Matriks \(\mathbf{A}\) berdimensi \(25\times25\), sedangkan \(\mathbf{V}\) berdimensi \(25\times2\). Oleh karena itu, hasil \(\mathbf{A}\mathbf{V}\) atau matriks keluaran attention \(\mathbf{O}_{\mathrm{att}}\) berdimensi \(25\times2\).

  • Contoh perhitungan untuk \(O_{\mathrm{att},1,1}\):

Pada baris pertama, terdapat 16 token Value berpola \((-1,1)\) dengan bobot sekitar \(0.05\), serta 9 token Value berpola \((1,-1)\) dengan bobot sekitar \(0.02\). Maka, komponen pertama dihitung sebagai:

\[ \begin{aligned} O_{\mathrm{att},1,1} &= \sum_{u=1}^{25}A_{1,u}V_{u,1}\\ &= 16(0.05)(-1.00)+9(0.02)(1.00)\\ &= -0.80+0.18\\ &= -0.62. \end{aligned} \]

Dengan cara yang sama, komponen kedua adalah:

\[ \begin{aligned} O_{\mathrm{att},1,2} &= \sum_{u=1}^{25}A_{1,u}V_{u,2}\\ &= 16(0.05)(1.00)+9(0.02)(-1.00)\\ &= 0.80-0.18\\ &= 0.62. \end{aligned} \]

Sehingga,

\[ \mathbf{O}_{\mathrm{att},1}= \begin{bmatrix} -0.62 & 0.62 \end{bmatrix}. \]

Aturan yang sama diterapkan pada seluruh token, sehingga diperoleh matriks \(AV\) berikut.

\[ \mathbf{O}_{\mathrm{att}} = \begin{bmatrix} -0.62 & 0.62\\ -0.62 & 0.62\\ 0.06 & -0.06\\ 0.06 & -0.06\\ -0.62 & 0.62\\ -0.62 & 0.62\\ -0.62 & 0.62\\ 0.06 & -0.06\\ 0.06 & -0.06\\ -0.62 & 0.62\\ -0.62 & 0.62\\ -0.62 & 0.62\\ 0.06 & -0.06\\ 0.06 & -0.06\\ -0.62 & 0.62\\ -0.62 & 0.62\\ -0.62 & 0.62\\ 0.06 & -0.06\\ 0.06 & -0.06\\ -0.62 & 0.62\\ -0.62 & 0.62\\ -0.62 & 0.62\\ 0.06 & -0.06\\ -0.62 & 0.62\\ -0.62 & 0.62 \end{bmatrix}. \]

h. Residual Attention

Residual attention menggabungkan matriks token awal \(\mathbf{T}\) dengan keluaran attention \(\mathbf{O}_{\mathrm{att}}\). Tujuannya adalah mempertahankan informasi awal token sambil menambahkan informasi global hasil self-attention.

  • Rumus:

\[ \mathbf{Z}' = \mathbf{T} + \mathbf{O}_{\mathrm{att}}. \]

Matriks \(\mathbf{T}\) dan \(\mathbf{O}_{\mathrm{att}}\) keduanya berdimensi \(25\times2\), sehingga \(\mathbf{Z}'\) juga berdimensi \(25\times2\).

  • Contoh perhitungan untuk token pertama:

\[ \mathbf{T}_1= \begin{bmatrix} -0.27 & 0.13 \end{bmatrix}, \qquad \mathbf{O}_{\mathrm{att},1}= \begin{bmatrix} -0.62 & 0.62 \end{bmatrix}. \]

Maka,

\[ \begin{aligned} \mathbf{Z}'_{1} &= \mathbf{T}_1+\mathbf{O}_{\mathrm{att},1}\\ &= \begin{bmatrix} -0.27 & 0.13 \end{bmatrix} + \begin{bmatrix} -0.62 & 0.62 \end{bmatrix}\\ &= \begin{bmatrix} -0.89 & 0.75 \end{bmatrix}. \end{aligned} \]

Aturan yang sama diterapkan pada seluruh token, sehingga diperoleh matriks residual attention \(\mathbf{Z}'\) berikut.

\[ \mathbf{Z}'= \begin{bmatrix} -0.89 & 0.75\\ -0.87 & 0.74\\ 0.62 & -0.34\\ 0.32 & -0.19\\ -0.89 & 0.76\\ -0.88 & 0.75\\ -0.85 & 0.74\\ 0.93 & -0.49\\ 0.52 & -0.29\\ -0.89 & 0.76\\ -0.88 & 0.75\\ -0.85 & 0.73\\ 0.93 & -0.49\\ 0.52 & -0.29\\ -0.89 & 0.76\\ -0.88 & 0.75\\ -0.87 & 0.75\\ 0.66 & -0.36\\ 0.30 & -0.18\\ -0.90 & 0.76\\ -0.89 & 0.76\\ -0.89 & 0.76\\ 0.16 & -0.11\\ -0.71 & 0.66\\ -0.90 & 0.76 \end{bmatrix}. \]

i. Normalisasi Keluaran Residual Attention

Matriks hasil residual attention \(\mathbf{Z}'\) dinormalisasi per token menggunakan Layer Normalization, dengan prosedur yang sama seperti normalisasi token sebelumnya.

  • Rumus:

\[ \left[\operatorname{LN}(\mathbf{Z}'_t)\right]_k = \frac{Z'_{t,k}-\mu_t} {\sqrt{\sigma_t^{2}+10^{-5}}}, \]

dengan:

\[ \mu_t = \frac{1}{2}\sum_{k=1}^{2}Z'_{t,k}, \qquad \sigma_t^{2} = \frac{1}{2}\sum_{k=1}^{2}(Z'_{t,k}-\mu_t)^2. \]

  • Contoh perhitungan untuk token pertama:

\[ \mathbf{Z}'_1= \begin{bmatrix} -0.89 & 0.75 \end{bmatrix}. \]

Rata-rata token pertama adalah:

\[ \begin{aligned} \mu_1 &= \frac{-0.89+0.75}{2}\\ &= -0.07. \end{aligned} \]

Variansnya adalah:

\[ \begin{aligned} \sigma_1^2 &= \frac{(-0.89-(-0.07))^2+(0.75-(-0.07))^2}{2}\\ &= \frac{(-0.82)^2+(0.82)^2}{2}\\ &= 0.6724. \end{aligned} \]

Elemen pertama setelah normalisasi adalah:

\[ \begin{aligned} \left[\operatorname{LN}(\mathbf{Z}'_1)\right]_1 &= \frac{-0.89-(-0.07)} {\sqrt{0.6724+10^{-5}}}\\ &= \frac{-0.82}{0.82}\\ &= -1.00. \end{aligned} \]

Dengan cara yang sama, \(\left[\operatorname{LN}(\mathbf{Z}'_1)\right]_2=1.00\). Oleh karena itu:

\[ \operatorname{LN}(\mathbf{Z}'_1)= \begin{bmatrix} -1.00 & 1.00 \end{bmatrix}. \]

Aturan yang sama diterapkan pada seluruh token, sehingga diperoleh hasil normalisasi residual attention \(\operatorname{LN}(\mathbf{Z}')\) berikut.

\[ \operatorname{LN}(\mathbf{Z}')= \begin{bmatrix} -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00 \end{bmatrix}. \]

j. Lapisan Linear Pertama MLP (Feed-Forward Network)

Lapisan linear pertama pada MLP memproyeksikan setiap token dari dua fitur menjadi tiga fitur. Tahap ini merupakan bagian pertama dari MLP pada Persamaan (2.17). Pada ilustrasi perhitungan, fungsi aktivasi GELU disederhanakan menjadi ReLU dan vektor bias tidak digunakan.

  • Bobot lapisan linear pertama:

\[ \mathbf{W}_1= \begin{bmatrix} 0.60 & -0.20 & 0.40\\ -0.30 & 0.50 & -0.40 \end{bmatrix}. \]

  • Rumus:

\[ \operatorname{ReLU} \left( \operatorname{LN}(\mathbf{Z}')\mathbf{W}_1 \right). \]

dengan:

\[ \operatorname{ReLU}(x)=\max(0,x). \]

Matriks \(\operatorname{LN}(\mathbf{Z}')\) berdimensi \(25\times2\) dan \(\mathbf{W}_1\) berdimensi \(2\times3\), sehingga hasil lapisan linear pertama setelah aktivasi ReLU berdimensi \(25\times3\).

  • Contoh perhitungan untuk token pertama:

\[ \operatorname{LN}(\mathbf{Z}'_1)= \begin{bmatrix} -1.00 & 1.00 \end{bmatrix}. \]

Sebelum ReLU:

\[ \begin{aligned} \operatorname{LN}(\mathbf{Z}'_1)\mathbf{W}_1 &= \begin{bmatrix} -1.00 & 1.00 \end{bmatrix} \begin{bmatrix} 0.60 & -0.20 & 0.40\\ -0.30 & 0.50 & -0.40 \end{bmatrix}\\ &= \begin{bmatrix} -0.90 & 0.70 & -0.80 \end{bmatrix}. \end{aligned} \]

Setelah ReLU:

\[ \begin{aligned} \operatorname{ReLU} \left( \operatorname{LN}(\mathbf{Z}'_1)\mathbf{W}_1 \right) &= \operatorname{ReLU} \left( \begin{bmatrix} -0.90 & 0.70 & -0.80 \end{bmatrix} \right)\\ &= \begin{bmatrix} 0.00 & 0.70 & 0.00 \end{bmatrix}. \end{aligned} \]

Aturan yang sama diterapkan pada seluruh token, sehingga diperoleh hasil lapisan linear pertama setelah aktivasi ReLU berikut.

\[ \operatorname{ReLU} \left( \operatorname{LN}(\mathbf{Z}')\mathbf{W}_1 \right) = \begin{bmatrix} 0.00 & 0.70 & 0.00\\ 0.00 & 0.70 & 0.00\\ 0.90 & 0.00 & 0.80\\ 0.90 & 0.00 & 0.80\\ 0.00 & 0.70 & 0.00\\ 0.00 & 0.70 & 0.00\\ 0.00 & 0.70 & 0.00\\ 0.90 & 0.00 & 0.80\\ 0.90 & 0.00 & 0.80\\ 0.00 & 0.70 & 0.00\\ 0.00 & 0.70 & 0.00\\ 0.00 & 0.70 & 0.00\\ 0.90 & 0.00 & 0.80\\ 0.90 & 0.00 & 0.80\\ 0.00 & 0.70 & 0.00\\ 0.00 & 0.70 & 0.00\\ 0.00 & 0.70 & 0.00\\ 0.90 & 0.00 & 0.80\\ 0.90 & 0.00 & 0.80\\ 0.00 & 0.70 & 0.00\\ 0.00 & 0.70 & 0.00\\ 0.00 & 0.70 & 0.00\\ 0.90 & 0.00 & 0.80\\ 0.00 & 0.70 & 0.00\\ 0.00 & 0.70 & 0.00 \end{bmatrix}. \]

k. Lapisan Linear Kedua MLP (Feed-Forward Network)

Lapisan linear kedua MLP memproyeksikan kembali hasil lapisan linear pertama dari tiga fitur menjadi dua fitur.

  • Bobot lapisan linear kedua:

\[ \mathbf{W}_2= \begin{bmatrix} 0.30 & -0.20\\ 0.20 & 0.40\\ -0.10 & 0.30 \end{bmatrix}. \]

  • Rumus:

\[ \operatorname{ReLU} \left( \operatorname{LN}(\mathbf{Z}')\mathbf{W}_1 \right) \mathbf{W}_2. \]

Hasil lapisan linear pertama setelah aktivasi ReLU berdimensi \(25\times3\) dan \(\mathbf{W}_2\) berdimensi \(3\times2\), sehingga keluaran lapisan linear kedua berdimensi \(25\times2\).

  • Contoh perhitungan untuk token pertama:

\[ \operatorname{ReLU} \left( \operatorname{LN}(\mathbf{Z}'_1)\mathbf{W}_1 \right) = \begin{bmatrix} 0.00 & 0.70 & 0.00 \end{bmatrix}. \]

Maka,

\[ \begin{aligned} \operatorname{ReLU} \left( \operatorname{LN}(\mathbf{Z}'_1)\mathbf{W}_1 \right) \mathbf{W}_2 &= \begin{bmatrix} 0.00 & 0.70 & 0.00 \end{bmatrix} \begin{bmatrix} 0.30 & -0.20\\ 0.20 & 0.40\\ -0.10 & 0.30 \end{bmatrix}\\ &= \begin{bmatrix} (0.00)(0.30)+(0.70)(0.20)+(0.00)(-0.10) & (0.00)(-0.20)+(0.70)(0.40)+(0.00)(0.30) \end{bmatrix}\\ &= \begin{bmatrix} 0.14 & 0.28 \end{bmatrix}. \end{aligned} \]

Aturan yang sama diterapkan pada seluruh token, sehingga diperoleh keluaran lapisan linear kedua MLP berikut.

\[ \operatorname{ReLU} \left( \operatorname{LN}(\mathbf{Z}')\mathbf{W}_1 \right) \mathbf{W}_2 = \begin{bmatrix} 0.14 & 0.28\\ 0.14 & 0.28\\ 0.19 & 0.06\\ 0.19 & 0.06\\ 0.14 & 0.28\\ 0.14 & 0.28\\ 0.14 & 0.28\\ 0.19 & 0.06\\ 0.19 & 0.06\\ 0.14 & 0.28\\ 0.14 & 0.28\\ 0.14 & 0.28\\ 0.19 & 0.06\\ 0.19 & 0.06\\ 0.14 & 0.28\\ 0.14 & 0.28\\ 0.14 & 0.28\\ 0.19 & 0.06\\ 0.19 & 0.06\\ 0.14 & 0.28\\ 0.14 & 0.28\\ 0.14 & 0.28\\ 0.19 & 0.06\\ 0.14 & 0.28\\ 0.14 & 0.28 \end{bmatrix}. \]

l. Residual MLP (Feed-Forward Network)

Residual MLP menggabungkan keluaran MLP dengan representasi \(\mathbf{Z}'\), yaitu keluaran dari residual attention. Operasi ini mempertahankan informasi dari tahap attention setelah MLP menambahkan transformasi fitur.

  • Rumus:

\[ \mathbf{Z} = \operatorname{ReLU} \left( \operatorname{LN}(\mathbf{Z}')\mathbf{W}_1 \right) \mathbf{W}_2 + \mathbf{Z}'. \]

Matriks \(\operatorname{ReLU}(\operatorname{LN}(\mathbf{Z}')\mathbf{W}_1)\mathbf{W}_2\) dan \(\mathbf{Z}'\) sama-sama berdimensi \(25\times2\), sehingga \(\mathbf{Z}\) berdimensi \(25\times2\).

  • Contoh perhitungan untuk token pertama:

\[ \mathbf{Z}'_1= \begin{bmatrix} -0.89 & 0.75 \end{bmatrix}, \]

\[ \operatorname{ReLU} \left( \operatorname{LN}(\mathbf{Z}'_1)\mathbf{W}_1 \right) \mathbf{W}_2 = \begin{bmatrix} 0.14 & 0.28 \end{bmatrix}. \]

Maka,

\[ \begin{aligned} \mathbf{Z}_1 &= \operatorname{ReLU} \left( \operatorname{LN}(\mathbf{Z}'_1)\mathbf{W}_1 \right) \mathbf{W}_2 + \mathbf{Z}'_1\\ &= \begin{bmatrix} 0.14 & 0.28 \end{bmatrix} + \begin{bmatrix} -0.89 & 0.75 \end{bmatrix}\\ &= \begin{bmatrix} -0.75 & 1.03 \end{bmatrix}. \end{aligned} \]

Aturan yang sama diterapkan pada seluruh token, sehingga diperoleh matriks \(\mathbf{Z}\) berikut.

\[ \mathbf{Z}=\begin{bmatrix} -0.75 & 1.03\\ -0.73 & 1.02\\ 0.81 & -0.28\\ 0.51 & -0.13\\ -0.75 & 1.04\\ -0.74 & 1.03\\ -0.71 & 1.02\\ 1.12 & -0.43\\ 0.71 & -0.23\\ -0.75 & 1.04\\ -0.74 & 1.03\\ -0.71 & 1.01\\ 1.12 & -0.43\\ 0.71 & -0.23\\ -0.75 & 1.04\\ -0.74 & 1.03\\ -0.73 & 1.03\\ 0.85 & -0.30\\ 0.49 & -0.12\\ -0.76 & 1.04\\ -0.75 & 1.04\\ -0.75 & 1.04\\ 0.35 & -0.05\\ -0.57 & 0.94\\ -0.76 & 1.04 \end{bmatrix}. \]

m. Normalisasi Keluaran Transformer

Tahap terakhir Transformer adalah normalisasi per token terhadap matriks keluaran residual MLP \(\mathbf{Z}\). Matriks hasil \(\mathbf{G}\) merupakan representasi global yang akan dilipat kembali ke bentuk spasial pada tahap berikutnya.

  • Rumus:

\[ G_{t,k} = \frac{Z_{t,k}-\mu_{Z,t}} {\sqrt{\sigma_{Z,t}^{2}+10^{-5}}}. \]

  • Contoh perhitungan untuk token pertama:

\[ \mathbf{Z}_{1}= \begin{bmatrix} -0.75 & 1.03 \end{bmatrix}. \]

Rata-rata token pertama adalah:

\[ \begin{aligned} \mu_{Z,1} &=\frac{-0.75+1.03}{2}\\ &=0.14. \end{aligned} \]

Variansnya adalah:

\[ \begin{aligned} \sigma_{Z,1}^2 &=\frac{(-0.75-0.14)^2+(1.03-0.14)^2}{2}\\ &=\frac{(-0.89)^2+(0.89)^2}{2}\\ &=0.7921. \end{aligned} \]

Elemen pertama setelah normalisasi adalah:

\[ \begin{aligned} G_{1,1} &=\frac{-0.75-0.14}{\sqrt{0.7921+10^{-5}}}\\ &=\frac{-0.89}{0.89}\\ &=-1.00. \end{aligned} \]

Dengan cara yang sama, \(G_{1,2}=1.00\). Maka:

\[ \mathbf{G}_{1}= \begin{bmatrix} -1.00 & 1.00 \end{bmatrix}. \]

Aturan yang sama diterapkan pada seluruh token, sehingga diperoleh representasi global Transformer \(\mathbf{G}\) berikut.

\[ \mathbf{G} =\begin{bmatrix} -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ -1.00 & 1.00\\ 1.00 & -1.00\\ -1.00 & 1.00\\ -1.00 & 1.00 \end{bmatrix}. \]

4. Folding, Proyeksi Fitur Global, dan Fusi Residual

Keluaran Transformer \(\mathbf{G}\) masih berbentuk matriks token berdimensi \(25\times2\). Tahap folding mengembalikan token tersebut ke susunan spasial \(5\times5\). Setelah itu, kedua kanal hasil folding diproyeksikan menjadi satu feature map global dan diaktifkan menggunakan fungsi Swish. Feature map global tersebut kemudian difusikan dengan feature map lokal \(\mathbf{L}\) dan feature map masukan \(\mathbf{X}\).

a. Folding Keluaran Transformer

Folding menempatkan kembali token ke-\(t\) pada posisi spasial \((i,j)\) berdasarkan urutan raster dari kiri ke kanan dan dari atas ke bawah:

\[ t=W(i-1)+j, \qquad W=5. \]

Kolom pertama dari matriks token \(\mathbf{G}\) dilipat menjadi kanal pertama \(\mathbf{G}_1\), sedangkan kolom kedua dilipat menjadi kanal kedua \(\mathbf{G}_2\). Kedua matriks hasil folding memiliki dimensi \(5\times5\).

  • Rumus:

\[ G_{n,i,j}=G_{t,n}, \qquad n=1,2, \qquad t=W(i-1)+j. \]

  • Contoh perhitungan pada posisi \((1,1)\):

Posisi \((1,1)\) bersesuaian dengan token pertama:

\[ \begin{aligned} t&=5(1-1)+1\\ &=1. \end{aligned} \]

Karena token pertama adalah:

\[ \mathbf{G}_{t=1}= \begin{bmatrix} -1.00 & 1.00 \end{bmatrix}, \]

maka hasil folding pada posisi \((1,1)\) adalah:

\[ G_{1,1,1}=G_{1,1}=-1.00, \qquad G_{2,1,1}=G_{1,2}=1.00. \]

Matriks kanal pertama setelah folding adalah:

\[ \mathbf{G}_1= \begin{bmatrix} -1.00 & -1.00 & 1.00 & 1.00 & -1.00\\ -1.00 & -1.00 & 1.00 & 1.00 & -1.00\\ -1.00 & -1.00 & 1.00 & 1.00 & -1.00\\ -1.00 & -1.00 & 1.00 & 1.00 & -1.00\\ -1.00 & -1.00 & 1.00 & -1.00 & -1.00 \end{bmatrix}. \]

Matriks kanal kedua setelah folding adalah:

\[ \mathbf{G}_2= \begin{bmatrix} 1.00 & 1.00 & -1.00 & -1.00 & 1.00\\ 1.00 & 1.00 & -1.00 & -1.00 & 1.00\\ 1.00 & 1.00 & -1.00 & -1.00 & 1.00\\ 1.00 & 1.00 & -1.00 & -1.00 & 1.00\\ 1.00 & 1.00 & -1.00 & 1.00 & 1.00 \end{bmatrix}. \]

b. Proyeksi dan Aktivasi Fitur Global

Kedua kanal hasil folding, yaitu \(\mathbf{G}_1\) dan \(\mathbf{G}_2\), diproyeksikan menjadi satu feature map global menggunakan pointwise convolution \(1\times1\). Pada ilustrasi ini, bias tidak digunakan. Bobot pointwise convolution untuk proyeksi global ditetapkan sebagai:

\[ \mathbf{W}_{\mathrm{pw}}^{(\mathrm{glob})} = \begin{bmatrix} 0.60 & -0.40 \end{bmatrix}. \]

  • Rumus:

\[ F_{\mathrm{pw},i,j,1}^{(\mathrm{glob})} = \sum_{n=1}^{2} W_{\mathrm{pw},n,1}^{(\mathrm{glob})} G_{n,i,j}. \]

Berdasarkan bobot yang digunakan, diperoleh:

\[ F_{\mathrm{pw},i,j,1}^{(\mathrm{glob})} = 0.60G_{1,i,j}-0.40G_{2,i,j}. \]

Keluaran proyeksi kemudian diaktifkan menggunakan fungsi Swish:

\[ \begin{aligned} G_{\mathrm{global},i,j} &= \operatorname{Swish} \left( F_{\mathrm{pw},i,j,1}^{(\mathrm{glob})} \right)\\ &= \frac{F_{\mathrm{pw},i,j,1}^{(\mathrm{glob})}} {1+e^{-F_{\mathrm{pw},i,j,1}^{(\mathrm{glob})}}}. \end{aligned} \]

Matriks \(\mathbf{F}_{\mathrm{pw}}^{(\mathrm{glob})}\) dan \(\mathbf{G}_{\mathrm{global}}\) keduanya berdimensi \(5\times5\).

  • Contoh perhitungan pada posisi \((1,1)\):

Diketahui:

\[ G_{1,1,1}=-1.00, \qquad G_{2,1,1}=1.00. \]

Nilai hasil pointwise convolution sebelum aktivasi adalah:

\[ \begin{aligned} F_{\mathrm{pw},1,1,1}^{(\mathrm{glob})} &= 0.60G_{1,1,1}-0.40G_{2,1,1}\\ &= 0.60(-1.00)-0.40(1.00)\\ &= -0.60-0.40\\ &= -1.00. \end{aligned} \]

Selanjutnya, nilai tersebut diaktifkan menggunakan fungsi Swish:

\[ \begin{aligned} G_{\mathrm{global},1,1} &= \frac{F_{\mathrm{pw},1,1,1}^{(\mathrm{glob})}} {1+e^{-F_{\mathrm{pw},1,1,1}^{(\mathrm{glob})}}}\\ &= \frac{-1.00}{1+e^{-(-1.00)}}\\ &= \frac{-1.00}{1+e^{1.00}}\\ &= \frac{-1.00}{1+2.72}\\ &= -0.27. \end{aligned} \]

Dengan perhitungan yang sama untuk seluruh posisi, diperoleh feature map global:

\[ \mathbf{G}_{\mathrm{global}}= \begin{bmatrix} -0.27 & -0.27 & 0.73 & 0.73 & -0.27\\ -0.27 & -0.27 & 0.73 & 0.73 & -0.27\\ -0.27 & -0.27 & 0.73 & 0.73 & -0.27\\ -0.27 & -0.27 & 0.73 & 0.73 & -0.27\\ -0.27 & -0.27 & 0.73 & -0.27 & -0.27 \end{bmatrix}. \]

c. Fusi Residual Fitur Lokal dan Global

Feature map masukan \(\mathbf{X}\), fitur lokal \(\mathbf{L}\), dan feature map global \(\mathbf{G}_{\mathrm{global}}\) digabungkan melalui fusi residual. Pada ilustrasi ini, pointwise convolution \(1\times1\) memproyeksikan fitur lokal dan fitur global menjadi satu kanal, kemudian hasilnya ditambahkan dengan fitur masukan \(\mathbf{X}\).

  • Bobot fusi:

\[ \mathbf{W}_{\mathrm{pw}}^{(\mathrm{fuse})} = \begin{bmatrix} 0.50 & 0.50 \end{bmatrix}. \]

  • Rumus:

\[ F_{\mathrm{pw},i,j,1}^{(\mathrm{fuse})} = 0.50L_{i,j} + 0.50G_{\mathrm{global},i,j}. \]

\[ X_{i,j}^{(0,0)} = X_{i,j} + F_{\mathrm{pw},i,j,1}^{(\mathrm{fuse})}. \]

Secara keseluruhan, proses fusi residual dirumuskan sebagai:

\[ \mathbf{X}^{(0,0)} = \mathbf{X} + \operatorname{Conv}_{1\times1}^{(\mathrm{fuse})} \left( \operatorname{Concat} \left[ \mathbf{L}, \mathbf{G}_{\mathrm{global}} \right] \right). \]

Seluruh matriks pada operasi tersebut berdimensi \(5\times5\), sehingga hasil fusi \(\mathbf{X}^{(0,0)}\) juga berdimensi \(5\times5\).

  • Contoh perhitungan pada posisi \((1,1)\):

Diketahui:

\[ X_{1,1}=-2.12, \qquad L_{1,1}=-0.27, \qquad G_{\mathrm{global},1,1}=-0.27. \]

Nilai keluaran pointwise convolution adalah:

\[ \begin{aligned} F_{\mathrm{pw},1,1,1}^{(\mathrm{fuse})} &= 0.50L_{1,1} + 0.50G_{\mathrm{global},1,1}\\ &= 0.50(-0.27) + 0.50(-0.27)\\ &= -0.135-0.135\\ &= -0.27. \end{aligned} \]

Maka, hasil fusi residual pada posisi \((1,1)\) adalah:

\[ \begin{aligned} X_{1,1}^{(0,0)} &= X_{1,1} + F_{\mathrm{pw},1,1,1}^{(\mathrm{fuse})}\\ &= -2.12+(-0.27)\\ &= -2.39. \end{aligned} \]

Aturan yang sama diterapkan pada seluruh posisi. Dengan menggunakan nilai \(\mathbf{G}_{\mathrm{global}}\) yang telah dibulatkan hingga dua angka di belakang koma, diperoleh feature map hasil fusi berikut:

\[ \mathbf{X}^{(0,0)} = \begin{bmatrix} -2.39 & -1.28 & 1.82 & 1.12 & -1.84\\ -2.38 & -1.00 & 2.24 & 1.50 & -1.70\\ -2.38 & -1.00 & 2.24 & 1.50 & -1.70\\ -2.38 & -1.14 & 1.84 & 1.11 & -1.85\\ -2.25 & -1.57 & 0.77 & -0.38 & -1.99 \end{bmatrix}. \]

5. Encoder Bertingkat

a. Downsampling Encoder Pertama (\(\mathbf{X}^{1,0}\))

Feature map masukan \(\mathbf{X}^{0,0}\) berukuran \(5\times5\) diproses menggunakan strided convolution dengan kernel \(3\times3\), stride \(2\), zero padding sebesar \(1\) pada setiap sisi, dan tanpa bias untuk menghasilkan feature map \(\mathbf{X}^{1,0}\).

Matriks feature map masukan yang digunakan adalah:

\[ \mathbf{X}^{0,0} = \begin{bmatrix} -2.39 & -1.28 & 1.82 & 1.12 & -1.84\\ -2.38 & -1.00 & 2.24 & 1.50 & -1.70\\ -2.38 & -1.00 & 2.24 & 1.50 & -1.70\\ -2.38 & -1.14 & 1.84 & 1.11 & -1.85\\ -2.25 & -1.57 & 0.77 & -0.38 & -1.99 \end{bmatrix}. \]

Ukuran keluaran strided convolution dihitung menggunakan:

\[ o = \left\lfloor \frac{i+2p-k}{s} \right\rfloor+1, \]

dengan \(i\) menyatakan ukuran spasial masukan, \(p\) merupakan jumlah padding pada setiap sisi, \(k\) merupakan ukuran kernel, dan \(s\) merupakan stride.

Pada ilustrasi ini, digunakan \(i=5\), \(k=3\), \(p=1\), dan \(s=2\), sehingga:

\[ \begin{aligned} o &= \left\lfloor \frac{5+2(1)-3}{2} \right\rfloor+1\\ &= \left\lfloor \frac{4}{2} \right\rfloor+1\\ &=3. \end{aligned} \]

Dengan demikian, ukuran spasial feature map berkurang dari \(5\times5\) menjadi \(3\times3\).

  • Penambahan Zero Padding:

Sebelum operasi konvolusi dilakukan, satu lapisan nilai nol ditambahkan pada keempat sisi matriks masukan, yaitu sisi atas, bawah, kiri, dan kanan. Penambahan padding ini mengubah ukuran matriks dari \(5\times5\) menjadi \(7\times7\).

Matriks setelah penambahan zero padding adalah:

\[ \mathbf{X}_{\mathrm{pad}}^{0,0} = \begin{bmatrix} 0.00 & 0.00 & 0.00 & 0.00 & 0.00 & 0.00 & 0.00\\ 0.00 & -2.39 & -1.28 & 1.82 & 1.12 & -1.84 & 0.00\\ 0.00 & -2.38 & -1.00 & 2.24 & 1.50 & -1.70 & 0.00\\ 0.00 & -2.38 & -1.00 & 2.24 & 1.50 & -1.70 & 0.00\\ 0.00 & -2.38 & -1.14 & 1.84 & 1.11 & -1.85 & 0.00\\ 0.00 & -2.25 & -1.57 & 0.77 & -0.38 & -1.99 & 0.00\\ 0.00 & 0.00 & 0.00 & 0.00 & 0.00 & 0.00 & 0.00 \end{bmatrix}. \]

  • Kernel Encoder Pertama:

Pada ilustrasi ini, matriks bobot kernel encoder pertama ditetapkan sebagai:

\[ \mathbf{W}_{\mathrm{enc}}^{(1)} = \begin{bmatrix} 0.00 & 0.00 & 0.00\\ 0.00 & 1.00 & 0.00\\ 0.00 & 0.00 & 0.00 \end{bmatrix}. \]

Kernel tersebut memiliki satu bobot bernilai \(1.00\) pada posisi tengah, sedangkan delapan bobot lainnya bernilai \(0.00\). Oleh karena itu, setiap hasil konvolusi diperoleh melalui perkalian sembilan elemen pada area feature map dengan sembilan bobot kernel, kemudian seluruh hasil perkalian dijumlahkan.

  • Rumus:

Operasi strided convolution dirumuskan sebagai:

\[ \mathbf{X}^{1,0} = \operatorname{Conv}_{3\times3,\,s=2,\,p=1} \left( \mathbf{X}^{0,0}; \mathbf{W}_{\mathrm{enc}}^{(1)} \right). \]

Untuk elemen keluaran pada baris ke-\(r\) dan kolom ke-\(c\), perhitungan konvolusi dapat dinyatakan sebagai:

\[ X_{r,c}^{1,0} = \sum_{a=1}^{3} \sum_{b=1}^{3} W_{\mathrm{enc},a,b}^{(1)} X_{\mathrm{pad},\,2r+a-2,\,2c+b-2}^{0,0}, \]

dengan \(r,c=1,2,3\), sedangkan \(a\) dan \(b\) merupakan indeks baris dan kolom kernel.

Pada setiap posisi, kernel mencakup area berukuran \(3\times3\). Karena stride bernilai \(2\), kernel bergeser dua kolom ke kanan untuk menghitung elemen berikutnya pada baris keluaran yang sama. Setelah mencapai posisi terakhir pada baris tersebut, kernel kembali ke sisi kiri dan bergeser dua baris ke bawah.

  • Contoh Perhitungan Konvolusi:

1. Perhitungan elemen pada posisi \((1,1)\)

Untuk menghasilkan elemen pertama \(\mathbf{X}^{1,0}\), kernel ditempatkan pada area \(3\times3\) di pojok kiri atas matriks yang telah diberi padding.

Area feature map yang diproses adalah:

\[ \begin{bmatrix} 0.00 & 0.00 & 0.00\\ 0.00 & -2.39 & -1.28\\ 0.00 & -2.38 & -1.00 \end{bmatrix}. \]

Area tersebut dikalikan secara elemen demi elemen dengan bobot kernel \(\mathbf{W}_{\mathrm{enc}}^{(1)}\), kemudian hasilnya dijumlahkan sebagai berikut:

\[ \begin{aligned} X_{1,1}^{1,0} ={}& (0.00)(0.00) +(0.00)(0.00) +(0.00)(0.00)\\ &+(0.00)(0.00) +(-2.39)(1.00) +(-1.28)(0.00)\\ &+(0.00)(0.00) +(-2.38)(0.00) +(-1.00)(0.00)\\ ={}&-2.39. \end{aligned} \]

Dengan demikian, elemen pertama pada feature map keluaran adalah \(X_{1,1}^{1,0}=-2.39\).

2. Perhitungan elemen pada posisi \((1,2)\)

Untuk menghitung elemen pada posisi \((1,2)\), kernel bergeser dua kolom ke kanan dari posisi sebelumnya karena stride yang digunakan adalah \(2\).

Area feature map yang diproses menjadi:

\[ \begin{bmatrix} 0.00 & 0.00 & 0.00\\ -1.28 & 1.82 & 1.12\\ -1.00 & 2.24 & 1.50 \end{bmatrix}. \]

Perhitungan konvolusi dilakukan menggunakan bobot kernel yang sama:

\[ \begin{aligned} X_{1,2}^{1,0} ={}& (0.00)(0.00) +(0.00)(0.00) +(0.00)(0.00)\\ &+(-1.28)(0.00) +(1.82)(1.00) +(1.12)(0.00)\\ &+(-1.00)(0.00) +(2.24)(0.00) +(1.50)(0.00)\\ ={}&1.82. \end{aligned} \]

Dengan demikian, elemen pada posisi \((1,2)\) dari feature map keluaran adalah \(X_{1,2}^{1,0}=1.82\).

Prosedur yang sama diterapkan pada seluruh posisi kernel. Karena hanya bobot tengah kernel yang bernilai \(1.00\), nilai keluaran pada setiap posisi sama dengan nilai elemen tengah dari area feature map yang sedang diproses. Hal tersebut merupakan konsekuensi dari bobot kernel yang ditetapkan pada ilustrasi ini, bukan karakteristik umum dari seluruh operasi konvolusi.

Setelah seluruh sembilan posisi konvolusi dihitung, diperoleh feature map keluaran berukuran \(3\times3\) sebagai berikut:

\[ \mathbf{X}^{1,0} = \begin{bmatrix} -2.39 & 1.82 & -1.84\\ -2.38 & 2.24 & -1.70\\ -2.25 & 0.77 & -1.99 \end{bmatrix}. \]

Hasil tersebut menunjukkan bahwa operasi strided convolution mengurangi ukuran spasial feature map dari \(5\times5\) menjadi \(3\times3\). Pada ilustrasi ini, nilai keluaran ditentukan oleh elemen tengah pada setiap area konvolusi karena bobot kernel lainnya bernilai nol.

b. Downsampling Encoder Kedua (\(\mathbf{X}^{2,0}\))

Feature map \(\mathbf{X}^{1,0}\) berukuran \(3\times3\) diproses kembali menggunakan strided convolution dengan kernel \(3\times3\), stride \(2\), zero padding sebesar \(1\) pada setiap sisi, dan tanpa bias untuk menghasilkan feature map \(\mathbf{X}^{2,0}\).

Matriks feature map masukan yang diperoleh dari tahap downsampling encoder pertama adalah:

\[ \mathbf{X}^{1,0} = \begin{bmatrix} -2.39 & 1.82 & -1.84\\ -2.38 & 2.24 & -1.70\\ -2.25 & 0.77 & -1.99 \end{bmatrix}. \]

Ukuran keluaran strided convolution dihitung menggunakan:

\[ o = \left\lfloor \frac{i+2p-k}{s} \right\rfloor+1, \]

dengan \(i\) menyatakan ukuran spasial masukan, \(p\) merupakan jumlah padding pada setiap sisi, \(k\) merupakan ukuran kernel, dan \(s\) merupakan stride.

Pada ilustrasi ini, digunakan \(i=3\), \(k=3\), \(p=1\), dan \(s=2\), sehingga:

\[ \begin{aligned} o &= \left\lfloor \frac{3+2(1)-3}{2} \right\rfloor+1\\ &= \left\lfloor \frac{2}{2} \right\rfloor+1\\ &=2. \end{aligned} \]

Dengan demikian, ukuran spasial feature map berkurang dari \(3\times3\) menjadi \(2\times2\).

  • Penambahan Zero Padding:

Sebelum operasi konvolusi dilakukan, satu lapisan nilai nol ditambahkan pada keempat sisi matriks masukan, yaitu sisi atas, bawah, kiri, dan kanan. Penambahan padding ini mengubah ukuran matriks dari \(3\times3\) menjadi \(5\times5\).

Matriks setelah penambahan zero padding adalah:

\[ \mathbf{X}_{\mathrm{pad}}^{1,0} = \begin{bmatrix} 0.00 & 0.00 & 0.00 & 0.00 & 0.00\\ 0.00 & -2.39 & 1.82 & -1.84 & 0.00\\ 0.00 & -2.38 & 2.24 & -1.70 & 0.00\\ 0.00 & -2.25 & 0.77 & -1.99 & 0.00\\ 0.00 & 0.00 & 0.00 & 0.00 & 0.00 \end{bmatrix}. \]

  • Kernel Encoder Kedua:

Pada ilustrasi ini, matriks bobot kernel encoder kedua ditetapkan sebagai:

\[ \mathbf{W}_{\mathrm{enc}}^{(2)} = \begin{bmatrix} 0.00 & 0.00 & 0.00\\ 0.00 & 1.00 & 0.00\\ 0.00 & 0.00 & 0.00 \end{bmatrix}. \]

Kernel tersebut memiliki satu bobot bernilai \(1.00\) pada posisi tengah, sedangkan delapan bobot lainnya bernilai \(0.00\). Oleh karena itu, setiap hasil konvolusi diperoleh melalui perkalian sembilan elemen pada area feature map dengan sembilan bobot kernel, kemudian seluruh hasil perkalian dijumlahkan.

  • Rumus:

Operasi strided convolution pada encoder kedua dirumuskan sebagai:

\[ \mathbf{X}^{2,0} = \operatorname{Conv}_{3\times3,\,s=2,\,p=1} \left( \mathbf{X}^{1,0}; \mathbf{W}_{\mathrm{enc}}^{(2)} \right). \]

Untuk elemen keluaran pada baris ke-\(r\) dan kolom ke-\(c\), perhitungan konvolusi dapat dinyatakan sebagai:

\[ X_{r,c}^{2,0} = \sum_{a=1}^{3} \sum_{b=1}^{3} W_{\mathrm{enc},a,b}^{(2)} X_{\mathrm{pad},\,2r+a-2,\,2c+b-2}^{1,0}, \]

dengan \(r,c=1,2\), sedangkan \(a\) dan \(b\) merupakan indeks baris dan kolom kernel.

Pada setiap posisi, kernel mencakup area berukuran \(3\times3\). Karena stride bernilai \(2\), kernel bergeser dua kolom ke kanan untuk menghitung elemen berikutnya pada baris keluaran yang sama. Setelah mencapai posisi terakhir pada baris tersebut, kernel kembali ke sisi kiri dan bergeser dua baris ke bawah.

  • Contoh Perhitungan Konvolusi:

1. Perhitungan elemen pada posisi \((1,1)\)

Untuk menghasilkan elemen pertama \(\mathbf{X}^{2,0}\), kernel ditempatkan pada area \(3\times3\) di pojok kiri atas matriks yang telah diberi padding.

Area feature map yang diproses adalah:

\[ \begin{bmatrix} 0.00 & 0.00 & 0.00\\ 0.00 & -2.39 & 1.82\\ 0.00 & -2.38 & 2.24 \end{bmatrix}. \]

Area tersebut dikalikan secara elemen demi elemen dengan bobot kernel \(\mathbf{W}_{\mathrm{enc}}^{(2)}\), kemudian seluruh hasil perkalian dijumlahkan sebagai berikut:

\[ \begin{aligned} X_{1,1}^{2,0} ={}& (0.00)(0.00) +(0.00)(0.00) +(0.00)(0.00)\\ &+(0.00)(0.00) +(-2.39)(1.00) +(1.82)(0.00)\\ &+(0.00)(0.00) +(-2.38)(0.00) +(2.24)(0.00)\\ ={}&-2.39. \end{aligned} \]

Dengan demikian, elemen pertama pada feature map keluaran adalah \(X_{1,1}^{2,0}=-2.39\).

2. Perhitungan elemen pada posisi \((1,2)\)

Untuk menghitung elemen pada posisi \((1,2)\), kernel bergeser dua kolom ke kanan dari posisi sebelumnya karena stride yang digunakan adalah \(2\).

Area feature map yang diproses menjadi:

\[ \begin{bmatrix} 0.00 & 0.00 & 0.00\\ 1.82 & -1.84 & 0.00\\ 2.24 & -1.70 & 0.00 \end{bmatrix}. \]

Perhitungan konvolusi dilakukan menggunakan bobot kernel yang sama:

\[ \begin{aligned} X_{1,2}^{2,0} ={}& (0.00)(0.00) +(0.00)(0.00) +(0.00)(0.00)\\ &+(1.82)(0.00) +(-1.84)(1.00) +(0.00)(0.00)\\ &+(2.24)(0.00) +(-1.70)(0.00) +(0.00)(0.00)\\ ={}&-1.84. \end{aligned} \]

Dengan demikian, elemen pada posisi \((1,2)\) dari feature map keluaran adalah \(X_{1,2}^{2,0}=-1.84\).

Prosedur yang sama diterapkan pada seluruh posisi kernel. Karena hanya bobot tengah kernel yang bernilai \(1.00\), nilai keluaran pada setiap posisi sama dengan nilai elemen tengah dari area feature map yang sedang diproses. Hal tersebut merupakan konsekuensi dari bobot kernel yang ditetapkan pada ilustrasi ini, bukan karakteristik umum dari seluruh operasi konvolusi.

Setelah seluruh empat posisi konvolusi dihitung, diperoleh feature map keluaran berukuran \(2\times2\) sebagai berikut:

\[ \mathbf{X}^{2,0} = \begin{bmatrix} -2.39 & -1.84\\ -2.25 & -1.99 \end{bmatrix}. \]

Hasil tersebut menunjukkan bahwa operasi strided convolution pada encoder kedua mengurangi ukuran spasial feature map dari \(3\times3\) menjadi \(2\times2\). Pada ilustrasi ini, nilai keluaran ditentukan oleh elemen tengah pada setiap area konvolusi karena bobot kernel lainnya bernilai nol.

6. Decoder UNet++

Pada tahap ini, decoder UNet++ mengembalikan resolusi spasial feature map secara bertahap melalui operasi Upsampling. Pada ilustrasi ini, \(\operatorname{Up}(\cdot)\) menyatakan Upsampling menggunakan interpolasi bilinear. Operasi tersebut memperbesar ukuran spasial feature map dengan menghitung nilai pada posisi keluaran berdasarkan jarak terhadap elemen masukan di sekitarnya.

Pada setiap node decoder, feature map hasil Upsampling digabungkan dengan feature map dari jalur encoder atau node decoder sebelumnya melalui nested skip connection. Penggabungan dilakukan menggunakan concatenation (Concat) pada dimensi kanal, kemudian dilanjutkan dengan konvolusi \(1\times1\) dan fungsi aktivasi ReLU.

Untuk mempermudah ilustrasi perhitungan manual, operasi konvolusi pada node decoder disederhanakan menjadi satu konvolusi \(1\times1\) tanpa bias. Bobot kernel ditentukan secara ilustratif dan tidak merepresentasikan bobot hasil pelatihan model. Penyederhanaan ini digunakan untuk menjelaskan mekanisme penggabungan fitur, bukan keseluruhan blok konvolusi pada implementasi UNet++.

Dengan demikian, pembentukan node decoder pada ilustrasi ini dinyatakan sebagai:

\[ \begin{aligned} \mathbf{X}^{1,1} &= \operatorname{ReLU} \left( \operatorname{Conv}_{1\times1}^{(1,1)} \left( \operatorname{Concat} \left[ \mathbf{X}^{1,0}, \operatorname{Up}(\mathbf{X}^{2,0}) \right] \right) \right),\\[6pt] \mathbf{X}^{0,1} &= \operatorname{ReLU} \left( \operatorname{Conv}_{1\times1}^{(0,1)} \left( \operatorname{Concat} \left[ \mathbf{X}^{0,0}, \operatorname{Up}(\mathbf{X}^{1,0}) \right] \right) \right),\\[6pt] \mathbf{X}^{0,2} &= \operatorname{ReLU} \left( \operatorname{Conv}_{1\times1}^{(0,2)} \left( \operatorname{Concat} \left[ \mathbf{X}^{0,0}, \mathbf{X}^{0,1}, \operatorname{Up}(\mathbf{X}^{1,1}) \right] \right) \right). \end{aligned} \]

Pada node \(\mathbf{X}^{1,1}\) dan \(\mathbf{X}^{0,1}\), masing-masing kanal masukan diberi bobot ilustratif \(1.00\). Sementara itu, pada node \(\mathbf{X}^{0,2}\), tiga kanal masukan diberi bobot ilustratif \(0.25\), \(0.50\), dan \(0.25\). Bobot tersebut digunakan untuk mempertahankan mekanisme penggabungan fitur yang telah ditetapkan dalam ilustrasi sebelumnya.

a. Upsampling \(\mathbf{X}^{2,0}\) dan Node Decoder \(\mathbf{X}^{1,1}\)

Feature map \(\mathbf{X}^{2,0}\) berukuran \(2\times2\), yang diperoleh dari tahap encoder sebelumnya, diperbesar menjadi \(3\times3\) menggunakan interpolasi bilinear. Proses ini bertujuan untuk menyesuaikan ukuran spasial feature map sehingga dapat digabungkan dengan feature map \(\mathbf{X}^{1,0}\) dari jalur encoder melalui nested skip connection.

Matriks feature map masukan adalah:

\[ \mathbf{X}^{2,0} = \begin{bmatrix} -2.39 & -1.84\\ -2.25 & -1.99 \end{bmatrix}. \]

  • Rumus interpolasi bilinear:

Interpolasi bilinear menentukan nilai keluaran berdasarkan jarak terhadap elemen-elemen pada feature map masukan. Elemen yang lebih dekat dengan posisi keluaran memiliki bobot lebih besar, sedangkan elemen yang berjarak satu satuan atau lebih pada salah satu arah memiliki bobot nol.

Pada feature map satu kanal, interpolasi bilinear dinyatakan sebagai:

\[ \left[ \operatorname{Up} \left( \mathbf{X}^{2,0} \right) \right]_{r,c} = \sum_{n=1}^{2} \sum_{m=1}^{2} X_{n,m}^{2,0} \max \left( 0, 1-\left|x_c-m\right| \right) \max \left( 0, 1-\left|y_r-n\right| \right). \]

Pada persamaan tersebut, \(r\) dan \(c\) menyatakan indeks baris dan kolom pada feature map keluaran, sedangkan \(n\) dan \(m\) menyatakan indeks baris dan kolom pada feature map masukan. Koordinat \(x_c\) menunjukkan posisi horizontal atau arah kolom, sedangkan \(y_r\) menunjukkan posisi vertikal atau arah baris.

Untuk mempermudah penjabaran, bobot interpolasi pada setiap elemen masukan dinotasikan sebagai:

\[ w_{n,m}^{(r,c)} = \max \left( 0, 1-\left|x_c-m\right| \right) \max \left( 0, 1-\left|y_r-n\right| \right). \]

Dengan demikian, rumus interpolasi bilinear dapat dituliskan sebagai:

\[ \left[ \operatorname{Up} \left( \mathbf{X}^{2,0} \right) \right]_{r,c} = \sum_{n=1}^{2} \sum_{m=1}^{2} w_{n,m}^{(r,c)}X_{n,m}^{2,0}. \]

  • Penentuan koordinat interpolasi:

Pada ilustrasi ini, koordinat matriks masukan menggunakan indeks yang dimulai dari \(1\). Karena ukuran feature map masukan adalah \(2\times2\) dan ukuran keluaran adalah \(3\times3\), koordinat interpolasi ditentukan sebagai:

\[ x_c = 1+(c-1)\frac{2-1}{3-1} = 1+\frac{c-1}{2}, \]

\[ y_r = 1+(r-1)\frac{2-1}{3-1} = 1+\frac{r-1}{2}, \]

dengan \(r,c=1,2,3\).

Angka \(1\) menunjukkan koordinat awal karena indeks matriks dimulai dari \(1\), sedangkan pembagian dengan \(2\) menunjukkan bahwa jarak antara dua koordinat masukan dibagi menjadi dua interval yang sama panjang.

Nilai koordinat yang diperoleh adalah:

Indeks keluaran Nilai koordinat
\(1\) \(1\)
\(2\) \(1.5\)
\(3\) \(2\)

Dengan demikian, koordinat interpolasi pada matriks keluaran dapat dituliskan sebagai:

\[ \begin{bmatrix} (1,1) & (1,1.5) & (1,2)\\ (1.5,1) & (1.5,1.5) & (1.5,2)\\ (2,1) & (2,1.5) & (2,2) \end{bmatrix}. \]

Setiap pasangan koordinat dituliskan dalam urutan \((y_r,x_c)\). Pada posisi sudut, nilai keluaran sama dengan nilai masukan karena koordinatnya berimpit. Sementara itu, posisi tengah sisi diperoleh dari dua elemen masukan, sedangkan posisi tengah matriks diperoleh dari empat elemen masukan.

  • Contoh perhitungan interpolasi bilinear pada posisi \((1,2)\):

Pada posisi \((1,2)\), koordinat interpolasi diperoleh sebagai berikut:

\[ y_1=1, \qquad x_2=1.5. \]

Posisi tersebut berada tepat di tengah antara kolom pertama dan kolom kedua pada baris pertama. Bobot interpolasi untuk elemen \(X_{1,1}^{2,0}\) dihitung sebagai:

\[ \begin{aligned} w_{1,1}^{(1,2)} &= \max(0,1-|1.5-1|) \max(0,1-|1-1|)\\ &= 0.5\times1\\ &= 0.5. \end{aligned} \]

Sementara itu, bobot untuk elemen \(X_{1,2}^{2,0}\) adalah:

\[ \begin{aligned} w_{1,2}^{(1,2)} &= \max(0,1-|1.5-2|) \max(0,1-|1-1|)\\ &= 0.5\times1\\ &= 0.5. \end{aligned} \]

Kedua elemen pada baris kedua memiliki bobot nol karena jarak vertikalnya terhadap posisi keluaran adalah satu satuan. Dengan demikian:

\[ w_{1,1}^{(1,2)} = w_{1,2}^{(1,2)} = 0.5, \qquad w_{2,1}^{(1,2)} = w_{2,2}^{(1,2)} = 0. \]

Dengan memasukkan bobot tersebut ke dalam rumus interpolasi bilinear, diperoleh:

\[ \begin{aligned} \left[ \operatorname{Up} \left( \mathbf{X}^{2,0} \right) \right]_{1,2} &= 0.5X_{1,1}^{2,0} + 0.5X_{1,2}^{2,0}\\ &= \frac{ X_{1,1}^{2,0} + X_{1,2}^{2,0} }{2}\\ &= \frac{-2.39-1.84}{2}\\ &= -2.115\\ & -2.12. \end{aligned} \]

  • Contoh perhitungan interpolasi bilinear pada posisi tengah \((2,2)\):

Pada posisi \((2,2)\), koordinat interpolasi diperoleh sebagai berikut:

\[ y_2=1.5, \qquad x_2=1.5. \]

Posisi tersebut berada tepat di tengah empat elemen matriks masukan. Bobot interpolasi untuk elemen \(X_{1,1}^{2,0}\) dihitung sebagai:

\[ \begin{aligned} w_{1,1}^{(2,2)} &= \max(0,1-|1.5-1|) \max(0,1-|1.5-1|)\\ &= 0.5\times0.5\\ &= 0.25. \end{aligned} \]

Karena posisi tengah berjarak sama dari keempat elemen masukan, maka:

\[ w_{1,1}^{(2,2)} = w_{1,2}^{(2,2)} = w_{2,1}^{(2,2)} = w_{2,2}^{(2,2)} = 0.25. \]

Dengan demikian, rumus interpolasi bilinear menjadi:

\[ \begin{aligned} \left[ \operatorname{Up} \left( \mathbf{X}^{2,0} \right) \right]_{2,2} &= 0.25X_{1,1}^{2,0} + 0.25X_{1,2}^{2,0}\\ &\quad+ 0.25X_{2,1}^{2,0} + 0.25X_{2,2}^{2,0}\\ &= \frac{ X_{1,1}^{2,0} + X_{1,2}^{2,0} + X_{2,1}^{2,0} + X_{2,2}^{2,0} }{4}\\ &= \frac{-2.39-1.84-2.25-1.99}{4}\\ &= -2.1175\\ & -2.12. \end{aligned} \]

Dengan menerapkan interpolasi bilinear pada seluruh posisi keluaran, diperoleh feature map hasil Upsampling berukuran \(3\times3\), yaitu:

\[ \operatorname{Up} \left( \mathbf{X}^{2,0} \right) = \begin{bmatrix} -2.39 & -2.12 & -1.84\\ -2.32 & -2.12 & -1.92\\ -2.25 & -2.12 & -1.99 \end{bmatrix}. \]

Hasil tersebut menunjukkan bahwa interpolasi bilinear mempertahankan nilai pada posisi sudut dan menghitung nilai pada posisi lainnya berdasarkan bobot jarak terhadap elemen masukan. Nilai hasil interpolasi ditampilkan hingga dua angka desimal.

  • Rumus node decoder:

Sesuai dengan persamaan UNet++, nested skip connection pada node decoder pertama dirumuskan sebagai:

\[ \mathbf{X}^{1,1} = H^{(1,1)} \left( \operatorname{Concat} \left[ \mathbf{X}^{1,0}, \operatorname{Up} \left( \mathbf{X}^{2,0} \right) \right] \right). \]

Pada persamaan tersebut, \(H^{(1,1)}\) menyatakan operasi pengolahan fitur pada node decoder \(\mathbf{X}^{1,1}\). Dalam ilustrasi perhitungan manual ini, operasi tersebut disederhanakan menggunakan konvolusi \(1\times1\) tanpa bias yang diikuti fungsi aktivasi ReLU.

Karena kedua feature map yang digabungkan berukuran \(3\times3\) dan masing-masing direpresentasikan oleh satu kanal, hasil Concat memiliki dua kanal. Satu filter konvolusi \(1\times1\) digunakan untuk menggabungkan kedua kanal tersebut menjadi satu kanal keluaran.

Pada ilustrasi ini, bobot kernel ditentukan sebagai:

\[ W_{\mathrm{dec},1}^{(1,1)}=[1.00], \qquad W_{\mathrm{dec},2}^{(1,1)}=[1.00]. \]

Bobot pertama diterapkan pada \(\mathbf{X}^{1,0}\), sedangkan bobot kedua diterapkan pada \(\operatorname{Up}(\mathbf{X}^{2,0})\).

Dengan demikian, untuk setiap posisi spasial \((r,c)\), keluaran node decoder dihitung sebagai:

\[ X_{r,c}^{1,1} = \operatorname{ReLU} \left( W_{\mathrm{dec},1}^{(1,1)}X_{r,c}^{1,0} + W_{\mathrm{dec},2}^{(1,1)} \left[ \operatorname{Up} \left( \mathbf{X}^{2,0} \right) \right]_{r,c} \right). \]

  • Contoh perhitungan node decoder pada posisi \((1,1)\):

\[ \begin{aligned} X_{1,1}^{1,1} &= \operatorname{ReLU} \left( W_{\mathrm{dec},1}^{(1,1)}X_{1,1}^{1,0} + W_{\mathrm{dec},2}^{(1,1)} \left[ \operatorname{Up} \left( \mathbf{X}^{2,0} \right) \right]_{1,1} \right)\\ &= \operatorname{ReLU} \left( 1.00(-2.39)+1.00(-2.39) \right)\\ &= \operatorname{ReLU}(-4.78)\\ &= 0.00. \end{aligned} \]

  • Contoh perhitungan node decoder pada posisi tengah \((2,2)\):

\[ \begin{aligned} X_{2,2}^{1,1} &= \operatorname{ReLU} \left( W_{\mathrm{dec},1}^{(1,1)}X_{2,2}^{1,0} + W_{\mathrm{dec},2}^{(1,1)} \left[ \operatorname{Up} \left( \mathbf{X}^{2,0} \right) \right]_{2,2} \right)\\ &= \operatorname{ReLU} \left( 1.00(2.24)+1.00(-2.12) \right)\\ &= \operatorname{ReLU}(0.12)\\ &= 0.12. \end{aligned} \]

Dengan menerapkan operasi yang sama pada seluruh posisi spasial, diperoleh feature map node decoder pertama sebagai berikut:

\[ \mathbf{X}^{1,1} = \begin{bmatrix} 0.00 & 0.00 & 0.00\\ 0.00 & 0.12 & 0.00\\ 0.00 & 0.00 & 0.00 \end{bmatrix}. \]

Hasil tersebut menunjukkan bahwa feature map hasil Upsampling dapat digabungkan dengan feature map dari jalur encoder melalui nested skip connection. Pada ilustrasi ini, penggabungan dilakukan menggunakan Concat, konvolusi \(1\times1\), dan fungsi aktivasi ReLU. Feature map \(\mathbf{X}^{1,1}\) selanjutnya digunakan pada pembentukan node decoder berikutnya.

b. Upsampling \(\mathbf{X}^{1,0}\) dan Nested Skip Pertama \(\mathbf{X}^{0,1}\)

Feature map encoder pertama \(\mathbf{X}^{1,0}\) berukuran \(3\times3\) diperbesar menjadi \(5\times5\) menggunakan interpolasi bilinear. Proses ini bertujuan untuk menyesuaikan ukuran spasial feature map sehingga dapat digabungkan dengan \(\mathbf{X}^{0,0}\) melalui nested skip connection.

Matriks feature map masukan adalah:

\[ \mathbf{X}^{1,0} = \begin{bmatrix} -2.39 & 1.82 & -1.84\\ -2.38 & 2.24 & -1.70\\ -2.25 & 0.77 & -1.99 \end{bmatrix}. \]

  • Rumus interpolasi bilinear:

Interpolasi bilinear dilakukan menggunakan prinsip yang sama seperti pada subbagian sebelumnya. Nilai keluaran dihitung berdasarkan jarak terhadap elemen-elemen pada feature map masukan.

Pada feature map satu kanal, rumus interpolasi bilinear dinyatakan sebagai:

\[ \left[ \operatorname{Up} \left( \mathbf{X}^{1,0} \right) \right]_{r,c} = \sum_{n=1}^{3} \sum_{m=1}^{3} X_{n,m}^{1,0} \max \left( 0, 1-\left|x_c-m\right| \right) \max \left( 0, 1-\left|y_r-n\right| \right). \]

Pada persamaan tersebut, \(r\) dan \(c\) menyatakan indeks baris dan kolom pada feature map keluaran, sedangkan \(n\) dan \(m\) menyatakan indeks baris dan kolom pada feature map masukan. Koordinat \(x_c\) menunjukkan posisi horizontal atau arah kolom, sedangkan \(y_r\) menunjukkan posisi vertikal atau arah baris.

Bobot interpolasi pada setiap elemen masukan dinyatakan sebagai:

\[ w_{n,m}^{(r,c)} = \max \left( 0, 1-\left|x_c-m\right| \right) \max \left( 0, 1-\left|y_r-n\right| \right). \]

Dengan demikian, rumus interpolasi bilinear dapat dituliskan sebagai:

\[ \left[ \operatorname{Up} \left( \mathbf{X}^{1,0} \right) \right]_{r,c} = \sum_{n=1}^{3} \sum_{m=1}^{3} w_{n,m}^{(r,c)}X_{n,m}^{1,0}. \]

  • Penentuan koordinat interpolasi:

Pada ilustrasi ini, koordinat matriks menggunakan indeks yang dimulai dari \(1\). Karena ukuran feature map masukan adalah \(3\times3\) dan ukuran keluaran adalah \(5\times5\), koordinat interpolasi ditentukan sebagai:

\[ x_c = 1+(c-1)\frac{3-1}{5-1} = 1+\frac{c-1}{2}, \]

\[ y_r = 1+(r-1)\frac{3-1}{5-1} = 1+\frac{r-1}{2}, \]

dengan \(r,c=1,2,3,4,5\).

Angka \(1\) menunjukkan koordinat awal matriks masukan, sedangkan pembagian dengan \(2\) menunjukkan bahwa setiap interval antara dua koordinat masukan dibagi menjadi dua bagian yang sama panjang.

Nilai koordinat yang diperoleh adalah:

Indeks keluaran Nilai koordinat
\(1\) \(1\)
\(2\) \(1.5\)
\(3\) \(2\)
\(4\) \(2.5\)
\(5\) \(3\)

Dengan demikian, nilai pada posisi keluaran yang berimpit dengan koordinat masukan dipertahankan, sedangkan nilai pada posisi lainnya dihitung berdasarkan bobot jarak terhadap elemen-elemen masukan di sekitarnya.

  • Contoh perhitungan interpolasi bilinear pada posisi \((1,2)\):

Pada posisi \((1,2)\), koordinat interpolasi diperoleh sebagai berikut:

\[ y_1=1, \qquad x_2=1.5. \]

Posisi tersebut berada tepat di tengah antara kolom pertama dan kolom kedua pada baris pertama. Bobot interpolasi untuk elemen \(X_{1,1}^{1,0}\) dihitung sebagai:

\[ \begin{aligned} w_{1,1}^{(1,2)} &= \max(0,1-|1.5-1|) \max(0,1-|1-1|)\\ &= 0.5\times1\\ &= 0.5. \end{aligned} \]

Sementara itu, bobot untuk elemen \(X_{1,2}^{1,0}\) adalah:

\[ \begin{aligned} w_{1,2}^{(1,2)} &= \max(0,1-|1.5-2|) \max(0,1-|1-1|)\\ &= 0.5\times1\\ &= 0.5. \end{aligned} \]

Elemen lainnya memiliki bobot nol karena berada di luar jarak interpolasi pada posisi tersebut. Dengan demikian:

\[ w_{1,1}^{(1,2)} = w_{1,2}^{(1,2)} = 0.5. \]

Dengan memasukkan bobot tersebut ke dalam rumus interpolasi bilinear, diperoleh:

\[ \begin{aligned} \left[ \operatorname{Up} \left( \mathbf{X}^{1,0} \right) \right]_{1,2} &= 0.5X_{1,1}^{1,0} + 0.5X_{1,2}^{1,0}\\ &= \frac{ X_{1,1}^{1,0} + X_{1,2}^{1,0} }{2}\\ &= \frac{-2.39+1.82}{2}\\ &= -0.285\\ &\approx-0.29. \end{aligned} \]

  • Contoh perhitungan interpolasi bilinear pada posisi tengah \((2,2)\):

Pada posisi \((2,2)\), koordinat interpolasi diperoleh sebagai berikut:

\[ y_2=1.5, \qquad x_2=1.5. \]

Posisi tersebut berada tepat di tengah empat elemen masukan, yaitu \(X_{1,1}^{1,0}\), \(X_{1,2}^{1,0}\), \(X_{2,1}^{1,0}\), dan \(X_{2,2}^{1,0}\).

Bobot interpolasi untuk elemen \(X_{1,1}^{1,0}\) dihitung sebagai:

\[ \begin{aligned} w_{1,1}^{(2,2)} &= \max(0,1-|1.5-1|) \max(0,1-|1.5-1|)\\ &= 0.5\times0.5\\ &= 0.25. \end{aligned} \]

Karena posisi tersebut berjarak sama dari keempat elemen masukan, maka:

\[ w_{1,1}^{(2,2)} = w_{1,2}^{(2,2)} = w_{2,1}^{(2,2)} = w_{2,2}^{(2,2)} = 0.25. \]

Dengan demikian, rumus interpolasi bilinear menjadi:

\[ \begin{aligned} \left[ \operatorname{Up} \left( \mathbf{X}^{1,0} \right) \right]_{2,2} &= 0.25X_{1,1}^{1,0} + 0.25X_{1,2}^{1,0}\\ &\quad+ 0.25X_{2,1}^{1,0} + 0.25X_{2,2}^{1,0}\\ &= \frac{ X_{1,1}^{1,0} + X_{1,2}^{1,0} + X_{2,1}^{1,0} + X_{2,2}^{1,0} }{4}\\ &= \frac{-2.39+1.82-2.38+2.24}{4}\\ &= -0.1775\\ &\approx-0.18. \end{aligned} \]

Dengan menerapkan interpolasi bilinear pada seluruh posisi keluaran, diperoleh feature map hasil Upsampling berukuran \(5\times5\), yaitu:

\[ \operatorname{Up} \left( \mathbf{X}^{1,0} \right) = \begin{bmatrix} -2.39 & -0.29 & 1.82 & -0.01 & -1.84\\ -2.39 & -0.18 & 2.03 & 0.13 & -1.77\\ -2.38 & -0.07 & 2.24 & 0.27 & -1.70\\ -2.32 & -0.41 & 1.51 & -0.17 & -1.85\\ -2.25 & -0.74 & 0.77 & -0.61 & -1.99 \end{bmatrix}. \]

Hasil tersebut menunjukkan bahwa interpolasi bilinear memperbesar ukuran spasial feature map dari \(3\times3\) menjadi \(5\times5\). Nilai pada posisi yang berimpit dengan koordinat masukan dipertahankan, sedangkan nilai pada posisi lainnya dihitung menggunakan bobot interpolasi berdasarkan jarak terhadap elemen masukan.

  • Rumus node decoder:

Sesuai dengan persamaan UNet++, nested skip connection pertama pada node decoder dirumuskan sebagai:

\[ \mathbf{X}^{0,1} = H^{(0,1)} \left( \operatorname{Concat} \left[ \mathbf{X}^{0,0}, \operatorname{Up} \left( \mathbf{X}^{1,0} \right) \right] \right). \]

Pada persamaan tersebut, \(H^{(0,1)}\) menyatakan operasi pengolahan fitur pada node decoder \(\mathbf{X}^{0,1}\). Dalam ilustrasi perhitungan manual ini, operasi tersebut disederhanakan menggunakan konvolusi \(1\times1\) tanpa bias yang diikuti fungsi aktivasi ReLU.

Karena kedua feature map yang digabungkan berukuran \(5\times5\) dan masing-masing direpresentasikan oleh satu kanal, hasil Concat memiliki dua kanal. Satu filter konvolusi \(1\times1\) digunakan untuk menggabungkan kedua kanal tersebut menjadi satu kanal keluaran.

Pada ilustrasi ini, bobot kernel ditentukan sebagai:

\[ W_{\mathrm{dec},1}^{(0,1)}=[1.00], \qquad W_{\mathrm{dec},2}^{(0,1)}=[1.00]. \]

Bobot pertama diterapkan pada \(\mathbf{X}^{0,0}\), sedangkan bobot kedua diterapkan pada \(\operatorname{Up}(\mathbf{X}^{1,0})\).

Dengan demikian, untuk setiap posisi spasial \((r,c)\), keluaran node decoder dihitung sebagai:

\[ X_{r,c}^{0,1} = \operatorname{ReLU} \left( W_{\mathrm{dec},1}^{(0,1)}X_{r,c}^{0,0} + W_{\mathrm{dec},2}^{(0,1)} \left[ \operatorname{Up} \left( \mathbf{X}^{1,0} \right) \right]_{r,c} \right). \]

  • Contoh perhitungan node decoder pada posisi \((1,1)\):

\[ \begin{aligned} X_{1,1}^{0,1} &= \operatorname{ReLU} \left( W_{\mathrm{dec},1}^{(0,1)}X_{1,1}^{0,0} + W_{\mathrm{dec},2}^{(0,1)} \left[ \operatorname{Up} \left( \mathbf{X}^{1,0} \right) \right]_{1,1} \right)\\ &= \operatorname{ReLU} \left( 1.00(-2.39) + 1.00(-2.39) \right)\\ &= \operatorname{ReLU}(-4.78)\\ &= 0.00. \end{aligned} \]

  • Contoh perhitungan node decoder pada posisi \((1,3)\):

\[ \begin{aligned} X_{1,3}^{0,1} &= \operatorname{ReLU} \left( W_{\mathrm{dec},1}^{(0,1)}X_{1,3}^{0,0} + W_{\mathrm{dec},2}^{(0,1)} \left[ \operatorname{Up} \left( \mathbf{X}^{1,0} \right) \right]_{1,3} \right)\\ &= \operatorname{ReLU} \left( 1.00(1.82) + 1.00(1.82) \right)\\ &= \operatorname{ReLU}(3.64)\\ &= 3.64. \end{aligned} \]

Dengan menerapkan operasi yang sama pada seluruh posisi spasial, diperoleh feature map node decoder sebagai berikut:

\[ \mathbf{X}^{0,1} = \begin{bmatrix} 0.00 & 0.00 & 3.64 & 1.11 & 0.00\\ 0.00 & 0.00 & 4.27 & 1.63 & 0.00\\ 0.00 & 0.00 & 4.48 & 1.77 & 0.00\\ 0.00 & 0.00 & 3.35 & 0.94 & 0.00\\ 0.00 & 0.00 & 1.54 & 0.00 & 0.00 \end{bmatrix}. \]

Hasil tersebut menunjukkan bahwa node \(\mathbf{X}^{0,1}\) menggabungkan informasi dari feature map encoder \(\mathbf{X}^{0,0}\) dan hasil Upsampling \(\mathbf{X}^{1,0}\) melalui nested skip connection. Pada ilustrasi ini, penggabungan dilakukan menggunakan Concat, konvolusi \(1\times1\), dan fungsi aktivasi ReLU. Feature map \(\mathbf{X}^{0,1}\) selanjutnya digunakan pada pembentukan node decoder berikutnya.

c. Upsampling \(\mathbf{X}^{1,1}\) dan Nested Skip Kedua \(\mathbf{X}^{0,2}\)

Node decoder \(\mathbf{X}^{1,1}\) berukuran \(3\times3\) diperbesar menjadi \(5\times5\) menggunakan interpolasi bilinear. Proses ini bertujuan untuk menyesuaikan ukuran spasial feature map sehingga dapat digabungkan dengan \(\mathbf{X}^{0,0}\) dan \(\mathbf{X}^{0,1}\) melalui nested skip connection.

Matriks feature map masukan adalah:

\[ \mathbf{X}^{1,1} = \begin{bmatrix} 0.00 & 0.00 & 0.00\\ 0.00 & 0.12 & 0.00\\ 0.00 & 0.00 & 0.00 \end{bmatrix}. \]

  • Rumus interpolasi bilinear:

Interpolasi bilinear dilakukan menggunakan prinsip yang sama seperti pada subbagian sebelumnya. Setiap nilai keluaran dihitung berdasarkan jarak terhadap elemen-elemen pada feature map masukan.

Pada feature map satu kanal, rumus interpolasi bilinear dinyatakan sebagai:

\[ \left[ \operatorname{Up} \left( \mathbf{X}^{1,1} \right) \right]_{r,c} = \sum_{n=1}^{3} \sum_{m=1}^{3} X_{n,m}^{1,1} \max \left( 0, 1-\left|x_c-m\right| \right) \max \left( 0, 1-\left|y_r-n\right| \right). \]

Pada persamaan tersebut, \(r\) dan \(c\) menyatakan indeks baris dan kolom pada feature map keluaran, sedangkan \(n\) dan \(m\) menyatakan indeks baris dan kolom pada feature map masukan. Koordinat \(x_c\) menunjukkan posisi horizontal atau arah kolom, sedangkan \(y_r\) menunjukkan posisi vertikal atau arah baris.

Bobot interpolasi pada setiap elemen masukan dinyatakan sebagai:

\[ w_{n,m}^{(r,c)} = \max \left( 0, 1-\left|x_c-m\right| \right) \max \left( 0, 1-\left|y_r-n\right| \right). \]

Dengan demikian, rumus interpolasi bilinear dapat dituliskan sebagai:

\[ \left[ \operatorname{Up} \left( \mathbf{X}^{1,1} \right) \right]_{r,c} = \sum_{n=1}^{3} \sum_{m=1}^{3} w_{n,m}^{(r,c)}X_{n,m}^{1,1}. \]

  • Penentuan koordinat interpolasi:

Pada ilustrasi ini, koordinat matriks menggunakan indeks yang dimulai dari \(1\). Karena ukuran feature map masukan adalah \(3\times3\) dan ukuran keluaran adalah \(5\times5\), koordinat interpolasi ditentukan sebagai:

\[ x_c = 1+(c-1)\frac{3-1}{5-1} = 1+\frac{c-1}{2}, \]

\[ y_r = 1+(r-1)\frac{3-1}{5-1} = 1+\frac{r-1}{2}, \]

dengan \(r,c=1,2,3,4,5\).

Angka \(1\) menunjukkan koordinat awal matriks masukan, sedangkan pembagian dengan \(2\) menunjukkan bahwa setiap interval antara dua koordinat masukan dibagi menjadi dua bagian yang sama panjang.

Nilai koordinat yang diperoleh adalah:

Indeks keluaran Nilai koordinat
\(1\) \(1\)
\(2\) \(1.5\)
\(3\) \(2\)
\(4\) \(2.5\)
\(5\) \(3\)

Dengan demikian, nilai pada posisi keluaran yang berimpit dengan koordinat masukan dipertahankan, sedangkan nilai pada posisi lainnya dihitung berdasarkan bobot jarak terhadap elemen-elemen masukan di sekitarnya.

  • Contoh perhitungan interpolasi bilinear pada posisi \((2,3)\):

Pada posisi \((2,3)\), koordinat interpolasi diperoleh sebagai berikut:

\[ y_2=1.5, \qquad x_3=2. \]

Posisi tersebut berada tepat di tengah secara vertikal antara baris pertama dan kedua, tetapi sejajar dengan kolom kedua. Oleh karena itu, hanya dua elemen pada kolom kedua yang memiliki bobot bukan nol.

Bobot interpolasi untuk elemen \(X_{1,2}^{1,1}\) dihitung sebagai:

\[ \begin{aligned} w_{1,2}^{(2,3)} &= \max(0,1-|2-2|) \max(0,1-|1.5-1|)\\ &= 1\times0.5\\ &= 0.5. \end{aligned} \]

Sementara itu, bobot untuk elemen \(X_{2,2}^{1,1}\) adalah:

\[ \begin{aligned} w_{2,2}^{(2,3)} &= \max(0,1-|2-2|) \max(0,1-|1.5-2|)\\ &= 1\times0.5\\ &= 0.5. \end{aligned} \]

Elemen lainnya memiliki bobot nol karena berada di luar jarak interpolasi pada posisi tersebut. Dengan demikian:

\[ w_{1,2}^{(2,3)} = w_{2,2}^{(2,3)} = 0.5. \]

Dengan memasukkan bobot tersebut ke dalam rumus interpolasi bilinear, diperoleh:

\[ \begin{aligned} \left[ \operatorname{Up} \left( \mathbf{X}^{1,1} \right) \right]_{2,3} &= 0.5X_{1,2}^{1,1} + 0.5X_{2,2}^{1,1}\\ &= \frac{ X_{1,2}^{1,1} + X_{2,2}^{1,1} }{2}\\ &= \frac{0.00+0.12}{2}\\ &= 0.06. \end{aligned} \]

  • Contoh perhitungan interpolasi bilinear pada posisi \((2,2)\):

Pada posisi \((2,2)\), koordinat interpolasi diperoleh sebagai berikut:

\[ y_2=1.5, \qquad x_2=1.5. \]

Posisi tersebut berada tepat di tengah empat elemen masukan, yaitu \(X_{1,1}^{1,1}\), \(X_{1,2}^{1,1}\), \(X_{2,1}^{1,1}\), dan \(X_{2,2}^{1,1}\).

Bobot interpolasi untuk elemen \(X_{1,1}^{1,1}\) dihitung sebagai:

\[ \begin{aligned} w_{1,1}^{(2,2)} &= \max(0,1-|1.5-1|) \max(0,1-|1.5-1|)\\ &= 0.5\times0.5\\ &= 0.25. \end{aligned} \]

Karena posisi tersebut berjarak sama dari keempat elemen masukan, maka:

\[ w_{1,1}^{(2,2)} = w_{1,2}^{(2,2)} = w_{2,1}^{(2,2)} = w_{2,2}^{(2,2)} = 0.25. \]

Dengan demikian, rumus interpolasi bilinear menjadi:

\[ \begin{aligned} \left[ \operatorname{Up} \left( \mathbf{X}^{1,1} \right) \right]_{2,2} &= 0.25X_{1,1}^{1,1} + 0.25X_{1,2}^{1,1}\\ &\quad+ 0.25X_{2,1}^{1,1} + 0.25X_{2,2}^{1,1}\\ &= \frac{ X_{1,1}^{1,1} + X_{1,2}^{1,1} + X_{2,1}^{1,1} + X_{2,2}^{1,1} }{4}\\ &= \frac{0.00+0.00+0.00+0.12}{4}\\ &= 0.03. \end{aligned} \]

Dengan menerapkan interpolasi bilinear pada seluruh posisi keluaran, diperoleh feature map hasil Upsampling berukuran \(5\times5\), yaitu:

\[ \operatorname{Up} \left( \mathbf{X}^{1,1} \right) = \begin{bmatrix} 0.00 & 0.00 & 0.00 & 0.00 & 0.00\\ 0.00 & 0.03 & 0.06 & 0.03 & 0.00\\ 0.00 & 0.06 & 0.12 & 0.06 & 0.00\\ 0.00 & 0.03 & 0.06 & 0.03 & 0.00\\ 0.00 & 0.00 & 0.00 & 0.00 & 0.00 \end{bmatrix}. \]

Hasil tersebut menunjukkan bahwa interpolasi bilinear memperbesar ukuran spasial feature map dari \(3\times3\) menjadi \(5\times5\). Nilai pada posisi yang berimpit dengan koordinat masukan dipertahankan, sedangkan nilai pada posisi lainnya dihitung menggunakan bobot interpolasi berdasarkan jarak terhadap elemen masukan.

  • Rumus node decoder:

Sesuai dengan persamaan UNet++, nested skip connection kedua pada node decoder dirumuskan sebagai:

\[ \mathbf{X}^{0,2} = H^{(0,2)} \left( \operatorname{Concat} \left[ \mathbf{X}^{0,0}, \mathbf{X}^{0,1}, \operatorname{Up} \left( \mathbf{X}^{1,1} \right) \right] \right). \]

Pada persamaan tersebut, \(H^{(0,2)}\) menyatakan operasi pengolahan fitur pada node decoder \(\mathbf{X}^{0,2}\). Dalam ilustrasi perhitungan manual ini, operasi tersebut disederhanakan menggunakan konvolusi \(1\times1\) tanpa bias yang diikuti fungsi aktivasi ReLU.

Karena ketiga feature map yang digabungkan berukuran \(5\times5\) dan masing-masing direpresentasikan oleh satu kanal, hasil Concat memiliki tiga kanal. Satu filter konvolusi \(1\times1\) digunakan untuk menggabungkan ketiga kanal tersebut menjadi satu kanal keluaran.

Pada ilustrasi ini, bobot kernel ditentukan sebagai:

\[ \mathbf{W}_{\mathrm{pw}}^{(0,2)} = \begin{bmatrix} 0.25 & 0.50 & 0.25 \end{bmatrix}. \]

Bobot tersebut merupakan parameter ilustratif untuk menyederhanakan perhitungan manual dan tidak merepresentasikan bobot hasil pelatihan model.

Bobot pertama diterapkan pada \(\mathbf{X}^{0,0}\), bobot kedua diterapkan pada \(\mathbf{X}^{0,1}\), sedangkan bobot ketiga diterapkan pada \(\operatorname{Up}(\mathbf{X}^{1,1})\).

Dengan demikian, untuk setiap posisi spasial \((r,c)\), keluaran node decoder dihitung sebagai:

\[ X_{r,c}^{0,2} = \operatorname{ReLU} \left( 0.25X_{r,c}^{0,0} + 0.50X_{r,c}^{0,1} + 0.25 \left[ \operatorname{Up} \left( \mathbf{X}^{1,1} \right) \right]_{r,c} \right). \]

  • Contoh perhitungan node decoder pada posisi \((1,1)\):

\[ \begin{aligned} X_{1,1}^{0,2} &= \operatorname{ReLU} \left( 0.25X_{1,1}^{0,0} + 0.50X_{1,1}^{0,1} + 0.25 \left[ \operatorname{Up} \left( \mathbf{X}^{1,1} \right) \right]_{1,1} \right)\\ &= \operatorname{ReLU} \left( 0.25(-2.39) + 0.50(0.00) + 0.25(0.00) \right)\\ &= \operatorname{ReLU}(-0.60)\\ &= 0.00. \end{aligned} \]

  • Contoh perhitungan node decoder pada posisi \((2,3)\):

\[ \begin{aligned} X_{2,3}^{0,2} &= \operatorname{ReLU} \left( 0.25X_{2,3}^{0,0} + 0.50X_{2,3}^{0,1} + 0.25 \left[ \operatorname{Up} \left( \mathbf{X}^{1,1} \right) \right]_{2,3} \right)\\ &= \operatorname{ReLU} \left( 0.25(2.24) + 0.50(4.27) + 0.25(0.06) \right)\\ &= \operatorname{ReLU} \left( 0.56+2.135+0.015 \right)\\ &= \operatorname{ReLU}(2.71)\\ &= 2.71. \end{aligned} \]

Dengan menerapkan operasi yang sama pada seluruh posisi spasial dan menampilkan hasil hingga dua angka desimal, diperoleh feature map keluaran node decoder sebagai berikut:

\[ \mathbf{X}^{0,2} = \begin{bmatrix} 0.00 & 0.00 & 2.28 & 0.84 & 0.00\\ 0.00 & 0.00 & 2.71 & 1.20 & 0.00\\ 0.00 & 0.00 & 2.83 & 1.28 & 0.00\\ 0.00 & 0.00 & 2.15 & 0.76 & 0.00\\ 0.00 & 0.00 & 0.96 & 0.00 & 0.00 \end{bmatrix}. \]

Hasil tersebut menunjukkan bahwa node \(\mathbf{X}^{0,2}\) menggabungkan informasi dari \(\mathbf{X}^{0,0}\), \(\mathbf{X}^{0,1}\), dan hasil Upsampling \(\mathbf{X}^{1,1}\) melalui nested skip connection. Pada ilustrasi ini, penggabungan dilakukan menggunakan Concat, konvolusi \(1\times1\), dan fungsi aktivasi ReLU. Feature map \(\mathbf{X}^{0,2}\) merupakan keluaran akhir decoder pada ilustrasi perhitungan manual ini.

7. Prediksi Probabilitas Piksel dan Mask Segmentasi

Keluaran akhir decoder \(\mathbf{X}^{0,2}\) digunakan untuk menghasilkan prediksi pada setiap piksel. Tahap ini terdiri atas pembentukan logit, konversi logit menjadi probabilitas menggunakan fungsi sigmoid, dan pembentukan mask segmentasi biner menggunakan nilai ambang lebih dari \(0.50\).

a. Head Segmentasi dan Matriks Logit (\(\mathbf{z}\))

Pada ilustrasi ini, head segmentasi menggunakan convolution \(1\times1\) tanpa bias dengan bobot \(1.00\). Bobot tersebut dinyatakan sebagai:

\[ \mathbf{W}_{\mathrm{seg}} = \begin{bmatrix} 1.00 \end{bmatrix}. \]

Karena bobot convolution bernilai \(1.00\) dan bias tidak digunakan, nilai logit sama dengan keluaran akhir decoder.

  • Rumus:

\[ z_{i,j} = W_{\mathrm{seg},1,1} X_{i,j}^{0,2}. \]

Pada ilustrasi ini, persamaan tersebut dapat disederhanakan menjadi:

\[ z_{i,j} = 1.00X_{i,j}^{0,2} = X_{i,j}^{0,2}. \]

Matriks \(\mathbf{z}\) berdimensi \(5\times5\).

  • Contoh perhitungan:

\[ \begin{aligned} z_{3,3} &= 1.00X_{3,3}^{0,2}\\ &= 1.00(2.83)\\ &= 2.83. \end{aligned} \]

Dengan aturan yang sama, diperoleh matriks logit:

\[ \mathbf{z} = \begin{bmatrix} 0.00 & 0.00 & 2.28 & 0.84 & 0.00\\ 0.00 & 0.00 & 2.71 & 1.20 & 0.00\\ 0.00 & 0.00 & 2.83 & 1.28 & 0.00\\ 0.00 & 0.00 & 2.15 & 0.76 & 0.00\\ 0.00 & 0.00 & 0.96 & 0.00 & 0.00 \end{bmatrix}. \]

b. Probabilitas Prediksi Piksel (\(\mathbf{p}\))

Fungsi sigmoid diterapkan pada setiap elemen logit untuk mengubah nilainya menjadi probabilitas pada rentang \([0,1]\). Nilai yang mendekati \(1\) menunjukkan keyakinan model yang lebih tinggi bahwa piksel tersebut termasuk kelas target.

  • Rumus:

\[ p_{i,j} = \sigma(z_{i,j}) = \frac{1}{1+e^{-z_{i,j}}}. \]

Matriks probabilitas \(\mathbf{p}\) berdimensi \(5\times5\).

  • Contoh perhitungan:

Untuk posisi \((3,3)\), diketahui \(z_{3,3}=2.83\). Maka:

\[ \begin{aligned} p_{3,3} &= \frac{1}{1+e^{-z_{3,3}}}\\ &= \frac{1}{1+e^{-2.83}}\\ &= \frac{1}{1+0.0590}\\ &= 0.9443\\ &= 0.94. \end{aligned} \]

Untuk logit nol, probabilitasnya adalah:

\[ \begin{aligned} p_{1,1} &= \frac{1}{1+e^{-0.00}}\\ &= \frac{1}{1+1}\\ &= 0.50. \end{aligned} \]

Dengan aturan yang sama, diperoleh matriks probabilitas:

\[ \mathbf{p} = \begin{bmatrix} 0.50 & 0.50 & 0.91 & 0.70 & 0.50\\ 0.50 & 0.50 & 0.94 & 0.77 & 0.50\\ 0.50 & 0.50 & 0.94 & 0.78 & 0.50\\ 0.50 & 0.50 & 0.90 & 0.68 & 0.50\\ 0.50 & 0.50 & 0.72 & 0.50 & 0.50 \end{bmatrix}. \]

c. Mask Segmentasi Biner (\(\widehat{\mathbf{M}}\))

Matriks probabilitas diubah menjadi mask segmentasi biner menggunakan nilai ambang lebih dari \(0.50\). Piksel dengan probabilitas tepat \(0.50\) dikategorikan sebagai latar belakang.

  • Rumus:

\[ \widehat{M}_{i,j} = \mathbb{1} \left[ p_{i,j}>0.50 \right]. \]

dengan:

\[ \widehat{M}_{i,j} = \begin{cases} 1, & \text{jika } p_{i,j}>0.50 \text{ (wilayah lesi)},\\ 0, & \text{jika } p_{i,j}\leq0.50 \text{ (latar belakang)}. \end{cases} \]

Matriks mask prediksi \(\widehat{\mathbf{M}}\) berdimensi \(5\times5\).

  • Contoh perhitungan:

Untuk posisi \((3,3)\):

\[ \begin{aligned} \widehat{M}_{3,3} &= \mathbb{1} \left[ p_{3,3}>0.50 \right]\\ &= \mathbb{1} \left[ 0.94>0.50 \right]\\ &= 1. \end{aligned} \]

Untuk posisi \((1,1)\):

\[ \begin{aligned} \widehat{M}_{1,1} &= \mathbb{1} \left[ p_{1,1}>0.50 \right]\\ &= \mathbb{1} \left[ 0.50>0.50 \right]\\ &= 0. \end{aligned} \]

Dengan aturan yang sama, diperoleh mask segmentasi prediksi:

\[ \widehat{\mathbf{M}} = \begin{bmatrix} 0 & 0 & 1 & 1 & 0\\ 0 & 0 & 1 & 1 & 0\\ 0 & 0 & 1 & 1 & 0\\ 0 & 0 & 1 & 1 & 0\\ 0 & 0 & 1 & 0 & 0 \end{bmatrix}. \]

Keterangan proses pelatihan: Mask biner \(\widehat{M}\) pada ilustrasi ini ditampilkan untuk memperlihatkan bentuk akhir hasil segmentasi dan untuk menghitung metrik evaluasi. Pada proses pelatihan, mask biner tersebut tidak digunakan untuk memperbarui bobot model. Pembaruan bobot dilakukan menggunakan probabilitas prediksi \(p\) dan ground truth \(M\) melalui BCE-Dice loss.

LS0tDQp0aXRsZTogIklsdXN0cmFzaSBQZW1iZW50dWthbiBTZWdtZW50YXNpIFVOZXQrKyBkZW5nYW4gRW5jb2RlciBNb2JpbGVWaVR2MyBWMSINCg0KDQphdXRob3I6IHwNCiAgPGRpdiBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyBmb250LXNpemU6IDE0cHg7IGNvbG9yOiAjNTU1NTU1OyBsaW5lLWhlaWdodDogMS42OyBtYXJnaW4tdG9wOiAxMHB4OyI+DQogIFNyaSBZdWxpYW5hICgxNDA3MjAyNTAwMykgPGJyPg0KDQogIFByb2dyYW0gU3R1ZGkgTWFnaXN0ZXIgU3RhdGlzdGlrYSBUZXJhcGFuIDxicj4NCiAgPC9kaXY+DQoNCg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgd29yZF9kb2N1bWVudDoNCiAgICB0b2M6IHRydWUNCmNzczogc3R5bGUuY3NzDQotLS0NCg0KDQojIyAxLiBDaXRyYSBtYXN1a2FuIGdyb3VuZCB0cnV0aCBkYW4gbm9ybWFsaXNhc2kNCg0KUGFkYSBjaXRyYSBncmF5c2NhbGUsIHNldGlhcCBwaWtzZWwgbWVtaWxpa2kgc2F0dSBuaWxhaSBpbnRlbnNpdGFzIHlhbmcgbWVudW5qdWtrYW4gdGluZ2thdCBrZWNlcmFoYW4uIEFwYWJpbGEgbmlsYWkgaW50ZW5zaXRhcyB0ZWxhaCBkaW5vcm1hbGlzYXNpIGtlIHJlbnRhbmcgXChbMCwxXVwpLCBtYWthIG5pbGFpIDAgbWVudW5qdWtrYW4gcGlrc2VsIHBhbGluZyBnZWxhcCAoaGl0YW0pLCBuaWxhaSAxIG1lbnVuanVra2FuIHBpa3NlbCBwYWxpbmcgdGVyYW5nIChwdXRpaCksIHNlZGFuZ2thbiBuaWxhaSBkaSBhbnRhcmEgMCBkYW4gMSBtZW51bmp1a2thbiBncmFkYXNpIGFidS1hYnUuIFNlbWFraW4gbWVuZGVrYXRpIDAsIHBpa3NlbCBzZW1ha2luIGdlbGFwOyBzZW1ha2luIG1lbmRla2F0aSAxLCBwaWtzZWwgc2VtYWtpbiB0ZXJhbmcuICANCkRhbGFtIGlsdXN0cmFzaSBpbmksIG1hdHJpa3MgY2l0cmEgYXdhbCBtYXNpaCBtZW5nZ3VuYWthbiBza2FsYSBpbnRlbnNpdGFzIDAtMjU1LiBPbGVoIGthcmVuYSBpdHUsIG5pbGFpIDAgbWVyZXByZXNlbnRhc2lrYW4gaGl0YW0sIG5pbGFpIDI1NSBtZXJlcHJlc2VudGFzaWthbiBwdXRpaCwgZGFuIG5pbGFpIHNlcGVydGkgNjQsIDEyOCwgYXRhdSAxOTIgbWVudW5qdWtrYW4gdGluZ2thdCBhYnUtYWJ1IHlhbmcgYmVyYmVkYS4gRGltZW5zaSBtYXRyaWtzIGFkYWxhaCBcKDVcdGltZXM1XCkuIA0KDQojIyMgYS4gQ2l0cmEgTWFzdWthbg0KXFsNClxtYXRoYmZ7SX09XGJlZ2lue2JtYXRyaXh9DQowICYgNjQgJiAxOTIgJiAxNjAgJiAzMlxcDQowICYgODAgJiAyMDggJiAxNzYgJiA0MFxcDQowICYgODAgJiAyMDggJiAxNzYgJiA0MFxcDQowICYgNzIgJiAxOTIgJiAxNjAgJiAzMlxcDQo4ICYgNDggJiAxNDQgJiAxMTIgJiAyNA0KXGVuZHtibWF0cml4fQ0KXF0NCg0KIyMjIGIuIEdyb3VuZCB0cnV0aCBiaW5lciANCg0KXFsNClxtYXRoYmZ7TX09XGJlZ2lue2JtYXRyaXh9DQowICYgMCAmIDEgJiAxICYgMFxcDQowICYgMSAmIDEgJiAxICYgMFxcDQowICYgMSAmIDEgJiAxICYgMFxcDQowICYgMCAmIDEgJiAxICYgMFxcDQowICYgMCAmIDAgJiAwICYgMA0KXGVuZHtibWF0cml4fQ0KXF0NCg0KR3JvdW5kIHRydXRoIFwoXG1hdGhiZntNfVwpIGJlcmFkYSBkaSBhd2FsIHNlYmFnYWkgdGFyZ2V0IGV2YWx1YXNpIGRpbWFuYSBuaWxhaSAwIG1lcnVwYWthbiBsYXRhciBiZWxha2FuZyBkYW4gMSBtZXJ1cGFrYW4gd2lsYXlhaCBsZXNpLCBidWthbiBtYXN1a2FuIGVuY29kZXIuIA0KDQojIyMgYy4gTm9ybWFsaXNhc2kga2FuYWwNCg0KLSAqKk5vcm1hbGlzYXNpIHByZXRyYWluZWQgSW1hZ2VOZXQgZGl0ZXJhcGthbiBwZXIga2FuYWw6KioNCg0KXFsNClxtYXRoYmZ7WH1fUj1cZnJhY3tJX1IvMjU1LTAuNDg1fXswLjIyOX0sXHFxdWFkDQpcbWF0aGJme1h9X0c9XGZyYWN7SV9HLzI1NS0wLjQ1Nn17MC4yMjR9LFxxcXVhZA0KXG1hdGhiZntYfV9CPVxmcmFje0lfQi8yNTUtMC40MDZ9ezAuMjI1fS4NClxdDQoNCi0gKipDb250b2g6KioNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0KXG1hdGhiZntYfV97MSwzfSY9XGZyYWN7KDE5Mi8yNTUtMC40ODUpfXswLjIyOX1cXA0KJj0xLjE3DQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpQYWRhIGlsdXN0cmFzaSBpbmkgbWVuZ2d1bmFrYW4gMSBrYW5hbCBqYWRpIHNldGlhcCBlbGVtZW4gZGloaXR1bmcgZGVuZ2FuIFwoWF97aSxqfT0oSV97aSxqfS8yNTUtMC40ODUpLzAuMjI5XCkuIEF0dXJhbiB5YW5nIHNhbWEgZGl0ZXJhcGthbiBwYWRhIHNlbHVydWggZWxlbWVuIG1hdHJpa3MgYmVyaWt1dC4NCg0KXFsNClxtYXRoYmZ7WH1fe1xtYXRocm17bm9ybX19PVxiZWdpbntibWF0cml4fQ0KLTIuMTIgJiAtMS4wMiAmIDEuMTcgJiAwLjYyICYgLTEuNTdcXA0KLTIuMTIgJiAtMC43NSAmIDEuNDQgJiAwLjkwICYgLTEuNDNcXA0KLTIuMTIgJiAtMC43NSAmIDEuNDQgJiAwLjkwICYgLTEuNDNcXA0KLTIuMTIgJiAtMC44OCAmIDEuMTcgJiAwLjYyICYgLTEuNTdcXA0KLTEuOTggJiAtMS4zMCAmIDAuMzUgJiAtMC4yMCAmIC0xLjcxDQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KDQoNCg0KIyMgMi4gUmVwcmVzZW50YXNpIExva2FsDQoNClBhZGEgaWx1c3RyYXNpIGluaSwgbWF0cmlrcyBcKFxtYXRoYmZ7WH1cKSBiZXJ1a3VyYW4gXCg1XHRpbWVzNVwpIG1lcmVwcmVzZW50YXNpa2FuIHNhdHUga2FuYWwgZGFyaSAqZmVhdHVyZSBtYXAqIG1hc3VrYW4gYmxvayBcKFxtYXRoYmZ7Rn1eeygwKX1cKSB5YW5nIHRlbGFoIGRpbm9ybWFsaXNhc2kuIFBlbWJlbnR1a2FuIHJlcHJlc2VudGFzaSBsb2thbCBkaWF3YWxpIGRlbmdhbiBvcGVyYXNpICpkZXB0aHdpc2UgY29udm9sdXRpb24qIG1lbmdndW5ha2FuIGtlcm5lbCBcKDNcdGltZXMzXCksICpzdHJpZGUqIFwoMVwpLCBkYW4gKnplcm8gcGFkZGluZyogc2ViZXNhciBcKDFcKSBwYWRhIHNldGlhcCBzaXNpLiBIYXNpbG55YSBrZW11ZGlhbiBkaXByb3NlcyBtZWxhbHVpIGZ1bmdzaSBha3RpdmFzaSBTd2lzaC4gU2VsYW5qdXRueWEsIHByb3lla3NpICpwb2ludHdpc2UgY29udm9sdXRpb24qIFwoMVx0aW1lczFcKSBkaXRlcmFwa2FuIHBhZGEgKmZlYXR1cmUgbWFwKiBsb2thbCB5YW5nIGRpaGFzaWxrYW4uDQoNCiMjIyBhLiBEZXB0aHdpc2UgQ29udm9sdXRpb24NCg0KTWF0cmlrcyAqZmVhdHVyZSBtYXAqIG1hc3VrYW4geWFuZyBkaWd1bmFrYW4gYWRhbGFoOg0KDQpcWw0KXG1hdGhiZntYfQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQotMi4xMiAmIC0xLjAyICYgMS4xNyAmIDAuNjIgJiAtMS41N1xcDQotMi4xMiAmIC0wLjc1ICYgMS40NCAmIDAuOTAgJiAtMS40M1xcDQotMi4xMiAmIC0wLjc1ICYgMS40NCAmIDAuOTAgJiAtMS40M1xcDQotMi4xMiAmIC0wLjg4ICYgMS4xNyAmIDAuNjIgJiAtMS41N1xcDQotMS45OCAmIC0xLjMwICYgMC4zNSAmIC0wLjIwICYgLTEuNzENClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQotICoqUGVuYW1iYWhhbiBaZXJvIFBhZGRpbmc6KioNCg0KU2ViZWx1bSBvcGVyYXNpICpkZXB0aHdpc2UgY29udm9sdXRpb24qIGRpbGFrdWthbiwgc2F0dSBsYXBpc2FuIG5pbGFpIG5vbCBkaXRhbWJhaGthbiBwYWRhIGtlZW1wYXQgc2lzaSBtYXRyaWtzIG1hc3VrYW4sIHlhaXR1IHNpc2kgYXRhcywgYmF3YWgsIGtpcmksIGRhbiBrYW5hbi4gUGVuYW1iYWhhbiAqemVybyBwYWRkaW5nKiBiZXJ0dWp1YW4gbWVtcGVydGFoYW5rYW4gdWt1cmFuIHNwYXNpYWwgKmZlYXR1cmUgbWFwKiBzZXRlbGFoIG9wZXJhc2kga29udm9sdXNpLg0KDQpVa3VyYW4ga2VsdWFyYW4gZGloaXR1bmcgbWVuZ2d1bmFrYW46DQoNClxbDQpvDQo9DQpcbGVmdFxsZmxvb3INClxmcmFje2krMnAta317c30NClxyaWdodFxyZmxvb3IrMSwNClxdDQoNCmRlbmdhbiBcKGlcKSBtZW55YXRha2FuIHVrdXJhbiBzcGFzaWFsIG1hc3VrYW4sIFwocFwpIG1lcnVwYWthbiBqdW1sYWggKnBhZGRpbmcqIHBhZGEgc2V0aWFwIHNpc2ksIFwoa1wpIG1lcnVwYWthbiB1a3VyYW4ga2VybmVsLCBkYW4gXChzXCkgbWVydXBha2FuICpzdHJpZGUqLg0KDQpQYWRhIGlsdXN0cmFzaSBpbmkgZGlndW5ha2FuIFwoaT01XCksIFwocD0xXCksIFwoaz0zXCksIGRhbiBcKHM9MVwpLCBzZWhpbmdnYToNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0Kbw0KJj0NClxsZWZ0XGxmbG9vcg0KXGZyYWN7NSsyKDEpLTN9ezF9DQpccmlnaHRccmZsb29yKzFcXA0KJj0NClxsZWZ0XGxmbG9vcg0KXGZyYWN7NH17MX0NClxyaWdodFxyZmxvb3IrMVxcDQomPTUuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpEZW5nYW4gZGVtaWtpYW4sIHVrdXJhbiBzcGFzaWFsIGtlbHVhcmFuIHRldGFwIFwoNVx0aW1lczVcKS4gUGVuYW1iYWhhbiAqemVybyBwYWRkaW5nKiBtZW5ndWJhaCB1a3VyYW4gbWF0cmlrcyBtYXN1a2FuIHNlbWVudGFyYSBkYXJpIFwoNVx0aW1lczVcKSBtZW5qYWRpIFwoN1x0aW1lczdcKS4NCg0KTWF0cmlrcyBzZXRlbGFoIHBlbmFtYmFoYW4gKnplcm8gcGFkZGluZyogYWRhbGFoOg0KDQpcWw0KXG1hdGhiZntYfV97XG1hdGhybXtwYWR9fQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQowLjAwICYgMC4wMCAmIDAuMDAgJiAwLjAwICYgMC4wMCAmIDAuMDAgJiAwLjAwXFwNCjAuMDAgJiAtMi4xMiAmIC0xLjAyICYgMS4xNyAmIDAuNjIgJiAtMS41NyAmIDAuMDBcXA0KMC4wMCAmIC0yLjEyICYgLTAuNzUgJiAxLjQ0ICYgMC45MCAmIC0xLjQzICYgMC4wMFxcDQowLjAwICYgLTIuMTIgJiAtMC43NSAmIDEuNDQgJiAwLjkwICYgLTEuNDMgJiAwLjAwXFwNCjAuMDAgJiAtMi4xMiAmIC0wLjg4ICYgMS4xNyAmIDAuNjIgJiAtMS41NyAmIDAuMDBcXA0KMC4wMCAmIC0xLjk4ICYgLTEuMzAgJiAwLjM1ICYgLTAuMjAgJiAtMS43MSAmIDAuMDBcXA0KMC4wMCAmIDAuMDAgJiAwLjAwICYgMC4wMCAmIDAuMDAgJiAwLjAwICYgMC4wMA0KXGVuZHtibWF0cml4fS4NClxdDQoNCi0gKipGaWx0ZXIgS2VybmVsOioqDQoNClBhZGEgaWx1c3RyYXNpIGluaSwgbWF0cmlrcyBib2JvdCBrZXJuZWwgKmRlcHRod2lzZSBjb252b2x1dGlvbiogZGl0ZXRhcGthbiBzZWJhZ2FpOg0KDQpcWw0KXG1hdGhiZntXfV97XG1hdGhybXtkd319DQo9DQpcYmVnaW57Ym1hdHJpeH0NCjAuMDAgJiAwLjEwICYgMC4wMFxcDQowLjEwICYgMC42MCAmIDAuMTBcXA0KMC4wMCAmIDAuMTAgJiAwLjAwDQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KS2VybmVsIHRlcnNlYnV0IG1lbWlsaWtpIGJvYm90IHB1c2F0IHNlYmVzYXIgXCgwLjYwXCksIGVtcGF0IGJvYm90IHNlYmVzYXIgXCgwLjEwXCkgcGFkYSBwb3Npc2kgYXRhcywgYmF3YWgsIGtpcmksIGRhbiBrYW5hbiwgc2VydGEgZW1wYXQgYm9ib3Qgc3VkdXQgYmVybmlsYWkgXCgwLjAwXCkuDQoNClNldGlhcCBoYXNpbCBrb252b2x1c2kgZGlwZXJvbGVoIG1lbGFsdWkgcGVya2FsaWFuIHNlbWJpbGFuIGVsZW1lbiBwYWRhIGFyZWEgKmZlYXR1cmUgbWFwKiBkZW5nYW4gc2VtYmlsYW4gYm9ib3Qga2VybmVsIHlhbmcgYmVyc2VzdWFpYW4sIGtlbXVkaWFuIHNlbHVydWggaGFzaWwgcGVya2FsaWFuIGRpanVtbGFoa2FuLg0KDQotICoqUnVtdXM6KioNCg0KT3BlcmFzaSAqZGVwdGh3aXNlIGNvbnZvbHV0aW9uKiB1bnR1ayBzYXR1IGthbmFsIG1hc3VrYW4gZGlueWF0YWthbiBzZWJhZ2FpOg0KDQpcWw0KRl97XG1hdGhybXtkd30sayxsfQ0KPQ0KXHN1bV97dT0xfV57M30NClxzdW1fe3Y9MX1eezN9DQpXX3tcbWF0aHJte2R3fSx1LHZ9DQpYX3tcbWF0aHJte3BhZH0sayt1LTEsbCt2LTF9LA0KXF0NCg0KZGVuZ2FuIFwoayxsPTEsMixcbGRvdHMsNVwpLCBzZWRhbmdrYW4gXCh1XCkgZGFuIFwodlwpIG1lcnVwYWthbiBpbmRla3MgYmFyaXMgZGFuIGtvbG9tIGtlcm5lbC4NCg0KUGFkYSBzZXRpYXAgcG9zaXNpLCBrZXJuZWwgbWVuY2FrdXAgYXJlYSBiZXJ1a3VyYW4gXCgzXHRpbWVzM1wpLiBLYXJlbmEgKnN0cmlkZSogYmVybmlsYWkgXCgxXCksIGtlcm5lbCBiZXJnZXNlciBzYXR1IGtvbG9tIGtlIGthbmFuIHVudHVrIG1lbmdoaXR1bmcgZWxlbWVuIGJlcmlrdXRueWEgcGFkYSBiYXJpcyBrZWx1YXJhbiB5YW5nIHNhbWEuIFNldGVsYWggbWVuY2FwYWkgcG9zaXNpIHRlcmFraGlyIHBhZGEgYmFyaXMgdGVyc2VidXQsIGtlcm5lbCBrZW1iYWxpIGtlIHNpc2kga2lyaSBkYW4gYmVyZ2VzZXIgc2F0dSBiYXJpcyBrZSBiYXdhaC4NCg0KLSAqKkNvbnRvaCBQZXJoaXR1bmdhbiBLb252b2x1c2k6KioNCg0KKioxLiBQZXJoaXR1bmdhbiBlbGVtZW4gcGFkYSBwb3Npc2kgXCgoMSwxKVwpKioNCg0KVW50dWsgbWVuZ2hhc2lsa2FuIGVsZW1lbiBwZXJ0YW1hIGRhcmkgKmZlYXR1cmUgbWFwKiBrZWx1YXJhbiwga2VybmVsIGRpdGVtcGF0a2FuIHBhZGEgYXJlYSBcKDNcdGltZXMzXCkgZGkgcG9qb2sga2lyaSBhdGFzIG1hdHJpa3MgeWFuZyB0ZWxhaCBkaWJlcmkgKnplcm8gcGFkZGluZyouDQoNCkFyZWEgKmZlYXR1cmUgbWFwKiB5YW5nIGRpcHJvc2VzIGFkYWxhaDoNCg0KXFsNClxiZWdpbntibWF0cml4fQ0KMC4wMCAmIDAuMDAgJiAwLjAwXFwNCjAuMDAgJiAtMi4xMiAmIC0xLjAyXFwNCjAuMDAgJiAtMi4xMiAmIC0wLjc1DQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KQXJlYSB0ZXJzZWJ1dCBkaWthbGlrYW4gc2VjYXJhIGVsZW1lbiBkZW1pIGVsZW1lbiBkZW5nYW4gYm9ib3Qga2VybmVsIFwoXG1hdGhiZntXfV97XG1hdGhybXtkd319XCksIGtlbXVkaWFuIHNlbHVydWggaGFzaWwgcGVya2FsaWFuIGRpanVtbGFoa2FuIHNlYmFnYWkgYmVyaWt1dDoNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0KRl97XG1hdGhybXtkd30sMSwxfQ0KPXt9Jg0KKDAuMDApKDAuMDApDQorKDAuMDApKDAuMTApDQorKDAuMDApKDAuMDApXFwNCiYrKDAuMDApKDAuMTApDQorKC0yLjEyKSgwLjYwKQ0KKygtMS4wMikoMC4xMClcXA0KJisoMC4wMCkoMC4wMCkNCisoLTIuMTIpKDAuMTApDQorKC0wLjc1KSgwLjAwKVxcDQo9e30mDQotMS4yNzItMC4xMDItMC4yMTJcXA0KPXt9Ji0xLjU4Ni4NClxlbmR7YWxpZ25lZH0NClxdDQoNCkhhc2lsIHBlcmthbGlhbiBiZXJkYXNhcmthbiBuaWxhaSBtYXN1a2FuIHlhbmcgZGl0YW1waWxrYW4gYWRhbGFoIFwoLTEuNTg2XCkuIFBhZGEgbWF0cmlrcyBpbHVzdHJhc2kgeWFuZyB0ZWxhaCBkaXN1c3VuIHNlYmVsdW1ueWEsIGVsZW1lbiBpbmkgdGVyY2F0YXQgc2ViZXNhciBcKC0xLjU4XCkuIE5pbGFpIHRlcnNlYnV0IGRpcGVydGFoYW5rYW4gc2VtZW50YXJhIGRhbiBha2FuIGRpdmFsaWRhc2kga2VtYmFsaSBiZXJzYW1hIHNlbHVydWggdGFoYXBhbiBwZXJoaXR1bmdhbi4NCg0KKioyLiBQZXJoaXR1bmdhbiBlbGVtZW4gcGFkYSBwb3Npc2kgXCgoMiwyKVwpKioNCg0KVW50dWsgbWVuZ2hpdHVuZyBlbGVtZW4gcGFkYSBwb3Npc2kgXCgoMiwyKVwpLCBrZXJuZWwgZGl0ZW1wYXRrYW4gcGFkYSBhcmVhIHlhbmcgZGltdWxhaSBkYXJpIGJhcmlzIGtlZHVhIGRhbiBrb2xvbSBrZWR1YSBtYXRyaWtzIHNldGVsYWggKnBhZGRpbmcqLiBQb3Npc2kgaW5pIGJlcmFkYSBzYXR1IGJhcmlzIGRpIGJhd2FoIGRhbiBzYXR1IGtvbG9tIGRpIGthbmFuIGRpYmFuZGluZ2thbiBwb3Npc2kgYXdhbC4NCg0KQXJlYSAqZmVhdHVyZSBtYXAqIHlhbmcgZGlwcm9zZXMgYWRhbGFoOg0KDQpcWw0KXGJlZ2lue2JtYXRyaXh9DQotMi4xMiAmIC0xLjAyICYgMS4xN1xcDQotMi4xMiAmIC0wLjc1ICYgMS40NFxcDQotMi4xMiAmIC0wLjc1ICYgMS40NA0KXGVuZHtibWF0cml4fS4NClxdDQoNClBlcmhpdHVuZ2FuIGtvbnZvbHVzaSBkaWxha3VrYW4gbWVuZ2d1bmFrYW4gYm9ib3Qga2VybmVsIHlhbmcgc2FtYToNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0KRl97XG1hdGhybXtkd30sMiwyfQ0KPXt9Jg0KKC0yLjEyKSgwLjAwKQ0KKygtMS4wMikoMC4xMCkNCisoMS4xNykoMC4wMClcXA0KJisoLTIuMTIpKDAuMTApDQorKC0wLjc1KSgwLjYwKQ0KKygxLjQ0KSgwLjEwKVxcDQomKygtMi4xMikoMC4wMCkNCisoLTAuNzUpKDAuMTApDQorKDEuNDQpKDAuMDApXFwNCj17fSYNCi0wLjEwMi0wLjIxMi0wLjQ1MFxcDQomKzAuMTQ0LTAuMDc1XFwNCj17fSYtMC42OTUuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpIYXNpbCBwZXJrYWxpYW4gYmVyZGFzYXJrYW4gbmlsYWkgbWFzdWthbiB5YW5nIGRpdGFtcGlsa2FuIGFkYWxhaCBcKC0wLjY5NVwpLiBQYWRhIG1hdHJpa3MgaWx1c3RyYXNpIHNlYmVsdW1ueWEsIGVsZW1lbiBpbmkgdGVyY2F0YXQgc2ViZXNhciBcKC0wLjY5XCkuIE5pbGFpIHRlcnNlYnV0IGp1Z2EgZGlwZXJ0YWhhbmthbiBzZW1lbnRhcmEgaGluZ2dhIHByb3NlcyB2YWxpZGFzaSBudW1lcmlrIGRpbGFrdWthbi4NCg0KUHJvc2VkdXIgeWFuZyBzYW1hIGRpdGVyYXBrYW4gcGFkYSBzZWx1cnVoIHBvc2lzaSBrZXJuZWwuIFBhZGEgc2V0aWFwIHBvc2lzaSwgZWxlbWVuLWVsZW1lbiBkYWxhbSBhcmVhIGtvbnZvbHVzaSBkaWthbGlrYW4gZGVuZ2FuIGJvYm90IGtlcm5lbCB5YW5nIGJlcnNlc3VhaWFuLCBrZW11ZGlhbiBzZWx1cnVoIGhhc2lsIHBlcmthbGlhbiBkaWp1bWxhaGthbiB1bnR1ayBtZW1iZW50dWsgc2F0dSBlbGVtZW4gKmZlYXR1cmUgbWFwKiBrZWx1YXJhbi4NCg0KTWF0cmlrcyBoYXNpbCAqZGVwdGh3aXNlIGNvbnZvbHV0aW9uKiB5YW5nIGRpZ3VuYWthbiBzZW1lbnRhcmEgZGFsYW0gaWx1c3RyYXNpIGluaSBhZGFsYWg6DQoNClxbDQpcbWF0aGJme0Z9X3tcbWF0aHJte2R3fX0NCj0NClxiZWdpbntibWF0cml4fQ0KLTEuNTggJiAtMC43OCAmIDAuODEgJiAwLjQyICYgLTEuMDJcXA0KLTEuNzcgJiAtMC42OSAmIDEuMTQgJiAwLjY5ICYgLTEuMDdcXA0KLTEuNzcgJiAtMC42OCAmIDEuMTQgJiAwLjY5ICYgLTEuMDdcXA0KLTEuNzcgJiAtMC44MyAmIDAuODUgJiAwLjQwICYgLTEuMTlcXA0KLTEuNTMgJiAtMS4wMyAmIDAuMTggJiAtMC4xOSAmIC0xLjIwDQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KTWF0cmlrcyB0ZXJzZWJ1dCBtZW1wZXJ0YWhhbmthbiBuaWxhaSBwYWRhIGlsdXN0cmFzaSBzZWJlbHVtbnlhIGRhbiBha2FuIGRpcGVyaWtzYSBrZW1iYWxpIG1lbGFsdWkgcGVyaGl0dW5nYW4gbnVtZXJpayB1bnR1ayBtZW1hc3Rpa2FuIGtvbnNpc3RlbnNpIHNlbHVydWggdGFoYXBhbi4NCg0KLSAqKkZ1bmdzaSBBa3RpdmFzaSBTd2lzaDoqKg0KDQpTZXRlbGFoIG9wZXJhc2kgKmRlcHRod2lzZSBjb252b2x1dGlvbiosIGZ1bmdzaSBha3RpdmFzaSBTd2lzaCBkaXRlcmFwa2FuIHNlY2FyYSBlbGVtZW4gZGVtaSBlbGVtZW4gcGFkYSAqZmVhdHVyZSBtYXAqIHlhbmcgZGloYXNpbGthbi4NCg0KUnVtdXMgZnVuZ3NpIGFrdGl2YXNpIFN3aXNoIGFkYWxhaDoNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0KTF97aSxqfQ0KJj0NClxvcGVyYXRvcm5hbWV7U3dpc2h9DQpcbGVmdCgNCkZfe1xtYXRocm17ZHd9LGksan0NClxyaWdodClcXA0KJj0NClxmcmFje0Zfe1xtYXRocm17ZHd9LGksan19DQp7MStlXnstRl97XG1hdGhybXtkd30saSxqfX19Lg0KXGVuZHthbGlnbmVkfQ0KXF0NCg0KLSAqKkNvbnRvaCBQZXJoaXR1bmdhbjoqKg0KDQpVbnR1ayBlbGVtZW4gcGFkYSBwb3Npc2kgXCgoMSwxKVwpLCBuaWxhaSB5YW5nIGRpZ3VuYWthbiBzZXN1YWkgZGVuZ2FuIG1hdHJpa3MgaGFzaWwgKmRlcHRod2lzZSBjb252b2x1dGlvbiogcGFkYSBpbHVzdHJhc2kgc2ViZWx1bW55YSwgeWFpdHUgXCgtMS41OFwpLg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpMX3sxLDF9DQomPVxvcGVyYXRvcm5hbWV7U3dpc2h9KC0xLjU4KVxcDQomPVxmcmFjey0xLjU4fXsxK2Veey0oLTEuNTgpfX1cXA0KJj1cZnJhY3stMS41OH17MStlXnsxLjU4fX1cXA0KJj1cZnJhY3stMS41OH17MSs0Ljg1fVxcDQomPVxmcmFjey0xLjU4fXs1Ljg1fVxcDQomPS0wLjI3Lg0KXGVuZHthbGlnbmVkfQ0KXF0NCg0KQmVyZGFzYXJrYW4gcGVuZXJhcGFuIGZ1bmdzaSBha3RpdmFzaSBTd2lzaCBwYWRhIG1hdHJpa3MgaWx1c3RyYXNpIHNlYmVsdW1ueWEsIGRpcGVyb2xlaDoNCg0KXFsNClxtYXRoYmZ7TH0NCj0NClxiZWdpbntibWF0cml4fQ0KLTAuMjcgJiAtMC4yNSAmIDAuNTYgJiAwLjI2ICYgLTAuMjdcXA0KLTAuMjYgJiAtMC4yMyAmIDAuODcgJiAwLjQ2ICYgLTAuMjdcXA0KLTAuMjYgJiAtMC4yMyAmIDAuODcgJiAwLjQ2ICYgLTAuMjdcXA0KLTAuMjYgJiAtMC4yNSAmIDAuNjAgJiAwLjI0ICYgLTAuMjhcXA0KLTAuMjcgJiAtMC4yNyAmIDAuMTAgJiAtMC4wOSAmIC0wLjI4DQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KTWF0cmlrcyBcKFxtYXRoYmZ7TH1cKSBtZXJ1cGFrYW4gcmVwcmVzZW50YXNpIGxva2FsIHNldGVsYWggcGVuZXJhcGFuIGZ1bmdzaSBha3RpdmFzaSBTd2lzaCBkYW4gZGlndW5ha2FuIHNlYmFnYWkgbWFzdWthbiBwYWRhIHRhaGFwIHByb3lla3NpICpwb2ludHdpc2UgY29udm9sdXRpb24qIGJlcmlrdXRueWEuIE5pbGFpIG1hdHJpa3MgaW5pIGRpcGVydGFoYW5rYW4gc2VzdWFpIGlsdXN0cmFzaSBzZWJlbHVtbnlhIGhpbmdnYSBkaWxha3VrYW4gdmFsaWRhc2kgbnVtZXJpayBzZWNhcmEgbWVueWVsdXJ1aC4NCg0KDQojIyMgYi4gUHJveWVrc2kgUG9pbnR3aXNlIENvbnZvbHV0aW9uIGRhbiBUb2tlbmlzYXNpDQoNCipGZWF0dXJlIG1hcCogbG9rYWwgXChcbWF0aGJme0x9XCkgbWVtaWxpa2kgZGltZW5zaSBcKDVcdGltZXM1XHRpbWVzMVwpLiBTZWxhbmp1dG55YSwgKnBvaW50d2lzZSBjb252b2x1dGlvbiogXCgxXHRpbWVzMVwpIGRpdGVyYXBrYW4gc2VjYXJhIGluZGVwZW5kZW4gcGFkYSBzZXRpYXAgcG9zaXNpIHNwYXNpYWwuIEJlcmJlZGEgZGVuZ2FuICpkZXB0aHdpc2UgY29udm9sdXRpb24qIFwoM1x0aW1lczNcKSwgb3BlcmFzaSBpbmkgdGlkYWsgbWVsaWJhdGthbiBwaWtzZWwgdGV0YW5nZ2EsIHRldGFwaSBtZW1wcm95ZWtzaWthbiBzYXR1IGthbmFsIG1hc3VrYW4gbWVuamFkaSBkdWEga2FuYWwga2VsdWFyYW4uDQoNClByb3lla3NpIHRlcnNlYnV0IG1lbmdoYXNpbGthbiB2ZWt0b3IgZml0dXIgYmVyZGltZW5zaSBkdWEgcGFkYSBzZXRpYXAgcG9zaXNpIHNwYXNpYWwgeWFuZyBzZWxhbmp1dG55YSBkaWd1bmFrYW4gc2ViYWdhaSAqZW1iZWRkaW5nKiB0b2tlbiB1bnR1ayBtYXN1a2FuIFRyYW5zZm9ybWVyLiBKdW1sYWggZHVhIGthbmFsIGRpZ3VuYWthbiBzZWJhZ2FpIHBlbnllZGVyaGFuYWFuIGlsdXN0cmFzaSBwZXJoaXR1bmdhbiBtYW51YWwgYWdhciBwZW1iZW50dWthbiB0b2tlbiBzZXJ0YSBvcGVyYXNpIFF1ZXJ5LCBLZXksIGRhbiBWYWx1ZSBkYXBhdCBkaXR1bmp1a2thbiBzZWNhcmEgZWtzcGxpc2l0LiBQYWRhIGltcGxlbWVudGFzaSBNb2JpbGVWaVR2My12MS1TIHNlYmVuYXJueWEsIGp1bWxhaCBrYW5hbCBkaXRlbnR1a2FuIGJlcmRhc2Fya2FuIGtvbmZpZ3VyYXNpIGFyc2l0ZWt0dXIuDQoNCi0gKipCb2JvdCAqcG9pbnR3aXNlIGNvbnZvbHV0aW9uKjoqKg0KDQpQYWRhIGlsdXN0cmFzaSBpbmksIG1hdHJpa3MgYm9ib3QgKnBvaW50d2lzZSBjb252b2x1dGlvbiogZGl0ZXRhcGthbiBzZWJhZ2FpOg0KDQpcWw0KXG1hdGhiZntXfV97XG1hdGhybXtwd319XnsoXG1hdGhybXt0b2t9KX0NCj0NClxiZWdpbntibWF0cml4fQ0KMS4wMCAmIC0wLjUwDQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KTWF0cmlrcyBib2JvdCBcKFxtYXRoYmZ7V31fe1xtYXRocm17cHd9fV57KFxtYXRocm17dG9rfSl9XCkgYmVyZGltZW5zaSBcKDFcdGltZXMyXCksIHNlaGluZ2dhIHNldGlhcCBuaWxhaSBwYWRhICpmZWF0dXJlIG1hcCogbG9rYWwgZGlwcm95ZWtzaWthbiBtZW5qYWRpIHZla3RvciBkZW5nYW4gZHVhIGVsZW1lbi4NCg0KLSAqKlJ1bXVzOioqDQoNClVudHVrIHNldGlhcCBwb3Npc2kgc3Bhc2lhbCBcKChpLGopXCksIGVsZW1lbiBrZS1cKG5cKSBkYXJpIHRva2VuIGtlLVwodFwpIGRpaGl0dW5nIG1lbmdndW5ha2FuOg0KDQpcWw0KVF97dCxufQ0KPQ0KXHN1bV97bT0xfV57Q19MfQ0KV197XG1hdGhybXtwd30sbSxufV57KFxtYXRocm17dG9rfSl9DQpMX3tpLGosbX0sDQpccXF1YWQNCnQ9NShpLTEpK2ouDQpcXQ0KDQpQYWRhIGlsdXN0cmFzaSBpbmksIFwoQ19MPTFcKSBkYW4gXChuPTEsMlwpLiBEZW5nYW4gZGVtaWtpYW4sIHBlcnNhbWFhbiB0ZXJzZWJ1dCBkYXBhdCBkaXNlZGVyaGFuYWthbiBtZW5qYWRpOg0KDQpcWw0KXG1hdGhiZntUfV90DQo9DQpMX3tpLGp9DQpcbWF0aGJme1d9X3tcbWF0aHJte3B3fX1eeyhcbWF0aHJte3Rva30pfS4NClxdDQoNCkRlbmdhbiBib2JvdCB5YW5nIGRpZ3VuYWthbiwga2FuYWwga2VsdWFyYW4gcGVydGFtYSBtZW1wZXJ0YWhhbmthbiBuaWxhaSBha3RpdmFzaSBsb2thbCwgc2VkYW5na2FuIGthbmFsIGtlZHVhIGJlcm5pbGFpIFwoLTAuNTBcKSBrYWxpIGFrdGl2YXNpIGxva2FsLiBIYXNpbCBwcm95ZWtzaSBtZW1iZW50dWsgKmZlYXR1cmUgbWFwKiBiZXJkaW1lbnNpIFwoMjVcdGltZXMyXCkuDQoNCi0gKipDb250b2ggcGVyaGl0dW5nYW4gcGFkYSBwb3Npc2kgXCgoMSwxKVwpOioqDQoNCkRpa2V0YWh1aSBcKExfezEsMX09LTAuMjdcKSwgc2VoaW5nZ2E6DQoNClxbDQpcYmVnaW57YWxpZ25lZH0NClxtYXRoYmZ7VH1fMQ0KJj0NCkxfezEsMX0NClxtYXRoYmZ7V31fe1xtYXRocm17cHd9fV57KFxtYXRocm17dG9rfSl9XFwNCiY9DQooLTAuMjcpDQpcYmVnaW57Ym1hdHJpeH0NCjEuMDAgJiAtMC41MA0KXGVuZHtibWF0cml4fVxcDQomPQ0KXGJlZ2lue2JtYXRyaXh9DQooLTAuMjcpKDEuMDApICYgKC0wLjI3KSgtMC41MCkNClxlbmR7Ym1hdHJpeH1cXA0KJj0NClxiZWdpbntibWF0cml4fQ0KLTAuMjcgJiAwLjEzNQ0KXGVuZHtibWF0cml4fVxcDQomPQ0KXGJlZ2lue2JtYXRyaXh9DQotMC4yNyAmIDAuMTQNClxlbmR7Ym1hdHJpeH0uDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpQb3Npc2kgc3Bhc2lhbCBcKCgxLDEpXCkgbWVydXBha2FuIHRva2VuIHBlcnRhbWEgYmVyZGFzYXJrYW46DQoNClxbDQp0PTUoMS0xKSsxPTEuDQpcXQ0KDQotICoqVG9rZW5pc2FzaToqKg0KDQpTZXRlbGFoIHByb3lla3NpICpwb2ludHdpc2UgY29udm9sdXRpb24qLCB2ZWt0b3IgZHVhIGthbmFsIHBhZGEgc2V0aWFwIHBvc2lzaSBzcGFzaWFsIGRpc3VzdW4gbWVuamFkaSB1cnV0YW4gdG9rZW4gbWVuZ2d1bmFrYW4gdXJ1dGFuIHJhc3RlciwgeWFpdHUgZGFyaSBraXJpIGtlIGthbmFuIGRhbiBkYXJpIGF0YXMga2UgYmF3YWguIEluZGVrcyB0b2tlbiBkaXRlbnR1a2FuIG9sZWg6DQoNClxbDQp0PTUoaS0xKStqLg0KXF0NCg0KU2ViYWdhaSBjb250b2gsIHBvc2lzaSBzcGFzaWFsIFwoKDEsMSlcKSwgXCgoMSwzKVwpLCBcKCgyLDEpXCksIGRhbiBcKCg1LDUpXCkgbWFzaW5nLW1hc2luZyBiZXJrb3Jlc3BvbmRlbnNpIGRlbmdhbiB0b2tlbiBrZS0xLCBrZS0zLCBrZS02LCBkYW4ga2UtMjUuDQoNClNldGlhcCB2ZWt0b3IgdG9rZW4gZGlueWF0YWthbiBzZWJhZ2FpOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpcbWF0aGJme1R9X3QNCiY9DQpMX3tpLGosMX0NClxtYXRoYmZ7V31fe1xtYXRocm17cHd9fV57KFxtYXRocm17dG9rfSl9XFwNCiY9DQpcYmVnaW57Ym1hdHJpeH0NCkxfe2ksaiwxfSAmIC0wLjUwTF97aSxqLDF9DQpcZW5ke2JtYXRyaXh9Lg0KXGVuZHthbGlnbmVkfQ0KXF0NCg0KVmVrdG9yIHRva2VuIFwoXG1hdGhiZntUfV90XCkgYmVyZGltZW5zaSBcKDFcdGltZXMyXCkuIERlbmdhbiBtZW55dXN1biBzZWx1cnVoIDI1IHZla3RvciB0b2tlbiBiZXJkYXNhcmthbiB1cnV0YW4gcmFzdGVyLCBkaXBlcm9sZWggbWF0cmlrcyBcKFxtYXRoYmZ7VH1cKSBiZXJkaW1lbnNpIFwoMjVcdGltZXMyXCk6DQoNClxbDQpcbWF0aGJme1R9DQo9DQpcYmVnaW57Ym1hdHJpeH0NCi0wLjI3ICYgMC4xM1xcDQotMC4yNSAmIDAuMTJcXA0KMC41NiAmIC0wLjI4XFwNCjAuMjYgJiAtMC4xM1xcDQotMC4yNyAmIDAuMTRcXA0KLTAuMjYgJiAwLjEzXFwNCi0wLjIzICYgMC4xMlxcDQowLjg3ICYgLTAuNDNcXA0KMC40NiAmIC0wLjIzXFwNCi0wLjI3ICYgMC4xNFxcDQotMC4yNiAmIDAuMTNcXA0KLTAuMjMgJiAwLjExXFwNCjAuODcgJiAtMC40M1xcDQowLjQ2ICYgLTAuMjNcXA0KLTAuMjcgJiAwLjE0XFwNCi0wLjI2ICYgMC4xM1xcDQotMC4yNSAmIDAuMTNcXA0KMC42MCAmIC0wLjMwXFwNCjAuMjQgJiAtMC4xMlxcDQotMC4yOCAmIDAuMTRcXA0KLTAuMjcgJiAwLjE0XFwNCi0wLjI3ICYgMC4xNFxcDQowLjEwICYgLTAuMDVcXA0KLTAuMDkgJiAwLjA0XFwNCi0wLjI4ICYgMC4xNA0KXGVuZHtibWF0cml4fS4NClxdDQoNCg0KDQojIyAzLiBUcmFuc2Zvcm1lciBNb2JpbGVWaVR2My12MS1TIChTZWxmLUF0dGVudGlvbikNCg0KIyMjIGEuIE5vcm1hbGlzYXNpIFRva2VuDQoNClNlYmVsdW0gbWVtYXN1a2kgbWVrYW5pc21lICpzZWxmLWF0dGVudGlvbiosIHNldGlhcCB0b2tlbiBwYWRhIG1hdHJpa3MgXChcbWF0aGJme1R9XCkgZGlub3JtYWxpc2FzaSBtZW5nZ3VuYWthbiAqTGF5ZXIgTm9ybWFsaXphdGlvbiogKExOKS4gTm9ybWFsaXNhc2kgZGlsYWt1a2FuIHNlY2FyYSBpbmRlcGVuZGVuIHBhZGEgc2V0aWFwIHRva2VuLCBzZWhpbmdnYSByYXRhLXJhdGEgZGFuIHZhcmlhbnMgZGloaXR1bmcgYmVyZGFzYXJrYW4gZHVhIGVsZW1lbiBmaXR1ciBwYWRhIHRva2VuIHlhbmcgc2FtYS4NCg0KLSAqKlJ1bXVzOioqDQoNClVudHVrIHRva2VuIGtlLVwodFwpLCByYXRhLXJhdGEgZGFuIHZhcmlhbnMgZGloaXR1bmcgc2ViYWdhaToNCg0KXFsNClxtdV90DQo9DQpcZnJhY3sxfXsyfVxzdW1fe2s9MX1eezJ9VF97dCxrfSwNClxxcXVhZA0KXHNpZ21hX3ReMg0KPQ0KXGZyYWN7MX17Mn1cc3VtX3trPTF9XnsyfShUX3t0LGt9LVxtdV90KV4yLg0KXF0NCg0KU2VsYW5qdXRueWEsIGVsZW1lbiBrZS1cKGtcKSBwYWRhIHRva2VuIGtlLVwodFwpIGRpbm9ybWFsaXNhc2kgbWVuZ2d1bmFrYW46DQoNClxbDQpbXG9wZXJhdG9ybmFtZXtMTn0oXG1hdGhiZntUfSldX3t0LGt9DQo9DQpcZnJhY3tUX3t0LGt9LVxtdV90fQ0Ke1xzcXJ0e1xzaWdtYV90XjIrXHZhcmVwc2lsb259fSwNClxxcXVhZA0KXHZhcmVwc2lsb249MTBeey01fS4NClxdDQoNCk1hdHJpa3MgdG9rZW4gXChcbWF0aGJme1R9XCkgYmVyZGltZW5zaSBcKDI1XHRpbWVzMlwpLCBzZWhpbmdnYSBtYXRyaWtzIGhhc2lsIG5vcm1hbGlzYXNpIFwoXG9wZXJhdG9ybmFtZXtMTn0oXG1hdGhiZntUfSlcKSBqdWdhIGJlcmRpbWVuc2kgXCgyNVx0aW1lczJcKS4NCg0KLSAqKkNvbnRvaCBwZXJoaXR1bmdhbiB1bnR1ayB0b2tlbiBwZXJ0YW1hOioqDQoNCkRpa2V0YWh1aSB2ZWt0b3IgdG9rZW4gcGVydGFtYSBhZGFsYWg6DQoNClxbDQpcbWF0aGJme1R9XzENCj0NClxiZWdpbntibWF0cml4fQ0KLTAuMjcgJiAwLjEzDQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KUmF0YS1yYXRhIHRva2VuIHBlcnRhbWEgZGloaXR1bmcgc2ViYWdhaToNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0KXG11XzENCiY9XGZyYWN7VF97MSwxfStUX3sxLDJ9fXsyfVxcDQomPVxmcmFjey0wLjI3KzAuMTN9ezJ9XFwNCiY9XGZyYWN7LTAuMTR9ezJ9XFwNCiY9LTAuMDcuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpWYXJpYW5zIHRva2VuIHBlcnRhbWEgZGlwZXJvbGVoOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpcc2lnbWFfMV4yDQomPVxmcmFjeyhUX3sxLDF9LVxtdV8xKV4yKyhUX3sxLDJ9LVxtdV8xKV4yfXsyfVxcDQomPVxmcmFjeygtMC4yNy0oLTAuMDcpKV4yKygwLjEzLSgtMC4wNykpXjJ9ezJ9XFwNCiY9XGZyYWN7KC0wLjIwKV4yKygwLjIwKV4yfXsyfVxcDQomPVxmcmFjezAuMDQrMC4wNH17Mn1cXA0KJj0wLjA0Lg0KXGVuZHthbGlnbmVkfQ0KXF0NCg0KU2VsYW5qdXRueWEsIGVsZW1lbiBwZXJ0YW1hIHRva2VuIGRpbm9ybWFsaXNhc2kgc2ViYWdhaToNCg0KDQoNCg0KJCQNClxiZWdpbnthbGlnbmVkfQ0KXGxlZnRbXG1hdGhybXtMTn0oXG1hdGhiZntUfSlccmlnaHRdX3sxLDF9DQomPSBcZnJhY3tUX3sxLDF9LVxtdV8xfXtcc3FydHtcc2lnbWFfMV4yK1x2YXJlcHNpbG9ufX1cXA0KJj0gXGZyYWN7LTAuMjctKC0wLjA3KX17XHNxcnR7MC4wNCsxMF57LTV9fX1cXA0KJj0gXGZyYWN7LTAuMjB9e1xzcXJ0ezAuMDQrMTBeey01fX19XFwNCiY9IFxmcmFjey0wLjIwfXswLjIwfVxcDQomPSAtMS4wMA0KXGVuZHthbGlnbmVkfQ0KJCQNCg0KRGVuZ2FuIHBlcmhpdHVuZ2FuIHlhbmcgc2FtYSwgZWxlbWVuIGtlZHVhIHRva2VuIHBlcnRhbWEgZGlwZXJvbGVoOg0KDQpcWw0KW1xvcGVyYXRvcm5hbWV7TE59KFxtYXRoYmZ7VH0pXV97MSwyfQ0KPTEuMDAuDQpcXQ0KDQpEZW5nYW4gZGVtaWtpYW4sIGhhc2lsIG5vcm1hbGlzYXNpIHRva2VuIHBlcnRhbWEgYWRhbGFoOg0KDQpcWw0KW1xvcGVyYXRvcm5hbWV7TE59KFxtYXRoYmZ7VH0pXV97MX0NCj0NClxiZWdpbntibWF0cml4fQ0KLTEuMDAgJiAxLjAwDQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KUHJvc2VzIG5vcm1hbGlzYXNpIHlhbmcgc2FtYSBkaXRlcmFwa2FuIHBhZGEgc2VsdXJ1aCB0b2tlbiwgc2VoaW5nZ2EgZGlwZXJvbGVoIG1hdHJpa3MgdG9rZW4gdGVybm9ybWFsaXNhc2kgYmVydWt1cmFuIFwoMjVcdGltZXMyXCkgc2ViYWdhaSBiZXJpa3V0Og0KDQpcWw0KXG9wZXJhdG9ybmFtZXtMTn0oXG1hdGhiZntUfSkNCj0NClxiZWdpbntibWF0cml4fQ0KLTEuMDAgJiAxLjAwXFwNCi0xLjAwICYgMS4wMFxcDQoxLjAwICYgLTEuMDBcXA0KMS4wMCAmIC0xLjAwXFwNCi0xLjAwICYgMS4wMFxcDQotMS4wMCAmIDEuMDBcXA0KLTEuMDAgJiAxLjAwXFwNCjEuMDAgJiAtMS4wMFxcDQoxLjAwICYgLTEuMDBcXA0KLTEuMDAgJiAxLjAwXFwNCi0xLjAwICYgMS4wMFxcDQotMS4wMCAmIDEuMDBcXA0KMS4wMCAmIC0xLjAwXFwNCjEuMDAgJiAtMS4wMFxcDQotMS4wMCAmIDEuMDBcXA0KLTEuMDAgJiAxLjAwXFwNCi0xLjAwICYgMS4wMFxcDQoxLjAwICYgLTEuMDBcXA0KMS4wMCAmIC0xLjAwXFwNCi0xLjAwICYgMS4wMFxcDQotMS4wMCAmIDEuMDBcXA0KLTEuMDAgJiAxLjAwXFwNCi0xLjAwICYgMS4wMFxcDQoxLjAwICYgLTEuMDBcXA0KLTEuMDAgJiAxLjAwXFwNCi0xLjAwICYgMS4wMA0KXGVuZHtibWF0cml4fS4NClxdDQoNCg0KDQojIyMgYi4gUHJveWVrc2kgUXVlcnkNCg0KU2V0ZWxhaCB0b2tlbiBkaW5vcm1hbGlzYXNpLCBzZXRpYXAgdG9rZW4gZGlwcm95ZWtzaWthbiBtZW5qYWRpICpRdWVyeSogKFEpLiBRdWVyeSBtZXJlcHJlc2VudGFzaWthbiBpbmZvcm1hc2kgeWFuZyBkaWNhcmkgb2xlaCBzZXRpYXAgdG9rZW4ga2V0aWthIG1lbmdoaXR1bmcgaHVidW5nYW4gZGVuZ2FuIHRva2VuLXRva2VuIGxhaW4gbWVsYWx1aSBtZWthbmlzbWUgKnNlbGYtYXR0ZW50aW9uKi4NCg0KLSAqKkJvYm90IFF1ZXJ5OioqDQoNClBhZGEgaWx1c3RyYXNpIGluaSwgbWF0cmlrcyBib2JvdCBwcm95ZWtzaSBRdWVyeSBkaXRldGFwa2FuIHNlYmFnYWk6DQoNClxbDQpcbWF0aGJme1d9X1ENCj0NCjAuNTBcbWF0aGJme0l9DQo9DQpcYmVnaW57Ym1hdHJpeH0NCjAuNTAgJiAwLjAwXFwNCjAuMDAgJiAwLjUwDQpcZW5ke2JtYXRyaXh9LA0KXF0NCg0KZGVuZ2FuIFwoXG1hdGhiZntJfVwpIG1lcnVwYWthbiBtYXRyaWtzIGlkZW50aXRhcyBiZXJ1a3VyYW4gXCgyXHRpbWVzMlwpLiBCb2JvdCB0ZXJzZWJ1dCBtZW5nYWxpa2FuIHNldGlhcCBlbGVtZW4gdG9rZW4gdGVybm9ybWFsaXNhc2kgZGVuZ2FuIFwoMC41MFwpLCB0YW5wYSBtZW5jYW1wdXJrYW4gaW5mb3JtYXNpIGFudGFyYSBrZWR1YSBrYW5hbCBmaXR1ci4NCg0KLSAqKlJ1bXVzOioqDQoNClByb3lla3NpIFF1ZXJ5IGRpcnVtdXNrYW4gc2ViYWdhaToNCg0KXFsNClxtYXRoYmZ7UX0NCj0NClxvcGVyYXRvcm5hbWV7TE59KFxtYXRoYmZ7VH0pXG1hdGhiZntXfV9RLg0KXF0NCg0KVW50dWsgdG9rZW4ga2UtXCh0XCksIHBlcnNhbWFhbiB0ZXJzZWJ1dCBkYXBhdCBkaXR1bGlza2FuIHNlYmFnYWk6DQoNClxbDQpcYmVnaW57YWxpZ25lZH0NClxtYXRoYmZ7UX1fdA0KJj0NCltcb3BlcmF0b3JuYW1le0xOfShcbWF0aGJme1R9KV1fe3R9XG1hdGhiZntXfV9RXFwNCiY9DQpcYmVnaW57Ym1hdHJpeH0NCltcb3BlcmF0b3JuYW1le0xOfShcbWF0aGJme1R9KV1fe3QsMX0gJg0KW1xvcGVyYXRvcm5hbWV7TE59KFxtYXRoYmZ7VH0pXV97dCwyfQ0KXGVuZHtibWF0cml4fQ0KXGJlZ2lue2JtYXRyaXh9DQowLjUwICYgMC4wMFxcDQowLjAwICYgMC41MA0KXGVuZHtibWF0cml4fS4NClxlbmR7YWxpZ25lZH0NClxdDQoNCk1hdHJpa3MgaGFzaWwgbm9ybWFsaXNhc2kgXChcb3BlcmF0b3JuYW1le0xOfShcbWF0aGJme1R9KVwpIGJlcnVrdXJhbiBcKDI1XHRpbWVzMlwpLCBzZWRhbmdrYW4gbWF0cmlrcyBib2JvdCBcKFxtYXRoYmZ7V31fUVwpIGJlcnVrdXJhbiBcKDJcdGltZXMyXCkuIERlbmdhbiBkZW1pa2lhbiwgbWF0cmlrcyBRdWVyeSBcKFxtYXRoYmZ7UX1cKSBiZXJ1a3VyYW4gXCgyNVx0aW1lczJcKS4NCg0KLSAqKkNvbnRvaCBwZXJoaXR1bmdhbiB1bnR1ayB0b2tlbiBwZXJ0YW1hOioqDQoNCkJlcmRhc2Fya2FuIHRhaGFwIG5vcm1hbGlzYXNpIHRva2VuIHNlYmVsdW1ueWEsIGhhc2lsIG5vcm1hbGlzYXNpIHRva2VuIHBlcnRhbWEgeWFuZyBkaXRhbXBpbGthbiBkZW5nYW4gZHVhIGFuZ2thIGRlc2ltYWwgYWRhbGFoOg0KDQpcWw0KW1xvcGVyYXRvcm5hbWV7TE59KFxtYXRoYmZ7VH0pXV97MX0NCj0NClxiZWdpbntibWF0cml4fQ0KLTEuMDAgJiAxLjAwDQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KU2VsYW5qdXRueWEsIFF1ZXJ5IHVudHVrIHRva2VuIHBlcnRhbWEgZGloaXR1bmcgc2ViYWdhaToNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0KXG1hdGhiZntRfV8xDQomPQ0KW1xvcGVyYXRvcm5hbWV7TE59KFxtYXRoYmZ7VH0pXV97MX1cbWF0aGJme1d9X1FcXA0KJj0NClxiZWdpbntibWF0cml4fQ0KLTEuMDAgJiAxLjAwDQpcZW5ke2JtYXRyaXh9DQpcYmVnaW57Ym1hdHJpeH0NCjAuNTAgJiAwLjAwXFwNCjAuMDAgJiAwLjUwDQpcZW5ke2JtYXRyaXh9XFwNCiY9DQpcYmVnaW57Ym1hdHJpeH0NCigtMS4wMCkoMC41MCkrKDEuMDApKDAuMDApICYNCigtMS4wMCkoMC4wMCkrKDEuMDApKDAuNTApDQpcZW5ke2JtYXRyaXh9XFwNCiY9DQpcYmVnaW57Ym1hdHJpeH0NCi0wLjUwICYgMC41MA0KXGVuZHtibWF0cml4fS4NClxlbmR7YWxpZ25lZH0NClxdDQoNCkRlbmdhbiBkZW1pa2lhbiwgZWxlbWVuIFF1ZXJ5IHVudHVrIHRva2VuIHBlcnRhbWEgYWRhbGFoOg0KDQpcWw0KUV97MSwxfT0tMC41MCwNClxxcXVhZA0KUV97MSwyfT0wLjUwLg0KXF0NCg0KUHJvc2VzIHByb3lla3NpIHlhbmcgc2FtYSBkaXRlcmFwa2FuIHBhZGEgc2VsdXJ1aCB0b2tlbi4gRGVuZ2FuIG1lbmFtcGlsa2FuIGhhc2lsIGhpbmdnYSBkdWEgYW5na2EgZGVzaW1hbCwgZGlwZXJvbGVoIG1hdHJpa3MgUXVlcnkgYmVydWt1cmFuIFwoMjVcdGltZXMyXCkgc2ViYWdhaSBiZXJpa3V0Og0KDQpcWw0KXG1hdGhiZntRfQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQotMC41MCAmIDAuNTBcXA0KLTAuNTAgJiAwLjUwXFwNCjAuNTAgJiAtMC41MFxcDQowLjUwICYgLTAuNTBcXA0KLTAuNTAgJiAwLjUwXFwNCi0wLjUwICYgMC41MFxcDQotMC41MCAmIDAuNTBcXA0KMC41MCAmIC0wLjUwXFwNCjAuNTAgJiAtMC41MFxcDQotMC41MCAmIDAuNTBcXA0KLTAuNTAgJiAwLjUwXFwNCi0wLjUwICYgMC41MFxcDQowLjUwICYgLTAuNTBcXA0KMC41MCAmIC0wLjUwXFwNCi0wLjUwICYgMC41MFxcDQotMC41MCAmIDAuNTBcXA0KLTAuNTAgJiAwLjUwXFwNCjAuNTAgJiAtMC41MFxcDQowLjUwICYgLTAuNTBcXA0KLTAuNTAgJiAwLjUwXFwNCi0wLjUwICYgMC41MFxcDQotMC41MCAmIDAuNTBcXA0KMC41MCAmIC0wLjUwXFwNCi0wLjUwICYgMC41MFxcDQotMC41MCAmIDAuNTANClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQoNCg0KIyMjIGMuIFByb3lla3NpIEtleQ0KDQpTZXRlbGFoIHRva2VuIGRpbm9ybWFsaXNhc2ksIHNldGlhcCB0b2tlbiBqdWdhIGRpcHJveWVrc2lrYW4gbWVuamFkaSAqS2V5KiAoSykuIFBhZGEgbWVrYW5pc21lICpzZWxmLWF0dGVudGlvbiosIEtleSBiZXJmdW5nc2kgc2ViYWdhaSByZXByZXNlbnRhc2kgcGVtYmFuZGluZy4gU2V0aWFwIFF1ZXJ5IGRpYmFuZGluZ2thbiBkZW5nYW4gc2VsdXJ1aCBLZXkgdW50dWsgbWVuZW50dWthbiB0aW5na2F0IGtldGVya2FpdGFuIGFudGFydG9rZW4uDQoNCi0gKipCb2JvdCBLZXk6KioNCg0KUGFkYSBpbHVzdHJhc2kgaW5pLCBtYXRyaWtzIGJvYm90IHByb3lla3NpIEtleSBkaXRldGFwa2FuIHNlYmFnYWk6DQoNClxbDQpcbWF0aGJme1d9X0sNCj0NClxiZWdpbntibWF0cml4fQ0KMC40MCAmIDAuMDBcXA0KMC4wMCAmIDAuNjANClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQpCb2JvdCB0ZXJzZWJ1dCBtZW1iZXJpa2FuIHNrYWxhIHlhbmcgYmVyYmVkYSBwYWRhIGtvbXBvbmVuIHBlcnRhbWEgZGFuIGtlZHVhIGRhcmkgc2V0aWFwIHRva2VuIHRlcm5vcm1hbGlzYXNpLCB0YW5wYSBtZW5jYW1wdXJrYW4gaW5mb3JtYXNpIGFudGFyYSBrZWR1YSBrb21wb25lbiBmaXR1ci4NCg0KLSAqKlJ1bXVzOioqDQoNClByb3lla3NpIEtleSBkaXJ1bXVza2FuIHNlYmFnYWk6DQoNClxbDQpcbWF0aGJme0t9DQo9DQpcb3BlcmF0b3JuYW1le0xOfShcbWF0aGJme1R9KVxtYXRoYmZ7V31fSy4NClxdDQoNClVudHVrIHRva2VuIGtlLVwodFwpLCBwZXJzYW1hYW4gdGVyc2VidXQgZGFwYXQgZGl0dWxpc2thbiBzZWJhZ2FpOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpcbWF0aGJme0t9X3QNCiY9DQpbXG9wZXJhdG9ybmFtZXtMTn0oXG1hdGhiZntUfSldX3t0fVxtYXRoYmZ7V31fS1xcDQomPQ0KXGJlZ2lue2JtYXRyaXh9DQpbXG9wZXJhdG9ybmFtZXtMTn0oXG1hdGhiZntUfSldX3t0LDF9ICYNCltcb3BlcmF0b3JuYW1le0xOfShcbWF0aGJme1R9KV1fe3QsMn0NClxlbmR7Ym1hdHJpeH0NClxiZWdpbntibWF0cml4fQ0KMC40MCAmIDAuMDBcXA0KMC4wMCAmIDAuNjANClxlbmR7Ym1hdHJpeH0uDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpNYXRyaWtzIGhhc2lsIG5vcm1hbGlzYXNpIFwoXG9wZXJhdG9ybmFtZXtMTn0oXG1hdGhiZntUfSlcKSBiZXJ1a3VyYW4gXCgyNVx0aW1lczJcKSwgc2VkYW5na2FuIG1hdHJpa3MgYm9ib3QgXChcbWF0aGJme1d9X0tcKSBiZXJ1a3VyYW4gXCgyXHRpbWVzMlwpLiBEZW5nYW4gZGVtaWtpYW4sIG1hdHJpa3MgS2V5IFwoXG1hdGhiZntLfVwpIGJlcnVrdXJhbiBcKDI1XHRpbWVzMlwpLg0KDQotICoqQ29udG9oIHBlcmhpdHVuZ2FuIHVudHVrIHRva2VuIHBlcnRhbWE6KioNCg0KQmVyZGFzYXJrYW4gdGFoYXAgbm9ybWFsaXNhc2kgdG9rZW4gc2ViZWx1bW55YSwgaGFzaWwgbm9ybWFsaXNhc2kgdG9rZW4gcGVydGFtYSB5YW5nIGRpdGFtcGlsa2FuIGRlbmdhbiBkdWEgYW5na2EgZGVzaW1hbCBhZGFsYWg6DQoNClxbDQpbXG9wZXJhdG9ybmFtZXtMTn0oXG1hdGhiZntUfSldX3sxfQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQotMS4wMCAmIDEuMDANClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQpTZWxhbmp1dG55YSwgS2V5IHVudHVrIHRva2VuIHBlcnRhbWEgZGloaXR1bmcgc2ViYWdhaToNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0KXG1hdGhiZntLfV8xDQomPQ0KW1xvcGVyYXRvcm5hbWV7TE59KFxtYXRoYmZ7VH0pXV97MX1cbWF0aGJme1d9X0tcXA0KJj0NClxiZWdpbntibWF0cml4fQ0KLTEuMDAgJiAxLjAwDQpcZW5ke2JtYXRyaXh9DQpcYmVnaW57Ym1hdHJpeH0NCjAuNDAgJiAwLjAwXFwNCjAuMDAgJiAwLjYwDQpcZW5ke2JtYXRyaXh9XFwNCiY9DQpcYmVnaW57Ym1hdHJpeH0NCigtMS4wMCkoMC40MCkrKDEuMDApKDAuMDApICYNCigtMS4wMCkoMC4wMCkrKDEuMDApKDAuNjApDQpcZW5ke2JtYXRyaXh9XFwNCiY9DQpcYmVnaW57Ym1hdHJpeH0NCi0wLjQwICYgMC42MA0KXGVuZHtibWF0cml4fS4NClxlbmR7YWxpZ25lZH0NClxdDQoNCkRlbmdhbiBkZW1pa2lhbiwgZWxlbWVuIEtleSB1bnR1ayB0b2tlbiBwZXJ0YW1hIGFkYWxhaDoNCg0KXFsNCktfezEsMX09LTAuNDAsDQpccXF1YWQNCktfezEsMn09MC42MC4NClxdDQoNClBhZGEgaWx1c3RyYXNpIGluaSwgbWF0cmlrcyBib2JvdCBcKFxtYXRoYmZ7V31fS1wpIGRpdGV0YXBrYW4gYmVyYmVkYSBkYXJpIG1hdHJpa3MgYm9ib3QgXChcbWF0aGJme1d9X1FcKSB1bnR1ayBtZW51bmp1a2thbiBiYWh3YSBRdWVyeSBkYW4gS2V5IGRpaGFzaWxrYW4gbWVsYWx1aSBwcm95ZWtzaSB5YW5nIGJlcmJlZGEuIFBhZGEgaW1wbGVtZW50YXNpIFRyYW5zZm9ybWVyIHNlYmVuYXJueWEsIGtlZHVhIG1hdHJpa3MgYm9ib3QgdGVyc2VidXQgbWVydXBha2FuIHBhcmFtZXRlciB5YW5nIGRpcGVsYWphcmkgc2VjYXJhIHRlcnBpc2FoIHNlbGFtYSBwcm9zZXMgcGVsYXRpaGFuLg0KDQpQcm9zZXMgcHJveWVrc2kgeWFuZyBzYW1hIGRpdGVyYXBrYW4gcGFkYSBzZWx1cnVoIHRva2VuLiBEZW5nYW4gbWVuYW1waWxrYW4gaGFzaWwgaGluZ2dhIGR1YSBhbmdrYSBkZXNpbWFsLCBkaXBlcm9sZWggbWF0cmlrcyBLZXkgYmVydWt1cmFuIFwoMjVcdGltZXMyXCkgc2ViYWdhaSBiZXJpa3V0Og0KDQpcWw0KXG1hdGhiZntLfQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQotMC40MCAmIDAuNjBcXA0KLTAuNDAgJiAwLjYwXFwNCjAuNDAgJiAtMC42MFxcDQowLjQwICYgLTAuNjBcXA0KLTAuNDAgJiAwLjYwXFwNCi0wLjQwICYgMC42MFxcDQotMC40MCAmIDAuNjBcXA0KMC40MCAmIC0wLjYwXFwNCjAuNDAgJiAtMC42MFxcDQotMC40MCAmIDAuNjBcXA0KLTAuNDAgJiAwLjYwXFwNCi0wLjQwICYgMC42MFxcDQowLjQwICYgLTAuNjBcXA0KMC40MCAmIC0wLjYwXFwNCi0wLjQwICYgMC42MFxcDQotMC40MCAmIDAuNjBcXA0KLTAuNDAgJiAwLjYwXFwNCjAuNDAgJiAtMC42MFxcDQowLjQwICYgLTAuNjBcXA0KLTAuNDAgJiAwLjYwXFwNCi0wLjQwICYgMC42MFxcDQotMC40MCAmIDAuNjBcXA0KMC40MCAmIC0wLjYwXFwNCi0wLjQwICYgMC42MFxcDQotMC40MCAmIDAuNjANClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQoNCg0KIyMjIGQuIFByb3lla3NpIFZhbHVlDQoNClNldGVsYWggdG9rZW4gZGlub3JtYWxpc2FzaSwgc2V0aWFwIHRva2VuIGp1Z2EgZGlwcm95ZWtzaWthbiBtZW5qYWRpICpWYWx1ZSogKFYpLiBQYWRhIG1la2FuaXNtZSAqc2VsZi1hdHRlbnRpb24qLCBWYWx1ZSBtZW11YXQgaW5mb3JtYXNpIGZpdHVyIHlhbmcgYWthbiBkaWFncmVnYXNpa2FuIGRhcmkgc2VsdXJ1aCB0b2tlbiBiZXJkYXNhcmthbiBib2JvdCAqYXR0ZW50aW9uKiB5YW5nIGRpaGl0dW5nIG1lbGFsdWkgaW50ZXJha3NpIGFudGFyYSBRdWVyeSBkYW4gS2V5Lg0KDQotICoqQm9ib3QgVmFsdWU6KioNCg0KUGFkYSBpbHVzdHJhc2kgaW5pLCBtYXRyaWtzIGJvYm90IHByb3lla3NpIFZhbHVlIGRpdGV0YXBrYW4gc2ViYWdhaSBtYXRyaWtzIGlkZW50aXRhczoNCg0KXFsNClxtYXRoYmZ7V31fVg0KPQ0KXG1hdGhiZntJfQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQoxLjAwICYgMC4wMFxcDQowLjAwICYgMS4wMA0KXGVuZHtibWF0cml4fS4NClxdDQoNCk1hdHJpa3MgaWRlbnRpdGFzIHRpZGFrIG1lbmd1YmFoIG5pbGFpIG1hdXB1biBtZW5jYW1wdXJrYW4ga2VkdWEgZWxlbWVuIGZpdHVyIHRva2VuLiBPbGVoIGthcmVuYSBpdHUsIHBhZGEgaWx1c3RyYXNpIGluaSBtYXRyaWtzIFZhbHVlIG1lbWlsaWtpIG5pbGFpIHlhbmcgc2FtYSBkZW5nYW4gbWF0cmlrcyB0b2tlbiB5YW5nIHRlbGFoIGRpbm9ybWFsaXNhc2kuDQoNCi0gKipSdW11czoqKg0KDQpQcm95ZWtzaSBWYWx1ZSBkaXJ1bXVza2FuIHNlYmFnYWk6DQoNClxbDQpcbWF0aGJme1Z9DQo9DQpcb3BlcmF0b3JuYW1le0xOfShcbWF0aGJme1R9KVxtYXRoYmZ7V31fVg0KPQ0KXG9wZXJhdG9ybmFtZXtMTn0oXG1hdGhiZntUfSlcbWF0aGJme0l9DQo9DQpcb3BlcmF0b3JuYW1le0xOfShcbWF0aGJme1R9KS4NClxdDQoNClVudHVrIHRva2VuIGtlLVwodFwpLCBwZXJzYW1hYW4gdGVyc2VidXQgZGFwYXQgZGl0dWxpc2thbiBzZWJhZ2FpOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpcbWF0aGJme1Z9X3QNCiY9DQpbXG9wZXJhdG9ybmFtZXtMTn0oXG1hdGhiZntUfSldX3t0fVxtYXRoYmZ7V31fVlxcDQomPQ0KXGJlZ2lue2JtYXRyaXh9DQpbXG9wZXJhdG9ybmFtZXtMTn0oXG1hdGhiZntUfSldX3t0LDF9ICYNCltcb3BlcmF0b3JuYW1le0xOfShcbWF0aGJme1R9KV1fe3QsMn0NClxlbmR7Ym1hdHJpeH0NClxiZWdpbntibWF0cml4fQ0KMS4wMCAmIDAuMDBcXA0KMC4wMCAmIDEuMDANClxlbmR7Ym1hdHJpeH0uDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpNYXRyaWtzIGhhc2lsIG5vcm1hbGlzYXNpIFwoXG9wZXJhdG9ybmFtZXtMTn0oXG1hdGhiZntUfSlcKSBiZXJ1a3VyYW4gXCgyNVx0aW1lczJcKSwgc2VkYW5na2FuIG1hdHJpa3MgYm9ib3QgXChcbWF0aGJme1d9X1ZcKSBiZXJ1a3VyYW4gXCgyXHRpbWVzMlwpLiBEZW5nYW4gZGVtaWtpYW4sIG1hdHJpa3MgVmFsdWUgXChcbWF0aGJme1Z9XCkgYmVydWt1cmFuIFwoMjVcdGltZXMyXCkuDQoNCi0gKipDb250b2ggcGVyaGl0dW5nYW4gdW50dWsgdG9rZW4gcGVydGFtYToqKg0KDQpCZXJkYXNhcmthbiB0YWhhcCBub3JtYWxpc2FzaSB0b2tlbiBzZWJlbHVtbnlhLCBoYXNpbCBub3JtYWxpc2FzaSB0b2tlbiBwZXJ0YW1hIHlhbmcgZGl0YW1waWxrYW4gZGVuZ2FuIGR1YSBhbmdrYSBkZXNpbWFsIGFkYWxhaDoNCg0KXFsNCltcb3BlcmF0b3JuYW1le0xOfShcbWF0aGJme1R9KV1fezF9DQo9DQpcYmVnaW57Ym1hdHJpeH0NCi0xLjAwICYgMS4wMA0KXGVuZHtibWF0cml4fS4NClxdDQoNClNlbGFuanV0bnlhLCBWYWx1ZSB1bnR1ayB0b2tlbiBwZXJ0YW1hIGRpaGl0dW5nIHNlYmFnYWk6DQoNClxbDQpcYmVnaW57YWxpZ25lZH0NClxtYXRoYmZ7Vn1fMQ0KJj0NCltcb3BlcmF0b3JuYW1le0xOfShcbWF0aGJme1R9KV1fezF9XG1hdGhiZntXfV9WXFwNCiY9DQpcYmVnaW57Ym1hdHJpeH0NCi0xLjAwICYgMS4wMA0KXGVuZHtibWF0cml4fQ0KXGJlZ2lue2JtYXRyaXh9DQoxLjAwICYgMC4wMFxcDQowLjAwICYgMS4wMA0KXGVuZHtibWF0cml4fVxcDQomPQ0KXGJlZ2lue2JtYXRyaXh9DQooLTEuMDApKDEuMDApKygxLjAwKSgwLjAwKSAmDQooLTEuMDApKDAuMDApKygxLjAwKSgxLjAwKQ0KXGVuZHtibWF0cml4fVxcDQomPQ0KXGJlZ2lue2JtYXRyaXh9DQotMS4wMCAmIDEuMDANClxlbmR7Ym1hdHJpeH0uDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpEZW5nYW4gZGVtaWtpYW4sIGVsZW1lbiBWYWx1ZSB1bnR1ayB0b2tlbiBwZXJ0YW1hIGFkYWxhaDoNCg0KXFsNClZfezEsMX09LTEuMDAsDQpccXF1YWQNClZfezEsMn09MS4wMC4NClxdDQoNCkthcmVuYSBcKFxtYXRoYmZ7V31fVj1cbWF0aGJme0l9XCksIHNldGlhcCBiYXJpcyBwYWRhIG1hdHJpa3MgXChcbWF0aGJme1Z9XCkgbWVtaWxpa2kgbmlsYWkgeWFuZyBzYW1hIGRlbmdhbiBiYXJpcyB5YW5nIGJlcnNlc3VhaWFuIHBhZGEgbWF0cmlrcyBcKFxvcGVyYXRvcm5hbWV7TE59KFxtYXRoYmZ7VH0pXCkuIFBhZGEgaW1wbGVtZW50YXNpIFRyYW5zZm9ybWVyIHNlYmVuYXJueWEsIG1hdHJpa3MgYm9ib3QgXChcbWF0aGJme1d9X1ZcKSBtZXJ1cGFrYW4gcGFyYW1ldGVyIHlhbmcgZGlwZWxhamFyaSBzZWxhbWEgcGVsYXRpaGFuIGRhbiB0aWRhayBoYXJ1cyBiZXJiZW50dWsgbWF0cmlrcyBpZGVudGl0YXMuDQoNClByb3NlcyBwcm95ZWtzaSB5YW5nIHNhbWEgZGl0ZXJhcGthbiBwYWRhIHNlbHVydWggdG9rZW4uIERlbmdhbiBtZW5hbXBpbGthbiBoYXNpbCBoaW5nZ2EgZHVhIGFuZ2thIGRlc2ltYWwsIGRpcGVyb2xlaCBtYXRyaWtzIFZhbHVlIGJlcnVrdXJhbiBcKDI1XHRpbWVzMlwpIHNlYmFnYWkgYmVyaWt1dDoNCg0KXFsNClxtYXRoYmZ7Vn0NCj0NClxiZWdpbntibWF0cml4fQ0KLTEuMDAgJiAxLjAwXFwNCi0xLjAwICYgMS4wMFxcDQoxLjAwICYgLTEuMDBcXA0KMS4wMCAmIC0xLjAwXFwNCi0xLjAwICYgMS4wMFxcDQotMS4wMCAmIDEuMDBcXA0KLTEuMDAgJiAxLjAwXFwNCjEuMDAgJiAtMS4wMFxcDQoxLjAwICYgLTEuMDBcXA0KLTEuMDAgJiAxLjAwXFwNCi0xLjAwICYgMS4wMFxcDQotMS4wMCAmIDEuMDBcXA0KMS4wMCAmIC0xLjAwXFwNCjEuMDAgJiAtMS4wMFxcDQotMS4wMCAmIDEuMDBcXA0KLTEuMDAgJiAxLjAwXFwNCi0xLjAwICYgMS4wMFxcDQoxLjAwICYgLTEuMDBcXA0KMS4wMCAmIC0xLjAwXFwNCi0xLjAwICYgMS4wMFxcDQotMS4wMCAmIDEuMDBcXA0KLTEuMDAgJiAxLjAwXFwNCi0xLjAwICYgMS4wMFxcDQoxLjAwICYgLTEuMDBcXA0KLTEuMDAgJiAxLjAwXFwNCi0xLjAwICYgMS4wMA0KXGVuZHtibWF0cml4fS4NClxdDQoNCiMjIyBlLiBTY2FsZWQgRG90LVByb2R1Y3QgQXR0ZW50aW9uDQoNClNldGVsYWggbWF0cmlrcyBRdWVyeSBcKFxtYXRoYmZ7UX1cKSBkYW4gbWF0cmlrcyBLZXkgXChcbWF0aGJme0t9XCkgZGlwZXJvbGVoLCB0aW5na2F0IGtldGVya2FpdGFuIGFudGFydG9rZW4gZGloaXR1bmcgbWVuZ2d1bmFrYW4gKnNjYWxlZCBkb3QtcHJvZHVjdCBhdHRlbnRpb24qLiBQZXJoaXR1bmdhbiBpbmkgbWVuZ2hhc2lsa2FuIG1hdHJpa3Mgc2tvciBwZXJoYXRpYW4gXChcbWF0aGJme1N9XCkuIEVsZW1lbiBcKFNfe3QsdX1cKSBtZW55YXRha2FuIHNrb3Iga2VzZXN1YWlhbiBhbnRhcmEgUXVlcnkgdG9rZW4ga2UtXCh0XCkgZGFuIEtleSB0b2tlbiBrZS1cKHVcKS4gU2VtYWtpbiBiZXNhciBza29yIHlhbmcgZGlwZXJvbGVoLCBzZW1ha2luIHRpbmdnaSB0aW5na2F0IGtlc2VzdWFpYW4ga2VkdWEgcmVwcmVzZW50YXNpIHRlcnNlYnV0Lg0KDQotICoqUnVtdXM6KioNCg0KTWVuZ2FjdSBwYWRhIFBlcnNhbWFhbiAoMi45KSwgbWF0cmlrcyBza29yIHBlcmhhdGlhbiBkaXJ1bXVza2FuIHNlYmFnYWk6DQoNClxbDQpcbWF0aGJme1N9DQo9DQpcZnJhY3tcbWF0aGJme1F9XG1hdGhiZntLfV57XHRvcH19e1xzcXJ0e2Rfa319Lg0KXF0NCg0KUGFkYSBpbHVzdHJhc2kgaW5pLCBzZXRpYXAgS2V5IG1lbWlsaWtpIGR1YSBrb21wb25lbiBmaXR1ciwgc2VoaW5nZ2E6DQoNClxbDQpkX2s9Mi4NClxdDQoNClVudHVrIHBhc2FuZ2FuIHRva2VuIGtlLVwodFwpIGRhbiBrZS1cKHVcKSwgc2tvciBwZXJoYXRpYW4gZGloaXR1bmcgbWVuZ2d1bmFrYW46DQoNClxbDQpTX3t0LHV9DQo9DQpcZnJhY3tcbWF0aGJme1F9X3RcbWF0aGJme0t9X3Vee1x0b3B9fXtcc3FydHsyfX0uDQpcXQ0KDQpNYXRyaWtzIFwoXG1hdGhiZntRfVwpIGRhbiBcKFxtYXRoYmZ7S31cKSBtYXNpbmctbWFzaW5nIGJlcnVrdXJhbiBcKDI1XHRpbWVzMlwpLCBzZWRhbmdrYW4gbWF0cmlrcyBcKFxtYXRoYmZ7S31ee1x0b3B9XCkgYmVydWt1cmFuIFwoMlx0aW1lczI1XCkuIERlbmdhbiBkZW1pa2lhbiwgbWF0cmlrcyBza29yIHBlcmhhdGlhbiBcKFxtYXRoYmZ7U31cKSBiZXJ1a3VyYW4gXCgyNVx0aW1lczI1XCkuIFNldGlhcCBiYXJpcyBtZXJlcHJlc2VudGFzaWthbiB0b2tlbiBRdWVyeSwgc2VkYW5na2FuIHNldGlhcCBrb2xvbSBtZXJlcHJlc2VudGFzaWthbiB0b2tlbiBLZXkuDQoNCi0gKipDb250b2ggcGVyaGl0dW5nYW4gc2tvciBwZXJoYXRpYW4gdG9rZW4gcGVydGFtYToqKg0KDQpCZXJkYXNhcmthbiBoYXNpbCBwcm95ZWtzaSBzZWJlbHVtbnlhLCBkaXBlcm9sZWggUXVlcnkgZGFuIEtleSB0b2tlbiBwZXJ0YW1hOg0KDQpcWw0KXG1hdGhiZntRfV8xDQo9DQpcYmVnaW57Ym1hdHJpeH0NCi0wLjUwICYgMC41MA0KXGVuZHtibWF0cml4fSwNClxxcXVhZA0KXG1hdGhiZntLfV8xDQo9DQpcYmVnaW57Ym1hdHJpeH0NCi0wLjQwICYgMC42MA0KXGVuZHtibWF0cml4fS4NClxdDQoNClNrb3IgcGVyaGF0aWFuIHRva2VuIHBlcnRhbWEgdGVyaGFkYXAgZGlyaW55YSBzZW5kaXJpIGRpaGl0dW5nIHNlYmFnYWk6DQoNClxbDQpcYmVnaW57YWxpZ25lZH0NClNfezEsMX0NCiY9DQpcZnJhY3tcbWF0aGJme1F9XzFcbWF0aGJme0t9XzFee1x0b3B9fXtcc3FydHsyfX1cXA0KJj0NClxmcmFjew0KXGJlZ2lue2JtYXRyaXh9DQotMC41MCAmIDAuNTANClxlbmR7Ym1hdHJpeH0NClxiZWdpbntibWF0cml4fQ0KLTAuNDBcXA0KMC42MA0KXGVuZHtibWF0cml4fQ0KfXtcc3FydHsyfX1cXA0KJj0NClxmcmFjeygtMC41MCkoLTAuNDApKygwLjUwKSgwLjYwKX17XHNxcnR7Mn19XFwNCiY9DQpcZnJhY3swLjIwKzAuMzB9e1xzcXJ0ezJ9fVxcDQomPQ0KXGZyYWN7MC41MH17XHNxcnR7Mn19XFwNCiY9MC4zNS4NClxlbmR7YWxpZ25lZH0NClxdDQoNClNlYmFnYWkgcGVtYmFuZGluZywgS2V5IHRva2VuIGtldGlnYSBhZGFsYWg6DQoNClxbDQpcbWF0aGJme0t9XzMNCj0NClxiZWdpbntibWF0cml4fQ0KMC40MCAmIC0wLjYwDQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KU2tvciBwZXJoYXRpYW4gUXVlcnkgdG9rZW4gcGVydGFtYSB0ZXJoYWRhcCBLZXkgdG9rZW4ga2V0aWdhIGRpaGl0dW5nIHNlYmFnYWk6DQoNClxbDQpcYmVnaW57YWxpZ25lZH0NClNfezEsM30NCiY9DQpcZnJhY3tcbWF0aGJme1F9XzFcbWF0aGJme0t9XzNee1x0b3B9fXtcc3FydHsyfX1cXA0KJj0NClxmcmFjew0KXGJlZ2lue2JtYXRyaXh9DQotMC41MCAmIDAuNTANClxlbmR7Ym1hdHJpeH0NClxiZWdpbntibWF0cml4fQ0KMC40MFxcDQotMC42MA0KXGVuZHtibWF0cml4fQ0KfXtcc3FydHsyfX1cXA0KJj0NClxmcmFjeygtMC41MCkoMC40MCkrKDAuNTApKC0wLjYwKX17XHNxcnR7Mn19XFwNCiY9DQpcZnJhY3stMC4yMC0wLjMwfXtcc3FydHsyfX1cXA0KJj0NClxmcmFjey0wLjUwfXtcc3FydHsyfX1cXA0KJj0tMC4zNS4NClxlbmR7YWxpZ25lZH0NClxdDQoNClByb3NlcyB5YW5nIHNhbWEgZGl0ZXJhcGthbiBwYWRhIHNlbHVydWggcGFzYW5nYW4gdG9rZW4uIERlbmdhbiBtZW5hbXBpbGthbiBoYXNpbCBoaW5nZ2EgZHVhIGFuZ2thIGRlc2ltYWwsIGRpcGVyb2xlaCBtYXRyaWtzIHNrb3IgcGVyaGF0aWFuIFwoXG1hdGhiZntTfVwpIGJlcnVrdXJhbiBcKDI1XHRpbWVzMjVcKSBzZWJhZ2FpIGJlcmlrdXQ6DQoNCg0KDQpcWw0KbWF0aGJme1N9DQo9XGJlZ2lue2JtYXRyaXh9DQowLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1XFwNCjAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzVcXA0KLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzVcXA0KLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzVcXA0KMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNVxcDQowLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1XFwNCjAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzVcXA0KLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzVcXA0KLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzVcXA0KMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNVxcDQowLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1XFwNCjAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzVcXA0KLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzVcXA0KLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzVcXA0KMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNVxcDQowLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1XFwNCjAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzVcXA0KLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzVcXA0KLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzVcXA0KMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNVxcDQowLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1XFwNCjAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzVcXA0KLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzVcXA0KMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNVxcDQowLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIC0wLjM1ICYgMC4zNSAmIDAuMzUgJiAwLjM1ICYgLTAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1ICYgMC4zNSAmIC0wLjM1ICYgLTAuMzUgJiAwLjM1ICYgMC4zNSAmIDAuMzUgJiAtMC4zNSAmIDAuMzUgJiAwLjM1DQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KTmlsYWkgcG9zaXRpZiBtZW51bmp1a2thbiBiYWh3YSBwb2xhIFF1ZXJ5IGRhbiBLZXkga2VkdWEgdG9rZW4gY2VuZGVydW5nIHNlcnVwYSwgc2VkYW5na2FuIG5pbGFpIG5lZ2F0aWYgbWVudW5qdWtrYW4gcG9sYSB5YW5nIGJlcmxhd2FuYW4uIE1hdHJpa3MgXChcbWF0aGJme1N9XCkgc2VsYW5qdXRueWEgZGlub3JtYWxpc2FzaSBtZW5nZ3VuYWthbiBmdW5nc2kgKnNvZnRtYXgqIHBhZGEgc2V0aWFwIGJhcmlzIHVudHVrIG1lbmdoYXNpbGthbiBtYXRyaWtzIGJvYm90IHBlcmhhdGlhbiBcKFxtYXRoYmZ7QX1cKS4NCg0KIyMjIGYuIFNvZnRtYXggQXR0ZW50aW9uIA0KDQpNYXRyaWtzIHNrb3IgXChTXCkgc2VsYW5qdXRueWEgZGl1YmFoIG1lbmphZGkgYm9ib3QgYXR0ZW50aW9uIG1lbmdndW5ha2FuIGZ1bmdzaSBzb2Z0bWF4IHBlciBiYXJpcy4gRGVuZ2FuIGRlbWlraWFuLCBzZXRpYXAgYmFyaXMgcGFkYSBtYXRyaWtzIFwoQVwpIG1lbWlsaWtpIGp1bWxhaCBuaWxhaSBzZWJlc2FyIHNhdHUuDQoNCi0gKipSdW11czoqKg0KDQpcWw0KQV97dCx1fQ0KPQ0KXGZyYWN7ZV57U197dCx1fX19DQp7XHN1bV97cj0xfV57MjV9ZV57U197dCxyfX19Lg0KXF0NCg0KTWF0cmlrcyBcKEFcKSBtZW1pbGlraSBkaW1lbnNpIFwoMjVcdGltZXMyNVwpLCBzYW1hIHNlcGVydGkgbWF0cmlrcyBza29yIFwoU1wpLg0KDQotICoqQ29udG9oIHBlcmhpdHVuZ2FuIHVudHVrIFwoQV97MSwxfVwpOioqDQoNClBhZGEgYmFyaXMgcGVydGFtYSBtYXRyaWtzIFwoU1wpLCB0ZXJkYXBhdCAxNiBza29yIGJlcm5pbGFpIFwoMC4zNVwpIGRhbiA5IHNrb3IgYmVybmlsYWkgXCgtMC4zNVwpLiBPbGVoIGthcmVuYSBpdHUsDQoNClxbDQpcYmVnaW57YWxpZ25lZH0NCkFfezEsMX0NCiY9DQpcZnJhY3tlXnswLjM1fX0NCnsxNmVeezAuMzV9KzllXnstMC4zNX19XFwNCiY9DQpcZnJhY3sxLjQyfQ0KezE2KDEuNDIpKzkoMC43MCl9XFwNCiY9DQpcZnJhY3sxLjQyfXsyMi43Mis2LjMwfVxcDQomPQ0KXGZyYWN7MS40Mn17MjkuMDJ9XFwNCiY9MC4wNS4NClxlbmR7YWxpZ25lZH0NClxdDQoNCk5pbGFpIFwoMC4wNVwpIG1lbnVuanVra2FuIGJhaHdhIHRva2VuIHBlcnRhbWEgbWVtYmVyaSBib2JvdCBwZXJoYXRpYW4gbGViaWggYmVzYXIga2VwYWRhIHRva2VuIHlhbmcgbWVtaWxpa2kgcG9sYSBRdWVyeS0tS2V5IHNlcnVwYSwgeWFpdHUgdG9rZW4gZGVuZ2FuIHNrb3IgXCgwLjM1XCkuDQoNCkF0dXJhbiB5YW5nIHNhbWEgZGl0ZXJhcGthbiBwYWRhIHNlbHVydWggYmFyaXMsIHNlaGluZ2dhIGRpcGVyb2xlaCBtYXRyaWtzIGJvYm90IGF0dGVudGlvbiBcKEFcKSBiZXJpa3V0Lg0KXFsNCkE9XGJlZ2lue2JtYXRyaXh9DQowLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDUgJiAwLjA1XFwNCjAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wNSAmIDAuMDVcXA0KMC4wMyAmIDAuMDMgJiAwLjA2ICYgMC4wNiAmIDAuMDMgJiAwLjAzICYgMC4wMyAmIDAuMDYgJiAwLjA2ICYgMC4wMyAmIDAuMDMgJiAwLjAzICYgMC4wNiAmIDAuMDYgJiAwLjAzICYgMC4wMyAmIDAuMDMgJiAwLjA2ICYgMC4wNiAmIDAuMDMgJiAwLjAzICYgMC4wMyAmIDAuMDYgJiAwLjAzICYgMC4wM1xcDQowLjAzICYgMC4wMyAmIDAuMDYgJiAwLjA2ICYgMC4wMyAmIDAuMDMgJiAwLjAzICYgMC4wNiAmIDAuMDYgJiAwLjAzICYgMC4wMyAmIDAuMDMgJiAwLjA2ICYgMC4wNiAmIDAuMDMgJiAwLjAzICYgMC4wMyAmIDAuMDYgJiAwLjA2ICYgMC4wMyAmIDAuMDMgJiAwLjAzICYgMC4wNiAmIDAuMDMgJiAwLjAzXFwNCjAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wNSAmIDAuMDVcXA0KMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjA1ICYgMC4wNVxcDQowLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDUgJiAwLjA1XFwNCjAuMDMgJiAwLjAzICYgMC4wNiAmIDAuMDYgJiAwLjAzICYgMC4wMyAmIDAuMDMgJiAwLjA2ICYgMC4wNiAmIDAuMDMgJiAwLjAzICYgMC4wMyAmIDAuMDYgJiAwLjA2ICYgMC4wMyAmIDAuMDMgJiAwLjAzICYgMC4wNiAmIDAuMDYgJiAwLjAzICYgMC4wMyAmIDAuMDMgJiAwLjA2ICYgMC4wMyAmIDAuMDNcXA0KMC4wMyAmIDAuMDMgJiAwLjA2ICYgMC4wNiAmIDAuMDMgJiAwLjAzICYgMC4wMyAmIDAuMDYgJiAwLjA2ICYgMC4wMyAmIDAuMDMgJiAwLjAzICYgMC4wNiAmIDAuMDYgJiAwLjAzICYgMC4wMyAmIDAuMDMgJiAwLjA2ICYgMC4wNiAmIDAuMDMgJiAwLjAzICYgMC4wMyAmIDAuMDYgJiAwLjAzICYgMC4wM1xcDQowLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDUgJiAwLjA1XFwNCjAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wNSAmIDAuMDVcXA0KMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjA1ICYgMC4wNVxcDQowLjAzICYgMC4wMyAmIDAuMDYgJiAwLjA2ICYgMC4wMyAmIDAuMDMgJiAwLjAzICYgMC4wNiAmIDAuMDYgJiAwLjAzICYgMC4wMyAmIDAuMDMgJiAwLjA2ICYgMC4wNiAmIDAuMDMgJiAwLjAzICYgMC4wMyAmIDAuMDYgJiAwLjA2ICYgMC4wMyAmIDAuMDMgJiAwLjAzICYgMC4wNiAmIDAuMDMgJiAwLjAzXFwNCjAuMDMgJiAwLjAzICYgMC4wNiAmIDAuMDYgJiAwLjAzICYgMC4wMyAmIDAuMDMgJiAwLjA2ICYgMC4wNiAmIDAuMDMgJiAwLjAzICYgMC4wMyAmIDAuMDYgJiAwLjA2ICYgMC4wMyAmIDAuMDMgJiAwLjAzICYgMC4wNiAmIDAuMDYgJiAwLjAzICYgMC4wMyAmIDAuMDMgJiAwLjA2ICYgMC4wMyAmIDAuMDNcXA0KMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjA1ICYgMC4wNVxcDQowLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDUgJiAwLjA1XFwNCjAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wNSAmIDAuMDVcXA0KMC4wMyAmIDAuMDMgJiAwLjA2ICYgMC4wNiAmIDAuMDMgJiAwLjAzICYgMC4wMyAmIDAuMDYgJiAwLjA2ICYgMC4wMyAmIDAuMDMgJiAwLjAzICYgMC4wNiAmIDAuMDYgJiAwLjAzICYgMC4wMyAmIDAuMDMgJiAwLjA2ICYgMC4wNiAmIDAuMDMgJiAwLjAzICYgMC4wMyAmIDAuMDYgJiAwLjAzICYgMC4wM1xcDQowLjAzICYgMC4wMyAmIDAuMDYgJiAwLjA2ICYgMC4wMyAmIDAuMDMgJiAwLjAzICYgMC4wNiAmIDAuMDYgJiAwLjAzICYgMC4wMyAmIDAuMDMgJiAwLjA2ICYgMC4wNiAmIDAuMDMgJiAwLjAzICYgMC4wMyAmIDAuMDYgJiAwLjA2ICYgMC4wMyAmIDAuMDMgJiAwLjAzICYgMC4wNiAmIDAuMDMgJiAwLjAzXFwNCjAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wNSAmIDAuMDVcXA0KMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjA1ICYgMC4wNVxcDQowLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDUgJiAwLjA1XFwNCjAuMDMgJiAwLjAzICYgMC4wNiAmIDAuMDYgJiAwLjAzICYgMC4wMyAmIDAuMDMgJiAwLjA2ICYgMC4wNiAmIDAuMDMgJiAwLjAzICYgMC4wMyAmIDAuMDYgJiAwLjA2ICYgMC4wMyAmIDAuMDMgJiAwLjAzICYgMC4wNiAmIDAuMDYgJiAwLjAzICYgMC4wMyAmIDAuMDMgJiAwLjA2ICYgMC4wMyAmIDAuMDNcXA0KMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjA1ICYgMC4wNVxcDQowLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDIgJiAwLjA1ICYgMC4wNSAmIDAuMDUgJiAwLjAyICYgMC4wMiAmIDAuMDUgJiAwLjA1ICYgMC4wNSAmIDAuMDIgJiAwLjAyICYgMC4wNSAmIDAuMDUgJiAwLjA1ICYgMC4wMiAmIDAuMDUgJiAwLjA1DQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KDQojIyMgZy4gQWdyZWdhc2kgVmFsdWUgQmVyYm9ib3QgQXR0ZW50aW9uDQoNCk1hdHJpa3MgYm9ib3QgYXR0ZW50aW9uIFwoXG1hdGhiZntBfVwpIGRpZ3VuYWthbiB1bnR1ayBtZW5nZ2FidW5na2FuIHNlbHVydWggVmFsdWUgXChcbWF0aGJme1Z9XCkuIFNldGlhcCBiYXJpcyBoYXNpbCBcKFxtYXRoYmZ7QX1cbWF0aGJme1Z9XCkgYWRhbGFoIGp1bWxhaCBiZXJib2JvdCBkYXJpIHNlbHVydWggdG9rZW4gVmFsdWUuDQoNClBhZGEgaWx1c3RyYXNpIHBlcmhpdHVuZ2FuIGluaSwgbWVrYW5pc21lIHNlbGYtYXR0ZW50aW9uIGRpc2VkZXJoYW5ha2FuIG1lbmdndW5ha2FuIHNhdHUgYXR0ZW50aW9uIGhlYWQuIE9sZWgga2FyZW5hIGl0dSwgb3BlcmFzaSBjb25jYXRlbmF0aW9uIHBhZGEgUGVyc2FtYWFuICgyLjE0KSB0aWRhayBtZW5nZ2FidW5na2FuIGJlYmVyYXBhIGtlbHVhcmFuIGhlYWQgZGFuIG1lbmdoYXNpbGthbiBrZWx1YXJhbiB5YW5nIHNhbWEgZGVuZ2FuIGhlYWQgdHVuZ2dhbCB0ZXJzZWJ1dC4gTWF0cmlrcyBwcm95ZWtzaSBrZWx1YXJhbiBcKFxtYXRoYmYgV15PXCkgZGl0ZXRhcGthbiBzZWJhZ2FpIG1hdHJpa3MgaWRlbnRpdGFzLCBzZWhpbmdnYSBwcm9zZXMgcHJveWVrc2kga2VsdWFyYW4gdGlkYWsgbWVuZ3ViYWggbmlsYWkgaGFzaWwgYWdyZWdhc2kgVmFsdWUuIERlbmdhbiBkZW1pa2lhbiwga2VsdWFyYW4gYXR0ZW50aW9uIHBhZGEgaWx1c3RyYXNpIGluaSBkaXBlcm9sZWggZGFyaSBwZXJrYWxpYW4gbWF0cmlrcyBib2JvdCBwZXJoYXRpYW4gXChcbWF0aGJmIEFcKSBkYW4gbWF0cmlrcyBWYWx1ZSBcKFxtYXRoYmYgVlwpLg0KDQotICoqUnVtdXM6KioNCg0KXFsNClxtYXRoYmZ7T31fe1xtYXRocm17YXR0fX09XG1hdGhiZntBfVxtYXRoYmZ7Vn0uDQpcXQ0KDQpQYWRhIGlsdXN0cmFzaSBpbmksIGthcmVuYSBib2JvdCBrZWx1YXJhbiBcKFxtYXRoYmZ7V31ee099PVxtYXRoYmZ7SX1cKSwgbWFrYToNCg0KXFsNClxtYXRoYmZ7T31fe1xtYXRocm17YXR0fX0NCj0NClxtYXRoYmZ7QX1cbWF0aGJme1Z9XG1hdGhiZntXfV57T30NCj0NClxtYXRoYmZ7QX1cbWF0aGJme1Z9Lg0KXF0NCg0KTWF0cmlrcyBcKFxtYXRoYmZ7QX1cKSBiZXJkaW1lbnNpIFwoMjVcdGltZXMyNVwpLCBzZWRhbmdrYW4gXChcbWF0aGJme1Z9XCkgYmVyZGltZW5zaSBcKDI1XHRpbWVzMlwpLiBPbGVoIGthcmVuYSBpdHUsIGhhc2lsIFwoXG1hdGhiZntBfVxtYXRoYmZ7Vn1cKSBhdGF1IG1hdHJpa3Mga2VsdWFyYW4gYXR0ZW50aW9uIFwoXG1hdGhiZntPfV97XG1hdGhybXthdHR9fVwpIGJlcmRpbWVuc2kgXCgyNVx0aW1lczJcKS4NCg0KLSAqKkNvbnRvaCBwZXJoaXR1bmdhbiB1bnR1ayBcKE9fe1xtYXRocm17YXR0fSwxLDF9XCk6KioNCg0KUGFkYSBiYXJpcyBwZXJ0YW1hLCB0ZXJkYXBhdCAxNiB0b2tlbiBWYWx1ZSBiZXJwb2xhIFwoKC0xLDEpXCkgZGVuZ2FuIGJvYm90IHNla2l0YXIgXCgwLjA1XCksIHNlcnRhIDkgdG9rZW4gVmFsdWUgYmVycG9sYSBcKCgxLC0xKVwpIGRlbmdhbiBib2JvdCBzZWtpdGFyIFwoMC4wMlwpLiBNYWthLCBrb21wb25lbiBwZXJ0YW1hIGRpaGl0dW5nIHNlYmFnYWk6DQoNClxbDQpcYmVnaW57YWxpZ25lZH0NCk9fe1xtYXRocm17YXR0fSwxLDF9DQomPQ0KXHN1bV97dT0xfV57MjV9QV97MSx1fVZfe3UsMX1cXA0KJj0NCjE2KDAuMDUpKC0xLjAwKSs5KDAuMDIpKDEuMDApXFwNCiY9DQotMC44MCswLjE4XFwNCiY9DQotMC42Mi4NClxlbmR7YWxpZ25lZH0NClxdDQoNCkRlbmdhbiBjYXJhIHlhbmcgc2FtYSwga29tcG9uZW4ga2VkdWEgYWRhbGFoOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpPX3tcbWF0aHJte2F0dH0sMSwyfQ0KJj0NClxzdW1fe3U9MX1eezI1fUFfezEsdX1WX3t1LDJ9XFwNCiY9DQoxNigwLjA1KSgxLjAwKSs5KDAuMDIpKC0xLjAwKVxcDQomPQ0KMC44MC0wLjE4XFwNCiY9DQowLjYyLg0KXGVuZHthbGlnbmVkfQ0KXF0NCg0KU2VoaW5nZ2EsDQoNClxbDQpcbWF0aGJme099X3tcbWF0aHJte2F0dH0sMX09DQpcYmVnaW57Ym1hdHJpeH0NCi0wLjYyICYgMC42Mg0KXGVuZHtibWF0cml4fS4NClxdDQoNCkF0dXJhbiB5YW5nIHNhbWEgZGl0ZXJhcGthbiBwYWRhIHNlbHVydWggdG9rZW4sIHNlaGluZ2dhIGRpcGVyb2xlaCBtYXRyaWtzIFwoQVZcKSBiZXJpa3V0Lg0KDQpcWw0KXG1hdGhiZntPfV97XG1hdGhybXthdHR9fQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQotMC42MiAmIDAuNjJcXA0KLTAuNjIgJiAwLjYyXFwNCjAuMDYgJiAtMC4wNlxcDQowLjA2ICYgLTAuMDZcXA0KLTAuNjIgJiAwLjYyXFwNCi0wLjYyICYgMC42MlxcDQotMC42MiAmIDAuNjJcXA0KMC4wNiAmIC0wLjA2XFwNCjAuMDYgJiAtMC4wNlxcDQotMC42MiAmIDAuNjJcXA0KLTAuNjIgJiAwLjYyXFwNCi0wLjYyICYgMC42MlxcDQowLjA2ICYgLTAuMDZcXA0KMC4wNiAmIC0wLjA2XFwNCi0wLjYyICYgMC42MlxcDQotMC42MiAmIDAuNjJcXA0KLTAuNjIgJiAwLjYyXFwNCjAuMDYgJiAtMC4wNlxcDQowLjA2ICYgLTAuMDZcXA0KLTAuNjIgJiAwLjYyXFwNCi0wLjYyICYgMC42MlxcDQotMC42MiAmIDAuNjJcXA0KMC4wNiAmIC0wLjA2XFwNCi0wLjYyICYgMC42MlxcDQotMC42MiAmIDAuNjINClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQoNCiMjIyBoLiBSZXNpZHVhbCBBdHRlbnRpb24NCg0KUmVzaWR1YWwgYXR0ZW50aW9uIG1lbmdnYWJ1bmdrYW4gbWF0cmlrcyB0b2tlbiBhd2FsIFwoXG1hdGhiZntUfVwpIGRlbmdhbiBrZWx1YXJhbiBhdHRlbnRpb24gXChcbWF0aGJme099X3tcbWF0aHJte2F0dH19XCkuIFR1anVhbm55YSBhZGFsYWggbWVtcGVydGFoYW5rYW4gaW5mb3JtYXNpIGF3YWwgdG9rZW4gc2FtYmlsIG1lbmFtYmFoa2FuIGluZm9ybWFzaSBnbG9iYWwgaGFzaWwgKnNlbGYtYXR0ZW50aW9uKi4NCg0KLSAqKlJ1bXVzOioqDQoNClxbDQpcbWF0aGJme1p9Jw0KPQ0KXG1hdGhiZntUfQ0KKw0KXG1hdGhiZntPfV97XG1hdGhybXthdHR9fS4NClxdDQoNCk1hdHJpa3MgXChcbWF0aGJme1R9XCkgZGFuIFwoXG1hdGhiZntPfV97XG1hdGhybXthdHR9fVwpIGtlZHVhbnlhIGJlcmRpbWVuc2kgXCgyNVx0aW1lczJcKSwgc2VoaW5nZ2EgXChcbWF0aGJme1p9J1wpIGp1Z2EgYmVyZGltZW5zaSBcKDI1XHRpbWVzMlwpLg0KDQotICoqQ29udG9oIHBlcmhpdHVuZ2FuIHVudHVrIHRva2VuIHBlcnRhbWE6KioNCg0KXFsNClxtYXRoYmZ7VH1fMT0NClxiZWdpbntibWF0cml4fQ0KLTAuMjcgJiAwLjEzDQpcZW5ke2JtYXRyaXh9LA0KXHFxdWFkDQpcbWF0aGJme099X3tcbWF0aHJte2F0dH0sMX09DQpcYmVnaW57Ym1hdHJpeH0NCi0wLjYyICYgMC42Mg0KXGVuZHtibWF0cml4fS4NClxdDQoNCk1ha2EsDQoNClxbDQpcYmVnaW57YWxpZ25lZH0NClxtYXRoYmZ7Wn0nX3sxfQ0KJj0NClxtYXRoYmZ7VH1fMStcbWF0aGJme099X3tcbWF0aHJte2F0dH0sMX1cXA0KJj0NClxiZWdpbntibWF0cml4fQ0KLTAuMjcgJiAwLjEzDQpcZW5ke2JtYXRyaXh9DQorDQpcYmVnaW57Ym1hdHJpeH0NCi0wLjYyICYgMC42Mg0KXGVuZHtibWF0cml4fVxcDQomPQ0KXGJlZ2lue2JtYXRyaXh9DQotMC44OSAmIDAuNzUNClxlbmR7Ym1hdHJpeH0uDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpBdHVyYW4geWFuZyBzYW1hIGRpdGVyYXBrYW4gcGFkYSBzZWx1cnVoIHRva2VuLCBzZWhpbmdnYSBkaXBlcm9sZWggbWF0cmlrcyByZXNpZHVhbCBhdHRlbnRpb24gXChcbWF0aGJme1p9J1wpIGJlcmlrdXQuDQoNClxbDQpcbWF0aGJme1p9Jz0NClxiZWdpbntibWF0cml4fQ0KLTAuODkgJiAwLjc1XFwNCi0wLjg3ICYgMC43NFxcDQowLjYyICYgLTAuMzRcXA0KMC4zMiAmIC0wLjE5XFwNCi0wLjg5ICYgMC43NlxcDQotMC44OCAmIDAuNzVcXA0KLTAuODUgJiAwLjc0XFwNCjAuOTMgJiAtMC40OVxcDQowLjUyICYgLTAuMjlcXA0KLTAuODkgJiAwLjc2XFwNCi0wLjg4ICYgMC43NVxcDQotMC44NSAmIDAuNzNcXA0KMC45MyAmIC0wLjQ5XFwNCjAuNTIgJiAtMC4yOVxcDQotMC44OSAmIDAuNzZcXA0KLTAuODggJiAwLjc1XFwNCi0wLjg3ICYgMC43NVxcDQowLjY2ICYgLTAuMzZcXA0KMC4zMCAmIC0wLjE4XFwNCi0wLjkwICYgMC43NlxcDQotMC44OSAmIDAuNzZcXA0KLTAuODkgJiAwLjc2XFwNCjAuMTYgJiAtMC4xMVxcDQotMC43MSAmIDAuNjZcXA0KLTAuOTAgJiAwLjc2DQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KIyMjIGkuIE5vcm1hbGlzYXNpIEtlbHVhcmFuIFJlc2lkdWFsIEF0dGVudGlvbg0KDQpNYXRyaWtzIGhhc2lsIHJlc2lkdWFsIGF0dGVudGlvbiBcKFxtYXRoYmZ7Wn0nXCkgZGlub3JtYWxpc2FzaSBwZXIgdG9rZW4gbWVuZ2d1bmFrYW4gKkxheWVyIE5vcm1hbGl6YXRpb24qLCBkZW5nYW4gcHJvc2VkdXIgeWFuZyBzYW1hIHNlcGVydGkgbm9ybWFsaXNhc2kgdG9rZW4gc2ViZWx1bW55YS4NCg0KLSAqKlJ1bXVzOioqDQoNClxbDQpcbGVmdFtcb3BlcmF0b3JuYW1le0xOfShcbWF0aGJme1p9J190KVxyaWdodF1faw0KPQ0KXGZyYWN7Widfe3Qsa30tXG11X3R9DQp7XHNxcnR7XHNpZ21hX3ReezJ9KzEwXnstNX19fSwNClxdDQoNCmRlbmdhbjoNCg0KXFsNClxtdV90DQo9DQpcZnJhY3sxfXsyfVxzdW1fe2s9MX1eezJ9Widfe3Qsa30sDQpccXF1YWQNClxzaWdtYV90XnsyfQ0KPQ0KXGZyYWN7MX17Mn1cc3VtX3trPTF9XnsyfShaJ197dCxrfS1cbXVfdCleMi4NClxdDQoNCi0gKipDb250b2ggcGVyaGl0dW5nYW4gdW50dWsgdG9rZW4gcGVydGFtYToqKg0KDQpcWw0KXG1hdGhiZntafSdfMT0NClxiZWdpbntibWF0cml4fQ0KLTAuODkgJiAwLjc1DQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KUmF0YS1yYXRhIHRva2VuIHBlcnRhbWEgYWRhbGFoOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpcbXVfMQ0KJj0NClxmcmFjey0wLjg5KzAuNzV9ezJ9XFwNCiY9DQotMC4wNy4NClxlbmR7YWxpZ25lZH0NClxdDQoNClZhcmlhbnNueWEgYWRhbGFoOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpcc2lnbWFfMV4yDQomPQ0KXGZyYWN7KC0wLjg5LSgtMC4wNykpXjIrKDAuNzUtKC0wLjA3KSleMn17Mn1cXA0KJj0NClxmcmFjeygtMC44MileMisoMC44MileMn17Mn1cXA0KJj0NCjAuNjcyNC4NClxlbmR7YWxpZ25lZH0NClxdDQoNCkVsZW1lbiBwZXJ0YW1hIHNldGVsYWggbm9ybWFsaXNhc2kgYWRhbGFoOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpcbGVmdFtcb3BlcmF0b3JuYW1le0xOfShcbWF0aGJme1p9J18xKVxyaWdodF1fMQ0KJj0NClxmcmFjey0wLjg5LSgtMC4wNyl9DQp7XHNxcnR7MC42NzI0KzEwXnstNX19fVxcDQomPQ0KXGZyYWN7LTAuODJ9ezAuODJ9XFwNCiY9DQotMS4wMC4NClxlbmR7YWxpZ25lZH0NClxdDQoNCkRlbmdhbiBjYXJhIHlhbmcgc2FtYSwgXChcbGVmdFtcb3BlcmF0b3JuYW1le0xOfShcbWF0aGJme1p9J18xKVxyaWdodF1fMj0xLjAwXCkuIE9sZWgga2FyZW5hIGl0dToNCg0KXFsNClxvcGVyYXRvcm5hbWV7TE59KFxtYXRoYmZ7Wn0nXzEpPQ0KXGJlZ2lue2JtYXRyaXh9DQotMS4wMCAmIDEuMDANClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQpBdHVyYW4geWFuZyBzYW1hIGRpdGVyYXBrYW4gcGFkYSBzZWx1cnVoIHRva2VuLCBzZWhpbmdnYSBkaXBlcm9sZWggaGFzaWwgbm9ybWFsaXNhc2kgcmVzaWR1YWwgYXR0ZW50aW9uIFwoXG9wZXJhdG9ybmFtZXtMTn0oXG1hdGhiZntafScpXCkgYmVyaWt1dC4NCg0KXFsNClxvcGVyYXRvcm5hbWV7TE59KFxtYXRoYmZ7Wn0nKT0NClxiZWdpbntibWF0cml4fQ0KLTEuMDAgJiAxLjAwXFwNCi0xLjAwICYgMS4wMFxcDQoxLjAwICYgLTEuMDBcXA0KMS4wMCAmIC0xLjAwXFwNCi0xLjAwICYgMS4wMFxcDQotMS4wMCAmIDEuMDBcXA0KLTEuMDAgJiAxLjAwXFwNCjEuMDAgJiAtMS4wMFxcDQoxLjAwICYgLTEuMDBcXA0KLTEuMDAgJiAxLjAwXFwNCi0xLjAwICYgMS4wMFxcDQotMS4wMCAmIDEuMDBcXA0KMS4wMCAmIC0xLjAwXFwNCjEuMDAgJiAtMS4wMFxcDQotMS4wMCAmIDEuMDBcXA0KLTEuMDAgJiAxLjAwXFwNCi0xLjAwICYgMS4wMFxcDQoxLjAwICYgLTEuMDBcXA0KMS4wMCAmIC0xLjAwXFwNCi0xLjAwICYgMS4wMFxcDQotMS4wMCAmIDEuMDBcXA0KLTEuMDAgJiAxLjAwXFwNCjEuMDAgJiAtMS4wMFxcDQotMS4wMCAmIDEuMDBcXA0KLTEuMDAgJiAxLjAwDQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KDQojIyMgai4gTGFwaXNhbiBMaW5lYXIgUGVydGFtYSBNTFAgKCpGZWVkLUZvcndhcmQgTmV0d29yayopDQoNCkxhcGlzYW4gbGluZWFyIHBlcnRhbWEgcGFkYSBNTFAgbWVtcHJveWVrc2lrYW4gc2V0aWFwIHRva2VuIGRhcmkgZHVhIGZpdHVyIG1lbmphZGkgdGlnYSBmaXR1ci4gVGFoYXAgaW5pIG1lcnVwYWthbiBiYWdpYW4gcGVydGFtYSBkYXJpIE1MUCBwYWRhIFBlcnNhbWFhbiAoMi4xNykuIFBhZGEgaWx1c3RyYXNpIHBlcmhpdHVuZ2FuLCBmdW5nc2kgYWt0aXZhc2kgR0VMVSBkaXNlZGVyaGFuYWthbiBtZW5qYWRpIFJlTFUgZGFuIHZla3RvciBiaWFzIHRpZGFrIGRpZ3VuYWthbi4NCg0KLSAqKkJvYm90IGxhcGlzYW4gbGluZWFyIHBlcnRhbWE6KioNCg0KXFsNClxtYXRoYmZ7V31fMT0NClxiZWdpbntibWF0cml4fQ0KMC42MCAmIC0wLjIwICYgMC40MFxcDQotMC4zMCAmIDAuNTAgJiAtMC40MA0KXGVuZHtibWF0cml4fS4NClxdDQoNCi0gKipSdW11czoqKg0KDQpcWw0KXG9wZXJhdG9ybmFtZXtSZUxVfQ0KXGxlZnQoDQpcb3BlcmF0b3JuYW1le0xOfShcbWF0aGJme1p9JylcbWF0aGJme1d9XzENClxyaWdodCkuDQpcXQ0KDQpkZW5nYW46DQoNClxbDQpcb3BlcmF0b3JuYW1le1JlTFV9KHgpPVxtYXgoMCx4KS4NClxdDQoNCk1hdHJpa3MgXChcb3BlcmF0b3JuYW1le0xOfShcbWF0aGJme1p9JylcKSBiZXJkaW1lbnNpIFwoMjVcdGltZXMyXCkgZGFuIFwoXG1hdGhiZntXfV8xXCkgYmVyZGltZW5zaSBcKDJcdGltZXMzXCksIHNlaGluZ2dhIGhhc2lsIGxhcGlzYW4gbGluZWFyIHBlcnRhbWEgc2V0ZWxhaCBha3RpdmFzaSBSZUxVIGJlcmRpbWVuc2kgXCgyNVx0aW1lczNcKS4NCg0KLSAqKkNvbnRvaCBwZXJoaXR1bmdhbiB1bnR1ayB0b2tlbiBwZXJ0YW1hOioqDQoNClxbDQpcb3BlcmF0b3JuYW1le0xOfShcbWF0aGJme1p9J18xKT0NClxiZWdpbntibWF0cml4fQ0KLTEuMDAgJiAxLjAwDQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KU2ViZWx1bSBSZUxVOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpcb3BlcmF0b3JuYW1le0xOfShcbWF0aGJme1p9J18xKVxtYXRoYmZ7V31fMQ0KJj0NClxiZWdpbntibWF0cml4fQ0KLTEuMDAgJiAxLjAwDQpcZW5ke2JtYXRyaXh9DQpcYmVnaW57Ym1hdHJpeH0NCjAuNjAgJiAtMC4yMCAmIDAuNDBcXA0KLTAuMzAgJiAwLjUwICYgLTAuNDANClxlbmR7Ym1hdHJpeH1cXA0KJj0NClxiZWdpbntibWF0cml4fQ0KLTAuOTAgJiAwLjcwICYgLTAuODANClxlbmR7Ym1hdHJpeH0uDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpTZXRlbGFoIFJlTFU6DQoNClxbDQpcYmVnaW57YWxpZ25lZH0NClxvcGVyYXRvcm5hbWV7UmVMVX0NClxsZWZ0KA0KXG9wZXJhdG9ybmFtZXtMTn0oXG1hdGhiZntafSdfMSlcbWF0aGJme1d9XzENClxyaWdodCkNCiY9DQpcb3BlcmF0b3JuYW1le1JlTFV9DQpcbGVmdCgNClxiZWdpbntibWF0cml4fQ0KLTAuOTAgJiAwLjcwICYgLTAuODANClxlbmR7Ym1hdHJpeH0NClxyaWdodClcXA0KJj0NClxiZWdpbntibWF0cml4fQ0KMC4wMCAmIDAuNzAgJiAwLjAwDQpcZW5ke2JtYXRyaXh9Lg0KXGVuZHthbGlnbmVkfQ0KXF0NCg0KQXR1cmFuIHlhbmcgc2FtYSBkaXRlcmFwa2FuIHBhZGEgc2VsdXJ1aCB0b2tlbiwgc2VoaW5nZ2EgZGlwZXJvbGVoIGhhc2lsIGxhcGlzYW4gbGluZWFyIHBlcnRhbWEgc2V0ZWxhaCBha3RpdmFzaSBSZUxVIGJlcmlrdXQuDQoNClxbDQpcb3BlcmF0b3JuYW1le1JlTFV9DQpcbGVmdCgNClxvcGVyYXRvcm5hbWV7TE59KFxtYXRoYmZ7Wn0nKVxtYXRoYmZ7V31fMQ0KXHJpZ2h0KQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQowLjAwICYgMC43MCAmIDAuMDBcXA0KMC4wMCAmIDAuNzAgJiAwLjAwXFwNCjAuOTAgJiAwLjAwICYgMC44MFxcDQowLjkwICYgMC4wMCAmIDAuODBcXA0KMC4wMCAmIDAuNzAgJiAwLjAwXFwNCjAuMDAgJiAwLjcwICYgMC4wMFxcDQowLjAwICYgMC43MCAmIDAuMDBcXA0KMC45MCAmIDAuMDAgJiAwLjgwXFwNCjAuOTAgJiAwLjAwICYgMC44MFxcDQowLjAwICYgMC43MCAmIDAuMDBcXA0KMC4wMCAmIDAuNzAgJiAwLjAwXFwNCjAuMDAgJiAwLjcwICYgMC4wMFxcDQowLjkwICYgMC4wMCAmIDAuODBcXA0KMC45MCAmIDAuMDAgJiAwLjgwXFwNCjAuMDAgJiAwLjcwICYgMC4wMFxcDQowLjAwICYgMC43MCAmIDAuMDBcXA0KMC4wMCAmIDAuNzAgJiAwLjAwXFwNCjAuOTAgJiAwLjAwICYgMC44MFxcDQowLjkwICYgMC4wMCAmIDAuODBcXA0KMC4wMCAmIDAuNzAgJiAwLjAwXFwNCjAuMDAgJiAwLjcwICYgMC4wMFxcDQowLjAwICYgMC43MCAmIDAuMDBcXA0KMC45MCAmIDAuMDAgJiAwLjgwXFwNCjAuMDAgJiAwLjcwICYgMC4wMFxcDQowLjAwICYgMC43MCAmIDAuMDANClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQojIyMgay4gTGFwaXNhbiBMaW5lYXIgS2VkdWEgTUxQICgqRmVlZC1Gb3J3YXJkIE5ldHdvcmsqKQ0KDQpMYXBpc2FuIGxpbmVhciBrZWR1YSBNTFAgbWVtcHJveWVrc2lrYW4ga2VtYmFsaSBoYXNpbCBsYXBpc2FuIGxpbmVhciBwZXJ0YW1hIGRhcmkgdGlnYSBmaXR1ciBtZW5qYWRpIGR1YSBmaXR1ci4NCg0KLSAqKkJvYm90IGxhcGlzYW4gbGluZWFyIGtlZHVhOioqDQoNClxbDQpcbWF0aGJme1d9XzI9DQpcYmVnaW57Ym1hdHJpeH0NCjAuMzAgJiAtMC4yMFxcDQowLjIwICYgMC40MFxcDQotMC4xMCAmIDAuMzANClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQotICoqUnVtdXM6KioNCg0KXFsNClxvcGVyYXRvcm5hbWV7UmVMVX0NClxsZWZ0KA0KXG9wZXJhdG9ybmFtZXtMTn0oXG1hdGhiZntafScpXG1hdGhiZntXfV8xDQpccmlnaHQpDQpcbWF0aGJme1d9XzIuDQpcXQ0KDQpIYXNpbCBsYXBpc2FuIGxpbmVhciBwZXJ0YW1hIHNldGVsYWggYWt0aXZhc2kgUmVMVSBiZXJkaW1lbnNpIFwoMjVcdGltZXMzXCkgZGFuIFwoXG1hdGhiZntXfV8yXCkgYmVyZGltZW5zaSBcKDNcdGltZXMyXCksIHNlaGluZ2dhIGtlbHVhcmFuIGxhcGlzYW4gbGluZWFyIGtlZHVhIGJlcmRpbWVuc2kgXCgyNVx0aW1lczJcKS4NCg0KLSAqKkNvbnRvaCBwZXJoaXR1bmdhbiB1bnR1ayB0b2tlbiBwZXJ0YW1hOioqDQoNClxbDQpcb3BlcmF0b3JuYW1le1JlTFV9DQpcbGVmdCgNClxvcGVyYXRvcm5hbWV7TE59KFxtYXRoYmZ7Wn0nXzEpXG1hdGhiZntXfV8xDQpccmlnaHQpDQo9DQpcYmVnaW57Ym1hdHJpeH0NCjAuMDAgJiAwLjcwICYgMC4wMA0KXGVuZHtibWF0cml4fS4NClxdDQoNCk1ha2EsDQoNClxbDQpcYmVnaW57YWxpZ25lZH0NClxvcGVyYXRvcm5hbWV7UmVMVX0NClxsZWZ0KA0KXG9wZXJhdG9ybmFtZXtMTn0oXG1hdGhiZntafSdfMSlcbWF0aGJme1d9XzENClxyaWdodCkNClxtYXRoYmZ7V31fMg0KJj0NClxiZWdpbntibWF0cml4fQ0KMC4wMCAmIDAuNzAgJiAwLjAwDQpcZW5ke2JtYXRyaXh9DQpcYmVnaW57Ym1hdHJpeH0NCjAuMzAgJiAtMC4yMFxcDQowLjIwICYgMC40MFxcDQotMC4xMCAmIDAuMzANClxlbmR7Ym1hdHJpeH1cXA0KJj0NClxiZWdpbntibWF0cml4fQ0KKDAuMDApKDAuMzApKygwLjcwKSgwLjIwKSsoMC4wMCkoLTAuMTApICYNCigwLjAwKSgtMC4yMCkrKDAuNzApKDAuNDApKygwLjAwKSgwLjMwKQ0KXGVuZHtibWF0cml4fVxcDQomPQ0KXGJlZ2lue2JtYXRyaXh9DQowLjE0ICYgMC4yOA0KXGVuZHtibWF0cml4fS4NClxlbmR7YWxpZ25lZH0NClxdDQoNCkF0dXJhbiB5YW5nIHNhbWEgZGl0ZXJhcGthbiBwYWRhIHNlbHVydWggdG9rZW4sIHNlaGluZ2dhIGRpcGVyb2xlaCBrZWx1YXJhbiBsYXBpc2FuIGxpbmVhciBrZWR1YSBNTFAgYmVyaWt1dC4NCg0KXFsNClxvcGVyYXRvcm5hbWV7UmVMVX0NClxsZWZ0KA0KXG9wZXJhdG9ybmFtZXtMTn0oXG1hdGhiZntafScpXG1hdGhiZntXfV8xDQpccmlnaHQpDQpcbWF0aGJme1d9XzINCj0NClxiZWdpbntibWF0cml4fQ0KMC4xNCAmIDAuMjhcXA0KMC4xNCAmIDAuMjhcXA0KMC4xOSAmIDAuMDZcXA0KMC4xOSAmIDAuMDZcXA0KMC4xNCAmIDAuMjhcXA0KMC4xNCAmIDAuMjhcXA0KMC4xNCAmIDAuMjhcXA0KMC4xOSAmIDAuMDZcXA0KMC4xOSAmIDAuMDZcXA0KMC4xNCAmIDAuMjhcXA0KMC4xNCAmIDAuMjhcXA0KMC4xNCAmIDAuMjhcXA0KMC4xOSAmIDAuMDZcXA0KMC4xOSAmIDAuMDZcXA0KMC4xNCAmIDAuMjhcXA0KMC4xNCAmIDAuMjhcXA0KMC4xNCAmIDAuMjhcXA0KMC4xOSAmIDAuMDZcXA0KMC4xOSAmIDAuMDZcXA0KMC4xNCAmIDAuMjhcXA0KMC4xNCAmIDAuMjhcXA0KMC4xNCAmIDAuMjhcXA0KMC4xOSAmIDAuMDZcXA0KMC4xNCAmIDAuMjhcXA0KMC4xNCAmIDAuMjgNClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQoNCiMjIyBsLiBSZXNpZHVhbCBNTFAgKCpGZWVkLUZvcndhcmQgTmV0d29yayopDQoNClJlc2lkdWFsIE1MUCBtZW5nZ2FidW5na2FuIGtlbHVhcmFuIE1MUCBkZW5nYW4gcmVwcmVzZW50YXNpIFwoXG1hdGhiZntafSdcKSwgeWFpdHUga2VsdWFyYW4gZGFyaSByZXNpZHVhbCBhdHRlbnRpb24uIE9wZXJhc2kgaW5pIG1lbXBlcnRhaGFua2FuIGluZm9ybWFzaSBkYXJpIHRhaGFwIGF0dGVudGlvbiBzZXRlbGFoIE1MUCBtZW5hbWJhaGthbiB0cmFuc2Zvcm1hc2kgZml0dXIuDQoNCi0gKipSdW11czoqKg0KDQpcWw0KXG1hdGhiZntafQ0KPQ0KXG9wZXJhdG9ybmFtZXtSZUxVfQ0KXGxlZnQoDQpcb3BlcmF0b3JuYW1le0xOfShcbWF0aGJme1p9JylcbWF0aGJme1d9XzENClxyaWdodCkNClxtYXRoYmZ7V31fMg0KKw0KXG1hdGhiZntafScuDQpcXQ0KDQpNYXRyaWtzIFwoXG9wZXJhdG9ybmFtZXtSZUxVfShcb3BlcmF0b3JuYW1le0xOfShcbWF0aGJme1p9JylcbWF0aGJme1d9XzEpXG1hdGhiZntXfV8yXCkgZGFuIFwoXG1hdGhiZntafSdcKSBzYW1hLXNhbWEgYmVyZGltZW5zaSBcKDI1XHRpbWVzMlwpLCBzZWhpbmdnYSBcKFxtYXRoYmZ7Wn1cKSBiZXJkaW1lbnNpIFwoMjVcdGltZXMyXCkuDQoNCi0gKipDb250b2ggcGVyaGl0dW5nYW4gdW50dWsgdG9rZW4gcGVydGFtYToqKg0KDQpcWw0KXG1hdGhiZntafSdfMT0NClxiZWdpbntibWF0cml4fQ0KLTAuODkgJiAwLjc1DQpcZW5ke2JtYXRyaXh9LA0KXF0NCg0KXFsNClxvcGVyYXRvcm5hbWV7UmVMVX0NClxsZWZ0KA0KXG9wZXJhdG9ybmFtZXtMTn0oXG1hdGhiZntafSdfMSlcbWF0aGJme1d9XzENClxyaWdodCkNClxtYXRoYmZ7V31fMg0KPQ0KXGJlZ2lue2JtYXRyaXh9DQowLjE0ICYgMC4yOA0KXGVuZHtibWF0cml4fS4NClxdDQoNCk1ha2EsDQoNClxbDQpcYmVnaW57YWxpZ25lZH0NClxtYXRoYmZ7Wn1fMQ0KJj0NClxvcGVyYXRvcm5hbWV7UmVMVX0NClxsZWZ0KA0KXG9wZXJhdG9ybmFtZXtMTn0oXG1hdGhiZntafSdfMSlcbWF0aGJme1d9XzENClxyaWdodCkNClxtYXRoYmZ7V31fMg0KKw0KXG1hdGhiZntafSdfMVxcDQomPQ0KXGJlZ2lue2JtYXRyaXh9DQowLjE0ICYgMC4yOA0KXGVuZHtibWF0cml4fQ0KKw0KXGJlZ2lue2JtYXRyaXh9DQotMC44OSAmIDAuNzUNClxlbmR7Ym1hdHJpeH1cXA0KJj0NClxiZWdpbntibWF0cml4fQ0KLTAuNzUgJiAxLjAzDQpcZW5ke2JtYXRyaXh9Lg0KXGVuZHthbGlnbmVkfQ0KXF0NCg0KQXR1cmFuIHlhbmcgc2FtYSBkaXRlcmFwa2FuIHBhZGEgc2VsdXJ1aCB0b2tlbiwgc2VoaW5nZ2EgZGlwZXJvbGVoIG1hdHJpa3MgXChcbWF0aGJme1p9XCkgYmVyaWt1dC4NCg0KXFsNClxtYXRoYmZ7Wn09XGJlZ2lue2JtYXRyaXh9DQotMC43NSAmIDEuMDNcXA0KLTAuNzMgJiAxLjAyXFwNCjAuODEgJiAtMC4yOFxcDQowLjUxICYgLTAuMTNcXA0KLTAuNzUgJiAxLjA0XFwNCi0wLjc0ICYgMS4wM1xcDQotMC43MSAmIDEuMDJcXA0KMS4xMiAmIC0wLjQzXFwNCjAuNzEgJiAtMC4yM1xcDQotMC43NSAmIDEuMDRcXA0KLTAuNzQgJiAxLjAzXFwNCi0wLjcxICYgMS4wMVxcDQoxLjEyICYgLTAuNDNcXA0KMC43MSAmIC0wLjIzXFwNCi0wLjc1ICYgMS4wNFxcDQotMC43NCAmIDEuMDNcXA0KLTAuNzMgJiAxLjAzXFwNCjAuODUgJiAtMC4zMFxcDQowLjQ5ICYgLTAuMTJcXA0KLTAuNzYgJiAxLjA0XFwNCi0wLjc1ICYgMS4wNFxcDQotMC43NSAmIDEuMDRcXA0KMC4zNSAmIC0wLjA1XFwNCi0wLjU3ICYgMC45NFxcDQotMC43NiAmIDEuMDQNClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQojIyMgbS4gTm9ybWFsaXNhc2kgS2VsdWFyYW4gVHJhbnNmb3JtZXINCg0KVGFoYXAgdGVyYWtoaXIgVHJhbnNmb3JtZXIgYWRhbGFoIG5vcm1hbGlzYXNpIHBlciB0b2tlbiB0ZXJoYWRhcCBtYXRyaWtzIGtlbHVhcmFuIHJlc2lkdWFsIE1MUCBcKFxtYXRoYmZ7Wn1cKS4gTWF0cmlrcyBoYXNpbCBcKFxtYXRoYmZ7R31cKSBtZXJ1cGFrYW4gcmVwcmVzZW50YXNpIGdsb2JhbCB5YW5nIGFrYW4gZGlsaXBhdCBrZW1iYWxpIGtlIGJlbnR1ayBzcGFzaWFsIHBhZGEgdGFoYXAgYmVyaWt1dG55YS4NCg0KLSAqKlJ1bXVzOioqDQoNClxbDQpHX3t0LGt9DQo9DQpcZnJhY3taX3t0LGt9LVxtdV97Wix0fX0NCntcc3FydHtcc2lnbWFfe1osdH1eezJ9KzEwXnstNX19fS4NClxdDQoNCi0gKipDb250b2ggcGVyaGl0dW5nYW4gdW50dWsgdG9rZW4gcGVydGFtYToqKg0KDQpcWw0KXG1hdGhiZntafV97MX09DQpcYmVnaW57Ym1hdHJpeH0NCi0wLjc1ICYgMS4wMw0KXGVuZHtibWF0cml4fS4NClxdDQoNClJhdGEtcmF0YSB0b2tlbiBwZXJ0YW1hIGFkYWxhaDoNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0KXG11X3taLDF9DQomPVxmcmFjey0wLjc1KzEuMDN9ezJ9XFwNCiY9MC4xNC4NClxlbmR7YWxpZ25lZH0NClxdDQoNClZhcmlhbnNueWEgYWRhbGFoOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpcc2lnbWFfe1osMX1eMg0KJj1cZnJhY3soLTAuNzUtMC4xNCleMisoMS4wMy0wLjE0KV4yfXsyfVxcDQomPVxmcmFjeygtMC44OSleMisoMC44OSleMn17Mn1cXA0KJj0wLjc5MjEuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpFbGVtZW4gcGVydGFtYSBzZXRlbGFoIG5vcm1hbGlzYXNpIGFkYWxhaDoNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0KR197MSwxfQ0KJj1cZnJhY3stMC43NS0wLjE0fXtcc3FydHswLjc5MjErMTBeey01fX19XFwNCiY9XGZyYWN7LTAuODl9ezAuODl9XFwNCiY9LTEuMDAuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpEZW5nYW4gY2FyYSB5YW5nIHNhbWEsIFwoR197MSwyfT0xLjAwXCkuIE1ha2E6DQoNClxbDQpcbWF0aGJme0d9X3sxfT0NClxiZWdpbntibWF0cml4fQ0KLTEuMDAgJiAxLjAwDQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KQXR1cmFuIHlhbmcgc2FtYSBkaXRlcmFwa2FuIHBhZGEgc2VsdXJ1aCB0b2tlbiwgc2VoaW5nZ2EgZGlwZXJvbGVoIHJlcHJlc2VudGFzaSBnbG9iYWwgVHJhbnNmb3JtZXIgXChcbWF0aGJme0d9XCkgYmVyaWt1dC4NCg0KXFsNClxtYXRoYmZ7R30NCj1cYmVnaW57Ym1hdHJpeH0NCi0xLjAwICYgMS4wMFxcDQotMS4wMCAmIDEuMDBcXA0KMS4wMCAmIC0xLjAwXFwNCjEuMDAgJiAtMS4wMFxcDQotMS4wMCAmIDEuMDBcXA0KLTEuMDAgJiAxLjAwXFwNCi0xLjAwICYgMS4wMFxcDQoxLjAwICYgLTEuMDBcXA0KMS4wMCAmIC0xLjAwXFwNCi0xLjAwICYgMS4wMFxcDQotMS4wMCAmIDEuMDBcXA0KLTEuMDAgJiAxLjAwXFwNCjEuMDAgJiAtMS4wMFxcDQoxLjAwICYgLTEuMDBcXA0KLTEuMDAgJiAxLjAwXFwNCi0xLjAwICYgMS4wMFxcDQotMS4wMCAmIDEuMDBcXA0KMS4wMCAmIC0xLjAwXFwNCjEuMDAgJiAtMS4wMFxcDQotMS4wMCAmIDEuMDBcXA0KLTEuMDAgJiAxLjAwXFwNCi0xLjAwICYgMS4wMFxcDQoxLjAwICYgLTEuMDBcXA0KLTEuMDAgJiAxLjAwXFwNCi0xLjAwICYgMS4wMA0KXGVuZHtibWF0cml4fS4NClxdDQoNCg0KIyMgNC4gRm9sZGluZywgUHJveWVrc2kgRml0dXIgR2xvYmFsLCBkYW4gRnVzaSBSZXNpZHVhbA0KDQpLZWx1YXJhbiBUcmFuc2Zvcm1lciBcKFxtYXRoYmZ7R31cKSBtYXNpaCBiZXJiZW50dWsgbWF0cmlrcyB0b2tlbiBiZXJkaW1lbnNpIFwoMjVcdGltZXMyXCkuIFRhaGFwICpmb2xkaW5nKiBtZW5nZW1iYWxpa2FuIHRva2VuIHRlcnNlYnV0IGtlIHN1c3VuYW4gc3Bhc2lhbCBcKDVcdGltZXM1XCkuIFNldGVsYWggaXR1LCBrZWR1YSBrYW5hbCBoYXNpbCAqZm9sZGluZyogZGlwcm95ZWtzaWthbiBtZW5qYWRpIHNhdHUgKmZlYXR1cmUgbWFwKiBnbG9iYWwgZGFuIGRpYWt0aWZrYW4gbWVuZ2d1bmFrYW4gZnVuZ3NpIFN3aXNoLiAqRmVhdHVyZSBtYXAqIGdsb2JhbCB0ZXJzZWJ1dCBrZW11ZGlhbiBkaWZ1c2lrYW4gZGVuZ2FuICpmZWF0dXJlIG1hcCogbG9rYWwgXChcbWF0aGJme0x9XCkgZGFuICpmZWF0dXJlIG1hcCogbWFzdWthbiBcKFxtYXRoYmZ7WH1cKS4NCg0KIyMjIGEuIEZvbGRpbmcgS2VsdWFyYW4gVHJhbnNmb3JtZXINCg0KKkZvbGRpbmcqIG1lbmVtcGF0a2FuIGtlbWJhbGkgdG9rZW4ga2UtXCh0XCkgcGFkYSBwb3Npc2kgc3Bhc2lhbCBcKChpLGopXCkgYmVyZGFzYXJrYW4gdXJ1dGFuIHJhc3RlciBkYXJpIGtpcmkga2Uga2FuYW4gZGFuIGRhcmkgYXRhcyBrZSBiYXdhaDoNCg0KXFsNCnQ9VyhpLTEpK2osDQpccXF1YWQgVz01Lg0KXF0NCg0KS29sb20gcGVydGFtYSBkYXJpIG1hdHJpa3MgdG9rZW4gXChcbWF0aGJme0d9XCkgZGlsaXBhdCBtZW5qYWRpIGthbmFsIHBlcnRhbWEgXChcbWF0aGJme0d9XzFcKSwgc2VkYW5na2FuIGtvbG9tIGtlZHVhIGRpbGlwYXQgbWVuamFkaSBrYW5hbCBrZWR1YSBcKFxtYXRoYmZ7R31fMlwpLiBLZWR1YSBtYXRyaWtzIGhhc2lsICpmb2xkaW5nKiBtZW1pbGlraSBkaW1lbnNpIFwoNVx0aW1lczVcKS4NCg0KLSAqKlJ1bXVzOioqDQoNClxbDQpHX3tuLGksan09R197dCxufSwNClxxcXVhZA0Kbj0xLDIsDQpccXF1YWQNCnQ9VyhpLTEpK2ouDQpcXQ0KDQotICoqQ29udG9oIHBlcmhpdHVuZ2FuIHBhZGEgcG9zaXNpIFwoKDEsMSlcKToqKg0KDQpQb3Npc2kgXCgoMSwxKVwpIGJlcnNlc3VhaWFuIGRlbmdhbiB0b2tlbiBwZXJ0YW1hOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQp0Jj01KDEtMSkrMVxcDQomPTEuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpLYXJlbmEgdG9rZW4gcGVydGFtYSBhZGFsYWg6DQoNClxbDQpcbWF0aGJme0d9X3t0PTF9PQ0KXGJlZ2lue2JtYXRyaXh9DQotMS4wMCAmIDEuMDANClxlbmR7Ym1hdHJpeH0sDQpcXQ0KDQptYWthIGhhc2lsICpmb2xkaW5nKiBwYWRhIHBvc2lzaSBcKCgxLDEpXCkgYWRhbGFoOg0KDQpcWw0KR197MSwxLDF9PUdfezEsMX09LTEuMDAsDQpccXF1YWQNCkdfezIsMSwxfT1HX3sxLDJ9PTEuMDAuDQpcXQ0KDQpNYXRyaWtzIGthbmFsIHBlcnRhbWEgc2V0ZWxhaCAqZm9sZGluZyogYWRhbGFoOg0KDQpcWw0KXG1hdGhiZntHfV8xPQ0KXGJlZ2lue2JtYXRyaXh9DQotMS4wMCAmIC0xLjAwICYgMS4wMCAmIDEuMDAgJiAtMS4wMFxcDQotMS4wMCAmIC0xLjAwICYgMS4wMCAmIDEuMDAgJiAtMS4wMFxcDQotMS4wMCAmIC0xLjAwICYgMS4wMCAmIDEuMDAgJiAtMS4wMFxcDQotMS4wMCAmIC0xLjAwICYgMS4wMCAmIDEuMDAgJiAtMS4wMFxcDQotMS4wMCAmIC0xLjAwICYgMS4wMCAmIC0xLjAwICYgLTEuMDANClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQpNYXRyaWtzIGthbmFsIGtlZHVhIHNldGVsYWggKmZvbGRpbmcqIGFkYWxhaDoNCg0KXFsNClxtYXRoYmZ7R31fMj0NClxiZWdpbntibWF0cml4fQ0KMS4wMCAmIDEuMDAgJiAtMS4wMCAmIC0xLjAwICYgMS4wMFxcDQoxLjAwICYgMS4wMCAmIC0xLjAwICYgLTEuMDAgJiAxLjAwXFwNCjEuMDAgJiAxLjAwICYgLTEuMDAgJiAtMS4wMCAmIDEuMDBcXA0KMS4wMCAmIDEuMDAgJiAtMS4wMCAmIC0xLjAwICYgMS4wMFxcDQoxLjAwICYgMS4wMCAmIC0xLjAwICYgMS4wMCAmIDEuMDANClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQojIyMgYi4gUHJveWVrc2kgZGFuIEFrdGl2YXNpIEZpdHVyIEdsb2JhbA0KDQpLZWR1YSBrYW5hbCBoYXNpbCAqZm9sZGluZyosIHlhaXR1IFwoXG1hdGhiZntHfV8xXCkgZGFuIFwoXG1hdGhiZntHfV8yXCksIGRpcHJveWVrc2lrYW4gbWVuamFkaSBzYXR1ICpmZWF0dXJlIG1hcCogZ2xvYmFsIG1lbmdndW5ha2FuICpwb2ludHdpc2UgY29udm9sdXRpb24qIFwoMVx0aW1lczFcKS4gUGFkYSBpbHVzdHJhc2kgaW5pLCBiaWFzIHRpZGFrIGRpZ3VuYWthbi4gQm9ib3QgKnBvaW50d2lzZSBjb252b2x1dGlvbiogdW50dWsgcHJveWVrc2kgZ2xvYmFsIGRpdGV0YXBrYW4gc2ViYWdhaToNCg0KXFsNClxtYXRoYmZ7V31fe1xtYXRocm17cHd9fV57KFxtYXRocm17Z2xvYn0pfQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQowLjYwICYgLTAuNDANClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQotICoqUnVtdXM6KioNCg0KXFsNCkZfe1xtYXRocm17cHd9LGksaiwxfV57KFxtYXRocm17Z2xvYn0pfQ0KPQ0KXHN1bV97bj0xfV57Mn0NCldfe1xtYXRocm17cHd9LG4sMX1eeyhcbWF0aHJte2dsb2J9KX0NCkdfe24saSxqfS4NClxdDQoNCkJlcmRhc2Fya2FuIGJvYm90IHlhbmcgZGlndW5ha2FuLCBkaXBlcm9sZWg6DQoNClxbDQpGX3tcbWF0aHJte3B3fSxpLGosMX1eeyhcbWF0aHJte2dsb2J9KX0NCj0NCjAuNjBHX3sxLGksan0tMC40MEdfezIsaSxqfS4NClxdDQoNCktlbHVhcmFuIHByb3lla3NpIGtlbXVkaWFuIGRpYWt0aWZrYW4gbWVuZ2d1bmFrYW4gZnVuZ3NpIFN3aXNoOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpHX3tcbWF0aHJte2dsb2JhbH0saSxqfQ0KJj0NClxvcGVyYXRvcm5hbWV7U3dpc2h9DQpcbGVmdCgNCkZfe1xtYXRocm17cHd9LGksaiwxfV57KFxtYXRocm17Z2xvYn0pfQ0KXHJpZ2h0KVxcDQomPQ0KXGZyYWN7Rl97XG1hdGhybXtwd30saSxqLDF9XnsoXG1hdGhybXtnbG9ifSl9fQ0KezErZV57LUZfe1xtYXRocm17cHd9LGksaiwxfV57KFxtYXRocm17Z2xvYn0pfX19Lg0KXGVuZHthbGlnbmVkfQ0KXF0NCg0KTWF0cmlrcyBcKFxtYXRoYmZ7Rn1fe1xtYXRocm17cHd9fV57KFxtYXRocm17Z2xvYn0pfVwpIGRhbiBcKFxtYXRoYmZ7R31fe1xtYXRocm17Z2xvYmFsfX1cKSBrZWR1YW55YSBiZXJkaW1lbnNpIFwoNVx0aW1lczVcKS4NCg0KLSAqKkNvbnRvaCBwZXJoaXR1bmdhbiBwYWRhIHBvc2lzaSBcKCgxLDEpXCk6KioNCg0KRGlrZXRhaHVpOg0KDQpcWw0KR197MSwxLDF9PS0xLjAwLA0KXHFxdWFkDQpHX3syLDEsMX09MS4wMC4NClxdDQoNCk5pbGFpIGhhc2lsICpwb2ludHdpc2UgY29udm9sdXRpb24qIHNlYmVsdW0gYWt0aXZhc2kgYWRhbGFoOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpGX3tcbWF0aHJte3B3fSwxLDEsMX1eeyhcbWF0aHJte2dsb2J9KX0NCiY9DQowLjYwR197MSwxLDF9LTAuNDBHX3syLDEsMX1cXA0KJj0NCjAuNjAoLTEuMDApLTAuNDAoMS4wMClcXA0KJj0NCi0wLjYwLTAuNDBcXA0KJj0NCi0xLjAwLg0KXGVuZHthbGlnbmVkfQ0KXF0NCg0KU2VsYW5qdXRueWEsIG5pbGFpIHRlcnNlYnV0IGRpYWt0aWZrYW4gbWVuZ2d1bmFrYW4gZnVuZ3NpIFN3aXNoOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpHX3tcbWF0aHJte2dsb2JhbH0sMSwxfQ0KJj0NClxmcmFje0Zfe1xtYXRocm17cHd9LDEsMSwxfV57KFxtYXRocm17Z2xvYn0pfX0NCnsxK2Veey1GX3tcbWF0aHJte3B3fSwxLDEsMX1eeyhcbWF0aHJte2dsb2J9KX19fVxcDQomPQ0KXGZyYWN7LTEuMDB9ezErZV57LSgtMS4wMCl9fVxcDQomPQ0KXGZyYWN7LTEuMDB9ezErZV57MS4wMH19XFwNCiY9DQpcZnJhY3stMS4wMH17MSsyLjcyfVxcDQomPQ0KLTAuMjcuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpEZW5nYW4gcGVyaGl0dW5nYW4geWFuZyBzYW1hIHVudHVrIHNlbHVydWggcG9zaXNpLCBkaXBlcm9sZWggKmZlYXR1cmUgbWFwKiBnbG9iYWw6DQoNClxbDQpcbWF0aGJme0d9X3tcbWF0aHJte2dsb2JhbH19PQ0KXGJlZ2lue2JtYXRyaXh9DQotMC4yNyAmIC0wLjI3ICYgMC43MyAmIDAuNzMgJiAtMC4yN1xcDQotMC4yNyAmIC0wLjI3ICYgMC43MyAmIDAuNzMgJiAtMC4yN1xcDQotMC4yNyAmIC0wLjI3ICYgMC43MyAmIDAuNzMgJiAtMC4yN1xcDQotMC4yNyAmIC0wLjI3ICYgMC43MyAmIDAuNzMgJiAtMC4yN1xcDQotMC4yNyAmIC0wLjI3ICYgMC43MyAmIC0wLjI3ICYgLTAuMjcNClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQojIyMgYy4gRnVzaSBSZXNpZHVhbCBGaXR1ciBMb2thbCBkYW4gR2xvYmFsDQoNCipGZWF0dXJlIG1hcCogbWFzdWthbiBcKFxtYXRoYmZ7WH1cKSwgZml0dXIgbG9rYWwgXChcbWF0aGJme0x9XCksIGRhbiAqZmVhdHVyZSBtYXAqIGdsb2JhbCBcKFxtYXRoYmZ7R31fe1xtYXRocm17Z2xvYmFsfX1cKSBkaWdhYnVuZ2thbiBtZWxhbHVpIGZ1c2kgcmVzaWR1YWwuIFBhZGEgaWx1c3RyYXNpIGluaSwgKnBvaW50d2lzZSBjb252b2x1dGlvbiogXCgxXHRpbWVzMVwpIG1lbXByb3lla3Npa2FuIGZpdHVyIGxva2FsIGRhbiBmaXR1ciBnbG9iYWwgbWVuamFkaSBzYXR1IGthbmFsLCBrZW11ZGlhbiBoYXNpbG55YSBkaXRhbWJhaGthbiBkZW5nYW4gZml0dXIgbWFzdWthbiBcKFxtYXRoYmZ7WH1cKS4NCg0KLSAqKkJvYm90IGZ1c2k6KioNCg0KXFsNClxtYXRoYmZ7V31fe1xtYXRocm17cHd9fV57KFxtYXRocm17ZnVzZX0pfQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQowLjUwICYgMC41MA0KXGVuZHtibWF0cml4fS4NClxdDQoNCi0gKipSdW11czoqKg0KDQpcWw0KRl97XG1hdGhybXtwd30saSxqLDF9XnsoXG1hdGhybXtmdXNlfSl9DQo9DQowLjUwTF97aSxqfQ0KKw0KMC41MEdfe1xtYXRocm17Z2xvYmFsfSxpLGp9Lg0KXF0NCg0KXFsNClhfe2ksan1eeygwLDApfQ0KPQ0KWF97aSxqfQ0KKw0KRl97XG1hdGhybXtwd30saSxqLDF9XnsoXG1hdGhybXtmdXNlfSl9Lg0KXF0NCg0KU2VjYXJhIGtlc2VsdXJ1aGFuLCBwcm9zZXMgZnVzaSByZXNpZHVhbCBkaXJ1bXVza2FuIHNlYmFnYWk6DQoNClxbDQpcbWF0aGJme1h9XnsoMCwwKX0NCj0NClxtYXRoYmZ7WH0NCisNClxvcGVyYXRvcm5hbWV7Q29udn1fezFcdGltZXMxfV57KFxtYXRocm17ZnVzZX0pfQ0KXGxlZnQoDQpcb3BlcmF0b3JuYW1le0NvbmNhdH0NClxsZWZ0Ww0KXG1hdGhiZntMfSwNClxtYXRoYmZ7R31fe1xtYXRocm17Z2xvYmFsfX0NClxyaWdodF0NClxyaWdodCkuDQpcXQ0KDQpTZWx1cnVoIG1hdHJpa3MgcGFkYSBvcGVyYXNpIHRlcnNlYnV0IGJlcmRpbWVuc2kgXCg1XHRpbWVzNVwpLCBzZWhpbmdnYSBoYXNpbCBmdXNpIFwoXG1hdGhiZntYfV57KDAsMCl9XCkganVnYSBiZXJkaW1lbnNpIFwoNVx0aW1lczVcKS4NCg0KLSAqKkNvbnRvaCBwZXJoaXR1bmdhbiBwYWRhIHBvc2lzaSBcKCgxLDEpXCk6KioNCg0KRGlrZXRhaHVpOg0KDQpcWw0KWF97MSwxfT0tMi4xMiwNClxxcXVhZA0KTF97MSwxfT0tMC4yNywNClxxcXVhZA0KR197XG1hdGhybXtnbG9iYWx9LDEsMX09LTAuMjcuDQpcXQ0KDQpOaWxhaSBrZWx1YXJhbiAqcG9pbnR3aXNlIGNvbnZvbHV0aW9uKiBhZGFsYWg6DQoNClxbDQpcYmVnaW57YWxpZ25lZH0NCkZfe1xtYXRocm17cHd9LDEsMSwxfV57KFxtYXRocm17ZnVzZX0pfQ0KJj0NCjAuNTBMX3sxLDF9DQorDQowLjUwR197XG1hdGhybXtnbG9iYWx9LDEsMX1cXA0KJj0NCjAuNTAoLTAuMjcpDQorDQowLjUwKC0wLjI3KVxcDQomPQ0KLTAuMTM1LTAuMTM1XFwNCiY9DQotMC4yNy4NClxlbmR7YWxpZ25lZH0NClxdDQoNCk1ha2EsIGhhc2lsIGZ1c2kgcmVzaWR1YWwgcGFkYSBwb3Npc2kgXCgoMSwxKVwpIGFkYWxhaDoNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0KWF97MSwxfV57KDAsMCl9DQomPQ0KWF97MSwxfQ0KKw0KRl97XG1hdGhybXtwd30sMSwxLDF9XnsoXG1hdGhybXtmdXNlfSl9XFwNCiY9DQotMi4xMisoLTAuMjcpXFwNCiY9DQotMi4zOS4NClxlbmR7YWxpZ25lZH0NClxdDQoNCkF0dXJhbiB5YW5nIHNhbWEgZGl0ZXJhcGthbiBwYWRhIHNlbHVydWggcG9zaXNpLiBEZW5nYW4gbWVuZ2d1bmFrYW4gbmlsYWkgXChcbWF0aGJme0d9X3tcbWF0aHJte2dsb2JhbH19XCkgeWFuZyB0ZWxhaCBkaWJ1bGF0a2FuIGhpbmdnYSBkdWEgYW5na2EgZGkgYmVsYWthbmcga29tYSwgZGlwZXJvbGVoICpmZWF0dXJlIG1hcCogaGFzaWwgZnVzaSBiZXJpa3V0Og0KDQpcWw0KXG1hdGhiZntYfV57KDAsMCl9DQo9DQpcYmVnaW57Ym1hdHJpeH0NCi0yLjM5ICYgLTEuMjggJiAxLjgyICYgMS4xMiAmIC0xLjg0XFwNCi0yLjM4ICYgLTEuMDAgJiAyLjI0ICYgMS41MCAmIC0xLjcwXFwNCi0yLjM4ICYgLTEuMDAgJiAyLjI0ICYgMS41MCAmIC0xLjcwXFwNCi0yLjM4ICYgLTEuMTQgJiAxLjg0ICYgMS4xMSAmIC0xLjg1XFwNCi0yLjI1ICYgLTEuNTcgJiAwLjc3ICYgLTAuMzggJiAtMS45OQ0KXGVuZHtibWF0cml4fS4NClxdDQoNCg0KIyMgNS4gRW5jb2RlciBCZXJ0aW5na2F0IA0KDQojIyMgYS4gRG93bnNhbXBsaW5nIEVuY29kZXIgUGVydGFtYSAoXChcbWF0aGJme1h9XnsxLDB9XCkpDQoNCipGZWF0dXJlIG1hcCogbWFzdWthbiBcKFxtYXRoYmZ7WH1eezAsMH1cKSBiZXJ1a3VyYW4gXCg1XHRpbWVzNVwpIGRpcHJvc2VzIG1lbmdndW5ha2FuICpzdHJpZGVkIGNvbnZvbHV0aW9uKiBkZW5nYW4ga2VybmVsIFwoM1x0aW1lczNcKSwgKnN0cmlkZSogXCgyXCksICp6ZXJvIHBhZGRpbmcqIHNlYmVzYXIgXCgxXCkgcGFkYSBzZXRpYXAgc2lzaSwgZGFuIHRhbnBhIGJpYXMgdW50dWsgbWVuZ2hhc2lsa2FuICpmZWF0dXJlIG1hcCogXChcbWF0aGJme1h9XnsxLDB9XCkuDQoNCk1hdHJpa3MgKmZlYXR1cmUgbWFwKiBtYXN1a2FuIHlhbmcgZGlndW5ha2FuIGFkYWxhaDoNCg0KXFsNClxtYXRoYmZ7WH1eezAsMH0NCj0NClxiZWdpbntibWF0cml4fQ0KLTIuMzkgJiAtMS4yOCAmIDEuODIgJiAxLjEyICYgLTEuODRcXA0KLTIuMzggJiAtMS4wMCAmIDIuMjQgJiAxLjUwICYgLTEuNzBcXA0KLTIuMzggJiAtMS4wMCAmIDIuMjQgJiAxLjUwICYgLTEuNzBcXA0KLTIuMzggJiAtMS4xNCAmIDEuODQgJiAxLjExICYgLTEuODVcXA0KLTIuMjUgJiAtMS41NyAmIDAuNzcgJiAtMC4zOCAmIC0xLjk5DQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KVWt1cmFuIGtlbHVhcmFuICpzdHJpZGVkIGNvbnZvbHV0aW9uKiBkaWhpdHVuZyBtZW5nZ3VuYWthbjoNCg0KXFsNCm8NCj0NClxsZWZ0XGxmbG9vcg0KXGZyYWN7aSsycC1rfXtzfQ0KXHJpZ2h0XHJmbG9vcisxLA0KXF0NCg0KZGVuZ2FuIFwoaVwpIG1lbnlhdGFrYW4gdWt1cmFuIHNwYXNpYWwgbWFzdWthbiwgXChwXCkgbWVydXBha2FuIGp1bWxhaCAqcGFkZGluZyogcGFkYSBzZXRpYXAgc2lzaSwgXChrXCkgbWVydXBha2FuIHVrdXJhbiBrZXJuZWwsIGRhbiBcKHNcKSBtZXJ1cGFrYW4gKnN0cmlkZSouDQoNClBhZGEgaWx1c3RyYXNpIGluaSwgZGlndW5ha2FuIFwoaT01XCksIFwoaz0zXCksIFwocD0xXCksIGRhbiBcKHM9MlwpLCBzZWhpbmdnYToNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0Kbw0KJj0NClxsZWZ0XGxmbG9vcg0KXGZyYWN7NSsyKDEpLTN9ezJ9DQpccmlnaHRccmZsb29yKzFcXA0KJj0NClxsZWZ0XGxmbG9vcg0KXGZyYWN7NH17Mn0NClxyaWdodFxyZmxvb3IrMVxcDQomPTMuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpEZW5nYW4gZGVtaWtpYW4sIHVrdXJhbiBzcGFzaWFsICpmZWF0dXJlIG1hcCogYmVya3VyYW5nIGRhcmkgXCg1XHRpbWVzNVwpIG1lbmphZGkgXCgzXHRpbWVzM1wpLg0KDQotICoqUGVuYW1iYWhhbiBaZXJvIFBhZGRpbmc6KioNCg0KU2ViZWx1bSBvcGVyYXNpIGtvbnZvbHVzaSBkaWxha3VrYW4sIHNhdHUgbGFwaXNhbiBuaWxhaSBub2wgZGl0YW1iYWhrYW4gcGFkYSBrZWVtcGF0IHNpc2kgbWF0cmlrcyBtYXN1a2FuLCB5YWl0dSBzaXNpIGF0YXMsIGJhd2FoLCBraXJpLCBkYW4ga2FuYW4uIFBlbmFtYmFoYW4gKnBhZGRpbmcqIGluaSBtZW5ndWJhaCB1a3VyYW4gbWF0cmlrcyBkYXJpIFwoNVx0aW1lczVcKSBtZW5qYWRpIFwoN1x0aW1lczdcKS4NCg0KTWF0cmlrcyBzZXRlbGFoIHBlbmFtYmFoYW4gKnplcm8gcGFkZGluZyogYWRhbGFoOg0KDQpcWw0KXG1hdGhiZntYfV97XG1hdGhybXtwYWR9fV57MCwwfQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQowLjAwICYgMC4wMCAmIDAuMDAgJiAwLjAwICYgMC4wMCAmIDAuMDAgJiAwLjAwXFwNCjAuMDAgJiAtMi4zOSAmIC0xLjI4ICYgMS44MiAmIDEuMTIgJiAtMS44NCAmIDAuMDBcXA0KMC4wMCAmIC0yLjM4ICYgLTEuMDAgJiAyLjI0ICYgMS41MCAmIC0xLjcwICYgMC4wMFxcDQowLjAwICYgLTIuMzggJiAtMS4wMCAmIDIuMjQgJiAxLjUwICYgLTEuNzAgJiAwLjAwXFwNCjAuMDAgJiAtMi4zOCAmIC0xLjE0ICYgMS44NCAmIDEuMTEgJiAtMS44NSAmIDAuMDBcXA0KMC4wMCAmIC0yLjI1ICYgLTEuNTcgJiAwLjc3ICYgLTAuMzggJiAtMS45OSAmIDAuMDBcXA0KMC4wMCAmIDAuMDAgJiAwLjAwICYgMC4wMCAmIDAuMDAgJiAwLjAwICYgMC4wMA0KXGVuZHtibWF0cml4fS4NClxdDQoNCi0gKipLZXJuZWwgRW5jb2RlciBQZXJ0YW1hOioqDQoNClBhZGEgaWx1c3RyYXNpIGluaSwgbWF0cmlrcyBib2JvdCBrZXJuZWwgZW5jb2RlciBwZXJ0YW1hIGRpdGV0YXBrYW4gc2ViYWdhaToNCg0KXFsNClxtYXRoYmZ7V31fe1xtYXRocm17ZW5jfX1eeygxKX0NCj0NClxiZWdpbntibWF0cml4fQ0KMC4wMCAmIDAuMDAgJiAwLjAwXFwNCjAuMDAgJiAxLjAwICYgMC4wMFxcDQowLjAwICYgMC4wMCAmIDAuMDANClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQpLZXJuZWwgdGVyc2VidXQgbWVtaWxpa2kgc2F0dSBib2JvdCBiZXJuaWxhaSBcKDEuMDBcKSBwYWRhIHBvc2lzaSB0ZW5nYWgsIHNlZGFuZ2thbiBkZWxhcGFuIGJvYm90IGxhaW5ueWEgYmVybmlsYWkgXCgwLjAwXCkuIE9sZWgga2FyZW5hIGl0dSwgc2V0aWFwIGhhc2lsIGtvbnZvbHVzaSBkaXBlcm9sZWggbWVsYWx1aSBwZXJrYWxpYW4gc2VtYmlsYW4gZWxlbWVuIHBhZGEgYXJlYSAqZmVhdHVyZSBtYXAqIGRlbmdhbiBzZW1iaWxhbiBib2JvdCBrZXJuZWwsIGtlbXVkaWFuIHNlbHVydWggaGFzaWwgcGVya2FsaWFuIGRpanVtbGFoa2FuLg0KDQotICoqUnVtdXM6KioNCg0KT3BlcmFzaSAqc3RyaWRlZCBjb252b2x1dGlvbiogZGlydW11c2thbiBzZWJhZ2FpOg0KDQpcWw0KXG1hdGhiZntYfV57MSwwfQ0KPQ0KXG9wZXJhdG9ybmFtZXtDb252fV97M1x0aW1lczMsXCxzPTIsXCxwPTF9DQpcbGVmdCgNClxtYXRoYmZ7WH1eezAsMH07DQpcbWF0aGJme1d9X3tcbWF0aHJte2VuY319XnsoMSl9DQpccmlnaHQpLg0KXF0NCg0KVW50dWsgZWxlbWVuIGtlbHVhcmFuIHBhZGEgYmFyaXMga2UtXChyXCkgZGFuIGtvbG9tIGtlLVwoY1wpLCBwZXJoaXR1bmdhbiBrb252b2x1c2kgZGFwYXQgZGlueWF0YWthbiBzZWJhZ2FpOg0KDQpcWw0KWF97cixjfV57MSwwfQ0KPQ0KXHN1bV97YT0xfV57M30NClxzdW1fe2I9MX1eezN9DQpXX3tcbWF0aHJte2VuY30sYSxifV57KDEpfQ0KWF97XG1hdGhybXtwYWR9LFwsMnIrYS0yLFwsMmMrYi0yfV57MCwwfSwNClxdDQoNCmRlbmdhbiBcKHIsYz0xLDIsM1wpLCBzZWRhbmdrYW4gXChhXCkgZGFuIFwoYlwpIG1lcnVwYWthbiBpbmRla3MgYmFyaXMgZGFuIGtvbG9tIGtlcm5lbC4NCg0KUGFkYSBzZXRpYXAgcG9zaXNpLCBrZXJuZWwgbWVuY2FrdXAgYXJlYSBiZXJ1a3VyYW4gXCgzXHRpbWVzM1wpLiBLYXJlbmEgKnN0cmlkZSogYmVybmlsYWkgXCgyXCksIGtlcm5lbCBiZXJnZXNlciBkdWEga29sb20ga2Uga2FuYW4gdW50dWsgbWVuZ2hpdHVuZyBlbGVtZW4gYmVyaWt1dG55YSBwYWRhIGJhcmlzIGtlbHVhcmFuIHlhbmcgc2FtYS4gU2V0ZWxhaCBtZW5jYXBhaSBwb3Npc2kgdGVyYWtoaXIgcGFkYSBiYXJpcyB0ZXJzZWJ1dCwga2VybmVsIGtlbWJhbGkga2Ugc2lzaSBraXJpIGRhbiBiZXJnZXNlciBkdWEgYmFyaXMga2UgYmF3YWguDQoNCi0gKipDb250b2ggUGVyaGl0dW5nYW4gS29udm9sdXNpOioqDQoNCioqMS4gUGVyaGl0dW5nYW4gZWxlbWVuIHBhZGEgcG9zaXNpIFwoKDEsMSlcKSoqDQoNClVudHVrIG1lbmdoYXNpbGthbiBlbGVtZW4gcGVydGFtYSBcKFxtYXRoYmZ7WH1eezEsMH1cKSwga2VybmVsIGRpdGVtcGF0a2FuIHBhZGEgYXJlYSBcKDNcdGltZXMzXCkgZGkgcG9qb2sga2lyaSBhdGFzIG1hdHJpa3MgeWFuZyB0ZWxhaCBkaWJlcmkgKnBhZGRpbmcqLg0KDQpBcmVhICpmZWF0dXJlIG1hcCogeWFuZyBkaXByb3NlcyBhZGFsYWg6DQoNClxbDQpcYmVnaW57Ym1hdHJpeH0NCjAuMDAgJiAwLjAwICYgMC4wMFxcDQowLjAwICYgLTIuMzkgJiAtMS4yOFxcDQowLjAwICYgLTIuMzggJiAtMS4wMA0KXGVuZHtibWF0cml4fS4NClxdDQoNCkFyZWEgdGVyc2VidXQgZGlrYWxpa2FuIHNlY2FyYSBlbGVtZW4gZGVtaSBlbGVtZW4gZGVuZ2FuIGJvYm90IGtlcm5lbCBcKFxtYXRoYmZ7V31fe1xtYXRocm17ZW5jfX1eeygxKX1cKSwga2VtdWRpYW4gaGFzaWxueWEgZGlqdW1sYWhrYW4gc2ViYWdhaSBiZXJpa3V0Og0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpYX3sxLDF9XnsxLDB9DQo9e30mDQooMC4wMCkoMC4wMCkNCisoMC4wMCkoMC4wMCkNCisoMC4wMCkoMC4wMClcXA0KJisoMC4wMCkoMC4wMCkNCisoLTIuMzkpKDEuMDApDQorKC0xLjI4KSgwLjAwKVxcDQomKygwLjAwKSgwLjAwKQ0KKygtMi4zOCkoMC4wMCkNCisoLTEuMDApKDAuMDApXFwNCj17fSYtMi4zOS4NClxlbmR7YWxpZ25lZH0NClxdDQoNCkRlbmdhbiBkZW1pa2lhbiwgZWxlbWVuIHBlcnRhbWEgcGFkYSAqZmVhdHVyZSBtYXAqIGtlbHVhcmFuIGFkYWxhaCBcKFhfezEsMX1eezEsMH09LTIuMzlcKS4NCg0KKioyLiBQZXJoaXR1bmdhbiBlbGVtZW4gcGFkYSBwb3Npc2kgXCgoMSwyKVwpKioNCg0KVW50dWsgbWVuZ2hpdHVuZyBlbGVtZW4gcGFkYSBwb3Npc2kgXCgoMSwyKVwpLCBrZXJuZWwgYmVyZ2VzZXIgZHVhIGtvbG9tIGtlIGthbmFuIGRhcmkgcG9zaXNpIHNlYmVsdW1ueWEga2FyZW5hICpzdHJpZGUqIHlhbmcgZGlndW5ha2FuIGFkYWxhaCBcKDJcKS4NCg0KQXJlYSAqZmVhdHVyZSBtYXAqIHlhbmcgZGlwcm9zZXMgbWVuamFkaToNCg0KXFsNClxiZWdpbntibWF0cml4fQ0KMC4wMCAmIDAuMDAgJiAwLjAwXFwNCi0xLjI4ICYgMS44MiAmIDEuMTJcXA0KLTEuMDAgJiAyLjI0ICYgMS41MA0KXGVuZHtibWF0cml4fS4NClxdDQoNClBlcmhpdHVuZ2FuIGtvbnZvbHVzaSBkaWxha3VrYW4gbWVuZ2d1bmFrYW4gYm9ib3Qga2VybmVsIHlhbmcgc2FtYToNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0KWF97MSwyfV57MSwwfQ0KPXt9Jg0KKDAuMDApKDAuMDApDQorKDAuMDApKDAuMDApDQorKDAuMDApKDAuMDApXFwNCiYrKC0xLjI4KSgwLjAwKQ0KKygxLjgyKSgxLjAwKQ0KKygxLjEyKSgwLjAwKVxcDQomKygtMS4wMCkoMC4wMCkNCisoMi4yNCkoMC4wMCkNCisoMS41MCkoMC4wMClcXA0KPXt9JjEuODIuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpEZW5nYW4gZGVtaWtpYW4sIGVsZW1lbiBwYWRhIHBvc2lzaSBcKCgxLDIpXCkgZGFyaSAqZmVhdHVyZSBtYXAqIGtlbHVhcmFuIGFkYWxhaCBcKFhfezEsMn1eezEsMH09MS44MlwpLg0KDQpQcm9zZWR1ciB5YW5nIHNhbWEgZGl0ZXJhcGthbiBwYWRhIHNlbHVydWggcG9zaXNpIGtlcm5lbC4gS2FyZW5hIGhhbnlhIGJvYm90IHRlbmdhaCBrZXJuZWwgeWFuZyBiZXJuaWxhaSBcKDEuMDBcKSwgbmlsYWkga2VsdWFyYW4gcGFkYSBzZXRpYXAgcG9zaXNpIHNhbWEgZGVuZ2FuIG5pbGFpIGVsZW1lbiB0ZW5nYWggZGFyaSBhcmVhICpmZWF0dXJlIG1hcCogeWFuZyBzZWRhbmcgZGlwcm9zZXMuIEhhbCB0ZXJzZWJ1dCBtZXJ1cGFrYW4ga29uc2VrdWVuc2kgZGFyaSBib2JvdCBrZXJuZWwgeWFuZyBkaXRldGFwa2FuIHBhZGEgaWx1c3RyYXNpIGluaSwgYnVrYW4ga2FyYWt0ZXJpc3RpayB1bXVtIGRhcmkgc2VsdXJ1aCBvcGVyYXNpIGtvbnZvbHVzaS4NCg0KU2V0ZWxhaCBzZWx1cnVoIHNlbWJpbGFuIHBvc2lzaSBrb252b2x1c2kgZGloaXR1bmcsIGRpcGVyb2xlaCAqZmVhdHVyZSBtYXAqIGtlbHVhcmFuIGJlcnVrdXJhbiBcKDNcdGltZXMzXCkgc2ViYWdhaSBiZXJpa3V0Og0KDQpcWw0KXG1hdGhiZntYfV57MSwwfQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQotMi4zOSAmIDEuODIgJiAtMS44NFxcDQotMi4zOCAmIDIuMjQgJiAtMS43MFxcDQotMi4yNSAmIDAuNzcgJiAtMS45OQ0KXGVuZHtibWF0cml4fS4NClxdDQoNCkhhc2lsIHRlcnNlYnV0IG1lbnVuanVra2FuIGJhaHdhIG9wZXJhc2kgKnN0cmlkZWQgY29udm9sdXRpb24qIG1lbmd1cmFuZ2kgdWt1cmFuIHNwYXNpYWwgKmZlYXR1cmUgbWFwKiBkYXJpIFwoNVx0aW1lczVcKSBtZW5qYWRpIFwoM1x0aW1lczNcKS4gUGFkYSBpbHVzdHJhc2kgaW5pLCBuaWxhaSBrZWx1YXJhbiBkaXRlbnR1a2FuIG9sZWggZWxlbWVuIHRlbmdhaCBwYWRhIHNldGlhcCBhcmVhIGtvbnZvbHVzaSBrYXJlbmEgYm9ib3Qga2VybmVsIGxhaW5ueWEgYmVybmlsYWkgbm9sLg0KDQoNCiMjIyBiLiBEb3duc2FtcGxpbmcgRW5jb2RlciBLZWR1YSAoXChcbWF0aGJme1h9XnsyLDB9XCkpDQoNCipGZWF0dXJlIG1hcCogXChcbWF0aGJme1h9XnsxLDB9XCkgYmVydWt1cmFuIFwoM1x0aW1lczNcKSBkaXByb3NlcyBrZW1iYWxpIG1lbmdndW5ha2FuICpzdHJpZGVkIGNvbnZvbHV0aW9uKiBkZW5nYW4ga2VybmVsIFwoM1x0aW1lczNcKSwgKnN0cmlkZSogXCgyXCksICp6ZXJvIHBhZGRpbmcqIHNlYmVzYXIgXCgxXCkgcGFkYSBzZXRpYXAgc2lzaSwgZGFuIHRhbnBhIGJpYXMgdW50dWsgbWVuZ2hhc2lsa2FuICpmZWF0dXJlIG1hcCogXChcbWF0aGJme1h9XnsyLDB9XCkuDQoNCk1hdHJpa3MgKmZlYXR1cmUgbWFwKiBtYXN1a2FuIHlhbmcgZGlwZXJvbGVoIGRhcmkgdGFoYXAgZG93bnNhbXBsaW5nIGVuY29kZXIgcGVydGFtYSBhZGFsYWg6DQoNClxbDQpcbWF0aGJme1h9XnsxLDB9DQo9DQpcYmVnaW57Ym1hdHJpeH0NCi0yLjM5ICYgMS44MiAmIC0xLjg0XFwNCi0yLjM4ICYgMi4yNCAmIC0xLjcwXFwNCi0yLjI1ICYgMC43NyAmIC0xLjk5DQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KVWt1cmFuIGtlbHVhcmFuICpzdHJpZGVkIGNvbnZvbHV0aW9uKiBkaWhpdHVuZyBtZW5nZ3VuYWthbjoNCg0KXFsNCm8NCj0NClxsZWZ0XGxmbG9vcg0KXGZyYWN7aSsycC1rfXtzfQ0KXHJpZ2h0XHJmbG9vcisxLA0KXF0NCg0KZGVuZ2FuIFwoaVwpIG1lbnlhdGFrYW4gdWt1cmFuIHNwYXNpYWwgbWFzdWthbiwgXChwXCkgbWVydXBha2FuIGp1bWxhaCAqcGFkZGluZyogcGFkYSBzZXRpYXAgc2lzaSwgXChrXCkgbWVydXBha2FuIHVrdXJhbiBrZXJuZWwsIGRhbiBcKHNcKSBtZXJ1cGFrYW4gKnN0cmlkZSouDQoNClBhZGEgaWx1c3RyYXNpIGluaSwgZGlndW5ha2FuIFwoaT0zXCksIFwoaz0zXCksIFwocD0xXCksIGRhbiBcKHM9MlwpLCBzZWhpbmdnYToNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0Kbw0KJj0NClxsZWZ0XGxmbG9vcg0KXGZyYWN7MysyKDEpLTN9ezJ9DQpccmlnaHRccmZsb29yKzFcXA0KJj0NClxsZWZ0XGxmbG9vcg0KXGZyYWN7Mn17Mn0NClxyaWdodFxyZmxvb3IrMVxcDQomPTIuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpEZW5nYW4gZGVtaWtpYW4sIHVrdXJhbiBzcGFzaWFsICpmZWF0dXJlIG1hcCogYmVya3VyYW5nIGRhcmkgXCgzXHRpbWVzM1wpIG1lbmphZGkgXCgyXHRpbWVzMlwpLg0KDQotICoqUGVuYW1iYWhhbiBaZXJvIFBhZGRpbmc6KioNCg0KU2ViZWx1bSBvcGVyYXNpIGtvbnZvbHVzaSBkaWxha3VrYW4sIHNhdHUgbGFwaXNhbiBuaWxhaSBub2wgZGl0YW1iYWhrYW4gcGFkYSBrZWVtcGF0IHNpc2kgbWF0cmlrcyBtYXN1a2FuLCB5YWl0dSBzaXNpIGF0YXMsIGJhd2FoLCBraXJpLCBkYW4ga2FuYW4uIFBlbmFtYmFoYW4gKnBhZGRpbmcqIGluaSBtZW5ndWJhaCB1a3VyYW4gbWF0cmlrcyBkYXJpIFwoM1x0aW1lczNcKSBtZW5qYWRpIFwoNVx0aW1lczVcKS4NCg0KTWF0cmlrcyBzZXRlbGFoIHBlbmFtYmFoYW4gKnplcm8gcGFkZGluZyogYWRhbGFoOg0KDQpcWw0KXG1hdGhiZntYfV97XG1hdGhybXtwYWR9fV57MSwwfQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQowLjAwICYgMC4wMCAmIDAuMDAgJiAwLjAwICYgMC4wMFxcDQowLjAwICYgLTIuMzkgJiAxLjgyICYgLTEuODQgJiAwLjAwXFwNCjAuMDAgJiAtMi4zOCAmIDIuMjQgJiAtMS43MCAmIDAuMDBcXA0KMC4wMCAmIC0yLjI1ICYgMC43NyAmIC0xLjk5ICYgMC4wMFxcDQowLjAwICYgMC4wMCAmIDAuMDAgJiAwLjAwICYgMC4wMA0KXGVuZHtibWF0cml4fS4NClxdDQoNCi0gKipLZXJuZWwgRW5jb2RlciBLZWR1YToqKg0KDQpQYWRhIGlsdXN0cmFzaSBpbmksIG1hdHJpa3MgYm9ib3Qga2VybmVsIGVuY29kZXIga2VkdWEgZGl0ZXRhcGthbiBzZWJhZ2FpOg0KDQpcWw0KXG1hdGhiZntXfV97XG1hdGhybXtlbmN9fV57KDIpfQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQowLjAwICYgMC4wMCAmIDAuMDBcXA0KMC4wMCAmIDEuMDAgJiAwLjAwXFwNCjAuMDAgJiAwLjAwICYgMC4wMA0KXGVuZHtibWF0cml4fS4NClxdDQoNCktlcm5lbCB0ZXJzZWJ1dCBtZW1pbGlraSBzYXR1IGJvYm90IGJlcm5pbGFpIFwoMS4wMFwpIHBhZGEgcG9zaXNpIHRlbmdhaCwgc2VkYW5na2FuIGRlbGFwYW4gYm9ib3QgbGFpbm55YSBiZXJuaWxhaSBcKDAuMDBcKS4gT2xlaCBrYXJlbmEgaXR1LCBzZXRpYXAgaGFzaWwga29udm9sdXNpIGRpcGVyb2xlaCBtZWxhbHVpIHBlcmthbGlhbiBzZW1iaWxhbiBlbGVtZW4gcGFkYSBhcmVhICpmZWF0dXJlIG1hcCogZGVuZ2FuIHNlbWJpbGFuIGJvYm90IGtlcm5lbCwga2VtdWRpYW4gc2VsdXJ1aCBoYXNpbCBwZXJrYWxpYW4gZGlqdW1sYWhrYW4uDQoNCi0gKipSdW11czoqKg0KDQpPcGVyYXNpICpzdHJpZGVkIGNvbnZvbHV0aW9uKiBwYWRhIGVuY29kZXIga2VkdWEgZGlydW11c2thbiBzZWJhZ2FpOg0KDQpcWw0KXG1hdGhiZntYfV57MiwwfQ0KPQ0KXG9wZXJhdG9ybmFtZXtDb252fV97M1x0aW1lczMsXCxzPTIsXCxwPTF9DQpcbGVmdCgNClxtYXRoYmZ7WH1eezEsMH07DQpcbWF0aGJme1d9X3tcbWF0aHJte2VuY319XnsoMil9DQpccmlnaHQpLg0KXF0NCg0KVW50dWsgZWxlbWVuIGtlbHVhcmFuIHBhZGEgYmFyaXMga2UtXChyXCkgZGFuIGtvbG9tIGtlLVwoY1wpLCBwZXJoaXR1bmdhbiBrb252b2x1c2kgZGFwYXQgZGlueWF0YWthbiBzZWJhZ2FpOg0KDQpcWw0KWF97cixjfV57MiwwfQ0KPQ0KXHN1bV97YT0xfV57M30NClxzdW1fe2I9MX1eezN9DQpXX3tcbWF0aHJte2VuY30sYSxifV57KDIpfQ0KWF97XG1hdGhybXtwYWR9LFwsMnIrYS0yLFwsMmMrYi0yfV57MSwwfSwNClxdDQoNCmRlbmdhbiBcKHIsYz0xLDJcKSwgc2VkYW5na2FuIFwoYVwpIGRhbiBcKGJcKSBtZXJ1cGFrYW4gaW5kZWtzIGJhcmlzIGRhbiBrb2xvbSBrZXJuZWwuDQoNClBhZGEgc2V0aWFwIHBvc2lzaSwga2VybmVsIG1lbmNha3VwIGFyZWEgYmVydWt1cmFuIFwoM1x0aW1lczNcKS4gS2FyZW5hICpzdHJpZGUqIGJlcm5pbGFpIFwoMlwpLCBrZXJuZWwgYmVyZ2VzZXIgZHVhIGtvbG9tIGtlIGthbmFuIHVudHVrIG1lbmdoaXR1bmcgZWxlbWVuIGJlcmlrdXRueWEgcGFkYSBiYXJpcyBrZWx1YXJhbiB5YW5nIHNhbWEuIFNldGVsYWggbWVuY2FwYWkgcG9zaXNpIHRlcmFraGlyIHBhZGEgYmFyaXMgdGVyc2VidXQsIGtlcm5lbCBrZW1iYWxpIGtlIHNpc2kga2lyaSBkYW4gYmVyZ2VzZXIgZHVhIGJhcmlzIGtlIGJhd2FoLg0KDQotICoqQ29udG9oIFBlcmhpdHVuZ2FuIEtvbnZvbHVzaToqKg0KDQoqKjEuIFBlcmhpdHVuZ2FuIGVsZW1lbiBwYWRhIHBvc2lzaSBcKCgxLDEpXCkqKg0KDQpVbnR1ayBtZW5naGFzaWxrYW4gZWxlbWVuIHBlcnRhbWEgXChcbWF0aGJme1h9XnsyLDB9XCksIGtlcm5lbCBkaXRlbXBhdGthbiBwYWRhIGFyZWEgXCgzXHRpbWVzM1wpIGRpIHBvam9rIGtpcmkgYXRhcyBtYXRyaWtzIHlhbmcgdGVsYWggZGliZXJpICpwYWRkaW5nKi4NCg0KQXJlYSAqZmVhdHVyZSBtYXAqIHlhbmcgZGlwcm9zZXMgYWRhbGFoOg0KDQpcWw0KXGJlZ2lue2JtYXRyaXh9DQowLjAwICYgMC4wMCAmIDAuMDBcXA0KMC4wMCAmIC0yLjM5ICYgMS44MlxcDQowLjAwICYgLTIuMzggJiAyLjI0DQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KQXJlYSB0ZXJzZWJ1dCBkaWthbGlrYW4gc2VjYXJhIGVsZW1lbiBkZW1pIGVsZW1lbiBkZW5nYW4gYm9ib3Qga2VybmVsIFwoXG1hdGhiZntXfV97XG1hdGhybXtlbmN9fV57KDIpfVwpLCBrZW11ZGlhbiBzZWx1cnVoIGhhc2lsIHBlcmthbGlhbiBkaWp1bWxhaGthbiBzZWJhZ2FpIGJlcmlrdXQ6DQoNClxbDQpcYmVnaW57YWxpZ25lZH0NClhfezEsMX1eezIsMH0NCj17fSYNCigwLjAwKSgwLjAwKQ0KKygwLjAwKSgwLjAwKQ0KKygwLjAwKSgwLjAwKVxcDQomKygwLjAwKSgwLjAwKQ0KKygtMi4zOSkoMS4wMCkNCisoMS44MikoMC4wMClcXA0KJisoMC4wMCkoMC4wMCkNCisoLTIuMzgpKDAuMDApDQorKDIuMjQpKDAuMDApXFwNCj17fSYtMi4zOS4NClxlbmR7YWxpZ25lZH0NClxdDQoNCkRlbmdhbiBkZW1pa2lhbiwgZWxlbWVuIHBlcnRhbWEgcGFkYSAqZmVhdHVyZSBtYXAqIGtlbHVhcmFuIGFkYWxhaCBcKFhfezEsMX1eezIsMH09LTIuMzlcKS4NCg0KKioyLiBQZXJoaXR1bmdhbiBlbGVtZW4gcGFkYSBwb3Npc2kgXCgoMSwyKVwpKioNCg0KVW50dWsgbWVuZ2hpdHVuZyBlbGVtZW4gcGFkYSBwb3Npc2kgXCgoMSwyKVwpLCBrZXJuZWwgYmVyZ2VzZXIgZHVhIGtvbG9tIGtlIGthbmFuIGRhcmkgcG9zaXNpIHNlYmVsdW1ueWEga2FyZW5hICpzdHJpZGUqIHlhbmcgZGlndW5ha2FuIGFkYWxhaCBcKDJcKS4NCg0KQXJlYSAqZmVhdHVyZSBtYXAqIHlhbmcgZGlwcm9zZXMgbWVuamFkaToNCg0KXFsNClxiZWdpbntibWF0cml4fQ0KMC4wMCAmIDAuMDAgJiAwLjAwXFwNCjEuODIgJiAtMS44NCAmIDAuMDBcXA0KMi4yNCAmIC0xLjcwICYgMC4wMA0KXGVuZHtibWF0cml4fS4NClxdDQoNClBlcmhpdHVuZ2FuIGtvbnZvbHVzaSBkaWxha3VrYW4gbWVuZ2d1bmFrYW4gYm9ib3Qga2VybmVsIHlhbmcgc2FtYToNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0KWF97MSwyfV57MiwwfQ0KPXt9Jg0KKDAuMDApKDAuMDApDQorKDAuMDApKDAuMDApDQorKDAuMDApKDAuMDApXFwNCiYrKDEuODIpKDAuMDApDQorKC0xLjg0KSgxLjAwKQ0KKygwLjAwKSgwLjAwKVxcDQomKygyLjI0KSgwLjAwKQ0KKygtMS43MCkoMC4wMCkNCisoMC4wMCkoMC4wMClcXA0KPXt9Ji0xLjg0Lg0KXGVuZHthbGlnbmVkfQ0KXF0NCg0KRGVuZ2FuIGRlbWlraWFuLCBlbGVtZW4gcGFkYSBwb3Npc2kgXCgoMSwyKVwpIGRhcmkgKmZlYXR1cmUgbWFwKiBrZWx1YXJhbiBhZGFsYWggXChYX3sxLDJ9XnsyLDB9PS0xLjg0XCkuDQoNClByb3NlZHVyIHlhbmcgc2FtYSBkaXRlcmFwa2FuIHBhZGEgc2VsdXJ1aCBwb3Npc2kga2VybmVsLiBLYXJlbmEgaGFueWEgYm9ib3QgdGVuZ2FoIGtlcm5lbCB5YW5nIGJlcm5pbGFpIFwoMS4wMFwpLCBuaWxhaSBrZWx1YXJhbiBwYWRhIHNldGlhcCBwb3Npc2kgc2FtYSBkZW5nYW4gbmlsYWkgZWxlbWVuIHRlbmdhaCBkYXJpIGFyZWEgKmZlYXR1cmUgbWFwKiB5YW5nIHNlZGFuZyBkaXByb3Nlcy4gSGFsIHRlcnNlYnV0IG1lcnVwYWthbiBrb25zZWt1ZW5zaSBkYXJpIGJvYm90IGtlcm5lbCB5YW5nIGRpdGV0YXBrYW4gcGFkYSBpbHVzdHJhc2kgaW5pLCBidWthbiBrYXJha3RlcmlzdGlrIHVtdW0gZGFyaSBzZWx1cnVoIG9wZXJhc2kga29udm9sdXNpLg0KDQpTZXRlbGFoIHNlbHVydWggZW1wYXQgcG9zaXNpIGtvbnZvbHVzaSBkaWhpdHVuZywgZGlwZXJvbGVoICpmZWF0dXJlIG1hcCoga2VsdWFyYW4gYmVydWt1cmFuIFwoMlx0aW1lczJcKSBzZWJhZ2FpIGJlcmlrdXQ6DQoNClxbDQpcbWF0aGJme1h9XnsyLDB9DQo9DQpcYmVnaW57Ym1hdHJpeH0NCi0yLjM5ICYgLTEuODRcXA0KLTIuMjUgJiAtMS45OQ0KXGVuZHtibWF0cml4fS4NClxdDQoNCkhhc2lsIHRlcnNlYnV0IG1lbnVuanVra2FuIGJhaHdhIG9wZXJhc2kgKnN0cmlkZWQgY29udm9sdXRpb24qIHBhZGEgZW5jb2RlciBrZWR1YSBtZW5ndXJhbmdpIHVrdXJhbiBzcGFzaWFsICpmZWF0dXJlIG1hcCogZGFyaSBcKDNcdGltZXMzXCkgbWVuamFkaSBcKDJcdGltZXMyXCkuIFBhZGEgaWx1c3RyYXNpIGluaSwgbmlsYWkga2VsdWFyYW4gZGl0ZW50dWthbiBvbGVoIGVsZW1lbiB0ZW5nYWggcGFkYSBzZXRpYXAgYXJlYSBrb252b2x1c2kga2FyZW5hIGJvYm90IGtlcm5lbCBsYWlubnlhIGJlcm5pbGFpIG5vbC4NCg0KDQoNCiMjIDYuIERlY29kZXIgVU5ldCsrDQoNClBhZGEgdGFoYXAgaW5pLCAqZGVjb2RlciogVU5ldCsrIG1lbmdlbWJhbGlrYW4gcmVzb2x1c2kgc3Bhc2lhbCAqZmVhdHVyZSBtYXAqIHNlY2FyYSBiZXJ0YWhhcCBtZWxhbHVpIG9wZXJhc2kgVXBzYW1wbGluZy4gUGFkYSBpbHVzdHJhc2kgaW5pLCBcKFxvcGVyYXRvcm5hbWV7VXB9KFxjZG90KVwpIG1lbnlhdGFrYW4gVXBzYW1wbGluZyBtZW5nZ3VuYWthbiBpbnRlcnBvbGFzaSBiaWxpbmVhci4gT3BlcmFzaSB0ZXJzZWJ1dCBtZW1wZXJiZXNhciB1a3VyYW4gc3Bhc2lhbCAqZmVhdHVyZSBtYXAqIGRlbmdhbiBtZW5naGl0dW5nIG5pbGFpIHBhZGEgcG9zaXNpIGtlbHVhcmFuIGJlcmRhc2Fya2FuIGphcmFrIHRlcmhhZGFwIGVsZW1lbiBtYXN1a2FuIGRpIHNla2l0YXJueWEuDQoNClBhZGEgc2V0aWFwIG5vZGUgKmRlY29kZXIqLCAqZmVhdHVyZSBtYXAqIGhhc2lsIFVwc2FtcGxpbmcgZGlnYWJ1bmdrYW4gZGVuZ2FuICpmZWF0dXJlIG1hcCogZGFyaSBqYWx1ciAqZW5jb2RlciogYXRhdSBub2RlICpkZWNvZGVyKiBzZWJlbHVtbnlhIG1lbGFsdWkgKm5lc3RlZCBza2lwIGNvbm5lY3Rpb24qLiBQZW5nZ2FidW5nYW4gZGlsYWt1a2FuIG1lbmdndW5ha2FuICpjb25jYXRlbmF0aW9uKiAoKkNvbmNhdCopIHBhZGEgZGltZW5zaSBrYW5hbCwga2VtdWRpYW4gZGlsYW5qdXRrYW4gZGVuZ2FuIGtvbnZvbHVzaSBcKDFcdGltZXMxXCkgZGFuIGZ1bmdzaSBha3RpdmFzaSBSZUxVLg0KDQpVbnR1ayBtZW1wZXJtdWRhaCBpbHVzdHJhc2kgcGVyaGl0dW5nYW4gbWFudWFsLCBvcGVyYXNpIGtvbnZvbHVzaSBwYWRhIG5vZGUgKmRlY29kZXIqIGRpc2VkZXJoYW5ha2FuIG1lbmphZGkgc2F0dSBrb252b2x1c2kgXCgxXHRpbWVzMVwpIHRhbnBhIGJpYXMuIEJvYm90IGtlcm5lbCBkaXRlbnR1a2FuIHNlY2FyYSBpbHVzdHJhdGlmIGRhbiB0aWRhayBtZXJlcHJlc2VudGFzaWthbiBib2JvdCBoYXNpbCBwZWxhdGloYW4gbW9kZWwuIFBlbnllZGVyaGFuYWFuIGluaSBkaWd1bmFrYW4gdW50dWsgbWVuamVsYXNrYW4gbWVrYW5pc21lIHBlbmdnYWJ1bmdhbiBmaXR1ciwgYnVrYW4ga2VzZWx1cnVoYW4gYmxvayBrb252b2x1c2kgcGFkYSBpbXBsZW1lbnRhc2kgVU5ldCsrLg0KDQpEZW5nYW4gZGVtaWtpYW4sIHBlbWJlbnR1a2FuIG5vZGUgKmRlY29kZXIqIHBhZGEgaWx1c3RyYXNpIGluaSBkaW55YXRha2FuIHNlYmFnYWk6DQoNClxbDQpcYmVnaW57YWxpZ25lZH0NClxtYXRoYmZ7WH1eezEsMX0NCiY9DQpcb3BlcmF0b3JuYW1le1JlTFV9DQpcbGVmdCgNClxvcGVyYXRvcm5hbWV7Q29udn1fezFcdGltZXMxfV57KDEsMSl9DQpcbGVmdCgNClxvcGVyYXRvcm5hbWV7Q29uY2F0fQ0KXGxlZnRbDQpcbWF0aGJme1h9XnsxLDB9LA0KXG9wZXJhdG9ybmFtZXtVcH0oXG1hdGhiZntYfV57MiwwfSkNClxyaWdodF0NClxyaWdodCkNClxyaWdodCksXFxbNnB0XQ0KXG1hdGhiZntYfV57MCwxfQ0KJj0NClxvcGVyYXRvcm5hbWV7UmVMVX0NClxsZWZ0KA0KXG9wZXJhdG9ybmFtZXtDb252fV97MVx0aW1lczF9XnsoMCwxKX0NClxsZWZ0KA0KXG9wZXJhdG9ybmFtZXtDb25jYXR9DQpcbGVmdFsNClxtYXRoYmZ7WH1eezAsMH0sDQpcb3BlcmF0b3JuYW1le1VwfShcbWF0aGJme1h9XnsxLDB9KQ0KXHJpZ2h0XQ0KXHJpZ2h0KQ0KXHJpZ2h0KSxcXFs2cHRdDQpcbWF0aGJme1h9XnswLDJ9DQomPQ0KXG9wZXJhdG9ybmFtZXtSZUxVfQ0KXGxlZnQoDQpcb3BlcmF0b3JuYW1le0NvbnZ9X3sxXHRpbWVzMX1eeygwLDIpfQ0KXGxlZnQoDQpcb3BlcmF0b3JuYW1le0NvbmNhdH0NClxsZWZ0Ww0KXG1hdGhiZntYfV57MCwwfSwNClxtYXRoYmZ7WH1eezAsMX0sDQpcb3BlcmF0b3JuYW1le1VwfShcbWF0aGJme1h9XnsxLDF9KQ0KXHJpZ2h0XQ0KXHJpZ2h0KQ0KXHJpZ2h0KS4NClxlbmR7YWxpZ25lZH0NClxdDQoNClBhZGEgbm9kZSBcKFxtYXRoYmZ7WH1eezEsMX1cKSBkYW4gXChcbWF0aGJme1h9XnswLDF9XCksIG1hc2luZy1tYXNpbmcga2FuYWwgbWFzdWthbiBkaWJlcmkgYm9ib3QgaWx1c3RyYXRpZiBcKDEuMDBcKS4gU2VtZW50YXJhIGl0dSwgcGFkYSBub2RlIFwoXG1hdGhiZntYfV57MCwyfVwpLCB0aWdhIGthbmFsIG1hc3VrYW4gZGliZXJpIGJvYm90IGlsdXN0cmF0aWYgXCgwLjI1XCksIFwoMC41MFwpLCBkYW4gXCgwLjI1XCkuIEJvYm90IHRlcnNlYnV0IGRpZ3VuYWthbiB1bnR1ayBtZW1wZXJ0YWhhbmthbiBtZWthbmlzbWUgcGVuZ2dhYnVuZ2FuIGZpdHVyIHlhbmcgdGVsYWggZGl0ZXRhcGthbiBkYWxhbSBpbHVzdHJhc2kgc2ViZWx1bW55YS4NCg0KDQojIyMgYS4gVXBzYW1wbGluZyBcKFxtYXRoYmZ7WH1eezIsMH1cKSBkYW4gTm9kZSBEZWNvZGVyIFwoXG1hdGhiZntYfV57MSwxfVwpDQoNCipGZWF0dXJlIG1hcCogXChcbWF0aGJme1h9XnsyLDB9XCkgYmVydWt1cmFuIFwoMlx0aW1lczJcKSwgeWFuZyBkaXBlcm9sZWggZGFyaSB0YWhhcCAqZW5jb2Rlciogc2ViZWx1bW55YSwgZGlwZXJiZXNhciBtZW5qYWRpIFwoM1x0aW1lczNcKSBtZW5nZ3VuYWthbiBpbnRlcnBvbGFzaSBiaWxpbmVhci4gUHJvc2VzIGluaSBiZXJ0dWp1YW4gdW50dWsgbWVueWVzdWFpa2FuIHVrdXJhbiBzcGFzaWFsICpmZWF0dXJlIG1hcCogc2VoaW5nZ2EgZGFwYXQgZGlnYWJ1bmdrYW4gZGVuZ2FuICpmZWF0dXJlIG1hcCogXChcbWF0aGJme1h9XnsxLDB9XCkgZGFyaSBqYWx1ciAqZW5jb2RlciogbWVsYWx1aSAqbmVzdGVkIHNraXAgY29ubmVjdGlvbiouDQoNCk1hdHJpa3MgKmZlYXR1cmUgbWFwKiBtYXN1a2FuIGFkYWxhaDoNCg0KXFsNClxtYXRoYmZ7WH1eezIsMH0NCj0NClxiZWdpbntibWF0cml4fQ0KLTIuMzkgJiAtMS44NFxcDQotMi4yNSAmIC0xLjk5DQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KLSAqKlJ1bXVzIGludGVycG9sYXNpIGJpbGluZWFyOioqDQoNCkludGVycG9sYXNpIGJpbGluZWFyIG1lbmVudHVrYW4gbmlsYWkga2VsdWFyYW4gYmVyZGFzYXJrYW4gamFyYWsgdGVyaGFkYXAgZWxlbWVuLWVsZW1lbiBwYWRhICpmZWF0dXJlIG1hcCogbWFzdWthbi4gRWxlbWVuIHlhbmcgbGViaWggZGVrYXQgZGVuZ2FuIHBvc2lzaSBrZWx1YXJhbiBtZW1pbGlraSBib2JvdCBsZWJpaCBiZXNhciwgc2VkYW5na2FuIGVsZW1lbiB5YW5nIGJlcmphcmFrIHNhdHUgc2F0dWFuIGF0YXUgbGViaWggcGFkYSBzYWxhaCBzYXR1IGFyYWggbWVtaWxpa2kgYm9ib3Qgbm9sLg0KDQpQYWRhICpmZWF0dXJlIG1hcCogc2F0dSBrYW5hbCwgaW50ZXJwb2xhc2kgYmlsaW5lYXIgZGlueWF0YWthbiBzZWJhZ2FpOg0KDQpcWw0KXGxlZnRbDQpcb3BlcmF0b3JuYW1le1VwfQ0KXGxlZnQoDQpcbWF0aGJme1h9XnsyLDB9DQpccmlnaHQpDQpccmlnaHRdX3tyLGN9DQo9DQpcc3VtX3tuPTF9XnsyfQ0KXHN1bV97bT0xfV57Mn0NClhfe24sbX1eezIsMH0NClxtYXgNClxsZWZ0KA0KMCwNCjEtXGxlZnR8eF9jLW1ccmlnaHR8DQpccmlnaHQpDQpcbWF4DQpcbGVmdCgNCjAsDQoxLVxsZWZ0fHlfci1uXHJpZ2h0fA0KXHJpZ2h0KS4NClxdDQoNClBhZGEgcGVyc2FtYWFuIHRlcnNlYnV0LCBcKHJcKSBkYW4gXChjXCkgbWVueWF0YWthbiBpbmRla3MgYmFyaXMgZGFuIGtvbG9tIHBhZGEgKmZlYXR1cmUgbWFwKiBrZWx1YXJhbiwgc2VkYW5na2FuIFwoblwpIGRhbiBcKG1cKSBtZW55YXRha2FuIGluZGVrcyBiYXJpcyBkYW4ga29sb20gcGFkYSAqZmVhdHVyZSBtYXAqIG1hc3VrYW4uIEtvb3JkaW5hdCBcKHhfY1wpIG1lbnVuanVra2FuIHBvc2lzaSBob3Jpem9udGFsIGF0YXUgYXJhaCBrb2xvbSwgc2VkYW5na2FuIFwoeV9yXCkgbWVudW5qdWtrYW4gcG9zaXNpIHZlcnRpa2FsIGF0YXUgYXJhaCBiYXJpcy4NCg0KVW50dWsgbWVtcGVybXVkYWggcGVuamFiYXJhbiwgYm9ib3QgaW50ZXJwb2xhc2kgcGFkYSBzZXRpYXAgZWxlbWVuIG1hc3VrYW4gZGlub3Rhc2lrYW4gc2ViYWdhaToNCg0KXFsNCndfe24sbX1eeyhyLGMpfQ0KPQ0KXG1heA0KXGxlZnQoDQowLA0KMS1cbGVmdHx4X2MtbVxyaWdodHwNClxyaWdodCkNClxtYXgNClxsZWZ0KA0KMCwNCjEtXGxlZnR8eV9yLW5ccmlnaHR8DQpccmlnaHQpLg0KXF0NCg0KRGVuZ2FuIGRlbWlraWFuLCBydW11cyBpbnRlcnBvbGFzaSBiaWxpbmVhciBkYXBhdCBkaXR1bGlza2FuIHNlYmFnYWk6DQoNClxbDQpcbGVmdFsNClxvcGVyYXRvcm5hbWV7VXB9DQpcbGVmdCgNClxtYXRoYmZ7WH1eezIsMH0NClxyaWdodCkNClxyaWdodF1fe3IsY30NCj0NClxzdW1fe249MX1eezJ9DQpcc3VtX3ttPTF9XnsyfQ0Kd197bixtfV57KHIsYyl9WF97bixtfV57MiwwfS4NClxdDQoNCi0gKipQZW5lbnR1YW4ga29vcmRpbmF0IGludGVycG9sYXNpOioqDQoNClBhZGEgaWx1c3RyYXNpIGluaSwga29vcmRpbmF0IG1hdHJpa3MgbWFzdWthbiBtZW5nZ3VuYWthbiBpbmRla3MgeWFuZyBkaW11bGFpIGRhcmkgXCgxXCkuIEthcmVuYSB1a3VyYW4gKmZlYXR1cmUgbWFwKiBtYXN1a2FuIGFkYWxhaCBcKDJcdGltZXMyXCkgZGFuIHVrdXJhbiBrZWx1YXJhbiBhZGFsYWggXCgzXHRpbWVzM1wpLCBrb29yZGluYXQgaW50ZXJwb2xhc2kgZGl0ZW50dWthbiBzZWJhZ2FpOg0KDQpcWw0KeF9jDQo9DQoxKyhjLTEpXGZyYWN7Mi0xfXszLTF9DQo9DQoxK1xmcmFje2MtMX17Mn0sDQpcXQ0KDQpcWw0KeV9yDQo9DQoxKyhyLTEpXGZyYWN7Mi0xfXszLTF9DQo9DQoxK1xmcmFje3ItMX17Mn0sDQpcXQ0KDQpkZW5nYW4gXChyLGM9MSwyLDNcKS4NCg0KQW5na2EgXCgxXCkgbWVudW5qdWtrYW4ga29vcmRpbmF0IGF3YWwga2FyZW5hIGluZGVrcyBtYXRyaWtzIGRpbXVsYWkgZGFyaSBcKDFcKSwgc2VkYW5na2FuIHBlbWJhZ2lhbiBkZW5nYW4gXCgyXCkgbWVudW5qdWtrYW4gYmFod2EgamFyYWsgYW50YXJhIGR1YSBrb29yZGluYXQgbWFzdWthbiBkaWJhZ2kgbWVuamFkaSBkdWEgaW50ZXJ2YWwgeWFuZyBzYW1hIHBhbmphbmcuDQoNCk5pbGFpIGtvb3JkaW5hdCB5YW5nIGRpcGVyb2xlaCBhZGFsYWg6DQoNCnwgSW5kZWtzIGtlbHVhcmFuIHwgTmlsYWkga29vcmRpbmF0IHwNCnw6LS0tOnw6LS0tOnwNCnwgXCgxXCkgfCBcKDFcKSB8DQp8IFwoMlwpIHwgXCgxLjVcKSB8DQp8IFwoM1wpIHwgXCgyXCkgfA0KDQpEZW5nYW4gZGVtaWtpYW4sIGtvb3JkaW5hdCBpbnRlcnBvbGFzaSBwYWRhIG1hdHJpa3Mga2VsdWFyYW4gZGFwYXQgZGl0dWxpc2thbiBzZWJhZ2FpOg0KDQpcWw0KXGJlZ2lue2JtYXRyaXh9DQooMSwxKSAmICgxLDEuNSkgJiAoMSwyKVxcDQooMS41LDEpICYgKDEuNSwxLjUpICYgKDEuNSwyKVxcDQooMiwxKSAmICgyLDEuNSkgJiAoMiwyKQ0KXGVuZHtibWF0cml4fS4NClxdDQoNClNldGlhcCBwYXNhbmdhbiBrb29yZGluYXQgZGl0dWxpc2thbiBkYWxhbSB1cnV0YW4gXCgoeV9yLHhfYylcKS4gUGFkYSBwb3Npc2kgc3VkdXQsIG5pbGFpIGtlbHVhcmFuIHNhbWEgZGVuZ2FuIG5pbGFpIG1hc3VrYW4ga2FyZW5hIGtvb3JkaW5hdG55YSBiZXJpbXBpdC4gU2VtZW50YXJhIGl0dSwgcG9zaXNpIHRlbmdhaCBzaXNpIGRpcGVyb2xlaCBkYXJpIGR1YSBlbGVtZW4gbWFzdWthbiwgc2VkYW5na2FuIHBvc2lzaSB0ZW5nYWggbWF0cmlrcyBkaXBlcm9sZWggZGFyaSBlbXBhdCBlbGVtZW4gbWFzdWthbi4NCg0KLSAqKkNvbnRvaCBwZXJoaXR1bmdhbiBpbnRlcnBvbGFzaSBiaWxpbmVhciBwYWRhIHBvc2lzaSBcKCgxLDIpXCk6KioNCg0KUGFkYSBwb3Npc2kgXCgoMSwyKVwpLCBrb29yZGluYXQgaW50ZXJwb2xhc2kgZGlwZXJvbGVoIHNlYmFnYWkgYmVyaWt1dDoNCg0KXFsNCnlfMT0xLA0KXHFxdWFkDQp4XzI9MS41Lg0KXF0NCg0KUG9zaXNpIHRlcnNlYnV0IGJlcmFkYSB0ZXBhdCBkaSB0ZW5nYWggYW50YXJhIGtvbG9tIHBlcnRhbWEgZGFuIGtvbG9tIGtlZHVhIHBhZGEgYmFyaXMgcGVydGFtYS4gQm9ib3QgaW50ZXJwb2xhc2kgdW50dWsgZWxlbWVuIFwoWF97MSwxfV57MiwwfVwpIGRpaGl0dW5nIHNlYmFnYWk6DQoNClxbDQpcYmVnaW57YWxpZ25lZH0NCndfezEsMX1eeygxLDIpfQ0KJj0NClxtYXgoMCwxLXwxLjUtMXwpDQpcbWF4KDAsMS18MS0xfClcXA0KJj0NCjAuNVx0aW1lczFcXA0KJj0NCjAuNS4NClxlbmR7YWxpZ25lZH0NClxdDQoNClNlbWVudGFyYSBpdHUsIGJvYm90IHVudHVrIGVsZW1lbiBcKFhfezEsMn1eezIsMH1cKSBhZGFsYWg6DQoNClxbDQpcYmVnaW57YWxpZ25lZH0NCndfezEsMn1eeygxLDIpfQ0KJj0NClxtYXgoMCwxLXwxLjUtMnwpDQpcbWF4KDAsMS18MS0xfClcXA0KJj0NCjAuNVx0aW1lczFcXA0KJj0NCjAuNS4NClxlbmR7YWxpZ25lZH0NClxdDQoNCktlZHVhIGVsZW1lbiBwYWRhIGJhcmlzIGtlZHVhIG1lbWlsaWtpIGJvYm90IG5vbCBrYXJlbmEgamFyYWsgdmVydGlrYWxueWEgdGVyaGFkYXAgcG9zaXNpIGtlbHVhcmFuIGFkYWxhaCBzYXR1IHNhdHVhbi4gRGVuZ2FuIGRlbWlraWFuOg0KDQpcWw0Kd197MSwxfV57KDEsMil9DQo9DQp3X3sxLDJ9XnsoMSwyKX0NCj0NCjAuNSwNClxxcXVhZA0Kd197MiwxfV57KDEsMil9DQo9DQp3X3syLDJ9XnsoMSwyKX0NCj0NCjAuDQpcXQ0KDQpEZW5nYW4gbWVtYXN1a2thbiBib2JvdCB0ZXJzZWJ1dCBrZSBkYWxhbSBydW11cyBpbnRlcnBvbGFzaSBiaWxpbmVhciwgZGlwZXJvbGVoOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpcbGVmdFsNClxvcGVyYXRvcm5hbWV7VXB9DQpcbGVmdCgNClxtYXRoYmZ7WH1eezIsMH0NClxyaWdodCkNClxyaWdodF1fezEsMn0NCiY9DQowLjVYX3sxLDF9XnsyLDB9DQorDQowLjVYX3sxLDJ9XnsyLDB9XFwNCiY9DQpcZnJhY3sNClhfezEsMX1eezIsMH0NCisNClhfezEsMn1eezIsMH0NCn17Mn1cXA0KJj0NClxmcmFjey0yLjM5LTEuODR9ezJ9XFwNCiY9DQotMi4xMTVcXA0KJg0KLTIuMTIuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQotICoqQ29udG9oIHBlcmhpdHVuZ2FuIGludGVycG9sYXNpIGJpbGluZWFyIHBhZGEgcG9zaXNpIHRlbmdhaCBcKCgyLDIpXCk6KioNCg0KUGFkYSBwb3Npc2kgXCgoMiwyKVwpLCBrb29yZGluYXQgaW50ZXJwb2xhc2kgZGlwZXJvbGVoIHNlYmFnYWkgYmVyaWt1dDoNCg0KXFsNCnlfMj0xLjUsDQpccXF1YWQNCnhfMj0xLjUuDQpcXQ0KDQpQb3Npc2kgdGVyc2VidXQgYmVyYWRhIHRlcGF0IGRpIHRlbmdhaCBlbXBhdCBlbGVtZW4gbWF0cmlrcyBtYXN1a2FuLiBCb2JvdCBpbnRlcnBvbGFzaSB1bnR1ayBlbGVtZW4gXChYX3sxLDF9XnsyLDB9XCkgZGloaXR1bmcgc2ViYWdhaToNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0Kd197MSwxfV57KDIsMil9DQomPQ0KXG1heCgwLDEtfDEuNS0xfCkNClxtYXgoMCwxLXwxLjUtMXwpXFwNCiY9DQowLjVcdGltZXMwLjVcXA0KJj0NCjAuMjUuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpLYXJlbmEgcG9zaXNpIHRlbmdhaCBiZXJqYXJhayBzYW1hIGRhcmkga2VlbXBhdCBlbGVtZW4gbWFzdWthbiwgbWFrYToNCg0KXFsNCndfezEsMX1eeygyLDIpfQ0KPQ0Kd197MSwyfV57KDIsMil9DQo9DQp3X3syLDF9XnsoMiwyKX0NCj0NCndfezIsMn1eeygyLDIpfQ0KPQ0KMC4yNS4NClxdDQoNCkRlbmdhbiBkZW1pa2lhbiwgcnVtdXMgaW50ZXJwb2xhc2kgYmlsaW5lYXIgbWVuamFkaToNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0KXGxlZnRbDQpcb3BlcmF0b3JuYW1le1VwfQ0KXGxlZnQoDQpcbWF0aGJme1h9XnsyLDB9DQpccmlnaHQpDQpccmlnaHRdX3syLDJ9DQomPQ0KMC4yNVhfezEsMX1eezIsMH0NCisNCjAuMjVYX3sxLDJ9XnsyLDB9XFwNCiZccXVhZCsNCjAuMjVYX3syLDF9XnsyLDB9DQorDQowLjI1WF97MiwyfV57MiwwfVxcDQomPQ0KXGZyYWN7DQpYX3sxLDF9XnsyLDB9DQorDQpYX3sxLDJ9XnsyLDB9DQorDQpYX3syLDF9XnsyLDB9DQorDQpYX3syLDJ9XnsyLDB9DQp9ezR9XFwNCiY9DQpcZnJhY3stMi4zOS0xLjg0LTIuMjUtMS45OX17NH1cXA0KJj0NCi0yLjExNzVcXA0KJg0KLTIuMTIuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpEZW5nYW4gbWVuZXJhcGthbiBpbnRlcnBvbGFzaSBiaWxpbmVhciBwYWRhIHNlbHVydWggcG9zaXNpIGtlbHVhcmFuLCBkaXBlcm9sZWggKmZlYXR1cmUgbWFwKiBoYXNpbCBVcHNhbXBsaW5nIGJlcnVrdXJhbiBcKDNcdGltZXMzXCksIHlhaXR1Og0KDQpcWw0KXG9wZXJhdG9ybmFtZXtVcH0NClxsZWZ0KA0KXG1hdGhiZntYfV57MiwwfQ0KXHJpZ2h0KQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQotMi4zOSAmIC0yLjEyICYgLTEuODRcXA0KLTIuMzIgJiAtMi4xMiAmIC0xLjkyXFwNCi0yLjI1ICYgLTIuMTIgJiAtMS45OQ0KXGVuZHtibWF0cml4fS4NClxdDQoNCkhhc2lsIHRlcnNlYnV0IG1lbnVuanVra2FuIGJhaHdhIGludGVycG9sYXNpIGJpbGluZWFyIG1lbXBlcnRhaGFua2FuIG5pbGFpIHBhZGEgcG9zaXNpIHN1ZHV0IGRhbiBtZW5naGl0dW5nIG5pbGFpIHBhZGEgcG9zaXNpIGxhaW5ueWEgYmVyZGFzYXJrYW4gYm9ib3QgamFyYWsgdGVyaGFkYXAgZWxlbWVuIG1hc3VrYW4uIE5pbGFpIGhhc2lsIGludGVycG9sYXNpIGRpdGFtcGlsa2FuIGhpbmdnYSBkdWEgYW5na2EgZGVzaW1hbC4NCg0KLSAqKlJ1bXVzIG5vZGUgZGVjb2RlcjoqKg0KDQpTZXN1YWkgZGVuZ2FuIHBlcnNhbWFhbiBVTmV0KyssICpuZXN0ZWQgc2tpcCBjb25uZWN0aW9uKiBwYWRhIG5vZGUgKmRlY29kZXIqIHBlcnRhbWEgZGlydW11c2thbiBzZWJhZ2FpOg0KDQpcWw0KXG1hdGhiZntYfV57MSwxfQ0KPQ0KSF57KDEsMSl9DQpcbGVmdCgNClxvcGVyYXRvcm5hbWV7Q29uY2F0fQ0KXGxlZnRbDQpcbWF0aGJme1h9XnsxLDB9LA0KXG9wZXJhdG9ybmFtZXtVcH0NClxsZWZ0KA0KXG1hdGhiZntYfV57MiwwfQ0KXHJpZ2h0KQ0KXHJpZ2h0XQ0KXHJpZ2h0KS4NClxdDQoNClBhZGEgcGVyc2FtYWFuIHRlcnNlYnV0LCBcKEheeygxLDEpfVwpIG1lbnlhdGFrYW4gb3BlcmFzaSBwZW5nb2xhaGFuIGZpdHVyIHBhZGEgbm9kZSAqZGVjb2RlciogXChcbWF0aGJme1h9XnsxLDF9XCkuIERhbGFtIGlsdXN0cmFzaSBwZXJoaXR1bmdhbiBtYW51YWwgaW5pLCBvcGVyYXNpIHRlcnNlYnV0IGRpc2VkZXJoYW5ha2FuIG1lbmdndW5ha2FuIGtvbnZvbHVzaSBcKDFcdGltZXMxXCkgdGFucGEgYmlhcyB5YW5nIGRpaWt1dGkgZnVuZ3NpIGFrdGl2YXNpIFJlTFUuDQoNCkthcmVuYSBrZWR1YSAqZmVhdHVyZSBtYXAqIHlhbmcgZGlnYWJ1bmdrYW4gYmVydWt1cmFuIFwoM1x0aW1lczNcKSBkYW4gbWFzaW5nLW1hc2luZyBkaXJlcHJlc2VudGFzaWthbiBvbGVoIHNhdHUga2FuYWwsIGhhc2lsICpDb25jYXQqIG1lbWlsaWtpIGR1YSBrYW5hbC4gU2F0dSBmaWx0ZXIga29udm9sdXNpIFwoMVx0aW1lczFcKSBkaWd1bmFrYW4gdW50dWsgbWVuZ2dhYnVuZ2thbiBrZWR1YSBrYW5hbCB0ZXJzZWJ1dCBtZW5qYWRpIHNhdHUga2FuYWwga2VsdWFyYW4uDQoNClBhZGEgaWx1c3RyYXNpIGluaSwgYm9ib3Qga2VybmVsIGRpdGVudHVrYW4gc2ViYWdhaToNCg0KXFsNCldfe1xtYXRocm17ZGVjfSwxfV57KDEsMSl9PVsxLjAwXSwNClxxcXVhZA0KV197XG1hdGhybXtkZWN9LDJ9XnsoMSwxKX09WzEuMDBdLg0KXF0NCg0KQm9ib3QgcGVydGFtYSBkaXRlcmFwa2FuIHBhZGEgXChcbWF0aGJme1h9XnsxLDB9XCksIHNlZGFuZ2thbiBib2JvdCBrZWR1YSBkaXRlcmFwa2FuIHBhZGEgXChcb3BlcmF0b3JuYW1le1VwfShcbWF0aGJme1h9XnsyLDB9KVwpLg0KDQpEZW5nYW4gZGVtaWtpYW4sIHVudHVrIHNldGlhcCBwb3Npc2kgc3Bhc2lhbCBcKChyLGMpXCksIGtlbHVhcmFuIG5vZGUgKmRlY29kZXIqIGRpaGl0dW5nIHNlYmFnYWk6DQoNClxbDQpYX3tyLGN9XnsxLDF9DQo9DQpcb3BlcmF0b3JuYW1le1JlTFV9DQpcbGVmdCgNCldfe1xtYXRocm17ZGVjfSwxfV57KDEsMSl9WF97cixjfV57MSwwfQ0KKw0KV197XG1hdGhybXtkZWN9LDJ9XnsoMSwxKX0NClxsZWZ0Ww0KXG9wZXJhdG9ybmFtZXtVcH0NClxsZWZ0KA0KXG1hdGhiZntYfV57MiwwfQ0KXHJpZ2h0KQ0KXHJpZ2h0XV97cixjfQ0KXHJpZ2h0KS4NClxdDQoNCi0gKipDb250b2ggcGVyaGl0dW5nYW4gbm9kZSBkZWNvZGVyIHBhZGEgcG9zaXNpIFwoKDEsMSlcKToqKg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpYX3sxLDF9XnsxLDF9DQomPQ0KXG9wZXJhdG9ybmFtZXtSZUxVfQ0KXGxlZnQoDQpXX3tcbWF0aHJte2RlY30sMX1eeygxLDEpfVhfezEsMX1eezEsMH0NCisNCldfe1xtYXRocm17ZGVjfSwyfV57KDEsMSl9DQpcbGVmdFsNClxvcGVyYXRvcm5hbWV7VXB9DQpcbGVmdCgNClxtYXRoYmZ7WH1eezIsMH0NClxyaWdodCkNClxyaWdodF1fezEsMX0NClxyaWdodClcXA0KJj0NClxvcGVyYXRvcm5hbWV7UmVMVX0NClxsZWZ0KA0KMS4wMCgtMi4zOSkrMS4wMCgtMi4zOSkNClxyaWdodClcXA0KJj0NClxvcGVyYXRvcm5hbWV7UmVMVX0oLTQuNzgpXFwNCiY9DQowLjAwLg0KXGVuZHthbGlnbmVkfQ0KXF0NCg0KLSAqKkNvbnRvaCBwZXJoaXR1bmdhbiBub2RlIGRlY29kZXIgcGFkYSBwb3Npc2kgdGVuZ2FoIFwoKDIsMilcKToqKg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpYX3syLDJ9XnsxLDF9DQomPQ0KXG9wZXJhdG9ybmFtZXtSZUxVfQ0KXGxlZnQoDQpXX3tcbWF0aHJte2RlY30sMX1eeygxLDEpfVhfezIsMn1eezEsMH0NCisNCldfe1xtYXRocm17ZGVjfSwyfV57KDEsMSl9DQpcbGVmdFsNClxvcGVyYXRvcm5hbWV7VXB9DQpcbGVmdCgNClxtYXRoYmZ7WH1eezIsMH0NClxyaWdodCkNClxyaWdodF1fezIsMn0NClxyaWdodClcXA0KJj0NClxvcGVyYXRvcm5hbWV7UmVMVX0NClxsZWZ0KA0KMS4wMCgyLjI0KSsxLjAwKC0yLjEyKQ0KXHJpZ2h0KVxcDQomPQ0KXG9wZXJhdG9ybmFtZXtSZUxVfSgwLjEyKVxcDQomPQ0KMC4xMi4NClxlbmR7YWxpZ25lZH0NClxdDQoNCkRlbmdhbiBtZW5lcmFwa2FuIG9wZXJhc2kgeWFuZyBzYW1hIHBhZGEgc2VsdXJ1aCBwb3Npc2kgc3Bhc2lhbCwgZGlwZXJvbGVoICpmZWF0dXJlIG1hcCogbm9kZSAqZGVjb2RlciogcGVydGFtYSBzZWJhZ2FpIGJlcmlrdXQ6DQoNClxbDQpcbWF0aGJme1h9XnsxLDF9DQo9DQpcYmVnaW57Ym1hdHJpeH0NCjAuMDAgJiAwLjAwICYgMC4wMFxcDQowLjAwICYgMC4xMiAmIDAuMDBcXA0KMC4wMCAmIDAuMDAgJiAwLjAwDQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KSGFzaWwgdGVyc2VidXQgbWVudW5qdWtrYW4gYmFod2EgKmZlYXR1cmUgbWFwKiBoYXNpbCBVcHNhbXBsaW5nIGRhcGF0IGRpZ2FidW5na2FuIGRlbmdhbiAqZmVhdHVyZSBtYXAqIGRhcmkgamFsdXIgKmVuY29kZXIqIG1lbGFsdWkgKm5lc3RlZCBza2lwIGNvbm5lY3Rpb24qLiBQYWRhIGlsdXN0cmFzaSBpbmksIHBlbmdnYWJ1bmdhbiBkaWxha3VrYW4gbWVuZ2d1bmFrYW4gKkNvbmNhdCosIGtvbnZvbHVzaSBcKDFcdGltZXMxXCksIGRhbiBmdW5nc2kgYWt0aXZhc2kgUmVMVS4gKkZlYXR1cmUgbWFwKiBcKFxtYXRoYmZ7WH1eezEsMX1cKSBzZWxhbmp1dG55YSBkaWd1bmFrYW4gcGFkYSBwZW1iZW50dWthbiBub2RlICpkZWNvZGVyKiBiZXJpa3V0bnlhLg0KDQoNCg0KDQojIyMgYi4gVXBzYW1wbGluZyBcKFxtYXRoYmZ7WH1eezEsMH1cKSBkYW4gKk5lc3RlZCBTa2lwKiBQZXJ0YW1hIFwoXG1hdGhiZntYfV57MCwxfVwpDQoNCipGZWF0dXJlIG1hcCBlbmNvZGVyKiBwZXJ0YW1hIFwoXG1hdGhiZntYfV57MSwwfVwpIGJlcnVrdXJhbiBcKDNcdGltZXMzXCkgZGlwZXJiZXNhciBtZW5qYWRpIFwoNVx0aW1lczVcKSBtZW5nZ3VuYWthbiBpbnRlcnBvbGFzaSBiaWxpbmVhci4gUHJvc2VzIGluaSBiZXJ0dWp1YW4gdW50dWsgbWVueWVzdWFpa2FuIHVrdXJhbiBzcGFzaWFsICpmZWF0dXJlIG1hcCogc2VoaW5nZ2EgZGFwYXQgZGlnYWJ1bmdrYW4gZGVuZ2FuIFwoXG1hdGhiZntYfV57MCwwfVwpIG1lbGFsdWkgKm5lc3RlZCBza2lwIGNvbm5lY3Rpb24qLg0KDQpNYXRyaWtzICpmZWF0dXJlIG1hcCogbWFzdWthbiBhZGFsYWg6DQoNClxbDQpcbWF0aGJme1h9XnsxLDB9DQo9DQpcYmVnaW57Ym1hdHJpeH0NCi0yLjM5ICYgMS44MiAmIC0xLjg0XFwNCi0yLjM4ICYgMi4yNCAmIC0xLjcwXFwNCi0yLjI1ICYgMC43NyAmIC0xLjk5DQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KLSAqKlJ1bXVzIGludGVycG9sYXNpIGJpbGluZWFyOioqDQoNCkludGVycG9sYXNpIGJpbGluZWFyIGRpbGFrdWthbiBtZW5nZ3VuYWthbiBwcmluc2lwIHlhbmcgc2FtYSBzZXBlcnRpIHBhZGEgc3ViYmFnaWFuIHNlYmVsdW1ueWEuIE5pbGFpIGtlbHVhcmFuIGRpaGl0dW5nIGJlcmRhc2Fya2FuIGphcmFrIHRlcmhhZGFwIGVsZW1lbi1lbGVtZW4gcGFkYSAqZmVhdHVyZSBtYXAqIG1hc3VrYW4uDQoNClBhZGEgKmZlYXR1cmUgbWFwKiBzYXR1IGthbmFsLCBydW11cyBpbnRlcnBvbGFzaSBiaWxpbmVhciBkaW55YXRha2FuIHNlYmFnYWk6DQoNClxbDQpcbGVmdFsNClxvcGVyYXRvcm5hbWV7VXB9DQpcbGVmdCgNClxtYXRoYmZ7WH1eezEsMH0NClxyaWdodCkNClxyaWdodF1fe3IsY30NCj0NClxzdW1fe249MX1eezN9DQpcc3VtX3ttPTF9XnszfQ0KWF97bixtfV57MSwwfQ0KXG1heA0KXGxlZnQoDQowLA0KMS1cbGVmdHx4X2MtbVxyaWdodHwNClxyaWdodCkNClxtYXgNClxsZWZ0KA0KMCwNCjEtXGxlZnR8eV9yLW5ccmlnaHR8DQpccmlnaHQpLg0KXF0NCg0KUGFkYSBwZXJzYW1hYW4gdGVyc2VidXQsIFwoclwpIGRhbiBcKGNcKSBtZW55YXRha2FuIGluZGVrcyBiYXJpcyBkYW4ga29sb20gcGFkYSAqZmVhdHVyZSBtYXAqIGtlbHVhcmFuLCBzZWRhbmdrYW4gXChuXCkgZGFuIFwobVwpIG1lbnlhdGFrYW4gaW5kZWtzIGJhcmlzIGRhbiBrb2xvbSBwYWRhICpmZWF0dXJlIG1hcCogbWFzdWthbi4gS29vcmRpbmF0IFwoeF9jXCkgbWVudW5qdWtrYW4gcG9zaXNpIGhvcml6b250YWwgYXRhdSBhcmFoIGtvbG9tLCBzZWRhbmdrYW4gXCh5X3JcKSBtZW51bmp1a2thbiBwb3Npc2kgdmVydGlrYWwgYXRhdSBhcmFoIGJhcmlzLg0KDQpCb2JvdCBpbnRlcnBvbGFzaSBwYWRhIHNldGlhcCBlbGVtZW4gbWFzdWthbiBkaW55YXRha2FuIHNlYmFnYWk6DQoNClxbDQp3X3tuLG19XnsocixjKX0NCj0NClxtYXgNClxsZWZ0KA0KMCwNCjEtXGxlZnR8eF9jLW1ccmlnaHR8DQpccmlnaHQpDQpcbWF4DQpcbGVmdCgNCjAsDQoxLVxsZWZ0fHlfci1uXHJpZ2h0fA0KXHJpZ2h0KS4NClxdDQoNCkRlbmdhbiBkZW1pa2lhbiwgcnVtdXMgaW50ZXJwb2xhc2kgYmlsaW5lYXIgZGFwYXQgZGl0dWxpc2thbiBzZWJhZ2FpOg0KDQpcWw0KXGxlZnRbDQpcb3BlcmF0b3JuYW1le1VwfQ0KXGxlZnQoDQpcbWF0aGJme1h9XnsxLDB9DQpccmlnaHQpDQpccmlnaHRdX3tyLGN9DQo9DQpcc3VtX3tuPTF9XnszfQ0KXHN1bV97bT0xfV57M30NCndfe24sbX1eeyhyLGMpfVhfe24sbX1eezEsMH0uDQpcXQ0KDQotICoqUGVuZW50dWFuIGtvb3JkaW5hdCBpbnRlcnBvbGFzaToqKg0KDQpQYWRhIGlsdXN0cmFzaSBpbmksIGtvb3JkaW5hdCBtYXRyaWtzIG1lbmdndW5ha2FuIGluZGVrcyB5YW5nIGRpbXVsYWkgZGFyaSBcKDFcKS4gS2FyZW5hIHVrdXJhbiAqZmVhdHVyZSBtYXAqIG1hc3VrYW4gYWRhbGFoIFwoM1x0aW1lczNcKSBkYW4gdWt1cmFuIGtlbHVhcmFuIGFkYWxhaCBcKDVcdGltZXM1XCksIGtvb3JkaW5hdCBpbnRlcnBvbGFzaSBkaXRlbnR1a2FuIHNlYmFnYWk6DQoNClxbDQp4X2MNCj0NCjErKGMtMSlcZnJhY3szLTF9ezUtMX0NCj0NCjErXGZyYWN7Yy0xfXsyfSwNClxdDQoNClxbDQp5X3INCj0NCjErKHItMSlcZnJhY3szLTF9ezUtMX0NCj0NCjErXGZyYWN7ci0xfXsyfSwNClxdDQoNCmRlbmdhbiBcKHIsYz0xLDIsMyw0LDVcKS4NCg0KQW5na2EgXCgxXCkgbWVudW5qdWtrYW4ga29vcmRpbmF0IGF3YWwgbWF0cmlrcyBtYXN1a2FuLCBzZWRhbmdrYW4gcGVtYmFnaWFuIGRlbmdhbiBcKDJcKSBtZW51bmp1a2thbiBiYWh3YSBzZXRpYXAgaW50ZXJ2YWwgYW50YXJhIGR1YSBrb29yZGluYXQgbWFzdWthbiBkaWJhZ2kgbWVuamFkaSBkdWEgYmFnaWFuIHlhbmcgc2FtYSBwYW5qYW5nLg0KDQpOaWxhaSBrb29yZGluYXQgeWFuZyBkaXBlcm9sZWggYWRhbGFoOg0KDQp8IEluZGVrcyBrZWx1YXJhbiB8IE5pbGFpIGtvb3JkaW5hdCB8DQp8Oi0tLTp8Oi0tLTp8DQp8IFwoMVwpIHwgXCgxXCkgfA0KfCBcKDJcKSB8IFwoMS41XCkgfA0KfCBcKDNcKSB8IFwoMlwpIHwNCnwgXCg0XCkgfCBcKDIuNVwpIHwNCnwgXCg1XCkgfCBcKDNcKSB8DQoNCkRlbmdhbiBkZW1pa2lhbiwgbmlsYWkgcGFkYSBwb3Npc2kga2VsdWFyYW4geWFuZyBiZXJpbXBpdCBkZW5nYW4ga29vcmRpbmF0IG1hc3VrYW4gZGlwZXJ0YWhhbmthbiwgc2VkYW5na2FuIG5pbGFpIHBhZGEgcG9zaXNpIGxhaW5ueWEgZGloaXR1bmcgYmVyZGFzYXJrYW4gYm9ib3QgamFyYWsgdGVyaGFkYXAgZWxlbWVuLWVsZW1lbiBtYXN1a2FuIGRpIHNla2l0YXJueWEuDQoNCi0gKipDb250b2ggcGVyaGl0dW5nYW4gaW50ZXJwb2xhc2kgYmlsaW5lYXIgcGFkYSBwb3Npc2kgXCgoMSwyKVwpOioqDQoNClBhZGEgcG9zaXNpIFwoKDEsMilcKSwga29vcmRpbmF0IGludGVycG9sYXNpIGRpcGVyb2xlaCBzZWJhZ2FpIGJlcmlrdXQ6DQoNClxbDQp5XzE9MSwNClxxcXVhZA0KeF8yPTEuNS4NClxdDQoNClBvc2lzaSB0ZXJzZWJ1dCBiZXJhZGEgdGVwYXQgZGkgdGVuZ2FoIGFudGFyYSBrb2xvbSBwZXJ0YW1hIGRhbiBrb2xvbSBrZWR1YSBwYWRhIGJhcmlzIHBlcnRhbWEuIEJvYm90IGludGVycG9sYXNpIHVudHVrIGVsZW1lbiBcKFhfezEsMX1eezEsMH1cKSBkaWhpdHVuZyBzZWJhZ2FpOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQp3X3sxLDF9XnsoMSwyKX0NCiY9DQpcbWF4KDAsMS18MS41LTF8KQ0KXG1heCgwLDEtfDEtMXwpXFwNCiY9DQowLjVcdGltZXMxXFwNCiY9DQowLjUuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpTZW1lbnRhcmEgaXR1LCBib2JvdCB1bnR1ayBlbGVtZW4gXChYX3sxLDJ9XnsxLDB9XCkgYWRhbGFoOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQp3X3sxLDJ9XnsoMSwyKX0NCiY9DQpcbWF4KDAsMS18MS41LTJ8KQ0KXG1heCgwLDEtfDEtMXwpXFwNCiY9DQowLjVcdGltZXMxXFwNCiY9DQowLjUuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpFbGVtZW4gbGFpbm55YSBtZW1pbGlraSBib2JvdCBub2wga2FyZW5hIGJlcmFkYSBkaSBsdWFyIGphcmFrIGludGVycG9sYXNpIHBhZGEgcG9zaXNpIHRlcnNlYnV0LiBEZW5nYW4gZGVtaWtpYW46DQoNClxbDQp3X3sxLDF9XnsoMSwyKX0NCj0NCndfezEsMn1eeygxLDIpfQ0KPQ0KMC41Lg0KXF0NCg0KRGVuZ2FuIG1lbWFzdWtrYW4gYm9ib3QgdGVyc2VidXQga2UgZGFsYW0gcnVtdXMgaW50ZXJwb2xhc2kgYmlsaW5lYXIsIGRpcGVyb2xlaDoNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0KXGxlZnRbDQpcb3BlcmF0b3JuYW1le1VwfQ0KXGxlZnQoDQpcbWF0aGJme1h9XnsxLDB9DQpccmlnaHQpDQpccmlnaHRdX3sxLDJ9DQomPQ0KMC41WF97MSwxfV57MSwwfQ0KKw0KMC41WF97MSwyfV57MSwwfVxcDQomPQ0KXGZyYWN7DQpYX3sxLDF9XnsxLDB9DQorDQpYX3sxLDJ9XnsxLDB9DQp9ezJ9XFwNCiY9DQpcZnJhY3stMi4zOSsxLjgyfXsyfVxcDQomPQ0KLTAuMjg1XFwNCiZcYXBwcm94LTAuMjkuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQotICoqQ29udG9oIHBlcmhpdHVuZ2FuIGludGVycG9sYXNpIGJpbGluZWFyIHBhZGEgcG9zaXNpIHRlbmdhaCBcKCgyLDIpXCk6KioNCg0KUGFkYSBwb3Npc2kgXCgoMiwyKVwpLCBrb29yZGluYXQgaW50ZXJwb2xhc2kgZGlwZXJvbGVoIHNlYmFnYWkgYmVyaWt1dDoNCg0KXFsNCnlfMj0xLjUsDQpccXF1YWQNCnhfMj0xLjUuDQpcXQ0KDQpQb3Npc2kgdGVyc2VidXQgYmVyYWRhIHRlcGF0IGRpIHRlbmdhaCBlbXBhdCBlbGVtZW4gbWFzdWthbiwgeWFpdHUgXChYX3sxLDF9XnsxLDB9XCksIFwoWF97MSwyfV57MSwwfVwpLCBcKFhfezIsMX1eezEsMH1cKSwgZGFuIFwoWF97MiwyfV57MSwwfVwpLg0KDQpCb2JvdCBpbnRlcnBvbGFzaSB1bnR1ayBlbGVtZW4gXChYX3sxLDF9XnsxLDB9XCkgZGloaXR1bmcgc2ViYWdhaToNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0Kd197MSwxfV57KDIsMil9DQomPQ0KXG1heCgwLDEtfDEuNS0xfCkNClxtYXgoMCwxLXwxLjUtMXwpXFwNCiY9DQowLjVcdGltZXMwLjVcXA0KJj0NCjAuMjUuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpLYXJlbmEgcG9zaXNpIHRlcnNlYnV0IGJlcmphcmFrIHNhbWEgZGFyaSBrZWVtcGF0IGVsZW1lbiBtYXN1a2FuLCBtYWthOg0KDQpcWw0Kd197MSwxfV57KDIsMil9DQo9DQp3X3sxLDJ9XnsoMiwyKX0NCj0NCndfezIsMX1eeygyLDIpfQ0KPQ0Kd197MiwyfV57KDIsMil9DQo9DQowLjI1Lg0KXF0NCg0KRGVuZ2FuIGRlbWlraWFuLCBydW11cyBpbnRlcnBvbGFzaSBiaWxpbmVhciBtZW5qYWRpOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpcbGVmdFsNClxvcGVyYXRvcm5hbWV7VXB9DQpcbGVmdCgNClxtYXRoYmZ7WH1eezEsMH0NClxyaWdodCkNClxyaWdodF1fezIsMn0NCiY9DQowLjI1WF97MSwxfV57MSwwfQ0KKw0KMC4yNVhfezEsMn1eezEsMH1cXA0KJlxxdWFkKw0KMC4yNVhfezIsMX1eezEsMH0NCisNCjAuMjVYX3syLDJ9XnsxLDB9XFwNCiY9DQpcZnJhY3sNClhfezEsMX1eezEsMH0NCisNClhfezEsMn1eezEsMH0NCisNClhfezIsMX1eezEsMH0NCisNClhfezIsMn1eezEsMH0NCn17NH1cXA0KJj0NClxmcmFjey0yLjM5KzEuODItMi4zOCsyLjI0fXs0fVxcDQomPQ0KLTAuMTc3NVxcDQomXGFwcHJveC0wLjE4Lg0KXGVuZHthbGlnbmVkfQ0KXF0NCg0KRGVuZ2FuIG1lbmVyYXBrYW4gaW50ZXJwb2xhc2kgYmlsaW5lYXIgcGFkYSBzZWx1cnVoIHBvc2lzaSBrZWx1YXJhbiwgZGlwZXJvbGVoICpmZWF0dXJlIG1hcCogaGFzaWwgVXBzYW1wbGluZyBiZXJ1a3VyYW4gXCg1XHRpbWVzNVwpLCB5YWl0dToNCg0KXFsNClxvcGVyYXRvcm5hbWV7VXB9DQpcbGVmdCgNClxtYXRoYmZ7WH1eezEsMH0NClxyaWdodCkNCj0NClxiZWdpbntibWF0cml4fQ0KLTIuMzkgJiAtMC4yOSAmIDEuODIgJiAtMC4wMSAmIC0xLjg0XFwNCi0yLjM5ICYgLTAuMTggJiAyLjAzICYgMC4xMyAmIC0xLjc3XFwNCi0yLjM4ICYgLTAuMDcgJiAyLjI0ICYgMC4yNyAmIC0xLjcwXFwNCi0yLjMyICYgLTAuNDEgJiAxLjUxICYgLTAuMTcgJiAtMS44NVxcDQotMi4yNSAmIC0wLjc0ICYgMC43NyAmIC0wLjYxICYgLTEuOTkNClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQpIYXNpbCB0ZXJzZWJ1dCBtZW51bmp1a2thbiBiYWh3YSBpbnRlcnBvbGFzaSBiaWxpbmVhciBtZW1wZXJiZXNhciB1a3VyYW4gc3Bhc2lhbCAqZmVhdHVyZSBtYXAqIGRhcmkgXCgzXHRpbWVzM1wpIG1lbmphZGkgXCg1XHRpbWVzNVwpLiBOaWxhaSBwYWRhIHBvc2lzaSB5YW5nIGJlcmltcGl0IGRlbmdhbiBrb29yZGluYXQgbWFzdWthbiBkaXBlcnRhaGFua2FuLCBzZWRhbmdrYW4gbmlsYWkgcGFkYSBwb3Npc2kgbGFpbm55YSBkaWhpdHVuZyBtZW5nZ3VuYWthbiBib2JvdCBpbnRlcnBvbGFzaSBiZXJkYXNhcmthbiBqYXJhayB0ZXJoYWRhcCBlbGVtZW4gbWFzdWthbi4NCg0KLSAqKlJ1bXVzIG5vZGUgZGVjb2RlcjoqKg0KDQpTZXN1YWkgZGVuZ2FuIHBlcnNhbWFhbiBVTmV0KyssICpuZXN0ZWQgc2tpcCBjb25uZWN0aW9uKiBwZXJ0YW1hIHBhZGEgbm9kZSAqZGVjb2RlciogZGlydW11c2thbiBzZWJhZ2FpOg0KDQpcWw0KXG1hdGhiZntYfV57MCwxfQ0KPQ0KSF57KDAsMSl9DQpcbGVmdCgNClxvcGVyYXRvcm5hbWV7Q29uY2F0fQ0KXGxlZnRbDQpcbWF0aGJme1h9XnswLDB9LA0KXG9wZXJhdG9ybmFtZXtVcH0NClxsZWZ0KA0KXG1hdGhiZntYfV57MSwwfQ0KXHJpZ2h0KQ0KXHJpZ2h0XQ0KXHJpZ2h0KS4NClxdDQoNClBhZGEgcGVyc2FtYWFuIHRlcnNlYnV0LCBcKEheeygwLDEpfVwpIG1lbnlhdGFrYW4gb3BlcmFzaSBwZW5nb2xhaGFuIGZpdHVyIHBhZGEgbm9kZSAqZGVjb2RlciogXChcbWF0aGJme1h9XnswLDF9XCkuIERhbGFtIGlsdXN0cmFzaSBwZXJoaXR1bmdhbiBtYW51YWwgaW5pLCBvcGVyYXNpIHRlcnNlYnV0IGRpc2VkZXJoYW5ha2FuIG1lbmdndW5ha2FuIGtvbnZvbHVzaSBcKDFcdGltZXMxXCkgdGFucGEgYmlhcyB5YW5nIGRpaWt1dGkgZnVuZ3NpIGFrdGl2YXNpIFJlTFUuDQoNCkthcmVuYSBrZWR1YSAqZmVhdHVyZSBtYXAqIHlhbmcgZGlnYWJ1bmdrYW4gYmVydWt1cmFuIFwoNVx0aW1lczVcKSBkYW4gbWFzaW5nLW1hc2luZyBkaXJlcHJlc2VudGFzaWthbiBvbGVoIHNhdHUga2FuYWwsIGhhc2lsICpDb25jYXQqIG1lbWlsaWtpIGR1YSBrYW5hbC4gU2F0dSBmaWx0ZXIga29udm9sdXNpIFwoMVx0aW1lczFcKSBkaWd1bmFrYW4gdW50dWsgbWVuZ2dhYnVuZ2thbiBrZWR1YSBrYW5hbCB0ZXJzZWJ1dCBtZW5qYWRpIHNhdHUga2FuYWwga2VsdWFyYW4uDQoNClBhZGEgaWx1c3RyYXNpIGluaSwgYm9ib3Qga2VybmVsIGRpdGVudHVrYW4gc2ViYWdhaToNCg0KXFsNCldfe1xtYXRocm17ZGVjfSwxfV57KDAsMSl9PVsxLjAwXSwNClxxcXVhZA0KV197XG1hdGhybXtkZWN9LDJ9XnsoMCwxKX09WzEuMDBdLg0KXF0NCg0KQm9ib3QgcGVydGFtYSBkaXRlcmFwa2FuIHBhZGEgXChcbWF0aGJme1h9XnswLDB9XCksIHNlZGFuZ2thbiBib2JvdCBrZWR1YSBkaXRlcmFwa2FuIHBhZGEgXChcb3BlcmF0b3JuYW1le1VwfShcbWF0aGJme1h9XnsxLDB9KVwpLg0KDQpEZW5nYW4gZGVtaWtpYW4sIHVudHVrIHNldGlhcCBwb3Npc2kgc3Bhc2lhbCBcKChyLGMpXCksIGtlbHVhcmFuIG5vZGUgKmRlY29kZXIqIGRpaGl0dW5nIHNlYmFnYWk6DQoNClxbDQpYX3tyLGN9XnswLDF9DQo9DQpcb3BlcmF0b3JuYW1le1JlTFV9DQpcbGVmdCgNCldfe1xtYXRocm17ZGVjfSwxfV57KDAsMSl9WF97cixjfV57MCwwfQ0KKw0KV197XG1hdGhybXtkZWN9LDJ9XnsoMCwxKX0NClxsZWZ0Ww0KXG9wZXJhdG9ybmFtZXtVcH0NClxsZWZ0KA0KXG1hdGhiZntYfV57MSwwfQ0KXHJpZ2h0KQ0KXHJpZ2h0XV97cixjfQ0KXHJpZ2h0KS4NClxdDQoNCi0gKipDb250b2ggcGVyaGl0dW5nYW4gbm9kZSBkZWNvZGVyIHBhZGEgcG9zaXNpIFwoKDEsMSlcKToqKg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpYX3sxLDF9XnswLDF9DQomPQ0KXG9wZXJhdG9ybmFtZXtSZUxVfQ0KXGxlZnQoDQpXX3tcbWF0aHJte2RlY30sMX1eeygwLDEpfVhfezEsMX1eezAsMH0NCisNCldfe1xtYXRocm17ZGVjfSwyfV57KDAsMSl9DQpcbGVmdFsNClxvcGVyYXRvcm5hbWV7VXB9DQpcbGVmdCgNClxtYXRoYmZ7WH1eezEsMH0NClxyaWdodCkNClxyaWdodF1fezEsMX0NClxyaWdodClcXA0KJj0NClxvcGVyYXRvcm5hbWV7UmVMVX0NClxsZWZ0KA0KMS4wMCgtMi4zOSkNCisNCjEuMDAoLTIuMzkpDQpccmlnaHQpXFwNCiY9DQpcb3BlcmF0b3JuYW1le1JlTFV9KC00Ljc4KVxcDQomPQ0KMC4wMC4NClxlbmR7YWxpZ25lZH0NClxdDQoNCi0gKipDb250b2ggcGVyaGl0dW5nYW4gbm9kZSBkZWNvZGVyIHBhZGEgcG9zaXNpIFwoKDEsMylcKToqKg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpYX3sxLDN9XnswLDF9DQomPQ0KXG9wZXJhdG9ybmFtZXtSZUxVfQ0KXGxlZnQoDQpXX3tcbWF0aHJte2RlY30sMX1eeygwLDEpfVhfezEsM31eezAsMH0NCisNCldfe1xtYXRocm17ZGVjfSwyfV57KDAsMSl9DQpcbGVmdFsNClxvcGVyYXRvcm5hbWV7VXB9DQpcbGVmdCgNClxtYXRoYmZ7WH1eezEsMH0NClxyaWdodCkNClxyaWdodF1fezEsM30NClxyaWdodClcXA0KJj0NClxvcGVyYXRvcm5hbWV7UmVMVX0NClxsZWZ0KA0KMS4wMCgxLjgyKQ0KKw0KMS4wMCgxLjgyKQ0KXHJpZ2h0KVxcDQomPQ0KXG9wZXJhdG9ybmFtZXtSZUxVfSgzLjY0KVxcDQomPQ0KMy42NC4NClxlbmR7YWxpZ25lZH0NClxdDQoNCkRlbmdhbiBtZW5lcmFwa2FuIG9wZXJhc2kgeWFuZyBzYW1hIHBhZGEgc2VsdXJ1aCBwb3Npc2kgc3Bhc2lhbCwgZGlwZXJvbGVoICpmZWF0dXJlIG1hcCogbm9kZSAqZGVjb2Rlciogc2ViYWdhaSBiZXJpa3V0Og0KDQpcWw0KXG1hdGhiZntYfV57MCwxfQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQowLjAwICYgMC4wMCAmIDMuNjQgJiAxLjExICYgMC4wMFxcDQowLjAwICYgMC4wMCAmIDQuMjcgJiAxLjYzICYgMC4wMFxcDQowLjAwICYgMC4wMCAmIDQuNDggJiAxLjc3ICYgMC4wMFxcDQowLjAwICYgMC4wMCAmIDMuMzUgJiAwLjk0ICYgMC4wMFxcDQowLjAwICYgMC4wMCAmIDEuNTQgJiAwLjAwICYgMC4wMA0KXGVuZHtibWF0cml4fS4NClxdDQoNCkhhc2lsIHRlcnNlYnV0IG1lbnVuanVra2FuIGJhaHdhIG5vZGUgXChcbWF0aGJme1h9XnswLDF9XCkgbWVuZ2dhYnVuZ2thbiBpbmZvcm1hc2kgZGFyaSAqZmVhdHVyZSBtYXAgZW5jb2RlciogXChcbWF0aGJme1h9XnswLDB9XCkgZGFuIGhhc2lsIFVwc2FtcGxpbmcgXChcbWF0aGJme1h9XnsxLDB9XCkgbWVsYWx1aSAqbmVzdGVkIHNraXAgY29ubmVjdGlvbiouIFBhZGEgaWx1c3RyYXNpIGluaSwgcGVuZ2dhYnVuZ2FuIGRpbGFrdWthbiBtZW5nZ3VuYWthbiAqQ29uY2F0Kiwga29udm9sdXNpIFwoMVx0aW1lczFcKSwgZGFuIGZ1bmdzaSBha3RpdmFzaSBSZUxVLiAqRmVhdHVyZSBtYXAqIFwoXG1hdGhiZntYfV57MCwxfVwpIHNlbGFuanV0bnlhIGRpZ3VuYWthbiBwYWRhIHBlbWJlbnR1a2FuIG5vZGUgKmRlY29kZXIqIGJlcmlrdXRueWEuDQoNCg0KDQojIyMgYy4gVXBzYW1wbGluZyBcKFxtYXRoYmZ7WH1eezEsMX1cKSBkYW4gKk5lc3RlZCBTa2lwKiBLZWR1YSBcKFxtYXRoYmZ7WH1eezAsMn1cKQ0KDQpOb2RlICpkZWNvZGVyKiBcKFxtYXRoYmZ7WH1eezEsMX1cKSBiZXJ1a3VyYW4gXCgzXHRpbWVzM1wpIGRpcGVyYmVzYXIgbWVuamFkaSBcKDVcdGltZXM1XCkgbWVuZ2d1bmFrYW4gaW50ZXJwb2xhc2kgYmlsaW5lYXIuIFByb3NlcyBpbmkgYmVydHVqdWFuIHVudHVrIG1lbnllc3VhaWthbiB1a3VyYW4gc3Bhc2lhbCAqZmVhdHVyZSBtYXAqIHNlaGluZ2dhIGRhcGF0IGRpZ2FidW5na2FuIGRlbmdhbiBcKFxtYXRoYmZ7WH1eezAsMH1cKSBkYW4gXChcbWF0aGJme1h9XnswLDF9XCkgbWVsYWx1aSAqbmVzdGVkIHNraXAgY29ubmVjdGlvbiouDQoNCk1hdHJpa3MgKmZlYXR1cmUgbWFwKiBtYXN1a2FuIGFkYWxhaDoNCg0KXFsNClxtYXRoYmZ7WH1eezEsMX0NCj0NClxiZWdpbntibWF0cml4fQ0KMC4wMCAmIDAuMDAgJiAwLjAwXFwNCjAuMDAgJiAwLjEyICYgMC4wMFxcDQowLjAwICYgMC4wMCAmIDAuMDANClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQotICoqUnVtdXMgaW50ZXJwb2xhc2kgYmlsaW5lYXI6KioNCg0KSW50ZXJwb2xhc2kgYmlsaW5lYXIgZGlsYWt1a2FuIG1lbmdndW5ha2FuIHByaW5zaXAgeWFuZyBzYW1hIHNlcGVydGkgcGFkYSBzdWJiYWdpYW4gc2ViZWx1bW55YS4gU2V0aWFwIG5pbGFpIGtlbHVhcmFuIGRpaGl0dW5nIGJlcmRhc2Fya2FuIGphcmFrIHRlcmhhZGFwIGVsZW1lbi1lbGVtZW4gcGFkYSAqZmVhdHVyZSBtYXAqIG1hc3VrYW4uDQoNClBhZGEgKmZlYXR1cmUgbWFwKiBzYXR1IGthbmFsLCBydW11cyBpbnRlcnBvbGFzaSBiaWxpbmVhciBkaW55YXRha2FuIHNlYmFnYWk6DQoNClxbDQpcbGVmdFsNClxvcGVyYXRvcm5hbWV7VXB9DQpcbGVmdCgNClxtYXRoYmZ7WH1eezEsMX0NClxyaWdodCkNClxyaWdodF1fe3IsY30NCj0NClxzdW1fe249MX1eezN9DQpcc3VtX3ttPTF9XnszfQ0KWF97bixtfV57MSwxfQ0KXG1heA0KXGxlZnQoDQowLA0KMS1cbGVmdHx4X2MtbVxyaWdodHwNClxyaWdodCkNClxtYXgNClxsZWZ0KA0KMCwNCjEtXGxlZnR8eV9yLW5ccmlnaHR8DQpccmlnaHQpLg0KXF0NCg0KUGFkYSBwZXJzYW1hYW4gdGVyc2VidXQsIFwoclwpIGRhbiBcKGNcKSBtZW55YXRha2FuIGluZGVrcyBiYXJpcyBkYW4ga29sb20gcGFkYSAqZmVhdHVyZSBtYXAqIGtlbHVhcmFuLCBzZWRhbmdrYW4gXChuXCkgZGFuIFwobVwpIG1lbnlhdGFrYW4gaW5kZWtzIGJhcmlzIGRhbiBrb2xvbSBwYWRhICpmZWF0dXJlIG1hcCogbWFzdWthbi4gS29vcmRpbmF0IFwoeF9jXCkgbWVudW5qdWtrYW4gcG9zaXNpIGhvcml6b250YWwgYXRhdSBhcmFoIGtvbG9tLCBzZWRhbmdrYW4gXCh5X3JcKSBtZW51bmp1a2thbiBwb3Npc2kgdmVydGlrYWwgYXRhdSBhcmFoIGJhcmlzLg0KDQpCb2JvdCBpbnRlcnBvbGFzaSBwYWRhIHNldGlhcCBlbGVtZW4gbWFzdWthbiBkaW55YXRha2FuIHNlYmFnYWk6DQoNClxbDQp3X3tuLG19XnsocixjKX0NCj0NClxtYXgNClxsZWZ0KA0KMCwNCjEtXGxlZnR8eF9jLW1ccmlnaHR8DQpccmlnaHQpDQpcbWF4DQpcbGVmdCgNCjAsDQoxLVxsZWZ0fHlfci1uXHJpZ2h0fA0KXHJpZ2h0KS4NClxdDQoNCkRlbmdhbiBkZW1pa2lhbiwgcnVtdXMgaW50ZXJwb2xhc2kgYmlsaW5lYXIgZGFwYXQgZGl0dWxpc2thbiBzZWJhZ2FpOg0KDQpcWw0KXGxlZnRbDQpcb3BlcmF0b3JuYW1le1VwfQ0KXGxlZnQoDQpcbWF0aGJme1h9XnsxLDF9DQpccmlnaHQpDQpccmlnaHRdX3tyLGN9DQo9DQpcc3VtX3tuPTF9XnszfQ0KXHN1bV97bT0xfV57M30NCndfe24sbX1eeyhyLGMpfVhfe24sbX1eezEsMX0uDQpcXQ0KDQotICoqUGVuZW50dWFuIGtvb3JkaW5hdCBpbnRlcnBvbGFzaToqKg0KDQpQYWRhIGlsdXN0cmFzaSBpbmksIGtvb3JkaW5hdCBtYXRyaWtzIG1lbmdndW5ha2FuIGluZGVrcyB5YW5nIGRpbXVsYWkgZGFyaSBcKDFcKS4gS2FyZW5hIHVrdXJhbiAqZmVhdHVyZSBtYXAqIG1hc3VrYW4gYWRhbGFoIFwoM1x0aW1lczNcKSBkYW4gdWt1cmFuIGtlbHVhcmFuIGFkYWxhaCBcKDVcdGltZXM1XCksIGtvb3JkaW5hdCBpbnRlcnBvbGFzaSBkaXRlbnR1a2FuIHNlYmFnYWk6DQoNClxbDQp4X2MNCj0NCjErKGMtMSlcZnJhY3szLTF9ezUtMX0NCj0NCjErXGZyYWN7Yy0xfXsyfSwNClxdDQoNClxbDQp5X3INCj0NCjErKHItMSlcZnJhY3szLTF9ezUtMX0NCj0NCjErXGZyYWN7ci0xfXsyfSwNClxdDQoNCmRlbmdhbiBcKHIsYz0xLDIsMyw0LDVcKS4NCg0KQW5na2EgXCgxXCkgbWVudW5qdWtrYW4ga29vcmRpbmF0IGF3YWwgbWF0cmlrcyBtYXN1a2FuLCBzZWRhbmdrYW4gcGVtYmFnaWFuIGRlbmdhbiBcKDJcKSBtZW51bmp1a2thbiBiYWh3YSBzZXRpYXAgaW50ZXJ2YWwgYW50YXJhIGR1YSBrb29yZGluYXQgbWFzdWthbiBkaWJhZ2kgbWVuamFkaSBkdWEgYmFnaWFuIHlhbmcgc2FtYSBwYW5qYW5nLg0KDQpOaWxhaSBrb29yZGluYXQgeWFuZyBkaXBlcm9sZWggYWRhbGFoOg0KDQp8IEluZGVrcyBrZWx1YXJhbiB8IE5pbGFpIGtvb3JkaW5hdCB8DQp8Oi0tLTp8Oi0tLTp8DQp8IFwoMVwpIHwgXCgxXCkgfA0KfCBcKDJcKSB8IFwoMS41XCkgfA0KfCBcKDNcKSB8IFwoMlwpIHwNCnwgXCg0XCkgfCBcKDIuNVwpIHwNCnwgXCg1XCkgfCBcKDNcKSB8DQoNCkRlbmdhbiBkZW1pa2lhbiwgbmlsYWkgcGFkYSBwb3Npc2kga2VsdWFyYW4geWFuZyBiZXJpbXBpdCBkZW5nYW4ga29vcmRpbmF0IG1hc3VrYW4gZGlwZXJ0YWhhbmthbiwgc2VkYW5na2FuIG5pbGFpIHBhZGEgcG9zaXNpIGxhaW5ueWEgZGloaXR1bmcgYmVyZGFzYXJrYW4gYm9ib3QgamFyYWsgdGVyaGFkYXAgZWxlbWVuLWVsZW1lbiBtYXN1a2FuIGRpIHNla2l0YXJueWEuDQoNCi0gKipDb250b2ggcGVyaGl0dW5nYW4gaW50ZXJwb2xhc2kgYmlsaW5lYXIgcGFkYSBwb3Npc2kgXCgoMiwzKVwpOioqDQoNClBhZGEgcG9zaXNpIFwoKDIsMylcKSwga29vcmRpbmF0IGludGVycG9sYXNpIGRpcGVyb2xlaCBzZWJhZ2FpIGJlcmlrdXQ6DQoNClxbDQp5XzI9MS41LA0KXHFxdWFkDQp4XzM9Mi4NClxdDQoNClBvc2lzaSB0ZXJzZWJ1dCBiZXJhZGEgdGVwYXQgZGkgdGVuZ2FoIHNlY2FyYSB2ZXJ0aWthbCBhbnRhcmEgYmFyaXMgcGVydGFtYSBkYW4ga2VkdWEsIHRldGFwaSBzZWphamFyIGRlbmdhbiBrb2xvbSBrZWR1YS4gT2xlaCBrYXJlbmEgaXR1LCBoYW55YSBkdWEgZWxlbWVuIHBhZGEga29sb20ga2VkdWEgeWFuZyBtZW1pbGlraSBib2JvdCBidWthbiBub2wuDQoNCkJvYm90IGludGVycG9sYXNpIHVudHVrIGVsZW1lbiBcKFhfezEsMn1eezEsMX1cKSBkaWhpdHVuZyBzZWJhZ2FpOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQp3X3sxLDJ9XnsoMiwzKX0NCiY9DQpcbWF4KDAsMS18Mi0yfCkNClxtYXgoMCwxLXwxLjUtMXwpXFwNCiY9DQoxXHRpbWVzMC41XFwNCiY9DQowLjUuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpTZW1lbnRhcmEgaXR1LCBib2JvdCB1bnR1ayBlbGVtZW4gXChYX3syLDJ9XnsxLDF9XCkgYWRhbGFoOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQp3X3syLDJ9XnsoMiwzKX0NCiY9DQpcbWF4KDAsMS18Mi0yfCkNClxtYXgoMCwxLXwxLjUtMnwpXFwNCiY9DQoxXHRpbWVzMC41XFwNCiY9DQowLjUuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpFbGVtZW4gbGFpbm55YSBtZW1pbGlraSBib2JvdCBub2wga2FyZW5hIGJlcmFkYSBkaSBsdWFyIGphcmFrIGludGVycG9sYXNpIHBhZGEgcG9zaXNpIHRlcnNlYnV0LiBEZW5nYW4gZGVtaWtpYW46DQoNClxbDQp3X3sxLDJ9XnsoMiwzKX0NCj0NCndfezIsMn1eeygyLDMpfQ0KPQ0KMC41Lg0KXF0NCg0KRGVuZ2FuIG1lbWFzdWtrYW4gYm9ib3QgdGVyc2VidXQga2UgZGFsYW0gcnVtdXMgaW50ZXJwb2xhc2kgYmlsaW5lYXIsIGRpcGVyb2xlaDoNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0KXGxlZnRbDQpcb3BlcmF0b3JuYW1le1VwfQ0KXGxlZnQoDQpcbWF0aGJme1h9XnsxLDF9DQpccmlnaHQpDQpccmlnaHRdX3syLDN9DQomPQ0KMC41WF97MSwyfV57MSwxfQ0KKw0KMC41WF97MiwyfV57MSwxfVxcDQomPQ0KXGZyYWN7DQpYX3sxLDJ9XnsxLDF9DQorDQpYX3syLDJ9XnsxLDF9DQp9ezJ9XFwNCiY9DQpcZnJhY3swLjAwKzAuMTJ9ezJ9XFwNCiY9DQowLjA2Lg0KXGVuZHthbGlnbmVkfQ0KXF0NCg0KLSAqKkNvbnRvaCBwZXJoaXR1bmdhbiBpbnRlcnBvbGFzaSBiaWxpbmVhciBwYWRhIHBvc2lzaSBcKCgyLDIpXCk6KioNCg0KUGFkYSBwb3Npc2kgXCgoMiwyKVwpLCBrb29yZGluYXQgaW50ZXJwb2xhc2kgZGlwZXJvbGVoIHNlYmFnYWkgYmVyaWt1dDoNCg0KXFsNCnlfMj0xLjUsDQpccXF1YWQNCnhfMj0xLjUuDQpcXQ0KDQpQb3Npc2kgdGVyc2VidXQgYmVyYWRhIHRlcGF0IGRpIHRlbmdhaCBlbXBhdCBlbGVtZW4gbWFzdWthbiwgeWFpdHUgXChYX3sxLDF9XnsxLDF9XCksIFwoWF97MSwyfV57MSwxfVwpLCBcKFhfezIsMX1eezEsMX1cKSwgZGFuIFwoWF97MiwyfV57MSwxfVwpLg0KDQpCb2JvdCBpbnRlcnBvbGFzaSB1bnR1ayBlbGVtZW4gXChYX3sxLDF9XnsxLDF9XCkgZGloaXR1bmcgc2ViYWdhaToNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0Kd197MSwxfV57KDIsMil9DQomPQ0KXG1heCgwLDEtfDEuNS0xfCkNClxtYXgoMCwxLXwxLjUtMXwpXFwNCiY9DQowLjVcdGltZXMwLjVcXA0KJj0NCjAuMjUuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpLYXJlbmEgcG9zaXNpIHRlcnNlYnV0IGJlcmphcmFrIHNhbWEgZGFyaSBrZWVtcGF0IGVsZW1lbiBtYXN1a2FuLCBtYWthOg0KDQpcWw0Kd197MSwxfV57KDIsMil9DQo9DQp3X3sxLDJ9XnsoMiwyKX0NCj0NCndfezIsMX1eeygyLDIpfQ0KPQ0Kd197MiwyfV57KDIsMil9DQo9DQowLjI1Lg0KXF0NCg0KRGVuZ2FuIGRlbWlraWFuLCBydW11cyBpbnRlcnBvbGFzaSBiaWxpbmVhciBtZW5qYWRpOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpcbGVmdFsNClxvcGVyYXRvcm5hbWV7VXB9DQpcbGVmdCgNClxtYXRoYmZ7WH1eezEsMX0NClxyaWdodCkNClxyaWdodF1fezIsMn0NCiY9DQowLjI1WF97MSwxfV57MSwxfQ0KKw0KMC4yNVhfezEsMn1eezEsMX1cXA0KJlxxdWFkKw0KMC4yNVhfezIsMX1eezEsMX0NCisNCjAuMjVYX3syLDJ9XnsxLDF9XFwNCiY9DQpcZnJhY3sNClhfezEsMX1eezEsMX0NCisNClhfezEsMn1eezEsMX0NCisNClhfezIsMX1eezEsMX0NCisNClhfezIsMn1eezEsMX0NCn17NH1cXA0KJj0NClxmcmFjezAuMDArMC4wMCswLjAwKzAuMTJ9ezR9XFwNCiY9DQowLjAzLg0KXGVuZHthbGlnbmVkfQ0KXF0NCg0KRGVuZ2FuIG1lbmVyYXBrYW4gaW50ZXJwb2xhc2kgYmlsaW5lYXIgcGFkYSBzZWx1cnVoIHBvc2lzaSBrZWx1YXJhbiwgZGlwZXJvbGVoICpmZWF0dXJlIG1hcCogaGFzaWwgVXBzYW1wbGluZyBiZXJ1a3VyYW4gXCg1XHRpbWVzNVwpLCB5YWl0dToNCg0KXFsNClxvcGVyYXRvcm5hbWV7VXB9DQpcbGVmdCgNClxtYXRoYmZ7WH1eezEsMX0NClxyaWdodCkNCj0NClxiZWdpbntibWF0cml4fQ0KMC4wMCAmIDAuMDAgJiAwLjAwICYgMC4wMCAmIDAuMDBcXA0KMC4wMCAmIDAuMDMgJiAwLjA2ICYgMC4wMyAmIDAuMDBcXA0KMC4wMCAmIDAuMDYgJiAwLjEyICYgMC4wNiAmIDAuMDBcXA0KMC4wMCAmIDAuMDMgJiAwLjA2ICYgMC4wMyAmIDAuMDBcXA0KMC4wMCAmIDAuMDAgJiAwLjAwICYgMC4wMCAmIDAuMDANClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQpIYXNpbCB0ZXJzZWJ1dCBtZW51bmp1a2thbiBiYWh3YSBpbnRlcnBvbGFzaSBiaWxpbmVhciBtZW1wZXJiZXNhciB1a3VyYW4gc3Bhc2lhbCAqZmVhdHVyZSBtYXAqIGRhcmkgXCgzXHRpbWVzM1wpIG1lbmphZGkgXCg1XHRpbWVzNVwpLiBOaWxhaSBwYWRhIHBvc2lzaSB5YW5nIGJlcmltcGl0IGRlbmdhbiBrb29yZGluYXQgbWFzdWthbiBkaXBlcnRhaGFua2FuLCBzZWRhbmdrYW4gbmlsYWkgcGFkYSBwb3Npc2kgbGFpbm55YSBkaWhpdHVuZyBtZW5nZ3VuYWthbiBib2JvdCBpbnRlcnBvbGFzaSBiZXJkYXNhcmthbiBqYXJhayB0ZXJoYWRhcCBlbGVtZW4gbWFzdWthbi4NCg0KLSAqKlJ1bXVzIG5vZGUgZGVjb2RlcjoqKg0KDQpTZXN1YWkgZGVuZ2FuIHBlcnNhbWFhbiBVTmV0KyssICpuZXN0ZWQgc2tpcCBjb25uZWN0aW9uKiBrZWR1YSBwYWRhIG5vZGUgKmRlY29kZXIqIGRpcnVtdXNrYW4gc2ViYWdhaToNCg0KXFsNClxtYXRoYmZ7WH1eezAsMn0NCj0NCkheeygwLDIpfQ0KXGxlZnQoDQpcb3BlcmF0b3JuYW1le0NvbmNhdH0NClxsZWZ0Ww0KXG1hdGhiZntYfV57MCwwfSwNClxtYXRoYmZ7WH1eezAsMX0sDQpcb3BlcmF0b3JuYW1le1VwfQ0KXGxlZnQoDQpcbWF0aGJme1h9XnsxLDF9DQpccmlnaHQpDQpccmlnaHRdDQpccmlnaHQpLg0KXF0NCg0KUGFkYSBwZXJzYW1hYW4gdGVyc2VidXQsIFwoSF57KDAsMil9XCkgbWVueWF0YWthbiBvcGVyYXNpIHBlbmdvbGFoYW4gZml0dXIgcGFkYSBub2RlICpkZWNvZGVyKiBcKFxtYXRoYmZ7WH1eezAsMn1cKS4gRGFsYW0gaWx1c3RyYXNpIHBlcmhpdHVuZ2FuIG1hbnVhbCBpbmksIG9wZXJhc2kgdGVyc2VidXQgZGlzZWRlcmhhbmFrYW4gbWVuZ2d1bmFrYW4ga29udm9sdXNpIFwoMVx0aW1lczFcKSB0YW5wYSBiaWFzIHlhbmcgZGlpa3V0aSBmdW5nc2kgYWt0aXZhc2kgUmVMVS4NCg0KS2FyZW5hIGtldGlnYSAqZmVhdHVyZSBtYXAqIHlhbmcgZGlnYWJ1bmdrYW4gYmVydWt1cmFuIFwoNVx0aW1lczVcKSBkYW4gbWFzaW5nLW1hc2luZyBkaXJlcHJlc2VudGFzaWthbiBvbGVoIHNhdHUga2FuYWwsIGhhc2lsICpDb25jYXQqIG1lbWlsaWtpIHRpZ2Ega2FuYWwuIFNhdHUgZmlsdGVyIGtvbnZvbHVzaSBcKDFcdGltZXMxXCkgZGlndW5ha2FuIHVudHVrIG1lbmdnYWJ1bmdrYW4ga2V0aWdhIGthbmFsIHRlcnNlYnV0IG1lbmphZGkgc2F0dSBrYW5hbCBrZWx1YXJhbi4NCg0KUGFkYSBpbHVzdHJhc2kgaW5pLCBib2JvdCBrZXJuZWwgZGl0ZW50dWthbiBzZWJhZ2FpOg0KDQpcWw0KXG1hdGhiZntXfV97XG1hdGhybXtwd319XnsoMCwyKX0NCj0NClxiZWdpbntibWF0cml4fQ0KMC4yNSAmIDAuNTAgJiAwLjI1DQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KQm9ib3QgdGVyc2VidXQgbWVydXBha2FuIHBhcmFtZXRlciBpbHVzdHJhdGlmIHVudHVrIG1lbnllZGVyaGFuYWthbiBwZXJoaXR1bmdhbiBtYW51YWwgZGFuIHRpZGFrIG1lcmVwcmVzZW50YXNpa2FuIGJvYm90IGhhc2lsIHBlbGF0aWhhbiBtb2RlbC4NCg0KQm9ib3QgcGVydGFtYSBkaXRlcmFwa2FuIHBhZGEgXChcbWF0aGJme1h9XnswLDB9XCksIGJvYm90IGtlZHVhIGRpdGVyYXBrYW4gcGFkYSBcKFxtYXRoYmZ7WH1eezAsMX1cKSwgc2VkYW5na2FuIGJvYm90IGtldGlnYSBkaXRlcmFwa2FuIHBhZGEgXChcb3BlcmF0b3JuYW1le1VwfShcbWF0aGJme1h9XnsxLDF9KVwpLg0KDQpEZW5nYW4gZGVtaWtpYW4sIHVudHVrIHNldGlhcCBwb3Npc2kgc3Bhc2lhbCBcKChyLGMpXCksIGtlbHVhcmFuIG5vZGUgKmRlY29kZXIqIGRpaGl0dW5nIHNlYmFnYWk6DQoNClxbDQpYX3tyLGN9XnswLDJ9DQo9DQpcb3BlcmF0b3JuYW1le1JlTFV9DQpcbGVmdCgNCjAuMjVYX3tyLGN9XnswLDB9DQorDQowLjUwWF97cixjfV57MCwxfQ0KKw0KMC4yNQ0KXGxlZnRbDQpcb3BlcmF0b3JuYW1le1VwfQ0KXGxlZnQoDQpcbWF0aGJme1h9XnsxLDF9DQpccmlnaHQpDQpccmlnaHRdX3tyLGN9DQpccmlnaHQpLg0KXF0NCg0KLSAqKkNvbnRvaCBwZXJoaXR1bmdhbiBub2RlIGRlY29kZXIgcGFkYSBwb3Npc2kgXCgoMSwxKVwpOioqDQoNClxbDQpcYmVnaW57YWxpZ25lZH0NClhfezEsMX1eezAsMn0NCiY9DQpcb3BlcmF0b3JuYW1le1JlTFV9DQpcbGVmdCgNCjAuMjVYX3sxLDF9XnswLDB9DQorDQowLjUwWF97MSwxfV57MCwxfQ0KKw0KMC4yNQ0KXGxlZnRbDQpcb3BlcmF0b3JuYW1le1VwfQ0KXGxlZnQoDQpcbWF0aGJme1h9XnsxLDF9DQpccmlnaHQpDQpccmlnaHRdX3sxLDF9DQpccmlnaHQpXFwNCiY9DQpcb3BlcmF0b3JuYW1le1JlTFV9DQpcbGVmdCgNCjAuMjUoLTIuMzkpDQorDQowLjUwKDAuMDApDQorDQowLjI1KDAuMDApDQpccmlnaHQpXFwNCiY9DQpcb3BlcmF0b3JuYW1le1JlTFV9KC0wLjYwKVxcDQomPQ0KMC4wMC4NClxlbmR7YWxpZ25lZH0NClxdDQoNCi0gKipDb250b2ggcGVyaGl0dW5nYW4gbm9kZSBkZWNvZGVyIHBhZGEgcG9zaXNpIFwoKDIsMylcKToqKg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpYX3syLDN9XnswLDJ9DQomPQ0KXG9wZXJhdG9ybmFtZXtSZUxVfQ0KXGxlZnQoDQowLjI1WF97MiwzfV57MCwwfQ0KKw0KMC41MFhfezIsM31eezAsMX0NCisNCjAuMjUNClxsZWZ0Ww0KXG9wZXJhdG9ybmFtZXtVcH0NClxsZWZ0KA0KXG1hdGhiZntYfV57MSwxfQ0KXHJpZ2h0KQ0KXHJpZ2h0XV97MiwzfQ0KXHJpZ2h0KVxcDQomPQ0KXG9wZXJhdG9ybmFtZXtSZUxVfQ0KXGxlZnQoDQowLjI1KDIuMjQpDQorDQowLjUwKDQuMjcpDQorDQowLjI1KDAuMDYpDQpccmlnaHQpXFwNCiY9DQpcb3BlcmF0b3JuYW1le1JlTFV9DQpcbGVmdCgNCjAuNTYrMi4xMzUrMC4wMTUNClxyaWdodClcXA0KJj0NClxvcGVyYXRvcm5hbWV7UmVMVX0oMi43MSlcXA0KJj0NCjIuNzEuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpEZW5nYW4gbWVuZXJhcGthbiBvcGVyYXNpIHlhbmcgc2FtYSBwYWRhIHNlbHVydWggcG9zaXNpIHNwYXNpYWwgZGFuIG1lbmFtcGlsa2FuIGhhc2lsIGhpbmdnYSBkdWEgYW5na2EgZGVzaW1hbCwgZGlwZXJvbGVoICpmZWF0dXJlIG1hcCoga2VsdWFyYW4gbm9kZSAqZGVjb2Rlciogc2ViYWdhaSBiZXJpa3V0Og0KDQpcWw0KXG1hdGhiZntYfV57MCwyfQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQowLjAwICYgMC4wMCAmIDIuMjggJiAwLjg0ICYgMC4wMFxcDQowLjAwICYgMC4wMCAmIDIuNzEgJiAxLjIwICYgMC4wMFxcDQowLjAwICYgMC4wMCAmIDIuODMgJiAxLjI4ICYgMC4wMFxcDQowLjAwICYgMC4wMCAmIDIuMTUgJiAwLjc2ICYgMC4wMFxcDQowLjAwICYgMC4wMCAmIDAuOTYgJiAwLjAwICYgMC4wMA0KXGVuZHtibWF0cml4fS4NClxdDQoNCkhhc2lsIHRlcnNlYnV0IG1lbnVuanVra2FuIGJhaHdhIG5vZGUgXChcbWF0aGJme1h9XnswLDJ9XCkgbWVuZ2dhYnVuZ2thbiBpbmZvcm1hc2kgZGFyaSBcKFxtYXRoYmZ7WH1eezAsMH1cKSwgXChcbWF0aGJme1h9XnswLDF9XCksIGRhbiBoYXNpbCBVcHNhbXBsaW5nIFwoXG1hdGhiZntYfV57MSwxfVwpIG1lbGFsdWkgKm5lc3RlZCBza2lwIGNvbm5lY3Rpb24qLiBQYWRhIGlsdXN0cmFzaSBpbmksIHBlbmdnYWJ1bmdhbiBkaWxha3VrYW4gbWVuZ2d1bmFrYW4gKkNvbmNhdCosIGtvbnZvbHVzaSBcKDFcdGltZXMxXCksIGRhbiBmdW5nc2kgYWt0aXZhc2kgUmVMVS4gKkZlYXR1cmUgbWFwKiBcKFxtYXRoYmZ7WH1eezAsMn1cKSBtZXJ1cGFrYW4ga2VsdWFyYW4gYWtoaXIgKmRlY29kZXIqIHBhZGEgaWx1c3RyYXNpIHBlcmhpdHVuZ2FuIG1hbnVhbCBpbmkuDQoNCg0KIyMgNy4gUHJlZGlrc2kgUHJvYmFiaWxpdGFzIFBpa3NlbCBkYW4gTWFzayBTZWdtZW50YXNpDQoNCktlbHVhcmFuIGFraGlyIGRlY29kZXIgXChcbWF0aGJme1h9XnswLDJ9XCkgZGlndW5ha2FuIHVudHVrIG1lbmdoYXNpbGthbiBwcmVkaWtzaSBwYWRhIHNldGlhcCBwaWtzZWwuIFRhaGFwIGluaSB0ZXJkaXJpIGF0YXMgcGVtYmVudHVrYW4gKmxvZ2l0Kiwga29udmVyc2kgKmxvZ2l0KiBtZW5qYWRpIHByb2JhYmlsaXRhcyBtZW5nZ3VuYWthbiBmdW5nc2kgc2lnbW9pZCwgZGFuIHBlbWJlbnR1a2FuICptYXNrKiBzZWdtZW50YXNpIGJpbmVyIG1lbmdndW5ha2FuIG5pbGFpIGFtYmFuZyBsZWJpaCBkYXJpIFwoMC41MFwpLg0KDQojIyMgYS4gSGVhZCBTZWdtZW50YXNpIGRhbiBNYXRyaWtzIExvZ2l0IChcKFxtYXRoYmZ7en1cKSkNCg0KUGFkYSBpbHVzdHJhc2kgaW5pLCAqaGVhZCogc2VnbWVudGFzaSBtZW5nZ3VuYWthbiAqY29udm9sdXRpb24qIFwoMVx0aW1lczFcKSB0YW5wYSBiaWFzIGRlbmdhbiBib2JvdCBcKDEuMDBcKS4gQm9ib3QgdGVyc2VidXQgZGlueWF0YWthbiBzZWJhZ2FpOg0KDQpcWw0KXG1hdGhiZntXfV97XG1hdGhybXtzZWd9fQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQoxLjAwDQpcZW5ke2JtYXRyaXh9Lg0KXF0NCg0KS2FyZW5hIGJvYm90ICpjb252b2x1dGlvbiogYmVybmlsYWkgXCgxLjAwXCkgZGFuIGJpYXMgdGlkYWsgZGlndW5ha2FuLCBuaWxhaSAqbG9naXQqIHNhbWEgZGVuZ2FuIGtlbHVhcmFuIGFraGlyIGRlY29kZXIuDQoNCi0gKipSdW11czoqKg0KDQpcWw0Kel97aSxqfQ0KPQ0KV197XG1hdGhybXtzZWd9LDEsMX0NClhfe2ksan1eezAsMn0uDQpcXQ0KDQpQYWRhIGlsdXN0cmFzaSBpbmksIHBlcnNhbWFhbiB0ZXJzZWJ1dCBkYXBhdCBkaXNlZGVyaGFuYWthbiBtZW5qYWRpOg0KDQpcWw0Kel97aSxqfQ0KPQ0KMS4wMFhfe2ksan1eezAsMn0NCj0NClhfe2ksan1eezAsMn0uDQpcXQ0KDQpNYXRyaWtzIFwoXG1hdGhiZnt6fVwpIGJlcmRpbWVuc2kgXCg1XHRpbWVzNVwpLg0KDQotICoqQ29udG9oIHBlcmhpdHVuZ2FuOioqDQoNClxbDQpcYmVnaW57YWxpZ25lZH0NCnpfezMsM30NCiY9DQoxLjAwWF97MywzfV57MCwyfVxcDQomPQ0KMS4wMCgyLjgzKVxcDQomPQ0KMi44My4NClxlbmR7YWxpZ25lZH0NClxdDQoNCkRlbmdhbiBhdHVyYW4geWFuZyBzYW1hLCBkaXBlcm9sZWggbWF0cmlrcyAqbG9naXQqOg0KDQpcWw0KXG1hdGhiZnt6fQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQowLjAwICYgMC4wMCAmIDIuMjggJiAwLjg0ICYgMC4wMFxcDQowLjAwICYgMC4wMCAmIDIuNzEgJiAxLjIwICYgMC4wMFxcDQowLjAwICYgMC4wMCAmIDIuODMgJiAxLjI4ICYgMC4wMFxcDQowLjAwICYgMC4wMCAmIDIuMTUgJiAwLjc2ICYgMC4wMFxcDQowLjAwICYgMC4wMCAmIDAuOTYgJiAwLjAwICYgMC4wMA0KXGVuZHtibWF0cml4fS4NClxdDQoNCiMjIyBiLiBQcm9iYWJpbGl0YXMgUHJlZGlrc2kgUGlrc2VsIChcKFxtYXRoYmZ7cH1cKSkNCg0KRnVuZ3NpIHNpZ21vaWQgZGl0ZXJhcGthbiBwYWRhIHNldGlhcCBlbGVtZW4gKmxvZ2l0KiB1bnR1ayBtZW5ndWJhaCBuaWxhaW55YSBtZW5qYWRpIHByb2JhYmlsaXRhcyBwYWRhIHJlbnRhbmcgXChbMCwxXVwpLiBOaWxhaSB5YW5nIG1lbmRla2F0aSBcKDFcKSBtZW51bmp1a2thbiBrZXlha2luYW4gbW9kZWwgeWFuZyBsZWJpaCB0aW5nZ2kgYmFod2EgcGlrc2VsIHRlcnNlYnV0IHRlcm1hc3VrIGtlbGFzIHRhcmdldC4NCg0KLSAqKlJ1bXVzOioqDQoNClxbDQpwX3tpLGp9DQo9DQpcc2lnbWEoel97aSxqfSkNCj0NClxmcmFjezF9ezErZV57LXpfe2ksan19fS4NClxdDQoNCk1hdHJpa3MgcHJvYmFiaWxpdGFzIFwoXG1hdGhiZntwfVwpIGJlcmRpbWVuc2kgXCg1XHRpbWVzNVwpLg0KDQotICoqQ29udG9oIHBlcmhpdHVuZ2FuOioqDQoNClVudHVrIHBvc2lzaSBcKCgzLDMpXCksIGRpa2V0YWh1aSBcKHpfezMsM309Mi44M1wpLiBNYWthOg0KDQpcWw0KXGJlZ2lue2FsaWduZWR9DQpwX3szLDN9DQomPQ0KXGZyYWN7MX17MStlXnstel97MywzfX19XFwNCiY9DQpcZnJhY3sxfXsxK2Veey0yLjgzfX1cXA0KJj0NClxmcmFjezF9ezErMC4wNTkwfVxcDQomPQ0KMC45NDQzXFwNCiY9DQowLjk0Lg0KXGVuZHthbGlnbmVkfQ0KXF0NCg0KVW50dWsgKmxvZ2l0KiBub2wsIHByb2JhYmlsaXRhc255YSBhZGFsYWg6DQoNClxbDQpcYmVnaW57YWxpZ25lZH0NCnBfezEsMX0NCiY9DQpcZnJhY3sxfXsxK2Veey0wLjAwfX1cXA0KJj0NClxmcmFjezF9ezErMX1cXA0KJj0NCjAuNTAuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpEZW5nYW4gYXR1cmFuIHlhbmcgc2FtYSwgZGlwZXJvbGVoIG1hdHJpa3MgcHJvYmFiaWxpdGFzOg0KDQpcWw0KXG1hdGhiZntwfQ0KPQ0KXGJlZ2lue2JtYXRyaXh9DQowLjUwICYgMC41MCAmIDAuOTEgJiAwLjcwICYgMC41MFxcDQowLjUwICYgMC41MCAmIDAuOTQgJiAwLjc3ICYgMC41MFxcDQowLjUwICYgMC41MCAmIDAuOTQgJiAwLjc4ICYgMC41MFxcDQowLjUwICYgMC41MCAmIDAuOTAgJiAwLjY4ICYgMC41MFxcDQowLjUwICYgMC41MCAmIDAuNzIgJiAwLjUwICYgMC41MA0KXGVuZHtibWF0cml4fS4NClxdDQoNCiMjIyBjLiBNYXNrIFNlZ21lbnRhc2kgQmluZXIgKFwoXHdpZGVoYXR7XG1hdGhiZntNfX1cKSkNCg0KTWF0cmlrcyBwcm9iYWJpbGl0YXMgZGl1YmFoIG1lbmphZGkgKm1hc2sqIHNlZ21lbnRhc2kgYmluZXIgbWVuZ2d1bmFrYW4gbmlsYWkgYW1iYW5nIGxlYmloIGRhcmkgXCgwLjUwXCkuIFBpa3NlbCBkZW5nYW4gcHJvYmFiaWxpdGFzIHRlcGF0IFwoMC41MFwpIGRpa2F0ZWdvcmlrYW4gc2ViYWdhaSBsYXRhciBiZWxha2FuZy4NCg0KLSAqKlJ1bXVzOioqDQoNClxbDQpcd2lkZWhhdHtNfV97aSxqfQ0KPQ0KXG1hdGhiYnsxfQ0KXGxlZnRbDQpwX3tpLGp9PjAuNTANClxyaWdodF0uDQpcXQ0KDQpkZW5nYW46DQoNClxbDQpcd2lkZWhhdHtNfV97aSxqfQ0KPQ0KXGJlZ2lue2Nhc2VzfQ0KMSwgJiBcdGV4dHtqaWthIH0gcF97aSxqfT4wLjUwIFx0ZXh0eyAod2lsYXlhaCBsZXNpKX0sXFwNCjAsICYgXHRleHR7amlrYSB9IHBfe2ksan1cbGVxMC41MCBcdGV4dHsgKGxhdGFyIGJlbGFrYW5nKX0uDQpcZW5ke2Nhc2VzfQ0KXF0NCg0KTWF0cmlrcyAqbWFzayogcHJlZGlrc2kgXChcd2lkZWhhdHtcbWF0aGJme019fVwpIGJlcmRpbWVuc2kgXCg1XHRpbWVzNVwpLg0KDQotICoqQ29udG9oIHBlcmhpdHVuZ2FuOioqDQoNClVudHVrIHBvc2lzaSBcKCgzLDMpXCk6DQoNClxbDQpcYmVnaW57YWxpZ25lZH0NClx3aWRlaGF0e019X3szLDN9DQomPQ0KXG1hdGhiYnsxfQ0KXGxlZnRbDQpwX3szLDN9PjAuNTANClxyaWdodF1cXA0KJj0NClxtYXRoYmJ7MX0NClxsZWZ0Ww0KMC45ND4wLjUwDQpccmlnaHRdXFwNCiY9DQoxLg0KXGVuZHthbGlnbmVkfQ0KXF0NCg0KVW50dWsgcG9zaXNpIFwoKDEsMSlcKToNCg0KXFsNClxiZWdpbnthbGlnbmVkfQ0KXHdpZGVoYXR7TX1fezEsMX0NCiY9DQpcbWF0aGJiezF9DQpcbGVmdFsNCnBfezEsMX0+MC41MA0KXHJpZ2h0XVxcDQomPQ0KXG1hdGhiYnsxfQ0KXGxlZnRbDQowLjUwPjAuNTANClxyaWdodF1cXA0KJj0NCjAuDQpcZW5ke2FsaWduZWR9DQpcXQ0KDQpEZW5nYW4gYXR1cmFuIHlhbmcgc2FtYSwgZGlwZXJvbGVoICptYXNrKiBzZWdtZW50YXNpIHByZWRpa3NpOg0KDQpcWw0KXHdpZGVoYXR7XG1hdGhiZntNfX0NCj0NClxiZWdpbntibWF0cml4fQ0KMCAmIDAgJiAxICYgMSAmIDBcXA0KMCAmIDAgJiAxICYgMSAmIDBcXA0KMCAmIDAgJiAxICYgMSAmIDBcXA0KMCAmIDAgJiAxICYgMSAmIDBcXA0KMCAmIDAgJiAxICYgMCAmIDANClxlbmR7Ym1hdHJpeH0uDQpcXQ0KDQo+ICoqS2V0ZXJhbmdhbiBwcm9zZXMgcGVsYXRpaGFuOioqIE1hc2sgYmluZXIgXChcd2lkZWhhdHtNfVwpIHBhZGEgaWx1c3RyYXNpIGluaSBkaXRhbXBpbGthbiB1bnR1ayBtZW1wZXJsaWhhdGthbiBiZW50dWsgYWtoaXIgaGFzaWwgc2VnbWVudGFzaSBkYW4gdW50dWsgbWVuZ2hpdHVuZyBtZXRyaWsgZXZhbHVhc2kuIFBhZGEgcHJvc2VzIHBlbGF0aWhhbiwgbWFzayBiaW5lciB0ZXJzZWJ1dCB0aWRhayBkaWd1bmFrYW4gdW50dWsgbWVtcGVyYmFydWkgYm9ib3QgbW9kZWwuIFBlbWJhcnVhbiBib2JvdCBkaWxha3VrYW4gbWVuZ2d1bmFrYW4gcHJvYmFiaWxpdGFzIHByZWRpa3NpIFwocFwpIGRhbiBncm91bmQgdHJ1dGggXChNXCkgbWVsYWx1aSBCQ0UtRGljZSBsb3NzLg0KDQo=