From 4936541000a8773c32cb941589f618f18bc3297d Mon Sep 17 00:00:00 2001 From: Mikola Lysenko Date: Fri, 19 Apr 2024 22:19:35 +0100 Subject: [PATCH 1/3] Replace BPE merge algorithm with n log n heap based merge --- js/src/core.ts | 186 ++++++++++++++++++++++++++++---- js/test/fixtures/evil-string.ts | 1 + js/test/perf.test.ts | 26 +++++ 3 files changed, 194 insertions(+), 19 deletions(-) create mode 100644 js/test/fixtures/evil-string.ts create mode 100644 js/test/perf.test.ts diff --git a/js/src/core.ts b/js/src/core.ts index 63e261ef..b48bf6b8 100644 --- a/js/src/core.ts +++ b/js/src/core.ts @@ -2,37 +2,185 @@ import base64 from "base64-js"; import type { TiktokenModel } from "./ranks/ranks"; import { never } from "./utils"; +type BPEMergeNode = { + listNext: BPEMergeNode | null; + listPrev: BPEMergeNode | null; + + deleted: boolean; + updated: boolean; + updatedRank: number; + removed: boolean; + + rank: number; + start: number; + end: number; +}; + +function compareNode (a:BPEMergeNode, b:BPEMergeNode) { + return a.rank - b.rank || a.start - b.start; +} + +// Helper function to swap elements at two indices +function swap(heap:BPEMergeNode[], i:number, j:number) { + const temp = heap[i]; + heap[i] = heap[j]; + heap[j] = temp; +} + +// Function to push an element onto the heap +function heapPush(heap:BPEMergeNode[], part:BPEMergeNode) { + heap.push(part); // Add the new element to the end + let currentIndex = heap.length - 1; + let parentIndex = Math.floor((currentIndex - 1) / 2); + + // Bubble the new element up to its correct position + while (currentIndex > 0 && compareNode(heap[currentIndex], heap[parentIndex]) < 0) { + swap(heap, currentIndex, parentIndex); + currentIndex = parentIndex; + parentIndex = Math.floor((currentIndex - 1) / 2); + } +} + +// Function to pop the root element from the heap +function heapPop(heap:BPEMergeNode[]) { + if (heap.length === 0) { + return undefined; // Return undefined if the heap is empty + } + + const rootValue = heap[0]; // The root element to return + const lastValue = heap.pop(); // Remove the last element + + if (heap.length > 0 && lastValue) { + heap[0] = lastValue; // Move the last element to the root + let currentIndex = 0; + + // Bubble down the new root element to its correct position + while (true) { + let leftChildIndex = 2 * currentIndex + 1; + let rightChildIndex = 2 * currentIndex + 2; + let smallestIndex = currentIndex; + + if (leftChildIndex < heap.length && compareNode(heap[leftChildIndex], heap[smallestIndex]) < 0) { + smallestIndex = leftChildIndex; + } + + if (rightChildIndex < heap.length && compareNode(heap[rightChildIndex], heap[smallestIndex]) < 0) { + smallestIndex = rightChildIndex; + } + + if (smallestIndex !== currentIndex) { + swap(heap, currentIndex, smallestIndex); + currentIndex = smallestIndex; + } else { + break; + } + } + } + + return rootValue; +} + function bytePairMerge( piece: Uint8Array, ranks: Map ): Array<{ start: number; end: number }> { - let parts: Array<{ start: number; end: number }> = Array.from( - { length: piece.length }, - (_, i) => ({ start: i, end: i + 1 }) - ); + const parts: BPEMergeNode[] = Array.from({ length: piece.length }, (_, i) => ({ + start: i, + end: i + 1, + rank: 0, + deleted: false, + updated: false, + updatedRank: 0, + removed: true, + listNext: null, + listPrev: null + })); + + const head = parts[0]; + for (let i = 0; i < parts.length; ++i) { + parts[i].listPrev = parts[i - 1] ?? null; + parts[i].listNext = parts[i + 1] ?? null; + } + + const heap:BPEMergeNode[] = [] + for (let i = 0; i < parts.length - 1; ++i) { + const slice = piece.slice(parts[i].start, parts[i + 1].end); + const rank = ranks.get(slice.join(",")); + if (rank == null) + continue; + const part = parts[i]; + part.removed = false; + part.rank = rank; + heapPush(heap, part); + } - while (parts.length > 1) { - let minRank: [number, number] | null = null; + while (heap.length > 0) { + const part = heapPop(heap); + if (!part) + break; - for (let i = 0; i < parts.length - 1; i++) { - const slice = piece.slice(parts[i].start, parts[i + 1].end); - const rank = ranks.get(slice.join(",")); - if (rank == null) continue; + // remove deleted nodes from heap + if (part.deleted) { + part.deleted = false; + part.removed = true; + continue + } - if (minRank == null || rank < minRank[0]) { - minRank = [rank, i]; + // reinsert updated nodes + if (part.updated) { + part.rank = part.updatedRank; + part.updated = false; + heapPush(heap, part); + continue; + } + + // mark node as removed from heap + part.removed = true + + // delete next part and collapse node + part.end = part.listNext?.end ?? piece.length; + if (part.listNext) + part.listNext.deleted = true; + part.listNext = part.listNext?.listNext ?? null; + + // update rank + if (part.listNext) { + part.listNext.listPrev = part; + const slice = piece.slice(part.start, part.listNext.end); + const rank = ranks.get(slice.join(",")); + if (rank != null) { + part.removed = false; + part.rank = rank; + heapPush(heap, part); } } - if (minRank != null) { - const i = minRank[1]; - parts[i] = { start: parts[i].start, end: parts[i + 1].end }; - parts.splice(i + 1, 1); - } else { - break; + // update previous part rank + if (part.listPrev) { + const prevSlice = piece.slice(part.listPrev.start, part.end); + const prevRank = ranks.get(prevSlice.join(",")); + if (prevRank != null) { + if (prevRank !== part.listPrev.rank) { + if (part.listPrev.removed) { + part.listPrev.removed = false + part.listPrev.rank = prevRank; + heapPush(heap, part) + } else { + part.listPrev.updated = true; + part.listPrev.updatedRank = prevRank; + } + } + } else { + part.listPrev.deleted = true; + } } } - return parts; + + const result: Array<{ start: number; end: number }> = []; + for (let node: BPEMergeNode | null = head; !!node; node = node.listNext) { + result.push({ start: node.start, end: node.end }); + } + return result; } function bytePairEncode(piece: Uint8Array, ranks: Map) { diff --git a/js/test/fixtures/evil-string.ts b/js/test/fixtures/evil-string.ts new file mode 100644 index 00000000..dcd4bafe --- /dev/null +++ b/js/test/fixtures/evil-string.ts @@ -0,0 +1 @@ +export const EVIL_STRING = `imZmZZZmimZZZmmmZimmmZmmmimZZZZmZZimZZZmmmmimmmZZmZimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimZmmZmmimZmmZmmimZmZZmmimZmZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZmmmZZimZZZmmZZimZmZZmmimZmZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZmmmmmimZmmZmZimZmZZmmimZmZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimmZZZZmimZmmZmmimZmZZmmimZmZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZmmmmZimmZZZZZimZmZZmmimZmZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimmZZZZZimmZZZZmimZmZZmmimZmZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimmZZZmZimmZZZmZimZmZZmmimZmZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimZmmmmmimmZZZmmimZmZZmmimZmZmmZimZmZZZmimmmmZmmimZZmmmmZimZZmZZZmimZZZmZmmimZZmZmZmimZmZZZmimmZZmZZimZZmZZZZimZZmmmmmimZZmmZZZimZZZmmZmimZZmmmmZimZZmZZmmimZZmmZZmimZZmmZZZimZmZZmZimZZZmZZmimZmmZmZimZmZZZmZimZmmmmmimmZZZZmimZZZmmmmimmZZZmZimZmmmmZimmZZZZZimZmZmmZimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZmmmZZimZmmZmZimZmmmZZimZZZmmmZimmZZZmmimZmZZmmimZmZZmZmimZZmmmZZimZZZmmmmimZZmmmmZimZZmmmmmimZZmmmZZimZZmmZZZimZZmZmZimZZZmZZmimZmmZmZimZmZZZmZimZmmmmmimmZZZZmimZZZmmmmimmZZZmZimZmmmmZimmZZZZZimZmZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZmmmZZimZmmZmZimZmmmZZimZZZmmmZimmZZZmmimmZZmZmimZmZZmmmimZmZmmZimZmZZZmimmmZZmmimZZZZZZmimmZmmmmimZZmZmZZimZZZZZmmimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimZmmmZmimZZZmmZZimZmZZmmimZmZmmZimZmZZZmimZZmmmZZimZZmZZZZimmZmmmmimZmZZmZZimZZZmmZmimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZZZmZmmimZZZmmZZimZmZZmmimZmZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimZmmZmmimmZZZmZimZmZZmmimZmZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZmmmmmimZmmmmmimZmZZmmimZmZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimZZZmZmmimZmmmmmimZmZZmmimZmZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimmZZZZmimZmmmZZimZmZZmmimZmZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimZmmZmmimZZZmmZZimZmZZmmimZmZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimmZZZmZimmZZZZZimZmZZmmimZmZmmZimZmZZZmimmZmmmZimZZZZZZZimZZZZZZZimmZmZmmimmmZmmmimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZZZmmZmimZZZmmmZimZmZZmmimZmZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimZZZmZmmimmZZZmZimZmZZmmimZmZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimZZZmmZZimZmmmmmimZmZZmmimZmZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZmmmZmimZmmZmmimZmZZmmimZmZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimmZZZmZimZmmmZZimZmZZmmimZmZmZmimZmZZZmimZZmZmmmimZmZZZmimZmZZmmmimmZZmZmimZZmmmZZimZZZmmmmimZZmmmmZimZZmmmmmimZZmmmZZimZZmmZZZimZZmZmZimZZmmZZZimZZZmmmmimZmZZZZmimZZmZmZimmmmZmZimZZmmmZZimZZmmZZmimZZmZmmmimZZmZZmmimZZmmmZmimZZZmmmmimZmZZmZimZZZmZmmimZZmmmZmimZmZZZmmimZZmmZZZimZZZmmZmimZZmZmZimZZZmZZmimZmmZmZimZmZZZmZimmZZZZZimmZZZmmimZmmZmmimZmmZmZimZZZmmZmimZmmmmmimmZZmmmimmZmZZZimZmZZmZmimZZZmmZmimZZmmZZmimZZmmZZZimZZmmmZmimZZmmmmZimZZmZmZimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimmZZmmmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmZmimmZZZZZimZmmmZmimZZmZZZZimZmmmmmimmZZmZmimZZmZZmmimZZmZZZZimZmZZmZimZZmZmmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmmimZmmZmmimZZZmmZZimZZZmmmZimZmmZmZimmZZZZZimZmZZmmimZZmmmZZimZZZmmmmimZZmmmmZimZZmmmmmimZZmmmZZimZZmmZZZimZZmZmZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZZZmmmmimZZZmmZmimZmZZmmimZZZZmmmimZmZZmZimZZZmZZmimZmmZmZimZmZZZmZimmZZZZZimmZZZmmimZmmZmmimZmmZmZimZZZmmZmimZmmmmmimZmZmmZimZmZZmZmimZmZZZmimZZZmmmZimZZZmmmmimZmZZZZZimZZZmmmmimZZmZmmZimZZmmZZmimZZmmZmZimZZZmmmmimZZmmmZZimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZZmZZZZimmZZZZZimZmZZmmimZZZZmmmimZmZmmZimZmZZZmimZZmmmZmimZZmmmmZimZZZmZmmimZZmmmmZimZZmmmmmimZZmmmZmimZmZZZmimmZZmZZimZZmZmmimZZZZmZmimZZZZmmmimZmZmmZimZmZZZmimZZZmmmmimZZmmmZZimZZmmmZZimZZmmZZmimZZmmmZZimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimmZZZmZimZZZmmZmimZmZZmmimZZZZmmmimZmZZmmmimZmZZmmimmZZmZmimZZmZZmmimZZmZZZZimZmZZmZimZZmZmmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmmimZmmZmmimZZZmmZZimZZZmmmZimZmmZmZimmZZZZZimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimmZZZmZimZmmmZZimZmZZmmimZZZZmmmimZmZZmZimZmmZZmimZZmZZmZimZZmmmmZimZZmmmmZimZZmmZmZimZZmmmZmimmZZmZZimZZZZmmZimZmmZZmimZZZZmmZimZmmZZmimZmZZZZmimZmZZZZmimZmZZZZmimZZZZmmZimZmmZZZimZZmmZmZimZZmZZmmimZZmmZZZimZZmmmmZimZZZmmmmimZZmmmZZimZZZmmmmimZZmmmZmimZZmmmmZimZZZZmmZimZmmZZZimZZZmmZmimZZmmZZmimZZmZmmmimZZZZmmZimZmmZZmimZmmZZZimZmZmZZimZmmZZmimZmZZmmimZmZZZZimZmZZZZimZZmZmmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmmimZmmZmmimZZZmmZZimZZZmmmZimZmmZmZimmZZZZZimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimmZZZmZimZmmmZZimZmZZmmimZZZZmmmimZmZZmZimZmmZZmimZZmZZmZimZZmmmmZimZZmmmmZimZZmmZmZimZZmmmZmimmZZmZZimZZZZmmZimZmmZZmimZZZZmmZimZmmZZmimZZmZZmmimZZmmZZZimZZZZmmZimZmmZZZimZZmmZmZimZZmZZmmimZZmmZZZimZZmmmmZimZZZmmmmimZZmmmZZimZZZmmmmimZZmmmZmimZZmmmmZimZZZZmmZimZmmZZZimZZZmmZmimZZmmZZmimZZmZmmmimZmmZZZimZmZmZZimZmmZZmimZmZZmmimZmZZZZimZmZZZZimZZmZmmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmmimZmmZmmimZZZmmZZimZZZmmmZimZmmZmZimmZZZZZimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimmZZZmZimZmmmZZimZmZZmmimZZZZmmmimZmZZmZimZmmZZmimZZmZZmZimZZmmmmZimZZmmmmZimZZmmZmZimZZmmmZmimmZZmZZimZZZZmmZimZmmZZmimZZZZmmZimZmmZZmimZZmmZmZimZZmZZmmimZZmmZZZimZZZZmmZimZmmZZZimZZmZZmmimZZmmmmZimZmmZZZimZmZmZZimZmmZZmimZmZZmmimZmZZmmimZZmmmZZimZZZmmmmimZZmmmmZimZZmmmmmimZZmmmZZimZZmmZZZimZZmZmZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZmmmZZimZZZmmmZimZmZZmmimZZZZmmmimZmZZmZimZZZmZZmimZmmZmZimZmZZZmZimmZZZZZimmZZZmmimZmmZmmimZmmZmZimZZZmmZmimZmmmmmimZmZmmZimZmZZmZmimZmZZZmimZZZmmmZimZZZmmmmimZmZZZZZimZZZmmmmimZZmZmmZimZZmmZZmimZZmmZmZimZZZmmmmimZZmmmZZimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZZmZZZZimmZZZZZimZmZZmmimZZZZmmmimZmZmmZimZmZZZmimZZmmmZmimZZmmmmZimZZZmZmmimZZmmmmZimZZmmmmmimZZmmmZmimZmZZZmimmZZmZZimZZmZmmimZZZZmZmimZZZZmmmimZmZmmZimZmZZZmimZZmZmmmimZZmmmZmimZZmZZZmimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZmmmZmimZZmZZZZimZmZZmmimZmZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimZmmmmmimZZZmmZmimZmZZmmimZmZZmmmimZmZZmmimmZZmZmimZZZmmZmimZZmmZZmimZZmmZZZimZZmmmZmimZZmmmmZimZZmZmZimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimmZZZmmimZZZmmZZimmZZZmmimZZZmZmmimZZZmZmmimmZZmmmimZZZmZmmimZmZZZZmimZZZmZmmimZZmZZmmimZZmmmmZimZZmZmZimZZZmZmmimZmZZZmZimZZmZZmmimZZmmZZmimZZmmmZmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZZmZZZZimZmmmmZimZmZZmmimZZZZmmmimZmZZmZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimmZZZmZimZZZmmZZimZmZZmmimZZZZmmmimZmZZmmimZmZmmZimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZZZmZmmimZmmmmmimZZZmZmmimZZZmZmmimZmmZmmimmZZmmmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimmZZZmmimZZZmmZZimmZZZmmimZZZmZmmimZZZmZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimmZZZmmimZmmmZmimZmZZmmimZZZZmmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimmZZZZmimmZZZZZimZmZZmmimZZZZmmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZmmmZZimZZZmmZmimZmZZmmimZZZZmmmimZmZmmZimZZZmZZmimZmmZmZimZmZZZmZimZmmmZZimZmmZmmimZZZmmmmimZZZmmZmimZZZmmZZimZmmmmmimmZZmmmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimmZZZmmimZZZmmZZimmZZZmmimZZZmZmmimZZZmZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimmZZZmmimZmmmZmimZmZZmmimZZZZmmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimmZZZZmimmZZZZZimZmZZmmimZZZZmmmimZZZZmZmimmmZmmmimZZZmZmmimZZmmmmZimZZmZZmZimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZmmmZZimZZmZZZZimZmZZmmimZZZZmmmimZmZZmZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZZZmZmmimmZZZmZimZmZZmmimZZZZmmmimZmZZmZimmmZmmmimZZZmZmmimZZmmmmZimZZmZZmZimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimZmmZmmimZmmmZmimZmZZmmimZZZZmmmimZmZZmZimZmZZmmimZmZmmZimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZZZmZmmimZmmmmmimZZZmZmmimZZZmZmmimZmmZmmimZmZZmmimZmZZmmimZZZZmmmimZmZmmZimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmmZimZmmZmmimZZZmmmZimZZZmmZmimmZZZmmimmZZmmmimZmZZmZmimZmZZZmimZZmZmmmimZZZmmmmimZZmmmmZimZZmZZmZimZZmmZZmimZZZmmmZimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZZZmmmmimZZZmZmmimZmZZmmimZZZZmmmimZmZmmZimZmZZZmimZZmmmmmimZZmmmZZimZZmZmmZimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZZZmmmmimZZmZZZZimZmZZmmimZZZZmmmimZmZmmZimZmZZZmimZZmmZmZimZZZmZmmimZZmmmZZimZZZmZmmimZZmZmmmimZZmmmZmimZmZZZmimmZZmZZimZmZZmZmimZmZZZmimZZmmmmmimZZmmmZZimZZmZmmZimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmmmmimZmmZmmimZZZmmZZimZZZmmmZimZmmZmZimmZZZZZimZmZZmmmimZmZmmZimZmZZZmimZZmZZmZimZZZmmmmimZZZmZmmimZZZmmmZimZZZmmmmimZZmmmZZimZZmmmZmimZmZZZmimmZZmZZimZmZZmZmimZmZZZmimZZZZZmZimZmZmmmimmmmmZZimZZZmZmmimZZmmZmZimZZmZZmmimZZZmmmZimmZmZmmimmmmZmZimmmZZmmimZmZmmmimmmZmZmimZZZmmmmimZmZZZmmimZmZZZmimmZZmZZimZmZZZmimZmZZZmimZmZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZZimZmmZmmimZZZmmmmimZZZmmZmimZZZmmZZimZmmmmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZZZmmmZimZmmmZZimZmZZmmimZZZZmmmimZmZmmZimZmZZZmimZZZZZmZimZmZmmmimmmmmZZimZZZmZmmimZZmmZmZimZZmZZmmimZZZmmmZimmZmZmmimmmmZmZimmmZZmmimZmZmmmimmmZZmZimZZmmZZmimZZmmmZmimZZmmmmZimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimmZZZmmimZZZmmmZimZmZZmmimZZZZmmmimZmZZmmmimZmZZmmmimmZZmZmimZZZmZmmimZmZZZmZimZZmZZmmimZZmmZZmimZZmmmZmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimmZZZmmimZmmZmmimZmZZmmimZZZZmmmimZmZZmZimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmmmZimZmmZmmimZZZmmmZimZZZmmZmimmZZZmmimZmZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimZmmmmZimZZZmmZZimZmZZmmimZZZZmmmimZmZZmZimZZmZZZZimZZmmmmmimZZmmZZZimZZZmmZmimZZmmmmZimZZmZZmmimZZmmZZmimZZmmZZZimZmZZmZimZZZmZZmimZmmZmZimZmZZZmZimZmmmZZimmZZZmZimZmmmmZimmZZZZmimZZZmZmmimZZZmmZmimZmZZmmimZmZZmZmimZZZmmZmimZZmmZZmimZZmmZZZimZZmmmZmimZZmmmmZimZZmZmZimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZmmmmZimZZZmZmmimZmmZmmimZmmZmZimZmmmmmimmZZmmmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimmZZmZmimZmZZZZZimZZZmZmmimZZmmmZZimZZmZmZimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZZZmmZZimZZZmmmmimmZZZZZimZZmZZZZimZZZmmmZimmZZmmmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZZimmZZZmZimZmmmmZimmZZZZmimZZZmZmmimZZZmmZmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZmmmmZimZZZmZmmimZmmZmmimZmmZmZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimmZZZmmimZmmmZmimZmZZmmimZZZZmmmimmZZmZmimZZmmmZZimZZZmmmmimZZmmmmZimZZmmmmmimZZmmmZZimZZmmZZZimZZmZmZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZmmmmZimZZZmZmmimZmmZmmimZmmZmZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZZZmmmmimZZZmmZmimZmZZmmimZZZZmmmimZmZZmZimZZZmZZmimZmmZmZimZmZZZmZimmZZZZZimmZZZmmimZmmZmmimZmmZmZimZZZmmZmimZmmmmmimZmZmmZimZmZZmZmimZmZZZmimZZZmmmZimZZZmmmmimZmZZZZZimZZZmmmmimZZmZmmZimZZmmZZmimZZmmZmZimZZZmmmmimZZmmmZZimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZmmmmZimZZZmZmmimZmmZmmimZmmZmZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZZmZZZZimmZZZZZimZmZZmmimZZZZmmmimZmZmmZimZmZZZmimZZZmmmZimZZZmmmmimZmZZZZZimZZmZZZZimZZZmmZZimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZmmmmZimZZZmZmmimZmmZmmimZmmZmZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZmmZmmimZZZmZmmimZmZZmmimZZZZmmmimZmZmmZimZmZZZmimZZZmmmZimZZZmmmmimZmZZZZZimZmZZZZmimZZmmZmZimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZmmmmZimZZZmZmmimZmmZmmimZmmZmZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimZZZmmZmimZZZmmZmimZmZZmmimZZZZmmmimZmZmmZimZmZZZmimZZmmmZmimZZmmmmZimZZZmZmmimZZmmmmZimZZmmmmmimZZmmmZmimZmZZZmimmZZmZZimZZmZmmimZZmZmmimZZZZmZmimZZZZmmmimZmZmmZimZmZZZmimZZmmZmZimZZmZmmZimZZZmZmmimZZmmmmZimZZmZZZZimZZmmZZmimZZmmmZZimZZmZmmmimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZmmmmZimZZZmZmmimZmmZmmimZmmZmZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZmmmmZimZZZmmmZimZmZZmmimZZZZmmmimZmZmmZimZmZZZmimZZmmmmZimZmZZZmmimZZmmZmZimZZZmmmmimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZZZmmZZimZZZmmmmimmZZZZZimZZmZZZZimZZZmmmZimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZmmmmZimZZZmZmmimZmmZmmimZmmZmZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimmZZZmmimZZZmmZZimZmZZmmimZZZZmmmimZmZmmZimZmZZZmimZZmmmmZimZZmZZmmimZZmmmmZimZZmZmmZimZZZmmmmimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZZZmmZZimZZZmmmmimmZZZZZimZZmZZZZimZZZmmmZimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZmmmmZimZZZmZmmimZmmZmmimZmmZmZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimmZZZmmimZmmmZmimZmZZmmimZZZZmmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZmmmmZimZZZmZmmimZmmZmmimZmmZmZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimZZZmmZmimZmmmZZimZmZZmmimZZZZmmmimZmZmmZimZmZZZmimZZmmmmmimZZmmmZZimZZmZmmZimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZZZmmZZimZZZmmmmimmZZZZZimZZmZZZZimZZZmmmZimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZmmmmZimZZZmZmmimZmmZmmimZmmZmZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimmZZZmmimZmmmZmimZmZZmmimZZZZmmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZmmmmZimZZZmZmmimZmmZmmimZmmZmZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimmZZZZZimZZZmZmmimZmZZmmimZZZZmmmimZmZmmZimZmZZZmimZZmmmmZimZZmZZmZimZZmmmmmimZZmZmmmimZZZmmZZimZZmmZZZimZZZmZmmimZZmZZmmimZZmZmmZimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZZZmmZZimZZZmmmmimmZZZZZimZZmZZZZimZZZmmmZimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZmmmmZimZZZmZmmimZmmZmmimZmmZmZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimmZZZmmimZmmmZmimZmZZmmimZZZZmmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZmmmmZimZZZmZmmimZmmZmmimZmmZmZimZmmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZmmmmmimZZmZZZZimZmZZmmimZZZZmmmimZmZZmmmimZmZZmmimmZZmZmimZmZZmmmimZmZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZZZmZmmimZmZZmmimZZZZmmmimZmZZmZimZZmZZZZimZZmmmmmimZZmmZZZimZZZmmZmimZZmmmmZimZZmZZmmimZZmmZZmimZZmmZZZimZmZZmZimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZZmZmmimZmmZmmimZZmZZZZimmZZZZZimZZmZZZZimZmZZmmimZmZZmZmimZZZmmZmimZZmmZZmimZZmmZZZimZZmmmZmimZZmmmmZimZZmZmZimZZZmZZmimZmmZmZimZmZZZmZimZmmmmmimZZZmmZZimZmmZmZimZmmZmZimZmmmZmimZmmmZZimmZZmmmimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimZZmZZZZimmZZZmmimZmmmZZimZmmmZmimZZZmmmmimmZZmZmimZZZmmZmimZZmmZZmimZZmmZZZimZZmmmZmimZZmmZZmimZZmZmmZimZZZmmmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmmimZZZmmZZimZmmZmZimZmmZmZimZmmmZmimZmmmZZimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZZZmmmmimZmmZmmimZmZZmmimZZZZmmmimZmZZmZimZmZZmZmimZmZZZmimZZZmmmZimZZZmmmmimZmZZZZZimZZZmmmmimZZmZmmZimZZmmZZmimZZmmZmZimZZZmmmmimZZmmmZZimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmmimZZZmmZZimZmmZmZimZmmZmZimZmmmZmimZmmmZZimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZZmZZZZimmZZZZZimZmZZmmimZZZZmmmimZmZmmZimZmZZZmimZZZmmmZimZZZmmmmimZmZZZZZimZZmZZZZimZZZmmZZimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmmimZZZmmZZimZmmZmZimZmmZmZimZmmmZmimZmmmZZimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZmmZmmimZZZmZmmimZmZZmmimZZZZmmmimZmZmmZimZmZZZmimZZZmmmZimZZZmmmmimZmZZZZZimZmZZZZmimZZmmZmZimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmmimZZZmmZZimZmmZmZimZmmZmZimZmmmZmimZmmmZZimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimZZZmmZmimZZZmmZmimZmZZmmimZZZZmmmimZmZmmZimZmZZZmimZZmmmZmimZZmmmmZimZZZmZmmimZZmmmmZimZZmmmmmimZZmmmZmimZmZZZmimmZZmZZimZZmZmmimZZZZmZmimZZZZmmmimZmZmmZimZmZZZmimZZmmZmZimZZmZmmZimZZZmZmmimZZmmmmZimZZmZZZZimZZmmZZmimZZmmmZZimZZmZmmmimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmmimZZZmmZZimZmmZmZimZmmZmZimZmmmZmimZmmmZZimZmZZmZimZmmZmZimZmZZZmZimZmmZmmimZmmmmZimZZZmmmZimZmZZmmimZZZZmmmimZmZmmZimZmZZZmimZZZmmmmimZZmmmZZimZZmmmZZimZZmmZZmimZZmmmZZimZmZZZmimmZZmZZimZZZmZZmimZmmZmZimZmZZZmZimZmmZmmimZmmZmZimZmmmZmimZZZmmZmimZZZmmZZimmZZZmmimZZZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmmimZZZmmZZimZmmZmZimZmmZmZimZmmmZmimZmmmZZimZmZZmZimZmmZmZimZmZZZmZimZmmmZZimZmmmmZimZmmmmZimZmZZmmimZZZZmmmimZmZZmmmimZmZZmmimmZZmZmimZmZZmmmimZmZZmmimmZZmZmimZmZZmmmimZmZZmmimmZZmZmimZmZZmmmimmZZmZmimZZmZZZZimZZmmmmmimZZmmZZZimZZZmmZmimZZmmmmZimZZmZZmmimZZmmZZmimZZmmZZZimZZmZmZimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZZmZZZZimZmmmZZimZZZmmmmimZmZZmZimZmZZmmimZmZZmZmimZZZmmZmimZZmmZZmimZZmmZZZimZZmmmZmimZZmmmmZimZZmZmZimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimmZZZZmimZZZmmZZimZmmmmmimZmmZmZimZmmmZmimmZZmmmimZZZZmZmimZmZZZmimmmmZZmimZZmZmZZimZZZmZmmimZZZmZmmimZZmmZZmimZmZZZmimZmZmmZimZmZZZmimmmmZZZimmmZZZmimmZmmmZimmmZmZZimZZmZmmZimZmZZZmimZmZmmZimZmZZZmimZmZZZZmimZZZmmmmimZZmmZZZimZZmmmmZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZmZZZZmimZZmmmZZimZZmmZZmimZZmmZZZimZZmZZZmimZmZZZmimZmZmmZimZmZZZmimZZZmmmmimZZmmmZZimZZmmZZZimZZZmZmmimZZmZmmZimZZZmZZmimZZmmmZZimZZZmmmmimZZmZZZZimZZZmmmmimZmZZZmimZmZmmZimZmZZZmimZZmZZmZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmmmmZimZZmZZmZimZZZmmmmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmmZmZimZZmmmZZimZZmmZZmimZZmZZZmimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZZmZZmZimZZZmmmmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimmmZmZZimZZmmZZZimmmmmZmimmmmmZZimZZZmZmmimZmZZZmimZmZmmZimZmZZZmimmmZZmZimmmmZZmimZZZmZmmimZZZmZmmimZZmZmmZimZmZZZmimZmZmmZimZmZZZmimmmZmmmimmmmZZmimmmZZmZimmZmZmmimmmZmmmimmmZmmmimmZmZmmimmZmmmZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmmmZZZimZmZZZmimZmZmmZimZmZZZmimZZmZZmZimmmZmmmimZZZZmZZimmZmmmmimZZZZZZZimZmZZZmimZmZmmZimZmZZZmimmmZZmmimmZmZmmimZZmmmZmimZZmmmmmimmmmmZmimZmZZZmimZmZmmZimZmZZZmimZZmZmmZimZZmZZmmimZZmmZZZimZZmZmZmimZZmmmZmimZmZZZmimZmZmmZimZmZZZmimZZZZZmZimmmZZZZimmmZZZmimZZmmZmZimZZmmZZmimZmZZZmimZmZmmZimZmZZZmimZZZmZmmimZZmmZmZimZZmZZmmimZmmZZmimZZmZZZmimZZZmmmmimZZmmmmZimZZZZZmmimmmmmmZimZZZZZZZimZmZZZmimZmZmmZimZmZZZmimZmZZmZimZmmZmmimZmZZmmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmZmZZZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmmmmZimZZZmmmZimmZZmZZimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZmZZZZimZZmZZmmimZZmmZZZimZZZmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmZmZimZZmZZmmimmmmmmZimmmZmmZimmmmmmmimZmZZZmimZmZmmZimZmZZZmimZZZmmZZimmmZZZmimZZZZmZZimZZZmmZZimZZmmmmZimZmZZZmimZmZmmZimZmZZZmimZZmZZZZimZZZmZmmimZZmmmZZimZZmZZmmimZmmZZmimZmmmmmimZmmmZmimmZZZZmimZmmZZZimZmmmZmimZmZZZmimZmZmmZimZmZZZmimZmmZZZimZZmZmZZimZZmmmZmimZZmmZZmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimZmZZmmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmZmZZZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZZmZmmimZmZZZmimZmZmmZimZmZZZmimZZZmZmmimZZmmZmZimZZmmmZmimZZZmZmmimZmZZZZZimZZZmmmmimZmmZZZimZZZmZmmimZZmmZmZimZZmmZmZimZmZZZmimZmZmmZimZmZZZmimZZmmZZmimZZmmmmZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZmZZZZZimZZZmZmmimZZmZmmZimZZmZZmmimZZZmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmZZZimZZZmZmmimZmZZZmmimZZZmZmmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZZZZmZimZmZZZmZimZZmZZmZimmmmmmZimZZmZZmZimZmZZZmimZmZmmZimZmZZZmimmZmmZZimmmmmmZimZZmZZmZimZZZZZmZimZZmmZmZimZmZZZmimZmZmmZimZmZZZmimZZmZmZmimmZmZmmimmmmZmmimmmmmZZimmZmmZZimZmZZZmimZmZmmZimZmZZZmimZmZZZmmimZZZZmZZimmmmZmZimZZZmmmmimmZmmmZimZmZZZmimZmZmmZimZmZZZmimZZmZZmZimZZmmmZZimZZZmmmmimZZmZZZZimZmZZZmimZmZmmZimZmZZZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmZmmZmimZZmZZmZimZZmmmZZimZZmmZZmimZZmZmmmimZZZmmmmimZmmZZmimZmmZmmimZmmZmZimZmZZZmimZmZmmZimZmZZZmimZmmZZZimZZZmmZmimZZmmZZmimZZmZmmmimZmmZZmimZmmZmmimZmmZmZimZmmZmZimZmmZmZimZmmZmZimZmZZZmimZmZmmZimZmZZZmimZmZZZmmimZZZmmmZimmmZmZmimZZmZZZmimmZmmmmimZmZZZmimZmZmmZimZmZZZmimZZmZmmZimZZZmmmZimZmZZmZimZmmmZZimZmZZmmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmZmZZZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmmmmZimZZZmmmZimZmZZZmimZmZmmZimZmZZZmimmmmZZZimZZZmZmmimZmZZZmmimZZZmZmmimZZmmZZZimZmmZZmimZZmZmmmimZZZmZmmimZZmZZmmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZmZmmZimmmmmZZimZZmZmZZimZZZZZZZimZZmZmZZimZmZZZmimZmZmmZimZmZZZmimmmZZZmimZZmZZmZimZmZZmZZimZmZZZmmimmZmmZmimZmZZZmimZmZmmZimZmZZZmimZZmmZmZimZZmmZZmimmZmZmmimmZmmZmimmmZmZZimZmZZZmimZmZmmZimZmZZZmimZZmmmZZimZZmmZZmimZZmZmmmimZZmZZmmimZZmmmmmimZZmZmmmimZZZZmmZimZmZZZmZimZmmmZZimZmmmZZimmZZmZmimZmZZZZZimmZZmmmimZmZZZmimZmZmmZimZmZZZmimZZmZmmZimZZmZZmmimZZZmmZmimZZZmZmmimZZmmmmZimZZmZZmmimZZmmZZmimZZmmZZZimZmmZZmimZZmmmZmimZmZZZmimZmZmmZimZmZZZmimmmZZZZimZZmZmZZimZZmZmZmimZZZmZmmimZZZZZZmimZmZZZmimZmZmmZimZmZZZmimmmZmmmimZZmmZZmimZmZZmZZimZZmZZmmimZZmZmmZimZZmZmmZimZZZmZmmimZmmZZmimZmmmmmimZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZmZZZZimZZmmmZZimZZmmZZmimZZmZmmmimmZmmZmimZZmZZmZimZZZmZmmimZZmmmZZimmZmmZmimZZmmZZmimZmZZZmimZmZmmZimZmZZZmimZZmZmmmimZZZmZmmimZZmmZmZimZmZZZmimZmZmmZimZmZZZmimZmmZZmimZmZZZmmimZZmmmmZimZmmZZZimZZmZmZZimZZmmmZmimZZmmZZmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZmmmZmimZZmmmZZimZZZmmZmimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZZmZZmZimZmZmmmimZZZmmZmimZZmZZmZimZZmZZmmimZZmZmmZimZZZmmmZimZmZZmZimZmmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmmmmimmmZZZZimZZmmmZZimZZZZZmmimmmmZZmimZmZZZmimZmZmmZimZmZZZmimZZZmmmZimmmZZmmimmZmmZmimZmZZmZZimZZZZZmZimZmZZZmimZmZmmZimZmZZZmimZZmZZmZimZZmmmmZimZZmmmmZimZZmmZmZimZZmmmZmimmZZmZZimZmmZZmimZmmZZmimZZmZZZZimZZZmZmmimZmZZZmimZmZmmZimZmZZZmimZZZZZZZimmmmmZmimZZmZZZmimZZZmZmmimZmZZZmZimZmZZZmimZmZmmZimZmZZZmimmmZmmmimZZmZmZmimZmZZZZZimZZmZZmmimZZmZmZmimZmZZZmimZmZmmZimZmZZZmimZmZZZZZimZZmZZmmimZmZZZZmimZZZmmmZimmmZmmmimZmZZZmimZmZmmZimZmZZZmimZZmmZZmimZZmZZZZimZZmZZZZimZZZmmZmZimmZZmZZmimZmmmZmZimmZmmZmmimZmZZZmimZmZmmZimZmZZZmimZZmZmmZimZZZmmmmimZmmZZZimZZmmZmZimZZmZZmZimZZmmZmZimmZmZZmimZZmZZmmimZZZmmmZimmZZmmmimZmZZZmimZmZmmZimZmZZZmimZZZmmmZimZZmmZZmimZmZZZZmimZZmmZZZimZmmZZZimZZmmZZZimZZZmmmmimZZmmmmZimZmmZZmimZZZmmmZimZmZZZmimZmZmmZimZmZZZmimZZZmmmZimZZZmmmmimZZZmmmZimZmZZZmimZmZmmZimZmZZZmimZZZmZZmimZZmmmZmimZZmmmmZimZZZmZmmimZZmmmmZimZZZmmmmimmZZmmmimZmZZmZmimZZmZZmmimZZZmZZmimZmZZZmimZmZmmZimZmZZZmimZZmmmZmimZZmmZmZimZZmZmmZimZZmZZmmimZZmmmmZimZmZZZmimZmZmmZimZmZZZmimmmZZZmimZZmZmZmimmmZmmZimmmmZmmimmmZZZmimZmZZZmimZmZmmZimZmZZZmimZZmZZmmimZZmmZZmimZZmmZZZimZmmZZmimZmZZZmZimZZmZmmmimZZmZmmZimmZZmZmimZZmmZmmimmZZmmmimZmZZZmimZmZmmZimZmZZZmimZZmZmmmimZZZmZmmimZZmmmmZimZZZmmZmimZZmZZmZimZmZZZmimZmZmmZimZmZZZmimZZmmmZmimZZmmmmZimZZmmmZZimZZmZZmmimZZmmZZZimZZmZZZmimZZmZZmmimZZmZZZZimZmZZZmmimZmZZZmimZmZmmZimZmZZZmimZZZmmmmimZmZZZmZimZZZmmmmimZZZmmZmimZmZZZmimZmZmmZimZmZZZmimZZmZmZmimmmmmZZimmmmZZZimZZZmmmmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZmmZmZimZZmZZmmimZZmmZZZimZZmmmmZimZZZmmmmimZZmmmZZimZZZmmmmimZZmmmZmimZZmmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmmZmimmmZmmmimZZmmZZZimZZmmmmmimmmmmmZimZmZZZmimZmZmmZimZmZZZmimZmmmZZimmZZZmmimZmmmmZimmZZZZZimmZZZmZimmZZZZZimmZZZmmimZmmZmmimmmmmmmimZZmZmZmimZZmmmmmimZZmZZmmimmmZmZZimmmZZZmimZmZZZmimZmZmmZimZmZZZmimZZmmZZmimZZmZmZmimZZmmmmmimZZZZmZZimmmZZmZimZmZZZmimZmZmmZimZmZZZmimZmZZZZZimZZZmmmmimZmmZZmimZZZmmmZimZZmZZmmimZZmmmZZimZZZmmmmimZZZmmZmimZZmmmmZimZmZmmmimZmZZZmimZmZmmZimZmZZZmimZZZmmmZimmmZmmmimZZZZmZZimZZZmmmmimmmZZmZimZmZZZmimZmZmmZimZmZZZmimZZmZZmZimmmmZZZimmmZmmZimZZmmZmmimmmmZZmimZmZZZmimZmZmmZimZmZZZmimZZmmZZmimmmmZZZimmZmmmZimZmZZZZZimmmmZZZimZmZZZmimZmZmmZimZmZZZmimZZmmZZmimZZmmmZZimZZmmmmZimZZmmmZmimZmZmmmimZZZmmmZimZZmmZZmimZmZZZZmimZZmmZZZimZZmZmmZimZmZZZmimZmZmmZimZmZZZmimZZmZmZmimZZZmmmmimZmZZZmmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmZZmmimZZmmZZZimZmZZZZZimZZZmZmmimZZmZmmZimZZmZZmmimZmZZZmimZmZmmZimZmZZZmimmZmZmmimmmmZmZimmmZZmmimZZZmZZmimmmZmZmimmZmmmmimZZZZZmmimZmZZZmimZmZmmZimZmZZZmimZZmZZZZimZZZmmZZimZZZmmmZimZZmmZZmimZmZZZZmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZmZZmmimZZmmmmZimmZZZZmimZZmmZZmimZmZZZZmimZZZZZmZimZmZZmmZimZmmZmZimZmZZmmZimmZZZmZimZmZZZmimZmZmmZimZmZZZmimZZZmmmZimZZZmZmmimZZmmmmZimZZZmZmmimZmZZZmimZmZmmZimZmZZZmimZZmmmZZimZmmZmmimZmmZZZimZZmmZmZimZmmZZZimZZmmmZZimZZZmZmmimZZmmZmZimZZmZZmmimZZZmmmZimZmZZZmimZmZmmZimZmZZZmimmZmZmmimZZZmZmmimZZmmZmmimmZmmmZimZmZZZmmimZmZZZmimZmZmmZimZmZZZmimZZmmZZZimZZZmmmZimZZmmZZmimZmZZZZmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZmZmZZimmmZZmmimZZZZZmmimmmmZZZimZmZZZmZimZmZZZmimZmZmmZimZmZZZmimZZmmZmZimZZmmZZmimZmZZZZmimZmZZZmimZmZmmZimZmZZZmimZZmmmZZimZZmmmZmimmmmZmZimZZmmmmmimmmmZmmimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZZmZZmmimZZmZmZmimZZZmmmZimZZmmZZmimZmZZZZmimZZmmZZZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZZmZmmimZZmmZmZimZmZZZmimZmZmmZimZmZZZmimmZmmZZimmmZZZZimmmmmZmimmmmZmmimmZmmmmimZmZZZmimZmZmmZimZmZZZmimZZZmmZmimZZZmmmmimZZmmmmZimZmZZZmmimZZmmmmmimZmZZZmimZmZmmZimZmZZZmimZZZZmmZimZmZZZmZimZmmmZZimZmmmZZimmZZZmmimZmmZmmimZZZZmmZimZmZZZmZimZmmmZZimZmmmZZimZmZZZmimZmZmmZimZmZZZmimZZZmmZmimmmmmZmimmmmZmmimZZmmmZmimZmZZmZZimZmZZZmimZmZmmZimZmZZZmimZZmmZmZimmmZmZZimmmmmmmimZZmZZmmimZmZZZmmimZmZZZmimZmZmmZimZmZZZmimZZmmZmZimmZmZZmimZZmZmmZimZZZmZmmimZZmmZZZimZZmZZZmimmZZmmmimZZmZZmmimZZZmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmmZmimmmmmZmimZZZmmZmimmmmmZmimmmZmmZimZmZZZmimZmZmmZimZmZZZmimmmZmZZimZZmZmZZimZZmmZmmimmmZZZZimZZZmmmmimZmZZZmimZmZmmZimZmZZZmimmmmZZZimmmZmZZimZZmmmZZimZZZmmmmimZZZmmmZimZmZZZmimZmZmmZimZmZZZmimZZZZZZZimmmmmmZimmmmZmZimZZZZZmZimmmmZZZimZmZZZmimZmZmmZimZmZZZmimZZZmZmmimZZmZZZmimZZZmmmmimZmZmmmimZZZmmmZimZZmmZZmimZmZZZZmimZZmmZZZimZZmZmmZimZZmmZZmimZmZZZmimZmZmmZimZmZZZmimZmmmZZimmZZZmmimZmmZmZimZmmmmmimmZZZZZimmZZmZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZZmmmmimZmZZZmZimZZmmmmZimZmZZZmimZmZmmZimZmZZZmimZmmZZZimZZmmmZZimZZZmZmmimZZmmZmZimZZmZZmmimZZZmmmZimZZZmZmmimZZmmZmZimZZmZZmmimZmmZZZimZmZZZmimZmZmmZimZmZZZmimZmZZZZZimZZmZZmmimZZZmmmZimZZZmmmmimZZmmZZmimZmZmmmimZZZmZmmimZZmmZZZimZZZmmmZimZmZmmmimZmZZZmimZmZmmZimZmZZZmimZZZmZmmimZZmmZZZimZZmZZZmimZZZmmmmimmZZmZmimZmZZZZZimmZZmmmimZZZmmZZimZmmmZmimmZZmZmimZmZZZmimZmZmmZimZmZZZmimZZZmmZmimZZmmZZmimZZmZmmmimZmZZZmimZmZmmZimZmZZZmimZmmmZmimZmmZZZimZmmZmZimZmmZZZimZmmZmZimZmmZZZimZmmZmZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmmmmZmimZZZmZmmimZmZZZmimZmZmmZimZmZZZmimZmZZZZmimZZmmZmmimZZmmZmZimmmZmmmimZZmZmmmimZmZZZmimZmZmmZimZmZZZmimZZmZmmmimmmZZZZimZZZZZZmimZmZZZmZimmmZmZZimZmmZmmimZmmmZZimmmmZZmimZmZZmZZimZmZZZZmimZmZZZmimZmZmmZimZmZZZmimZZmmZZmimZZmmZZZimZZZmmZmimZZmZmmZimZZmZZmmimZZZmmZmimZZmZmZmimZmZZZmimZmZmmZimZmZZZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmmZZmimZZmZZZZimZZmZZZZimZZZmmZmZimmZZmZZmimZmmmZmZimmZmmZmmimZmZZZmimZmZmmZimZmZZZmimZZZmmmmimZZZmZmmimZZZmmZmimZZmZZmZimZmZZZmimZmZmmZimZmZZZmimZZZZmmZimZmZZZmZimZmmmZZimZmmmZZimmZZmZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZZmmmZimZZmmZZmimZZZmmZmimZZmmmmmimZZmZmmmimZZZmmmmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZZmmmZZimZZmZZmmimZZmZmmmimZmZZZmimZmZmmZimZmZZZmimmZZZZZimZZmmmZmimmZmmZmimmmmmmmimmmZZmZimZZZmmZmimZZZZZZZimZmZZZmimZmZmmZimZmZZZmimZZmmZZmimmmmZmmimmmmZmZimmZmmmmimmmmZmZimZmZZZmimZmZmmZimZmZZZmimZZmZZmmimZZmZmmmimZZZmZmmimZZmZZZmimZZZmmmmimZmZmmmimZZZmmmZimZZmmZZmimZmZZZZmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimZmmZmZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZmZZmZimZZZZZZmimZZmZZmmimZZmmZZZimZZZmmmZimZZmmZZmimZmZZZZmimZZmmmZmimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZZZmmmmimZmZZZmZimZZmmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmmmmimmmmZmZimZmZZZmZimZZmZmmmimmmmmZZimZmZZZmimZmZmmZimZmZZZmimZZmmmZZimZZmZmmmimZmZmmmimZZmmmmmimZZmmmZZimZZmZmmZimZZZmmmmimZZmmZZZimZZZmmZmimZZmmZZmimZmZZZmimZmZmmZimZmZZZmimZZmZmmmimZmmZZmimZZZmZmmimZZmmZmZimZZmZZmmimZmmZZmimmZmZZmimZZmmmmmimZZmmmZZimZZmZmmZimZmZZZmimZmZmmZimZmZZZmimmmZZZmimZZmmmmmimZZZmmZZimmmmZZmimmmZZmmimZmZZZmimZmZmmZimZmZZZmimZZmZZmmimZZZmmmZimmmZZZZimZZZZZZmimZZZmmZmimZmZZZmimZmZmmZimZmZZZmimZZZmmZZimZZZZZmZimmmZZmZimmmmZZZimmmZZmmimZmZZZmimZmZmmZimZmZZZmimZmZZmZimZmmmmZimZmZZmmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmZmZZZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZZmZmmimZmZZZmimZmZmmZimZmZZZmimmmZmmZimZZZZZZmimZmZZmZZimmmZmmmimmmZmZmimZmZZZmimZmZmmZimZmZZZmimmmmmZmimZmZZmZZimZZmmZmZimZZmmZmmimZZZmmZZimZmZZZmimZmZmmZimZmZZZmimZZmZZmmimZZZmmmZimZZZmmmmimZZmmZZmimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZZmZZmmimZZmmmmZimZZmZmmZimZZZmmmmimZmZZZmimZmZmmZimZmZZZmimZZmmZmZimZZmmmmmimZZmmmmZimmZmmmZimZZZmZmmimZZmmmmZimZZZmZmmimZZZZmmZimZmZZZmZimZmmmZZimZmmmZZimZmZZmmimZmmZZZimZmZZZmimZmZmmZimZmZZZmimmZmmZZimZZmmZmmimmmZmZmimmmZmmZimZZmmmZmimZmZZZmimZmZmmZimZmZZZmimZZmZmZmimZZmZmmZimZZmZmmmimZZmmZZZimZZmmZZmimZZmmZmZimZZmmZmmimZZmmmZZimZZmmmZmimZZmmmmZimZmZZZmimZmZmmZimZmZZZmimZZmZZZmimZZZmmZZimmZmZmmimZZmZZmZimZZZZZmZimZmZZZmimZmZmmZimZmZZZmimZmmZmZimZmmZZZimmZZZmmimZmZmmZimZZmZZmmimZZmZmmmimZZZmZmmimZZmZZZmimZZZmmmmimZmmZZmimZmZZZmimZmZmmZimZmZZZmimmmmZZZimZZZmZmmimZmZZZmmimZZZmZmmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZmmZmmimZZmmZZZimmmZZZmimmmZmmZimZZmmZmmimZmZZZmimZmZmmZimZmZZZmimZZmmmZZimZZZmmmmimZZZmmmZimZZmmmmmimZZZmmZmimZZZmmmmimZmZZZmimZmZmmZimZmZZZmimZZmZmmZimmmZZmmimZZZmmZZimmmZmZmimmZmmZZimZmZZZmimZmZmmZimZmZZZmimmmZmZZimZZZZZZmimZZmZZmZimZmZZmZZimZZmZmZmimZmZZZmimZmZmmZimZmZZZmimZmZZZZmimZmmZZZimZZmZZZZimZZZmZmmimZZZmmZmimZZZmmmmimZZZmmZZimZZmmZZmimZZmmZZmimZZmZmZmimZmZZZmimZmZmmZimZmZZZmimZZmZZmmimZZZZZZZimZZZmmmmimmZmmZZimZZmmmZmimZmZZZmimZmZmmZimZmZZZmimmZmmZmimmmZZmZimZZZZZmZimZZmZmZZimmmZmmZimZmZZZmimZmZmmZimZmZZZmimmmZmmmimZZmZZmmimZZmmmZmimZZmmmZmimZZmZZmmimZZmmZZZimZZmZZZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmZmZmimZZZmmmmimZmZZZmimZmZmmZimZmZZZmimZZZmmZmimZZZmZmmimZZmmmmZimZZZmmZmimZZmZZmZimZmZZZmimZmZmmZimZmZZZmimZZZmmmZimZZmZZmmimZZZmZmmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmZmZZZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmZZZZimZZmZZmmimZZmZZZmimZZmmmmmimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZmZZZZmimZZmZZmmimZZmmmmZimZZmmmmZimZZZmmmmimZZmmmZZimZZZmmmZimZZmmZZmimZmZZZZmimZmZZZmimZmZmmZimZmZZZmimZZmZZmmimmmZmZZimmZmmmZimZZmmmmmimmmZZZZimZmZZZmimZmZmmZimZmZZZmimZZmZmmZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmmmmZimZZmmZZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmZmmZimZZZmZmmimZZmmmmmimZZmmZZZimZZZmmZmimZmZZZmimZmZmmZimZmZZZmimZZmmZZmimZZZmZmmimZZZmmmZimZZZmmmmimZZmmmZZimZmmZmmimZmmZZZimZZmmZmZimZmmZZZimZZmmmZZimZmZZZmimZmZmmZimZmZZZmimZmmZmZimmZZZmmimZmmmmmimmZZZmmimmZZZZmimZmmmmZimmZZZmmimmZZZZmimZmmZmmimZmmmZZimZmZZZmimZmZmmZimZmZZZmimZZZmmmmimmZmmZmimZZZmmmZimZZmZmZmimZZZZZZmimZmZZZmimZmZmmZimZmZZZmimZZZZZmmimZmZZZZZimZZmZZmmimmmZZmmimZZmZmZZimZmZZZmimZmZmmZimZmZZZmimZZmmZZZimZZmZmZmimmmmZZmimmmZZZmimmmZZZZimZmZZZmimZmZmmZimZmZZZmimZZmZZmmimZmmZZZimZZZmmZmimZZmmZZmimZZmZmmmimZmmZZmimZZZmZmmimZZmmZmZimZZmZZmmimZmmZZmimZmZZZmimZmZmmZimZmZZZmimZZmZmZmimZZZmmmmimZmZZZmmimZZZZZZZimZZmZZmmimZZZmmmZimZZZmmmmimZZmmZZmimZmZZZmimZmZmmZimZmZZZmimmmZZZmimmZmmmZimmmmmZZimmmmmZmimZZmZmZZimZmZZZmimZmZmmZimZmZZZmimZZmmmZmimZZmZmmZimZZmZZmmimZZZmmZmimZZZmmmmimZmZZZmimZmZmmZimZmZZZmimmmZZZmimZZmmmmmimZZmmZmZimmmmZmmimmmZmZZimZmZZZmimZmZmmZimZmZZZmimZZZZZmmimZmZZZmZimmmmmmZimmmmmZZimZZZZZZmimZmZZZmimZmZmmZimZmZZZmimZmZZZZmimZmZZZZZimZZmZmZZimmmmmmmimZZmZZZmimZmZZZmimZmZmmZimZmZZZmimZZmZmmmimZmmZZmimZZmZmmmimZZZmmmmimZZZmmmZimZZmZZmmimZZZmZmmimZmmZZmimZZmZZmZimZZmmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmZZZimZZZmmmZimZZmmZZmimZmZZZZmimZZmmZZZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZZmZmmimZZmmZmZimZZmZZmmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZmZZZmimZmZmmZimZmZZZmimZZZmmmZimZZmZZmmimZmZZZZZimZmmZZZimZZZmmmZimZZmmZZmimZmZZZZmimZZmmZZZimZZmZmmZimZZmmZZmimZmZZZmimZmZmmZimZmZZZmimZZZmmmZimZZZmmmmimZZmmZZmimZmZmmmimZZZmZmmimZZmmZZZimZZZmmmZimZmZmmmimZZmmmZmimZZmZZmZimZmZZZmimZmZmmZimZmZZZmimZZmZZZmimZZZmmmmimZZmmmmZimmZmmmmimZZmZmmZimZZZmmmmimZZmZmmmimZZZmmmmimZZmmZZZimZZmmmmZimZmZZZmimZmZmmZimZmZZZmimmmZmZZimZZZZZZZimmmZZmmimmmmmZmimZZmmZmmimZmZZZmimZmZmmZimZmZZZmimmmmmmZimmmZZmZimmZmmmZimZZZZZmmimZZmZZZmimZmZZZmimZmZmmZimZmZZZmimZZmmZmZimZmmmZmimmZZZZmimZmZZmZZimZZmZmZZimZZmZZZmimZmZZmZZimZZmZZZmimZmZZZZZimZmmZmmimZmZZZmimZmZmmZimZmZZZmimZZZmmmmimmZZZmZimZZmmmmZimZmmmZZimZmZZZmZimZZZmmmZimmZZZmZimmZmZmmimZmmmZZimZmZZZZmimZmZZZmimZmZmmZimZmZZZmimZZmZZmmimZZmmZZZimZZZmmZmimZZmZmmZimZZmmmmmimZZZmmmZimZZZmmmmimZZmmmZmimZmZZZmimZmZmmZimZmZZZmimZZmZmmZimZmZZZZZimmmmmmZimmmmmZZimmmmZmZimZmZZZmimZmZmmZimZmZZZmimZmZZZmZimZZmZmZmimZZmmmZZimmmZmZZimmZmZmmimZmZZZmimZmZmmZimZmZZZmimZZmmZmZimZZZZZZmimZZmmmmZimZZmmmmmimZZmZZZmimZmZZZmimZmZmmZimZmZZZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmmmZZZimmmmmmZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZmmZmmimZmmZmZimZmmZZZimZmmZmZimmZZmZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZmZZZmimZmZmmZimZmZZZmimZZmZZZmimZZmmZZmimZZmmZZmimZZmZZZmimZZmZmmZimZZZmmmmimZmZmmmimZZZmmmZimZZmmmZZimZZmZZmmimZmZZZmimZmZmmZimZmZZZmimZZmZZmZimZZmmZZmimZmZZmZZimmmmZmmimZZZZmZZimZmZZZmimZmZmmZimZmZZZmimZmZZZZmimZmmZZZimZZmZZZmimZZmZZmmimZZmmmmZimZZmZZmZimZZmmmmmimZZZmmZZimZZmmmmmimZZmmmZmimZmZZZmimZmZmmZimZmZZZmimZZmZmmZimZZZmmmmimZZmmZZZimZZmZZZmimZZmmmmZimZZmZZmZimZmZZZmimZmZmmZimZmZZZmimmmmZmmimZZZmZmmimZZmZZZmimmmZmmmimmmZZZZimZmZZZmimZmZmmZimZmZZZmimZZmZZZZimZZZmmZmimmmZZmmimZZZZZmZimmmmZZmimZmZZZmimZmZmmZimZmZZZmimZZmZZZZimZZmZmmZimZZmmZZmimZZmmZZmimZZmmmZZimZmZZZmimZmZmmZimZmZZZmimZZmmZmZimZmZZZZZimZZZZZZZimmmZmZZimZmZZZZmimZmZZZmimZmZmmZimZmZZZmimZZmZmmZimZZmmZZmimZZZmZmmimZZZmmmZimZZZmmmmimZZmmmZZimZmmZZZimZZmmZmZimZmmZZZimZZmmmZZimZmZZZmimZmZmmZimZmZZZmimZZZmZmmimZmZZZmmimZZZmZmmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZmZZmZimZZmmmZZimmmZmmmimZZZZZmmimZmZZZZmimZmZZZmimZmZmmZimZmZZZmimZZmZmmmimZZZmmmZimZZmZmmmimmmmmmmimZZmmmZZimZmZZZmimZmZmmZimZmZZZmimZZmZZZmimmmmmmZimZZmmmZmimmmmZmZimZmZZZmmimZmZZZmimZmZmmZimZmZZZmimmmmZmZimZZZZZmZimZZmZZmmimmZmZmmimZmZZZZZimZmZZZmimZmZmmZimZmZZZmimZmmZmmimmZZZZZimZmmmZmimZmmZmmimZmmmmmimmZZZZmimZmmZmmimmmZZmZimZZmmZmZimZZZmmmmimZZmZmmmimZmZZZmZimZZmZmZmimZmZZZmimZmZmmZimZmZZZmimZmmZmmimZmmmZmimZmmZmZimZmmZmZimmZZZZmimZmmZmmimmZZZmZimZZmmZZZimmZmmZmimmmmmmZimZZmZZmZimZZZZZZZimmmZmZZimZmZZZmimZmZmmZimZmZZZmimZZmZZmZimZZmmmmZimZZmmmmZimZZmmZmZimZZmmmZmimmZZmZZimZmmZZmimZmmZZmimZZmmmmZimZmZZZZmimZmZZZmimZmZmmZimZmZZZmimmmmmmmimZZZZZmmimZmZZmZZimZZZZZmmimZZmZZZZimZmZZZmimZmZmmZimZmZZZmimmmZZmZimmmmmZZimmmmZmmimZZmZmZmimZmZZZmmimZmZZZmimZmZmmZimZmZZZmimmmZZZmimmZmZmmimZmmZmmimZmmZZZimZmmmZZimZmmZZZimZmmZmmimZmmZmZimZmmmZZimZmmmZZimZmZZZmimZmZmmZimZmZZZmimmZZZmmimZmmmZmimmZZZZZimZmmmZZimZmmmZZimZmmZmZimZmmZmZimmZZmZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmZZZmimZmZZZmimZmZmmZimZmZZZmimmZmZmmimZZZZZmmimmZmZmmimmmmZZZimZmZZZmimZmZmmZimZmZZZmimmmZmmZimZZmZZmmimZZmmZZZimZZmZmZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmmmmmmimZZmmmZZimZZmZmmZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZZmmZmimZZZmmmmimZZZmmZZimZZmmZZmimZZmmZZmimZZmZmZmimZmZmmmimZZmZmmmimZZZmmmmimZZZmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmmZmimZZZZZmZimmmZmZZimmmmmmZimZZZZZZmimZmZZZmimZmZmmZimZmZZZmimZmZZZZZimmmZmmZimZZmZZZZimmmZmZZimmmZZZZimZmZZZmimZmZmmZimZmZZZmimZmZZZZZimmZmmmZimZmZZZmmimZZZmmmmimZZZZZmmimZmZZZmimZmZmmZimZmZZZmimmmZZmZimmmmmmZimmmZmmmimmmZmmZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmZZmmmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZZZmmZimZmZZZmZimZmmmZZimZmmmZZimZmZZZmimZmZmmZimZmZZZmimZZmZZZmimZZZmmmZimZZmmmZZimZZmZZmmimZmZZZZZimZZZmmmmimZmZmmmimZZmZmmZimZZmZZmmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimmZmZmmimmmmZZZimZmZmmmimZmmmmZimZmmZmZimZmmmmZimZmmZZmimmmZmmmimZZmmmZZimZmZmmmimZmZZZmimZmZmmZimZmZZZmimZZmZZmmimZZmZmmmimZZmZZZmimZmZZZmimZmZmmZimZmZZZmimZZmZZmmimZZmmZZZimZZZmmmZimZZZmmmmimZmZZZmZimmmmZZmimZZmZZZZimZmZZZmimZmZmmZimZmZZZmimZZmmZZZimZZZmmmmimZZmmmZZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmZZZZimZZmmZZmimZZmmmZZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmZmZmimZZZmmmmimZmZZZmimZmZmmZimZmZZZmimZmmZmmimZmmZmmimmZZZZZimZmmmZZimZmmmZZimmZZZZmimmZZZZZimZmmZmZimZZmZZZmimmmZZZmimmmmmZZimZZZZZmZimZZZmmZmimmmmmZmimZmZZZmimZmZmmZimZmZZZmimZZZmmZZimZZmmmmZimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimmmmmZZimZZmmmZZimmmZZmmimZmZZZZmimmZmmZZimZmZZZmimZmZmmZimZmZZZmimZZmZZZmimZZmZZZmimZZmZZZmimZmZZmZZimmmmZmmimZmZZZmimZmZmmZimZmZZZmimZmmZmZimZmmZmmimZmmmZZimZmmmZmimZmmmmZimZmmmmmimmZZZZZimmZZZZmimmZZZmZimmZZZmmimZmZZZmimZmZmmZimZmZZZmimZZmmZmmimmmmZZmimZZZmmmmimmZmZmmimmmZZmmimZmZZZmimZmZmmZimZmZZZmimZZZmmmmimZZmmmZZimZZZmmZmimZZmmZZmimZZmmZZZimZZmmmmZimZZZmmmmimZZmmZZZimZZmmmmZimZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZZmZmmimZZmmmZZimZZmmmmZimZZmZZmmimZZZmmZmimZZmZmmZimZZZmmmmimZmmZZZimZZmZmmmimZZZmmmmimZmZZZmimZmZmmZimZmZZZmimmmZmmmimZZmmZZmimZZmZZmZimZZZmZmmimZZmZmmmimZZmZmmmimZZZmZmmimZZZmmmZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmmmZZZimZmZZZmimZmZmmZimZmZZZmimZZmmZmmimZZmZZmZimZZmmmZZimmmZmmmimZZZmmZZimZmZZZmimZmZmmZimZmZZZmimmZmmmmimZZmZZmmimZZmmZZZimmmZmmZimZZmZmZZimZmZZZmimZmZmmZimZmZZZmimZZZmmmZimZZZmmmmimZZmmZZmimZmZmmmimZZZmZmmimZZmmZZZimZZZmmmZimZmZmmmimZZmZZmmimZZmZmmmimZmZZZmimZmZmmZimZmZZZmimmmZmZZimZZmZmmZimmmZmZZimZmZZZmZimZZmZmmZimZmZZZmimZmZmmZimZmZZZmimZZZmZmmimZZZmmmZimZmZmmmimZZmZZmmimZZmmmmZimZZZmmmmimZZmZmmmimZZmmmZmimZZZmZZmimZZZmZZmimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZZZmmmmimZmZZZmZimZZmmmmZimZmmZZmimZZmZZmZimZZmmmmZimZZmZmmmimZZmZmmZimZmZmmZimZmZZZmimZmZmmZimZmZZZmimZmmmmZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmmmmZmimZZZmZmmimZZmZZZZimZZZmZmmimZZmmmZZimZZmZZmmimZmmZZmimZmmmmmimZmZZZmimZmZmmZimZmZZZmimZmZZZmmimZZmmmmZimZZZmmmZimZZmmZZmimZmZZZZmimZZmmZZZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZZmZmmimZZmmZmZimZZmZZmmimZmZZZmimZmZmmZimZmZZZmimmmmZmZimmmmZZmimmmmmZmimmmmmmZimZmZZZmimZmZmmZimZmZZZmimZZmZmZmimmZmZmmimmZmmmZimZZmmZmmimZZZZZZZimZmZZZmimZmZmmZimZmZZZmimZZmZmmZimZZmZZmmimZZmmZZZimZZmZmZmimZmZZZmimZmZmmZimZmZZZmimZZZmmZmimZZmmZZmimZZmmZZZimZZmmmmZimZZZmZmmimZZZmmZmimZZmmmmZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmmZZmimZmZZZZmimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZZmZZmZimZZmmmmmimZZmZmmmimZZZmmZZimZZmmZZZimZZZmZmmimZZmZZmmimZZmZmmZimZmZZZmimZmZmmZimZmZZZmimZZmmmZZimZZmZZmmimZmZZZZZimZZZmmmmimZmZmmmimZZmZmmZimZZmZZmmimZZmmZZZimZZmZmZmimZmZmmmimZmZZZmimZmZmmZimZmZZZmimZZZZZZmimmmmZZZimZZmmZZmimmmZmmZimZZmZZZmimZmZZZmimZmZmmZimZmZZZmimZZmmmmmimZZmmmmZimZZmmmmmimZZZmmZZimZZZmmmmimZmZmmmimZmZZZZZimZZmZZmmimZZZmmmZimZZZmmmmimZmZZZmimZmZmmZimZmZZZmimZZmmZZmimZmZmmmimZZZmZmmimZZmmZZZimZZZmmmZimZmZmmmimZZmmmZmimZZmZZmZimZZmmZZmimZZmmmZZimZmZZZmimZmZmmZimZmZZZmimmmmmZmimZZZZZZmimmZmZmmimZZZmZmmimmZmmZZimZmZZZmimZmZmmZimZmZZZmimZmZZZZmimZZZZZmZimmmmmZZimmmmmZmimmmmmZZimZmZZZmimZmZmmZimZmZZZmimZZZmmmmimZZmmZZmimmmZZmmimmmmmmZimZmZZZmmimZmZZZmimZmZmmZimZmZZZmimZZZmmZmimmZmmZZimmmZmmZimZZZmmmZimZZmZZZZimZmZZZmimZmZmmZimZmZZZmimZZZmmmZimZZZmmmmimZZmmmZZimZmmZmmimZmmZZZimZZmmZmZimZmmZZZimZZmmmZZimZZZmZmmimZZmmZmZimZmZZZmimZmZmmZimZmZZZmimmmZmmmimmmmmmZimZZmZZmZimZZZmZmmimZZmZZmZimZmZZZmimZmZmmZimZmZZZmimZZmmmmmimZZmmmZZimZZmZmmZimZmZZZmimZmZmmZimZmZZZmimZZmmZmZimZZZZZZZimZZmmZZZimZZZZZZZimZZmZZZmimZmZZZmimZmZmmZimZmZZZmimZZmmmZZimZZZmmmmimZZmZmmmimZZmmZZmimZmZZZZZimZZZmmmmimZmZZmZimZmZZmmimmZZmZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimmmmZZZimmmZZmmimmmmmZZimZmZZmZZimZmZZZmimZmZmmZimZmZZZmimZZmmmmmimZmZZZZZimZmZZZZmimZmZZZmZimZmZZZmmimZmZZmZZimmZmZmmimmZmmZZimmZmmZmimmZmmmZimZmZZZmimZmZmmZimZmZZZmimZZmZmZZimmZmmmZimmmmZmZimZZZmmmZimmmZZZZimZmZZZmimZmZmmZimZmZZZmimZZZZmZZimmmmZZZimZmZZZZmimZZmmmmmimmmmZmZimZmZZZmimZmZmmZimZmZZZmimZZZmmZmimZZmmZZmimZZmZmmmimZmmZZmimmmZmmmimmmmmZZimZmZmmmimmmmZZZimmZmZmmimZZZZZmmimZmZZZmimZmZmmZimZmZZZmimZZZmZmmimZZZmmmZimZZZmmmmimZZmmmZZimZmmZZZimZZmmZmZimZmmZZZimZZmmmZZimZZZmZmmimZZmmZmZimZmZZZmimZmZmmZimZmZZZmimmmZmZmimZZmZZmmimZZmmmmZimZmmZZmimZmmmmmimZmmmZmimmZZZZmimZmmZZZimZmmmZmimmZZZZZimZmZZZmimZmZmmZimZmZZZmimZZmmZZZimZmmZZmimZmZZZmZimZmZmmmimZmZZZZmimZmZZZZmimZmZZZZmimZmZmmmimZZmZZZZimZZmmZZmimZmZZZmimZmZmmZimZmZZZmimZmmmmmimmZZZmmimZmmmZmimmZZZmZimZmmmmZimmZZZZmimZZZmmmmimZZmZZZZimmZmmZmimZZmmZmmimmmmZZmimZZZmZmmimZmZZZmimZmZmmZimZmZZZmimZZmZmZmimZZZmmmmimZmZZZmmimZmZZZmimZmZmmZimZmZZZmimZZZZmZZimmZmmmmimmmZmZZimZZZmmZZimZZZZmZZimZmZZZmimZmZmmZimZmZZZmimZZmZmmZimZZmmZZmimZZZmZmmimZZZmmmZimZmZZZmimZmZmmZimZmZZZmimZmmZZZimZmmZmZimZmmZZZimZmmmmZimZmmmmZimmZZZZmimZmmmZZimZmmZZZimZmmZmmimZmmmZZimZmZZZmimZmZmmZimZmZZZmimZZmZZmZimZZmmmmZimZZmmmmZimZZmmZmZimZZmmmZmimmZZmZZimZmmZZmimZmmZZmimZZmZZZmimZZZmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmmmimZmmmZmimmZmmmZimmZZmZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZZmZZmimZZmZZZmimZZmZZmmimZZZmmmZimmZZmmmimZmZZZmimZmZmmZimZmZZZmimZZmmZZmimZZmZmmmimZZmmZmZimZZmmZZmimZZmmZZZimZZZmmmmimZZmmZZZimZZmmmmZimZmZZmZimZZZmmmmimZmZZZmimZmZmmZimZmZZZmimZmmZZZimZZZmmZmimZZmmZZmimZZmZmmmimZmmZZmimZZmmZmZimZZmmmZZimZZmmZZmimZZmZZZZimZZmZZmmimZmZZZmimZmZmmZimZmZZZmimZZmZmmZimZmZmmZimZZZmZmmimZZmmZmZimZZmmZmZimZZmZmmZimZZmZZmmimZZZmmZmimZZZmZmmimZZmmmmZimZmZZZmimZmZmmZimZmZZZmimZZZmmZmimmmmmmZimZZZmmmZimZmZZZmZimZZZmmmmimZmZZZmimZmZmmZimZmZZZmimZZmmZmZimZZmmmmmimZZmmmZmimZZmZZmZimZmZZZmimZmZmmZimZmZZZmimZZZmZmmimmmZZZZimmmZZZZimZZmZZZZimZZmZZmZimZmZZZmimZmZmmZimZmZZZmimZZZmZmmimZZmmZmZimZZmZZmmimZZZmmmZimZZZmZmmimZZmmZmZimZZmZZmmimZmmZZZimZZZmmZmimZZmmZZmimZmZZZmimZmZmmZimZmZZZmimZZmZmZZimZZmmmmmimZZmZZZmimmmZmmmimmZmZmmimZmZZZmimZmZmmZimZmZZZmimZZmmZZmimZZmZmZmimZZmZZmmimZZZmmmmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmmmmZimZZmmZZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmZmmZimZZZmZmmimZmZZZmimZmZmmZimZmZZZmimZZmZmmZimmmZZZmimmZmmmmimZZmZmmmimZZmmmmZimZmZZZmimZmZmmZimZmZZZmimZZmZZmmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmmZZmimZZmZZZZimZZmZZZZimZZZmmZmZimmZZmZZmimZmmmZmZimmZmmZmmimZmZZZmimZmZmmZimZmZZZmimZmmZmmimZmmZmZimZmmZmmimZmmmmZimmZZZmZimmZZZmmimZmmmmmimZmmmZmimmZZZZmimmZZZmmimZmZZZmimZmZmmZimZmZZZmimZmmZZmimZZmmZmZimZZmZZmmimZZmmZZZimZZmmmmZimZZZmZmmimZZmmmZZimZZZmmmmimZZmmmZmimZZmmmmZimZmZZZmimZmZmmZimZmZZZmimZmmZZmimZZmZZmmimZZZmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZZZmmZZimZZmmZZmimZZZmmmZimZmZZZmmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmZmZZZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmmmmZimZZmmmZZimZmZZZmimZmZmmZimZmZZZmimZZmZZmmimZZmZmZmimZZZmmmmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmmZZZmimZZZmmmmimZZZmmZmimZZmZmZmimZZmmZZmimZmZZmmimZmZZZmimZmZmmZimZmZZZmimZZmZZmZimZZmmmmZimZZmmmmZimZZmmZmZimZZmmmZmimmZZmZZimZmmZZmimZmmZZmimZmZZZZmimZmZZZZmimZmZZZmimZmZmmZimZmZZZmimmmZZZmimmZmmmZimmmZmmZimZZmZZmmimZZmmZZZimZZmZmZmimZmZZZmimZmZmmZimZmZZZmimZmmZZmimZmZZZZmimZZZmmmmimZZZmmZZimZZmmZmZimZmZmmZimZZmZZmmimZZmZmmmimZZZmZmmimZZmZZZmimZmZZZmimZmZmmZimZmZZZmimmmmmmZimZmZZmZZimmmZZmZimZZZmZmmimZmZZZZZimZmZZZmimZmZmmZimZmZZZmimZZZmZZmimZZmZZZmimZZZmZmmimmZZmmmimmmZZZmimmZmZmmimZmmZmmimZmmZZZimZmmmZZimZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZmmmZZimZZZmmmmimZZmmZmmimZZmmmmmimZZZmmmmimZZmmmZmimZZmmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZmmZZZimZZmZZZmimZZZmmmmimZZmmmmZimmZmmmmimZZmZmmZimZZZmmmmimZZmZmmmimZZZmmmmimZmZZZmimZmZmmZimZmZZZmimZZmmZmmimmZZmmmimZmmZmZimZmmZZZimmZZZmmimZmZZZmimZmZmmZimZmZZZmimZZmZmmZimmZZmZZimZmmZmZimZmZZmmmimmZZmZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZZmZZmimZZmZZZmimZZZmZmmimZZmmmmZimZmZZZmimZmZmmZimZmZZZmimZmZZZmmimZZmmmmmimmZmZmmimmmZmmZimZZmmZZmimZmZZZmimZmZmmZimZmZZZmimmmZmmmimmmZZZmimZZZmZmmimZZmmZZZimmmZZmmimZmZZZmimZmZmmZimZmZZZmimZZZmmmmimZZmZZZmimZZmmmmZimZZmZmZmimmZmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmZZZimZmmZZmimZZmZmZZimZZmmmZmimZZmmZZmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZZZmmZimZmZZZmZimZmmmZZimZmmmZZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmmmZZZimZZmmZZmimZZmmmmZimmZZmZmimmZmZmmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmZmmZZimZZmmmZZimZmZZZmimZmZmmZimZmZZZmimZZmmZZmimZZmmZZZimZZZZmmZimZmZZZmZimZmmmZZimZmmmZZimZmZZmmimZmmZZZimZZmZZmmimZZmmZZZimZZmmZZZimZZZmmmmimZZmmmZZimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZmZZZmmimZZmmZmZimZZZmmmmimZmZZZmimZmZmmZimZmZZZmimZZmZmmmimmmmmZZimZZmmZmZimZZmmmZmimmmmmmmimZmZZZmimZmZmmZimZmZZZmimmZmmmZimZZZZZZZimZZZZZZZimmZmZmmimmmZmmmimZmZZZmimZmZmmZimZmZZZmimZZmZZmZimZZmZmZZimZZmZZZZimZmZZZZZimZZmmZZmimZmZZZmimZmZmmZimZmZZZmimZZmZmZZimmmmmmmimZZmZZZZimZmZZZZmimZZmmmZZimZmZZZmimZmZmmZimZmZZZmimmZZZZZimZmmmmZimZmmmmZimZmmmmmimZmmZmZimmZZZmmimmZZZZZimZZZZmZZimZZmmZmZimmZmZmmimZZmmZmmimZZmmmZZimZmZZZmmimZmZZZmimZmZmmZimZmZZZmimZZZmmZZimZZmmmmmimZZmmmmZimZZmmmmZimZZmmZZmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimmZZmZZimZZmmZZZimZZmmmmZimZZmZZmZimZmZmmmimZZZmmZmimZZmZZmZimZZmZZmmimZZmZmmZimZZZmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmZZZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZZmZmmimZZmmZmZimZZmZZmmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmmZZmimZZmZZZZimZZmZZZZimZZZmmZmZimmZZmZZmimZmmmZmZimmZmmZmmimZmZZZmimZmZmmZimZmZZZmimZZZmZmmimZZmmZmZimZZmZZmmimZmmZZZimZZZmmZmimZZmmZZmimZZmZmmmimZmZZZmimZmZmmZimZmZZZmimZZmZZZZimZZZmmZZimZZZmmmZimZZmmZZmimZmZZZZmimZZmmZZZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZZmZmmimZZmmZmZimZZmZZmmimZmZZZmimZmZmmZimZmZZZmimZZmZZZmimZZmmZZmimZZmmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmZmmimZmZZZZmimZZmZmmZimmmmmZZimZZmZmZZimZmZZZmimZmZmmZimZmZZZmimmmmZmmimZZmmmmZimZZmZZZmimZZZmZmmimZZmZmZmimZmZZZmimZmZmmZimZmZZZmimZmmmmZimmZZZmmimmZZZZmimZmmZmmimZmmmZZimZmZZZmimZmZmmZimZmZZZmimZZmZZmmimZZZmZmmimZmZmmmimZZZmZmmimZZmmZmZimZZmZZmmimZmmZZZimZZmmZmZimZmmZZZimZZmmmZZimZmZZZmimZmZmmZimZmZZZmimZZmZZmZimZZmmmmZimZZmmmmZimZZmmZmZimZZmmmZmimmZZmZZimZmmZZmimZmmZZmimZZmmZmZimZZmZZmmimZmZZZmimZmZmmZimZmZZZmimZmmZZmimZZZmZmmimZZZmmZmimZZmmmmZimZZmZZmmimZZmmZZmimZZmmZZZimZmmZZZimZZmmZmZimZZmZZmZimZmZZZmimZmZmmZimZmZZZmimZZZmmZmimZZZmZmmimZZmZZZZimZZmmZZZimZZmmZmmimZmZZZmimZmZmmZimZmZZZmimZZmZmmZimmZmZmmimZmZZZmmimmZmmmZimmmZZZZimZmZZZmimZmZmmZimZmZZZmimZmmZmmimmZZZZZimZmmZmmimZmmmmmimZmmmZZimmZZZmmimmZZZmZimZmmmmZimZmmmmZimmZZZmmimZmZZZmimZmZmmZimZmZZZmimmmZmmmimmmZmmmimmmmZZZimZZmZmZZimZZmZZmZimZmZZZmimZmZmmZimZmZZZmimZZmmZmZimZZmZZmmimZZmmZZZimZZmmmmZimZZZmZmmimZZmmmZZimZZZmmmmimZZmmmZmimZZmmmmZimZmZZZmimZmZmmZimZmZZZmimmmZmZmimZZmZmZZimZZmmmZmimZZZZZmmimmmZZZmimZmZZZmimZmZmmZimZmZZZmimZZZmmmZimZZmZZmZimmZmmmmimZZmZZZZimmmZZmZimZmZZZmimZmZmmZimZmZZZmimZZZZZZmimmmZZZZimZZmmmZmimmmZZZmimZZZZmZZimZmZZZmimZmZmmZimZmZZZmimZZmmmZZimZZZmmmmimZZmmmZZimmZZmmmimZZmmZmZimZZZmZmmimZZZmmmZimZZmZZmZimZZmmmmmimmmmmmmimZmZZZmimZmZmmZimZmZZZmimZmmZZZimZmmZmmimmZZZZZimZmmmmmimmZZZmZimmZZZZZimmZZZZZimmZZZmmimZmmmmZimZmmZmZimZmZZZmimZmZmmZimZmZZZmimmmZZZZimZZmZZZmimZZmZZZZimmmZZZZimmmZZZmimZmZZZmimZmZmmZimZmZZZmimZmZZmZZimmmmmmmimZZmmZmZimmmZZZmimZZmZmZmimZmZZZmimZmZmmZimZmZZZmimZZZmmmZimmmZZZZimZZZZmZZimZZmmZmZimZZmZZmmimZmZZZmimZmZmmZimZmZZZmimmZZZmZimZmmmmmimZmmmmmimZmmZmmimZmmmZmimmZZZmZimZmmZZZimZmmZmmimmZZZZZimZmmmmmimZmZZZmimZmZmmZimZmZZZmimZZmmZmZimZZmmZZmimZZmmmZmimZZmmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmZZmimZmZZZZmimZZmmZZZimZZmZmmZimZZmmZZmimZZZmZmmimZZZmmmZimZmmZZZimZZmmZmZimZZmZZmZimZmZZZmimZmZmmZimZmZZZmimmmZmmZimZZZZZmmimZZmZZZZimmmmZZZimZZZmmmmimZmZZZmimZmZmmZimZmZZZmimmmmZmmimmmmZZZimmmZmZZimmmmmmmimZZmZZZZimZmZZZmimZmZmmZimZmZZZmimmmZmmmimmZmmmmimmmZZZZimmmmZZmimZZZmmmZimZmZZZmimZmZmmZimZmZZZmimZmZZZmmimZZZmZmmimmmZmmmimZZmmmmmimmZmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmmZZimZZZmmmmimZmZZZZZimZZZmmmmimZZmmmZZimZZmmmZmimZZZmmmmimZmZZZmimZmZmmZimZmZZZmimZZmZZZmimZZmmZZZimZZmmmmmimmmZmmmimmmZZZmimZmZZZmimZmZmmZimZmZZZmimmmZZmmimZmZZZmZimZZZmZmmimmZmmZZimZZmmZZmimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZZZmZmmimZZZmmZZimZZmZmmZimZZZmmmmimZmmZZZimZZmmmmZimZZZmZmmimZZZmmZZimZZmZmmZimZmZZZmimZmZmmZimZmZZZmimmmmmmZimmZmmZmimZZmmZmZimmmZmZmimZZmmmmZimZmZZZmimZmZmmZimZmZZZmimZZZmmmZimZZZmmmmimZZZmmZmimZZmmZZmimZZZmmmZimZZZmmmmimmmmmmmimmmmmZZimmmZZmmimmZmmZmimZmZZZmimZmZmmZimZmZZZmimmmmmZZimmmZZmZimZmZZZZZimZZZmmZZimZmZZZZZimZmZZZmimZmZmmZimZmZZZmimZZZmZmmimZmZZZmZimZZmZZmmimZZmmZZmimZZmmmZmimZmZZZmimZmZmmZimZmZZZmimZZmmZmZimmmZmmZimZZmmZmZimZZZZZZmimmZmmmZimZmZZZmimZmZmmZimZmZZZmimZZZZZZmimZZmmZmZimZZZmmZZimmmmZZmimmmmZZmimZmZZZmimZmZmmZimZmZZZmimZZZmZmmimZZmmmmZimZZmmmmZimZZmmmZZimZmZZZmimZmZmmZimZmZZZmimZmZZZZZimZZmmmZmimZZmmZmmimZZmZZZZimZZmZmZmimZmZZZmimZmZmmZimZmZZZmimZZmmZmZimZZmZZmmimZZmmZZZimZZmmmmZimZZZmmmmimZZmmmZZimZZZmmmmimZZmmmZmimZZmmmmZimZmZmmmimZmZZZmimZmZmmZimZmZZZmimmmmZmZimZZmZmZmimZmZZZZZimmmmmmmimZZZmmmmimZmZZZmimZmZmmZimZmZZZmimZZZmmmmimZmZZZmZimZZmmZmZimZZmmZZmimZZmmmZZimZZmmmmZimZZmmmZmimZmZZZmimZmZmmZimZmZZZmimZZZZmZZimmmmZmZimmmmmmZimmmmmmZimZZmZmZZimZmZZZmimZmZmmZimZmZZZmimmmZZZZimmmmmZZimmZmmZZimZZmZmZZimmmmZmZimZmZZZmimZmZmmZimZmZZZmimmmZmZmimmZmmmmimZZZZZmmimZmZZZmimZmZmmZimZmZZZmimZZmZZZmimZZZmmmmimZZmmZZZimZZZmmmmimZZmmmZZimZZZmZmmimZZmmmmZimZZmmZZmimZZmmmZZimZmmZmmimZmZZZmimZmZmmZimZmZZZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmZmmZmimZZmZZmZimZZmmmZZimZZmmZZmimZZmZmmmimZZZmmmmimZmmZZmimmZZZmmimZmmZmmimZmZZZmimZmZmmZimZmZZZmimZZmmZmmimZZZmmmZimZmZZmZZimZZmmZmmimZmZZZZZimZmZZZmimZmZmmZimZmZZZmimZZmmZZZimZZmmZZmimmmZmZmimZZmZZZmimZZmmZmZimZmZZZmimZmZmmZimZmZZZmimZZmZZmmimZZmZZZmimZZmmZZZimZZZmmmmimZZZmmmZimZmZmmmimZZZmmmmimZmZZZmZimZZZmmZmimZZmZZmZimZmZZZmimZmZmmZimZmZZZmimZZmZmmZimZZmmZZmimZZZmZmmimZZZmmmZimZmZmmmimZZmmmZmimZZZmmmmimZZZmmZmimZZmmmmZimZZmZZmmimZmZZZmimZmZmmZimZmZZZmimZZZmZmmimZmZZZZZimmZmZmmimZZmZZmmimmmZmZZimZmZZZmimZmZmmZimZmZZZmimmZZmmmimZZZZmmZimZmZZZmZimZmmmZZimZmmmZZimmZZZmmimZmmZmmimZZZZmmZimZmZZZmZimZmmmZZimZmmmZZimZmZmmZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZZZmmZimZmZZZmZimZmmmZZimZmmmZZimmZmmZmimZZmZZmZimZmZZZmimZmZmmZimZmZZZmimZZZmmZmimZZmZZmZimZZZmmmmimZZZmmmmimZZmmmZZimZZmZZmmimZZmmZZmimZmZZZmimZmZmmZimZmZZZmimZZmmZZZimZZmmmmZimmZmmZZimZmZZZmmimmmZZmmimZZZmmmZimZmZZmZimZZZZmmZimZmZZZmZimZmmmZZimZmmmZZimZZmZZmmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZZmZmmimZZmmZmZimZZmmZmZimZZmZmmZimZZmZZmmimZZZmmZmimZZZmZmmimZZmmmmZimZZmZZmmimZZmmZZmimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZZmZZmZimZZmmmmmimZZmZmmmimZZZmmZZimZmZZZmimZmZmmZimZmZZZmimZZmZmmmimZZZmmmmimZZZmmmZimZZmZZmmimZZZmZmmimZZmmmZmimZmZZZmimZmZmmZimZmZZZmimmZmmZZimZmZZZmmimmmZZmmimZZZmmmZimZmZZmZimZZZZmmZimZmZZZmZimZmmmZZimZmmmZZimZZZmmmZimZZmmZZmimZmZZZZmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZZmmmmimZZmmmZZimZZmmmZZimZZmmZZmimZZmmmZZimZmZZZmimZmZmmZimZmZZZmimZZmmZmZimZZmmmmmimZmZZZmmimZZmZZmZimmmZZmZimZmZZZmimZmZmmZimZmZZZmimZZmZZmmimZZZZmZZimZZmmmmZimmmmmmmimmZmmmmimZmZZZmimZmZmmZimZmZZZmimZZZZmmZimZmZZZmZimZmmmZZimZmmmZZimZmZmmZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZZZmmZimZmZZZmZimZmmmZZimZmmmZZimmmZZZmimZZmmZZmimZZmmZZmimZZmZZZmimZZmZmmZimZZZmmmmimZmZZZmimZmZmmZimZmZZZmimmZZmZmimZZmmZmmimmZZmmmimZmmZmZimZmmZZZimmZZZmZimZmZmmZimZZZmZmmimZZmmZmZimZZmmZmZimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZZmZZmmimZZmZmZmimZZZmmmZimZZmmZZmimZmZZZZmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZZmmmZimZZmmZZmimZmZZZZmimZZmmZZZimZZmZmmZimZZmmZZmimZZZmZmmimZZZmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmmZmimZZZmmZmimZZZmZmmimZZmmZmZimZZZmmmmimZmZZmZimZZmmmZZimZmZZmmimZmZZmmimZmZZmmmimZmZZZmimZmZmmZimZmZZZmimmmmZmZimZmZZZmZimZZmZZZZimmmmZZmimZZmmmZZimZmZZZmimZmZmmZimZmZZZmimmmZZmmimZZZZZZmimmZmmmmimZZmZmZZimZZZZZmmimZmZZZmimZmZmmZimZmZZZmimZmmZZmimZZmZmZmimZZZmmmmimZmZZZmmimZmmZZZimZZmZmZZimZZmmmZmimZZmmZZmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZmZZZmZimZZmmZmmimZmZZZmZimmmZZmZimZmZZZmimZmZmmZimZmZZZmimmmmmmZimZZmZmZmimmmmZmmimZZmZZZmimmmmZZmimZmZZZmimZmZmmZimZmZZZmimZZZmZmmimZZZmmZZimZZZmmZmimZZZmmmZimZZZmmmmimZZmZZZZimZZmZZZmimZZmZZmZimZZmZZmmimZZmZmZZimZmZZZmimZmZmmZimZmZZZmimZZmmmZZimZZmZZZZimmZmmmmimZmZZmZZimZZZmmZmimZmZZZmimZmZmmZimZmZZZmimmZmZZmimZZmZZmZimZZZmmmZimmZZmmmimZmmZmmimZmZZZmimZmZmmZimZmZZZmimZmZZmZZimZZmZZmmimmZmmZmimmmZmmmimmZmZmmimZmZZZmimZmZmmZimZmZZZmimZZZZZmmimZZZZmZZimZmZmZmimZmmZZmimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZZmmmZZimmZZmZZimZZmmZZZimZZmmmmZimZZmZZmZimZmZmmmimZZZmmZmimZZmZZmZimZZmZZmmimZmZZZmimZmZmmZimZmZZZmimZZmZZZmimZZZmmmmimZZmmmmZimZmZZZmimZmZmmZimZmZZZmimZZmZmZmimZmZmmmimZZmZZZmimZZZmmmmimZZmmZZZimZZZmmmmimZZmmmZZimZZZmZmmimZZmmmmZimZZmmZZmimZmZZZmimZmZmmZimZmZZZmimZmZZZmZimmmmZmmimmmmZmZimmmmZZmimmmmZmmimZmZZZmimZmZmmZimZmZZZmimZZmZmmmimmZmmmZimmmZZmmimZZZZZmZimZZmmmZZimZmZZZmimZmZmmZimZmZZZmimZZmZmmmimmmZZmZimZZmZmmZimZmZZZZZimmmmZZZimZmZZZmimZmZmmZimZmZZZmimmmmmZmimZZmZmZZimZZmZmmmimZZZZZmmimZmZZZmZimZmZZZmimZmZmmZimZmZZZmimZZZmZmmimZmZZZZZimZZmZZmmimZZmZZZZimZmZmmZimZZmZZmmimZZmZmmmimZZZmZmmimZZmZZZmimZZZmmmmimZmZZZmimZmZmmZimZmZZZmimZmZZZmmimZZmmmmZimZZZmmmZimZZmmZZmimZmZZZZmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimZZmZZZZimZZZmZmmimZZZmmZmimZZZmmmmimZZZmmZZimZZmmZZmimZZmmZZmimZZmZmZmimZmZmmmimZZmZmmmimZmZZZmimZmZmmZimZmZZZmimZmZZZmmimZZmmmmmimZZmZmmmimZmZZmZZimmmZZmZimZmZZZmimZmZmmZimZmZZZmimZZmmmmmimmZmmmZimmmZZmZimZZZmmZZimZZmmmZmimZmZZZmimZmZmmZimZmZZZmimmmmZZmimmmmZmZimmmmZmmimmmmmZZimmmmmZmimmmmmmZimmmmmmmimZZZZZZZimZZZZZZmimZZZZZmZimZmZZZmimZmZmmZimZmZZZmimZmZZZmmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmmmmZimZZmmZZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmZmmZimZZZmZmmimZZmmmmmimZZmmZZZimZZZmmZmimZmZZZmimZmZmmZimZmZZZmimmZmmZZimZZmZmmZimZZZmZmmimZZmmZZZimZZmZmZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZZmmmZimZZZmZmmimZZmmmmZimZZZmZmmimZmZZZmimZmZmmZimZmZZZmimZZZmmZmimmmmZmZimZmZZZmZimmZmmmZimZZZZZmZimZmZZZmimZmZmmZimZmZZZmimmmZZZmimZZZZZmmimmmmZZmimZmZZZmmimZZZZZZZimZmZZZmimZmZmmZimZmZZZmimZZmZZmZimZZZmmZZimZmZZmZZimZZmZZmZimmmmZmmimZmZZZmimZmZmmZimZmZZZmimZZmZZZmimmZmmZmimZmZZmZZimZZmZmmZimZZmZmZZimZmZZZmimZmZmmZimZmZZZmimZmmmmmimmZZZmZimZmmmmmimmZZZmZimmZZZmmimZmmmmZimZmmmmmimZZmmmmmimmmZZZZimZZmZmZZimZmZZZZmimZZZmmZZimZZZZZZmimZmZZZmimZmZmmZimZmZZZmimZZZmmmmimZZZmmmZimZZmZZmmimZZZmZmmimZmZmmmimZZZmZmmimZZmmZmZimZZmZZmmimZmmZZZimZZmmZmZimZmZZZmimZmZmmZimZmZZZmimZmmZZmimZZmZZZmimZZZmmmZimZZmmmZZimZZmZZmmimZmZZZZZimZZZmmmmimZmmZZZimZZmZmZZimZZmmmZmimZmZZZmimZmZmmZimZmZZZmimZZmmZmmimmmZZZmimZZZmmmmimZZmmmmmimmZmmmZimZmZZZmimZmZmmZimZmZZZmimZZZmZmmimZmZZZmZimmmZmZZimmmZZmmimZZZZZZZimZmZZZmimZmZmmZimZmZZZmimZZmZmZmimZZZmmZmimZZZZmZZimmmZmmmimZZmZmmZimZmZZZmimZmZmmZimZmZZZmimZZZZZmZimZZmZZmZimZZmmmmZimmZmmmZimmmZmZZimZmZZZmimZmZmmZimZmZZZmimZmmZmmimZmmZmZimZmmZmZimZmmZmZimZmmZmZimZmmZmZimmZZZmmimZmmmmmimmZZZmmimmZZZZmimZmZZZmimZmZmmZimZmZZZmimZZmZZmmimZZZmmZmimZmZZZmmimZZmZZmZimmmmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmZmmimmmZmZZimmmmmmmimZZmZZmZimmmZmmZimZmZZZmimZmZmmZimZmZZZmimmmmmZmimmmmZZZimZZmZmmZimmmmmmZimZZZmZmmimZmZZZmimZmZmmZimZmZZZmimZZmZZmZimZZmmmmZimZZmmmmZimZZmmZmZimZZmmmZmimmZZmZZimZmmZZmimZmmZZmimZZmmmZZimZZZmZmmimZmZZZmimZmZmmZimZmZZZmimZZZZZmmimmZmmmmimmmZZmZimmmZmmmimmmmZZmimZmZZZmimZmZmmZimZmZZZmimZZmmmZZimZZZmZmmimZZmmZZZimZZZmmmZimZZmmZZmimZZmZmmmimZmZZZmimZmZmmZimZmZZZmimZZmZmmmimZZmmmZmimZZmZmmZimmmZZZZimZZmZmZmimZmZZZmimZmZmmZimZmZZZmimmmZmmmimZZmZZmmimZZmmmZmimZZmmmZmimZZmZZmmimZZmmZZZimZZmZZZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmmmmmimZZmmmZZimZmZZZmimZmZmmZimZmZZZmimZZmmZmZimmmZmZmimZZZmmmmimZmZZZmmimZZmmZmmimZmZZZmimZmZmmZimZmZZZmimmmZmmZimZZmZmmmimZZmZZZmimZZZmmZmimmmmZmZimZmZZZmimZmZmmZimZmZZZmimZZmmZZZimZZmmmmZimZZZmmmmimZZmmmZZimZZZmmmmimZZmmmZmimZZmmmmZimZmZmmmimZmZZZZZimZZmZZmmimZmZZZmimZmZmmZimZmZZZmimmZmmmmimmmZZZZimmmZZZmimmmZZmZimmmZZmmimmmZmZZimmmZmZmimmmZmmZimmmZmmmimmmmZZZimZmZZZmimZmZmmZimZmZZZmimZZmmmZmimZZmmZZmimZZmZmmmimZZZmmmmimZZmmmmZimZZmZZmZimZZmZZmmimZZmmZZZimZZmZZZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZmZZZmimZmZmmZimZmZZZmimZZmZZmmimZZZmmmZimZZZmZmmimZZmmZmZimZZmZZmmimZmmZZZimZZZmmZmimZZmmZZmimZZmZmmmimZmmZZmimZmZZZmimZmZmmZimZmZZZmimZZmZmZZimmZmmZZimZZZmmZZimZZmZmmZimZZZZZZZimZmZZZmimZmZmmZimZmZZZmimZZmmmZZimZZZmZmmimZZmZmmmimZmZZZmimZmZmmZimZmZZZmimZmmmZmimmZZZZmimZmmZZZimZmmmZmimmZZZZZimZmZZZmimZmZmmZimZmZZZmimZmZZZmmimZZmmZZmimZZmmmmmimZZmmmmZimZZmmmmmimZZZmmZZimZZZmmmmimZmZmmmimZmZZZZZimZZmZZmmimZmZZZmimZmZmmZimZmZZZmimmmZmmmimZZmZZmmimZZmmmZmimZZmmmZmimZZmZZmmimZZmmZZZimZZmZZZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZZmmZmimZZmmZZmimZmZZZmimZmZmmZimZmZZZmimZZmmZZZimmmmZmmimmmZZZZimZZZmmmmimZZZmZmmimZmZZZmimZmZmmZimZmZZZmimZmZZZZmimZmmZZZimZZmmmmZimZZmZZmmimZZmZmZmimZmZZZZmimZZmZmmmimZmmZZZimZZZmmZmimZZmmZZmimZmZZZmimZmZmmZimZmZZZmimZZmmZZmimZZZZZZmimmmZmmmimZmZZZmZimmZmmZZimZmZZZmimZmZmmZimZmZZZmimZmmmZmimmZZmZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmZZZmimZZmmmmZimmZZmmmimZmmZmmimZmmmmmimZmmmmmimZmmmmZimZmZZZmimZmZmmZimZmZZZmimZZmZZZZimmmmmZmimmZmZmmimmZmmmZimmmmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZZmmmZmimZmZmmmimZZZmmmZimZZmmZZmimZmZZZZmimZZmmZZZimZZmZmmZimZZmmZZmimZZZmZmmimZmZZZmimZmZmmZimZmZZZmimmmmmZZimmmZmmmimZZZmmmmimZZmmZmmimZZmZZZmimZmZZZmimZmZmmZimZmZZZmimZZZmmmZimZZmmmmmimmmmmZmimZZmZmZZimZZmZZmmimZmZZZmimZmZmmZimZmZZZmimZZmmmmmimZZmmZZZimZZZmmZmimZZmZZmZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmmmmZimZZmZZmZimZZZmmmmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmmZmZimZmZZZmimZmZmmZimZmZZZmimmZmmZZimmmmZZZimmmmmZZimZmZZZmZimZZZZZZZimZmZZZmimZmZmmZimZmZZZmimZZmmmZZimZZmmZZmimZZmZZZmimZZmmmZZimZZZmZmmimZZmZmmmimZmZZZmimZmZmmZimZmZZZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmZmmZmimZZmZZmZimZZmmmZZimZZmmZZmimZZmZmmmimZZZmmmmimZZZZmmZimZmZZZmZimZmmmZZimZmmmZZimmZZmZmimZmZZZZZimZmZZZmimZmZmmZimZmZZZmimZZZmmmmimZmmZZmimZZZmZmmimZZmmZmZimZZmmZZZimZZmZZZmimZmZmmZimZmZmZZimZmmZZmimZmZmZZimZmZZZmimZmZmmZimZmZZZmimZmmZmmimZmmZmZimZmmmZmimmZZZZZimZmmmmmimZmmmmmimZmmZmmimZmmmZmimZmmmZmimZmmmZZimZmZZZmimZmZmmZimZmZZZmimZZmZZmZimZZmmmmZimZZmmmmZimZZmmZmZimZZmmmZmimmZZmZZimZmmZZmimZmmZZmimZZmmmZmimZZmmZZZimZmZZZmimZmZmmZimZmZZZmimmZZZmZimZZmmmZZimmmmmmmimZmZZZmZimmmmmZZimZZmZmZmimZZmZZZmimZmZZZmimZmZmmZimZmZZZmimZZmZZmmimmZmmmZimZZmmmZZimmmmmmZimmmZZmZimZmZZZmimZmZmmZimZmZZZmimZZmZZmZimZZmmmmZimZZmmmmZimZZmmZmZimZZmmmZmimmZZmZZimZmmZZmimZmmZZmimZmZZZmmimZZmmZZmimZmZZZmimZmZmmZimZmZZZmimZmZZmmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimmZmZmmimZZmmZmZimZZmmZmZimZZmZmmZimZZZmmmmimZZZZZZmimZZZmmmmimZZZmmZZimZmZZZmimZmZmmZimZmZZZmimZmmZZZimZZmmZmZimZmmZZZimZZmmmZZimZZZmZmmimZZmmZmZimZZmZZmmimZZZmmmZimZZZmZmmimZZmmZmZimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZZmmZZmimmmmmZmimZZmmmmZimZZmmmZZimZZmZZmmimZZmmZZZimZZmZZZmimZmZZZmimZmZmmZimZmZZZmimZZmZmZZimZZmmmZmimmmmmZmimZZmmmZmimmmmZZZimZmZZZmimZmZmmZimZmZZZmimZZmmZmmimZmZZZmZimZZZmmmZimZZmZmmZimZZZmmZmimZmZZZmimZmZmmZimZmZZZmimmZmmmmimmZmZmmimmmmmZmimmmmmmZimmmmmmZimZmZZZmimZmZmmZimZmZZZmimZZmZmZmimmmZmZZimmmmmmmimZZZmmZmimmmmmmZimZmZZZmimZmZmmZimZmZZZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZmZZmZimmmZmZmimmmZZmZimmmmmmZimmmZmmmimmmZmmZimZmZmmZimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZZmZmmZimZmZZZmimZmZmmZimZmZZZmimmmZZZmimmZmmmmimmmmmmZimZmZZZmimZmZmmZimZmZZZmimZZZZZZZimmmZmZmimmmZZZmimmmmZmZimmmmmZZimZmZZZmimZmZmmZimZmZZZmimZZmmmZZimZZZmmmmimZZmmZmZimZZmZmmZimZZZmZmmimZZZmmZmimZZZmmmmimZmZZZmimZmZmmZimZmZZZmimZZZZZZmimZZmZZmmimZZmmZZZimmZZZZZimZmmmmZimmZZmZmimZZZZmmZimZmZZZmZimZmmmZZimZmmZmZimZmZZZmZimmZZZZZimZmmmmZimZmZZZmimZmZmmZimZmZZZmimZZmmmmZimZZZmmmmimZZmmmZmimZZmmmmZimZmZZZmimZmZmmZimZmZZZmimZmZZZZmimZZZmZmmimZmmZZZimZZmZmmmimZZZmmmmimZmmZZmimZmZmZmimmZZZmZimmZZZmZimZmmZmZimZmZZZmimZmZmmZimZmZZZmimZZmmZZZimZmmZZmimZmZZZmZimZZmZZmZimZZmmmmZimZZmZmmmimZZmZmmZimZmZmZmimZmZZZmZimZZmZmmmimZmZZZmimZmZmmZimZmZZZmimmmZmmmimZZZmmmmimZZmmmmmimZZmmmmmimmZmmZmimZmZZZmimZmZmmZimZmZZZmimZZZmZmmimZZmmZZZimZZZmmmZimZZZZmmZimZmZZZmZimZmmmZZimZmmmZZimmZZmZmimZmZZZZZimmZZmmmimZZZZmmZimZmZZZmZimZmmmZZimZmmmZZimmZZZmmimmZZZmmimZmZZZmimZmZmmZimZmZZZmimmZmmmmimZZmmmmZimZmZZZZZimmmmmmZimZZmZZmmimZmZZZmimZmZmmZimZmZZZmimmZmZmmimmmmZmmimmZmmmZimmmZZmZimmmZmmZimZmZZZmimZZZZmmmimmZZmZmimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZZmZZZZimZmmmZZimZZZmmmmimmZZmmmimZZmZZZZimZZmmmmmimZZmmZZZimZZZmmZmimZZmmmmZimZZmZZmmimZZmmZZmimZZmmZZZimZmZZmZimZmZZmmimZmZZmZmimZZmmmZZimZZZmmmmimZZmmmmZimZZmmmmmimZZmmmZZimZZmmZZZimZZmZmZimZZZmZZmimZmmZmZimZmZZZmZimZmmmZmimmZZZZmimZZZmmZZimZmmmmmimZmmZmZimZmmmZmimmZZmZmimZmZZmmmimmZZmZmimZZmmmZZimZZZmmmmimZZmmmmZimZZmmmmmimZZmmmZZimZZmmZZZimZZmZmZimZZZmZZmimZmmZmZimZmZZZmZimZmmmmZimZZmZZZZimZmmmZZimZZZmmmmimZmZZmZimZmZZmmimmZZmZmimZmZZmmmi` \ No newline at end of file diff --git a/js/test/perf.test.ts b/js/test/perf.test.ts new file mode 100644 index 00000000..ecbd3b30 --- /dev/null +++ b/js/test/perf.test.ts @@ -0,0 +1,26 @@ +import { test, expect, describe, afterAll } from "vitest"; +import { get_encoding } from "../../wasm/dist"; +import { getEncoding } from "../src/index"; +import { EVIL_STRING } from "./fixtures/evil-string"; + +describe("Tokenizer resolves in acceptable time", () => { + const full = get_encoding("cl100k_base"); + + afterAll(() => full.free()); + + test("Test wasm performance", () => { + const start = Date.now(); + const result = full.encode(EVIL_STRING); + const end = Date.now(); + expect(end - start).toBeLessThanOrEqual(5000); + }); + + const lite = getEncoding("cl100k_base"); + + test("Test wasm performance", () => { + const start = Date.now(); + const result = lite.encode(EVIL_STRING); + const end = Date.now(); + expect(end - start).toBeLessThanOrEqual(5000); + }); +}); \ No newline at end of file From 9ce1658b2ff65b3554310ef2cef8b8f1bcf45720 Mon Sep 17 00:00:00 2001 From: Mikola Lysenko Date: Fri, 19 Apr 2024 22:29:12 +0100 Subject: [PATCH 2/3] handle empty input case --- js/src/core.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/js/src/core.ts b/js/src/core.ts index b48bf6b8..fd238b8e 100644 --- a/js/src/core.ts +++ b/js/src/core.ts @@ -27,7 +27,7 @@ function swap(heap:BPEMergeNode[], i:number, j:number) { heap[j] = temp; } -// Function to push an element onto the heap +// standard binary heap push, generated by gpt4 function heapPush(heap:BPEMergeNode[], part:BPEMergeNode) { heap.push(part); // Add the new element to the end let currentIndex = heap.length - 1; @@ -41,7 +41,7 @@ function heapPush(heap:BPEMergeNode[], part:BPEMergeNode) { } } -// Function to pop the root element from the heap +// standard heap pop, also ai generated function heapPop(heap:BPEMergeNode[]) { if (heap.length === 0) { return undefined; // Return undefined if the heap is empty @@ -96,6 +96,10 @@ function bytePairMerge( listPrev: null })); + if (parts.length === 0) { + return []; + } + const head = parts[0]; for (let i = 0; i < parts.length; ++i) { parts[i].listPrev = parts[i - 1] ?? null; From 8685e3c82d274a20d5e19bc01ed2ea4a9caf8407 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Wed, 2 Oct 2024 20:13:44 +0200 Subject: [PATCH 3/3] Format code --- js/src/core.ts | 67 ++++++++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/js/src/core.ts b/js/src/core.ts index fd238b8e..6ba2edc9 100644 --- a/js/src/core.ts +++ b/js/src/core.ts @@ -16,25 +16,28 @@ type BPEMergeNode = { end: number; }; -function compareNode (a:BPEMergeNode, b:BPEMergeNode) { +function compareNode(a: BPEMergeNode, b: BPEMergeNode) { return a.rank - b.rank || a.start - b.start; } // Helper function to swap elements at two indices -function swap(heap:BPEMergeNode[], i:number, j:number) { +function swap(heap: BPEMergeNode[], i: number, j: number) { const temp = heap[i]; heap[i] = heap[j]; heap[j] = temp; } // standard binary heap push, generated by gpt4 -function heapPush(heap:BPEMergeNode[], part:BPEMergeNode) { +function heapPush(heap: BPEMergeNode[], part: BPEMergeNode) { heap.push(part); // Add the new element to the end let currentIndex = heap.length - 1; let parentIndex = Math.floor((currentIndex - 1) / 2); // Bubble the new element up to its correct position - while (currentIndex > 0 && compareNode(heap[currentIndex], heap[parentIndex]) < 0) { + while ( + currentIndex > 0 && + compareNode(heap[currentIndex], heap[parentIndex]) < 0 + ) { swap(heap, currentIndex, parentIndex); currentIndex = parentIndex; parentIndex = Math.floor((currentIndex - 1) / 2); @@ -42,7 +45,7 @@ function heapPush(heap:BPEMergeNode[], part:BPEMergeNode) { } // standard heap pop, also ai generated -function heapPop(heap:BPEMergeNode[]) { +function heapPop(heap: BPEMergeNode[]) { if (heap.length === 0) { return undefined; // Return undefined if the heap is empty } @@ -60,11 +63,17 @@ function heapPop(heap:BPEMergeNode[]) { let rightChildIndex = 2 * currentIndex + 2; let smallestIndex = currentIndex; - if (leftChildIndex < heap.length && compareNode(heap[leftChildIndex], heap[smallestIndex]) < 0) { + if ( + leftChildIndex < heap.length && + compareNode(heap[leftChildIndex], heap[smallestIndex]) < 0 + ) { smallestIndex = leftChildIndex; } - if (rightChildIndex < heap.length && compareNode(heap[rightChildIndex], heap[smallestIndex]) < 0) { + if ( + rightChildIndex < heap.length && + compareNode(heap[rightChildIndex], heap[smallestIndex]) < 0 + ) { smallestIndex = rightChildIndex; } @@ -84,17 +93,20 @@ function bytePairMerge( piece: Uint8Array, ranks: Map ): Array<{ start: number; end: number }> { - const parts: BPEMergeNode[] = Array.from({ length: piece.length }, (_, i) => ({ - start: i, - end: i + 1, - rank: 0, - deleted: false, - updated: false, - updatedRank: 0, - removed: true, - listNext: null, - listPrev: null - })); + const parts: BPEMergeNode[] = Array.from( + { length: piece.length }, + (_, i) => ({ + start: i, + end: i + 1, + rank: 0, + deleted: false, + updated: false, + updatedRank: 0, + removed: true, + listNext: null, + listPrev: null, + }) + ); if (parts.length === 0) { return []; @@ -106,12 +118,11 @@ function bytePairMerge( parts[i].listNext = parts[i + 1] ?? null; } - const heap:BPEMergeNode[] = [] + const heap: BPEMergeNode[] = []; for (let i = 0; i < parts.length - 1; ++i) { const slice = piece.slice(parts[i].start, parts[i + 1].end); const rank = ranks.get(slice.join(",")); - if (rank == null) - continue; + if (rank == null) continue; const part = parts[i]; part.removed = false; part.rank = rank; @@ -120,14 +131,13 @@ function bytePairMerge( while (heap.length > 0) { const part = heapPop(heap); - if (!part) - break; + if (!part) break; // remove deleted nodes from heap if (part.deleted) { part.deleted = false; part.removed = true; - continue + continue; } // reinsert updated nodes @@ -139,12 +149,11 @@ function bytePairMerge( } // mark node as removed from heap - part.removed = true + part.removed = true; // delete next part and collapse node part.end = part.listNext?.end ?? piece.length; - if (part.listNext) - part.listNext.deleted = true; + if (part.listNext) part.listNext.deleted = true; part.listNext = part.listNext?.listNext ?? null; // update rank @@ -166,9 +175,9 @@ function bytePairMerge( if (prevRank != null) { if (prevRank !== part.listPrev.rank) { if (part.listPrev.removed) { - part.listPrev.removed = false + part.listPrev.removed = false; part.listPrev.rank = prevRank; - heapPush(heap, part) + heapPush(heap, part); } else { part.listPrev.updated = true; part.listPrev.updatedRank = prevRank;