From 39bd5f669146cd469c979c3e13e37dbabe0ca903 Mon Sep 17 00:00:00 2001 From: jacob Date: Sun, 11 Aug 2024 23:16:13 -0600 Subject: [PATCH 01/10] Completed implementation of real and complex sparse COO tensors. --- .../org/flag4j/arrays/sparse/CooCTensor.java | 206 ++++++++--------- .../org/flag4j/arrays/sparse/CooTensor.java | 142 ++++++++---- .../org/flag4j/arrays/sparse/CsrMatrix.java | 2 + .../core/ComplexTensorExclusiveMixin.java | 37 ---- .../org/flag4j/core/TensorExclusiveMixin.java | 2 +- src/main/java/org/flag4j/io/PrettyPrint.java | 208 ++++++++++++++++++ .../complex/ComplexDenseSparseOperations.java | 43 ++++ .../real/RealDenseSparseTensorOperations.java | 44 +++- .../RealComplexDenseSparseOperations.java | 86 ++++++++ .../complex/ComplexCooTensorOperations.java | 79 +++++++ .../coo/real/RealCooTensorOperations.java | 79 +++++++ .../RealComplexCooTensorOperations.java | 142 ++++++++++++ .../sparse/csr/real/RealCsrOperations.java | 3 + src/main/java/org/flag4j/util/ArrayUtils.java | 2 +- .../java/org/flag4j/util/ParameterChecks.java | 13 ++ target/flag4j-v0.1.0-beta.jar | Bin 633923 -> 640797 bytes 16 files changed, 906 insertions(+), 182 deletions(-) create mode 100644 src/main/java/org/flag4j/io/PrettyPrint.java diff --git a/src/main/java/org/flag4j/arrays/sparse/CooCTensor.java b/src/main/java/org/flag4j/arrays/sparse/CooCTensor.java index adb1ebb55..c77591d24 100644 --- a/src/main/java/org/flag4j/arrays/sparse/CooCTensor.java +++ b/src/main/java/org/flag4j/arrays/sparse/CooCTensor.java @@ -31,7 +31,8 @@ import org.flag4j.core.Shape; import org.flag4j.core.TensorBase; import org.flag4j.core.sparse_base.ComplexSparseTensorBase; -import org.flag4j.operations.dense.real.RealDenseOperations; +import org.flag4j.io.PrettyPrint; +import org.flag4j.io.PrintOptions; import org.flag4j.operations.dense.real.RealDenseTranspose; import org.flag4j.operations.dense_sparse.coo.complex.ComplexDenseSparseOperations; import org.flag4j.operations.dense_sparse.coo.real_complex.RealComplexDenseSparseOperations; @@ -197,32 +198,67 @@ public CooCTensor H() { /** - * Sets an index of this tensor to a specified value. + *

Copies this tensor and sets the specified {@code index} to {@code value}.

* - * @param value Value to set. - * @param indices The indices of this matrix for which to set the value. - * @return A reference to this tensor. - * @throws IllegalArgumentException If the number of indices is not equal to the rank of this tensor. - * @throws IndexOutOfBoundsException If any of the indices are not within this tensor. + *

Note: unlike with dense tensors, this method returns a copy of this + * tensor with the specified value updated and does NOT return a reference to this tensor. Because of this, it may be + * expensive to make frequent updates to a sparse tensor.

+ * + * @param value Value to set. + * @param index The index of this tensor for which to set the value. + * @return A copy of this tensor with the specified value set. */ @Override - public CooCTensor set(CNumber value, int... indices) { - // TODO: Implementation. - return null; + public CooCTensor set(CNumber value, int...index) { + ParameterChecks.assertValidIndex(shape, index); + CooCTensor dest; + + // Check if value already exists in tensor. + int idx = -1; + for(int i=0; i -1) { + // Copy entries and set new value. + dest = new CooCTensor(shape, entries.clone(), ArrayUtils.deepCopy(indices, null)); + dest.entries[idx] = value; + dest.indices[idx] = index; + } else { + // Copy old indices and insert new one. + int[][] newIndices = new int[indices.length + 1][getRank()]; + ArrayUtils.deepCopy(indices, newIndices); + newIndices[indices.length + 1] = index; + + // Copy old entries and insert new one. + CNumber[] newEntries = Arrays.copyOf(entries, entries.length+1); + newEntries[newEntries.length-1] = value; + + dest = new CooCTensor(shape, newEntries, newIndices); + dest.sortIndices(); + } + + return dest; } /** - * Sets an index of this tensor to a specified value. + *

Copies this tensor and sets the specified {@code index} to {@code value}.

* - * @param value Value to set. - * @param indices The indices of this tensor for which to set the value. - * @return A reference to this tensor. + *

Note: unlike with dense tensors, this method returns a copy of this + * tensor with the specified value updated and does NOT return a reference to this tensor. Because of this, it may be + * expensive to make frequent updates to a sparse tensor.

+ * + * @param value Value to set. + * @param index The index of this tensor for which to set the value. + * @return A copy of this tensor with the specified value set. */ @Override public CooCTensor set(double value, int... indices) { - // TODO: Implementation. - return null; + return set(new CNumber(value), indices); } @@ -264,18 +300,43 @@ public CooCTensor reshape(Shape newShape) { /** - * Flattens tensor to single dimension. To flatten tensor along a single axis. + * Flattens tensor to single dimension. This method does not preserve rank. To flatten tensor along a single axis (and preserve + * the rank) use {@link #flatten(int)}. * * @return The flattened tensor. + * @see #flatten(int) */ @Override public CooCTensor flatten() { int[][] destIndices = new int[entries.length][1]; - for(int i = 0; i < entries.length; i++) - destIndices[i][0] = RealDenseOperations.prod(indices[i]); + for(int i=0, size=entries.length; ithis.{@link #getRank()}-1. + * @see #flatten() + */ + @Override + public CooCTensor flatten(int axis) { + ParameterChecks.assertIndexInBounds(indices[0].length, axis); + int[][] destIndices = new int[indices.length][indices[0].length]; + + // Compute new shape. + int[] destShape = new int[indices[0].length]; + destShape[axis] = shape.totalEntries().intValueExact(); - return new CooCTensor(shape, Arrays.copyOf(entries, entries.length), destIndices); + for(int i=0, size=entries.length; ithis.{@link #getRank()}-1. - */ - @Override - public CooCTensor flatten(int axis) { - // TODO: Implementation. - return null; - } - - /** * A factory for creating a complex sparse tensor. * @@ -745,15 +785,6 @@ protected CooTensor makeRealTensor(Shape shape, double[] entries, int[][] indice } - /** - * Sorts the indices of this tensor in lexicographical order while maintaining the associated value for each index. - */ - @Override - public void sortIndices() { - // TODO: Implementation - } - - /** * Converts a sparse {@link CooCTensor} from a dense {@link Tensor}. This is likely only worthwhile for very sparse tensors. * @param src Dense tensor to convert to sparse COO tensor. @@ -885,53 +916,24 @@ public CooCTensor H(int... axes) { /** - * Computes the element-wise addition of two tensors of the same rank and stores the result in this tensor. - * - * @param B Second tensor in the addition. + *

Formats this sparse COO tensor as a human-readable string specificing the full shape, + * non-zero entries, and non-zero indices.

* - * @throws IllegalArgumentException If this tensor and {@code B} have different shapes. + * @return A human-readable string specificing the full shape, non-zero entries, and non-zero indices of this tensor. */ - @Override - public void addEq(Tensor B) { - // TODO: Remove. It does not make sense for this to be in a sparse tensor. - } + public String toString() { + int maxCols = PrintOptions.getMaxColumns(); + int padding = PrintOptions.getPadding(); + int precision = PrintOptions.getPrecision(); + boolean centring = PrintOptions.useCentering(); + StringBuilder sb = new StringBuilder(); - /** - * Computes the element-wise addition of two tensors of the same rank and stores the result in this tensor. - * - * @param B Second tensor in the addition. - * - * @throws IllegalArgumentException If this tensor and {@code B} have different shapes. - */ - @Override - public void addEq(CooCTensor B) { - // TODO: Remove. It does not make sense for this to be in a sparse tensor. - } - + sb.append("Shape: " + shape + "\n"); + sb.append("Non-zero Entries: " + PrettyPrint.abrivatedArray(entries, maxCols, padding, precision, centring) + "\n"); + sb.append("Non-zero Indices: " + + PrettyPrint.abrivatedArray(indices, PrintOptions.getMaxRows(), maxCols, padding, 20, centring)); - /** - * Computes the element-wise subtraction of two tensors of the same rank and stores the result in this tensor. - * - * @param B Second tensor in the subtraction. - * - * @throws IllegalArgumentException If this tensor and {@code B} have different shapes. - */ - @Override - public void subEq(Tensor B) { - // TODO: Remove. It does not make sense for this to be in a sparse tensor. - } - - - /** - * Computes the element-wise subtraction of two tensors of the same rank and stores the result in this tensor. - * - * @param B Second tensor in the subtraction. - * - * @throws IllegalArgumentException If this tensor and {@code B} have different shapes. - */ - @Override - public void subEq(CooCTensor B) { - // TODO: Remove. It does not make sense for this to be in a sparse tensor.FEq + return sb.toString(); } } diff --git a/src/main/java/org/flag4j/arrays/sparse/CooTensor.java b/src/main/java/org/flag4j/arrays/sparse/CooTensor.java index c1e881675..02c25a9ff 100644 --- a/src/main/java/org/flag4j/arrays/sparse/CooTensor.java +++ b/src/main/java/org/flag4j/arrays/sparse/CooTensor.java @@ -32,6 +32,8 @@ import org.flag4j.core.TensorBase; import org.flag4j.core.TensorExclusiveMixin; import org.flag4j.core.sparse_base.RealSparseTensorBase; +import org.flag4j.io.PrettyPrint; +import org.flag4j.io.PrintOptions; import org.flag4j.linalg.TensorInvert; import org.flag4j.operations.dense.real.RealDenseTranspose; import org.flag4j.operations.dense_sparse.coo.real.RealDenseSparseTensorOperations; @@ -218,16 +220,50 @@ protected CooCTensor makeComplexTensor(Shape shape, CNumber[] entries, int[][] i /** - * Sets an index of this tensor to a specified value. + *

Copies this tensor and sets the specified {@code index} to {@code value}.

* - * @param value Value to set. - * @param indices The indices of this tensor for which to set the value. - * @return A reference to this tensor. + *

Note: unlike with dense tensors, this method returns a copy of this + * tensor with the specified value updated and does NOT return a reference to this tensor. Because of this, it may be + * expensive to make frequent updates to a sparse tensor.

+ * + * @param value Value to set. + * @param index The index of this tensor for which to set the value. + * @return A copy of this tensor with the specified value set. */ @Override - public CooTensor set(double value, int... indices) { - // TODO: Implementation. - return null; + public CooTensor set(double value, int... index) { + ParameterChecks.assertValidIndex(shape, index); + CooTensor dest; + + // Check if value already exists in tensor. + int idx = -1; + for(int i=0; i -1) { + // Copy entries and set new value. + dest = new CooTensor(shape, entries.clone(), ArrayUtils.deepCopy(indices, null)); + dest.entries[idx] = value; + dest.indices[idx] = index; + } else { + // Copy old indices and insert new one. + int[][] newIndices = new int[indices.length + 1][getRank()]; + ArrayUtils.deepCopy(indices, newIndices); + newIndices[indices.length + 1] = index; + + // Copy old entries and insert new one. + double[] newEntries = Arrays.copyOf(entries, entries.length+1); + newEntries[newEntries.length-1] = value; + + dest = new CooTensor(shape, newEntries, newIndices); + dest.sortIndices(); + } + + return dest; } @@ -269,7 +305,8 @@ public CooTensor reshape(Shape newShape) { /** - * Flattens tensor to single dimension. To flatten tensor along a single axis see {@link #flatten(int)}. + * Flattens tensor to single dimension. This method does not preserve rank. To flatten tensor along a single axis (and preserve + * the rank) use {@link #flatten(int)}. * * @return The flattened tensor. * @see #flatten(int) @@ -278,10 +315,33 @@ public CooTensor reshape(Shape newShape) { public CooTensor flatten() { int[][] destIndices = new int[entries.length][1]; - for(int i = 0; i < entries.length; i++) + for(int i=0, size=entries.length; ithis.{@link #getRank()}-1. + * @see #flatten() + */ + @Override + public CooTensor flatten(int axis) { + ParameterChecks.assertIndexInBounds(indices[0].length, axis); + int[][] destIndices = new int[indices.length][indices[0].length]; + + // Compute new shape. + int[] destShape = new int[indices[0].length]; + destShape[axis] = shape.totalEntries().intValueExact(); + + for(int i=0, size=entries.length; ithis.{@link #getRank()}-1. - */ - @Override - public CooTensor flatten(int axis) { - // TODO: Implementation - return null; - } - - /** * Simply returns a reference of this tensor. * @@ -778,4 +817,27 @@ public Tensor toDense() { return new Tensor(shape, entries); } + + + /** + *

Formats this sparse COO tensor as a human-readable string specificing the full shape, + * non-zero entries, and non-zero indices.

+ * + * @return A human-readable string specificing the full shape, non-zero entries, and non-zero indices of this tensor. + */ + public String toString() { + int maxEntries = PrintOptions.getMaxColumns(); + int padding = PrintOptions.getPadding(); + int precision = PrintOptions.getPrecision(); + boolean centring = PrintOptions.useCentering(); + + StringBuilder sb = new StringBuilder(); + + sb.append("Shape: " + shape + "\n"); + sb.append("Non-zero Entries: " + PrettyPrint.abrivatedArray(entries, maxEntries, padding, precision, centring) + "\n"); + sb.append("Non-zero Indices: " + + PrettyPrint.abrivatedArray(indices, PrintOptions.getMaxRows(), maxEntries, padding, 20, centring)); + + return sb.toString(); + } } diff --git a/src/main/java/org/flag4j/arrays/sparse/CsrMatrix.java b/src/main/java/org/flag4j/arrays/sparse/CsrMatrix.java index eb3123913..3cd9ae4db 100644 --- a/src/main/java/org/flag4j/arrays/sparse/CsrMatrix.java +++ b/src/main/java/org/flag4j/arrays/sparse/CsrMatrix.java @@ -2447,6 +2447,8 @@ public CsrMatrix copy() { */ @Override public CsrMatrix elemMult(CsrMatrix B) { + // TODO: While technically correct, this does not take advantage of x*0 = 0*x = 0 for any x and will likely store many + // zeros explicitly. return RealCsrOperations.applyBinOpp(this, B, (Double a, Double b) -> a*b, null); } diff --git a/src/main/java/org/flag4j/core/ComplexTensorExclusiveMixin.java b/src/main/java/org/flag4j/core/ComplexTensorExclusiveMixin.java index f6dc9ba7d..b085d5ea8 100644 --- a/src/main/java/org/flag4j/core/ComplexTensorExclusiveMixin.java +++ b/src/main/java/org/flag4j/core/ComplexTensorExclusiveMixin.java @@ -26,7 +26,6 @@ import org.flag4j.arrays.dense.CTensor; -import org.flag4j.arrays.dense.Tensor; import org.flag4j.arrays.sparse.CooCTensor; import org.flag4j.complex_numbers.CNumber; @@ -89,40 +88,4 @@ default T hermTranspose(int... axes) { * @throws IllegalArgumentException If {@code axes} is not a permutation of {@code {1, 2, 3, ... N-1}}. */ T H(int... axes); - - - /** - * Computes the element-wise addition of two tensors of the same rank and stores the result in this tensor. - * - * @param B Second tensor in the addition. - * @throws IllegalArgumentException If this tensor and {@code B} have different shapes. - */ - void addEq(Tensor B); - - - /** - * Computes the element-wise addition of two tensors of the same rank and stores the result in this tensor. - * - * @param B Second tensor in the addition. - * @throws IllegalArgumentException If this tensor and {@code B} have different shapes. - */ - void addEq(CooCTensor B); - - - /** - * Computes the element-wise subtraction of two tensors of the same rank and stores the result in this tensor. - * - * @param B Second tensor in the subtraction. - * @throws IllegalArgumentException If this tensor and {@code B} have different shapes. - */ - void subEq(Tensor B); - - - /** - * Computes the element-wise subtraction of two tensors of the same rank and stores the result in this tensor. - * - * @param B Second tensor in the subtraction. - * @throws IllegalArgumentException If this tensor and {@code B} have different shapes. - */ - void subEq(CooCTensor B); } diff --git a/src/main/java/org/flag4j/core/TensorExclusiveMixin.java b/src/main/java/org/flag4j/core/TensorExclusiveMixin.java index e595e2763..7f306ec99 100644 --- a/src/main/java/org/flag4j/core/TensorExclusiveMixin.java +++ b/src/main/java/org/flag4j/core/TensorExclusiveMixin.java @@ -275,7 +275,7 @@ default T transpose(int... axes){ * @return The result of the element-wise tensor multiplication. * @throws IllegalArgumentException If the tensors do not have the same shape. */ - CTensor elemMult(CTensor B); + W elemMult(CTensor B); /** diff --git a/src/main/java/org/flag4j/io/PrettyPrint.java b/src/main/java/org/flag4j/io/PrettyPrint.java new file mode 100644 index 000000000..9d3dc9a2d --- /dev/null +++ b/src/main/java/org/flag4j/io/PrettyPrint.java @@ -0,0 +1,208 @@ +/* + * MIT License + * + * Copyright (c) 2024. Jacob Watters + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.flag4j.io; + + +import org.flag4j.complex_numbers.CNumber; +import org.flag4j.util.ErrorMessages; +import org.flag4j.util.ParameterChecks; +import org.flag4j.util.StringUtils; + +/** + * Utility class for formatting arrays as human-readable strings. + */ +public final class PrettyPrint { + + + private PrettyPrint() { + // Hide default constructor in utility class. + throw new IllegalStateException(ErrorMessages.getUtilityClassErrMsg()); + } + + + /** + * Formats array as an abbrivated array so that no more than {@code maxEntries} is actually printed. + * @param arr Array to format. + * @param maxEntries The maximum number of entreis to print. + * @param padding The amount of padding to use between each entry. + * @param precision The number of decimal places to print for each value. + * @param centring Flag indicating if each value should be centered within the padding. + * @return A string representing the abriviated and formatted array. + */ + public static String abrivatedArray(double[] arr, int maxEntries, int padding, int precision, boolean centring) { + ParameterChecks.assertNonNegative(maxEntries, padding, precision); + + StringBuilder result = new StringBuilder("["); + String value; + int width; + + // Get entries up until the stopping point. + for(int i=0; i 0) result.append(offsetPad); + result.append(String.format("%-" + width + "s\n", value)); + } + + // Add last value. + if(maxRows < arr.length) { + width = padding + 3; + value = "..."; + result.append(offsetPad).append(" ").append(String.format("%-" + width + "s\n", value)); + } + + value = abrivatedArray(arr[arr.length-1], maxCols, padding, centering); + width = padding + value.length(); + result.append(offsetPad).append(String.format("%-" + width + "s", value)); + + return result.append("]").toString(); + } + + + /** + * Formats array as an abbrivated array so that no more than {@code maxEntries} is actually printed. + * @param arr Array to format. + * @param maxEntries The maximum number of entreis to print. + * @param padding The amount of padding to use between each entry. + * @param precision The number of decimal places to print for each value. + * @param centring Flag indicating if each value should be centered within the padding. + * @return A string representing the abriviated and formatted array. + */ + public static String abrivatedArray(int[] arr, int maxEntries, int padding, boolean centring) { + ParameterChecks.assertNonNegative(maxEntries, padding); + + StringBuilder result = new StringBuilder("["); + String value; + int width; + + // Get entries up until the stopping point. + for(int i=0; iComputes the element-wise multiplication between two complex sparse COO tensors.

+ * + *

Assumes indices of both tensors are sorted lexicographically.

+ * + * @param src1 First tensor in the element-wise multiplication. + * @param src2 Second tensor in the element-wise multiplication. + * @return The element-wise product of {@code src1} and {@code src2}. + */ + public static CooCTensor elemMult(CooCTensor src1, CooCTensor src2) { + ParameterChecks.assertEqualShape(src1.shape, src2.shape); + + // Swap src1 and src2 if src2 has fewer non-zero entries for possibly better performance. + if (src2.nnz < src1.nnz) { + CooCTensor temp = src1; + src1 = src2; + src2 = temp; + } + + CNumber[] productEntries = new CNumber[Math.min(src1.nnz, src2.nnz)]; + int[][] productIndices = new int[Math.min(src1.nnz, src2.nnz)][src1.indices[0].length]; + int count = 0; + + int src2Idx = 0; + for(int i = 0; i < src1.nnz && src2Idx < src2.nnz; i++) { + int cmp = -1; + + while(src2Idx < src2.nnz && (cmp = Arrays.compare(src2.indices[src2Idx], src1.indices[i])) < 0) { + src2Idx++; + } + + if(src2Idx < src2.nnz && cmp == 0) { + productEntries[count] = src1.entries[i].mult(src2.entries[src2Idx]); + productIndices[count] = src1.indices[i]; + count++; + } + } + + // Truncate arrays if necessary. + return new CooCTensor(src1.shape, Arrays.copyOf(productEntries, count), Arrays.copyOf(productIndices, count)); + } + + + /** + *

Computes the element-wise division between two complex sparse COO tensors.

+ * + *

Assumes indices of both tensors are sorted lexicographically.

+ * + * @param src1 First tensor in the element-wise division. + * @param src2 Second tensor in the element-wise division. + * @return The element-wise quotient of {@code src1} and {@code src2}. + */ + public static CooCTensor elemdiv(CooCTensor src1, CooCTensor src2) { + ParameterChecks.assertEqualShape(src1.shape, src2.shape); + + CNumber[] productEntries = new CNumber[Math.min(src1.nnz, src2.nnz)]; + int[][] productIndices = new int[Math.min(src1.nnz, src2.nnz)][src1.indices[0].length]; + int count = 0; + + int src2Idx = 0; + for(int i = 0; i < src1.nnz && src2Idx < src2.nnz; i++) { + int cmp = -1; + + while(src2Idx < src2.nnz && (cmp = Arrays.compare(src2.indices[src2Idx], src1.indices[i])) < 0) { + src2Idx++; + } + + if(src2Idx < src2.nnz && cmp == 0) { + productEntries[count] = src1.entries[i].div(src2.entries[src2Idx]); + productIndices[count] = src1.indices[i]; + count++; + } + } + + // Truncate arrays if necessary. + return new CooCTensor(src1.shape, Arrays.copyOf(productEntries, count), Arrays.copyOf(productIndices, count)); + } } diff --git a/src/main/java/org/flag4j/operations/sparse/coo/real/RealCooTensorOperations.java b/src/main/java/org/flag4j/operations/sparse/coo/real/RealCooTensorOperations.java index ead498382..eb16b494e 100644 --- a/src/main/java/org/flag4j/operations/sparse/coo/real/RealCooTensorOperations.java +++ b/src/main/java/org/flag4j/operations/sparse/coo/real/RealCooTensorOperations.java @@ -140,4 +140,83 @@ public static CooTensor sub(CooTensor src1, CooTensor src2) { return new CooTensor(src1.shape, sumEntries, sumIndices); } + + + /** + *

Computes the element-wise multiplication between two sparse COO tensors.

+ * + *

Assumes indices of both tensors are sorted lexicographically.

+ * + * @param src1 First tensor in the element-wise multiplication. + * @param src2 Second tensor in the element-wise multiplication. + * @return The element-wise product of {@code src1} and {@code src2}. + */ + public static CooTensor elemMult(CooTensor src1, CooTensor src2) { + ParameterChecks.assertEqualShape(src1.shape, src2.shape); + + // Swap src1 and src2 if src2 has fewer non-zero entries for possibly better performance. + if (src2.nnz < src1.nnz) { + CooTensor temp = src1; + src1 = src2; + src2 = temp; + } + + double[] productEntries = new double[Math.min(src1.nnz, src2.nnz)]; + int[][] productIndices = new int[Math.min(src1.nnz, src2.nnz)][src1.indices[0].length]; + int count = 0; + + int src2Idx = 0; + for(int i = 0; i < src1.nnz && src2Idx < src2.nnz; i++) { + int cmp = -1; + + while(src2Idx < src2.nnz && (cmp = Arrays.compare(src2.indices[src2Idx], src1.indices[i])) < 0) { + src2Idx++; + } + + if(src2Idx < src2.nnz && cmp == 0) { + productEntries[count] = src1.entries[i] * src2.entries[src2Idx]; + productIndices[count] = src1.indices[i]; + count++; + } + } + + // Truncate arrays if necessary. + return new CooTensor(src1.shape, Arrays.copyOf(productEntries, count), Arrays.copyOf(productIndices, count)); + } + + + /** + *

Computes the element-wise division between two sparse COO tensors.

+ * + *

Assumes indices of both tensors are sorted lexicographically.

+ * + * @param src1 First tensor in the element-wise division. + * @param src2 Second tensor in the element-wise division. + * @return The element-wise quotient of {@code src1} and {@code src2}. + */ + public static CooTensor elemdiv(CooTensor src1, CooTensor src2) { + ParameterChecks.assertEqualShape(src1.shape, src2.shape); + + double[] productEntries = new double[Math.min(src1.nnz, src2.nnz)]; + int[][] productIndices = new int[Math.min(src1.nnz, src2.nnz)][src1.indices[0].length]; + int count = 0; + + int src2Idx = 0; + for(int i = 0; i < src1.nnz && src2Idx < src2.nnz; i++) { + int cmp = -1; + + while(src2Idx < src2.nnz && (cmp = Arrays.compare(src2.indices[src2Idx], src1.indices[i])) < 0) { + src2Idx++; + } + + if(src2Idx < src2.nnz && cmp == 0) { + productEntries[count] = src1.entries[i] / src2.entries[src2Idx]; + productIndices[count] = src1.indices[i]; + count++; + } + } + + // Truncate arrays if necessary. + return new CooTensor(src1.shape, Arrays.copyOf(productEntries, count), Arrays.copyOf(productIndices, count)); + } } diff --git a/src/main/java/org/flag4j/operations/sparse/coo/real_complex/RealComplexCooTensorOperations.java b/src/main/java/org/flag4j/operations/sparse/coo/real_complex/RealComplexCooTensorOperations.java index b26305bbf..b02c28b54 100644 --- a/src/main/java/org/flag4j/operations/sparse/coo/real_complex/RealComplexCooTensorOperations.java +++ b/src/main/java/org/flag4j/operations/sparse/coo/real_complex/RealComplexCooTensorOperations.java @@ -191,4 +191,146 @@ public static CooCTensor sub(CooTensor src1, CooCTensor src2) { return new CooCTensor(src1.shape, sumEntries, sumIndices); } + + + /** + *

Computes the element-wise multiplication between two sparse COO tensors.

+ * + *

Assumes indices of both tensors are sorted lexicographically.

+ * + * @param src1 First tensor in the element-wise multiplication. + * @param src2 Second tensor in the element-wise multiplication. + * @return The element-wise product of {@code src1} and {@code src2}. + */ + public static CooCTensor elemMult(CooCTensor src1, CooTensor src2) { + ParameterChecks.assertEqualShape(src1.shape, src2.shape); + CNumber[] productEntries = new CNumber[Math.min(src1.nnz, src2.nnz)]; + int[][] productIndices = new int[Math.min(src1.nnz, src2.nnz)][src1.indices[0].length]; + int count = 0; + + int src2Idx = 0; + for(int i = 0; i < src1.nnz && src2Idx < src2.nnz; i++) { + int cmp = -1; + + while(src2Idx < src2.nnz && (cmp = Arrays.compare(src2.indices[src2Idx], src1.indices[i])) < 0) { + src2Idx++; + } + + if(src2Idx < src2.nnz && cmp == 0) { + productEntries[count] = src1.entries[i].mult(src2.entries[src2Idx]); + productIndices[count] = src1.indices[i]; + count++; + } + } + + // Truncate arrays if necessary. + return new CooCTensor(src1.shape, Arrays.copyOf(productEntries, count), Arrays.copyOf(productIndices, count)); + } + + + /** + *

Computes the element-wise multiplication between two sparse COO tensors.

+ * + *

Assumes indices of both tensors are sorted lexicographically.

+ * + * @param src1 First tensor in the element-wise multiplication. + * @param src2 Second tensor in the element-wise multiplication. + * @return The element-wise product of {@code src1} and {@code src2}. + */ + public static CooCTensor elemMult(CooTensor src1, CooCTensor src2) { + ParameterChecks.assertEqualShape(src1.shape, src2.shape); + CNumber[] productEntries = new CNumber[Math.min(src1.nnz, src2.nnz)]; + int[][] productIndices = new int[Math.min(src1.nnz, src2.nnz)][src1.indices[0].length]; + int count = 0; + + int src2Idx = 0; + for(int i = 0; i < src1.nnz && src2Idx < src2.nnz; i++) { + int cmp = -1; + + while(src2Idx < src2.nnz && (cmp = Arrays.compare(src2.indices[src2Idx], src1.indices[i])) < 0) { + src2Idx++; + } + + if(src2Idx < src2.nnz && cmp == 0) { + productEntries[count] = src2.entries[src2Idx].mult(src1.entries[i]); + productIndices[count] = src1.indices[i]; + count++; + } + } + + // Truncate arrays if necessary. + return new CooCTensor(src1.shape, Arrays.copyOf(productEntries, count), Arrays.copyOf(productIndices, count)); + } + + + /** + *

Computes the element-wise division between two sparse COO tensors.

+ * + *

Assumes indices of both tensors are sorted lexicographically.

+ * + * @param src1 First tensor in the element-wise division. + * @param src2 Second tensor in the element-wise division. + * @return The element-wise quotient of {@code src1} and {@code src2}. + */ + public static CooCTensor elemdiv(CooCTensor src1, CooTensor src2) { + ParameterChecks.assertEqualShape(src1.shape, src2.shape); + + CNumber[] productEntries = new CNumber[Math.min(src1.nnz, src2.nnz)]; + int[][] productIndices = new int[Math.min(src1.nnz, src2.nnz)][src1.indices[0].length]; + int count = 0; + + int src2Idx = 0; + for(int i = 0; i < src1.nnz && src2Idx < src2.nnz; i++) { + int cmp = -1; + + while(src2Idx < src2.nnz && (cmp = Arrays.compare(src2.indices[src2Idx], src1.indices[i])) < 0) { + src2Idx++; + } + + if(src2Idx < src2.nnz && cmp == 0) { + productEntries[count] = src1.entries[i].div(src2.entries[src2Idx]); + productIndices[count] = src1.indices[i]; + count++; + } + } + + // Truncate arrays if necessary. + return new CooCTensor(src1.shape, Arrays.copyOf(productEntries, count), Arrays.copyOf(productIndices, count)); + } + + + /** + *

Computes the element-wise division between two sparse COO tensors.

+ * + *

Assumes indices of both tensors are sorted lexicographically.

+ * + * @param src1 First tensor in the element-wise division. + * @param src2 Second tensor in the element-wise division. + * @return The element-wise quotient of {@code src1} and {@code src2}. + */ + public static CooCTensor elemdiv(CooTensor src1, CooCTensor src2) { + ParameterChecks.assertEqualShape(src1.shape, src2.shape); + + CNumber[] productEntries = new CNumber[Math.min(src1.nnz, src2.nnz)]; + int[][] productIndices = new int[Math.min(src1.nnz, src2.nnz)][src1.indices[0].length]; + int count = 0; + + int src2Idx = 0; + for(int i = 0; i < src1.nnz && src2Idx < src2.nnz; i++) { + int cmp = -1; + + while(src2Idx < src2.nnz && (cmp = Arrays.compare(src2.indices[src2Idx], src1.indices[i])) < 0) { + src2Idx++; + } + + if(src2Idx < src2.nnz && cmp == 0) { + productEntries[count] = new CNumber(src1.entries[i]).div(src2.entries[src2Idx]); + productIndices[count] = src1.indices[i]; + count++; + } + } + + // Truncate arrays if necessary. + return new CooCTensor(src1.shape, Arrays.copyOf(productEntries, count), Arrays.copyOf(productIndices, count)); + } } diff --git a/src/main/java/org/flag4j/operations/sparse/csr/real/RealCsrOperations.java b/src/main/java/org/flag4j/operations/sparse/csr/real/RealCsrOperations.java index b0079e86f..7af2154ed 100644 --- a/src/main/java/org/flag4j/operations/sparse/csr/real/RealCsrOperations.java +++ b/src/main/java/org/flag4j/operations/sparse/csr/real/RealCsrOperations.java @@ -137,6 +137,9 @@ public static CsrMatrix applyBinOpp(CsrMatrix src1, CsrMatrix src2, } + + + /** * Transposes a sparse CSR matrix. * @param src The matrix to transpose. diff --git a/src/main/java/org/flag4j/util/ArrayUtils.java b/src/main/java/org/flag4j/util/ArrayUtils.java index 5b1f2d32c..24afac953 100644 --- a/src/main/java/org/flag4j/util/ArrayUtils.java +++ b/src/main/java/org/flag4j/util/ArrayUtils.java @@ -54,7 +54,7 @@ private ArrayUtils() { public static int[][] deepCopy(final int[][] src, int[][] dest) { if(dest == null) dest = new int[src.length][src[0].length]; if(src == dest) return dest; - else ParameterChecks.assertArrayLengthsEq(src.length, dest.length); + else ParameterChecks.assertGreaterEq(src.length, dest.length); for(int i = 0; i < src.length; i++) { dest[i] = new int[src[i].length]; diff --git a/src/main/java/org/flag4j/util/ParameterChecks.java b/src/main/java/org/flag4j/util/ParameterChecks.java index adeadc2cc..ecc04b8a9 100644 --- a/src/main/java/org/flag4j/util/ParameterChecks.java +++ b/src/main/java/org/flag4j/util/ParameterChecks.java @@ -384,6 +384,19 @@ public static void assertNonNegative(int value) { } + /** + * Checks if values are all non-negative according to {@link #assertNonNegative(int)}. + * @param values Values of interest. + * @throws IllegalArgumentException If any element of {@code values} is negative. + * @see #assertPositive(int) + */ + public static void assertNonNegative(int... values) { + for(int value : values) { + assertNonNegative(); + } + } + + /** * Checks if a shape represents a square matrix. * @param shape Shape to check. diff --git a/target/flag4j-v0.1.0-beta.jar b/target/flag4j-v0.1.0-beta.jar index 37658b10c1c992ca6d7bddff8f366bc4c6d77bb8..24705ef7e7d8a5c0d58d9b82d12f03a67246b50d 100644 GIT binary patch delta 75423 zcmZ6y1yCJN^d$_z-QC^YJ-AzN4ek$kxIf(8-QC>@!QI{6T|yw(mtS_bzW?sjRGsPD zcTV5#>F%1jr)FT4IwzI}Nktw45*`c;77R?M1t9^665>DLd_~i4LC^vF9|vxl>K|~d zq@T;sNqXS$5Pz$atiU<{VIDa5KU@W8|A$Cl7$CI%*5`o}r?IHPA^(py{xiFL;rZuQ z`-Scwu76?r=WdKZn8X5!og@eW|F0Ya!Jgy|f%3nvMgRHEL5Tb-&q1)G0i9U>|KR@; z>m*IU68vKbgGBx3l?nOvALb(vrina25dS}cP(rc&tJa3%`bQoQCGZcYp``xV}N&mxAxa9wB=Sr)Ig+oZXMf_i*qYuZG#wrR2 zkMMsU-+y$aa9pYP(5OlNNbpG`u&7DP(D-SnYcMeXPpifVg8#_#5hVWMJ0eTkM+FRQ z67gU1|9C`^{uyA>jId$h{>BEMCM^z!nM44AkOq>0!9aEXpF{t@`oWUMRdfMNq%kwj;!lqy@0MdOQN+z@qV zjlHI1RW?u|4J;7&$FP$rxNSrNGe69ZcqhEJBGg@Gi*sF;YfWJT30nl*t=8XHBNng8 z;+-&EK2Ra~)?fQYr8oIc79U&4V4ai{aZsqZ_Q1U;e1Cgfbe>)WZTG;O(zI45UFjto zmsaoVh!{M^d=w+eCvtBt3{1b>l<-W2h?L}I+=!I5Jqu;Ug@3>OY&&aG(wXZ}MXPU3suz|Md>fk&)zIH)Y~7r2Y-h;ZiHwf8EWsSJR~V+uZ{JFfhvhvkEam za2{$aDIal+uWS3pfqj(Flh=a;xLHh$;N8aAM%V;0eX^qieyd+}*b@~Hr`8i|bk;e& zo5V8Xn`Py=4^ zKa<0LMHF(Q^h~x-WF#1z*=45W@URHz5iXg1;T^VZXlzxwiWIY?-`nn`Y4t}yzQNfV zANeAknXEl7K~?As8wBI6QJqPym?rSXCUFfjcBV1>Q!)>^F}?x*CXEK^W=D6@39%LF zQnQok+iHw8?**0I9G5&_KE#Kw{X4#iv-K@(=NnTS$Ks>21{!Eg1^BO-L)r`&_zFeO zt?n2^ahInn;mLrOD*rqJ6a9EeVL3(=%lO zW@x_@8q`PiutVTP7|X8>l#Ja-o;aynl`pc9Ai$nfkVVP^cwk0Jsp;VVs%mv`H6J`AMFr%&g$g`Xj{`rdOht0*aLnI@u4z!*j%+RFC-*>e5!I9 zenP^i(@kxOlLEL4F3yW~%rrC$-fS~kdEEeg^AKh-0TZVB2eo#!+en}E*cg6pV-Dq0 z*x*1xW2cIRxh%IEE`dUjV5dfLTM62xN&U>LxsfVy>%{5ALiF}@c|kp*8Md_GmbmuNu+i%Qcd+$O$;7uT{`Z~)tyjb-m2X!Q@97R@_OY93<1B>P* z*z2V5t3_iI6mPe<@7NB=(iTlE!(Eb%-#gt}t7?5=txo6AB&^awD@+3o5O}S^MiRX9 zG)PU==Z9F$B*sW+M5>Qy*!)&uUQ_jCRs0rEv0Xn^Vr@2eEFsAgMNrP+mYG(N<&ggTNIFTM&1&OmvZBF`2LroV!)K+K54WRz2;5 ze(lYmqz6b+W=DM0cbc37^`sBf!+$;S-Yr3~g4@&b-bkUu zpqPKIO(iTC9>ytHePHWh=8_uIk*9(hf#0V@v8h7>@Aeon(CzKKE#G93wY2R-M7(gv zo4e~9ROAt@BpbVz@b#W|1>2fej&_W;X#Dw?uwaZOCm}}v4Enir;{r2*;#$?V4MP(j z&P_`R9vUvl^>_kyDa>Iv3qKbp#*oyGNK#j>B0Hrdo8B!iOZh_D#ioa1!cTq#h^3V9 zV{5-Y?dX+Ze40-Dj*u|EBj-B?IScF%20yep&ZtFX%xlRB5)lnB5~muE)m!(^mu{D* zk8SM0iDMUh2Wt<#kv6JY+Y!Q*7~oS!1JhT|&srGW9BX-dGhA;WvAu(Fp;~E`)jM{XH_qN^PycPq~rr2Q-j*A#^Dvb}UoY)GczrjmW$RbkGEpwY76odBNUId$h8k-qNoZ zh#U)EoX@Z6^|3SQO_;NhI#g(RC?tEPNFpnD%Fidp8Wmh=6DvXmta-U`69!6vtFd3b z7i%}-`pHosDwVEgP{F~@9SI`f@hMYuyXY9yMFgAFX(xnxt@c(H`Z<5M^DRc%H9bOk zD9h8zMXfG}Zp2w}%j9t-?2E5ZUpUHV)OYLWme`%$&-QBk#GlfM_Q(yyAQiE|s4|O$ z`;1r)axu%~DdVOAl7u9VDp7n-mvM3y0eUt~#>S0yI;uAQ1i<i^Gf`z8MZHE$r1TP@Pp~|IG0`-al;=~n1a&H}@ zWLu$W-(C$MYbc%BJqDON5efH07O1fV63pk8NU70s&GB!iREX+clq@ND&O#y4uEs^aDRS82|wGV#3-@1O3>Uz(f zw~Ucc9#6m&Baonfd8yO6_IwNQ_qC;yxAoCmJY8Ked0fB$wiCsJ5M2i9(J2zvKrWVh zj&LuLJG+EP9SuBO(XZ%G*r)q2DqE|YBkK=TC?4|DM+GM7|M9eSCa9f5O5~A7?R@{Cf8{hmyQKTg?FUY zAKE};!oy3V#WvNa1PZ%7{4;hh{ijFZnuFK@DzI`*?JzRIl(voL`ohKJ;Gk)dj_eg5 zRF*ssHRhVjy9JUFqp_1(ENG=QkC|z}jtKS2GEYH&`ux=Jk5~c)JQ$tRqCV3unn-nt z=iDWc2$-0LwrCHtW2aKjH1+poo_6Q8mMxYFnsk0Jp58+!euE>q`7YGiGuI%!c9?4R zO|Ap>2k$`Sfcg2o0#5FP{)#TCZ$VP^!#-m4F}Zi@#jiWoL!F2g#ryb>u{qXiMmMx> z-Yd*1U0_D)%JB^d9)Ipfy(}k#L48;9M%A#7G>P-h`5^&j+rHIhpcD`y9b89g7f|rS zF|1>{&TqQKkP)@X$)o}yr10moFmNb*JjUMnP`%r*ZqSpk4mkxNU*8^vqy?wS2tAbHrg7R@ zAG>fb3RJ5HX)38-$40Y=RXeOx;Zh>Iid+|7WGb zdf`H2-P zKpo~awfcKZ_qm3dIW3%JtYxgPv=%s?2+lT|R&G|9B-4fD05AqUloLn)H#?augoKg2 zmAjK)xN!uk!C8)I_ELEEd)hr%fVa(njTE;iod^EoHD#CrxZd_$fdj8=Ga(e9Sz1A+ z@C8#*KxJb9{}uWl=R-jz5?nsH!<0(w3f@7MiF4x z0V&4v8YLqdhZI|x+*UJ6+q?HQstlh)gvWyHbmK@&p@wz^_W=T&UyrmS?p+wTs!>xmx@Vt=tR$;-GCb>%JKkDlQOs&(`1W^@Qt{xKijg-0_b=Sag08Jguma#Htrf) zbp5tAvlRM%$DOHbrzF-nZ*ym$unu^m8Bog@9*k;LUR=D6-^;UzOcSptv>MBRLEyS--JWlkdRf>#;Me6hr~KdN%4DpKi_rjM^prFnY7BMht02?5B$bK zQbQ-zPhZVX2+hxTv_+A>4pkA&AojpNLDv(0q`)=MMBD^oq`8eSvjGEjhRKZ8Af` zd!2M!vDhFZ@M%SToy;qkxCOXe-VKYHJNQHd*ELE))z1tpzU+UN`h_b*Jfm+&0PU`ud;vw^uNzabbeLLPegTgIIb+!b9BDp_%o7J&> z*!@9WKB&EqZc0fp45G%xCc>< z2pwE|xa}ZGH}ituNSTn@CXtPj;rUe$Gf_j)AWQ~4im(&q!Urf8XVfgDplpVmaar}^ zTnJ9UDAq>DVVEV(uxIVCeq4Z)GEAyhXT$Kp2=L3Vcd)5Os4~%@ zxD|SM8&J3I=M9H*xIT{eh=|k(O8tcy`F7$SX_Iv66Kns-qf_E$v=JU!GDLnAD+V+6|Tz|_LmdhA? z?g96$4>~(Tdx6E7QMU`S;Dl1s^DZ0aMa^o*Q8G&ax>>i@yEjAqH}Y)AS^Z^aT7~-j z19!?0Hx`Ln!Y?`56D*oQmK1x0j${RkCQ=OU7X6T3qb42RWFSmA_0}aJOp;wApb@m1 zGBiJ_UG13T1GGqD0csf^m1}6rvrvO;WalrLg8k8Cp9Ncr!47W&YUK~Jff2bw*x*CN zSH&HmyyCO#G2eih4k1k2&5xAPw_rbwE`;S8d*A!e+5)F$9F0%%$4Y09sm! zYhY@$ZkBaz^=igHU$-Zbv!?9WBR*`$x-&d)e*d`eUAg4Q6YfO$Nxs5Lq8~hVC!x2r zZdDH$)&XhM+&#rwc`RgVTYAg$CRA4%6haHP!>yk${ersfKM~K3^}$4qJ!{}ZtCe$u z#2CBHOf_QH*RVC>s*;`mh=ttKPL_cW-d5Nz{v75|i&GWQzS zIusv4B?&#}MU)JtU|)v9h}h+mO`@izF|<_?y#-O46ZDr8zTz11BL6lHjx~v<#N3!B zN3=z$Md2w!Pf+32>2;H}$%^dieoeE_@7i!G4$^;bxGV1=;4f@-K!ze zB|Qke#wMInt(z5(kEi-nT@8YtUS-UsbRR*|Fu1XC3A$v?sJh0+dO~M!d2!Pz%Tib! zP2U8QKXzHQrZsBFw5mVi*(Au8%+UpWcwd`{D}5}{A!gXL`#rqze%qhjyET^21n@(K z5z`tAlEnhYh(DI;=NH10fjfR|6SM+aZ$1!N9aDB?40ICX<$(8YRT$$Be#WOgNTTmQ zBZ58g(Bs^LG5XXgiJK-%xQLZ63d*QhwrBC8?~%Ra@YMdaHiR*qu=jMtQm53Rf9owj zpyaHV37WG4aOMh&2bbg>Xu7&KX2eqQr$&DGF!q-k+4Tqt=tyH^u9a$QADRF9brcIi zMR0`Ie0HpiU8qlFB{Pj_>^JX|s29qHr?FWH(OYRcjMV1Yldyrx3s>=F#N3vkojSrj z9Kf)T}n;u3Du-ADwA;YIcz|Tg95jr%^scLK9^^K zV|x+zb{|baeY8QeN5)cULfhDyp0qY7IZ1HDUOt^ye#EPO;)V!?o4eNzadXRg&h^b=;j-4i3i*)!=!d=)1!x$oDAaAXDPE)9at z58Wz$Wft(G-=TVww1zo_ZbmZ+>sOjGFcSom7!>9LZ0FBW6)meM)y{NT2l;QF30)GOCXk2zZZ5BmVXUq+#-1eDUBlqE>-M&5HqF^06CKB_|N=SoJ}sxPQXt z7eeiNx1Ylh98oR5%;*~CW!G|Pf!oQqK%D0pUX!b zSqiq-YF(%8E?)yX<4}osSvtN{a#VSU1wYrbK8X{(-cd{o_s=g1aHv& z-tdsKdS)wl|GYC>y{ZNs(D3J~W*p!9Fa!Nc4^BK%O{Xe{6y@Qh`59td-o!>8o=fP> z7c)+5X1V*#FZQ6iPY2}r4TtNzkE`4sYW%;GY>YOi@P*F_ch5JCPosT@za{9VraQh+ zkebG9QaXwgeoKY$(>!N@G6YB7MFPjmn2C-_O}qn)CGYI9w@!jeYxSrkcS#Pxx+xGs zWw@U#i9mhdW9%js7^!kss$4EH-wZ~&o?&{q_dAjif*Z_#`I>p~e^ea!zD1=Z!DbEp z4%BDlZ^;53hzP%Fjf6dyTQU^p4LW*~Vd#4l;|FDXINc>^S(LsB z`)qy}@6%TE|J(zqCA{b;(s3MA7`XsDBUt$jR$5`yE-JAl*VAtu zvk1ZN<5#4GbMA{{35QAGVfuXG8oXL)x zmL@XkWc2gaxJX(NmY0nEi@780CmE$^>X$_c{4waM>{XyvnQj}MKu?`@Mk6$cP}8@)5)%;$EuGEAJ zzmD7h*+n~l6Jc?;^|CczPXE1JTLG+J*jn10UZI*RzhZq!+ah6XZHi@;i>_kX0|&G$ z@GB^#^#BZ3Bq)s_IIn_2RJ5SNo;17d9J8>#*^+OkGRl!wq~WuAgwKbd>|1jzgRW(w z6S7aL(uM5$Bw&7%j$vZIBknQWB+-m6!}YXT6f-ezT-_xxN!4VQh4&nnPqx}+oi^Q4 zKKGCoYvqhkr(Q|w`*C*gH+KH-QkD~^VtAm6Hk_uTd8$hDWBm&c)l@_J%AL%qvIY1h zL#7Rh9l1!YQ7ZwQDqmZ_p91=H?Rw@eE#X#O(Ld;mh}QT~y;onen~|6SWhMRgco);^{gePZ~ccv_?ck`iL}hDS?b1tQt_9)_{9jTb?~ z;y%?Vw&8>Qp(V^be-Z}>_G|i1BaO((e;P*>rY#?+!ZY%i?>!=3 zJZE!MQdC6+@f*F?1Fg0&$5X@Lt9Sbq&(}>1gR;oSil!JAzMFa4+Kv@SW2bLwbTLFVaPKr$Rx6U#;}M)B#VYaaqbzKC#6$#YltKg<#M`T?}|FC z^*;GLKO2;$yO3U*2&sj*dbNx68%TP^EeXV@Aa9L)KUjcQ%*uL?jkG}Ikwy3!t@*zKBpXzA3D3CnDZEBPR3U% z<~4o>+{KHLH^kiiGF|}f;1i`{1lCk|>=X9KWDxgfTgAJYuwqAsCJ`DPTnGppKiLx> z>eA|DPPufEY(9pTAHjF?C8C=yU6?jFioI7;Wj}U=IwD_$tLI&?_CNn9b5b%>7^Y;- z=qByN`k7G(^9Oq8>agqRZF6X4?!&*-m!#NQS<;6Fnic$ zK`X{2RS^4Q%$*{pr8&wz?9HM1%`NIq)@$b&Iqm_O_{a1e4E>YF<$(}AN}ny)wTb)D z4+Gp86e*#AhN0`8{1mLA>!ROA`VZJVTfVnQ1)^%4(Z-BMaG^$YQoCl+(ipLO7j}$V zkCVGOQpW6C0TjESR3WDE>mze|-TDE%wLFRx9QkGxO`LC>-((bR%P`7AN zN`oyMX2)UF91qUy0|yaZtYld^XK6ZbgrmnNh{u*l4;X_I&H15q52)k2mXSj>+> z>Z%-*`BD)#deKxHTVrqI<8s^AXoRxms9D~SemL6NDLx!q-E&@viFCEjI{M#_?>y5d z59oMFu-Zw3s^y~ootl4yBCF-NBfW8NHd0^4yS!`Mf8TZ8&>r7t6^j^UG$_NFbcp;k zgX(m|1bvS)uIyqB`n;d2_Pv*`+Fp5pw0@9(zjwkJzIU~+P@u25?(e2y?eUC?LfW6Q zLuL`@Yu%&O59nBpmHNSbAUCupQCfhXlq?E6G{Iz;wh$ypUh*~|`LZ;deD7NF6frr8 z=P_btfx&`p5qk@B9XR6auuF$%o_hTHvXgWBSAT@g_1`|NJC(ZX!3GSZxHy>cZ4Sb` zV@D6vU@Ib;t2#jnNuWHq9qg9e+;gNAjtv|l9+7|L52wb$8ds|?e@D??KGsma*8JId zw+u;rW|+yKeC$bH?gPrVYwjZW_1gk`GtC&~1>5}PQ79n+-*t|ds?X>AI3X)QxfQl5 z0pv~gv#vn`f2)9*af13T0TKNdXT*Fk5!i4NH!jYE!w*En(us+A=v*u{6LUuQrS=wl z<%SVXT3}{Vq|nlv&5|N5?bBlWjnoHr9B+n6+XeFE8iH>LM@yyHAP+SxhK69erpul7W}z!f((_p zu<-y9w_byAm4c#;-4e`%S)zIbxP&Z|U~7d+w;fYY%EhDD$|{1N^z&y?n& zz`5-TlN=1NFMftac_0wB^3!EN03q@;TgM8Jf`ks_QlxrxW9n9U>~S=0xIA?g{eXUS z8*0GZM%wSLz>i0Co=+Wj3&rhJpF7nvKIvqSrPuv#bQI-qW-b__BUT|mlklIYYO7Y-AW#*P^j&=W-?gN3B7?bT6pZxC2uBJ^u8OM{o^XrTp&}CB z!93?G_Z#vf>b;DtZh7dHHMX2J_nVJUx6Us2%G?-H+22nAmX7P~-k{00xyx}2xgvPL# zjZ3O-4B{~1o_JOpm2kVA$+@4++uIT7c@a2lgwzR=>a6gZuhN4b6r03KSKVQI$GF%* zXO*vDsx-89W&k#-7`L*J2k(o$?5ufe*Y?f#J_hggbJ2OCzWLz4)}r5#Wh^`5e-S<+ zwlOY3G8U|n(SF3K!7vvhwI?Ua;VasOjyN@vvE%SGPbE%p z|J^?m@ZTk@2ZN@@Nx78ZmuETT)|a$JMa*%I`y?4#kh+&`q5ZB*sSnknA7vj&CdMg<**s^booig@0Y5JTH%3u*LyKWYjW#8W-CQpgRIBczKj_$aravO5D>>s?sP z&+L!zO$knZrBQtS-lx!sPBW{)n^N1C@u)%h;)N{I8(%xJ(^tTJ3%JviSSzoU=0bbQB*jmj}4KHs=fiaZhLQ0quES8dDzJn}FLF($ihu z4^+GcI=sw}6Dw=jv89AvD+rb*I+Mk36 zKjC0*uTN3#>1e-8%ifYY{2$I0OKZ3pQ&4FkdyOtFdHrt9f*COjn{l;ndY$OHoO-&` zlcFGbUF9w&p`+t6A)L?xikHy5E*lSi0zeYr=x)-Vm3u>j_&x{{!?euF-ye;fSFqXz zAyop7f^E-;bxua+OXV}JiB!n^IgGlS(=OTDV?2+RdCdhrqWjg?iVNN3uG#@M!Q89P zxp7gcblI+RGqXoN${Q}H_%9Lm6r(QnS~`FCpR6Nw&pbR;sih>Qm<^6%ReM>NURNh4 z+o!(l)Jmn8H_npp(Id_#f(|BjS2zb9*|@_M-gv#-Y{ywN)Oo*N2yudY$3w?m+A~TX z>eLOz?rrn@#yojo_*iHW+uk(C=W|qvuqp#Z`Bi$FA7rJz=vW0{>GtG^C8sl$i8XQ814<9{)$CH_lT@GO`PpcxRL<$-xSY12xXeL!6Mks z$iHX~45@TPxZ?&$ATktNBXbqGsQ{q1!gZFRVs2v3bx2I>B$YyDm1h@tA6h$iH8<=8LTUKH0#hVS{yh6>_ZdOb)>#Y z_Nq#K3#T~4I&%fW8_LyXO5F?kS);pTohirtc1P#k$Fj_;pz;k zyBR_luY!7t&()a!tB||W6l#O2q^Z8g&EYe;^9M8RGz$oA7q`Wm(^yg!6%&}K!>Os? z&>OfcWoYz2&8WLfUFx{F&KbY27%1~qcQtcpbJ?;VD+W?rbtpM7kHR4g& zqRBTHx&qv`Y<3I$?B}&Fnp-Vf-wxfXuGj6C4D@O`tA;AOG&5aSjz2)>wVwL!Tsp2= zgUP2;K~-I;kJVig$w5p#*Y28L);LZ6EXLpt!&X<{o*?wlW|>D6uHYAKHyY%+&}-H; zR!3JJo?oceTUHAU!U&o#m_$KzMUT4nFQHjX2|IQvhTogy>J&B4uz2L_h>+#$&NR;? z>s0@2EHpUfU->)`;emr986#PYC3AC-rcUkeITQJTQ- zunF>4ee`&UgzK`TW^PIw5IU`WV!T-t4LibOG1X89PD|Atmj}oxjt3-h2JZqu!-+W)DmWbf55gqp^t!4(+X^Rhgq+%qUQ|7 zL!S7RW|2wD-=`z#6bi?}32GkoTp1tgL;cF^Bt~q!#EB-1wfmO#^aO1Y@y`HWFu8^N zv2VRRBHS95+@+mXK)2t%7E(Uk1Zs~k#3;tn2EmUap@I<~Rwz0mGNU0fvv~@mMN{;1 zBk?`2{X(d|c;TRzTEu4RNzN2~sDq@)umc6t@7lx=RaRsu@vTaPFL z*ys=z#ymZi;5t)P%;$uVD$G~*`1Nk?>(1`i{t@feGh3cPVBXysp~$jZkXQ;TYm>-!Cb4(A9Btd?%jZ7&;@pK~MUf8bUo zf5O&!mpBU0f((j3Y-+`1CerjfZOf}*sXk%;FO8|~mmat??LU#pHW-{<;Gf9!5crE= z`me|Yr;rxM{)H6e;Gk}9@9f~jY-(rh?A)S<@K+=v+Ji?m`RCBx}gOsnuT=wD_^r#Zr(n z^IvIEtEAF(_45QfJ*(!-HJ4hJ=M|_38v79V@K5=p{S#mpFuVv7!W#tWEg9SKn)tBcnzQCQnQXg)M0NduW6&(oL3j8H zvt%UH*n*tg=C4{0adTuoP{0 z0*JO|zNGl#j*<}G3Tzrg%3KCvc&tf(01?3gOst@)?}k9%&jJm|+CE0el9pH+y5$1M zH&|UpMl&&5X8V?5$QTuA&x2!t1wot~-~s*0*@YJ4OK5*Vj0I&ky@Yat7+@`I5u zS(YY2KQ96WDzgJO1vmxns%d<_20o(^(56QPJj$g!7(qq|(C0X6_9Fj{#^P~^pV3%v z;R~qX=_|p^Y2c6{ZJ?xKd1w@;cI^PXc0_!ZV7B%(t0|W#g&cXzRTvAtwLwe0T+kA~ zK4KcFI`t{@rnywKHYs7FVkHwHb6os8HSS%dZ70%l6){FD_NSM%2#1nsx<=ur5*rniZ~>Utd$ov84rk>)}; z$WU;BpNKh#n!J6Bv&+VcJ2>0KN%iR)8pgSi5KQm{nr5lky>b{)alq^~UuGvL?al1&w;ypek2ZBWIDKh_2Gs0a&-J7(H5S%oPwd ze#}xqWKM+v3`TjFO>>*G2#m=3DEX123*2cvQY(eW82$w#1$7q-b?NzP6Tc@oSumY- zL}OrH+HGh14Hs<4*{jnC?I7prvN6mh<>q00^K>|Fj>Tm3q8-;pYZ7C}A)*CkYXD(O z4kV{L5@$fX8PDb1?x%|f$z_c5Y8ePm>@j^FhcnjMm5RW#VCDQ49GMLNZq_Wgm17dd zwVn8B4vbspI2(Eqoufr?SDgRyBt2W)D~e+z>NOmhr(b%ElCeWes$a@G3oQmu4D_%N zkz1Ovl7zr>=E&i*`7IIg0n;ZcB-UvUn@AY0Ezxoel}5*D;hdKlgpX|Hm<2*^8|Who zLEBic9l)$qHW08%wVt|fU@lULqgAxaj zn(}F2%4mON?*iW^XzZ1`{|{Mwo2g*aaMvGFrm z*7J&XAj#cU+=8~$v4tTA<-{|c@}DNrU+EF}Fqx}5aWm(R*nXlq`FNZH1f4<64uID@ zD4Y?}7Y4%*_l)=N4_lyxZlQOnu$}%JD{q|{Dy5u*;}fta*6yDZXq9giJMVC0&%Mr0 zG*Wr~y|;rRrf7!qd*;s!I2wZhfRQx5@pPO4U)66c?7byUejyg%hA5KZa~E>mfQUo^ zy$Q?GODvw$H`r&K?t;Ev*JqUOwO&|QXfdgJakpxOt9*$7w_?!OaM~KYMO_Zr9Gg8R zqU})ka$fGhzDy(D9~b1D*=^kgt*J>?%-m=R$G}4 zan>Ua)XUqfvq1!7o&}OI7vjBCS5p((aF}R8n&_RyY7j+H2aF{k8&TpL<{yN#r^BNZ zRZSqOrhp7m=d?R`1IznM@R=7H@L9x0m6rqXqOPzrjq0`t;VxNCEV=}7vqrhB47Q|3 z%*mOJmbK2cF;>ve>gc*T#?@-~Uo@THH^*HS_)$Yd-?YmP@Vk>Ig|TB7wmu0bkBd+V zT=b)2C;^MP@zGM475&Z5ckIH19zUCWUJz zsDVaML&vyr`H(X|2&>&x8ZheX=GX#Ng&ASx&rvN^;Hp$l;KsBMQ`3=WRJm{ z2v;1`D0sOs{s1{$l+m3GL5#UBc2!t*dkB~kOQfr2XVidFUw1~`^NQdRQEsAPn8O*wKWCi7jJE^Ws-j_sa#9LL_8YhJ(mxCh@nJ#1-tuz^s% zCFJO6WWSi9u%V#bZ)tf(N+%BVv7+#IuMYf-yES0JLlCClJ~zAOq;Y8{Qns+!!y}@y z@xV8>a4K&iu3cZkzKn%-OGgSY2tajcwqDR&U$N=G!pxCcf)Oh<@4u*l*k=2+$4$}R z7Y_N{W#=-~3Qfy6J!wV+k<${Tg$v?*O>8b3m91O*X4o~iyLl+(N42bcx@7?Dv!woI zkcp2_Y3*a^)V9oTKW&ff5*)4V9vq*^j=2VertvTwznnB7`85dkt|y8IaGtc<*fw$* zgYxRX2W+M<2K&ePQUI`;k?({T=znkSLm>t%-7BFM=$oD!NrkB-s|J33XaQxtbuJRH zyRYAvJVzP8wL>hg{lK>>Q@tw)Ds&&D7Dsr_&ategwS61H^|s;*91Ux2-Suh!Mwen?O@+SzW~0&*N$ z=8iA>UIeajC47pp|$Pw)yjIlxh2${eFmF=L<&xqLyWwoBh(8YX{LR@@2a+0~3J|=>zhhsA}lyt66(WTM&mu0H*Gb0@rjypGx zZTaVmZ6``}Tc3ve1=XNP3`z&*c7b_|T4YCh_Ic>^3HUK#@0Iz!MNOW-7_*9=4dsKhxyTmowqgk>v-4i`kv6oWqLTrL#v8mc=xCKx7cqKJl-94bLDtgyC8J_qDg|KU- z-dDMha<;&}UP4si=@7PtOlD|a8?G=wTD&N2MQ*;L-+zPh1AdxaCzJ-hxPgrolyMw1dniVo6! zgZ3q`L>h9~Z}SIz^5lYqWNt@$yAm*PcS|e4rC#MvvUAl^iM^Q2#3>H@`N6N+px0)L zs5p00`o6H;S$(|Y#~l3>&y_XT0?|d49@r z;CI&{)^I)uveTIO(w}}64#@=&x@8igCL0Q$9;!UhBewtRNq6M{8CuX`Gd!rwEs1n*_N#;tgk2~$zdGU3vRa(_Vn)>GS+%M>$} zQvMm5YI>XNcu?Sn#2LrVv-~hwfm|8gK<-bThpRR8xG9<~{fXs# z>KO)_S%A>1xp@^V?zqVYW0Buhl{*$F>wSUNu}_QNP%ePnMK$Z&qI~T!Yx_Om@{B$i zGEfg2`xD*+jJc?lVVA5S*Cx@6IeAz4&a!!5tQ`Fhc4~mgh~-%(lxVuNn?e?JGeVRm zYztPYO0V!nt5;5gw-A*p8_c3JWR>-7r6?Kb9nJUA9T_{YtWL3{^wZI5_rX-)QKx`B z499T1fNr&nSUxL`s@)_OfXUa&a2#)}*FY-`4UI$MI|0XB0JKxu#+a4EAPjP3|M-m_ zJ#Bm74e+TObieEHt6X(WU7Z@M@5R-(6Wma~ym<#T#cUaA}dty3^51E zuH;Q><&^~z|9=2!K$gGlItX5$r_y~NWD6Vmwa=~G1Iwf(#eKkvDt%rMT;j@iS&w|~ z*-d>pTrf^+NzWaWTJWIr!`5qc}MZQNqENhmy@Vb>cK@{$Rsde2Wxhfbyh;xE8h-`&zY}GzQ>cHHIDZ2clfkr7wCRBV zLKNPiU~vv^CiV`Z3J;4}?!vb1=V%!EDlFf&0e{b7oUqx@D-UlwPs+KTHRTjDC^Pxquki*>b9^Jx@F zTGYxcwKCh6T}W#8WeLS=6~64b`7Zj{dUa*izHAQq@jf&1J>t19E8k5Wf{pT~OLly2 zpGKee35V-v970ij`dI_~)^h^!kPkW*Kz|+TniZ zMb~yLfllQv6oRhB7wFDSF=wZxYoV_)@SG#yEPt_e zn4IZ4h++RrhfdXoF3w?!>zY;hGf_QGch3h$(8d*Jg&Y3+w531fEg?MZEk9m5VC zf`w$29!U>vk`#ih=tfaZCNtbpQBc?mUlf7uj2%3ayf$!2!IKHMe9Xd(+-NSj)GYusjUDY3c=U*z2Z=EDYji6V;|t|iiLrLi8FJgIMyAn$;W6s1u%@+O6~ z>-cqsWYd&v9$+??2{H?b%zx6;#O9YNYJ7$H5+boA3Zc=(>yA-;bZAfPDuAfq&22B)3oqeqNAV z2A2uC-Mo66?gRKTSsYU9Ez;qqQ=amo*dzTA6ePPS1Xv_nVR;(3&atlxH!niTG{9R> zN_C^H2l z>uGRa6MHe^9B|_2d&xNG(&GGG^6aShA0*)@`XG8gmC7^YJd=!5FbL15Qh8>apCse> z2jTf_ye#Rjub(I5EFRPj9rg9gWSmul=;swbU9#L$G>Bc7VGR{+j$n$clCo<08l5u`MuqX15NF>fOiIYus_F6$N z{4*Kq#RRBq8!8)L7pV&JPnK*4K+#LVWQ;cwFccd@!GC`U3>W_tN@C0r%jB4pgrO=4 z1{23X{uP!Sc^UQdh=r6E^YO=jk0b$PC8VN>3;Cx^MYHi=6kn`mz99}U5dTg2x&?nd zrA|Du+)aF+^OyFZ+AxRAyBD>!CvXH6=ZS`2rdE`>Dvsf(q%$CO47k;?kfY|oSan>2 zK;^bT<$sh%a2b+AS^0nY6p9kNLVQb}M7|FHkOF-{hKh^)JvgQZ$DP#b?GQ1ov|p)U z$A~5oAfDqR3Q;M_Q;LK#L7hfL<_ySFXTlu1R;aV>AfZzw6%P^@NpZcfNSsLM7e zUH}u-#k9aBuv)ExdUYwhm#&6dZJ%P1sB(!eXv4RKon}$S`Hmn!hgLi%((=);LE-;j zwSSA^Y=fdGDv_A2xD>a{xqY;7&N>fky;y$&a$7VG>>i5iT4ReltFgu7YCMMP>a~+v zi#n>Q#g&ImO)c&`T;J5<$-@mz4caLvYEi{7m4>-!7+pPTV>4lJE48@X39W9?N-Zv$ z#_g7^o_?*Gn7Dau-)Yzq*TeXpd{+-%)qi(zKAFn}wT8%B4O7&MVX=A%98lN5A+?_N zqXt3NLTh=7N8!?93Vci+JS~QZJkL5{AEX~5&w7o|I&y1qi;^Xe)GHE8$R2D@KH$0_ z!SQ7Ysbtgr2(tcMi2ozVZHiYy&X?(hMvy(Ybs$770Wn)iKnp23&H|2SCHpB42IV-8jL#>T`s0lhDqJeN97bLdoXrn01SN~#`icb zXjf)3?NvrdndaGhSwRo}-$0{13DUSx(z@4Cifc2I!mW%^iOZgm`dOJ-hpN*Uv{gyeIt!IyAK8EXUCwNMY zYt9i`ndk&`Y#2ZVDM?*HVd~LJX4~rRN})tsBsb|C5l%R-J3bI%PTDkx%2)BT3uTfr zSzMcUu7!}jP&kpY8<)vVUY z_N9@A=C*LFtTDuZp_Ct}i!|1nl}L!gNe&|zc#31>jxu006k|@*lwp4tCaG+R0i{re zWQ3cMb|RzS!mXigp>cl=k#Q@+tqq~ZhOfOmydO@tM_O^z`akC{0D7RwNlp3?-A}Y36=G9_fVBS(#ro(arR=`RIBU~k5 zYUnD&MMQt~isf@Hsum>Zr;EN#&!h}dvl`auaEbwI;Zz2*<0?g3!mXjUhDftru`b#= zt`*0Q96&b8qV|8rwuY9*hB{doTQHP?q)>t{zz78o=iKZ-Lc6oB<`nhvKEQ)e(( znh{fH)J2+F8pAtG=FGG!k1fZ}P<2KeRog60fsg?kp$-RFTLhml7*(91G{Ue+hs{)b z3xnaQhFo>bSdC7D9iuB3?e)8y({^hLZZ}u4C(&>Xcn$Gjc55QXSVXU#EV#fWgAlRCjMc=i+>`BLEk{ z#X4LdB=orv5l|)D%Xqzj{l!?o1rx+32-~TicdK zq78p-4co%za%gn`_QAb6+-E>vxSzqG)XK!*1h=(LMl;rf20R20qi@?5k)20tr;I8- zVn7ERK$@GdqtWp7c&>9G?}JBjafPv!oQp#S9EKmEw;$&etc=85(p{=16DR&mIzPR0 zkfDzjghvfHO4iI5ZVWfk0LTR&nXhx;C&WC-PZ?b1PIL7!6K$LHOdZl7JWdo}K$F-L zlzK9)U)&ukGo3g5ri^|`GWwN^jE=i&k*SRK!EX$B8h(qH@izh-fA{db4lfw+2Y3;! zK^H0(KsR4&YG|hAKf=}0GW3rI{0Uyh5x1$K5q)(pu25^pT)YZ@*5NM({1skfFwkjr zSk6e=OubrSb)g!=|Q#pNyjN032yi=q#2qd$)2WX#0Mf5(7#X$8Yp z(%pMx1l~v2KkZP=e`w@?V8Fjf(!8ye&_6WbBlr&rVpGFL2GcUMFv`yPgb4kV!Tg>( zfKIRSbNE7sFNxx>5{b6uz8jsn{OY0ECB#-3h5$*l{H(p&_vjeEv{Qrg171wA1 zHCp(;a=PLg9%Qh=q##}0ygag<9t@=i{U|k@Qu&k`NvT2_6{8JS%*L3(m`EgDFeVnv zq&N;MHCP$he?1R+?{#NVPC4eVacS24Hb%w`O(0lKsY#TYoMs7Yhkw$v&?UVJHdSZS zND?Qc3@q8!Azff84jieTZm=p6lpbo|+!StZqr91z$Hq}=7NsP2b0{^LQZ>ZqTo;Ej z?Eq8?@g#zrpSEwh3wtubE^wJs(hnfDz!nkc;`H6ze?4Hflr7WQa)Yg4D-%NND|SZP z!c7ePvTj|ZWha9YMaaBXk%bcR z0NcpIe?-+L^f8KQzS+VWbhg!CXR^iwF`1qOs`0i^V|#eXCfZl1QMejeteHi0)v-1u1HTHG1Nttbtwov2T*e20{n0MQRE-1Roo4Y8u zkbOgE7a8ng!tARm#Gn^Cn5#)db9aR5V#a?fVm^*dp?W|c&TK3Bfb~%?& zI|3Jf(qLDy@1VX!EhS9pC)o;^Mor^ZSs#$DUTv^z*tHCDO93=xX+T1FmB~I1a8xcUJ4`+0E4Kp5rjoLib!)+Lr_07*g5HDA5&b@jp6+x8s0}3R2HvGw%C~t;wkJX!92!bdIC($K4y;d6TD^IDHn zt)I(U>E_3{T2C76e<@;}EF1a6nDtA_dW=%PrqoX<^)#h^PO0A+>>2hf1;uTHo5mBd z4Q|Fn{hr!*KBeE(eb7G;=!*=hir1-nIdh;t640L*%t!>X`#E!@R|x4<2BnCUMqd-^ z{e|lN)vTA+8M5omXRjOVZ;awNTS8G>=+=j=vm+GbVQ?-=Y|_78OZ zTEk6|ZDCXovJ9D%`M$ya$v&VX9I^UQ3VyB29O2&v`!EiHPS6C{f7r)5`@~?Mvd?hH zcFW)`3N<&hv^U09{l4h-P>V^{m<*i;GDZJkUl{C5YFz?IsvyY0;EZz|N)6GKtqlvM zX*!i22!ngNe;%x&EZyKf%JMZt&1pUW`*^_MS(J&UcwT#BoN+4u?jvCClNl1LAC27k_l2QfH{Rd6yRfciOx%rOJ2rcQnyqr zc7SKmadWb2e4@c8QG`Rs0&Q*K zX41_me+IAMQ!%eKY#k$;(VY#XB>HuJ0xkjL3}s_ucyp+6cI)PLTJX=^Q5S9@kp}p5 zUZwLH2A|1KWKiUcQ_pQ}jkGQbN28(5(qTc5fA)@sC}uP0FBfug)_4Ur-Mo2vfKTJI zNk8T|4tiP7WeAbi7;qM!%i!VT)@T2<10@Rof2En9MD)*RaCt`b*ZglzyW~PZ?%MDL zL>-#LechI>+gSY{oC(Q=EZCY023(p8z35LiGJ~qJ+~6x{1JB>q8fuQVknO`Evx-z~ zb;f@4>Rjke=t0`V+{aI)+Urue%QfLr_*Utt-1MZoo_(3cPjLp_J+p#aI24R ze?&`9lgJQ>P&s5|G!WqRJgoCg2H(uLB*u7TU7VmcMOtw-kvqmoLuFlZfJZst&fv3s z{7f`cizCfr&knanhFAwoD~GJ3r%eWL<`HZx)Y1}eu4gb-H7=8~EY7fjvv{k{qXuuI z*)M)Kt06LODHd&8(qc^~z0gD~3hlrNf4aS?IZ8FR8GJicGw{jM)^J@zR2rV09OZeA z!O!LAF(_~v9+LoThs;=Q26&cJ2#LZmHEO$a7XO;Tzb+?eYAaMb(oI*%CbB8w+wzM|2CGbletpClG;+Wp9?wsa)a;Ue^;QA zG={Ir0NU(FyJ{iGqWL&=px z&|~D+8vHtby^P$%G^k&((hU3f4Gb6peIGjoyJLuTq8D*cBW@y`o1Gh{F-fA{-(v8+ z92fFACMVJ;#9~F8j&0UY?TjXDe}(hg41PPm0|yq7AJ)7YH*TW5 z4s;>-fwU`w1e$(`b)b$?hj7`>56cC6H+VW?@JIPkI=kK&ZmMb6mU1(oe>1;aN&Oiwh<*g{$ii`Sa;lVhKX|gTY^J|8qu*(}WiOO7&jLe`qnBQ15S4?~NWV#}km=BBZx_79oi9cHcourUIZQ{y|N= zcYH!73AF!{fIm3)kVyjQzX|liw1;B55Bwj4J;guHAXb%7>r<-rSq5>jgj!!vtuK2N zm5ayG0C6Q0c+e-VBY#*MNYoY_mu->+ zqKgb|kT#e>)@B*4oV`gpMd{8{B@jE*(1yhz(2C6oH&WCysEsh#<=RNv+w8{9P*59f zXvHKr^nt96Ow24Xf7p7hG=pGS99?4#t(@w3H(P<&pf=uMRoaB(veTR3$Y_%Yc=9pt zODBR>5a`t7v4@@@;1dY8@>qBK6CkS$R;Ep$)J#fErqnD-O{LTvN>x&-hMJyxTnnoFr=bSy=-f4qWHvgK9ubRiWkrQ1^s zHdtGm=Dcn<4jUolI)YrE@(^Hm;7&JKuC|s^8z{A&QX37ePQ&$>9*w<#nd+2s+_>9h zXq#gdtw^rcV8BP()-(qS3ReL0))lsu2fw5y4%Y zmcq=puY=k*(G53+bt$E!h%Td7Pu{20E_Aicr&m%+KK%|I?vPKvXJ}W`+AE9V+OgG_ zcCB`uu3b;XcPE~Waak|WM3T4!a1Dne_KgPg(!Nixe+tmqU(C44&~DcD(CK7aD4pE> z6-uhs_L5BYQ0o7Pp*^~GdtwAdu3JrUE^64((5!2BCLV^B1t@qPR|u&$x2Jk9Y-kRf z&8;-!+_?)Qb)m-9q1Fbvw=zZBmIfU1BQmjy)`98Ov{l?%mnLS{r7BpSHKcCBF3h0U z3Oe?;e<;)vBM_UKNW>?_&=7Vbx)1b@#Kh_q%kg#&gOM2x<<#Z6CME_$(kVKFp=s?) zI_9lmnEF(5#_!6cq{uFl^0an$Ud>4>OS_yF-qAuYaO`M_G>4n%69v(Rv%}7%e|ih; zHmcHk&D}&}Tjk4hO{uiNW=?O7Y+un9X*t$Tf3#KR*gL3e*hbqzv^$tpAC9)!=h5U{ zZR|@5A}WdZ(uWf2cVIV3eq=Q-Cg)PfHt0MIM_)cjFe*D+Vuodeqij|3R6SGbj(f4# zN|Va@k%lFkHpwF@qD>yR^C77*3Na}u)avMr84)a*&}5igYo+~nuRLEEHJ>hR!?}Ug zf8evmNL_kaXMBzc0UM&V3^7@Jo-(QwOY)1P1%_Vd9cuj3F`wWS&_zid{~XrB&|1##@%6g>(0|)!imrhng;2->xj&Z z!^n)H#tU+#RKw8|cIQCGzV)_g&3S)oNFO9uB8I?Oqf9~OU z1w>`$k#_m8>x(keY3n%|lH%n_+bec+rS9A5iqief$hhLkDAkusR0W-ZYr9*gW#|kl zFdfI6BwM(nKx~_TxU#oZaUf{ zV`B0cjjyL}ZKyL4sc3J26<<_TAC~lHgQEVB;I@nl{#lMpzruBPL9eoseW6lXDbNKy>BMZDKpo?}~$^&jyT`fIe(5 zD>K@@al{1lZ`Z5ZIbOjYM|0yH?nf#njJS#?B;HQzx((IWkC=+?oI`*Wi87VUPe}xs zoOnAa@pfWj6B80|kq`fhe}>J?p|lOz1tQ&A;zK#Tssib#8FU3gvt1r)MvfO29E^?gnx z(iUxN4Yio-m}pR(<}ewSjm*f|@9h<51lSg_!O)%%A&Pb4TBIf@f9B$Y`Tzt)*buA5 z$w6^4W^AF121Bf(jC{qLoAVZfArxf@ohsamIAq)?sgesk>vGCy1U8{3*_B*>F#@msFn4up}T7h zF<;iZp6+%VqDIX1i5qdT;wEvkF7_DW7O^+s&~rocw#b>`aSNs8!JZCn z3Xw9RY0qkkzx!o;$6J+5#h4#zu5S!SabX`hv%Mu=KGs6qf2|^gvwHT>Y%+D-G09J> zLye6q8rs6t8UGg$w~56L}>i z`(c1K@ewGLDS@fM4@*Y4-yC zS504{MY51E?LLdJJCQIAud7QA0blDm99XLrELkfGXO|p+VMJ*`GL=Zl$QYrN?gp(p zU<{lMQ{Wt!4d=oFI1g6A`I6QlCKWcVtED)ZOp!pj6z9Vh)z>1`9=wh(DJ?rvHrAvs zUr6%C5(W7JTThm!lb%Z<7rUlETn4QX91j$&NiTHeXm& zdnDCFFp}*dvRwr1B>qMi0Y88exCxuT8LD6p%!gYf@iWbaZQ^TfVb)s0q!h8C$Pcr6iLBh(U<>w94#+y|$?{ZJ1N#OZk0W;Lwck112fA23;9wU&4O6WG*7Hs{X_xj)0xN$a4(C7OsCXIG?cJ%Zd7!D(6t=5Z;BZ1C#Y>~mO)qL_t(VA=uLW^rGM+>;EwC8eFP>H%AEy>guW zD^5ARb}L@3(^O8xxj==p&Vj?g73YU0j<(RknPK7JEYblRl1XB{;-LIClplYg9R1I{6Iw*%;JL-lBH4Al*N*N`k2XUqX)(K5cw9#>BhK*(*+94Cog~twvI-x33 z^9b#Xs|edJ2|L?~R_#jIVT&-e#5&+>PN=16C3b;|unQ$&-*BR>cO^_}1s#O3&}uBS zpe6r<@GUYYNqx`|hZwXGgLZ!(>~igc%bZX<)AYeEyAKkGyMl z)(=-Xp}v==HTO7QRgMV^^O1$&`)8Qyd*x=6zr^Mf*KHf}0le*wW>10Q=Gg6waQ z$KHT}>}?pr-ht8VT^NhkN$fp)dK?Bha#GZAV#w2ej3Os;r`Y69(SAY>lr<@cp#KZd zb=ZefVi1`)%44E95fOi=W>#s*L3997Uk*Cu@kN|Gvg`)3?0!D#I?|3fpm-q7NIR;X zrK0OGqU*;_u>P)e9k#&S2HDS?P$SX|vZKk9Uuj7v{M?B%KK0~Br!bxT(O`Xw`1^$u zY-Sq%o`&CAU=!s%m@3x+zjh)ml1PSG#zOK#Uq02UKMjeYXW4%xjkdD{I1931tH>2>dzIbf! zPIze`Ik}ZWL(l4!N{^`U=6MTmg@Mh@EBhZhxKoM_+Q9KG`@j8ibgA@4=i% zrTWXYi5KS6o3zMv0Bx_iHtC15G}k6YFu`1#$RU^y{40dh8Dlz()oCp1(odx??ti2; z*;6UErqT}hJL>8`I^ds9L0+83`S?iN>M|Vv?S%Snn&E%=5%!9ju>A_cZgM5eT;6=d zJT7P-cfe;(w7b)I3?FGfQ=`!YmV|a7jbrqY_PE+sFwF_|)6}+t4uV@yf5aNJCSQ4o zdDr69(E9-MEu@9Q5m7%wn^{!27b@wtsJuet37HZb%J;(H()}!eD~qD_6Rf31o|sU# z{33z6{-S@JJ$_!=rPy-a$)5&;{|*P^Gf=>vh4K73n1|Pec)y(g!Hy3MhcVjEQDp_v zUuDf7NT0=p0rRydv?q~^zA#IBid0)FFP8rj`svKeaAiSn02Y5rOKv(VZ*jUGIi-nk zuElAd#i?9BS*#AXxT3XDQMt`p5phO5y-amW53ql%F4kn!fWMBcy#aarO(^7VK?Po` z_&fGQ*dJH5F-GRvjGSOGl82%=-Dad0@GqgiWaLvAfeXZ3ZN0)JVA;+-|HRcLphgI1 ztqP~F14r|wc6AWv7b=|oPMkieT^+>vr3z=D6K6P~j9gamJ>R&tSEDhB$F5 z)5w2kuv$LDoH!??kS6KbQY**IiE*GQBIoQ`)wUFOQ^VT;qbE}Tw8 zi|a(&?aJvvi_;5SIGv&fyxo;kIkC`(WL2k|<=UqwI-&lQrcbL}`*gOV3;v#_PpeY(sS5DpG<{m8Rl1N@oh&!ub0IHg&C0Z? zE@<-jY5s6dXzJ2Nh5!^ zs&2_`OB%UVbxUqLQp=5A!nJp+Jkkf8L+)Kc`3!kMFR!qk7C1*}X+w@s;aF|#kxsUR zoTI{gVcr~KtE4l9ijwj!oAb=^!y& z&`j5UB^NAxp%SmDdlEBtx>Jl|e8fdrT5FE7{w#rY!UHTx%YvduqaO&r$bd-A-U>@0ut<__>* zB5)wMLS;z&I5} z2I2|uh^L^B_yr6Szk=c7H!w~-4b#MLp<4V77K&$Kjd%{ics&!JwTVB#PVo|4CSHc? z#4E5zybAY-zd(ohD;x{P>yI)23Gt@v{EL^IRRSV^ANt4|I_!aAR*ie0zg6Q3sIHy=vxU^{q>fa43rcU7UhXf_H74( zhsT+JwtziK0&;9HnR><=B?0Y4YdsjyUXp@h^tA@7rCPk#q-iTGP@6VSPTYoDylIOy zWg0p1od(5V*&1uy>@fF5XIlHDxU#oRSuEi#lIkk3i{&z^RGMW05Dnt~kYG5Py@8nW+NQ~T_Ivx;^Z1N(vj8;GO&{qT1;|Vr1#p6?WmjnhR^Kharl?bY zddaD|u!CKZ>^FE$jO)E#Hub%lC)CZCv(n2l zC~|N#>Oq&iGW&Kd_U$_GdrpHsp3|X!z;gzS^n_r%XCqAa)WLjAFUDspJzMOf6=Pte zCD*%33=-yi^;Y{l(frz*1kJ+FSF+AbZ~E8=E)Sbi5}a z?6kCep>#JNB9E(d))!6gE{-wAa%O$55b zUZN(Dbc++`Nmr5%TO_^avKRER6YBSA_JTUJ3sofjpA+Y=sbgZ=>zpTbc_+JLp9AJy zRhQFO>Me)u1}tY_);zL4(w{Cue;S>jPIhmJeaxxSt5x`Th2I>5U7_ZG@z$UW*n=`l z4$44Y7R|!fk$-)ob%KRvsogLs!6&TrpkwVHy*$3968kV!rG5w8oab*7^|EE@Jc$^ zFU<7nFyHHkHQoT!d3(VYZ#HcA_J;GkLAcbL1J`@|z|G#iaIZHH4tWQ_6W)CIwRa%A z=`Df}y@TL$?_k!?JB*F=4rk?fo$NJFlw1MXXs$;}D?~q;S0Jr_P!?>5q1xZju6f`Z zr0xy0EjlZJd})tp>v&#Fy)gAA8Eu(*#k5wK`lGaJ_rh)qWiT79y@e=VI0ToOcrc8O z(B9Vmj_HwXsI+;0X|F25`xR_}ES#L_!)3HdXS#{A*eAdye+3spziva99jwzaV!TuApnjs?^``cY<#)Yexp-NUB~3a9%*{DCoa`KU zt6iM~&2kRjHJt#Y>~jD= zm>lXZVK} z@LJS=8UZ=6;4Y1o-zvZl#0{4m8$1Waajyi=vEv3g){2Ol`M_#swbe|vNk6vnoT7~< z)_8)B(EJ5|`pUbAlo$KS{^wd~CeRRvwH&>&h{=p~@(Wzb6>3;p$S7@?1Y3Ho@L ztxr(AJD}kj_5&*v`L2CLB_Xz3(82z$U_buYO?+&B_dSVr0e!31B~tvJ0_|iq8dOOO z!03Cp7TP?VAgNR?p;=+l4)!kv=IS`iTpKf2+H0clLstq_Xd7K99BNWXAN;k@PPR;* zucQFG@1wXa&H&ZcBjD9r;w+xeM)PU^vSJ55?cbKg`_cvX^CaB!5chl++z)NskF0kt z`q-*}*yUHF4m$j5{Zi#ps=u;wp0o1R%F3g)|0pVtbPD`tRb~1m7h4g`b5uF8CGMWs z5psw*rzX(daX{7tAYC@pqu#S<%Kq5KTxenTBTR9#JgJx`+<+g61MU|G>;)~T5io&B6Zy=R ze9~|6SOE^QoD`uy4FSDX1-oIDHlxstY%EBM`Q-^*@_6z*MYlk)T$^~x3vUIlDGnKb z-tbJwzHT>l|3#j!?)d5j`4+{)aYCtpUP$2U;L+azzy2ol(cglB`r9a+cVN8!E=k_fjXvMwf(6(S~)+9Zh-kvJ&kY0KjlH+i5W zo|p1?#3>J-0FTcLexD9~d_EZH^TP;V7L@x8IKkHos(jh7z}FiVVcrTXv(}eq%VRW@ z+44BSmd7}`z#@4pw&k(Tmd9$PJPJ@AeQkMYpW2#N8?Sl0X_9r-Jl}8^&BLL8n=2JB z%Z5!n+{yh8TjVQOh1TiEp49aXXZ=cL{TzFMJL)?PsjpU9zppB~!E>FJS1N5`e`RH- z751H>s;qrxS6*Woy(#KuYGkEZ z1xgOF3K>g?xiEZCS5TxYByxZdI}aK8w#7A8V$0yZl(~E&6liS0vUfgPA|0n%ZC-(7dYE+G#K->FYPV0q4d_-Xt`Auf2Q{f zC}ivtYm1D2AHx#zGHjB}rN5-Kc!22S#ZGm8IL_~m4?Ny)t>^sOSK439u%rM?33T-i z^24@oZyv$yOM)6p!N1XCweqo|JR#5`9V*{Z@cAB#bEx{-t@Vw?k5GRaa`O;bsEC~t z=fprZK6^@bMklAUobsK*8S=f=newGowDmHoC!_mxz`?6k=rVX%xEI#p-z{bsGS62Y zi_GQuWH54Cp5F{UmT#!Yq5x!Lg+Z5=ieCBNJUy=$#RiSoi-|guF}$O45BWCPK+#?p zfJJ;%gs%1uGsXEz6I6fH+%}7g_sOkb-)~Ve&p?jvS?KS34hH#NfRVmG-~{s$Oz`~) zDt#}*EZ?iBQ-6j!-(O*??=?8f_cz$#dlSCldkZeXXP0BS@B01$H~QX#yYc#f?*l36 z>!CM}x8Z`xh~8Ex6m$&3fV0pe(lFHv=Z|WsnE`a$7s^dxKTLl{EqqXJ%3T8mRtn{B z_t#TG$d`O`;D^E^C$RqTu<*+1Z4m4ey0z7Fn~e8)P@lgq<9%M30K0{cHuTfy-0sW+adFxi9JS9Mosp0{#^Bg3%AJSb8_bvK?7+=a)}NUSasYh%+Ktwt<^u zuYB&tVM%JezTkfb7~1vju~@P;c9P==y@K4qC(9RW;)>Xh*9s9Ua)?h`TOglmGP{#k z9^kVcg#>rg?+4+}f?<9GM*Fj2u0JQv-CS>rcfIi2?xp}fY#7jsZ?R)|$*&6XY6tKB z!D$Y~xAR}xXdXEjjgrwZw0TanQZ-aOGT%e0m3-cqf6MyZfK@nF+Ej(Nv&`xB?e8|9ME zI`2>WzS(~Xo4@kdm%j~s{&q0@+aT!Q4#obRFx`K4+}Vg(HcPXl1!qX(WGiqU#Fdm8 zI4_0)GR7~gl@$85(IU z5Bh~B`%GHb8)5tu)thSmTT;HMCg|s}EU;7158@H;kDHU@ zl*RtELeT!SLJ*~0fFug~c`vJ#`PNyJz#-U&tsLNMo%o02X5qL~EjE6@!WZ=0Wl6N7 zKWNjQ95m5@=`e5X3%M@ebA_eX8#|Jat%KXs&tb1(v-qt56>AG8cLFD=dX_ zDj$DTY94M7`P}J)eq+a(%4=uKktG9UW1#3)CF7`6Z7tk9WHueSN)5JE~bkwfn zH(OrLRpy&$Y*opAzP{=ZKVxkl9uhx-nR0)=8M&g9*B#&ui^}@&tsT5^O($;=^#!87 z6P}wHn~!dS*EH+k;_|oy4ZOXR@2K>2^7HdO9sGg~73cSS%uY##>-T|I`Po<|U zPaNcz;e;cb%=b`()R6Ru?<*=G*-u9dFV^qFuOz(8K`d$zD)8&8H zV5$$_ZROu+<_|XW*OYbeA9Qu~Mi_uy{U&()Z^0n{+c3)i4ovjF4>SB9z&!uI;1vJA zq0avyZ1;ZzS7P2Z{!ifh{!ign|7UQg|8qF({{o&3FnA-t;e&w2yaB-m1#~tl;Ab-f z0k$+?NL6V;cdHI2ie6GxPJtQPn<9T3yL=X`vW{Ke3KOiScS4!<^aCif^4@@{RvxNE zEH=QF%2yZ}3}REY4@7TNxQT4I2$B*?HCsUE?Pie^6=XU;gOO!~uW&JK=ir}u%$tpu zk74i^FpM(j?i0xW0@btYE?C3&iX0r<=5pMO;rmK(=y&ivj!_Q_l9%HmmqveqM&ms8 z4K<+zF*1ELz&SuN%XU58gCyvDd^yj zq^j+WqsGH5u})G_;oOXOp`w>NW&#W-iUGFvnfjvRg0+J?=k!dpZ#I8aPm!c@i#1|BH z@Za`ikg-o)(4OfL+J|D0O7hQj+n&9sHjFQH+a&!{P0>r;26|Ub(Vw~v^o$ssJgF8I zb?{euI;kS$5H;jqjsbG08uImHfE=cVeDfF}hg*S*@Rc?I<(=LGMgjf zwZ=RT# z&MlNofGSl$&b_uwfTpW}=Jx=oN(JQHtIGsvh6-p=4|+{0?8Q9*QVM%%4}g@yUfu&B zrLdjbd6@tyg}u7lK!ep|ZA}k=lw&RBY@!6pRa10-S`UDf6rIuS>8MUQ&xSJdlQt_W zhcolgJ`yukENtm^DC;9}q6+BDZUa57bo-h!3t2xZW~r!%bUV=Ws8an?N0^oD997$z z)*b*US!?S7kkUkK>j99`MC|Cc`k$+ep=r)9EvKibL(EoDbY2gD=BR+a-UA?&VNZHD zIujs&Wv@9u_?!ulTg*8nQObyVhp1Lyu~lhA?t-P#Ciq7WwhWXb&iR>=On_9gd(v0C zGXYX6LCPHr7a*k)e5(gQ%AxE0T)hQQ98J_N3@bPUcMI+iEVu;M;0{58yF(ysaJK+K zg1bv_C&Aq%xCD21xV-Fl|GM8_wN?96cORLanV!>6pXouDqv6MwHTncS+>GK;kTm^4 zJP`wn$V=h)e|^wgCN)1jAfhO_77z1y5wGr9=c-nM*P5yi@q4D28Rw|qP;c!LI3$5d z<_ldOm29}}cK}Jmm@}-FD}F=nTCG7tF4su4fmHt%xZ7lI<41;d311B+}})ojDv?AI`8CbRV`IYp9N z&X(>TwE6ZBGG80uCejR>Fmapp)yJ6Fc#MXn&{ZpBuqh87aV1gnv`K)(ccj9X>gkWK zUkA=Ey1grf!FM=E)1JHEbqtp#>OCX_mI5y2$a>%ud(;xez)6g zPgkR{Y@Hq1v!vmV-3Gr~V~K6cKAS5eo1;Iu5s1yTevbCY|Kb1L8B(hjIT70$(D1r3 zH;tc)gf{PU_$z@w$>iF4g2cvi_UzE|6X)l zI4NTN2Ll762MYs3ohZ5lz)HMRN5o0w0RoR+71D!%h)^|LU||2NntE7tU<4G!5CWH= z$blLt0)F+SngO`{DjLrS%zrJa7kmeN3;Sx%W=3Yk0|Wyjg#rV^0JUfE4hWYR!VbiP zI4_7}Kh1onSa4+xn5Qn%$F%S-8*4(NuW__G$)g6)`bx^s`KZ`n#5cLc9Lf)%y!pE7 z-htd{oq<1LbOZZ9i$7A1P3?xQ>2s3qe5KcRo~AGJ{BV6|4}-(G9wMUhmNwJS&!}nt zV5{BwXLGpMt=VkVS9;dPTh1*{n zNvzy5d+)>#(V`dgsIav4N4YML8v+Iy%BfCpX$b7#X1}`3*}VC3K>@h;udaBD%0r@gJ(oa7( zH-<-cLF^4{8`J#oDE&6*(ack4; zFXjJTW+(Z%pRRlav7fZq8Y$wC7aU!7PC-W5b!_Mx6sVzNoFu>w9zl{2r>|7P-I5k_ zzXWT3LfYfS8n6*x<>j=~Do!+Ki6fhMqdI#H*N+FNi(gF-2^1 zCaHBZkvXNulekBQ2N?8#G`p0s_Li!^fJtPhMLB8@$L?^Vuhq9U(~H+TA!mGcky;rR zhllRBfok%8Y9|`TI-Bs?N||S>3{?F#wfGETeeynBUbo9_yBDS2wF|Dw5ZvB$>ma=b zs_X;f82fO6C}+4y$Nga=KXB3eIitd~V|`RB`Z52t-#2Z=8!*;yO?JOc;Fr~1db^J0 z-|Hj&9-T7^FbaFK?$g%~e}U_^tozT4b%+jNH53?vwK(00MjwHvk1iCJqAHr4IfQN)4 z=5oQa3=*tR-beq@7!d*)HODw6>h~CSMvB-e-SB-X?^rf7l|{jpLy$NsWj#!?b#7DH z@7}>wV9zu8*usRi9_1P81PPhyXcT zk~jFOLOs|=h!J{sT809@v>1uWF0^@UkTb5yK%1r@;nq#lxy00 z#CDDBvC?GvLZPNDxo49Gw_G~BSB2b=0Cx)W;%AED=0}OgJ!J@=L%rp5u9-`rnS@V& z`@%yC&L1U-;aM`o$Epg5;@v=qL7<|^`aWLUqukp2RP*k0U4qjRlj+&nfVQLkPl%7! zpCA+$sIk5HRYV2nG4a3id-WqV#+xNIZ|(?==60UZ!u z21y6#*o?#vym=k_zyiRg*Qbw&wOmQ<%eaaL`zpSqgGicqunIs*L>2_rzK)Kaf7X%U{M(HBr)cXhn>!AAIe*iANj@!6mz--9NGf3N;sNoh4 z0R~0^0|tid#g4s`IjfnCkvXRotED}wl9Q>6i>H#4rJW0OALQ;tT?Zmfg5GCqndXwq zEwf_ourkiETxEIV-Yi#4UYVbLZaJ&E>r=nqSWcfBZ@=5Pu?Uo-kKs>fnoZ<#D;Y*mmswymC8o zw~%~&s;;u<}rbF`bF9Y=iu!|gL-`y zUC-uH@*nk&@PChPs(1a=S*n|xQ#BoQoup>{3Vc?a!*02OgfroW?;VVtJfEXrfnxxqG#$z-`GB%hLMN`Hp zzBTva+ry!Qh{16ixB3n@sCMFFk@ZMnPqAJS$YcM^6?X1mke_d*q+RScR{VX~ei%;s>L2qT5Rgv(H_O(eGQGT{_?X3d&Rl;~ss6twY@3SjnO1FkeIMdN%?`HQ zXiFXW4{@u1Kn6~wEEB$#>>#IoXY6k5?do-SLlWJv3<;1hyV7(Nn5vC0t1BL~6)y>G zo$K8!Rq4m2pI2AdF;&3PpLfYkip$TZ0m3^db-u;A4#l?9$qn1!zIKdSVf4kxM*kx; zI>Kj)cmhkz?J2-Bh)$xxA_bq_xFinG$LsUUroc2M4>x|bCMpNC{ z5QV-;X2{M?Y`-?P%uE^`&Ovf;cpO$|ou-}QwRBFgBHtbM6pHP*qhESm$W#XBX=aSV z<-vE`TR6ovEJ8Si)Sei>n+fKHHets1<%VTk2fV5R^^KkB=EF{G$)leYH8;gX<4&&V zvECrt&#Qf_^mCXWK5Z%8cM5Yuzm>6W==jmZ@*ZN11IILqvBDT>1er4Wwco4}Q4+~V z9Xzjz5CE_G1$R($Kh@1?U4)L{iC3-rOdz(>ZGgvU*ae$cNsYJ+8=;t7rzwlK8?%=t zMwOSDLnobyP5Bf@Mzu01ft7#RHsK!}7dAGrJX)FTN`hO1t@gNbquj(=ev+(> zJBctZ#8Df*^(LRc*QF};htW-qzoJ;#18keIbw-tlj0pDCy!$(xJq$XLvsb;ff6oN= zrLD*F+i7y6Ph~1H?l+U}db>KJ7NVdCkkmrL8vXQ_=Qo=+;_~V?leH|@`~QB|H@#`6 zS4*It(8wA)zTrN%F$EWs=>0t&gI2l#Vfwgh@SaJzE(f zQlz}X2`6^h>c1AW{98KPozyk4(y`KR63m%Pk)t;Kus($dJ)qKl zzRLI~r%VKqiZQQSsDjUNxKXJF1Mze6oCDJmmYwJHck^iQr9=xqTKn0C)r8eRta3Le zkYq{%qzYXDkf308(MCTP)7FwXP3_U`5Bebn1q+2iGJ(Q`$IMlGu0b`03Y{8(Wx=toA-(z6F)gPGPMnwRs}^r~_wL%AYNVW|E=3(&f<}$3;%KFEay#C_n*6g! zE#6EPP9#n!yr<0Vpp-Io;*s{IPo+GJh>1h3{KZsb$x%on3GZ9YqP1x;B&pW=wzQ#% zI91VR^<3NUoVeSA)O|zZM{30>_?$YmYmoRHiPUsq;|5MB+TQ73{RzOJlj!EE85fU?G7$SJo^llzoc);(3u--QqesKTo1??FU88 zp&15JRZG}xL4ikh2g>vb3f+yLx6m+CNFoFH(XWbm?$&V}Yn zi1XUCR2TRiDlTdORDjOBV?P6Zp|e69D3zEHD}cVq{nzgKZb!gP#4Olft66FjTV5jP<{OCKy)Zw zptuX1fNG{Z2TnmH?(TtiDO?7u@e#e5Yg&IslWsOb2Ri|IH+1YCU6<_Ecc3lvyfknTFZlBpJ; z-$Bh;LcpSMuOelE;05R@4G#k^Ly=81xER`wAP!s&b!)T${0yaP#(#mypdEVN0Oo`u zhIVi%vuFo$c1RG}JxHKGd;%W#YVIm~x?;{C{n*6E8y%aUr#d$M&k~#6204WX+{6Y`xt0c08sZ7RpLU zLOSpf_LHVv{ZWHW5SD9$U*;D4cKpCD3u6!42%5H&G~w*y2nu!zI7G=$7TM#5>ltg- zIjhb`t=5BeX5q<$GhSXkLZjRFf-7;49?$y=Fj1N4-{1{U+sGdZF$yzgK24kO3PLg> zBjptaU6eDozQw)|g9o={oiqfw0-_V(shxR~r=3kCTIt|f@-}V8+0J1>l?GyLA$&II z793?Z2YQO5N9j?+IFWib9lzumsgc2gjK}~5ZEf$^L&;Moh$1WYTpGh?FrnC5)|sM- z#9*Jf7jR6eqD$ycXjb0i+NqAs2S`p(K6y%&wxMqKQIqLzB63y45Z>nlkg$SW$0weO zQCZ(%F&xUtd}aV*Np`y& zzv#-I&e^~EZtYuY>2&*sJLm2oga#MW6-^M6z8O2iLK<-MJ$y54&{Gvz2!?!ws{-7t|KpIhNRA*H;na{ANHr zHip+FN{l(zlyqRUsg{RPPzo88=3THKF~HR#%NBVGx-F>VEoCDy`dloUE?+pl!L{;) zcrR5YNZ3W5j&(9TwCO?N7KphrNDMi_*C5h^(9@?QrCQ_IuRHe1hr*Pwn4HOKXrFeEQ++I3JEq z3mangGbax_Gg%#4wMsBy&`?b}(QGoz!x8sg*fy%7ENWR+kb%<}2Z66MBh3N(WB91P zy+@ve8XB$4Qf8W8LKJdMg@8ol0mhD2Bp_;}4=|Y%HO=<*ZQf|p#Y}%{s?6VHj>mRS zeaWa5hmpB2)Fm#d2lkNuz>N}mTf~iNhKV1gO~$s`X`J>(cEz&)W^n?sOvlSM|3f8A^|WEiH0LY42M#yC(a79FbhorbEeAnxJi58EpICJpA{|; z19Bc_;8|C`MaFuD=#J6YWxJ6QwVTGln;bcuu%EmQ!16}s>pX=}^xT$q%e4Gsx#YmR zJoglEB0)`?t=gm^Z4Few(z`u1Iwt)T7ad9Bj^6b6w&|A8^6WA-r?Tu!Qh-wt?;t_wsRvUFo*%Sjg9%4j%*FR_U{^0eQ~>OZ(;vZchqI zcV-9O^eDF6M_fvC{T#WMX=>ZCBmiUnisTG1?L zht|_yk<@JH6K^@AA1BD$6tTrJb<^(l6nGYeGMi#eMzol$e?7|8*eMC|udkTyCZngX zKdl!EXjiAdrrZ1!AMk!*_Y5`=5H_1T)a4@euDYIG*0FBs$hJBIU>he+#~ zaWYG99a2Vj8nwtD@0v)x%`e+J_$&^g+x#H-MHVcmJP-&Pt(DPtEnTS2^RwIj&>DyA z$e%T<^gJz10A zGnbF&C8M&C?2-aoz`Y}%pJr(`pPLA|`$&6u@mx2#AfK;r=eaIZ$b_rKf3D<3m5s(2n;!68=@HLwPm6*$95)jtP_aQz%MTvJU_4)Wy%xgW@)+SR zfDz^Kn1VaWH|3#6ps@j;q>3i~M$@IR7t^Q>zt4sn z{q92_s?NM7{9chDQogPUQl0yK)5+By)_HODkE9Kz2RUJQx>9YDu&hLGTWY-&;A`qGS^Qqgg~{b0*U;$kn{EuP|!DA zzhG(?$#Nix<*Zt;D~tLjz+{A*Qk7I;x@*wCJ95}-89qxhYW4>G>m(_P zk~?iS9domZsaiVAfheE34d#0F$&DEh$h6Pze;|u;J`-D$0--fK%LquNF*tsJE0}}z z7Dw~>-krcM5+plqYY-}mr?_uPpA{oO=Jd8OqqjHsvw(V!mzJUGl}B6rH%j(Qp=0yU zg)Mt_PGd zVzNl_w9=T>O7x`D(Ror____0~!t?}(vj}|y(QsgOf{7F1$a$KP*>b-B~EfU#xL{PAlke^ z*g90E>{sc>D%+sQEBZgV5!Rwt2d?MTh6387%gGz$fp59eD`yBFOTT_u()#mN^u#8Z z-Awi{UZrNh?Yna5Mg9+&$Qq=Pcl`>D5j2%P%dp$Si|;={_KrEuWADwAUD$Pb#H;5v zQAT)=h(oG5hfVe1`5T{8MHT?4e;Kb`HpJNf5reNq>7CL`107wPEY49bMQxIVrv6?l zBurkB4_X-0mFZQ3Cleo(eXkbdEru-}j_#1Y7;oq(3F7}CDRF9pd(K?^YRo9qzoL9L zs^W8=hz(+aoR<=Clfp`*%Y^VdT&+kxQH33ysgR~mUE`nCTFoi@e?09o6^Qz{!SOKC zt9nz4A&b3l++1+v$acE*!OO$2@`(QZK;#gz;Nt`*PLz}#1(Mw#lqhee*CzOHgLDe=xTZ; zbMt9!j9YMXSRQ#U^utkC_;}aXNm7q-Kgk0LqAR12UdqK~=~UeO#UR%k;&o8jcK$O` zG%+SHqj$2&c>5GAAl7Fba3Z1q?nwHS+JkODefd*h%k|A31#MW`Vku8mZzy5$1sY*e zfA!5T2>lpC6g9X>{0BG96FT@zK2sH`OHN<)tP@i@Jr{9`?$h^Kb5N82z)O^pEyof1 z<~%ef$PkOiZ0CYQwIG;%e@Y^)seeYSIA^LTk?&GDZUf<*C&-s7t(Yk-g*lByxxl(f zF|lycxk=HSIqi;PuWQB1_jB6S4xj$0A=Pd$#5728Um>kHS5dv6&y;nhE=Xu9t9)S z?1r>RV||{)!YvY(FMMRO>yns~yc>XXX zx3Rcl*z>su6To?PvX6|0J_0!L0<jJawHc-Zv^3Iy6G!91_BO&IE6ibPgL zxb;nK3YmN%NFa(X=QDAvoYd1JuABNXr;u)`l@eJq=|Jsf5^Y4g^mA)sOhY&E7rRY| zvCmU-A;dK2iHLjc*kxY0arXvK@suCZl`eSL!TivY%^$<7o0)>B6CwJQxz8j*@pdJJ zc&)gtbHEEvcZhnG#Aed^;AcLl{hf6wt0k>+HL*D@+m|=6+NLe>VU9J0cDd&OhBcWR4mOjQytwRQc4oUN7kng=v!-pBr=Sv{7Abi~Q% z!T{ME-*jW~2>ahE1D*5CNAfy2o@Hq@u&M!@#?0K|t`_L~p$)h|27L5&hM;An+FfqkKHYWCmt8#C|x5Y^BFNX$$kx- z@l&kL6F^RCPdLp0(biM-g1ELeS7WIl8X7~g!-v7WMvjiD`;saz z%n27d42(>oqcl86;z%4K0c2S7W$D-)=gDVDLxnq$J682)0FQ!-TpgAXHQjH;MVc_V z_&ztxJWG=IRMwVQ6_l0<3IAv;ePLL{76{TkGO5RqC(Y)aEahk&7c7Gbf_BmK(d_~g z*?UF;R zf8?c=bupR_7w??LTjrzf=7m`z-Y{8xq z8XqnB1d<(&mL2U)N^*p9QBW1`J~a#x$a~ynsTK`KxoaoIpctYPPu%EC#sSW)$8sZ+xYf%7;iaCT7B5~ zLjs+@Oz%W^C4nxsx1I#1F8GJuWNbMHA9Ds?h&ac2@+2NV#qoVWn88J?WRrNwI^otD z+67~SK4F{K>I{VFp0)D*ynIsCmJ>!7OY%j$$g$tQWTHdY{W&9o?r&lIr!ql(YPoW8 zfO?6aE=KSZ3|9jutqJp5FB#Ab_$u!r9u;Q{Ksbc^nY?g$=SB zN#ZSY&@%CKSem;~??q)m{VWvFEc0*DS*2QOcHdf-ZYCaEENKdfY3_2EDg#HO%1Lnd zfdF>YA|2si>Ka!@EgnN~ZPubL{ z{@2~l#_g8ZwY-^W%={hH+sSjw@;8qy7Tw<6<28#0sbyA;s{T5E>naTW4s}^~x|*KR=~vGpZ9g&h=~LLYOhre9eYa5+;v1KVw_tnoZK| z(tL4`m6e`#{Q<@z!k;%N3Z; zt%tH=TsyXwHRK5>5NH!st-C%bj5V%j0Z5ti8%9jel$= zwl`ArDa3K%dYk}}=8M>p6N*%>BdP5&zA|Rnnx)Gp5vh{)lDCCa2BLrbn{|N#87kr? zo{n2#Ide;dKZ+;kuIT1eobqY!_i)Yu67vGP~X-^36IiNmK=>pjuNPa@B4J_RXe zrI92#WPQud1)5Wj^qE)T(+Hj$)}D+@BDY-Z9rGxll6}2LW>Q0N6ZZKS&G30l@d1r1 zogoR5`?g3sv1v4cPpqg~U;$(rG*;WoM7 z%JN&15VU{8hIn-ui1;H_qH^Rf&!;~};7p%t?Wn`XcfC>kbtx_Pc<(clfB(aguBNcm zpvf#i{4U{998e*dqVS#JI+kj?!C9E}5AfxKVj~-1Z#4Tg5_=wxGA$=(x-#fNMa>^Tk zN=2-3(;w#lH}WdBCMNAHvW z^o(l$1Y2XxvhK{Zz0eEb)|Y6!J~e zMrCm@cliT38TlNk6>)cg?ambjl}y+-`6@A_k-glVKh)kqIl=BiBR4`7f`lo=g~?3Hta}6obcv@;xTf@TSn5eE)f{-y#Eh1>;tv0zo-GjmA9OthF9QB06Z*fvgX%kcJ5+8f4IToG1(Yw#u8Ce^ z0o*q*Fk*>s@8RhZ9lGJciOWg<1qA;$mrSZY;WO7eg?MpG`8aN{OkIgIB2tw~L1;pL zm??jxYC)9Bj?VlXk(`c%PNTxNtj?q#ZhcroY@7s{Bo;`jLAXg(mdT0+7Qe+BKanCu zpTL;j0XWi744=$5m-?>ohc;nH_YNApSL#=IpI3OB4Q}okD`0v2AkpA8KV4s15UV#J zZF`!4OIf2NE;KguTxT5ngk-9u=`ZVQR8J4!gff#H{{#F7fII$We^=u#zQ$wk4`s8{ z;gRAw`7=a1#vN>mmeWDXcqiQXQz7q1N)@^Rx}!)+z~yp8#Szs-@FaOSDh?2gXkv~+4k$UHO1mj?=|Vn zuohvNGUsIKcBuEkjfXemP<@#5&t?8M4FB$%3MT`0a7mtcvL#DT@=>=Cm<-`<$d~+;Z-jXiBD1t4I!Zd-yTvof-s_X>lbdoE=q@yKBO;~mmkHt$(dqzHPU`-KN z3Nn}fZRzVZFCUSjp{cM`$ai0CfgjqG{{xFwo9CxZR~3Zv15h$_z;R*4TvC}ix+oy{Fi$a>H*a!R>8bsTm1JgEULo>*&f&;fqb@7h|@jX*aS^VVQ6k)!BvO<~5)N<@^$?A1ZKFvR~gzgWf zQAJomwXu-IU56?&>nbma5dV^EUExkU151s*{v%yUg<2lL+?i4fB(;ep3&oR&i2)tc zLT&E6d7ZqTr);M8Q+tv{+MH?hb0mr*%h}_lDRPav`z3u^)L(<*h`3TNv)wXSI996Q z@Z1OGW4rKI*w01>`Bym5JwnP_Taf<}W%zp}=DAEMh|uwH@o1XH zq9tUG6*Z%?x~27)Z`}xTCXz{e@bS_$z|;XP&#P0GVd7nMdP#^>%aUA>tP^R`@v8sJ z-b^M9pU@jS`6Dg9Y4&J&zNiWdjxF^GF$f@1Ox zmA&z=JO5$aVMlEsee6hN^CMe>Z3$FIhjW&kO$U{=op>OT>ct6Ly?fS%fa!5> z2HS8-wC5A7X%s^tTg-)xwmJ!;zXn&-rHJ;wjoZid`f^c&55Hjz{6Zd47jCIt-o_!d zLc${vxAfdaygU$VmY=CDM$1s=pSZ`G76N@-Z1X;SBD0L!r!F(>)wKr*-{Tc3C_h+c zYtUH1DVHc0BF7hsA}VCh3q(e*G6+Q_p7Quad|Z8>)P2l*#w`@szDhst zTOfhQQlI7aSM*Q@z7~&o>I=z#KMFL6RT`R=0emeHn$FK!HX7qPQ1n`~tl&RHzSkM4 zt*p=6$z?2?yG+AeseDf@*eRqk$&s#6PQkWM4Q#J1!!+6?=<@nQ`cwN8WWwyv&s3qm z)~M3Y&^}xWJnNC&T!^W(%@4R(ptm5b!U$uzcqXzIVN`%Gx{UD8#ksi z6Q!!@NIBQMatO7W`%*_6Q4I>ZvF;S3Ts8}nu<%nfC+Cw1>U~x0=Kj>leaI^O!?lU; z!g}yS;<^IL8S}e{3ettB>U}EV z8==`5eBJO4(C2vBFg!1GTE9C7?*q-)u-bsX{-1n_J@{#83?OgY%3ivdk0r*zj{0F6Ni7f}9LO)=zXTw@@N!a&M4@*tsZTZqV4o z;1(_}ck`f6K!x#i&kUfJd5=szpG=L2PmCm2S|t`OXM<;h%(m9mA-{|xD(88JN2A!y z0-WLOemqQ5Sy|;OnQVHU>NV;)$~$`Qwc>Ri&M5qa1k%CaJs3)%g{`Gu`J08!w16-3 zj>5{Nxx#rtkvSf-k`+~|v&alKygt7f9}Sz)p-BmlD5B0(wRCMLzGTooSwMri*Otpl zpot|jJc}7#YcrMIul1qh$6{6wm+!7EZ>LyQz}Eiv_bFlTWZ=@6*zP4y+1FBUi1Qg5 zx&tj8kRd|@$+3!olx>$*9}Z_#bh1r@apx2M#ZG-zk;|PqP%McpACi1n7U1u9=5;>W zWf}S=C4wk*|L1LF7ISNBnc`yD0``#0n%fX29a(!u!WsV0xpfbzjQnn0+_TqL#YC_zVvK=$Dhp~AKOB&N(Kx!`3B zCyH+pNPGG>0)B9mIbLgoVX4J5bY<(CRXWx>I83D0=IN_vA+AU%ps+8R{NvwD&%}q% z#7iL7O>&h0Mx0WoEN}^!CbFCfoT+5>DdXG10ypVGe#)@ZthIgvmV2y`LQ@83eZ6*h zjiO|$?kZZjS`rFc&ES$N0_PUB#Q|=`?ySpT-fXi&wBG!8dHc9W7Cdfatn2>s8cBH2 z))(Z(iPjrGKTkPJ!2E=|&h({~h`jC~64iQ`FBRh6hnO+_Maz+2c9 z0+X!C2)DZTR|7Worh&*D-&(q4)pouRlj7GKv~g4pynL!`Q|Ag`W*_!LKJb1zex|;M zE@9+z)5?K7K}J*Z{g$`qkB++}1EXFKNDHgo4KXpEvE^F^F6S)E4ce=^fx$d|dajxh z{mA`OoP*Y)%|M=IcF{pFW7P|P{CHSOJ~X8SNzJ2854p?}qgNH$@GDAW#+H*()n0Oe z!zKvuR5WTf-W8YDCHhgUzLazhRw29@AAOH^JNo-mTeApx&oadm($lKN4lK|vNk86WE;l4HpnFS`kbR9$c}vHoc#porN;(|;^_*FLflk0DvPMWE(k zlWy$H9eh8U&BYJQJIluy-WaNZBQf6D!=;=7%|OnHi3L?CBx~Q~9AcZ+?5WsG60|2O zb>(?W=msTw2YFR}A1VF7p;286cc>LkDwI-hOcK~m^f424)JSmTr0PZv;G1|d-Krp^yjc2q_I=OLzoJu9NgfzGHb}0<5Z#^?P z@~4y4=Myh_ZyYYitsG}y59n?Wd+u`?D|`mpFM=A<;;S+`BoG(v0EwCUGK2~Fu|SaB zo2Mw)dnp5peJ6-&NQxJ{G8yj z0C37*P*i&m6y3xRgSV}D_-YcrQszzM>S|Y_On3;Jb1d$gZYvGN_G39ig|Y@|Op z@_VNxrN_5w$d);gZqPWbW#tYhrwM!eN~W-VcIxuoElNr6!o&V1iO{T1q@rFfW_#Ap zW0mpizM=bn>-GQENzP8ZmQGQp3bC%MhNRyU?$%xWWpU+@Mb=H8P>HH$GDP0}k#Qhc zbgvg};vsw82s^rJS!dH^uU@Hd%F|7UBeeU|W!|A)jrVq{K>)OSa?9}}I_XUBiFwJNwZX`F+hXc9Vq|H%J5YySK zk7@d)<`C*^lucv42V=NB30}e*$ypjZv4RGYcWos3-8KRg#TK)~^XidtEfAflC)Uri z${fv#pAVaEcB`#3Vi`{n&1a1*XDRkrG7@tuf=Vu`%%6WdK}v9AX~GpzAOb%aQW9TW8QRCxjQex(a(}1%oPykJ(hVwwkg-Vq9AoN3-8_z(5R7AuV z&Dy%(jE*G}Nuv>DAlj%Ny3?LM(NE=6gNQM7-Bf6bskv?keQxsL(9pMYBTAJUQ;L8d zmVc6MZt-;A8@{LUa5B~e1$-bdVGf)q@5wr@G%w60Yc!j8HnnJibj^|fS6kQ zk!)r^`-@Fwx$~$HWh$nFK5?jo$}r%ncu${j5wN{Y6PT@Rq7>~`a1lT5MrT8%66-O9 z%qq)y<4xBM@I7nb)q0OU4bM8K`93~Oe1Be^!_E!AKUc_t3jE+NX+?WaSrq%DFkRlM zfs&W5vZ1(15K^z|J`m9b_p@cp;fKqW4NGYXpF!)Ozl2ul@8eF)mXC&}%STO?dzAf6 zpFg~hlhl`+I2dc(i}}XUsQD2eaBMyLlO*b=q<%f|YPl)T$4(WpA6cm|*itq6?=OLp z18lliglmrxyG%VsNkw)0K?sWTZer6YJ?1+<3^Q0Or2`>_Zhx7U?4zkv4VZ%Udm1N# zWlJ&X-fh6w_fo$5(lKn?`j)q$C-^!?RwNviWG9U5-#4X4>#v2e;Vo+(oY?!(0g<@} z2HRpVuBmoi2x0O=-#J@iJ@o61Brh!fRkqPuaavl$c-4Fv4?*Vi?g%DlVaimr_71_a zw9<-3BS-^6*wxE!`{h4cF#LwInHu}o**!;9NrAW5p~S>gq~@+omH(464Y6}d)iEx4 z0xNVUq(kDi@uO<3rPasFsd7v`KRGU&tJp_o0J4*p?B{-`*7o)g9c>d$ukj#e!Y2_) z@5YY5o~|N0@Thn7xeW2`miZaYcHKCH^QO5Z0Gvs2NK-Z27}umHTkT-DqRs4yC|T1O zvxC7q4jl8(uJ1CC;f8K}IWKm#@XW6&|JWD*usrNiBy(Gn^$m2Apb1J&3~0&y7|k?L zLNG7Sd2D-#dKolv`FFcB_}7$8s8pPRUicEB3)vNUYM#mnvJwMv^o0C3G4|>cg?RoUgXsYsGX(n$2uY3U zlV%EJ-^nXS)KdMZ&JC7?>OXUNvPJk4qTRAl`05F{%Cuu_gy~a-=EhMH@Y+ZdG%p9g z8SL=(M3Q(2J`EP~2E9kOoRr4r6V#DVD>$dNor9chCBrLB`JK34$}J;pf4+v*kftWnt(ynGXse?X4rml>y6O$wGhnNx-k&A8 z!P=dr1#66kDTkZhvmj0sm{+Gs?6Q2WRuem8#7evn_nG)p4I<{tFM5It5^EQVR5H;i#x>~io3g0oZ{{*Rwxcd7B4Qv zp}1RdcXuf6Uf|o(=f3xQ?*29~nfYfjndF?^1If&$j5h6$qydM?QZ^I;ow;5#4UIyM zpq)v~Q)+wMI!R**f@tC<-pNs`n9%EAOc{IczOiLQPp=~2*;)dDp^qHOUDJ&}r^?xc zqwc+CeAtZ)oOk(E3o}$4-f)b_#vwp6W25X>T$c)ZQcI_xXhisuktOyc*ErAc+d6UL zEpA~Z4SI@oQ;H&XCp!1_Ha>;$&y3Q|ntR^UN?l2jr5z#dxovJ1Yi5|IB9HD*AR}qw zG;($Sn5mH)G7#Gawx}4)bwBc51&2$;y9+D2gLm!~hRDI)O`gX3Oi5gf8l_T83(%^@ zP+~cHGT3Bj=3TPeP#@n*5B;Xtx|crDIZ_3OT^k|o_3I1zaYq|{*5gK=w_AuuuCtxd;E53%D9y| zFZV#97wdv-Vy&HgwIKAiP6`5UmDc+Lym{2vz(J2K?kdaK=&jZJ;PA$y0aIk+WZN7w z_qFDH;LS7Zx3}i1!b8y=tM2fhhSE`Mw=IeG_b{4`6?AJxt4hV!1d?Cy_B6+aR0J)W zO|!k4w?xgsi6t@P9@6a7*IH!@ z2#-R&DdYAXY@SFtc3cQbH8i9)}jQMaGvYwzXwhw=u{HTH_0w zz3MK~jr8i_7GyY%%q|#KHZp&}+4`k*i>#5zGmB%3RlQS(-`8jsopT-u{(i_3L*qQS z{s0xd0?gR5(1Y#d8d;Zz`|JZkEcMBS__1>Oa}Ifwjo0V4i0bEBTgN*#on3wb2~naG zq$263fRzlV-^29ORYj6cxx*}Bwq~QOa};iJ>)$2&$wN06=ah!VY-u{(7=FSlM>Can zqL%h4u%BnN;b?y3^12K3=8(HO-#Hg;Af1a1n*(mLMDs%uE1pyS4n^2n8;{Yv_iBX* z%K2(PbN%IugqS#+At@I*6Yo9ea?D}RdpVZCJnrz1=d?uFitDj=f)YK74q7ddhrJb5 zqAk&cHg3z7e4%T5#?y6}TnpbFr!_*A)v@e*G)~a9 z1p7{7$O9SehL?bzm2G!5@7oe*h`RTlCE$d4DN15So!crd~^ypd_)oKSTf8mc!&!0B}66L1iEnP+Y zN5FTYD^rC(+&I07n-x9zN(E0jy~j5|SLI20#p(%eFsv;EuCeUQeA|&asLaLJd=F5+ zrPyRp+jMljy)fr&T;_um+EuLpP3rsH(88d#L_4}?_(WUHw?&COlQOyCa*iuAY3R@4|D@8+NJ`3uy;}a)*b7HS2BgCKP{mJBB^??%=o5^PW+Wa z?9HB;jyvlPu$aafZQxQfTxZUin&$vW2J3z1TbGXM@w=8x4S;n?F=II1UU)* zbzxr=`4PhLH={19cnDm>n1gPiu}JG?N6mHzp;o4X>w@mtVENjnji9~^;`=_KjH*_-?qp~_#k^2eK1(3W z?;5h0=}5$Kxv`gMju(9EXSVbg{d|T|HkU9MEsDEbF_CA)rVGxbnnQV@-Z^i&mBw!* zzpu)HWk0reAG#5pwZ&jE;0KlVC{X8UmcAz8?55qmk15bKU2-bnHHA>756W5NJb^_t5DdKl3_eR3lC`w0-TY zB@a4`Bh#}V?7N-^EI;rCYs^<_%~y$VE0gP4Qpj=wxE6!)mc#*QKz(LKOlq{5&$vI{ zAuUQEEz0Bmu*Ln6=s8YOl_elz`4Z$`nv7^`_U;FlBK+~l=kaHD=wp8`xM&>VN6Gu~ z)s$}aZzOYyIO_z%kOVHyS0~htF+y`%-@5N$PL4HbgbJ0O^+*N}cVKlH$Om^A8ZVV8 z>6Dl?jB>TYhI;5+z5r)_VOV>(YJVo=_N&n?eL4T|X>5%4Fqi3j%?zGlU}h)(*UsOwWW%RJeZP^Y z&n!-fkMJ;WBBV~DDBQ6I7+>b>u?Bnr1HQBm9wq!;H+|fG5thIjqthBAH0??*ol5&^ zBl{Yois7Iq4Wt`gz#}vEOkszCHp1iizL8KS+M{(6FY}IH3(%Mw$=g1Tx1tWO$azm~ zIEefcyYKv+XSzDSIR^pD zhebnBiHS=)_*oL+{!O%`MIwz)FTJ0Hs=~iUu~f4ta8mV4V1XhiZZ02rZ%DD>8A~~J zwK#ONY^y834|jj+>H5@zIY+Cdt`IR3`LLjy_YJe;R!Imb30RTOTTq@ndSm5=WOd_s zuxC3xrl=%jU+A|g@x(9l)N*;NBV?GSE#w_>rE2`Vda$<#c=RS zuzfVo8SgbNsjaJ9lt08}w4Kp7o|>(uk_jzeq6oW$!>XZKS|-^ zstN9Vxa(Zz+soW}c^a$FN2KxyeOp%k>_feSl$vrh&B2bnh);A71;3Te@%SLxecmZGFU~~g@^wjG zwMZ(K8FQu4s87jZZ&MaGvIjmCw=_(GeBwG=i=lxH8*6(3KippU(a7iJAlrx`r0>v# z4_3aStZ>!muYSI?d3T4E??EnTGS8aK{&_AAFd0I+7uwcQBi3sf&SsZo; zEo5sCK2$=)DYSD@L}xqCoGU{(f*N57AAdnG*x)nt1r<+0JSaoQKPKN!M`EbzW|kw( z3ua_ru-0aNf>UQB&yC9!I6l}D=oFL}IgjVtw>}=5)zoCW&t6bpIZmR}+w6z?qrQBI z;-_ea9XKPqU3{k<&3bBU%fmv;74K>zGLnngJYQx-)ab^?y$j4GUOrE@IV3uH;WdFb z5zR$uULLBP7X?!9k*wm=ysT>8?&ZsYlV#8DDm1sH+0>t}U#_@70$btL;Njs^eh5NZ z(nBvE6xh08K){-`lxH=jz^Ft>MJ~%ToeOg5%lYzyce>)l>nmFv*6~8IomxyK(cfF~ z<(}fH!8tZfxqL5+75ULE&A0L+qPE;}GtlTA=iM{9dsB~mGoZxE0g_=Mcmdns1kX)1 zIHXg9pUi3`2l*O*5$Lg(YZqR1EXU^VXF}6t0Yidxu|0)gLye0jv9)~8%5_XWEZBQA zkFy$_lC{0#nvs!_l8!R<3^^Nw))i|MsBbfC0{}Jece{LuB@f@oiBA*UEQlE_=oDaT z3K!hXD_Oa6Y?4qi`)>VJq*^ifX75(A>wMjan~DSF(tc;+8*n>&jw(UX?xk?Wg;*c$ zX;ttIs>JPWNZ`b?eweWS@>b3AmUEbJ^*)kaQ-GZq79X>QD0QamjQ!zuDA##+ni*k% zQH&S;%5I)A*NTGshge(vw-rDdOw@cY>xkc+yuS*V+3vjUyR* zSkVg?d3VUK<=KCnSU)=(e^zHHqWe7+EX*g-rP7CI6TQB#bB*$FYs_-QlS#v#wh<>o@YJ(SfZ0fQQm*|3K(HL2C`T~?zA}8#u)62md)028pXm_3j zHtgSC!3%TX*ZCponvOZp5JXC%JEIhT4%{`n*h#Ux$6`LSDDn(x#3J~tuTPBc&xqrW z79vX3HX@8)E!#x?)R}!5G$H(4PH=r!F3gQ%@9qXXoq{VPLHHb^IW$~QiK>nBJZo># zjTdwmT7nxvhWQKn-OUkrJJHQ)NO%#)@{vX=j&>lY5xrARtze-1X^i&N+Cl`nM`9omIZM< zUZ}zWdVE8xo0uu)F5fGz8&OWS+rCmJ)+pAVXr_t6l#RtT=naf0GxcV)krN10IQNi4 z6h4&8Z?44BOY_+K((u2%RWLs(RafaWsdfM!xgav9XUK4jMAky(E#<~uBQ#m*eae{* zHPuv1vNOZ-J$v2&hnwR*4R<*_v~-^2=B##iu;6|}y3te3LRcEv4O`Y9)o=5)&dh)= z6yNjw_@!r)hgk(Ph9;x#cy;iIeTUl?7Br`=b^h%WG^Sk|^`}8j;e8%2l zDZIzjbSmZ6OKmu;-_=+6&h&JuT?sP>(y-N@HQ1_aA%w!R8a8(Fq_c5whS8hvu6MZw z-0-Pas*&TLRgffd(>p%j6z$qpFYvqplDs*x;M(2B=+?t-xU-Yx#$A4QI3Gz(#9v1d z&o41uI(l(O6p8cJkh64iW@M>6z;_p8lFECGNn$4dq{ogu^d=gnG4*;c{fn(xWA0PL zuq<0gKhJy8OzaTy^BE2O(rmT&(BwxxglJ;Wg$NT$Hl{SA3yT_s9^bTcY6!9-fLMop zTiKQPaB_LP^~I7Z@A2Q|t)Il5-SoHBhOz7rF-?_<-K1ykhp8SpO)fQtE-Y75Qnv!e zL1J*-())ZPo25bs>35(6{0kia+VZpSz6Bv-k0X4xM(9;@v19MGYSUoDTK=rRq$7bKVnQ9_KcjkZS&)ggZPwLj(BhOxp3ksIJ z-!90a8cRTtr2{AEMbgY1F@jK^1@iM zq19qNT3+Q!j8=M@kJVkxPIc6>vIR~he;hRIfxWLPCOZ6B3{pY+ogjT;hC)?V8h zLf|*vMAGYa_!1>R`dIJjfJP|Nw(#=;*C~XEKq)lpzEf)x{3SKs$~-ZpMCkIPfsF@3 zxt0=peJOQ44A&f)Oy4XcE0EbC9hM4rDmUd8y^31WD1)bBF}}op%=0JI{`By;>f5K} zeR=adc)JttW$znepzI5MD!+2bVd3_JcJcH3W%l98g|LQQm-f*~1!+zmXP%WS$8iyBy_ z^~QJq#Jx~+=Um+`m8RDsN4xo36S6d%!mapwp3;xZ z?*RMd09Oc0DD*|@h7j41V1Za?oOrp$_wAS7K)%4I_XvV9YbGx@KYX1y`g`h_-jKXO z?A>*dBx{xoIVLN)oUwtvk3Gl`U6<*l z&d!))v6bO?|GQ{MPNgV@08hj zepTGL41BzlF7$dJJXtn(_ewG7to1j@pPN>@HBmvC;|SPN+a|rV9x+i=3d>z0ZHSNT zczUktn8!#hul0Tcn!sCWbR6Dt#t=JSZ|11nl~1Z}FtAnbmOb2u?M(o#S^8>OQe!(%L$%|TzGm9sPvcb3zLI8kfKAAHJVmbRB# z3c~tx&w~)+p)I1dHIvp5rWT&I(#u!4S~R5~|3$PS=;_Eq*2RxOIv<5?VW%AdwH$2I zPJnA5&NMSEu!y+vLz&zMTS2jFY4ev@I4-yb$BtHP2j*N{Jl*XxOqJu$EGWl){x_eDn&2#jgk>FUbFFPHTX7fNvV3)OY{w$& zWO4*ja^PhH>N>={=_oA)%Bm(Q=Zq{X8MN>Fl(5&hr5$?16FSH-8xv?>>pM;E9w_KylxHkH6+#-ddv|oH zLy3v4b(Nw8w%d1_qDeCltDF&p^{#6(=BJaxEC$<{sG%>dWSL z9qd8_lr4Ud3aMb z4XgtR@W$TO{sLRa6s8YH9H-cu<6i(R%Hfe5Ly5Q1guOO~smdsxE^d}1MYoBJC}ovg zIFrO)!f2%-d+prcEJDjM#F2P~#V(reueP;~53k8!P=$FaDbu1JAI`<~Zk1iNB}ZPR zK{LLqHI{DK2SF2l<2O1J#0G&SWV!4a@JX(!gKF7Dw!urbK|KkztU6fN3{X#(=8&(# zeE{KE;GmmOj#opNjD}X(xrTsbQe=Lk+>`n)$;5>oCya9l!x8T5dcBrhE_8CG|AiPp zq?8Ioqb{o#os!(H{d|pLLQH_Q%O{ly7qhzjN$m|Jr=>uUa0ExJ52N~~4*6&u5H~Yg zd_HSId{_l8itmF~Ie!-W@$Wn<=pmQSI}ow&lXPOrheoC!D-%nwy6Or1zDZWRj~-v7 zfTl_|kZMmE?8RkpZG)-N5-Fq)O1-`5lMsrPBtB$p_W6iD$K(U<+7G$!;N=u=YcIm5|sl;G{e8ea<1n_au)>lf=}5uLh9GuJ?awx>mlZB*X z_Y_4BxZ)IkuE|kK1Z`JL6hL_vDg_kalCK9K!cZ#*c)#uPMc*J)3V6(dx-Bf~AWTAx zRLFsnFD4r=V}M%WRffg=5d7IV4s!z+;^R{JEonZaa9{e$fX(!&fJ_h&HSZl#T&!KS zS+3g=nn{ynY<5&@@DHK;d+UO2MV{#1$fwUS5KDSkuVz?HLd2<}m;+E< zHMAWO$1!H@@K8F+&_0f7HN+}Cj|_gnSf)y=3~|j^I)Yy}77z*z977T>j5KXoC#YR# zdz*{~!;9W{`_LENIBQJ|sW957gIq>A7Qe@$B&G2yv!wvnA_#4uX>H5qppg}g@cI#M zq=Ms&R#b*{+admhCI?EA1&6m_f=Cj;vC%ZolCelkLccny{BtC;vYT#!FP18D@V5y7 z^Rx0>X0fW5rbH-pV3jB6-IB%SZhIH2BdM6KMc7R+X4$nqx~zsvw6-btr-A)sQI6=w z?LOCR6G2AzX>GEZd9hEmVxQE>@ROuQUE*Y_!+#9YnQI9ks|w&|bRSe%#;@tN(~1ia zMF_uOI`Qaak;tk}oA{_)b7xKG((99^ah(N@wEEeb*dGLz0IQ6sarJ^==M?nN&EF3M zZW1-FH|8wS*~kN|OX%REd8(`viDbW{s)Q|5#`u8~KZ+SxN%7!1q)U268w|SJ6j((w zs)bocZ9!R^AYznY?Yor?*WW3Ef580o?)6gI^6yd$N16TEe+ax`l%JOZ;EQ2^F<#;_|850%MntxUfDWXp^CK zEh*vKD>&j@tEO&ru@)%I9;daYsqkE)(T4*YcMQujds%IUS*(314w_sd1kBnIr-a>E1Q+)#mR1Iv1Emu}4)l@F% zkLkJ`OdBX(6K_g_`3XO`eb>a;fUSL!CuNh!enAG8ew+d|<)>#;qri_WJwDtq&q5r& zzon$RxPA%m6A?X5%_)m%P`96tTpdmBV21{r!0zj2ht~XNGK{$xMgqvT(2*2n>lIJ$ zH?qn1sPOoPsj~~MP}q z)?#VHc+kzJ1j#D6O!5hz%SI9Rv}D_6Rn}?Gwn_6Y5DN>lihFU+$kr|zyviBYOJx@y z!BOZe=3n9w<%3$b74jZe??r;GJN0 z@0GXi^>>A-O}dJokLIUNOct&P4qBB4GF2YS(@_mdsu#DeC4}IJd1e@e#B|yWb1Q;U z#E0a~2ldmaOeCD+W$CHvITJtCTKy2A&sNYI>%5Ixyuvm|)f$eZPL7+Y8yNO*GY^i* zjbZ4(8lF#WkYST$k52)#%A31=$p}v|?j25&PPQ8PDTl+>4Sz|y{X3LmFO1y@XdalZ z6U#=pJ)E7msK-kSHWNc?%C33`G@2mjTjA+#<+ZJ*b^g57%75T#r!`Kd9h?EbmkbL1+$a1# zrc08m%f(KT&1~h=XO`$cTr`@?MW&SaR`}D!_DTQ|lofF!AwOK*T)agR^4LO`2G(I* zT}1k#9o=k5ks6X}3T`%{Ewjx#nGv1HBrEbCh-+iBH_~T^5I;*4nmyB+#ni$kD2-Wr zxc3<_K*rd)>2Km_Rq-=`@0b#4Rbd&iK?5#B4AfaL2HFZ*ZCH;wiS|_Q9(()_ZEKmj z6@<+`m_)aK&C~ixbxfyg)Ab?oCyo}*BKXglsRt%>_7!K}Yra`Q#`r0#nthWAvekGi z3wMm9mbLO>${{1$cVg0OB9)pe!ss?oap zvFWj^`|4U6t?)#eNP#%Vn{-p=g+}04N1rGZX$(MyCw{ywGU1|Rd*&q1vw_pneQEWe zaT>qI|`| z$7$joRR#Bn{Kg&ndmss1Uueg)GJLiGcI zDWSR?84U};8rI9l)E$hJq~gtqHp$c*n4=AD94kerLB|U#MQtm+fJLX2pOB+VPCr0y zw5`l|q>0gFoTxR4rzAeKq1LV+RV_ehCbI%Q8IP0+piopFz#an*4m?5lPYAOQ9_$SJ4<%c$C62GQRTZ{{eOlRNDKWQ zLUN(Sb3n z6p_8k{{d7nlvsIiYI<|~u5|^GZ>VSjk&h1tXXovXGwYEWIU>-2ci8g>qNxvL6_s$z zf>RKpSfVL5w_?sj<>)yHyzu3^)Qsb4)Z2rIFm^Fq`cmj6v-5?M*2M4~YpV($M&I^& zQHd#C%O=w5?wMu*ufD_w>FEK3))-Pp^TBMRkTsx*L#S~~Hub38vuW$b%`XAk`>?iv zi>oNLg4@8t5w%?VY>4uRE2LuaHJOqt+v%V~+$Uptp<%{&qBcx@Ya#^^)|APOGcxk!>V>ei0ab(g1$_4Y z=~KWsvjx$X6>xHMdGtBq65WZx<>@(#9%%RLU9{9pPvwjqD95B^d3Q z(2x=3EDYdG>viFQd&M+*S^zDS`T9K-Hq|H5yhD&`fL}*a3a-pt9}rPIiXvQKNl4Ay zEA;N`b>NDRz6ut%0yt^i<>!Ro`Uvd|R!zV~AGB+ox9UfVA6pNz?&d^~4zsSl)wa&k z)^7Sn)#@JzsFAJWB@2C_i_=1-W6-2ws8Ov-82me@RH`y-Db_H)$@ND~i3QhPnW?rEJ6jt$_>uRVcqk4X` zxtZbypIvsDaR@;IoL2nHS+D9_A1H)&v|vT34K)8V+P6Nu^j+uD=zdRE=xxa<-FQ>z zf@s0a5E~T%XIvld$k5vo0v-6NQBReD2ttMEOe6kh$(KL4?#&>4V53hs=6ep=4S~=B z>!h6ivW(z2B8bl440F8!%EO)sLcb7c99_-Sh*q@lQ+L+A1PLR{g(^g}4um8d1d%$# zsp>{O0d9XAk9k{XI)qB=lqr>2&IZTWGln5m%i(UvgSRXc{^#Lr_~NFxTxXzR0Y-b( zXJet^WMs6&H)iOiM1kt#PI{UI>OV%$ChjFTj(@sVD4RUGs?{R0?2&~~K{?3{tJtfX zutH*8j8bH!)+O_qde03#VVzFNN&_RzQ?3I~Vf0S9N7Uo)2-lAcd!E8;5PP*fFh}PF zG4m1?-r#` zAdEtjxB-lP+IVih(1Qi;fmDDHcQ3|qZV zeD}#_`6SL|c-qdr%ID+2V8aN9p>8_-I15?StWsr~80mx=p&>d zFB~Y#I1slOsnOQ?j`=8hjj*G#K+V&UR!#@A*_y=JnkuzqHtb2CN^gpq{kMRs`vdVBa>+K_aXhE@piN*0bf@Rn@qV zP5P=ssEx9rpy$V+6_ijoYCR}f)L)_3yU8S^R;wHy z9dBfi8WwZUExk(o1%9|y5RwG!I0uncC9~x8JxqEn{z@fc{W&!uwv5D#+n8-dBN6t& zmW*ezMW`S~518diMjXZAP8lC&8WSh8Pc9+T!DXChzxQbQASEfMn19zu%|WI_qO&9r z3Y-QhNNka(wK|xDQRohaWe>GitQ_{LBs6bKDFw)&4hoaXP(H+olgKhw z8i%j8xP2q^3rPAr92ME4=IqXH_iMnm3d7`m@mRb;?mK^-2bFg;4Uu`r*(WV7oOm7? zbCBvH}%e{$@&idFFk`HnNpC$h!*bFguw5k~4(plv`6X_g%#J?*c}!5(@58X=FThiIa2e$RB3xp(k(4yYDf&YH*>qQ$S`I}< z*Mh{>OixLlz|E-e!%ni__%ErR(5oxri7T3KDpmrS1sM-MJZWRfTx4Vm>>%NFT&p@= zGWT84q)ji5qpza4s>`E!ojb`#yrw`vyLz|nFE)Xxk{JB%Mrat3A6}pHS{n4b4Z?CK zG`K(xxZ5iP50p|?a1?vigmCP?Sx-!>NoGy3ewIH$J&%u^q8~Q1FQe#ZS<n>JlL8;DV{4klAvQe)a+zzE5!W@6S;Rr!x<&x3<9hujYha*5NFwDA>fMiu6CT%5U(&gen zN-sOv&tMb~BH~KPyp`V|*-a6hT${_roAg!P`1peu>$5saI~6#JaSD?<X`!w#3psx>L!Sm?hpTLH_wSLU+eZYf+WH=ja>zEqah?_ zJr~MA+vHAvp#oVP5jzp<&X((B=8VNhuY(gkdnv>?tf8thRBJ|`sa(VzIhwfQr}s#-S5nhwZ0V3OIFx{TA?`8CM26-RXw;1 zmwKPxp#Y%-lDo*fxUnI#NO1I)FK7+tJOPP3BV>X$awn-$r;F_ZEEuE;J1!A@Re8uv zK1qHjQpl>C#tWR@)IZ_CVQES9!y`LPtY7LvGAi-PN2G_QYQ~9N#MXFMOjJ$fl0RR?D;p2H)4Jm*X-Cpq06# z#veha;KdywRojlmu&rsDY_XVJlsAOieQ)eWuDLilpeLX`Or~(k*C50mq9;B^P6_P! z_*^Ja`0-(xrKoV*Psz0)fpF}-EZgUKI-rwNAy0~cG_tv*DIx7%C<7XA;=8)?E6Yi# zC@SObi(Cf%a51qJApPa79)2x1mL5~YP@B1R^@27m0n(2qAK1tw`imIzHP(^p3GtBv z^7_bhCG$3}G?W@X{ETgI5V4ZD3zc2OX(tQTIsBL<%-g)-!sy_uqB$bt6FqA!7bIO* z!uYLS?jgGZGw!Q_UwUiHwiJC-9_Sx;l)oX@)_ELCMb?~S1JiQJ&X-KJle|YpMOYm0 zXZ=lgt@vP$f3aF(?i#eYklkq_rr+TgiA!;Q%m* zo{n$lE>rLe@Il%vQhCfQaYU?cV(K5YlrYos$c*h2DJF|uR7g)*CUe6!5+t#!8eQe1 zoi|i0#^r8}fV>z)?17(XVc@|lGEU4(Rmr1=EMV6s$jo|(Et`cVl|Lt$QEH~yh&^B8 zp!2*j3kK_P0Y`l@KkzU}k0dNCPFdmVWLwFY$$VbSL3W(nqd~Wj9|wCxeuLo)L==$fQTEo+~+u;|x_e4LLje|joe)JL8X;FXI6ZYYCWm`p_xreA%L`6(6$ zRLL$Y6@gGXx20B?$;plTFVTImuM2L5cJy^{sc{X`F=%~})89|THrIRZc8Az1$9n`M zO_7=x;p|g>8O85M6qu1tk)3nbh?CT6pZ2gO?a}8P;0gzro$@DWe?pZ&y8X)852W{W zcfxyn2JHJ?`#FuW^KtWx=gXzTtzzykB3#3Ddcx;m&5Bgq%@9+@=LE%69wK0f&|WKo zh2tozD_&oJ70yOT4UIR1>}c+Hq2>2c2hLhn>n*9YJ}};7NH+#ZrSE)jhcaTaz5_d3m;rpF#%4hopebkM* zC~jZn@jf-i=!9kPqpYQO=e--sdlw4$Xw5;?7td{~>=}7_)MB`2S#J*rwjl0SJqv}F z-|*i$DVRE&UmDB$RV1J8`Pj^XW_0cu{MbEZ$sc;nlW-sn_lx}OIM$*`W*JgwH3|Ya z=Ln3@iQ$`&!ISk89(6RrH+K}qXhk*bX{9q_yp#1AAp72VPK8%l)Pk^QtOKMw}8 zW)8tMT4^dcmG)PMr&6D%-Sc6BUjy#1QY*jA6>6!qBXiaGVGy^5yAZsY zaFrXm{=M?k$d0U2w_kb^Eq;Oy@qyYW%6XanVeHceQ&;nuYg_zg(>aQc|5r7XzNP6S zr>(RuCT51N=eZ3Z=p7lW0$krEl|_1B;wo7pCvmghr?P}a7lxQwO{X8LYD$Ml(+_0Y zzz9SGV=J!|-u58#mM+X|OuG(i%f8$3AX4+%**(jZk5)64j3u=oozsyS9opK=SRF;F zvYDh=GX5A~)eqFl@F4{iWm4XIh(U_OhjCh2YfZ!~SG&Yp9fjf;BY!71NomCuGdsS+{4LI-(V zhRNj0!k_>dx?q&ru4p*HdIZh7OwHIu*}S)es`SL4CO@gu8cpUz)+^;1w+F5&A-9{b z{KnpEG^4isWtG12$=>;ns8&@AIQ7f<{op8_#Wf478p(G-jh$g7m)OlqBwD5b#e}cM z_yqUMGMc6|4{xxgCyI4OhZ?eI3<}ApcWJ!T`ZZ+2#q;jM#T`j$WxhRr`d-MY_9H|*KO18|n}W-w6w$y4S8(h9S!g0Wu4?%v2H;>)dqo7|jl3^)3=!xYQ6 z3=Kh7U((+o%=uUnJdSP(XaK8&t)n> z)3-y~&sY;W{Si_N_rxxF#duAJFj>S?)E2AeH{g`rSn_x{j+A+RDFPUSzL{IJ-Kvq^ z&$OY^q$e_v+R9M4ir0OEyG%!K5E?nzz9EVG+q-m1TA#b78ARw^+bhKAKB-=Ea_1QoE$yDV!?|bLL!c;F$Bo(1y40Gb zSd)t*+|f<(qA#&lAP3UiXY@__?P0C@d0&_NNsg2|d)PyE#nf#3qPlJ(@le`RKCkGA z)1Q+zQdUG4y@b6CdJQa(J?`KaJ+LRq7+v#6-R^X!283F)f}<~>CXv3_e!NetWYEB= z@=G155zxrIFFBPotKIsc&QWmQY4zK@P5crEJFGD5S}ywV_Yts%hgP#U;c?AoP+q&Q z7$vgX-WP+q$&=!qn52}zywIZ(i5*rUSA=m|+d1X}9PPXWdbWOd{LoYy*D!yw!g0Yb zV`Q69uW2nW^qV9W(2&_+m}v|1M3FVL7-jk0a!FS+YJ~;8Cd-k1j@a(6i-_+ItpO3Z zYkSGFPD8HNzQ2HN@Ec_nPL+PgXU&-*g-2~{XAk;p9uV`}Oy1*96gE$8?adWy%0f}0 z4-XmdT%FZUt?oY6 zaj2x#ul`;Y6t^;LhY3b0(T1s5L$-+2@^r~=pz3YH)#Pjg&1IOHieQ#%viVD%O(A~h<}4=A zFjpY258em11RVGnXX>L1=nC-HahxrP6jhbwXT2w|jlxz}R36dBh|6V!#6zX` zI_4ou0`CXnRMw~_&+TL~Ew$~UG$rG#hS5~YlhkiL_+D%s*2JVd$Lh+62dUolxd>;d z7x4~=iu&Ip9e=_Ud|?2Dz(Z?;PiA1S1K3{)DR#iY>sbvB4uI$@;mrXMdnKYd0fe9x z4gmdY4T%#V@=7Ri0{H$M>HvY|5-@+xZ-Dp&z^S+{H~|c=fOlK~o>xMj3n1`{%-{mZ zy%Ha|!7Aao0i6G-DZc^}xB-fCG0Kp?61f2^2SYB&jYY0If1OaQWZDT)xYXU+5p;sAD z2%z~&EC>O9{70_yN`OU#AOv9m|9|9!AY)-b%xmqn12mEUzXJo2fBgCCy;>2l_x_l2 zA_6FSC0?!gA^H#KOcbE}+6!1t2r?7{2)=@{!~ndn1bF%gL3d(+x39I=Ip!1x&+(sC z0R|C*fZ_ns*BaQf;;+Q3O)wH*oBm8Yw*)}x_1Mn$PYDh`u^=D_K#39niC5XG1b`3< z(IH+Kk^qDw3BZ44vPgoNJTb3KOG&_+w_xkFq4U=x9l@uH0>Fh1T>kUQ3z(VtgN#R+ z#RU1v0+8SSSz(!Wsv6YbuD19fASnI=1^>xf0)2O zOdbSKwlp|bw=DuB3TRa3AI%Ir0i=)k5D>=-5D>Kg(hS}!@QPm)2jfYk0k0w4L5$J> zB1pr(5=&_S{;PST%h85=ybuulLl6)&|59S`r3UOrq z8O3`Uu)*I}{&KCs+*bv>o(%~PTo4c_{r_ugF*Ha?7Cd)tG614isFjj|mn1g?gk;bE z_I1Gb7h28=g$DAG0K4JObex{$6F7k_4+Izbe~rN11#|0=k*hQfPQ z@G3g^BkB$OD~j}l!T_}t{o`W2H0tpzaK6PDaM)RxEWsul!1xN#9OINt5Q6hs#Pf&RT6DawP}u2%kS8!P{hCrkct!P);_ zH7b@uAu%Y)LPB9f|2G}Hjz0>vEZ96PaAcT&YaeR-+bpdT3h8w?ub0e61+d1CZGS|> zpfm*l$*bipU@r9Ab|}z!Bh(wvPAwERXw?~j{O*r))0Brq9Kd$_gUi3ySX9?P4P+Jn z(PN_s)+5&a%4ST82W$AV{-@K|JP^Tg0B_iB;rd4=MGp8lhOL36zQfo*sk~gva4$E50nNJp#s2tg`S9TQssgnli>32A)p-mf&LxBZJkJ6BN%}U z9>%{>FRv)DMH}GNX`}wn>eMERi^oBQfUstRfMEZZ0q{qEv=W2HH=*!f2lr}401#dz z3yfO_7Y14wc*pCHXyoays6y=@ zcMkmF=Dz&pKC1!Vy>{ka1(MAM4`d(gp?_bNlK_yA`aidPZ*_3n79>!zI{0(%Pwzv2 z7-q`x|{9}MNfZ|oPi)ITu9T+A8w)fu?bT9lD+Qtoy^WVvT)CT+AM(nTXz0N<={4?nT zku!K0QQ-3LVOWTR9CiL#Q{_6~wiFV77;ixP{Lug3nnKhCizp@kiiC9kSyS47xOq~4 zxzW1+bVl9y#VQHh(VvUt-zNXRvaSOxs$&bU>;iiQX(}opASgBv>?QkseCYZA zIp@sGnKS3k)t$mof*LspF0%!~^PSxkXjwR#I!sZz^kwNR-Tm-iHb$LpjI&PX1toPK zv#IqMy)G#wHZUe(T5ONFz&S~Qp((Q#ELaqpGKU(yqww!Tr3mQLM^Dt#`N8@&l#nW; zX`S7~-77GX$1sxZ>Qv&l*`%MWr^MlUKYD$tbm;|i>B1ChF%?xT3;3~9A;^lN_^C=4 zE+~dTKWK)YJ_v)6t91>3WxUuq)FuiS{^CY!{!Q!D7k{t{o6DpfC?isF<0>{Y>AfT& zt%;PQ_j%`t^e%956|yn*SM_5y^-5z@Q3u6Eq3tJ2n826pqm?GKE>_`pw$PUhs!mrS zKORSRS&xUYMSdUu*%~{%`Z1eQvjml0h)s*5Wil;_hL(fNRH!LEh?e=KmO-zwRmhrh z7wa8p+%$@dj(VdXLcVR;0J5fEm)U;2D6L{7X2NK0|JZB}|%p zSV&)0=pE^PU4xelx^P55{b$N0IcTtZ*B{tTH*IygUg|)yKyth&sKrMS-vxPc18|OT z`uYs23vYz8HjVYaDfnkD=$-5NUk1($jz$EWZ-N_jH2Np}B=|MoA)73oCA+n17QD21 zph5<^FiTd(zc8rgsRa}eqcrEEdGC{;ZF3Q0!%+2()L41?Lh!SG(RZYMG1AJh7zFbf zgJHvudLII0q^VE!o*d^1xP0Ytzf;J8Q=xOPMqg+bhhSl!m1DQHSwvt`ZIZ#Jaex(n%k+}=a!v!$Ea3>q6Eprf<#q`^Y& z29u^v6jH}IiXV5m{;qVL&PU@y@5zFS>(f0r_3EeryS8BYG{!t?SLMSf15KM|XhTV1 z278K$moEN32NrKnug5&eF<$yOIS$y|7>O0e$t73C#I*@h{5($abCH2Qi!}u2C(7#k>9ky{gP54P&9Recdg`7*^AeO$ zUZXGlHgsT>olckGrqd14u)3_IngnG6ABwg{xY!+&2kW!hVURB;om;1ym^$5BN}ue@K#6UNP~YkEHmF+2BsONz%%+dB9u_ z8+Z)nRu~+pY@UQF8B}##KsEE^95hOX^x#QVYD0aJl@@$Jl5Q=|j>5m6DEDl*^E;du z{E!sIiHfTbOQp%u%08yAs@ej7m@H$)F$Iv}z6$yCP9`yF`V%27OHur|^emHRJrmMb zcPv+p+kE7SZ))lC0#x9~=PO2voUi!sJYoNq-Qiovx+Y|=V9gZf>1g0$R0^Tb46bx> zzT&~HJYcFW+NzKrUBV8`@4 zPgvLH!M_Ea_Cqsezce(Z{^>H=8r+Ic6O!jB)QsBX9OEQ>LL(=dk_va(GFp-fcf(v& zNDSajCVkCKNKY88TTwuooQ&W!K&RR>$d5A9l=fWBE+*aHiAlTB^ECNP6!XZKaSThP z63(!1IH~)XO_@Q0>h5LTgp{SydAp4hhMoZb2>9BiMLh-I_^vD-9=-#E2m1->xQ^EL z^sq#F7_ku0(E$STUZgap$PLy`RF*CA%M4E#uj1|a`&-=q2boo9?6~ z==-Hr0{V1`jPXO=3r9O5(o)f%zM8)8TuaFrD6x8`Tesvv#$$YBIfXOKUcGp(IT zc?S-`K*an4`?OVB%$X;)0_{93sA7CE z4}Vl#D?NwNxQ*=q=T7R!Y)U&R9B{~#3qBwdZWWvp(k@kXbB<&i@ngZs+Hh!j{*UXP8!$ixl}YJL`!WPC4#Bk&hKLMvBCY+8(J&kqHHc3wWbE~xuK9y6;(U#Dq0={2^-p*?O4# zKb7j1|GTvvUwM3NA5Z^kZ4EZhli@nu1WlXkR@7)6EZ2D3c+#VHk&#(6wps?uT|Bi= zW4dl{BSV($ScQx<(cglkE=1mQr}uzIbW`yjqUWsXS_aMR%^;-V_mrO8%ZFW`(N?UP zDeZK+w>4fWuc_45G<&(+H`XtQmbPOppq6WtcHDNW_W?zXw}9*i+Q^}24s2m~{A3Fp zmx+sgqV)*D? z49|%ZHGI2yD!&CqCE7Hm+-zyOXeCS^&eYk`WY%@(A7c#MQ5Xb58jg%Wb14|YqqJ7 zc)?N0q`FU3X%M|aZ@8I|HGuGi_k5V3%fH@Z&DHK2k58Rb`F`xCcMp-8;zOFOz|z0v zt;2&Qr6X=13S87aHD8FH`PSWs?)i8bxcQ9@p96a*Q#5E*LT; z2(@WTY&_#NZBw2wYDeNL9N4;Vpv#+4 zp_Jt+UFo+AHf~}QWJ@nT7kHMFijU!~9xy=L28N2V6 z|Jo7hdn|k(t#PKhhoIK9vF$|xcnsuPg7a{GUbF#kogi;RAFP*$&o7k|v=!~|<42on zn+;L*D0DXur3Q;m#|`ktVJL%qDQmE;BNDuP_E`4(ojdu7pY;@u^Z6i0*##(kM+;JHrNL|VhYrfr$;y{UKjK>T= z^tOt3;KfHo8KiGSsZxbX%P_tyjH(zke+GkmDJaG0Lb)T1I7q`Y5FhC(W5?b_m{fQB zhLai)XVGY6s8Pfd_oApAN;@Z8;P=brS!@zuuqM5cZoz*!-EyseHoRr^ z-zd=7k<4Jt%(YviHu4bBA>AQzYA`j z58~p!baa=@yOsoA^DQdY_Y3&f)D7ewW Lg*eG$C5-O>P{XpX delta 69133 zcmY&;1C%98({0wr#t6+S9f%ZQGuA?|k3?-v4T4t(_SWiHM4< zRclw~#8MBgQXwkKfkVK7fWUx&;Dy5`AX0$;3mosLxZ$umAph&aN$ZyY#Z0?4hJ{Mf z1BCg>Y&|NQuOOY;wpm_eaGa(3)NT4bH)}^35|6)J%e->*DPn~un z011`E0)zZlk^lb$5NXQykg!R*$Q2;yG>bXvVGEPRqb z3`~+6!he>U56_%7+x3s|=D((&2>%JZ2%^m2v0@PE{vsk6LDDkff85CfB}mg_hei2c zPyC;JN+Ly~`!}zW6p=XpVkijyvfc#HI$8&Rw@fSJ>2%#`Y(i{>|nzAu0 zLX)^YCOR-}El{x$@-RH#UP^f(ubRM8r;g8hg%3hC)?%I2N+j%*lUl@H4CTP8^r;~I zl%?lNoQ}^*Rf*4bg%v_1c0C8cap`{{Zu5*H%?rl|gb5_L^xMr3a>#M@cw0w-;I%A^ z3QNqn0qIHT_33sucz6`K-Ufd_*IOQYk{D-E(-gU_W_ptZ&WBRU;9s2@TYf#yXB`dX z&Cg6e=Pl@cXKR$+!&3 zzxxWjWGCABpS>0E&rSEg_7(hc4AQ^RfEDCRCH^NG@qi?iIHI&X6IcXbi!Qvc`clRp zU{c1WSvv#_1R~1zTsH|tcQ8pjHfbh`JP5qXE?Wl$cv1!nd;hm3o2a@stD5UKh$^cp zEF)4p@%KiJ6~F7&t}TzPFb~hIONXtrOU;w#Egwr4c2`R_*o_Z=_UCQanOESSYviUHQQ7KJ&r3v00tQ>lT+i8DzuTLG;9Q}qn<19(s#tS_VqjsN5^ob8ROKhN& zt~S3{F0NoHc8a9p85#*TNg;o}gmgk!t&&D$z1>zKgu;@3fkLIz@u5*}f@Oh@AyE1( zuVxD@Zxlm*Z~5^D&)!kEPDNSV$(@TPT}s=^4c4mvYWzr8_<9+vW%ugKaKwt>=G0FG zNOLj_#-Ls=J!}HRK##QZeJ}bFHaF!VfNMKT2w!GYEt3fDGxyymEFeosol3Pt04p@8 z&+1{r#*Q?WTOFhvyOua+OQtVZZh(-3Rf}PQN?Ui*224^klF!xGKB66^xs90N5KcbH zdN_nRYq7&lD3|2x4!cy7Ov-Mh#Ft6niGJD*Y7YjYLE8a+utSYPmf)CF8=!30ysUki z?h8r9AOpLKo16Nh+}pMLzhmOpvzC?{!@J@btEM@d4wa#z@RuSz!r`fN$SNx}@$z8J z@iv4{OQ3VnTWLDOGEq*p@XD|=SVOs#;C4bN4P}2jE^#W`!Tin&t*72>Opkm6DJnw5 zQZ#gR(%J)jcQ;D*X^VP@mFO;FOqBb_H+i*%>}g}pN4`LMdcIm3Oc;M-9Em~AQJ7V~z&xkl`rd2+PZS@1 zsajx4?BkJVMCHgOWzobt>LcE0l9O|D!39CDHB`DDJd{ZV>3_> zwq!cGEu`gJF*C*-{s#iaGMV+6DWI}Bpj(-ZG-L?HU}-Iutc?$-%^L-r6wZc!E^o(vzQu^quX$WT`W4C3MG;VG zpXzlBLZp5ZA6d7*d#l5BO6I?xj9#>Xp5M z7`q3{N68yH3O07AuUEc7)-MBvwv5q1eU9F=+UB)ML!`e$WGK zr632}pZ3Kq_JKUN_OK7!m+P#@?i<@RK5qT!^W+v%AR8f38S?G7AM9BVcKnkPgSQsFkcS& zc!wB9jq8@kwHLJ6!{2%6d^qeyx}RD71O3ZeUBf2!@Xpm2zHV7xljG}`UN?3`Rxt(KvJh7m(3L{qmW93@C^H<)(@!~+N;^* zTwk^{A0N|KYqJ4=ED#1dvg{52*;9k;)4aw1AWqXDNAr@KA0%BqN0ya#x?N;Y6;yMU z6fci%#XYENWXgL-ZxPR(chJo$NZoQdr#WR+&U1_(qYCa5 z?utU6^ELc}whEPndPsT7T3kA%*|3ZYgDXjV9M<8niWf;Am@PVY)*#HWN}>O%?UP# z!4vveXtr+%irY4c=QpfSFgf2*H{(5+IderTBDiiV+o9`&QOWHl`gNK6u+=KLtfIM5^Z)ArDzs~J~UpUKnSrA=+X6x-N&Pm>Pw z29s?^7B_zGsWk%VanF_TgmOmZb`lTKrnTdnk!@_&oS+eI8#)|OVB2d)a0B^9{w4Ok z3MhD)(#sBV(YP)-6AW?lXw%!oyyI4Bmc-f(MsmNJo7ZlkAlOn(qUT77Yr{DfD7-T}%eon+2wlREsQa zJauyB!7{?iO+j>Wcto2)BTzik`nbuy4l#eep;GC!At6iU?2gI`BjZA_$hf=8!}{*q(Um7w_zsG4KR!4X2qfQ6K@J={KO(1R!H9tM zKl4KHiF%oc5p!F{4R)9S5%=x8I2Or0f%m@$vcWuM-ch*;h2B-7HYj_lE(lHqt%UJ`O_$eleOIa9ko)Gkgh?>JS*c(WbdqZUhY_(-@xF-ys zv`~%n!KlHzPWBckx%{G6C zZid4%a-z1MCCzE61dSZfb;Jj{B(w>`;zk5I&%Z({ji0QH6$aUyhND1;0BHsE%m zMO6s=)gw3#@|hk0?2WEucz_!ujn?1_Ot)|T7#CKXYQw@CBdy`Qb4aCuAI@wPx!^st zuW>@|*J9mx$Y4;lA9T8OV_&;sG`XWRFEU-S@Mq8PA5l9&fai}AP3;KRzjcoY8Cud2 zYF)*0^O!Tq8}`RZWcNg^qp#^(y5cIs!*^m)U6t1|8{(EcNfno|dU4qo-W09yWk1 zGFf}FaZ@s&6Zn>Og!T+qO8htzJ@G&bdD09F$6m4&y*)ZJz~P5oXH+j)=NN5wNK0r8 zwM%KTc}Bpkgy#xMZ?d#?QOtZYPYGbmG7B6Hinkkt0e8SYVjo~vkcdv5Z2A%q-BpKI zK<4RrZ;%?$J1S~qtMx)3v1&k@%-JBZM$ecnIg$cQS01;RaaNu;B%pC73F);MYTDcy z^kmwk8C}FWa3G=&JdWrZ4kQ>bYJy}$?*%4DO<4&9>UTyIJz7kbkaKi=;s*9?OyX2#rdmH9O1juHuMY@n1Gh93H(0n*LMX}x#cB4pk8Hv$M z%rTENC-&eDZyA(;9S~@Iv6@jI`JqB~A*(me6wa)Uyg+_CdB`Qs)HuJG_x~qbHHAUz1|l)`63~SJ z{vZd?`i;u%MMtiqzMETR>?X9Cq z@eNVdfe^ZUB|^zB%>b-84B7M0+y3c~KF_`Y@DbVG3R9RrUTA;jbrb&Fl6+m>k$#MC zaq3}B|Iu-@vx&qfmb+t)WYS<9?^>e9ngbVePBKO0JdDKj zy1O1DQ!Ai-Ft2=cXPi<6jj!*of3zM)uMa(Y47a1{&^3WM;8!cizsDC|R10J=beFj4 zJ-6}Q!TUK{JIHh189ME1Aa}37f`4@}NTJ`qbbvlGHfr9U-sURBo4@?6%NZ|m3cr`` z{8B|-+i@)@b%R=kl#rcjfsE{XVsC#zJ6vCJnORdyrIj$aFPDlfRHL%F3~Hx|3rNCFu!8n053MCtCOq5A$3{$}hj9RbCQ4&!g$+LO6vR>1(1`&Vt&3XcCBOa zI~qqVqlVd3y=Iq*0~iC-_*&Vpv~#m6z^MkjZAnW*uGu#Y23!h8!gUJ#^@D00!2bS` ztRz%!G3ovrUeELjfue@vjb(Z-^qMS+U*2{palwt}|3}Q}2!K7!fDnOz=Cm-4 z>e1G&OX}l2 z3+nNka(NL<5{yJ^5e#~#C}5CrOuU$UbD`eez>#B|;Z=f)x%7l)#2dnhX9RpeAXp{_ zAlfCClHg@7$AbzhLCzh#UbuTGn2d77qsoIEd@B0+3encLt?XYKtCKzjKWf5_Qcg6aJDGGa%Ka)qGZa)vIG?IiQd50eotX-`hJN$s;5_Rbpd zVJJ&7FEz+_Phm&6i?2iWN0oS&|19KR+yjykYo2Kj_eKRyo(5-6J2f)lof$XI5C+!~ zvH3k}?+@w{V(+63L~@MmZ|#cH;6{uxcv{Des(IjCjM;iTh8A`Q=BiI8zpZopN^9!a zc99B_<&G#%J8MUXk+-J7tBD#>V->ghf=H{ZOB;5pUYKKex@QeJ7i-A5yMQA+p92mE z4x6RC;p52?k{<2K+THBZ5o(!|?|wA%j>9t}Q;Hhwn(?T#32gSN$q%=}QYTiS-zrP_ zlvC5Hh_tilIsCe7cMF2Jv>;sB(G?}CGKMM*maX79#j<-OEiOX5q`g)Fqis7j-hT3W z&ONd(tcq#kUX}P!kCFQ0K&Pq+_5#SCc4!PB6TFyhK+l%NS_fD`-xJiz2aC;(KYpk% z8)en3R6BT*ZTBY}SxRdHLfetI_&i8iq4F#T@jPncTz?!=&20a}OZPar4qE74v#BdQ zR~N?`UbJSHk}jiO*@oA|K9BGX1%E*WNfG+-J^es0)T@?FKlVK9;oh|%b^y*f(>su7 zr=9kU>(m|qNIU;YJnk?A^sR5T-@{^i8ch$_Q(>ra<%fFJMh)7tl0r#6=&Wh*?c+h8 zPhOG{(!U|J^Jkx&DbSrC>>6$!4}S6??SYE!hht&PtR}J*c}bVjF62nSyVuvb0l`}3 z51GO^hzBfvU#e*yNebL?lz_kYggG(6CBG|bIdtXdhAPF-5dv-|#dxasVTddweZFrr zGF*nwiQMt(yt#S}h0VYx8IkB8#g9d^%!q!Y00b0m%o3E};`E*jva0Mm*CLE&m(36V zp-@X!>+8i<3Mc0$@$ig8^yYs7c7Z$V_;z5p`a09Fb8UaI ztx*vEHmYpnvN+B10wFeZ#!m_RYVzb0t8mIJQT^1XhOk$Kyt~~#DI2{QUhfx1f9mW% z{^`?eIt|tuGQinet}ms`3@K4jqhZLJ%8 zh({32K3T&-C{VeXyStQmF&9IxuWlcl*4n)ZU(-EnXh^DX7I#2`SdLUBG~CT4p;Wea z6=`6z-#A0y!u{^#fReaPcYZbsQcWejr(6qkub2ewLqF$^CeKgjMs0ON&|`3CHpm^X zY{839$|lK)tx03*iembfTDr_DXfvlutsr@8ztt7e78vrQJEM5PEOQ_>&&CoKGz^eD zS2XXpwywqnP31%L>HFWLA-0`H};D&$@S%jq6nSoJVb8=_xQ4{n`GuaC!Jem@#_Ua&K`k3F!XJ3SRv)& zS7dJpACM7ks9Ce+&om)O-NYi)ZJ-?cqnqyRMplW6{O=*m&zmPAPKTx)Lpo0_7*++B z6*AA7jE!+^e6$=cn2H(~&z8*!POgT!S>28ZnRs~PEE92)WRq3I+|4*%tOUjXP3 z7wRaI13c#F-R#sLekO5SYZ<8>c!yO z^Ewy+D5zZP_G%vFE167MIW?-z)-Y-ZB#exqPv$XuZjg0Iu)irPFZi!JEfue+h8CYT%92tyA!nv6qamc(9T}PG z$K(-iWCpbHqLy{WJ~9m+9o!U)2~y?fobM_Z=YfPGxUdNuF&YZY)qjzcMXZYJ6nnmqsW zRmB4RHkck-lq!#4F2j~Z-(+a$fY;remDiChPXxrW7JOM zkpObTtjww%yQ!$3U$XdVgF&I^XYr=&k{&AfiFa zVQ~taJD0-)6ec!BULWM?6IQj4mMZ-udaXz6RjQ`vDqW*o-kC+eA5gx(e2$?{zDah5JF#~h zTthk$$GswWV}@+~k|GQ{Rv^gjI2qEvcc9EXvFM%XH_#Dz*$K> z+#yM%9*dPhXUUzGfR)nuQFm{hcnEZbOgBDkdZeP$+KRU zSjoIIn*QhKyQ`NNEwQjxsHGYUBl3Z^+i`if_?bgqhxgHJPH9}<&$Z>7TMdQ|9GgCI zr%R3*?t3m9wJh#VxlHI;_Lc)y!&c&zym&@nri)$6`+aQdWRZqXRJSB!eLT=$(H2ep zpvK1d_Y3g83^~)JzK|bxdgonS`YS=iSFTT|4qXSfeCBQ>wtXB8)Zbe zQ!;r=9l3wnW{>41oEHwZ4IxaD!F{8rY@3oX?MchDT+2=POnW(sJZTi2zxT|AwuWb< zx3+2+_WBJEy9r;sj}c)8gw<&wqq@0-gfQ4bfDRhH=c=?%0| z#YDPJqfvg8jvuV5VKUrls&mkr{9ZraojGRwzI8ZITeeDm@qM~cZvyBJZUx`em9mED z9I!DhVGbRr&%)1jXtdf`!fnozu+Zx z{kDGi+4v3Po#1vs%wly$w9Z6F3`J$Q5g%G1RUq;(!zs_0rw;B3j;#WUx|9T6&;YVM z`y~^!F$x^a(y!+HGTz?%d8_^_JCSdCdPw=X&3J_yxIkWHPr-1e`ViAMa~U}L*uZ(O8TZ|2DY zhqeu2ffE7)m;**3n`U?5C#&ZuYmCk0j{aO@sQpf>g-zADN8{{XwAca<|KeX!wNfbn zH+7`jGGjf}ve+egnLyp8OPUek9#`TNr2|Mq(u0j?)~5q5Foe&qwKK-Vs8)@_>Y^rX zH9lKDvXJW@CH%8?snBQDS59~F=>0*d?2m$!2o+OFAdqR}UgIkL4;%Vf3P<^a|K&m@ z5$P*>5bE%&2$nMvEkfG|Xt+6Gf05jX6VBy=b%;+$hMwS_vEKJwn3Q<%9PX9;x}mnnULC?X@kQ-k@DM8Is_j2XMlWJ(s zeg9KJ4R`bp$d}(1?MLb-$>+~<{i=Vy!E=WGWV<7{|188DD8eK)$_jREp|w_2wdR$f zB-8{dCdR>^gcH;Y<5h(zP`_gJ+QU7hXDDg8EPgr)Z5s!1=tj6%%*yMYv78CeC*et{ zI_3`8(p5RrKO0NZmrYrm9_34CMY;4c&C1re@x=nR)%gsp$FpWOWvYu?T=t`{zQyvf z$Z+aCT6j9`m~!exL38VU1}D7NtPnowt-AoZrrW66=Q{;j5~+P`Y*tc@%4b9p=Atp;<`v8L^< zCVcEf8AaF28+szzSPP-8+sjevDLU?IReTaz-0}Xt-S;e zIrMH1&0NoRI!kYa4C=;7JhWIdYE`A+$Lb~%x9HYF*Q8d>*mUe!Ot}9tp3pFE(RWK0 zv<%%MgSE=qtlr9P6-l5()xkVdIj`rXANtfGjjs8VkWlin38Tu-)`+2mOf4ZI;2508 zjr>tHKV$hemg9ZbPGjH2He-1L?<)k1z1IX){e#06N7NEFiA#P!ho=;m5s#fYl^93* zE<=nomlm3S&KET@-L_g>gErF8Nv1P8mBhQdAwNl^= z8Hqb>BbGKIrZj;C<22G_q%@pDtuv$XFj~!?kMr$zjRUtq&Lr zeA50dloE>-1t147cW-A5)1S)V*H-v8>${5CSl+_t$Ta-&xC67iatY3DR4e$tNJmgm z#z=CGP?nb(3rdsat`)uB34IA{sUmDqhQ4gkCS@z7<4AUt~cBXo+tRaoS$l5p1C6r@qZeha7Y(AGnE zFjN*R-|`=|djJEG1N~h6RgOdU9Z*1?AMK*tH(_b;55F`eAD=?H``ym`|BUkv@Qj3+1_VSR;4h!t zM*a;{g61#hY#RkY&`9r6ENNd@=eqsb@>Gr11VSwm`Q29?K}i28~lvA3F~B(U+id84POGNffH3H z6a{pEEO_Ne9XyNk^q>wf^e231L|b!Po&<~=%7HKinaU8EsRdTzLk>qr{$<+$o%={S zpl%qmfy53T7MvHKUb=KhtZXnuvzh!Ig|f<=bxj1$T<&^}&r_B`H{H8o{9>=RRErr4 zUep!aegmS)d`QN(sKqnwKt55f8Xqt<#%QPN)~)EU80nXKk?7iaC(@<`0&#)VQ>&j6 zX1TS}3^r_kQr3cT{X$|>E^Kvq)(NjnfRTdLFead>kPTSaw%TPy3H)dw851%S0v3(5 zCKTZ%w1YQ?3W-&?_#FC$`>J*rR?h4vlYV|Alyd2~uJP)+Hygv>E?}N__4ZoJ0k4UY$iB%z0z+n; zuCFhn(!slmTto{sr_46G(ub3o78(#YWcs&C*H*+AA>im}#Cc`S6|F>|se>mVmyh9W zw1&)9ZQBD8cn-Gbfor2ds{uLkWi-S&g!T$Dpm7=RJQI&-yR}rjrNk`Dz?En8@7-)?1-m}nz3q;=qd&Ox#G&gkCd zvY5q4u0K*lz~+OqoTEbZ+zI;aP2r>fCYh!fkFR3|&JW~K5-wM%vSAUY)0FIoDuj6l z@)ZeCt@v}`cCkw5F9?FRwz`p9Xa>aRaUMzE!7v$91A^NB^3)v5ltDJeA?RZa+dN9! zRr`XQN=&#hL|7<|x^&jRrE?8 zXhU-i?~<)!VVIQo5nFqdsfXqPat6HOP4rQ~BvvC-9u^DgiM4=smMOItHILi<$^N|C zlMP<}!JaJc7~mNDS9XNIr#hgMbzeF-=K^P_imx}0SUK=|2da0tfr9s-m3U7I?@M(w z?pCX!)UrHf56!Gne1XeafQ!6GH;AAC|Y{mnRmGeVf2OfOLOq|sTU$psGBe< zxJa^CO2ICIsQ6CAn~p$$W|qSy&`r%Z>lT^MKLA*44~#^O;E*t>&}W!^O3+9;vRGCG z`-hR9dBJq&(L*7W*;+dVhUjB$T=GSsQC@_?~M*d8Ay_X#-bmA4aQAJiJ z1BM-3G)B1j(-DWIGg1B+obZ^|u$r)Ye1f)a^}T?b+5ue4%WW4^Fd$+w)Esnps1h~P z8ym3<=0p_T`yf0z8*HlQ(uOGIlH($u2`+eA0O&4Xq4;f%M!~vs5#5bd1>Sc^JbXyd%qjo80Hsuz{&G(%LPKC2{eBUG7SPu3)J>ON!lHh0emc%8V+b z?ueDfB9`eWl1=a-JiTYiSk^c#I&(ljXl6yCLt9wa^rrO-#<^`QWm#WMyEqC?MW*n% z9(bbG(KWMudN)K@%dM)n)LCvUcR;O{5p>N|U_x`o_8y6>_B&`#bVQ$yrEkChgyZG| zl3!PmFrs{aPL_!AaL$HktjyNkxk1~~5k;^4X43O1n*r~9ZCe2hU+P+9OKKFV)fG36 z$sCnSwd%B%+fB&?U9K-dsz$z$k)1ud3AlwES%a`SQe=NXX41v4>k#Hn!PddK zY%cDBbIStM;`ST!Gp^J-bU45{O_n0cMSV=+oiSiT@@hizwRSc>QV@(L9C>*31JaI6 zupiY7l?Ph<7w{3g1Jz#IGGA+`4$Yb1xH_QEnx=!%wNmq`EOR=spo!ZUzg zj~1l-Mp8N*Ky8^fb6X(YU6p$fPkpNCbDkyzgjk-GAl;V8nY2=*uK%e~C!GJDfuq6T zev*RCiCmEe-`j3S6x1Ny=4XL*031Cvx+oe1>rC;8x8gwhbx!2Y2{jPG=T7+wcj;!& zjN57MX&@-Zgmn&?IhwW`I)g&v%4!)<#UW{ji+h`*HzCq#4u57!7*9;0p@tEjl@O~P z3^kG)OmIMHS`q7+9n;>DO>?ZmTzNtJvNaeVu`cABcDmCSVsGJMRJ|cM1*8;RB6m+j zLg7_Y@JLEem3yrrWXwHsI-4@U&kF;%>Zj-pA~luie5Ma3g(x0hDx$N$<88>Lc3o%^ zu&^7#tv;{B)>K=ZyJlpyyOMNonp>XKyM=5x3>w#%;E7gPAtP0bB|A7+;Cj@C-&@@8Vns3W_s38RPI^knfKYZ*h_U`!|dXpW<{Q!0c z&3bG5@Qd7I?ij-B)RmB`5LKDXWqes9de^}gI8SBE zO5E>}mHAEaUjIQ@Kxa~AgQDS9;|=*3q%E8GVE(G}b+epDc!jjhSwiaXg}{E=S(!|o zGGDn=_f6y-HIB#sD=h<~!?_81L_{78c?&~D_iX*{t``ZOmU z&Jt7h(>1r$n-k(R?m$Qi9@0NLnFV~FDwQUk8N~~I+9f^ zvLcS0dhaZT79aT2T}}B>`}B|v`&^juBQrtH66o+v1_<%sD{l%Ve-lfv4qoC<8YU)c z<24@F>3nk_wJp7wbuzybdsTF;o>IZ5_Xap4(iLS`UmlMaNRxBjfpFV54CvQFtz;dF zq3>h`b3F&R7pvZITCJ6~_`BC+s+KF?@xg`zbVlp-w`h?TYi<;t6}(Q2Co3|q05MfY z;%U%Y45h~c!vP`}O})gh@rS)WP$Ea&Ws#enw@%N%7?$6HW1iuvus1w+HxRd96t9=; z>0$fj{Y~1T%xWH9NE;{Hn9Ug$-pgn!oaGoQsN@lH4YKQ50_3!BL+)-jLd>0Eqy?NXUa#O(r_!i2l*A^vIu*x}#SZ{6UIjPH+wK zA6g69Oji5Q_8<8J&$qDlTpNs78IAXt2d)Ee{JW@oxj17FXCh|i<+G@JTUpC)yy>2ui zg>XBKAVJRCM{+zrqO?%tlCs{!A9rB%3U-Aokp6Ph&j7f|whHxbv5Fl6*jH$m?&mS! z=(H)KOs^tLGYoQVfoEj!TM|R1$N~eUvmUS z%$*ZzZ6fGEz*lz7-m!QehXE=P8nk(5b_n407@_zgq+NlaP>I;tEeR(-A@7BcqP9#2 z6qjrXCYySPKSLBA^0r0z3$=+tEC22*+*kMX=!I)&z$xpM3&}tkVBtSzF!TN*aVL%94&Glx4ht7^=>#h4^tIV zekqJmmJnTfE9^8@gV@b$TZ$CkHP)tVM~r>=-Mkp>X`jDxVyWyl0>Kf>-C6~hXj#Rl zbmUDcMXaVFq~xpr`uKbcezB@bPw?k4E3XBN$ons*CaHtbxabgc<9 zcGM;A(&l#5$ojHloGFEI>o&Y}4*5Q!u@1>lxBFP9QHFFkE8$sYsg;9Bx3J^d{+r^m zRRt}e8bdwTsN}@?=?En%8vJ3H?HNiEDO?IAQ_wnDw#966G8r0{GFiYl0H?-&GXn`c8aD{Me#!(S1u;=6Wk1Gtkz zubPV48yM57_@ne{RwT_Q9MfidA2iU@myN}2iaAOC(-wQ(sp!Y$^G!ute<;w8Yg8`$ z+4N?j?`!0<+ob01$Ls{yr#;!6_yZCiC+os66v6$Te-_x^$}0>?JL-k{I$7g|uArLw zBSk0YD6V^qPmKZ-vvKAnKb~esZpQSh!n(6j{I-H#45`*Tn=b=vXWNBiAWf^lN2WgZ z)QtHn_*Nw|5@_+SA6T)d&8r~u4*#)B?bj_b6Wd5xg(XD?_!GAox0v9HAN^rL%6;+ajC@sF$pV1~EOdan!*9oGXoI6d zxym?E<|M#{CS|G-eCz4mh8)vE8g=@%x$Ykr#g&0=Yjt_QKwjK+t1_5=m1$IEFbj%# z524*RxfC%B5$-8M0_j^MyBn94M4psL*U3KRHcVU&7hYBvEpPDGAxZ(>Ep5H)T0poz zInK*FuL2*rZ7Mt7&}#h0^Ej0)xRscmWA>7u?pr|5duwP;hmt)a_q|884|&#ybXj=p zq+NeNxToQ~?xmZuCZ`?!x8tBoHr(!MJ>w2^^{(A!`yXjsk%ov8+x!frwmoe>6=C=; zlT~4NO@v?wS_EzYCd3s_radi_ig*(Ih9iYffT<((Q}lS2P47DNW5 z;O`63T9saQ*N)C>*Of20$ww;{2?-?HGv$s96>;v5KxKJI;1C>E$(OnE%A_Mwf%cLVL^U_$v1*csP>2$DbIw?=$(_?A4P&0QA<_yyhVH3D9V#R8#EQ<5$@Ha6W z>=ceT-vWLn||#GvPP6D_EW~;jycgHo4J{fF=Xw zIyFrH4^>|o7H8A54ZFA&cPs8%+}#Qk_u}sEOVQ#KTf9hdFJ7RyySuv;cl)^E`SHC! zmOaU2lFZC?Bspg1nnVXiWMGV>vWDL4o=H%Dio#9d@h5f$SP`--HF_+;TXfxyKyJ}! zUvMv-!&7I;^+37|!CQ#$j;zZ@6V^rs=2B<)bH)UcOJy-`LO4y0e<#~W*X&kN5C%s9 z_x4NmZOkmMQD)UXb)lU_it6NBS$`V>EJd5P=*mbj5cSQsjG-S6A3B~VLg z&HB=1NLZ@3P0TtVK#&{$zfDZU!5$4+@Dm^46A0c%wfpI1xOv{UDNSk)3J^rGBqc4{ z01WXL2B0_Eqp2pDd^3oPnh)wMnby`RDXi7EDESVuZ~pX47|UC;7F?!XTW6(Hp?#u$ zIQ(*xc5`idbKJcAIqQnt^I~V%XZPk|*xv6VZFR`|VQLnZ7}B3-V+F!t%;f`&N82DN zGic(E=Td&p*iOGr@3e$==cc+1d~Fb(MOvpVlDOk>vNn+q((RuG2q;oH*iL`_*kOa_ zYO@;3DSYIgb*z}kF*?L3pUPuz=sSnUr4I>*OxDV*EbJ`O`VBPCL`|C}t!Jl8OZ4i? z-G;1$pva^`b%FQ7UrW(61g9487w~Eq2tXP{wtARW*0yu)!uEFd+Qjq3rfpV5enP-| z71M!=XbwqQ=2ic1O8%b6!&k_zh72W!-j~1n{6)H~)U8b(CZxrjbsE%WaE;oO22iIY z@U4esDZ17vLeY@;yIGy2@L2G}S*fiCDq9ibRqML^m1)G-I)jObazB*xgYO z%*R0|=&)MJMrk>rVd*ejSXD8z*wZph8a6`G8&C$Km7}wKa>3g8nA7Ujecp(zhKPPS zDY2Swt{hURg>3D@-S1!Pz!o^~nD~)#eMU(~?ALs`CXOx9Y`C!$3Mql<7jKZUj+mUW zSO!Dn`S-fu)I+hdtLj`TM5NRhqV5z-gf=g3iBOfWqDfqa;qOJ02OmE(My(T3Ih!pc z_9o?;7xI$79%N6-7w+?qQVIo@G6pE(M$(Na;Tz8V>NG2E32r}C6)Wd8E0rv0j~-8q zaPuyKED$4~z_PNmTD^W?5awte0VBxxm zWD#m>aV~asg`_a_{XUX|6bJVxOQB-~?_h@KqLd=e2|K;4lV^%`mrWBi6BX@bOkg~yX>R}_5+wpVUV?=>*ADsJM+a(4VXkLHiKw#ch1o%4(m=qY7fxUud1 zQpK+Lf`wPomEA7!D`&Nn_Dfk#3E>Vo92mD!4kg**p-1;aB{|M=PsCpT&3?aU;~FL2 zS9pzmhg!(lw%WNcfm(LZL0B73+7Ye|FVzkeP|lH3*SziOR19XmYDOd199@L|&y@wA zAUbQd@|YnOTpO}OE{gZ}gf!ezK1nlC#vMi}OO^>XHCyLeVmqp&=NOUAal~pq=|5-`H_B~+3uqvBBL9ve-uStx1S(+;QPfms|o}&pwD)F z`r)Q69#8W#8}fl6aARX(0qN6D%xN2-UUM(N&ev@9|o{#o#;p34@gUb0t>ISKw_ z5-UZLBh07$C<)1b%osG%J2C`rN&$b+irEFaw@ehmAa_jtlz;I(4IzRkUF60EW)Np9 z|2210Eloqtq(QqT8CUAggtkxFNpNmtSOUSu^yJQBt~$l!QBub{d9H9qaZ=|O->>~% z2r8J$=OL$To?kll!>w!l@fjb#^5{7tqq5BzD94uD=@ZW@poUBY`X%5i6#2+T{Zb{1 z3Ll4|H!~hGkf(@a!o>g~nkf^8CgPVy9%aI|-29oOEg*EBYv8czH|kntwX zrwHY^CZ2>;`6B!c=kf@#6gLREU=M)Eh~gsGaqZZANFEG9Qpmx}Heb`X<>82BFt>f3@ zK1J)X_&!Q_*%Xs}SH{0)E>rLP_7Njzzb34B5PSc8Bg_NL1J%M%owQD& zqn%B>h44_5ttbxW^7gPEX8P#gylOa61uJ|9Ny#-8F6R#po1-gm+1DtgG?Rz z_7TZ^uKUNOS_<0N5y)=vi>Ch`OD${)#bB__Ihv;O$8)%;eGr<448YYVxqrnODdqR6 z=Mj=6KX0mQfk=Lo>swZq%uORXeb&=+l=LqAL|9z})WbQOOT3t`g;^Xf?_61+(a5Lo z$e#Jbs7K6qy=QeT1}rxe;)N-fbXPw-oR6A1$~0yF^a&+W$7Bxdf8f5cQ*(L{VYp-wkR)$5u?2DXy`AcNH1V%quiuPDZUiVc@UCuoN=rgKetViMmwg3cg=$?oQ;h1KJU~L7ihO8 z)J_b?IM!xz%z;$8c(pjs!&nbz6RvRc{N##$svKC#KE)}6SmxM|v=G7MP?HAfJ+!L1|uMR#u|w5*yObIb50D->iun2tY?(y_ui*K{P{@}%AQ z`G>8cD(Y{fl=!=E?SdvG<7m;EPc+c2Gp5m}_JO{Hp~BP_fFq$Jl?-3A%F%foZj&a{ zQ|#bW0__C?;}XBGF5ZRR6xQ+~3c!?{m&yvH>rb^zkQ8bkwhSD4cu?{}_6BA`f+sjK zR*!V97s&>@N;%JNc?^I4Ne&b#8vn!TB;m93-4S8{+XWI(0faWU6@g{ zCjJhD8T~P$6aVXTl3D$QAk2vzy9jpD%KQ{&kGX5Y>gd`NZL7PO3#ay7xj9^-z3^AT zSW%{da!1K^kL>n{KJTkwe1Z}J@^J@$)EzMw!KpP+=dA+_)`3D%1ji?dRO7Q8$C-R3 zA6!ZCQ43pkV1M?bg*vYU2dwj*pq`S7!AJc}t05R^wfQ5gWO!n*nKdEBpd&1!wcW zNSp~_TS|A?g8HnHxC2K`PuExvt6vtrp$ET!CWaJA?|0c7D9G=vpScS3oXAMsZEpcN zD8uW2?c`={OP^6kg0@7lZHA$NOasCCm(&C)B5GQ8r&u-LcI~Z^KS}BIU9ZP#Nzm2t z8n=47GF?(#lG+;m+oV=Gb}d@k#`kQF|7mopvd>X8v*eRM!j-kahvlWE`G5IcDNXW*94|nQCJab1CXuqR_Zp{CiNkJ*?V;Of^AJOKo?B7g0ZMlRFufq}a z<4rB<{;^YK9->1oRtn5d6q^~JqzdG^faAorvV`ZFWydYS2g_(-o6oi3HLLA@39KJK z!f8#L{(x7H8Bxb*S(P8JZ}Aa3*li68w7fD!n3uYU^f#jz@7Bc9x}ltm4tZ1|`ka4o z&HTa{7n2(~M#jHZ%&e3X$UjIMB)*=EU%Si`2BRkx1e166Orc;J@8}$1kQ=$ z2v(4qEox+%s>{zte)?<1`(=VE=5O)A{q1(4(f0PXpdU2QPqwYM!X!4zZz6UsduxDf zkM+C+*$=r@UDD17f2u;$GQ{_h7Y6B@-}j7w<=3-!;}P72Xj~sgqDG=7lPSKO*t6a0 zM;MA7x|( zJ{NseLC`q-+F708g^eR`hM+M^aG_l8}1{N zr{CR8`(iB_F&TvYtZ=122(n;JS2{s1zA-}uZ^BEzkp8Oo#wPoI;kGIwmk-FITFIqa z5#l6^hguM#Sc{1kG>L<_w+B3NA7{_~1HSYcD4r>@e^;ZNx=*+A{UM^ukUgWJdU!}I zvAyBQAxs!`MIk+xN01ug_e1*=M@&1@?oVaef+?JYbCm;YSyMwtf`njC{&4hdAJPd`kmi7hp&DMnwwyE3d!%2^o2rJ2aNo_usk#m%-r0m$^3 zdYA~y!h+(x(mcwhhP&ksDC1vPeunC!3rw`cp!pQ998de2bg9sO3RO-_D9+B`C5{JT zh2`*m8{tovD$ot914fr@)md}mz>Bz!jrgjknwQ~S~$sa=>G?lif(t^Xu z5jwo1p6d8-Dfq`9rOg8+Yv8g@N{+1@5akXnMN{Ii?b2$2&aO-jqxw)8i(wRBnadEz zY|I*(=s^dBX%&X{{qtvvjd&vqxF)n^ST89fqpR?355Ca$zQ_=#11CKUj6kw|%#8N2 znrlj;iy0PqUpk&mcT;6$6R?b@b`xL4&acEgJq5%Qi)3`sl}rU zi}P~MYf5Oe#4hiBG59OK$}|e0->Eq9&a@^3F2o_Z%p?@Ji5ZNnoopRn>gYU+GihCW zTQqI*WVRorJL5j5ZJ}X}Q^hRa#ZKV{CnsQ9xw`a3!X?RDu*sL#PCPehWHLvlDuV0Q zm)fjAr&`9pm|9BN1$%@1k;k=RzU`d4>5R3U<}W-yL%H>GUO*^t?l7O+>q869nS}Jr z_lLoZ#)12PyNVW8Sbes0OH=!(h&TOXb*PYxHYoS}m6` zV<@Guo$qs`Cl|By8?1A)^Lx(XJCmjDBKkZb$P&en1b#vg6H_lqXPMHzm=RhWK%g#ilsy0``G=RlVg zS8=l*Llem_PBw<#VgfCW32B5`Qd)oPW=QKfNEz)k2z?9nS$$z}f~$lMz&$G&kpo1O zpc{u~Kn~l5bd%5Al|;&Z%~d**%-Q*`W2~k|<(p#{iT!6Y6WueDgo8oK;((F1+U2rI zHWwJI1)LS}Pa086%Bu?GdnsNi%re=ALlZ51% zwnVqlG@g&^__JAp+S4z|CzD8>8daHa5bwv-It%&oeLVSP;8Vo1i%Dh2P+FZ{IeR`I z7t!$#R#wl*o>`T8&MCa_sx@3~;mmZ!sB&J_B40q#jtd`qO%I%DEt2EH77Gf&RH|{s zR^bpb#a87rsc=5QBG#s%^$Z^ngbWm+XV*^(v_kcx8Q z^Vu>YIqipHWz{b{h``1VTnOZZsQrs4LKHuq;B^nx_yD`a>&78W zYC&pr%ZR$#5bYsXc@7!{$7G~INwck^o9pmNfK9}lfraAt58b?ujLI08Am=j?Ux}TB*FA=CFemvX*S|qzsW3tyq(SEBGxz1vSTm!Om&cN* zrDtVGje~0gg0z zJ$L!@$pa{4QhT$9E8)|dPtIH;>Aq=%vfk#zYwaK8R8;{z(LH~joSesc`o%dA(~NY%YCyd zny(A!=^@fH=cn6h_*g(UMyJ4DYgd_~e4+`tS`-7L&TRi%_&sY@>PjP_TRD^K&atLn zs(s@6GW}vK!fCfGm;(uIQ)>@sA=d62tKZhTTalIE3Oc1Nf}AV@EXRGK|R=sSRpVp2hTW&|ltQ@)TcK%x>+vOSLlg(?10p7YGst4HT|t}3l; z>L6y3Kb6War~nI4P(33)D3U{&pcbJ&+SkP9Z)M@Nba9vg#iE!=6WpB4;}r|Q4~o(O z$O$4>Z6{7f<&xPjPeoqrnqBB9tqqc)H4=+25{dJWMI#_K3aqG`^O&1ha*&~o3wY@v z45^CIoJGM61)b$r0;z~#mQCPKVAF0`eH{-Zys$(2MO;C!acu?k9O2BeeP}A^y=~F%w-8_ z#evxX{wZT%z#*8~Y^B6;a9jMLF)TV+3JAWGry3{&RQ$l@pbbeGBY1H$`bp%^#tjwE zq6Zn%!N3hdqV6!}=JrD%SjQOy#B_RkJfZMIuZDhY*Kb}yY5nn$uKjOW==#Fb?_K7A zc69`3qljY^%tatgIc%O=7`dj%Bv~Qw{_2zm=>Z-0fsik79GuEHeCscWA3e)1Cu{i$s5PNA#%i%?l-KDD0X@W;^@?t3dj}bN#pvrEmpVr3^50p}=hjwp0hu zgQy8dKs{g1*op_~9oU)?bk-_9bU$!<2#hSHTV8cEQpeO^C*6|mzY;G z8#0C)VIu@sJ{YET`%*e7vRx)6xOEgi*mPeFI9^w9Z(lBydDJSX@SyGTV~y~_q5w70 zNz%9%L=nwHf&;6iVQr+T!mh#t&li>aKtWz@0jVVc#TrVV#;^|j3B8UB388us#!Hcb>q^3>Y3^oF4f9aHFs z{`TD2N%@I$o^%}};2__@u)38*mLe>d4?UtKRbv53kEm_#{pl1}B4UI_W0FVvY0`hnAOEp^WGW(Ia-sYeE0L}vr28-EUL@6T&h$nM;HWXzMS0a7 zRo<22J8pO*(INfv4P)1C_J`f|Yc7e5HDX6SB7&2Sa!idqLQa=X!sD3f(CsXc$0Z}h0I}n+S^N+*3FKduq`=gpCKK!F^Z$)K1A7Y@J zLu?s5&37J$#ve&0N&Hgnr~>&w0C$alJ9qfO#9o-#8w2Kdy&;@8tYo#jA%i}3)y?s~ zBkoq8%$LqEGQ|hl@btb6qj)}v2Rt67nO~#<&lSS6h9nAMA|@LwF<~1X;-IWltvpKD zF-UP=p0$Kt4af7o-voWXAMPp-rMx?Sb8yNdP1%NSMGU-vCuo5eSYgf z_&>~Ii4-y)W#xF+!3ybTMbtvP!TVb=Fo!B#s}<=6?31TAuZP0`X*4J8s*NbOWf+z} z#My?}u;WPX&x_QbETxeI20=_@uvJ0)oeH;s7^a^IW$ScxlW86p6V9Ca1M^@}RHsn7 zr?0Jq!1Rhjz5`RmPb8N?F3n8D-vjp>@q$AyyN$iwJLG`<{biW=Ug{O9UgE)AqdFe! zP#3S)T_@?Tbyr=A{1paseB}=?)fa+muLUAHRK=alquTSp;Mqel+k*li>_b-g0Z$%? zm}ly^-MK8-74f&6+?gk_2_sTgA;Kg)eHOOA=d>ABid%KlJPZX}WFlVguewgPj`yRH zbGB86!WgOzBMi7}iy=)P!JRZLRWSYn_M`K4e8DK|&y;Qal<3wb^hIO!&>uA;;L#0# zcN4?5WYFQU9^)XKqZ4$7afJ2B5S13LsXdX!+4BPaq9Mz70rD&N_&@ngR-c?F(I`m_ zP4tClj_7gfg-t7+b`I*PQI$mmUN}3ECp_!1RG)2;9lZz@v6H8v`dDm)nD6&^3qv^_ zElM)=65CiG75ftAl>XwtfCak%4Zmr$h1#{Pw!+|D2bn(<9)dt|)xFGeO_)06e0P%u zr$TE6J}?Nk)hwApuotI)KAeCraE@==9B^}=(ACsQpVVd^zg=qS;<9}87WGDN+(WFc zDUhzsJ2$$k$o@IfjHH2m31e`!TeFp4eU4p#N>;#uHd4zyT+N+$NF6b~j;&F{Nk><& zMgMW+djYt}Zr=}-G~JyViGMo#qn3*-rWHE)kwod+EZuXo0NQo0nr-BdMo#ixt;nrx z8iiWCedtH)J!ZT+Ldi7%tA$GEUOz^_3_jrJXj$;#8ZNE~w(vcp}t5mRkr_jZrmaO;b73h3kzI*N#y& zWHG8{eRh`c9y*x$*Jta8->Bv)XGfg}`k|v%zg0&WwN(6vvYx1DTatNwp-GK+A2>pG zQ=a7$(wqg>&{RZBm$I-Fi&k3Kv^^rvuz}~13cl-T=IK+HF-O2*f0$2Y!vCd1!33eF z3+LPIZjjXgCmD9qPT?rCq%cO9R?agaV$_h8QvM{#q~;h9Fi>Q};s zUq}pDUn}mJq=AM~xl8+RwmkXfL3lgEwrj0zF-*IgPInEnanAOQW+sc@RmN+s&vi|;;GkubG4(^n4FZp0>xQEmBR z4aGX0b@FS{Gzo{Avgml@s|Y3|ka;J1HZk@u)~@RC8Pr>YD&2(aW;1_eg6wG1bDz|` zvH2|7YO+&6*cvILS}lfx54lfAp5D+0clh}SrFbvqU&YYM#pwm1WA^)TtUb-l&saT9 zdN)9l$E#Xu=&hD!_K}1L3`}d@4)X?#I$kHijlVU-J%fAYm2Nz?JDVA?yfR@Q2Ee<^ zh)=y6YT%6R++lK(ffvR`Q00Cz^33az@!=K>7n*(1z%@?YaF<$kt@&u!v@!U8!EvsSlUYcRD%D1};hy$xkAV{S#=f8=2HiZMa~}+UU^u7UlC8~Fw4;{F>LX|z zvt$%h70<%;rEf28U15v=78lTw!$02tcUSoIlzS3{T`46a9F0t+GOC$Nk@eKCjS5o( z{`JaV)^1gVee%h20ReF;e>fhaejVF>!RT{}WVBC#2&-mY4?Y*)knecPj390Kk*x~0 zoJYj3KjAG(l&}E`NkbYA7?C44T?}Ai^Ty`e%9T1j<$4fy8a~3og}~hkRIVC|R$u3b zF#(VmSuZ;wjF)7a!zc~zAs#YTCacmm?Kjg*A7bIV1 zfQWLLl;V|wWSf+PBs900-`4&%?T%PUdyoLqcd}wSG5}LOAZKoFdR2fw`!XM^?Q<#7 z&3FTkAP%_YdRv>0TQg15eId4}`Of1*e{ zG}N>NlOCZdsZZrSQ6xMVV{k_KD|nQHYUEiVa@HL-VcXnrcjh5YGug8zoH+?k zcwp5%MuJt&v|4t3_!jt(ihuDU(gcPjSdwlN_6m>aZ5-j{ObMmFsQwht4N;&SKKSTK}n_wv?yZjq*Ks4I>9{me0Bu1Z#n% z^LRO_Mwd>I&V7@=vYiz}-5{Pt;v`BWi}CGWCAbitVtK2}b0YDV7`9AB;}Nv)LD0Q% zYD*T%u@9Ea%Wl`5_d#;6n9G8Qv7eIE zh4IUJMkLO~msVJU`s-Z11{#H)pyp3B!0W7`xIng8utfFgr>(DF?K2FrwXC@0Wl!Ph z1@<%_q?lvui@F5m)rwYOxOVOq#anE&cw>w@$yz2b+;IviKn{^fC*$Xjd#CgM#^;X- z*aSww7mrsn=rV(|WgWctFGgYePm@vA9OtTNeep*Ezj2%#*^rZWQvnvzpq2dLk8uQ_ zbMEf_+(6(WTS*leCT9|tL0E4dqzfySiNkLQ6*y*IuE{4?o%r?;2hA-85nKdy-rk)& zE2O$x!{4l1eAguHzcwtU!NRrx*Wm31A7}VJtej)F_pXSX=DD*R?h^G#dWBXyH7i`F zQp++0+i=X1=V9gi9HNg^2hkwbbt)Yr*H{xbAQX9H*hY*XkbYetU*OHeQDK&Ek&x8M z*Jmxm%711kTUf4K6vZ2ow0;rBWF`!X_{@*nBWYo8{nB+Q&8fP;-&&)QxF!G~AVs7$ zzjwg1ok+3UV7SJs?3Y^eflD6!!&#Sni3b~-X*Hh|SJCDceA(pi8T6!N_yzXRB@*`p zldtgSo_kAPi}9Uag(j1Jl8H?G2&A(!3JN73?247fu5fjFp!?@tf5DU;n8!kZM+*I^ zw@lmD2FMpxNS{;!mg`>_w<=s~Uupc)bietctQ9PoJ_Z49OKaHtgkX-CHowyPGt1I% zG8t&#y+}g(eAdQuhXgeZ+`1#I=}Zi8!#pCr%mMTx?iI;Nsj-*xs?NQkZ=W01)I9<4gtTE8-vV(W%%Y=F_TL+ zS)6T$bS*2wI%4!_RkLkfvKE z4LbUmndjU>{t4Ps0=2|_u&#{+%jlQwuA~NUBdI>Jo%B>;_Z~9bp_zFV2-+S@@cE3oI?rzZh%p^a%8klnbP$~Takz}w!$55^C(iMH1AY2rA z>tR4D4~EeRL}L-jJV0ysrD@fw>=;fYCMfd&hXaxCaMAXFWin1f6!g#Mrvby3n2@N6 z3@AtkT?;3^4*@M++BQx+T$&K`qGsDMK8;@qeN@hq|0p3;(Z6>Wx>Ye$P>=-a^3E`b z8F9cDhH&=~TJ5im=Gq~01dBa%lGfp1^)@U1fQ=`i`Ji#SuE7s}?8S4+j!_2oDM>YBPT;=_{%tS6GzCmM_^yG zKI~gilZ>?^F8wjLCOog~`iJ+C@i4Kn+sY(Q3tATCHv*pA_eK^UB@Lxt^c25;@}Z*Q z-PLt}Qa2i0%QT+rxC5720I20KHK!!zHX3}J&-51EGv|^rv9M3{LNp9BjuO2+T6y49 zC^qvjmXIyFBX2#FOBg#4Mc(M4PWlRoia7uoIuG%O_`1O)mH<3TItAvM z=fO~{1r6>+2M*ke+KOYw+U(1jd5cChY*79UJ&nl`J6O*WfD2+7If+K)U$HLReOy30 zwl~vMhRBEd;{|(5wph;u!rr}-uGgT)V&#Mhs+ePX(KRDF+U?t3<* zXpkE{zcZ+Ijf6QHkrMnApybPqpVU&gQ&>m3TRD)wo1k0p!kdmC_vKw%o2GNY<7Zex zJUl(YW=BfdrH=tg?40|s;qow!+QX0xa;chpf%sk3ktHW5QQ>2snK>I_6exMrEuPVj zyJFZF>Jwp;WxAp3cfHt-JeSOTF^sh9KE4!m77J z%ZYCTM#asYU|if^Y_ClZ0;c51J=?O?WPLrvQ zhwc0&H6?>QrDr#g0A-L*KNqYY1HTjC5ET`nB7Fs>T`*fmN1(pX<0tIZT`1eiZZLeM z&aFkf;(-$gPvVYhaM*yTfj`eq@?84oL!98Kh;KgQ+UOT%+^5sP!{o5JU)XplG)C(qK(c6Wjdh zWj)cf18q!swCJ8|?LJwqa`72nXb?Y~*MA#bMF{~BKs_yH&$VLYKa5855wH%LStix2 zAz7x|K#v4A#IXT)yIF*LZi8#%L|ff>gOBk*PgXy=+bIsqNL!aE=SMYoB~FjI(Qc2` zP7Swj*Q}>DH^Zkk1O2l51>-XB&{GLh83UcnXb4I^ z6Vg*@Ux@H;EIT?orT?D$sSdaB`pKz5j1?CVIx($fTjjMz=Z1TzOnmYw!*~&1Vju*$ z7kBrdYTgF;H8F&_UBcQf#5W7RVC-AsNCJ+Li2dha=~vplekoq*g%+UfBMyIJZfX0C zV}>=bskifS)Gs(sNntxscDNHc$43k-n`U3xOfl;QD?{OAp{X3^ozne+ba^fW3w#0v zWk2I&b-a9JXgg#Z(%F28C_6OHn)3psn9>|vAu3mR=Z0eI^iAvV-voThr^fM4*{0u% zLLqoSIJYz+u;sOyJtbgd-gUb8%u!doMfUga0jZF!EeSEY(6<0#x39nGp z57Qv>hU7ZuQ$>ND;hw<)mRovUNj#Suye&}h!MrO@>AJTBO0=yrk6q8HFD3US-z{-( zVJLL}pyLm@T;W_t;)l@K`fx$)EhzfuVsaB$cVZK1;i=6JPy8sy3ga4|*Nz1!95~DU zsi}U3tv@KQYhgG#aN@IZNSHP-=MFSWZ)pvwYDRFTcc6%Un6)K(T=Au4iBv@gN%xNd zQ^q-DE~_o@?Me7(_tsDgz^V2CBAV}zb=N8PIhz5sfqc7{@-_CHAk{4$i}*j$H-sU+ zM32-(r;i8&Yn9+tdjK|MGx*vbzy|tUA7-WDeA7e>(dfAQ=q9iIZ*De+roRgZ)9rNi z#w50CRBtSEA8n!6C|34-)O9iQNyZlU>t3DAz0&7#xn&qHjnCs>{~%vR;->Q#VPm_V zYIyM$ecbx+X=^na;8cizewFJ_m>=SENJAQ`6RX0|$3Up@_|x)BwQ_E>62?9Jzb_wn zm67k-zkn+p0GOZ&a_`dw8uc9C8L=8x*&1f=@9H_?d=p|d%80hVgR$FI#yoi2{0Y{! z52DA!WBQtOm(fz|LoEiP$9x3DRosHG_sCLpq<+D;9DfJq$g_^jVH29Cj&C};2}jln z0NC?iH&pc!sN)pJ{&+zt$TLc9qg%DGJHglf&C&hB!^I8)oqsjbg<)Q9sNok@(>ery zF+KWs7XHtyq_XM4dt!NklvQN=gJrP5xTI||V(JAsUdsM8rBTkXO-G3<(ZZ>G$}rlQ zw($?G(xb;ODX#5athAPP^jXf|N8C@@elE^L^dp$d5lrft%h7896I~arOVCv?{eE$l z!wO^3WrYcVAX19~sT05~OS&w}Wf(e@K?^Tb{{*(waUf}4Wct^RJ}7D0+*k{KG^*Y+#<2@dnpBx0Gb^FtEr1nvRux`7f{Y!gq;4U|fR6?J zo=qq58G-6!+)0n4F%@qSQ>Cw*E9Us<-mYwk(L5W-2;Bbe?3Yi0K{|buc{%;>bttm2 zPOzQO(nV0K$B?m3d%Qwjas4PE%5&gL2x(fI-GT#lNM!`R?T~Q9*U^KoUx`O{hd$k`J?tKJ2=#1DS|=Tq}U6g3q$UJJ-JX+ zTMeaJjun~|CAdl&Xa7_ve}Cx8IX%uaJ&`5TY6|Ch`OoBOd7KHp0q0q6pet?B#R|Pp z+5N{cK_NjDRtpTADPD#y)8&c4pp(H8553H2;oVtbbkMr6$Xd9|cP>6OX8FJdHsdD) zoy7Ypx=j?*umR%SZu`mKyv~IOs!F6?_;kz)=+@g;CRHdEsKVv9WEMs(+-f#8%C1K7 zi3>J)b>Wi|)rmM&7uwyNQuOvsdYkeD+k|JI>0SRmT`syEG^sb1Z5SbXmNZP+Z9cd) z(%Uv$v$(ReIA)L|b<;omfr30p4`u9{^6?NJxkO>He<_2<8#M1m!;j_Pz(~zL88H08a0!7oGrU}m?wi@*enepY+huNxr$x+LuQupHLO@W0t9Aew;7|v6EN~$b@ZVdX6l5U$ zyPP}}VE?-uM?7HU8>*uKF29r3n1I62Z?=$g09W36LVW_}zme+8c!6Y)Z|V?dc#mJUP*6H=Eb9VvpO@k2Z1J&%g-Q~T3eJ%++}kl zW!_vVG)Zv@ju6D}QBo+d>eMXRrQb7X8D6m8=sBu1<>*sOIUr_>KM& z(HqB%Ta#mM}z_c9r_-blJsSiSt12F!)WWY{u#iwBYu)F23S;2T@h; zBe3ePX>C)FfrUzrbgH~pNHcB{mGgmOu@NRJkD_d+R_@2_G}az0Rx8mKzAArvFOg{H zA}Ho)4@YYQj-O=&4@^Xc`n^SHcpu81o`_px!$o49{>jRh_{2g()BRK?laVaxR>BuE zJ1v5T`?6qjCan_+Q5iI6P?&zAcWvE2 z8@S%S^>-j1!Wz=pQg|PCIQq`VcP{%u53X&rs}rsRQ|S8xq~c0Jeb#P^*x%_aLYT9h zyKQ+j1}~cxM5i9XH5@=!m{?=#b?c3#`NW>@Hk?q|j5-zJYXwKGnzY$HjXwK|^x;37 z#*0@~SdS1A^_sZ%;@R zOB#J4=TYObC}9ax&guelh4!1FoWWE&9IA0gXL6gsw;ysOh>^V>=){>_xS5J3(dG-2 zCx||%x;_=UK0L>8_U!zaNCjJ8vt?V2>GEn2$k&_>kz7D`P}2_yd$2i{!shM{IZ^4e zk|VZac^O#al9AWv1q*$iwp&Y_>N3%!m&_ZHiIRH!zoG!;je7ifnCR}4<RU_XE)Xy2C%}!@AuB788#>rf4UCZj}26X)^?LOWALgx z;e1)%XFdX{p-#3f=Ra+xu2-c}-ci2TU05Z-iQ!=>f+#L~GoN|(tqU&MTzIMe`mN8m zV)|`*&giz*s`#mudf$hPaS1%pXY)C#`7q8|P&`8EqHA!^}QH;N8~fFOJKZ691;ecO;LJYv0x6j1hER+TjH z{9RVQ9B}E)w+G7ubKatftr{@vJq~@)2KK%={`v)7VC6fC`U-4)3qclhy9@611`@qTtX&^qGVm>aBKn_6?E@enj$j}lxZ=s6 zD8P!|@YwYO{=kcOL2ZFRX}C8vh><|q;X z0`z}x#jgb#0^cHnUjtCg5 zo03Xus7S;&B*YGdhx~?ggrO*~-g-|@>n?e`hNt4!jDq2<_kJKeetoMNQ~(spYX+bt zr*oO(@tShDBE}oQ;MSXKL&d!t`uG*fnET zu22r|e8!$o9q+47;|KKt;msz#?@)M1Z%88nY7gqoy0e%Q^bR+g#D*uK7@VIaWb1lQp1F2UU;xVyW1Slr#+-Q5Z9?(Xgm!NQOG!&CLv z_pRcOu5-4}nVlW_>b|;X8baV}9(0o-*1qP3Cj(;hOTx>ADErbFD}bo~T9m%65FarA zt*`r{_3Y8l@3RM+Tr(EO(#V*hL8g`*HGUr$}1hN$?u7QP6<_%))g4TwpE|3(yZ z4)K4B4*w1U=j$%d3k3O>hUo`{&)3^e!60S79AYj!ND_qqW>b)kh$Hj!?KTJ?AQGRm zNt`Ty2Z7aGK?B+RrEbCm3H2q}vqR>64F{bU67y>^7-bTo-a`LwX_C+kQHA8bMl9r2K+Y}ai>PvfKS^b1)mJ`hZIPj zDu6}@HmY99DXL<6%L46k6Gr|P5>QZCXi_#Fr-U6R5S1&)^W*OJOMRZsDrwtEE2>>5 z=dIp!ez#jk@4d2%Tu&-Ht~E{nT1TpxbdI=UT7Qz|c-2@5)*)8C zXD|Jfw-%@!vg&WUp33gMU<@>{#=BEi*0^8wz?0$O@s1=KC?(v5dXJqHAFl5i^7525 zokplrMhy*VSkxsD*4rKmV`xsqXa0x_FmK-T+qAxHebQnk%oZ=(UPh%krbOS0%u}Fg zvsLFbbaFm(p_7g}^y|k{CC}W+D9;W2LIfO2tL7DYrz=j?h%gqU%gra4YMpo)C4xNI zKvb5OnScqfwNV#U8O6@n=z<0-o$!deB?gF&XHM2)Xe&IbdTHz;bgX#TPGz&C8x3%m zDul$TQZmB_oS+|*!72@u%ZEcQ4T`0zrP<0d&cCS5Og=J_v2h;C;*E^@mftCeB% zA}YDG_!aYFxcDF>##VReo|HztJs>8fN329wtN|Mv{E51?o4LIx^N?{J#A#4OL0YQ3 zI*6Am8BZW*rfg^~dq{5b&yv!F?(-ms_Q99(qbl~6U*FaH?8~a+WjCcoAy(O4Vv{z& zepLJWEK<@=-InOHOVg3eXXNV?Ce5Ius2q%c*lI2L>@8d{tI+DBMaMs&(*yCg-e$*t zQmUcZ_x-7>&C)UP+AizfPM^^ibh#=_btbO54e5jw6%Y^}k2Cqz&2B=IDshoO$GlQ2 zAmcg$8TNx?OiJ0Cit|<@u$yA*W&04NhOzf`?nkV0mt8iGYbg2A-3`7b@}$YCVsAWT&ycxyC-)fo~#SEfZhQ@+h0tJ zdnfYVrbli8s-0nZc<`ZAQoP%!kcy?l5|LC1#P647RH`#kxv7z9J;sW;r3357wW>7r+?7 zB^ngakiJtl)G2@)3ULL-_>oF%22vQuG7Z0>hB2YyVx0~%2NJlR=%t!LDbi7j!)i^P zXb6a)>Y%}Z!5}cd%eiN&=r^T20;|pOx6-7y=#FBoSI~f<_8Y(*&bXz@Y(}{PjuHPZk+QT;emU zLs>WeCC-JK^aJK5CbQ&c>Ney(Uw1dkycDulNV2$iy?m(fF+}LT2T4_Izq4OwsEbzs z3NGNrKDIxJ3E4ib#VR%=zMmA#N<+p#DzqQhDY)PIl7#p^@t|j8>2w&Mil}+t_P4}8 zmC$w4SfDQWrcokrj2!$QCH4)L2M6B35&E&q>O4n|whF#`u2**c8(KL}%RkXbf5(3l z+tStkcd)x1G8wwaN7lP#YZ}|=oT~DR_e6|wEZzXMD_~=HO$80v}0v~8tv$LTC5d+ zGG8(Ne_s3l(1khYfItGsi@0Y`Yc3| z+=ATtr*l#KiBr*BQRWH$^a)9(InaK!V9W8+*cAz#EtJXbit}mnF5~E~V{_~R5$OJ{ z+gt0t7Zg|wpu=BRBdU1|cx*rqvkcvt&do*fV4 z;H?l2>`u$rV4a(nEf!?tiJcYV;U<#-b+r)2S%RSY>6jHkCc}do%bpe{PkB&@zRaMi zWTC}ONu41bMC-1jl)LKB%F7+l$g;3;9?YtUGdI_Ug*TI*U!W^%up!-?nURA!Yd`myv{1BwHICr*MQcWP2cD-bUJI&1p_&k9+M&+>WMO)DE$S~>#$#Dof! zw*(S-@k$6p05m!_1nU=RZdW$4pU(WAKB6G6RgcPN)n5HYJX>tmeq14=Ha;TxkQ^+{ zog*jk+uNPNXHis5UvQ>d0A2=$cz3bps4I}f;Dtnc|L7EnXxAeiFagH;o*7QeKH_73zx@kT3|NlAx_l*sSqWBE8_I#ASKq}dAA)-l zFl1!LOIO2}4GTLfjvZdQ$jIewB4SInzIvnHYD(VcxR`a<-zFL5k}x8a56*MmhXiz* z>(Zbhv+LFkv4Kd-gXH1GRqje3RaROGutw8l!!? z%^BvUA4y;iF2JsovhfCaAP&S&{%7pF!Z}py6pzfyQ9v1qs$Je;VBM6RoW4&MghwWvFw$9@j0HBiJ^w4P$ta)8yQuc56y;-67Kmh;vN1TW>K-ANZk%EC zjq0VD(U?B;8n_XSLorbTj>n{G)vN7zs{OIhr=Gmd7x;&IH$DXk#oedQoPi5U+G8Ga zc8%K}lxLo>zE29sQtnixgY6E~@bV?je&F~Ma^yzWd-pevR5F38wi{TwjaE_8>8HGO zt#|Rsd%&^+I5)h6@G{`pz5O+YY?3pS+NyG^rdsE;FRQxjq2V23J9I8>TEc=3UmVy? z+imm_>E+GFXwNHGJj@EaJ@!$Xbq>3IPeMqb_Z_qwmlr6j^D}(sl@8NYpBZ9I; z{zwpj&SF6Cxtou<>jn(4*4=H8KX9oSNM@9rhWxXWwKq)5c#YPPL*oLYI}jc~BLb(Z zh+Zzht|J&Dn!5YGVCU6eD8)_jP!sA|Gvu$Kaf09?A5ZMI()55&p(@FnW|(tk#wR+5 zf9%ktBxR`GTh&H=9H&x}B)WXEd!NH1;4-bJDZ*<<;V>zo*#T5c9?%tn_Yvyn^J5a` zxY}Xw{^ewk+k*n*$%R%*{zx6*e3M?TuFqBIfOVeF=7ROO!%a8MtvLD-^`Tz~xY$LQ z(C9C|B-bIq*NJc&DqV#-g8U`>-8R6@@Cow@N+%N_2X=3A6Sd-&J+=!^6Y_*g+?p24 zoq}i^=T=<0st%mYCLFEr=aT9;g6VFL>G7-tx!RE9rp4bxz0oPMIO6Q$Pf!hY&2rQ2 z8gi>v%nN*i9d)`{&+H~r%gIdy@OLoJYWRGdOw*2nKe>**v1?a zjouh~PwD2#V%%_e=b0HLF7r>Sq6#ru&T=YSmPiE^Z2*f>6-XCubWu@qV*6~@9YJUj zyQiS+QbBALRK<>qlq)`BPO3b_Kem8h0@E(!@Xc!NaJN!$1zQc1osXq4s8Y;R)pT6<* zVU8NDlx5JI5not_HAOdIl)R0$sy9(Jhj^_)z5&DGIledid=7)tdqbD3CQ2QUR!=GS zgKhHD1I@g|?|&mNyXM9D09dttDi$^$bE|;g8hD~8z-+&MU!fpHA7u-?{f2YU^gg?2onNua9jORVUR0M|<=G>l zUUO+XvraqL8zNEAH``c~fgV_HPV(8z%Ke;U^D3JegQC*h&@WG$F$1XuKV;7`+ zGr7%3zD41H7&_F2;h$}ehlj#}w?X#9Z z!rxxoJW>?3w4oi`L~uhD65P)&2i+s~nL`LzN}{cP(~80_c7S77ZoLMFtwt=>eq&%R;%8%StqXXcIWjx zkd2

*6av3k*=_pr8J(Pm@gnM1Ipjt284v;spxulb~6lswq-kgGrCpWD>CH)syIj z`>@B+6fag0`B5m&-9;G>&!;ICs`W(_I*&~|3_@6Q1B;)ik5QMInw+xd0yDfXjs9@( zRB5`<*tZzfOs~~w3rG+AKCX)CjDcN}H!3ly&5;a9mk^DIKkh+*cq%_0_y$IeZeVn} zo|!ZO6F^jYFnSUlHTr<3G!yJSDxPe$LdQVvsxRMT1KlB}w|8-e!GT$7oIbN^u`|T0 zejmWE3sk@tpI+zLPRPAeA(fT2WMozS>1POhnIlblj{}KN8FU=skTV zjSYt_x#8O=@vuUAP~k#1?aNlPj(<-QsmBiR$1m>tm-TzwV{ zY}qva{;kmp7z10WjmMFc&=+YgHkQFzfF}7DCJhaaxx7KWf$0TQh;BtA^W_2=Wy39C z3yAuBq(4>-1CCI;)TdJO;H(w+H$e0U!rc!VPS@VC_FX92#`A!Dw}j7giTezVecD*W za6oEv_Y^5I-zM^653w1;or8ZKMfTyE>lYs=RX<^~MFe!H)|O5+>n(bEpvhJ9?I%a! z@BU!Z>=G6m#=nAf8gXSH>ET?cr!DC3>jA1ebp}7yR6B0|3Izta{g4ef;{^Ufy4#R) zT%z{X-pPT>9GGmLL4OSVW>ezS<>&hh#WFeqqrsupME5dK*eVTCo)p;C4*3y61G95l zZE$6bKB-A{Ns;!vIa2pvNDDdbxA9hXPKe>j7y`cas=i7XaSg^5N`k8+S{>8XEDjtP zD%k!R{y`hH19*A&8@l1*Ibxtv*%?7rhaigHHZC|pA?S7Fh|*VR!^htSUv(RZqZ^DA z=bXka6uAi%jbN<**#JeKm2;r40z|2gbbs1LEZA-GFqYD z^DsUsbhP10;G~=S`1MwJ#Dbsud4OAVPR+j_4~TYD>GN}hx4=a0@s}Lxnpk(=#w`io zPF-!i&T#O>+LR;eW!=EjYKw*CzUHOnQW%v;OQ0i8Di)1S6jOT9I1I@>jYOSzw9rc! z%{ANzFwIG4dzje`eri{nJ9^9wRCkZmOAhN@xND2!j$8+Ww}WtTXF`O@b3rI^CH%A3 zuY>X8(Em5M z)mH-WekB9$!74l(KN<19PXrK5u3ZO^B!91lMo<3J@|kUVPy=**8SG|lfbkd2i|-E5 z`ZD|8zJUJ&3W`Vo+?UyBPXqiPm28;{fcau)-HHKSU-0m=9sq>=FIEOmGlYWtwDHNG z84{uYy_PmvwjLTfsSWTy1Ha{nqKwJYEYW6O#}A(L2*T%p;z8?R@v^|MWUB({C~G?uQlcVdGga%8 z_zkO7rYm?sWuiV0ZvjGGgn8I%abZiDnNax9ohN*cuZ6vV ziIsvy;vYS&CkbANBN}HxJCJoXj1D+5ax%PPx(&WZ?m2On7)hR=aRkd9mS^dlCB*9I zy%!fBJs$A(U63kY<=Q(;)S8Tvsh(G6@|c}$(H#VZlQ$}pDLN?{l;DHB$b*BvpC@sB zc8Gq+M?nT6K%ZBKEryrns-@}JC8jMrq~uaPFC+cYT8V1&CNY+usztY))e!hWIU!p* z_-mkaa2EcPjT$tQ-#(XuMWs-x2rlSNP1{;E*JJ7Kx_S2z$ki z>Zy&k5;d4*a#aY7>$E@5)i1cWr!<4EJ=xB4qRbpmHjc>?=l_;8LO_mNe6L`|Lg?{2=G8&(jSy01S%)>yEwiMBw8T7T#`5s66A zaqW--JI0$r0kqnXX2W($kiufG2=!`a8sK~{FM&aQz4!W=C=lQ?FGuRqa$ z6#fN6&fa~7#6@JEJqRN~Z@>FI0I%OA(BI`A2=>Cuuesb@I}%ys$$dsNp1+b+DF_D` zTSV(h0XmiWsUE#-Z3O~n>ExC%Y&!h?o7DuX6%XUhc0B2ULmoAF5)FCL>^6Mrocw15 zkPIPxn7t$`TzydCMp~qwT{^&<8NzI@VZ6IPW0S3Fj;JkrK^A=lt3k@(CZbsK8(v1B zsQ4;YM_&qK6uf>`?3!C=EC((j815MbE!8ipZbp+uAC+2clm_k)D8!p)#;XlC9~9vS z#=flBg_0Y54P#Vunmrk9+C9FwjL681}=erBnta`72fZtx=q>tomH_<+E z(!+=~WP=&STDh4zs2WQjlnv>PflbXoNwXgd!d)uqC-i5Et4^JgV@lVjGTZIIm{quu zF8bR2df?<+CbYlgg%w+L-T+d{Cc-w8r&3@~SK-(KO?|!tm@l;PYMBsKA z)NY#DzynpOwrk;I6?J2@cByl#!kI%Mx=Z2Wx#Yx=e%MZ)a zho1^-16p;H7s;b(Z^=Jst`jrCAUkBKIS!eVE04FT`{~Y`R zl@a3~pLX_Jay0;oJ=whJGdW*+4IuwY6&~2$!X|xY$8zA4YXDGe$s7N>P4x=M`7+)U zpim26L}wuYY98i4QfQJ5JI!mgcv4D-qnpUXFm_r}M z%`2MbflW084zyNMCp8e^4eQN5um>6xO(J7Xu0E7&8^$J@bf^A7W=hlj?DNt6ha1PFJ4O{tagsPPU^C= z5qTnarEZ)YdOqj3#0R+~uJK2GghM79Zf|M+W!QSOaf}qBGY49|cKt%`l;EGGnw|U- z1R1h*J;8xyM!+}^Zewhwku;aJCGnCUZRTc-dnt<;bDC&0$R!t8nm7DRMffL?hzR#5 zMTJ34%l;~eX*Fs+$oQ9{j!ChWt#*haZ5Cvj<=|>6Ep!#zS+x#_&~#E(^3zoE^K*wi z3KcPEl?iB#3(g+3*p{dj4}<}1zR*i9N$`644Q5I?KY`P{cx#JoHmMID_-xxcOchcO zwB(&Ot#hJS&hgz|mr80lTFW%`Yeds=$vL%@I_%YF37WQd`t9p&%h>1fcL?|{1{iln zJUf45x;yv7mo)vfvGSroDvUw9 z5Y>{i1=cHq5i`{CAk7$LViWFiJJyppcjwF{t)+pRi$|H;{i!c}2ol9gZ}TInO(3L2 zM@`Wb-;;6MV{dpKE!)UFiPSw@L4LJFFhhTs~i!z?f5b zf82JicvTAt$dEX2gPA*v>Z&L-*X-q`88q`^0j4grx@(0T1Ui|MvX^0BEu$ngk8vqz z>~EXUnh&XNtLAJdJqQXTZseW%9fcJWGn$FsKLk}cO-8O*B^(fh$o}Ctkb|!Fau(d? zokYK*a-*%p4|EInCvv)3GsIz^Zb90>eV!FP?!nX9;10f&15nJmEx|%H{=-dxIFk1U z1t#JyhQOw@rQW4F)C9Vk*ekR*x9$@iIx8nf5KSw1SgWb5SD>=Dmub)1Vbb5#Z6nWH zs49lH3wV2$8DFpJH_%k5q`hUqLjCa(kc{O+<-9db_phEZg-9twBsw_or6Nx>n}WG)M&~PJ?3_q zAIGZOUK1C1?RQNn;y>+hPcV>4-&ti5Did#IM?HCa<_;nnecVN z^Dp23gNEwRP3L-PpM`S1pLsW_&-!Cq2UB_ztL7iLP$yqyAkYL*3SVU8(yFR1<*2UYO(q@5I~kuRw-8!7|(zbB;= ztrH4-qG|{U2nf&rkd-jGy9*j0IHC62OKBn1d(vxvQkpC$E*IfDI9OT?g9MZ)VGMe_ zJOD)yMc8n5)Yt(9GAQ+ClH@y0y9Kf2iH7CEf=y|hi1|fTW2ID{ys)cfD`YGG^f)}QN&2mi`_>W=ryaq{5xisv^1uv_`BEuvM8 zrJdW3aBMe(=L2CUS)Lfc;-||MtDuB$UgVA$#|nwwXLst-9#T6A7kLI`M#y_{RRuZh zN`R0kH&&Dg&vlNP|57;eI0{90>NnPRq~CfQn`u2p913$5X^iz7;w1N=#Dv>83~@_! zJQ=t)QOBX+?Q1CCzzWe4fz~UDZE+?XKc|m zUYfProW4dD=(Alh3cj`!!?qyyNjGh>h}$XrIio7F=as1ke?|6%09u4wBu+5BHQ5oJ z^e8MJ@T$7~ib@0eF5nAn&J%MPfVpuR{7f!I*>6hC&{@)M@<8a!zHSy!9hU7d z?$d^TNY0q5p!?yR8Q=`P;zC^d_`J`cLB$Xxe58(5Kbh~rO64P>s8F0Ft7>3=8|OL_ zyEG3Lb1EedUNju6R%-eysxl6Fvy!Y0)u7l7BYb+N5wO0y<2(&ny-w@uj5SvrFn-v=dA7ZJ4124uC!8FVMbuk>Fi z1rSf>Xv1$IZLEK$JvH2ed-|2WoImWwV_C2b5kVu`^wYt&VYDNS%2VR-8PdZH?DoY; zXo$!$r0C4WSOV)RTZk~nTb61}2lJu_6hx}^>F2nOOYj1aVym9wZP8{+0pCJKl3KbK z&CgmuQdTwW^n-WlE zzZVkm5~a?R0JGZHBW5h0jaHIEmegCpCMnK$G;p;|r$CBj8H;4sNGU+OJiNiwK)+w^ zxjB3&t>wBG&Q#?Ip)wKjtN!5C8+!I?a-Yk8_FXN1N9uk(UatQACdB?)baBka!b|3k z&DgG8cMxa~uN!OeD9>9qCymr1ZE=I^)ow3H#6%^}i*k)lMQ*2%cN@ZgP_bgsH0unb zyKv2#T03N-N#UrGJQXt$VF(W-uoIaqNl{RNsXSmxV6c=Hik^46?HN6-5v|cmGyJ_j z@wv9=#d~UnRK-?BtZQTNR!Z-<_dVNYV%Jd)3xE&SSB{;ck|{rz+*Y0YOBuJSQoXR18uSg{7C+n8UdKE&)zvHM*&X9{a=JAl}Q)c(s za2U($w-`MBwztYAlxu{AX;jzozD4H2og#S+Tk&7!crKe0PKK`+Wtr$tgxHZ`wpxJe zV*+9zaaIK^Jxu>`;i+;d7-`RGr{?~?5bsaM{&!E8__=6(hTr?qB9fMeJROXpctX{d1aa9^eW&wC8T_BiN?fpCw^Y7PsY^k<0siD1l z?D5$elI4PsXBsKU`&BYe>r)~n;}lm_s<`O%%vLr-OQ3Q6bNmSAI^P`s*wrSY=WV@zx_-K>1|+{B#uos^}^vY8sTq4W5 zZ;(Oukm?(Q##@xdqjI)b<&-jeRHO0ue} z;%oC0Q&eSdv8?n`(+t7aw4>VDD>cO$>FFfxLsYs)E|{0O$*}s#_1>$5^fMqlhl_JY z8pY_E*B;AE!LMO>%BeBeTmH2N0Rx#mZtHHu2(#UJ&of-6eD9;yUq208ZTaC(Vb4!v z-chPEd;Dxh;JXZQ*WP4-GaN1vJ1^wJ#KF6(&GHjRY^a7@k~h!^xhTm7fW=)6mfQ3{ z5KD#_ZO^`*-=yzv_io}jLgj$5q3pX7kKFJ-rf!Mfj03K#kNeKvIMT=ylk$43Y$wwHec>DwjeAki6^*p)f|Zo7k?{-b%7 zZue>cv$nGPqDgXHzq}`;EEFk$p(q(s2;yv@KYJ(I3@!gx#10EBhDJYd4>SKjl(aK? zZnmFmJ-g0mVw+MF(Ks`gG{G5tD|SKb3^z+ZH)%DAL3;|hl4%X>8E8tgFJ+CVR9gu( zW&dLFSZMOEmi11qB6Z8y*5d6B_k-sFSaL@$51kwYaeCzeugU7A)CcRu6yjPd9^%SK zA*^S7@}`@&|D&Ob_MH@{(gA-|t%qW32(6=}ar67~Lax=3lzNx-a&+P`d3K)1RmC!Y zWpCMean7dEy=espmsjFSQXuC1XU~Zv6|F!r)eqC0++o!OCbSQngsVJ$|3lY;1W~lqU5{Tt?IY~$v7_@C?b5>V z0ZKS4n7KlH?N?THAyjp$$@g0D~BA^Cq$R7TW;3yus zh+Iy#66+0A)b6kKKExrwjWTbSXbT>(1fKq=EK^`Kwcx;sJw&I32Z#8pi1`^_(c2W7 zF&>HgKfzyTCRHRr&v5Y`n>U{%MX=~Dr2r}ugGt4Ah&@kq;J`E63lHrFVxs4<7#vV$ z?2`ZmEP*FGQ<2S6A$0H~bVL@GD!pz6im|=JVBB697JxXu3BAcs9kF3-9nMTRVuemw z{2rW6;&{Q<3a7k6{rihV$&X??E1^ePg4Xu>r9&aOxisUma0{OFPh1^}+7%2B!WKENE9AEg)9;rqSr1NY$uyT|$7HReFFyxs*k?n_EBd5pX(&gwS`MiaFmgy)P845D?!Ljcu*~kN%EwXIPxi+{)+lWRa+O8B~`4b zQC%ZLab|12lJMZ#a6bA{OB9ywar>mTFjA7;%}4QDO}g!!m^P9NbAXTXR(wKjFtzk% zt8tLeHWHY%*HxS_z}XWc?gQZmOb{RL^2_ZAF0}Fh0+u=;OvBJVBC-n-^{9DTIX+@~ zwa}3Sj(nMx8KZ=hB~fJe?Akj^X^Oqaz~DdI^O0fg(3E>4H(%-te0EGd!WDtg6jeH* z3N!Q7?sUddFmuk8b>4h4>z_PYDz87lCMfIfszuf5Q+P{&>WI>KgTuLYJlw@F8^Q^> zUNYJO3Urh*Esh*F*Ocfg7^{xiS5pMAZ%YPt#nU$a#ZdMcQ#;=~k;WaR_*u!!9SN>_ zK2WZ;QFN^ZJJhaLw8O^et85O67gv3Y$j}4hY=mQsR%G{^Hqz1)d#MkiWiu=MEVJ1D zd4bCSQl6MuKBTvdIdA4zCRxD2I%Ls9X(UJ?+=D>E{v;VO^J-JS$9`>YAO;8E9lD7EjTM_dY`$$_VP z?e5o5;r5P-~@zjPnz(5-va+KGhreE%rOTehzPs$NY$W@^kfV79MLLQr;Q^`pO zE@cWe*y?{E*{2G&CBL4KNmiHVZ3*6*9CvKw-Jyq1%AjYy(vDv>Fm%PId`Qo@(=&d! zgJxb$^}N|Ur}cRK#&%pt8F=HHO$nY$!Kdzi+tC^aez4%ZU+d|LEz^^?Rui;Vle8|y zuj7bcMv^>{-QSwHr#zZ21C_Lldp0eBJ$Maz)y;ZaMm?JrJvv$6UKwE@4FldW!cOD$ z=%<3;`;}_4hXdc?r7|%bc{ceN6MQ?1`7>2l?&ez!nGXBYRB1z{;Cx)M&fkeJDj=}h|tWRLwr zPuXu_Zfe#+7kR|w&2A)*Tle|b@b?9`=UQFk4Q~``U9)5aBr$fa&^#vy)~AgJqr|KA z{bRrau@)vi@^yF+YNaLHDq_b1X^8jVX8+?iB6I!5mEN+=UW@oZWp@OXK6I77q!!uU zGB3%BqJ^m}u=fPD-ytvV)Vb{zkt{fb6E@@%Q86a2@_f+>e0);x+@kN?lJB^=-roP% zHTbqtboe}B?iCIG?VKJZL%-THJrXiK>N7opV{wh1@=CmW1-v{{Jlv5y+!3B08Fux& zP+n)BhCg-v`~RzZy=aEI_zHwKK92+c3XWSwq5f}EkmMp1+1Fji6{zR`nC4{LU8ubO zN;pvWpd`Mw9qC;_C4WV}FE>!~-~XebduNb@mk2;Wl#*4!pxJ>V0W{2n0ko+Se!>z2 zguh4#X82=#RBBj-nD|M?`%^;&G0H0!S640AD>WM$&@>z6G{^EVtt$sK8pqD^ni~Hs zEp=91cupk;-~QWbHN9LPM}|Dx12|q~cqV;3@ol;M;o^RH6haYpD*D?Pj$6Pf;TkXC z?q{Nd+riS}MuG|4tZlJf8_4Zx$>~7r+u3nTCaCuW3Gap&)*GI5U@T=dd_3lvqk?XgVNJbpAnu&Yzcumm#@>zoFzLJm0jUCP(_Y!MH` zy<}aYenUwhkv|j0P>2D0{YO}EUb#yUq${X67CNHH9(DfA_U5L%o0ylW)dQ(t#7iX) z{84L3T8HdyYiZD-G+`OgmIiN?wuE5#8-O_96XN+|TAGZ@gNfyVVYAim)M^`&xLr(4 z(31`(`eGA^9yW+xtwC?Ar6hHycKhsi|6(KB5QENHx+w#{kHIq5M7`r?CPqO;0p!5t zqv!ZMFS;Edid{M)F=3-2T`V1&%f-}W4c-Y8yf5P*%}&o%4}xFZcEX|&*4SLJxlC^6 zeHBV**t}|%8lTi&n)wqMR`Ql~WLs;Cmz#;GtCg~}wvC3g^!39U9g6K!Da;*pI9pm<4ao02SWS^fmihJW z%bXqkiE_7kRIe47*b*ZZu~$wysrO9Y#4_ zZ{Mv0op?I|Ye=}*k~1&hIka$Q;pt7Yfgq?6H*J3CM#$o{M2rsXt^Kd-PDt?ApViTc z9fXMwO*Z9340i%-)~&OGtAob?h(w``O_t6xih}RfuCoa27e*5_X>9~*A@E&%{h4$w zb9B8H*jgY`Y{qPX$*+MMsJXvt(4xgP>M5jwLP2bs&n4*w=U^tOTwR2y8$6KF5bn3; za2hD#fPDK)x775;}T0PCwoqnIb}*qB!NcRP_QHT5dnKWJ9g3**oRxd z-h93hp=v3L?Dcpf8=)9Jmpe7l;t~{#+>j9xX$rtwTr1{zh{c>rTWQ0c4Mw z6+yDxXXeYR6Nt8l!Og>L(mi+&Y;7A7dp2$UmjMKtp8T8J;v~3|4~yu})(ulKx+b>| zY5@{|(*B$lwVQPjs9GIeKeiaO_*^If>2?dMNi$OS4XhcO>iGgGwk8Xy3+q^)& z!|Dy~)_8MloqDwEq*r#xv^XUY%=2s)+0HiCnAtfw8C{KjcH`r<8qK*d)Gyr&XBWA4 ziu}}jW&2?_E5QCEug}lKR2>4Rk&A;W80KgGzy3Ru?(iWP2SOfcv5fnWbh2aMFADL; zs&UW|_#WnYqg}nzj4gek7rIx%k^86F6dep)=b62ERdKNs3G(-D8M)fC)Y$Vtybu)V zLT>Vg+e0oh=J0{2+12SkSzn04($Kt#rd%D8^sr zdG5Y-=*ZrxsxY{oq%hCmK0=hOq8zw0($3hP?P2$xV+NpVq=(lLLq-^|nZ5l{d9klr@lIJ0f79+z&h$ z_(};niaujRxnxsbmbqbEp5Pq*s!U^B`&wz{wuPmjbx2o7-I2J_GgFPH@^M1H#RGAz zs{KQX zh(_dswfvX|s5Wygi@bR;BUQO1n*+t)*PAl|_>&x0VNPdfr*^X>Y;{04F%C@pz5Y5% zoQjA(h|1x}VXHV7BOR(>EcYAhkN#awdIjWYip-{q&65@LQTtWNDo`W+0bm}yc#Cyb z3Fn&d3M6W+d5R{`3`Wspik370GD?J5QS&*3w~;bjVZK;4r8ZluAf<=GX=R3hQjK9E z!Q}+INRw;j*Q9z@6KXLL&$*>Tn()JeRg6q}LCTBDI+RA6 zfuiS2O%=;u2UJ9JhM|+%F^-d@A%+wBMm?5MXf3m5i%lwEdS>5F?v8+qp)4NbXfPPY zmNmkV-`W8un_-~;P?AyHP)J&FJ$F@k4cPuzP+~`$`xxfu`E!@iy|^EEt0W!gw%w;EuRgqBGs1of5-0;&U%*MB#76P&4vYRwR=v ztLVjU+3vzXQ&xTq^2O*OA$?}J6me%8#pnV(CPDF@4Z|JlSRPAcLn;ofBK6R7^`w(f z#dD|GwbtO3^*U1WPUvY2v7kPQllF=C}v@9IRHW zCLhlOW;N@d;TCVF@v4+D9Te@zrV`+#sP1PdU{zxoeOdeZ0YgM|(9-a%d9L z^cbChsHKewo|60uB0dQ9S((dXhTl#1;nGbX&&6$dptXukMeUH8$CnWj)tGT32R!}H zms*_&E|yr4TWL@ek37Aw{Kcfbd@V8IYio}TKiJ@}OoWEn*VHxzCu4+!%9c~`BS>NP zXVava%SXLlnDGw>M8&qlAVeI;JRGF#9C?I+C(CW5hY(Tq-Tek0EO&TBj|Wf{Tt~{U z4i6WcQ)&d6X;>aG1^CRJBj@+sl^!zbuxf`1#}{lX;#M}Ehvtrbt7%PkQLP93Kld|4 zv%s64OvIfwCw{*ibD`~Mi^K|0C;VYKOe0L&2sd)KK|#(~eiV0V_F9|HEY0I8tS}V? z;?gp~bm_Y8ZYr{pIToJ}wV?EkWDR6zz8kOI?;1-YVPs;4Ncv5U#=Sd4rSFkY;p@bU z{4=uV5sSQ$;R?^0nB$p3ZF6LK9+M;J=F0l1+OxEO_$J5i@C1!D>K>_t*7cSR_#35~ z?AQ82Y&g?1ou-cfH!u?C#*El)|2i%XB*6<8^UpsMyvdBsU6#J-qq#Ei41?ETP~=YM z?vb4k^bEV}kJjEL-z}ECskXUczH$5;ZPc}MT^OsKJJ8v)u@>Z~M$^K>0p-8#@n-Yd zTznBVPqe`0X-3ESz8rL4T<%9q{N85|oNU|R z*|DRb0)9sh;~a4GL*FOKQtTioF?p#HpBkTR2&f_h++^!$!H*IP0DGEcXYIt4&iTZ5 z^&NEVLSPUSZt~3>rgd*l;`-2IW#RAH*IOqp@0mLNEI~UZt4m7}3>Dy)9(?na_Oq`o zX;I|lL-UvLTf!r{-v^PFAku)qyelvsh8fq8(FWOSpaK2_yxaR`QYdkiw^jqlzndi? zCFew;bH0CT-R~*C;>AxX@UyMeJh2kz95lp#%u7>G&q`R@ZAqDm2Q(h*%H5qfdk7im z$^nZNC|^8Y0GHtJ)>ss>K{aLvG7q_PX(hFl@mG{DE( zrTdj(L1+7kP1iBz^o8`0Z;e4!pDE9o<(uWJ**Dr8#}g&3WW}yPX9N$@8W)hWmi|@H z3R|+;NeW(3Fg0q@#gAWVwyJ7tjy)P#-EIATFUc$=-+Zva=LPtGc{SQ_xZty=n=Xym+u(+)KHSJme}Xqa*N zK3a!1F*C1Pgg&~3;WdC-`-VOWOHMn)Bo$B#z;oWXGgrK$@8Sypl>~6kjuA8>&J$P3X^mNXkc92)#tv~Yuq{uA91iPy(Y@XI~o6jYH5 z9^`f78+sKo0nrP($?xxPzhTKd`3+9u{FWqXAg3%S54;Gc$&7IF9fsKet1RxtJF>~* zu*3EdEFhUe5P}#%KrrlhZ{*z<&u=K1pIL&j^Jk6K2g&#Jd4~{<>RFK6>QVyyLiKyh zV|UcM-(r3=L(=sWy8EC(bkJ|XdTH)ASo?128M3kT{pldrI z0pqRH3`*VTvoH!z?4Aswk`ApF3eF}3`WgynDO~PU`pR4K2O|v_1YN8AbPVSZJI{4) zT)LI-838Iv18lr7jz-x3R{8R8Z;G^bEQk2ER1H-gi(%d;SVYYMy2|>mcTtKt<*pVL zhKK@^sUp8*A9rP4fx59oy<}Oo&?cH>sd`mv0e=3MojfLT_gp>SdtP4!S^#2h>rp9Vpb2c(}cG81Tw8WPojFlx7E;W=BQiXTvPA zO(E&}s8w&G*xj2$#kXqEtg%Zh68nOOTalb7C z#_+1{0Eh%~$?YnZR^d{OU5D}hw~2>p%Z%gM6oxI{TNaP|B$xbIs2YJYEI5sdpnb~{ zm?aJSBw(W*7P`K_2?nDo7Rx1we(9~xY{OlA5j>4C%orMfui7bh8y&kMez!`MB-ED8 z-`{whvmC;fad0VmFNE)8W#7|l|G&Df0xqiU`7h0-MLMM$rAxvLhfs}$$;{WX3eaOD||LsTKyF2qeGjrz5nRD*l-7`bM^nD)m zM{~N4<~T)3u;ERw2qC-y6R_c-=I_Ky7=7W<)F3L z5v;t!*M zNomq-!BywGrN>rtwcOZz9`;#Ax~G0nJT0H?9F-cfasx$rtD@`Zdzw=su}1ffvvl(6 zJroi-+J=snRMc2fon#u&uXs#zMoqtHhE$Br>3~tQh%saF?U{7a+6>CA`~Gb+iv+!$ z;HM8)RnU1e3FeR6BPDINe@n)<+CWOvkR6cG3&9SE1S;zME3lJ9a5SF*NmU>11dI`WolSV{FMuzO}A*E`FnRY0yf# zt>2b*n6ULv#?|H*={MvLG53oIEUSDk0ZHbP2@jcflIx62$F)bCK`NaTR|CoJ9=0o^zNhY= zaZyG13%wq^BkJGmc8;uw>5@s%YlEu?HY%ToTx|HrGSD_7)|L6Ji&l`gzO~`;bBFl- zXY(fK=XK*9{E{W#U-RH7;U#2Q0h$bE}^#*97wDv%niYCj1m1 zH0+~0cIMF*6lVQ%b_w2j{aJq~o_B`R`BVvv?boUO8F)lIxZqr$K!>rGK~Gru1@Qyw zcS{tRUIu723z$^t7hcpYyeN?3bYoVJxs1Q!q*zr4RmF9u@}86jR;uaVtD)@j#iiFj z$i8U3X`5hCs$~-sqGwRSWhuP&S$ni6eXYq+w{>!S2%Xn3B`W?Vp2X7SiJU3(6;{0m z`HD7@K?$GhXdV_{xiD;gOe_0MooIr<@K)*Z#T2bpw>wn4_hgH2l5l)7$-R^Joipo9 zx{HkYwDr8=^kn(qn z0D;5v%d5Aud~fpx2fDu0SIEktI9)YOvecZeM>*}*dzMIvBkyYCCdbe(O0&iKeT!cO zdsj7;87I-Oiti({kYeS!r>_JPXp7}8Owm1IWG9ng{uKMGl<1-qYfnpak{{TYe{$E3nJJayT_cOw0s@@#erYPUa^Z@zhC1bvo#V1eh>bWn!dhp*@KPJvvowTwNH@`E=Z?WyE?)WO;V!PK-`TN&e$u zM(`E+@AaE^MW-rt$F@?-{3tm75QVCr@O@!PmTDWNF&sbtcD?1u{`7I{C?c^QRpt}J zAC9X_h7X)r8)(z?>dK#BRH)i_%mVVH{?c=wGuS{>>N46MB5VE-*7i`LEJK*vyyRzu zDVqgd&pfe=E$IWP4~MPX(!~`r%lv(^6IlE8C95(f#`MZxyYZAr-1fB{?EXb)UANbo{U-~`98=L*wXO>uFU_2$e|A2c5 z|0j;v?A$nTcQ`{c-m5LI)YY}_rB<%JkYki(7n9BUEPs^yV=7-p{(runqh^4 zgjuOX5v#RW|Ld_*Q=1bNXI0522ZzTbJe39HdS}k$4xzIY1mu3_Upx2wXqf`XIk&=j zeI?4QB?i8u>HXrKDf;!(TZQl6gk}wWV{-b~E!i1((dA=A!Xu*VpMT5~TJufvX{PUt zS=bH@w0GYtl3wt(IeUL1=H|!fo2lPB7n$~D`mgBRd26vbb6zYbG41{3w1k_KCBY z0Y4n$f+8f^g3Rl(9zE7Np2nieD|jp}b%5cl$O);0{b(0ySJ4vFt|DpI@%3tC$!UkzOGKP!{CUyhD$iWa3Fb1}B?Dq&1D%)zXcgSnwUUQH9G_Ts+d?S<{mBr1}Yq)I&CE-uJBf&EzT? zQ{}{Z&yl=y428RO?91#o;q~VJ;lPyXX3G(M`?C{S==K!?$HU|awBV=1OlsGaDKf~#ueK;wjK2t{d_3bc(xW5rutM7TT#=*A3viU# zVAKM08~P_lwJNRmAi?;(8fTSsg7F{P~EBkqo#JSysFXpuR4!-&U>7j#}Dh%9ev(!hiHM>7y4kG&h0| zvDg10tyduMrJveio)RQjtg4*qmWfnJr&#4f714lG0Ifd9-WaMRdc7m@m zP+kABMH93x{UghB^Y)2i*FUoU84;b`+xIRl=6Lpn5IkNzTK@9g(2aS~=3a})Tt2lj z&(GnaDuFLO&*rQT-6WKK6lR@iNaFF7ZPPd{f1|%Tq^kZseZP3Fq0p_5dEzfYF@T$? zXUysPDbX*(z<*!P6-NKOCNQ=xTktMPlx?f*&ND-imuh@!Ug<`fW##eTmJKKL4E`94 zo@S+eb#PJ3QOj(J+CO8#EPg(VkWK8C;P2&wgQJ-!H4ga$S3V!>U-xdg{48rdMsoRr z{je#;pV;C;uk`zte#KUspft`wo_i6Z$JOJRzUq3Q%if0rP-tyUOl?c~lX zXXWI6y`X@wFwEdu4%_kRLEY<*lPoU99Xv3?|5?h$*DR_uCXVpaSy?s<&ZV<-wR8z) zX`z0E#twRgJm0I^m8pdz9W* z&@S^0=qaHY`hJE|EgF53T0OonXE?&{oA@41$@@GnVmPVsF+@FR?0DU#8^u(^@zzM| zHHli2NuBU|-;skg-%~v=OpKIq{<<+UAU{9VtWT13xWQ;b{B3#ugD#0zWVI%D>W4)a zZ=Q1kU$nlzp}4~&ZD(82*5_m48IV)XG(;j;e(}~~6MA1jIuG~i)AMwB+e9~7i#M3y+8T%s_pY&5vgJ4o=VYD2wJls9!Cxpzq3E;1-o>HVu0k^2E1AvW%LeDD2Ob zjiWj{l2;ti>9P(kE!RUNl0<)&RKH&{+GaoSbIoXTaLj)Gru9n8$e83Bm*~DF%0BMn zX(z?E7}CWU(}T-S>3kfd-mr8P%!Xf2O%NzL5OQR5oXx2~cafG%T#^~wRC?PK=YKfz zhwBO>$)_JLBt~wy?m*!h3JbGzzjbmM{q1d*MsLa1lcM<_=-Zd^MI4-@S{G_Mwmx!m zLXh>zDp~2tKZ5-u+=WV;kIL-TQSa1GSJ)ri?_lot8NSgt>lC~6Q}^2gkGu6YTzo9k zqwjgznGGYCp#$4$bZXEQbyRyvuagU)}7sG9Q2N@AEs+TU1=q4pF~Z^ zYOI@3v_H*8D>iBIY-b;RlTI+b?~}IQ_vff}3XXSP)i*{xl6Oc6pQwAI#>FFjn6COz zI6fv;EJMA|qSP3DN+?Ur$a?D8i?Z%RXOfe(bmO-fB0n&-tx%zQ7~8hY)~ljOYWxy1 z{SK8xnk~s@YGK{{|d44nS9mgrOpZ0+}NlNFrhh@=c&vW(4&L})I`gWZ)b^12_ z9ga)p8r3@13G-i0$W_UOozFEs*682dSz7m7x%|Y{jB|9yKrIu&x$;NlQkjuZusglc zv8;a1n&$bBJ2!rPDJpE$JlFr@(h`g962F8|@;dv}H;2yOF%NXQtb*7E-l)+Rn(OgY zJ#={XN9g(8l0#^VoM#zdcTCvq^z$n+=U7UNn(tp3^IwoPD3a?o89QD3>Y}YyoGX*v z1yP#$A)-H-`C{HL86SS85Nnt_P?F5#ekXQI-La%1!RttLkD%R!n7e*Dj9VjrDDBLb zlI{-Ydr^P3rfdk&7`1+Jf#$O{S;NTXyBG4kI<#M|%{6L{UPhNk{SihY=F;pt-AmN#&APL<7blB%L_bab))sO7*b!~qvQLQn?vFTK zpR~ls7GLkTg(TN$aG;rJ^*8FsA04ht*=J=FfO4%m8hpGU?D*~NxT9apg;nWYW3Qaq zIkbJxW9lw(eWDTTUGr{pd4EPG#e=`?niYPHwWZk%8a&F?FKo}Qa#Ry_QY&_h&@6hr z_T7D9e(3ot&)HXQBr}J88(ZBHL=z;NEJ!EGvncQyy*pl4FDdK$5KU;-@`_II_WPMy zt`{wQv_x};qMY&iSL)&R4$_Qf#cfy5#8wdX?T#r)H z*(Ucfyiw96GsE1OSw+Xx$}kw~VEpmlzsz>zgPvgzc9jr>46r9{L>z=HvA-U8a|k+( z<*Lg-HCWoJEVMy@9GnrcZTl^b7KNJNh5yKc-*7K?fz$tsEGdH+Mlb9vwbW4&GF8=z zNw`U9*jpSuT4PL2&Ot|bPXh9G;yA(?%1`~O-Bat^-Rd)0%KF(x!rHF|6CB<+PNa8x zHN% zYn$ElHA+6V6wOVe*zE7&-@#YypBG`|r~T#2bov6(R@{^9$P&IxgE@H$MHjKa;OYIR zlx2jIbyzz>$`6)&io1K`h>JKZ`#NG>YLHUDBg~9KTuP=xBGhzqnR?5*``lAAT}we1 zw~#n*3vT%u!Y59Afn<|H=dLT8hR8o3RDJ6dRsQDLB5NVK#a1wr%YNxPGo`>=&1{y& z)vafC5#lG(n2%5omrm#Nt{#zbsa=i#>_Y0wO4hw*b}@lbcXczZv6-B*cEHtlR=~}s zA=Ts9ptlY+_yK%)`l>SZKJnWJ882OWt~A=3}tKbr}s-$?lFn{SkxAhOGMe!;={TBh5;bU;}3{j}UF}r)Jz7mW{ASc>`gM-hG`y)$HV!fW!}NZkD^zv@RKyx| zt@hx}^cg=ogANg`^JwqYx$?_HF>aD+`MGHO(z6JCapPidj;^Jkvw9s{D+B~Rxx^l{ z#eKC>k96Ox*+}NmdakQ}p|c$6n(X69fTLe zYF;vi-tmxO)-S%pN~2H^YVply=6U0G5JOLMklx(phX*0(FHGmc4!GK;92@bfQN1D5 zq*yeqz5S#zcq8S*TQ9ea7ldBAHxpF_HZ9A(&$e@G(`Kj3>I5sbeMXxl)DOlcLgHec zWM6n(oVS8}x8C>91%(LP4AJJcx1$cP3;&+*pfR2ye9IErqeT|iXJB`O=6u%W5KlN) z``P4AT}xm7r)b;954V^L=R-E{2s|HdHIT5)BdHT5S;Lt$z2%Qe zjz_+Y5`J3bF3n(O?s;XcPX8{Gq$+on_kBU7U$YMU6bE}BqVLEKcss-=6vf?Wd@b7W zHr+t1?^&amq*tMMNJ{TVYacW5gMqawZV)}$hGD#K$M?rx8iUU`^S-KD9c<|nugiYt z#gz6$V&wEiPAMZ6<1=a5+z(VgTU>jS9l*!Rr{Y|EZC1;wf#JrLhS8gg<1{A2^-qDyBP^LPqUn+6%>g_dWT*@5@L@IPTjLU%v`j zDSI!f#PxkvOysUS@iq1K2)kd-981NYFfTLS@J8|Bfa{No(6+XRuQlubD(MT2j}yJH zEu|)Jv2H9SSYdiEW^$&lS&7z%l2oec1VA? zUrv5wHSq5Gmcs1E!Rw6(2qMSW$Hd;4G!*S z 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 B5h?%x From a21d7ac8928472c3ca25dce2617c2fc3e036f324 Mon Sep 17 00:00:00 2001 From: jacob Date: Sun, 11 Aug 2024 23:18:35 -0600 Subject: [PATCH 02/10] Fixed issue with incorrect override annotations in the complex dense tensor class. --- .../java/org/flag4j/arrays/dense/CTensor.java | 4 ---- target/flag4j-v0.1.0-beta.jar | Bin 640797 -> 641004 bytes 2 files changed, 4 deletions(-) diff --git a/src/main/java/org/flag4j/arrays/dense/CTensor.java b/src/main/java/org/flag4j/arrays/dense/CTensor.java index 626128cd7..c159e6879 100644 --- a/src/main/java/org/flag4j/arrays/dense/CTensor.java +++ b/src/main/java/org/flag4j/arrays/dense/CTensor.java @@ -318,7 +318,6 @@ public CTensor H(int... axes) { * @param B Second tensor in the addition. * @throws IllegalArgumentException If this tensor and {@code B} have different shapes. */ - @Override public void addEq(Tensor B) { RealComplexDenseOperations.addEq(this.entries, this.shape, B.entries, B.shape); } @@ -330,7 +329,6 @@ public void addEq(Tensor B) { * @param B Second tensor in the addition. * @throws IllegalArgumentException If this tensor and {@code B} have different shapes. */ - @Override public void addEq(CooCTensor B) { ComplexDenseSparseOperations.addEq(this, B); } @@ -342,7 +340,6 @@ public void addEq(CooCTensor B) { * @param B Second tensor in the subtraction. * @throws IllegalArgumentException If this tensor and {@code B} have different shapes. */ - @Override public void subEq(Tensor B) { RealComplexDenseOperations.subEq(this.entries, this.shape, B.entries, B.shape); } @@ -354,7 +351,6 @@ public void subEq(Tensor B) { * @param B Second tensor in the subtraction. * @throws IllegalArgumentException If this tensor and {@code B} have different shapes. */ - @Override public void subEq(CooCTensor B) { ComplexDenseSparseOperations.subEq(this, B); } diff --git a/target/flag4j-v0.1.0-beta.jar b/target/flag4j-v0.1.0-beta.jar index 24705ef7e7d8a5c0d58d9b82d12f03a67246b50d..ff7761f0ceddd62c8470588313e4d57c1d95ec03 100644 GIT binary patch delta 35271 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 SfD3103&c#Y-v?GGH2(*o8o^rt delta 35032 zcmY&<1yCJL&@BXacMtCFa0w9H-QC?TE*E#dxCVE33+@u!-JPI;AbH96*Q@uxs;NEO zJ>6$#ZEE-Q?qvdPZagirvK$mNA_N3H1cXjY5;FCtze~=yPueYDc1W&&U7}^nXN|(4zk`MBz!mtkAe%G#Jc(CM68VKhT2V`Nx_7BlHiZVWj>!6JVIqcViG> z|NoJz!vg+wroeLi3mt>y|7T@FlYq(LsQ!5*;k^DqAKaIJV2nhU-j|7h^uIX%dPU(U z|7D>f$o-4aLy-OlB?zhi0V^J9Y0rDr3^d0WMhj9btKejx`|FP3qx&FVs(rE#cqcZ-zGQbL` zJpUjJRroJk(-5kZ0@}Z`QfZswJc0!QLHGp%Jcmk}PG*XL4F0N*1=3UC2!i-57YwhH zm=Q`23H^DWx`PS|oXN)7zdK*KR9O?f-nrDd7hEG}AdU^ad7)~j*WyvPe${hw;R|^E zeR)rRljG||1I`p2S5OWRvAp)X_dod~aw2%*cj5=u5&`{24|M(AhXzB6V~7GU#~6_) zWTxH_^O=0RqE<*M2dT`@R<;pAGm}PL6jVA35ptP^BEW>TY&;tH$Yhf`G1H^9sz)41 z#$YhtQxfqryb*?rQWBqVMJ19TkFH!4pyFQA(^YG-2eZ|nx$60joo-@YTW{EYHKWF< znt~ING--}zCmh-58`xB@otEUYv|po0m2tGN}6PL`49uIAZTTZ7C-c(iXb?=(PW}WPJKD5h-wt>DWt>k_TC2-{X z%?`z>;U_T|1)?L5<$&=V3MoiFnk)aFo$1vE6J{$K1ZDeMdd~+(A~drW`A~}8vLb_d zmpZh&n7Rjh`4($|j>(z2Q8gAIo8wOEE63V%t~_QvCq7xkOyXdFSUE#eBup9``ks*h z)?k{gM~{IAtJ14W6eU^bV#J&=H!>HQHNLk-Wba@^gE;wR+)a}G%})lItMBwvqV3XL z@NtSktPe3R(cvY0sZf>l^WS~*YKTlUM9oSBf4Dh(90jX8M%R9Pk~sN>sllLW&4 z00yU>mKy1pXq!rq^y4*gjNKB*pILe55ids0>JFsH-!U)+eabHj4*6nJ{cz9W=8#8* zqFrU03krYaYZ_f+zPO1Wj^h!Fr&p*}q+^iwys?cauw82+jD0f0BGkw!G2xt{kykpw zw_7Q)T#r(Jpv!AwCbZ$iLN~D>lX9J}s-88G%u-*_J&6RLg<^4(*2~6tg2OGx2W(?7 zjEW*Wr6pHsFxCd55_<;JS&2kZHZ0bE=2h!2fhu^1sr$pAD->v)Y`JLhJ{J~{2zu*f zizTtydFYFpbnd-HQq&fT53=NJSn*aP_e^bp^hw^6)rK)@^RLY0XPG>6+vkb>%SE)@zr!eBnmH+cRATc+_rx z2X(8>&kTLq4v#Ikb=R-l=Rn!%I|>~RX&G2ACyj5B8iE`h-S=tNN#N1?I-o!@M@Ku6 zDw)!@%tr%e^Gtt{?oTaz(N2NfJmu!fCH}m0aBkw$SXdn)@^7w?VN=6#k}4tN*l24(Rmg_ zH(|~ju0S27^T^LH`oaZow2J^4ZU`C<0nbk+s^5J=uz0T?{nlAsRvy4Olt)y_DKPY% zvCKcX3w2%=7V=QdemCurel zpG?@<_hbmD+e7oJa{^-^hCeFDY#FLYcoL|z*3;r|OO(61AR}L9FaS>LKqxvt9_^^k zM_-@8U;pISe5@Vi_8Z-@GJI$Z_U;XS$G4Q~)J-^dklc*aY$j9?Eap1a&3I%?kbF3% z$yF+@p{PANwyb=8rN{e-?zMSFd!y}l8czx6s|IkgsNNdAuN5esw6?10M)%r1JH3T; zLEF@xx9Onx`*3QUvYn1ff#wbTLqXBZf3yUeY}2P1?q5Z&8Pql|@8XTi*CH(s+y=&Q zND7p{S18$hOl9mSk*mtgjfro6S19aA(^$ogYCXGDjv*oRg8PVHfygi9$~O5D_a@Iz z_+o<}v%Ikp$Cj_$lyeO`A8s!^@y3-SSA%GvVd z%2lm>48>ojU)tcrP;yJzRk@vt=;n)t(#*R2+$B0Ci*!}gSwsk9XL$(pN>qevj@b=~ zPcZcvc(vT!P->D&CXZ}tBroKVYEzZ0qJ??UElWLG2&f&BapD>W43t#Gv$+NItTzmx z$b2|_;w1$fK&jal7gLAF-1jfMk&X7)+%e{qEomN}!-i?w>uBAQU-a57Da5gnCKf!d zZF3h1Ts73iDU!N0@&@#+RjI_i`I}8Wu&=NSNq_xQ&}k0L8w;%j@;#=&p#2h!aBQ1HApZ5pf&ODsqmY@a^IOU49$b1e2N!!D z=*DYf8xF8@OB)GLOGB+~l*V&z%!V2b`uLnKRX#XB>?r=j#NlOE=^B`O(#4hq^^^m2 zI#n~|XUg2U!MxaY*G^kNw@0|Rji-Z~mkVLtNJDSu-r<#GyqJha8iK@&>bk7C;)_20r|v9;xuROycIN=KV^3M1-^#@Lay(Dj(1poRzL z4~2)Q`-O%sJb^3Ov%De zW-3vB>T}#e9NU;*eNT1AdMoZu;E-vYSJs?G!@)~x90NGGK*~hK*699o0()+n17s|w ze3*s|=v8bY`H|W(Cr+H8cSX!gnnRQ6YI%&a1YA3g_(L53;!NT zU?jw5);XTZzGcro;=*&ld09iEiA~oU_2hT}e_vIVF}C#cAd70%1mVACU;cT+&9PxP z;_{h}1yLvnG0iZy9)Zzcpy<|X3!_?gt=XKnGik?3jKxtBqKzs{)+Jb+-9O#2MGQu1 zZ4BdiN{2ewPk<6s=kWzFNZC&6ZR)(8z+JKHdHZSz+e_5sqJ-%s^Qk+uzs|zCP9JJ* zx5_~TpW;aeWhSk_5wSN3ICCSS1`VYu zhqIMi0ruzpLKb`B(>lf{k3qUT>nj{7Rl9dcI-(xr4zpBkpk`8wjRE|<9oa?vNe$d~ zL^PUquE^c>JHo;(9#}mICYih?<&mKLZ5S$HU~@Oh16Bax0XU`ydBJ#>N3GIfEqAx3Vxuzz@!iQpIwNL!^l1yVGW@DrFGMc=Bbtz zP_3(o)nsL30&$D<=HXKc*Vhx8m#{4KVwyKGh3DbU{^wy~)BqR$*I}GXJgr6}eL$d* zP#>r7{kI`!9@q7lHblUA&irMeZl|I zUK9O+W8)Xj3^OZj|FnGHwEXkNUjLx*0mLuV!JbLy8)S%IR1!I{0aQz}AX0K6u zw$#jhg)3l&?u0_{tB>n%(`_M_)FcVg3kW|IRZrb=zr2((si#Amj%Uxpd({bBi&Y3) z10^&;i9ZRdg+_avU-`d-miWMY6F$ru%j#*|4iGv{DBE%YIoH$^_VSv?#^D^k5Uk!Y zt%8~NRu#wk0_0a@0^{Da8j8~pQR-x%?%%yYWe`+VZ`9JxZ13;8E`7qQsI6xOhO1WO zW-|7LR&^iYnI2UB9+()NMQ^mBhmX72F+2$iSUl=6C^+>$GJBsv&qq6G zyG3z9+gJ5nF$oF|AGA0RgyxLCZ2BE62waJ5CV_d)*O2(lld!@}VdTA9G-p=0`FW-Z z&8c?9>-Sqx4FiMKk_4?D`6*Xq4i8UE`~6C`Py;j-2kMSiSeyMc?MN>ZhEponq8*K_ zF2yd4GOraI&3+}*4LL0hBV0_N#@{$i+S6fo1jqGYT+(6dE|~X7k<9FtNL;-MI;)?^ zsS%b>%fIDNcNgN!0QZ29j5GW)Uf{uLz}*r~LP<5t1fVIK%jy2BVlrow`X6R>cb_^_@NUEJ5VzF~ zha)EJppV?MzIBVfOk^K}6x-Z5dou+K%lN!{^!4)wQU@TPI#jERLWI)7HrQ4^JXqUy zmfO0+TBVSSgnUMj-_D9>DFmhfJ?Nk!N}=Qah)s7LyB#w!j+LyBMofMw0x=6I3Y`22 z1UTa1?rn_wg!uN>y*4GbBTjiR&9;;--02~#OBuy0%NGOQjeaP zWYs7G$9cE6oIw>n#5>TUt8RF%O^+uY^OaKCmhb((tk1TIOGox_YICw-{bPpH#h#Tg z74LlX2i0?~Mn&;o^+wUNOjfwZx+!zP7ayo%0IF(A&UhZPL zgIiHVXR8z|TTn$4i{dvFU6#^dSA!jA?~9XMJ}0Vb764i?WTlxI!vS_Kl4VUtnFDi zJ0a5O=byH-w#4h?Q_lxDAF_@=X#Zqc?7y-xJj6c%kf;ym{*n{|g3}BFf*Jw>!pYT& z)zaPsyoHL{1aSUD_D?MoOURP^r#fygwf!^Gm#wh=V&nN2(!bCq1`lZ`jQWp@i9d+! zl>h?bN-EsTz4Y?OU(ojupN$;y)1Er{nnI)`GA|;+@**^wD0clm zO;>2@wBza)xvmqs%DGDOHZv}(ZHu8pr0HCmZH+@qD`^c}jn>VwuAN@Z#GlvgDb(y~ zdyc3NyYcQ!@0(xWFZ@?7Ir9OXXnmho*vRxl$8W#tEv;MEJB;XPfNE}^;;p?Fvb3#y z<@l1SD-8-^0qqFu=Sz<;KL<|4^Wy!m(c{k=xG-vEJ)p71e`ci_bLeZ>8FN=jO%67g z3pGUMV|CwuZjiQxENHE!Ao}KQP){k;7T_-a=j*hE&xF>Y_$WGA_&Fc4L?|W4G7MJK zF24+zhKAPAPFeIP707~Upq%&>&zKMOmq}>6X)G1?#>{7AJG5Ff-ZIQ2Wj>u=4;d@2 z2~`HHtZw|8B4{)C@6NHbq2SOY6e}2B*s9OBmB-GXF=HiXP+GtKoh0a}j`s z9OSsk~!n*8e5x5oxSD7P1kHIfI5c0DYiiTvPw;B%&=M2K-9Bo zh#iG95OQQ+n}j=KJlQF3#H{;0vhi*^ki)k%p5N5ryEGHF4GuJ`C7!WBJagYC;*-H! z0bEmz0yAL{a(;hU5QD0Q3HvwjXXDC*`Iu&WtR0%h! z(nUcTHS6{)LF^r>k1T=O@79J0<`a&dj(D2XI!x8x@&hWadg+ikYX`18fOu$0{(+{u zdt+uiwLn_*hab~Gsj+>Jkf4qfR@Pdnw)T<5TRn$O{b;+*7p6m0kCh4#6<3!K}Fc((g#3+iJHV!bk#!jsy@ z*Yu>cQ$S#$QAfE9KDkk!`pKWIcaCx^(TNUJL-V4(jb#XCTYkp%+sje!LqnCx#UZarI3; zf`O%0|1bc+@^ep&>WO_HC5#`LL3tAciogaEsJZ2RLVBVtplC?&-hHu6) z1N1A+7+Huy$&9`6_se6N0`Ju#Mu-5T;0mS{%hG<^QZbel7noK(L=~%YKr7ug0n)e$ zT@^2~;%KTs?Z6UKoTkP0!bA>(aAe*2YLFeZPY%f?8>(iHm@tgdf{U=DafG#fzDJ}i zXxVl^LBKH$VK5e9av@rlwvOiOpxyjAx`I^|mD-su+mOJ` zGchpvX%cm~1*z@TIfBid*2J3(w`&B_ZXzvi7CgQwAlQn$fv;TdVr(0KJhmUv*&<|kt9dXK&lD6iRwh|stQ{tJ@k z-f^lw_dssNtKXV_O2~UWbCaY5?kDI65V0o4;m_q`&a4I7Yqjn(_Lr~0oeAh9e5@Ux zDmkmX#6q9z*`CBnUT-O900VQ*zGhZjsUcZEPC_^6e{FclT0gTFy#Kj1U%je60MQEM zsbn7C`LVbJlpdUTrI}4v4lBqZNC_~;{gs|Z@1IK;EEY3QY-f1}EH3t7x=#n?1Pn*& ze2=R#$Tr5BQ~4w30NwLV6Ehe_h(C$CY3PqHnf0h;HGFouw* zyC{$ZnLlFV(voi-##46oI9jJlLA83+61!xF5Z#nW;nF-$RwST)qd5C1c_!+-l`7yR z_M5?I*E3u%&wfV=QfPz4qrbVAz(>V_|65Ed7(RRWSFk>lKub30Km_onH5&0;ZpB!b zKjiHF8DGw0X!uLG%Q_(v43@rEF=0rKm+NhkmSyQ1z;Dw?ykA=_@XwwaDCwmi;6pfL z8v?AAEC$DL(Q_VD7z158qu2xtR$AfIE-G;))-!%OXA?u*C9X&Ta_@@ciA;E-*r+hU zVpW{oUTXEJ4iQ7@X$`H0&$pW9969#>26z{U~ipulkh`)YQ3|Cv8>Dv{Nq0v?vVL19>(~ zJMd_UKpc3qQ%EsXk5Xn_{ACzAmu8+SU@jARrIBqQcBk|=Rh1tQ+GMeyi4sS)+CjyN ziV%?&(VAnM?pp=dw3LNFD!5n5X&__LqgQ2!MPpmN%WO5V$MhQH9LNByEI#XQfe8)ss3D?!1>l94(Ca%s4UqFoy8=C3Q zDdu*RIkLG$z|SNxXtPaiwAB+)y=9p$;I1|1dEVSQTr zm|^mZ zfByXISlrXrAT;C@TMF658#C#Kgjg_~t1P(Yf+&Opaa79lDYd=|l>^K}Yh~4ZLYrmy ztFfK#wZKp5ynl|L#HQA^@p#6~H4l$%Kk_oH>f*>Hz^#}WSKgflU+^#yA;Ndvf$lPm z{{fUOl#1&ri^baufpU|pEAxY6j=@`L0=a(sD_^J3jH3EHgi}3rh2v&Hy&oxKWY~{Z zThfjORi}iB-Dg5}fU0#8`XA~Ut9$Cm%zTzRuc#OA*<9sR6;UC=MxXUy>n-ewvFXvZpJf zwTWnxxy&3JE48*5FVIUSi=K_jBa`#q0m>hT}p6oh$+18jyE!2=@w&}JIUvYvqJ6nhACL7#978%?w<~mBy zV2S~zh^S-~%Z5X7o*%SNil>-1P+&5pa{9-21s%3}zi+&K4T>{eC@)RKG{QV`R)W(h z4$CZrUbRcvCj_XWmQBB6w~sR*?WjPaJd=RamWh5Pt7Cr5IV-#EEH~VT55o;9)#F&U zacab@gWRa)p9mN->ZpPbuAO6%xyyxKLaB%4%O+lR=6OiTfn$*QoJojx`YeiSX+vhI zC*fGPQI?CG+wBMudQS3xrkzmlJG)_6@)>`eOsrJQYxD)(CW?J-h`W6>S=a#)lB8h; z*Hn1z6A#2?k`ClpC%T)m;YNppiH#2~1O<2$KDfn8*q58>rUh~50jm}W~C zW)03_@72^f4;|sos27py`4?;h&)>^j70u;Gs8}+)$vbiSG7I5;!|q%ib{)NK4zJ98 z1eW@f727C@xm^W~{xQJzFj)nKyv<0o-R>039=2K1i7`tS#D5?6q>O86j&Y25b83F` zh`E*V**Qi{xJM=ZK64Al@T75hAk2W)Z^wOY>Us3t0RIP?q;OEf@O96(RGi`KqF=`P z_qe=U{y$L)MAf)rO_+=k!j0)Acg~{u2EI}9KtdGy%UfDLKJYSz-eqzKZ4z+BUA4kw|-n(%O9z=DqQDos3EAyy z3}Tsb^lV?~06cB&R6owG?m3_2Wcpe+9etzYTknji1A0C(oObe%YT20on&xle=xSM> zXkYxBjkK4EF5eo@U$D@fDErg)sI21rt$TF(K^?2{lHYj_WQX^@ zmKG3#Q$*p1Cz%b?7ea(Sm%I&1ye!S8+_{%LMNLf+c#WD{VzJ^{#{Y!74j%P)+NDRf zNIQOg*~$HB{R;$}7r1>|cPe?+gX=Ju3Uo5(-yDK_$BiAV!Bs%EP;rG8{)%?*aj;u* zbH|xpI6ioYeDwK?KqL(g&V*Wh`8%5S^09`}wPs)E?J_jYnPC>A(y{mFazD^F`{pj9 z$6uC^o9QNKFSr&j55h@Fgzj^s)ctr|-zfrIVBMuz5IYrWQ<|OYJR$N)4l2bS_y<(ZWk_wo3|hbWe-z zHFR{6(OW^svXE|CTsv{xh&%qJ=qw{b zQV!btd)%P1G_R?2oN1bJ?>(ul$e+gXZJ~cQPEcX87B=po64q;wu2Rvoaa%%}al8<` zyvZTCV;p25A?Gt)bdD{s-RauUT&;rF3^;{MY1?IKbAL#fX|6ouMlH1Wj zeY9ycGIOAKS^&88PbAa!-_tvZa(z&G9g_^%E=(rhHM(wojl$+aDd-0_h`(bZmb%~@ z(*w;jKY4S;&nw527d+q-LDI7dMMPmb{RVtkWJ&Q-;{EK3kQfSbEPjSZyC(uz2k0^) zA%l3EZQ=#VLBa>JsggaqadoS_j(D23+}^qh0WJab8)`0jjdVutE*}q=ynl2&Efu!Y z{BBjw_@z?3mR|R}G0~JFS-9ayj)zv-oPP>=wOIoaEy%;YQ@qwNQP=wLD0W6A$rGX} zcHpFDt(Sk`%a=5ie{;zY#p1hE7`o*`cm#0~SpDSwsy3^r<^oU{v=I89e4;N0Nj-qN ztjX*A56XQIKQb6?h*LOD8sYJ# zzOuUQTC*^a6xmOT5Wf$b$m^b+_auryj(f%6LUUj9P^PO(Fh4S6j8#27#)W zrEU}3|K3YFC(_u9#-S*W#(0u2vQ^x@h{RibP8HFFP8PXWd8()n=y%dGy5-?lHn_4j zJa2x&(Z{+xTA@*z(l#6t94T(yw5ev@a{Tmv1wqVkzyLJvf@bG%F^J#?#_P;MhT&SA zTqCouPB`OC(@<`i7*xfan&n5b6i9@};f(;*D?EY;q!Ndghd%a|ruHS1pG(lJA7kCasYR z>Qy^ur2(l!<*-C(D7l%q1{68yDik$*C^I>ywxw?q`k6G#RGq_$Rb|4dQh~s?5^8w+ zY$2VY|9eg0f_R$OR_bR1r6{T53x29Cn4Hd_)_NeT#hK#~p&8N1V>;y*qkj2LOxjru zzSP?O%m)ps7avrS-o)C`B_LF7Q8p8O-2n6vM0Z9!c=}u4rQY55AW*;vkJKA5!uyi8 zNKHmZ972WKf;V47e1en{q8*JRM~md?%siU#Iiung{$L3*y^iG=GIQ{o>9(N=(sSD7 zL4#mX;+?L!_u0uqwQPdNe7t>5U@y_m)W{kb>x4h7sf#y$)=i6NM(us~ve;;K&P|DD zCWhZ7kJn{+ZO#qE1DeU^cX8x>X-vKMY;xJYkecc8y{G0g(BWfwm|R)IjV~qcS`n!s zN-#e-<#!IK`1F0Z`0~`7iO34bLR|bW?O=^h?RV0B03ejd=Z`4QOl-iVRc}ch;di%+ zr8WG_X_)k|y+&Y5{(wibP-fi1WMziPpBG*l=c;Yl6}vZZBAPHQ{^+hsbtvv zIh?wO>n_FHLn5!1Ma=~vvgg&8iVNM8uG&F%p}eckxd~Cp44JNTbMps&svB>+b4m_tc-0R;d{G##LezJL+aC1ewYEK$@dCb-c)aw zIGzo^fr>?9GKO}y<+gpwf4UzE>1NM)KoLq%}iP#(JOXVC6!RsPT1d`ISNJNMmKonN|5*PMcqsk5lEnb(6z0QtQ? zRgQC_iaDI5E^E_hBI?{rlPNrR(>aIHJXJ!V%iNFSlZjt{AMOEvww{g04c`*3$eYMi zD>Sq^tA6c*#ls7H4A$knnsw+FEf1U>9K(~;btF|KdQ~J@q+m1~P$+UYp+Lbxf)`1z<+CjUtMmz>rH01_MSCGe!-F`uU#gs}t>dmWlyW*9Qq`6AP~G)4C4{->+EdfV z2CpfQ)dbRM#QIA02}%!RmSt4_3USeHqd~R{vu0gmb!_GS`GtDDWwpQ{f~fg|SrkNH z^q}kb5}wVRv}2!YXw)QIr=WR;!z))uf+|;crgRqj&j*J2IL1|d&wV*H!tqJlLm+0H7pB^s>pe|eT$4zMiQm2hy zoG+__VMjzfwi^22X(@dIrc?_{B}ZqEsk@onC{9<`S%#F2$4Iu$7MGR1%^bWp_a7Aj zz47!iAzftkHBtq{qUfXY=L9il!OnMiYBp2ZYi62_j!WwaCphQ(UR~ zFbCl1hy!^uBW+TsDr<^d`!27FqG94ad)xzlD?!#Wk!-PYb~TDER@Kbmga(yd{%tp#8HDmb7S4oHnOdd`Dv);hUzV~m8pOJ$9fE+j47-v z%*NUdlOU)3%1Qo6T9+k=&0{2WY)7HltePPh=Sd8&j6y=7Zb|Tgtx~EQfIn~<(wE=ndQon zu-?OS-OcklFlycA$Ch^p#KiCx4AgOL)Q8RJmIM?{Wz_Z!j_L>~ZQak^16$Rw^;bwX z+$Eg&1FPUiEAppPD8X+4;e?uRPa9AMJn-K@8;}M7cyc|0$Fn|H;;uidkdNNSt`P4l zsHc^p#5j73+|mo@R+En72gw634Ze81u4E#uPT-_Y zRs&);3zWV2$NiiH&XF3}tUO@bUN$QK%#EJ^Mp&8ZgRk{1aTcTl85Dom){03_rt5dw zl~=)2|AG78#i=$EV@M#~zY^0*BqXEYe@+^yt~Yb-J*>bA#oU)u z+a15UP6AF`esnbXpXY)O${>wP8oxlnh&njb+y^6V5_$n=$&pM9`Q}x=Q(FU>HZ`|# z<1>!tSST^Mc^!BPExo}u(0^ssM@u@w`08Rw=pXZ6=+LVqGj#Ryg*v^f<}5UqT9)VK zsfil{{31R1Ot>kuMp2+%iG!oT3>!)}0(I@okW*ac$4grM`y zSVQM>M?9MNaS@uc=Q^3~x5nEYmg{$8$=MW zfqy$hg$gpWRT+T{UHtzPXh7HYGeMWM#M9C*7eK$k>oPH!i_x(-wv0f>DNA`D96MMN zCCED5V_vxd>99V94-~{%Qgt(Y)z45_mhM2kHwI8-YZ49cAyJ~UIPp+IQsS?gC4SQ& zWHNTK?NNq|0hWg%NeeslJCB*a$f?p=J`4*mndmKiDtH2YA^LF|JZwl8EMZt49>b+w zJBX+qm6$D*qkYY0#w|)I`#J6^f|bz5pru|mWJy3DIh|ac=9FdALNZpHoVZb;l9`w# zA@Q9C|F+Vu6J@!I6sr~YkB^NAr=nSgM&<+kT6sTVC;^mvO~da-m&J=&2s@d)R_B%L z=&Y8l+-wEVU0}=bA>h5Hw~5jEdL0{+r0}Sb_5u)MD6}9z!V*IBxqXYP%hsAFG{@9c z)covE_4z@v()W8mIlkQt{0+fRJzs4S@P?!arMHP{49-vg+1Y->4Ig&)>N-j{#C5uC z0(VKZd6?Kd6N#T|ITgET&%MzKX6iUZwxnteB5uir=JG`03Q9ERy`0d=xLko3*Qi2F-+zYvvInz;f-;yrWb^xITTM!v`PiwTQ& z-NPjTAhac0jib}*xGtRYv499st(~(`+dzZ;6k!+}3wDFpHH~KezY6Yg#i9S8l3?W) zM(ey+qk8t8*lP}BUWhRcZWVYeTf5|z_^|qkMhNb)n3gHy$K4bIqrR~%V3OloQ zD9|;-K@P`zqK`4oP~dpId_y3kNP4Ne>HkM3O%`h|?Y(hU5jNNkgF z6rV>Q^8b_`#pI~)!*trapkc&t1`G7F7;8(C!HiBb*r>`GCm;)yBq zV&0Kx=c5cMpO!w@v6?EwXhmBao3|7vC_grNrpSI?(GDiN-AY){mOQpJrdRsi zB>I>UMF^L*s*~{J+!;4OROcH3mmpDRNVAi}Yd#F#DESMc;fH7DyV3pDLN`eGT{2>4 z;Ktfl=LfZ7?!oa1#1mV0-y}xm8|BVB0>yK$n=7qkeqis_-D4)%4)-kQ;|cE1GUoe!@tG^9t-GK# z4Q$QAgON00QkQz?Od6-Gtk3(!^+F;&-thsw1Vb$^oJlU7%BqxRYQP?)N8tEde7$iX zGY>tz4jH@HTrHcOI~Vn3fd{1+wN!Qgw`QMoKHLTdX%slYorZ8P7wBV?pS{pCz=`uo4r^Py(Dl-0JdOY7i>s#O1Cn-sk}|%DsEeSc_bq8f_>> z5PG`O)^VkQq~26a7@y4GxIi>#?ht3emv%pcPyt?#aTG7;B_b49hnfEC8RZly#RV4u zv;$dllBM(@WjNj+iw%*WYgc;UC)8^9 zUo_p`Hz(ZX1<=Dp-?YmP2)k3J0J!lBTYreBj*HNVfci0UR1S-IiLsK{6$8y~w;TXs zuf8U~S0wHmeeX#SXWppcS+3s3eY)(AJKQTYE1IL8#5iVYp1I0{)aUJwiEWa&%v^J> zJ;%>OR%AN};nMI6r&JU?drO3b0*)iC&))KX0N5s-&w6Yr$I4&Zzf~OIUM5Oaa`4B& zO)=m6Zl)W&nvQ`aX`_Jop~4i7lT(bY0hLpW{GG(BL2VQr6h6*_&ySk*L0s*j+<;YI zH^&~V0$_rdJ4d%fQw^f6?bI73X$Su(JkktPPSzo0;UQp1?Wh356UpJ(XJ)BTo~7dx6NC@EJ*Bj?2&jU5f`ZcEEMS}J+4 zpAAi*dv&lc;imyB0TO^=``rARix${UqGV~iM?muTvsXeBOV{!y(%SVU+{<`aj|`L` zgCKOLW}5}g^%dKJE9_j!B{;ECi-C(8sBQMgJs!&T{z&NOE_>i`D=Zz;%#=9^RBlU* z7CzT2D7m?8Or~y4)v#-Bck@s(fO=W!bj!e{--_nZAd3*G(#FrwwQX6zamEo97#geX z8Jd{IfxYGeOY3DgaXDp5_BaIbt|v<1;5KEwv26?-hw&M>bJ)yS3=K^1r*yz+M!f|r zF#Ouwhd~Znx>H0i&^J3bmW)tNQ3?KX-;(_X>Rcq^@Laz!eU33eXop%}`%Y+GrX-6Y z&9lCA7zM(0Pjw14z)@R2s-uiriOLBnsr1w zvuiAIBQRyF{aQ|9$aT2`Wugn~AI*UXq)JOV3_5$ zmj!Yz;o8KY>*|#C2RZ8ZYF*v#hlS)|ob9$PpeA5s?f7$C?z(iKSlZjQZv`OXgRm*+=4>vLy*;nc)&~#lOgSM$VBhtMxX4E#{vR=H};> zmB`ETGZk7r9RE>6Mept!TN+DvS*9ZQW3=PKdFSS#?c4cc+leCm)*r+Dg6e225S5c# zyWqTKEvhpE$2@GtBx0dhJXd^XQcm49I0_KJvgr5pX_O42iZSw2<1Z!K zh1rG1da!Ocev-}w-wsQNSsv%ra zagG%@!LIzC@Wlfy)+dsb{@MLEF#^LM0EVO}N^FSk8>~N(70R&Fep}!lUQixLSo-H! zZ&wl){%&anq~xpINluO_5jEFNYX2wpTkDT^!nmVHA&N52 zBOrjCFnh%pG16r`-zS{+ftb*h%;Yak|3^f4}iH5{MB`cGx80(6J$bq8OX4TfC6*~ z-!ctTlL<%62v-{H5!-)!(p@<~J4L;X0E*zIxGgFy^~r&nKX`4(2VNst?AW_P#UL!7 z<$B>ASCZywO{kb{GV?#SkQ^VS&klASeu7nP<5wHwFfOktNgV?b>d9#OBOEf}C(_Je z0U;uVXEZ@@AbE#qP~y14ek>K|36wbf@KLk2=1dBf^2&hy3$x_-CsvDz({(T8tb}!3 zYnh+)9M4cx{SIsd0BWjPW_)^4o)73>dTP6}Sz>0AN`2vJWiP&sJOvpbqXb=f1Is%@67}sbP7I4;2BO7(65$}%4H`|x0}X0VDq;! z9w(aUHPA`H!s3znPa?1sxY#RhW6jE95r;T)eEh6mP5c^ZKFnaq*ZR{`pXF}#N?4w*~D(45y zgtJ8sWpCmk&!iM5T)q;PcP~NXtGuGl)>YS2DV4wXSvqriUK}|!E9fvG{lVgUm2PTC zi}msm4nzAV1F|g&ui%4*-rwD!UY|{!bJu@vU3n1^;{L4DmuY2DQ*lXS;`%n3aWnoC z=}R>xp;7*2d&<5;CucqRbgiOS>~O!I1!EVpm{mEo1vtsK#Yz~O1L*GEI?~AE*`-hd z4K|U$ZG)r!^HAA1^Do^_vWct5$n0OQZyHSWZ%e+*JK|j`u{FH=jQHpL-MBwVpDw?_ zf*&>rK408@)t~9z(Zs>`xBPynHJO>6DE|r zB_|_W@4H}K?+6@X`8vtb>0WVOvrt*6$;;=g;(XzkB?T+E$&2+>(+RMIUaf5LN7<&E z6|KK2?_IsTU~yYGi+o&cK4O>AknzZa?G+I@zpAe3%X#?*Zc_es+mnv&bJdZ^H_HY` z=1*>c4uvkx8~LU1cQf&yNIZO6z=+u|hvUTg={;6vTNFpFtt?;AJ9EU%r}5j2{@j`& zRT{@!X{hnYyyjk_M9U7Dlf zcf3UC9Sw`^qkKk>KE5otX6h&T>5mAFZ9v{5M{shcl~Kk~0` z5-3!!KbkG{IX07{+Ddt8OJd9HkC3FpkMn#5T$Eu*fj;HlqsQc)Nm$A|D)A?qj_ZZ0 zht>PqqWx3*Oj5*;m+bleyGCI#-7UOCUuRcuqHct>uvF;&ycPA}DP=k*=ND5o4^H}p z9&D%I7C3dI(DAt7^{0D}V`38SbY$OIl_Webc2RxJ5YtYOUd(NzJ1S16$ymIA(VK2d z9U0FotB#E(65<}bB8y$KB*i#oInu&V+gN)<@h9951v@_LS-D4VYi&xGDqe`LvT%sq zki;Jlb8rpkZ5?X5M89*J?p>uW2TS893(kx8x6M{XE+h^1%`dXwWENNJf17Z7;85y^ zTQ}*ZTuKab0*zNYhI7+`)#Zkou~U1cnFfPJc&6?NsciXk->8(_pA%SWmb!eZCwv&1 za=5EPHcnk`=-K7(cR{hY zk}EK)O*~pU~)LMsol$43R`$2sB)3;rA=F+7yiFdLBPnh_>ejPkqVjDj_ zo7db~YSMSz*Cl!}lZGs2E?!nJZ2SEjAK$@wjfE(MqHN2{Gi>QQ&y~9z+vVcefAdfl z_whk#x5VTjjzR~=v|gGKW1=L>gGTFE>+I~Qfn-OOGP=%65%C`%3_BBJPG7&w)hGE} zw|t34(&}Qoahr3)sEa2i+|t(*Bja1KkENseFzuTU_r;lO?PxxklOrF(1JZ{_T->!4 z*vkxE+=}i`+IcdsL@!N0V4TqLT#S)OUEQrPl&zyaeZHBvx{GJ3M@ZmHP=k8fvYWz? zP5hnZpauzrq4Au+7|lkBrA$MyA%&D&v(Rt$I@^9L@_g*Y*ZFRi-t5d(Pq$=|?@QEv zXmaat+DdA=?uC+2Z3FZPo& z#b^$TS5>6Y|Ex9DZ(elfa6a$eDa<6#vS#+PjX>6@HdntqY8F+t41YU2B7gGU4X&0J zi2(ejsgxw=ntgfKr8C~vRVfOEFtk2x%Bq~abs)s?g!YH4+8^=^$N@Y#yX}6Ge{!5+ zyP+FpQmWU;}DU}n1a zM0JNsh~2iKx=+1!r!TUTr;qMR3RYn}oE_0Lr?L<8#pT1MpNq$u&j#c?c$#XGVWTtr zJ)zFo%CexiKhrz&UGJiSMwpS{Y;cN!rA$}#)>zpP;pvYe+!vfM>`!~Ibcr|GUpNsF zBGnFGOtSYYbIYy^O4;hweJ$~fhgILt3?c24`_v^KEj?`1dAsJ^k~%^5jjxcD&Mvsn z%5m-9_2?@BL#oU^9S6wRAO|I;Ie}BN_J>l{&NcPE^Hxuq{n(OgpQ_qW-+TI`nVH-t zb;t216L-5A%@{|dB)zSA5c=V&68BurU;17@_CnVOX;^tTAgRQKHz@z z?ISn3C{qD-xuj(E2dXZDRe~Z9BGMnI2KfZ0=7?uLkzq5rBj9VH`KC?i)}lL9fB5k# z>GB`Pm;MG2L>NFq$1@*4`Udjh5Ej$Z1vjjp)hZ| z$FOknWu%=B^Ph3;N)6~ytJR~n=T@hD6mxH1NHfho5&tWzy48ut-J#5VTM=2ga4@91 zv2)YHA0x_!#rEB(_uK@Y&`eZL%{j?XZf( zSsI)^uaH3o6LWWGzZ#8(Ji}SYTpJf*#9MqUZ+co@Y~VOHB8;1D7dG0DTRVe~aoT5y z)xK~Vf6SL#n;>O$P{;M-Lt~FuALotB^&G@@&hW9Ct6WmkWN|YeQA!@zzt~Lgo}*yr zSSx8WQ)IAd)>qrT=tqgLW-4!8Hd$UK~B2V zu&KxoT)}3?u-6d+DFmC%h@2Fk!0w<$P97y=KjM*-&U9?WX7rI$RM7zpk%+<6F~F`Z zSjlVo^;kY4!g8e%TZZ!5wqT9Xlk)4>JUn7xXD7A;VfogH^}!*8L$|Rl2!Xd7OG|^C zi1c7BA>`!Pee5nQEAsWJ5ZZyHO;`-35RbuZhpi^D?C_coBuqYSV`lM6nLhd>pptO5W?KP!V<;^91>fP4GWx=ne zbOtpqUem9H`>@@U^Zi?P$dy1Z1I3y5?%aFgmh4G0g;d*ZEC#FQ2Myup(Wl-wxW@mg zb&MFvjQ99_&xYYrjnYtEe0SD+oJB|ZiMyA2 z{W+W`biu?tFlUf>;yrK6sf=e6UO799PdalepW0d2n)h4xrI`rN)1jBD?vk&QtPgHI z&B>X6R6Do9`FRTY)AggC$E7h<86f{6}!;9`{s3czyrxBJtqUO6vW*EH8Br zKR-l1_$z@&#Mwpka`8$UJz z>=V?O#Tr%)`9ZX6F%WK=2I=Wu^tf7tz{-FVM_E)Dadha39usZ=piAIkvxDNg50oU6|%3 zmIKaI!$H^X>)?#gXt?!oKM{@W`nVg&aabR>hA4cv2N#Vhv^2ymqn!FCxG}_YF;iS6 zI9|JJiqjz>tPHlea@6D{JKP;C0);!`n$QHuI^()<2+t=soG2{&0(<3LZ74W=h z`CQS$i*G_)6}H89;n6N<;_#&+jDW#}(C50)a$h6b<8x3g#m@L8G&`AY_+->k9uIsv z>O`F{{s+oa5rm&b)14WD4@7ye;rMQ(uwLtr#7cz12&B%YT6apGGpeg}z8{P_~kbmPl5SLpt396{R2qM87of9VM z3AYd}^$Y}0G$=L}!VCd%cy$wD7NvaTAta&+4U{0fMl)a~O?ZLkL`I&#iJt7dZHdq&}2cFqf!XZ zP(6Fo35U^>wk(1!+Nb~I6GqXrj}{Zg(UXp|gmWm5cNO6ZVzgH1I)NT-@h>%_Wdoqa z-_gUC0|fbNPCbP8sH1uV1j^(ZIZU{KQly^|6o`mzr!m3y=>!wJkV7j6TiVmgkn_iEHrsOdmE|UEO{jjd^w9cNevB8} z+43)gx+aO*e#Y3-nA4djOoDjx{X@I`>-;{KJX;*GsvQb@UThxH_pr%EHMHtXVEdx( zs!jW1-@}iQ$|i=!A`i!DKYGZZ;i&jbH>t|N(%PD_7 zm3jUW$6!H2>D;33Z6@Jw;ziT1evE2aC8|C#@giqEOg<>4d^Dt2>GbA(^0z`#iMtOS z+isdf=c8j3oOCd|y*#k{{jGwqVVlG)tO3m3ap_IxuehCZNqXC}T)`v9=9JyU^@|R^ z_I8_eP0j?5e-dZdZ|S$6g%10B(8BprnRem^QQ}p3)88z@pop7>gEUF;gyz)kuh@$M z4ExT7k<(po_)pu6D$#}vl-H4LRb?Md!>rny<9nW$DtRbg!9Eg>uZ_~Hq zIc#8hz+z!`ug3VX19g5U##8;X@*XP;#r|$12k#(XY0NQ{cU(9vI_5kiBs{^$6RjKf z%D!~`+xz`5v?}!C6^7oL(OP)hRbB|Wz4OhurS%Q#;N?^E(vj&j4|6X#YK6R#Vi;_V z6}H!XepI2cF+tRc;gH^KeV(JPd9DwZhi2K$SvIFH9V~pK&ad!jCwD`1UgXNxSK`xs z1;a07es3oWGlZm+-^}A5lx`*Y{R*~DD0Z8cdoU*Mt!*&O&~5qJQuMx=eu-Mf;8ckQ z&(5?Kc|u{@%S?ly<~lxMQJtZN^g7iC7Ztbo-fvWN>)GU|D}3&8$K#p1vUN&Qyf1Yb zH5filzPfrRmT}6W+$1$g_-0*#YhmC>`~`OguH84h;>mD}CZk0_>gd7UM-zWMt;-2r z+Na~-7my;{ZhMwpJm+fQ^d!-Z$FA<|nCzGRLFu&>-)PM{!0%WM`nKHh{Z#Pmk4BW8 zfrHfJdyj8am$-bp1-mWurMW8(J*cl(xv+M4t$X6aiG8MzpC|vQuab$*jD4#xb|$Xa zUfa)wFt@$xF4>^YUT2>DW031JP5WLYLG>?fMV0v_{29m34!4}b-cu`&sW>apHiQ>& z@qC4wi%Eb5EB$jsuI(A?kn>{>T-Z8vRV((h)JQL8MQ!xaSC)glD{XaORYOh{+cdrM z5B+>eV&2&*>e_|bO)CdzGAel`tTJtmji<9j$nTk#`Z8iq##Pm_;*t*~dt@t!bj+U?%dkChV3-r=6+Y_u*$&~KBzvnB_n=iI= zty0C)WRqu(Wer)fSMeCR@XI~xK#w|umpKz(bb?>R1itXV*`=tZT(}^x%DjDnBjiMe zK#6lLdpGvM!%bgOCj7iRI3DuoHR>g9-%g@ue^Pp@g>USWdYfH^$;h#0y?&$ccYE5# zW{=f#d37|4pZ_kvIwmqZwq>@%qU~t*SIr-no;{Y@Wfwax8Ac`?yswTa|D$%yAhFYS z@xfTj3Qpvr>%&iB3De@=A&dCh=&xHIzw zH!J?iqF-P^m?lQg*+lT2kfsjt)9}khDUF-ERmxtT?KeCkvC4J!wzUV-lVjSmUXDeR zZIXSBKc3WV+WSlIn1=oC+JsPu)%cdxFE7U+>xGVY!-0{5(5X%B9bfzIsZpL0fY0Tsa>(>z+#D1f64=qrX7a|Ov|Nwo}1on^u4+1;wmH6()h3|E#+S8 zsy8hUI?Fr^pgo69=`pdi7tqN?E`jzTGA~|Dqn$t}koP&XH_(Z)yomM^x+Jo$q7C9i zCabbqj*^Y}_l--{ZqNF(c4 zg~y6$YL%x=Yt9_;7^#BED;5&-U)HWZeq~x?wh}eP$8=+Gt1s{Q${SNFF`qyGEd9RP z`8EAGS)K3(SuaI7hKJ74< z? z7I8jSeG=x#v+o^NyxV(%`_f5vu4q$3t8^s!9{coEc0zH+7{{E4*Z0 z)c-#B>uJYN$-W>7V@Jtey0{%il`=&&j%ks*y_GITWG*SzKq?cW0|nBJB3WM!%h%Mu z76`AD5_DI1EghHMyt}ubBfTlAso+8K{@9?sDouTfEe8zhAHB?!EK+FLviJVZ3fc!b zF;XeEa&NVEn)9TaUTq^cSLJ*N3OPy>Jo@JL9$&UFA>Pzd%a#HyWBsbml53$7%Jja5 z;nBxrE1bB~GBTO!?MG*4pD>G^f0gJRhA(;RCCT?hlz~D1L@g#HY#6#k@6c%LVypTp zraq;_sPnQ)Rl}jq7ccbVbay&WjeGx*=~DJRUU4gt|HWONdnBl$&dc7w*H^9<%o;z0Uz7%FP(9{5ru!> z&0n8kvUtONIMg?*X>6&IY_$|RSQUB4WY~$v=;p|*u3$#+((bngc%~b{M(PG_!@RKGmZ1~zGP^w-~-K2oq%6};X?^sPruXq)24}G*Nw==Q9}gA%gGfF z4G4IXv)u0#WNpWkEnfKBrd0LkeRd9bE5a?O#j0q)=@qbclqdgfiP&oElldHN6aV`X zgTKEISe9j#3veAcBe(aQqhTqFO3^Vj>eC}`!33JwV~HrkAHqx z&FHXGre~{`Pm0ln%jYec{F2hYN!_kW^U?V>7qTqwqHg!#b>TaqMByE!jn8;j&qqg$ z9k?B>v*3GD!NYhy&-%(hXpU9NmzsQ|^ec2j+wYoPPutQM^O|Pr{^(9;^2g7L%h|s? z3y&!{sOUAn_`oo<>l0scv(kNcN21#GwG!=DSjLw!-;cf9t?-_Y@LfkLsPuedU`U(S zGQ(FL-vZ4iFTb0ee*8^n(92Eof@3q`G5p&q?%Qad*Zm^_pH}E1+}_z+YH;WCp9|`w zT{}A(?Ixpncid{}fpyF>%z@uZUOvyGEI^}QYLu)N@NIn0AF)%PmaGLzpM2+DYVm$y z6>qV4$6YV7c za=}j?swBmUooSFgQzUn0t5vN}n>k$fIJnK+Q|`=);>VtG@3_NfzD=theBdHBbCT?y zWIk(lrlHE*_O7bC!XpKXQ`zcC*#jTsW-8f;=}*eMtK16-yfxaM$LfsrBrWr>y^?+0 z=^WMB6T7%)cm@qErVdvrL`aPp)-JZ&UAgJz$n*1nb@iCe*|Ht#!>&H{S>V?%Z+P#T zx?Cb%MN*q%O@jpzp52itVcQg29Mspy znpQE|?G8PW;>7kT*>;~@_g=5|(0g{@*xg81mqmk&4N1I}&BsrhG;n6#vfjR`k-pde-T{H^m_NHyy-vUW5@S?x%~F?V=fv}S zGje>lkB0ER6j#n!P8w=VNPV@bxr@{e5X*|gJ}(n9Y%`Jj0yg6H(+%!{gr0vjJYI`Un8 zlK;Z2^vHpt^ec}8#6u5dx=M@{Pd*yn=Kx<;@a=Mo`BPX&cCY-iS^4efVL`>{7KNT?!~q?eEvi z?wxLF@O8I7{ngGPUNhLoQuW5bzAZbmi?_V_Y)bCRHFCh<N_n#Aef1lMEt5WJ zV%t|E;`4%crDWbWE!+9(OZ7ebvW#U9whX6aH+r910hu1<310)n%xJgT#LGM~rgQ`E~AAaAjjHmTAbzAN1n7ztW!&s{oIN-JA((~%zuQ{_S1A1Bwy%68z zB5UBIiH5$2GlRFreSe+jeB^iiLb2nv8ONA2gUa2!El=Kz4Bptb`%m7l*W|x8Ou;Tf z?o(PEx`R~kmi8;U(#xEoZAVvnX3Mmt=*j$V+85|9SU-W7gKn)juo6$9TQpMw#29p6 z!BdoIif**E>>y^N6hl>FHL?K(f7U1dKo*QMdx)v%qB7KscnvkR&6cQz@&?!u+0nIR zq7%_$Gr~L{PCSU(G(ADAL-(=1r4t!Zn}lK_*f#+@yDEtE=t6c+9kC1LAzdNHq9#tY z5hG9@+S|nM=$_45AMpyZHG8e)4zUg0C<+`S2BIe3e;}%&VF@h~$>>gO`7h!RR8KLM z^bB<@m_&MtLdNW*WHc*J_((LU^UsAyHs~Ib>~@kLx+7DpMY2Rs=FLcF(UVL^QU>w} zTIY|PAbVf)k$gV1^@s3o9 zq;ldN$ruf9>nBnHYV*z#$qL;%+Khu(g%O^uV$dMEY58jlWPzr@R318j`c<=?u10q?7TC8P7=Y}H(*~2Xa{nvw18$2AF?bVJ>>Yz64FPG{8o?w za`do*b|c4gR**WdkI?yGf;A+ATqszhZzh4GtRYo|snr@n-hBdZw*yQZHqdtDqSyvp z9I}Cw*DtIQPMy7gNWT|SLWtnP5|8Yn!_xK;FMMe)v=bpu?}e<8V=SU=zb%BkNCnQZ zg>;eQZx=vZvW27(Z36osQ{?Eo5897_;F=G9yAP5_F4*@&=E(8Tejo{$YWG7%$Td*U z2QwW2X#hn115g2SME&}80QdziKp1Ao5jgM*k%+d39FXe~d*}diRC0ijCussqIc02*!=i3WbChTRPNlW3S>X%C1&7*YJcUw6b{r2f+ij#Y6r`s)Hd zhased!O4e#nrY{CYPt(h^ItsU2;`K!4)M4{yr}a3eXkFLk)%?d+P%&z-$TO$N4rzf zlIjlBl#Q)Jy+93O_bo!L$6*oo`C)z!hzFsncmV20HIym^$AWl}1ZE)A(td`>?U~DlM>HQ0AZ)oVe%133|8}kkO>90@B+lNdI~Yy3*thE4G8gd zBZWBU1#zRTUJZfo&4K5}m%!VgM02g@CHiKZ&Q%8+w1v6 zHF;gVo8AdDOoRWjRGRd<5q@5H%^M6P5S_3OaLg3e^q~}v9$>lQMjwbD z%{kSRaw>fCzS@aC-6-_ zkcOMSkR;;K3{Zg0e2)-CV88cRR@mn#MYW+HK=LOkNU|TLdCCEirU~x!qZFn!gop7X z!XpVM2UB>Q`~h(dC5phM{*=zqfe?vv6ytAZu{^MU5XFw*Q4oUv3Kn)*!*ap4M8VI)ujbHcxs0cwGod=Hq8{y!;2$ijNdK?^1j}t}95^C$! zLjAV)fX5N|CQilc4(|@6OiAH^z*ZU~4mM)MZGkQQDdFD(RGI>KCJ>TFBh0^P!=VBO z+ZI6#W*3#F!#p@xm}Q@Z|qLGf*gi#P*;N#W-rg%UerA8?+GH|LZ;C1}HB#ToMX#qAhyW?Q!^d z@buk<{$FpZ;D@1<-otntm?<<__rT9&-8n&|_h?O@G4%wI90&h}!2kdLs^Y@n_~Xzv zw2MV;Zv9CMYML1<1_RoAr7E99lls$)z^g9REL=`vAhGiv__k55c#{pleyhQWkFD zt1f(4wQ&kjXdFimcg0e2F@zvCQwSmkv&4ZlFwn6*4iIVQDa6S+919b*CvY~x@Mf99 z(6tPT?06hS-#mgWub@GI*FKWqkrkXU+UL-GId&&~fg79BNYe`_7G;p8>w_hG&E4PpLgJ2 zF61xd$Vo^7jcavqE3Gd`n+=GIx)$vVr|`3+fQ6}6I7kx`5~A)GqHc4{U+|t}NEAVQ zk^!^e65YIu06{+x8DTJGNgGc8CGb#Gw5ND%_fOM+)FthW^6NZcvl$lgnT z!Lpa|+#7B37J+>m|ALXXrozUJ>pZC43Qr)Z6k`josP#W-tt(AhPr9r%?lJK#@lvdE1Qoy_zRj#hzq_C!>QHpdu zBH!FYA-+nZESXmjBGVv+_<8`(2mgp#PpJ4%9{mcKY#hK~rLMQvM>hCb;KC6QQ+>+1 z5O1arn8epI+P`QJj`%CC&I>d*%AHXfI+y=7e35q&(t3@sS#qYR;r~9`s24(=) zW4}?jEWZIS=F--u+l;uKk{&>-0`P>oi$8|PGbq!oOePS|!N5A%kRZJ60O%S4nUE;z zRM{6z12<1~5X@se%|HQu7nxRw97~-d0Q*CToaJRR#)=dKM+`j#+@XiW0@((kx2Z zzljh%SP)K0*q84hx+KM&E~2K?ysG}t?D)^ zE=^vFeI8x{8yp2zcIbLQ{Jk(u4%le|W7#SPI8`l;h;zeP8U$YW zTNZ&8HY=cv8Tphwk_H6H3g19>pzRh`EIWJ* zv|B%Dw>?xD9!~koMrR6vbHhd|3^diHQ()wE%J4mSefoJC+ZQ7Ofk^;VE8ZiWHDt})gegCv%e6JX9Q+=+Z9R{m`ebBdF(H^ zXbiweCqnxvFAMk7c94bwkaKM+XX5An66z{}M9|djd^#)F2Kec~L{Hu1Y|9(`bnwCw zVarBK95@4fkYAyO`O&e0wBvmQwqK)$dEx0?%D#toDS*eYuxmBgUtuYR2ykpE*d_sj zw-98j05u}I(GEIg0JfF=3kF{Cz^1aal*T}Md@I6Zr|>V2r2;Lb$D%oMV^H6!3Sv$M z72b?0M~8PJl2XWLL3!cTB3cHt`XGuM&jQ7eCIyZy2g_giNg~UCqk304K*h{AP;@)` z7D9Bk-XIFWu?g$0qHg@}1E}B=LsV|~fDaF?yCF@fsz^Wklb(2a4AgTxCkC^hioeul zgP#}v{B%85#BJkB;KKsAsjP-H;Bz&g|ARc=M2PeO6rx}?SPuwQK|-ichkDL9YJiax z1N!q`DjTijzxdCVLxL#()z#{r!(if*XZtq>PjE|z7zO%8(DHp%;8#ot$a)FrY1HAW z!YFgc&%V+TMFtm{WL5{6YHjo_~^);;?ARTWIWDD~0d2Q6?UWepu*5J3f@F#k1z^Vu6vP`rMwBSX*$a>^nvyF*=kA&U z@0z&5+KtLPzg-m809B&Ih7ya5KnaKb1_HrCdx)E1pS<-#s`{RANDg#Y8c-y3snjv; zfft*>{)kWnkr|dTAhMyw8TBEsWOk1==)OBZ_cfvtDmJASg5cOozyXkfQslUI?*_aH zK5k27|9_hRU$EyRTRq$KuNBXET+d;{JJ58b37VNC!DjN3r?;BCSrcC@LH(&TjH4O9&h#SC`m zOgBs+H^!UOH)J-$k`*9;J!+P{!X z&Fht=>LP9dS+TzXsi9t*$-xWFkO`t#;|dVJbR7}j0cRl>fOru(%G^STvarx3krw`Q zg;FB9TL2=~w}Fsg?-t4`B?Uo7`Zo};nbAU7R{TVe{Lu}B5w^TaSw9C{1qk$E0}(<; z9SCX~0rVF(00vm|8lV8z9Fb$+%3sKTDH=wQE*jYC2IzyIuRzSOP%C9--PH<^0^(mt zN-L#UUOfZr*?e;Eis?a_|G=Yf!NdOJOi}R4w~k zaD!hA-YQJu_%A5AHlWQ)egjq7u+xYjU78z+0L*-2y$$7Y4ymS0pu38IFQ`%3VS_Di zfCu6rCxthF_!S34Tnc`3gYpEHrX3LV!1f11G;F7I7FUEAd5!Sd;(P4Ja=N+S&+ zh@3YCiS2;6U<)4-E85S|5uD0qAZZBt(QmGQ*9J0y8$xP`Hys^7)9a|eY_N0!3P83Z zNAa``M4WPW1&}fXiO)ij+yF)*td&b5!Dq5bjPTFS^}-`BaYe@x^yW(71@)5+xg07% z4!EnGGCKWl0<}*Hs8AC8sgT4@8Ni^YjUp^(%l=_$J4-_AH8Q}gx&Vh({XZO~2o-qV zjvU`y`v+ZVB~fl2(cCr6+@16UZ5R*Qa35704&V4skOltJ2JR7JZ$VOs+H<#n+H(W{ zp!nPC%ZoZ5!k0%_3au=aD3C>(Q}l83b0K%2+Q4TK$5y9gelg5YKV zf^(Z7!RGHsBIxrd#JWm1pc3DaV69IiPS~#-;zFN))b4%OY7a^+vb_XC+4!r9vzbSE zMbX^?l=spjp*apv?fJmQ3H4U~{NlRa&r2i*^pQ21q|nJj{7;227!$CB1BZ>jsyJ;d zoZSPl!FvX Date: Mon, 12 Aug 2024 13:52:29 -0600 Subject: [PATCH 03/10] Add tests for sparse tensors. --- .../org/flag4j/arrays/sparse/CooCTensor.java | 4 +- .../org/flag4j/arrays/sparse/CooTensor.java | 5 +- .../ComplexSparseTensorElemBinOpsTests.java | 349 +++++++++ .../CooCTensorGetSetTests.java | 100 +++ .../sparse_tensor/CooTensorGetSetTests.java | 91 +++ .../CooTensorSpElemBinOpsTests.java | 704 ++++++++++++++++++ target/flag4j-v0.1.0-beta.jar | Bin 641004 -> 640987 bytes 7 files changed, 1249 insertions(+), 4 deletions(-) create mode 100644 src/test/java/org/flag4j/sparse_complex_tensor/ComplexSparseTensorElemBinOpsTests.java create mode 100644 src/test/java/org/flag4j/sparse_complex_tensor/CooCTensorGetSetTests.java create mode 100644 src/test/java/org/flag4j/sparse_tensor/CooTensorGetSetTests.java create mode 100644 src/test/java/org/flag4j/sparse_tensor/CooTensorSpElemBinOpsTests.java diff --git a/src/main/java/org/flag4j/arrays/sparse/CooCTensor.java b/src/main/java/org/flag4j/arrays/sparse/CooCTensor.java index c77591d24..bcd6e0497 100644 --- a/src/main/java/org/flag4j/arrays/sparse/CooCTensor.java +++ b/src/main/java/org/flag4j/arrays/sparse/CooCTensor.java @@ -231,7 +231,7 @@ public CooCTensor set(CNumber value, int...index) { // Copy old indices and insert new one. int[][] newIndices = new int[indices.length + 1][getRank()]; ArrayUtils.deepCopy(indices, newIndices); - newIndices[indices.length + 1] = index; + newIndices[indices.length] = index; // Copy old entries and insert new one. CNumber[] newEntries = Arrays.copyOf(entries, entries.length+1); @@ -674,7 +674,7 @@ public CooCTensor T() { */ @Override public CNumber get(int... indices) { - ParameterChecks.assertEquals(indices.length, getRank()); + ParameterChecks.assertValidIndex(shape, indices); for(int i = 0; i < nnz; i++) { if(Arrays.equals(this.indices[i], indices)) { diff --git a/src/main/java/org/flag4j/arrays/sparse/CooTensor.java b/src/main/java/org/flag4j/arrays/sparse/CooTensor.java index 02c25a9ff..3d9872e58 100644 --- a/src/main/java/org/flag4j/arrays/sparse/CooTensor.java +++ b/src/main/java/org/flag4j/arrays/sparse/CooTensor.java @@ -253,12 +253,13 @@ public CooTensor set(double value, int... index) { // Copy old indices and insert new one. int[][] newIndices = new int[indices.length + 1][getRank()]; ArrayUtils.deepCopy(indices, newIndices); - newIndices[indices.length + 1] = index; + newIndices[indices.length] = index; // Copy old entries and insert new one. double[] newEntries = Arrays.copyOf(entries, entries.length+1); newEntries[newEntries.length-1] = value; + // Ensure indices are sorted. dest = new CooTensor(shape, newEntries, newIndices); dest.sortIndices(); } @@ -658,7 +659,7 @@ public CooTensor T() { */ @Override public Double get(int... indices) { - ParameterChecks.assertEquals(indices.length, getRank()); + ParameterChecks.assertValidIndex(shape, indices); for(int i = 0; i < nnz; i++) { if(Arrays.equals(this.indices[i], indices)) { diff --git a/src/test/java/org/flag4j/sparse_complex_tensor/ComplexSparseTensorElemBinOpsTests.java b/src/test/java/org/flag4j/sparse_complex_tensor/ComplexSparseTensorElemBinOpsTests.java new file mode 100644 index 000000000..b5988ea93 --- /dev/null +++ b/src/test/java/org/flag4j/sparse_complex_tensor/ComplexSparseTensorElemBinOpsTests.java @@ -0,0 +1,349 @@ +package org.flag4j.sparse_complex_tensor; + +import org.flag4j.arrays.sparse.CooCTensor; +import org.flag4j.complex_numbers.CNumber; +import org.flag4j.core.Shape; +import org.flag4j.util.exceptions.LinearAlgebraException; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class ComplexSparseTensorElemBinOpsTests { + + CooCTensor A; + Shape aShape; + CNumber[] aEntries; + int[][] aIndices; + + CooCTensor B; + Shape bShape; + CNumber[] bEntries; + int[][] bIndices; + + CooCTensor exp; + Shape expShape; + CNumber[] expEntries; + int[][] expIndices; + + @Test + void elemMultTest() { + // ------------------------ Sub-case 1 ------------------------ + aShape = new Shape(3, 4, 5); + aEntries = new CNumber[]{new CNumber(0.3554027346190748, 0.17814806338585254), new CNumber(0.4679008020105414, 0.552234592711959), new CNumber(0.8023911579050015, 0.9369773311398271), new CNumber(0.5361245107886304, 0.8426048494330756), new CNumber(0.5116663669327101, 0.14226079103124079), new CNumber(0.6031886469745519, 0.5507006336519896), new CNumber(0.30173187058465345, 0.44768758628894023), new CNumber(0.47089846293340487, 0.12372049483112735), new CNumber(0.8332812297009098, 0.14164829949927782)}; + aIndices = new int[][]{ + {0, 1, 2}, + {0, 1, 4}, + {0, 2, 0}, + {0, 2, 2}, + {1, 2, 1}, + {1, 2, 3}, + {2, 0, 2}, + {2, 0, 4}, + {2, 3, 3}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + bShape = new Shape(3, 4, 5); + bEntries = new CNumber[]{new CNumber(0.641688013673216, 0.6529926214338411), new CNumber(0.2861597200166691, 0.7749988114606634), new CNumber(0.768889671662357, 0.9929463956356764), new CNumber(0.7183956240028645, 0.8537468523253172), new CNumber(0.027404474628255016, 0.4765076195110751), new CNumber(0.8646619116065113, 0.25569175902000085), new CNumber(0.8117289028941926, 0.050361733504989625), new CNumber(0.38088270679667247, 0.9284192721773488), new CNumber(0.724481029520081, 0.7172167668050126), new CNumber(0.38627225756249206, 0.9663366975684748), new CNumber(0.5492034964244268, 0.25026921484309506), new CNumber(0.7637541926826775, 0.3901141826226544), new CNumber(0.3099992969453177, 0.08109621445801574), new CNumber(0.6784683457632178, 0.9760264123930158), new CNumber(0.9404512577097293, 0.849340176282691), new CNumber(0.24859753416430375, 0.8897819832223416)}; + bIndices = new int[][]{ + {0, 1, 2}, + {0, 2, 0}, + {0, 2, 4}, + {1, 0, 1}, + {1, 1, 1}, + {1, 1, 2}, + {1, 1, 4}, + {1, 2, 0}, + {1, 2, 3}, + {1, 3, 3}, + {2, 0, 3}, + {2, 1, 2}, + {2, 1, 3}, + {2, 2, 3}, + {2, 3, 0}, + {2, 3, 1}}; + B = new CooCTensor(bShape, bEntries, bIndices); + + expShape = new Shape(3, 4, 5); + expEntries = new CNumber[]{new CNumber(0.11172830391805331, 0.34639084027746325), new CNumber(-0.49654428890900426, 0.8899773644438604), new CNumber(0.04202700400959636, 0.8315891731821327)}; + expIndices = new int[][]{ + {0, 1, 2}, + {0, 2, 0}, + {1, 2, 3}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + + assertEquals(exp, A.elemMult(B)); + + // ------------------------ Sub-case 2 ------------------------ + aShape = new Shape(3, 4, 5); + aEntries = new CNumber[]{new CNumber(0.8090733448617681, 0.4514905847217746), new CNumber(0.5139505427121954, 0.1480659883061629), new CNumber(0.5538830826585828, 0.39096787547155687), new CNumber(0.01148067313092116, 0.3414711394381831), new CNumber(0.8287843463670005, 0.09420330954836731), new CNumber(0.34229624969929295, 0.986859223440192), new CNumber(0.5049744445088055, 0.305164515526821), new CNumber(0.8313739736384473, 0.24290072013606512), new CNumber(0.5498472829959157, 0.8566546560473144)}; + aIndices = new int[][]{ + {0, 1, 0}, + {0, 1, 2}, + {0, 3, 4}, + {1, 0, 1}, + {1, 2, 1}, + {1, 3, 1}, + {1, 3, 2}, + {2, 2, 4}, + {2, 3, 0}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + bShape = new Shape(3, 4, 5); + bEntries = new CNumber[]{new CNumber(0.06894633766030189, 0.5338176684872393), new CNumber(0.5749573099425286, 0.6336906486388725), new CNumber(0.3153452897134157, 0.47285192243696095)}; + bIndices = new int[][]{ + {1, 2, 4}, + {2, 0, 1}, + {2, 2, 3}}; + B = new CooCTensor(bShape, bEntries, bIndices); + + expShape = new Shape(3, 4, 5); + expEntries = new CNumber[]{}; + expIndices = new int[][]{ + }; + exp = new CooCTensor(expShape, expEntries, expIndices); + + // ------------------------ Sub-case 3 ------------------------ + aShape = new Shape(3, 4, 1, 2); + A = new CooCTensor(aShape); + + bShape = new Shape(3, 4, 1, 2, 1); + B = new CooCTensor(bShape); + + assertThrows(LinearAlgebraException.class, ()->A.elemMult(B)); + + // ------------------------ Sub-case 4 ------------------------ + aShape = new Shape(3, 4, 1, 2); + A = new CooCTensor(aShape); + + bShape = new Shape(3, 12, 1, 2); + B = new CooCTensor(bShape); + + assertThrows(LinearAlgebraException.class, ()->A.elemMult(B)); + } + + + @Test + void addTests() { + aShape = new Shape(3, 4, 5); + aEntries = new CNumber[]{new CNumber(0.46213195128555784, 0.001797636584227047), new CNumber(0.46406207172042513, 0.5621122046310777), new CNumber(0.5725470068968052, 0.9700746820433621), new CNumber(0.9843102251516707, 0.2404706780804564), new CNumber(0.9860977087720486, 0.021269606309532563), new CNumber(0.7283075275461912, 0.10972824977304207), new CNumber(0.030709421345043286, 0.9359805400567995), new CNumber(0.8846542888774562, 0.08743530919856501), new CNumber(0.09825508993525567, 0.7679866718281502)}; + aIndices = new int[][]{ + {0, 1, 4}, + {0, 2, 0}, + {0, 2, 2}, + {0, 2, 3}, + {1, 0, 2}, + {1, 0, 3}, + {1, 3, 3}, + {1, 3, 4}, + {2, 0, 1}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + bShape = new Shape(3, 4, 5); + bEntries = new CNumber[]{new CNumber(0.4178929367564942, 0.2097901696665011), new CNumber(0.9428201725612915, 0.8603359879641461), new CNumber(0.5230084456156013, 0.044652376148752726)}; + bIndices = new int[][]{ + {1, 1, 4}, + {1, 3, 1}, + {1, 3, 4}}; + B = new CooCTensor(bShape, bEntries, bIndices); + + expShape = new Shape(3, 4, 5); + expEntries = new CNumber[]{new CNumber(0.46213195128555784, 0.001797636584227047), new CNumber(0.46406207172042513, 0.5621122046310777), new CNumber(0.5725470068968052, 0.9700746820433621), new CNumber(0.9843102251516707, 0.2404706780804564), new CNumber(0.9860977087720486, 0.021269606309532563), new CNumber(0.7283075275461912, 0.10972824977304207), new CNumber(0.4178929367564942, 0.2097901696665011), new CNumber(0.9428201725612915, 0.8603359879641461), new CNumber(0.030709421345043286, 0.9359805400567995), new CNumber(1.4076627344930577, 0.13208768534731774), new CNumber(0.09825508993525567, 0.7679866718281502)}; + expIndices = new int[][]{ + {0, 1, 4}, + {0, 2, 0}, + {0, 2, 2}, + {0, 2, 3}, + {1, 0, 2}, + {1, 0, 3}, + {1, 1, 4}, + {1, 3, 1}, + {1, 3, 3}, + {1, 3, 4}, + {2, 0, 1}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.add(B)); + + // ------------------------ Sub-case 2 ------------------------ + aShape = new Shape(3, 2, 1, 2, 3); + aEntries = new CNumber[]{new CNumber(0.6160738463715426, 0.1968914050559546), new CNumber(0.18076095086893407, 0.6136186390756889), new CNumber(0.772159908547494, 0.35655250177408504), new CNumber(0.4591634888667765, 0.6382625477088578), new CNumber(0.7179540532210842, 0.9920449208502049)}; + aIndices = new int[][]{ + {0, 0, 0, 1, 2}, + {0, 1, 0, 0, 0}, + {1, 0, 0, 0, 2}, + {1, 0, 0, 1, 0}, + {1, 0, 0, 1, 2}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + bShape = new Shape(3, 2, 1, 2, 3); + bEntries = new CNumber[]{new CNumber(0.763978006457422, 0.8959301015405149)}; + bIndices = new int[][]{ + {2, 0, 0, 1, 2}}; + B = new CooCTensor(bShape, bEntries, bIndices); + + expShape = new Shape(3, 2, 1, 2, 3); + expEntries = new CNumber[]{new CNumber(0.6160738463715426, 0.1968914050559546), new CNumber(0.18076095086893407, 0.6136186390756889), new CNumber(0.772159908547494, 0.35655250177408504), new CNumber(0.4591634888667765, 0.6382625477088578), new CNumber(0.7179540532210842, 0.9920449208502049), new CNumber(0.763978006457422, 0.8959301015405149)}; + expIndices = new int[][]{ + {0, 0, 0, 1, 2}, + {0, 1, 0, 0, 0}, + {1, 0, 0, 0, 2}, + {1, 0, 0, 1, 0}, + {1, 0, 0, 1, 2}, + {2, 0, 0, 1, 2}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.add(B)); + + // ------------------------ Sub-case 3 ------------------------ + aShape = new Shape(3, 4, 1, 2); + A = new CooCTensor(aShape); + + bShape = new Shape(3, 4, 1, 2, 1); + B = new CooCTensor(bShape); + + assertThrows(LinearAlgebraException.class, ()->A.add(B)); + + // ------------------------ Sub-case 4 ------------------------ + aShape = new Shape(3, 4, 1, 2); + A = new CooCTensor(aShape); + + bShape = new Shape(3, 12, 1, 2); + B = new CooCTensor(bShape); + + assertThrows(LinearAlgebraException.class, ()->A.add(B)); + } + + + @Test + void subTests() { + // ------------------------ Sub-case 1 ------------------------ + aShape = new Shape(3, 4, 5); + aEntries = new CNumber[]{new CNumber(0.17614198390401192, 0.9506050536197737), new CNumber(0.31444950275574934, 0.7698169544040158), new CNumber(0.6367546698696576, 0.41787425228492703), new CNumber(0.7815522736625252, 0.7719692133463149), new CNumber(0.2944302437797989, 0.9771280639457677), new CNumber(0.3918838885588891, 0.9684349409321966), new CNumber(0.7006607124763364, 0.693548623559356), new CNumber(0.6655396902912524, 0.5003215039870123), new CNumber(0.21520203030603913, 0.6556408883606212)}; + aIndices = new int[][]{ + {0, 0, 2}, + {0, 0, 4}, + {0, 3, 4}, + {1, 1, 2}, + {1, 1, 4}, + {1, 2, 1}, + {2, 1, 0}, + {2, 1, 3}, + {2, 3, 1}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + bShape = new Shape(3, 4, 5); + bEntries = new CNumber[]{new CNumber(0.6093967458567611, 0.7786077333918526), new CNumber(0.7447643624118477, 0.6813810317763505), new CNumber(0.12151981120621747, 0.8591037209429343)}; + bIndices = new int[][]{ + {1, 0, 2}, + {1, 2, 2}, + {2, 2, 3}}; + B = new CooCTensor(bShape, bEntries, bIndices); + + expShape = new Shape(3, 4, 5); + expEntries = new CNumber[]{new CNumber(0.17614198390401192, 0.9506050536197737), new CNumber(0.31444950275574934, 0.7698169544040158), new CNumber(0.6367546698696576, 0.41787425228492703), new CNumber(-0.6093967458567611, -0.7786077333918526), new CNumber(0.7815522736625252, 0.7719692133463149), new CNumber(0.2944302437797989, 0.9771280639457677), new CNumber(0.3918838885588891, 0.9684349409321966), new CNumber(-0.7447643624118477, -0.6813810317763505), new CNumber(0.7006607124763364, 0.693548623559356), new CNumber(0.6655396902912524, 0.5003215039870123), new CNumber(-0.12151981120621747, -0.8591037209429343), new CNumber(0.21520203030603913, 0.6556408883606212)}; + expIndices = new int[][]{ + {0, 0, 2}, + {0, 0, 4}, + {0, 3, 4}, + {1, 0, 2}, + {1, 1, 2}, + {1, 1, 4}, + {1, 2, 1}, + {1, 2, 2}, + {2, 1, 0}, + {2, 1, 3}, + {2, 2, 3}, + {2, 3, 1}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.sub(B)); + + // ------------------------ Sub-case 2 ------------------------ + aShape = new Shape(3, 4, 2, 1, 5); + aEntries = new CNumber[]{new CNumber(0.03099867357042463, 0.16406141241826533), + new CNumber(0.40025480480395215, 0.3573176589499272), + new CNumber(0.5829756217789057, 0.4565973342942867), + new CNumber(0.7547388953906143, 0.07578782068550338), + new CNumber(0.7641536538894649, 0.47648315038565714), + new CNumber(0.21477832989403312, 0.8465035759034767), + new CNumber(0.08855744900763618, 0.5455018436675453), + new CNumber(0.26992640122762657, 0.03869668362006762), + new CNumber(0.20360217842311057, 0.7965727538938915), + new CNumber(0.194673963657913, 0.0009715427968347568), + new CNumber(0.37937000326996617, 0.4216812678687796), + new CNumber(0.5731671837653347, 0.7676951841845797), + new CNumber(0.08121898085530821, 0.1787417726037127), + new CNumber(0.33182392659238336, 0.6266462602129336), + new CNumber(0.5777169151653782, 0.8267276078397521), + new CNumber(0.6983057129995509, 0.3050526193484504), + new CNumber(0.9457803294130197, 0.4347251210252875), + new CNumber(0.9151417933380515, 0.1816520611532081)}; + aIndices = new int[][]{ + {0, 0, 1, 0, 3}, + {0, 2, 0, 0, 1}, + {0, 3, 0, 0, 2}, + {0, 3, 1, 0, 0}, + {0, 3, 1, 0, 1}, + {1, 0, 0, 0, 1}, + {1, 1, 0, 0, 2}, + {1, 1, 1, 0, 4}, + {1, 2, 0, 0, 3}, + {1, 2, 1, 0, 4}, + {2, 0, 0, 0, 3}, + {2, 0, 1, 0, 2}, + {2, 0, 1, 0, 3}, + {2, 1, 0, 0, 4}, + {2, 1, 1, 0, 0}, + {2, 2, 0, 0, 4}, + {2, 3, 0, 0, 0}, + {2, 3, 1, 0, 0}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + bShape = new Shape(3, 4, 2, 1, 5); + bEntries = new CNumber[]{new CNumber(0.9786839486132947, 0.009654575491062634)}; + bIndices = new int[][]{ + {2, 2, 1, 0, 4}}; + B = new CooCTensor(bShape, bEntries, bIndices); + + expShape = new Shape(3, 4, 2, 1, 5); + expEntries = new CNumber[]{new CNumber(0.03099867357042463, 0.16406141241826533), new CNumber(0.40025480480395215, 0.3573176589499272), new CNumber(0.5829756217789057, 0.4565973342942867), new CNumber(0.7547388953906143, 0.07578782068550338), new CNumber(0.7641536538894649, 0.47648315038565714), new CNumber(0.21477832989403312, 0.8465035759034767), new CNumber(0.08855744900763618, 0.5455018436675453), new CNumber(0.26992640122762657, 0.03869668362006762), new CNumber(0.20360217842311057, 0.7965727538938915), new CNumber(0.194673963657913, 0.0009715427968347568), new CNumber(0.37937000326996617, 0.4216812678687796), new CNumber(0.5731671837653347, 0.7676951841845797), new CNumber(0.08121898085530821, 0.1787417726037127), new CNumber(0.33182392659238336, 0.6266462602129336), new CNumber(0.5777169151653782, 0.8267276078397521), new CNumber(0.6983057129995509, 0.3050526193484504), new CNumber(-0.9786839486132947, -0.009654575491062634), new CNumber(0.9457803294130197, 0.4347251210252875), new CNumber(0.9151417933380515, 0.1816520611532081)}; + expIndices = new int[][]{ + {0, 0, 1, 0, 3}, + {0, 2, 0, 0, 1}, + {0, 3, 0, 0, 2}, + {0, 3, 1, 0, 0}, + {0, 3, 1, 0, 1}, + {1, 0, 0, 0, 1}, + {1, 1, 0, 0, 2}, + {1, 1, 1, 0, 4}, + {1, 2, 0, 0, 3}, + {1, 2, 1, 0, 4}, + {2, 0, 0, 0, 3}, + {2, 0, 1, 0, 2}, + {2, 0, 1, 0, 3}, + {2, 1, 0, 0, 4}, + {2, 1, 1, 0, 0}, + {2, 2, 0, 0, 4}, + {2, 2, 1, 0, 4}, + {2, 3, 0, 0, 0}, + {2, 3, 1, 0, 0}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.sub(B)); + + // ------------------------ Sub-case 3 ------------------------ + aShape = new Shape(3, 4, 1, 2); + A = new CooCTensor(aShape); + + bShape = new Shape(3, 4, 1, 2, 1); + B = new CooCTensor(bShape); + + assertThrows(LinearAlgebraException.class, ()->A.sub(B)); + + // ------------------------ Sub-case 4 ------------------------ + aShape = new Shape(3, 4, 1, 2); + A = new CooCTensor(aShape); + + bShape = new Shape(3, 12, 1, 2); + B = new CooCTensor(bShape); + + assertThrows(LinearAlgebraException.class, ()->A.sub(B)); + } +} diff --git a/src/test/java/org/flag4j/sparse_complex_tensor/CooCTensorGetSetTests.java b/src/test/java/org/flag4j/sparse_complex_tensor/CooCTensorGetSetTests.java new file mode 100644 index 000000000..5c6e6bfb8 --- /dev/null +++ b/src/test/java/org/flag4j/sparse_complex_tensor/CooCTensorGetSetTests.java @@ -0,0 +1,100 @@ +package org.flag4j.sparse_complex_tensor; + +import org.flag4j.arrays.sparse.CooCTensor; +import org.flag4j.complex_numbers.CNumber; +import org.flag4j.core.Shape; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class CooCTensorGetSetTests { + static CooCTensor A; + static Shape aShape; + static CNumber[] aEntries; + static int[][] aIndices; + + static CooCTensor exp; + static Shape expShape; + static CNumber[] expEntries; + static int[][] expIndices; + + + @Test + void cooTensorSetTest() { + aShape = new Shape(3, 4, 5, 1); + aEntries = new CNumber[]{ + new CNumber(1, 2), new CNumber(0.2324, -239.1), + new CNumber(5.1), new CNumber(0, 18.2)}; + aIndices = new int[][]{{0, 1, 0, 0}, {1, 2, 0, 0}, {2, 3, 2, 0}, {2, 3, 4, 1}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + // --------------- Sub-case 1 --------------- + expShape = new Shape(3, 4, 5, 1); + expEntries = new CNumber[]{ + new CNumber(1, 2), new CNumber(2.41, -23.23), + new CNumber(5.1), new CNumber(0, 18.2)}; + expIndices = new int[][]{{0, 1, 0, 0}, {1, 2, 0, 0}, {2, 3, 2, 0}, {2, 3, 4, 1}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + + assertEquals(exp, A.set(new CNumber(2.41, -23.23), 1, 2, 0, 0)); + + // --------------- Sub-case 2 --------------- + expShape = new Shape(3, 4, 5, 1); + expEntries = new CNumber[]{ + new CNumber(1, 2), new CNumber(0.2324, -239.1), new CNumber(0, -9.2), + new CNumber(5.1), new CNumber(0, 18.2)}; + expIndices = new int[][]{{0, 1, 0, 0}, {1, 2, 0, 0}, {1, 2, 4, 0}, {2, 3, 2, 0}, {2, 3, 4, 1}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + + assertEquals(exp, A.set(new CNumber(0, -9.2), 1, 2, 4, 0)); + + // --------------- Sub-case 3 --------------- + expShape = new Shape(3, 4, 5, 1); + expEntries = new CNumber[]{ + new CNumber(0.001), new CNumber(1, 2), new CNumber(0.2324, -239.1), + new CNumber(5.1), new CNumber(0, 18.2)}; + expIndices = new int[][]{{0, 0, 0, 0}, {0, 1, 0, 0}, {1, 2, 0, 0}, {2, 3, 2, 0}, {2, 3, 4, 1}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + + assertEquals(exp, A.set(0.001, 0, 0, 0, 0)); + + // --------------- Sub-case 4 --------------- + assertThrows(IndexOutOfBoundsException.class, () -> A.set(5, -1, 0, 0, 0)); + assertThrows(IndexOutOfBoundsException.class, () -> A.set(5, 0, 0, 0)); + assertThrows(IndexOutOfBoundsException.class, () -> A.set(5, 0, 0, 0, 0, 0)); + assertThrows(IndexOutOfBoundsException.class, () -> A.set(5, 1, 2, 5, 0)); + } + + + @Test + void cooTensorGetTest() { + aShape = new Shape(3, 4, 5, 1); + aEntries = new CNumber[]{ + new CNumber(1, 2), new CNumber(0.2324, -239.1), + new CNumber(5.1), new CNumber(0, 18.2)}; + aIndices = new int[][]{{0, 1, 0, 0}, {1, 2, 0, 0}, {2, 3, 2, 0}, {2, 3, 4, 1}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + // --------------- Sub-case 1 --------------- + assertEquals(new CNumber(0.2324, -239.1), A.get(1, 2, 0, 0)); + + // --------------- Sub-case 2 --------------- + assertEquals(CNumber.ZERO, A.get(1, 2, 4, 0)); + + // --------------- Sub-case 3 --------------- + assertEquals(CNumber.ZERO, A.get(0, 0, 0, 0)); + + // --------------- Sub-case 4 --------------- + assertEquals(new CNumber(1, 2), A.get(0, 1, 0, 0)); + + // --------------- Sub-case 5 --------------- + assertEquals(new CNumber(5.1), A.get(2, 3, 2, 0)); + + // --------------- Sub-case 6 --------------- + assertThrows(IndexOutOfBoundsException.class, () -> A.get(-1, 0, 0, 0)); + assertThrows(IndexOutOfBoundsException.class, () -> A.get(0, 0, 0)); + assertThrows(IndexOutOfBoundsException.class, () -> A.get(0, 0, 0, 0, 0)); + assertThrows(IndexOutOfBoundsException.class, () -> A.get(1, 2, 5, 0)); + } +} diff --git a/src/test/java/org/flag4j/sparse_tensor/CooTensorGetSetTests.java b/src/test/java/org/flag4j/sparse_tensor/CooTensorGetSetTests.java new file mode 100644 index 000000000..41d1e5205 --- /dev/null +++ b/src/test/java/org/flag4j/sparse_tensor/CooTensorGetSetTests.java @@ -0,0 +1,91 @@ +package org.flag4j.sparse_tensor; + +import org.flag4j.arrays.sparse.CooTensor; +import org.flag4j.core.Shape; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class CooTensorGetSetTests { + static CooTensor A; + static Shape aShape; + static double[] aEntries; + static int[][] aIndices; + + static CooTensor exp; + static Shape expShape; + static double[] expEntries; + static int[][] expIndices; + + static double expScalar; + + + @Test + void cooTensorSetTest() { + aShape = new Shape(3, 4, 5, 1); + aEntries = new double[]{1, 223.1333, -0.991233, 100.1234}; + aIndices = new int[][]{{0, 1, 0, 0}, {1, 2, 0, 0}, {2, 3, 2, 0}, {2, 3, 4, 1}}; + A = new CooTensor(aShape, aEntries, aIndices); + + // --------------- Sub-case 1 --------------- + expShape = new Shape(3, 4, 5, 1); + expEntries = new double[]{1, -451.2, -0.991233, 100.1234}; + expIndices = new int[][]{{0, 1, 0, 0}, {1, 2, 0, 0}, {2, 3, 2, 0}, {2, 3, 4, 1}}; + exp = new CooTensor(expShape, expEntries, expIndices); + + assertEquals(exp, A.set(-451.2, 1, 2, 0, 0)); + + // --------------- Sub-case 2 --------------- + expShape = new Shape(3, 4, 5, 1); + expEntries = new double[]{1, 223.1333, 32.1, -0.991233, 100.1234}; + expIndices = new int[][]{{0, 1, 0, 0}, {1, 2, 0, 0}, {1, 2, 4, 0}, {2, 3, 2, 0}, {2, 3, 4, 1}}; + exp = new CooTensor(expShape, expEntries, expIndices); + + assertEquals(exp, A.set(32.1, 1, 2, 4, 0)); + + // --------------- Sub-case 3 --------------- + expShape = new Shape(3, 4, 5, 1); + expEntries = new double[]{0.001, 1, 223.1333, -0.991233, 100.1234}; + expIndices = new int[][]{{0, 0, 0, 0}, {0, 1, 0, 0}, {1, 2, 0, 0}, {2, 3, 2, 0}, {2, 3, 4, 1}}; + exp = new CooTensor(expShape, expEntries, expIndices); + + assertEquals(exp, A.set(0.001, 0, 0, 0, 0)); + + // --------------- Sub-case 4 --------------- + assertThrows(IndexOutOfBoundsException.class, () -> A.set(5, -1, 0, 0, 0)); + assertThrows(IndexOutOfBoundsException.class, () -> A.set(5, 0, 0, 0)); + assertThrows(IndexOutOfBoundsException.class, () -> A.set(5, 0, 0, 0, 0, 0)); + assertThrows(IndexOutOfBoundsException.class, () -> A.set(5, 1, 2, 5, 0)); + } + + + @Test + void cooTensorGetTest() { + aShape = new Shape(3, 4, 5, 1); + aEntries = new double[]{1, 223.1333, -0.991233, 100.1234}; + aIndices = new int[][]{{0, 1, 0, 0}, {1, 2, 0, 0}, {2, 3, 2, 0}, {2, 3, 4, 1}}; + A = new CooTensor(aShape, aEntries, aIndices); + + // --------------- Sub-case 1 --------------- + assertEquals(223.1333, A.get(1, 2, 0, 0)); + + // --------------- Sub-case 2 --------------- + assertEquals(0, A.get(1, 2, 4, 0)); + + // --------------- Sub-case 3 --------------- + assertEquals(0, A.get(0, 0, 0, 0)); + + // --------------- Sub-case 4 --------------- + assertEquals(1, A.get(0, 1, 0, 0)); + + // --------------- Sub-case 5 --------------- + assertEquals(-0.991233, A.get(2, 3, 2, 0)); + + // --------------- Sub-case 6 --------------- + assertThrows(IndexOutOfBoundsException.class, () -> A.get(-1, 0, 0, 0)); + assertThrows(IndexOutOfBoundsException.class, () -> A.get(0, 0, 0)); + assertThrows(IndexOutOfBoundsException.class, () -> A.get(0, 0, 0, 0, 0)); + assertThrows(IndexOutOfBoundsException.class, () -> A.get(1, 2, 5, 0)); + } +} diff --git a/src/test/java/org/flag4j/sparse_tensor/CooTensorSpElemBinOpsTests.java b/src/test/java/org/flag4j/sparse_tensor/CooTensorSpElemBinOpsTests.java new file mode 100644 index 000000000..fe6ec3b5a --- /dev/null +++ b/src/test/java/org/flag4j/sparse_tensor/CooTensorSpElemBinOpsTests.java @@ -0,0 +1,704 @@ +package org.flag4j.sparse_tensor; + +import org.flag4j.arrays.sparse.CooTensor; +import org.flag4j.core.Shape; +import org.flag4j.util.exceptions.LinearAlgebraException; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class CooTensorSpElemBinOpsTests { + + CooTensor A; + Shape aShape; + double[] aEntries; + int[][] aIndices; + + CooTensor B; + Shape bShape; + double[] bEntries; + int[][] bIndices; + + CooTensor exp; + Shape expShape; + double[] expEntries; + int[][] expIndices; + + @Test + void elemMultTest() { + // ------------------------ Sub-case 1 ------------------------ + aShape = new Shape(3, 4, 1, 2); + aEntries = new double[]{-0.16684361210076226, -0.5052399843372454, -1.1124588299404807, -0.022660648601335445}; + aIndices = new int[][]{ + {0, 1, 0, 1}, + {0, 2, 0, 0}, + {0, 2, 0, 1}, + {1, 0, 0, 0}}; + A = new CooTensor(aShape, aEntries, aIndices); + + bShape = new Shape(3, 4, 1, 2); + bEntries = new double[]{1.4418647728434826, 2.0726552515293313, -0.3569517918248444, 0.9715372108728183, -0.5988716850281584, 0.7384018809658556}; + bIndices = new int[][]{ + {0, 1, 0, 0}, + {0, 2, 0, 1}, + {1, 0, 0, 0}, + {1, 1, 0, 0}, + {1, 2, 0, 1}, + {2, 3, 0, 1}}; + B = new CooTensor(bShape, bEntries, bIndices); + + expShape = new Shape(3, 4, 1, 2); + expEntries = new double[]{-2.3057436359863126, 0.00808875912215984}; + expIndices = new int[][]{ + {0, 2, 0, 1}, + {1, 0, 0, 0}}; + exp = new CooTensor(expShape, expEntries, expIndices); + + assertEquals(exp, A.elemMult(B)); + + // ------------------------ Sub-case 2 ------------------------ + aShape = new Shape(3, 4, 1, 2); + aEntries = new double[]{1.620948207485194, -0.6318752045782683}; + aIndices = new int[][]{ + {0, 3, 0, 1}, + {2, 1, 0, 0}}; + A = new CooTensor(aShape, aEntries, aIndices); + + bShape = new Shape(3, 4, 1, 2); + bEntries = new double[]{0.2971890286543011}; + bIndices = new int[][]{ + {2, 2, 0, 1}}; + B = new CooTensor(bShape, bEntries, bIndices); + + expShape = new Shape(3, 4, 1, 2); + expEntries = new double[]{}; + expIndices = new int[][]{ + }; + exp = new CooTensor(expShape, expEntries, expIndices); + + assertEquals(exp, A.elemMult(B)); + + // ------------------------ Sub-case 3 ------------------------ + aShape = new Shape(3, 4, 1, 2); + A = new CooTensor(aShape); + + bShape = new Shape(3, 4, 1, 2, 1); + B = new CooTensor(bShape); + + assertThrows(LinearAlgebraException.class, ()->A.elemMult(B)); + + // ------------------------ Sub-case 4 ------------------------ + aShape = new Shape(3, 4, 1, 2); + A = new CooTensor(aShape); + + bShape = new Shape(3, 12, 1, 2); + B = new CooTensor(bShape); + + assertThrows(LinearAlgebraException.class, ()->A.elemMult(B)); + } + + + @Test + void addTest() { + // ------------------------------ sub-case 1 ------------------------------ + aShape = new Shape(3, 4, 6, 1, 5); + aEntries = new double[]{0.21271988542678913, 0.4910515378490831, -0.24639003895647324, 0.06641088749813011, 0.16500346832399831, -0.712196883239192, -0.9027269554225115, 0.5302886660113901, 0.0554796776957832, -1.069050745498048, 1.635492834799256, -0.24852013364240885, 2.3628236961279203, -0.15743529013594634, 0.03331901921129941, -1.262779235757704, -1.722636484760481, -0.15095034333007482, -0.23551692651137207, 0.703144233399921, -0.32415584931390173, 0.4690748702304838, 0.5878363790342139, 1.5120735176478024, -0.5363142790993337, 1.1089772351757516, -1.2364658717672565, -0.12980209770875445, 1.1384712325644109, -1.9666222600660057, 0.3303069965746997, -0.3087781084499124, 0.6644884845502304, 0.25983980776189985, -1.682467890553107, -1.039639118211318, 0.980396784918533, -0.33855547201752695, 0.8130472164219463, 0.11574933668073632, 0.4876965002122167, -0.4099683710072427, 0.27379575847214693, 0.07234280566759424, 0.7415165524784838, 1.1139497969769019, -0.6981164442443558, 0.7082474745518845, 0.6928676615023016, 0.19023223795392719, -0.7004333004673201, 1.3768256284398517, 0.1468548398333117, 0.8733236418909152, 0.311778156088708, -1.1656713775090164, -0.19921128583708514, 1.1728712714013305, 0.027399683603257403, 0.6620043229328887, -0.39492787055113454, -0.5550301570279559, 0.6638581241381123, 0.10899495829142322, -0.7947932192969646, 0.8877649747228633, -2.510241251220681, 0.5594096043704835, -2.6156284691224867, 0.03836071433776447, 0.5014356687803425}; + aIndices = new int[][]{ + {0, 0, 0, 0, 1}, + {0, 0, 1, 0, 2}, + {0, 0, 1, 0, 4}, + {0, 0, 2, 0, 1}, + {0, 0, 2, 0, 3}, + {0, 0, 2, 0, 4}, + {0, 0, 3, 0, 0}, + {0, 0, 4, 0, 4}, + {0, 0, 5, 0, 0}, + {0, 1, 0, 0, 0}, + {0, 1, 2, 0, 1}, + {0, 1, 3, 0, 0}, + {0, 1, 5, 0, 0}, + {0, 1, 5, 0, 1}, + {0, 1, 5, 0, 2}, + {0, 1, 5, 0, 3}, + {0, 2, 0, 0, 4}, + {0, 2, 2, 0, 3}, + {0, 2, 3, 0, 0}, + {0, 2, 3, 0, 2}, + {0, 2, 4, 0, 0}, + {0, 2, 4, 0, 4}, + {0, 2, 5, 0, 2}, + {0, 3, 2, 0, 2}, + {0, 3, 2, 0, 3}, + {0, 3, 2, 0, 4}, + {0, 3, 4, 0, 1}, + {0, 3, 4, 0, 3}, + {0, 3, 5, 0, 4}, + {1, 0, 0, 0, 3}, + {1, 0, 1, 0, 1}, + {1, 0, 2, 0, 2}, + {1, 0, 3, 0, 0}, + {1, 0, 4, 0, 0}, + {1, 0, 5, 0, 1}, + {1, 1, 0, 0, 4}, + {1, 1, 1, 0, 4}, + {1, 1, 3, 0, 0}, + {1, 1, 3, 0, 1}, + {1, 1, 4, 0, 0}, + {1, 2, 2, 0, 1}, + {1, 2, 4, 0, 3}, + {1, 2, 5, 0, 3}, + {1, 3, 0, 0, 3}, + {1, 3, 2, 0, 0}, + {1, 3, 3, 0, 4}, + {1, 3, 5, 0, 3}, + {1, 3, 5, 0, 4}, + {2, 0, 1, 0, 4}, + {2, 0, 3, 0, 1}, + {2, 0, 5, 0, 4}, + {2, 1, 0, 0, 2}, + {2, 1, 0, 0, 3}, + {2, 1, 2, 0, 2}, + {2, 1, 2, 0, 3}, + {2, 1, 3, 0, 1}, + {2, 1, 4, 0, 4}, + {2, 2, 2, 0, 2}, + {2, 2, 2, 0, 3}, + {2, 2, 3, 0, 2}, + {2, 2, 3, 0, 3}, + {2, 2, 4, 0, 3}, + {2, 2, 5, 0, 1}, + {2, 2, 5, 0, 3}, + {2, 3, 1, 0, 1}, + {2, 3, 1, 0, 2}, + {2, 3, 1, 0, 4}, + {2, 3, 3, 0, 0}, + {2, 3, 3, 0, 3}, + {2, 3, 5, 0, 0}, + {2, 3, 5, 0, 3}}; + A = new CooTensor(aShape, aEntries, aIndices); + + bShape = new Shape(3, 4, 6, 1, 5); + bEntries = new double[]{0.4452122047056537, -0.9497516327600265, -1.9156122460622127, -0.6996728596976195, -1.3149595445441993, -0.35720080890725536, -1.2680188421281426, -0.43664074764597705, -0.021663210187867588, 0.5080293933893716, -0.7721970069128593, -0.40397112092278037, 0.09861035580802854, 2.145762790156657, 0.24972799251636188, -1.184346275948209, 0.5332680892301638, 1.085408338164909, -0.4663489646956424, -0.47930029680790354, -0.032101578354987774, -1.467964504073855, 0.019880407810883963, 0.1092198472073466, 0.40615922039703517, -0.8907742091410573, 0.5221931312466919, -1.2449681251500704, 0.4767871798521082, 0.2847869484063784, 0.5934528169521122, -1.6018108726064841, -1.006753177962152, 0.4234447816878154, 0.572648996383347, 0.5458070374666198, 0.20751519786275413, 1.4819111731736458, -0.4215273977053324, 0.8276204939779518, -0.8970190235235809, -0.4089956174814017, 3.8447900599566767, -1.3982918189227995, 2.7497232877428877, -1.2373906111872148, 1.423393056780044, -0.8997150090269198, -0.8133241165221952, -1.0321980382185065, 0.6138808599258287, -0.3475095765449233, 1.3206130398073723, -1.052441576735374, 0.26150935284677895, -0.5175704694289492, -1.4640719753541447, -2.2976846611324517, -2.324671711561876, -0.7695128098063991, 0.48907014821949163, 1.422228853385413, -1.4924747118888395, 0.10619881860235283, -0.5745319938512158, -0.564071153032398, -0.652495907584853, -0.14382771421924054, -0.508776368080984, 1.0473388351981363, -1.5396488960146058, 1.8906564665466268, 0.7115464810691853, -0.8896885613701434, 0.8798999211414029, 0.3321858676642957, -0.1980261328270126, -0.02518325887305506, 1.1736942761981215, 0.32129422945581415, -0.3274779852727927, 0.843815572813266, 0.9483380972743869, 0.9162331442087179, -0.784511096372904, -1.1502552471011351, 0.14875876866843532, 1.0703050467008823, 0.5504978899417385, -0.5182332569532772}; + bIndices = new int[][]{ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1}, + {0, 0, 0, 0, 4}, + {0, 0, 1, 0, 3}, + {0, 0, 1, 0, 4}, + {0, 0, 2, 0, 1}, + {0, 0, 2, 0, 2}, + {0, 0, 2, 0, 4}, + {0, 0, 3, 0, 2}, + {0, 0, 4, 0, 4}, + {0, 0, 5, 0, 0}, + {0, 1, 0, 0, 0}, + {0, 1, 1, 0, 1}, + {0, 1, 1, 0, 2}, + {0, 1, 1, 0, 3}, + {0, 1, 2, 0, 2}, + {0, 1, 3, 0, 0}, + {0, 1, 4, 0, 4}, + {0, 1, 5, 0, 4}, + {0, 2, 0, 0, 1}, + {0, 2, 1, 0, 0}, + {0, 2, 1, 0, 3}, + {0, 2, 2, 0, 1}, + {0, 2, 2, 0, 2}, + {0, 2, 2, 0, 4}, + {0, 2, 4, 0, 2}, + {0, 2, 4, 0, 3}, + {0, 3, 0, 0, 1}, + {0, 3, 1, 0, 2}, + {0, 3, 4, 0, 0}, + {0, 3, 4, 0, 4}, + {0, 3, 5, 0, 0}, + {1, 0, 0, 0, 0}, + {1, 0, 0, 0, 3}, + {1, 0, 1, 0, 4}, + {1, 0, 2, 0, 2}, + {1, 0, 3, 0, 0}, + {1, 0, 3, 0, 2}, + {1, 0, 3, 0, 4}, + {1, 0, 4, 0, 0}, + {1, 0, 4, 0, 1}, + {1, 1, 0, 0, 1}, + {1, 1, 0, 0, 4}, + {1, 1, 1, 0, 4}, + {1, 1, 2, 0, 0}, + {1, 1, 3, 0, 4}, + {1, 1, 5, 0, 1}, + {1, 1, 5, 0, 4}, + {1, 2, 0, 0, 4}, + {1, 2, 1, 0, 1}, + {1, 2, 2, 0, 4}, + {1, 2, 3, 0, 3}, + {1, 2, 3, 0, 4}, + {1, 2, 4, 0, 0}, + {1, 3, 1, 0, 0}, + {1, 3, 2, 0, 3}, + {1, 3, 4, 0, 1}, + {1, 3, 5, 0, 3}, + {2, 0, 0, 0, 0}, + {2, 0, 0, 0, 2}, + {2, 0, 1, 0, 2}, + {2, 0, 1, 0, 3}, + {2, 0, 2, 0, 2}, + {2, 0, 3, 0, 4}, + {2, 0, 4, 0, 2}, + {2, 1, 0, 0, 3}, + {2, 1, 1, 0, 0}, + {2, 1, 1, 0, 4}, + {2, 1, 2, 0, 3}, + {2, 1, 2, 0, 4}, + {2, 1, 3, 0, 3}, + {2, 1, 4, 0, 2}, + {2, 1, 4, 0, 4}, + {2, 2, 0, 0, 0}, + {2, 2, 0, 0, 4}, + {2, 2, 1, 0, 1}, + {2, 2, 1, 0, 4}, + {2, 2, 2, 0, 1}, + {2, 2, 2, 0, 3}, + {2, 2, 2, 0, 4}, + {2, 2, 4, 0, 3}, + {2, 2, 5, 0, 1}, + {2, 2, 5, 0, 3}, + {2, 2, 5, 0, 4}, + {2, 3, 0, 0, 0}, + {2, 3, 0, 0, 4}, + {2, 3, 2, 0, 1}, + {2, 3, 3, 0, 2}, + {2, 3, 3, 0, 3}, + {2, 3, 4, 0, 4}}; + B = new CooTensor(bShape, bEntries, bIndices); + + expShape = new Shape(3, 4, 6, 1, 5); + expEntries = new double[]{0.4452122047056537, -0.7370317473332374, -1.9156122460622127, 0.4910515378490831, -0.6996728596976195, -1.5613495835006725, -0.29078992140912524, -1.2680188421281426, 0.16500346832399831, -1.1488376308851689, -0.9027269554225115, -0.021663210187867588, 1.0383180594007617, -0.7167173292170761, -1.4730218664208283, 0.09861035580802854, 2.145762790156657, 0.24972799251636188, 1.635492834799256, -1.184346275948209, 0.2847479555877549, 1.085408338164909, 2.3628236961279203, -0.15743529013594634, 0.03331901921129941, -1.262779235757704, -0.4663489646956424, -0.47930029680790354, -1.722636484760481, -0.032101578354987774, -1.467964504073855, 0.019880407810883963, 0.1092198472073466, -0.15095034333007482, 0.40615922039703517, -0.23551692651137207, 0.703144233399921, -0.32415584931390173, -0.8907742091410573, 0.5221931312466919, 0.4690748702304838, 0.5878363790342139, -1.2449681251500704, 0.4767871798521082, 1.5120735176478024, -0.5363142790993337, 1.1089772351757516, 0.2847869484063784, -1.2364658717672565, -0.12980209770875445, 0.5934528169521122, -1.6018108726064841, 1.1384712325644109, -1.006753177962152, -1.5431774783781904, 0.3303069965746997, 0.572648996383347, 0.23702892901670747, 0.8720036824129844, 1.4819111731736458, -0.4215273977053324, 1.0874603017398516, -0.8970190235235809, -1.682467890553107, -0.4089956174814017, 2.8051509417453584, -0.41789503400426653, 2.7497232877428877, -0.33855547201752695, 0.8130472164219463, -1.2373906111872148, 0.11574933668073632, 1.423393056780044, -0.8997150090269198, -0.8133241165221952, -1.0321980382185065, 0.4876965002122167, 0.6138808599258287, -0.3475095765449233, 1.3206130398073723, -1.052441576735374, -0.4099683710072427, 0.27379575847214693, 0.07234280566759424, 0.26150935284677895, 0.7415165524784838, -0.5175704694289492, 1.1139497969769019, -1.4640719753541447, -2.9958011053768074, 0.7082474745518845, -2.324671711561876, -0.7695128098063991, 0.48907014821949163, 1.422228853385413, 0.6928676615023016, -1.4924747118888395, 0.19023223795392719, 0.10619881860235283, -0.5745319938512158, -0.7004333004673201, 1.3768256284398517, -0.41721631319908625, -0.652495907584853, -0.14382771421924054, 0.8733236418909152, -0.19699821199227602, 1.0473388351981363, -1.1656713775090164, -1.5396488960146058, 1.8906564665466268, 0.5123351952321001, -0.8896885613701434, 0.8798999211414029, 0.3321858676642957, -0.1980261328270126, -0.02518325887305506, 1.1728712714013305, 1.201093959801379, 0.32129422945581415, 0.6620043229328887, -0.39492787055113454, -0.8825081423007486, 1.5076736969513784, 1.05733305556581, 0.9162331442087179, -0.784511096372904, -1.1502552471011351, -0.7947932192969646, 0.8877649747228633, -2.510241251220681, 0.14875876866843532, 0.5594096043704835, 1.0703050467008823, -2.065130579180748, -0.5182332569532772, 0.03836071433776447, 0.5014356687803425}; + expIndices = new int[][]{ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1}, + {0, 0, 0, 0, 4}, + {0, 0, 1, 0, 2}, + {0, 0, 1, 0, 3}, + {0, 0, 1, 0, 4}, + {0, 0, 2, 0, 1}, + {0, 0, 2, 0, 2}, + {0, 0, 2, 0, 3}, + {0, 0, 2, 0, 4}, + {0, 0, 3, 0, 0}, + {0, 0, 3, 0, 2}, + {0, 0, 4, 0, 4}, + {0, 0, 5, 0, 0}, + {0, 1, 0, 0, 0}, + {0, 1, 1, 0, 1}, + {0, 1, 1, 0, 2}, + {0, 1, 1, 0, 3}, + {0, 1, 2, 0, 1}, + {0, 1, 2, 0, 2}, + {0, 1, 3, 0, 0}, + {0, 1, 4, 0, 4}, + {0, 1, 5, 0, 0}, + {0, 1, 5, 0, 1}, + {0, 1, 5, 0, 2}, + {0, 1, 5, 0, 3}, + {0, 1, 5, 0, 4}, + {0, 2, 0, 0, 1}, + {0, 2, 0, 0, 4}, + {0, 2, 1, 0, 0}, + {0, 2, 1, 0, 3}, + {0, 2, 2, 0, 1}, + {0, 2, 2, 0, 2}, + {0, 2, 2, 0, 3}, + {0, 2, 2, 0, 4}, + {0, 2, 3, 0, 0}, + {0, 2, 3, 0, 2}, + {0, 2, 4, 0, 0}, + {0, 2, 4, 0, 2}, + {0, 2, 4, 0, 3}, + {0, 2, 4, 0, 4}, + {0, 2, 5, 0, 2}, + {0, 3, 0, 0, 1}, + {0, 3, 1, 0, 2}, + {0, 3, 2, 0, 2}, + {0, 3, 2, 0, 3}, + {0, 3, 2, 0, 4}, + {0, 3, 4, 0, 0}, + {0, 3, 4, 0, 1}, + {0, 3, 4, 0, 3}, + {0, 3, 4, 0, 4}, + {0, 3, 5, 0, 0}, + {0, 3, 5, 0, 4}, + {1, 0, 0, 0, 0}, + {1, 0, 0, 0, 3}, + {1, 0, 1, 0, 1}, + {1, 0, 1, 0, 4}, + {1, 0, 2, 0, 2}, + {1, 0, 3, 0, 0}, + {1, 0, 3, 0, 2}, + {1, 0, 3, 0, 4}, + {1, 0, 4, 0, 0}, + {1, 0, 4, 0, 1}, + {1, 0, 5, 0, 1}, + {1, 1, 0, 0, 1}, + {1, 1, 0, 0, 4}, + {1, 1, 1, 0, 4}, + {1, 1, 2, 0, 0}, + {1, 1, 3, 0, 0}, + {1, 1, 3, 0, 1}, + {1, 1, 3, 0, 4}, + {1, 1, 4, 0, 0}, + {1, 1, 5, 0, 1}, + {1, 1, 5, 0, 4}, + {1, 2, 0, 0, 4}, + {1, 2, 1, 0, 1}, + {1, 2, 2, 0, 1}, + {1, 2, 2, 0, 4}, + {1, 2, 3, 0, 3}, + {1, 2, 3, 0, 4}, + {1, 2, 4, 0, 0}, + {1, 2, 4, 0, 3}, + {1, 2, 5, 0, 3}, + {1, 3, 0, 0, 3}, + {1, 3, 1, 0, 0}, + {1, 3, 2, 0, 0}, + {1, 3, 2, 0, 3}, + {1, 3, 3, 0, 4}, + {1, 3, 4, 0, 1}, + {1, 3, 5, 0, 3}, + {1, 3, 5, 0, 4}, + {2, 0, 0, 0, 0}, + {2, 0, 0, 0, 2}, + {2, 0, 1, 0, 2}, + {2, 0, 1, 0, 3}, + {2, 0, 1, 0, 4}, + {2, 0, 2, 0, 2}, + {2, 0, 3, 0, 1}, + {2, 0, 3, 0, 4}, + {2, 0, 4, 0, 2}, + {2, 0, 5, 0, 4}, + {2, 1, 0, 0, 2}, + {2, 1, 0, 0, 3}, + {2, 1, 1, 0, 0}, + {2, 1, 1, 0, 4}, + {2, 1, 2, 0, 2}, + {2, 1, 2, 0, 3}, + {2, 1, 2, 0, 4}, + {2, 1, 3, 0, 1}, + {2, 1, 3, 0, 3}, + {2, 1, 4, 0, 2}, + {2, 1, 4, 0, 4}, + {2, 2, 0, 0, 0}, + {2, 2, 0, 0, 4}, + {2, 2, 1, 0, 1}, + {2, 2, 1, 0, 4}, + {2, 2, 2, 0, 1}, + {2, 2, 2, 0, 2}, + {2, 2, 2, 0, 3}, + {2, 2, 2, 0, 4}, + {2, 2, 3, 0, 2}, + {2, 2, 3, 0, 3}, + {2, 2, 4, 0, 3}, + {2, 2, 5, 0, 1}, + {2, 2, 5, 0, 3}, + {2, 2, 5, 0, 4}, + {2, 3, 0, 0, 0}, + {2, 3, 0, 0, 4}, + {2, 3, 1, 0, 1}, + {2, 3, 1, 0, 2}, + {2, 3, 1, 0, 4}, + {2, 3, 2, 0, 1}, + {2, 3, 3, 0, 0}, + {2, 3, 3, 0, 2}, + {2, 3, 3, 0, 3}, + {2, 3, 4, 0, 4}, + {2, 3, 5, 0, 0}, + {2, 3, 5, 0, 3}}; + exp = new CooTensor(expShape, expEntries, expIndices); + + assertEquals(exp, A.add(B)); + + // ------------------------------ sub-case 2 ------------------------------ + aShape = new Shape(3, 4, 6, 1, 5); + aEntries = new double[]{-0.6228105703680185}; + aIndices = new int[][]{ + {2, 1, 1, 0, 0}}; + A = new CooTensor(aShape, aEntries, aIndices); + + bShape = new Shape(3, 4, 6, 1, 5); + bEntries = new double[]{0.6237288645617417, 0.4572169708135583, -0.6223261232137111}; + bIndices = new int[][]{ + {0, 1, 5, 0, 2}, + {0, 2, 3, 0, 3}, + {0, 3, 1, 0, 3}}; + B = new CooTensor(bShape, bEntries, bIndices); + + expShape = new Shape(3, 4, 6, 1, 5); + expEntries = new double[]{0.6237288645617417, 0.4572169708135583, -0.6223261232137111, -0.6228105703680185}; + expIndices = new int[][]{ + {0, 1, 5, 0, 2}, + {0, 2, 3, 0, 3}, + {0, 3, 1, 0, 3}, + {2, 1, 1, 0, 0}}; + exp = new CooTensor(expShape, expEntries, expIndices); + + assertEquals(exp, A.add(B)); + + // ------------------------ Sub-case 3 ------------------------ + aShape = new Shape(3, 4, 1, 2); + A = new CooTensor(aShape); + + bShape = new Shape(3, 4, 1, 2, 1); + B = new CooTensor(bShape); + + assertThrows(LinearAlgebraException.class, ()->A.add(B)); + + // ------------------------ Sub-case 4 ------------------------ + aShape = new Shape(3, 4, 1, 2); + A = new CooTensor(aShape); + + bShape = new Shape(3, 12, 1, 2); + B = new CooTensor(bShape); + + assertThrows(LinearAlgebraException.class, ()->A.add(B)); + } + + + @Test + void subTests() { + // ------------------------ Sub-case 1 ------------------------ + aShape = new Shape(3, 4, 6, 1, 5); + aEntries = new double[]{-0.5712449609116215, -0.49004395314295557, 1.5715008978339873, -0.21667718838818686, 0.1745431703984849, -1.1004498342966045, -0.676995637130515, -1.7320614784970159, 1.5586547564195028, 0.611153895691038, -0.11208629951030782, 0.1444101865940601, -1.4335819402326644, 0.39041521163262366, 0.8106806718394286, 1.0422855257722368, 1.4272121513673586, -0.15504834834306788, -1.448099724471449, 0.24695194385889596, 1.1330513492380099, 0.66168304985216, -0.16203755702244307, 0.8040919212753633, 0.9578074577602911, -0.5750889348437798, -1.0000201229925485, 0.4770867265534327, -1.44133976954641, -0.20458485556356368, 0.6309627756447167, -0.08803380901022782, -0.43872137489317253, -0.11012183817754316, 0.8961589435738292, -0.8456141086004313, 2.8686395931180426, -0.40191741376948503, 0.4858071825781344, -0.5943075013972965, 0.2942967344752604, -1.0826431548972546, -0.4707149930209947, 0.3952349674229234, 0.22624625058757672, -1.129416696902452, 0.004551844692751868, 0.9556659511444416, 1.358027713041654, 0.49197835259702577, -1.8175067468344335, 0.4868379358144251, -0.3410350665089444, 0.716654948250773}; + aIndices = new int[][]{ + {0, 0, 0, 0, 4}, + {0, 0, 1, 0, 0}, + {0, 0, 1, 0, 1}, + {0, 0, 1, 0, 3}, + {0, 0, 2, 0, 0}, + {0, 0, 3, 0, 2}, + {0, 0, 4, 0, 0}, + {0, 0, 4, 0, 3}, + {0, 0, 4, 0, 4}, + {0, 0, 5, 0, 0}, + {0, 0, 5, 0, 4}, + {0, 1, 2, 0, 1}, + {0, 1, 2, 0, 4}, + {0, 1, 3, 0, 3}, + {0, 1, 3, 0, 4}, + {0, 1, 4, 0, 0}, + {0, 1, 4, 0, 1}, + {0, 1, 4, 0, 4}, + {0, 2, 0, 0, 4}, + {0, 2, 1, 0, 2}, + {0, 2, 4, 0, 3}, + {0, 3, 0, 0, 4}, + {0, 3, 1, 0, 0}, + {0, 3, 2, 0, 1}, + {0, 3, 2, 0, 4}, + {0, 3, 3, 0, 2}, + {0, 3, 4, 0, 4}, + {1, 0, 0, 0, 2}, + {1, 0, 3, 0, 3}, + {1, 0, 4, 0, 4}, + {1, 0, 5, 0, 1}, + {1, 1, 5, 0, 4}, + {1, 2, 3, 0, 3}, + {1, 2, 4, 0, 0}, + {1, 3, 3, 0, 2}, + {1, 3, 4, 0, 3}, + {1, 3, 5, 0, 2}, + {2, 0, 0, 0, 1}, + {2, 0, 0, 0, 2}, + {2, 0, 2, 0, 2}, + {2, 0, 4, 0, 2}, + {2, 1, 0, 0, 0}, + {2, 1, 0, 0, 3}, + {2, 1, 1, 0, 0}, + {2, 1, 2, 0, 2}, + {2, 1, 3, 0, 1}, + {2, 1, 5, 0, 1}, + {2, 1, 5, 0, 4}, + {2, 2, 0, 0, 2}, + {2, 2, 4, 0, 4}, + {2, 3, 0, 0, 3}, + {2, 3, 2, 0, 3}, + {2, 3, 3, 0, 4}, + {2, 3, 4, 0, 4}}; + A = new CooTensor(aShape, aEntries, aIndices); + + bShape = new Shape(3, 4, 6, 1, 5); + bEntries = new double[]{0.25749787460040247, 0.42810436253612655, -1.6990399554621591, -0.14162670591726237, -1.2156389247224306, 0.7655794435655864, -1.3283848630735486, -0.9709125642022862, 0.5032372168752851, 0.35754224417321595, 0.6448918786545342, 0.6919003333683309, 0.37318821706569305, -0.4799224390852263, -0.738181938577228, -0.7196554105181794, 1.685298290445505, 0.1041052956087065, -1.9255068249497573, -1.2222243573789249, -2.8639122810420745, -0.18810275714606653, -1.135743429612358, -0.35335118028050827, -0.6288242667416721, 0.678417186142117, 1.2234810535724336, 1.3348632716714322, -0.007293378755596761, -1.0260978828600755, 0.5317952637994143, 0.3802663183093493, -1.1814694383625668, 1.778845538477331, 1.31760559540134}; + bIndices = new int[][]{ + {0, 0, 0, 0, 0}, + {0, 0, 2, 0, 2}, + {0, 0, 3, 0, 3}, + {0, 0, 4, 0, 4}, + {0, 1, 0, 0, 3}, + {0, 1, 5, 0, 2}, + {0, 3, 2, 0, 0}, + {0, 3, 5, 0, 3}, + {1, 0, 3, 0, 3}, + {1, 0, 5, 0, 4}, + {1, 1, 3, 0, 1}, + {1, 1, 3, 0, 3}, + {1, 3, 1, 0, 2}, + {1, 3, 2, 0, 3}, + {1, 3, 5, 0, 1}, + {2, 0, 0, 0, 0}, + {2, 0, 0, 0, 4}, + {2, 0, 1, 0, 3}, + {2, 0, 1, 0, 4}, + {2, 1, 2, 0, 0}, + {2, 1, 2, 0, 1}, + {2, 1, 2, 0, 2}, + {2, 1, 5, 0, 2}, + {2, 2, 0, 0, 1}, + {2, 2, 3, 0, 0}, + {2, 2, 4, 0, 4}, + {2, 2, 5, 0, 3}, + {2, 3, 0, 0, 4}, + {2, 3, 1, 0, 0}, + {2, 3, 2, 0, 0}, + {2, 3, 3, 0, 0}, + {2, 3, 3, 0, 3}, + {2, 3, 4, 0, 0}, + {2, 3, 4, 0, 2}, + {2, 3, 5, 0, 2}}; + B = new CooTensor(bShape, bEntries, bIndices); + + expShape = new Shape(3, 4, 6, 1, 5); + expEntries = new double[]{-0.25749787460040247, -0.5712449609116215, -0.49004395314295557, 1.5715008978339873, -0.21667718838818686, 0.1745431703984849, -0.42810436253612655, -1.1004498342966045, 1.6990399554621591, -0.676995637130515, -1.7320614784970159, 1.7002814623367652, 0.611153895691038, -0.11208629951030782, 1.2156389247224306, 0.1444101865940601, -1.4335819402326644, 0.39041521163262366, 0.8106806718394286, 1.0422855257722368, 1.4272121513673586, -0.15504834834306788, -0.7655794435655864, -1.448099724471449, 0.24695194385889596, 1.1330513492380099, 0.66168304985216, -0.16203755702244307, 1.3283848630735486, 0.8040919212753633, 0.9578074577602911, -0.5750889348437798, -1.0000201229925485, 0.9709125642022862, 0.4770867265534327, -1.944576986421695, -0.20458485556356368, 0.6309627756447167, -0.35754224417321595, -0.6448918786545342, -0.6919003333683309, -0.08803380901022782, -0.43872137489317253, -0.11012183817754316, -0.37318821706569305, 0.4799224390852263, 0.8961589435738292, -0.8456141086004313, 0.738181938577228, 2.8686395931180426, 0.7196554105181794, -0.40191741376948503, 0.4858071825781344, -1.685298290445505, -0.1041052956087065, 1.9255068249497573, -0.5943075013972965, 0.2942967344752604, -1.0826431548972546, -0.4707149930209947, 0.3952349674229234, 1.2222243573789249, 2.8639122810420745, 0.41434900773364325, -1.129416696902452, 0.004551844692751868, 1.135743429612358, 0.9556659511444416, 0.35335118028050827, 1.358027713041654, 0.6288242667416721, -0.18643883354509122, -1.2234810535724336, -1.8175067468344335, -1.3348632716714322, 0.007293378755596761, 1.0260978828600755, 0.4868379358144251, -0.5317952637994143, -0.3802663183093493, -0.3410350665089444, 1.1814694383625668, -1.778845538477331, 0.716654948250773, -1.31760559540134}; + expIndices = new int[][]{ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 4}, + {0, 0, 1, 0, 0}, + {0, 0, 1, 0, 1}, + {0, 0, 1, 0, 3}, + {0, 0, 2, 0, 0}, + {0, 0, 2, 0, 2}, + {0, 0, 3, 0, 2}, + {0, 0, 3, 0, 3}, + {0, 0, 4, 0, 0}, + {0, 0, 4, 0, 3}, + {0, 0, 4, 0, 4}, + {0, 0, 5, 0, 0}, + {0, 0, 5, 0, 4}, + {0, 1, 0, 0, 3}, + {0, 1, 2, 0, 1}, + {0, 1, 2, 0, 4}, + {0, 1, 3, 0, 3}, + {0, 1, 3, 0, 4}, + {0, 1, 4, 0, 0}, + {0, 1, 4, 0, 1}, + {0, 1, 4, 0, 4}, + {0, 1, 5, 0, 2}, + {0, 2, 0, 0, 4}, + {0, 2, 1, 0, 2}, + {0, 2, 4, 0, 3}, + {0, 3, 0, 0, 4}, + {0, 3, 1, 0, 0}, + {0, 3, 2, 0, 0}, + {0, 3, 2, 0, 1}, + {0, 3, 2, 0, 4}, + {0, 3, 3, 0, 2}, + {0, 3, 4, 0, 4}, + {0, 3, 5, 0, 3}, + {1, 0, 0, 0, 2}, + {1, 0, 3, 0, 3}, + {1, 0, 4, 0, 4}, + {1, 0, 5, 0, 1}, + {1, 0, 5, 0, 4}, + {1, 1, 3, 0, 1}, + {1, 1, 3, 0, 3}, + {1, 1, 5, 0, 4}, + {1, 2, 3, 0, 3}, + {1, 2, 4, 0, 0}, + {1, 3, 1, 0, 2}, + {1, 3, 2, 0, 3}, + {1, 3, 3, 0, 2}, + {1, 3, 4, 0, 3}, + {1, 3, 5, 0, 1}, + {1, 3, 5, 0, 2}, + {2, 0, 0, 0, 0}, + {2, 0, 0, 0, 1}, + {2, 0, 0, 0, 2}, + {2, 0, 0, 0, 4}, + {2, 0, 1, 0, 3}, + {2, 0, 1, 0, 4}, + {2, 0, 2, 0, 2}, + {2, 0, 4, 0, 2}, + {2, 1, 0, 0, 0}, + {2, 1, 0, 0, 3}, + {2, 1, 1, 0, 0}, + {2, 1, 2, 0, 0}, + {2, 1, 2, 0, 1}, + {2, 1, 2, 0, 2}, + {2, 1, 3, 0, 1}, + {2, 1, 5, 0, 1}, + {2, 1, 5, 0, 2}, + {2, 1, 5, 0, 4}, + {2, 2, 0, 0, 1}, + {2, 2, 0, 0, 2}, + {2, 2, 3, 0, 0}, + {2, 2, 4, 0, 4}, + {2, 2, 5, 0, 3}, + {2, 3, 0, 0, 3}, + {2, 3, 0, 0, 4}, + {2, 3, 1, 0, 0}, + {2, 3, 2, 0, 0}, + {2, 3, 2, 0, 3}, + {2, 3, 3, 0, 0}, + {2, 3, 3, 0, 3}, + {2, 3, 3, 0, 4}, + {2, 3, 4, 0, 0}, + {2, 3, 4, 0, 2}, + {2, 3, 4, 0, 4}, + {2, 3, 5, 0, 2}}; + exp = new CooTensor(expShape, expEntries, expIndices); + + assertEquals(exp, A.sub(B)); + + // ------------------------ Sub-case 2 ------------------------ + aShape = new Shape(3, 4, 6, 1, 5); + aEntries = new double[]{-1.083066215874416}; + aIndices = new int[][]{ + {2, 3, 0, 0, 4}}; + A = new CooTensor(aShape, aEntries, aIndices); + + bShape = new Shape(3, 4, 6, 1, 5); + bEntries = new double[]{0.4701746769877878, -1.0749912650738502, 1.1109847828371984}; + bIndices = new int[][]{ + {1, 3, 1, 0, 4}, + {2, 0, 3, 0, 4}, + {2, 2, 3, 0, 3}}; + B = new CooTensor(bShape, bEntries, bIndices); + + expShape = new Shape(3, 4, 6, 1, 5); + expEntries = new double[]{-0.4701746769877878, 1.0749912650738502, -1.1109847828371984, -1.083066215874416}; + expIndices = new int[][]{ + {1, 3, 1, 0, 4}, + {2, 0, 3, 0, 4}, + {2, 2, 3, 0, 3}, + {2, 3, 0, 0, 4}}; + exp = new CooTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.sub(B)); + + // ------------------------ Sub-case 3 ------------------------ + aShape = new Shape(3, 4, 1, 2); + A = new CooTensor(aShape); + + bShape = new Shape(3, 4, 1, 2, 1); + B = new CooTensor(bShape); + + assertThrows(LinearAlgebraException.class, ()->A.sub(B)); + + // ------------------------ Sub-case 4 ------------------------ + aShape = new Shape(3, 4, 1, 2); + A = new CooTensor(aShape); + + bShape = new Shape(3, 12, 1, 2); + B = new CooTensor(bShape); + + assertThrows(LinearAlgebraException.class, ()->A.sub(B)); + } +} diff --git a/target/flag4j-v0.1.0-beta.jar b/target/flag4j-v0.1.0-beta.jar index ff7761f0ceddd62c8470588313e4d57c1d95ec03..26451c1f65c60a3f5e830f006de4cf8f000952a7 100644 GIT binary patch delta 26384 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 delta 26153 zcmZ6z1z1#F_dX0$Fmx;3At2qQfOK~w-6@@eBGQsFloHb2jUXu<(xH?fogxD2H_Z6{ z-tYZ;JzRU8d&R!j+H0RV=Q__h%L%Lp39Pu9DnJkx8X6`Vnq(Vx5-t<)ZV$+3x)hY zDd<5Yk?J=Pl=~1w1bLhZqDrB|U_#0Y7=Fm{BL<4CB{nO(1`fske?sLV;9LNNI3*Y} z5owPPRYs1cPzB^z1Wo;i3&Oifq1Y)WIH;UVp@Q%*LJSPN|E)ku5eg?r3B$!o8N?(= znS)TIDPUmyKNDMGOCaOsVn0ESzj3(XiK`fxDK!7$OXDH|47dj|CKN#rE5#cJl}au) zH=H&e^S@Mn#UyS^V!UhOVgJ)S9$1pjW0DZ5F}4`|TP_^r`WrtoO$r91$%NK@H_ z4Ai=Poozz8q|ezABL(!mM>Karvn(dMlO*0dm}jOIw;VFmd{d@7g%K6shm*dMI0dmg8mbTbD7KtaMQ==w-kC<@nwCTdxVp zo$>46__X4fx#Kz{VUawN?;NU^2ykJI6N`qk6vqcKubL}je|T5nv$mD*!OP^)%wIJ5 zx?1DiVuBJ287W0yE&^Y%^ysac??V+K(G%C;nfHXDp>a7ix<7gzMyX8@ zyvm1bDf8-=7Z2Gc;M2TT*y&5ap!rMQw|Q#oX*LYgWJhi*H4Us3wrR>wSRS$LvGp;@ z&{1vTt-JMH6~*U`<&`ORlrd*Vz06N?&HFKRa*GxNtv7v;4eTMw`{VGUx!|K_Xy)tP z^pC`YR?C<(>9Iy4EMe9@skx~<#xS*|l(;A5nGCB+Gz-*=Wcts_s-&sEl~{H$u|`C5S}4-t^He-?chj$n;?N&^Kue%1#ew$j*Ha z@yhr$=O8igc?X_~2TA>M?mZLJ3}&cpQY@#t;^oG8BSMc6dlHSNK3#j?=Os+y#zRIw zNW_R1*N1;`6S7twsrnR{2J)zTt+7GU^Fm-?(`@|-8+r5~r=Mf|ppNhT??Wo%$56Qd zh-7K@1D|DyZa9DImtcdp%JWer#d{*SYO0QG6qN}BI?how2iDnTdD1MOYjp?tYM+KZ zFeQv}O|~!IH+)WZ`GBRop`aF4J40%PH{M-_Ha_D?rceA@o$`H$M*th)9u8}7^!00x zeHJ^e1Xp5pCWF%$2j{rPh-QKqelW!7RMarG9w?$P*lGwr1A;55(g}ZCer9`~+!!zM zQV_>71g%nRse4>_h%1G{AJXivs&68)qDOnY@g~uvhh9E^)VOzO+4d0TL$Jpevm@pb zO+@MA0*J(caZEJ1geM-<3{$*Kd#6bJnGpUxb)WAfh#C*7a$DsSbWy;Bw}Bha(3sU^wd2CHRiREMB(9a2Q`}(_#jm=J2pZ z6ZbJ?R?j(}iRNJ^BCbAwaxW4&sSQiaM*$D`?9G{NOv^XLOx=_6n4IHg`-7}pH=>y1 zd+2-7k5Y>huP}B?5r*j)nJ|BWG4|r&a+XQ;R9O z1>e@(R*1XJsef)r$$U=iW9iBJ-bT{SaWyc0!smRSJ6F?$GH>5HSA=xlZ2CfPg|>VC zNoh5)z8FVgMcsIW6AX8HYN2iV&Ax~B2+xn2CiZ)H=Xw$)*0eOqi8J+5y)#w!sp)dE zN@+g|1HO~8{3KTQ8Y*!8VN1u8oYB4RddW58Pm%!kcs%2uUB68jnc#i;X#CUqT=nsQ zwCBs4J}wQ#{bh0os#p9t6NFtHR8mR~-onn|;cW9|^Wz8I=8yl?ec^iMjm?Ta9lXd#~LEiaa&v+4x@f>VMjToG+)H(h- zv){&p=j;h)8DroXckf#=?lZgwyP+7{ml;P`)e5KLQ@fthp+eCY%eVr8u=VfaE+eUP@=*3zFs)VF67ftP?#&F`Pm$epknmC`e(mA0 zRfWc%@{Af@`xG|Kg#M5rc!Tjd7TuK1+oH)ScK+9{OjP_Hjy5>l0`Wx{4zJYt3#pX2 zH5gCJzCo*G(|j^+F4=tH+XTnEQ}4zNo8u(pi>+GJIJ$xJkAh4jheF6|gt|I&US!&H+8LuA>B8{Sxv zD7u(*F-4~M8o|K#kq^yA$}A7;6FiNv)Gi6n2LS>a#m1QvUL(=QArf;G%J0aPd_7cx zSr=V_{0d@WwTTUy#c~(Wst+<|X6yHhPe`iJ(qPxeGjVuheXN8yDPgHEr9!12bD=i{u| zeBSKaG!0o^^j3e}pA9Ait&NG9J?@ZnIDF=-r)~9Fz$>)qv(V5PiO#(}@1%5k@eH>w zDk8K6Do|LCw-4R+9^Ff>d!vWRc`aom-fc1vrozUQdh|A3V*?fE_6A=imCnwz-*2jP zSYI5u#tYkix9?wTKMV{lC`fQ42+HBEq%8Cyo}X4|x~;Kqk@N6V*~gZdQk!m5Gj3k? zyGfz}fA=n)3~Fz+89IE% zpA{0!D-iz5{@h(#%S`UHIzzRmErPz}SD+mc0RNlUB3gWt zZ(&0jtoDc5nw=!KRbTK;cVqmSNIUa14K{NSQQYdbHWcn9rpC6H))JSs@}@cDYI7T- zsy3XMT~t}ELEo#mptbUvc>VjZe`=(VB3{D>lU4uap0gj^tYja$%Y?QD#5jMJcEnc` zZhD)=Hk>});1n`x;yNFdjEzix`lu7Cm$KFO9_Bii)JbP7+{#xdm?7LCm(6QJlZp9Z za^s=X-j8j)HY#^>qe2OeFcY@l37j9v4Y_pfIkx%1%sn%C8_+yUo8@oaG%p>wu07^H zcKq-*7PE6#>=Pf`Ft*+-BjM5$iEqf|A2|0mdYeb`w=Tl|hY8zc=^mD&54jI$Wcm#| zbqmb7{Q3_=f+KEZjGKBI7Jt#y%gtAxsHuZRt3|U9qMD7qVj88TCA?!6Q?*IZ&v+Co zit}zwb3qZ0ZMN$?%EGQ(bVJxCJ)k6ccu(Ym4c&`Ug7qix-2|ZBa~n~-iDEqU&qSq# zOkG!+W)zWobq@aRw-#Zv_AeeRnG-{LscjC+|TZu9)i{&-{6>kQ)2-hSNiCN3?(eOPVn6Z6QeZ;Bpx`4E<+qqaGxVQ-J+TLjeZOma%O9G^+WwIB#1@$eVCoP zbrjQ|ZB=FO-hay*k4^t5>Ihsz=7MpJ^%WNK=2-vC3;!u=8d&f!i%u;FE7Sf_ux$ce z^F8a!Q*r#&37CTHW>;)dq?qbs$&mQt0ZQxL{R^}$81Xj@`#6nfX)fa@58r(poL{Q5 z`1SEDTtY$aQHTEK!xMd~mGB3*7Cppl>?bs6m0a8>G+neQCcgfT$Lnx8h}sZObZr>S zF0My=%UZN(&3klvU!s96VEaUsnCC4`ACAARx=Nj~4xgjmXDMdC%Gj`E{w68f~qZRn(OV z4nR4jVrP!ejq%GlJ>G5;JrQh!a*kGdhRFYFrh?uWk{*zB#x;L^_B3GLz7rOd`c<+h z^-=B<*vhlbFa|4Iqr`r!%MFna<94M%ypey;#-cI4CFqBEtYJ-)k->*XB-u9hZ>@H9 zO;=;V8o710k&)CJr0uT^@=3%!sj3EoO?!_*1&vP}3)gki@+dy1%0~5ZJTxehwXVdIn8+NFYzpHBqAP8{Rx-jJo8cKP)duhIqs0=(xGVWbhrpIv`^6{oJ58;R@e%;t*>DACU;ZH~&8r<-(_&MyD`#`QW zhD6n8F+8pL*KA4ApS4GYI5O-#ApG{&=l*>SF$+_cN4oqx z3kttSg-)_th$yWKiwDYQudsrPWR)f*YP$`_s^?Z-WCNbY`*GL#T`_$k@t5?=yF|N~ zXV;KEkugPUH7bUd`{9vahb8meKhkzOFOWn15pL)(e^km_?4G_X8o3i_K zar)`>g5ZxS+KML`$5&+xi}4B7B5>4#MORWk^~$%-oKK4Hq5ICV<@+Rrkr z;M|*c0)U?n1=Sdr4^2DOVb{ej=3v#ODuBzd>o~AGZ;LlOGApPTiQa36*pXb%-n^)g zq4kU6;-@sT8@%TSx;i$m4W8Vldlf`-y-0i=vZni~xytiXe(<&%OybNDuv|%JV87vH>J znKG#w+43f$Rm3D9vZ5mLVHs@^ZCNJ+t>2^eQ>Yr@aR-x3>BLPsCc zx{txxU}qdTC1HPgfG~UV<%i@|7DuhLbnqy~lN*;4Ki=54uMX!e!7)3AOs5I@&eYM* zGaEv&$?7v=Ui8mqwkFSBdam;|`rRr;NrlyxcP8vq%;A_kU5ce1x!l}CkChS$`*E7w zKWXY)6Ob;`DDt{mu%SC9Ghj5Uc94V*pE(9hHf7^1FrJ%Jk`8;&mhfUnmL#UC!o2po zJmF{ASbqv5JA-ud(wCgZbCDY5blP)WPld7$2ffntNeW9pit5E+;01pHe5Fy{_AYB< z>jyWJk|!H=CNsS6sS5dpc38~+EmvOMLj9XfZN_hx2isH6E)zc!Za9mR?`|=Wg`&T( zyY}I$z9k~nGo&AZxmV@pobg+Y>i0)ShS&)HRwXO9vd=&0XYJ)qqNg)?#$2n>Q7*Ja z=}^538VM*6ktSo6Ck?rZla%l-IJ7sKTQPEiG0$GNW`OLbxZ@tvcOCPN)uh{!xpyf8 zuJebada=qo`>mq$H^c*$%vY{*3#wA|yfuwD?d=++DhHmz)`XueiFSbyx}YuI_Xo0F{4~jb)rrwSDz!Ag@mJ=uKUPZ_ z?ji3>PB!(;CF#&mL7ZUyM#L;aW!K3r7;a?^HaP{2FZ79R*ccdfn96nO3MI`|r{24% zF{^Zn=P&nxT{!pq3hGatAJj;h4p*4V!G3Xnj~zX79X&cUEmA@H4E2rzxu?0V$PHvON&7W_Z97>)IJ7CYC(O@IIc?FCE(aJYM$9 ze07o|JAN5B{<_{5Gl)9>{O#7ST59`Eg3F~Hm+G8FPa%BE>X7lv>j>(dGsb0=(7nV~ zoSQe)hsJ~2N53pBR}OTChmM6*X*CYOXsv3t%_*qxjbH_;j%%Ab1wet#kx8tl&pX9DDz30GoxTc5&W%L?J zddrnFY7tal=n-p_leRQG_&hq;nB38xu~USr@xJ6%M~r!0La0-e-o>y*HEH(OWzSHt zm-8R^`~|Vb%YC!qk%sZ^o=~SXP65xl#U|J`Z05Y$x5RHccY1=^T>n>$K`4RUVmBM5 zmmV{-f|qZapoXz_y7TjI#*yZ&*&USjo~_$P*#@CgLjEtB-T}!u;~W{PviP1OvM>VM7*w z9LC8V^ip$epPBDS@6UPM`rDTl*YsAux@DipWg6`2vh>#pL5++F&l-lT4Ae;s+604i-UV&Zkn?DXqZsI#RR;lby zYZ8KOKbjA_aqWCtPP#_(Kgx)Lm{USj-p>@N5A$0KL|Rg&-O{2gy~=TwMW-K@g}j67Y9Jsz(+frU0< z7w7#ze_3$GS}1#iUWqZa%6u5W70P}kW+L7ny5qOw=vrzEIsITBG#jK_*;*{ z;h@kou`HEYSzJ3n*FNK{tQW?dY^Sb-x6(z!NV1|yZ;?@K@FA7z)LfpfIR5NXAm_Ak zt*LWw;KMk!udEH2P0o~_Z^+a*qREV5%u`$=iR~514sbmpGsibi_A8Se8jXltY0H?5 zyP2o3%9&!)DI{BHCq-V<*p}ZQc=bRbJLe= zH`AAUqp!!*Wg!G#eVXB2>lH++W;Ur%Pj;y_lrM!f=Z~*ByZ76>qlDY$LhFaMH^Za~ zb{w&(Wm}2=v**nT>Va|U>OsBITPbq=0l&`nW(GxKvZ@0e9bva6TaA!IA^*l@(RW|a z&Dx2r8zj>URwJIpbEq8B2sj3L!tkETE`{hz*lMYTb~qHyr>fX_%Kd5EP#846E`K(} zYns(1?f$G<$)Tug%H-sm;K}w6zjIk_pX&f6?#h~+iunR&y6pgH=h&eZRl!-}HJpAT zA0{GOMM1x1#q>RgW$VA-U+#7Iqi=4cN1H9jxjp^8`j)i6CjfO$7v^m)pvM^%?bZu(o%2TR9FY%aI>(pH z1Od6KOJ@8ohx(H@>PsPk3o@0t_z>3za{YKuQ_UX!XwKeT`_W6bPdX06q`s(!b$S53 z7ogvxk_HLCC-P73yu#mlPCU7zK$pa*AdC-N4ETglI&%RN2ch5R*11XTqhGhE^C=dH zqK9~bh(rOayZ}0d*B=CK<9kIx!2zJh8{L9_tW|B~gWCayM1U=FP`PXFk5r(yWM&G`}ii|=U?~BU!OH- zFv5%#lCbbVg@w#(=&UU;T@UA68N43RB!{4HO^IJVSOnQRGdbxFv|TuiF4XBIkiXf- zk(^=rP%Ye3tJsj{#?S(X^nUcm?P-{PH8Z6~9SE;wn$*_df8#m|#@{NzX4XB<`B zt5kS@eUzSES;s}hYya4z|31Ld3gUvl)oVyP;K)ORMbOdINig6G+Y^r~@)uaJ>jNz7 z`$Wn#+)mfU)1;#j>!lY+)2qs-XA5+Q)8OcF*|!R5a=c1>Ke)%ZY9b4Q>nzE{vOAYf zgj=y`S;jzgEGc@vA6~1kQY{k1^%G{-uIar>XYbY-o3vmV%@1A9Pf{lyJuuK*;_>)S z1Te6~d-0yRJ0;Z#rU{V(3DOYq(Wj<0rCZAcwsb!GF?T4>k)YhQL%%d4SV91J#kf8u zFHpyzYI>h{PO%WO(;X}$G#Z3StQu!gP&X6>`Js8j{uX4G-_y#e-ic9Wkq4RepeZdD zB!N+nz4c*z?jjjy?jsK$Ingh6Hxz6@(oVI zpYf{1sd{Ekm{=dXt;SpkS*L%IAVo!l&l8U9cav#qkI-YT2Ef6PVxo8Nw~&x&2{<7vf3UCb$4?#}pQ1s+@WsSWGCK z??WxWkC)7xll?JjKsfn*Q&O1xgat9Cl5ejbdxu8&&t427s!Qir1gozuz;8B9b6xnk zFDP)OKEddpFw@NKu2bW9RYK-Jnp1SMjAVZf3$!YFhY_q89zvCJuILWk_V=WnTVp)Y z;)CiOEjc`Kcb>KOH2dxz$}+{jvi)PLH=bezL@WG;saFF0RXgu}@KpgM=S9{~y-idK zXRCvcZGLYh#R{a^i!G|}$7IYCy6n^_vA2O8@9SVf3pAL6@xJR%{CdpTgN?%{c$mSy zZwchVy%lfVtmP8EQ0xRq4MIGcvyB|Cu_+EBgE;wK+C2AgEf8NBh+)G`r#_Cj(G|)4 zDBS`xOd7|M|3QdV(t7&G_o^a7)RIAnI_0;%iwwS#2PO?eXG2UPfANf)E``J~LxO|H zeHvz1ByME2%;Q>ks8RUfn&%fQzg@GUQV3J2g1~p{Ou-ag{<`yURzZpXIG1<&re~4!t*!3r2e88G0IT1|zv)>T0sKQNB*YAe=@M$>tkj%6@^m@H zE%_gr<>5fCGC)&M2JV8+2?e)8$(j4gwYbdpzdKvLaiRDA3=wyYGTfSk3$Hyg9UyG} z@$oJBOHpxO+v+dPhA;oxP3{^+FAF)Hbc<8KvS0D%3y{^`vwY=h$IAnv%a@gtlVxp# zq*3Qt7~(gMyncS7u1w;ffb}YRx{bb4FiW+BMi1AE2R`g6Nm7O_N7T+GvuQL!xwkLs znqc|v6~*iP(FN525ibQcc3hlf^&pS9SHDEk*y1V9Zf%W<8YIL8*Zny)r^?qs*-;)x zFgg<#W$iktvPf$)!nr*|cETRlz|@#*|M%(-0uw}{c%Ai0u_Hya_#*v1h{&|aUiXJn z8EOr&oV($#?0qa1QS0BO7+*7e^ec+(eyJ&OArs68zCx{_^=qo+^Emn55ze6h7ALO# zIS-fWoMtOIPV@O;D@EFwYrMNc{G3Ic7fds7?ek>9w~JhHyBV!kD}vB=k;h9F8xk+0 ze;2aPi>_ZT9a)r&MFrLXG9^W5%XKB-W!9!Vxne>$&&FMK_Js;AP5AK8$^|9xCyL2` zeXrmma+}@EdU1;9R7K%9YH*f5F_c9(+;b=d{r4ZU+uN(4blK$CkT??Y!vTznKjosgBEf{Sk;VnE5n(D!@PG?9 zC^1{daYs*mZ8P!Wz1Y!}l=?V`mv-{RiA7TQ-2&0o5ype~UdhtJkL^lRlK#}zM{?;# znQtp$Q8#{G`w(_^5Bz4Sp32UZ>-)`ppR)vRMM8VTUO_$Nc|U(qoZh}7DZjLP85=py zQ}6fE#Hdx+Yv0#RuGNQ?dz-5aMp@5sQI~VTKiX@ya!sY->E|SJ-}3P2BR9{<>PlN= z9Jq_kJl^J5;HRSp0ltm%x)HT+ssE#%iWyCNDbuOX6nn41eiZQ^-&v$L7sqAXe^Jjh zEkEU`D$C=N&eHKkf|+`rz;RZV@`poW*GSg5zd~ZuH>1T0>l&c*DNUH&Q&{#Xo6t8i zy`^>zitL=gl&>7P1c81AGABk4Lf}P%FDNLUCN5PncQ<=wy*RX#{6fuK;A0fyA|6gH z!ENj2TbmGg26_Ad80QqTUnx%UgRAwi-;)p16!3SUr%=0w#+W&JbF56#IF*imx|+Z* z(EQ5O3OrkH%=&s|0*4Pm;a_2*fjt9U`wYb6e0&sU_5d1@jf@-UtdFx1U0JHX4rGtCk#n(Cz zi^T^IH^WDDXreV3Jr|tUqvPzCNrr(jI(GW;k#0uVK7+Pjwq8@@{YZil6i=8~=Sz#) z<%1|JZSC-iA9#uVc*&RewC%Dy_E|GctX1Pkg}GvgS@esDz~&eO#5uZNQXy`-tS8P< zLgsV(gsUqRTh~;S-;<>ZVQXHkr#9nHUFrA`*N-y-57N)M=^Rd;WR=Bu$%QsMaMwPn zpLPk<5U78g#VR}Nr9U_WBN?e{Ij>jEcHz-6uQC4V{HnRS_`H>elC~-1>XtJ_H!Cl; zPR-9{U}>8-d}mKDCDJ~qUJN5R9yJZ5l=8+&x?OYDTm71@%^jo*2(F5Pd<@p zVFKX85|-cbb!M+F|HA!6$~S@sKa=dfZld4_&o+u{Lffu=!A3SG4`VpJ@0w(0ry2K6 zL?WBf)7wY_S5g!&p089d$)jISUVu++!0&v>;pOQZaVzd*3a^{Ohe6&sUUi?i`4b5R zbXWV|a|AfYaR)p$1;P{2`g@h9imAix;>o=!2M#elwKQ(ndnxf0Zeeozd$5N&<_kA98-~u@DvWl!%;nmN%*CyyA%-bp)mkvy2bB z%n0ZFUQ3i|Lh4bK?$7zRD0bj15N~7`NA#_MYGlY7waxGtXbAxJFq%#^cUG)V?~)Gd@Z3Pt_rr+8fXtdNK`D+T-9pCR;tvae zSfyq-(&^CUlmb|WtrGu8vK^W38vLa|y#;S0$!%RBcIajLj|0!ZIgYvDCyFbqN`aXd zz57p(&r=Nln4f(1`2sE3ivV9JJsp2EPOCh7`g}W=ljHKV_qXPgdFK9=(scQUlIZnW zmtrT~83x)0_aphfzw)wR<$P{7sW{KF@K9eQ-lpWm?iEM^#?EB!Ug;w#rS!1x{R|EM zYyKHEt&g&>hCj^?bUioGTwc7AGW2NtA%AYVze#Mt$mBmKr~Uf=wR24y@0Uhc@sxsc zskqIMka|r!+`ol}<)akab4tz(%;97k7Mk8-hc+UQP0zL+0=`y7DlF|!J234S+y+Da z@tOAo4t7n!EU@=|zY0~!%?xOt7xkurGl^DYATUZL4{_D!CNDvmP)6oY{l&aa>dzYm zB8KB=BI3ss)+BMymK3kD9LqKZl^d7$xfbzvM#Rm3-pY+DjZZayh3foH$qw=OMLf9| zruOZkV|D*10`L6BT-fnwOY5X&>oAn>>)G>dN~_klGHx*12%@mxiNK$U2S1ZnXN@lmtFq;O8fFOgNO$!HzxUX4f^1n|)htK@ zG}f2E30t)=^mmi%W#H)EkCquZQ8s%_eZ4%n2&-$x>+i=noM?W3B_rHAhw`2$gjY`5 zzlxDCZ^@B`>6AQ`EE395f7UNC!gj`KFv{2~WUciM2S;6MD2>=ub#ozGLLo1LMFfzf zd+W|j{&ukEr{NV%^zoMUwRbJBXhE&C<`Jc_%k2_c?avd(>V|qLnV~#;?mBXV3+WlH zL!vZhGZ@y>&Lj4~8824!nXGm)xrNNzckX}-3Yuxd>F^XSMWtDTEi za@AvGF>w7_X2){mw}F-+y8oNBUldv=Vxntb*}DI}WxK(MxSo$b7q%cISH+gg^1b5j zTN41s^20ocYyDW+PcX&u@K;Z$%1!`*pjEgQ8!c{qVL)>?)2$fcae*g%t^P?JB@KP^ zABbf=ahF5sH@S5RHe*&LEbzN@Di`5YJ(gwYD`J*QZ=q(In*d zSxHInwl)n*`+IFz4odO)h_|MNHC3rL`NOa4Krk;sJJY`lR>e7w%$WOG_LUp=^d2M% zaLkG-`&0=xr_UUX5ylvlceI{ky}g+7wDlSPVv2ViEya($y3s0JJSj&lQ*QfS#W&co zS~&;fWiKudUS3J)Z&SeSo;%U0CME@$G&-3qRQRM&vr5h|fIJ8eO#AGyYx2zJRh;6s%-sc$~iAY;UD` zS`eg|UipF;V^NVmG@;X^hCezb^G%0z0PGX{0*|JPX7(agA8;CTjzEf18jm@R#HA~p zXuFpG!RU^m*G|+Eu-yI)pX=C1+Ne)2ZiyL7UtufRHC={Kxi~AE7LjGX?XN&QHk{Y7l)!#8CESu;ZnJ>NwZe0a^BB_3VYso!2h@bTNI2_XPoa#^Sr1aNb ze@4--YBl#B(SI^jP&R$MD9tdqU_Vud4`b8qsicK6`hINeDJ31&tnQ{g7s5WbWc>3| zrUAQ(e!8lt)-5A~-93e__#?-Ro?KNs4D<5DnP#Ynez7Bd(Uj#ACkx;2!RRq_tS$|n zrwnaX$pT`eb!Kp-&BDH94(a#Kf7-B4025!v~&!l{i5;V4_Za;tP2x+Gigr29sx=fL6Ae$el1$s9nqbl^ zaZ}+G{-Y{_vAOa#X7lHdj|SSFAK);;9rEX1eAJQO0)$9+zR`Q&+_t`zm?+-pct^N% zk7$QWJo~s{BYP<7Jh^Ytd7X`6vOUD>W)0(k$m195$E=?N?6RLCe8oW%D7kQB2Jz&q^ht=Y=F{qejSA{%JXhF{AMLu?BaxHy zN~x{l@9yTQNfZyibIDHF2*K=GEVaL1~1w( zfpah|_Pc6Q>*A0hRqmJ<7^nCdXMa#k>TQtXb-w_rmX{YSK8YWF?*)>}viMBO5- z2B|f-TZqd_J7-Rf%Ii2_VcPpq)~#|g&+`3VkG_%UXeC+m=I^GiBMT|z+$qA>(GZuT+$y0m-2NUz9W<^BL$ z%z!V7Kc5T)@RRN|ew0jtnKF8&DP^11)i=jp6KLm>C=lsZf#1Y-!N^KuQea=0^M)g$ z1eV}2yzEMguV2>vg4;gZGTz%Eleto16)km=Oa<^rJ&0E&+px`$-`?OLp;RS=F{*nK zXso+4-}}Ja8-;<+n~1|NARm``P7lK5|&a(@y zPXrL%16*w6t3^cX)|RyNsZf|*GR-kd((moZ#++kcP049&Fh?tN`a3?_KaWz-Ona_V z`kd+;U@{fkvO*g>~CS%KQdKGXP%x4dVHJTG!8bS$uwY|7wT*g`+>RN!Bn2si2Emg>Ahm( zuf!{bM9Pz6qGumge(JtB=x>m%wRs{4<(*G@IT!c0=AOrAOt9%|cyECA;+yG6Gn{;cc{)nq#y*BMlV~BG%oU>nw-OEzhPWDaCj`;Dg znELx8qC->X9lD6d3#)kx|5l;osUxS@Z@c{qHMMw)#_PaE&((1ECC^T;7E>J|hvL)n zx|9v4<&Vb`<1lOu?Ug2@9>HGo9;MrAunqHWr~e^l7@yMhBUjPIk$hYrIvsfo{L1<_R7-(o* za4k%9s^)_zKoYXlU$k z%N_tlvsfR16?*sLRkO_)Km>qv$e92L1CZF_6kr-1DOG(21QH-6jx7KPfQRrf%4kzI znMM>y1RZ|*0YH5BqTn^sL~RFPgbW2Q-31&YV`l9kNFbH(_W?F|cM=@y8nA zG$$|uS5cBX7w|C{Sp(Z2`mTux(&dOhet7LZf_EYp@IHK>A6STtogx4%0wW~}F(5rE zwuLyb6NJR*9s{4D|;gX834KXtgTUwX$VHGXsA+tl?OuMrYgWjq$`OkFdymKstSCJ ziIi@2fw`zA$T0#AqSnpP6j+0jsGb75kX_LH#R|v(L3#ikfjcPd&;^)`nl|0F2>T}( z4b2!E{yZ4SdiSm-q`A!biy#8I7-q82P&f2X2t?VfXGDOT_)InKy*1aKHM@0$ePjx1UKU(0OwFm{w)o7 z0Y$Q1$pxySqHq)duTUAVlmo+1+R_G~B@nqDxGg{te`k-q%_V4B1digy+QY1#G2kHVL^Hwpr$oEH-(g!=m0&>6k z(g>7{3Kjblbc$Lum=!1zl?v1j6o(>|?gILWq7B)#qs~OM+Yy4gAc8h2{Bb@A4_@N~ zg2Mm2g5oqUJOdT{3*-axKvnzq2p7Z!aq7{*yj$Pz>Y{W_#8I48yPJF2W$sK?spJH_5d7FcooFU(LyPNnB?$o954?2BoRu| ztV96LL#@IgDR>W6`z3PlOVl!2vVvDp1(jw8&!g-pdBCJ7iC+**j*>LQzz~$Lp(MBx z)fSlA;5<~tD$Ky>D4I1k;9n?@3Ma4_3fuJrKSoKM0bof2BzKo+@GL6clX$Q-N-9eP zOQZ5XN&_#WYBHJy{(_P!bHQaOJL3XyJ&FNAEBG%Kvh^;CR&s_B71+dvKN<$}G^_Q2 zw@^F;hQR`;sLqq%3KT{$2j)dFQeOp+;~^Q*9)SP#W7Qd$5~Use1!hHgT>b%vp=J*N zK-4Lb9>dfSCY0|f2Lv58#}8fzCeoux7?O{I3MC=;QAu~JK}1l=+-O0ds6C5e3{gf+ zrfUh&K(%6#6XZV1_oD}-4AnYrVUP+G0qU2KNtDM)EMy&JHO zb;t!OIBXZvj-n`e4ta}`R&OEms8pK47)huoDufu(sQ#L#!3aU6Y`}=2LWEo^?AeID z2Z#-;4uzk_V^F~pDxpHn03i&1l%a?iMgcMm{Hq+sPh_PRS0Ks z94w45h){X>m}A(Y)@C&T!xY6z;sr)Aiq&>J1`aNgfj)JJ!7$<+^APWjfegI84oc9h zorN)jn&d$~1{O*ZD#7SNIbYRdz))CV8%6+%!sSPdOB99U0gQUosi5!^Mk}g0Emtu- zP!wjqVThul5S(I!qRN|egYgp;FBX6~i=uChi8+JPiV)+Vvr6~8`VZs zyqGSizKeZ?sezJK)i85V63i4c9@QxL7MPqUUnv{RX4GU?PM9|+>CzLk21Tkg1oH{1 z$xh-hO;8@{Ntnf`gsze?3s4?88JI&T$vGD@8@2jaWti_!^Om<@9-`*W>cCt;VZI}n z|IVqH^O!6sE$vLMk;^;1iK&Fjo8|};jv~-@bKPt@dbp}5LE>s&SEa*Ztk%GrvG`<$xq{Cv5G#1s4hTyzq<|=*98y41(y&BOy1T>= zxBORFm58{-NtZ3`7fdIs4dJRMj6RV*)ZW)c2G(rIY&+NKm`#r zG=;wZH*kaaf6bT00eEnCJ1FwE1RjcT21ITf|FKViYuW!>_jr56d;?McHy;KZ zaa&3XU$XzlXZKED7Y~5vwE`I7><&=m)iwN)0|M4B{RboNQtu&ak$DG~)ck{&9iaD- z%nPAHjOd6Tv}(kMX&(L$6Q#y~w!)78LTEW6LcD23!d&pTj{kU6+`$|lkT4Z|+Yw4b zcei$rXNS+2fM{s-h&(y|C-UA0IF~b&9FEt8xG$qg`xnN-2}%ht=s~H1dH_Vo@*+by zG!4anK!o^?_~ZPaPkfWDfrRoG@5cY%dI)X*pA!Mx*!>@u zBv(W{tsRtV#1)GC9f2R;p_RM;hhoFmb^(YBN4I}fRChz@bM{dBC^y7;`i@)W9a_AP zLMQeSt-I#>ZyJ1egbME(&g%ia4}aqR&%yByz50i~bB8h^>+sSu&>W8VNt!_{EB*h} z!4W<(cv!75OGr&kuWv9gAqvaU)|)L&Wr1x?khhK2R_OO#QLuRj~BwAiT}R__fVwn zij;Jxg9`xR9^$}z@HT<}_}%Hg-sv8T{nL?n|NB7}^+v!p|6f_x0+;i-$6vjd-v4w@ zEv39^b1l7@W~XUy7-L9SJBwUqE}PlJj!QzdcBx58)300`ZHFvELS$^k*qPxBhfc;e z&M`*hIHzWIzR&Z2{QvKh_oEM<@9+NmJ-_GjfBiknhkNODUBHH)h%=Hs&KOA(Q$+56 zWy2){gb-Yg_;D@yDFho8t(#EIMhIuF%*THmnJ_@PlV57gP zhefD`L3IM^Js;J?8pP`}9o^!PH=jqUsh;M{M>R2`>M4Iu{Tw@>$?e;k@jM-xk7{D_ zf1eNee;Tf;#;uH6Oq}2G?{y<)z=Z|)vEk?8rz|so<}OeoInm;vy)70rz>(et0}`%% z$}(%|&;q45S8{s+lo%4pW1$#uEX2U3BpRKn_)}ey(K|e0csrL4M(x|XgHfiv;Qtz86pXXk0SnQ%kpqY7oE_G4si!U+h=LoxJ~ zgpNyNOm-TTrucAw1MGut4TLL`F*jxXizp*aeXSRLn+AP;8MI@u(w&B8V4e?KBJBVA z+gZLXxZbj(o6D-kW~uZG7At{VRVUB6%dR1LXW3npWYv1AT&xV@@zAf!+7g}5Q|00E z%tO~dVZ3R;XK0QceQ~=f3B6XN#;16R!r!7r`0qo^*bUs~p+nNrSwtwpc#buy5 zvDrNle{gBIs6pxqevpkeUsXpRWQgTIG!vtr-B3qyZ|LpW#zo3x6dBDb#kOXnJDtcB zVQpkkVJn9UJk53y4WbE^~>dxIl+EmNN0I5u1U|D`%zC9U*-99n)iv zw6j<9V6g3;>W1SU)Hmb`^?8~7x=)A5J}^OEE8n?qqNoBTgl^`ETa}=Ew7x!gxK)77 zTSC6lhc}Q7cb|K~2jO(X#O*IR@HTytFYaM(G1d$1Ics5)#g%%k5FsA10?0ZyRVZ%t zJ5wnR%)I`$GsxnlLHxqs##fHr(~rlO!0Zt)`)Nt(Z9gY^o4>gOUCI~h`m1q1ug2g2 zJ_%>oNQvoUN8K`OpxKAsEK%IJcU`XRjmkpNZG?voiDw!$6)5rC&;cu9=-{4AMpsI( z&iQqj#rs zh2qeCn~6$})gU*D`&jA9ZF}QmKyG7X=rMAvMoF-R^Af`=Cph7etCUV0ieCk&YN`{o z?jdx5L6tL|pkHU2eaW#(_!dzF{MR`uo>HWA;{sQ+QG2R3>P~N`nms6fwMfvyHQ^`! zf~+1zR)3eYC)f416)I`M z4fA8vt61b|crm2hDRP2(kl9^NRwctvu5rR!ij_dF>Z<>d-;!W;@gudkqtuChQi-^5 zT2um26U&^S;rn39ie{Aht#T2-8;q#KKAET^4;2sP1mw@fzs?EA6Cp1i6<)VBNe6oW z0RI&pxtl5*A z(EPZ(KbX8RjZSz@BXBLhfnEXsih|H$BqdHVD(r^FWYeAKcjkIT4d@@k5M=WCgs1Y3>tqWP>fqCg+gG~|_O(7>qy6>CV_%QaB`$QT40kdq%gttL zT93Xi=VJ#WIuR@rJ;$X+Z2`xRt8smSWLPX+@9C!)+NVcrY%Kb zza+_@o1roJ@_OTwp!)Yu>!xC@wBxHXvi+fSvP_xGg;t0BwsanxT#F);iS8~_ja>ez zNX>wxc17`!*9!~0O!|+NDygl|;?$a=K7&82Rx>DqDmN>gb$_{i(i2R{pCNSWGvys_ z-&=;8lZsJ89;l($B%+!cC&`t66`ijzG3STgm|!iqq?jzx|NRS{9*;^bZL)pq`wKZM za2)J``{{8KWBNB5qxuBs=4Lqd;TdhTGhIC6?D*m>z;iD%yeoTIb{zMletdT17$_*k z%bw#U1zFcL(mptkhF`wl7Ejo!g!1sx>BTGk z5Q%8$dsWi6pH^&DQn*oT?7we$9Gij#z1r67C~qp*stn`yaMJXYT`4wX;t!PgKuKOh z2qO)k2O+NEbnSC7eV#s5)NtS1V5r6cSiT$>AEweT4RZ}4`!+F&$5p_eE!YrLD1V~L z3gJbSZR@cS@M1>*Hi?qf{?t?<9!5E~f%T`sj5U-zhqwk&?qOj?%+Kc6B2eG$&`)Hm z8;5W!@J{k@-ov?*bJkuTG6ppsjT#>&shc_SA$b^8jzo9SR{Ol|&>ohk`joKI)kb@g zt-g<39NcyJJZ(4P_Z7U6EtyK8mC9(Iv?Z(38eD=5hKWNB2K>@KWtpi|P$?d;U9V)B z#{dhuZHF?LoBo}7&&mFf?T>sXXpHPc827G5+KnE>T73CJ%b6y=aY^|Uq4C6Y86h$K zvRq^8N)dZRQBK|o)h(-?AUs@G_e&QT6tPi-5QbiSo6Vcvuw8&+HfxZL*6$KcrEHtA zi5&ng!E$-8cYhbBM}FEtTt;lYXsI0=VA| z=Pjm0oT$QF42D6H-_1uP9&bw8EjCH1yCHJR*AnbUCw7aC%{2y3Ym{Jg!)jsla4gogiyI5&XqiYm-?iCy5 z9(yr715JbvFWf6`#MiOm=Y08aSN5L$2)($2_W}F5la6&Dk6^10Uwip^(rdyM_lsCO zruHxxk|gWDu{m?y+^2-|VhFB*L|arF%uV;Llo8}RoC%=P!fS?461#EyvJoDbBwg^G zK1t-_X7Rhr}I6 z`L$zLXCP5oNYu+xqBb00r1+m5yj?v=j?kLJ5VhzVC;Z-Fr4x_%=8opOr!iyMSHWaA z-OgEQzy)hhn((Cv+2SuDCi(&&w(G0Rc{UvNla*qBvUbs*P7jQjp3b%yJ@Jhyn`G%( z(DuG*^{3>ol*hRhe|_of-f?K;W3dpzG3`^9*#+Nk0d1Imzp?$a?M4TzC7q($K36z! zN65W+$LdD2@PZsJeE!wfg3s9ST|ev~@tgK3%k;$8X@iVd;99E0={)=T24f+@@e_=} zu0{L65K6BT+k}cbJhr<<$Lf?meEL1W-(BMDlu?iU{xkJTcRr;YPgT9_4N<`mB~Pi< zlwL2U)UkT7w(G01_UMae%E3oO!Gs@ymTDS$M0`&q9e+3O?5EJde%J%CI^}AFI%I|;q7`#e7l(xdsInuX^5xijw;>AeH2Qw{;1+*nK%ktC&T{%7#gGT From c74ca83beec04684ab741e5737c35d6b406b8b0d Mon Sep 17 00:00:00 2001 From: jacob Date: Mon, 12 Aug 2024 21:14:20 -0600 Subject: [PATCH 04/10] Add tests for sparse tensors. --- .../org/flag4j/arrays/sparse/CooCTensor.java | 30 ++- .../org/flag4j/arrays/sparse/CooTensor.java | 24 +- .../CooCTensorHermTransposeTests.java | 252 ++++++++++++++++++ .../CooCTensorReshapeTests.java | 218 +++++++++++++++ .../sparse_tensor/CooTensorReshapeTests.java | 209 +++++++++++++++ .../CooTensorTransposeTests.java | 147 ++++++++++ target/flag4j-v0.1.0-beta.jar | Bin 640987 -> 641230 bytes 7 files changed, 863 insertions(+), 17 deletions(-) create mode 100644 src/test/java/org/flag4j/sparse_complex_tensor/CooCTensorHermTransposeTests.java create mode 100644 src/test/java/org/flag4j/sparse_complex_tensor/CooCTensorReshapeTests.java create mode 100644 src/test/java/org/flag4j/sparse_tensor/CooTensorReshapeTests.java create mode 100644 src/test/java/org/flag4j/sparse_tensor/CooTensorTransposeTests.java diff --git a/src/main/java/org/flag4j/arrays/sparse/CooCTensor.java b/src/main/java/org/flag4j/arrays/sparse/CooCTensor.java index bcd6e0497..b8f5ecfeb 100644 --- a/src/main/java/org/flag4j/arrays/sparse/CooCTensor.java +++ b/src/main/java/org/flag4j/arrays/sparse/CooCTensor.java @@ -276,20 +276,21 @@ public CooCTensor reshape(Shape newShape) { newShape.makeStridesIfNull(); int rank = indices[0].length; + int newRank = newShape.getRank(); int nnz = entries.length; int[] oldStrides = shape.getStrides(); int[] newStrides = newShape.getStrides(); - int[][] newIndices = new int[nnz][rank]; + int[][] newIndices = new int[nnz][newRank]; - for (int i = 0; i < nnz; i++) { + for(int i=0; iComputes the transpose of a tensor. Same as {@link #transpose()}.

+ * + *

This method transposes the tensor by exchanges the first and last index + * of the tensor. Thus, for a rank 2 tensor, this method is equivalent to a matrix transpose.

+ * + *

{@link #T(int, int)} and {@link #T(int...)} offer more general tensor transposes.

* * @return The transpose of this tensor. + * @see #transpose() + * @see #T(int, int) + * @see #T(int...) */ @Override public CooCTensor T() { @@ -870,7 +880,7 @@ public CooCTensor H(int axis1, int axis2) { } // Create sparse coo tensor and sort values lexicographically. - CooCTensor transpose = new CooCTensor(shape, transposeEntries, transposeIndices); + CooCTensor transpose = new CooCTensor(shape.swapAxes(axis1, axis2), transposeEntries, transposeIndices); transpose.sortIndices(); return transpose; @@ -908,7 +918,7 @@ public CooCTensor H(int... axes) { } // Create sparse coo tensor and sort values lexicographically. - CooCTensor transpose = new CooCTensor(shape, transposeEntries, transposeIndices); + CooCTensor transpose = new CooCTensor(shape.swapAxes(axes), transposeEntries, transposeIndices); transpose.sortIndices(); return transpose; diff --git a/src/main/java/org/flag4j/arrays/sparse/CooTensor.java b/src/main/java/org/flag4j/arrays/sparse/CooTensor.java index 3d9872e58..7c1c48ad6 100644 --- a/src/main/java/org/flag4j/arrays/sparse/CooTensor.java +++ b/src/main/java/org/flag4j/arrays/sparse/CooTensor.java @@ -282,12 +282,13 @@ public CooTensor reshape(Shape newShape) { newShape.makeStridesIfNull(); // Ensure this shape object has strides computed. int rank = indices[0].length; + int newRank = newShape.getRank(); int nnz = entries.length; int[] oldStrides = shape.getStrides(); int[] newStrides = newShape.getStrides(); - int[][] newIndices = new int[nnz][rank]; + int[][] newIndices = new int[nnz][newRank]; for (int i = 0; i < nnz; i++) { int flatIndex = 0; @@ -295,7 +296,11 @@ public CooTensor reshape(Shape newShape) { flatIndex += indices[i][j] * oldStrides[j]; } - for (int j = 0; j < rank; j++) { + for (int j = 0; j < newRank; j++) { + int[] arr1 = newIndices[i]; + int v1 = newIndices[i][j]; + int v2 = newStrides[j]; + newIndices[i][j] = flatIndex / newStrides[j]; flatIndex %= newStrides[j]; } @@ -337,6 +342,7 @@ public CooTensor flatten(int axis) { // Compute new shape. int[] destShape = new int[indices[0].length]; + Arrays.fill(destShape, 1); destShape[axis] = shape.totalEntries().intValueExact(); for(int i=0, size=entries.length; iComputes the transpose of a tensor. Same as {@link #transpose()}.

+ * + *

This method transposes the tensor by exchanges the first and last index + * of the tensor. Thus, for a rank 2 tensor, this method is equivalent to a matrix transpose.

+ * + *

{@link #T(int, int)} and {@link #T(int...)} offer more general tensor transposes.

* * @return The transpose of this tensor. * @see #transpose() diff --git a/src/test/java/org/flag4j/sparse_complex_tensor/CooCTensorHermTransposeTests.java b/src/test/java/org/flag4j/sparse_complex_tensor/CooCTensorHermTransposeTests.java new file mode 100644 index 000000000..75340ddff --- /dev/null +++ b/src/test/java/org/flag4j/sparse_complex_tensor/CooCTensorHermTransposeTests.java @@ -0,0 +1,252 @@ +package org.flag4j.sparse_complex_tensor; + +import org.flag4j.arrays.sparse.CooCTensor; +import org.flag4j.complex_numbers.CNumber; +import org.flag4j.core.Shape; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class CooCTensorHermTransposeTests { + static CooCTensor A; + static Shape aShape; + static CNumber[] aEntries; + static int[][] aIndices; + + static CooCTensor exp; + static Shape expShape; + static CNumber[] expEntries; + static int[][] expIndices; + + @Test + void hermTransposeTests() { + // ----------------------- Sub-case 1 ----------------------- + aShape = new Shape(3, 4, 2, 1, 5); + aEntries = new CNumber[]{new CNumber(0.6522, 0.3289), new CNumber(0.7167, 0.9757), new CNumber(0.7091, 0.0283), new CNumber(0.2897, 0.9174), new CNumber(0.2596, 0.4461), new CNumber(0.4028, 0.9296), new CNumber(0.9347, 0.0967), new CNumber(0.4156, 0.7123), new CNumber(0.5299, 0.2536), new CNumber(0.8344, 0.3449), new CNumber(0.3802, 0.6804)}; + aIndices = new int[][]{ + {0, 0, 0, 0, 2}, + {0, 2, 0, 0, 0}, + {1, 0, 0, 0, 3}, + {1, 1, 0, 0, 1}, + {1, 1, 1, 0, 3}, + {1, 3, 0, 0, 3}, + {1, 3, 1, 0, 4}, + {2, 1, 0, 0, 2}, + {2, 1, 0, 0, 3}, + {2, 1, 1, 0, 3}, + {2, 2, 1, 0, 3}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + expShape = new Shape(5, 4, 2, 1, 3); + expEntries = new CNumber[]{new CNumber(0.7167, -0.9757), new CNumber(0.2897, -0.9174), new CNumber(0.6522, -0.3289), new CNumber(0.4156, -0.7123), new CNumber(0.7091, -0.0283), new CNumber(0.5299, -0.2536), new CNumber(0.2596, -0.4461), new CNumber(0.8344, -0.3449), new CNumber(0.3802, -0.6804), new CNumber(0.4028, -0.9296), new CNumber(0.9347, -0.0967)}; + expIndices = new int[][]{ + {0, 2, 0, 0, 0}, + {1, 1, 0, 0, 1}, + {2, 0, 0, 0, 0}, + {2, 1, 0, 0, 2}, + {3, 0, 0, 0, 1}, + {3, 1, 0, 0, 2}, + {3, 1, 1, 0, 1}, + {3, 1, 1, 0, 2}, + {3, 2, 1, 0, 2}, + {3, 3, 0, 0, 1}, + {4, 3, 1, 0, 1}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.H()); + + // ----------------------- Sub-case 2 ----------------------- + aShape = new Shape(3, 4, 2, 1, 5); + aEntries = new CNumber[]{new CNumber(0.8546, 0.6631), new CNumber(0.8133, 0.2484), new CNumber(0.0033, 0.7366), new CNumber(0.0844, 0.3648), new CNumber(0.8295, 0.2401), new CNumber(0.1182, 0.7329), new CNumber(0.6894, 0.0494), new CNumber(0.4388, 0.4951), new CNumber(0.8198, 0.6859), new CNumber(0.8987, 0.6718), new CNumber(0.2785, 0.8425)}; + aIndices = new int[][]{ + {0, 2, 0, 0, 1}, + {0, 2, 1, 0, 0}, + {0, 3, 1, 0, 3}, + {1, 0, 0, 0, 3}, + {1, 0, 1, 0, 2}, + {1, 2, 1, 0, 4}, + {1, 3, 1, 0, 3}, + {2, 0, 1, 0, 1}, + {2, 0, 1, 0, 4}, + {2, 1, 1, 0, 0}, + {2, 1, 1, 0, 2}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + expShape = new Shape(2, 4, 3, 1, 5); + expEntries = new CNumber[]{new CNumber(0.0844, -0.3648), new CNumber(0.8546, -0.6631), new CNumber(0.8295, -0.2401), new CNumber(0.4388, -0.4951), new CNumber(0.8198, -0.6859), new CNumber(0.8987, -0.6718), new CNumber(0.2785, -0.8425), new CNumber(0.8133, -0.2484), new CNumber(0.1182, -0.7329), new CNumber(0.0033, -0.7366), new CNumber(0.6894, -0.0494)}; + expIndices = new int[][]{ + {0, 0, 1, 0, 3}, + {0, 2, 0, 0, 1}, + {1, 0, 1, 0, 2}, + {1, 0, 2, 0, 1}, + {1, 0, 2, 0, 4}, + {1, 1, 2, 0, 0}, + {1, 1, 2, 0, 2}, + {1, 2, 0, 0, 0}, + {1, 2, 1, 0, 4}, + {1, 3, 0, 0, 3}, + {1, 3, 1, 0, 3}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + + assertEquals(exp, A.H(0, 2)); + assertEquals(exp, A.H(2, 0)); + + // ----------------------- Sub-case 3 ----------------------- + aShape = new Shape(3, 4, 2, 1, 5); + aEntries = new CNumber[]{new CNumber(0.2252, 0.8303), new CNumber(0.7022, 0.9162), new CNumber(0.6672, 0.2974), new CNumber(0.4421, 0.7193), new CNumber(0.3796, 0.9056), new CNumber(0.2784, 0.3588), new CNumber(0.3264, 0.909), new CNumber(0.1959, 0.2546), new CNumber(0.7772, 0.396), new CNumber(0.2936, 0.491), new CNumber(0.5877, 0.1148)}; + aIndices = new int[][]{ + {0, 0, 0, 0, 2}, + {0, 0, 1, 0, 2}, + {0, 3, 0, 0, 2}, + {1, 0, 1, 0, 1}, + {1, 0, 1, 0, 4}, + {1, 2, 1, 0, 4}, + {2, 0, 0, 0, 0}, + {2, 0, 1, 0, 2}, + {2, 2, 1, 0, 0}, + {2, 3, 1, 0, 2}, + {2, 3, 1, 0, 3}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + expShape = new Shape(3, 1, 5, 4, 2); + expEntries = new CNumber[]{new CNumber(0.2252, -0.8303), new CNumber(0.7022, -0.9162), new CNumber(0.6672, -0.2974), new CNumber(0.4421, -0.7193), new CNumber(0.3796, -0.9056), new CNumber(0.2784, -0.3588), new CNumber(0.3264, -0.909), new CNumber(0.7772, -0.396), new CNumber(0.1959, -0.2546), new CNumber(0.2936, -0.491), new CNumber(0.5877, -0.1148)}; + expIndices = new int[][]{ + {0, 0, 2, 0, 0}, + {0, 0, 2, 0, 1}, + {0, 0, 2, 3, 0}, + {1, 0, 1, 0, 1}, + {1, 0, 4, 0, 1}, + {1, 0, 4, 2, 1}, + {2, 0, 0, 0, 0}, + {2, 0, 0, 2, 1}, + {2, 0, 2, 0, 1}, + {2, 0, 2, 3, 1}, + {2, 0, 3, 3, 1}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + + assertEquals(exp, A.H(0, 3, 4, 1, 2)); + + // ----------------------- Sub-case 4 ----------------------- + assertThrows(IllegalArgumentException.class, ()->A.H(0, 1, 3, 2)); + assertThrows(IllegalArgumentException.class, ()->A.H(0, 3, 4, 1, 2, 5)); + assertThrows(IllegalArgumentException.class, ()->A.H(0, 3, -4, 1, 2)); + assertThrows(IllegalArgumentException.class, ()->A.H(0, 15, 4, 1, 2)); + assertThrows(IndexOutOfBoundsException.class, ()->A.H(5, 1)); + } + + + @Test + void transposeTests() { + // ----------------------- Sub-case 1 ----------------------- + aShape = new Shape(3, 4, 2, 1, 5); + aEntries = new CNumber[]{new CNumber(0.9613, 0.238), new CNumber(0.9947, 0.4532), new CNumber(0.1439, 0.7333), new CNumber(0.2738, 0.7492), new CNumber(0.0159, 0.6496), new CNumber(0.44, 0.5992), new CNumber(0.2544, 0.174), new CNumber(0.0317, 0.3052), new CNumber(0.3788, 0.4169), new CNumber(0.2586, 0.7146), new CNumber(0.148, 0.1819)}; + aIndices = new int[][]{ + {0, 0, 0, 0, 4}, + {0, 0, 1, 0, 1}, + {0, 1, 0, 0, 2}, + {0, 1, 1, 0, 3}, + {1, 1, 1, 0, 0}, + {1, 1, 1, 0, 4}, + {1, 2, 0, 0, 4}, + {1, 2, 1, 0, 1}, + {1, 2, 1, 0, 4}, + {2, 0, 1, 0, 4}, + {2, 1, 1, 0, 4}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + expShape = new Shape(5, 4, 2, 1, 3); + expEntries = new CNumber[]{new CNumber(0.0159, 0.6496), new CNumber(0.9947, 0.4532), new CNumber(0.0317, 0.3052), new CNumber(0.1439, 0.7333), new CNumber(0.2738, 0.7492), new CNumber(0.9613, 0.238), new CNumber(0.2586, 0.7146), new CNumber(0.44, 0.5992), new CNumber(0.148, 0.1819), new CNumber(0.2544, 0.174), new CNumber(0.3788, 0.4169)}; + expIndices = new int[][]{ + {0, 1, 1, 0, 1}, + {1, 0, 1, 0, 0}, + {1, 2, 1, 0, 1}, + {2, 1, 0, 0, 0}, + {3, 1, 1, 0, 0}, + {4, 0, 0, 0, 0}, + {4, 0, 1, 0, 2}, + {4, 1, 1, 0, 1}, + {4, 1, 1, 0, 2}, + {4, 2, 0, 0, 1}, + {4, 2, 1, 0, 1}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.T()); + + // ----------------------- Sub-case 2 ----------------------- + aShape = new Shape(3, 4, 2, 1, 5); + aEntries = new CNumber[]{new CNumber(0.5902, 0.9131), new CNumber(0.3367, 0.9463), new CNumber(0.4198, 0.1293), new CNumber(0.6835, 0.2796), new CNumber(0.5134, 0.2389), new CNumber(0.7717, 0.3427), new CNumber(0.7304, 0.4389), new CNumber(0.4974, 0.184), new CNumber(0.1768, 0.9627), new CNumber(0.5433, 0.2314), new CNumber(0.9679, 0.4831)}; + aIndices = new int[][]{ + {0, 1, 0, 0, 3}, + {0, 1, 1, 0, 4}, + {0, 2, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 2}, + {1, 2, 0, 0, 3}, + {1, 3, 0, 0, 0}, + {2, 1, 0, 0, 4}, + {2, 1, 1, 0, 0}, + {2, 2, 0, 0, 3}, + {2, 3, 0, 0, 4}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + expShape = new Shape(2, 4, 3, 1, 5); + expEntries = new CNumber[]{new CNumber(0.6835, 0.2796), new CNumber(0.5134, 0.2389), new CNumber(0.5902, 0.9131), new CNumber(0.4974, 0.184), new CNumber(0.4198, 0.1293), new CNumber(0.7717, 0.3427), new CNumber(0.5433, 0.2314), new CNumber(0.7304, 0.4389), new CNumber(0.9679, 0.4831), new CNumber(0.3367, 0.9463), new CNumber(0.1768, 0.9627)}; + expIndices = new int[][]{ + {0, 0, 1, 0, 1}, + {0, 0, 1, 0, 2}, + {0, 1, 0, 0, 3}, + {0, 1, 2, 0, 4}, + {0, 2, 0, 0, 1}, + {0, 2, 1, 0, 3}, + {0, 2, 2, 0, 3}, + {0, 3, 1, 0, 0}, + {0, 3, 2, 0, 4}, + {1, 1, 0, 0, 4}, + {1, 1, 2, 0, 0}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + + assertEquals(exp, A.T(0, 2)); + assertEquals(exp, A.T(2, 0)); + + // ----------------------- Sub-case 3 ----------------------- + aShape = new Shape(3, 4, 2, 1, 5); + aEntries = new CNumber[]{new CNumber(0.8834, 0.1986), new CNumber(0.3184, 0.3042), new CNumber(0.8551, 0.4776), new CNumber(0.7626, 0.7819), new CNumber(0.1152, 0.4055), new CNumber(0.6564, 0.7552), new CNumber(0.3097, 0.5647), new CNumber(0.3279, 0.7208), new CNumber(0.4838, 0.6065), new CNumber(0.8963, 0.7191), new CNumber(0.2443, 0.4567)}; + aIndices = new int[][]{ + {0, 0, 0, 0, 3}, + {0, 0, 1, 0, 0}, + {0, 1, 0, 0, 4}, + {0, 2, 0, 0, 2}, + {1, 0, 0, 0, 3}, + {1, 2, 0, 0, 0}, + {1, 2, 1, 0, 3}, + {2, 1, 1, 0, 4}, + {2, 2, 0, 0, 4}, + {2, 2, 1, 0, 0}, + {2, 3, 1, 0, 1}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + expShape = new Shape(3, 1, 5, 4, 2); + expEntries = new CNumber[]{new CNumber(0.3184, 0.3042), new CNumber(0.7626, 0.7819), new CNumber(0.8834, 0.1986), new CNumber(0.8551, 0.4776), new CNumber(0.6564, 0.7552), new CNumber(0.1152, 0.4055), new CNumber(0.3097, 0.5647), new CNumber(0.8963, 0.7191), new CNumber(0.2443, 0.4567), new CNumber(0.3279, 0.7208), new CNumber(0.4838, 0.6065)}; + expIndices = new int[][]{ + {0, 0, 0, 0, 1}, + {0, 0, 2, 2, 0}, + {0, 0, 3, 0, 0}, + {0, 0, 4, 1, 0}, + {1, 0, 0, 2, 0}, + {1, 0, 3, 0, 0}, + {1, 0, 3, 2, 1}, + {2, 0, 0, 2, 1}, + {2, 0, 1, 3, 1}, + {2, 0, 4, 1, 1}, + {2, 0, 4, 2, 0}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + + assertEquals(exp, A.T(0, 3, 4, 1, 2)); + + // ----------------------- Sub-case 4 ----------------------- + assertThrows(IllegalArgumentException.class, ()->A.T(0, 1, 3, 2)); + assertThrows(IllegalArgumentException.class, ()->A.T(0, 3, 4, 1, 2, 5)); + assertThrows(IllegalArgumentException.class, ()->A.T(0, 3, -4, 1, 2)); + assertThrows(IllegalArgumentException.class, ()->A.T(0, 15, 4, 1, 2)); + assertThrows(IndexOutOfBoundsException.class, ()->A.T(5, 1)); + } +} diff --git a/src/test/java/org/flag4j/sparse_complex_tensor/CooCTensorReshapeTests.java b/src/test/java/org/flag4j/sparse_complex_tensor/CooCTensorReshapeTests.java new file mode 100644 index 000000000..39df27aba --- /dev/null +++ b/src/test/java/org/flag4j/sparse_complex_tensor/CooCTensorReshapeTests.java @@ -0,0 +1,218 @@ +package org.flag4j.sparse_complex_tensor; + +import org.flag4j.arrays.sparse.CooCTensor; +import org.flag4j.complex_numbers.CNumber; +import org.flag4j.core.Shape; +import org.junit.jupiter.api.Test; + +import static org.junit.Assert.assertThrows; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class CooCTensorReshapeTests { + static CooCTensor A; + static Shape aShape; + static CNumber[] aEntries; + static int[][] aIndices; + + static CooCTensor exp; + static Shape expShape; + static CNumber[] expEntries; + static int[][] expIndices; + + @Test + void reshapeTests() { + // -------------------------- Sub-case 1 -------------------------- + aShape = new Shape(5, 4, 2, 1); + aEntries = new CNumber[]{new CNumber(0.2856, 0.1775), new CNumber(0.2455, 0.6139), new CNumber(0.9386, 0.8602), new CNumber(0.194, 0.921), new CNumber(0.8078, 0.4986), new CNumber(0.359, 0.5673)}; + aIndices = new int[][]{ + {0, 0, 0, 0}, + {0, 0, 1, 0}, + {2, 2, 1, 0}, + {2, 3, 1, 0}, + {3, 3, 0, 0}, + {4, 3, 0, 0}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + expShape = new Shape(2, 5, 2, 2); + expEntries = new CNumber[]{new CNumber(0.2856, 0.1775), new CNumber(0.2455, 0.6139), new CNumber(0.9386, 0.8602), new CNumber(0.194, 0.921), new CNumber(0.8078, 0.4986), new CNumber(0.359, 0.5673)}; + expIndices = new int[][]{ + {0, 0, 0, 0}, + {0, 0, 0, 1}, + {1, 0, 0, 1}, + {1, 0, 1, 1}, + {1, 2, 1, 0}, + {1, 4, 1, 0}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.reshape(2, 5, 2, 2)); + + // ----------------------------- Sub-case 2 ----------------------------- + aShape = new Shape(5, 4, 2, 3, 15); + aEntries = new CNumber[]{new CNumber(0.8103, 0.0203), new CNumber(0.5684, 0.4151), new CNumber(0.9044, 0.8734), new CNumber(0.201, 0.7032), new CNumber(0.9682, 0.2723), new CNumber(0.4699, 0.8203), new CNumber(0.3871, 0.3395), new CNumber(0.7851, 0.3768), new CNumber(0.2315, 0.7695), new CNumber(0.8333, 0.8837), new CNumber(0.0398, 0.559), new CNumber(0.0405, 0.9707), new CNumber(0.488, 0.8343), new CNumber(0.2441, 0.7806), new CNumber(0.3995, 0.6793), new CNumber(0.3689, 0.6126), new CNumber(0.0767, 0.9631), new CNumber(0.8007, 0.4023)}; + aIndices = new int[][]{ + {0, 0, 0, 0, 0}, + {0, 1, 0, 0, 7}, + {0, 2, 1, 2, 4}, + {0, 3, 0, 0, 11}, + {0, 3, 1, 0, 10}, + {0, 3, 1, 2, 6}, + {1, 1, 1, 0, 7}, + {2, 0, 0, 0, 8}, + {2, 0, 0, 0, 10}, + {2, 2, 0, 2, 12}, + {2, 2, 1, 1, 6}, + {3, 0, 0, 0, 2}, + {3, 0, 1, 1, 1}, + {4, 0, 0, 2, 10}, + {4, 0, 1, 0, 7}, + {4, 2, 1, 1, 8}, + {4, 3, 0, 0, 6}, + {4, 3, 1, 2, 13}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + expShape = new Shape(15, 2, 4, 15); + expEntries = new CNumber[]{new CNumber(0.8103, 0.0203), new CNumber(0.5684, 0.4151), new CNumber(0.9044, 0.8734), new CNumber(0.201, 0.7032), new CNumber(0.9682, 0.2723), new CNumber(0.4699, 0.8203), new CNumber(0.3871, 0.3395), new CNumber(0.7851, 0.3768), new CNumber(0.2315, 0.7695), new CNumber(0.8333, 0.8837), new CNumber(0.0398, 0.559), new CNumber(0.0405, 0.9707), new CNumber(0.488, 0.8343), new CNumber(0.2441, 0.7806), new CNumber(0.3995, 0.6793), new CNumber(0.3689, 0.6126), new CNumber(0.0767, 0.9631), new CNumber(0.8007, 0.4023)}; + expIndices = new int[][]{ + {0, 0, 0, 0}, + {0, 1, 2, 7}, + {2, 0, 1, 4}, + {2, 0, 2, 11}, + {2, 1, 1, 10}, + {2, 1, 3, 6}, + {4, 0, 1, 7}, + {6, 0, 0, 8}, + {6, 0, 0, 10}, + {7, 1, 2, 12}, + {8, 0, 0, 6}, + {9, 0, 0, 2}, + {9, 1, 0, 1}, + {12, 0, 2, 10}, + {12, 0, 3, 7}, + {14, 0, 0, 8}, + {14, 0, 2, 6}, + {14, 1, 3, 13}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.reshape(15, 2, 4, 15)); + + // ----------------------------- Sub-case 3 ----------------------------- + aShape = new Shape(3, 16); + aShape = new Shape(3, 16); + aEntries = new CNumber[]{new CNumber(0.5938, 0.762), new CNumber(0.4295, 0.7988), new CNumber(0.0332, 0.3233), new CNumber(0.7022, 0.1686), new CNumber(0.7114, 0.6353), new CNumber(0.5935, 0.0851), new CNumber(0.7148, 0.5695)}; + aIndices = new int[][]{ + {1, 5}, + {1, 14}, + {1, 15}, + {2, 0}, + {2, 2}, + {2, 3}, + {2, 10}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + expShape = new Shape(2, 4, 3, 2); + expEntries = new CNumber[]{new CNumber(0.5938, 0.762), new CNumber(0.4295, 0.7988), new CNumber(0.0332, 0.3233), new CNumber(0.7022, 0.1686), new CNumber(0.7114, 0.6353), new CNumber(0.5935, 0.0851), new CNumber(0.7148, 0.5695)}; + expIndices = new int[][]{ + {0, 3, 1, 1}, + {1, 1, 0, 0}, + {1, 1, 0, 1}, + {1, 1, 1, 0}, + {1, 1, 2, 0}, + {1, 1, 2, 1}, + {1, 3, 0, 0}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.reshape(2, 4, 3, 2)); + + // ----------------------------- Sub-case 4 ----------------------------- + assertThrows(IllegalArgumentException.class, ()->A.reshape(150, 12)); + } + + + @Test + void flattenTests() { + // -------------------------- Sub-case 1 -------------------------- + aShape = new Shape(3, 16); + aEntries = new CNumber[]{ + new CNumber(1, -2), new CNumber(9.145, 0.00013), + new CNumber(234), new CNumber(0, 15)}; + aIndices = new int[][]{ + {0, 4}, + {0, 7}, + {1, 9}, + {2, 10}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + expShape = new Shape(48); + expEntries = new CNumber[]{new CNumber(1, -2), new CNumber(9.145, 0.00013), + new CNumber(234), new CNumber(0, 15)}; + expIndices = new int[][]{ + {4}, + {7}, + {25}, + {42}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.flatten()); + + // -------------------------- Sub-case 2 -------------------------- + aShape = new Shape(3, 2, 4); + aEntries = new CNumber[]{new CNumber(0, 15), new CNumber(0), new CNumber(-9, 154)}; + aIndices = new int[][]{ + {0, 1, 3}, + {1, 0, 1}, + {1, 1, 0}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + expShape = new Shape(24); + expEntries = new CNumber[]{new CNumber(0, 15), new CNumber(0), new CNumber(-9, 154)}; + expIndices = new int[][]{ + {7}, + {9}, + {12}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.flatten()); + + // -------------------------- Sub-case 3 -------------------------- + aShape = new Shape(3, 2, 4); + aEntries = new CNumber[]{new CNumber(0, 15), new CNumber(2), new CNumber(-9, 154)}; + aIndices = new int[][]{ + {1, 0, 1}, + {1, 1, 1}, + {2, 0, 1}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + expShape = new Shape(1, 24, 1); + expEntries = new CNumber[]{new CNumber(0, 15), new CNumber(2), new CNumber(-9, 154)}; + expIndices = new int[][]{ + {0, 9, 0}, + {0, 13, 0}, + {0, 17, 0}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.flatten(1)); + + // -------------------------- Sub-case 4 -------------------------- + aShape = new Shape(3, 2, 4); + aEntries = new CNumber[]{new CNumber(0, 15), new CNumber(234), new CNumber(-9, 154)}; + aIndices = new int[][]{ + {1, 0, 1}, + {1, 1, 1}, + {2, 0, 1}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + expShape = new Shape(1, 1, 24); + expEntries = new CNumber[]{new CNumber(0, 15), new CNumber(234), new CNumber(-9, 154)}; + expIndices = new int[][]{ + {0, 0, 9}, + {0, 0, 13}, + {0, 0, 17}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.flatten(2)); + + // -------------------------- Sub-case 5 -------------------------- + aShape = new Shape(3, 2, 4); + aEntries = new CNumber[]{new CNumber(0, 15), new CNumber(234), new CNumber(-9, 154)}; + aIndices = new int[][]{ + {1, 0, 1}, + {1, 1, 1}, + {2, 0, 1}}; + A = new CooCTensor(aShape, aEntries, aIndices); + assertThrows(IndexOutOfBoundsException.class, ()->A.flatten(5)); + assertThrows(IndexOutOfBoundsException.class, ()->A.flatten(-1)); + } +} diff --git a/src/test/java/org/flag4j/sparse_tensor/CooTensorReshapeTests.java b/src/test/java/org/flag4j/sparse_tensor/CooTensorReshapeTests.java new file mode 100644 index 000000000..f2dfe6567 --- /dev/null +++ b/src/test/java/org/flag4j/sparse_tensor/CooTensorReshapeTests.java @@ -0,0 +1,209 @@ +package org.flag4j.sparse_tensor; + +import org.flag4j.arrays.sparse.CooTensor; +import org.flag4j.core.Shape; +import org.junit.jupiter.api.Test; + +import static org.junit.Assert.assertThrows; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class CooTensorReshapeTests { + static CooTensor A; + static Shape aShape; + static double[] aEntries; + static int[][] aIndices; + + static CooTensor exp; + static Shape expShape; + static double[] expEntries; + static int[][] expIndices; + + @Test + void reshapeTests() { + // -------------------------- Sub-case 1 -------------------------- + aShape = new Shape(5, 4, 2, 1); + aEntries = new double[]{-0.2594625644447393, -0.11800739013805872, -1.8499182919471657}; + aIndices = new int[][]{ + {2, 2, 0, 0}, + {2, 3, 0, 0}, + {4, 1, 1, 0}}; + A = new CooTensor(aShape, aEntries, aIndices); + + expShape = new Shape(2, 5, 2, 2); + expEntries = new double[]{-0.2594625644447393, -0.11800739013805872, -1.8499182919471657}; + expIndices = new int[][]{ + {1, 0, 0, 0}, + {1, 0, 1, 0}, + {1, 3, 1, 1}}; + exp = new CooTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.reshape(2, 5, 2, 2)); + + // ----------------------------- Sub-case 2 ----------------------------- + aShape = new Shape(5, 4, 2, 3, 15); + aEntries = new double[]{-1.1499856217218563, -0.33276615768221923, -1.7712698524382784, 0.45988194186997083, -1.0000258840502727, -1.2896045900552038, -1.0495292341142137, 0.5653540034076624, 0.09844833075965526, 1.389726418783007, -0.03253455760212258, 0.8128434562240154, -0.5805363805458708, -0.9687145707590211, 0.005130776492485523, -1.1693463926292427, -0.18736097719279932, -0.588774063376806}; + aIndices = new int[][]{ + {0, 2, 1, 2, 8}, + {1, 0, 0, 0, 2}, + {1, 1, 0, 1, 9}, + {1, 2, 0, 2, 13}, + {1, 3, 1, 1, 3}, + {1, 3, 1, 1, 7}, + {2, 0, 0, 1, 9}, + {2, 2, 1, 0, 11}, + {2, 3, 1, 2, 10}, + {3, 0, 0, 1, 13}, + {3, 0, 1, 0, 6}, + {3, 1, 0, 0, 10}, + {3, 1, 1, 1, 9}, + {4, 0, 1, 0, 9}, + {4, 1, 1, 0, 14}, + {4, 2, 0, 0, 8}, + {4, 3, 0, 2, 6}, + {4, 3, 1, 2, 12}}; + A = new CooTensor(aShape, aEntries, aIndices); + + expShape = new Shape(15, 2, 4, 15); + expEntries = new double[]{-1.1499856217218563, -0.33276615768221923, -1.7712698524382784, 0.45988194186997083, -1.0000258840502727, -1.2896045900552038, -1.0495292341142137, 0.5653540034076624, 0.09844833075965526, 1.389726418783007, -0.03253455760212258, 0.8128434562240154, -0.5805363805458708, -0.9687145707590211, 0.005130776492485523, -1.1693463926292427, -0.18736097719279932, -0.588774063376806}; + expIndices = new int[][]{ + {2, 0, 1, 8}, + {3, 0, 0, 2}, + {3, 1, 3, 9}, + {4, 1, 2, 13}, + {5, 1, 2, 3}, + {5, 1, 2, 7}, + {6, 0, 1, 9}, + {7, 1, 3, 11}, + {8, 1, 3, 10}, + {9, 0, 1, 13}, + {9, 0, 3, 6}, + {9, 1, 2, 10}, + {10, 0, 2, 9}, + {12, 0, 3, 9}, + {13, 0, 1, 14}, + {13, 1, 0, 8}, + {14, 1, 0, 6}, + {14, 1, 3, 12}}; + exp = new CooTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.reshape(15, 2, 4, 15)); + + // ----------------------------- Sub-case 3 ----------------------------- + aShape = new Shape(3, 16); + aEntries = new double[]{-0.5564583772612858, 1.3880160320768695, -0.041746799108138805, 0.22670438356409295}; + aIndices = new int[][]{ + {0, 7}, + {0, 8}, + {0, 15}, + {1, 7}}; + A = new CooTensor(aShape, aEntries, aIndices); + + expShape = new Shape(2, 4, 3, 2); + expEntries = new double[]{-0.5564583772612858, 1.3880160320768695, -0.041746799108138805, 0.22670438356409295}; + expIndices = new int[][]{ + {0, 1, 0, 1}, + {0, 1, 1, 0}, + {0, 2, 1, 1}, + {0, 3, 2, 1}}; + exp = new CooTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.reshape(2, 4, 3, 2)); + + // ----------------------------- Sub-case 4 ----------------------------- + aShape = new Shape(3, 16); + aEntries = new double[]{-0.5564583772612858, 1.3880160320768695, -0.041746799108138805, 0.22670438356409295}; + aIndices = new int[][]{ + {0, 7}, + {0, 8}, + {0, 15}, + {1, 7}}; + A = new CooTensor(aShape, aEntries, aIndices); + assertThrows(IllegalArgumentException.class, ()->A.reshape(150, 12)); + } + + + @Test + void flattenTests() { + // -------------------------- Sub-case 1 -------------------------- + aShape = new Shape(3, 16); + aEntries = new double[]{-0.4396095255063526, -0.008544443239199374, 1.6354416874939133, -0.7535470743266395}; + aIndices = new int[][]{ + {0, 4}, + {0, 7}, + {1, 9}, + {2, 10}}; + A = new CooTensor(aShape, aEntries, aIndices); + + expShape = new Shape(48); + expEntries = new double[]{-0.4396095255063526, -0.008544443239199374, 1.6354416874939133, -0.7535470743266395}; + expIndices = new int[][]{ + {4}, + {7}, + {25}, + {42}}; + exp = new CooTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.flatten()); + + // -------------------------- Sub-case 2 -------------------------- + aShape = new Shape(3, 2, 4); + aEntries = new double[]{0.8809801303815625, 1.2884192212811383, 0.6540684159095426}; + aIndices = new int[][]{ + {0, 1, 3}, + {1, 0, 1}, + {1, 1, 0}}; + A = new CooTensor(aShape, aEntries, aIndices); + + expShape = new Shape(24); + expEntries = new double[]{0.8809801303815625, 1.2884192212811383, 0.6540684159095426}; + expIndices = new int[][]{ + {7}, + {9}, + {12}}; + exp = new CooTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.flatten()); + + // -------------------------- Sub-case 3 -------------------------- + aShape = new Shape(3, 2, 4); + aEntries = new double[]{-0.2100281314624281, 1.4401356481011265, -0.1396976427551165}; + aIndices = new int[][]{ + {1, 0, 1}, + {1, 1, 1}, + {2, 0, 1}}; + A = new CooTensor(aShape, aEntries, aIndices); + + expShape = new Shape(1, 24, 1); + expEntries = new double[]{-0.2100281314624281, 1.4401356481011265, -0.1396976427551165}; + expIndices = new int[][]{ + {0, 9, 0}, + {0, 13, 0}, + {0, 17, 0}}; + exp = new CooTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.flatten(1)); + + // -------------------------- Sub-case 4 -------------------------- + aShape = new Shape(3, 2, 4); + aEntries = new double[]{-0.2100281314624281, 1.4401356481011265, -0.1396976427551165}; + aIndices = new int[][]{ + {1, 0, 1}, + {1, 1, 1}, + {2, 0, 1}}; + A = new CooTensor(aShape, aEntries, aIndices); + + expShape = new Shape(1, 1, 24); + expEntries = new double[]{-0.2100281314624281, 1.4401356481011265, -0.1396976427551165}; + expIndices = new int[][]{ + {0, 0, 9}, + {0, 0, 13}, + {0, 0, 17}}; + exp = new CooTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.flatten(2)); + + // -------------------------- Sub-case 5 -------------------------- + aShape = new Shape(3, 2, 4); + aEntries = new double[]{-0.2100281314624281, 1.4401356481011265, -0.1396976427551165}; + aIndices = new int[][]{ + {1, 0, 1}, + {1, 1, 1}, + {2, 0, 1}}; + A = new CooTensor(aShape, aEntries, aIndices); + assertThrows(IndexOutOfBoundsException.class, ()->A.flatten(5)); + assertThrows(IndexOutOfBoundsException.class, ()->A.flatten(-1)); + } +} diff --git a/src/test/java/org/flag4j/sparse_tensor/CooTensorTransposeTests.java b/src/test/java/org/flag4j/sparse_tensor/CooTensorTransposeTests.java new file mode 100644 index 000000000..b875ee008 --- /dev/null +++ b/src/test/java/org/flag4j/sparse_tensor/CooTensorTransposeTests.java @@ -0,0 +1,147 @@ +package org.flag4j.sparse_tensor; + +import org.flag4j.arrays.sparse.CooTensor; +import org.flag4j.core.Shape; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class CooTensorTransposeTests { + static CooTensor A; + static Shape aShape; + static double[] aEntries; + static int[][] aIndices; + + static CooTensor exp; + static Shape expShape; + static double[] expEntries; + static int[][] expIndices; + + @Test + void transposeTests() { + // ----------------------- Sub-case 1 ----------------------- + aShape = new Shape(3, 4, 2, 1, 5); + aEntries = new double[]{0.3369876012099134, -1.2778944176165061, 0.3003526634585191, -2.871698370528301, -0.7476330328637798, 0.0005862743350540067, 0.27050784380653264, -0.8804057494085602, 0.3433759561302188, -0.6271337465977211, -0.535101554634142, -1.9109729935630098, 0.7218896402785697, 0.8404528180001959, 0.5203214826154133, 0.3371173022767966, -0.6726729311708143, 0.08353784066932919}; + aIndices = new int[][]{ + {0, 0, 1, 0, 1}, + {0, 1, 1, 0, 4}, + {0, 2, 0, 0, 0}, + {0, 2, 1, 0, 1}, + {0, 3, 0, 0, 2}, + {1, 1, 0, 0, 0}, + {1, 1, 1, 0, 0}, + {1, 1, 1, 0, 2}, + {1, 2, 1, 0, 0}, + {1, 2, 1, 0, 4}, + {2, 0, 0, 0, 0}, + {2, 0, 0, 0, 4}, + {2, 0, 1, 0, 4}, + {2, 1, 0, 0, 0}, + {2, 1, 1, 0, 1}, + {2, 1, 1, 0, 3}, + {2, 1, 1, 0, 4}, + {2, 3, 0, 0, 2}}; + A = new CooTensor(aShape, aEntries, aIndices); + + expShape = new Shape(5, 4, 2, 1, 3); + expEntries = new double[]{-0.535101554634142, 0.0005862743350540067, 0.8404528180001959, 0.27050784380653264, 0.3003526634585191, 0.3433759561302188, 0.3369876012099134, 0.5203214826154133, -2.871698370528301, -0.8804057494085602, -0.7476330328637798, 0.08353784066932919, 0.3371173022767966, -1.9109729935630098, 0.7218896402785697, -1.2778944176165061, -0.6726729311708143, -0.6271337465977211}; + expIndices = new int[][]{ + {0, 0, 0, 0, 2}, + {0, 1, 0, 0, 1}, + {0, 1, 0, 0, 2}, + {0, 1, 1, 0, 1}, + {0, 2, 0, 0, 0}, + {0, 2, 1, 0, 1}, + {1, 0, 1, 0, 0}, + {1, 1, 1, 0, 2}, + {1, 2, 1, 0, 0}, + {2, 1, 1, 0, 1}, + {2, 3, 0, 0, 0}, + {2, 3, 0, 0, 2}, + {3, 1, 1, 0, 2}, + {4, 0, 0, 0, 2}, + {4, 0, 1, 0, 2}, + {4, 1, 1, 0, 0}, + {4, 1, 1, 0, 2}, + {4, 2, 1, 0, 1}}; + exp = new CooTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.T()); + + // ----------------------- Sub-case 2 ----------------------- + aShape = new Shape(3, 4, 2, 1, 5); + aEntries = new double[]{0.5495928325292689, -0.4063964781150276, -2.059856306563159, 0.21626315719045072, 0.700470594502127, -0.9551549318514719, 0.20625241662218816, -0.002902831572102285, 0.027379206391192006, -0.048618618464467335, -0.062183293526625626}; + aIndices = new int[][]{ + {0, 1, 0, 0, 1}, + {0, 1, 0, 0, 2}, + {0, 1, 1, 0, 3}, + {1, 0, 1, 0, 0}, + {1, 1, 0, 0, 0}, + {1, 2, 0, 0, 1}, + {2, 0, 1, 0, 1}, + {2, 0, 1, 0, 3}, + {2, 0, 1, 0, 4}, + {2, 1, 1, 0, 3}, + {2, 2, 1, 0, 1}}; + A = new CooTensor(aShape, aEntries, aIndices); + + expShape = new Shape(2, 4, 3, 1, 5); + expEntries = new double[]{0.5495928325292689, -0.4063964781150276, 0.700470594502127, -0.9551549318514719, 0.21626315719045072, 0.20625241662218816, -0.002902831572102285, 0.027379206391192006, -2.059856306563159, -0.048618618464467335, -0.062183293526625626}; + expIndices = new int[][]{ + {0, 1, 0, 0, 1}, + {0, 1, 0, 0, 2}, + {0, 1, 1, 0, 0}, + {0, 2, 1, 0, 1}, + {1, 0, 1, 0, 0}, + {1, 0, 2, 0, 1}, + {1, 0, 2, 0, 3}, + {1, 0, 2, 0, 4}, + {1, 1, 0, 0, 3}, + {1, 1, 2, 0, 3}, + {1, 2, 2, 0, 1}}; + exp = new CooTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.T(0, 2)); + assertEquals(exp, A.T(2, 0)); + + // ----------------------- Sub-case 3 ----------------------- + aShape = new Shape(3, 4, 2, 1, 5); + aEntries = new double[]{0.7755080687938627, -0.35048451266628083, -1.1870851252844012, 0.7738863613063384, 1.486547192285357, 0.2252740863565129, -0.2975058226231608, -0.09472050340155494, -0.15340207810250436, 2.84248590850813, -1.7279407634814916}; + aIndices = new int[][]{ + {0, 1, 0, 0, 2}, + {0, 1, 0, 0, 3}, + {0, 1, 1, 0, 2}, + {0, 3, 1, 0, 1}, + {1, 0, 0, 0, 2}, + {1, 1, 1, 0, 0}, + {2, 0, 0, 0, 0}, + {2, 0, 0, 0, 3}, + {2, 3, 0, 0, 0}, + {2, 3, 0, 0, 1}, + {2, 3, 1, 0, 0}}; + A = new CooTensor(aShape, aEntries, aIndices); + + expShape = new Shape(3, 1, 5, 4, 2); + expEntries = new double[]{0.7738863613063384, 0.7755080687938627, -1.1870851252844012, -0.35048451266628083, 0.2252740863565129, 1.486547192285357, -0.2975058226231608, -0.15340207810250436, -1.7279407634814916, 2.84248590850813, -0.09472050340155494}; + expIndices = new int[][]{ + {0, 0, 1, 3, 1}, + {0, 0, 2, 1, 0}, + {0, 0, 2, 1, 1}, + {0, 0, 3, 1, 0}, + {1, 0, 0, 1, 1}, + {1, 0, 2, 0, 0}, + {2, 0, 0, 0, 0}, + {2, 0, 0, 3, 0}, + {2, 0, 0, 3, 1}, + {2, 0, 1, 3, 0}, + {2, 0, 3, 0, 0}}; + exp = new CooTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.T(0, 3, 4, 1, 2)); + + // ----------------------- Sub-case 4 ----------------------- + assertThrows(IllegalArgumentException.class, ()->A.T(0, 1, 3, 2)); + assertThrows(IllegalArgumentException.class, ()->A.T(0, 3, 4, 1, 2, 5)); + assertThrows(IllegalArgumentException.class, ()->A.T(0, 3, -4, 1, 2)); + assertThrows(IllegalArgumentException.class, ()->A.T(0, 15, 4, 1, 2)); + assertThrows(IndexOutOfBoundsException.class, ()->A.T(5, 1)); + } +} diff --git a/target/flag4j-v0.1.0-beta.jar b/target/flag4j-v0.1.0-beta.jar index 26451c1f65c60a3f5e830f006de4cf8f000952a7..2c1d72bc94a95831f2d644265b6fa173f825555a 100644 GIT binary patch delta 25412 zcmZsD1z1#Vw>HcSFhh4q2uOD~NOzZXcStJ|Bdv4~ARyfcNQWRHNSA^jDIwh|BIrM} zeb4uu_guf%z*^6`SFdO98Qin?=VaE&R90MF4KM^74GoHhmRpsI%M3#P7Q6xFRHgHy z3!#WJx-g0qpo^l&0=giI;DWgR3h5ELJ0Sf3Fg8k>02V~hdxA02pZ?EU9wnXz-$yA=g9V9ve0l$yT22+NY5ExS4$1|h;3*6< zJrM%<$$`kB4CJ7Hy%S&%quelI2%v}wh6suzV@RRM1cu7r6&J!g9)|h9az=uNm@+6Z z0~0WOk138?Nk7E}@-~NwAf6IoVd4F&NTfC(CQN^dhn+qQB}|{kq|Q>o!uoe08ysnr zPdO+X5+h01fdMXWaQP4^D_GEUy1yar;{j_dgf|HkmL3AdPWQ)^{l^Y59SSA+pImNm zf!^Q8Q%9i*c$_GL3!+7wsK7ANKjQ)33()_r5p+WTsynwT{VqNya@VA5;ftV1G`=)) zB29z%Dq1LtX8|E4$VQIu&RepJLpn4xL3_0H8GO1X8E+6hN^ZAgct|n=0?mX z$EEv$fvW$l1Iwf)p-&YKPrIQxBF@;YF|MWg3wbfL#kj7eHITQ(t>&XwYha5}&G}2e zwHLz<=P})iaN&#Nu9H>2sh^V_Ukm(JFFFY5C80K{HG^0bwokZLOO8QR%}^`!RA`VC>h;l@Ti2X$4pTSTkspTAEANY8 z{*0n>y@)t_eA*o~LefNH?%^$Wde4EX|BCD27eBRq2%NH}1Z@+F(OLp6>5OX|g zohie`Vr`b>IiEUne>w$;KdBvKA4S~xQ{4!@SFZNnehnNnHEuZX2KrPVyL(&S6IzS4 z>*rDd{gTV(n$}@x*PzDTsMyO+qU!b*>dd^K7?d5oC^J5z7op#;+Tx-kKvU(0&6*~~ zPqa#{9|Er~LZ{uXw2?_~jER-ut0^DwZQcBSC)HN22

vJ5_F6?b8w{>uzP=^MsJ#d*s{O!&w>l_t;9l?p2bxUqqMCZUh#szmt;X z@QI-RCbk%>v-{wgQq;}(UR2(suCLF%Y@3GR%aVGy1XT|v*O_fqlFk>>{s^H#`<0@{ zd{jwF+D zVvQq){@2MqRWX>Rnkw;0j>WR{3ZJMGywZB+{F{ptJ>&W~xLrNC0u*PG=Ne~Y1^q*) zYoG?R@EtZz3%UfXF8LANkh2)wUo6TzF9S&8SWV88c3lzzqgn~$n#3^|&%$c^oI@Ve zY-;9Zz6L9qQSljE#%PvZsm}|YlVA3Yq-sM?|wdft=v_|x~v#5I4HTz zzdxdE-=_LUT;hw3T(crujw`}6h&sYI*xzHQqx&818}7K_2->4QMg4B7jdqVu4twNm z$|Xu+t@~p16ofY(k>w_2vL+ns$wNvKGV$?2YdQEIg~$kM+70pA4Tl{+vD^{N!d1>H zT|S0KWw7pIvxpjUV?Pp6PA}5l)~bJ-DPvJ)-}T`4gD$x!qK(RICmolOESq5c`3~jU zbu+*1%!v12{VkI3a4C{HC(bA}7P!PduvfEJ-?X0gVe+yonvdPCJr%(CwnZK?6KfuD z_||jaRHK$&K^l+W__5cy>aV=y8H37v2f^2oaQch;WB2_-)P`w4jp(=5SPE4PR(WFh zR3z2gAZYZzVs<6oy5AL|w*KfNdc1MVo=omV^pV_AqAX11YOmd7ctO#ivxs8AXe_e+ z;1d&pG8I8q>=#REwdkhWOD)sAFoxb8wk`U%kup-Ho3>K&F4Tt3XS#g8#_B$GA?a1! zj_`S*)y}>oeEA>4g>ODQ|Dp^2HT`v^W`0MPe!yfCYCw&3wy

ej|^#4cO-G1ZXBZFbB}x9 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 delta 24858 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 BwF>|M From 3877f84ae2104418f6496dc04d8b61f8bdedb5bd Mon Sep 17 00:00:00 2001 From: jacob Date: Mon, 12 Aug 2024 21:27:43 -0600 Subject: [PATCH 05/10] Add tests for sparse tensors. --- .../sparse_tensor/CooTensorToStringTests.java | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/test/java/org/flag4j/sparse_tensor/CooTensorToStringTests.java diff --git a/src/test/java/org/flag4j/sparse_tensor/CooTensorToStringTests.java b/src/test/java/org/flag4j/sparse_tensor/CooTensorToStringTests.java new file mode 100644 index 000000000..398d81b5c --- /dev/null +++ b/src/test/java/org/flag4j/sparse_tensor/CooTensorToStringTests.java @@ -0,0 +1,91 @@ +package org.flag4j.sparse_tensor; + +import org.flag4j.arrays.sparse.CooTensor; +import org.flag4j.core.Shape; +import org.flag4j.io.PrintOptions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class CooTensorToStringTests { + + static CooTensor A; + static Shape aShape; + static double[] aEntries; + static int[][] aIndices; + + String exp; + + @AfterEach + void reset() { + PrintOptions.resetAll(); + } + + @Test + void cooTensorToStringTests() { + // ----------------------- Sub-case 1 ----------------------- + aShape = new Shape(3, 4, 2, 1, 5); + aEntries = new double[]{0.3369876012099134, -1.2778944176165061, 0.3003526634585191, -2.871698370528301, -0.7476330328637798, 0.0005862743350540067, 0.27050784380653264, -0.8804057494085602, 0.3433759561302188, -0.6271337465977211, -0.535101554634142, -1.9109729935630098, 0.7218896402785697, 0.8404528180001959, 0.5203214826154133, 0.3371173022767966, -0.6726729311708143, 0.08353784066932919}; + aIndices = new int[][]{ + {0, 0, 1, 0, 1}, + {0, 1, 1, 0, 4}, + {0, 2, 0, 0, 0}, + {0, 2, 1, 0, 1}, + {0, 3, 0, 0, 2}, + {1, 1, 0, 0, 0}, + {1, 1, 1, 0, 0}, + {1, 1, 1, 0, 2}, + {1, 2, 1, 0, 0}, + {1, 2, 1, 0, 4}, + {2, 0, 0, 0, 0}, + {2, 0, 0, 0, 4}, + {2, 0, 1, 0, 4}, + {2, 1, 0, 0, 0}, + {2, 1, 1, 0, 1}, + {2, 1, 1, 0, 3}, + {2, 1, 1, 0, 4}, + {2, 3, 0, 0, 2}}; + A = new CooTensor(aShape, aEntries, aIndices); + + exp = "Shape: (3, 4, 2, 1, 5)\n" + + "Non-zero Entries: [ 0.3369876 -1.27789442 0.30035266 -2.87169837 -0.74763303 5.8627E-4 0.27050784 -0.88040575 0.34337596 ... 0.08353784 ]\n" + + "Non-zero Indices: [ [ 0 0 1 0 1 ] \n" + + " [ 0 1 1 0 4 ] \n" + + " [ 0 2 0 0 0 ] \n" + + " [ 0 2 1 0 1 ] \n" + + " [ 0 3 0 0 2 ] \n" + + " [ 1 1 0 0 0 ] \n" + + " [ 1 1 1 0 0 ] \n" + + " [ 1 1 1 0 2 ] \n" + + " [ 1 2 1 0 0 ] \n" + + " ... \n" + + " [ 2 3 0 0 2 ] ]"; + assertEquals(exp, A.toString()); + + // ----------------------- Sub-case 2 ----------------------- + PrintOptions.setMaxRows(15); + PrintOptions.setMaxColumns(3); + PrintOptions.setPrecision(3); + + exp = "Shape: (3, 4, 2, 1, 5)\n" + + "Non-zero Entries: [ 0.337 -1.278 ... 0.084 ]\n" + + "Non-zero Indices: [ [ 0 0 ... 1 ] \n" + + " [ 0 1 ... 4 ] \n" + + " [ 0 2 ... 0 ] \n" + + " [ 0 2 ... 1 ] \n" + + " [ 0 3 ... 2 ] \n" + + " [ 1 1 ... 0 ] \n" + + " [ 1 1 ... 0 ] \n" + + " [ 1 1 ... 2 ] \n" + + " [ 1 2 ... 0 ] \n" + + " [ 1 2 ... 4 ] \n" + + " [ 2 0 ... 0 ] \n" + + " [ 2 0 ... 4 ] \n" + + " [ 2 0 ... 4 ] \n" + + " [ 2 1 ... 0 ] \n" + + " ... \n" + + " [ 2 3 ... 2 ] ]"; + assertEquals(exp, A.toString()); + } +} From 2c161ffe5413e045b5a48e580bfce96a58a9c5b5 Mon Sep 17 00:00:00 2001 From: jacob Date: Mon, 12 Aug 2024 21:34:19 -0600 Subject: [PATCH 06/10] Add tests for sparse tensors. --- .../CooCTensorToStringTests.java | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/test/java/org/flag4j/sparse_complex_tensor/CooCTensorToStringTests.java diff --git a/src/test/java/org/flag4j/sparse_complex_tensor/CooCTensorToStringTests.java b/src/test/java/org/flag4j/sparse_complex_tensor/CooCTensorToStringTests.java new file mode 100644 index 000000000..43e5f8934 --- /dev/null +++ b/src/test/java/org/flag4j/sparse_complex_tensor/CooCTensorToStringTests.java @@ -0,0 +1,92 @@ +package org.flag4j.sparse_complex_tensor; + +import org.flag4j.arrays.sparse.CooCTensor; +import org.flag4j.complex_numbers.CNumber; +import org.flag4j.core.Shape; +import org.flag4j.io.PrintOptions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class CooCTensorToStringTests { + + static CooCTensor A; + static Shape aShape; + static CNumber[] aEntries; + static int[][] aIndices; + + String exp; + + @AfterEach + void reset() { + PrintOptions.resetAll(); + } + + @Test + void cooCTensorToStringTests() { + // ----------------------- Sub-case 1 ----------------------- + aShape = new Shape(5, 4, 2, 3, 15); + aEntries = new CNumber[]{new CNumber(0.8103, 0.0203), new CNumber(0.5684, 0.4151), new CNumber(0.9044, 0.8734), new CNumber(0.201, 0.7032), new CNumber(0.9682, 0.2723), new CNumber(0.4699, 0.8203), new CNumber(0.3871, 0.3395), new CNumber(0.7851, 0.3768), new CNumber(0.2315, 0.7695), new CNumber(0.8333, 0.8837), new CNumber(0.0398, 0.559), new CNumber(0.0405, 0.9707), new CNumber(0.488, 0.8343), new CNumber(0.2441, 0.7806), new CNumber(0.3995, 0.6793), new CNumber(0.3689, 0.6126), new CNumber(0.0767, 0.9631), new CNumber(0.8007, 0.4023)}; + aIndices = new int[][]{ + {0, 0, 0, 0, 0}, + {0, 1, 0, 0, 7}, + {0, 2, 1, 2, 4}, + {0, 3, 0, 0, 11}, + {0, 3, 1, 0, 10}, + {0, 3, 1, 2, 6}, + {1, 1, 1, 0, 7}, + {2, 0, 0, 0, 8}, + {2, 0, 0, 0, 10}, + {2, 2, 0, 2, 12}, + {2, 2, 1, 1, 6}, + {3, 0, 0, 0, 2}, + {3, 0, 1, 1, 1}, + {4, 0, 0, 2, 10}, + {4, 0, 1, 0, 7}, + {4, 2, 1, 1, 8}, + {4, 3, 0, 0, 6}, + {4, 3, 1, 2, 13}}; + A = new CooCTensor(aShape, aEntries, aIndices); + + exp = "Shape: (5, 4, 2, 3, 15)\n" + + "Non-zero Entries: [ 0.8103 + 0.0203i 0.5684 + 0.4151i 0.9044 + 0.8734i 0.201 + 0.7032i 0.9682 + 0.2723i 0.4699 + 0.8203i 0.3871 + 0.3395i 0.7851 + 0.3768i 0.2315 + 0.7695i ... 0.8007 + 0.4023i ]\n" + + "Non-zero Indices: [ [ 0 0 0 0 0 ] \n" + + " [ 0 1 0 0 7 ] \n" + + " [ 0 2 1 2 4 ] \n" + + " [ 0 3 0 0 11 ] \n" + + " [ 0 3 1 0 10 ] \n" + + " [ 0 3 1 2 6 ] \n" + + " [ 1 1 1 0 7 ] \n" + + " [ 2 0 0 0 8 ] \n" + + " [ 2 0 0 0 10 ] \n" + + " ... \n" + + " [ 4 3 1 2 13 ] ]"; + assertEquals(exp, A.toString()); + + // ----------------------- Sub-case 2 ----------------------- + PrintOptions.setMaxRows(15); + PrintOptions.setMaxColumns(3); + PrintOptions.setPrecision(3); + + exp = "Shape: (5, 4, 2, 3, 15)\n" + + "Non-zero Entries: [ 0.81 + 0.02i 0.568 + 0.415i ... 0.801 + 0.402i ]\n" + + "Non-zero Indices: [ [ 0 0 ... 0 ] \n" + + " [ 0 1 ... 7 ] \n" + + " [ 0 2 ... 4 ] \n" + + " [ 0 3 ... 11 ] \n" + + " [ 0 3 ... 10 ] \n" + + " [ 0 3 ... 6 ] \n" + + " [ 1 1 ... 7 ] \n" + + " [ 2 0 ... 8 ] \n" + + " [ 2 0 ... 10 ] \n" + + " [ 2 2 ... 12 ] \n" + + " [ 2 2 ... 6 ] \n" + + " [ 3 0 ... 2 ] \n" + + " [ 3 0 ... 1 ] \n" + + " [ 4 0 ... 10 ] \n" + + " ... \n" + + " [ 4 3 ... 13 ] ]"; + assertEquals(exp, A.toString()); + } +} From eeee0733723a84e064a87fb3832ac04c00793c2f Mon Sep 17 00:00:00 2001 From: jacob Date: Mon, 12 Aug 2024 21:36:16 -0600 Subject: [PATCH 07/10] Add tests for sparse tensors. --- src/main/java/org/flag4j/io/PrintOptions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/flag4j/io/PrintOptions.java b/src/main/java/org/flag4j/io/PrintOptions.java index 2d2e650e0..678c3b1f9 100644 --- a/src/main/java/org/flag4j/io/PrintOptions.java +++ b/src/main/java/org/flag4j/io/PrintOptions.java @@ -30,7 +30,7 @@ /** * Print options for matrices and vectors */ -public abstract class PrintOptions { +public final class PrintOptions { /** * Default padding between elements when printing. From 30949bbb3b8edbd26f84cdb68976941a63893dfe Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 13 Aug 2024 18:02:11 -0600 Subject: [PATCH 08/10] Add tests for sparse tensors. --- .../RealComplexCooTensorBinOpsTests.java | 141 ++++++++++++++++++ target/flag4j-v0.1.0-beta.jar | Bin 641230 -> 641230 bytes 2 files changed, 141 insertions(+) create mode 100644 src/test/java/org/flag4j/sparse_tensor/RealComplexCooTensorBinOpsTests.java diff --git a/src/test/java/org/flag4j/sparse_tensor/RealComplexCooTensorBinOpsTests.java b/src/test/java/org/flag4j/sparse_tensor/RealComplexCooTensorBinOpsTests.java new file mode 100644 index 000000000..4c5e763e3 --- /dev/null +++ b/src/test/java/org/flag4j/sparse_tensor/RealComplexCooTensorBinOpsTests.java @@ -0,0 +1,141 @@ +package org.flag4j.sparse_tensor; + +import org.flag4j.arrays.sparse.CooCTensor; +import org.flag4j.arrays.sparse.CooTensor; +import org.flag4j.complex_numbers.CNumber; +import org.flag4j.core.Shape; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class RealComplexCooTensorBinOpsTests { + + CooTensor A; + Shape aShape; + double[] aEntries; + int[][] aIndices; + + CooCTensor B; + Shape bShape; + CNumber[] bEntries; + int[][] bIndices; + + CooCTensor exp; + Shape expShape; + CNumber[] expEntries; + int[][] expIndices; + + @Test + void addTests() { + // -------------------------- Sub-case 1 -------------------------- + aShape = new Shape(3, 16); + aEntries = new double[]{1.7463475926857943, -1.130295792343086, -1.4629436086045846, -0.3100760165046801, -0.09665657433974414, 0.13476509808719928, -0.0638077132075331}; + aIndices = new int[][]{ + {0, 2}, + {0, 13}, + {0, 15}, + {1, 5}, + {1, 13}, + {2, 1}, + {2, 3}}; + A = new CooTensor(aShape, aEntries, aIndices); + + bShape = new Shape(3, 16); + bEntries = new CNumber[]{new CNumber(0.318, 0.9927), new CNumber(0.3394, 0.6087), new CNumber(0.2087, 0.4036), new CNumber(0.8053, 0.9675), new CNumber(0.474, 0.0026), new CNumber(0.1479, 0.0052), new CNumber(0.0073, 0.7328)}; + bIndices = new int[][]{ + {0, 9}, + {0, 12}, + {1, 3}, + {1, 4}, + {2, 6}, + {2, 9}, + {2, 11}}; + B = new CooCTensor(bShape, bEntries, bIndices); + + expShape = new Shape(3, 16); + expEntries = new CNumber[]{new CNumber(1.7463475926857943, 0.0), new CNumber(0.318, 0.9927), new CNumber(0.3394, 0.6087), new CNumber(-1.130295792343086, 0.0), new CNumber(-1.4629436086045846, 0.0), new CNumber(0.2087, 0.4036), new CNumber(0.8053, 0.9675), new CNumber(-0.3100760165046801, 0.0), new CNumber(-0.09665657433974414, 0.0), new CNumber(0.13476509808719928, 0.0), new CNumber(-0.0638077132075331, 0.0), new CNumber(0.474, 0.0026), new CNumber(0.1479, 0.0052), new CNumber(0.0073, 0.7328)}; + expIndices = new int[][]{ + {0, 2}, + {0, 9}, + {0, 12}, + {0, 13}, + {0, 15}, + {1, 3}, + {1, 4}, + {1, 5}, + {1, 13}, + {2, 1}, + {2, 3}, + {2, 6}, + {2, 9}, + {2, 11}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + + assertEquals(exp, A.add(B)); + + // -------------------------- Sub-case 1 -------------------------- + aShape = new Shape(5, 3, 2, 1, 8); + aEntries = new double[]{1.605979015236944, -1.2944465840036907, 0.18895750482591192, -0.7307330521229386, -0.4500047202309869, -0.2760206404103061, -0.05495875438029267, 0.4398947793476673, 1.485028116781792, 2.0853070263385405, -1.295509717819037, -0.19473190000656226}; + aIndices = new int[][]{ + {0, 0, 0, 0, 2}, + {1, 0, 0, 0, 6}, + {1, 1, 1, 0, 1}, + {2, 1, 1, 0, 5}, + {2, 2, 0, 0, 2}, + {2, 2, 0, 0, 4}, + {2, 2, 1, 0, 1}, + {3, 0, 0, 0, 6}, + {3, 1, 0, 0, 6}, + {3, 1, 1, 0, 0}, + {3, 2, 0, 0, 0}, + {4, 2, 0, 0, 0}}; + A = new CooTensor(aShape, aEntries, aIndices); + + bShape = new Shape(5, 3, 2, 1, 8); + bEntries = new CNumber[]{new CNumber(0.2165, 0.1597), new CNumber(0.2, 0.8495), new CNumber(0.6178, 0.9117), new CNumber(0.7567, 0.522), new CNumber(0.5328, 0.1192), new CNumber(0.0001, 0.3608), new CNumber(0.8431, 0.8437), new CNumber(0.9877, 0.5206), new CNumber(0.2649, 0.8721), new CNumber(0.1699, 0.1777), new CNumber(0.1255, 0.0734), new CNumber(0.0357, 0.9614)}; + bIndices = new int[][]{ + {0, 1, 0, 0, 0}, + {0, 1, 0, 0, 2}, + {0, 1, 1, 0, 1}, + {1, 2, 1, 0, 5}, + {2, 1, 0, 0, 5}, + {3, 1, 0, 0, 5}, + {3, 1, 0, 0, 7}, + {3, 1, 1, 0, 3}, + {3, 2, 1, 0, 7}, + {4, 1, 0, 0, 7}, + {4, 2, 1, 0, 2}, + {4, 2, 1, 0, 3}}; + B = new CooCTensor(bShape, bEntries, bIndices); + + expShape = new Shape(5, 3, 2, 1, 8); + expEntries = new CNumber[]{new CNumber(1.605979015236944, 0.0), new CNumber(0.2165, 0.1597), new CNumber(0.2, 0.8495), new CNumber(0.6178, 0.9117), new CNumber(-1.2944465840036907, 0.0), new CNumber(0.18895750482591192, 0.0), new CNumber(0.7567, 0.522), new CNumber(0.5328, 0.1192), new CNumber(-0.7307330521229386, 0.0), new CNumber(-0.4500047202309869, 0.0), new CNumber(-0.2760206404103061, 0.0), new CNumber(-0.05495875438029267, 0.0), new CNumber(0.4398947793476673, 0.0), new CNumber(0.0001, 0.3608), new CNumber(1.485028116781792, 0.0), new CNumber(0.8431, 0.8437), new CNumber(2.0853070263385405, 0.0), new CNumber(0.9877, 0.5206), new CNumber(-1.295509717819037, 0.0), new CNumber(0.2649, 0.8721), new CNumber(0.1699, 0.1777), new CNumber(-0.19473190000656226, 0.0), new CNumber(0.1255, 0.0734), new CNumber(0.0357, 0.9614)}; + expIndices = new int[][]{ + {0, 0, 0, 0, 2}, + {0, 1, 0, 0, 0}, + {0, 1, 0, 0, 2}, + {0, 1, 1, 0, 1}, + {1, 0, 0, 0, 6}, + {1, 1, 1, 0, 1}, + {1, 2, 1, 0, 5}, + {2, 1, 0, 0, 5}, + {2, 1, 1, 0, 5}, + {2, 2, 0, 0, 2}, + {2, 2, 0, 0, 4}, + {2, 2, 1, 0, 1}, + {3, 0, 0, 0, 6}, + {3, 1, 0, 0, 5}, + {3, 1, 0, 0, 6}, + {3, 1, 0, 0, 7}, + {3, 1, 1, 0, 0}, + {3, 1, 1, 0, 3}, + {3, 2, 0, 0, 0}, + {3, 2, 1, 0, 7}, + {4, 1, 0, 0, 7}, + {4, 2, 0, 0, 0}, + {4, 2, 1, 0, 2}, + {4, 2, 1, 0, 3}}; + exp = new CooCTensor(expShape, expEntries, expIndices); + assertEquals(exp, A.add(B)); + } +} diff --git a/target/flag4j-v0.1.0-beta.jar b/target/flag4j-v0.1.0-beta.jar index 2c1d72bc94a95831f2d644265b6fa173f825555a..86348a284ce2f5caca768b5d519104a1f56e1678 100644 GIT binary patch delta 7944 zcmZ8md0bA}|9_slJoldV6q8DY$R25ji^HAQU zY)H!&(?0dd9?EW_|M}CBI%VoeJ;VyMz>%&Jo1(Q)Y>w97#3pD}rp6Mw9&G%TQu!bA za<%o81!5nkMx*t2YCKwf6?LV?%pj>Xjm@XiCh(WdfR)DoKVc>k?4YNU)kHlk-1y(% z<>5-(cpbSJ*nWeSNYfc?E039hREn?<=%d2${|U>GorFY|v1Vw^Vy)16gPlX3$Lg(( zSRWDgABX>z2X?qKTCk~&QTvbSy%KD?Rbq)uln)gD zW1>jWXs?yN5^Wgo$Z`L1=BsFp8fXk; zrPkC=gy6(TsurpBMp9YI2*qxrOeF}NPN8}jgo-n$V(ff&Ikk{OG+0d)V6J5iHIG3q z-Q$%t=QASFG9E4}r$)(SXDA;e1GO8edZc!*ky=g55uDRZokFB<%@iv}h;5-30)$*| zP?i)r1}@}gZtE3`L|TH~Nl>g!Yrq-7Kv~w*P5}zZUb{)%#QMd*Qk&EeP45ZCVD5-# zlosaBcuu(?8q9w|{f)#jdiz~xzoh(C7U*oNnK>XsN~SgsrD_!Njl zKBM8pXVf5=83rWKIt&av9YVjxq5CS(&yYhnUx_}5EWKBv4RH)QDm1{zNR@6yJ4N zIJFbY4Sb4C7gaBrxFmROYGeEFIZWD94wS`nfnbgHvH|xWtlIzP@Sm+mZydI$Y&cx% z)BD@t%ok~1L;iVw*sgM_bIiHxRO{Bso*z0tek=Gpy71$(wx^w&WsQ>8x-Lsj4OL4l zDIPL}`a}7f*|fkHx5LLZ*7)wxO~~l6KmEvaARlLIv~%Wqg*4sxn+JpTM4o*3JY&}x zHIRe|f64%w$ zQ%dsd$4cXht?cLAo-|HeJ>X(cLdVa!Eyu!RQj4-5Cz&e!nKr{>@3XXUCyQRm()qJn zhnuMm8y7IG=#O!8*jb&~PUXM(uXudwe)OW|ocm6)_xn=v+`7wuzxgdI>F|24r=YSS zx^cq@ZxVl#o z=|5)aaMy14$rWtO^|-P_#?E7V0-a=IZhpw$8Bu!S)Q-tNy8jt1zHXkM*cokMH{y(m zQ<*G8$H6P3&z_#Tv3>lAyzKS~DqDgk9}V5?dpcZkr`;{4Blkh5QSjN@E;@ZDDotOG zEbVJD_&wx(Gi`g4wJ83Z8J4 zopP%7iux*PdUKFpc=?;B^3#Z-oUwG@>R_DGCOHIO$dpwno;+qE%e zi(Zgw-CXmYA<0`3Uk_25VApkTwm=?kp)iFRtwj+_Id2~#sr_q*J z@k%DGjA_3?`aOQ1{8CIWz+Alp^e60oa0MNYx%sDQU&O7cqusEWXFWX~-MeH3H|Wvo z$i>xedLWP9VAqWOt$l=2v?;@^2u4dY{IXpcxu{2nC z=hL-zw6KIj> zitxk12EM6ehQO)_Mgl8+7$sTd3dSB6;%gw2hLcGRWKV2YeK+=MoC4x(GM(hsg{NRjPyl=cNjncOPfO_^m3F=0;o*1pUOY=oS61;0xrW zuZp>WC+pe?hQjVTYMASoR$R-J;hWgpCgvl9N^P{GWVE(KB3k~*@hOz z5Z7UU8*>=lb!BrqnYrpHTJ6j=14ao-)0A)!^4}4#GXto}?!077u%6;OMvMbc{m3km zAZHl~7NY`%`k4s2R#J6-u=KTrlVyElGH?ZlirFbRz~wv}gtTF+65E7wOH*b8vDiOq z>~q|jhlAJ`n08&8O~eziWEA@V?>*D8>|HFUGKn3C(MWT4FpGkjXWDkJQrP6Hgvqvs z)dB2e*t$okb*2?thxO;%u*WoUT^F;(c=8IpSTPQXS5wbitqO%h6;BW$S|Q2h)$Ugq$Mb;3r9-?2Ja zq45iAgpKt4VB>KBYiWrizQ#A`Net0#SN3?EM2vNxn@D)9@yz$z&=IRMvH0v$NSj;lZkUbEwN;zGDNay1-ERZ}-5?{{HqZI(dqF3t!#mU07SZZ6zM zTt#PhZUFAoDsL_TceH&I=ZWJr-o_om@!reelyJPy_i<#9bW1q}>~8cCt`W=ip5o## zE%+=KjeF5^f%||DmCkz-W~uN4Y`Cz!eunCAIWxGRMmSZ>uW;V@D9UN&>hNGM>EhPm zC@w$crYNFww#=n9V2JRWg@!(Ww}2V7!Y>DdTA}RjZ#g3cl<$+!w~E=qOcyCbU%;Eo zWd_MQzj8%5s#u!8jq`N@{I9sl<2Csms8fezLwH>FGeh~scvw|U__cVvV`uOSF=}_@ z3ssP})7dGumO^!V8Qc`%Lxdu%uLpx=4a@mi_`Tgdy~4X&km(WL-6qi2oimh~`to0J z{U-(RG8|d&8om#so^ZYjS2I7Bx5ab+XFBhJLz}sqKZI-5E9J}Z`FXE!|N9Uj={0C0 zze(o}VOBA(0t=gj;{KV(M`6QW#e6;<$#3O+0nVkMj(>$i$!Oqz!?d7ld?pT{?=C+Q za}7KB&!`>H;4xo<#;xTsKMz+>{cj%P=#IYQ7vaKvr-9l~B&R+CT*U`xml1Hp0T@pL zt~iSn6X1`zuT8-TOgmr>K4VmD35H>Nm*#>bPX5sZE?fjm5lC7DUdTPb2q*9}0(DNn zRt~ZkgE@#WZ!wsKK*nN#zHbN|9r$c97>lR_o$xfWDHzPG_(HQDT<} z8nc%G^nnlxPfmz@a|u|8fZpPQj6qLgS1=!eg|5J*pP~bsUBN{3^uZN4ATVbc(cifY%taKzkq&&l44`j* zaFiQ>hfJ9oXXu&^J9O z@O9vvsaawLsxJ9zzTdkG?=n!WQPH5=y*4kI%1{nndQVuBATrNGyL`+a~7 z66*2+QxOnarUT7=fr0!9^=-Yc&^P%A2r@db!58SGC!vzF5kS$*@*~k~@FNXq?FYIm z2qkm{sm=KnU@3Ao*q>0=^n(U}fRoV-AYe^DxDWuGk(O2<0U`b1VjvOLSxH!7D@jAI zt^^)PYt$;@G=3FuLzMfgh_FczScWL+L4?)QPqAH1ScU!I%W7iTc@1$|zJ_#>Sxa1a zt|gXFtOcIPvU)I~tPBQzh;l8Mu*QZEgNY#|)JGwNH8YfeqEO(Cw5WB&m*+YXYVA6* zWwRUMZz?RCK+sx zCi8nQnrIkpA|P@TF@JFrsn*ENAP{Acxf!fL;GfNe<+_EinzoRJjEEtu9sQuEAIy&> zm8ggXKFE%097!%Hjx_CZ9FZ9nPbf+8q_nT%Nok!DNNKARh#k$XgtC4sDN_4Z5Q$vO z-3G!DXxIiq5SWli4xi{mFb`2$5`iNEgSM0U1Z^jQHE$=)*GM9{M<;W_ajFs&U zlKYVzBp#(?QkKYm(3K2=k(Of$Scky*6k=!mPOutL@^%s#g;e6*Kb7QlF_m~9lSZ7T zq!C{)(@5i{rjuhJEuEzEAe~fWN(QNFUIsDvC4;zFl1YRQWRjRwvcO6dPgFm6ltoV3 z>AQ&2l3k=1lHCNX-c4jK? z0twj8A&`l{)WaYHfwsdS6#=&+#QPsd2qm-}Y(uPn%0V;&VMj?iZ;pZpL|It@(h&Gi zK_c9IjEr&bF>(|*90%yXZ1D1NQdN^mQt-UW{+X{L^-1UlpQ;FJRWz|rLUi|wubn+UqixhmXXP9laVe@uO;AQ zEtxUhIzq{+BV|!L12&+*QqF)x1k}!wHc9)zpn5WpTk1&>9@mpyY1=?1yt;u{9&wHg zNzpkHym})6TN{b`i$*e{PEBMo8=J_Gn4TvEFYE^j7sw=JTp;z~n~8d8Gugt|n#n6b z=OQ^IG delta 7944 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 From e563729722cb70af6acdb42a38ec6bcc4752490e Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 13 Aug 2024 21:15:55 -0600 Subject: [PATCH 09/10] Removed un-needed sparse division methods. --- .../RealComplexCooTensorOperations.java | 72 ------------------- 1 file changed, 72 deletions(-) diff --git a/src/main/java/org/flag4j/operations/sparse/coo/real_complex/RealComplexCooTensorOperations.java b/src/main/java/org/flag4j/operations/sparse/coo/real_complex/RealComplexCooTensorOperations.java index b02c28b54..88912037a 100644 --- a/src/main/java/org/flag4j/operations/sparse/coo/real_complex/RealComplexCooTensorOperations.java +++ b/src/main/java/org/flag4j/operations/sparse/coo/real_complex/RealComplexCooTensorOperations.java @@ -261,76 +261,4 @@ public static CooCTensor elemMult(CooTensor src1, CooCTensor src2) { // Truncate arrays if necessary. return new CooCTensor(src1.shape, Arrays.copyOf(productEntries, count), Arrays.copyOf(productIndices, count)); } - - - /** - *

Computes the element-wise division between two sparse COO tensors.

- * - *

Assumes indices of both tensors are sorted lexicographically.

- * - * @param src1 First tensor in the element-wise division. - * @param src2 Second tensor in the element-wise division. - * @return The element-wise quotient of {@code src1} and {@code src2}. - */ - public static CooCTensor elemdiv(CooCTensor src1, CooTensor src2) { - ParameterChecks.assertEqualShape(src1.shape, src2.shape); - - CNumber[] productEntries = new CNumber[Math.min(src1.nnz, src2.nnz)]; - int[][] productIndices = new int[Math.min(src1.nnz, src2.nnz)][src1.indices[0].length]; - int count = 0; - - int src2Idx = 0; - for(int i = 0; i < src1.nnz && src2Idx < src2.nnz; i++) { - int cmp = -1; - - while(src2Idx < src2.nnz && (cmp = Arrays.compare(src2.indices[src2Idx], src1.indices[i])) < 0) { - src2Idx++; - } - - if(src2Idx < src2.nnz && cmp == 0) { - productEntries[count] = src1.entries[i].div(src2.entries[src2Idx]); - productIndices[count] = src1.indices[i]; - count++; - } - } - - // Truncate arrays if necessary. - return new CooCTensor(src1.shape, Arrays.copyOf(productEntries, count), Arrays.copyOf(productIndices, count)); - } - - - /** - *

Computes the element-wise division between two sparse COO tensors.

- * - *

Assumes indices of both tensors are sorted lexicographically.

- * - * @param src1 First tensor in the element-wise division. - * @param src2 Second tensor in the element-wise division. - * @return The element-wise quotient of {@code src1} and {@code src2}. - */ - public static CooCTensor elemdiv(CooTensor src1, CooCTensor src2) { - ParameterChecks.assertEqualShape(src1.shape, src2.shape); - - CNumber[] productEntries = new CNumber[Math.min(src1.nnz, src2.nnz)]; - int[][] productIndices = new int[Math.min(src1.nnz, src2.nnz)][src1.indices[0].length]; - int count = 0; - - int src2Idx = 0; - for(int i = 0; i < src1.nnz && src2Idx < src2.nnz; i++) { - int cmp = -1; - - while(src2Idx < src2.nnz && (cmp = Arrays.compare(src2.indices[src2Idx], src1.indices[i])) < 0) { - src2Idx++; - } - - if(src2Idx < src2.nnz && cmp == 0) { - productEntries[count] = new CNumber(src1.entries[i]).div(src2.entries[src2Idx]); - productIndices[count] = src1.indices[i]; - count++; - } - } - - // Truncate arrays if necessary. - return new CooCTensor(src1.shape, Arrays.copyOf(productEntries, count), Arrays.copyOf(productIndices, count)); - } } From d92152bd12b979250c1ff4d943b37b9cb5b98bea Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 13 Aug 2024 21:23:57 -0600 Subject: [PATCH 10/10] Removed un-needed sparse division methods. --- .../complex/ComplexCooTensorOperations.java | 36 ------------------- .../coo/real/RealCooTensorOperations.java | 36 ------------------- 2 files changed, 72 deletions(-) diff --git a/src/main/java/org/flag4j/operations/sparse/coo/complex/ComplexCooTensorOperations.java b/src/main/java/org/flag4j/operations/sparse/coo/complex/ComplexCooTensorOperations.java index 9db83148b..2a8905520 100644 --- a/src/main/java/org/flag4j/operations/sparse/coo/complex/ComplexCooTensorOperations.java +++ b/src/main/java/org/flag4j/operations/sparse/coo/complex/ComplexCooTensorOperations.java @@ -184,40 +184,4 @@ public static CooCTensor elemMult(CooCTensor src1, CooCTensor src2) { // Truncate arrays if necessary. return new CooCTensor(src1.shape, Arrays.copyOf(productEntries, count), Arrays.copyOf(productIndices, count)); } - - - /** - *

Computes the element-wise division between two complex sparse COO tensors.

- * - *

Assumes indices of both tensors are sorted lexicographically.

- * - * @param src1 First tensor in the element-wise division. - * @param src2 Second tensor in the element-wise division. - * @return The element-wise quotient of {@code src1} and {@code src2}. - */ - public static CooCTensor elemdiv(CooCTensor src1, CooCTensor src2) { - ParameterChecks.assertEqualShape(src1.shape, src2.shape); - - CNumber[] productEntries = new CNumber[Math.min(src1.nnz, src2.nnz)]; - int[][] productIndices = new int[Math.min(src1.nnz, src2.nnz)][src1.indices[0].length]; - int count = 0; - - int src2Idx = 0; - for(int i = 0; i < src1.nnz && src2Idx < src2.nnz; i++) { - int cmp = -1; - - while(src2Idx < src2.nnz && (cmp = Arrays.compare(src2.indices[src2Idx], src1.indices[i])) < 0) { - src2Idx++; - } - - if(src2Idx < src2.nnz && cmp == 0) { - productEntries[count] = src1.entries[i].div(src2.entries[src2Idx]); - productIndices[count] = src1.indices[i]; - count++; - } - } - - // Truncate arrays if necessary. - return new CooCTensor(src1.shape, Arrays.copyOf(productEntries, count), Arrays.copyOf(productIndices, count)); - } } diff --git a/src/main/java/org/flag4j/operations/sparse/coo/real/RealCooTensorOperations.java b/src/main/java/org/flag4j/operations/sparse/coo/real/RealCooTensorOperations.java index eb16b494e..bf14d27f4 100644 --- a/src/main/java/org/flag4j/operations/sparse/coo/real/RealCooTensorOperations.java +++ b/src/main/java/org/flag4j/operations/sparse/coo/real/RealCooTensorOperations.java @@ -183,40 +183,4 @@ public static CooTensor elemMult(CooTensor src1, CooTensor src2) { // Truncate arrays if necessary. return new CooTensor(src1.shape, Arrays.copyOf(productEntries, count), Arrays.copyOf(productIndices, count)); } - - - /** - *

Computes the element-wise division between two sparse COO tensors.

- * - *

Assumes indices of both tensors are sorted lexicographically.

- * - * @param src1 First tensor in the element-wise division. - * @param src2 Second tensor in the element-wise division. - * @return The element-wise quotient of {@code src1} and {@code src2}. - */ - public static CooTensor elemdiv(CooTensor src1, CooTensor src2) { - ParameterChecks.assertEqualShape(src1.shape, src2.shape); - - double[] productEntries = new double[Math.min(src1.nnz, src2.nnz)]; - int[][] productIndices = new int[Math.min(src1.nnz, src2.nnz)][src1.indices[0].length]; - int count = 0; - - int src2Idx = 0; - for(int i = 0; i < src1.nnz && src2Idx < src2.nnz; i++) { - int cmp = -1; - - while(src2Idx < src2.nnz && (cmp = Arrays.compare(src2.indices[src2Idx], src1.indices[i])) < 0) { - src2Idx++; - } - - if(src2Idx < src2.nnz && cmp == 0) { - productEntries[count] = src1.entries[i] / src2.entries[src2Idx]; - productIndices[count] = src1.indices[i]; - count++; - } - } - - // Truncate arrays if necessary. - return new CooTensor(src1.shape, Arrays.copyOf(productEntries, count), Arrays.copyOf(productIndices, count)); - } }