pax_global_header00006660000000000000000000000064145426217160014522gustar00rootroot0000000000000052 comment=4a7d053185f57820aafeba88ca99cc66eee638cf golang-set-2.6.0/000077500000000000000000000000001454262171600135675ustar00rootroot00000000000000golang-set-2.6.0/.github/000077500000000000000000000000001454262171600151275ustar00rootroot00000000000000golang-set-2.6.0/.github/workflows/000077500000000000000000000000001454262171600171645ustar00rootroot00000000000000golang-set-2.6.0/.github/workflows/ci.yml000066400000000000000000000010021454262171600202730ustar00rootroot00000000000000on: [push, pull_request] name: CI jobs: test: strategy: matrix: go-version: [1.20.1, 1.21.1] os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - name: Install Go uses: actions/setup-go@v3 with: go-version: ${{ matrix.go-version }} stable: false - name: Checkout code uses: actions/checkout@v3 - name: Test run: | go test -v -race ./... # go vet ./... # go test -bench=.golang-set-2.6.0/.gitignore000066400000000000000000000004011454262171600155520ustar00rootroot00000000000000# Compiled Object files, Static and Dynamic libs (Shared Objects) *.o *.a *.so # Folders _obj _test # Architecture specific extensions/prefixes *.[568vq] [568vq].out *.cgo1.go *.cgo2.c _cgo_defun.c _cgo_gotypes.go _cgo_export.* _testmain.go *.exe .ideagolang-set-2.6.0/LICENSE000066400000000000000000000022201454262171600145700ustar00rootroot00000000000000Open Source Initiative OSI - The MIT License (MIT):Licensing The MIT License (MIT) Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) 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.golang-set-2.6.0/README.md000066400000000000000000000125041454262171600150500ustar00rootroot00000000000000![example workflow](https://github.com/deckarep/golang-set/actions/workflows/ci.yml/badge.svg) [![Go Report Card](https://goreportcard.com/badge/github.com/deckarep/golang-set/v2)](https://goreportcard.com/report/github.com/deckarep/golang-set/v2) [![GoDoc](https://godoc.org/github.com/deckarep/golang-set/v2?status.svg)](http://godoc.org/github.com/deckarep/golang-set/v2) # golang-set The missing `generic` set collection for the Go language. Until Go has sets built-in...use this. ## Update 3/5/2023 * Packaged version: `2.2.0` release includes a refactor to minimize pointer indirection, better method documentation standards and a few constructor convenience methods to increase ergonomics when appending items `Append` or creating a new set from an exist `Map`. * supports `new generic` syntax * Go `1.18.0` or higher * Workflow tested on Go `1.20` ![With Generics](new_improved.jpeg) Coming from Python one of the things I miss is the superbly wonderful set collection. This is my attempt to mimic the primary features of the set collection from Python. You can of course argue that there is no need for a set in Go, otherwise the creators would have added one to the standard library. To those I say simply ignore this repository and carry-on and to the rest that find this useful please contribute in helping me make it better by contributing with suggestions or PRs. ## Install Use `go get` to install this package. ```shell go get github.com/deckarep/golang-set/v2 ``` ## Features * *NEW* [Generics](https://go.dev/doc/tutorial/generics) based implementation (requires [Go 1.18](https://go.dev/blog/go1.18beta1) or higher) * One common *interface* to both implementations * a **non threadsafe** implementation favoring *performance* * a **threadsafe** implementation favoring *concurrent* use * Feature complete set implementation modeled after [Python's set implementation](https://docs.python.org/3/library/stdtypes.html#set). * Exhaustive unit-test and benchmark suite ## Trusted by This package is trusted by many companies and thousands of open-source packages. Here are just a few sample users of this package. * Notable projects/companies using this package * Ethereum * Docker * 1Password * Hashicorp ## Star History [![Star History Chart](https://api.star-history.com/svg?repos=deckarep/golang-set&type=Date)](https://star-history.com/#deckarep/golang-set&Date) ## Usage The code below demonstrates how a Set collection can better manage data and actually minimize boilerplate and needless loops in code. This package now fully supports *generic* syntax so you are now able to instantiate a collection for any [comparable](https://flaviocopes.com/golang-comparing-values/) type object. What is considered comparable in Go? * `Booleans`, `integers`, `strings`, `floats` or basically primitive types. * `Pointers` * `Arrays` * `Structs` if *all of their fields* are also comparable independently Using this library is as simple as creating either a threadsafe or non-threadsafe set and providing a `comparable` type for instantiation of the collection. ```go // Syntax example, doesn't compile. mySet := mapset.NewSet[T]() // where T is some concrete comparable type. // Therefore this code creates an int set mySet := mapset.NewSet[int]() // Or perhaps you want a string set mySet := mapset.NewSet[string]() type myStruct struct { name string age uint8 } // Alternatively a set of structs mySet := mapset.NewSet[myStruct]() // Lastly a set that can hold anything using the any or empty interface keyword: interface{}. This is effectively removes type safety. mySet := mapset.NewSet[any]() ``` ## Comprehensive Example ```go package main import ( "fmt" mapset "github.com/deckarep/golang-set/v2" ) func main() { // Create a string-based set of required classes. required := mapset.NewSet[string]() required.Add("cooking") required.Add("english") required.Add("math") required.Add("biology") // Create a string-based set of science classes. sciences := mapset.NewSet[string]() sciences.Add("biology") sciences.Add("chemistry") // Create a string-based set of electives. electives := mapset.NewSet[string]() electives.Add("welding") electives.Add("music") electives.Add("automotive") // Create a string-based set of bonus programming classes. bonus := mapset.NewSet[string]() bonus.Add("beginner go") bonus.Add("python for dummies") } ``` Create a set of all unique classes. Sets will *automatically* deduplicate the same data. ```go all := required .Union(sciences) .Union(electives) .Union(bonus) fmt.Println(all) ``` Output: ```sh Set{cooking, english, math, chemistry, welding, biology, music, automotive, beginner go, python for dummies} ``` Is cooking considered a science class? ```go result := sciences.Contains("cooking") fmt.Println(result) ``` Output: ```false false ``` Show me all classes that are not science classes, since I don't enjoy science. ```go notScience := all.Difference(sciences) fmt.Println(notScience) ``` ```sh Set{ music, automotive, beginner go, python for dummies, cooking, english, math, welding } ``` Which science classes are also required classes? ```go reqScience := sciences.Intersect(required) ``` Output: ```sh Set{biology} ``` How many bonus classes do you offer? ```go fmt.Println(bonus.Cardinality()) ``` Output: ```sh 2 ``` Thanks for visiting! -deckarep golang-set-2.6.0/bench_test.go000066400000000000000000000427501454262171600162440ustar00rootroot00000000000000/* Open Source Initiative OSI - The MIT License (MIT):Licensing The MIT License (MIT) Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) 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 mapset import ( "math/rand" "testing" ) func nrand(n int) []int { i := make([]int, n) for ind := range i { i[ind] = rand.Int() } return i } func benchAdd(b *testing.B, n int, newSet func(...int) Set[int]) { nums := nrand(n) b.ResetTimer() for i := 0; i < b.N; i++ { s := newSet() for _, v := range nums { s.Add(v) } } } func BenchmarkAddSafe(b *testing.B) { benchAdd(b, 1000, NewSet[int]) } func BenchmarkAddUnsafe(b *testing.B) { benchAdd(b, 1000, NewThreadUnsafeSet[int]) } func benchRemove(b *testing.B, s Set[int]) { nums := nrand(b.N) for _, v := range nums { s.Add(v) } b.ResetTimer() for _, v := range nums { s.Remove(v) } } func BenchmarkRemoveSafe(b *testing.B) { benchRemove(b, NewSet[int]()) } func BenchmarkRemoveUnsafe(b *testing.B) { benchRemove(b, NewThreadUnsafeSet[int]()) } func benchCardinality(b *testing.B, s Set[int]) { for i := 0; i < b.N; i++ { s.Cardinality() } } func BenchmarkCardinalitySafe(b *testing.B) { benchCardinality(b, NewSet[int]()) } func BenchmarkCardinalityUnsafe(b *testing.B) { benchCardinality(b, NewThreadUnsafeSet[int]()) } func benchClear(b *testing.B, s Set[int]) { b.ResetTimer() for i := 0; i < b.N; i++ { s.Clear() } } func BenchmarkClearSafe(b *testing.B) { benchClear(b, NewSet[int]()) } func BenchmarkClearUnsafe(b *testing.B) { benchClear(b, NewThreadUnsafeSet[int]()) } func benchClone(b *testing.B, n int, s Set[int]) { nums := nrand(n) for _, v := range nums { s.Add(v) } b.ResetTimer() for i := 0; i < b.N; i++ { s.Clone() } } func BenchmarkClone1Safe(b *testing.B) { benchClone(b, 1, NewSet[int]()) } func BenchmarkClone1Unsafe(b *testing.B) { benchClone(b, 1, NewThreadUnsafeSet[int]()) } func BenchmarkClone10Safe(b *testing.B) { benchClone(b, 10, NewSet[int]()) } func BenchmarkClone10Unsafe(b *testing.B) { benchClone(b, 10, NewThreadUnsafeSet[int]()) } func BenchmarkClone100Safe(b *testing.B) { benchClone(b, 100, NewSet[int]()) } func BenchmarkClone100Unsafe(b *testing.B) { benchClone(b, 100, NewThreadUnsafeSet[int]()) } func benchContains(b *testing.B, n int, s Set[int]) { nums := nrand(n) for _, v := range nums { s.Add(v) } nums[n-1] = -1 // Definitely not in s b.ResetTimer() for i := 0; i < b.N; i++ { s.Contains(nums...) } } func BenchmarkContains1Safe(b *testing.B) { benchContains(b, 1, NewSet[int]()) } func BenchmarkContains1Unsafe(b *testing.B) { benchContains(b, 1, NewThreadUnsafeSet[int]()) } func BenchmarkContains10Safe(b *testing.B) { benchContains(b, 10, NewSet[int]()) } func BenchmarkContains10Unsafe(b *testing.B) { benchContains(b, 10, NewThreadUnsafeSet[int]()) } func BenchmarkContains100Safe(b *testing.B) { benchContains(b, 100, NewSet[int]()) } func BenchmarkContains100Unsafe(b *testing.B) { benchContains(b, 100, NewThreadUnsafeSet[int]()) } func benchContainsOne(b *testing.B, n int, s Set[int]) { nums := nrand(n) for _, v := range nums { s.Add(v) } b.ResetTimer() for i := 0; i < b.N; i++ { s.ContainsOne(-1) } } func BenchmarkContainsOne1Safe(b *testing.B) { benchContainsOne(b, 1, NewSet[int]()) } func BenchmarkContainsOne1Unsafe(b *testing.B) { benchContainsOne(b, 1, NewThreadUnsafeSet[int]()) } func BenchmarkContainsOne10Safe(b *testing.B) { benchContainsOne(b, 10, NewSet[int]()) } func BenchmarkContainsOne10Unsafe(b *testing.B) { benchContainsOne(b, 10, NewThreadUnsafeSet[int]()) } func BenchmarkContainsOne100Safe(b *testing.B) { benchContainsOne(b, 100, NewSet[int]()) } func BenchmarkContainsOne100Unsafe(b *testing.B) { benchContainsOne(b, 100, NewThreadUnsafeSet[int]()) } // In this scenario, Contains argument escapes to the heap, while ContainsOne does not. func benchContainsComparison(b *testing.B, n int, s Set[int]) { nums := nrand(n) for _, v := range nums { s.Add(v) } b.Run("Contains", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { for _, v := range nums { s.Contains(v) // 1 allocation, v is moved to the heap } } }) b.Run("Contains slice", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { for i := range nums { s.Contains(nums[i : i+1]...) // no allocations, using heap-allocated slice } } }) b.Run("ContainsOne", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { for _, v := range nums { s.ContainsOne(v) // no allocations, using stack-allocated v } } }) } func BenchmarkContainsComparison1Unsafe(b *testing.B) { benchContainsComparison(b, 1, NewThreadUnsafeSet[int]()) } func BenchmarkContainsComparison1Safe(b *testing.B) { benchContainsComparison(b, 1, NewSet[int]()) } func BenchmarkContainsComparison10Unsafe(b *testing.B) { benchContainsComparison(b, 10, NewThreadUnsafeSet[int]()) } func BenchmarkContainsComparison10Safe(b *testing.B) { benchContainsComparison(b, 10, NewSet[int]()) } func BenchmarkContainsComparison100Unsafe(b *testing.B) { benchContainsComparison(b, 100, NewThreadUnsafeSet[int]()) } func BenchmarkContainsComparison100Safe(b *testing.B) { benchContainsComparison(b, 100, NewSet[int]()) } func benchEqual(b *testing.B, n int, s, t Set[int]) { nums := nrand(n) for _, v := range nums { s.Add(v) t.Add(v) } b.ResetTimer() for i := 0; i < b.N; i++ { s.Equal(t) } } func BenchmarkEqual1Safe(b *testing.B) { benchEqual(b, 1, NewSet[int](), NewSet[int]()) } func BenchmarkEqual1Unsafe(b *testing.B) { benchEqual(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func BenchmarkEqual10Safe(b *testing.B) { benchEqual(b, 10, NewSet[int](), NewSet[int]()) } func BenchmarkEqual10Unsafe(b *testing.B) { benchEqual(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func BenchmarkEqual100Safe(b *testing.B) { benchEqual(b, 100, NewSet[int](), NewSet[int]()) } func BenchmarkEqual100Unsafe(b *testing.B) { benchEqual(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func benchDifference(b *testing.B, n int, s, t Set[int]) { nums := nrand(n) for _, v := range nums { s.Add(v) } for _, v := range nums[:n/2] { t.Add(v) } b.ResetTimer() for i := 0; i < b.N; i++ { s.Difference(t) } } func benchIsSubset(b *testing.B, n int, s, t Set[int]) { nums := nrand(n) for _, v := range nums { s.Add(v) t.Add(v) } b.ResetTimer() for i := 0; i < b.N; i++ { s.IsSubset(t) } } func BenchmarkIsSubset1Safe(b *testing.B) { benchIsSubset(b, 1, NewSet[int](), NewSet[int]()) } func BenchmarkIsSubset1Unsafe(b *testing.B) { benchIsSubset(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func BenchmarkIsSubset10Safe(b *testing.B) { benchIsSubset(b, 10, NewSet[int](), NewSet[int]()) } func BenchmarkIsSubset10Unsafe(b *testing.B) { benchIsSubset(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func BenchmarkIsSubset100Safe(b *testing.B) { benchIsSubset(b, 100, NewSet[int](), NewSet[int]()) } func BenchmarkIsSubset100Unsafe(b *testing.B) { benchIsSubset(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func benchIsSuperset(b *testing.B, n int, s, t Set[int]) { nums := nrand(n) for _, v := range nums { s.Add(v) t.Add(v) } b.ResetTimer() for i := 0; i < b.N; i++ { s.IsSuperset(t) } } func BenchmarkIsSuperset1Safe(b *testing.B) { benchIsSuperset(b, 1, NewSet[int](), NewSet[int]()) } func BenchmarkIsSuperset1Unsafe(b *testing.B) { benchIsSuperset(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func BenchmarkIsSuperset10Safe(b *testing.B) { benchIsSuperset(b, 10, NewSet[int](), NewSet[int]()) } func BenchmarkIsSuperset10Unsafe(b *testing.B) { benchIsSuperset(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func BenchmarkIsSuperset100Safe(b *testing.B) { benchIsSuperset(b, 100, NewSet[int](), NewSet[int]()) } func BenchmarkIsSuperset100Unsafe(b *testing.B) { benchIsSuperset(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func benchIsProperSubset(b *testing.B, n int, s, t Set[int]) { nums := nrand(n) for _, v := range nums { s.Add(v) t.Add(v) } b.ResetTimer() for i := 0; i < b.N; i++ { s.IsProperSubset(t) } } func BenchmarkIsProperSubset1Safe(b *testing.B) { benchIsProperSubset(b, 1, NewSet[int](), NewSet[int]()) } func BenchmarkIsProperSubset1Unsafe(b *testing.B) { benchIsProperSubset(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func BenchmarkIsProperSubset10Safe(b *testing.B) { benchIsProperSubset(b, 10, NewSet[int](), NewSet[int]()) } func BenchmarkIsProperSubset10Unsafe(b *testing.B) { benchIsProperSubset(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func BenchmarkIsProperSubset100Safe(b *testing.B) { benchIsProperSubset(b, 100, NewSet[int](), NewSet[int]()) } func BenchmarkIsProperSubset100Unsafe(b *testing.B) { benchIsProperSubset(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func benchIsProperSuperset(b *testing.B, n int, s, t Set[int]) { nums := nrand(n) for _, v := range nums { s.Add(v) t.Add(v) } b.ResetTimer() for i := 0; i < b.N; i++ { s.IsProperSuperset(t) } } func BenchmarkIsProperSuperset1Safe(b *testing.B) { benchIsProperSuperset(b, 1, NewSet[int](), NewSet[int]()) } func BenchmarkIsProperSuperset1Unsafe(b *testing.B) { benchIsProperSuperset(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func BenchmarkIsProperSuperset10Safe(b *testing.B) { benchIsProperSuperset(b, 10, NewSet[int](), NewSet[int]()) } func BenchmarkIsProperSuperset10Unsafe(b *testing.B) { benchIsProperSuperset(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func BenchmarkIsProperSuperset100Safe(b *testing.B) { benchIsProperSuperset(b, 100, NewSet[int](), NewSet[int]()) } func BenchmarkIsProperSuperset100Unsafe(b *testing.B) { benchIsProperSuperset(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func BenchmarkDifference1Safe(b *testing.B) { benchDifference(b, 1, NewSet[int](), NewSet[int]()) } func BenchmarkDifference1Unsafe(b *testing.B) { benchDifference(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func BenchmarkDifference10Safe(b *testing.B) { benchDifference(b, 10, NewSet[int](), NewSet[int]()) } func BenchmarkDifference10Unsafe(b *testing.B) { benchDifference(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func BenchmarkDifference100Safe(b *testing.B) { benchDifference(b, 100, NewSet[int](), NewSet[int]()) } func BenchmarkDifference100Unsafe(b *testing.B) { benchDifference(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func benchIntersect(b *testing.B, n int, s, t Set[int]) { nums := nrand(int(float64(n) * float64(1.5))) for _, v := range nums[:n] { s.Add(v) } for _, v := range nums[n/2:] { t.Add(v) } b.ResetTimer() for i := 0; i < b.N; i++ { s.Intersect(t) } } func BenchmarkIntersect1Safe(b *testing.B) { benchIntersect(b, 1, NewSet[int](), NewSet[int]()) } func BenchmarkIntersect1Unsafe(b *testing.B) { benchIntersect(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func BenchmarkIntersect10Safe(b *testing.B) { benchIntersect(b, 10, NewSet[int](), NewSet[int]()) } func BenchmarkIntersect10Unsafe(b *testing.B) { benchIntersect(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func BenchmarkIntersect100Safe(b *testing.B) { benchIntersect(b, 100, NewSet[int](), NewSet[int]()) } func BenchmarkIntersect100Unsafe(b *testing.B) { benchIntersect(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func benchSymmetricDifference(b *testing.B, n int, s, t Set[int]) { nums := nrand(int(float64(n) * float64(1.5))) for _, v := range nums[:n] { s.Add(v) } for _, v := range nums[n/2:] { t.Add(v) } b.ResetTimer() for i := 0; i < b.N; i++ { s.SymmetricDifference(t) } } func BenchmarkSymmetricDifference1Safe(b *testing.B) { benchSymmetricDifference(b, 1, NewSet[int](), NewSet[int]()) } func BenchmarkSymmetricDifference1Unsafe(b *testing.B) { benchSymmetricDifference(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func BenchmarkSymmetricDifference10Safe(b *testing.B) { benchSymmetricDifference(b, 10, NewSet[int](), NewSet[int]()) } func BenchmarkSymmetricDifference10Unsafe(b *testing.B) { benchSymmetricDifference(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func BenchmarkSymmetricDifference100Safe(b *testing.B) { benchSymmetricDifference(b, 100, NewSet[int](), NewSet[int]()) } func BenchmarkSymmetricDifference100Unsafe(b *testing.B) { benchSymmetricDifference(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func benchUnion(b *testing.B, n int, s, t Set[int]) { nums := nrand(n) for _, v := range nums[:n/2] { s.Add(v) } for _, v := range nums[n/2:] { t.Add(v) } b.ResetTimer() for i := 0; i < b.N; i++ { s.Union(t) } } func BenchmarkUnion1Safe(b *testing.B) { benchUnion(b, 1, NewSet[int](), NewSet[int]()) } func BenchmarkUnion1Unsafe(b *testing.B) { benchUnion(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func BenchmarkUnion10Safe(b *testing.B) { benchUnion(b, 10, NewSet[int](), NewSet[int]()) } func BenchmarkUnion10Unsafe(b *testing.B) { benchUnion(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func BenchmarkUnion100Safe(b *testing.B) { benchUnion(b, 100, NewSet[int](), NewSet[int]()) } func BenchmarkUnion100Unsafe(b *testing.B) { benchUnion(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]()) } func benchEach(b *testing.B, n int, s Set[int]) { nums := nrand(n) for _, v := range nums { s.Add(v) } b.ResetTimer() for i := 0; i < b.N; i++ { s.Each(func(elem int) bool { return false }) } } func BenchmarkEach1Safe(b *testing.B) { benchEach(b, 1, NewSet[int]()) } func BenchmarkEach1Unsafe(b *testing.B) { benchEach(b, 1, NewThreadUnsafeSet[int]()) } func BenchmarkEach10Safe(b *testing.B) { benchEach(b, 10, NewSet[int]()) } func BenchmarkEach10Unsafe(b *testing.B) { benchEach(b, 10, NewThreadUnsafeSet[int]()) } func BenchmarkEach100Safe(b *testing.B) { benchEach(b, 100, NewSet[int]()) } func BenchmarkEach100Unsafe(b *testing.B) { benchEach(b, 100, NewThreadUnsafeSet[int]()) } func benchIter(b *testing.B, n int, s Set[int]) { nums := nrand(n) for _, v := range nums { s.Add(v) } b.ResetTimer() for i := 0; i < b.N; i++ { c := s.Iter() for range c { } } } func BenchmarkIter1Safe(b *testing.B) { benchIter(b, 1, NewSet[int]()) } func BenchmarkIter1Unsafe(b *testing.B) { benchIter(b, 1, NewThreadUnsafeSet[int]()) } func BenchmarkIter10Safe(b *testing.B) { benchIter(b, 10, NewSet[int]()) } func BenchmarkIter10Unsafe(b *testing.B) { benchIter(b, 10, NewThreadUnsafeSet[int]()) } func BenchmarkIter100Safe(b *testing.B) { benchIter(b, 100, NewSet[int]()) } func BenchmarkIter100Unsafe(b *testing.B) { benchIter(b, 100, NewThreadUnsafeSet[int]()) } func benchIterator(b *testing.B, n int, s Set[int]) { nums := nrand(n) for _, v := range nums { s.Add(v) } b.ResetTimer() for i := 0; i < b.N; i++ { c := s.Iterator().C for range c { } } } func BenchmarkIterator1Safe(b *testing.B) { benchIterator(b, 1, NewSet[int]()) } func BenchmarkIterator1Unsafe(b *testing.B) { benchIterator(b, 1, NewThreadUnsafeSet[int]()) } func BenchmarkIterator10Safe(b *testing.B) { benchIterator(b, 10, NewSet[int]()) } func BenchmarkIterator10Unsafe(b *testing.B) { benchIterator(b, 10, NewThreadUnsafeSet[int]()) } func BenchmarkIterator100Safe(b *testing.B) { benchIterator(b, 100, NewSet[int]()) } func BenchmarkIterator100Unsafe(b *testing.B) { benchIterator(b, 100, NewThreadUnsafeSet[int]()) } func benchString(b *testing.B, n int, s Set[int]) { nums := nrand(n) for _, v := range nums { s.Add(v) } b.ResetTimer() for i := 0; i < b.N; i++ { _ = s.String() } } func BenchmarkString1Safe(b *testing.B) { benchString(b, 1, NewSet[int]()) } func BenchmarkString1Unsafe(b *testing.B) { benchString(b, 1, NewThreadUnsafeSet[int]()) } func BenchmarkString10Safe(b *testing.B) { benchString(b, 10, NewSet[int]()) } func BenchmarkString10Unsafe(b *testing.B) { benchString(b, 10, NewThreadUnsafeSet[int]()) } func BenchmarkString100Safe(b *testing.B) { benchString(b, 100, NewSet[int]()) } func BenchmarkString100Unsafe(b *testing.B) { benchString(b, 100, NewThreadUnsafeSet[int]()) } func benchToSlice(b *testing.B, s Set[int]) { nums := nrand(b.N) for _, v := range nums { s.Add(v) } b.ResetTimer() for i := 0; i < b.N; i++ { s.ToSlice() } } func BenchmarkToSliceSafe(b *testing.B) { benchToSlice(b, NewSet[int]()) } func BenchmarkToSliceUnsafe(b *testing.B) { benchToSlice(b, NewThreadUnsafeSet[int]()) } golang-set-2.6.0/go.mod000066400000000000000000000000621454262171600146730ustar00rootroot00000000000000module github.com/deckarep/golang-set/v2 go 1.18 golang-set-2.6.0/go.sum000066400000000000000000000000001454262171600147100ustar00rootroot00000000000000golang-set-2.6.0/iterator.go000066400000000000000000000037441454262171600157570ustar00rootroot00000000000000/* Open Source Initiative OSI - The MIT License (MIT):Licensing The MIT License (MIT) Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) 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 mapset // Iterator defines an iterator over a Set, its C channel can be used to range over the Set's // elements. type Iterator[T comparable] struct { C <-chan T stop chan struct{} } // Stop stops the Iterator, no further elements will be received on C, C will be closed. func (i *Iterator[T]) Stop() { // Allows for Stop() to be called multiple times // (close() panics when called on already closed channel) defer func() { recover() }() close(i.stop) // Exhaust any remaining elements. for range i.C { } } // newIterator returns a new Iterator instance together with its item and stop channels. func newIterator[T comparable]() (*Iterator[T], chan<- T, <-chan struct{}) { itemChan := make(chan T) stopChan := make(chan struct{}) return &Iterator[T]{ C: itemChan, stop: stopChan, }, itemChan, stopChan } golang-set-2.6.0/iterator_example_test.go000066400000000000000000000032241454262171600205220ustar00rootroot00000000000000/* Open Source Initiative OSI - The MIT License (MIT):Licensing The MIT License (MIT) Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) 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 mapset import ( "testing" ) type yourType struct { name string } func Test_ExampleIterator(t *testing.T) { s := NewSet( []*yourType{ {name: "Alise"}, {name: "Bob"}, {name: "John"}, {name: "Nick"}, }..., ) var found *yourType it := s.Iterator() for elem := range it.C { if elem.name == "John" { found = elem it.Stop() } } if found == nil || found.name != "John" { t.Fatalf("expected iterator to have found `John` record but got nil or something else") } } golang-set-2.6.0/new_improved.jpeg000066400000000000000000003541471454262171600171520ustar00rootroot00000000000000ÿØÿàJFIFHHÿáòExifMM*V^1&f2Œ‡i HHAdobe Illustrator CC 2014 (Macintosh)2014:07:17 18:03:17Ö   Ã2014:07:17 14:03:13ÿá—>http://ns.adobe.com/xap/1.0/ Print ÿínPhotoshop 3.08BIM6Z%G>20140717? 140313-0400Print8BIM%íäcPAÔLÇBZx¥”RÿÀÃÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÛCÿÛCÿÝ2ÿÚ ?üo¯ìƒü¯ ( € ( € ( € ( € ( € ( € ( € ( € ( € ( AsµsýÔ›'§ Ï4=ÞÊ”£¬¼‡ËÛ®û‘öT$ ÷8·\óÆéüµÎùî£%=!¯¦¿•ÿ¯ÂªSÍU{4Þò´WþMoÔv‘þ ¾M3ÃÐÏâ=MÆSMðå½Ïˆõ&\…Þ4í Fü¦â|¬g9 «Rx{JíBæÔ¥åÊ®uaòü^2¬haa*µ¥{Fš•Gek»SŒä’º»µµJúéõ·ÃÏØöÜøªøöLý¡µ»bN/î¾ë> Ó~P¥‡ö—Å |bøWS‘!È?(c<5Lª€ÙéWºÃ= VTmê¶þðþ‡I#dv\(qç?ÊüUûa~x J¼9S1ÍjÂöX,§å7ÙTÌ]}-¬”nï{oûIô•7üTÕ–E¸ñ¶µÉŸ“Nk PàEÓì–`t>qozþdâ_§gÒƒ‰¨Ö£Œã Þ:Ò–˜E‚ËÔ"äÚŒ>­„•d¢”¾²æì¯&õ>óá¯`œ}–_‡”£Ö§=VßwÏ6¿ò[~ŸÿÐüo¯ìƒü¯ ( € k¼q¡’YRÐny%uDA>bÛTÌ^IÇ™«·d›u+¶”{½¿¯¾ïE®â:H‹$N’ÄãrI«£Œã(êYXgÐðGä4Ó³V};êškºÛ·õýYÔ€( € ( € ( € ( € ( € ( € (ñ£ÊBÃÌÇ´HÒûåtüö&Ô~&£ë¡Tá:®Ô£)?$ßåëðŽá’Ïþ?&·³ã?é—ö‡“Œì¹–6À?çû¤}õî'%Ý&×Þ¯ýwéR¥8MS©Ë e)(¿ºM3¡ð§„¼YãËŸ±xž-ñÝט!û/|%âÏç0ÊÃåxGEÖ¤3 q»ž|N+ ƒIâêS¤žÜó„.¿íùGúÿÉ}·%Í3z®–YB¶"qv~ΕY¤Þ¶r§ ¤í­·¶¶×O³>ÿÁ0ÿà¡a´¹ðŸìñÃìw¦?³_x§@оXH— ˜&’o‰þ'ðeô6ïÔ¸´§ñ€p…‰ãÂOÙÖÆÐ¿^W:–ÿÁtåÿíäŸGßí0ñöa†–&†YŠM/v5*.}¬êÕƒ‚}çI4ž±½Ô¾×ðwüýûuë e7ïÿgƒZ|ÞD—“øçã ߈5+dûû´/xA,帀Œ´c[U9ùeÎ@ø!ñßÃ~£R¾s˜ÑÃR¦›æ­:xy7:õ´^n«·è¹OÑ«Ž³'FТ¹Úö‹ž­iEuP 4ù¥ëU-owdŸÓžÿ‚ü7Òñ‡öñðÙ‘oÒ¾ | MFq |\Dºß¹ãÿøAô[¬Ê\‰4ÏÛx>8axÿvQP.Îq¸æ¿˜xËöÊø3”N2ál&yšTnÉá²ÈP§ZÒ•LÊ­)¨½î”šÒé+ÛõŒ—è;‚ú¼°ÙÄý¥)s_Ûbê7i6ùT0ªI'Ê’KO;·ô×…?eø'Ãv´“À_°gÀÙn¬ˆx5oˆÖò|FÕT›íNÒx•5ɌѺæ@0×ùƒ‹ÿmbq¥Â¼9(á%ïãsfµÙ'‡ÀP­£Wæ´K¢¿OÖ2o¡ÿ‡Ù|)¬E täœy0tå(´îš©Y·ÌžªVºzú}7¤ü`Õ<+YøÂ þÙm•`´ð/€4M(có„*Ç–8$ˆ¹#{ÿ+ñOíLúGg±¯O-¯’å”ês*o —ÔÄT‚jѽ\v.*RŽéýY+ï-ÿ^˼àŒ5*Õyš¢‚öí(-û_çÔÈÕ>.|IÖU’ÿƾ%tc¼Ço©6'ãòô˜lÎßöwcù·óg}2>‘üeAa³Ž1â/d¥ÌÕU<g¥­(å¸|$ù_X*Î/¶î?g‚àÀ>l6]„RÚò§íùÕœþû\à®îî¯å3ß\Íw1ÿ–·³Ï}'N›ï¥»lär? ü>âÎ!â|öŸbëãqê.*xšµ±rIÚéÐQ‚û £úúw® Q…;yÎå\úí\^q š§'·v£î+÷´TUüíÿe÷××þ‡ž¼ýyÿ=k9ÍÕw¨ÜŸž¿Ÿõú»%°T€P@ÿÑüo¯ìƒü¯ ( €s‚9Áô>‡Šéì}]û x‡RðŸí‹û4x›IÓ¼9«Þh?4mU´ßií©è:mžâiõƾ´EûË} ‰-gÉû%òÃ>Öòö·Äð…L‡N¯?$°í{®Îüôùu³ÓšÜËNhÝskuú†51ø×.©…ö<ðŦÕH¹'e[ÚY'¥É~I]¨I©8É'yWÇo‹×¾3|QøÛ}¡hºø«ãŸxÖMÂÖ¦ø{KƒRºû.™o¦YÈÍ",š6Ÿm4ò¶æòY§*¾nÕïʰ +ËèåÊRš¡N0»wmüO_)JI.‰%wf߃Åyêâ\÷ž*P¤±U¥>XÇ–ÊþÎ.ÍEûÔá 7$›”›²M%äõè8P@P@P@P@PRÔãùÐ ÛRh žpLM0îÑG$Š3ܲ)}GøÌ§üM'æÒþ¿¯žÔ¨W¬¯FšïÚüõùÔžæÎØ”»¿Ó¬äS´Åu¨YC0b2Ä÷`Øçr}=.<Ów‚“^IÛﵿø Ò’o™ÁJ;®hÝzÆüËçÿé^ øEñsâX„ü6øMñ_â"ÜŒÛÉà_…þ>ñt‚â"Éy¡xvöÈGæ¥ÚTE'–ÈÌrüÝ<^#Jiê§VœZõNwù%ÓÖËøk>ͰË•ౘš-^.ž¼”¿Âýš‹»ÓâJûµÓíÿÁ!?टå¶]/öMø…áë[‚Kj?u‡ß ìmÑÌóÅâ/¿ˆP‚ÃiŒ[° >{Ç\+†Œ¥,e98­£’oÿ)Æ*Ý[šÛcîðž xƒŒö\™}Jj¤š~Ò¥\ŠÍóIûZ²wÙ(Ònï[+µö'„?àß/ÚÊ䙾+|]ý–¾ Ù*6õÔ¼{⯈ڲȻ0¿ÙúðêĶùÈ#•#üŸŒ~”ð.X¾&ΰ Pv”±x¼+ÊõªÍóy[þê9ÑcóLb‡,gƒäÓ’8Šõ¼ýœ0ðŒWø¥ÍÕ+kôß„¿àƒ³ž‰ 7ÅÛ‹Å~"¾óÍÓ¾ |ðÞ‰m°Æ»R[Åq|I¾B’g,g à zÿ+ñ‡íIú-ðÅXÓ£ÄY~6³½¡„XÜÎNɶÛÀÒöI5¥ÛI=»~Ãý ¸Š­9,Å✮¤©ápܪÊÉ{gZ¦›¶å+ô]Ó¾ÿ‚XÁ-¼ö¨ü3øññ¦êÓk¼Ÿþ-ø†ÇG»•cØÞn‹ jzœc/— mÀRp8Ë\Yûh<4ËñU0œ/”ñ:<·Uc…Á`h»ý•S]WMhŸîõNé½Rýƒ)úäN•?ígBn›ºUqšíÙZò„\iË{Ùé}tÑ/§|ð{ö0øUp· a¿Ù³Â×Öà-¶¯¬x7Nñv·`vÕ5=6êìÊAË1,ÜœžWùk‹?l¯‰y­:Øl‡°8j<ÏÙ¼ng‰ÅúIÑÂaá諒«µ­Ì·®dŸE?²š±ÄŠŒmÍG B”­Ûž\Ó¶Ÿ=Ïx‹ã§Žì,¿³|9'‡¼a²8ÒËÂÑ´{hcŒlŽ8s9#!~_”é_ËœOûL¾“ÜE†T°ù¾+ªÚmà2Ê)÷’\}|c\Û6è^Û(½Wéøø#ÿݧU-½¥Yé4ÔÊïærZ¯ÄëdOÅÞ&»LcÊ“[½†_õ{ØEŸªœ/çn*úSø÷Æ8•ˆÎø³ˆëEG—ټʽ /[ÝÑËÖ öææ¶ÉÛ°Ápw åëý“ƒ†»ûJ_øNwùœTŽÒ±–\<®ÛÝåâVoS-ÀšBxþ÷ÿ[ð¬fiÇâ*âñ’\UysTD«Ô”¬•Ý\Gµ«²Kø¡…8A(CH%¢^ê_(Ù~ð-ÀÜØ¸…AÐW7Ö+òª~Ò§³JÉsK•.Ê7²^J)¡»¤®%bÝõ(( € ( € (ÿÒüo¯ìƒü¯ ( ÈÌ!#J¶÷MÊåa{¥¶•­wd·{ ‚B! !ä\5–åù>?‡jb§ N¢©íd¤½¥)ÒOE¥9©TœjBTÕ ¢½Ô1ý–nÿáø‹âsKð{àíñFßURûKøysáÝ-˜6åt7Þ& @Rß6@$WN~½®ž »C‹ÃÒn×ÑÏ™ú|)ôütòü9ƒ§Öͨǟ—å˜ÜD#ÍÊœ½”iÁ=ônmm¥ïÚß5âÒã³Ó..-¡–ÊÚÇE'º‚´\iv6ú{ÁkçI \Ë›bp€±ë˜íEó.t¤âÛ–Íé&ä¯m·þº|]xÖ«^~Û•W‚Q–©.jqŒ%Ë{_ÞVÓºÚêóU„m5ºH½Í´sË“ ´·Çs*¼ÐÂò$³x©É㨣^—õ³²õv·õÓ­(·&â­mI»»++ÝÝ軽Ýí%…P@P@…•~óú?i¤ÞÂvŠ÷½¯ëó±­Ô‰æ%­ËÇÿ=ˆ‡~d)åŽ=Y¨ÍÔ¦œ’Ÿkë÷oýuëÑO ‰©xS¨áß•ÛïÛñE{`eH?´´æžGTKh/ ½»wvv–stï¸ã úw»OùeeÕ§¾r²üHtš¦¦åFÒ\²Sm½J›“w},{ÿ€ÿe¿ÚgâÅ­·ÃoÙÓãÏŽ퀷¹ð÷ÂϦ>èštfÖït=?D‰%ʳܨaÓ9ÍyUóÌ— O‹ÂÁGtêÁ¿üR~z;~_M…àŽ/ÇV§K–æ]WdÖ¤b´r¼§US„U–œÒÕ´–­)}¿ðÿþŸÿ)ø‰öv?ôò!c¨üWø“ðóÁ1*β8w´Òµokñ¢*á´á*3PíùÌwˆÜ#€§íªbÔ—÷a6¾n~ÉwÙôßkýæYàOˆ†)R­…T0öOžu©EÝßHŸ·mÆÊüÊ+Ukëo¬ü%ÿöüpX¡¸øÁûR~Ëß ÌŽ&£·~+êðBÃ÷ }ð³M’æ˜òe‰Éà®9ü3þ™^p£O‰x'ÁN[G˜à°Ó—øi¹V¨×¦«­´¿ê|;ôHãœÖœÞ"¼nÐt¨bk(®ó“–œ›Þ܉-®÷PøCþeûxhYKñ+ö¸øáñêÙm%Ô´ÿ…ÞðgÃÍ*îX›uÜ0êsxk_× ¶¸ ò•Õ Ñƒþµ«ùc‹?k'Ñ$«_–æË1œüÁà³j\×I*ÞÎG%küI=•ÕÿdȾ„9¬°ô?´gˆ…xò¹ÉO …ö’›¼iÂu£=,§Ì“·3Õ¿¦<+ÿáÿ‚Yøe¹ƒöfñ·ÅÛØV+¯ÄU‹’‡·ž_–BM6¢ù©ÔÄWP’WNT¹ÕõŠwKö,£è[ÂÔkج$«$µ›Äb¬®›´jÉS¾×²Ö˦‹êè³ÏÂ{qoðsöHýš¾ÚcºÒþè—Ú¤{e!þÐ:u´²H’ Á™Î9ãùgŒ¿lyí d96I€Ä6½ìV'™J*êöTㄦÚ×ÇÊÛ½í£ýs"ú4x‘¿ÜA¨½Z£F†I÷vŒäõï¯ëêWŸþ'ÜD–Ö¾$5œaÄv~Ò4­ Ù+k‰“Àž}GógþÑ¥×S‡Ï/èÉ:x  Ÿ5­ûÚëYrÙ¤×,½æÛnÖýá/àa¦ 5%}êT©?ü•8G_O»§©øÓŚ˻êÞ%ñ¤e ¼^ëzœÉÎ1]AlA|×ó¯ý «oØÛã9ý’öÖXüÿ#ø©Á÷ âÂÞ9_Ëâtðd3 ÿb-ºèÓxÖÙ%:‡Úš6[mäíáÿ¬yrÎÿ°z±ÞÇÚ|ç/'´ø¹¯~MmÉkéÍßôøqÄá_õ¶š¡,·öN*¯ï/í=“—'³ååçÓø¼Ü¾÷"~âÄðë¯e¯ˆÚŽ¡ðWâ—€þ-éRHÛ§_üa±_‚þ>¶~Qma¦øÇHð¾»w ýÙk™€9pWŒ°yí*‹›—F¥&—óQj´=[ƒ$·I+_ey|©ç¼ ŠÂÉÐU2ÜETg);ûð· ñü-Šv2 ;©$°°ñ—ŒôÏÛX#Ú>¥®Y¼†á`°‘«ËͰ?Û9® FµZTòöªÎTÚNR¨áì¡ñhý9Tç³ä‹K—šV>ƒ†sYpo có|à ‡­‹Î”èS§^’:*§¶©+SjQöõáCÙ9ÓU\e8Ôå‹kâo‡_üYñ;Ävð~Ÿý¥«-õëËûëm+HÐü5 Ã÷ŽËl«ÇÌn.L0÷Ý\Ôã)rŧ.ËW÷+¿ÀéXLE¹å BÍ%Éü \±üFi‘6·}™¢®êr±iž†çÄú„ŽY@D²ðí¾©r]šEÀÚ7€b­EF›«[÷t–îmA}óq_×ݵ #ˆ†Šu15q5*²i4ž””úµ»KòR|<ý†ÿlß‹‡¿²‡í âH—P“áwˆ<1¤H’Ë䆋Xñºx[M‘VEÚäK„êØŸÄü?ƒŠ–#…W{F§´kÕSç·•÷>§.ðç³Jò¡†Ê±þâOšt}”ÿ–U¥KšÖÖËN¶º¿Û~ÿ‚ÿÁGü]kþ·ð¿áÿ«9K~óâ·Æo h×0„“ai¬|cñ"q•;•w(eþ%<”Í|WàŒž.¦/j)]Ë•F6ïÍV¥¶m§émþï'ú>øƒšF^ÓJ„õQŒ«'&ï§4hÒ®’{®Y·nÏÝ_Uxcþ ïñ›[Ÿ‹¿¶ßÀ/J¼ß韼⟈ڤeXf(/µÏøfļ±äm(”?Âýù׌>ž¿FÎ ÅUÁgœSÑÆÒ‹r¥<Ï ëGKûÔ(F¥köŠi˧—ë™/ÐßóL-9IÔw%Í:xJ²‹ŠzÆ/Z4ÓkNwMÚ÷ågÔ~ÿ‚*ÿÁ>üâçÆßÿj‹þRL†ÃÃþøU£Ü?˱Ò_ xOAÕÆ×R9¿(Á¹^¯å./ý¯ÿGl£W’VÇæ²ƒ—/Õ2¼lý¤¡vsCÔš²•ÒÙó(êÿlÉ>„uá‹…|\êSŠ‹Nœ±iCÞ·¼ã„§í’OG6µÚöké þÂ?ðL/‡ªNûèþ>¿2yƒVø×ãŸ|C»$ÇfKê¾$¶*<°DaB«Wçù[muGN0àžÌëÎö¾'ƒÀEGW~Lqm»½UÓkí;$~¯‘} 8'9ÔÅÇ)Ô—4œ©TÅI»F?&z.X­IjívÛú§ÂÞ!ðÃ{k{„¿>|*³´EKUðÃ- Òê‘#)q­ ,"P¹#§þ=ü¹Æ?µ³Çì÷í2LeøfŸ3ònOïroñÿ‚Ò²²Ñ R@P@P@P@P@P@ÿÔüo¯ìƒü¯ŽQÕÀ\£«€êK#” är;ŠR\Éùÿ_×õ{„œ&¦¬ÜZzê´wÕu]×o¼û³Hýµ4ûÿÙ?á×ìkñ;à€<]ðÇá÷üAã‹/ˆ^×u‡Ÿ£Õµë^á5-?ŶZn¡¡Í«éË®\Cqý¡oui®Ùˆ­¯b¡cóxrqÎêçøLUJxºŒ\%:-E/u§.nWË’Ö›Ö ´­ú†_â!‡àìß/¥ˆËèΫUa?gеS^ÒÙ:^Ú*­EÏ&•M¹[•¼¥~h?äófÿˆvuã’å~xâßGøcñúÚ%gi¡Ñü?uÿ ëâìz|*LמÔÓ!üKác´v,Ú® ÂÕQ‚ÓÛBõh7e¼’ö”›oEV-ÝüVÔóªð~ :Ÿ¶àì]%×<3â/jzŸ†¯ »Ð>2|ñµÇ‰|3§ø«Âúä1k:W‰¼3ybÞñRCmkq¡øœZG}¤êv–²ÇtÖË4oÑŠÁaópÄÒšUâÔ¨Ö‡$ùeù\d“çù”©sZQr÷9­ËçäùÞiÃR­”ch_,­¦/ ]T¤å Bñ©ï'Bj¦ã‰QýÝEKš£Š÷~…øqðßDðÆï ø:ËÄ×^$øûaü8ø¡ð‡À¿õc°Õ5m'ÇZki6ºo‰­5´Ñ>0ü.ø­¤é:wˆì ¡‹TÝÅEyqøØÌe|fUS*|¹ž]^•iÓZÅ:ní­nèΜ¥*rW÷‹~íßÛåù>‡ø¿£[þ1ÜûˆÃS­Sâ~Ú1åW”g¬Â¼! °ž²©8Ï–NrQç~ü>ñ?> x_á¶ž"Ð<}ñŸöÁ]W¹½ŒE‡t¿‚_¯n¾ x›U¶–H ¼ðן|CÔuÕŠÅö,ÅÓ ×Œ¥C1ž6~þ —sFÚÝÖ¯jqº»ŒëS„a{_–Wz#<¯'öù,žœ\3|~~”ý§î§Ë…ÂÞµ^IJ µ<-Z³¬áÓæŒœS•­—â-/ÚÆúçŠ<+uiðçö`ø5£xWá®ãߦ¥qáχ?¼5ö¾†{KHm|OãïŠßîµ zÏÃ:h—^Ö/õÔó$¶…ÅÚmF¿öF8z÷«âªJ·5JÓ³©ÖTáN’J©+SЧ+FNñ^v3(¯ÆĘ̈GêÜ…P¡ “N0¡ƒ ¦©»:t«Ô«^NU#B<õ%*ñýä)Úrá~"üXÑ®|5ÂO„º£àO„º†¡¦É{i­Écwñ+ã·ˆô‹ŒèÞ(øµs£FmüIq¦NÊú/ƒôt›Ã~f\W7*’ÅÓ‚ÀT†!æúж:*VjþΊkÞ>o‚é{õ¦ÕZ‹ªM¹yYæ‡ÆåË"áܰy=IS¿2^Ûá$©J·"~×’R&š©B‹j2RwŒ}ûöý¤´¯Ùc^ý±|Iàû ü%мu£xâÓÆZ•ÿ‡þ'êWþ ÕtÍO×ô߇ºž‹ý§uá˽_XŠ5ž{›{éÔIq¬/šØÃ‰²š¹Ä2*=¦2TÜïI(ÅÉÅÔRQMF;F.)Ùs'¢šÞq.…*ñv:“¡§^4Üj¹ªòö•!MTTy%9)TžóœjÉ^~ÍèåòÕ¼Ö ›õM]Û7êw6úleÇË.¡-ª?BF Ü:g ÷#Rþæÿ rü"Ÿéþ_,*å«v½ö©Ý­íÎã–é]]m­áŸ x‡Æ·dðVâÝ1ýŸÀÞñ'¦-ÅTxSGÕã. ‚Wv@ëŠËŠ¡„JX©BŠóòp§ÿ¥Ê/ÿ%ÿí{°9g™T• µç Õ*ujÛKÚôá(ÞÎöæ¾Ýõúÿáÿügöþø¡oׂÿcߎ÷6·M¶ßø[Nøqfp›÷´ßµ¯ 4q²ÁŠaÉ W‰ŠâîÂOÙ×ÇaïýÇ*‹ï§¿»¯Õe¾ñæi‡úÎ*ÆÅ]¤«FžM¯*µc$ŸFâ“Ý]oö¿ƒÿà€Ÿ·î»öIéÞ”ZLÄå‘:+ã9þ]ãŸÛà†Iìÿ°°ÙÖcRoGC,öI¦ùåW7­‡²Ñ/u;¶½×«ìÜ=ô#§CÚ,­éÔµãSÒŠJܰ§‚„"–­»Þ]/k%ô§„?dÏø'?ÃV°—À¿°w GQÓ¼–Þ"ø£-ßÄ}m®m_Ì‚î{oÍ-Ö@-!œ»‘óŸå~2ýµð ¶»¡øeµ]+¾(ñìšçˆî–‹a‹á-3XÕۮǖ%1,(åT¸fU?ªx?à×xéÅË‚|=§«Ÿ}^­wV7ƒ‡²¢¯RjUç>E¬•8M¨©JVŒd׋Ÿq[Ãxí,ÒU#†çŒo s¨ù¥²´SµöW¶¶[»/=ý•oÙ3öÕ¶×ßöpøÁ¤xëTð ŽOøR÷J×¼ã} ÖwÙm©j ñ~›¢x…t{™~XïRµfà>z}GF?¼ö¼LÊV)ÅO’Ž3 ^–39ëû¿¬Ðr„j;;SŸ$´Né>ドùéå5ùëÓÖP”eN¢]ù$“k_‰]zëo°kð3ê€ ( €?ÿÕüo¯ìƒü¯ ÷Ÿ‡_²çíñwáÇÄ/‹¿ ~ øÛâß…¶gÄxVÖÃRþÀÔµ++ N×O‹BÑx_¼M7U¶¹¹Nµºk;[ˆå›j·n+:ʰXªx,n&•MexF|ÉI&âÛ’N1W‹IÉ«´íÒÿO—ð_fÙmlß,Ëñœº†•'O‘É>XÉ(Ó”Ôê·&ýš|‰«ÝÞ1åeø ñâHÞ ÿg¿Ž³Û™Y ›àÏŽ.!ó£8ŠqhòªÝBÕÌ€Mæ6VÁÿiåkÞúî [ª¯ þ{^Í­ŸX³Ž<;Åm:ØÙÇ$¯tðu,ù¢âÛOfã'ei¨¶£%{¿  ñ?íý‘¦øwãïìíñ3〴vHôµøÇðçâ–ñ ÁÉ,Ùeø{ñûLÒ­þ)øZY¦1"Åu>±nëDb(váò~yUÊ1Øl.*K_cV“„ì­ûÌ<š¥+.mcÉg&í}O¸¥šqîð¼S’æ–]¦¾³…Ä*”Ÿµu_±ÆSŒ±Ó¨©ZœÕX8RŒ6>‘ýŸ>ÞüK¹ºøyð§Løú¾ñN½áÛü<ø¹ðsÆăß<ñ‡þ üQ°ðÖ“ð[âÞ· ßXçëÞ{¯ k>%ðjIkwku4V±¿›fÐÂ[Žx9W‚œèÖ„¡Z•EûÊ)9:Ô£$Û§S–¤)Öw‹Ûé%ÃUê३氘ŠiQÃãpŠu°xª †2V¡9ÅÔæÁ©^ß³æ©I¸~¼xçþ Wñ·Zðf¹eáø†Ò_jß/"hþ=ø¹àŸ_xÊêÃDðö¯ñB ézú¶¥ Ã1ßÜ,RÞÏom'Âaø» Gµ§©Æ—*j\¼ô)ºt§>]Z¦¥)ò¦”çÊŸº›_©ãøˆÁÔ£B~ÝâTýäåì±uJð§Ï(ÁJ|°§ MIR¤¥îÎîà¬ÿàˆß|i§øjoÚ3ã/Á?„ž ð’^7ÃÿÙ·áŽom<ðêÒúæUÕ×Tø£â _x›Æ¾:ñAugá¯ÚãÃÿ!»—lן²çÀ­7ĵk5ŸÎkO|}øï©|rñ^¬·!Ølít†‹x´aE7ñoíú.dÕ! _`ó¼sºTpo™Å4’æ…¦%8è’”æéÉÙ6ܵýK†¾Œ¼e‚W…ÃSÀàçí,ãF4+~õÊRu18ªõjÔ’œœâ¡q‹²pp\§S¦ÿÁ.ÿà›ú+M'­ÿkïÚ"þêí5=fãâ×í ñÏDñ± E ¶³­xsCñ…´=OZ´‚ W3X<ñ[“ °‡÷gù׌¿lg†=‰©‡áœ—=¯ìâíR9~ /¤¯r3 ÐĤÛm¨Òvv“NV·ÚåßC¼>;+þÌâ,D1TjU…Z޾"µzµ*SŠ„gQÑŒ"ýÔ¯og++ÇEo¡|ðCöøUt·¿ a?ÙÃ×ð+Å­â ØøÇY1¸]Þmþ­a=ä™* äÓžOòGþÚ3_m‡áÎÃR¤äý›ÆæxŒCÛÝ”¨á°ÔéÝ;éÎëªëúžKôPà<ªp¯(QUâ­ÍK FIî”æç+;.Ÿð}úŽ4Ò­ÇÃxGÁG…µðwƒ´]"×@‹1ÌSúéÏòß~Ó¥/àçG še9=I}¬[ 8úO_ëwgòoõƒ< ‚’ÿf«Zßóò«_…8ÁÀüySâgµ¡OÆ>&»Œ±ýÑÖ.-àlŒsob-“ôàq_ÏœUô°ú@ñ‹‹Ï8ÉjÓŽ¼°ÇË NWMZTðð·Ž··=›ßÏë°<¹zÿeËðq—wIMýõ9¿Cšâ[‰ ·Ï•°K÷²·xó¾Oùôˆæ\EšæØÉæYœÖ#4”ªWæÅTil¹ñ’ÄJÚìšòHú*T)Q%ËMt ¾èr¯Áœ[ßnÝî¦Åc¸Â( úñó^at¾¯íë,?òFR„?ð\aÿ’ÿÀÓ’½—?{]ýûÿ_{xü~¾½k‰B)Ý$™AT@P@P@P@P@P@P@˜ÿð\Ö³ø#¯í'iug¦Õ¾9þÇÚ5½ô¶ÐIÖïãƒuÛ1|È%û(ƒGÕ—¤cÃ`¹ß²C*ÁbøwŒ3f]–KC—*8¯«Gë‹Ûàeíé¼²WžîÂG·W6ÖÒK½¼Oï¨pŸÑÓ•ÐfœAšar÷í(FªTgˆ¯Q9?r½5J…GéóTP7;TùŸ²éã8ª5Û’£…¡:ªÒkÞmB)Ûì¿{™^ͨÝ;iý÷€OõürÍÍíï©ýp-P@ÿÖóÿÁ¿à¥?}Ñ~Í:‡¬¶þÓø«ãÿx&À CX[k~#Ö£8 ŒÛõÈàƒ_Ò8ß8GEÖ©‹S¶ê’îåQSãò?„2ß¼BÇ⽌°*[©Õ¯J7Ê¡IVüݗݯÖ>ÿƒ{¿hgˆ\ü^ý¥ÿeß…™v-2ÿÆ?õ4ÈIFèaáÍ«MænR‹9nàÎ8¯Å¸ÛéàOÂ58›ˆ2œ“åÿkÌ0Xfçg.XÂS¨Ûå\É-ZOM5ý;‡>‰œ›J_[äåæ÷U šÞí–²›ö >k¦’i+{Í»/º~Á!þü&ðˆþêßðRÚ¦÷Á¾;›E¾ø•ðûö{Ñ´¯…Þñ¥î‰¸Ó¦Ô®ntßëpÜÙ½¤q íu+i¦µŽ8n ±¢þPãÚ‘ôT˳Oa…Ìp™®eB›”˜f\±Ÿ7ü¾£Ia[½ýÙKÝ“æQŠ•åýÂDN5ÊòйulvcJ–&TGíèácz6ÒïRPŒÕ£7iT•5{GÊ™ôoÃïØöð>­ š/?kŸŒúâJ%X~*þÖÿ´½as ]²Ksá o‰Òøz )d”9´Ä·¨ª¯ç|Ïö·ä¼A˜>ðß‚x‹:ΤÜaF–,ÂÕåN+ÚNž#B’r‡ï«Ñ§IJRŠw³Sú3Q§…£[>ÌhRÃÐKÞöµÚvV´Ü]V“Õµ'6Þº´íö§†m¾|+TÃ>|>šÐA ³[kÿ‰^3‰í?y“Ëu}ooct· ‹ÛÀÊß3g·åÜWûC|RË¡ÅÔxS…ñôã)ÕËá‰ÄqqUŽœðØIå¸ ©I©,F;J•ÁÔƒŒŸ/×ež ð¼lòØã1pmZ«Œ0”K©ÔZµ,úS„›×^þÇañ¯Æ:‹ép4©£ÙêŠóé¶rC`š½Þo¾âëÄz‘´‚ /xbÎÞ ¬×WÌ¡a&éG“ÃÿM8·3Êèâ£,«/Îc:Ø:–æ5òÚ)Ô¯žc¥N1Ãe5të*ØŒ^k5àëFŠ©Š=LG‡<=‚§YÓ¶©AòÎQsöPªôŽšmξ"RqM7tSn¤\­âo‹:î½hç¹Eá½3Å‹¥›»Í6{ßÞ¬©¨otÉa»ÓuŠìI¾ø^e)&ÅÏÅx™ô©âÎ+˪<²x‰ÎŸ ฃêO_W“â]JxéSÅ`e¸~[N41Ê®µgV…\e%B»£NkÔÉx-˪¨ÔŒñu0ÞÓ’5+Á§M8Ô¼jRªù©ÚIZJ›æ3KË?¶|A®0 ø ê7/‚þñE—‡æ×¤* ¿ö^£5‚éž%UPÍû¶‚à(ˆ“šþP«Ç~(ñì©×ðƒŒ?´3œ¼Ù.wƒÉe›JÑ‚©õl°ÑÀgK•U«7‡­„ÄÂ’Š–Ô|Ïí³ò¬µ:yÖÙQ[b0óÄ*+WoiMMÔý—¼§NûT¶‹’ºñ^©ÒCªøw—76íåϧá +k¨ãܤKm5¼„v`¹í‘Éü_>ñ·Œ²üdðüeœ‰Í°ö…Xãøv…*ôe+IS¯JZ3}#RSÕÒu#ïþ!ÀÔ¦ª`qxèQ’¼]ûÂ÷ô8ÆñŽ^¸æ\i—ð✞"§>U_•Fœ¥ieXjyš‹šŒg<5)Í'ï(Ó”å+8ÿ^èåÕžT²úØÛ.DÕh^í'üYºW¶©JI|쟟êÑéɪjQèòÝM¤®¡|ºd·¨"¼“N[™EŒ—q€.žÔ)q†=ÈËümC†°¼ašaø6®&· Ã1ÅGS óÂ*óXiW‹Qq¯**ªqO›Y(Ô”á­Ëå‹– Œ±êÇ:Puâªr®uÖ<×·—ufP¯–:€ ( € ( € ( € ( € ( € ( ÁÀm­´ô$6ÒG11$~8<õÁÓ™|7júÚêͤöm&›I¶“»IjÁ$àbì*î ãùC=øÒe8A.w¦úµýí~¿æ ò9úsþxªæÿÚ#ö¿ý™?dÛj´wÆÏü"‹ÅŸÚ§Â¶Þ-Õ~Ϫx‘thu—Ð4{h®u=N-(êë<‘DÉÜDŒw:†ý{¿?Á ü5/ìËñÀ¿,üoûrü7ÓWÔ©eXûZU"ÜjRö®qR‹~ü'âÑü½âßå¦*2¤¥‰ñXÌ7ÖâHÓÁTÂÐá·‡\ÓP„ë*‹WhÍuvIÙÓPÖÜú>jóÆ:Ýͱ±¶šÛCÒÀÉÒt uÑtâ1󛦵q{y¸·&iœ±õ8¯Ëó¯†;­rÚízTŽ};ÂÓ ®æª½¶£â›UÚ­4©‡·Ó[J6½ÎØð‡î2üƒ†üÊãšx‡‡£™ø‰Z4êa2 ”Ó¡„uaa±Yæ<©Ö«J¸L–oÛ׊…lÊtè¥ |ÄbsÚ®Ž[9RÊ¢Ú©‰‹÷ªYûÔðó}ºž!{±Ö4y¥ï9ïoK­Zþæ[¯xí¥ÜÎâK…ð½„À]K!ß É3NÏ1œ9Щ†Î0ª¸zôª$§Jµºu)Í'$¥ ŧiI?Š2”ZgÓá±qt)â°òS¡R Q’ÕJ2WM>Í2·ùë×µyJM;¦Õ»hÍ‚’VЀ ( € ’@31$ £,Äœ*ªŽI$98QŒ§8Ó‚r”¤¢’M·);F1JîR“ÑE&ßE¸®–­¥þF6â/ø‰nŸÃÚö‰âí%xnÛBÖ4Ý`ZM”’+¯ìË»Ão$n¤2¾Òüýl߇x‡ „*g¸ vDœ^"…Z1’i5iN*:ÝhÚz­/¢Æž+ ˆ¿°©N¥·å’“þ¿=šñ̀؀HY…f)o<±K•ŠÃI<®íE˜ð=»2ü+4ÇÐË00•Ln&½:4ãÎr•J³8F0§Ôœ¥)$¡Nœ¾Ìdô"­HR§*µZPŒ\›m$’Wní¤´êÚGòñþ’¾ðïÆÍwBð_ì± êß´kÖÓ-SÆ?5|QÔåÓg–ÛV¿¹›Dð爼¡¼÷¸·³‘®7WQ»:CþÛd²O…êpMÄüQ›Sãé9:µ°Øj/M¶ù! ."TñU¹ç9B¤›j'Ë Où×ã¶)f2ú– ‹Ë-¢œäª=5npR‚¿D®—Yn£ýR| ø³¥|yø/ð›ãvƒ¢ë¾Ñ>.ü:ð‡Ä#@ñ<Öþ"ÑtïhÖºÕ¦™­Ãi-Ūjvq]—Êw#r±Rÿ|Nà\_†>"çžcñ±xì5Ä`§^’”iÕ–|®¤#?yF[¥%{k¥Ò_½dÙ¥<ë+Ãæ´£(SÄQ…Ek¥5t´ºî¿ž«_za@P@ þÒß³çŠ~1xŸö|ðçÆŸ†ÚçÇ/Ø6§â¯„ú_Šô«¿hv1Ckqq=îƒæä 8/àk•PÏl³Çæ…Þ¹ýO8ðKÅ̇Ãü'ŠùÏfxo1²Š£)*2çn4ܯ¬#VQ’¥)$§Ë+|2’ñ¨qI‰Í'“añTgšÓW•%$ä­¿­“\ÖÚÿ3ÛÃЃô ÿ*üµ§k´íýi꺯¼ö.¯n§Ç?µßííû4þú‚ïh?kš%ÇÄ;fè^ðoˆ¼sâ-^ßÉbþ!Õ—HðÝåÕ¶‹¢6©kÅÔ¡bI®¢–‘Aþ€ð7èÍâ§ÒY…Oé`c—e~Ê8ŒF3 5Ô¯ÎèÑŒ§w*•#J¬¢’µ©Ï[Å¥óIÅù/ *_Ú’¨êVæå89ɨۚV[$åßv»œïì©ÿ&ýŒ¿m/ë> ýŸ>1ÚøŸÇ~Ð×ÄzÇ€uÿ øŸÀž4³Ñ¾ÚšuÅüZŒtëT‡O½š¹6hÿi€¾Õž"þ׌Cÿ< ÈèñGå4¥ÂÕñ>ÂÌ"–6´qr‚©õw9Qö±ŒÝ/içÉ=$ù9¸8k‰qSÀå•åõØC™Ó© S•¯m9ÒRµ×7+vº»Õ_ëÏxûÁ? ¼âˆüYáÿøÂz|ú¯‰¼[â½R×DÐ4-:õ—Zž¡zñAl›¾U†wùTÂþÂø[ð[öªøñǾ*Ôíô½ÂñîwâRY¥Œ\3ÃÒ\[êš²´gžO)lq18 Hþ‚­ô2úFe9žÅœ1™åy.+0ÀágŽ•_ ‡ž?CFU§N\‹÷•ÓQ”£ÌÒ‹~ò¿Ì.?á:ôjTÂc°õ«B•Iªjj3’§NU%Ë«÷böO¿GÁÏÙ ã÷ĉ?ðpŸí£áX|}ñ_‡þñ?íq𡼬ø¿Z¾ð“迳޳ðŸá¯†~Ëá· éfñ=–§¨ÛÍmg æMN]ìÆGÏú‹ôåð;üúÐྡAá²nUb«áð‹VU+ãUz²ÄÑ¡J§µÄËIûÊ:4Õ8¨¤ÿðÛ‰³>!ñY†.rON³pŒª{8¥\‘P”š´;¨§Í);»ŸÁx¿à¥µ—ÃÛ“âìûðOãÄï†ø¾ðÜú?ÃMkJðÕ®¿ñ×Á¶ßþ ë×úåž•yâMIt;hú|¶w3Çb¯k0X ÿdú&}8Ão 2üO‰Y/æþ#ætªbq•ëáªb¥Fž!S–]Æ’ú½8Êr©Nš—=oÝQ‡Ç>%fY¦{VžM‰ÅPʨK’ Tù¥%:Å9>gd“v´v×_¿ÿàœ¿ðVÏÚúïãwÀØ÷öúø#{kâߎ>ð‰þ|`C¹ð?oÞ©:p—Ùx}â®k™fT8:„kT­%N’j¢•D½É­4’ƒZ{¶»_9ÿÁSüŸ·üwàìD—šÄž ø_á„ >*évçXÓ­eÓ5-ëöý¢¤±ÖôϰÝYK­ø,èzÜ$ÒCj÷q†R_øcÜ!ô*úÒã NW„«Äø<ªŽk˜.vªc3|DhÓ¡KÚÔŒ½Êrš¥KÙÐs§FSj-Sök೬^?ÄO%–Ò­8àe^T)4®¡Bs—*jíò¶îÒ“IitÞOüð3öMøK'ì%â¯ÙÏö|ðWÁ¿üSðWÇ7ñÝÇ„mãÐî/|/ðËUøWàŸhš†¥?öMýžŸ©_ÎÖWeþTE *YW÷_£'p§‰>àüCà¼.c€Èó¬n2¿Õ±˜™be‡¯ MJ¨PŸµ­Ma%^”ëP)F—-OktåRpÌñ¦0Êø†®U™T¥[‡§NÒPç‹„g IY7S–J2ms;r¹I$ßé‡ü©ð÷KðWü²=sM€#|Gøÿñ¯Ä×Sãæºÿ„{_¶øqa&s‚#Ó< C&8ïþþÔ#Åç_H\¿,ÄÆœV[¸G–M·õ—<\”ÖÑœgV]Ü¢âÛVIHø3ƒŽ…jU‹oÛcjË_îrÓVò´£¿Ï÷v¿Î#õ  € ( ÿÐþ+þ'Ïô`(ñDÓKQFòK,‰qÇË#É+lŽ(¢d–Yev ˆ¡™Øàs]¹n[‹Íñô²ü¾œªckT…8F”ç)Î\„!çR¤äù)Ò‚s©7Ë{Ú*T…n­V•8¦Ûm$’Õ¶Þ‰%«oD·;ã§€v_øÎ68ÛɺӼ'0ä< y–º—Š`*˜’ÛNlæNÓµ°\3ôxÃÃ_Øf^8ÂW§é×Âd5ÔtD¹ècsº*|ЦÕ\Q9F¤–#©{O•SÄñ4š\Ô¸q­^±ž%_e´©áßWîÔ®®—-;·ÎèštÞ#Ö¢µ¸ºxÒæ[»ýWS¸‘ÜÚXÂ{­j÷7¬…æŽÑ‹ÈÄ´¬¼ôùG‡\5˜x§â »3ÅÔ§‡¯V¾+0ÇU©)}[ ËšfëÔ[ÕT#6ëWmÏRŠs-4½|ÏO)ËeV”pŒaNœWÅ6Ô(ÒŒU´riZ6´T´Ý´ñ&¯ý·ªÝ_EÙ-²é–=†“ajöú]EwTh-#M¸k¿Ò¯Å>8ñ¾+6ÃPx<–8iÐÁal’Áåø\-JX "„gR•,’ß$Ô ÝâϨM¿&jhúÖ­áýBÓVÑoîtÝFÉä’ÖòÑöO ÍA)Œ¸uh˜«‚ ¸ê8úÎãî/ð߈°œSÁY†'/ϰU':¨¸©Ó•Zr¥UÅN…ªÓ“…X¸8ÔJ<ɸAÇ‹0Ëp®x,”+aj$¥+¦“º½šz5tï£ùÞ…Íä××—3½Ýýä×—,¡îîd–S%ÍÓ©Ý4¥æ—p¬¡›’8Ç‹›f·æÞ&Í%_ÄâªWÄâ&œœëלªT©ZªŠ‚©Vr”Û—/3o•Y$ºhÓ¡†¥ -R„ad”b¬”VöŠI+W”jP@P'‰|Iáïø{]ño‹5­/Ã~ðÆ“¨øƒÄ~"×/`Ót]CÒ,å¾Õ5[P¹t‚ËNÓ¬àye•ð¨ŠO×ÔÈò<߉³¼'pö¶7>Çâ!C‡£:µ«U’Œ)Â1M¹I¾Ú+·¢1ÅbpØ,5L^*q§…¥)ÊNÑŒb®äÞÉ$ÿðU_ø._ÅÏÚÓÅ:ÿÀßÙoW×þ~Í )°‹PÓîo|#ñãe•£Iw{âßk s§êžøc©ZB&±ÐÒ[;‰4Ðך¼ëëgý}¾<àvY‡â¾:§†Î<`œyªÖ”a_ –7<._ )R©Z”›úÆ>Jw«O ”i{Yÿ%ñç‰øþ!­<VçC"Z$¯Ö_ÏQ¦¥I|4“NÎóß•xgÂ?ø'oíõû>~ÇZ÷üÄø×XýŽ~[Íá-?áN³w¯øÏáwÅÚ3Åzߊ¬t¿øwágÃoEe>¡àý~âæyƽâØ"¶ºÓ ¼[Il„—ûÇ?áNâ̺Y7apùžW5Qº8ÚtñtÛ©ÍF¼fâÚå¼ ãgf¹]­ùŽ1Æà+}cRtk¦½êmÓz=å²}wOÒßõuÿDÿ‚ƒ|Lý¼ÿgo·Æ{[MSâwÀ¿hÞ×¾&höi?Å}?WÐ#Ö´?Í£ÛÛÛÙèÞ,kt‘58-‘-&>]ÔQÀ&kx¿çö„}x'èÿâ&_˜øtÖ„¸†–"¬2÷)OêU¨Tq© <¤Ü¥„šjTÔäçFOÙ7%iËúßÂÞ/Ì8§*«O5\øì,¡U$½¢”nœ’ÑMlí£ÞËhþÒWùø~¢w_eû?‹4»öQ¬^Bà? xžë8|)*aÈÏýô ¤ªý(8F)Û=¢õ×áÀf²ìû]y¥ÛO…ñ*|œ™KgõY/¾¥%úëå×·øý|"ðfµñ»ãG‚|qåëüoáO Ï|ÐÂ%’óâ—Ž4o Ow+B'Ýã¸P©µYrÿOœSžÑÈòLN}‰„ªÐÂQ¯‰šJMÉa(ÖÅM>YE´ÖI¥$ä®›Lþ0Ëð¯ІR©(ÁÜIF îçù[Õëq¢hº†tmÃz\1Zé~Ò´ÍM·ˆ,QCa¢Ø[é–pÄŠ6"%µ¢€Óþ4óÜçÄ™î7ˆqr•L^a¯ˆ”Ÿ3r•z³¨Ÿ½y6Ô•“¼¬•îÓoýÃѧ„ÃSÃGHS„b½"’òìi×’nV½½³Ólîõû»k >ÂÚâöúúöx­lì¬íb3Ý^]ÜÏ$0ÛÛ[A<ŽìI<žœ˜âéeù}*•ñõêF:TâçR¤äíB+YJOH¥»ü"u)Ò„ªÕj4¢®ÛÑ$·môK¿ôþ{økû`~Ê?¼['€~~Ò¿¾'xÞ+I5ð—€þ(øGÄþ#{R9&¼ƒHÒõ;‹Û›hc‘Yš%`zuýs‹þŽþ<øÃqã8àþ!ʸZV¶/„© *ûsËW>x«=ífxx+á¬Óð9v? _¯îB¤\´ÞÊúü¿ÌøCþ 1ÿzðü£â7€¾xÛàÅ?Þ|Bðt¾8Ñ‚¶ž)¶ðÆ­¤[Ýø~_"X¯¼ÛÙ&·‚Þ9..!‰Ô?gωøï³²Œã'”²<£˜c3,M,n Bž>©BXû •Õ_e?k&©8Æ”e98Å9"~)dô¸v‡WÃâ-‰¯R•:0tçRn›jN/ž0jêËÞ»m+j“ú+öÿ‚œþÊ·?ÆÛ^ oŠþ*é‹{âo†ßþëñ5–‘¡ëÚ>—âÑoqp.´©uI¬Z­Õ˜Ÿíp}¡ËÀ8íÌ~uáÿpÆ'ñù6kánwÄùNYS1Ë1NtãO0«%Ú\•!DhÕÃá«Û—ÛÊ6j£¤œPñ7.ÍpÊy},MZ4kÓåmÒŠvm^-ÅÊ.Qæ¿.»'oäWWŸöÀÿ‚oÿÁS¿à£>*øSðSøÙão€:—í@þ%×,ô¿x×À|ñŸX“âÿ‡hˆšîhšuŠü5Ž×6ºåþš/nR[v¸óa1÷ƒÅŸ£§x½áÝ ³šØ¼? aëåòq¦Ô«VÃåtÝ,> Uå.ztªÃJÕÿyVÎV§)NLþfȸÃ2ÈóYçTãNxùB­¯~Xμ”§5£qwj>ìtø´±èÿðKÏø,—üËã'íwð7à'Œ~%ø{ãW‡þ,|QÐô-sGø‹à¯ iZÕ¯„otÍOľ5×|-âhÞ½°>ðÞ“-ý¬[ÜÀ °Û¹Ž&?’>“?B_¢¦QányÆ\ƒý_Çåy5zÔ±9eJÑQ­gK Ô«U©Nj¥iÑ Üšr‡´¥Q»ýçø‹Æ˜¼ó —ÔĬM*؈ŬbÛ‹¼ª8Ê1Œ£Ë)+'gÊ´Z­ÿø:{âŒú×íOðWàÍ„:Lö_gO _Måeµ™èp Îâ—ç¢êß³×ÃŒ}ø2úž–yÄ ®kˆ¯N<“«Dæ°PžŽSú¾s£ ÊnÐn1ŒSiüÿ‹½|ÇqTUYK …P¡=¢â¹ªµ­—<ù[VÝ]ÉénWþgÿÓøuûR·í3à?ÚÃâ?ÃÿŒ7¿°Þ•ûC~Æ>4ðÿ‰ïô=kBÔuOüH³ƒâo„n´ ae¶û[øBÎÙ ˜Áö‹hnhYýÆôpøÌ÷'Èc™×Ëó ÃUÆ—Õp˜œ.aN…i_ŒŽ&…_r¥':´åFtqPœ*Nx¨8ËäòÉÔ§ƒÄãUU£Bœný¥HT¤ç'Õ¦á%ª•¢ù” ÓJQwºûëâ7Æï~Ô¿ðj?~=|R¼¼ñgÅß…>ø'Vñ–©wwy¬jv¾ ý¢<7á}+[Ôo§šk‹Ïë¡j·÷³;Ks6Xœ’Oó¯ƒGŸ 8é+âFq’åXjyµ9å•p®1Œ!ƒÃç9EØêXZTÔaEWÅ óß'ÅB7Ö\õÿw›z?qÇ­ÔžÚßôI~|`ø-ÿÁK¦ýƒÿfÝOö¢ñÕ¦•‰n4‹MWþøað›âíkið[âgˆÛVŽGHZ¼çç9Z1æqŒ¤ôøþâYð¶:¾2ÝJÓÂV£{rN£‚羯ÝQz$ÛvÕ[_æ#áWÃ/ŠÿðPOø)ÿ…þ|e×´¿øÓöý§uÈþ-kz&µzÚvµ&£ãßëŸõM ö¶ºµÒnô?jVzBÅå ],!R©¯¤ñ¿Ž±^xYŸñfY,ã •Wúœ#h¼mnL[ MÊ<¿_Å`ãi{®)Þ)7n^Ë)æÙî[\<ëÇÚ7ÿ>ãz•[²ÝÒ…Mº½ß_ëÛöTð—ü3þ ÇûPþÚpEmû<~ÉÞ*ðìqð K{²iZ¯| áÛ/‡Þ!½Ñ\‚–^ µÖ|O*´p-•Ý¿‰-$‡&'gþFúpxGœ ôo̤±<_â}’PÌ`á%Ë–ÑÇa-Î.*3¥ŽÇAÒ÷?‡õ*ñ’pšåûÏ ²•,^gÅð.*ÃâeK[§QÓŸ³µ¤õ…'Íï^þÒF™òwüÖMãwüÿ-øÓâ{ µøkã_ÚžÏI¸‹ÎžXâºøÓá߀þmòƦÝí¼-ð*÷åø¹*¸çÎý§ÜKO‡üÁd´dùñ¼MŒãkap0«Š¨¹nªj¹¾GÏ[´¶ðSñ\OS%ü<F›þz²Œwèõ•»Ý®ŠÿÿÁÔ£ñ_í¹û+| ŽK&Ó¾~Ë ¡Ô£0‹ÛO|kø™¬xÏ[Ó®l¸•E¶áÍ>VbA_´(`¡¿ôGÑg(Ÿ }x7R”éׇ QÄJ‹„£:ÔyÆQi5.iI;ë}ícäxßwf5"×ûó‚w¾j üVµ‘ýÁü-gáø%¿ì‹cdï"k ñŒ®žGy$mKÆÞ:ñ7Š5Fy$,ÌßnÔß© Ï÷íâ(ñ/ÒÛŠñP¢¨}RxLI(©}K J‚¨’Óß„#®î×wz/ê_ ° À¸999Æu/ÿ_*Jvé³oúßõR¿Ð€ ( €?ÿÑþ+þ'Ïô`Üðׇµ/ëºg‡´xâ—QÕnµªÏ:ÛÃægœù³2$6îÄáÉÆ$Œþ…ág†¼IâçeÞð”(Ï>ÌñÆ’«UQ§Íì«VnuyfáÒ¡VMÆ“åQŒ\¤šó3|Û ‘åµ³\{’ÂQ‡4œW3µÔtZ]·$·[ÞöZuúÔá½Õö‡jþg i´ý[Y…‹Aáæx£ûN›á·dG:„–ó(¸Ô™UÕ[Ê·TùÚ¿{㼿ô\Åã83"¨«xß<&72¦Û§”óÓ„«á2yJ kR…jqÅç5#”éÍarêt\«T¥óÙ}Yq…:y•m8zV*/zö~íJé_ÜRM‚m6¹ê¹{©ù¨ ²‚B®@Î8E-ÉQ€p$÷'$òI?É1q­Zœ+IS£xÂön4éókhïhÞSjüÓ“”¤ÜääþÎÚ7mwõÖž_ÝJÑõ -ü3¢ü3¶Ô4¯Û_ø¿Åñéºî…儻Ѵ;Yo.§¶M€Hc¾»¶µóäq²â ± ߨ5°žx{ô^£Ä<ÄØ<‹\S§ƒÍ2æ£ N]–Щˆ­^„T«ÉˆÄPÁGV³TqøxÇQ‡" ¹ÎcÆRÂc°u)äX*n¥×¼jÖ’ŒSíxFU9#iɹJîÖòãÂÊI$ùWLNFI6òàž¹$õ¯ä<LL¥UÊSx|Sm»ÉÉák¶ÛѶޭõw¿ŸÛÊ:$´\ÑÿÒ¢v^>ù|YªGÎØ­´(—' AÓW®âHËqýk÷O¤úö~7çxh¶éQ¡”Â7w²ŽS…Òýun×èþkç¸S\ŠŒºÊuŸßZ×õ¯)mq5­Ä6îðÜ[ÍöóD3,7H²ÛÏç2Ã:+(îF:_ŠäyÎ3‡sl>w«*Ü-ju©ÕŠNTªÑ’©J´Óž…HƬiK•Ó“äœÓ÷ëц"”©UŠ•9Åŧ´£%iEùI6Ÿ­÷K—âgÅo„^žËÄZïį‡Äz½î‰y§k~6ðÞ’Úoôû/í?ø[ʼÕ"h5ÓÙuXm\$âÂf XØê|#ã?žÅÿ8w4«”ñ *˜ŒV…©8à³*n?Ú4Óæ’XlLçK2Ëß2öØLUY¤•òNy—劦I™b¨Ç…j0”çêQ“×â*º;T†ë™^¿‡üKáßÙ.§áh~$Ó^E„jÖ´ÝnÃÍ`­å›Í*êîÜHÚX6Ó¸ä1æ¼7Ÿä8êyvÆ`1µehÃB¥Isû7(©Æ<éKÝn.Jê×Õ_êèâð¸˜:˜iÂ¥5Ö2R[_£vºïÿ üÇÁbÎê¢S©Nuäß2V\·jÿ jÒv?¨é2I€d“táÎ::WüøÑ•éEënU¿¡ýH÷~£+AP@,_ðs¿íiñ á_¿²ç„÷FÐþ8XxŸâ7ÄmBDÿ„§ÂÞ ñá øÁp.ô;¿ÞI¨êQnEºþɆÖE’Þy”ÿµ_²ÓèíN¬38«7ŠöÒ˲™IiNe˜â©8ÍIUçÔc;>^jÓ¦Ô¡ ËùãÆ®,•?eÃ:ŠÎ>Öº]S·²„ºr»ûFºÚ)èÚ~ÿëÁ(þxëK—þ ûUxSIø‰áÝ'Åú–•û;ü+ñÄZÖñâƒ5o#Å¿~([Æï§ðïᯌí›OÒt‡•×Ä&²¹»¸Vµµ²qýÉô¼ú_ðÇÑŸ…)å™0ÙŠY–O/Á;¼= JÐXÜw±÷£…ŒœaCØÚ¼´irCÚV¥ù§p;ŒñÒ¯‰s£‘ѪÔûr–þΗ6ŽoyM§kWÍ+EýÃÿB| ý°þ8ü(ý‘üYàï üIø‰ðbóÅ_í|Aÿ ÿÁZçÚÃâåèð÷>èá Øj:†’'„~e›a}áÄ_<Ü?Þ=†¤â›R”13ä¶¼ÊÊÚ·üÃÀx(c¸¯/£+Ûë´žŸÜR©÷^ þ_î7üŸþ ûa|ý²¼Iû5~Ï~.Ô~è?µ-Cñ»¦èÞ×õïˆÞ$ñO‚|ñóTñ^9ð§ˆ,ô¿økFñdvz]´~dÓ¼×WsöxOðçÐßèáu?0|gãW¼ßŒs¼ýøÅ¥‡ˆ#[ ˜åÞ ð†1aãKˆ—´©Š¯K†Ž.½:Δc J½X¸Ô’§N2ûKêsoó—‚r¼w=¼E§ÌÝHÙ(GYÏÙÅÇ™ë«4¯$ßDþC°ÿ‚Ÿ~ÐßðQïø'¿ÄŸºö‘ð÷´í#ñÿàÏì“à›Ÿ…šOˆtí#Rð7ÅŸ ÚüFøµªjšˆuïÜi–Þøg¦êV÷·k|ÑÍ Ä¬QÈQúßÂïÙóÀ>}&2Ž;á'šTá£.Äâá }xb% ÓëpØ'Nµ*xyIQ¤¾·Ë(ÝÊp´¼Z_ ø©™g|ˆË±¾Æ9†"¬)·J.7¢ãÔº”§»ýÕ×K½À?ø&WícÆÿðSOÙ3Á~ ñ,pgö‘ðˆ-|E¢è–:ýÏ…|­kþ7¿–%Ó µ¼Óôïø3Â.ÒE$-c}å°h›û'é™å5àfY9ÖË¡bé¸Î¬Úoa)9{NxÉûZð·<]çd¥IJ?Ÿp} V3‰p4¨µJWQ[Aº’µ¹Z¼a%£ÑtiYþôÿÁÖž8ѵOÚö ð±¸óuŸþÊšÇõë}É,–þ×¾9 GHu HQtÿÞ"dþI88øß¡®ŒúpE,UIsÔÈc‡U~ê_»ƒÑ+ªPœ,•Ý’ø›×ÐñT¨ø…™:jê5ÔùWWËv»{Í>Êìôoø'÷Á9>*~ÙðK¯ kžÒ5†ŸðMÏø'?¯ÚoQðÛ^iVÿ´ÇÇíBóÅÚâ#Pc$·¶‘Yk¯ Ãqm¨è +JpˆúCø§Œú%xeÄþ%ðÌ0uüRã^-s¢±j­z3Âa©¸Ñ^Æ5)MÓÂåôªÓQx…Ë,de^rúNÉ!ǹΠ$ĺ‘É2ÜRö|±j¬Ýåïk¬êÉ;ò´Õ7v“Vöÿé°ßÿÁÝ_¶E®„dÓ´˜ü#ý±/Ù¶Àðjš÷ÀÙ¼xŽþ'r’¾±tgcqeÜrÙÝõŸN̲¯}pX »_™f|YÂÔhÏ7N­:˜œt]7FjÎ5)9J´$£xÊ’žœºðx]V8>*©V´c:4px×%%tÔ)Ùótå–‘¶»µÖë_ŠúŒ¿ðOïø9cöØñ$Vz]¿íUñ³â7ÁmÄ0Û[Oyâ_økÅ:oì÷ðæ#ª ¸M>çUñ}ü^R®Ï:Gë–'ö <}Äø¿¤õp•©.ʸûG0¼#*µ1õñ2Âá«=`¹0µêºqIÎuay5¤¾rYf> œÇb3EF‹M¨Æ’<í ŸÆ£w𨷦Çç—üSðJËǶGíñâhæ—Jøà{DðÚÜZ!¶ƒÅ¿üCªiö7¶woÉs¦ø+Àæ0‘± ÏA»'ù ö¢ñÇú½à΂`íW‰3*°”£;7†Ëpuq3„¢¹eˆ©OVÜRWI¸þàžZ±|A<ÂVåÂQNÖÚu梚~P‹ûúlþ9ÿƒ‰Wÿ‡È~Õ‘FéÇ‚5o‡:k1I Ò´¯†ÿ²ÿÁïi–vвÖ¯µ+¹ ‚ó6zšÿB|?Êp<á÷pÍ |™F[–eØHSŠQå§JŸ*²V~ûI¶í¢µ•Ÿä¹iæ™®3'ûúõëTníë«O[«Y-ýµ?«ï‹±ÇÙëöOÿ‚uÿÁIÿa9>jŸ`¯ø'üŸ³íOð÷â&±†´?ŠŸ³•§ÁÝGZÖµ5«{+ƒˆ¼âmJë]²ŒV»üæû8µ¸ü»ÂŸøSÇÌ—-â|ª”q¯*â*Åá?á:°»Q¦x?áŸi·7PA¾yµBÞÙ#¨Ô²ÎÁdþ g|b±¶óÜ.]´gì”aG.£ì0ò§iËR/ßœ¥+ɵNIIßÅÄf51yV.q‹Ã`êVåœyµ•Y^j^òW‹Z+-—7”}þ Q±´Ÿö¬øãá »„¸[·º»šE…ÍŽ‘ñÃÆY»•d2·–šSË<¤¾W’z×ðoÓÛ‚«ø†ø‚V®' šø‹ÃÔåŠqTå†ÃÊ·=ôåú­ÖŸ´•;ÝAÉÔ”g$”¤£ÊÛŠ\¿ÃWüBãö—oÚëÂÚìãà|QûSx㿾|?ñgŠïÿ±ÛàÿŠ>"i÷†ü_ñŸU¸¼ÒµAj~x^Mjþéî eŒÝ8"IŒ6×Õ>$á8MpµLçŽñ_Và\¦x|ÇÏodèåµ¾¶•g9ÓNÖ§g5)U¥I+6çÉ*cÖ=a²Ø)昅:4­ñsV³n6NÍEË[YEÉék?ô†ÿ‚}~Í¿ ¿aO…ÿ¾xNþÆÇÁ ¥Óuø×[–×I]Ö|é5|Fñ5åÌZض¯©4·r4Œ‘ZÀ?” Qÿ>\!ãfeãÿÓÿ‡¼JâI~ãÅxXa)T|ÞÇ EVXhYÛ÷­rÖ®íÍí§ï·R2gõN7‡hð¿…øÌ£ «§—Õç’ûU$¯7»Òí¨®‘J×Våþr?à’?þi_ðS¿ø+^µªüDð øuâ­SâÇ |KþÔ†üMð.Úƒã'Ä=SâF‰y®A¦<¾ø‘e ºmî¤öòMm4Iþ“~Ñï xÅ £Ãì"ÃÔ¬ñ¼q,¾¥Z1½j 2ÂP¢¤›Œ©òÊŽÝÛ¼áÆ3œ¬¿ ð‡<ÁäµsL^*j –]í½í"ÕÎOªÙÎ6od®þƒð¯üƒ[ÿ‚Î~À¿ðPÛDð¾…oûRþÒ¿¶>ûL~ÊV^!±—Â:Æ¥ðö}ÑWágÁŸ\ë¼×hQüRøqe¬E䊶1_ÝÚÎëä©ûƒ¸ï‚3ž"μ'È*Ó–aÂrü"’© Ÿ¹¯‚§V”áËgJn½)BÉÒ¯Nµ)Ú¤f—æXì»5£‚Ãñ5IQÌ*W©ã(ÚQ«$ÓOÉE©-*C–q÷Z¹ÿ¿¼ÿ‚ª|ýáý‹bÿ‚gü[_üñ'‹´ ühý¢¼U¤üø á?j÷÷Þ,†çâ7‰Ú_kš¬> ŸR¸µµ‡ÂÐë‡R´†ÝD°;Hbÿ=~“A®ñsÆÃÆ~'âÉd¼1†ÉáW7§ #§ÊðÜHc+ªX:^Þ/iU¹ÍƤÔÔ¬îÿ[᳇‡èd8<Ö1•+¸áßµRÒ¬ïiS‹•WÉ)Y++ÅlèkÁ~)é_¼âOˆ7–>,Õb²Ót?øëBÐâðŸ‡üAã¢ÚÅö‰à÷Ö5‹ÿèwZ²I¤ÝÝ<*«’Èû¤?ãçx+ÅŸâ¼yà¾Çe^ c3ª˜L ¯‹£‰­E*Ï Jm!Zsu¢éOé“ÄóSTáNÕOß0þ žaÇâéÖâ:xuR¢Œ½Õ'(ï¬ù”9œ¹5nODµüð¤šMuþ¿¯êÿNÀ( €?ÿÒþ+þ'Ïô`–¦¶š+‹y¥·žY!ž d‚XäC”’bhäŠE#†Rþ}Ùfg˜dØúY¦W^¶1¡5:uiT*”ç†têS”' ®’„”–ªöm<êÒ§^¥Z1•)&š’M4÷M4Ó^M?ól’É4’M<’O4ŽòË,²<²Ë,Œ]¤–I¤’I’ÌI$þ±ŽÇbó,e\ÇV¥luz’©R¥IÎ¥IÎošsœç)Ns“ÖSœ¥)=ÞŠî8R‚§M(ÓŠI$’I-’JÉ%Ñ/øvW!b瀹2׉ãý"Ö.à~çK°~bÅ~ýô¦n~;q Y+?¬ai½9ƒ—`ã¶÷×U·cÀáM8{ –ü’}I³È¾#iRê ~4½¾±w \é?~0øŽÓW±a݅߇<ªêV—óˆÛÌ· ¸ñH`úÿ¡O„y_ŒH>áŒç:9t1qså§N¯:ÀÆ•UFPªœ+:œµ/ÔUàÔµ^OˆyínáL^>„9ê((/yÆÎ£qæºÖñÝyþ?ç‘ÿòý¥ÿa­ÁŸ¶Â_ø)'Ãÿ?| ñ{ှ,|:Ó¼wy¨jzíOá½+\Õàø§}ââ}]ðÏŒ¼Agãf³ºñ·Ù×vosm­yðM7ýS`pð˰ðÂa\¡B“JœbÜcJV¥N’M*p£t£ (BQ]WñZÒ«UÖG»i6ßW&þ''w+Þíë~¿º_ðkN¤¯ìéûQxžÖÒÞ ^÷ã'€´Ëé-Ñmak]ዪ&Ë8ìp£k•Ô¥ã<ÒùÎÜÿk^3¸«°4'9a°ø<Ë͹¯kJª|ד沌mÍktZ(ÿJøN›Àf5ZJ¬ëQ‹¶š8i¢ÓvÝìõèj~К®©ñwþ}øYà;{¼Ðÿgßü Òµ[ãqGm7ÂÏÙcÆ8½…AÄ“5¯ˆÿh«gÀRY†r˜Õ¾6º~͸ä8ÊðŽo…à¯iS—-Jø‰a¡*vÚ.TãZIóK–J)ë#â8{›6ñ‚¦.r¡<Ö½MÒ4ã;K¥×3в×}’»þž—•Ôé×óîkþo’²K²·Ýý]?­E € øKþ WûVx³ö*ýŽþ"þÐ>ðÿ‡¼Iã']ø{àiþ2:ˆðˆñWÄØø[OÔËðñ™|²h©5*s«xÂx¬M7F3pš‡$ç(8ÆÒøŽ<âÏõO&Xº“̪Õ:QÚm´æÚ‹M¨Aó5̯¢ºéë?±ÇÇËÏÚöYøûCê>‹ÁÚÅÿ‡/ü1m}&¥i£_ê¼¶±¿š('»°73Àï¿–À75ùŸÒÂÜ‚Þ2çÞ娹ãrܯ¡F´ÒU%Jqç„j$íí ½Ù5£;úü-œÔâÂç5iªS¯Nî+Tšvvò{¯êßK+lt|ØêûOFØÁ°xèÏ¿ã¸zψ§‰QStªB|¯irIK•ùJÖ~L÷乓]Z·õýÁüóÿ‚ÊþÃÿ±·í·û iÿþ<|{ðÏì‰ñKö3²×µoütñlW7¾ ÔxËÂvZž—¨øÊÇÇÚ啌ZbéRÿÂE¥xž;iôá(š{Kßú6ýšž8p'ø7ð_-t°¼wÃXzîxEdñx9V©YæT ¥/j››Yƒç‡Ä©ºª0«Ju“‰á ø‹WÕ'x…Ç4Ï• Ñ­‹Å,6!áàéP©_ NpS«J’…8Ê©AÆ>õ)Nu*Oäòx›#ɱ²ÌO±Âª’”yiÓrŠ›æšŒÚvR“rÖwz;$—÷ÿ2ÿ‚™þÖ´§ìâÍãΟ©ZxÛÂþ›aeñ3Tð]ç† øàÿønè¾5ð£Ç£økÃSêÉ%ÕåÖ™m6—tðGj#[¥Jÿ;¾–#ñ·ÐËÂßó î(ÂâëÃ5W‹Èq2›ú×ömibe<= \jÇJÈâ Ó­*š)ú×e9g‰9ïQ©<ßRu4,éšÔº»¢Á0àÞø-|„ΩáOÚ“ö·ð¿‡txµˆ.#šH´íB×Á× ñmÙr‚áHf 6þá>_–p~gS(ž¯úÕÆçñZõ%J4–' £FVŒm*0ÆS§MÝÞ”œmîóKë8‚µLu^5?Øòü6¢•““„Û–ïY86÷Õ-­gðoü™ð~oˆßðPÏø°.³ÿïÀ?µ—ÆÍ2É<Æðô:ú|-ñÂ;Ä7YE#ñv¬ÖøU“bòÄ ~‘ļO_-âL‡‡èÔ£šfê„”•ê:t0ümuÓø8ni4ô—*åm7â`ðQ©€ÅâÜdÝ 72z¤œ«R¥û¿zvZíð¯ü¿àmÅðSxŠòÒÚëWø_û1ø«ÇºSK r5–¤ÿ ~ øO¿·s–Šá ñÅü[— ¶VÃ?ifœ9ô`Í倨©PÆæf~ü£Î¥SŠ”m&¹ðt¹¡/vIõi[ô°t±|cEÍ^t©VšÛGhA=¬ªJÏËÍÛžÿƒ•>.Yx»þ gñCÒã_ÿ > ~ÎâêXÙ¯$´øs®øÇÆ1Û9‘ÚÆû⥺¾0åAÆF[úOèãÂσ<àέ5,~†°P¬¢¥í%NíÚZ^\¼ús[š×»i|gc%˜ñfg‹³TgŽ©ÈÛ‹¼ce¥›i&ÜuQ»OK$ßôeÿÒµŠÿ ¿h_Ú§ÄþÓü=âŸÚ#ã?„~éc’;†áçìñà/ |!Ñ4ô1C½½¼>+åÀŠ,G¾f|’Äò#öžñN#úeøÍœÔœgO.£“et¥ÏC SJ£RI©)U§97(¶Ü“¶ßKÅØ9ežpæ’iUuë´Ó‹Nq„Òi««)%f“V³Wßæÿø6ãâŸÁ…³÷í¡¦üJø‡à‡^)ðçÅ]'ÅÞ1“Ç&Ñü'›ðúÇá­–›Šno5Û«oZëÖ {µÌ1ì߬ þ^ý§üâ_ñÏRá\Ÿš`+`s 5/ªP©ˆ—×+W¼iÔTÓŒé:\“›I7.f’wû_³LŸ/Ë1òÆW¥F¤jRœ¹ä¢½œiüJï[IJöòßcòsþ¶‰ðP߉?¶/à üD¸ý›koEñà/įx:oh¿4áO‚¾øçÆþWº‹VÔ>¿BÓßNÔïítïí-?P‹Q·I´»‹KÙÿÙn­|§ Y©Ó©᪸¸¾xû)R«(Ê6o™r8¸Ù»é¯Úþ|J4ñ„lÕç®›š)§t­ªwþŸï÷üþ Ià¡ÿpÐt‚Þ(³ñoÅÛ³àþxOáç‡õuo¾…â+häÖô*åîíïîéêîì’Ù$¿°gÁïø+ì‘㌞ ø#ûþןþ4þÎ?þéþ$ñOÀŸ‹¿ ô?…Ò|TþÈ~"M­ø÷Ú7‚á!ðÂß%Ú®¸¥Äï0KtIÿÒN6Áð• Œ8º­6YÃXÙg/ZJðÏ Åaªb*I§hRÂâqqÚrq¿½5øæ[W9Ï-ÀÅÔ­¤°Ü©^Rç« ¨¯78C]9Ro½¿»ø&gÀ¯~À¿?f‚ÐÉm{ÂO YÚxÏXÒìÚµÏxŽÖöçâ?‰íí7O1]CÄZÍÅÄh]ÜA\’Fç;-úZe9·Ó¢‡ÒWŠ)p ÞTè«J¥\>Q,#,ƒtã*’¥†­O(ÆœeìéN1´´õÅ^/ §Â>WŽxm^ÊUÔãYë}§·eu}.~lþÖ?ðl—Ä _ö¸½ý·¿à™¶€~júÇŒ5‰þð÷<7¨ê÷ ¼gã-W\Ö|pžñ®‘©j~©à?]ø›PoìkGºŠÚBâм¶¾D6ÿô=šbü9ñgÃêøIÿeq7gX%Ñx”ð˜Ì=NJ‘R©F¢vR:°i©B¤#$ÓZ'P§œä´gjø<΄ô|žWNÑ’wºm=Ó‹{§¯Ñmÿ¹øÉã[9ÿà§?ðP+ïڇºDöš~ÇŸ³?ƒlþ| ñ­ýµ¥ü/kñÿÅÚ-Õߎ~!ø6K‹ØäŸDéö×OnŠÑHŒèßçWñŸÐÇèC†ÆfždÙ+ÆŠ˜yªj5êfUðón6«ŠÇUu^‚nJœcŠ­yÑ£ýw–ø…â4áC6Äbipښ眠¨©¯å§J6u$õ³“pŽ’—-¬þÂý¦ÿaoø&íªxâwÆïÙf-Sâ_Ã_‡:oÂýGðf·âÏ…ÞÕ<£\Ú\hžñl¿ ²ñyê,E)B½¸yÕiS£Q8ÑP§ uaV2«?Þ3È1¹<2|Ò)etãÆ2|¼œŠÑå’q”d–ò›»º³´y~Û~ ñœ¯ kÿ<%ây­ää𧃵K_],ñœÄ×øk­ÝÜO®WÎVÃtã¼ø©Ç_Mï²U€ñž>söžÆ¾ ’åíД5XUxx×tª8ÎØšµ£%8Ò\ªGÌä™g‡œ1ˆsÉþ¬³ [š2•z©Jú&œå$¾ÄUífú>ûÃþ;_|&°—K—Åvú!ñæ´±YxDñ…Zi­<5¢ÎomôOZÙÞµ³\ß3Ç9å.GÌ ?#ƵxË„¾x> Íó8ÕÃGq²t0Ù«©Ê –HE³x2ÞÒ3¾8Ì×jædþ¾(óG²ü¾óùÎ.ÏÏúþ¿úÿƒQüjÚdž?kÿ„£›«]oà_ŒìÙð"¸>/еÏÜG{5µÎ‡”ìo\rüfýª| ™fؾÏòxN®iŠÅfyZNMR‹ÄÊŒ)]%+N¤ñi¦“n4Úe?è¯3P§™aêÚ4©ÆkÛV£svÒ*{õ¿®~È"¸øëÿÿÁH>'ZÆo<1ðÖoº–«øsá´6 £ðÆŸãÇ^×}?g‡Ü{á&]ÇÞ1PÎgÄYÍ9b)áé㾡.S”pò”)áñjñ‹¬½¤â£G*v«ë8ßŬÏ+Ïjå™ °ôŒ¤éûW:–Nj[QÑjﯺï÷çü‡þ kð+öïño„~ ë¾Ö>|ñ=šE£èÒÞYø—á§uë{­CRÒ¼ãKVîÏYM.É­ÚXjIj„-Ø8}$¿g_x3„­ÅÜŽ¥žðBÅQ¦éÍ{à N"†‹ÄFÎj_XÄÑ¡,E Î)Ëžvøeõ|â¶WÄ5#€ÇÒ–1po›â¥7ÊRQeË K–i;h¯fÏÌÿÚ_þ*øáû;~Û~Ü| ø?â?„??hü#ñIµ_IñG]Ó~ø’ÛÃzôz¡mª ÛxšÇPŠîÚ4-i{u+ýš2doì¾ý”æ^ah瘼ÿâÞ+.¢¤ãŒÃÕÁa³ ‘÷ã:QéףN£WTåȤâ§& ¿=Æøåšaóz’£ $¸~Y»ºsIÒ‹ÒJn¢ŒJNò‹MÙ>T›uÁjà©ß´‡ü®€_>ü;¸Òþ6xÄí¼wñ[M×¼Mö­+Ú_x{Eðo‡|Oàæ³¾¶—ÄösI¨^_¼aáŠ8‘Ÿ¾†ß³÷…übàìWø¸³úX ˜ùPËá…©G‡ÄÑ¥)ÆxØÖœ1UªÐ©:r§èÑÖT§F¥hsÊ_YÇþ)b¸{O-É>ªñ ’W5*’„¥f©¸©B1—+æø¥³MGK|‘ûeþÔ_ÿà _ðn‡ÅïÚwÇßü3ðçÄßÿlÏZn³sðÿ^ÔµxçFðÅõ¿ƒ.¼]…¬ÂÚÏ…´Ø¾&xÝìãÓ®//Y$µó–æD‘qþšýþŽ^xÅœeÂ| ™bñ”qôrIÔúäi¬NˆÁûzj•àÕ[ø«Ç>&Ô¬-Viü;àýYaŸT¾1Y®¡{ig拨Qÿ¤/ñGŠ>/ø«ã áhC€2lÿSˆž" Šö˜ˆáéa°µ%e‹ÅNmÍa©~ò0I¸Æ0›ô— c°y>I’ä8™·˜×ÂÁB /›Ý‡4¥(¯‚ hå'nf–­«þË4PC$ó˼0Å$ÓO;¬PÛÅ 4³Oq+íX¡‚$,ìxURkù.޾&¼0¸hJ®*¥HÓ„#¬§9K–0w)4–ûßcî%8Ƥ¢•Û{$µmú/ë·ùÙÿÁgÿà¦>#ý¼?h8¾|4Ö®l?g_ƒž ×­þ[G~£Lñ^©¥%Ö¯þÐZªióÜZÉ>©kit¾™üÉô¯«\©> ûé÷èCô]Ëþ޾ª™¥5v’„miU~ë’å§Ï%gâðSø.7ü‹Gñf•ÅOšßüæ×ÅZX¹ðw‡­>ê^Öoüᢴ+ƒ¦|GøµŠ-õ¯°j:­º]˧èsÚ‹hvǾ7—óþ.ú!xIâG/Êòn¬ªÁsÆ<Ó»¨åËÒvZy0Çqn{_÷U1øªò–œ²­6›¶Ê-¥²ÚÚÛoµýFüø3®þÏ ¼%ðoļsûHê¾·»Ð¤øÏñK[øÒÖéM…ÝõݬPÍyigdÉ´·mq$©º¸¸˜´­ÿ.Hþ&áÎ/ñ³ˆsÎÀäX †y…Jt£“*‘Ë«ª2tÞ3 ‰rGeVP‚T¡$ãK÷j<ßÚ)‚Åà2 6WW©''ˆåubä¯ìæã£pønÛnÚ»Üñø)v¤º'üþ 5ªLå!ÿ†;ø¡!  ›ŸjÚ&ƒoh+),§ [Ѓû“öNåXüGøìÖ*?Ù¸nÇ)wU1ü<#¥¶qÂÎîÚ4»¶¿5ñÒ´aÂT©_ßžaKî9¿ý¹ZÈ×ü=á˙࠿õP7ß³wÅ1Ë=/|AñgÀú4cä¿SŒ2zqIË’T¡Gía4­Eûx¾Y&›Õ+«¯ÍüU»%ì–¼¯Õ7:i[­ýתù½O«àí7ü,ØÞ%–ãwì]¯ÝF$‘æ`×?´g†ª³aò[ª ù¿¢~„ÔêPú)pDkÔZ•2hUrœ¥7ûÉÉÛšr”­¹còÂ)F E$¾WÄ«¯y—*J*²’KhG[.íß»ëw«ðÿ„šŒ´ø7Gþ SñßÄþ#Õµ~Òß´ìãð¹<[u+>±©ø;ÀüàÓoo[þ?,n¬¼{E‹,{@PÍídýóé3™að”í‰áÿpÕ;;Wγ,μ—-­,%4ï–œg¹yñøWCƒ0ꦔ1YµF¬Þ« JŒS½×ü¼smhµqjKEö—ü à£ñ—í5ñ Å iq øŽËá7ÁX„È»Œ/ð×ü_â(&™Ø©[Éþ"Y \`yx9Ï‹} .xcãÏŠþ5´ƒÀŸ¾|.‡GÒ쿵>,xw]ñ¿µÿ€Þ5ðDš Ð->!hž ð¦¥èú¢è ¨j~¯Å«ÚyÑ¢KúïÒ£ÀlËéá–ÃŒ/ƒK?ËqÕjbcVtçG*ÞÞ-(M¹U§W–žœ¼é©hÏŸàž+¡Áù´óz”ªÕV«MF·¼Ü9]ç(+'{½šMÝ?Ëïø*/Á/Úá/íQmâ_Úª)âßÇÿ øSöµø“à(侸×~jÿ´f·â/[ü*Ö¢Õ/®®b×ü'á/[ØÊ‚ÒÚÒ Qº¶ïèXÒ•¯ØájST©aáJ‹|‘„!F”hRNPQRKÙ§9ë'7&Ûz¿“u=¥iR/ÚJnRµîå)9KG{^ú/ø6ýêý‘¿à«~ý‡?à—? > øOà—ǽ'öŸÖ¬|Aið{Qø‰ðÃÄ6¿ ~"x×ã¡®øëGøÃáŸÙDá2ðŒw> il´{“Äš¥Å²ÚZÚ’ÈõþXq§Ñ=ñ£é­1ç b8'Å`'‰Ààqq¯˜ág•%BކŒ§õ,eYÒUg:±$“©yÞ/öü·0Ü7áÚÉcCÒ¼*¨T«O’”Õfç*°—=8©Y%y=ÓÞ_tþÃßðG¿Ú _ÿ‚;þÓ¿ õo¿ÁÏÚö¶ñÊ¿&ø´5Ç:?Ák¯øVûÄñB­Ž·¯iŸ¼[ð³Ã—š…ö}˜ñ¹=Ķ‚F’×soò•ô—ñÄ.#©O€ðe†”i(J3ÇfuñyŽ>”(¸IÐÃ`éOd¡ i9T^÷†¸nµNʲŒ2tëg¹”f·-*1…:NV[êêË™Y·+®VÏéWàïˆô_…á¼;áÛ?øûÂQx^ð¥Ýµ”öZ†á°ŠÁ,ä±¾GÓ®T[#Å%¼ß¸š^6ìOøñôXúWf^xÑšñ¶‡­Ê3ïo Ë NT•YJ¦"xªUhÔªãŠÃT©VŸ$êÓ§Z5*GU>Þø×ðüWÃÔ²Ü4Õ,FÆTfÓåV#Œ’»ä’IÝ+ŤìÕÔ~>²ÿ‚_Áþ|KãWÂÿø'ÏÃ&ø‰o}m¬i6^+±Ön~hZÝ¥ÏÚìõ[?†Zλ¬x>‹;¢$† M=!GDÛ³bÿE¼]ý¦žQËcŒðÿÄxÌçØÉCŽ©S,ʹ墖29¼F?•6Ö•:´êr¥QÓ÷jGò¬ƒÁÌå7G6­ƒ§…çMΜU\E»Sœ¢£Jö^ó³‹Ö)»§õ‡Æÿ‡²gíÕðp| ý¼>i|¥jòø‡Âz¼v7ÚV·àíT¬Ñ[_øK\ð…æâÏêö6w mÖ“q–ÏËœú2þÓŒäµr¤/×e›S¯^­<Ï ƒö”Ý*•eR|F ÏV‹¢§ì°õ)Bµ)ЧVª¯óíÆ^ Wž!b¸KÙª.Œ¨Ô›M8ÅGž5%u.ksMJÍI¶“‹J? |+ÿ‚BÿÁ?e_/ÄoÙÛöX›Ä_­/ Ôü3ñã/‰üyñ9¼ªÛ_ý¾×ÄÐþ x‡SÒ¬|W¦ÌwÙ_Åb.­æD˜Í½oGéAûJxáŽcÁÞ ÕÍ«çù® ¦ f¬<°˜|.û¼J£N¼°õ«Wt%:TTi{*ršž"§³çU0àï³Y½ˉapõcUR„½¤§R›æ¦äÒ”b£5·ÌÝÒåIÙ¯µ4ÿˆ·_ ¯O‰¡ñ=ƒ§†ÞhPÖ/´› si3FÓÅtuöKY v…Y· ‡PÀƒœÿ‘ qÿ‹Þq|8¯Á¯á¸Ò– ‚úç5®%‡”*áêÒ«N§±„Üei9GÚRœ$å)þõŸåys€x T§ƒrSjsä´•Ò’jQqk™«¦•š—O™þ4ÿÁ_?e?G©ø_âçíÓð/I™ ©øZˆÞ›VxÛË¡øU.uIRY! &vÊÊF?Ù™ÖcûI~œ1_…óŒâøC6T¡R/ƒÊðµ)ɦ¡9RÃB¼©ÉÅ{Xû{kjÐömÅþ}†¥á ãcŒÃÔÁSÇÑ»OÚάâík¤ç$¶ÒýÏ-?ள‡mc¹øðËö»ý§d¼¸k]&o‚²ÏÅ{Ÿk?hû©’ðÏq>" ¸VÆæ˜L£ 9§.J•0\%i»®HU‡×dêÒæä«J¦ÚÇâ.^ÓŒËpqm^4èT¯5.•IÕ‚»ÕÆ^É(»^2KÞõ߆ðOï‰çñ6“ñ#öåý«>$Eý…q©Ýèëã¯~κ,Âó£ÛèW_³Wï‡;µó …-.·;C+ÜY›öïñ3ñÇ<Ì2¿øž̲l®¦?Ûft±¹ÅZê5mJœ¡šb±t\¡Zœ¯Yaå Tf½¤&¥Ççø’êÞ~#Ìó¬mÞ2eøóᎹaq'ž>Ñu¯üø‰¦øÕa‚+·ü#Zµä«†Èòz’¿ÎßKß«ñ¦_Áؼ7W‚ñ+‡î”_¹„ÄT•LLù¹­w,eóIÂ7Š»_káöj²éæ*nÔg”b—ý¿htÿ§Ýûù_î¯ø7'P_?¶Oü³ãª£Ýè_>+è¶šN¾òF´ ø—ñëã'Ä­bPá‹Ä?±u¸&•ÈUÚàƒÁÇá_´Ï#Ãñ6káφø‡[ˆ8¾¥Æ’¼9Ë‚jmm(Òž"¤jh¡¹s&“>‹Á|D°¸l×9”Tc†ÀFW’÷“µZ›=wQM[[¯;ÿ;ž$ðN±ÿÿ‚´øßÃ1jwú¬_´'í‰ñ Lšú;Í=îtÿë‹ÁÚZi¾“âþh¿ ôŸXÞ[Û5¾¹á {Ç‹¨,_f¶M+|.û%οJÖÃNá Ê–Ÿx…Äü1‡–ÚJކ[™cîJQÃR£?gïÆÓ’åqeÁy óL×JSx<« |ÏNiû*´©[K^Üò~öÂ×½ÏåÇz>ñ3þ 4[˜F±mñ#þ !âm>ì[wÒx‹öòñ„—ÓK·w™Ú –r1å`Ÿ”f¿ª¼PÇË'à\ó8¡VžêYFcˆR¹S£‚ÄÊ V·¨©Æ×ÖöWvOá8~Œq9¦Q9*µèÇN¼Õ ŸNÜϧèÿfàêÏèÚ×íû|#k¶{ÿþʇ\½³’ †[K/‰ÿ´=’èñ­ÃâÚO´Xxè¬hÙD‹•©?Ï_BJxœ¿ègÁµ±3sÄÿcÖª¹§yò¹ºÑ·%M)¨ÃNT—,~—Öx—Ë[Ä\|`­OÛS‹ii~[;Û®šìÏ¡~xm4ÿø6_áÀÍ~ëOÔ?mÚödør³ÛÍöKýCQø½ûdÏã­Nã‚X.5¾ ÒeYcC™ Q»(kã¼5âÚ4~•þ3ç˜åO ÃY' ðêÅJ*U)Ãê|_-iÅ'/h°ª2œ"œ­È•ÿvߥžà}§ðæ›çÇⱘ®E¤[ö²‹qWÒÜú&ôÝÛsú&øGû~ÊŸ²³ÝÚŽ|gã½GJÓ¼=â¿Úã§ü[ñGã7‰¼9£DIð‰âOêšÆ§à¯…:%Øk‹}ÄÛZKtD¯:™ü™údý,¸ÅŽË|&ðæ­ÀøLc̱9‹ËðùTóLuXÏÙÔ¥—`éa©a°”#S™N½'ˆÅÖP“©T­ˆýÇ€8’ã+gÙ³k1«KØÂ’«*ê…(µxºµœç&µåjW¶éCýº¼ñ7ư?íÑÁë]|CÐdÿŒ:÷‡m¼'ôÞ)ºž×@{{Ëo C¥‰5Yµ×Ò§ºke¶V¸iQDy‘—?ìßð‹âÒC™gQæÉøc <ÝŨJLEÔ¨àéο<]YÔœââàãJÒº’K³ê¹'T†ýãQaÓ»N1”e)É5³QVZ§w÷Ÿ—ü௄~4ÁR?g¿øÆÏMÕ¼ oñSø€Ú6±yum‰|7ð›Â—þè‘ÛïŒëZN§{c¢ÝËc6èî¬l¿x¬ªÈÿï/ÒKÄÌ×Àÿx›Ä§íóü£+U(9/qâ+×…^«¹Tç[M%UÆ EJëù„2|7q6,Ç>\>"³RI¯‚rpŠk[¤£Ñ¨¦ÑþŸ^øÁãßC« V†ׯ†«©Oq¦Y_Ïq~ñ,Fež}’F¾Z…XùùTt¯ùÔð·é¡ã¯„óº<3šÓxœï1–;[ƒ¡‹«WáukºÕjÒ”Ô"Ý+N•=]5Ýÿ­3¯øg>xw˜Pn8ZJ8ƤáÓ½ÔyctíßFúÞÇñ_ÿXþÛþý£~ ~Ìß³V“yáüHý›4>!ø»âÈt«;™<5©|U·ð}Ž…àƒ©i×-.•>‡àÝmc\µŠÞâO´!Dî¿èèsâoˆ¾)x —q¿ŠtœxŸ‰ÅrTt#…úÎWqÂWhSU#/gOÞ÷Ü»w”¿–|Bɲ|ŠjåÙÿc8^*n|“å÷âå«v·3ß–öò_´¿ðEOÙ§Æÿ²çüëá?ƒþ&hú‡‡$jiªø[úޟ©ZÚ^é#±ð”v/©ÙÉ =¦¡4±6Y ?á§íã¼»Œ~”®,…)ÓÈpxl¦¥^XTZøhÊx‡MÞ¤%JjÓ§Jpv©ÎìÝ—ô§…]\·ƒh:ÎJX™ÎºZ¦£Qû—øuqIÉ=›¶ÚŸ«Þþ¼÷þ¿ýjþœ¥99Í·6îÛÝŸ£¤’²>Gÿ‚üøÇñóþ •ûvü(øðóľ+øÃá?‚ôï øÂ?ÙGÄ:åª|Tѯ|DtÈ5«í>Öõô¿ÛÏw%´R›ë˜¡hí"žäÇ ÿ±ÿ²2”q6)ïO‡°ðëÿ/qøçÚÝÖÏMÕ¿Á ŸIc$ÿðqþ¿>‡ó“ÿôþËÿµoÀŸÚ¿ãˆ~5~Ì_¾ x#\ø!¦Yø§ã_Â/|":†»'Å˽sLÒ<=iãÿhsø’[*þYîZÈJ¶IB-¤@oý«58s ávEK˜:\OWŠ)×Âàî¿Ú0ôðЧŒ¬Òmû<%©7)$”êz7òþ¬\³ÌC§JøàœgSù&ê^œ|ÜÓ“òQóÓö«þ )ÿ[ý ?ાý’~(þÌ~(øAkâ¿„ ñLj~øµâ?x6ÏRÐ/|u¡xÛúÎâ? øSÆÍ扮xpÅwcq`Ÿj³¿gŠh¤wN}ø‡ Å?D¾ŽIWÂeõpV¼ÔêákÕ¡%(é%-ììÜZiÚI¯ñKSÇØéÍ>Z•!V?ÞŒ¡¦ë£Wòò=›ö1ÿ‚fþÎþÿ‚giðLŸÛv83Ó­t¯AŸŠ'Y-®'¶·K˜C$°,dÆ?“|=úføIŸK_¸›ÄLÇ–ðþqW,ËrêµpõjÁSȪæ8 {_«ýcêЫ4ªÒ盋NMÔæMwœøsŸcø%ÁåTá[‡U«U:‹¾%S«§?/3I¸¾º$’Gyû,þÀß³?üÃNø‡ðóöS×þ$xƒÁž5ñͧ/5ïˆÞ&_x€êÖú†‡ia¦jéš<ñhºŸ¥[ChÏNJ3;±¯áŸ§÷Ò##ñÆ|6?ÜÉbxO!ÃQ§‚Äá•J.Uç)â1xŠu›U9©â=±«Æ*¤g$ªr;~•ᇠâ¸w‡],Ú—&?9J¬%Ë$¢’…84¬¬á~dÛ½õµõý(¾ý£üW¨xz ]CEð¥÷‰4›¥øÂóLûNµ§Ü‹fQ³·šllõCó,r"ù¼¿à?£á¿j'Õ¼2—Æ–Qþ½¬º¥%œ:uÖ&ð¥+â Sx­¸Å¿iíþ®ª?kõWõgä¿8cûacœ±PuSú½ãÉ«øy¿‰ÉýÛs[Nw¹þuðsf«&£ÿWøÍgq<óMៃ³æ’²Ë$Ï2LŸüqâo>Y 4¦ëUó )åØŸ½šÿuxb0>ðÕÒ•ZñÊrêu%Q¹Ên§³INR»”ä§)JRrnMÉÉ·¯ó&l©Öâ,uH{°úÍv­¢\·qIid¹RI_M4ëýÈ~È_´“û9~Â?²¯ÂýcQø[áM/á¿ìçð[úˆ¼g©iZMö“m x F´±»ëú¢Z\j6ñG”¸vS»,Tœçü‚â¿§·Ò;žñ_p 帼ú†mŠÃa³ &Y˜T­zŠšœ¨ÁO НN-Ú¬ñ4a%)ᤢã?ßðp|ðØ,Ë0Å׆T!9Ò©Zœ`å8¦×3JpŒŸÙI¶•”–ë㿉?ðV¿ø'?ùu«~Ú¯5(no³gá_/Ä=rMB;‰e¾Ž÷Oð\ZÅÍÍð¼ ]ÿ8 üG€ú}18÷2Åãªð†yKšNukÕÇÎ85ˆœæ±N¥yÕ”UyU«?o•W$æù©û+B1ý·pWF4þ¿†p¢”c^ÿ*K‘(¨'Ê’\¶Z¤µ¿_ÏïÿÁÊðNO ùvžŽŸ5›«‹{K-'À¿ ît)¯î.çŽ!€üA¼ðÄ’É#È0ª†G$Vo”þçÂÿ²éœÊK‰1Ü9“R„g)ÎxЏÅF JMá#UrɾI7nI;Éòê¾oão á´ÃCˆ“µ’¦¡«v·ïzkÖëÌæl¿à²·Ƌ߲~Ê_ðHÚÅ6Û‰£ñ/Æm^ÿᆔÂVÿGx'»ðÅ¿‡5tœG«¡A´œ†}EOÙõôxà#ÇxÃãS„­í9}†ênVåqnKÛËNQ­Þ¢\¯–{ñGÅ*Í**yAˆœ9n¥QÍ-ÿÀ ï?ŽëÍ+®“¬ÁĿ޿o þÃÿ²'†uBJÁ­¶©ñ â†í¤‹H–:¿Œ<7¬jÊÝ6Ñ?ÄG>6/û+¼9—»Šâ¾3ÌèÅ5ì¥Yá«Ï‘]$á©Jœ®Úrç©N¬yn£%nŠU|j;Æ/¥'Õ'8«úÕMÛÑ4ïkÞý-—ü'þ ñ;NšËö ÿ‚Â~Ðz¥½ÙFŸJýœ¼áo‚%÷o$+®höö³K™TüÉo²lÆAòêý3~Œ| ˆö¾x/’SÅÓšj®i8bTÜy©ûOgV5ª':Nò攟´O›Gááÿf1¶}Ä8—¾ Ùöv¼l¬Ÿ’Ó¶©÷úü³ö’çHÕ¾2Z|tý¨×vl·7Ú&™ªèú ÃNïF„Ä{(íñy·í$úBK[/àj<7¹EzJ›¥–åÔ½ØÆ6Œa:ÊR‡#÷©µySwJRŒš]Ô<#ánhVÌÞ/ˆ‹¿5jÒwwÖê6NöÕlûyü'ýŠ?cïS5×ÁßÙƒà?ë÷Š&Õü3ðÃÂvÚåÌVÞo·zäúlÚÅß”eb¦KŒ†v=I'ù·Œ¾’ßH)ý_‹¸Çˆqx.i5Gë•iP‹””ß%*.œ`¹’jß ­££û ð¾Vù° -9ÿ2§-µ“W?Ÿuôê.5Š/ÝD£jÅîâP:…Ž-¨¡}Å~%ˆ©SSÛbç:Õ_Ú©)N]ZÖnNɶҾ—}õúÆ0VŠIyh&ÿ_¿çÖ¥%v:/!‹@,/ntÛÛ]BÊco{cqͬà‘äχ˜Å¢b¡d^CÆH ñ_EÂ\G™ð`x—%¬ðÙ¶ ÔjÝ¥N¬q”ùu•)[“ UJqq“åK›„£ŒÃTÂâ#ÍB¤d»¦¬þ}búI'æºYÚý¢Ï\Ó [m'ÄpÏml‡ ¦êM³\ÑçMÔe-y“\ ýWÇLƒ'þÒÀxƒÂØxáxC‰¨UÄУ¢°xÊUy3l²ÍÆMà±³u(µJ–O“šœ!o#!ÄÖöu2Ì\œñØI(JOþ^A«Ñ­×ø”Õ¥­Ôá+ë¢äCô5ø%oáKü/ò>…n½N×ZÂøCÂIó]øÎ^~öµ¥D3ØàAŒ÷â¿¥üMQ£àwÐ劓Åq,î·wÍòøj½(ÛÍz3æ²´Þ}}¡„_ùF«ÿÛ¾þšëÏèšzêºÆ—¦<²B·ú–bÒÃÚ$/o ·–XáÊyÏ R3„þ=¼ð?$ðã…hñ·e|/^¥ZTqùž )Ó§í'bqT¨Ô©='*T¥R²§ö•99^œ*%êæxÇÀVÅÅ)J•Í&ùSq‹’N]i+ô¿v¯½ãýÃ~ñEþ—áO¿‰´{e¶Hu7Ž4g¸òÛm¼ÈR(.E¬ë·ÍEU%ˆä©5÷ŸHÎðÛß±Ü+á_Tâ>ÃF‚Ž*p‚’¬á/¬ÒuiFG±©¯kJœbÝGI¹N„Ûó8[1Íólž–7<¬a>kÓMü7÷%gwe¯+m«_í$¹{++­Fê +y®®®eX ··F–y¥»Q/Í$¬½²³ ãò®á¬ë‹³¬>Caëb³LMUN:Psœç-¡«sM«µ(¥*•'NŒ*U‡·‰ÅPÁЖ'(„å&ì’][è¼õÖÉ&ÚOÒïçðFƒà­O³hÐë><›Q‚é¼We<2Xh‹°ùº-µÉ”>¦Ö°Äé3CÙ¤šB7™?ÖœW_À¯ |Í<&Æe3Ÿ*ã©Ö–w‡•˜l¶J¬9òê8‰T…\[ÃQ„éb>­Aàëb*ÔŒ§ÍNr_„¥Ä™§QÎሕ'«M5:·O–¬£kSæm8sKÚF1Z.k/+=N:Hƒ' Î¿‹ª89ÊT×-7&ÒÞÊú+õ²ÒýO¼?ÿÕþ+þ'Ïô`( € ( ËŸø.WÚdÿ‚<~ÚVWÓØ]ø‹Xý”ü# Öï$rHšÿí=ðù/-Y¢tÌ6ò¬¨Ä$±FÈ$öSöAá¥SŒ8×ü—.¦ßok‹Æ;^ÝT;ëæ?øùW—,Ë©6&«ÿÀiÇüÿ®¾ ÿ\ø)iû@ÿÁ ?hVÅâoÚáWíߤi—*<ÍâI¯Â­‹‚ƒ”a V2N¢„dé{8FTãuÔOè죅ªð×…¹†­›b2üEj÷ÖJn”šƒz7É£v“½ï¬uþ<24ÿÁuü#a©$v–z?üÃÇžŽ{i¢¶Óÿ´¢ý®~-évd¼„½¥Å¬Wºµˆ 4LŸ nIí?Ò‡/ÇæŸGî9Áà(Ô¯Ÿ æÊ‚¼ÜÖr\«Gtâåmåv»Ñÿ:ðEZt¸§-•I(ÒXêoks¥úÛçÓ¯ØÿðY†Ÿ¿mŠÿµÇíýð±tßþËŸ²í!ð#ö Õõí";¿µøb×ᯥ»ñŒõ[Ë«µ°> Óþ(xîòÊòîòa’öÆSû—’àúž ðsàŸ8[éEÏ€áLÜá'R¤°Üí»F*´áÁɸԌԹZäŽC™,Ë‹qù›mS©˜TzÆQ²„ù4¾­>Vã$­(´ÕÓMþ‡ÿÁ6þ#øGö½ðüörð£¥x@ý‰|1ãßÚ«ö†ÊÊþî×Áÿü=¢jgÏë7¤.Ÿ§x¯Ä7ž+Õ ñV•¹rBrÁÇFƒ­»Ô©MRÃÊi¨ÅAWW—2´ý_‚)SâL÷ ÂÐjXl§R¥{&Ҩ극|*W–Ú·Êú'ËýF:’OROR{ç†É?JÿŸß>Ÿ–½têPðËÇs|;ñe¦¼–¿o³x¦Óµ<ìΡ¤Þìû\_÷fxÌk$Jß#:m<1Çô—ÑWÇìoÑÇż'ÐÃϕʜð¸Ü4Tñ*ò¦ê““QúÅ)Ó§_ ¥(Âu!*.QöüÇÉq¯ Qâ솦SR^η29î¡R)ò·×•¦ã;]ÙßìÙþ þÜßðm]ÿŒ~2iß¶×üâ߇~xõ|sqñ:oƒÞ$ñ.­á ?Â:¿ÕnõÍVûàßÄ }#ŇÀšf¥ª_¯ëú>©áÄ“Áj,¬æxkþøsŠ|)úDøw,Ç$­Ï¸6ÂÊ•jr\Ë’¢J®F\µhV‹INœÕ:Ô§§ Å5üiŒÀç¼!›*X˜TÂæT&¥-.ÖÓ„•ã8öjñiÙ§{/ñ‡ÿàêï‰z·Á”ý‘>üÔ.î$мEûEü?ø‘ð6ÆïS²]B u­ï\ø­ã™¼£¦ÂñÍu„õ;æyüËx4öâþWá_Ù­ôXá®/ÿ[iåy¦? ¼ôp9†9ÖÂP|²³•TiË¡S–ta:Ð…8¥±Ä+§÷ï¸Ç€x%V…*Ž):´©Ú¤–—´¥& íu& ÛzÇ—wèßðOïø7Ïá÷ìeñNý¤?m¿xOö‰ý¨ôíRoø_à÷…îµoü!øsãɵOí«?‰i÷rj?¶ÃÍ^7xâ¹Óþßø£âuÅÛî ½§Ã›-J”V ovhÐrYTd}‡‡_C§z8Œ«‡2<ß#ÀâÔ]xâ³åQšRäýõ(⨩νèUŒª(¥ìù’Iqf~!øwJQ«‹Åañ`ß/%?nÓµýÙ(J×[ü+ñ+þTý‡¼*Çà‡¿´wÅ%.u‹_hŸ<:ŽZ3wª|Fñƒu \•eø œý[…e§¤ž/‰8›‡2¬DZs§J¦'‰“u¨ ððœe._}JM)·ï«¹3ÁÇxÏÃÔ}ÌZ6øœaJ EoŽQ{é¢z&öJÿkðsGÅxŽo þÏ߱ޅªjw‰$šöïÄŸ|MñÚF"ŽYî<ðgÀ~%hD7 ¡MéÝ‘ŽµûÎ]û*8(Ë–{ÇÜ_âpñoÛÊ\>_B“’¶'^\ÔbùÓ‚ä~ò|©_åêø×™âj¼>Y€ÃÅ·î'RudÕ•ï Pv÷žžó½»»*¶¿¶'üaûKxcW“áwìí¬|-ûE¶§me©h?³×†~©v°¸Kyl5ÏÚâlZ‰²ûC)ûChÙtË ½¹øû4<"Ìj>1Í2Ü]áñÐÅgµó,BIkc’a­í£Ê”j¯r^ÿ4o#žMãyI}BZU¹¡ïSÂÆŒòx™¿q¾éµ²iï[þ Ñÿÿ‚|vý¶~,þÑ~ ý›üwñ‡áŸÄ…_³§ˆ|+⯄¶¾ñuŽïÿZ/ümá¿é3x»B×ôoAãh/g&ËLÔmo4똦€–I OõË ‰Êp¹%,fÓ¥‘ÓÂÂpzÂÚ”]ž±Œ)¤ìídµÖìü¥¿â¸üâH­tæÎAkya\ÄS#âljŸµo6È8‘x[ÂùeL—‰« 8œN3Rtùyq´èa¾­í£ï':mʼ¹y_ô^Qà–„¥_:ÆWUå¹B‚”;Óæšœ½Ý´}׺ý,øSÿ ÿ‚]|(™/mf›ê qµßůø¿â¬¾^XHt GT‡Ã1³6Kl³ºŒcùŒ?iÒ»‹)Ë G<Âe87;¥ÁP§Q/yYâ%Yû­EÝÚñSŠ„î}ÆÂNÀÉNXYW¨•¯V¤ä¿ð òï¯ÃÕ­Ò†_³÷À‚úlG‚¿ >i¶ûŒ6~ø{áO E;¼®ÀézT3’Y‰2Y‰<ó_ËÜcã?‹Þ!W–#Ž8£?ÍjÍZOޝ4×,agÊiÆM4Ó²ºoWöywäyL92Ü„/{Bœ#«m·¶í¶ý^篳3˜³Á™˜@cñÿ̧9:µ•VÛrzÉ·»rz¶ú·«=Ènè加€ ( €½Ç9;w Ä×8KI‡ðC…oÔ³ž1Éü(Ê«pG†XªxœûEÓÍsºÑX˜ÉZynM)rÖÃdð’¾#½ž;:«%:=C_8­~m 4$¥G+>F¶«^Ï–uÿ’ž´è-=êš®+מÀ Ðg  þÏ*N¬ý­GyÙ.‹E¢I$’Ih£¢–‰%e§ ÌÿÖþ+þ'Ïô`( € ( Ë?ø.áÿªø×—Tý¢¿bí,(,gãmÿ—³çóòÖãäõÃsŽ?ÚŸØóFµ<ˆ¸¹){ªä‹iÚêXùÉ'³k™6“_n×WþwñþIÒÊ)ÿÓÌCÿÉi.ÿ×åÚÁ½±Yü5ÿ‚wþ·1GäZK¢ëºÝú¢•WƒÇÿüas¬É*K€ë4šávÏÊFHÈÆ>'Å_ãÀ_µŒu+•µÕ´í*ÓÆèò]Z¼‹Ý*xØE"2/ûÛ”¶òíÓðôôíü´Ýß_ø=ë¿öeÿ´éš„aÏxƒVû2i~0ý£~4]kÐÚ\Ù\ øv÷u xóJøâ_ xçÀ4Ó¼14:U·‰ü=y¬#ÿf­àŽ!yy§Ïþ©øÂT|@ðÿ6હže•`sl¾¦X¼¿•âéF§+ç£xÏ™JÜ•cJ•(Îq¥Z…^JÔÿ ÉñòʳŒ>f¨Q­Z…e5 ºAµug²V½âÝÔd•ã%x¿Ø}3àOüÃöµð­½—í3¢x þ /û>ëZ~«§|@“á×Å;/Ÿ¶ßŒ­Œö0Áᄦ‘`Ÿ¾ÜøƒH‘¶µ,Ú–§§‡ŠH­¡‘]ãÿ3ò¢/ÑGèx¥ã?ŠÎgbrÌM9e2£Kíñ4é{JtðyM*Õ*bqŠqp¡Ï%*r¬é{8ó¯Øñ\uÆÜ{/õs!ÃÒÃÆ´¬éIÔå„›©_•F¶²åNR¿*’“³ô‰?ðAoø"/ŽÀ÷žøuñ#öXñG€¼'àÏ ¥ÿÀßx¿ÂÖ½eà•#MÔ|Q“â=ƾ7¹bZïÄ’ÄÚæ£)\\É(V¹p÷íú-ñ'Kçu²,ΕÕ¯ƒÅá+ΪZóÒ£*4«PÅóÚQO:ŽQjI.ešÆxCƘü4kÙÊöïÄê~ ñÖ«7Œõï^øšî[x¯ÆšïŠøñˆ ƒÄ!žÞiõßÅá{K+KÛÈm KkT;’ÖÝv¦Ðp¿ÌLÿ¥ž#é7ÅX–àke¼“Qœpt+WUkJ¶%ÆXœN'ÙNt}£Q =8ί°¢¦ùâê*qúÿ¸ªªÕlË4êN1å,¡&Ó²»”›KšOgk½¼¯¨üëø™µ‹Cô1Ì ¡‘••0KÈàÇ©gl ÉÿE#ò–Kÿ|[ð¿ƒæËIåA‚}rÚy÷ÊÛ9'y¯è¯ø7éEK4xßò~4†iRÜÕ2ÊXì5I{ûUÎŒj¨ÂïÙâ#Z;Hr¶ŸËg¹{eŸWËå‡_f´©I+»])s[^±¶»½Œ¾-ÁÃÿ°‚hºÏíµu㻉ı¦ð«Fñ×ÄX®|­»â}WÁžME—ͼ Î ýßO¯ÚsâvH°Yž?<Ëò¸Ú3úöw…À9'uΰ”°¸¹ÂVä—ïeiZ5RM§ù¬³ï2ŒJ––¦!ݧK :»;;9sÁ5ºÑ]]ÆöÓócâüëûè—÷Zoÿ‚_´ÄKˆÐÉi©jöþøo ßJîËû·ñ'‰[^åɳÝó¼s+"ý”ž(f0†aÆ[‘a)N¥êSÂÑÅc+EÊŸ½95MÒ•NkFnSn¢\î|Ú½1>7d´[§‚ÁbªYhæáJ/^—wµ»E[küLÿƒ£¾6Ok¨Úü7ý˜¾|=Ô_íi£Ý|IøƒãoO…•–ÒêçNðï†|-¤JJg‰5 £;|Úþá?ÙEáµ œMİ©*<öV”º+ñ»<œZÁá0˜z—|¼òG¾®XÇm×7_‹¿Ê_ðZ¿ø,í73YüÔüE °¸eÔtïÙ¿öeYk–kpãMƒ^m/ãµå´gÁ)o/* ®M~ã•ý>‡ÞÒ†#в<ºN¤iºU³¬ÎvI9'RP­W-¥%S–Q’¼éÉźqæZüíO¸û9—& ½]/xáè-ôvºyiumWÕ£ªÓÿcÿø/÷í[«Zjž5Ÿö±´ÐüKh!¿??h8þ økE·+4žaðφ¼_¥].^]®… áT:…/6/Ç Wƒ eùf;ðØìƒ§·.¥ŽÄÖpQtíR8jÏÝM¸KûE6Ô¢¦¥£ª|9âŽQU¯O2*­ßÛVt¡ïwgR;´“J‹èöÕ{?Ãø6ö™ñR^ß|iøùð#À×·òÝùÚ.‡ã_ŽÞ'e¸D’[KYÕæøs¦]j rï¹^+ˆÆÜÙ þ[ÅŸµgÁ ¢¥p®YÅå*TÔe¨e”4œ­\òÅÊ4ùg¹¯(Ê1’N~¾Á.#ÄF_]­‚Ã]·iW–©6åeI7Í{«½,ÓÖËô›áoüAû!øZâÊóâGÆŸÚâ_‘lÑ]h:&£á?„þ»‘ŒE¤6ž Ð-õõÚ„ÿN l‚pGò·~Õo³*0¼#¹_);Ç‹©ˆÇâ ù²S¨è»JÒWƒº÷dÒÕýÆÁLšœ”ñØÌUT¾Ì)Eë×–*[yÿÁýø[ÿjÿ‚eü#·Š-öAøaâk„™®Rø©­ñwS’âGÞÒ›ˆžµYÎBˆö&~PùÏ‹>ŸŸK-¬ªÏ‹q9dÐË(ÑÀ(¥+¥Qƒ–Ÿ Þ® Â|ÊÉ}^ ÂîÁAÃêë9o휫^êÎênJϪۮšßô;žðW,aÓ<àÿ x7N¶A>ðΉá»HPtHáѬl‘TýßþÇù>ã^2⪮¿fùžaUÚïНWdÒÒSåÑ6—ºß+qøt_i†Ëð8%Ë„£J”»¯É/Óõ:¦fc–bÙã.wgÔŲìrãëó4¹hÊôRŒ¼’ÚÖ³V³M6œZi¦ÓM6Ÿ[×sÓ´ÿŒ¿ô½t OjI¥-¤–ÛÏo¦_46²¡ŒÅ ååœ×È‚3µ3#ùkÂöÇõoý5þ’¼7ÂPàœ«Šóðõ<,°ñ¥V†ãFWNÄâ°óÅE(?gOÚU¯ìa¤9­O‹Åø{ÂÌÁæu°4ž5ÔS挪BòN÷p„£ï«´cÌ÷ë0ôëÑT{* UîrUT¿Ÿåj•'V\õ>.XÇÒ0Š„W]#Æ*í»-[woí-eóoïÕÿ_Ó+0 ( € ( €='Âþ8Ó4_ x‹ÂºŸ…4ÍbßÄW²M«™ÖË[Òã‚(bOì«§²ºD–‹Í„±EIY·îVÈþ­ðÇÎàÏ ¸ƒÂŽ*áL³3Àq"ŒªãÕha³,iQ¥JR¦OÚP/­a%RtéÑÄN§µæ„¹åñÙ× c1ùÎ;Ác«Ð­…Œ’¥ÊåF£“o÷‘SƒjIòNÚ¸¥ËfµÊ“±j©-Ï„/F¶¨ž|Ú<%—Š,ãÛºS6Œ¬ÑjDŒ Ï§´¾ð¯Zùìwƒ9gQ­œx'˜nBÝZ™léG ža£gR~×,V†2•(Δ/(uT¤ÚúÛšë§žTÀIPÏ©}]·eUIË7²µW­97rº•W±Ç©h_vd£+2f9b‘?+L71:†PpUÔg¡ðl5LvKUÿ}F½ ª2pnZsŒ“²—»*UéÎ*tÔ¹e °‹”}ÙDú)(V‡.Ž2]uM?Î-;>?;§‰b]jÚÃÅöë“S›û;ÄPÄ¥RÛÀ³IxŠB‘ˆtåhÀ•&\–RúÅÜ%/rŒ³Æ¬²ÖÍ1+œÓ¤š…,ê•(Tž" ÆÙg  A¨Õ£Š¥)ºÊQ—ÍäÒy}z¹Vù(Çžƒníáäì£×Þ¡RôŸ÷]7³÷Kë­BÃáÞ•hŸi»½Ò.üˆ˜°ß>§â­`ij ±f2ÎùºVnÜÞ{Ã9¿ð/­ç8Ü—Rœ;櫘g˜ÙRX®gIÓ”ëTÓ› J½E­=G ‰Í±ÕŸ-b#wÚ4ðԮמ¶Kùš]Kz­œ¾ Õâдb}ÂöOe£u9µÓcµ‚v—[ñ6«r|È­­µ-XÉ)`I#Ž%f £ÙãnÇø™Æ¸ú©áÏ `žÌEgGT«9æ™Þcˆst¨ÐÅãÕlEJ±N¾"8z0”êUQtùðXŠyVæy¢k3ÆTçt⹪94•=8èå*tùck(ŹÎmFíæjZÝ•Æá£*ir…MWW¸‡ìÚ‰&È{¸òN›¡#óm§‚w¬œ³«òSâ.WÃY'Ão ý¬8RjÇf5i{ fsR þóí‚Ê£'ÿ ù>œÑÿiÌ%Z¥_`ûpYmlV&9¦qo®+ºt£.jxtúEÿËÊÍ¿O‚’ŒW3w„|­x¾úÂ+eK=:êö YµíK6ú5˜–CI=ôÏS¸+…Š'y]È\ ’0ðkèûÇ~3çx5‚ÁðÖ'J\ÓÃMJ§³œ¥‰œ¨Â¼âÓŒ(a«T­R³…9{(¹N5žñ&_áªN«u1p¦å4í*²²½”“Šï)EEFîïc?źð¯ˆõ¶¡cªe^½ŸÛô÷cgrV(¥ßé%eÚ'ÚÊd}’+/8ãä|gðéxIâ^oáü³ eý—•¬a[ö5-J[ÅJue•eNtÝZީՇ<’Iuä9·öÞQC4TªQUé©rO⎲Vz+ü7NÊñiÛ]yðŒFB1rˆüÇùÅ,.*²æ¥J¤¡ÝFM}ö·âz®qNͤÏÿ×þ+þ'Ïô`( € (  MWá÷ìéñÏáÅ?Ùóö¦ø|~"ü"ø£i¢I¨iq=ý½þ­xjæ[íZÐõ]ûK×ü5âmQ1]iº®ŸsÝ…Ü*êëÃôö}}*¼?ú:c8“+ñ–7û9§„©N¶Œ±…L$kEÑ©F2çq¯ÇÙÔ‚å„Ô£U¨Ê ü—Å>Í8¾–®Q*K†•Dã9r'œ¾ò–ÉÅÇT÷[j¬yWŸ„ >ü9ðÁ¯ƒžŸÂ¿ ~iÃðÝÆ©©k7ZO†í¦¸6—:Ʊu}ª_Þ$Sn’{‰§•æ%‹1æ¿‹|`ñ#⯊߈¹”êVÄf¸ìLÿyN•),<çR8zR§J>Ê£‡tãuZ´9Û›W¡äYM,—'ÃåTŒ(SŠÑ¶¹’NM9Jí9_w³·“ú§Ä¾;øIñj¿fï„_|aáx4È4¯øçÃ^ñü'LÃso>»áÝGRÓeYdyqHcYX°ë•ÿQ8Wö²ç¹Ga2¬ã„¨f\S„ÃУ,BÍ!‡¥Šp§Ô¯RŒ°ó­B¤Ú”(ªÐRøjJkñ|wx,NeS‡ÇÎŽ ¤å%cÎávÚŒeÏÒ½“i;to¾:CêŒÚ†ü?á-.ïP¼½µðç…ôË/EÓÜ‚I ³±Óím­• ]„JevfnXçü¼ñ§Å<ËÅÿsŸszt°¸ìÛ:þÊHÒ‡³§FcR¤bêÂ*Q…åÆ\Ó^ÍBMKö^ɨd9.'ÃÉΕ j)µg'vÜšZ&ÛovöÕÛÝî,¾.xÿÃ:bZ[øÛ\Òt›8‚Æ—œÚÚÀ‹÷!ŸUµ™­¡G %؃ _¨ðÒßé#Ã9àÞ#â'•áãt¨Ñ«J§hÂ?¬`±Õá-Nš­(/†”c ¼¬Ã‚x?‰–;0Áay;ÊR-ßW.YÂ-÷m]îÛ{|sñ—öðý•¾_ý£ã—íkðOš³ ¼¸?ku;D=¯Âÿ†>?ñ]”ùC´[x€èšg‡e$ÇŽ.N;ñÉýg‡?fïÒ¿6ÃSÄãrì¿'ÂToýë2¡®Y(ÉJÊiÛßíÇi§·ƒŠñs‚(NT©W©^Kþ}Ò›[]{Í$û=ìúøûþ“ý›tèõ8¾~ÌÿüS{m%Äv2üDñ7ï†Zeÿ”O“p‹³âMf;;œ‚ €HüÈ_è.ý’_:—ñžYO4î²ì+àù–ŽU¡N:Æ÷÷“Œö”¢Ó)ŠñÓ/Qo€®ä¶öµ)Ó¾ŸÝmþêýO„~ ÁÑ´ï‰mü„¾xïr<£Z¸øñ‡V‚4G •§€tY§^0MÏ–êÃýÃß²›ÀœšRÿZón%Íh%5 ʶ.„¤Ü}”¥¼L’ŽªQäµDõåkO—ÆxÛÄXˆòà(a);«ûµ+;YÞßÃ[Û[»vgÁཿðRï^É"~З¾Óš*ü:ðG¿‡ „i>Ó­Y|GñHpUž.9Æy?М/ôú.pöSÂð†[‰Å¹Iªø™ã±íÆV´ï0Ôm¯á)AÝ)4Ú_+ñ71Snxê°…—»J•š¾»Nwwïg¦þ~Ó¯¿à©¶"‘¥Û_ãæ—ã;é?ö‡í âÏÉüo.øç‚ïÃß ¬ô–‰ŽÕ" l6Áçö,M|$”êb¿Õ«ƒRæ\™>JIÂŒîœ~¹*—åKs»ÿ^íø0|UžÇ–Ú¸Ôw½ño{É[UNÝVÉ/†û?¨~Á¾¿ðR¯‰nË­üð÷Âë"µm;Wø¥ñá×nd¨oÞiž±ø£â‡6Åæœ[ÌÙã$?ã?ÚôZákÕ|UO4Ì%&ªQÀÑÇf^앜«}VŠÖ<Ž1”ã .¹gÑeþq¦:vx?cI$ÔªJ•%%i-7Ù_½ïoÒ¿…?ðkoÄ+ÕÐo>7þÔÿü:ÉOâ=á—ÃÏøþæi ³ù¶Ú‰þ&xŽ nÜ9ÐU¤Dû‘îù–¸¿ö±xm©Š£Àœ1žæP“kW_ —F+š-Jt°ôç[Þ‡<\%òJÒçœtk€ð;5©<χ¤×Ä¡ Õ}tRœ”w³¿&½“ßôsáüoÿýðu¬ñ|@Õ~;üjûL‚I,üKñ|  ÆžTQ½½®‹ð¯Lð’Cjå mgwÜççÆÿ2q_íPñß6«œ'”pÞI*k–5˜êÒWŸ½9bçV<íI/vÑŒ¢¥ÕÓû‚Ü5E5­‹Ä_uΩÇd´TÔtÓç}Yú?ð«þ ™ÿýø->}ðïöAø¥jÚJ¨ÓüC«xMñw‰mˆB†Tñ‹W[ÔŒ®­ó>íÍßÛù“‹þ™_Iþ6l>uÆ™Ì05Õ§G Q`¨¿†ëÙÐIZñRI5Ë/z·³û ‡Ü—JÃåØgVÝ”ãí$šº”îïfךvwéöÖ™¦éÚ-¤vZ5…ŽeªGe¤YZéVQ¢à*¥®½º(àž¿ÎÙ¦m›ç•¥‰Îñx¬n"M·,Ej•›nNNþÖS_rµ­ÍªIê}],= <}Fí¢¿½?­nàuïêzŸ©ï^d#.Xé`¦@P@P@P@‰á¯ÚxƒÂþ#ñ ¾/ðÞ‹q¡]XÛŤk7?d¸Ôì@Âx®„’µ¼_½eŒˆ&"0m dQxUô}ȼGð³ˆ8ûÆ3“æ9&3 GêYo«Î¼1 Œ•hâUJN^Ò¥<;xñŠ®èôë•î³6WÁ—;M†£už¡þã>‹ž9a©KC Çb¨ÅoAàkô¾ŸVÌ1ÿ·nüº2UÃòv–*”÷•Hépõøå·‡Û¦«ˆ<­Až·§†ÿÃò¥ÀŸH×µ]fþÐÒΑª(s*™í—÷ª­±¿FðÀ²ì,>ŽÞ*qAK‚òœ£3០iJ2¥„޾kžæéEFž;6§„PÁÓÄÊ*+ O¡‚ÊùU*xz’Œ+Coõ¯$Âbž;‰¡‹ÍäšuHPÃR‹zÓ£*Âÿ©ÒJ¯W+{«Z/„>-Ò­^öËÁV‰ º´âoŠ ÐË[ Ë´ÑhÖ÷é:p…ØÒ$»@çßì¸sè_ã.O <<Àá3r¼3N/Ç`ñ•Ó“”ï…ʰ¯ÂN•GJR§VÑ…œ$ýåäã|Gá•®k›T>´p4êB=½êõ*M5½¥ú;üVø½û4|5-?íûr~Í»¶îÓõ‰šµ©X¬Y’m VÉmäUeT‘î$Ÿ›õwû/~“.òæ~&ñf ¦>.\‘†›S¡8¨ª4§,·E8Â7 èÔ½¥å9|f+éᯠVX ¾¥ˆ©{Fu¨PN_‰ÚõkN×Õ¹I«­¶$ø«þ ‡ÿ¬ð-ÅÅ´_¾+|_¹³Ü¦„¿éÄr#ø{Ç_|E…¢<ºæ¯à=÷J%¡”1 €1óÿBð·ì°ú?etSâ)qo‡³åu±´p¸yró{Nz4!ˆ›OwÜS³jñ–¶_)Žñ³‰ëÊØU„¡IßᄪImmdà´×[Jý»|!ã¿ø-ïü×ℚ¼‡ö’ø¥c£_;ˆì~xcÀ tÍ"6…"haºÒ'½ýý¢ÙÚø×âÏÄ_‰÷º†¢e‰ìV]Sñˆ´ûËÆ»D(¿ÙêL½Gpïð¿ Už#…2ì6]Ó’’Áàp¸BŸ½9(ÊŽ„£N+šVö–)´ÒM¯”Åæ†:1Ž6´ëJêÞÒ¬ê¶öM©NI¿ûw^»ÙûoÂø'OíóñËT‡þßìµñÎö7…5Ý?áE÷€tVŠç|_.»âÛ_‡Z À„öÝ0‚ÄgŸ…âÿ|àL ±]Äù Ræ†'1¥ZªqQ¨äéBxª÷å’’~ÏšJî I3ÑÀpÇæ5ÀàñRºÞ¥Ùù¸Ó´þkw±úKð¯þ ¶ÿ‚ˆü@µÓoüq£ü*øNóÞ[ýº/‰ÿVÔí´Ö˜-̲xoᦃâñ5ð¶ÜÉ×"ð­*Œ°þaâÏÚUôWáLLðÙ~oÍãÉ/ì¼¶­H¹§$’¯‰©…‚2‹æteÍM¹ÁI®Cì°>qž2ÕhÒ ïÿ/«$íçj£Û§2³ß»ý:øQÿ°øVÂy.>1~ÕMsi4vûtO„t« mfF‘ç‘|QñSWñõÔ†\ C¥¸a8mß/ò‡~ÖìL4hpGcjââäÝlÃ0TéÉ8%ðøxwhÍIÊõ%Ï +rÊ:ýÎÀ¶§Í˜c©Æ?ËJ•ÞÿÍUÏ[v‹³þe·èÿÃ?ø7»þ ³àH4Sâ¯üIøÛ¨è¾K%ÿÅŠ¾'¼²»¸Š€Ïyá ÜxsÂóù€³¾Ê°‚Ü Àù£ŠÿiÇÒS<¯^|6²Ãb$ï&ªF<êj1¯Šçª¹~ùï8|Ræ¼¥ö/8C ¬RÄâ§ùùVI=-~XZ>{iä´_£ÿ b¯Ùàa2|!ý˜þü=ºo,¾¡á¿†^ƒW›ÉÈ…®u‹› JâHÇFyK__åÞ1úIý 8þŸÕø»Œxƒ…WJ›ÅÔ§I'•:|ªÎ/•ëïE.dÚæ>Ï/áÊåÏ€ÀaiÔþeN.[ÝjõÑê½íÖÕ?§"QKJ!@ X†^R¶ÀÁ@ ü[Z¶6«¯ŽœëV“»•YJ¬›Ó^j’”¯¢»½Ý•Ý’Oè#SV‚J+¢Ñ}ËþAŠÈ¡h € ( € ( € ( € (œO äþTཤ¹)ûÕ;-_Ü®ÿÏÝŠïaÅFY Ÿ¼ýØÿÈ…õ®™à±tÒ•zr¥ìKRMù{N[“ÍŽþšþWþ¿òWC Üʱۣ\Ny m\ÌÜû4rÈ3žpF{úŽì«*Í3\rË2Ju1YœâÚ§‡§\EzÑZ>Js·ÉÕ4þë~gxÃö§ýˆ>^&™ñ'þ #ðÃZ˜*§@ðWî¼eâ9¹S –áoUÔngI†T´r½ÔpG÷þË?¤°¡Çól¿ hûE•¬áKM\i×Äfq£l¹¥…’jöŒdÔ—ãùçÒcÃ\$+T• Ob¯?mW ùÙÎ0¥9E=w’õvÒ­Ïü?ö?ð~€ž*Ö> þÐÃÂ3L¶–>*ø«á¯øQ>Õ®‡ï< LøÕká?øÄÜÚ‚ðHÔÒaÂ6sënúã8b´0ù¯ñÆ:p_¹«Ââ)èíyû,-Y«ÞÏÚb•ﻹù¾qô‹Èe†ú÷Ô2ü¿åeRµ ¸k·ihýbTß%åîS•¹dœd£åúWü#à/‹µ/ ]üýž|C®øgZñkx'Â~'ÏgáOøY9Š+¯í|ð³Ù7üq}£ÚZ½×ˆõk›mÃÞÒ­®îo®ËÛ›I?¡p?DŸ ²#øvçÄŸ>=|,ý¤þéºq—V¹øðÛÄ¿¼e¢iš’Ðj?~iž:³øÁáˆç*Ígwe.µ¤½º¼ßÚ2¤~‡áNÂÖX|u N&ííjÓœ$Õî©Öö~ÆVûJJœ”­VîÇ3¯ø÷*™ TÁãòµîBgЧ>[â(*”+Âí7NP¥8JãÍ/ËïþÙ^6øµ#ßüPøeû?|e¶Í |PÐ>,øÛLŽîS™¤{=sã±Z£¡*áÕË%YOZû, àðk_†ŸzR¥ Yyªqm]]Yµ~½ÿ'Æø±ŸbêRÇTÂåxŽF¥ Ö†*JjêPýô¹'gýÙÙö:¿ÙÇöÁðÀO‹¾ø‘sû þÅ~(Ñ|s+xCÃ^ñdºKÍ*÷NŠM3PÕ5¿øoOÔld»Æ÷zUÔ%C&ÔfY<׆ªæ8*¸oí,ÍT©oz¤ãQhÓ÷¢”%+Û¤®žº¥ii–ø³¥ŸRÎsL§$ÄNÎ\±­ Òr‹^íjÎp‹»M¹ÂWIÆéÉ8üã¿ÚxÃÇ6ñvŸáÍÁš‹|iâïØø?ûLJ¼%gâ_êzí¯…´’8dþÆðì‚ÙÚå0§j‚~‹ BX|5:“©8S„\ŸÅ'F.RßY[™ë»ë»üÓ5ÆC0ÌñêTãF\EZŠœ~*•'S’>ìosr§Ê®•ìúrµÐyçÿÑþ+þ'Ïô`( € (ò¯þ g¢ë~"ÿ‚b~ÔZ†´MwÄzþ±£xNÒô hú¯ˆ5½Nòóâ_„ †ÒÇHÑ,ïµ+¶f“çÙ,q†w+»W÷'ìâÄàð_Kl‹­C„§—f²•JÕ!JœRÀÔzΤ£úE^ò•£ɤÿ7ñnJÜ‹¥F2WV…”S“¾ŽÉ&ý|·²»Â×Ãïø$7ügãÖ¥®x'öHøÍ›¨kƒÚj7Ð4Ï…ÖSC-ü¥n¥“â–¹àÝB;y"`ûÖÖS´ä+wÿ|8«éWôyðòð¼SÆ<=B¤(Æêž-b¤½ÆÔTpPÄ^MÁÁEÊ)OÝ”¢Ïæ,ñVi',&Ó“ÖPöiëÞ¤£¦«[mÑî~™|%ÿƒ`lßßi÷_|eðáv‹-“6£ÿŒ|Yñ7Ä6÷lb0Å‰à¯øCJE´›ÉÖåÃ"€$ån1ý©ŸGL–…Z\=,ÿ9ÇÆ~çÕp0ÃQœU›XÆU©vÓ´Ù’MITåѯµËüâœL¢ñUÃÒ¶¼õ%9'þqK×ßíkêÒï„¿ðkÀ½Òɾ0~ÓŸ|Yoz·sAð£Àžøcbð¥Èš=95~×âŒÒßÉQ’. “H2Áž?–¸Ãö¶ç¸šòÿQx6…:.—"yž>¶"òq”]GG õjÖ5!NQŒ—$ý¤lßÛeþa)Çþ±ór¾ÔiFi§4ý¤»Ýó'Õr´~“ü5ÿ‚ÿÁ2¾Þ®©'ìïÄÝdEo šŸÆ_øÃâP•`iYö6»¬>ƒ/)$GnŠÙä` þ]âÚ+ô¨â—g8,vã·B„ã)(¦Õ~Ojìà¥'.F䵋³û<'……—=L<ñÓZÕ'=¿»~^¯¢¿´ýøkû?ü ø7§[i? þ ü*øk¦Ù ŽÞËÀÿü-áØâEäl{ -':ïÉ5üÍÅž3x»Ç˜™bøÇ‰óìË'y:øÚÍ7Ì佨J ÉÉò¯²›Iò¶—Ø`r “,³Àa0Ô`¿’œWKvŸßÓØ‹€®îàtÎà}±íÇø2pŒ¥Ï$Ní'/ü ÝéÑ^ˡ몠€ ( € ( € ( € (nÚ€ª  /쀹ü†Ojº4êb¥Ë…ŒêÔí¹¿º7×Þ›Qø½tþ¿¯›Š²ý𱞠I"Fqî²yGô?á¼ðXšrä¯Ò¯j“…'oðÔ”e÷/ø)IKá»ôMþIÿ]{Y³ÓïµòôÛ;ÍBBÛvXXÝݸn¸Å¼2ƒŸóïîð÷q?T•.Àc³:З,£ƒÂâ±M>‹÷j+»«{Î÷Ò÷ºçÅcp¸(óã*S¥óœ ¿òi#¾Òþ|PÖU^ËÀÞ!HÜi“ßÌÕg°Ø¾üãÒ¿}១oÒƒ‹°‘ÅåžB”Õãõªt07ÖÚýw‡œ<ïNM-mmþ_âeòk˜á\–êuþSŒÿ5êZ×¾Åà›i/¾&|HøCð¿O¶I¦¼»ñßÄIKh ÿ]+†hcV~oß:vþ™áOÙIô‘Ï*PþÓy]Nr^ÕVÆ×ÅTŠ×HRÁ`â¥;ÛO­¥kû×±ñ9§Žü —S•Oi^¤b›º„iÇNò«5eÝòiù|±â¿Û/þ ©ðä^7‹o/„þ!»³Þ­¢|±Ô~+j²Mäľ‹ÅÎÒJ[üªýÒy¯ëNý‹yä±>Ó‹x†ªÃ8éO ”•îäñ¦#Ú·jpåîïeøþyôÅà,5ð•p’§?†_ZöÜÝŒ0Ѽމ7sæ?Ág?àšþ ‰ ð‡ƒ¿jŸ×¡æMñxcLøo¢Ë€¦wñ®±áBi›å8³iT ”8çú—„?cׂ8#Âñ%\ç4‹¿7Ö³YÒŒ”›¼U,®zi%¢J)5»“ø#â§ YRË¡'&íûœ+´l·sÅJ*Ïm.ïÑ­WÌ>.ÿƒ‚ü=cpÑüýƒ<§ÀŠE¶¯ñâµÞ¿xÊÂI>‰áŸ ê1YrÅVø†^7s_Óü#û9¾Œ+ Upœ+Ãÿ[¥+ÆSÀG4ÿ™VÆJR½´½®·õüƒ:úhñv3:XeŠú£‹´åŠ-{{,<&íçͯm¯óŒ?à¿?ðP p^AàÝGàOÁë ˿ÿƒkªßZÆÑyeSWñ§‰î¡f.ì*Uñ÷€ÁþœÉ<à,‚œie˜8Ñ„~Í5F„>Q£GM4ø¶êÉ3O¤‡æJ§<èF£~ëTêÖ”U´¼«Õ‚n÷],÷|Aÿ‚’~Þâ{o~׿´¡i#¤’Yè>8µøo`ÌDQöo…z‚®ãB®C(º*ãïym…àîÂ7*8<2m}¨Ê­¿ðlçü—N–ëð—‹V!©[ Mñ z˜ÜL`“朽—5Õœ)EBR|©E¹Êó•ä㪿Ðã¼BŽV< ƒ§€ÂÕ­RJÔ©¼L¡5'%WRU”©7V1§JPQ¥Íš\¥·…4_ ÅÆ?Ú¢_ø«Äþ1Ò¶< ð‹[ñ'ˆ×â¿Å]V–O|UñηuªøãáÀ{™£aË:ëÞ+ $zM­½ŠKus¤ªÖ¯/¨pÿ$(R’Sª£eNO^JpŠTê×]lœ)]sÎR²„Ó†…yçˆÄTÅâ£7G )TZ” ½œªÕ©9:Ô0ÕJîQ©]?ÝSJSu;Ë_xÏÄ~ Ö~'ø³QX>"~ÐiûþÏzf…h¾Ð~ü,ÕµÝÁõ¿…¾Òe†×áç…¼%câOø{û:Csµ©ÞÜKy<Ü? JxzU£ƒ ¯†Â'‹®ß½*µTeRŒjIßÚJv•jœÉ'¥ŸÒå8ÌzŸúÃŽ‹YŽaR8 ERÃÑæ…:Ò†¥?e To0Œ}§´”ê¶ä¥uÝüAøƒâ_þÛíá]OSÐ|Sð?ãW„ÿiŸ„šÖ,vºÏ†%øöß³ÏÅ o@»tk.l~êq$ðÿ‰ ´ø×áêZƃsðgâOНg´²ø‘ðãVÓ/,|Aáƒu;ì«owøsÄ’\h·Mi=£Åëa'u¿°ñÉÔ¡:w£9Æ/ÚÓ‚O’¤ZqZ1µÛMΚH¥%ï|ni Õpãl†O ˜SÄÊ8º1©9Fj’”}¥ ¾íJ4+Îî š¥ZR¡;Sw§ZoºÄ) §í+ðæ?ˆš°‹ì'âÿ‚‘ðÃöˆÒãn[Õ,ôx~ü^ŽÌH6Ùø“G·fزÊùØ•ð‹›$¯ì©ÞþÊ\Õ0òÿ æu)7¯½NRßG¡1㜿6—±ã ¶¯nYV‚T1q]T›Œ)×Ir¯gVÛÙ©í*Ãör›â =×ìÕâû/*Ñ‹¦øwi¥Ÿ~к=»ù`‹ÿ‚ÚÕôíã-%ž8$Ôü¨ëVW „´µPTm òX6©çtÞ[{KóÐoÊ´c.Fìß%hÆJ:¹Ë¯›ˆàÌ>mIãx&·×£ËÌðööX¸®XÉÿ³ÔqçIÉEÏ9Sçj¥6¼{âGÃ/ˆŸ|e¬ü;ø«àŸü;ñ߇ÞÑ5ßø»L}']ÒΡg¡`÷Vm$‘˜/ì¦Y`–)%ŠT$«±WÖÁc°yŽ8¼ HUÃËiEÝ;h÷I¦ž4Ÿ•šoäsŒ—3áü|òÜÚJÚv¼f’v’¼^ŽI©-SŒšv’º”f£ÃWYåÿÒþ+þ'Ïô`( € (ä`‚TƒÈpÊ}Aê 5&¶m;[F×ä×Ü&¯ýÃÿ_‚³;œ´ýé¤lznrÍÏÖ¦1Tß4Rî’OÎíY»õoWÖÝ_—A)€P@P@P@P@&ÒWnÈUgûˆÎ}Y±õ ?Zè¡…ÅbôÂÒ«Yršûâ¥oëå.qޤüÚ_×õóÁ;Ú8ðyß,`þ Üg°ÿëk,jwöΕ9Gu:´Ô—¬9M¿»¯O!I=cvŸ“·ßk~&¶Ÿ kº¾Ñ¤hÚ¾ªï÷—¥jÙúmˆ çßú³È<-ñŠððÄð¦Cžf´*|2Áe¸ìLdŸU(áÔ[·ÌÒZù¾ Vo•à/õìN‹_óò­8~Wþ¾G¡éß¾,j@4~ Ô,áÃ<“ê÷:v‹HŠ[|‚úïÎUsò~xþŠáÏ 'Ò·‰jц„q¸Zµ1•ðX8Ár¹^J¦&uµvŠJ„ßK;|–7ÄîÁEº™…)Ét¦ªToçòÿäßð9Ÿi þZ˨üfý¢ÿg„¶íÏ'~)è:|Ñ<ñ—‰<›‹­!KHäa,znÈÏôßþÈ¿3üj†{ŽÈ°X^Dùa‰†«ûfZ|I½Ü éÿþø³â9 ù™TÔü;áÿièbdÖ¸]¥—pçú¿‚ÿb½:tøËˆ³•œ¯þË€À`¾ÔÇýzµûO7«å[Ÿ’g¿LžÁ׎𮼕Ô}¥lCk{¸áã¥eÕ¥ªWwWù—Æð\ø'ÿ…¦ò|û?~ÓŸÞÝ#)yâ­CÁßôk‰C8•$ƒQñkëh›@aÿÒ§v>R¯ê®ý‘ŸG̶Žg˜\^iV‹ûögޝ8¯Štpîž©u‹…“ZE+_ñ¼çéÆãZ¥¾5¢­½<=K^ŠX‰ª—VZòÛU­î£òç‰ÿàáoÛµÚ|!ý‰¾ø’éeª|@ñ‰>"j*‚bÑO5–áß@áá“íO±‰!˜b¿©8;è!ôsàzðÄä<5‘PÄ(¤çK,Ã{M:{jÎuOU&õõÑ~;šý1¸ã5¥R)¾f¡í1“”Z¾’”0ô’WV¼TõkSåÿÁu¿à¤>1³šÃJø¹à_…V“œˆ~|ð¾—=º¼Ý–ú¯/¼i:º¨ØÃÊu]Äšþ…Êü(ଢ>Ï „~Á- æ¡¶÷hÒ¥¦··2×ï_•fŸH=Ì©Gý¢Wºå*T9¯fœ”eˆ«Q¥%îÝÓm'}öø“â'íÉûb|XwoˆŸµ/íâ˜äI¬æø¹â é.’¿˜ñ>ðæ_éÏñŽŽ¢àp>§ ÂÙ<´0˜X»­}’›ù:Ϋû­~·Ñ¯‹Ì#¨óÒÉõ½Eu:ééjwW§E´ùêµÏU^Œb¤£ú$ð4|3N®*Tq&ø¢îOøËÅC®_h:Cj:^•⊞4¿Õnôد-<-o{ ‰n­æ\˜môí>ØGå['VcŒÊøo,ö•Üiá"¹cW3³jœ,¥nvšnÏ–îs““æ—‘eÜEâ?¨ÞUqWU''ï*qRŒ}¬îãÍÉ{­œç p5%^ð^·áÏŠß¶ÇÀöŽ‘ð«áoŒ´|,Ð/£¹†ÿJø]û?Úø£Äi¨ê¶Ú„P_/ˆ Y£Ëiuá?ÚfçWÑ5¼ {+McÆÚ]ÃsòG 8ùp},çÉ’Ô¡†½ÃÂ3§'tÔðÊ/KlÜaQ+évµ[¿…szøŽ5§<Ò“äÅÎ¥,E88:XÙIKÚsòóB¥ù}ë]r½™ð7Æì×ûCh3|Qðî¡ãøÅÞ ø[ñÛáîŸ5”Câ_Ã{9uoüNø¨Ù뉩éþ-†ÊÚôÛÞ‘žÞ'Y!•ReÓ1ÃÏ;Ê$ð“T«U§´g$ï ¾Z”æš¼¢ãyCš:ÙìÖ‹ÏÈ3j<ÅÖÆÁ×ÂaëÏ ˆ¥JV„©Ãž…jnjæå¥Q¬¹Sã(ÉÞ\çí âoƒ>2øÛñ#ųÇÃ[á'Á=sÄ^|8øo®ßC¨jžГDÒ-.tû¹íµ]vÚ1q®Û^^Gw·Ik ÒB%m™®¼¢Ža‡ËhÐÍ*ªøøBÓ¨¯i>i4õŒ^‘qÚMµó~ã2<È18îÃË ”Õ¨¥N”­x§)+FSнE9Ú2iswº˜x{_Ö|)¯øwÅ>Ô®´øKÄšŒ<3¬Yy"ÿAñO†u;]gÃþ"Òd¸Šâ+=cGÕ,âš Â6°1³¤•èRÄÒÉ:s„¡%®±’q”]¬ÜZm5óVi8ùY~cŒÊñTñ˜*’§VHÎ6¶“Œ”£$š²’iZVÕ{²n”gÝ|føÕñWö…ø‹®üYøÓã½câ7Ä?G¤Ã­ø§[¶Ò¬nníô-94­Ò 3B²Ótm.ÃM±BÁm"—w;žG-†_—`²¼4py}(ÑÂÆNÑݹÝå&å&ô»o¢JÉ+õgyöqÄxùfyÞ&¦'5å5üå\´à” ’»QŠÞR“rrvòÚí<ƒÿÓþ+þ'Ïô`( € ( € ( € ( € 2_æó¥)FI¤üÿ¥ý~-&ö#‘¹ÈG÷‚>ßŶ:óÿ죀Ì1Qö˜|=yÒþe 8¯Yòò¯›ÿ›©N.Ò’O×þúû¤Ð $…UIGfÎÉ›!b[ ýwOZ£ŒyèóÎQŒTjB¤¤äÒŠP¢êÔm¶•”/w·w)¤›³Óºi}îËúûú]/Á~-ÖSIðLjõ=ø*ö:¥4XÿjV¶†%ùÿë~¯ÃŸGï8º½W¯^)E>É'ùø¸Þ%È2ø¹cq¸JVÝJ´/÷&ÛûŽö×à/Äù`7wÚ‚`½ïˆµ½#G…*Kq<©tϱ¯ènýœßJ¾(¯Ë_‡#•á-ªc±ø:7»wµ:2ÆUN6»æ¦š²}>KâÏ`WûﵟjtêKñjÿÉ¿Éy7޼[û3ü@ß?lً᜸•…Ž©ñ;D½Õñž\Â=1u=6êæXX€È‰!^þµý?Á±ÓÆŒó êñs“áfÝ’Âá³ ÅÁ6íÍ.lº“vWÖ-¶ºkùÆyôœà–´hTªÎüªµzíkòź’v¾¶Õ]kµ¾^ñWüÇþ _à'–øhψÿ.­´‰ðgàß‹µM.êHœŸ&ßÄ÷^ƒÃ†;’IcÛϘ23ýa±g…°ø|<ø£ˆ3ÊÕ£(¹ºË2ÅS–I¸¿Üâ1q„­i(ÖçIû³M]~E›}4¸j”ëÓ˾­9Q^÷,q8›v\ÐP¤åä¯n©].xÃþ ÃûøíÃáìwñ£â-ÜBî-6ûâ¯ÄOx/M¹’3þ‰<ö.¹ãVÖÊ‚êöqÊŠqµŽ@þ­áÙEôhɱ´ñ¹¦O Ër¹cñ™Ž=%'ÿuVªÃ9.Ugꮹ¬ÝÿÏ>œ™¥L5G”Ãí½îXF8\73ZFòr©V–þôy’wq¾‹åïÁÂßä‚Ko„?³ìÃðœy’¯µ˜<[ñ;V·Ž@þ_l¥¹€’ÁŠ”cÁ\¨ø+èwà_ÅÓá̃)ÁÁÝÿ²åø<;r{·%’ÖÊýt^‹ñþ úZñîmý_–5[\Þ߈¬”z¥FŒ\­{7eÞúßåÿÁk?à¥?>[þÒW~°Ä«ý™ð›á×€<,‘ˆBE©jZgŒu¨Õ¥f¬Ûƒ?kÁxoÂx^ÊE4­nz“vÿ·i*1ûïµ­mÿ6Ìütãœn!U¥‹ö4¹dœ)Q¥Ûå³sªëÏݳ²J?½ì­ðÿ?jÚ?âÅÕÏÄoÚ㿎¤¼`÷ø£ã/ÄK9ŠÂ!Âèš.½áÿÆ%ôÁ;³’Òaø&ÂÆ*† ^±£NûßYN5&õ}dü»Ÿ‹ñ‹q“«R¶;5Uëâ*¸¥Ê£hF”¨B*ÊúGâm´Ûºð4³±¶”\ÛéZE¥Ã"æÛEÓ!½~w:—Øÿ´æ\ó3r3þï®âù¥97ÞRkîºáÿå§ŒÄ:Q¡î*0iÆ*œ-¶i¸¹§çÍÓCš„‹{ÍBS…Hä’{×8è¤l/n¸þiF•5x¨Áy$¿+~¿ç•I×Äû•%R³þô¥'øó]Z ÀãéÇùâ¬Å$´@x“À½7Ã$“N“W@Ö_JŠ_&]ItËÆ±Žn?t÷B!dù‡Ê[<ÖN½?fç~×WûŽ…„Å:^ÝS©ìS·7+µýv1YNÖR¤vaƒùÔÁ¦´{‰@‚€ (ppi$Ž @= ”èŸ þ,üHøñÃÿþøÓ]ø{ñ²ÞËáïxq솧¥¶¥§ÜéZ„I«c©éW¶—úuäÏouo=¼Èß2eU“‹—á3<,°xÚq«‡¯^ÎÎëX´ÓOfšk^§ìdYîcÙ<Û+«:8Êw´£Ët¤¹d­(Ê-5¼dšvOIF-s^)ñOˆ¼oâ_xÇÅÚÎ¥âOø«\Õ|Iâ?këUÖõíníïµ][Q¸ s^ß]JYÊ¢"¨Š¨¨‰¶G B|êÒiù_åñtÝJY“NQr§ÏiÝ):Pq„›^ò¼©Âk•ÝK–Îé_ô?þ 7ð{ß~(ü=ø— |høMñbÚ_á?…>6x‹IøW©&§kà]xÁš‰4íFé5+ïµ[x¿^zž›;Åe;ÇÜrÛ«B²Iò­ˆÁTÀÔÃ×£%iQR¨­Î¹ªMieÊà­FòÖQwW³ý/Ŭ›…Íig”1¸þ}çÙ#Ps×'õû_ }þW{|Ž?ÆNÀ·Ë‰«Y/ù÷JVûê:KúûüÆÿaÿ„·Oañköïýšü1©Û²Eñ–›âíuUâ3$qéš^§-ë4¡pŸèÄ3p2Hú£„?c‰¥U¸ˆð”bäœÞ,Åâ´ÒñLN+F÷ѹaåe¯k~_œ}*¸+«R„eGÛB7q«Š£NIZé¸ATšVÕj¯ù|Áâø+'ü×ÀñÜM¥øãöŽøÓql»b‡áÿÁÝwÂÚ]ô›9ò5¿é¾ÒØ n~ØrFåËë^ ýŒÞåy…,OfÙî)Æ-:kÀRmÛÞœrüÏ ˆ«95} ëºtìí¤¢ô|ÖÕüµâïø/Çìû£ÆcøIû xƒÄW~bÔ¾4übÐôØ‚íHeÓ¼iñ4ä»@”gÊÿ¨8;ö\}xfS©[‡2ÜeyÉIϱyII%ù˜UqI¥¬b”.®£«oò úoñg yoÖe¿-L=ÅjßðY¶ž–·]ÒZüÅãø8Göþu‡áwÂÙsàÕŒqªFÚo€üEã½f&Gb®—úÖ½áí=³ CYqŒŽ¸Ôü'ôdðƒ0pÁpöSƒÁÒ¤£G …Âá#ÅZ)*tfýß³g¢ÒÝ_ã¹ßÒ—s\_:ö ãï{Z˜Šõ¯Òò£»¦Ÿèþ?ñ÷üÛþ ?ñK“­þÖŸôKKŸ”é¿4¿ü6²‰7´!ŸCðÍÖ²“€Æè1PÎ+õ,7ð¾% 75Ör©?ü•Jùréøâ¼hãÜ\ªsãªFzF•:4”}$áZoÕËîÜø‹Æ¿~*|Jó‡Äo‰ßþ" ¢MÊ|@øŸñ Æ6Óî“Î+&™­x¢mÄfù¼¿²ˆƒt?E†Êòüý¦ 3[:t©Á­-ñ(sí¥ù¯æúüF?‹xƒ5ÃýW0Åb1n›öÕ«Ô»O™]{HÁûÊöäåÓd¬9µHtögÓmlt¦n¯¤éšn)‚Z}6ÖÞwlެŏëéÚéÓ—»;ËüNR_t›G<~6¥EUÎÕ²qŒ!$»)B1•¾}>Cåw·Ï$“¾Ió'wšLú–”³’q×?âj)AZšIyiùXå©)V|Õܧ%ÖMÉýòmþ?ðLA@aøóö8ñÃí;öcñ¯ñWáEç‚¿jÍ2mSÀ9Ó&ø7†tHl5äð¾»mãî<m}¦ê>פ[mFÞÚÞòkV`λcàáóêX™c)Â…u_í8>Ngu̹}öš”uMÙ>÷>ÇÁ¸Œ2ÊõqxGƒÍczUWµä¥É/hÝ$Ó„šŒÒRq¾ªÚ¨¾#~Ç^+øMñûâ×ìóñâ7Ãoø—àLJµ¿xÃÄ×Kñ ü·FÐíõØôí:òˬÜ^ë_ÚA¦»X¥­õÕí¼QLÍ2x\úŽ3-¡™á©UDÔcÉÍ«µß¿k+7-[I6Õ³Åeyö/‡ñøœ53k÷ZlêÍ'7O5¸¹¹€%Ä‘xÔ³¼&_•æYž–*¤¨âêûHMݪŠ0råÖJ£ué­–ÉýV#…3,ëˆ2,‡3Ä`(ÒÅe´=Z1i:u#5ËS;?[®i+IÇèŸØcàN‹û=~ݺï<)ñ·àÏÆ›}wáíƒá«Í3ÁPë:߈|%‚¾ø¦ïEOÞøËÀµðæ½qªÙCûÍ"éܽ¤èî `$òx2©špäq5°øŒ<£_ $çesÎ7åQœ¹•¯ñ.«KŸEÀù㪘&7Œ„ð¸ø8Óæ”éû:RqöŽt ¡6Òþ·Œ•ùwü×ñ·ì_âß ~Í‹ûPxâÁÏŠÒüw¤ü6ñî‘ðçĚޭ↞,×t»­SI´ñ]¶§áHº°¾[VŠ+í*óR²šlæuË­Ãgôkæ¿Ùh×£‰tÝH:‘J5"Ÿ-¤ÝÕö’‹]WoÍqÜŠÂpçú͇Å`ñXW*±£9Jtg%x©Þ‹NÖR„¥ömj}qÿÖø+ðæÇà§íŸûtüRð–…ñ ×öMð¯øªÖKÂ:ÇÆ/I}§xg\ñ^:Ëo­i¾ŽÍ¾Ã:<O{–Âx¼Y˜b¥˜`8w9RxÚ¯ÚN:IR¹”_G%}Uš·™õždÙ}<›8ãŒÎ”1ʨ/aJi:rÄTºŒ§y”-¢ô|ÝÖŸóürý¡ê¾ÆŒp–µšŸ«kWæîÞ÷nççï=âW7e¼¬““IÐðŸìKñâ†~øçÀ~.øâo|Løçcû8ÛøÁo:ñ¯Áÿ„š†ikÙcdzüHñ³i'áßÄ;#Ķ£¨xÅôÝ3V¶°ðÅšè!q“Mp÷<I’Xù*qN WX|=*õêϱöq¿<ŠJi¹k{Y%f›NÉú4¼;Íþ§,n:¾ B–bðU]jœ¾ÊªŒÛuM({©&®ß4ZN7’êþ#~Ï_,?fO…>Ð5?€¿ü¨~×ÿ~ü7Õ> اˆ~#xÛâ´0éú%äQxÎ/X\x‹ÀݽµÎ„¿hcqü2ù{<±8\Ó.–q_QbhâVZŠ«å§ {ü<Ï–kU>Öj÷»}™—ç”ø_ ƒÃÏ‹Ëå›Ö¡Eá×=j•þûÎUÏJVNžº©Eín_&°ý‰~$kÿð¾tÏø³áçügû6è7%ø­ào jºÝƳ¦éN·eá¯Ï ê·ž²ð‡‹[ÁÚõê[ÞÿfjWK7úË#uï+¶\E…¥õiW§Vž.Zs’Vm®hÝs9Gš*ëš*ßjÏCɇf5þ¿K[_–Þ½(9s%(O–N*œýœ¥É7}àä­~'dzF»ðêïã_‡|Kã¿ÚüAø=½¯¾yþ(Ämxž0Ðü â  ß\øb xŽïÂ%סŽý-µßn’ÝZ›X¤™z0ÙÅËW÷+¿ÀŠïaåcÌ_,v2:@N˰Ìÿ‡l²ÜÂ6öÔeEKgYÆ‚z_G^TÓÓ³ÿ'*p{;ú{ß’×ájÓO¼¾s•´÷®6XÛ\ß>[¢±Á8,~«ýG½ðOñ=yaøw ˆÌ1i8á0øœd“jé²Ð­ ùs§ë»çÄcpØHóâ§ Qï9F ÿ'”_àÿϹÒþüKÕÑÃÀþ$‘$ÆÙ.ìF™ zùú•ŪàU¯Ý¸oèiô—â¼$qyq£;[ë4¨eÉßψ§%¦·p^véóÞ?àü œ19Ž5ü“u_ÝN24µo„—¾„ÜøÿÆß >Z&׸¸ñÏÄ-IHÎÀdRåC0q“Ç^ŸÑÜ1û+~“ìè¼Æ9UF£\뫈«½íO†”e%Õ{h®Ï·Çf8ð.2’©^³]cMA}õg¾ßð>^ñwíiÿãøhnÓÇ··Á‹Ûý?zÝh EßÄý}ç†S ÖðØøUüCw-Ôl¤ÖÛ~yÛëýYÁß±W‰ñ8šU¸³‰j,3м0™SŠ“vwöù†*µ5lý‚N÷{YþGŸ}/ø ,ÃT«Bxf©¶›x¥RI¦âãìðñ”ܹ´åMÊúXùŸÅÿðXÏø&‡"qámö¬øÛ|îêŸÙþµøa¡Iåžíßõ/‡l¶Ó($:G7$‚Nßêîý޾ äÞÕçØ¼ë1”Ú¼kfQÃÓKKÆrz4,µRmêÚkF~IÄM¬6Ò† —¹Vö•<+´U›æLdéÆ+M,›m¯uï–¼_ÿøMÃðkö ð” ¿ÙõŒî5»Ö”80Ï.á kö’0~tþÖA’6ÈFsýAÁß³_è»Ât(¬? äs­E§×Â&Ô­fžØýÙ>À€çæSÛú—#ð/Ã΄)å8(Q„Ô¡B„<íT´O¯¼õ×MŸãy§ÒWó7Sá ¤ß#å­ZI[G)T«)/ú÷ÒϯŞ?ÿ‚šÁ@¾'Cumã?Û ãÍ­çö‹ øƒGøm§• rC¿Ãý@¸ŠŒãhŸåꤑ÷Xn á¬$ùè`¨'ýîz»yNn?ù+ô}~âÏcð¿WÅfx§'{ÊŸ²Ã·úõK™iü³O³OWñ׊<[âo\}«Ç>"ñ/ŽîLžwÚ<â¯øös6оy>2Öµè|ð‹ámã8à{¸lšÂ¯¿³„)ÿé¸ÅÛÊò_¯Ëcø›8Í*F¦:´êÎ;:“«U¦Õ›µJ’…í¥ù—[6Œi¤²ŒÅ`˦ÄNL:T0èð¶G9‡LŠÊ"x翾î•9k5Ìÿ½y~2¹äËŒ»’«8JNíÂÔ®ö×Ù¨_EmHÛç1þy:o™Ø{»sþ{wÑ{ªËcš^ü½¤õ©Ýêþ÷¯õ÷%P@P@¦þ?ü4Ô¿a/ˆ_¾*kBÏâGìÛñgÃÿ?dÐê“ßk¯ŽPø;ÇÞ¶Äe9¬í˜å¸¸â°=\¥S÷u)-½ÈÏ’¼•õ´»YÁûjü}øsñ«áÇìáñÚ×Û~=|DýŸ| ðëöš·Q¸¶Ô~x‡YðW‡u=nû{­Î­ñKIð\BDoi‹e&YnŠ£È2ÌVŠÃU²Ú8™Ïçí¢¥$—jwœSÖîr_fíq§eÙÖY—fiógØœ*8Å¥ÓÂÎP‹“þjê4ê5£Q§´¬¾«ñÅï„þý«àŒÿuO‰ß5üý¿e üXÖ<-ã_ xÆ/‡¾ ð‡Å/êþ&Ó“ZÞ­c¦NÜ´¶ðH’+‚ŒÀ^Æ:iñ~ u^zÊSP—,\ÔyS—-“vÙµçcåòŠøZ>g8 µðñÆÕÆáe n­?i8Órç”aÍÍ$®µK^—C`Úá·ÃþÕ²çÇmBûÿ?kï†Ö>¼ñý†›{®Kð¿â7„›W»ø}ã+íÂ+›íGÂñjÃÿjGi׌°@c\#añ6O‹Æb0yÆZ”ñø®J ¥í!+sÅ7¢–žíìµz“ÀO–å˜,Ó…óÙJžM›aÔTœ½Xs{:Ž)6áy{ü©ËHÛDíã|âo…¿´¿Ã=bÓã'¿ iþ ø™áÍV÷⮃ñ«ÁphV¾ÑfœS|œ¼íhã}êo‹ÿnŸÙËâŸü'öÂñ–¥ñG^Ò¿g_Ú«öyÕ?eï |hm3Ä6§áuÆ«ðïáežŸã«=öÚÓ_Ó<=kñÀ3yŠÛæ+溗b|…Í0œ¡ 1y¦±¥x¿iiÔn ­¹&»íe­‘ún'ø{2ñ?6ÅÕÅTf™|°TñšöT¨%QEÚQ‚«IÞÉ|\ïK³ã? |8“à§íû9¿m‚ßt›?Ú#á¹hžøÚÞ8ðfŸáŸøßEÖµ¯x×ÄÚÍÖ™áéšf“m Ž û„Õ^wÚ-–5’U÷*âÖ?+Å}[/¯BU«ÏK’nRƒŒa¤å6ßT¹m×dþO —¼›ˆrç˜gx±ðÿÄm_âǶþé^Ö.|Câ{¿YF%‚;I&*@°+ÎÅañO Èi*Ýjœ©NnPTái¹.[ÅEïtc/Æà#Æ5?ðPÝâM¾ŸªøÛ@Ó> ø³Àš'ìýâïêm| ¯ë‘øîM ÷Å7ÑEl׉w,r£<1¾ôNú4ñ ‹ébgB¥:ÙnÔ$áºÑš‡$ðGˆ5o„?ðPï|]ñ¯Ãm/Æ~Ô¾"éß uxCÃ?ð”C«Ë⤊k[·´[Ç›‹tÜUX8ós|¯šgYŽ”*FòÈÓ…G (:‘œ¥ËÏetO]Ÿßîð×e¼=Ây&3V…J¸LþuêQJr«2¥|þÍKŸMZ¼wKe©óÏÆÏÙsáG…>#xÏâ?„n?€š¿Àÿˆ*¾½ðÍ炼yy­üd¾ðß‹µÁ¬i:‹~ØÃmâMPÑå’ݵwÕÚÒÆØÛ<ÂY&HáOœãka)á+eØ•˜R‚RS…©)EY¸Ôz4ÕùynÝík;¯9á|§ ™W̰¹î上ÍÅÒªåˆp©>hÆt¥nhÔcËÍvÒ‹÷߉_´‡þ1üý¨ü!ûj·ì·ñ#â_ü¦Y~Ï´oÂvðLß>$üS°ñ>¦h’jÚÇÃýJI¼[à=SÁ‚îëQ¹Ö,íVÑP$ƒíò"Åæàòª¸Ç_ úå,%JסWŸØÓ¦âÛ²š´f¥eï½ùw÷s>"¡›ä™¦W‰Ì(QK ‹ é¼MjÊqQmÒ“s¦áyMÎ1QZ5ÎÒ_ˆUú!ø€ž=ˆ<çùÐ&“V{3Û4ßÚ?ãž“ð+Äß³6ñ;Ä6¿,Dº§âí2ïIÔm5g¾ŸN}~ÖªhVw“ÙÁwÍíºO"3†-æÏ'Ëg™C6taý¡8*—’’ƒRMY>Ví'&›QÑtkèéq_ÒÈêpäq•^GVª©*4åQJRç”]H®jjNj›sz¶Ÿ‰œ’I$’I$õ$õ$I9ÿ>¾‘óÍßP A@PÿÖþŠàáÊFGieŽëŽ#•ƒG¡ÿø¬y~1MÓ«Q¨•Ú«R%µù*Îû¢Þš.ÿ躜\oµä›_zM–¯ªãû3LÔµ"Ǻn™z\†*B4íÃ6=ëì¸wÂî<âì:Åp¶Sšæ”[i<_Åó8ÉÁòΖØ»I8ÝV庳’éÊÍrìûízëåJpü%$ÿ—Wè:wÀÿŠz¡jöÑ`³\êoe¢Âˆ%ØêK @'oONÿÐü=ô úRñJ+Áù*^µ1•pXÁw”*b*ÖßKF›—[Zî?'Œñ/‚p*^Ó1¡&ºSSªßþäÆŠ<1à߇·Z—Å¿ŽŸ~iöÜKxþ2ø›¡Y\À¶Ñù×íä¹µBa…K6;Wô‡~ÉO¤6<çÃÙvKE ¸Ìu~fÒK’ =6ÝšªÝÕ­®Ÿ œý!8 'ÃËVu8&ܧì¨ÓI+¶åRnÉ-]ã¢ÿÉ~Uñ_íßÿ¾øxk߶ׇ> _ù¯öGÀÿxâmÞõ„̪·ÒüWm²B¥D¬R ÿ)e=?ª¸'ö(U|õxω3ÚÝG—a0PŒmn|Ʀ6R’—3ºŠm5h«;þIŸ}2x3.p§…xG:’å«TÄJNÎ_+-Ü”SÓ™6“ù§Æ_ð[?ø'ƒ\Úx'àíKñ…¢XÈ¿ñžøQ£\1;ßÅ~0ðö¼‚9WæL?!Ü»øSý[Áÿ²èý”å´°¹Ý<Ë5Qk›ëy®6\í[YÒËVÓjü¶QÞ-rÙ?È3ß§°ÆÔÃaÓ¢ãÔ㇣J »¾HOWÚ9i­¡Ê®½ë§o–¼Oÿ ê¶sOÿ {öøá$»±Ô~"ü@ñ/õHÀFV’{Â>° ÒÃn¦ü 09%ªxCèôqà¼E,ÔXe˜ƒ{â¹õ»¬rH $œdóíQÂ*öTT¡J÷å‚TÕý)¨.‹î>SŸb±U劭V2ÄÍ$å9:²²m¥zÒ«³mée¯Í‹¨L‘ x¯d‚ÝFÑmm7Ù-qÛ–Æ u/)ô­=„y¹œ/.í]ýí7øœ_Úy}Ÿ·”aü±Ÿ$ð8ÇðÿWt –Ýæ;˜årO“ÔšÓ–Våå‰Ì§‡MÉ8s=ÝÕߨ¾dßOûíj}œ»Kñ/ÚÐþuø˜y‘ÿ}?ïµ£ÙË´¿ö´?~ædßOûíhörí/Ä=­ç_‡ù‡™÷ÓþûZ=œ»KñkCù×áþaæGýôÿ¾Ög.ÒüCÚÐþuø˜y‘ÿ}?ïµ£ÙË´¿ö´?~ædßOûíhörí/Ä=­ç_‡ù‡™÷ÓþûZ=œ»KñkCù×áþaæGýôÿ¾Ög.ÒüCÚÐþuø˜y‘ÿ}?ïµ£ÙË´¿ö´?~ædßOûíhörí/Ä=­ç_‡ù‡™÷ÓþûZ=œ»KñkCù×áþaæGýôÿ¾Ög.ÒüCÚÐþuø˜y‘ÿ}?ïµ£ÙË´¿ö´?~ædßOûíhörí/Ä=­ç_‡ù‡™÷ÓþûZ=œ»KñkCù×áþaæGýôÿ¾Ög.ÒüCÚÐþuø˜y‘ÿ}?ïµ£ÙË´¿ö´?~ædßOûíhörí/Ä=­ç_‡ù‡™÷ÓþûZ=œ»KñkCù×áþaæGýôÿ¾Ög.ÒüCÚÐþuø˜y‘ÿ}?ïµ£ÙË´¿ö´?~ædßOûíhörí/Ä=­ç_‡ù‡™÷ÓþûZ=œ»KñkCù×áþaæGýôÿ¾Ög.ÒüCÚÐþuø˜y‘ÿ}?ïµ£ÙË´¿ö´?~ædßOûíhörí/Ä=­ç_‡ù‡™÷ÓþûZ=œ»KñkCù×áþaæGýôÿ¾Ög.ÒüCÚÐþuø˜y‘ÿ}?ïµ£ÙË´¿ö´?~ædßOûíhörí/Ä=­ç_‡ù‡™÷ÓþûZ=œ»KñkCù×áþaæGýôÿ¾Ög.ÒüCÚÐþuø˜y‘ÿ}?ïµ£ÙË´¿ö´?~ædßOûíhörí/Ä=­ç_‡ù‡™÷ÓþûZ=œ»KñkCù×áþaæGýôÿ¾Ög.ÒüCÚÐþuø˜y‘ÿ}?ïµ£ÙË´¿ö´?~æÿ×þì¿á_øÃ63è^ðÞ›†\3“bTå^G.þÚ²z¨™ù‘âÏ7Æg–÷âwÄÏÚ/ÅÍxÓÉqgûSþÒ°i}¥ñ"üS½Ô¤•dšMFïÆÓÞÉ2°;9a^å_¥¿ôãì!ÐTyšåY^P•»[ê·‘ò•>Žþâñ/ˆÊªKýþo®æ ó_âÓµÑ}ƃþÅ?³{æ7ð_ˆž5,oñcã F¿s¢î}?JçKb¯ã ¿î•“ÿó¿ôÿм ð¾iBx K…¶y†bÿ÷oôÿƒ\~Ãÿ³0éà=l}>)|\û¾ûzÕÿÄØøõÿCœ7þ²þa2§à/…OþeÕ¶ÿ ìÃÿš¿¯¼_øbÙ£þ„MsÿŸÅÏþo«oøšÿès†ÿÃ^QÿÌ#ÿˆ áWý «ÿávcÿÍaÿ Aû4Љ®áÓø¹ÿÍõñ5þ<ÿÐç ÿ†¼£ÿ˜Cþ '…_ô.¯ÿ…Ùÿ5‡ü1ìÑÿB&¹ÿ‡Oâçÿ7ÔÄ×øóÿCœ7þòþaø€žк¿þf?üÖðijGýšçþ?‹ŸüßQÿ_ãÏýpßøkÊ?ù„?âxUÿBêÿø]˜ÿóXÃ~Íô"kŸøtþ.ó}GüM?ô9Ãá¯(ÿæÿˆ áWý «ÿávcÿÍaÿ Aû4Љ®áÓø¹ÿÍõñ5þ<ÿÐç ÿ†¼£ÿ˜Cþ '…_ô.¯ÿ…Ùÿ5‡ü1ìÑÿB&¹ÿ‡Oâçÿ7ÔÄ×øóÿCœ7þòþaø€žк¿þf?üÖðijGýšçþ?‹ŸüßQÿ_ãÏýpßøkÊ?ù„?âxUÿBêÿø]˜ÿóXÃ~Íô"kŸøtþ.ó}GüM?ô9Ãá¯(ÿæÿˆ áWý «ÿávcÿÍaÿ Aû4Љ®áÓø¹ÿÍõñ5þ<ÿÐç ÿ†¼£ÿ˜Cþ '…_ô.¯ÿ…Ùÿ5‡ü1ìÑÿB&¹ÿ‡Oâçÿ7ÔÄ×øóÿCœ7þòþaø€žк¿þf?üÖðijGýšçþ?‹ŸüßQÿ_ãÏýpßøkÊ?ù„?âxUÿBêÿø]˜ÿóXÃ~Íô"kŸøtþ.ó}GüM?ô9Ãá¯(ÿæÿˆ áWý «ÿávcÿÍaÿ Aû4Љ®áÓø¹ÿÍõñ5þ<ÿÐç ÿ†¼£ÿ˜Cþ '…_ô.¯ÿ…Ùÿ5‡ü1ìÑÿB&¹ÿ‡Oâçÿ7ÔÄ×øóÿCœ7þòþaø€žк¿þf?üÖðijGýšçþ?‹ŸüßQÿ_ãÏýpßøkÊ?ù„?âxUÿBêÿø]˜ÿóXÃ~Íô"kŸøtþ.ó}GüM?ô9Ãá¯(ÿæÿˆ áWý «ÿávcÿÍaÿ Aû4Љ®áÓø¹ÿÍõñ5þ<ÿÐç ÿ†¼£ÿ˜Cþ '…_ô.¯ÿ…Ùÿ5‡ü1ìÑÿB&¹ÿ‡Oâçÿ7ÔÄ×øóÿCœ7þòþaø€žк¿þf?üÖðijGýšçþ?‹ŸüßQÿ_ãÏýpßøkÊ?ù„?âxUÿBêÿø]˜ÿóXÃ~Íô"kŸøtþ.ó}GüM?ô9Ãá¯(ÿæÿˆ áWý «ÿávcÿÍaÿ Aû4Љ®áÓø¹ÿÍõñ5þ<ÿÐç ÿ†¼£ÿ˜Cþ '…_ô.¯ÿ…Ùÿ5‡ü1ìÑÿB&¹ÿ‡Oâçÿ7ÔÄ×øóÿCœ7þòþaø€žк¿þf?üÖðijGýšçþ?‹ŸüßQÿ_ãÏýpßøkÊ?ù„?âxUÿBêÿø]˜ÿóXÃ~Íô"kŸøtþ.ó}GüM?ô9Ãá¯(ÿæÿˆ áWý «ÿávcÿÍaÿ Aû4Љ®áÓø¹ÿÍõñ5þ<ÿÐç ÿ†¼£ÿ˜Cþ '…_ô.¯ÿ…Ùÿ5‡ü1ìÑÿB&¹ÿ‡Oâçÿ7ÔÄ×øóÿCœ7þòþaø€žк¿þf?üÖðijGýšçþ?‹ŸüßQÿ_ãÏýpßøkÊ?ù„?âxUÿBêÿø]˜ÿóXÃ~Íô"kŸøtþ.ó}GüM?ô9Ãá¯(ÿæÿˆ áWý «ÿávcÿÍaÿ Aû4Љ®áÓø¹ÿÍõñ5þ<ÿÐç ÿ†¼£ÿ˜Cþ '…_ô.¯ÿ…Ùÿ5‡ü1ìÑÿB&¹ÿ‡Oâçÿ7ÔÄ×øóÿCœ7þòþaø€žк¿þf?üÖðijGýšçþ?‹ŸüßQÿ_ãÏýpßøkÊ?ù„?âxUÿBêÿø]˜ÿóXÃ~Íô"kŸøtþ.ó}GüM?ô9Ãá¯(ÿæÿˆ áWý «ÿávcÿÍaÿ Aû4Љ®áÓø¹ÿÍõñ5þ<ÿÐç ÿ†¼£ÿ˜Cþ '…_ô.¯ÿ…Ùÿ5‡ü1ìÑÿB&¹ÿ‡Oâçÿ7ÔÄ×øóÿCœ7þòþaø€žк¿þf?üÖðijGýšçþ?‹ŸüßQÿ_ãÏýpßøkÊ?ù„?âxUÿBêÿø]˜ÿóXÃ~Íô"kŸøtþ.ó}GüM?ô9Ãá¯(ÿæÿˆ áWý «ÿávcÿÍaÿ Aû4Љ®áÓø¹ÿÍõñ5þ<ÿÐç ÿ†¼£ÿ˜Cþ '…_ô.¯ÿ…Ùÿ5‡ü1ìÑÿB&¹ÿ‡Oâçÿ7ÔÄ×øóÿCœ7þòþaø€žк¿þf?üÖðijGýšçþ?‹ŸüßQÿ_ãÏýpßøkÊ?ù„?âxUÿBêÿø]˜ÿóXÃ~Íô"kŸøtþ.ó}GüM?ô9Ãá¯(ÿæÿˆ áWý «ÿávcÿÍaÿ Aû4Љ®áÓø¹ÿÍõñ5þ<ÿÐç ÿ†¼£ÿ˜Cþ '…_ô.¯ÿ…Ùÿ5‡ü1ìÑÿB&¹ÿ‡Oâçÿ7ÔÄ×øóÿCœ7þòþaø€žк¿þf?üÖðijGýšçþ?‹ŸüßQÿ_ãÏýpßøkÊ?ù„?âxUÿBêÿø]˜ÿóYÿÙgolang-set-2.6.0/set.go000066400000000000000000000203441454262171600147140ustar00rootroot00000000000000/* Open Source Initiative OSI - The MIT License (MIT):Licensing The MIT License (MIT) Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) 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 mapset implements a simple and set collection. // Items stored within it are unordered and unique. It supports // typical set operations: membership testing, intersection, union, // difference, symmetric difference and cloning. // // Package mapset provides two implementations of the Set // interface. The default implementation is safe for concurrent // access, but a non-thread-safe implementation is also provided for // programs that can benefit from the slight speed improvement and // that can enforce mutual exclusion through other means. package mapset // Set is the primary interface provided by the mapset package. It // represents an unordered set of data and a large number of // operations that can be applied to that set. type Set[T comparable] interface { // Add adds an element to the set. Returns whether // the item was added. Add(val T) bool // Append multiple elements to the set. Returns // the number of elements added. Append(val ...T) int // Cardinality returns the number of elements in the set. Cardinality() int // Clear removes all elements from the set, leaving // the empty set. Clear() // Clone returns a clone of the set using the same // implementation, duplicating all keys. Clone() Set[T] // Contains returns whether the given items // are all in the set. Contains(val ...T) bool // ContainsOne returns whether the given item // is in the set. // // Contains may cause the argument to escape to the heap. // See: https://github.com/deckarep/golang-set/issues/118 ContainsOne(val T) bool // ContainsAny returns whether at least one of the // given items are in the set. ContainsAny(val ...T) bool // Difference returns the difference between this set // and other. The returned set will contain // all elements of this set that are not also // elements of other. // // Note that the argument to Difference // must be of the same type as the receiver // of the method. Otherwise, Difference will // panic. Difference(other Set[T]) Set[T] // Equal determines if two sets are equal to each // other. If they have the same cardinality // and contain the same elements, they are // considered equal. The order in which // the elements were added is irrelevant. // // Note that the argument to Equal must be // of the same type as the receiver of the // method. Otherwise, Equal will panic. Equal(other Set[T]) bool // Intersect returns a new set containing only the elements // that exist only in both sets. // // Note that the argument to Intersect // must be of the same type as the receiver // of the method. Otherwise, Intersect will // panic. Intersect(other Set[T]) Set[T] // IsEmpty determines if there are elements in the set. IsEmpty() bool // IsProperSubset determines if every element in this set is in // the other set but the two sets are not equal. // // Note that the argument to IsProperSubset // must be of the same type as the receiver // of the method. Otherwise, IsProperSubset // will panic. IsProperSubset(other Set[T]) bool // IsProperSuperset determines if every element in the other set // is in this set but the two sets are not // equal. // // Note that the argument to IsSuperset // must be of the same type as the receiver // of the method. Otherwise, IsSuperset will // panic. IsProperSuperset(other Set[T]) bool // IsSubset determines if every element in this set is in // the other set. // // Note that the argument to IsSubset // must be of the same type as the receiver // of the method. Otherwise, IsSubset will // panic. IsSubset(other Set[T]) bool // IsSuperset determines if every element in the other set // is in this set. // // Note that the argument to IsSuperset // must be of the same type as the receiver // of the method. Otherwise, IsSuperset will // panic. IsSuperset(other Set[T]) bool // Each iterates over elements and executes the passed func against each element. // If passed func returns true, stop iteration at the time. Each(func(T) bool) // Iter returns a channel of elements that you can // range over. Iter() <-chan T // Iterator returns an Iterator object that you can // use to range over the set. Iterator() *Iterator[T] // Remove removes a single element from the set. Remove(i T) // RemoveAll removes multiple elements from the set. RemoveAll(i ...T) // String provides a convenient string representation // of the current state of the set. String() string // SymmetricDifference returns a new set with all elements which are // in either this set or the other set but not in both. // // Note that the argument to SymmetricDifference // must be of the same type as the receiver // of the method. Otherwise, SymmetricDifference // will panic. SymmetricDifference(other Set[T]) Set[T] // Union returns a new set with all elements in both sets. // // Note that the argument to Union must be of the // same type as the receiver of the method. // Otherwise, Union will panic. Union(other Set[T]) Set[T] // Pop removes and returns an arbitrary item from the set. Pop() (T, bool) // ToSlice returns the members of the set as a slice. ToSlice() []T // MarshalJSON will marshal the set into a JSON-based representation. MarshalJSON() ([]byte, error) // UnmarshalJSON will unmarshal a JSON-based byte slice into a full Set datastructure. // For this to work, set subtypes must implemented the Marshal/Unmarshal interface. UnmarshalJSON(b []byte) error } // NewSet creates and returns a new set with the given elements. // Operations on the resulting set are thread-safe. func NewSet[T comparable](vals ...T) Set[T] { s := newThreadSafeSetWithSize[T](len(vals)) for _, item := range vals { s.Add(item) } return s } // NewSetWithSize creates and returns a reference to an empty set with a specified // capacity. Operations on the resulting set are thread-safe. func NewSetWithSize[T comparable](cardinality int) Set[T] { s := newThreadSafeSetWithSize[T](cardinality) return s } // NewThreadUnsafeSet creates and returns a new set with the given elements. // Operations on the resulting set are not thread-safe. func NewThreadUnsafeSet[T comparable](vals ...T) Set[T] { s := newThreadUnsafeSetWithSize[T](len(vals)) for _, item := range vals { s.Add(item) } return s } // NewThreadUnsafeSetWithSize creates and returns a reference to an empty set with // a specified capacity. Operations on the resulting set are not thread-safe. func NewThreadUnsafeSetWithSize[T comparable](cardinality int) Set[T] { s := newThreadUnsafeSetWithSize[T](cardinality) return s } // NewSetFromMapKeys creates and returns a new set with the given keys of the map. // Operations on the resulting set are thread-safe. func NewSetFromMapKeys[T comparable, V any](val map[T]V) Set[T] { s := NewSetWithSize[T](len(val)) for k := range val { s.Add(k) } return s } // NewThreadUnsafeSetFromMapKeys creates and returns a new set with the given keys of the map. // Operations on the resulting set are not thread-safe. func NewThreadUnsafeSetFromMapKeys[T comparable, V any](val map[T]V) Set[T] { s := NewThreadUnsafeSetWithSize[T](len(val)) for k := range val { s.Add(k) } return s } golang-set-2.6.0/set_test.go000066400000000000000000000663441454262171600157650ustar00rootroot00000000000000/* Open Source Initiative OSI - The MIT License (MIT):Licensing The MIT License (MIT) Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) 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 mapset import ( "testing" ) func makeSetInt(ints []int) Set[int] { s := NewSet[int]() for _, i := range ints { s.Add(i) } return s } func makeUnsafeSetInt(ints []int) Set[int] { s := NewThreadUnsafeSet[int]() for _, i := range ints { s.Add(i) } return s } func makeSetIntWithAppend(ints ...int) Set[int] { s := NewSet[int]() s.Append(ints...) return s } func makeUnsafeSetIntWithAppend(ints ...int) Set[int] { s := NewThreadUnsafeSet[int]() s.Append(ints...) return s } func assertEqual[T comparable](a, b Set[T], t *testing.T) { if !a.Equal(b) { t.Errorf("%v != %v\n", a, b) } } func Test_NewSet(t *testing.T) { a := NewSet[int]() if a.Cardinality() != 0 { t.Error("NewSet should start out as an empty set") } assertEqual(NewSet([]int{}...), NewSet[int](), t) assertEqual(NewSet([]int{1}...), NewSet(1), t) assertEqual(NewSet([]int{1, 2}...), NewSet(1, 2), t) assertEqual(NewSet([]string{"a"}...), NewSet("a"), t) assertEqual(NewSet([]string{"a", "b"}...), NewSet("a", "b"), t) } func Test_NewUnsafeSet(t *testing.T) { a := NewThreadUnsafeSet[int]() if a.Cardinality() != 0 { t.Error("NewSet should start out as an empty set") } } func Test_AddSet(t *testing.T) { a := makeSetInt([]int{1, 2, 3}) if a.Cardinality() != 3 { t.Error("AddSet does not have a size of 3 even though 3 items were added to a new set") } } func Test_AddUnsafeSet(t *testing.T) { a := makeUnsafeSetInt([]int{1, 2, 3}) if a.Cardinality() != 3 { t.Error("AddSet does not have a size of 3 even though 3 items were added to a new set") } } func Test_AppendSet(t *testing.T) { a := makeSetIntWithAppend(1, 2, 3) if a.Cardinality() != 3 { t.Error("AppendSet does not have a size of 3 even though 3 items were added to a new set") } } func Test_AppendUnsafeSet(t *testing.T) { a := makeUnsafeSetIntWithAppend(1, 2, 3) if a.Cardinality() != 3 { t.Error("AppendSet does not have a size of 3 even though 3 items were added to a new set") } } func Test_AddSetNoDuplicate(t *testing.T) { a := makeSetInt([]int{7, 5, 3, 7}) if a.Cardinality() != 3 { t.Error("AddSetNoDuplicate set should have 3 elements since 7 is a duplicate") } if !(a.Contains(7) && a.Contains(5) && a.Contains(3)) { t.Error("AddSetNoDuplicate set should have a 7, 5, and 3 in it.") } } func Test_AddUnsafeSetNoDuplicate(t *testing.T) { a := makeUnsafeSetInt([]int{7, 5, 3, 7}) if a.Cardinality() != 3 { t.Error("AddSetNoDuplicate set should have 3 elements since 7 is a duplicate") } if !(a.Contains(7) && a.Contains(5) && a.Contains(3)) { t.Error("AddSetNoDuplicate set should have a 7, 5, and 3 in it.") } } func Test_AppendSetNoDuplicate(t *testing.T) { a := makeSetIntWithAppend(7, 5, 3, 7) if a.Cardinality() != 3 { t.Error("AppendSetNoDuplicate set should have 3 elements since 7 is a duplicate") } if !(a.Contains(7) && a.Contains(5) && a.Contains(3)) { t.Error("AppendSetNoDuplicate set should have a 7, 5, and 3 in it.") } } func Test_AppendUnsafeSetNoDuplicate(t *testing.T) { a := makeUnsafeSetIntWithAppend(7, 5, 3, 7) if a.Cardinality() != 3 { t.Error("AppendSetNoDuplicate set should have 3 elements since 7 is a duplicate") } if !(a.Contains(7) && a.Contains(5) && a.Contains(3)) { t.Error("AppendSetNoDuplicate set should have a 7, 5, and 3 in it.") } } func Test_RemoveSet(t *testing.T) { a := makeSetInt([]int{6, 3, 1}) a.Remove(3) if a.Cardinality() != 2 { t.Error("RemoveSet should only have 2 items in the set") } if !(a.Contains(6) && a.Contains(1)) { t.Error("RemoveSet should have only items 6 and 1 in the set") } a.Remove(6) a.Remove(1) if a.Cardinality() != 0 { t.Error("RemoveSet should be an empty set after removing 6 and 1") } } func Test_RemoveAllSet(t *testing.T) { a := makeSetInt([]int{6, 3, 1, 8, 9}) a.RemoveAll(3, 1) if a.Cardinality() != 3 { t.Error("RemoveAll should only have 2 items in the set") } if !a.Contains(6, 8, 9) { t.Error("RemoveAll should have only items (6,8,9) in the set") } a.RemoveAll(6, 8, 9) if a.Cardinality() != 0 { t.Error("RemoveSet should be an empty set after removing 6 and 1") } } func Test_RemoveUnsafeSet(t *testing.T) { a := makeUnsafeSetInt([]int{6, 3, 1}) a.Remove(3) if a.Cardinality() != 2 { t.Error("RemoveSet should only have 2 items in the set") } if !(a.Contains(6) && a.Contains(1)) { t.Error("RemoveSet should have only items 6 and 1 in the set") } a.Remove(6) a.Remove(1) if a.Cardinality() != 0 { t.Error("RemoveSet should be an empty set after removing 6 and 1") } } func Test_RemoveAllUnsafeSet(t *testing.T) { a := makeUnsafeSetInt([]int{6, 3, 1, 8, 9}) a.RemoveAll(3, 1) if a.Cardinality() != 3 { t.Error("RemoveAll should only have 2 items in the set") } if !a.Contains(6, 8, 9) { t.Error("RemoveAll should have only items (6,8,9) in the set") } a.RemoveAll(6, 8, 9) if a.Cardinality() != 0 { t.Error("RemoveSet should be an empty set after removing 6 and 1") } } func Test_ContainsSet(t *testing.T) { a := NewSet[int]() a.Add(71) if !a.Contains(71) { t.Error("ContainsSet should contain 71") } a.Remove(71) if a.Contains(71) { t.Error("ContainsSet should not contain 71") } a.Add(13) a.Add(7) a.Add(1) if !(a.Contains(13) && a.Contains(7) && a.Contains(1)) { t.Error("ContainsSet should contain 13, 7, 1") } } func Test_ContainsUnsafeSet(t *testing.T) { a := NewThreadUnsafeSet[int]() a.Add(71) if !a.Contains(71) { t.Error("ContainsSet should contain 71") } a.Remove(71) if a.Contains(71) { t.Error("ContainsSet should not contain 71") } a.Add(13) a.Add(7) a.Add(1) if !(a.Contains(13) && a.Contains(7) && a.Contains(1)) { t.Error("ContainsSet should contain 13, 7, 1") } } func Test_ContainsMultipleSet(t *testing.T) { a := makeSetInt([]int{8, 6, 7, 5, 3, 0, 9}) if !a.Contains(8, 6, 7, 5, 3, 0, 9) { t.Error("ContainsAll should contain Jenny's phone number") } if a.Contains(8, 6, 11, 5, 3, 0, 9) { t.Error("ContainsAll should not have all of these numbers") } } func Test_ContainsMultipleUnsafeSet(t *testing.T) { a := makeUnsafeSetInt([]int{8, 6, 7, 5, 3, 0, 9}) if !a.Contains(8, 6, 7, 5, 3, 0, 9) { t.Error("ContainsAll should contain Jenny's phone number") } if a.Contains(8, 6, 11, 5, 3, 0, 9) { t.Error("ContainsAll should not have all of these numbers") } } func Test_ContainsOneSet(t *testing.T) { a := NewSet[int]() a.Add(71) if !a.ContainsOne(71) { t.Error("ContainsSet should contain 71") } a.Remove(71) if a.ContainsOne(71) { t.Error("ContainsSet should not contain 71") } a.Add(13) a.Add(7) a.Add(1) if !(a.ContainsOne(13) && a.ContainsOne(7) && a.ContainsOne(1)) { t.Error("ContainsSet should contain 13, 7, 1") } } func Test_ContainsOneUnsafeSet(t *testing.T) { a := NewThreadUnsafeSet[int]() a.Add(71) if !a.ContainsOne(71) { t.Error("ContainsSet should contain 71") } a.Remove(71) if a.ContainsOne(71) { t.Error("ContainsSet should not contain 71") } a.Add(13) a.Add(7) a.Add(1) if !(a.ContainsOne(13) && a.ContainsOne(7) && a.ContainsOne(1)) { t.Error("ContainsSet should contain 13, 7, 1") } } func Test_ContainsAnySet(t *testing.T) { a := NewSet[int]() a.Add(71) if !a.ContainsAny(71) { t.Error("ContainsSet should contain 71") } if !a.ContainsAny(71, 10) { t.Error("ContainsSet should contain 71 or 10") } a.Remove(71) if a.ContainsAny(71) { t.Error("ContainsSet should not contain 71") } if a.ContainsAny(71, 10) { t.Error("ContainsSet should not contain 71 or 10") } a.Add(13) a.Add(7) a.Add(1) if !(a.ContainsAny(13, 17, 10)) { t.Error("ContainsSet should contain 13, 17, or 10") } } func Test_ClearSet(t *testing.T) { a := makeSetInt([]int{2, 5, 9, 10}) a.Clear() if a.Cardinality() != 0 { t.Error("ClearSet should be an empty set") } } func Test_ClearUnsafeSet(t *testing.T) { a := makeUnsafeSetInt([]int{2, 5, 9, 10}) a.Clear() if a.Cardinality() != 0 { t.Error("ClearSet should be an empty set") } } func Test_CardinalitySet(t *testing.T) { a := NewSet[int]() if a.Cardinality() != 0 { t.Error("set should be an empty set") } a.Add(1) if a.Cardinality() != 1 { t.Error("set should have a size of 1") } a.Remove(1) if a.Cardinality() != 0 { t.Error("set should be an empty set") } a.Add(9) if a.Cardinality() != 1 { t.Error("set should have a size of 1") } a.Clear() if a.Cardinality() != 0 { t.Error("set should have a size of 1") } } func Test_CardinalityUnsafeSet(t *testing.T) { a := NewThreadUnsafeSet[int]() if a.Cardinality() != 0 { t.Error("set should be an empty set") } a.Add(1) if a.Cardinality() != 1 { t.Error("set should have a size of 1") } a.Remove(1) if a.Cardinality() != 0 { t.Error("set should be an empty set") } a.Add(9) if a.Cardinality() != 1 { t.Error("set should have a size of 1") } a.Clear() if a.Cardinality() != 0 { t.Error("set should have a size of 1") } } func Test_SetIsSubset(t *testing.T) { a := makeSetInt([]int{1, 2, 3, 5, 7}) b := NewSet[int]() b.Add(3) b.Add(5) b.Add(7) if !b.IsSubset(a) { t.Error("set b should be a subset of set a") } b.Add(72) if b.IsSubset(a) { t.Error("set b should not be a subset of set a because it contains 72 which is not in the set of a") } } func Test_SetIsProperSubset(t *testing.T) { a := makeSetInt([]int{1, 2, 3, 5, 7}) b := makeSetInt([]int{7, 5, 3, 2, 1}) if !a.IsSubset(b) { t.Error("set a should be a subset of set b") } if a.IsProperSubset(b) { t.Error("set a should not be a proper subset of set b (they're equal)") } b.Add(72) if !a.IsSubset(b) { t.Error("set a should be a subset of set b") } if !a.IsProperSubset(b) { t.Error("set a should be a proper subset of set b") } } func Test_UnsafeSetIsSubset(t *testing.T) { a := makeUnsafeSetInt([]int{1, 2, 3, 5, 7}) b := NewThreadUnsafeSet[int]() b.Add(3) b.Add(5) b.Add(7) if !b.IsSubset(a) { t.Error("set b should be a subset of set a") } b.Add(72) if b.IsSubset(a) { t.Error("set b should not be a subset of set a because it contains 72 which is not in the set of a") } } func Test_UnsafeSetIsProperSubset(t *testing.T) { a := makeUnsafeSetInt([]int{1, 2, 3, 5, 7}) b := NewThreadUnsafeSet[int]() b.Add(7) b.Add(1) b.Add(5) b.Add(3) b.Add(2) if !a.IsSubset(b) { t.Error("set a should be a subset of set b") } if a.IsProperSubset(b) { t.Error("set a should not be a proper subset of set b (they're equal)") } b.Add(72) if !a.IsSubset(b) { t.Error("set a should be a subset of set b") } if !a.IsProperSubset(b) { t.Error("set a should be a proper subset of set b because set b has 72") } } func Test_SetIsSuperset(t *testing.T) { a := NewSet[int]() a.Add(9) a.Add(5) a.Add(2) a.Add(1) a.Add(11) b := NewSet[int]() b.Add(5) b.Add(2) b.Add(11) if !a.IsSuperset(b) { t.Error("set a should be a superset of set b") } b.Add(42) if a.IsSuperset(b) { t.Error("set a should not be a superset of set b because set b has a 42") } } func Test_SetIsProperSuperset(t *testing.T) { a := NewSet[int]() a.Add(5) a.Add(2) a.Add(11) b := NewSet[int]() b.Add(2) b.Add(5) b.Add(11) if !a.IsSuperset(b) { t.Error("set a should be a superset of set b") } if a.IsProperSuperset(b) { t.Error("set a should not be a proper superset of set b (they're equal)") } a.Add(9) if !a.IsSuperset(b) { t.Error("set a should be a superset of set b") } if !a.IsProperSuperset(b) { t.Error("set a not be a proper superset of set b because set a has a 9") } b.Add(42) if a.IsSuperset(b) { t.Error("set a should not be a superset of set b because set b has a 42") } if a.IsProperSuperset(b) { t.Error("set a should not be a proper superset of set b because set b has a 42") } } func Test_UnsafeSetIsSuperset(t *testing.T) { a := NewThreadUnsafeSet[int]() a.Add(9) a.Add(5) a.Add(2) a.Add(1) a.Add(11) b := NewThreadUnsafeSet[int]() b.Add(5) b.Add(2) b.Add(11) if !a.IsSuperset(b) { t.Error("set a should be a superset of set b") } b.Add(42) if a.IsSuperset(b) { t.Error("set a should not be a superset of set b because set a has a 42") } } func Test_UnsafeSetIsProperSuperset(t *testing.T) { a := NewThreadUnsafeSet[int]() a.Add(5) a.Add(2) a.Add(11) b := NewThreadUnsafeSet[int]() b.Add(2) b.Add(5) b.Add(11) if !a.IsSuperset(b) { t.Error("set a should be a superset of set b") } if a.IsProperSuperset(b) { t.Error("set a should not be a proper superset of set b (they're equal)") } a.Add(9) if !a.IsSuperset(b) { t.Error("set a should be a superset of set b") } if !a.IsProperSuperset(b) { t.Error("set a not be a proper superset of set b because set a has a 9") } b.Add(42) if a.IsSuperset(b) { t.Error("set a should not be a superset of set b because set b has a 42") } if a.IsProperSuperset(b) { t.Error("set a should not be a proper superset of set b because set b has a 42") } } func Test_SetUnion(t *testing.T) { a := NewSet[int]() b := NewSet[int]() b.Add(1) b.Add(2) b.Add(3) b.Add(4) b.Add(5) c := a.Union(b) if c.Cardinality() != 5 { t.Error("set c is unioned with an empty set and therefore should have 5 elements in it") } d := NewSet[int]() d.Add(10) d.Add(14) d.Add(0) e := c.Union(d) if e.Cardinality() != 8 { t.Error("set e should have 8 elements in it after being unioned with set c to d") } f := NewSet[int]() f.Add(14) f.Add(3) g := f.Union(e) if g.Cardinality() != 8 { t.Error("set g should still have 8 elements in it after being unioned with set f that has duplicates") } } func Test_UnsafeSetUnion(t *testing.T) { a := NewThreadUnsafeSet[int]() b := NewThreadUnsafeSet[int]() b.Add(1) b.Add(2) b.Add(3) b.Add(4) b.Add(5) c := a.Union(b) if c.Cardinality() != 5 { t.Error("set c is unioned with an empty set and therefore should have 5 elements in it") } d := NewThreadUnsafeSet[int]() d.Add(10) d.Add(14) d.Add(0) e := c.Union(d) if e.Cardinality() != 8 { t.Error("set e should have 8 elements in it after being unioned with set c to d") } f := NewThreadUnsafeSet[int]() f.Add(14) f.Add(3) g := f.Union(e) if g.Cardinality() != 8 { t.Error("set g should still have 8 elements in it after being unioned with set f that has duplicates") } } func Test_SetIntersect(t *testing.T) { a := NewSet[int]() a.Add(1) a.Add(3) a.Add(5) b := NewSet[int]() a.Add(2) a.Add(4) a.Add(6) c := a.Intersect(b) if c.Cardinality() != 0 { t.Error("set c should be the empty set because there is no common items to intersect") } a.Add(10) b.Add(10) d := a.Intersect(b) if !(d.Cardinality() == 1 && d.Contains(10)) { t.Error("set d should have a size of 1 and contain the item 10") } } func Test_UnsafeSetIntersect(t *testing.T) { a := NewThreadUnsafeSet[int]() a.Add(1) a.Add(3) a.Add(5) b := NewThreadUnsafeSet[int]() a.Add(2) a.Add(4) a.Add(6) c := a.Intersect(b) if c.Cardinality() != 0 { t.Error("set c should be the empty set because there is no common items to intersect") } a.Add(10) b.Add(10) d := a.Intersect(b) if !(d.Cardinality() == 1 && d.Contains(10)) { t.Error("set d should have a size of 1 and contain the item 10") } } func Test_SetDifference(t *testing.T) { a := NewSet[int]() a.Add(1) a.Add(2) a.Add(3) b := NewSet[int]() b.Add(1) b.Add(3) b.Add(4) b.Add(5) b.Add(6) b.Add(99) c := a.Difference(b) if !(c.Cardinality() == 1 && c.Contains(2)) { t.Error("the difference of set a to b is the set of 1 item: 2") } } func Test_UnsafeSetDifference(t *testing.T) { a := NewThreadUnsafeSet[int]() a.Add(1) a.Add(2) a.Add(3) b := NewThreadUnsafeSet[int]() b.Add(1) b.Add(3) b.Add(4) b.Add(5) b.Add(6) b.Add(99) c := a.Difference(b) if !(c.Cardinality() == 1 && c.Contains(2)) { t.Error("the difference of set a to b is the set of 1 item: 2") } } func Test_SetSymmetricDifference(t *testing.T) { a := NewSet[int]() a.Add(1) a.Add(2) a.Add(3) a.Add(45) b := NewSet[int]() b.Add(1) b.Add(3) b.Add(4) b.Add(5) b.Add(6) b.Add(99) c := a.SymmetricDifference(b) if !(c.Cardinality() == 6 && c.Contains(2) && c.Contains(45) && c.Contains(4) && c.Contains(5) && c.Contains(6) && c.Contains(99)) { t.Error("the symmetric difference of set a to b is the set of 6 items: 2, 45, 4, 5, 6, 99") } } func Test_UnsafeSetSymmetricDifference(t *testing.T) { a := NewThreadUnsafeSet[int]() a.Add(1) a.Add(2) a.Add(3) a.Add(45) b := NewThreadUnsafeSet[int]() b.Add(1) b.Add(3) b.Add(4) b.Add(5) b.Add(6) b.Add(99) c := a.SymmetricDifference(b) if !(c.Cardinality() == 6 && c.Contains(2) && c.Contains(45) && c.Contains(4) && c.Contains(5) && c.Contains(6) && c.Contains(99)) { t.Error("the symmetric difference of set a to b is the set of 6 items: 2, 45, 4, 5, 6, 99") } } func Test_SetEqual(t *testing.T) { a := NewSet[int]() b := NewSet[int]() if !a.Equal(b) { t.Error("Both a and b are empty sets, and should be equal") } a.Add(10) if a.Equal(b) { t.Error("a should not be equal to b because b is empty and a has item 1 in it") } b.Add(10) if !a.Equal(b) { t.Error("a is now equal again to b because both have the item 10 in them") } b.Add(8) b.Add(3) b.Add(47) if a.Equal(b) { t.Error("b has 3 more elements in it so therefore should not be equal to a") } a.Add(8) a.Add(3) a.Add(47) if !a.Equal(b) { t.Error("a and b should be equal with the same number of elements") } } func Test_UnsafeSetEqual(t *testing.T) { a := NewThreadUnsafeSet[int]() b := NewThreadUnsafeSet[int]() if !a.Equal(b) { t.Error("Both a and b are empty sets, and should be equal") } a.Add(10) if a.Equal(b) { t.Error("a should not be equal to b because b is empty and a has item 1 in it") } b.Add(10) if !a.Equal(b) { t.Error("a is now equal again to b because both have the item 10 in them") } b.Add(8) b.Add(3) b.Add(47) if a.Equal(b) { t.Error("b has 3 more elements in it so therefore should not be equal to a") } a.Add(8) a.Add(3) a.Add(47) if !a.Equal(b) { t.Error("a and b should be equal with the same number of elements") } } func Test_SetClone(t *testing.T) { a := NewSet[int]() a.Add(1) a.Add(2) b := a.Clone() if !a.Equal(b) { t.Error("Clones should be equal") } a.Add(3) if a.Equal(b) { t.Error("a contains one more element, they should not be equal") } c := a.Clone() c.Remove(1) if a.Equal(c) { t.Error("C contains one element less, they should not be equal") } } func Test_UnsafeSetClone(t *testing.T) { a := NewThreadUnsafeSet[int]() a.Add(1) a.Add(2) b := a.Clone() if !a.Equal(b) { t.Error("Clones should be equal") } a.Add(3) if a.Equal(b) { t.Error("a contains one more element, they should not be equal") } c := a.Clone() c.Remove(1) if a.Equal(c) { t.Error("C contains one element less, they should not be equal") } } func Test_Each(t *testing.T) { a := NewSet[string]() a.Add("Z") a.Add("Y") a.Add("X") a.Add("W") b := NewSet[string]() a.Each(func(elem string) bool { b.Add(elem) return false }) if !a.Equal(b) { t.Error("The sets are not equal after iterating (Each) through the first set") } var count int a.Each(func(elem string) bool { if count == 2 { return true } count++ return false }) if count != 2 { t.Error("Iteration should stop on the way") } } func Test_Iter(t *testing.T) { a := NewSet[string]() a.Add("Z") a.Add("Y") a.Add("X") a.Add("W") b := NewSet[string]() for val := range a.Iter() { b.Add(val) } if !a.Equal(b) { t.Error("The sets are not equal after iterating (Iter) through the first set") } } func Test_UnsafeIter(t *testing.T) { a := NewThreadUnsafeSet[string]() a.Add("Z") a.Add("Y") a.Add("X") a.Add("W") b := NewThreadUnsafeSet[string]() for val := range a.Iter() { b.Add(val) } if !a.Equal(b) { t.Error("The sets are not equal after iterating (Iter) through the first set") } } func Test_Iterator(t *testing.T) { a := NewSet[string]() a.Add("Z") a.Add("Y") a.Add("X") a.Add("W") b := NewSet[string]() for val := range a.Iterator().C { b.Add(val) } if !a.Equal(b) { t.Error("The sets are not equal after iterating (Iterator) through the first set") } } func Test_UnsafeIterator(t *testing.T) { a := NewThreadUnsafeSet[string]() a.Add("Z") a.Add("Y") a.Add("X") a.Add("W") b := NewThreadUnsafeSet[string]() for val := range a.Iterator().C { b.Add(val) } if !a.Equal(b) { t.Error("The sets are not equal after iterating (Iterator) through the first set") } } func Test_IteratorStop(t *testing.T) { a := NewSet[string]() a.Add("Z") a.Add("Y") a.Add("X") a.Add("W") it := a.Iterator() it.Stop() for range it.C { t.Error("The iterating (Iterator) did not stop after Stop() has been called") } } func Test_PopSafe(t *testing.T) { a := NewSet[string]() a.Add("a") a.Add("b") a.Add("c") a.Add("d") aPop := func() (v string) { v, _ = a.Pop() return } captureSet := NewSet[string]() captureSet.Add(aPop()) captureSet.Add(aPop()) captureSet.Add(aPop()) captureSet.Add(aPop()) finalNil := aPop() if captureSet.Cardinality() != 4 { t.Error("unexpected captureSet cardinality; should be 4") } if a.Cardinality() != 0 { t.Error("unepxected a cardinality; should be zero") } if !captureSet.Contains("c", "a", "d", "b") { t.Error("unexpected result set; should be a,b,c,d (any order is fine") } if finalNil != "" { t.Error("when original set is empty, further pops should result in nil") } } func Test_PopUnsafe(t *testing.T) { a := NewThreadUnsafeSet[string]() a.Add("a") a.Add("b") a.Add("c") a.Add("d") aPop := func() (v string) { v, _ = a.Pop() return } captureSet := NewThreadUnsafeSet[string]() captureSet.Add(aPop()) captureSet.Add(aPop()) captureSet.Add(aPop()) captureSet.Add(aPop()) finalNil := aPop() if captureSet.Cardinality() != 4 { t.Error("unexpected captureSet cardinality; should be 4") } if a.Cardinality() != 0 { t.Error("unepxected a cardinality; should be zero") } if !captureSet.Contains("c", "a", "d", "b") { t.Error("unexpected result set; should be a,b,c,d (any order is fine") } if finalNil != "" { t.Error("when original set is empty, further pops should result in nil") } } func Test_EmptySetProperties(t *testing.T) { empty := NewSet[string]() a := NewSet[string]() a.Add("1") a.Add("foo") a.Add("bar") b := NewSet[string]() b.Add("one") b.Add("two") b.Add("3") b.Add("4") if !empty.IsSubset(a) || !empty.IsSubset(b) { t.Error("The empty set is supposed to be a subset of all sets") } if !a.IsSuperset(empty) || !b.IsSuperset(empty) { t.Error("All sets are supposed to be a superset of the empty set") } if !empty.IsSubset(empty) || !empty.IsSuperset(empty) { t.Error("The empty set is supposed to be a subset and a superset of itself") } c := a.Union(empty) if !c.Equal(a) { t.Error("The union of any set with the empty set is supposed to be equal to itself") } c = a.Intersect(empty) if !c.Equal(empty) { t.Error("The intesection of any set with the empty set is supposed to be the empty set") } if empty.Cardinality() != 0 { t.Error("Cardinality of the empty set is supposed to be zero") } } func Test_ToSliceUnthreadsafe(t *testing.T) { s := makeUnsafeSetInt([]int{1, 2, 3}) setAsSlice := s.ToSlice() if len(setAsSlice) != s.Cardinality() { t.Errorf("Set length is incorrect: %v", len(setAsSlice)) } for _, i := range setAsSlice { if !s.Contains(i) { t.Errorf("Set is missing element: %v", i) } } } func Test_NewSetFromMapKey_Ints(t *testing.T) { m := map[int]int{ 5: 5, 2: 3, } s := NewSetFromMapKeys(m) if len(m) != s.Cardinality() { t.Errorf("Length of Set is not the same as the map. Expected: %d. Actual: %d", len(m), s.Cardinality()) } for k := range m { if !s.Contains(k) { t.Errorf("Element %d not found in map: %v", k, m) } } } func Test_NewSetFromMapKey_Strings(t *testing.T) { m := map[int]int{ 5: 5, 2: 3, } s := NewSetFromMapKeys(m) if len(m) != s.Cardinality() { t.Errorf("Length of Set is not the same as the map. Expected: %d. Actual: %d", len(m), s.Cardinality()) } for k := range m { if !s.Contains(k) { t.Errorf("Element %q not found in map: %v", k, m) } } } func Test_NewThreadUnsafeSetFromMapKey_Ints(t *testing.T) { m := map[int]int{ 5: 5, 2: 3, } s := NewThreadUnsafeSetFromMapKeys(m) if len(m) != s.Cardinality() { t.Errorf("Length of Set is not the same as the map. Expected: %d. Actual: %d", len(m), s.Cardinality()) } for k := range m { if !s.Contains(k) { t.Errorf("Element %d not found in map: %v", k, m) } } } func Test_NewThreadUnsafeSetFromMapKey_Strings(t *testing.T) { m := map[int]int{ 5: 5, 2: 3, } s := NewThreadUnsafeSetFromMapKeys(m) if len(m) != s.Cardinality() { t.Errorf("Length of Set is not the same as the map. Expected: %d. Actual: %d", len(m), s.Cardinality()) } for k := range m { if !s.Contains(k) { t.Errorf("Element %q not found in map: %v", k, m) } } } func Test_Example(t *testing.T) { /* requiredClasses := NewSet() requiredClasses.Add("Cooking") requiredClasses.Add("English") requiredClasses.Add("Math") requiredClasses.Add("Biology") scienceSlice := []interface{}{"Biology", "Chemistry"} scienceClasses := NewSet(scienceSlice) electiveClasses := NewSet() electiveClasses.Add("Welding") electiveClasses.Add("Music") electiveClasses.Add("Automotive") bonusClasses := NewSet() bonusClasses.Add("Go Programming") bonusClasses.Add("Python Programming") //Show me all the available classes I can take allClasses := requiredClasses.Union(scienceClasses).Union(electiveClasses).Union(bonusClasses) fmt.Println(allClasses) //Set{English, Chemistry, Automotive, Cooking, Math, Biology, Welding, Music, Go Programming} //Is cooking considered a science class? fmt.Println(scienceClasses.Contains("Cooking")) //false //Show me all classes that are not science classes, since I hate science. fmt.Println(allClasses.Difference(scienceClasses)) //Set{English, Automotive, Cooking, Math, Welding, Music, Go Programming} //Which science classes are also required classes? fmt.Println(scienceClasses.Intersect(requiredClasses)) //Set{Biology} //How many bonus classes do you offer? fmt.Println(bonusClasses.Cardinality()) //2 //Do you have the following classes? Welding, Automotive and English? fmt.Println(allClasses.ContainsAll("Welding", "Automotive", "English")) */ } golang-set-2.6.0/sorted.go000066400000000000000000000027461454262171600154270ustar00rootroot00000000000000//go:build go1.21 // +build go1.21 /* Open Source Initiative OSI - The MIT License (MIT):Licensing The MIT License (MIT) Copyright (c) 2013 - 2023 Ralph Caraveo (deckarep@gmail.com) 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 mapset import ( "cmp" "slices" ) // Sorted returns a sorted slice of a set of any ordered type in ascending order. // When sorting floating-point numbers, NaNs are ordered before other values. func Sorted[E cmp.Ordered](set Set[E]) []E { s := set.ToSlice() slices.Sort(s) return s } golang-set-2.6.0/sorted_test.go000066400000000000000000000037411454262171600164620ustar00rootroot00000000000000//go:build go1.21 // +build go1.21 /* Open Source Initiative OSI - The MIT License (MIT):Licensing The MIT License (MIT) Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) 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 mapset import ( "testing" ) func Test_Sorted(t *testing.T) { test := func(t *testing.T, ctor func(vals ...string) Set[string]) { set := ctor("apple", "banana", "pear") sorted := Sorted(set) if len(sorted) != set.Cardinality() { t.Errorf("Length of slice is not the same as the set. Expected: %d. Actual: %d", set.Cardinality(), len(sorted)) } if sorted[0] != "apple" { t.Errorf("Element 0 was not equal to apple: %s", sorted[0]) } if sorted[1] != "banana" { t.Errorf("Element 1 was not equal to banana: %s", sorted[1]) } if sorted[2] != "pear" { t.Errorf("Element 2 was not equal to pear: %s", sorted[2]) } } t.Run("Safe", func(t *testing.T) { test(t, NewSet[string]) }) t.Run("Unsafe", func(t *testing.T) { test(t, NewThreadUnsafeSet[string]) }) } golang-set-2.6.0/threadsafe.go000066400000000000000000000133261454262171600162310ustar00rootroot00000000000000/* Open Source Initiative OSI - The MIT License (MIT):Licensing The MIT License (MIT) Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) 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 mapset import "sync" type threadSafeSet[T comparable] struct { sync.RWMutex uss threadUnsafeSet[T] } func newThreadSafeSet[T comparable]() *threadSafeSet[T] { return &threadSafeSet[T]{ uss: newThreadUnsafeSet[T](), } } func newThreadSafeSetWithSize[T comparable](cardinality int) *threadSafeSet[T] { return &threadSafeSet[T]{ uss: newThreadUnsafeSetWithSize[T](cardinality), } } func (t *threadSafeSet[T]) Add(v T) bool { t.Lock() ret := t.uss.Add(v) t.Unlock() return ret } func (t *threadSafeSet[T]) Append(v ...T) int { t.Lock() ret := t.uss.Append(v...) t.Unlock() return ret } func (t *threadSafeSet[T]) Contains(v ...T) bool { t.RLock() ret := t.uss.Contains(v...) t.RUnlock() return ret } func (t *threadSafeSet[T]) ContainsOne(v T) bool { t.RLock() ret := t.uss.ContainsOne(v) t.RUnlock() return ret } func (t *threadSafeSet[T]) ContainsAny(v ...T) bool { t.RLock() ret := t.uss.ContainsAny(v...) t.RUnlock() return ret } func (t *threadSafeSet[T]) IsEmpty() bool { return t.Cardinality() == 0 } func (t *threadSafeSet[T]) IsSubset(other Set[T]) bool { o := other.(*threadSafeSet[T]) t.RLock() o.RLock() ret := t.uss.IsSubset(o.uss) t.RUnlock() o.RUnlock() return ret } func (t *threadSafeSet[T]) IsProperSubset(other Set[T]) bool { o := other.(*threadSafeSet[T]) t.RLock() defer t.RUnlock() o.RLock() defer o.RUnlock() return t.uss.IsProperSubset(o.uss) } func (t *threadSafeSet[T]) IsSuperset(other Set[T]) bool { return other.IsSubset(t) } func (t *threadSafeSet[T]) IsProperSuperset(other Set[T]) bool { return other.IsProperSubset(t) } func (t *threadSafeSet[T]) Union(other Set[T]) Set[T] { o := other.(*threadSafeSet[T]) t.RLock() o.RLock() unsafeUnion := t.uss.Union(o.uss).(threadUnsafeSet[T]) ret := &threadSafeSet[T]{uss: unsafeUnion} t.RUnlock() o.RUnlock() return ret } func (t *threadSafeSet[T]) Intersect(other Set[T]) Set[T] { o := other.(*threadSafeSet[T]) t.RLock() o.RLock() unsafeIntersection := t.uss.Intersect(o.uss).(threadUnsafeSet[T]) ret := &threadSafeSet[T]{uss: unsafeIntersection} t.RUnlock() o.RUnlock() return ret } func (t *threadSafeSet[T]) Difference(other Set[T]) Set[T] { o := other.(*threadSafeSet[T]) t.RLock() o.RLock() unsafeDifference := t.uss.Difference(o.uss).(threadUnsafeSet[T]) ret := &threadSafeSet[T]{uss: unsafeDifference} t.RUnlock() o.RUnlock() return ret } func (t *threadSafeSet[T]) SymmetricDifference(other Set[T]) Set[T] { o := other.(*threadSafeSet[T]) t.RLock() o.RLock() unsafeDifference := t.uss.SymmetricDifference(o.uss).(threadUnsafeSet[T]) ret := &threadSafeSet[T]{uss: unsafeDifference} t.RUnlock() o.RUnlock() return ret } func (t *threadSafeSet[T]) Clear() { t.Lock() t.uss.Clear() t.Unlock() } func (t *threadSafeSet[T]) Remove(v T) { t.Lock() delete(t.uss, v) t.Unlock() } func (t *threadSafeSet[T]) RemoveAll(i ...T) { t.Lock() t.uss.RemoveAll(i...) t.Unlock() } func (t *threadSafeSet[T]) Cardinality() int { t.RLock() defer t.RUnlock() return len(t.uss) } func (t *threadSafeSet[T]) Each(cb func(T) bool) { t.RLock() for elem := range t.uss { if cb(elem) { break } } t.RUnlock() } func (t *threadSafeSet[T]) Iter() <-chan T { ch := make(chan T) go func() { t.RLock() for elem := range t.uss { ch <- elem } close(ch) t.RUnlock() }() return ch } func (t *threadSafeSet[T]) Iterator() *Iterator[T] { iterator, ch, stopCh := newIterator[T]() go func() { t.RLock() L: for elem := range t.uss { select { case <-stopCh: break L case ch <- elem: } } close(ch) t.RUnlock() }() return iterator } func (t *threadSafeSet[T]) Equal(other Set[T]) bool { o := other.(*threadSafeSet[T]) t.RLock() o.RLock() ret := t.uss.Equal(o.uss) t.RUnlock() o.RUnlock() return ret } func (t *threadSafeSet[T]) Clone() Set[T] { t.RLock() unsafeClone := t.uss.Clone().(threadUnsafeSet[T]) ret := &threadSafeSet[T]{uss: unsafeClone} t.RUnlock() return ret } func (t *threadSafeSet[T]) String() string { t.RLock() ret := t.uss.String() t.RUnlock() return ret } func (t *threadSafeSet[T]) Pop() (T, bool) { t.Lock() defer t.Unlock() return t.uss.Pop() } func (t *threadSafeSet[T]) ToSlice() []T { keys := make([]T, 0, t.Cardinality()) t.RLock() for elem := range t.uss { keys = append(keys, elem) } t.RUnlock() return keys } func (t *threadSafeSet[T]) MarshalJSON() ([]byte, error) { t.RLock() b, err := t.uss.MarshalJSON() t.RUnlock() return b, err } func (t *threadSafeSet[T]) UnmarshalJSON(p []byte) error { t.RLock() err := t.uss.UnmarshalJSON(p) t.RUnlock() return err } golang-set-2.6.0/threadsafe_test.go000066400000000000000000000250101454262171600172610ustar00rootroot00000000000000/* Open Source Initiative OSI - The MIT License (MIT):Licensing The MIT License (MIT) Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) 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 mapset import ( "encoding/json" "math/rand" "runtime" "sync" "sync/atomic" "testing" ) const N = 1000 func Test_AddConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s := NewSet[int]() ints := rand.Perm(N) var wg sync.WaitGroup wg.Add(len(ints)) for i := 0; i < len(ints); i++ { go func(i int) { s.Add(i) wg.Done() }(i) } wg.Wait() for _, i := range ints { if !s.Contains(i) { t.Errorf("Set is missing element: %v", i) } } } func Test_AppendConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s := NewSet[int]() ints := rand.Perm(N) n := len(ints) >> 1 var wg sync.WaitGroup wg.Add(n) for i := 0; i < n; i++ { go func(i int) { s.Append(i, N-i-1) wg.Done() }(i) } wg.Wait() for _, i := range ints { if !s.Contains(i) { t.Errorf("Set is missing element: %v", i) } } } func Test_CardinalityConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s := NewSet[int]() var wg sync.WaitGroup wg.Add(1) go func() { elems := s.Cardinality() for i := 0; i < N; i++ { newElems := s.Cardinality() if newElems < elems { t.Errorf("Cardinality shrunk from %v to %v", elems, newElems) } } wg.Done() }() for i := 0; i < N; i++ { s.Add(rand.Int()) } wg.Wait() } func Test_ClearConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s := NewSet[int]() ints := rand.Perm(N) var wg sync.WaitGroup wg.Add(len(ints)) for i := 0; i < len(ints); i++ { go func() { s.Clear() wg.Done() }() go func(i int) { s.Add(i) }(i) } wg.Wait() } func Test_CloneConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s := NewSet[int]() ints := rand.Perm(N) for _, v := range ints { s.Add(v) } var wg sync.WaitGroup wg.Add(len(ints)) for i := range ints { go func(i int) { s.Remove(i) wg.Done() }(i) } s.Clone() wg.Wait() } func Test_ContainsConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s := NewSet[int]() ints := rand.Perm(N) integers := make([]int, 0) for _, v := range ints { s.Add(v) integers = append(integers, v) } var wg sync.WaitGroup for range ints { wg.Add(1) go func() { s.Contains(integers...) wg.Done() }() } wg.Wait() } func Test_ContainsOneConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s := NewSet[int]() ints := rand.Perm(N) for _, v := range ints { s.Add(v) } var wg sync.WaitGroup for _, v := range ints { number := v wg.Add(1) go func() { s.ContainsOne(number) wg.Done() }() } wg.Wait() } func Test_ContainsAnyConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s := NewSet[int]() ints := rand.Perm(N) integers := make([]int, 0) for _, v := range ints { if v%N == 0 { s.Add(v) } integers = append(integers, v) } var wg sync.WaitGroup for range ints { wg.Add(1) go func() { s.ContainsAny(integers...) wg.Done() }() } wg.Wait() } func Test_DifferenceConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s, ss := NewSet[int](), NewSet[int]() ints := rand.Perm(N) for _, v := range ints { s.Add(v) ss.Add(v) } var wg sync.WaitGroup for range ints { wg.Add(1) go func() { s.Difference(ss) wg.Done() }() } wg.Wait() } func Test_EqualConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s, ss := NewSet[int](), NewSet[int]() ints := rand.Perm(N) for _, v := range ints { s.Add(v) ss.Add(v) } var wg sync.WaitGroup for range ints { wg.Add(1) go func() { s.Equal(ss) wg.Done() }() } wg.Wait() } func Test_IntersectConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s, ss := NewSet[int](), NewSet[int]() ints := rand.Perm(N) for _, v := range ints { s.Add(v) ss.Add(v) } var wg sync.WaitGroup for range ints { wg.Add(1) go func() { s.Intersect(ss) wg.Done() }() } wg.Wait() } func Test_IsEmptyConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s := NewSet[int]() var wg sync.WaitGroup wg.Add(1) go func() { for i := 0; i < N; i++ { size := s.Cardinality() if s.IsEmpty() && size > 0 { t.Errorf("Is Empty should be return false") } } wg.Done() }() for i := 0; i < N; i++ { s.Add(rand.Int()) } wg.Wait() } func Test_IsSubsetConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s, ss := NewSet[int](), NewSet[int]() ints := rand.Perm(N) for _, v := range ints { s.Add(v) ss.Add(v) } var wg sync.WaitGroup for range ints { wg.Add(1) go func() { s.IsSubset(ss) wg.Done() }() } wg.Wait() } func Test_IsProperSubsetConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s, ss := NewSet[int](), NewSet[int]() ints := rand.Perm(N) for _, v := range ints { s.Add(v) ss.Add(v) } var wg sync.WaitGroup for range ints { wg.Add(1) go func() { s.IsProperSubset(ss) wg.Done() }() } wg.Wait() } func Test_IsSupersetConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s, ss := NewSet[int](), NewSet[int]() ints := rand.Perm(N) for _, v := range ints { s.Add(v) ss.Add(v) } var wg sync.WaitGroup for range ints { wg.Add(1) go func() { s.IsSuperset(ss) wg.Done() }() } wg.Wait() } func Test_IsProperSupersetConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s, ss := NewSet[int](), NewSet[int]() ints := rand.Perm(N) for _, v := range ints { s.Add(v) ss.Add(v) } var wg sync.WaitGroup for range ints { wg.Add(1) go func() { s.IsProperSuperset(ss) wg.Done() }() } wg.Wait() } func Test_EachConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) concurrent := 10 s := NewSet[int]() ints := rand.Perm(N) for _, v := range ints { s.Add(v) } var count int64 wg := new(sync.WaitGroup) wg.Add(concurrent) for n := 0; n < concurrent; n++ { go func() { defer wg.Done() s.Each(func(elem int) bool { atomic.AddInt64(&count, 1) return false }) }() } wg.Wait() if count != int64(N*concurrent) { t.Errorf("%v != %v", count, int64(N*concurrent)) } } func Test_IterConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s := NewSet[int]() ints := rand.Perm(N) for _, v := range ints { s.Add(v) } cs := make([]<-chan int, 0) for range ints { cs = append(cs, s.Iter()) } c := make(chan interface{}) go func() { for n := 0; n < len(ints)*N; { for _, d := range cs { select { case <-d: n++ c <- nil default: } } } close(c) }() for range c { } } func Test_RemoveConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s := NewSet[int]() ints := rand.Perm(N) for _, v := range ints { s.Add(v) } var wg sync.WaitGroup wg.Add(len(ints)) for _, v := range ints { go func(i int) { s.Remove(i) wg.Done() }(v) } wg.Wait() if s.Cardinality() != 0 { t.Errorf("Expected cardinality 0; got %v", s.Cardinality()) } } func Test_StringConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s := NewSet[int]() ints := rand.Perm(N) for _, v := range ints { s.Add(v) } var wg sync.WaitGroup wg.Add(len(ints)) for range ints { go func() { _ = s.String() wg.Done() }() } wg.Wait() } func Test_SymmetricDifferenceConcurrent(t *testing.T) { runtime.GOMAXPROCS(2) s, ss := NewSet[int](), NewSet[int]() ints := rand.Perm(N) for _, v := range ints { s.Add(v) ss.Add(v) } var wg sync.WaitGroup for range ints { wg.Add(1) go func() { s.SymmetricDifference(ss) wg.Done() }() } wg.Wait() } func Test_ToSlice(t *testing.T) { runtime.GOMAXPROCS(2) s := NewSet[int]() ints := rand.Perm(N) var wg sync.WaitGroup wg.Add(len(ints)) for i := 0; i < len(ints); i++ { go func(i int) { s.Add(i) wg.Done() }(i) } wg.Wait() setAsSlice := s.ToSlice() if len(setAsSlice) != s.Cardinality() { t.Errorf("Set length is incorrect: %v", len(setAsSlice)) } for _, i := range setAsSlice { if !s.Contains(i) { t.Errorf("Set is missing element: %v", i) } } } // Test_ToSliceDeadlock - fixes issue: https://github.com/deckarep/golang-set/issues/36 // This code reveals the deadlock however it doesn't happen consistently. func Test_ToSliceDeadlock(t *testing.T) { runtime.GOMAXPROCS(2) var wg sync.WaitGroup set := NewSet[int]() workers := 10 wg.Add(workers) for i := 1; i <= workers; i++ { go func() { for j := 0; j < 1000; j++ { set.Add(1) set.ToSlice() } wg.Done() }() } wg.Wait() } func Test_UnmarshalJSON(t *testing.T) { s := []byte(`["test", "1", "2", "3"]`) //,["4,5,6"]]`) expected := NewSet( []string{ string(json.Number("1")), string(json.Number("2")), string(json.Number("3")), "test", }..., ) actual := NewSet[string]() err := json.Unmarshal(s, actual) if err != nil { t.Errorf("Error should be nil: %v", err) } if !expected.Equal(actual) { t.Errorf("Expected no difference, got: %v", expected.Difference(actual)) } } func TestThreadUnsafeSet_UnmarshalJSON(t *testing.T) { expected := NewThreadUnsafeSet[int64](1, 2, 3) actual := NewThreadUnsafeSet[int64]() err := actual.UnmarshalJSON([]byte(`[1, 2, 3]`)) if err != nil { t.Errorf("Error should be nil: %v", err) } if !expected.Equal(actual) { t.Errorf("Expected no difference, got: %v", expected.Difference(actual)) } } func Test_MarshalJSON(t *testing.T) { expected := NewSet( []string{ string(json.Number("1")), "test", }..., ) b, err := json.Marshal( NewSet( []string{ "1", "test", }..., ), ) if err != nil { t.Errorf("Error should be nil: %v", err) } actual := NewSet[string]() err = json.Unmarshal(b, actual) if err != nil { t.Errorf("Error should be nil: %v", err) } if !expected.Equal(actual) { t.Errorf("Expected no difference, got: %v", expected.Difference(actual)) } } golang-set-2.6.0/threadunsafe.go000066400000000000000000000160051454262171600165710ustar00rootroot00000000000000/* Open Source Initiative OSI - The MIT License (MIT):Licensing The MIT License (MIT) Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) 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 mapset import ( "encoding/json" "fmt" "strings" ) type threadUnsafeSet[T comparable] map[T]struct{} // Assert concrete type:threadUnsafeSet adheres to Set interface. var _ Set[string] = (threadUnsafeSet[string])(nil) func newThreadUnsafeSet[T comparable]() threadUnsafeSet[T] { return make(threadUnsafeSet[T]) } func newThreadUnsafeSetWithSize[T comparable](cardinality int) threadUnsafeSet[T] { return make(threadUnsafeSet[T], cardinality) } func (s threadUnsafeSet[T]) Add(v T) bool { prevLen := len(s) s[v] = struct{}{} return prevLen != len(s) } func (s threadUnsafeSet[T]) Append(v ...T) int { prevLen := len(s) for _, val := range v { (s)[val] = struct{}{} } return len(s) - prevLen } // private version of Add which doesn't return a value func (s threadUnsafeSet[T]) add(v T) { s[v] = struct{}{} } func (s threadUnsafeSet[T]) Cardinality() int { return len(s) } func (s threadUnsafeSet[T]) Clear() { // Constructions like this are optimised by compiler, and replaced by // mapclear() function, defined in // https://github.com/golang/go/blob/29bbca5c2c1ad41b2a9747890d183b6dd3a4ace4/src/runtime/map.go#L993) for key := range s { delete(s, key) } } func (s threadUnsafeSet[T]) Clone() Set[T] { clonedSet := newThreadUnsafeSetWithSize[T](s.Cardinality()) for elem := range s { clonedSet.add(elem) } return clonedSet } func (s threadUnsafeSet[T]) Contains(v ...T) bool { for _, val := range v { if _, ok := s[val]; !ok { return false } } return true } func (s threadUnsafeSet[T]) ContainsOne(v T) bool { _, ok := s[v] return ok } func (s threadUnsafeSet[T]) ContainsAny(v ...T) bool { for _, val := range v { if _, ok := s[val]; ok { return true } } return false } // private version of Contains for a single element v func (s threadUnsafeSet[T]) contains(v T) (ok bool) { _, ok = s[v] return ok } func (s threadUnsafeSet[T]) Difference(other Set[T]) Set[T] { o := other.(threadUnsafeSet[T]) diff := newThreadUnsafeSet[T]() for elem := range s { if !o.contains(elem) { diff.add(elem) } } return diff } func (s threadUnsafeSet[T]) Each(cb func(T) bool) { for elem := range s { if cb(elem) { break } } } func (s threadUnsafeSet[T]) Equal(other Set[T]) bool { o := other.(threadUnsafeSet[T]) if s.Cardinality() != other.Cardinality() { return false } for elem := range s { if !o.contains(elem) { return false } } return true } func (s threadUnsafeSet[T]) Intersect(other Set[T]) Set[T] { o := other.(threadUnsafeSet[T]) intersection := newThreadUnsafeSet[T]() // loop over smaller set if s.Cardinality() < other.Cardinality() { for elem := range s { if o.contains(elem) { intersection.add(elem) } } } else { for elem := range o { if s.contains(elem) { intersection.add(elem) } } } return intersection } func (s threadUnsafeSet[T]) IsEmpty() bool { return s.Cardinality() == 0 } func (s threadUnsafeSet[T]) IsProperSubset(other Set[T]) bool { return s.Cardinality() < other.Cardinality() && s.IsSubset(other) } func (s threadUnsafeSet[T]) IsProperSuperset(other Set[T]) bool { return s.Cardinality() > other.Cardinality() && s.IsSuperset(other) } func (s threadUnsafeSet[T]) IsSubset(other Set[T]) bool { o := other.(threadUnsafeSet[T]) if s.Cardinality() > other.Cardinality() { return false } for elem := range s { if !o.contains(elem) { return false } } return true } func (s threadUnsafeSet[T]) IsSuperset(other Set[T]) bool { return other.IsSubset(s) } func (s threadUnsafeSet[T]) Iter() <-chan T { ch := make(chan T) go func() { for elem := range s { ch <- elem } close(ch) }() return ch } func (s threadUnsafeSet[T]) Iterator() *Iterator[T] { iterator, ch, stopCh := newIterator[T]() go func() { L: for elem := range s { select { case <-stopCh: break L case ch <- elem: } } close(ch) }() return iterator } // Pop returns a popped item in case set is not empty, or nil-value of T // if set is already empty func (s threadUnsafeSet[T]) Pop() (v T, ok bool) { for item := range s { delete(s, item) return item, true } return v, false } func (s threadUnsafeSet[T]) Remove(v T) { delete(s, v) } func (s threadUnsafeSet[T]) RemoveAll(i ...T) { for _, elem := range i { delete(s, elem) } } func (s threadUnsafeSet[T]) String() string { items := make([]string, 0, len(s)) for elem := range s { items = append(items, fmt.Sprintf("%v", elem)) } return fmt.Sprintf("Set{%s}", strings.Join(items, ", ")) } func (s threadUnsafeSet[T]) SymmetricDifference(other Set[T]) Set[T] { o := other.(threadUnsafeSet[T]) sd := newThreadUnsafeSet[T]() for elem := range s { if !o.contains(elem) { sd.add(elem) } } for elem := range o { if !s.contains(elem) { sd.add(elem) } } return sd } func (s threadUnsafeSet[T]) ToSlice() []T { keys := make([]T, 0, s.Cardinality()) for elem := range s { keys = append(keys, elem) } return keys } func (s threadUnsafeSet[T]) Union(other Set[T]) Set[T] { o := other.(threadUnsafeSet[T]) n := s.Cardinality() if o.Cardinality() > n { n = o.Cardinality() } unionedSet := make(threadUnsafeSet[T], n) for elem := range s { unionedSet.add(elem) } for elem := range o { unionedSet.add(elem) } return unionedSet } // MarshalJSON creates a JSON array from the set, it marshals all elements func (s threadUnsafeSet[T]) MarshalJSON() ([]byte, error) { items := make([]string, 0, s.Cardinality()) for elem := range s { b, err := json.Marshal(elem) if err != nil { return nil, err } items = append(items, string(b)) } return []byte(fmt.Sprintf("[%s]", strings.Join(items, ","))), nil } // UnmarshalJSON recreates a set from a JSON array, it only decodes // primitive types. Numbers are decoded as json.Number. func (s threadUnsafeSet[T]) UnmarshalJSON(b []byte) error { var i []T err := json.Unmarshal(b, &i) if err != nil { return err } s.Append(i...) return nil }