pax_global_header00006660000000000000000000000064133727760550014531gustar00rootroot0000000000000052 comment=e560bb8f49bb7f34d4f59b7e771f6e1307c329da scylladb-go-set-e560bb8/000077500000000000000000000000001337277605500151375ustar00rootroot00000000000000scylladb-go-set-e560bb8/.golangci.yml000066400000000000000000000004711337277605500175250ustar00rootroot00000000000000run: deadline: 5m tests: false silent: true linters-settings: lll: line-length: 180 linters: enable-all: true disable: - dupl - gas - interfacer issues: exclude-use-default: false exclude: - composite literal uses unkeyed fields - Error return value of `.+\.Close` is not checked scylladb-go-set-e560bb8/.travis.yml000066400000000000000000000001321337277605500172440ustar00rootroot00000000000000sudo: false language: go go: - 1.10.x install: - make get-deps get-tools script: - make scylladb-go-set-e560bb8/LICENSE000066400000000000000000000236751337277605500161610ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONSscylladb-go-set-e560bb8/Makefile000066400000000000000000000013121337277605500165740ustar00rootroot00000000000000all: check test ifndef GOBIN export GOBIN := $(GOPATH)/bin endif define dl @curl -sSq -L $(2) -o $(GOBIN)/$(1) && chmod u+x $(GOBIN)/$(1) endef define dl_tgz @curl -sSq -L $(2) | tar zxf - --strip 1 -C $(GOBIN) --wildcards '*/$(1)' endef .PHONY: fmt fmt: @go fmt ./... .PHONY: check check: @$(GOBIN)/golangci-lint run ./... .PHONY: test test: go test -cover -race ./... .PHONY: bench bench: @go test -tags all -run=XXX -bench=. -benchmem ./... .PHONY: get-deps get-deps: go get -t ./... .PHONY: get-tools get-tools: @echo "==> Installing tools at $(GOBIN)..." @$(call dl_tgz,golangci-lint,https://github.com/golangci/golangci-lint/releases/download/v1.9.3/golangci-lint-1.9.3-linux-amd64.tar.gz) scylladb-go-set-e560bb8/README.md000066400000000000000000000266071337277605500164310ustar00rootroot00000000000000# Set [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/scylladb/go-set) [![Go Report Card](https://goreportcard.com/badge/github.com/scylladb/go-set)](https://goreportcard.com/report/github.com/scylladb/go-set) [![Build Status](https://travis-ci.org/scylladb/go-set.svg?branch=master)](https://travis-ci.org/scylladb/go-set) Package set is a type-safe, zero-allocation port of the excellent package [fatih/set](https://github.com/fatih/set). It contains sets for most of the basic types and you can generate sets for your own types with ease. ## Example Example code using the generated string set: ```go import "github.com/scylladb/go-set/strset" s1 := strset.New("entry 1", "entry 2") s2 := strset.New("entry 2", "entry 3") s3 := strset.Intersection(s1, s2) // s3 now contains only "entry 2" ``` The library exposes a number of top level factory functions that can be used to create a specific instances of the set type you want to use. For example to create a set to store `int` you could do like this: ```go import "github.com/scylladb/go-set" s := set.NewIntSet() // use the set... ``` ## Usage In every subpackage Set is the main set structure that holds all the data and methods used to working with the set. #### func Difference ```go func Difference(set1 *Set, sets ...*Set) *Set ``` Difference returns a new set which contains items which are in in the first set but not in the others. #### func Intersection ```go func Intersection(sets ...*Set) *Set ``` Intersection returns a new set which contains items that only exist in all given sets. #### func New ```go func New(ts ...T) *Set ``` New creates and initializes a new Set. #### func NewWithSize ```go func NewWithSize(size int) *Set ``` NewWithSize creates a new Set and gives make map a size hint. #### func SymmetricDifference ```go func SymmetricDifference(s *Set, t *Set) *Set ``` SymmetricDifference returns a new set which s is the difference of items which are in one of either, but not in both. #### func Union ```go func Union(sets ...*Set) *Set ``` Union is the merger of multiple sets. It returns a new set with all the elements present in all the sets that are passed. #### func (*Set) Add ```go func (s *Set) Add(items ...T) ``` Add includes the specified items (one or more) to the Set. The underlying Set s is modified. If passed nothing it silently returns. #### func (*Set) Clear ```go func (s *Set) Clear() ``` Clear removes all items from the Set. #### func (*Set) Copy ```go func (s *Set) Copy() *Set ``` Copy returns a new Set with a copy of s. #### func (*Set) Each ```go func (s *Set) Each(f func(item T) bool) ``` Each traverses the items in the Set, calling the provided function for each Set member. Traversal will continue until all items in the Set have been visited, or if the closure returns false. #### func (*Set) Has ```go func (s *Set) Has(items ...T) bool ``` Has looks for the existence of items passed. It returns false if nothing is passed. For multiple items it returns true only if all of the items exist. #### func (*Set) IsEmpty ```go func (s *Set) IsEmpty() bool ``` IsEmpty reports whether the Set is empty. #### func (*Set) IsEqual ```go func (s *Set) IsEqual(t *Set) bool ``` IsEqual test whether s and t are the same in size and have the same items. #### func (*Set) IsSubset ```go func (s *Set) IsSubset(t *Set) bool ``` IsSubset tests whether t is a subset of s. #### func (*Set) IsSuperset ```go func (s *Set) IsSuperset(t *Set) bool ``` IsSuperset tests whether t is a superset of s. #### func (*Set) List ```go func (s *Set) List() []T ``` List returns a slice of all items. There is also StringSlice() and IntSlice() methods for returning slices of type string or int. #### func (*Set) Merge ```go func (s *Set) Merge(t *Set) ``` Merge is like Union, however it modifies the current Set it's applied on with the given t Set. #### func (*Set) Pop ```go func (s *Set) Pop() T ``` Pop deletes and returns an item from the Set. The underlying Set s is modified. If Set is empty, the zero value is returned. #### func (*Set) Pop2 ```go func (s *Set) Pop2() (T, bool) ``` Pop2 tries to delete and return an item from the Set. The underlying Set s is modified. The second value is a bool that is true if the item existed in the set, and false if not. If Set is empty, the zero value and false are returned. #### func (*Set) Remove ```go func (s *Set) Remove(items ...T) ``` Remove deletes the specified items from the Set. The underlying Set s is modified. If passed nothing it silently returns. #### func (*Set) Separate ```go func (s *Set) Separate(t *Set) ``` Separate removes the Set items containing in t from Set s. Please aware that it's not the opposite of Merge. #### func (*Set) Size ```go func (s *Set) Size() int ``` Size returns the number of items in a Set. #### func (*Set) String ```go func (s *Set) String() string ``` String returns a string representation of s ## Performance The improvement in performance by using concrete types over `interface{}` is notable. Below you will find benchmark results comparing type-safe sets to `fatih/set` counterparts for `string`, `int64`, `int32`, `float64` and `float32` on a local machine, Intel(R) Core(TM) i7-7500U CPU @ 2.70GHz. ``` pkg: github.com/scylladb/go-set/strset BenchmarkTypeSafeSetHasNonExisting-4 200000000 7.02 ns/op 0 B/op 0 allocs/op BenchmarkInterfaceSetHasNonExisting-4 20000000 60.0 ns/op 32 B/op 2 allocs/op BenchmarkTypeSafeSetHasExisting-4 200000000 9.02 ns/op 0 B/op 0 allocs/op BenchmarkInterfaceSetHasExisting-4 20000000 97.0 ns/op 32 B/op 2 allocs/op BenchmarkTypeSafeSetHasExistingMany-4 100000000 16.8 ns/op 0 B/op 0 allocs/op BenchmarkInterfaceSetHasExistingMany-4 30000000 106 ns/op 32 B/op 2 allocs/op BenchmarkTypeSafeSetAdd-4 3000000 469 ns/op 58 B/op 0 allocs/op BenchmarkInterfaceSetAdd-4 2000000 909 ns/op 117 B/op 2 allocs/op pkg: github.com/scylladb/go-set/i64set BenchmarkTypeSafeSetHasNonExisting-4 300000000 5.51 ns/op 0 B/op 0 allocs/op BenchmarkInterfaceSetHasNonExisting-4 30000000 49.4 ns/op 24 B/op 2 allocs/op BenchmarkTypeSafeSetHasExisting-4 200000000 7.53 ns/op 0 B/op 0 allocs/op BenchmarkInterfaceSetHasExisting-4 20000000 68.5 ns/op 24 B/op 2 allocs/op BenchmarkTypeSafeSetHasExistingMany-4 100000000 11.0 ns/op 0 B/op 0 allocs/op BenchmarkInterfaceSetHasExistingMany-4 20000000 74.5 ns/op 24 B/op 2 allocs/op BenchmarkTypeSafeSetAdd-4 10000000 225 ns/op 40 B/op 0 allocs/op BenchmarkInterfaceSetAdd-4 3000000 403 ns/op 82 B/op 2 allocs/op pkg: github.com/scylladb/go-set/i32set BenchmarkTypeSafeSetHasNonExisting-4 300000000 5.61 ns/op 0 B/op 0 allocs/op BenchmarkInterfaceSetHasNonExisting-4 30000000 48.8 ns/op 20 B/op 2 allocs/op BenchmarkTypeSafeSetHasExisting-4 200000000 7.07 ns/op 0 B/op 0 allocs/op BenchmarkInterfaceSetHasExisting-4 20000000 69.3 ns/op 20 B/op 2 allocs/op BenchmarkTypeSafeSetHasExistingMany-4 100000000 11.7 ns/op 0 B/op 0 allocs/op BenchmarkInterfaceSetHasExistingMany-4 20000000 71.1 ns/op 20 B/op 2 allocs/op BenchmarkTypeSafeSetAdd-4 10000000 206 ns/op 25 B/op 0 allocs/op BenchmarkInterfaceSetAdd-4 3000000 394 ns/op 78 B/op 2 allocs/op pkg: github.com/scylladb/go-set/f64set BenchmarkTypeSafeSetHasNonExisting-4 300000000 5.82 ns/op 0 B/op 0 allocs/op BenchmarkInterfaceSetHasNonExisting-4 30000000 49.8 ns/op 24 B/op 2 allocs/op BenchmarkTypeSafeSetHasExisting-4 50000000 26.8 ns/op 0 B/op 0 allocs/op BenchmarkInterfaceSetHasExisting-4 20000000 77.6 ns/op 24 B/op 2 allocs/op BenchmarkTypeSafeSetHasExistingMany-4 50000000 27.6 ns/op 0 B/op 0 allocs/op BenchmarkInterfaceSetHasExistingMany-4 20000000 82.3 ns/op 24 B/op 2 allocs/op BenchmarkTypeSafeSetAdd-4 10000000 270 ns/op 40 B/op 0 allocs/op BenchmarkInterfaceSetAdd-4 3000000 428 ns/op 82 B/op 2 allocs/op pkg: github.com/scylladb/go-set/f32set BenchmarkTypeSafeSetHasNonExisting-4 300000000 5.78 ns/op 0 B/op 0 allocs/op BenchmarkInterfaceSetHasNonExisting-4 30000000 49.3 ns/op 20 B/op 2 allocs/op BenchmarkTypeSafeSetHasExisting-4 50000000 24.9 ns/op 0 B/op 0 allocs/op BenchmarkInterfaceSetHasExisting-4 20000000 78.6 ns/op 20 B/op 2 allocs/op BenchmarkTypeSafeSetHasExistingMany-4 50000000 25.1 ns/op 0 B/op 0 allocs/op BenchmarkInterfaceSetHasExistingMany-4 20000000 81.1 ns/op 20 B/op 2 allocs/op BenchmarkTypeSafeSetAdd-4 10000000 246 ns/op 24 B/op 0 allocs/op BenchmarkInterfaceSetAdd-4 3000000 408 ns/op 78 B/op 2 allocs/op ``` ## Code generation For code generation we use [Google go_generics tool](https://github.com/mmatczuk/go_generics) that we forked to provide bazel-free installation, to install run: ```bash go get -u github.com/mmatczuk/go_generics/cmd/go_generics ``` Once you have `go_generics` installed properly you can regenerate the code using `go generate` in the top level directory. ### Your custom types If you have types that you would like to use but the are not amenable for inclusion in this library you can simply generate code on your own and put it in your package. For example, to generate a set for `SomeType` in package `sometypeset` call: ```bash ./gen_set.sh SomeType sometypeset ``` this would generate a new directory `sometypeset` in current working directory. If you think your addition belongs here we are open to accept pull requests. ## License Copyright (C) 2018 ScyllaDB This project is distributed under the Apache 2.0 license. See the [LICENSE](https://github.com/scylladb/gocqlx/blob/master/LICENSE) file for details. It contains software from: * [github.com/fatih/set](https://github.com/fatih/set), licensed under the MIT license GitHub star is always appreciated! scylladb-go-set-e560bb8/b16set/000077500000000000000000000000001337277605500162435ustar00rootroot00000000000000scylladb-go-set-e560bb8/b16set/b16set.go000066400000000000000000000143031337277605500176770ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package b16set import ( "fmt" "math" "strings" ) var ( // helpful to not write everywhere struct{}{} keyExists = struct{}{} nonExistent [16]byte ) // Set is the main set structure that holds all the data // and methods used to working with the set. type Set struct { m map[[16]byte]struct{} } // New creates and initializes a new Set. func New(ts ...[16]byte) *Set { s := NewWithSize(len(ts)) s.Add(ts...) return s } // NewWithSize creates a new Set and gives make map a size hint. func NewWithSize(size int) *Set { return &Set{make(map[[16]byte]struct{}, size)} } // Add includes the specified items (one or more) to the Set. The underlying // Set s is modified. If passed nothing it silently returns. func (s *Set) Add(items ...[16]byte) { for _, item := range items { s.m[item] = keyExists } } // Remove deletes the specified items from the Set. The underlying Set s is // modified. If passed nothing it silently returns. func (s *Set) Remove(items ...[16]byte) { for _, item := range items { delete(s.m, item) } } // Pop deletes and returns an item from the Set. The underlying Set s is // modified. If Set is empty, the zero value is returned. func (s *Set) Pop() [16]byte { for item := range s.m { delete(s.m, item) return item } return nonExistent } // Pop2 tries to delete and return an item from the Set. The underlying Set s // is modified. The second value is a bool that is true if the item existed in // the set, and false if not. If Set is empty, the zero value and false are // returned. func (s *Set) Pop2() ([16]byte, bool) { for item := range s.m { delete(s.m, item) return item, true } return nonExistent, false } // Has looks for the existence of items passed. It returns false if nothing is // passed. For multiple items it returns true only if all of the items exist. func (s *Set) Has(items ...[16]byte) bool { has := false for _, item := range items { if _, has = s.m[item]; !has { break } } return has } // HasAny looks for the existence of any of the items passed. // It returns false if nothing is passed. // For multiple items it returns true if any of the items exist. func (s *Set) HasAny(items ...[16]byte) bool { has := false for _, item := range items { if _, has = s.m[item]; has { break } } return has } // Size returns the number of items in a Set. func (s *Set) Size() int { return len(s.m) } // Clear removes all items from the Set. func (s *Set) Clear() { s.m = make(map[[16]byte]struct{}) } // IsEmpty reports whether the Set is empty. func (s *Set) IsEmpty() bool { return s.Size() == 0 } // IsEqual test whether s and t are the same in size and have the same items. func (s *Set) IsEqual(t *Set) bool { // return false if they are no the same size if s.Size() != t.Size() { return false } equal := true t.Each(func(item [16]byte) bool { _, equal = s.m[item] return equal // if false, Each() will end }) return equal } // IsSubset tests whether t is a subset of s. func (s *Set) IsSubset(t *Set) bool { if s.Size() < t.Size() { return false } subset := true t.Each(func(item [16]byte) bool { _, subset = s.m[item] return subset }) return subset } // IsSuperset tests whether t is a superset of s. func (s *Set) IsSuperset(t *Set) bool { return t.IsSubset(s) } // Each traverses the items in the Set, calling the provided function for each // Set member. Traversal will continue until all items in the Set have been // visited, or if the closure returns false. func (s *Set) Each(f func(item [16]byte) bool) { for item := range s.m { if !f(item) { break } } } // Copy returns a new Set with a copy of s. func (s *Set) Copy() *Set { u := NewWithSize(s.Size()) for item := range s.m { u.m[item] = keyExists } return u } // String returns a string representation of s func (s *Set) String() string { v := make([]string, 0, s.Size()) for item := range s.m { v = append(v, fmt.Sprintf("%v", item)) } return fmt.Sprintf("[%s]", strings.Join(v, ", ")) } // List returns a slice of all items. There is also StringSlice() and // IntSlice() methods for returning slices of type string or int. func (s *Set) List() [][16]byte { v := make([][16]byte, 0, s.Size()) for item := range s.m { v = append(v, item) } return v } // Merge is like Union, however it modifies the current Set it's applied on // with the given t Set. func (s *Set) Merge(t *Set) { for item := range t.m { s.m[item] = keyExists } } // Separate removes the Set items containing in t from Set s. Please aware that // it's not the opposite of Merge. func (s *Set) Separate(t *Set) { for item := range t.m { delete(s.m, item) } } // Union is the merger of multiple sets. It returns a new set with all the // elements present in all the sets that are passed. func Union(sets ...*Set) *Set { maxPos := -1 maxSize := 0 for i, set := range sets { if l := set.Size(); l > maxSize { maxSize = l maxPos = i } } if maxSize == 0 { return New() } u := sets[maxPos].Copy() for i, set := range sets { if i == maxPos { continue } for item := range set.m { u.m[item] = keyExists } } return u } // Difference returns a new set which contains items which are in in the first // set but not in the others. func Difference(set1 *Set, sets ...*Set) *Set { s := set1.Copy() for _, set := range sets { s.Separate(set) } return s } // Intersection returns a new set which contains items that only exist in all // given sets. func Intersection(sets ...*Set) *Set { minPos := -1 minSize := math.MaxInt64 for i, set := range sets { if l := set.Size(); l < minSize { minSize = l minPos = i } } if minSize == math.MaxInt64 || minSize == 0 { return New() } t := sets[minPos].Copy() for i, set := range sets { if i == minPos { continue } for item := range t.m { if _, has := set.m[item]; !has { delete(t.m, item) } } } return t } // SymmetricDifference returns a new set which s is the difference of items // which are in one of either, but not in both. func SymmetricDifference(s *Set, t *Set) *Set { u := Difference(s, t) v := Difference(t, s) return Union(u, v) } scylladb-go-set-e560bb8/b16set/b16set_bench_test.go000066400000000000000000000047171337277605500221050ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package b16set import ( "github.com/fatih/set" "testing" ) func BenchmarkTypeSafeSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } b.StartTimer() s := New() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExisting(b *testing.B) { b.StopTimer() var e1 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } b.StartTimer() s := New() s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExisting(b *testing.B) { b.StopTimer() var e1 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExistingMany(b *testing.B) { s := New() b.StopTimer() var e1 [16]byte for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.([16]byte); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExistingMany(b *testing.B) { s := set.New(set.NonThreadSafe) b.StopTimer() var e1 [16]byte for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.([16]byte); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetAdd(b *testing.B) { b.StopTimer() var e [16]byte s := New() objs := make([][16]byte, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.([16]byte); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } func BenchmarkInterfaceSetAdd(b *testing.B) { b.StopTimer() var e [16]byte s := set.New(set.NonThreadSafe) objs := make([][16]byte, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.([16]byte); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } scylladb-go-set-e560bb8/b16set/b16set_test.go000066400000000000000000000252661337277605500207500ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package b16set import ( "fmt" "math/rand" "reflect" "strings" "testing" "testing/quick" "time" ) func TestAdd(t *testing.T) { var e1, e2 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if len(s.m) != 2 { t.Errorf("expected 2 entries, got %d", len(s.m)) } } func TestRemove(t *testing.T) { var e1, e2 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Remove(e1) if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if _, ok := s.m[e2]; !ok { t.Errorf("wrong entry %v removed, expected %v", e1, e2) } } func TestPop(t *testing.T) { var e1, e2 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } s := New() popped := s.Pop() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } s.Add(e1) s.Add(e2) s.Pop() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } } func TestPop2(t *testing.T) { var e1, e2 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } s := New() popped, found := s.Pop2() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } if found { t.Errorf("set is empty, no element should have been found") } s.Add(e1) s.Add(e2) _, found = s.Pop2() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if !found { t.Errorf("expected to find an entry") } } func TestHas(t *testing.T) { var e1, e2, e3 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.Has(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.Has(e2) { t.Errorf("expected the set to contain %v", e2) } if s.Has(e3) { t.Errorf("did not expect the set to contain %v", e3) } } func TestHasAny(t *testing.T) { var e1, e2, e3 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.HasAny(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.HasAny(e2) { t.Errorf("expected the set to contain %v", e2) } if s.HasAny(e3) { t.Errorf("did not expect the set to contain %v", e3) } if !s.HasAny(e1, e3) { t.Errorf("expected the set to contain %v", e1) } } func TestSize(t *testing.T) { var e1, e2 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if s.Size() != 2 { t.Errorf("expected the set size to be 2 but it was %d", s.Size()) } } func TestClear(t *testing.T) { var e1, e2 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Clear() if s.Size() != 0 { t.Errorf("expected the cleared set size to be 0 but it was %d", s.Size()) } } func TestIsEmpty(t *testing.T) { var e1, e2 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } s := New() if !s.IsEmpty() { t.Errorf("expected new set to be empty but it had %d elements", s.Size()) } s.Add(e1) s.Add(e2) if s.IsEmpty() { t.Error("expected a set with added items to not be empty") } } func TestIsEqual(t *testing.T) { var e1, e2 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } s1 := New() s2 := New() if !s1.IsEqual(s2) { t.Error("expected 2 new sets to be equal") } s1.Add(e1) s1.Add(e2) if s1.IsEqual(s2) { t.Errorf("expected 2 different sets to be equal, %v, %v", s1, s2) } s2.Add(e1) s2.Add(e2) if !s1.IsEqual(s2) { t.Error("expected 2 sets with the same items added to be equal") } } func TestIsSubset(t *testing.T) { var e1, e2, e3 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e3 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s1.IsSubset(s2) { t.Errorf("expected %v to be a subset of %v", s2, s1) } s2.Add(e2) s2.Add(e3) if s1.IsSubset(s2) { t.Errorf("expected %v not to be a subset of %v", s2, s1) } } func TestIsSuperset(t *testing.T) { var e1, e2 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s2.IsSuperset(s1) { t.Errorf("expected %v to be a super set of %v", s1, s2) } } func TestCopy(t *testing.T) { var e1, e2 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := s1.Copy() if !s2.IsEqual(s1) { t.Errorf("expected %v to be equal to %v after copy", s1, s2) } } func TestString(t *testing.T) { var e1 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } s1 := New() s1.Add(e1) s := s1.String() if s == "" { t.Errorf("expected string representation %v to exist", s) } if !strings.HasPrefix(s, "[") && !strings.HasSuffix(s, "]") { t.Errorf("expected string representation %v to start with '[' and end with ']'", s) } } func TestMerge(t *testing.T) { var e1, e2 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s2.Add(e2) s1.Merge(s2) if s1.Size() != 2 { t.Errorf("expected merged set %v have size 2 but it has %d", s1, s1.Size()) } } func TestList(t *testing.T) { var e1, e2 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) l := s.List() if len(l) != s.Size() { t.Errorf("expected a set of size %d to give a list of size 2 but it has %d", s.Size(), len(l)) } for _, e := range l { if !s.Has(e) { t.Errorf("listed entry %v not available in the set %s", e, s) } } } func TestSeparate(t *testing.T) { var e1, e2 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e2) s1.Separate(s2) if s1.Size() != 1 { t.Errorf("expected separated set %v have size 1 but it has %d", s1, s1.Size()) } if s1.Has(e2) { t.Errorf("separated set %v still contains %v", s1, e2) } } func TestEach(t *testing.T) { var e1, e2 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) found := make(map[[16]byte]bool) s1.Each(func(item [16]byte) bool { found[item] = true return true }) if len(found) != 2 { t.Errorf("not all items traversed only %v", found) } found = make(map[[16]byte]bool) count := 0 s1.Each(func(item [16]byte) bool { found[item] = true count++ if count > 0 { return false } return true }) if len(found) != 1 { t.Errorf("more than expected 1 items traversed %v", found) } } func TestIntersection(t *testing.T) { var e1, e2, e3 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.([16]byte); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Intersection(s1, s2) if s3.Size() != 1 || !s3.Has(e2) { t.Errorf("expected the intersection to only contain '%v' but it is %v", e2, s3.List()) } } func TestUnion(t *testing.T) { var e1, e2, e3 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.([16]byte); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Union(s1, s2) if s3.Size() != 3 || !(s3.Has(e1) && s3.Has(e2) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestDifference(t *testing.T) { var e1, e2, e3 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.([16]byte); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Difference(s1, s2) if s3.Size() != 1 || !s3.Has(e1) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestSymmetricDifference(t *testing.T) { var e1, e2, e3 [16]byte e := createRandomObject(e1) if v, ok := e.([16]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([16]byte); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.([16]byte); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := SymmetricDifference(s1, s2) if s3.Size() != 2 || !(s3.Has(e1) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func createRandomObject(i interface{}) interface{} { v, ok := quick.Value(reflect.TypeOf(i), rand.New(rand.NewSource(time.Now().UnixNano()))) if !ok { panic(fmt.Sprintf("unsupported type %v", i)) } return v.Interface() } scylladb-go-set-e560bb8/b32set/000077500000000000000000000000001337277605500162415ustar00rootroot00000000000000scylladb-go-set-e560bb8/b32set/b32set.go000066400000000000000000000143031337277605500176730ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package b32set import ( "fmt" "math" "strings" ) var ( // helpful to not write everywhere struct{}{} keyExists = struct{}{} nonExistent [32]byte ) // Set is the main set structure that holds all the data // and methods used to working with the set. type Set struct { m map[[32]byte]struct{} } // New creates and initializes a new Set. func New(ts ...[32]byte) *Set { s := NewWithSize(len(ts)) s.Add(ts...) return s } // NewWithSize creates a new Set and gives make map a size hint. func NewWithSize(size int) *Set { return &Set{make(map[[32]byte]struct{}, size)} } // Add includes the specified items (one or more) to the Set. The underlying // Set s is modified. If passed nothing it silently returns. func (s *Set) Add(items ...[32]byte) { for _, item := range items { s.m[item] = keyExists } } // Remove deletes the specified items from the Set. The underlying Set s is // modified. If passed nothing it silently returns. func (s *Set) Remove(items ...[32]byte) { for _, item := range items { delete(s.m, item) } } // Pop deletes and returns an item from the Set. The underlying Set s is // modified. If Set is empty, the zero value is returned. func (s *Set) Pop() [32]byte { for item := range s.m { delete(s.m, item) return item } return nonExistent } // Pop2 tries to delete and return an item from the Set. The underlying Set s // is modified. The second value is a bool that is true if the item existed in // the set, and false if not. If Set is empty, the zero value and false are // returned. func (s *Set) Pop2() ([32]byte, bool) { for item := range s.m { delete(s.m, item) return item, true } return nonExistent, false } // Has looks for the existence of items passed. It returns false if nothing is // passed. For multiple items it returns true only if all of the items exist. func (s *Set) Has(items ...[32]byte) bool { has := false for _, item := range items { if _, has = s.m[item]; !has { break } } return has } // HasAny looks for the existence of any of the items passed. // It returns false if nothing is passed. // For multiple items it returns true if any of the items exist. func (s *Set) HasAny(items ...[32]byte) bool { has := false for _, item := range items { if _, has = s.m[item]; has { break } } return has } // Size returns the number of items in a Set. func (s *Set) Size() int { return len(s.m) } // Clear removes all items from the Set. func (s *Set) Clear() { s.m = make(map[[32]byte]struct{}) } // IsEmpty reports whether the Set is empty. func (s *Set) IsEmpty() bool { return s.Size() == 0 } // IsEqual test whether s and t are the same in size and have the same items. func (s *Set) IsEqual(t *Set) bool { // return false if they are no the same size if s.Size() != t.Size() { return false } equal := true t.Each(func(item [32]byte) bool { _, equal = s.m[item] return equal // if false, Each() will end }) return equal } // IsSubset tests whether t is a subset of s. func (s *Set) IsSubset(t *Set) bool { if s.Size() < t.Size() { return false } subset := true t.Each(func(item [32]byte) bool { _, subset = s.m[item] return subset }) return subset } // IsSuperset tests whether t is a superset of s. func (s *Set) IsSuperset(t *Set) bool { return t.IsSubset(s) } // Each traverses the items in the Set, calling the provided function for each // Set member. Traversal will continue until all items in the Set have been // visited, or if the closure returns false. func (s *Set) Each(f func(item [32]byte) bool) { for item := range s.m { if !f(item) { break } } } // Copy returns a new Set with a copy of s. func (s *Set) Copy() *Set { u := NewWithSize(s.Size()) for item := range s.m { u.m[item] = keyExists } return u } // String returns a string representation of s func (s *Set) String() string { v := make([]string, 0, s.Size()) for item := range s.m { v = append(v, fmt.Sprintf("%v", item)) } return fmt.Sprintf("[%s]", strings.Join(v, ", ")) } // List returns a slice of all items. There is also StringSlice() and // IntSlice() methods for returning slices of type string or int. func (s *Set) List() [][32]byte { v := make([][32]byte, 0, s.Size()) for item := range s.m { v = append(v, item) } return v } // Merge is like Union, however it modifies the current Set it's applied on // with the given t Set. func (s *Set) Merge(t *Set) { for item := range t.m { s.m[item] = keyExists } } // Separate removes the Set items containing in t from Set s. Please aware that // it's not the opposite of Merge. func (s *Set) Separate(t *Set) { for item := range t.m { delete(s.m, item) } } // Union is the merger of multiple sets. It returns a new set with all the // elements present in all the sets that are passed. func Union(sets ...*Set) *Set { maxPos := -1 maxSize := 0 for i, set := range sets { if l := set.Size(); l > maxSize { maxSize = l maxPos = i } } if maxSize == 0 { return New() } u := sets[maxPos].Copy() for i, set := range sets { if i == maxPos { continue } for item := range set.m { u.m[item] = keyExists } } return u } // Difference returns a new set which contains items which are in in the first // set but not in the others. func Difference(set1 *Set, sets ...*Set) *Set { s := set1.Copy() for _, set := range sets { s.Separate(set) } return s } // Intersection returns a new set which contains items that only exist in all // given sets. func Intersection(sets ...*Set) *Set { minPos := -1 minSize := math.MaxInt64 for i, set := range sets { if l := set.Size(); l < minSize { minSize = l minPos = i } } if minSize == math.MaxInt64 || minSize == 0 { return New() } t := sets[minPos].Copy() for i, set := range sets { if i == minPos { continue } for item := range t.m { if _, has := set.m[item]; !has { delete(t.m, item) } } } return t } // SymmetricDifference returns a new set which s is the difference of items // which are in one of either, but not in both. func SymmetricDifference(s *Set, t *Set) *Set { u := Difference(s, t) v := Difference(t, s) return Union(u, v) } scylladb-go-set-e560bb8/b32set/b32set_bench_test.go000066400000000000000000000047171337277605500221010ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package b32set import ( "github.com/fatih/set" "testing" ) func BenchmarkTypeSafeSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } b.StartTimer() s := New() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExisting(b *testing.B) { b.StopTimer() var e1 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } b.StartTimer() s := New() s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExisting(b *testing.B) { b.StopTimer() var e1 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExistingMany(b *testing.B) { s := New() b.StopTimer() var e1 [32]byte for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.([32]byte); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExistingMany(b *testing.B) { s := set.New(set.NonThreadSafe) b.StopTimer() var e1 [32]byte for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.([32]byte); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetAdd(b *testing.B) { b.StopTimer() var e [32]byte s := New() objs := make([][32]byte, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.([32]byte); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } func BenchmarkInterfaceSetAdd(b *testing.B) { b.StopTimer() var e [32]byte s := set.New(set.NonThreadSafe) objs := make([][32]byte, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.([32]byte); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } scylladb-go-set-e560bb8/b32set/b32set_test.go000066400000000000000000000252661337277605500207440ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package b32set import ( "fmt" "math/rand" "reflect" "strings" "testing" "testing/quick" "time" ) func TestAdd(t *testing.T) { var e1, e2 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if len(s.m) != 2 { t.Errorf("expected 2 entries, got %d", len(s.m)) } } func TestRemove(t *testing.T) { var e1, e2 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Remove(e1) if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if _, ok := s.m[e2]; !ok { t.Errorf("wrong entry %v removed, expected %v", e1, e2) } } func TestPop(t *testing.T) { var e1, e2 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } s := New() popped := s.Pop() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } s.Add(e1) s.Add(e2) s.Pop() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } } func TestPop2(t *testing.T) { var e1, e2 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } s := New() popped, found := s.Pop2() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } if found { t.Errorf("set is empty, no element should have been found") } s.Add(e1) s.Add(e2) _, found = s.Pop2() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if !found { t.Errorf("expected to find an entry") } } func TestHas(t *testing.T) { var e1, e2, e3 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.Has(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.Has(e2) { t.Errorf("expected the set to contain %v", e2) } if s.Has(e3) { t.Errorf("did not expect the set to contain %v", e3) } } func TestHasAny(t *testing.T) { var e1, e2, e3 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.HasAny(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.HasAny(e2) { t.Errorf("expected the set to contain %v", e2) } if s.HasAny(e3) { t.Errorf("did not expect the set to contain %v", e3) } if !s.HasAny(e1, e3) { t.Errorf("expected the set to contain %v", e1) } } func TestSize(t *testing.T) { var e1, e2 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if s.Size() != 2 { t.Errorf("expected the set size to be 2 but it was %d", s.Size()) } } func TestClear(t *testing.T) { var e1, e2 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Clear() if s.Size() != 0 { t.Errorf("expected the cleared set size to be 0 but it was %d", s.Size()) } } func TestIsEmpty(t *testing.T) { var e1, e2 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } s := New() if !s.IsEmpty() { t.Errorf("expected new set to be empty but it had %d elements", s.Size()) } s.Add(e1) s.Add(e2) if s.IsEmpty() { t.Error("expected a set with added items to not be empty") } } func TestIsEqual(t *testing.T) { var e1, e2 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } s1 := New() s2 := New() if !s1.IsEqual(s2) { t.Error("expected 2 new sets to be equal") } s1.Add(e1) s1.Add(e2) if s1.IsEqual(s2) { t.Errorf("expected 2 different sets to be equal, %v, %v", s1, s2) } s2.Add(e1) s2.Add(e2) if !s1.IsEqual(s2) { t.Error("expected 2 sets with the same items added to be equal") } } func TestIsSubset(t *testing.T) { var e1, e2, e3 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e3 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s1.IsSubset(s2) { t.Errorf("expected %v to be a subset of %v", s2, s1) } s2.Add(e2) s2.Add(e3) if s1.IsSubset(s2) { t.Errorf("expected %v not to be a subset of %v", s2, s1) } } func TestIsSuperset(t *testing.T) { var e1, e2 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s2.IsSuperset(s1) { t.Errorf("expected %v to be a super set of %v", s1, s2) } } func TestCopy(t *testing.T) { var e1, e2 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := s1.Copy() if !s2.IsEqual(s1) { t.Errorf("expected %v to be equal to %v after copy", s1, s2) } } func TestString(t *testing.T) { var e1 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } s1 := New() s1.Add(e1) s := s1.String() if s == "" { t.Errorf("expected string representation %v to exist", s) } if !strings.HasPrefix(s, "[") && !strings.HasSuffix(s, "]") { t.Errorf("expected string representation %v to start with '[' and end with ']'", s) } } func TestMerge(t *testing.T) { var e1, e2 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s2.Add(e2) s1.Merge(s2) if s1.Size() != 2 { t.Errorf("expected merged set %v have size 2 but it has %d", s1, s1.Size()) } } func TestList(t *testing.T) { var e1, e2 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) l := s.List() if len(l) != s.Size() { t.Errorf("expected a set of size %d to give a list of size 2 but it has %d", s.Size(), len(l)) } for _, e := range l { if !s.Has(e) { t.Errorf("listed entry %v not available in the set %s", e, s) } } } func TestSeparate(t *testing.T) { var e1, e2 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e2) s1.Separate(s2) if s1.Size() != 1 { t.Errorf("expected separated set %v have size 1 but it has %d", s1, s1.Size()) } if s1.Has(e2) { t.Errorf("separated set %v still contains %v", s1, e2) } } func TestEach(t *testing.T) { var e1, e2 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) found := make(map[[32]byte]bool) s1.Each(func(item [32]byte) bool { found[item] = true return true }) if len(found) != 2 { t.Errorf("not all items traversed only %v", found) } found = make(map[[32]byte]bool) count := 0 s1.Each(func(item [32]byte) bool { found[item] = true count++ if count > 0 { return false } return true }) if len(found) != 1 { t.Errorf("more than expected 1 items traversed %v", found) } } func TestIntersection(t *testing.T) { var e1, e2, e3 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.([32]byte); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Intersection(s1, s2) if s3.Size() != 1 || !s3.Has(e2) { t.Errorf("expected the intersection to only contain '%v' but it is %v", e2, s3.List()) } } func TestUnion(t *testing.T) { var e1, e2, e3 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.([32]byte); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Union(s1, s2) if s3.Size() != 3 || !(s3.Has(e1) && s3.Has(e2) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestDifference(t *testing.T) { var e1, e2, e3 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.([32]byte); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Difference(s1, s2) if s3.Size() != 1 || !s3.Has(e1) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestSymmetricDifference(t *testing.T) { var e1, e2, e3 [32]byte e := createRandomObject(e1) if v, ok := e.([32]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([32]byte); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.([32]byte); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := SymmetricDifference(s1, s2) if s3.Size() != 2 || !(s3.Has(e1) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func createRandomObject(i interface{}) interface{} { v, ok := quick.Value(reflect.TypeOf(i), rand.New(rand.NewSource(time.Now().UnixNano()))) if !ok { panic(fmt.Sprintf("unsupported type %v", i)) } return v.Interface() } scylladb-go-set-e560bb8/b64set/000077500000000000000000000000001337277605500162465ustar00rootroot00000000000000scylladb-go-set-e560bb8/b64set/b64set.go000066400000000000000000000143031337277605500177050ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package b64set import ( "fmt" "math" "strings" ) var ( // helpful to not write everywhere struct{}{} keyExists = struct{}{} nonExistent [64]byte ) // Set is the main set structure that holds all the data // and methods used to working with the set. type Set struct { m map[[64]byte]struct{} } // New creates and initializes a new Set. func New(ts ...[64]byte) *Set { s := NewWithSize(len(ts)) s.Add(ts...) return s } // NewWithSize creates a new Set and gives make map a size hint. func NewWithSize(size int) *Set { return &Set{make(map[[64]byte]struct{}, size)} } // Add includes the specified items (one or more) to the Set. The underlying // Set s is modified. If passed nothing it silently returns. func (s *Set) Add(items ...[64]byte) { for _, item := range items { s.m[item] = keyExists } } // Remove deletes the specified items from the Set. The underlying Set s is // modified. If passed nothing it silently returns. func (s *Set) Remove(items ...[64]byte) { for _, item := range items { delete(s.m, item) } } // Pop deletes and returns an item from the Set. The underlying Set s is // modified. If Set is empty, the zero value is returned. func (s *Set) Pop() [64]byte { for item := range s.m { delete(s.m, item) return item } return nonExistent } // Pop2 tries to delete and return an item from the Set. The underlying Set s // is modified. The second value is a bool that is true if the item existed in // the set, and false if not. If Set is empty, the zero value and false are // returned. func (s *Set) Pop2() ([64]byte, bool) { for item := range s.m { delete(s.m, item) return item, true } return nonExistent, false } // Has looks for the existence of items passed. It returns false if nothing is // passed. For multiple items it returns true only if all of the items exist. func (s *Set) Has(items ...[64]byte) bool { has := false for _, item := range items { if _, has = s.m[item]; !has { break } } return has } // HasAny looks for the existence of any of the items passed. // It returns false if nothing is passed. // For multiple items it returns true if any of the items exist. func (s *Set) HasAny(items ...[64]byte) bool { has := false for _, item := range items { if _, has = s.m[item]; has { break } } return has } // Size returns the number of items in a Set. func (s *Set) Size() int { return len(s.m) } // Clear removes all items from the Set. func (s *Set) Clear() { s.m = make(map[[64]byte]struct{}) } // IsEmpty reports whether the Set is empty. func (s *Set) IsEmpty() bool { return s.Size() == 0 } // IsEqual test whether s and t are the same in size and have the same items. func (s *Set) IsEqual(t *Set) bool { // return false if they are no the same size if s.Size() != t.Size() { return false } equal := true t.Each(func(item [64]byte) bool { _, equal = s.m[item] return equal // if false, Each() will end }) return equal } // IsSubset tests whether t is a subset of s. func (s *Set) IsSubset(t *Set) bool { if s.Size() < t.Size() { return false } subset := true t.Each(func(item [64]byte) bool { _, subset = s.m[item] return subset }) return subset } // IsSuperset tests whether t is a superset of s. func (s *Set) IsSuperset(t *Set) bool { return t.IsSubset(s) } // Each traverses the items in the Set, calling the provided function for each // Set member. Traversal will continue until all items in the Set have been // visited, or if the closure returns false. func (s *Set) Each(f func(item [64]byte) bool) { for item := range s.m { if !f(item) { break } } } // Copy returns a new Set with a copy of s. func (s *Set) Copy() *Set { u := NewWithSize(s.Size()) for item := range s.m { u.m[item] = keyExists } return u } // String returns a string representation of s func (s *Set) String() string { v := make([]string, 0, s.Size()) for item := range s.m { v = append(v, fmt.Sprintf("%v", item)) } return fmt.Sprintf("[%s]", strings.Join(v, ", ")) } // List returns a slice of all items. There is also StringSlice() and // IntSlice() methods for returning slices of type string or int. func (s *Set) List() [][64]byte { v := make([][64]byte, 0, s.Size()) for item := range s.m { v = append(v, item) } return v } // Merge is like Union, however it modifies the current Set it's applied on // with the given t Set. func (s *Set) Merge(t *Set) { for item := range t.m { s.m[item] = keyExists } } // Separate removes the Set items containing in t from Set s. Please aware that // it's not the opposite of Merge. func (s *Set) Separate(t *Set) { for item := range t.m { delete(s.m, item) } } // Union is the merger of multiple sets. It returns a new set with all the // elements present in all the sets that are passed. func Union(sets ...*Set) *Set { maxPos := -1 maxSize := 0 for i, set := range sets { if l := set.Size(); l > maxSize { maxSize = l maxPos = i } } if maxSize == 0 { return New() } u := sets[maxPos].Copy() for i, set := range sets { if i == maxPos { continue } for item := range set.m { u.m[item] = keyExists } } return u } // Difference returns a new set which contains items which are in in the first // set but not in the others. func Difference(set1 *Set, sets ...*Set) *Set { s := set1.Copy() for _, set := range sets { s.Separate(set) } return s } // Intersection returns a new set which contains items that only exist in all // given sets. func Intersection(sets ...*Set) *Set { minPos := -1 minSize := math.MaxInt64 for i, set := range sets { if l := set.Size(); l < minSize { minSize = l minPos = i } } if minSize == math.MaxInt64 || minSize == 0 { return New() } t := sets[minPos].Copy() for i, set := range sets { if i == minPos { continue } for item := range t.m { if _, has := set.m[item]; !has { delete(t.m, item) } } } return t } // SymmetricDifference returns a new set which s is the difference of items // which are in one of either, but not in both. func SymmetricDifference(s *Set, t *Set) *Set { u := Difference(s, t) v := Difference(t, s) return Union(u, v) } scylladb-go-set-e560bb8/b64set/b64set_bench_test.go000066400000000000000000000047171337277605500221130ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package b64set import ( "github.com/fatih/set" "testing" ) func BenchmarkTypeSafeSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } b.StartTimer() s := New() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExisting(b *testing.B) { b.StopTimer() var e1 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } b.StartTimer() s := New() s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExisting(b *testing.B) { b.StopTimer() var e1 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExistingMany(b *testing.B) { s := New() b.StopTimer() var e1 [64]byte for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.([64]byte); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExistingMany(b *testing.B) { s := set.New(set.NonThreadSafe) b.StopTimer() var e1 [64]byte for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.([64]byte); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetAdd(b *testing.B) { b.StopTimer() var e [64]byte s := New() objs := make([][64]byte, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.([64]byte); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } func BenchmarkInterfaceSetAdd(b *testing.B) { b.StopTimer() var e [64]byte s := set.New(set.NonThreadSafe) objs := make([][64]byte, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.([64]byte); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } scylladb-go-set-e560bb8/b64set/b64set_test.go000066400000000000000000000252661337277605500207560ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package b64set import ( "fmt" "math/rand" "reflect" "strings" "testing" "testing/quick" "time" ) func TestAdd(t *testing.T) { var e1, e2 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if len(s.m) != 2 { t.Errorf("expected 2 entries, got %d", len(s.m)) } } func TestRemove(t *testing.T) { var e1, e2 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Remove(e1) if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if _, ok := s.m[e2]; !ok { t.Errorf("wrong entry %v removed, expected %v", e1, e2) } } func TestPop(t *testing.T) { var e1, e2 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } s := New() popped := s.Pop() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } s.Add(e1) s.Add(e2) s.Pop() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } } func TestPop2(t *testing.T) { var e1, e2 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } s := New() popped, found := s.Pop2() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } if found { t.Errorf("set is empty, no element should have been found") } s.Add(e1) s.Add(e2) _, found = s.Pop2() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if !found { t.Errorf("expected to find an entry") } } func TestHas(t *testing.T) { var e1, e2, e3 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.Has(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.Has(e2) { t.Errorf("expected the set to contain %v", e2) } if s.Has(e3) { t.Errorf("did not expect the set to contain %v", e3) } } func TestHasAny(t *testing.T) { var e1, e2, e3 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.HasAny(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.HasAny(e2) { t.Errorf("expected the set to contain %v", e2) } if s.HasAny(e3) { t.Errorf("did not expect the set to contain %v", e3) } if !s.HasAny(e1, e3) { t.Errorf("expected the set to contain %v", e1) } } func TestSize(t *testing.T) { var e1, e2 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if s.Size() != 2 { t.Errorf("expected the set size to be 2 but it was %d", s.Size()) } } func TestClear(t *testing.T) { var e1, e2 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Clear() if s.Size() != 0 { t.Errorf("expected the cleared set size to be 0 but it was %d", s.Size()) } } func TestIsEmpty(t *testing.T) { var e1, e2 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } s := New() if !s.IsEmpty() { t.Errorf("expected new set to be empty but it had %d elements", s.Size()) } s.Add(e1) s.Add(e2) if s.IsEmpty() { t.Error("expected a set with added items to not be empty") } } func TestIsEqual(t *testing.T) { var e1, e2 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } s1 := New() s2 := New() if !s1.IsEqual(s2) { t.Error("expected 2 new sets to be equal") } s1.Add(e1) s1.Add(e2) if s1.IsEqual(s2) { t.Errorf("expected 2 different sets to be equal, %v, %v", s1, s2) } s2.Add(e1) s2.Add(e2) if !s1.IsEqual(s2) { t.Error("expected 2 sets with the same items added to be equal") } } func TestIsSubset(t *testing.T) { var e1, e2, e3 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e3 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s1.IsSubset(s2) { t.Errorf("expected %v to be a subset of %v", s2, s1) } s2.Add(e2) s2.Add(e3) if s1.IsSubset(s2) { t.Errorf("expected %v not to be a subset of %v", s2, s1) } } func TestIsSuperset(t *testing.T) { var e1, e2 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s2.IsSuperset(s1) { t.Errorf("expected %v to be a super set of %v", s1, s2) } } func TestCopy(t *testing.T) { var e1, e2 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := s1.Copy() if !s2.IsEqual(s1) { t.Errorf("expected %v to be equal to %v after copy", s1, s2) } } func TestString(t *testing.T) { var e1 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } s1 := New() s1.Add(e1) s := s1.String() if s == "" { t.Errorf("expected string representation %v to exist", s) } if !strings.HasPrefix(s, "[") && !strings.HasSuffix(s, "]") { t.Errorf("expected string representation %v to start with '[' and end with ']'", s) } } func TestMerge(t *testing.T) { var e1, e2 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s2.Add(e2) s1.Merge(s2) if s1.Size() != 2 { t.Errorf("expected merged set %v have size 2 but it has %d", s1, s1.Size()) } } func TestList(t *testing.T) { var e1, e2 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) l := s.List() if len(l) != s.Size() { t.Errorf("expected a set of size %d to give a list of size 2 but it has %d", s.Size(), len(l)) } for _, e := range l { if !s.Has(e) { t.Errorf("listed entry %v not available in the set %s", e, s) } } } func TestSeparate(t *testing.T) { var e1, e2 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e2) s1.Separate(s2) if s1.Size() != 1 { t.Errorf("expected separated set %v have size 1 but it has %d", s1, s1.Size()) } if s1.Has(e2) { t.Errorf("separated set %v still contains %v", s1, e2) } } func TestEach(t *testing.T) { var e1, e2 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) found := make(map[[64]byte]bool) s1.Each(func(item [64]byte) bool { found[item] = true return true }) if len(found) != 2 { t.Errorf("not all items traversed only %v", found) } found = make(map[[64]byte]bool) count := 0 s1.Each(func(item [64]byte) bool { found[item] = true count++ if count > 0 { return false } return true }) if len(found) != 1 { t.Errorf("more than expected 1 items traversed %v", found) } } func TestIntersection(t *testing.T) { var e1, e2, e3 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.([64]byte); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Intersection(s1, s2) if s3.Size() != 1 || !s3.Has(e2) { t.Errorf("expected the intersection to only contain '%v' but it is %v", e2, s3.List()) } } func TestUnion(t *testing.T) { var e1, e2, e3 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.([64]byte); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Union(s1, s2) if s3.Size() != 3 || !(s3.Has(e1) && s3.Has(e2) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestDifference(t *testing.T) { var e1, e2, e3 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.([64]byte); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Difference(s1, s2) if s3.Size() != 1 || !s3.Has(e1) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestSymmetricDifference(t *testing.T) { var e1, e2, e3 [64]byte e := createRandomObject(e1) if v, ok := e.([64]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([64]byte); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.([64]byte); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := SymmetricDifference(s1, s2) if s3.Size() != 2 || !(s3.Has(e1) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func createRandomObject(i interface{}) interface{} { v, ok := quick.Value(reflect.TypeOf(i), rand.New(rand.NewSource(time.Now().UnixNano()))) if !ok { panic(fmt.Sprintf("unsupported type %v", i)) } return v.Interface() } scylladb-go-set-e560bb8/b8set/000077500000000000000000000000001337277605500161645ustar00rootroot00000000000000scylladb-go-set-e560bb8/b8set/b8set.go000066400000000000000000000142621337277605500175450ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package b8set import ( "fmt" "math" "strings" ) var ( // helpful to not write everywhere struct{}{} keyExists = struct{}{} nonExistent [8]byte ) // Set is the main set structure that holds all the data // and methods used to working with the set. type Set struct { m map[[8]byte]struct{} } // New creates and initializes a new Set. func New(ts ...[8]byte) *Set { s := NewWithSize(len(ts)) s.Add(ts...) return s } // NewWithSize creates a new Set and gives make map a size hint. func NewWithSize(size int) *Set { return &Set{make(map[[8]byte]struct{}, size)} } // Add includes the specified items (one or more) to the Set. The underlying // Set s is modified. If passed nothing it silently returns. func (s *Set) Add(items ...[8]byte) { for _, item := range items { s.m[item] = keyExists } } // Remove deletes the specified items from the Set. The underlying Set s is // modified. If passed nothing it silently returns. func (s *Set) Remove(items ...[8]byte) { for _, item := range items { delete(s.m, item) } } // Pop deletes and returns an item from the Set. The underlying Set s is // modified. If Set is empty, the zero value is returned. func (s *Set) Pop() [8]byte { for item := range s.m { delete(s.m, item) return item } return nonExistent } // Pop2 tries to delete and return an item from the Set. The underlying Set s // is modified. The second value is a bool that is true if the item existed in // the set, and false if not. If Set is empty, the zero value and false are // returned. func (s *Set) Pop2() ([8]byte, bool) { for item := range s.m { delete(s.m, item) return item, true } return nonExistent, false } // Has looks for the existence of items passed. It returns false if nothing is // passed. For multiple items it returns true only if all of the items exist. func (s *Set) Has(items ...[8]byte) bool { has := false for _, item := range items { if _, has = s.m[item]; !has { break } } return has } // HasAny looks for the existence of any of the items passed. // It returns false if nothing is passed. // For multiple items it returns true if any of the items exist. func (s *Set) HasAny(items ...[8]byte) bool { has := false for _, item := range items { if _, has = s.m[item]; has { break } } return has } // Size returns the number of items in a Set. func (s *Set) Size() int { return len(s.m) } // Clear removes all items from the Set. func (s *Set) Clear() { s.m = make(map[[8]byte]struct{}) } // IsEmpty reports whether the Set is empty. func (s *Set) IsEmpty() bool { return s.Size() == 0 } // IsEqual test whether s and t are the same in size and have the same items. func (s *Set) IsEqual(t *Set) bool { // return false if they are no the same size if s.Size() != t.Size() { return false } equal := true t.Each(func(item [8]byte) bool { _, equal = s.m[item] return equal // if false, Each() will end }) return equal } // IsSubset tests whether t is a subset of s. func (s *Set) IsSubset(t *Set) bool { if s.Size() < t.Size() { return false } subset := true t.Each(func(item [8]byte) bool { _, subset = s.m[item] return subset }) return subset } // IsSuperset tests whether t is a superset of s. func (s *Set) IsSuperset(t *Set) bool { return t.IsSubset(s) } // Each traverses the items in the Set, calling the provided function for each // Set member. Traversal will continue until all items in the Set have been // visited, or if the closure returns false. func (s *Set) Each(f func(item [8]byte) bool) { for item := range s.m { if !f(item) { break } } } // Copy returns a new Set with a copy of s. func (s *Set) Copy() *Set { u := NewWithSize(s.Size()) for item := range s.m { u.m[item] = keyExists } return u } // String returns a string representation of s func (s *Set) String() string { v := make([]string, 0, s.Size()) for item := range s.m { v = append(v, fmt.Sprintf("%v", item)) } return fmt.Sprintf("[%s]", strings.Join(v, ", ")) } // List returns a slice of all items. There is also StringSlice() and // IntSlice() methods for returning slices of type string or int. func (s *Set) List() [][8]byte { v := make([][8]byte, 0, s.Size()) for item := range s.m { v = append(v, item) } return v } // Merge is like Union, however it modifies the current Set it's applied on // with the given t Set. func (s *Set) Merge(t *Set) { for item := range t.m { s.m[item] = keyExists } } // Separate removes the Set items containing in t from Set s. Please aware that // it's not the opposite of Merge. func (s *Set) Separate(t *Set) { for item := range t.m { delete(s.m, item) } } // Union is the merger of multiple sets. It returns a new set with all the // elements present in all the sets that are passed. func Union(sets ...*Set) *Set { maxPos := -1 maxSize := 0 for i, set := range sets { if l := set.Size(); l > maxSize { maxSize = l maxPos = i } } if maxSize == 0 { return New() } u := sets[maxPos].Copy() for i, set := range sets { if i == maxPos { continue } for item := range set.m { u.m[item] = keyExists } } return u } // Difference returns a new set which contains items which are in in the first // set but not in the others. func Difference(set1 *Set, sets ...*Set) *Set { s := set1.Copy() for _, set := range sets { s.Separate(set) } return s } // Intersection returns a new set which contains items that only exist in all // given sets. func Intersection(sets ...*Set) *Set { minPos := -1 minSize := math.MaxInt64 for i, set := range sets { if l := set.Size(); l < minSize { minSize = l minPos = i } } if minSize == math.MaxInt64 || minSize == 0 { return New() } t := sets[minPos].Copy() for i, set := range sets { if i == minPos { continue } for item := range t.m { if _, has := set.m[item]; !has { delete(t.m, item) } } } return t } // SymmetricDifference returns a new set which s is the difference of items // which are in one of either, but not in both. func SymmetricDifference(s *Set, t *Set) *Set { u := Difference(s, t) v := Difference(t, s) return Union(u, v) } scylladb-go-set-e560bb8/b8set/b8set_bench_test.go000066400000000000000000000046741337277605500217510ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package b8set import ( "github.com/fatih/set" "testing" ) func BenchmarkTypeSafeSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } b.StartTimer() s := New() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExisting(b *testing.B) { b.StopTimer() var e1 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } b.StartTimer() s := New() s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExisting(b *testing.B) { b.StopTimer() var e1 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExistingMany(b *testing.B) { s := New() b.StopTimer() var e1 [8]byte for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.([8]byte); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExistingMany(b *testing.B) { s := set.New(set.NonThreadSafe) b.StopTimer() var e1 [8]byte for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.([8]byte); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetAdd(b *testing.B) { b.StopTimer() var e [8]byte s := New() objs := make([][8]byte, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.([8]byte); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } func BenchmarkInterfaceSetAdd(b *testing.B) { b.StopTimer() var e [8]byte s := set.New(set.NonThreadSafe) objs := make([][8]byte, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.([8]byte); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } scylladb-go-set-e560bb8/b8set/b8set_test.go000066400000000000000000000251511337277605500206030ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package b8set import ( "fmt" "math/rand" "reflect" "strings" "testing" "testing/quick" "time" ) func TestAdd(t *testing.T) { var e1, e2 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if len(s.m) != 2 { t.Errorf("expected 2 entries, got %d", len(s.m)) } } func TestRemove(t *testing.T) { var e1, e2 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Remove(e1) if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if _, ok := s.m[e2]; !ok { t.Errorf("wrong entry %v removed, expected %v", e1, e2) } } func TestPop(t *testing.T) { var e1, e2 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } s := New() popped := s.Pop() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } s.Add(e1) s.Add(e2) s.Pop() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } } func TestPop2(t *testing.T) { var e1, e2 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } s := New() popped, found := s.Pop2() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } if found { t.Errorf("set is empty, no element should have been found") } s.Add(e1) s.Add(e2) _, found = s.Pop2() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if !found { t.Errorf("expected to find an entry") } } func TestHas(t *testing.T) { var e1, e2, e3 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.Has(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.Has(e2) { t.Errorf("expected the set to contain %v", e2) } if s.Has(e3) { t.Errorf("did not expect the set to contain %v", e3) } } func TestHasAny(t *testing.T) { var e1, e2, e3 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.HasAny(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.HasAny(e2) { t.Errorf("expected the set to contain %v", e2) } if s.HasAny(e3) { t.Errorf("did not expect the set to contain %v", e3) } if !s.HasAny(e1, e3) { t.Errorf("expected the set to contain %v", e1) } } func TestSize(t *testing.T) { var e1, e2 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if s.Size() != 2 { t.Errorf("expected the set size to be 2 but it was %d", s.Size()) } } func TestClear(t *testing.T) { var e1, e2 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Clear() if s.Size() != 0 { t.Errorf("expected the cleared set size to be 0 but it was %d", s.Size()) } } func TestIsEmpty(t *testing.T) { var e1, e2 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } s := New() if !s.IsEmpty() { t.Errorf("expected new set to be empty but it had %d elements", s.Size()) } s.Add(e1) s.Add(e2) if s.IsEmpty() { t.Error("expected a set with added items to not be empty") } } func TestIsEqual(t *testing.T) { var e1, e2 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } s1 := New() s2 := New() if !s1.IsEqual(s2) { t.Error("expected 2 new sets to be equal") } s1.Add(e1) s1.Add(e2) if s1.IsEqual(s2) { t.Errorf("expected 2 different sets to be equal, %v, %v", s1, s2) } s2.Add(e1) s2.Add(e2) if !s1.IsEqual(s2) { t.Error("expected 2 sets with the same items added to be equal") } } func TestIsSubset(t *testing.T) { var e1, e2, e3 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e3 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s1.IsSubset(s2) { t.Errorf("expected %v to be a subset of %v", s2, s1) } s2.Add(e2) s2.Add(e3) if s1.IsSubset(s2) { t.Errorf("expected %v not to be a subset of %v", s2, s1) } } func TestIsSuperset(t *testing.T) { var e1, e2 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s2.IsSuperset(s1) { t.Errorf("expected %v to be a super set of %v", s1, s2) } } func TestCopy(t *testing.T) { var e1, e2 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := s1.Copy() if !s2.IsEqual(s1) { t.Errorf("expected %v to be equal to %v after copy", s1, s2) } } func TestString(t *testing.T) { var e1 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } s1 := New() s1.Add(e1) s := s1.String() if s == "" { t.Errorf("expected string representation %v to exist", s) } if !strings.HasPrefix(s, "[") && !strings.HasSuffix(s, "]") { t.Errorf("expected string representation %v to start with '[' and end with ']'", s) } } func TestMerge(t *testing.T) { var e1, e2 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s2.Add(e2) s1.Merge(s2) if s1.Size() != 2 { t.Errorf("expected merged set %v have size 2 but it has %d", s1, s1.Size()) } } func TestList(t *testing.T) { var e1, e2 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) l := s.List() if len(l) != s.Size() { t.Errorf("expected a set of size %d to give a list of size 2 but it has %d", s.Size(), len(l)) } for _, e := range l { if !s.Has(e) { t.Errorf("listed entry %v not available in the set %s", e, s) } } } func TestSeparate(t *testing.T) { var e1, e2 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e2) s1.Separate(s2) if s1.Size() != 1 { t.Errorf("expected separated set %v have size 1 but it has %d", s1, s1.Size()) } if s1.Has(e2) { t.Errorf("separated set %v still contains %v", s1, e2) } } func TestEach(t *testing.T) { var e1, e2 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) found := make(map[[8]byte]bool) s1.Each(func(item [8]byte) bool { found[item] = true return true }) if len(found) != 2 { t.Errorf("not all items traversed only %v", found) } found = make(map[[8]byte]bool) count := 0 s1.Each(func(item [8]byte) bool { found[item] = true count++ if count > 0 { return false } return true }) if len(found) != 1 { t.Errorf("more than expected 1 items traversed %v", found) } } func TestIntersection(t *testing.T) { var e1, e2, e3 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.([8]byte); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Intersection(s1, s2) if s3.Size() != 1 || !s3.Has(e2) { t.Errorf("expected the intersection to only contain '%v' but it is %v", e2, s3.List()) } } func TestUnion(t *testing.T) { var e1, e2, e3 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.([8]byte); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Union(s1, s2) if s3.Size() != 3 || !(s3.Has(e1) && s3.Has(e2) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestDifference(t *testing.T) { var e1, e2, e3 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.([8]byte); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Difference(s1, s2) if s3.Size() != 1 || !s3.Has(e1) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestSymmetricDifference(t *testing.T) { var e1, e2, e3 [8]byte e := createRandomObject(e1) if v, ok := e.([8]byte); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.([8]byte); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.([8]byte); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := SymmetricDifference(s1, s2) if s3.Size() != 2 || !(s3.Has(e1) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func createRandomObject(i interface{}) interface{} { v, ok := quick.Value(reflect.TypeOf(i), rand.New(rand.NewSource(time.Now().UnixNano()))) if !ok { panic(fmt.Sprintf("unsupported type %v", i)) } return v.Interface() } scylladb-go-set-e560bb8/doc.go000066400000000000000000000005271337277605500162370ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found in the LICENSE file. // Package set is a type-safe, zero-allocation port of the excellent package // fatih/set. It contains sets for most of the basic types and you can generate // set for your own types with ease. package set scylladb-go-set-e560bb8/f32set/000077500000000000000000000000001337277605500162455ustar00rootroot00000000000000scylladb-go-set-e560bb8/f32set/f32set.go000066400000000000000000000142631337277605500177100ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package f32set import ( "fmt" "math" "strings" ) var ( // helpful to not write everywhere struct{}{} keyExists = struct{}{} nonExistent float32 ) // Set is the main set structure that holds all the data // and methods used to working with the set. type Set struct { m map[float32]struct{} } // New creates and initializes a new Set. func New(ts ...float32) *Set { s := NewWithSize(len(ts)) s.Add(ts...) return s } // NewWithSize creates a new Set and gives make map a size hint. func NewWithSize(size int) *Set { return &Set{make(map[float32]struct{}, size)} } // Add includes the specified items (one or more) to the Set. The underlying // Set s is modified. If passed nothing it silently returns. func (s *Set) Add(items ...float32) { for _, item := range items { s.m[item] = keyExists } } // Remove deletes the specified items from the Set. The underlying Set s is // modified. If passed nothing it silently returns. func (s *Set) Remove(items ...float32) { for _, item := range items { delete(s.m, item) } } // Pop deletes and returns an item from the Set. The underlying Set s is // modified. If Set is empty, the zero value is returned. func (s *Set) Pop() float32 { for item := range s.m { delete(s.m, item) return item } return nonExistent } // Pop2 tries to delete and return an item from the Set. The underlying Set s // is modified. The second value is a bool that is true if the item existed in // the set, and false if not. If Set is empty, the zero value and false are // returned. func (s *Set) Pop2() (float32, bool) { for item := range s.m { delete(s.m, item) return item, true } return nonExistent, false } // Has looks for the existence of items passed. It returns false if nothing is // passed. For multiple items it returns true only if all of the items exist. func (s *Set) Has(items ...float32) bool { has := false for _, item := range items { if _, has = s.m[item]; !has { break } } return has } // HasAny looks for the existence of any of the items passed. // It returns false if nothing is passed. // For multiple items it returns true if any of the items exist. func (s *Set) HasAny(items ...float32) bool { has := false for _, item := range items { if _, has = s.m[item]; has { break } } return has } // Size returns the number of items in a Set. func (s *Set) Size() int { return len(s.m) } // Clear removes all items from the Set. func (s *Set) Clear() { s.m = make(map[float32]struct{}) } // IsEmpty reports whether the Set is empty. func (s *Set) IsEmpty() bool { return s.Size() == 0 } // IsEqual test whether s and t are the same in size and have the same items. func (s *Set) IsEqual(t *Set) bool { // return false if they are no the same size if s.Size() != t.Size() { return false } equal := true t.Each(func(item float32) bool { _, equal = s.m[item] return equal // if false, Each() will end }) return equal } // IsSubset tests whether t is a subset of s. func (s *Set) IsSubset(t *Set) bool { if s.Size() < t.Size() { return false } subset := true t.Each(func(item float32) bool { _, subset = s.m[item] return subset }) return subset } // IsSuperset tests whether t is a superset of s. func (s *Set) IsSuperset(t *Set) bool { return t.IsSubset(s) } // Each traverses the items in the Set, calling the provided function for each // Set member. Traversal will continue until all items in the Set have been // visited, or if the closure returns false. func (s *Set) Each(f func(item float32) bool) { for item := range s.m { if !f(item) { break } } } // Copy returns a new Set with a copy of s. func (s *Set) Copy() *Set { u := NewWithSize(s.Size()) for item := range s.m { u.m[item] = keyExists } return u } // String returns a string representation of s func (s *Set) String() string { v := make([]string, 0, s.Size()) for item := range s.m { v = append(v, fmt.Sprintf("%v", item)) } return fmt.Sprintf("[%s]", strings.Join(v, ", ")) } // List returns a slice of all items. There is also StringSlice() and // IntSlice() methods for returning slices of type string or int. func (s *Set) List() []float32 { v := make([]float32, 0, s.Size()) for item := range s.m { v = append(v, item) } return v } // Merge is like Union, however it modifies the current Set it's applied on // with the given t Set. func (s *Set) Merge(t *Set) { for item := range t.m { s.m[item] = keyExists } } // Separate removes the Set items containing in t from Set s. Please aware that // it's not the opposite of Merge. func (s *Set) Separate(t *Set) { for item := range t.m { delete(s.m, item) } } // Union is the merger of multiple sets. It returns a new set with all the // elements present in all the sets that are passed. func Union(sets ...*Set) *Set { maxPos := -1 maxSize := 0 for i, set := range sets { if l := set.Size(); l > maxSize { maxSize = l maxPos = i } } if maxSize == 0 { return New() } u := sets[maxPos].Copy() for i, set := range sets { if i == maxPos { continue } for item := range set.m { u.m[item] = keyExists } } return u } // Difference returns a new set which contains items which are in in the first // set but not in the others. func Difference(set1 *Set, sets ...*Set) *Set { s := set1.Copy() for _, set := range sets { s.Separate(set) } return s } // Intersection returns a new set which contains items that only exist in all // given sets. func Intersection(sets ...*Set) *Set { minPos := -1 minSize := math.MaxInt64 for i, set := range sets { if l := set.Size(); l < minSize { minSize = l minPos = i } } if minSize == math.MaxInt64 || minSize == 0 { return New() } t := sets[minPos].Copy() for i, set := range sets { if i == minPos { continue } for item := range t.m { if _, has := set.m[item]; !has { delete(t.m, item) } } } return t } // SymmetricDifference returns a new set which s is the difference of items // which are in one of either, but not in both. func SymmetricDifference(s *Set, t *Set) *Set { u := Difference(s, t) v := Difference(t, s) return Union(u, v) } scylladb-go-set-e560bb8/f32set/f32set_bench_test.go000066400000000000000000000046751337277605500221140ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package f32set import ( "github.com/fatih/set" "testing" ) func BenchmarkTypeSafeSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } b.StartTimer() s := New() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExisting(b *testing.B) { b.StopTimer() var e1 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } b.StartTimer() s := New() s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExisting(b *testing.B) { b.StopTimer() var e1 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExistingMany(b *testing.B) { s := New() b.StopTimer() var e1 float32 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(float32); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExistingMany(b *testing.B) { s := set.New(set.NonThreadSafe) b.StopTimer() var e1 float32 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(float32); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetAdd(b *testing.B) { b.StopTimer() var e float32 s := New() objs := make([]float32, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(float32); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } func BenchmarkInterfaceSetAdd(b *testing.B) { b.StopTimer() var e float32 s := set.New(set.NonThreadSafe) objs := make([]float32, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(float32); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } scylladb-go-set-e560bb8/f32set/f32set_test.go000066400000000000000000000251521337277605500207460ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package f32set import ( "fmt" "math/rand" "reflect" "strings" "testing" "testing/quick" "time" ) func TestAdd(t *testing.T) { var e1, e2 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if len(s.m) != 2 { t.Errorf("expected 2 entries, got %d", len(s.m)) } } func TestRemove(t *testing.T) { var e1, e2 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Remove(e1) if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if _, ok := s.m[e2]; !ok { t.Errorf("wrong entry %v removed, expected %v", e1, e2) } } func TestPop(t *testing.T) { var e1, e2 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } s := New() popped := s.Pop() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } s.Add(e1) s.Add(e2) s.Pop() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } } func TestPop2(t *testing.T) { var e1, e2 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } s := New() popped, found := s.Pop2() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } if found { t.Errorf("set is empty, no element should have been found") } s.Add(e1) s.Add(e2) _, found = s.Pop2() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if !found { t.Errorf("expected to find an entry") } } func TestHas(t *testing.T) { var e1, e2, e3 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.Has(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.Has(e2) { t.Errorf("expected the set to contain %v", e2) } if s.Has(e3) { t.Errorf("did not expect the set to contain %v", e3) } } func TestHasAny(t *testing.T) { var e1, e2, e3 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.HasAny(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.HasAny(e2) { t.Errorf("expected the set to contain %v", e2) } if s.HasAny(e3) { t.Errorf("did not expect the set to contain %v", e3) } if !s.HasAny(e1, e3) { t.Errorf("expected the set to contain %v", e1) } } func TestSize(t *testing.T) { var e1, e2 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if s.Size() != 2 { t.Errorf("expected the set size to be 2 but it was %d", s.Size()) } } func TestClear(t *testing.T) { var e1, e2 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Clear() if s.Size() != 0 { t.Errorf("expected the cleared set size to be 0 but it was %d", s.Size()) } } func TestIsEmpty(t *testing.T) { var e1, e2 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } s := New() if !s.IsEmpty() { t.Errorf("expected new set to be empty but it had %d elements", s.Size()) } s.Add(e1) s.Add(e2) if s.IsEmpty() { t.Error("expected a set with added items to not be empty") } } func TestIsEqual(t *testing.T) { var e1, e2 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } s1 := New() s2 := New() if !s1.IsEqual(s2) { t.Error("expected 2 new sets to be equal") } s1.Add(e1) s1.Add(e2) if s1.IsEqual(s2) { t.Errorf("expected 2 different sets to be equal, %v, %v", s1, s2) } s2.Add(e1) s2.Add(e2) if !s1.IsEqual(s2) { t.Error("expected 2 sets with the same items added to be equal") } } func TestIsSubset(t *testing.T) { var e1, e2, e3 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e3 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s1.IsSubset(s2) { t.Errorf("expected %v to be a subset of %v", s2, s1) } s2.Add(e2) s2.Add(e3) if s1.IsSubset(s2) { t.Errorf("expected %v not to be a subset of %v", s2, s1) } } func TestIsSuperset(t *testing.T) { var e1, e2 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s2.IsSuperset(s1) { t.Errorf("expected %v to be a super set of %v", s1, s2) } } func TestCopy(t *testing.T) { var e1, e2 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := s1.Copy() if !s2.IsEqual(s1) { t.Errorf("expected %v to be equal to %v after copy", s1, s2) } } func TestString(t *testing.T) { var e1 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } s1 := New() s1.Add(e1) s := s1.String() if s == "" { t.Errorf("expected string representation %v to exist", s) } if !strings.HasPrefix(s, "[") && !strings.HasSuffix(s, "]") { t.Errorf("expected string representation %v to start with '[' and end with ']'", s) } } func TestMerge(t *testing.T) { var e1, e2 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s2.Add(e2) s1.Merge(s2) if s1.Size() != 2 { t.Errorf("expected merged set %v have size 2 but it has %d", s1, s1.Size()) } } func TestList(t *testing.T) { var e1, e2 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) l := s.List() if len(l) != s.Size() { t.Errorf("expected a set of size %d to give a list of size 2 but it has %d", s.Size(), len(l)) } for _, e := range l { if !s.Has(e) { t.Errorf("listed entry %v not available in the set %s", e, s) } } } func TestSeparate(t *testing.T) { var e1, e2 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e2) s1.Separate(s2) if s1.Size() != 1 { t.Errorf("expected separated set %v have size 1 but it has %d", s1, s1.Size()) } if s1.Has(e2) { t.Errorf("separated set %v still contains %v", s1, e2) } } func TestEach(t *testing.T) { var e1, e2 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) found := make(map[float32]bool) s1.Each(func(item float32) bool { found[item] = true return true }) if len(found) != 2 { t.Errorf("not all items traversed only %v", found) } found = make(map[float32]bool) count := 0 s1.Each(func(item float32) bool { found[item] = true count++ if count > 0 { return false } return true }) if len(found) != 1 { t.Errorf("more than expected 1 items traversed %v", found) } } func TestIntersection(t *testing.T) { var e1, e2, e3 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(float32); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Intersection(s1, s2) if s3.Size() != 1 || !s3.Has(e2) { t.Errorf("expected the intersection to only contain '%v' but it is %v", e2, s3.List()) } } func TestUnion(t *testing.T) { var e1, e2, e3 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(float32); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Union(s1, s2) if s3.Size() != 3 || !(s3.Has(e1) && s3.Has(e2) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestDifference(t *testing.T) { var e1, e2, e3 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(float32); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Difference(s1, s2) if s3.Size() != 1 || !s3.Has(e1) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestSymmetricDifference(t *testing.T) { var e1, e2, e3 float32 e := createRandomObject(e1) if v, ok := e.(float32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float32); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(float32); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := SymmetricDifference(s1, s2) if s3.Size() != 2 || !(s3.Has(e1) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func createRandomObject(i interface{}) interface{} { v, ok := quick.Value(reflect.TypeOf(i), rand.New(rand.NewSource(time.Now().UnixNano()))) if !ok { panic(fmt.Sprintf("unsupported type %v", i)) } return v.Interface() } scylladb-go-set-e560bb8/f64set/000077500000000000000000000000001337277605500162525ustar00rootroot00000000000000scylladb-go-set-e560bb8/f64set/f64set.go000066400000000000000000000142631337277605500177220ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package f64set import ( "fmt" "math" "strings" ) var ( // helpful to not write everywhere struct{}{} keyExists = struct{}{} nonExistent float64 ) // Set is the main set structure that holds all the data // and methods used to working with the set. type Set struct { m map[float64]struct{} } // New creates and initializes a new Set. func New(ts ...float64) *Set { s := NewWithSize(len(ts)) s.Add(ts...) return s } // NewWithSize creates a new Set and gives make map a size hint. func NewWithSize(size int) *Set { return &Set{make(map[float64]struct{}, size)} } // Add includes the specified items (one or more) to the Set. The underlying // Set s is modified. If passed nothing it silently returns. func (s *Set) Add(items ...float64) { for _, item := range items { s.m[item] = keyExists } } // Remove deletes the specified items from the Set. The underlying Set s is // modified. If passed nothing it silently returns. func (s *Set) Remove(items ...float64) { for _, item := range items { delete(s.m, item) } } // Pop deletes and returns an item from the Set. The underlying Set s is // modified. If Set is empty, the zero value is returned. func (s *Set) Pop() float64 { for item := range s.m { delete(s.m, item) return item } return nonExistent } // Pop2 tries to delete and return an item from the Set. The underlying Set s // is modified. The second value is a bool that is true if the item existed in // the set, and false if not. If Set is empty, the zero value and false are // returned. func (s *Set) Pop2() (float64, bool) { for item := range s.m { delete(s.m, item) return item, true } return nonExistent, false } // Has looks for the existence of items passed. It returns false if nothing is // passed. For multiple items it returns true only if all of the items exist. func (s *Set) Has(items ...float64) bool { has := false for _, item := range items { if _, has = s.m[item]; !has { break } } return has } // HasAny looks for the existence of any of the items passed. // It returns false if nothing is passed. // For multiple items it returns true if any of the items exist. func (s *Set) HasAny(items ...float64) bool { has := false for _, item := range items { if _, has = s.m[item]; has { break } } return has } // Size returns the number of items in a Set. func (s *Set) Size() int { return len(s.m) } // Clear removes all items from the Set. func (s *Set) Clear() { s.m = make(map[float64]struct{}) } // IsEmpty reports whether the Set is empty. func (s *Set) IsEmpty() bool { return s.Size() == 0 } // IsEqual test whether s and t are the same in size and have the same items. func (s *Set) IsEqual(t *Set) bool { // return false if they are no the same size if s.Size() != t.Size() { return false } equal := true t.Each(func(item float64) bool { _, equal = s.m[item] return equal // if false, Each() will end }) return equal } // IsSubset tests whether t is a subset of s. func (s *Set) IsSubset(t *Set) bool { if s.Size() < t.Size() { return false } subset := true t.Each(func(item float64) bool { _, subset = s.m[item] return subset }) return subset } // IsSuperset tests whether t is a superset of s. func (s *Set) IsSuperset(t *Set) bool { return t.IsSubset(s) } // Each traverses the items in the Set, calling the provided function for each // Set member. Traversal will continue until all items in the Set have been // visited, or if the closure returns false. func (s *Set) Each(f func(item float64) bool) { for item := range s.m { if !f(item) { break } } } // Copy returns a new Set with a copy of s. func (s *Set) Copy() *Set { u := NewWithSize(s.Size()) for item := range s.m { u.m[item] = keyExists } return u } // String returns a string representation of s func (s *Set) String() string { v := make([]string, 0, s.Size()) for item := range s.m { v = append(v, fmt.Sprintf("%v", item)) } return fmt.Sprintf("[%s]", strings.Join(v, ", ")) } // List returns a slice of all items. There is also StringSlice() and // IntSlice() methods for returning slices of type string or int. func (s *Set) List() []float64 { v := make([]float64, 0, s.Size()) for item := range s.m { v = append(v, item) } return v } // Merge is like Union, however it modifies the current Set it's applied on // with the given t Set. func (s *Set) Merge(t *Set) { for item := range t.m { s.m[item] = keyExists } } // Separate removes the Set items containing in t from Set s. Please aware that // it's not the opposite of Merge. func (s *Set) Separate(t *Set) { for item := range t.m { delete(s.m, item) } } // Union is the merger of multiple sets. It returns a new set with all the // elements present in all the sets that are passed. func Union(sets ...*Set) *Set { maxPos := -1 maxSize := 0 for i, set := range sets { if l := set.Size(); l > maxSize { maxSize = l maxPos = i } } if maxSize == 0 { return New() } u := sets[maxPos].Copy() for i, set := range sets { if i == maxPos { continue } for item := range set.m { u.m[item] = keyExists } } return u } // Difference returns a new set which contains items which are in in the first // set but not in the others. func Difference(set1 *Set, sets ...*Set) *Set { s := set1.Copy() for _, set := range sets { s.Separate(set) } return s } // Intersection returns a new set which contains items that only exist in all // given sets. func Intersection(sets ...*Set) *Set { minPos := -1 minSize := math.MaxInt64 for i, set := range sets { if l := set.Size(); l < minSize { minSize = l minPos = i } } if minSize == math.MaxInt64 || minSize == 0 { return New() } t := sets[minPos].Copy() for i, set := range sets { if i == minPos { continue } for item := range t.m { if _, has := set.m[item]; !has { delete(t.m, item) } } } return t } // SymmetricDifference returns a new set which s is the difference of items // which are in one of either, but not in both. func SymmetricDifference(s *Set, t *Set) *Set { u := Difference(s, t) v := Difference(t, s) return Union(u, v) } scylladb-go-set-e560bb8/f64set/f64set_bench_test.go000066400000000000000000000046751337277605500221260ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package f64set import ( "github.com/fatih/set" "testing" ) func BenchmarkTypeSafeSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } b.StartTimer() s := New() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExisting(b *testing.B) { b.StopTimer() var e1 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } b.StartTimer() s := New() s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExisting(b *testing.B) { b.StopTimer() var e1 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExistingMany(b *testing.B) { s := New() b.StopTimer() var e1 float64 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(float64); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExistingMany(b *testing.B) { s := set.New(set.NonThreadSafe) b.StopTimer() var e1 float64 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(float64); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetAdd(b *testing.B) { b.StopTimer() var e float64 s := New() objs := make([]float64, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(float64); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } func BenchmarkInterfaceSetAdd(b *testing.B) { b.StopTimer() var e float64 s := set.New(set.NonThreadSafe) objs := make([]float64, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(float64); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } scylladb-go-set-e560bb8/f64set/f64set_test.go000066400000000000000000000251521337277605500207600ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package f64set import ( "fmt" "math/rand" "reflect" "strings" "testing" "testing/quick" "time" ) func TestAdd(t *testing.T) { var e1, e2 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if len(s.m) != 2 { t.Errorf("expected 2 entries, got %d", len(s.m)) } } func TestRemove(t *testing.T) { var e1, e2 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Remove(e1) if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if _, ok := s.m[e2]; !ok { t.Errorf("wrong entry %v removed, expected %v", e1, e2) } } func TestPop(t *testing.T) { var e1, e2 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } s := New() popped := s.Pop() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } s.Add(e1) s.Add(e2) s.Pop() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } } func TestPop2(t *testing.T) { var e1, e2 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } s := New() popped, found := s.Pop2() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } if found { t.Errorf("set is empty, no element should have been found") } s.Add(e1) s.Add(e2) _, found = s.Pop2() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if !found { t.Errorf("expected to find an entry") } } func TestHas(t *testing.T) { var e1, e2, e3 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.Has(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.Has(e2) { t.Errorf("expected the set to contain %v", e2) } if s.Has(e3) { t.Errorf("did not expect the set to contain %v", e3) } } func TestHasAny(t *testing.T) { var e1, e2, e3 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.HasAny(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.HasAny(e2) { t.Errorf("expected the set to contain %v", e2) } if s.HasAny(e3) { t.Errorf("did not expect the set to contain %v", e3) } if !s.HasAny(e1, e3) { t.Errorf("expected the set to contain %v", e1) } } func TestSize(t *testing.T) { var e1, e2 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if s.Size() != 2 { t.Errorf("expected the set size to be 2 but it was %d", s.Size()) } } func TestClear(t *testing.T) { var e1, e2 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Clear() if s.Size() != 0 { t.Errorf("expected the cleared set size to be 0 but it was %d", s.Size()) } } func TestIsEmpty(t *testing.T) { var e1, e2 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } s := New() if !s.IsEmpty() { t.Errorf("expected new set to be empty but it had %d elements", s.Size()) } s.Add(e1) s.Add(e2) if s.IsEmpty() { t.Error("expected a set with added items to not be empty") } } func TestIsEqual(t *testing.T) { var e1, e2 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } s1 := New() s2 := New() if !s1.IsEqual(s2) { t.Error("expected 2 new sets to be equal") } s1.Add(e1) s1.Add(e2) if s1.IsEqual(s2) { t.Errorf("expected 2 different sets to be equal, %v, %v", s1, s2) } s2.Add(e1) s2.Add(e2) if !s1.IsEqual(s2) { t.Error("expected 2 sets with the same items added to be equal") } } func TestIsSubset(t *testing.T) { var e1, e2, e3 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e3 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s1.IsSubset(s2) { t.Errorf("expected %v to be a subset of %v", s2, s1) } s2.Add(e2) s2.Add(e3) if s1.IsSubset(s2) { t.Errorf("expected %v not to be a subset of %v", s2, s1) } } func TestIsSuperset(t *testing.T) { var e1, e2 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s2.IsSuperset(s1) { t.Errorf("expected %v to be a super set of %v", s1, s2) } } func TestCopy(t *testing.T) { var e1, e2 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := s1.Copy() if !s2.IsEqual(s1) { t.Errorf("expected %v to be equal to %v after copy", s1, s2) } } func TestString(t *testing.T) { var e1 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } s1 := New() s1.Add(e1) s := s1.String() if s == "" { t.Errorf("expected string representation %v to exist", s) } if !strings.HasPrefix(s, "[") && !strings.HasSuffix(s, "]") { t.Errorf("expected string representation %v to start with '[' and end with ']'", s) } } func TestMerge(t *testing.T) { var e1, e2 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s2.Add(e2) s1.Merge(s2) if s1.Size() != 2 { t.Errorf("expected merged set %v have size 2 but it has %d", s1, s1.Size()) } } func TestList(t *testing.T) { var e1, e2 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) l := s.List() if len(l) != s.Size() { t.Errorf("expected a set of size %d to give a list of size 2 but it has %d", s.Size(), len(l)) } for _, e := range l { if !s.Has(e) { t.Errorf("listed entry %v not available in the set %s", e, s) } } } func TestSeparate(t *testing.T) { var e1, e2 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e2) s1.Separate(s2) if s1.Size() != 1 { t.Errorf("expected separated set %v have size 1 but it has %d", s1, s1.Size()) } if s1.Has(e2) { t.Errorf("separated set %v still contains %v", s1, e2) } } func TestEach(t *testing.T) { var e1, e2 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) found := make(map[float64]bool) s1.Each(func(item float64) bool { found[item] = true return true }) if len(found) != 2 { t.Errorf("not all items traversed only %v", found) } found = make(map[float64]bool) count := 0 s1.Each(func(item float64) bool { found[item] = true count++ if count > 0 { return false } return true }) if len(found) != 1 { t.Errorf("more than expected 1 items traversed %v", found) } } func TestIntersection(t *testing.T) { var e1, e2, e3 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(float64); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Intersection(s1, s2) if s3.Size() != 1 || !s3.Has(e2) { t.Errorf("expected the intersection to only contain '%v' but it is %v", e2, s3.List()) } } func TestUnion(t *testing.T) { var e1, e2, e3 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(float64); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Union(s1, s2) if s3.Size() != 3 || !(s3.Has(e1) && s3.Has(e2) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestDifference(t *testing.T) { var e1, e2, e3 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(float64); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Difference(s1, s2) if s3.Size() != 1 || !s3.Has(e1) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestSymmetricDifference(t *testing.T) { var e1, e2, e3 float64 e := createRandomObject(e1) if v, ok := e.(float64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(float64); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(float64); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := SymmetricDifference(s1, s2) if s3.Size() != 2 || !(s3.Has(e1) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func createRandomObject(i interface{}) interface{} { v, ok := quick.Value(reflect.TypeOf(i), rand.New(rand.NewSource(time.Now().UnixNano()))) if !ok { panic(fmt.Sprintf("unsupported type %v", i)) } return v.Interface() } scylladb-go-set-e560bb8/gen_set.sh000077500000000000000000000013101337277605500171150ustar00rootroot00000000000000#!/usr/bin/env bash set -eu -o pipefail if [ $# -ne 2 ]; then echo "Usage: $0 " exit 1 fi which go_generics > /dev/null || (echo "Could not find go_generics, to install run: \"go get -u github.com/mmatczuk/go_generics/cmd/go_generics\""; exit 1) TYPE=$1 PKG=$2 mkdir -p ${PKG} echo "type T = int" | cat internal/set/set.go - | go_generics -i /dev/stdin -t T=${TYPE} -o ${PKG}/${PKG}.go -p ${PKG} echo "type T = int" | cat internal/set/set_test.go - | go_generics -i /dev/stdin -t T=${TYPE} -o ${PKG}/${PKG}_test.go -p ${PKG} echo "type T = int" | cat internal/set/set_bench_test.go - | go_generics -i /dev/stdin -t T=${TYPE} -o ${PKG}/${PKG}_bench_test.go -p ${PKG} scylladb-go-set-e560bb8/go.mod000066400000000000000000000001071337277605500162430ustar00rootroot00000000000000module github.com/scylladb/go-set require github.com/fatih/set v0.2.1 scylladb-go-set-e560bb8/go.sum000066400000000000000000000002371337277605500162740ustar00rootroot00000000000000github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA= github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI= scylladb-go-set-e560bb8/i16set/000077500000000000000000000000001337277605500162525ustar00rootroot00000000000000scylladb-go-set-e560bb8/i16set/i16set.go000066400000000000000000000142231337277605500177160ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package i16set import ( "fmt" "math" "strings" ) var ( // helpful to not write everywhere struct{}{} keyExists = struct{}{} nonExistent int16 ) // Set is the main set structure that holds all the data // and methods used to working with the set. type Set struct { m map[int16]struct{} } // New creates and initializes a new Set. func New(ts ...int16) *Set { s := NewWithSize(len(ts)) s.Add(ts...) return s } // NewWithSize creates a new Set and gives make map a size hint. func NewWithSize(size int) *Set { return &Set{make(map[int16]struct{}, size)} } // Add includes the specified items (one or more) to the Set. The underlying // Set s is modified. If passed nothing it silently returns. func (s *Set) Add(items ...int16) { for _, item := range items { s.m[item] = keyExists } } // Remove deletes the specified items from the Set. The underlying Set s is // modified. If passed nothing it silently returns. func (s *Set) Remove(items ...int16) { for _, item := range items { delete(s.m, item) } } // Pop deletes and returns an item from the Set. The underlying Set s is // modified. If Set is empty, the zero value is returned. func (s *Set) Pop() int16 { for item := range s.m { delete(s.m, item) return item } return nonExistent } // Pop2 tries to delete and return an item from the Set. The underlying Set s // is modified. The second value is a bool that is true if the item existed in // the set, and false if not. If Set is empty, the zero value and false are // returned. func (s *Set) Pop2() (int16, bool) { for item := range s.m { delete(s.m, item) return item, true } return nonExistent, false } // Has looks for the existence of items passed. It returns false if nothing is // passed. For multiple items it returns true only if all of the items exist. func (s *Set) Has(items ...int16) bool { has := false for _, item := range items { if _, has = s.m[item]; !has { break } } return has } // HasAny looks for the existence of any of the items passed. // It returns false if nothing is passed. // For multiple items it returns true if any of the items exist. func (s *Set) HasAny(items ...int16) bool { has := false for _, item := range items { if _, has = s.m[item]; has { break } } return has } // Size returns the number of items in a Set. func (s *Set) Size() int { return len(s.m) } // Clear removes all items from the Set. func (s *Set) Clear() { s.m = make(map[int16]struct{}) } // IsEmpty reports whether the Set is empty. func (s *Set) IsEmpty() bool { return s.Size() == 0 } // IsEqual test whether s and t are the same in size and have the same items. func (s *Set) IsEqual(t *Set) bool { // return false if they are no the same size if s.Size() != t.Size() { return false } equal := true t.Each(func(item int16) bool { _, equal = s.m[item] return equal // if false, Each() will end }) return equal } // IsSubset tests whether t is a subset of s. func (s *Set) IsSubset(t *Set) bool { if s.Size() < t.Size() { return false } subset := true t.Each(func(item int16) bool { _, subset = s.m[item] return subset }) return subset } // IsSuperset tests whether t is a superset of s. func (s *Set) IsSuperset(t *Set) bool { return t.IsSubset(s) } // Each traverses the items in the Set, calling the provided function for each // Set member. Traversal will continue until all items in the Set have been // visited, or if the closure returns false. func (s *Set) Each(f func(item int16) bool) { for item := range s.m { if !f(item) { break } } } // Copy returns a new Set with a copy of s. func (s *Set) Copy() *Set { u := NewWithSize(s.Size()) for item := range s.m { u.m[item] = keyExists } return u } // String returns a string representation of s func (s *Set) String() string { v := make([]string, 0, s.Size()) for item := range s.m { v = append(v, fmt.Sprintf("%v", item)) } return fmt.Sprintf("[%s]", strings.Join(v, ", ")) } // List returns a slice of all items. There is also StringSlice() and // IntSlice() methods for returning slices of type string or int. func (s *Set) List() []int16 { v := make([]int16, 0, s.Size()) for item := range s.m { v = append(v, item) } return v } // Merge is like Union, however it modifies the current Set it's applied on // with the given t Set. func (s *Set) Merge(t *Set) { for item := range t.m { s.m[item] = keyExists } } // Separate removes the Set items containing in t from Set s. Please aware that // it's not the opposite of Merge. func (s *Set) Separate(t *Set) { for item := range t.m { delete(s.m, item) } } // Union is the merger of multiple sets. It returns a new set with all the // elements present in all the sets that are passed. func Union(sets ...*Set) *Set { maxPos := -1 maxSize := 0 for i, set := range sets { if l := set.Size(); l > maxSize { maxSize = l maxPos = i } } if maxSize == 0 { return New() } u := sets[maxPos].Copy() for i, set := range sets { if i == maxPos { continue } for item := range set.m { u.m[item] = keyExists } } return u } // Difference returns a new set which contains items which are in in the first // set but not in the others. func Difference(set1 *Set, sets ...*Set) *Set { s := set1.Copy() for _, set := range sets { s.Separate(set) } return s } // Intersection returns a new set which contains items that only exist in all // given sets. func Intersection(sets ...*Set) *Set { minPos := -1 minSize := math.MaxInt64 for i, set := range sets { if l := set.Size(); l < minSize { minSize = l minPos = i } } if minSize == math.MaxInt64 || minSize == 0 { return New() } t := sets[minPos].Copy() for i, set := range sets { if i == minPos { continue } for item := range t.m { if _, has := set.m[item]; !has { delete(t.m, item) } } } return t } // SymmetricDifference returns a new set which s is the difference of items // which are in one of either, but not in both. func SymmetricDifference(s *Set, t *Set) *Set { u := Difference(s, t) v := Difference(t, s) return Union(u, v) } scylladb-go-set-e560bb8/i16set/i16set_bench_test.go000066400000000000000000000046311337277605500221160ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package i16set import ( "github.com/fatih/set" "testing" ) func BenchmarkTypeSafeSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } b.StartTimer() s := New() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExisting(b *testing.B) { b.StopTimer() var e1 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } b.StartTimer() s := New() s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExisting(b *testing.B) { b.StopTimer() var e1 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExistingMany(b *testing.B) { s := New() b.StopTimer() var e1 int16 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(int16); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExistingMany(b *testing.B) { s := set.New(set.NonThreadSafe) b.StopTimer() var e1 int16 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(int16); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetAdd(b *testing.B) { b.StopTimer() var e int16 s := New() objs := make([]int16, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(int16); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } func BenchmarkInterfaceSetAdd(b *testing.B) { b.StopTimer() var e int16 s := set.New(set.NonThreadSafe) objs := make([]int16, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(int16); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } scylladb-go-set-e560bb8/i16set/i16set_test.go000066400000000000000000000247221337277605500207620ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package i16set import ( "fmt" "math/rand" "reflect" "strings" "testing" "testing/quick" "time" ) func TestAdd(t *testing.T) { var e1, e2 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if len(s.m) != 2 { t.Errorf("expected 2 entries, got %d", len(s.m)) } } func TestRemove(t *testing.T) { var e1, e2 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Remove(e1) if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if _, ok := s.m[e2]; !ok { t.Errorf("wrong entry %v removed, expected %v", e1, e2) } } func TestPop(t *testing.T) { var e1, e2 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } s := New() popped := s.Pop() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } s.Add(e1) s.Add(e2) s.Pop() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } } func TestPop2(t *testing.T) { var e1, e2 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } s := New() popped, found := s.Pop2() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } if found { t.Errorf("set is empty, no element should have been found") } s.Add(e1) s.Add(e2) _, found = s.Pop2() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if !found { t.Errorf("expected to find an entry") } } func TestHas(t *testing.T) { var e1, e2, e3 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.Has(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.Has(e2) { t.Errorf("expected the set to contain %v", e2) } if s.Has(e3) { t.Errorf("did not expect the set to contain %v", e3) } } func TestHasAny(t *testing.T) { var e1, e2, e3 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.HasAny(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.HasAny(e2) { t.Errorf("expected the set to contain %v", e2) } if s.HasAny(e3) { t.Errorf("did not expect the set to contain %v", e3) } if !s.HasAny(e1, e3) { t.Errorf("expected the set to contain %v", e1) } } func TestSize(t *testing.T) { var e1, e2 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if s.Size() != 2 { t.Errorf("expected the set size to be 2 but it was %d", s.Size()) } } func TestClear(t *testing.T) { var e1, e2 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Clear() if s.Size() != 0 { t.Errorf("expected the cleared set size to be 0 but it was %d", s.Size()) } } func TestIsEmpty(t *testing.T) { var e1, e2 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } s := New() if !s.IsEmpty() { t.Errorf("expected new set to be empty but it had %d elements", s.Size()) } s.Add(e1) s.Add(e2) if s.IsEmpty() { t.Error("expected a set with added items to not be empty") } } func TestIsEqual(t *testing.T) { var e1, e2 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } s1 := New() s2 := New() if !s1.IsEqual(s2) { t.Error("expected 2 new sets to be equal") } s1.Add(e1) s1.Add(e2) if s1.IsEqual(s2) { t.Errorf("expected 2 different sets to be equal, %v, %v", s1, s2) } s2.Add(e1) s2.Add(e2) if !s1.IsEqual(s2) { t.Error("expected 2 sets with the same items added to be equal") } } func TestIsSubset(t *testing.T) { var e1, e2, e3 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e3 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s1.IsSubset(s2) { t.Errorf("expected %v to be a subset of %v", s2, s1) } s2.Add(e2) s2.Add(e3) if s1.IsSubset(s2) { t.Errorf("expected %v not to be a subset of %v", s2, s1) } } func TestIsSuperset(t *testing.T) { var e1, e2 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s2.IsSuperset(s1) { t.Errorf("expected %v to be a super set of %v", s1, s2) } } func TestCopy(t *testing.T) { var e1, e2 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := s1.Copy() if !s2.IsEqual(s1) { t.Errorf("expected %v to be equal to %v after copy", s1, s2) } } func TestString(t *testing.T) { var e1 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } s1 := New() s1.Add(e1) s := s1.String() if s == "" { t.Errorf("expected string representation %v to exist", s) } if !strings.HasPrefix(s, "[") && !strings.HasSuffix(s, "]") { t.Errorf("expected string representation %v to start with '[' and end with ']'", s) } } func TestMerge(t *testing.T) { var e1, e2 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s2.Add(e2) s1.Merge(s2) if s1.Size() != 2 { t.Errorf("expected merged set %v have size 2 but it has %d", s1, s1.Size()) } } func TestList(t *testing.T) { var e1, e2 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) l := s.List() if len(l) != s.Size() { t.Errorf("expected a set of size %d to give a list of size 2 but it has %d", s.Size(), len(l)) } for _, e := range l { if !s.Has(e) { t.Errorf("listed entry %v not available in the set %s", e, s) } } } func TestSeparate(t *testing.T) { var e1, e2 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e2) s1.Separate(s2) if s1.Size() != 1 { t.Errorf("expected separated set %v have size 1 but it has %d", s1, s1.Size()) } if s1.Has(e2) { t.Errorf("separated set %v still contains %v", s1, e2) } } func TestEach(t *testing.T) { var e1, e2 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) found := make(map[int16]bool) s1.Each(func(item int16) bool { found[item] = true return true }) if len(found) != 2 { t.Errorf("not all items traversed only %v", found) } found = make(map[int16]bool) count := 0 s1.Each(func(item int16) bool { found[item] = true count++ if count > 0 { return false } return true }) if len(found) != 1 { t.Errorf("more than expected 1 items traversed %v", found) } } func TestIntersection(t *testing.T) { var e1, e2, e3 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int16); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Intersection(s1, s2) if s3.Size() != 1 || !s3.Has(e2) { t.Errorf("expected the intersection to only contain '%v' but it is %v", e2, s3.List()) } } func TestUnion(t *testing.T) { var e1, e2, e3 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int16); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Union(s1, s2) if s3.Size() != 3 || !(s3.Has(e1) && s3.Has(e2) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestDifference(t *testing.T) { var e1, e2, e3 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int16); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Difference(s1, s2) if s3.Size() != 1 || !s3.Has(e1) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestSymmetricDifference(t *testing.T) { var e1, e2, e3 int16 e := createRandomObject(e1) if v, ok := e.(int16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int16); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int16); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := SymmetricDifference(s1, s2) if s3.Size() != 2 || !(s3.Has(e1) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func createRandomObject(i interface{}) interface{} { v, ok := quick.Value(reflect.TypeOf(i), rand.New(rand.NewSource(time.Now().UnixNano()))) if !ok { panic(fmt.Sprintf("unsupported type %v", i)) } return v.Interface() } scylladb-go-set-e560bb8/i32set/000077500000000000000000000000001337277605500162505ustar00rootroot00000000000000scylladb-go-set-e560bb8/i32set/i32set.go000066400000000000000000000142231337277605500177120ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package i32set import ( "fmt" "math" "strings" ) var ( // helpful to not write everywhere struct{}{} keyExists = struct{}{} nonExistent int32 ) // Set is the main set structure that holds all the data // and methods used to working with the set. type Set struct { m map[int32]struct{} } // New creates and initializes a new Set. func New(ts ...int32) *Set { s := NewWithSize(len(ts)) s.Add(ts...) return s } // NewWithSize creates a new Set and gives make map a size hint. func NewWithSize(size int) *Set { return &Set{make(map[int32]struct{}, size)} } // Add includes the specified items (one or more) to the Set. The underlying // Set s is modified. If passed nothing it silently returns. func (s *Set) Add(items ...int32) { for _, item := range items { s.m[item] = keyExists } } // Remove deletes the specified items from the Set. The underlying Set s is // modified. If passed nothing it silently returns. func (s *Set) Remove(items ...int32) { for _, item := range items { delete(s.m, item) } } // Pop deletes and returns an item from the Set. The underlying Set s is // modified. If Set is empty, the zero value is returned. func (s *Set) Pop() int32 { for item := range s.m { delete(s.m, item) return item } return nonExistent } // Pop2 tries to delete and return an item from the Set. The underlying Set s // is modified. The second value is a bool that is true if the item existed in // the set, and false if not. If Set is empty, the zero value and false are // returned. func (s *Set) Pop2() (int32, bool) { for item := range s.m { delete(s.m, item) return item, true } return nonExistent, false } // Has looks for the existence of items passed. It returns false if nothing is // passed. For multiple items it returns true only if all of the items exist. func (s *Set) Has(items ...int32) bool { has := false for _, item := range items { if _, has = s.m[item]; !has { break } } return has } // HasAny looks for the existence of any of the items passed. // It returns false if nothing is passed. // For multiple items it returns true if any of the items exist. func (s *Set) HasAny(items ...int32) bool { has := false for _, item := range items { if _, has = s.m[item]; has { break } } return has } // Size returns the number of items in a Set. func (s *Set) Size() int { return len(s.m) } // Clear removes all items from the Set. func (s *Set) Clear() { s.m = make(map[int32]struct{}) } // IsEmpty reports whether the Set is empty. func (s *Set) IsEmpty() bool { return s.Size() == 0 } // IsEqual test whether s and t are the same in size and have the same items. func (s *Set) IsEqual(t *Set) bool { // return false if they are no the same size if s.Size() != t.Size() { return false } equal := true t.Each(func(item int32) bool { _, equal = s.m[item] return equal // if false, Each() will end }) return equal } // IsSubset tests whether t is a subset of s. func (s *Set) IsSubset(t *Set) bool { if s.Size() < t.Size() { return false } subset := true t.Each(func(item int32) bool { _, subset = s.m[item] return subset }) return subset } // IsSuperset tests whether t is a superset of s. func (s *Set) IsSuperset(t *Set) bool { return t.IsSubset(s) } // Each traverses the items in the Set, calling the provided function for each // Set member. Traversal will continue until all items in the Set have been // visited, or if the closure returns false. func (s *Set) Each(f func(item int32) bool) { for item := range s.m { if !f(item) { break } } } // Copy returns a new Set with a copy of s. func (s *Set) Copy() *Set { u := NewWithSize(s.Size()) for item := range s.m { u.m[item] = keyExists } return u } // String returns a string representation of s func (s *Set) String() string { v := make([]string, 0, s.Size()) for item := range s.m { v = append(v, fmt.Sprintf("%v", item)) } return fmt.Sprintf("[%s]", strings.Join(v, ", ")) } // List returns a slice of all items. There is also StringSlice() and // IntSlice() methods for returning slices of type string or int. func (s *Set) List() []int32 { v := make([]int32, 0, s.Size()) for item := range s.m { v = append(v, item) } return v } // Merge is like Union, however it modifies the current Set it's applied on // with the given t Set. func (s *Set) Merge(t *Set) { for item := range t.m { s.m[item] = keyExists } } // Separate removes the Set items containing in t from Set s. Please aware that // it's not the opposite of Merge. func (s *Set) Separate(t *Set) { for item := range t.m { delete(s.m, item) } } // Union is the merger of multiple sets. It returns a new set with all the // elements present in all the sets that are passed. func Union(sets ...*Set) *Set { maxPos := -1 maxSize := 0 for i, set := range sets { if l := set.Size(); l > maxSize { maxSize = l maxPos = i } } if maxSize == 0 { return New() } u := sets[maxPos].Copy() for i, set := range sets { if i == maxPos { continue } for item := range set.m { u.m[item] = keyExists } } return u } // Difference returns a new set which contains items which are in in the first // set but not in the others. func Difference(set1 *Set, sets ...*Set) *Set { s := set1.Copy() for _, set := range sets { s.Separate(set) } return s } // Intersection returns a new set which contains items that only exist in all // given sets. func Intersection(sets ...*Set) *Set { minPos := -1 minSize := math.MaxInt64 for i, set := range sets { if l := set.Size(); l < minSize { minSize = l minPos = i } } if minSize == math.MaxInt64 || minSize == 0 { return New() } t := sets[minPos].Copy() for i, set := range sets { if i == minPos { continue } for item := range t.m { if _, has := set.m[item]; !has { delete(t.m, item) } } } return t } // SymmetricDifference returns a new set which s is the difference of items // which are in one of either, but not in both. func SymmetricDifference(s *Set, t *Set) *Set { u := Difference(s, t) v := Difference(t, s) return Union(u, v) } scylladb-go-set-e560bb8/i32set/i32set_bench_test.go000066400000000000000000000046311337277605500221120ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package i32set import ( "github.com/fatih/set" "testing" ) func BenchmarkTypeSafeSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } b.StartTimer() s := New() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExisting(b *testing.B) { b.StopTimer() var e1 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } b.StartTimer() s := New() s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExisting(b *testing.B) { b.StopTimer() var e1 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExistingMany(b *testing.B) { s := New() b.StopTimer() var e1 int32 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(int32); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExistingMany(b *testing.B) { s := set.New(set.NonThreadSafe) b.StopTimer() var e1 int32 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(int32); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetAdd(b *testing.B) { b.StopTimer() var e int32 s := New() objs := make([]int32, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(int32); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } func BenchmarkInterfaceSetAdd(b *testing.B) { b.StopTimer() var e int32 s := set.New(set.NonThreadSafe) objs := make([]int32, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(int32); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } scylladb-go-set-e560bb8/i32set/i32set_test.go000066400000000000000000000247221337277605500207560ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package i32set import ( "fmt" "math/rand" "reflect" "strings" "testing" "testing/quick" "time" ) func TestAdd(t *testing.T) { var e1, e2 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if len(s.m) != 2 { t.Errorf("expected 2 entries, got %d", len(s.m)) } } func TestRemove(t *testing.T) { var e1, e2 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Remove(e1) if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if _, ok := s.m[e2]; !ok { t.Errorf("wrong entry %v removed, expected %v", e1, e2) } } func TestPop(t *testing.T) { var e1, e2 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } s := New() popped := s.Pop() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } s.Add(e1) s.Add(e2) s.Pop() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } } func TestPop2(t *testing.T) { var e1, e2 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } s := New() popped, found := s.Pop2() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } if found { t.Errorf("set is empty, no element should have been found") } s.Add(e1) s.Add(e2) _, found = s.Pop2() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if !found { t.Errorf("expected to find an entry") } } func TestHas(t *testing.T) { var e1, e2, e3 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.Has(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.Has(e2) { t.Errorf("expected the set to contain %v", e2) } if s.Has(e3) { t.Errorf("did not expect the set to contain %v", e3) } } func TestHasAny(t *testing.T) { var e1, e2, e3 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.HasAny(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.HasAny(e2) { t.Errorf("expected the set to contain %v", e2) } if s.HasAny(e3) { t.Errorf("did not expect the set to contain %v", e3) } if !s.HasAny(e1, e3) { t.Errorf("expected the set to contain %v", e1) } } func TestSize(t *testing.T) { var e1, e2 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if s.Size() != 2 { t.Errorf("expected the set size to be 2 but it was %d", s.Size()) } } func TestClear(t *testing.T) { var e1, e2 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Clear() if s.Size() != 0 { t.Errorf("expected the cleared set size to be 0 but it was %d", s.Size()) } } func TestIsEmpty(t *testing.T) { var e1, e2 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } s := New() if !s.IsEmpty() { t.Errorf("expected new set to be empty but it had %d elements", s.Size()) } s.Add(e1) s.Add(e2) if s.IsEmpty() { t.Error("expected a set with added items to not be empty") } } func TestIsEqual(t *testing.T) { var e1, e2 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } s1 := New() s2 := New() if !s1.IsEqual(s2) { t.Error("expected 2 new sets to be equal") } s1.Add(e1) s1.Add(e2) if s1.IsEqual(s2) { t.Errorf("expected 2 different sets to be equal, %v, %v", s1, s2) } s2.Add(e1) s2.Add(e2) if !s1.IsEqual(s2) { t.Error("expected 2 sets with the same items added to be equal") } } func TestIsSubset(t *testing.T) { var e1, e2, e3 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e3 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s1.IsSubset(s2) { t.Errorf("expected %v to be a subset of %v", s2, s1) } s2.Add(e2) s2.Add(e3) if s1.IsSubset(s2) { t.Errorf("expected %v not to be a subset of %v", s2, s1) } } func TestIsSuperset(t *testing.T) { var e1, e2 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s2.IsSuperset(s1) { t.Errorf("expected %v to be a super set of %v", s1, s2) } } func TestCopy(t *testing.T) { var e1, e2 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := s1.Copy() if !s2.IsEqual(s1) { t.Errorf("expected %v to be equal to %v after copy", s1, s2) } } func TestString(t *testing.T) { var e1 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } s1 := New() s1.Add(e1) s := s1.String() if s == "" { t.Errorf("expected string representation %v to exist", s) } if !strings.HasPrefix(s, "[") && !strings.HasSuffix(s, "]") { t.Errorf("expected string representation %v to start with '[' and end with ']'", s) } } func TestMerge(t *testing.T) { var e1, e2 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s2.Add(e2) s1.Merge(s2) if s1.Size() != 2 { t.Errorf("expected merged set %v have size 2 but it has %d", s1, s1.Size()) } } func TestList(t *testing.T) { var e1, e2 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) l := s.List() if len(l) != s.Size() { t.Errorf("expected a set of size %d to give a list of size 2 but it has %d", s.Size(), len(l)) } for _, e := range l { if !s.Has(e) { t.Errorf("listed entry %v not available in the set %s", e, s) } } } func TestSeparate(t *testing.T) { var e1, e2 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e2) s1.Separate(s2) if s1.Size() != 1 { t.Errorf("expected separated set %v have size 1 but it has %d", s1, s1.Size()) } if s1.Has(e2) { t.Errorf("separated set %v still contains %v", s1, e2) } } func TestEach(t *testing.T) { var e1, e2 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) found := make(map[int32]bool) s1.Each(func(item int32) bool { found[item] = true return true }) if len(found) != 2 { t.Errorf("not all items traversed only %v", found) } found = make(map[int32]bool) count := 0 s1.Each(func(item int32) bool { found[item] = true count++ if count > 0 { return false } return true }) if len(found) != 1 { t.Errorf("more than expected 1 items traversed %v", found) } } func TestIntersection(t *testing.T) { var e1, e2, e3 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int32); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Intersection(s1, s2) if s3.Size() != 1 || !s3.Has(e2) { t.Errorf("expected the intersection to only contain '%v' but it is %v", e2, s3.List()) } } func TestUnion(t *testing.T) { var e1, e2, e3 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int32); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Union(s1, s2) if s3.Size() != 3 || !(s3.Has(e1) && s3.Has(e2) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestDifference(t *testing.T) { var e1, e2, e3 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int32); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Difference(s1, s2) if s3.Size() != 1 || !s3.Has(e1) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestSymmetricDifference(t *testing.T) { var e1, e2, e3 int32 e := createRandomObject(e1) if v, ok := e.(int32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int32); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int32); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := SymmetricDifference(s1, s2) if s3.Size() != 2 || !(s3.Has(e1) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func createRandomObject(i interface{}) interface{} { v, ok := quick.Value(reflect.TypeOf(i), rand.New(rand.NewSource(time.Now().UnixNano()))) if !ok { panic(fmt.Sprintf("unsupported type %v", i)) } return v.Interface() } scylladb-go-set-e560bb8/i64set/000077500000000000000000000000001337277605500162555ustar00rootroot00000000000000scylladb-go-set-e560bb8/i64set/i64set.go000066400000000000000000000142231337277605500177240ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package i64set import ( "fmt" "math" "strings" ) var ( // helpful to not write everywhere struct{}{} keyExists = struct{}{} nonExistent int64 ) // Set is the main set structure that holds all the data // and methods used to working with the set. type Set struct { m map[int64]struct{} } // New creates and initializes a new Set. func New(ts ...int64) *Set { s := NewWithSize(len(ts)) s.Add(ts...) return s } // NewWithSize creates a new Set and gives make map a size hint. func NewWithSize(size int) *Set { return &Set{make(map[int64]struct{}, size)} } // Add includes the specified items (one or more) to the Set. The underlying // Set s is modified. If passed nothing it silently returns. func (s *Set) Add(items ...int64) { for _, item := range items { s.m[item] = keyExists } } // Remove deletes the specified items from the Set. The underlying Set s is // modified. If passed nothing it silently returns. func (s *Set) Remove(items ...int64) { for _, item := range items { delete(s.m, item) } } // Pop deletes and returns an item from the Set. The underlying Set s is // modified. If Set is empty, the zero value is returned. func (s *Set) Pop() int64 { for item := range s.m { delete(s.m, item) return item } return nonExistent } // Pop2 tries to delete and return an item from the Set. The underlying Set s // is modified. The second value is a bool that is true if the item existed in // the set, and false if not. If Set is empty, the zero value and false are // returned. func (s *Set) Pop2() (int64, bool) { for item := range s.m { delete(s.m, item) return item, true } return nonExistent, false } // Has looks for the existence of items passed. It returns false if nothing is // passed. For multiple items it returns true only if all of the items exist. func (s *Set) Has(items ...int64) bool { has := false for _, item := range items { if _, has = s.m[item]; !has { break } } return has } // HasAny looks for the existence of any of the items passed. // It returns false if nothing is passed. // For multiple items it returns true if any of the items exist. func (s *Set) HasAny(items ...int64) bool { has := false for _, item := range items { if _, has = s.m[item]; has { break } } return has } // Size returns the number of items in a Set. func (s *Set) Size() int { return len(s.m) } // Clear removes all items from the Set. func (s *Set) Clear() { s.m = make(map[int64]struct{}) } // IsEmpty reports whether the Set is empty. func (s *Set) IsEmpty() bool { return s.Size() == 0 } // IsEqual test whether s and t are the same in size and have the same items. func (s *Set) IsEqual(t *Set) bool { // return false if they are no the same size if s.Size() != t.Size() { return false } equal := true t.Each(func(item int64) bool { _, equal = s.m[item] return equal // if false, Each() will end }) return equal } // IsSubset tests whether t is a subset of s. func (s *Set) IsSubset(t *Set) bool { if s.Size() < t.Size() { return false } subset := true t.Each(func(item int64) bool { _, subset = s.m[item] return subset }) return subset } // IsSuperset tests whether t is a superset of s. func (s *Set) IsSuperset(t *Set) bool { return t.IsSubset(s) } // Each traverses the items in the Set, calling the provided function for each // Set member. Traversal will continue until all items in the Set have been // visited, or if the closure returns false. func (s *Set) Each(f func(item int64) bool) { for item := range s.m { if !f(item) { break } } } // Copy returns a new Set with a copy of s. func (s *Set) Copy() *Set { u := NewWithSize(s.Size()) for item := range s.m { u.m[item] = keyExists } return u } // String returns a string representation of s func (s *Set) String() string { v := make([]string, 0, s.Size()) for item := range s.m { v = append(v, fmt.Sprintf("%v", item)) } return fmt.Sprintf("[%s]", strings.Join(v, ", ")) } // List returns a slice of all items. There is also StringSlice() and // IntSlice() methods for returning slices of type string or int. func (s *Set) List() []int64 { v := make([]int64, 0, s.Size()) for item := range s.m { v = append(v, item) } return v } // Merge is like Union, however it modifies the current Set it's applied on // with the given t Set. func (s *Set) Merge(t *Set) { for item := range t.m { s.m[item] = keyExists } } // Separate removes the Set items containing in t from Set s. Please aware that // it's not the opposite of Merge. func (s *Set) Separate(t *Set) { for item := range t.m { delete(s.m, item) } } // Union is the merger of multiple sets. It returns a new set with all the // elements present in all the sets that are passed. func Union(sets ...*Set) *Set { maxPos := -1 maxSize := 0 for i, set := range sets { if l := set.Size(); l > maxSize { maxSize = l maxPos = i } } if maxSize == 0 { return New() } u := sets[maxPos].Copy() for i, set := range sets { if i == maxPos { continue } for item := range set.m { u.m[item] = keyExists } } return u } // Difference returns a new set which contains items which are in in the first // set but not in the others. func Difference(set1 *Set, sets ...*Set) *Set { s := set1.Copy() for _, set := range sets { s.Separate(set) } return s } // Intersection returns a new set which contains items that only exist in all // given sets. func Intersection(sets ...*Set) *Set { minPos := -1 minSize := math.MaxInt64 for i, set := range sets { if l := set.Size(); l < minSize { minSize = l minPos = i } } if minSize == math.MaxInt64 || minSize == 0 { return New() } t := sets[minPos].Copy() for i, set := range sets { if i == minPos { continue } for item := range t.m { if _, has := set.m[item]; !has { delete(t.m, item) } } } return t } // SymmetricDifference returns a new set which s is the difference of items // which are in one of either, but not in both. func SymmetricDifference(s *Set, t *Set) *Set { u := Difference(s, t) v := Difference(t, s) return Union(u, v) } scylladb-go-set-e560bb8/i64set/i64set_bench_test.go000066400000000000000000000046311337277605500221240ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package i64set import ( "github.com/fatih/set" "testing" ) func BenchmarkTypeSafeSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } b.StartTimer() s := New() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExisting(b *testing.B) { b.StopTimer() var e1 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } b.StartTimer() s := New() s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExisting(b *testing.B) { b.StopTimer() var e1 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExistingMany(b *testing.B) { s := New() b.StopTimer() var e1 int64 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(int64); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExistingMany(b *testing.B) { s := set.New(set.NonThreadSafe) b.StopTimer() var e1 int64 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(int64); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetAdd(b *testing.B) { b.StopTimer() var e int64 s := New() objs := make([]int64, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(int64); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } func BenchmarkInterfaceSetAdd(b *testing.B) { b.StopTimer() var e int64 s := set.New(set.NonThreadSafe) objs := make([]int64, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(int64); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } scylladb-go-set-e560bb8/i64set/i64set_test.go000066400000000000000000000247221337277605500207700ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package i64set import ( "fmt" "math/rand" "reflect" "strings" "testing" "testing/quick" "time" ) func TestAdd(t *testing.T) { var e1, e2 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if len(s.m) != 2 { t.Errorf("expected 2 entries, got %d", len(s.m)) } } func TestRemove(t *testing.T) { var e1, e2 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Remove(e1) if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if _, ok := s.m[e2]; !ok { t.Errorf("wrong entry %v removed, expected %v", e1, e2) } } func TestPop(t *testing.T) { var e1, e2 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } s := New() popped := s.Pop() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } s.Add(e1) s.Add(e2) s.Pop() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } } func TestPop2(t *testing.T) { var e1, e2 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } s := New() popped, found := s.Pop2() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } if found { t.Errorf("set is empty, no element should have been found") } s.Add(e1) s.Add(e2) _, found = s.Pop2() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if !found { t.Errorf("expected to find an entry") } } func TestHas(t *testing.T) { var e1, e2, e3 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.Has(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.Has(e2) { t.Errorf("expected the set to contain %v", e2) } if s.Has(e3) { t.Errorf("did not expect the set to contain %v", e3) } } func TestHasAny(t *testing.T) { var e1, e2, e3 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.HasAny(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.HasAny(e2) { t.Errorf("expected the set to contain %v", e2) } if s.HasAny(e3) { t.Errorf("did not expect the set to contain %v", e3) } if !s.HasAny(e1, e3) { t.Errorf("expected the set to contain %v", e1) } } func TestSize(t *testing.T) { var e1, e2 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if s.Size() != 2 { t.Errorf("expected the set size to be 2 but it was %d", s.Size()) } } func TestClear(t *testing.T) { var e1, e2 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Clear() if s.Size() != 0 { t.Errorf("expected the cleared set size to be 0 but it was %d", s.Size()) } } func TestIsEmpty(t *testing.T) { var e1, e2 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } s := New() if !s.IsEmpty() { t.Errorf("expected new set to be empty but it had %d elements", s.Size()) } s.Add(e1) s.Add(e2) if s.IsEmpty() { t.Error("expected a set with added items to not be empty") } } func TestIsEqual(t *testing.T) { var e1, e2 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } s1 := New() s2 := New() if !s1.IsEqual(s2) { t.Error("expected 2 new sets to be equal") } s1.Add(e1) s1.Add(e2) if s1.IsEqual(s2) { t.Errorf("expected 2 different sets to be equal, %v, %v", s1, s2) } s2.Add(e1) s2.Add(e2) if !s1.IsEqual(s2) { t.Error("expected 2 sets with the same items added to be equal") } } func TestIsSubset(t *testing.T) { var e1, e2, e3 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e3 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s1.IsSubset(s2) { t.Errorf("expected %v to be a subset of %v", s2, s1) } s2.Add(e2) s2.Add(e3) if s1.IsSubset(s2) { t.Errorf("expected %v not to be a subset of %v", s2, s1) } } func TestIsSuperset(t *testing.T) { var e1, e2 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s2.IsSuperset(s1) { t.Errorf("expected %v to be a super set of %v", s1, s2) } } func TestCopy(t *testing.T) { var e1, e2 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := s1.Copy() if !s2.IsEqual(s1) { t.Errorf("expected %v to be equal to %v after copy", s1, s2) } } func TestString(t *testing.T) { var e1 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } s1 := New() s1.Add(e1) s := s1.String() if s == "" { t.Errorf("expected string representation %v to exist", s) } if !strings.HasPrefix(s, "[") && !strings.HasSuffix(s, "]") { t.Errorf("expected string representation %v to start with '[' and end with ']'", s) } } func TestMerge(t *testing.T) { var e1, e2 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s2.Add(e2) s1.Merge(s2) if s1.Size() != 2 { t.Errorf("expected merged set %v have size 2 but it has %d", s1, s1.Size()) } } func TestList(t *testing.T) { var e1, e2 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) l := s.List() if len(l) != s.Size() { t.Errorf("expected a set of size %d to give a list of size 2 but it has %d", s.Size(), len(l)) } for _, e := range l { if !s.Has(e) { t.Errorf("listed entry %v not available in the set %s", e, s) } } } func TestSeparate(t *testing.T) { var e1, e2 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e2) s1.Separate(s2) if s1.Size() != 1 { t.Errorf("expected separated set %v have size 1 but it has %d", s1, s1.Size()) } if s1.Has(e2) { t.Errorf("separated set %v still contains %v", s1, e2) } } func TestEach(t *testing.T) { var e1, e2 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) found := make(map[int64]bool) s1.Each(func(item int64) bool { found[item] = true return true }) if len(found) != 2 { t.Errorf("not all items traversed only %v", found) } found = make(map[int64]bool) count := 0 s1.Each(func(item int64) bool { found[item] = true count++ if count > 0 { return false } return true }) if len(found) != 1 { t.Errorf("more than expected 1 items traversed %v", found) } } func TestIntersection(t *testing.T) { var e1, e2, e3 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int64); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Intersection(s1, s2) if s3.Size() != 1 || !s3.Has(e2) { t.Errorf("expected the intersection to only contain '%v' but it is %v", e2, s3.List()) } } func TestUnion(t *testing.T) { var e1, e2, e3 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int64); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Union(s1, s2) if s3.Size() != 3 || !(s3.Has(e1) && s3.Has(e2) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestDifference(t *testing.T) { var e1, e2, e3 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int64); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Difference(s1, s2) if s3.Size() != 1 || !s3.Has(e1) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestSymmetricDifference(t *testing.T) { var e1, e2, e3 int64 e := createRandomObject(e1) if v, ok := e.(int64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int64); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int64); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := SymmetricDifference(s1, s2) if s3.Size() != 2 || !(s3.Has(e1) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func createRandomObject(i interface{}) interface{} { v, ok := quick.Value(reflect.TypeOf(i), rand.New(rand.NewSource(time.Now().UnixNano()))) if !ok { panic(fmt.Sprintf("unsupported type %v", i)) } return v.Interface() } scylladb-go-set-e560bb8/i8set/000077500000000000000000000000001337277605500161735ustar00rootroot00000000000000scylladb-go-set-e560bb8/i8set/i8set.go000066400000000000000000000142021337277605500175550ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package i8set import ( "fmt" "math" "strings" ) var ( // helpful to not write everywhere struct{}{} keyExists = struct{}{} nonExistent int8 ) // Set is the main set structure that holds all the data // and methods used to working with the set. type Set struct { m map[int8]struct{} } // New creates and initializes a new Set. func New(ts ...int8) *Set { s := NewWithSize(len(ts)) s.Add(ts...) return s } // NewWithSize creates a new Set and gives make map a size hint. func NewWithSize(size int) *Set { return &Set{make(map[int8]struct{}, size)} } // Add includes the specified items (one or more) to the Set. The underlying // Set s is modified. If passed nothing it silently returns. func (s *Set) Add(items ...int8) { for _, item := range items { s.m[item] = keyExists } } // Remove deletes the specified items from the Set. The underlying Set s is // modified. If passed nothing it silently returns. func (s *Set) Remove(items ...int8) { for _, item := range items { delete(s.m, item) } } // Pop deletes and returns an item from the Set. The underlying Set s is // modified. If Set is empty, the zero value is returned. func (s *Set) Pop() int8 { for item := range s.m { delete(s.m, item) return item } return nonExistent } // Pop2 tries to delete and return an item from the Set. The underlying Set s // is modified. The second value is a bool that is true if the item existed in // the set, and false if not. If Set is empty, the zero value and false are // returned. func (s *Set) Pop2() (int8, bool) { for item := range s.m { delete(s.m, item) return item, true } return nonExistent, false } // Has looks for the existence of items passed. It returns false if nothing is // passed. For multiple items it returns true only if all of the items exist. func (s *Set) Has(items ...int8) bool { has := false for _, item := range items { if _, has = s.m[item]; !has { break } } return has } // HasAny looks for the existence of any of the items passed. // It returns false if nothing is passed. // For multiple items it returns true if any of the items exist. func (s *Set) HasAny(items ...int8) bool { has := false for _, item := range items { if _, has = s.m[item]; has { break } } return has } // Size returns the number of items in a Set. func (s *Set) Size() int { return len(s.m) } // Clear removes all items from the Set. func (s *Set) Clear() { s.m = make(map[int8]struct{}) } // IsEmpty reports whether the Set is empty. func (s *Set) IsEmpty() bool { return s.Size() == 0 } // IsEqual test whether s and t are the same in size and have the same items. func (s *Set) IsEqual(t *Set) bool { // return false if they are no the same size if s.Size() != t.Size() { return false } equal := true t.Each(func(item int8) bool { _, equal = s.m[item] return equal // if false, Each() will end }) return equal } // IsSubset tests whether t is a subset of s. func (s *Set) IsSubset(t *Set) bool { if s.Size() < t.Size() { return false } subset := true t.Each(func(item int8) bool { _, subset = s.m[item] return subset }) return subset } // IsSuperset tests whether t is a superset of s. func (s *Set) IsSuperset(t *Set) bool { return t.IsSubset(s) } // Each traverses the items in the Set, calling the provided function for each // Set member. Traversal will continue until all items in the Set have been // visited, or if the closure returns false. func (s *Set) Each(f func(item int8) bool) { for item := range s.m { if !f(item) { break } } } // Copy returns a new Set with a copy of s. func (s *Set) Copy() *Set { u := NewWithSize(s.Size()) for item := range s.m { u.m[item] = keyExists } return u } // String returns a string representation of s func (s *Set) String() string { v := make([]string, 0, s.Size()) for item := range s.m { v = append(v, fmt.Sprintf("%v", item)) } return fmt.Sprintf("[%s]", strings.Join(v, ", ")) } // List returns a slice of all items. There is also StringSlice() and // IntSlice() methods for returning slices of type string or int. func (s *Set) List() []int8 { v := make([]int8, 0, s.Size()) for item := range s.m { v = append(v, item) } return v } // Merge is like Union, however it modifies the current Set it's applied on // with the given t Set. func (s *Set) Merge(t *Set) { for item := range t.m { s.m[item] = keyExists } } // Separate removes the Set items containing in t from Set s. Please aware that // it's not the opposite of Merge. func (s *Set) Separate(t *Set) { for item := range t.m { delete(s.m, item) } } // Union is the merger of multiple sets. It returns a new set with all the // elements present in all the sets that are passed. func Union(sets ...*Set) *Set { maxPos := -1 maxSize := 0 for i, set := range sets { if l := set.Size(); l > maxSize { maxSize = l maxPos = i } } if maxSize == 0 { return New() } u := sets[maxPos].Copy() for i, set := range sets { if i == maxPos { continue } for item := range set.m { u.m[item] = keyExists } } return u } // Difference returns a new set which contains items which are in in the first // set but not in the others. func Difference(set1 *Set, sets ...*Set) *Set { s := set1.Copy() for _, set := range sets { s.Separate(set) } return s } // Intersection returns a new set which contains items that only exist in all // given sets. func Intersection(sets ...*Set) *Set { minPos := -1 minSize := math.MaxInt64 for i, set := range sets { if l := set.Size(); l < minSize { minSize = l minPos = i } } if minSize == math.MaxInt64 || minSize == 0 { return New() } t := sets[minPos].Copy() for i, set := range sets { if i == minPos { continue } for item := range t.m { if _, has := set.m[item]; !has { delete(t.m, item) } } } return t } // SymmetricDifference returns a new set which s is the difference of items // which are in one of either, but not in both. func SymmetricDifference(s *Set, t *Set) *Set { u := Difference(s, t) v := Difference(t, s) return Union(u, v) } scylladb-go-set-e560bb8/i8set/i8set_bench_test.go000066400000000000000000000046061337277605500217620ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package i8set import ( "github.com/fatih/set" "testing" ) func BenchmarkTypeSafeSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } b.StartTimer() s := New() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExisting(b *testing.B) { b.StopTimer() var e1 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } b.StartTimer() s := New() s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExisting(b *testing.B) { b.StopTimer() var e1 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExistingMany(b *testing.B) { s := New() b.StopTimer() var e1 int8 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(int8); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExistingMany(b *testing.B) { s := set.New(set.NonThreadSafe) b.StopTimer() var e1 int8 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(int8); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetAdd(b *testing.B) { b.StopTimer() var e int8 s := New() objs := make([]int8, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(int8); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } func BenchmarkInterfaceSetAdd(b *testing.B) { b.StopTimer() var e int8 s := set.New(set.NonThreadSafe) objs := make([]int8, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(int8); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } scylladb-go-set-e560bb8/i8set/i8set_test.go000066400000000000000000000246051337277605500206240ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package i8set import ( "fmt" "math/rand" "reflect" "strings" "testing" "testing/quick" "time" ) func TestAdd(t *testing.T) { var e1, e2 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if len(s.m) != 2 { t.Errorf("expected 2 entries, got %d", len(s.m)) } } func TestRemove(t *testing.T) { var e1, e2 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Remove(e1) if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if _, ok := s.m[e2]; !ok { t.Errorf("wrong entry %v removed, expected %v", e1, e2) } } func TestPop(t *testing.T) { var e1, e2 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } s := New() popped := s.Pop() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } s.Add(e1) s.Add(e2) s.Pop() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } } func TestPop2(t *testing.T) { var e1, e2 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } s := New() popped, found := s.Pop2() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } if found { t.Errorf("set is empty, no element should have been found") } s.Add(e1) s.Add(e2) _, found = s.Pop2() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if !found { t.Errorf("expected to find an entry") } } func TestHas(t *testing.T) { var e1, e2, e3 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.Has(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.Has(e2) { t.Errorf("expected the set to contain %v", e2) } if s.Has(e3) { t.Errorf("did not expect the set to contain %v", e3) } } func TestHasAny(t *testing.T) { var e1, e2, e3 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.HasAny(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.HasAny(e2) { t.Errorf("expected the set to contain %v", e2) } if s.HasAny(e3) { t.Errorf("did not expect the set to contain %v", e3) } if !s.HasAny(e1, e3) { t.Errorf("expected the set to contain %v", e1) } } func TestSize(t *testing.T) { var e1, e2 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if s.Size() != 2 { t.Errorf("expected the set size to be 2 but it was %d", s.Size()) } } func TestClear(t *testing.T) { var e1, e2 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Clear() if s.Size() != 0 { t.Errorf("expected the cleared set size to be 0 but it was %d", s.Size()) } } func TestIsEmpty(t *testing.T) { var e1, e2 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } s := New() if !s.IsEmpty() { t.Errorf("expected new set to be empty but it had %d elements", s.Size()) } s.Add(e1) s.Add(e2) if s.IsEmpty() { t.Error("expected a set with added items to not be empty") } } func TestIsEqual(t *testing.T) { var e1, e2 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } s1 := New() s2 := New() if !s1.IsEqual(s2) { t.Error("expected 2 new sets to be equal") } s1.Add(e1) s1.Add(e2) if s1.IsEqual(s2) { t.Errorf("expected 2 different sets to be equal, %v, %v", s1, s2) } s2.Add(e1) s2.Add(e2) if !s1.IsEqual(s2) { t.Error("expected 2 sets with the same items added to be equal") } } func TestIsSubset(t *testing.T) { var e1, e2, e3 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e3 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s1.IsSubset(s2) { t.Errorf("expected %v to be a subset of %v", s2, s1) } s2.Add(e2) s2.Add(e3) if s1.IsSubset(s2) { t.Errorf("expected %v not to be a subset of %v", s2, s1) } } func TestIsSuperset(t *testing.T) { var e1, e2 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s2.IsSuperset(s1) { t.Errorf("expected %v to be a super set of %v", s1, s2) } } func TestCopy(t *testing.T) { var e1, e2 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := s1.Copy() if !s2.IsEqual(s1) { t.Errorf("expected %v to be equal to %v after copy", s1, s2) } } func TestString(t *testing.T) { var e1 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } s1 := New() s1.Add(e1) s := s1.String() if s == "" { t.Errorf("expected string representation %v to exist", s) } if !strings.HasPrefix(s, "[") && !strings.HasSuffix(s, "]") { t.Errorf("expected string representation %v to start with '[' and end with ']'", s) } } func TestMerge(t *testing.T) { var e1, e2 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s2.Add(e2) s1.Merge(s2) if s1.Size() != 2 { t.Errorf("expected merged set %v have size 2 but it has %d", s1, s1.Size()) } } func TestList(t *testing.T) { var e1, e2 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) l := s.List() if len(l) != s.Size() { t.Errorf("expected a set of size %d to give a list of size 2 but it has %d", s.Size(), len(l)) } for _, e := range l { if !s.Has(e) { t.Errorf("listed entry %v not available in the set %s", e, s) } } } func TestSeparate(t *testing.T) { var e1, e2 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e2) s1.Separate(s2) if s1.Size() != 1 { t.Errorf("expected separated set %v have size 1 but it has %d", s1, s1.Size()) } if s1.Has(e2) { t.Errorf("separated set %v still contains %v", s1, e2) } } func TestEach(t *testing.T) { var e1, e2 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) found := make(map[int8]bool) s1.Each(func(item int8) bool { found[item] = true return true }) if len(found) != 2 { t.Errorf("not all items traversed only %v", found) } found = make(map[int8]bool) count := 0 s1.Each(func(item int8) bool { found[item] = true count++ if count > 0 { return false } return true }) if len(found) != 1 { t.Errorf("more than expected 1 items traversed %v", found) } } func TestIntersection(t *testing.T) { var e1, e2, e3 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int8); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Intersection(s1, s2) if s3.Size() != 1 || !s3.Has(e2) { t.Errorf("expected the intersection to only contain '%v' but it is %v", e2, s3.List()) } } func TestUnion(t *testing.T) { var e1, e2, e3 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int8); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Union(s1, s2) if s3.Size() != 3 || !(s3.Has(e1) && s3.Has(e2) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestDifference(t *testing.T) { var e1, e2, e3 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int8); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Difference(s1, s2) if s3.Size() != 1 || !s3.Has(e1) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestSymmetricDifference(t *testing.T) { var e1, e2, e3 int8 e := createRandomObject(e1) if v, ok := e.(int8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int8); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int8); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := SymmetricDifference(s1, s2) if s3.Size() != 2 || !(s3.Has(e1) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func createRandomObject(i interface{}) interface{} { v, ok := quick.Value(reflect.TypeOf(i), rand.New(rand.NewSource(time.Now().UnixNano()))) if !ok { panic(fmt.Sprintf("unsupported type %v", i)) } return v.Interface() } scylladb-go-set-e560bb8/internal/000077500000000000000000000000001337277605500167535ustar00rootroot00000000000000scylladb-go-set-e560bb8/internal/set/000077500000000000000000000000001337277605500175465ustar00rootroot00000000000000scylladb-go-set-e560bb8/internal/set/set.go000066400000000000000000000141201337277605500206660ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package set import ( "fmt" "math" "strings" ) var ( // helpful to not write everywhere struct{}{} keyExists = struct{}{} nonExistent T ) // Set is the main set structure that holds all the data // and methods used to working with the set. type Set struct { m map[T]struct{} } // New creates and initializes a new Set. func New(ts ...T) *Set { s := NewWithSize(len(ts)) s.Add(ts...) return s } // NewWithSize creates a new Set and gives make map a size hint. func NewWithSize(size int) *Set { return &Set{make(map[T]struct{}, size)} } // Add includes the specified items (one or more) to the Set. The underlying // Set s is modified. If passed nothing it silently returns. func (s *Set) Add(items ...T) { for _, item := range items { s.m[item] = keyExists } } // Remove deletes the specified items from the Set. The underlying Set s is // modified. If passed nothing it silently returns. func (s *Set) Remove(items ...T) { for _, item := range items { delete(s.m, item) } } // Pop deletes and returns an item from the Set. The underlying Set s is // modified. If Set is empty, the zero value is returned. func (s *Set) Pop() T { for item := range s.m { delete(s.m, item) return item } return nonExistent } // Pop2 tries to delete and return an item from the Set. The underlying Set s // is modified. The second value is a bool that is true if the item existed in // the set, and false if not. If Set is empty, the zero value and false are // returned. func (s *Set) Pop2() (T, bool) { for item := range s.m { delete(s.m, item) return item, true } return nonExistent, false } // Has looks for the existence of items passed. It returns false if nothing is // passed. For multiple items it returns true only if all of the items exist. func (s *Set) Has(items ...T) bool { has := false for _, item := range items { if _, has = s.m[item]; !has { break } } return has } // HasAny looks for the existence of any of the items passed. // It returns false if nothing is passed. // For multiple items it returns true if any of the items exist. func (s *Set) HasAny(items ...T) bool { has := false for _, item := range items { if _, has = s.m[item]; has { break } } return has } // Size returns the number of items in a Set. func (s *Set) Size() int { return len(s.m) } // Clear removes all items from the Set. func (s *Set) Clear() { s.m = make(map[T]struct{}) } // IsEmpty reports whether the Set is empty. func (s *Set) IsEmpty() bool { return s.Size() == 0 } // IsEqual test whether s and t are the same in size and have the same items. func (s *Set) IsEqual(t *Set) bool { // return false if they are no the same size if s.Size() != t.Size() { return false } equal := true t.Each(func(item T) bool { _, equal = s.m[item] return equal // if false, Each() will end }) return equal } // IsSubset tests whether t is a subset of s. func (s *Set) IsSubset(t *Set) bool { if s.Size() < t.Size() { return false } subset := true t.Each(func(item T) bool { _, subset = s.m[item] return subset }) return subset } // IsSuperset tests whether t is a superset of s. func (s *Set) IsSuperset(t *Set) bool { return t.IsSubset(s) } // Each traverses the items in the Set, calling the provided function for each // Set member. Traversal will continue until all items in the Set have been // visited, or if the closure returns false. func (s *Set) Each(f func(item T) bool) { for item := range s.m { if !f(item) { break } } } // Copy returns a new Set with a copy of s. func (s *Set) Copy() *Set { u := NewWithSize(s.Size()) for item := range s.m { u.m[item] = keyExists } return u } // String returns a string representation of s func (s *Set) String() string { v := make([]string, 0, s.Size()) for item := range s.m { v = append(v, fmt.Sprintf("%v", item)) } return fmt.Sprintf("[%s]", strings.Join(v, ", ")) } // List returns a slice of all items. There is also StringSlice() and // IntSlice() methods for returning slices of type string or int. func (s *Set) List() []T { v := make([]T, 0, s.Size()) for item := range s.m { v = append(v, item) } return v } // Merge is like Union, however it modifies the current Set it's applied on // with the given t Set. func (s *Set) Merge(t *Set) { for item := range t.m { s.m[item] = keyExists } } // Separate removes the Set items containing in t from Set s. Please aware that // it's not the opposite of Merge. func (s *Set) Separate(t *Set) { for item := range t.m { delete(s.m, item) } } // Union is the merger of multiple sets. It returns a new set with all the // elements present in all the sets that are passed. func Union(sets ...*Set) *Set { maxPos := -1 maxSize := 0 for i, set := range sets { if l := set.Size(); l > maxSize { maxSize = l maxPos = i } } if maxSize == 0 { return New() } u := sets[maxPos].Copy() for i, set := range sets { if i == maxPos { continue } for item := range set.m { u.m[item] = keyExists } } return u } // Difference returns a new set which contains items which are in in the first // set but not in the others. func Difference(set1 *Set, sets ...*Set) *Set { s := set1.Copy() for _, set := range sets { s.Separate(set) } return s } // Intersection returns a new set which contains items that only exist in all // given sets. func Intersection(sets ...*Set) *Set { minPos := -1 minSize := math.MaxInt64 for i, set := range sets { if l := set.Size(); l < minSize { minSize = l minPos = i } } if minSize == math.MaxInt64 || minSize == 0 { return New() } t := sets[minPos].Copy() for i, set := range sets { if i == minPos { continue } for item := range t.m { if _, has := set.m[item]; !has { delete(t.m, item) } } } return t } // SymmetricDifference returns a new set which s is the difference of items // which are in one of either, but not in both. func SymmetricDifference(s *Set, t *Set) *Set { u := Difference(s, t) v := Difference(t, s) return Union(u, v) } scylladb-go-set-e560bb8/internal/set/set_bench_test.go000066400000000000000000000045161337277605500230740ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package set import ( "github.com/fatih/set" "testing" ) func BenchmarkTypeSafeSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } b.StartTimer() s := New() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExisting(b *testing.B) { b.StopTimer() var e1 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } b.StartTimer() s := New() s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExisting(b *testing.B) { b.StopTimer() var e1 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExistingMany(b *testing.B) { s := New() b.StopTimer() var e1 T for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(T); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExistingMany(b *testing.B) { s := set.New(set.NonThreadSafe) b.StopTimer() var e1 T for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(T); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetAdd(b *testing.B) { b.StopTimer() var e T s := New() objs := make([]T, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(T); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } func BenchmarkInterfaceSetAdd(b *testing.B) { b.StopTimer() var e T s := set.New(set.NonThreadSafe) objs := make([]T, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(T); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } scylladb-go-set-e560bb8/internal/set/set_test.go000066400000000000000000000242371337277605500217370ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package set import ( "fmt" "math/rand" "reflect" "strings" "testing" "testing/quick" "time" ) func TestAdd(t *testing.T) { var e1, e2 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if len(s.m) != 2 { t.Errorf("expected 2 entries, got %d", len(s.m)) } } func TestRemove(t *testing.T) { var e1, e2 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Remove(e1) if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if _, ok := s.m[e2]; !ok { t.Errorf("wrong entry %v removed, expected %v", e1, e2) } } func TestPop(t *testing.T) { var e1, e2 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } s := New() popped := s.Pop() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } s.Add(e1) s.Add(e2) s.Pop() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } } func TestPop2(t *testing.T) { var e1, e2 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } s := New() popped, found := s.Pop2() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } if found { t.Errorf("set is empty, no element should have been found") } s.Add(e1) s.Add(e2) _, found = s.Pop2() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if !found { t.Errorf("expected to find an entry") } } func TestHas(t *testing.T) { var e1, e2, e3 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.Has(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.Has(e2) { t.Errorf("expected the set to contain %v", e2) } if s.Has(e3) { t.Errorf("did not expect the set to contain %v", e3) } } func TestHasAny(t *testing.T) { var e1, e2, e3 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.HasAny(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.HasAny(e2) { t.Errorf("expected the set to contain %v", e2) } if s.HasAny(e3) { t.Errorf("did not expect the set to contain %v", e3) } if !s.HasAny(e1, e3) { t.Errorf("expected the set to contain %v", e1) } } func TestSize(t *testing.T) { var e1, e2 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if s.Size() != 2 { t.Errorf("expected the set size to be 2 but it was %d", s.Size()) } } func TestClear(t *testing.T) { var e1, e2 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Clear() if s.Size() != 0 { t.Errorf("expected the cleared set size to be 0 but it was %d", s.Size()) } } func TestIsEmpty(t *testing.T) { var e1, e2 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } s := New() if !s.IsEmpty() { t.Errorf("expected new set to be empty but it had %d elements", s.Size()) } s.Add(e1) s.Add(e2) if s.IsEmpty() { t.Error("expected a set with added items to not be empty") } } func TestIsEqual(t *testing.T) { var e1, e2 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } s1 := New() s2 := New() if !s1.IsEqual(s2) { t.Error("expected 2 new sets to be equal") } s1.Add(e1) s1.Add(e2) if s1.IsEqual(s2) { t.Errorf("expected 2 different sets to be equal, %v, %v", s1, s2) } s2.Add(e1) s2.Add(e2) if !s1.IsEqual(s2) { t.Error("expected 2 sets with the same items added to be equal") } } func TestIsSubset(t *testing.T) { var e1, e2, e3 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e3 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s1.IsSubset(s2) { t.Errorf("expected %v to be a subset of %v", s2, s1) } s2.Add(e2) s2.Add(e3) if s1.IsSubset(s2) { t.Errorf("expected %v not to be a subset of %v", s2, s1) } } func TestIsSuperset(t *testing.T) { var e1, e2 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s2.IsSuperset(s1) { t.Errorf("expected %v to be a super set of %v", s1, s2) } } func TestCopy(t *testing.T) { var e1, e2 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := s1.Copy() if !s2.IsEqual(s1) { t.Errorf("expected %v to be equal to %v after copy", s1, s2) } } func TestString(t *testing.T) { var e1 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } s1 := New() s1.Add(e1) s := s1.String() if s == "" { t.Errorf("expected string representation %v to exist", s) } if !strings.HasPrefix(s, "[") && !strings.HasSuffix(s, "]") { t.Errorf("expected string representation %v to start with '[' and end with ']'", s) } } func TestMerge(t *testing.T) { var e1, e2 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s2.Add(e2) s1.Merge(s2) if s1.Size() != 2 { t.Errorf("expected merged set %v have size 2 but it has %d", s1, s1.Size()) } } func TestList(t *testing.T) { var e1, e2 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) l := s.List() if len(l) != s.Size() { t.Errorf("expected a set of size %d to give a list of size 2 but it has %d", s.Size(), len(l)) } for _, e := range l { if !s.Has(e) { t.Errorf("listed entry %v not available in the set %s", e, s) } } } func TestSeparate(t *testing.T) { var e1, e2 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e2) s1.Separate(s2) if s1.Size() != 1 { t.Errorf("expected separated set %v have size 1 but it has %d", s1, s1.Size()) } if s1.Has(e2) { t.Errorf("separated set %v still contains %v", s1, e2) } } func TestEach(t *testing.T) { var e1, e2 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) found := make(map[T]bool) s1.Each(func(item T) bool { found[item] = true return true }) if len(found) != 2 { t.Errorf("not all items traversed only %v", found) } found = make(map[T]bool) count := 0 s1.Each(func(item T) bool { found[item] = true count++ if count > 0 { return false } return true }) if len(found) != 1 { t.Errorf("more than expected 1 items traversed %v", found) } } func TestIntersection(t *testing.T) { var e1, e2, e3 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(T); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Intersection(s1, s2) if s3.Size() != 1 || !s3.Has(e2) { t.Errorf("expected the intersection to only contain '%v' but it is %v", e2, s3.List()) } } func TestUnion(t *testing.T) { var e1, e2, e3 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(T); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Union(s1, s2) if s3.Size() != 3 || !(s3.Has(e1) && s3.Has(e2) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestDifference(t *testing.T) { var e1, e2, e3 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(T); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Difference(s1, s2) if s3.Size() != 1 || !s3.Has(e1) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestSymmetricDifference(t *testing.T) { var e1, e2, e3 T e := createRandomObject(e1) if v, ok := e.(T); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(T); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(T); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := SymmetricDifference(s1, s2) if s3.Size() != 2 || !(s3.Has(e1) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func createRandomObject(i interface{}) interface{} { v, ok := quick.Value(reflect.TypeOf(i), rand.New(rand.NewSource(time.Now().UnixNano()))) if !ok { panic(fmt.Sprintf("unsupported type %v", i)) } return v.Interface() } scylladb-go-set-e560bb8/internal/set/t.go000066400000000000000000000003261337277605500203410ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package set // T is a Template type. type T = int scylladb-go-set-e560bb8/iset/000077500000000000000000000000001337277605500161035ustar00rootroot00000000000000scylladb-go-set-e560bb8/iset/iset.go000066400000000000000000000141611337277605500174010ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package iset import ( "fmt" "math" "strings" ) var ( // helpful to not write everywhere struct{}{} keyExists = struct{}{} nonExistent int ) // Set is the main set structure that holds all the data // and methods used to working with the set. type Set struct { m map[int]struct{} } // New creates and initializes a new Set. func New(ts ...int) *Set { s := NewWithSize(len(ts)) s.Add(ts...) return s } // NewWithSize creates a new Set and gives make map a size hint. func NewWithSize(size int) *Set { return &Set{make(map[int]struct{}, size)} } // Add includes the specified items (one or more) to the Set. The underlying // Set s is modified. If passed nothing it silently returns. func (s *Set) Add(items ...int) { for _, item := range items { s.m[item] = keyExists } } // Remove deletes the specified items from the Set. The underlying Set s is // modified. If passed nothing it silently returns. func (s *Set) Remove(items ...int) { for _, item := range items { delete(s.m, item) } } // Pop deletes and returns an item from the Set. The underlying Set s is // modified. If Set is empty, the zero value is returned. func (s *Set) Pop() int { for item := range s.m { delete(s.m, item) return item } return nonExistent } // Pop2 tries to delete and return an item from the Set. The underlying Set s // is modified. The second value is a bool that is true if the item existed in // the set, and false if not. If Set is empty, the zero value and false are // returned. func (s *Set) Pop2() (int, bool) { for item := range s.m { delete(s.m, item) return item, true } return nonExistent, false } // Has looks for the existence of items passed. It returns false if nothing is // passed. For multiple items it returns true only if all of the items exist. func (s *Set) Has(items ...int) bool { has := false for _, item := range items { if _, has = s.m[item]; !has { break } } return has } // HasAny looks for the existence of any of the items passed. // It returns false if nothing is passed. // For multiple items it returns true if any of the items exist. func (s *Set) HasAny(items ...int) bool { has := false for _, item := range items { if _, has = s.m[item]; has { break } } return has } // Size returns the number of items in a Set. func (s *Set) Size() int { return len(s.m) } // Clear removes all items from the Set. func (s *Set) Clear() { s.m = make(map[int]struct{}) } // IsEmpty reports whether the Set is empty. func (s *Set) IsEmpty() bool { return s.Size() == 0 } // IsEqual test whether s and t are the same in size and have the same items. func (s *Set) IsEqual(t *Set) bool { // return false if they are no the same size if s.Size() != t.Size() { return false } equal := true t.Each(func(item int) bool { _, equal = s.m[item] return equal // if false, Each() will end }) return equal } // IsSubset tests whether t is a subset of s. func (s *Set) IsSubset(t *Set) bool { if s.Size() < t.Size() { return false } subset := true t.Each(func(item int) bool { _, subset = s.m[item] return subset }) return subset } // IsSuperset tests whether t is a superset of s. func (s *Set) IsSuperset(t *Set) bool { return t.IsSubset(s) } // Each traverses the items in the Set, calling the provided function for each // Set member. Traversal will continue until all items in the Set have been // visited, or if the closure returns false. func (s *Set) Each(f func(item int) bool) { for item := range s.m { if !f(item) { break } } } // Copy returns a new Set with a copy of s. func (s *Set) Copy() *Set { u := NewWithSize(s.Size()) for item := range s.m { u.m[item] = keyExists } return u } // String returns a string representation of s func (s *Set) String() string { v := make([]string, 0, s.Size()) for item := range s.m { v = append(v, fmt.Sprintf("%v", item)) } return fmt.Sprintf("[%s]", strings.Join(v, ", ")) } // List returns a slice of all items. There is also StringSlice() and // IntSlice() methods for returning slices of type string or int. func (s *Set) List() []int { v := make([]int, 0, s.Size()) for item := range s.m { v = append(v, item) } return v } // Merge is like Union, however it modifies the current Set it's applied on // with the given t Set. func (s *Set) Merge(t *Set) { for item := range t.m { s.m[item] = keyExists } } // Separate removes the Set items containing in t from Set s. Please aware that // it's not the opposite of Merge. func (s *Set) Separate(t *Set) { for item := range t.m { delete(s.m, item) } } // Union is the merger of multiple sets. It returns a new set with all the // elements present in all the sets that are passed. func Union(sets ...*Set) *Set { maxPos := -1 maxSize := 0 for i, set := range sets { if l := set.Size(); l > maxSize { maxSize = l maxPos = i } } if maxSize == 0 { return New() } u := sets[maxPos].Copy() for i, set := range sets { if i == maxPos { continue } for item := range set.m { u.m[item] = keyExists } } return u } // Difference returns a new set which contains items which are in in the first // set but not in the others. func Difference(set1 *Set, sets ...*Set) *Set { s := set1.Copy() for _, set := range sets { s.Separate(set) } return s } // Intersection returns a new set which contains items that only exist in all // given sets. func Intersection(sets ...*Set) *Set { minPos := -1 minSize := math.MaxInt64 for i, set := range sets { if l := set.Size(); l < minSize { minSize = l minPos = i } } if minSize == math.MaxInt64 || minSize == 0 { return New() } t := sets[minPos].Copy() for i, set := range sets { if i == minPos { continue } for item := range t.m { if _, has := set.m[item]; !has { delete(t.m, item) } } } return t } // SymmetricDifference returns a new set which s is the difference of items // which are in one of either, but not in both. func SymmetricDifference(s *Set, t *Set) *Set { u := Difference(s, t) v := Difference(t, s) return Union(u, v) } scylladb-go-set-e560bb8/iset/iset_bench_test.go000066400000000000000000000045631337277605500216040ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package iset import ( "github.com/fatih/set" "testing" ) func BenchmarkTypeSafeSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } b.StartTimer() s := New() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExisting(b *testing.B) { b.StopTimer() var e1 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } b.StartTimer() s := New() s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExisting(b *testing.B) { b.StopTimer() var e1 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExistingMany(b *testing.B) { s := New() b.StopTimer() var e1 int for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(int); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExistingMany(b *testing.B) { s := set.New(set.NonThreadSafe) b.StopTimer() var e1 int for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(int); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetAdd(b *testing.B) { b.StopTimer() var e int s := New() objs := make([]int, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(int); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } func BenchmarkInterfaceSetAdd(b *testing.B) { b.StopTimer() var e int s := set.New(set.NonThreadSafe) objs := make([]int, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(int); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } scylladb-go-set-e560bb8/iset/iset_test.go000066400000000000000000000244701337277605500204440ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package iset import ( "fmt" "math/rand" "reflect" "strings" "testing" "testing/quick" "time" ) func TestAdd(t *testing.T) { var e1, e2 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if len(s.m) != 2 { t.Errorf("expected 2 entries, got %d", len(s.m)) } } func TestRemove(t *testing.T) { var e1, e2 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Remove(e1) if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if _, ok := s.m[e2]; !ok { t.Errorf("wrong entry %v removed, expected %v", e1, e2) } } func TestPop(t *testing.T) { var e1, e2 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } s := New() popped := s.Pop() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } s.Add(e1) s.Add(e2) s.Pop() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } } func TestPop2(t *testing.T) { var e1, e2 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } s := New() popped, found := s.Pop2() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } if found { t.Errorf("set is empty, no element should have been found") } s.Add(e1) s.Add(e2) _, found = s.Pop2() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if !found { t.Errorf("expected to find an entry") } } func TestHas(t *testing.T) { var e1, e2, e3 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.Has(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.Has(e2) { t.Errorf("expected the set to contain %v", e2) } if s.Has(e3) { t.Errorf("did not expect the set to contain %v", e3) } } func TestHasAny(t *testing.T) { var e1, e2, e3 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.HasAny(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.HasAny(e2) { t.Errorf("expected the set to contain %v", e2) } if s.HasAny(e3) { t.Errorf("did not expect the set to contain %v", e3) } if !s.HasAny(e1, e3) { t.Errorf("expected the set to contain %v", e1) } } func TestSize(t *testing.T) { var e1, e2 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if s.Size() != 2 { t.Errorf("expected the set size to be 2 but it was %d", s.Size()) } } func TestClear(t *testing.T) { var e1, e2 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Clear() if s.Size() != 0 { t.Errorf("expected the cleared set size to be 0 but it was %d", s.Size()) } } func TestIsEmpty(t *testing.T) { var e1, e2 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } s := New() if !s.IsEmpty() { t.Errorf("expected new set to be empty but it had %d elements", s.Size()) } s.Add(e1) s.Add(e2) if s.IsEmpty() { t.Error("expected a set with added items to not be empty") } } func TestIsEqual(t *testing.T) { var e1, e2 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } s1 := New() s2 := New() if !s1.IsEqual(s2) { t.Error("expected 2 new sets to be equal") } s1.Add(e1) s1.Add(e2) if s1.IsEqual(s2) { t.Errorf("expected 2 different sets to be equal, %v, %v", s1, s2) } s2.Add(e1) s2.Add(e2) if !s1.IsEqual(s2) { t.Error("expected 2 sets with the same items added to be equal") } } func TestIsSubset(t *testing.T) { var e1, e2, e3 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e3 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s1.IsSubset(s2) { t.Errorf("expected %v to be a subset of %v", s2, s1) } s2.Add(e2) s2.Add(e3) if s1.IsSubset(s2) { t.Errorf("expected %v not to be a subset of %v", s2, s1) } } func TestIsSuperset(t *testing.T) { var e1, e2 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s2.IsSuperset(s1) { t.Errorf("expected %v to be a super set of %v", s1, s2) } } func TestCopy(t *testing.T) { var e1, e2 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := s1.Copy() if !s2.IsEqual(s1) { t.Errorf("expected %v to be equal to %v after copy", s1, s2) } } func TestString(t *testing.T) { var e1 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } s1 := New() s1.Add(e1) s := s1.String() if s == "" { t.Errorf("expected string representation %v to exist", s) } if !strings.HasPrefix(s, "[") && !strings.HasSuffix(s, "]") { t.Errorf("expected string representation %v to start with '[' and end with ']'", s) } } func TestMerge(t *testing.T) { var e1, e2 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s2.Add(e2) s1.Merge(s2) if s1.Size() != 2 { t.Errorf("expected merged set %v have size 2 but it has %d", s1, s1.Size()) } } func TestList(t *testing.T) { var e1, e2 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) l := s.List() if len(l) != s.Size() { t.Errorf("expected a set of size %d to give a list of size 2 but it has %d", s.Size(), len(l)) } for _, e := range l { if !s.Has(e) { t.Errorf("listed entry %v not available in the set %s", e, s) } } } func TestSeparate(t *testing.T) { var e1, e2 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e2) s1.Separate(s2) if s1.Size() != 1 { t.Errorf("expected separated set %v have size 1 but it has %d", s1, s1.Size()) } if s1.Has(e2) { t.Errorf("separated set %v still contains %v", s1, e2) } } func TestEach(t *testing.T) { var e1, e2 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) found := make(map[int]bool) s1.Each(func(item int) bool { found[item] = true return true }) if len(found) != 2 { t.Errorf("not all items traversed only %v", found) } found = make(map[int]bool) count := 0 s1.Each(func(item int) bool { found[item] = true count++ if count > 0 { return false } return true }) if len(found) != 1 { t.Errorf("more than expected 1 items traversed %v", found) } } func TestIntersection(t *testing.T) { var e1, e2, e3 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Intersection(s1, s2) if s3.Size() != 1 || !s3.Has(e2) { t.Errorf("expected the intersection to only contain '%v' but it is %v", e2, s3.List()) } } func TestUnion(t *testing.T) { var e1, e2, e3 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Union(s1, s2) if s3.Size() != 3 || !(s3.Has(e1) && s3.Has(e2) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestDifference(t *testing.T) { var e1, e2, e3 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Difference(s1, s2) if s3.Size() != 1 || !s3.Has(e1) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestSymmetricDifference(t *testing.T) { var e1, e2, e3 int e := createRandomObject(e1) if v, ok := e.(int); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(int); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(int); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := SymmetricDifference(s1, s2) if s3.Size() != 2 || !(s3.Has(e1) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func createRandomObject(i interface{}) interface{} { v, ok := quick.Value(reflect.TypeOf(i), rand.New(rand.NewSource(time.Now().UnixNano()))) if !ok { panic(fmt.Sprintf("unsupported type %v", i)) } return v.Interface() } scylladb-go-set-e560bb8/set.go000066400000000000000000000147601337277605500162710ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found in the LICENSE file. package set import ( "github.com/scylladb/go-set/b16set" "github.com/scylladb/go-set/b32set" "github.com/scylladb/go-set/b64set" "github.com/scylladb/go-set/b8set" "github.com/scylladb/go-set/f32set" "github.com/scylladb/go-set/f64set" "github.com/scylladb/go-set/i16set" "github.com/scylladb/go-set/i32set" "github.com/scylladb/go-set/i64set" "github.com/scylladb/go-set/i8set" "github.com/scylladb/go-set/iset" "github.com/scylladb/go-set/strset" "github.com/scylladb/go-set/u16set" "github.com/scylladb/go-set/u32set" "github.com/scylladb/go-set/u64set" "github.com/scylladb/go-set/u8set" "github.com/scylladb/go-set/uset" ) //go:generate ./gen_set.sh [8]byte b8set // NewByte8Set is a convenience function to create a new b8set.Set func NewByte8Set(ts ...[8]byte) *b8set.Set { return b8set.New(ts...) } // NewByte8SetWithSize is a convenience function to create a new b8set.Set. func NewByte8SetWithSize(size int) *b8set.Set { return b8set.NewWithSize(size) } //go:generate ./gen_set.sh [16]byte b16set // NewByte16Set is a convenience function to create a new b16set.Set func NewByte16Set(ts ...[16]byte) *b16set.Set { return b16set.New(ts...) } // NewByte16SetWithSize is a convenience function to create a new b16set.Set. func NewByte16SetWithSize(size int) *b16set.Set { return b16set.NewWithSize(size) } //go:generate ./gen_set.sh [32]byte b32set // NewByte32Set is a convenience function to create a new b32set.Set func NewByte32Set(ts ...[32]byte) *b32set.Set { return b32set.New(ts...) } // NewByte32SetWithSize is a convenience function to create a new b32set.Set. func NewByte32SetWithSize(size int) *b32set.Set { return b32set.NewWithSize(size) } //go:generate ./gen_set.sh [64]byte b64set // NewByte64Set is a convenience function to create a new b64set.Set func NewByte64Set(ts ...[64]byte) *b64set.Set { return b64set.New(ts...) } // NewByte64SetWithSize is a convenience function to create a new b64set.Set. func NewByte64SetWithSize(size int) *b64set.Set { return b64set.NewWithSize(size) } //go:generate ./gen_set.sh float32 f32set // NewFloat32Set is a convenience function to create a new f32set.Set func NewFloat32Set(ts ...float32) *f32set.Set { return f32set.New(ts...) } // NewFloat32SetWithSize is a convenience function to create a new f32set.Set. func NewFloat32SetWithSize(size int) *f32set.Set { return f32set.NewWithSize(size) } //go:generate ./gen_set.sh float64 f64set // NewFloat64Set is a convenience function to create a new f64set.Set func NewFloat64Set(ts ...float64) *f64set.Set { return f64set.New(ts...) } // NewFloat64SetWithSize is a convenience function to create a new f64set.Set. func NewFloat64SetWithSize(size int) *f64set.Set { return f64set.NewWithSize(size) } //go:generate ./gen_set.sh int iset // NewIntSet is a convenience function to create a new iset.Set func NewIntSet(ts ...int) *iset.Set { return iset.New(ts...) } // NewIntSetWithSize is a convenience function to create a new iset.Set. func NewIntSetWithSize(size int) *iset.Set { return iset.NewWithSize(size) } //go:generate ./gen_set.sh int8 i8set // NewInt8Set is a convenience function to create a new i8set.Set func NewInt8Set(ts ...int8) *i8set.Set { return i8set.New(ts...) } // NewInt8SetWithSize is a convenience function to create a new i8set.Set. func NewInt8SetWithSize(size int) *i8set.Set { return i8set.NewWithSize(size) } //go:generate ./gen_set.sh int16 i16set // NewInt16Set is a convenience function to create a new i16set.Set func NewInt16Set(ts ...int16) *i16set.Set { return i16set.New(ts...) } // NewInt16SetWithSize is a convenience function to create a new i16set.Set. func NewInt16SetWithSize(size int) *i16set.Set { return i16set.NewWithSize(size) } //go:generate ./gen_set.sh int32 i32set // NewInt32Set is a convenience function to create a new i32set.Set func NewInt32Set(ts ...int32) *i32set.Set { return i32set.New(ts...) } // NewInt32SetWithSize is a convenience function to create a new i32set.Set. func NewInt32SetWithSize(size int) *i32set.Set { return i32set.NewWithSize(size) } //go:generate ./gen_set.sh int64 i64set // NewInt64Set is a convenience function to create a new i64set.Set func NewInt64Set(ts ...int64) *i64set.Set { return i64set.New(ts...) } // NewInt64SetWithSize is a convenience function to create a new i64set.Set. func NewInt64SetWithSize(size int) *i64set.Set { return i64set.NewWithSize(size) } //go:generate ./gen_set.sh uint uset // NewUintSet is a convenience function to create a new uset.Set func NewUintSet(ts ...uint) *uset.Set { return uset.New(ts...) } // NewUintSetWithSize is a convenience function to create a new uset.Set. func NewUintSetWithSize(size int) *uset.Set { return uset.NewWithSize(size) } //go:generate ./gen_set.sh uint8 u8set // NewUint8Set is a convenience function to create a new u8set.Set func NewUint8Set(ts ...uint8) *u8set.Set { return u8set.New(ts...) } // NewUint8SetWithSize is a convenience function to create a new u8set.Set. func NewUint8SetWithSize(size int) *u8set.Set { return u8set.NewWithSize(size) } //go:generate ./gen_set.sh uint16 u16set // NewUint16Set is a convenience function to create a new u16set.Set func NewUint16Set(ts ...uint16) *u16set.Set { return u16set.New(ts...) } // NewUint16SetWithSize is a convenience function to create a new u16set.Set. func NewUint16SetWithSize(size int) *u16set.Set { return u16set.NewWithSize(size) } //go:generate ./gen_set.sh uint32 u32set // NewUint32Set is a convenience function to create a new u32set.Set func NewUint32Set(ts ...uint32) *u32set.Set { return u32set.New(ts...) } // NewUint32SetWithSize is a convenience function to create a new u32set.Set. func NewUint32SetWithSize(size int) *u32set.Set { return u32set.NewWithSize(size) } //go:generate ./gen_set.sh uint64 u64set // NewUint64Set is a convenience function to create a new u64set.Set func NewUint64Set(ts ...uint64) *u64set.Set { return u64set.New(ts...) } // NewUint64SetWithSize is a convenience function to create a new u64set.Set. func NewUint64SetWithSize(size int) *u64set.Set { return u64set.NewWithSize(size) } //go:generate ./gen_set.sh string strset // NewStringSet is a convenience function to create a new strset.Set func NewStringSet(ts ...string) *strset.Set { return strset.New(ts...) } // NewStringSetWithSize is a convenience function to create a new strset.Set. func NewStringSetWithSize(size int) *strset.Set { return strset.NewWithSize(size) } scylladb-go-set-e560bb8/strset/000077500000000000000000000000001337277605500164635ustar00rootroot00000000000000scylladb-go-set-e560bb8/strset/strset.go000066400000000000000000000142431337277605500203420ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package strset import ( "fmt" "math" "strings" ) var ( // helpful to not write everywhere struct{}{} keyExists = struct{}{} nonExistent string ) // Set is the main set structure that holds all the data // and methods used to working with the set. type Set struct { m map[string]struct{} } // New creates and initializes a new Set. func New(ts ...string) *Set { s := NewWithSize(len(ts)) s.Add(ts...) return s } // NewWithSize creates a new Set and gives make map a size hint. func NewWithSize(size int) *Set { return &Set{make(map[string]struct{}, size)} } // Add includes the specified items (one or more) to the Set. The underlying // Set s is modified. If passed nothing it silently returns. func (s *Set) Add(items ...string) { for _, item := range items { s.m[item] = keyExists } } // Remove deletes the specified items from the Set. The underlying Set s is // modified. If passed nothing it silently returns. func (s *Set) Remove(items ...string) { for _, item := range items { delete(s.m, item) } } // Pop deletes and returns an item from the Set. The underlying Set s is // modified. If Set is empty, the zero value is returned. func (s *Set) Pop() string { for item := range s.m { delete(s.m, item) return item } return nonExistent } // Pop2 tries to delete and return an item from the Set. The underlying Set s // is modified. The second value is a bool that is true if the item existed in // the set, and false if not. If Set is empty, the zero value and false are // returned. func (s *Set) Pop2() (string, bool) { for item := range s.m { delete(s.m, item) return item, true } return nonExistent, false } // Has looks for the existence of items passed. It returns false if nothing is // passed. For multiple items it returns true only if all of the items exist. func (s *Set) Has(items ...string) bool { has := false for _, item := range items { if _, has = s.m[item]; !has { break } } return has } // HasAny looks for the existence of any of the items passed. // It returns false if nothing is passed. // For multiple items it returns true if any of the items exist. func (s *Set) HasAny(items ...string) bool { has := false for _, item := range items { if _, has = s.m[item]; has { break } } return has } // Size returns the number of items in a Set. func (s *Set) Size() int { return len(s.m) } // Clear removes all items from the Set. func (s *Set) Clear() { s.m = make(map[string]struct{}) } // IsEmpty reports whether the Set is empty. func (s *Set) IsEmpty() bool { return s.Size() == 0 } // IsEqual test whether s and t are the same in size and have the same items. func (s *Set) IsEqual(t *Set) bool { // return false if they are no the same size if s.Size() != t.Size() { return false } equal := true t.Each(func(item string) bool { _, equal = s.m[item] return equal // if false, Each() will end }) return equal } // IsSubset tests whether t is a subset of s. func (s *Set) IsSubset(t *Set) bool { if s.Size() < t.Size() { return false } subset := true t.Each(func(item string) bool { _, subset = s.m[item] return subset }) return subset } // IsSuperset tests whether t is a superset of s. func (s *Set) IsSuperset(t *Set) bool { return t.IsSubset(s) } // Each traverses the items in the Set, calling the provided function for each // Set member. Traversal will continue until all items in the Set have been // visited, or if the closure returns false. func (s *Set) Each(f func(item string) bool) { for item := range s.m { if !f(item) { break } } } // Copy returns a new Set with a copy of s. func (s *Set) Copy() *Set { u := NewWithSize(s.Size()) for item := range s.m { u.m[item] = keyExists } return u } // String returns a string representation of s func (s *Set) String() string { v := make([]string, 0, s.Size()) for item := range s.m { v = append(v, fmt.Sprintf("%v", item)) } return fmt.Sprintf("[%s]", strings.Join(v, ", ")) } // List returns a slice of all items. There is also StringSlice() and // IntSlice() methods for returning slices of type string or int. func (s *Set) List() []string { v := make([]string, 0, s.Size()) for item := range s.m { v = append(v, item) } return v } // Merge is like Union, however it modifies the current Set it's applied on // with the given t Set. func (s *Set) Merge(t *Set) { for item := range t.m { s.m[item] = keyExists } } // Separate removes the Set items containing in t from Set s. Please aware that // it's not the opposite of Merge. func (s *Set) Separate(t *Set) { for item := range t.m { delete(s.m, item) } } // Union is the merger of multiple sets. It returns a new set with all the // elements present in all the sets that are passed. func Union(sets ...*Set) *Set { maxPos := -1 maxSize := 0 for i, set := range sets { if l := set.Size(); l > maxSize { maxSize = l maxPos = i } } if maxSize == 0 { return New() } u := sets[maxPos].Copy() for i, set := range sets { if i == maxPos { continue } for item := range set.m { u.m[item] = keyExists } } return u } // Difference returns a new set which contains items which are in in the first // set but not in the others. func Difference(set1 *Set, sets ...*Set) *Set { s := set1.Copy() for _, set := range sets { s.Separate(set) } return s } // Intersection returns a new set which contains items that only exist in all // given sets. func Intersection(sets ...*Set) *Set { minPos := -1 minSize := math.MaxInt64 for i, set := range sets { if l := set.Size(); l < minSize { minSize = l minPos = i } } if minSize == math.MaxInt64 || minSize == 0 { return New() } t := sets[minPos].Copy() for i, set := range sets { if i == minPos { continue } for item := range t.m { if _, has := set.m[item]; !has { delete(t.m, item) } } } return t } // SymmetricDifference returns a new set which s is the difference of items // which are in one of either, but not in both. func SymmetricDifference(s *Set, t *Set) *Set { u := Difference(s, t) v := Difference(t, s) return Union(u, v) } scylladb-go-set-e560bb8/strset/strset_bench_test.go000066400000000000000000000046531337277605500225440ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package strset import ( "github.com/fatih/set" "testing" ) func BenchmarkTypeSafeSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } b.StartTimer() s := New() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExisting(b *testing.B) { b.StopTimer() var e1 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } b.StartTimer() s := New() s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExisting(b *testing.B) { b.StopTimer() var e1 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExistingMany(b *testing.B) { s := New() b.StopTimer() var e1 string for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(string); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExistingMany(b *testing.B) { s := set.New(set.NonThreadSafe) b.StopTimer() var e1 string for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(string); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetAdd(b *testing.B) { b.StopTimer() var e string s := New() objs := make([]string, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(string); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } func BenchmarkInterfaceSetAdd(b *testing.B) { b.StopTimer() var e string s := set.New(set.NonThreadSafe) objs := make([]string, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(string); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } scylladb-go-set-e560bb8/strset/strset_test.go000066400000000000000000000250361337277605500214030ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package strset import ( "fmt" "math/rand" "reflect" "strings" "testing" "testing/quick" "time" ) func TestAdd(t *testing.T) { var e1, e2 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if len(s.m) != 2 { t.Errorf("expected 2 entries, got %d", len(s.m)) } } func TestRemove(t *testing.T) { var e1, e2 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Remove(e1) if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if _, ok := s.m[e2]; !ok { t.Errorf("wrong entry %v removed, expected %v", e1, e2) } } func TestPop(t *testing.T) { var e1, e2 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } s := New() popped := s.Pop() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } s.Add(e1) s.Add(e2) s.Pop() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } } func TestPop2(t *testing.T) { var e1, e2 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } s := New() popped, found := s.Pop2() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } if found { t.Errorf("set is empty, no element should have been found") } s.Add(e1) s.Add(e2) _, found = s.Pop2() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if !found { t.Errorf("expected to find an entry") } } func TestHas(t *testing.T) { var e1, e2, e3 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.Has(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.Has(e2) { t.Errorf("expected the set to contain %v", e2) } if s.Has(e3) { t.Errorf("did not expect the set to contain %v", e3) } } func TestHasAny(t *testing.T) { var e1, e2, e3 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.HasAny(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.HasAny(e2) { t.Errorf("expected the set to contain %v", e2) } if s.HasAny(e3) { t.Errorf("did not expect the set to contain %v", e3) } if !s.HasAny(e1, e3) { t.Errorf("expected the set to contain %v", e1) } } func TestSize(t *testing.T) { var e1, e2 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if s.Size() != 2 { t.Errorf("expected the set size to be 2 but it was %d", s.Size()) } } func TestClear(t *testing.T) { var e1, e2 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Clear() if s.Size() != 0 { t.Errorf("expected the cleared set size to be 0 but it was %d", s.Size()) } } func TestIsEmpty(t *testing.T) { var e1, e2 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } s := New() if !s.IsEmpty() { t.Errorf("expected new set to be empty but it had %d elements", s.Size()) } s.Add(e1) s.Add(e2) if s.IsEmpty() { t.Error("expected a set with added items to not be empty") } } func TestIsEqual(t *testing.T) { var e1, e2 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } s1 := New() s2 := New() if !s1.IsEqual(s2) { t.Error("expected 2 new sets to be equal") } s1.Add(e1) s1.Add(e2) if s1.IsEqual(s2) { t.Errorf("expected 2 different sets to be equal, %v, %v", s1, s2) } s2.Add(e1) s2.Add(e2) if !s1.IsEqual(s2) { t.Error("expected 2 sets with the same items added to be equal") } } func TestIsSubset(t *testing.T) { var e1, e2, e3 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e3 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s1.IsSubset(s2) { t.Errorf("expected %v to be a subset of %v", s2, s1) } s2.Add(e2) s2.Add(e3) if s1.IsSubset(s2) { t.Errorf("expected %v not to be a subset of %v", s2, s1) } } func TestIsSuperset(t *testing.T) { var e1, e2 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s2.IsSuperset(s1) { t.Errorf("expected %v to be a super set of %v", s1, s2) } } func TestCopy(t *testing.T) { var e1, e2 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := s1.Copy() if !s2.IsEqual(s1) { t.Errorf("expected %v to be equal to %v after copy", s1, s2) } } func TestString(t *testing.T) { var e1 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } s1 := New() s1.Add(e1) s := s1.String() if s == "" { t.Errorf("expected string representation %v to exist", s) } if !strings.HasPrefix(s, "[") && !strings.HasSuffix(s, "]") { t.Errorf("expected string representation %v to start with '[' and end with ']'", s) } } func TestMerge(t *testing.T) { var e1, e2 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s2.Add(e2) s1.Merge(s2) if s1.Size() != 2 { t.Errorf("expected merged set %v have size 2 but it has %d", s1, s1.Size()) } } func TestList(t *testing.T) { var e1, e2 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) l := s.List() if len(l) != s.Size() { t.Errorf("expected a set of size %d to give a list of size 2 but it has %d", s.Size(), len(l)) } for _, e := range l { if !s.Has(e) { t.Errorf("listed entry %v not available in the set %s", e, s) } } } func TestSeparate(t *testing.T) { var e1, e2 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e2) s1.Separate(s2) if s1.Size() != 1 { t.Errorf("expected separated set %v have size 1 but it has %d", s1, s1.Size()) } if s1.Has(e2) { t.Errorf("separated set %v still contains %v", s1, e2) } } func TestEach(t *testing.T) { var e1, e2 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) found := make(map[string]bool) s1.Each(func(item string) bool { found[item] = true return true }) if len(found) != 2 { t.Errorf("not all items traversed only %v", found) } found = make(map[string]bool) count := 0 s1.Each(func(item string) bool { found[item] = true count++ if count > 0 { return false } return true }) if len(found) != 1 { t.Errorf("more than expected 1 items traversed %v", found) } } func TestIntersection(t *testing.T) { var e1, e2, e3 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(string); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Intersection(s1, s2) if s3.Size() != 1 || !s3.Has(e2) { t.Errorf("expected the intersection to only contain '%v' but it is %v", e2, s3.List()) } } func TestUnion(t *testing.T) { var e1, e2, e3 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(string); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Union(s1, s2) if s3.Size() != 3 || !(s3.Has(e1) && s3.Has(e2) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestDifference(t *testing.T) { var e1, e2, e3 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(string); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Difference(s1, s2) if s3.Size() != 1 || !s3.Has(e1) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestSymmetricDifference(t *testing.T) { var e1, e2, e3 string e := createRandomObject(e1) if v, ok := e.(string); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(string); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(string); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := SymmetricDifference(s1, s2) if s3.Size() != 2 || !(s3.Has(e1) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func createRandomObject(i interface{}) interface{} { v, ok := quick.Value(reflect.TypeOf(i), rand.New(rand.NewSource(time.Now().UnixNano()))) if !ok { panic(fmt.Sprintf("unsupported type %v", i)) } return v.Interface() } scylladb-go-set-e560bb8/u16set/000077500000000000000000000000001337277605500162665ustar00rootroot00000000000000scylladb-go-set-e560bb8/u16set/u16set.go000066400000000000000000000142431337277605500177500ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package u16set import ( "fmt" "math" "strings" ) var ( // helpful to not write everywhere struct{}{} keyExists = struct{}{} nonExistent uint16 ) // Set is the main set structure that holds all the data // and methods used to working with the set. type Set struct { m map[uint16]struct{} } // New creates and initializes a new Set. func New(ts ...uint16) *Set { s := NewWithSize(len(ts)) s.Add(ts...) return s } // NewWithSize creates a new Set and gives make map a size hint. func NewWithSize(size int) *Set { return &Set{make(map[uint16]struct{}, size)} } // Add includes the specified items (one or more) to the Set. The underlying // Set s is modified. If passed nothing it silently returns. func (s *Set) Add(items ...uint16) { for _, item := range items { s.m[item] = keyExists } } // Remove deletes the specified items from the Set. The underlying Set s is // modified. If passed nothing it silently returns. func (s *Set) Remove(items ...uint16) { for _, item := range items { delete(s.m, item) } } // Pop deletes and returns an item from the Set. The underlying Set s is // modified. If Set is empty, the zero value is returned. func (s *Set) Pop() uint16 { for item := range s.m { delete(s.m, item) return item } return nonExistent } // Pop2 tries to delete and return an item from the Set. The underlying Set s // is modified. The second value is a bool that is true if the item existed in // the set, and false if not. If Set is empty, the zero value and false are // returned. func (s *Set) Pop2() (uint16, bool) { for item := range s.m { delete(s.m, item) return item, true } return nonExistent, false } // Has looks for the existence of items passed. It returns false if nothing is // passed. For multiple items it returns true only if all of the items exist. func (s *Set) Has(items ...uint16) bool { has := false for _, item := range items { if _, has = s.m[item]; !has { break } } return has } // HasAny looks for the existence of any of the items passed. // It returns false if nothing is passed. // For multiple items it returns true if any of the items exist. func (s *Set) HasAny(items ...uint16) bool { has := false for _, item := range items { if _, has = s.m[item]; has { break } } return has } // Size returns the number of items in a Set. func (s *Set) Size() int { return len(s.m) } // Clear removes all items from the Set. func (s *Set) Clear() { s.m = make(map[uint16]struct{}) } // IsEmpty reports whether the Set is empty. func (s *Set) IsEmpty() bool { return s.Size() == 0 } // IsEqual test whether s and t are the same in size and have the same items. func (s *Set) IsEqual(t *Set) bool { // return false if they are no the same size if s.Size() != t.Size() { return false } equal := true t.Each(func(item uint16) bool { _, equal = s.m[item] return equal // if false, Each() will end }) return equal } // IsSubset tests whether t is a subset of s. func (s *Set) IsSubset(t *Set) bool { if s.Size() < t.Size() { return false } subset := true t.Each(func(item uint16) bool { _, subset = s.m[item] return subset }) return subset } // IsSuperset tests whether t is a superset of s. func (s *Set) IsSuperset(t *Set) bool { return t.IsSubset(s) } // Each traverses the items in the Set, calling the provided function for each // Set member. Traversal will continue until all items in the Set have been // visited, or if the closure returns false. func (s *Set) Each(f func(item uint16) bool) { for item := range s.m { if !f(item) { break } } } // Copy returns a new Set with a copy of s. func (s *Set) Copy() *Set { u := NewWithSize(s.Size()) for item := range s.m { u.m[item] = keyExists } return u } // String returns a string representation of s func (s *Set) String() string { v := make([]string, 0, s.Size()) for item := range s.m { v = append(v, fmt.Sprintf("%v", item)) } return fmt.Sprintf("[%s]", strings.Join(v, ", ")) } // List returns a slice of all items. There is also StringSlice() and // IntSlice() methods for returning slices of type string or int. func (s *Set) List() []uint16 { v := make([]uint16, 0, s.Size()) for item := range s.m { v = append(v, item) } return v } // Merge is like Union, however it modifies the current Set it's applied on // with the given t Set. func (s *Set) Merge(t *Set) { for item := range t.m { s.m[item] = keyExists } } // Separate removes the Set items containing in t from Set s. Please aware that // it's not the opposite of Merge. func (s *Set) Separate(t *Set) { for item := range t.m { delete(s.m, item) } } // Union is the merger of multiple sets. It returns a new set with all the // elements present in all the sets that are passed. func Union(sets ...*Set) *Set { maxPos := -1 maxSize := 0 for i, set := range sets { if l := set.Size(); l > maxSize { maxSize = l maxPos = i } } if maxSize == 0 { return New() } u := sets[maxPos].Copy() for i, set := range sets { if i == maxPos { continue } for item := range set.m { u.m[item] = keyExists } } return u } // Difference returns a new set which contains items which are in in the first // set but not in the others. func Difference(set1 *Set, sets ...*Set) *Set { s := set1.Copy() for _, set := range sets { s.Separate(set) } return s } // Intersection returns a new set which contains items that only exist in all // given sets. func Intersection(sets ...*Set) *Set { minPos := -1 minSize := math.MaxInt64 for i, set := range sets { if l := set.Size(); l < minSize { minSize = l minPos = i } } if minSize == math.MaxInt64 || minSize == 0 { return New() } t := sets[minPos].Copy() for i, set := range sets { if i == minPos { continue } for item := range t.m { if _, has := set.m[item]; !has { delete(t.m, item) } } } return t } // SymmetricDifference returns a new set which s is the difference of items // which are in one of either, but not in both. func SymmetricDifference(s *Set, t *Set) *Set { u := Difference(s, t) v := Difference(t, s) return Union(u, v) } scylladb-go-set-e560bb8/u16set/u16set_bench_test.go000066400000000000000000000046531337277605500221520ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package u16set import ( "github.com/fatih/set" "testing" ) func BenchmarkTypeSafeSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } b.StartTimer() s := New() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExisting(b *testing.B) { b.StopTimer() var e1 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } b.StartTimer() s := New() s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExisting(b *testing.B) { b.StopTimer() var e1 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExistingMany(b *testing.B) { s := New() b.StopTimer() var e1 uint16 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(uint16); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExistingMany(b *testing.B) { s := set.New(set.NonThreadSafe) b.StopTimer() var e1 uint16 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(uint16); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetAdd(b *testing.B) { b.StopTimer() var e uint16 s := New() objs := make([]uint16, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(uint16); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } func BenchmarkInterfaceSetAdd(b *testing.B) { b.StopTimer() var e uint16 s := set.New(set.NonThreadSafe) objs := make([]uint16, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(uint16); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } scylladb-go-set-e560bb8/u16set/u16set_test.go000066400000000000000000000250361337277605500210110ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package u16set import ( "fmt" "math/rand" "reflect" "strings" "testing" "testing/quick" "time" ) func TestAdd(t *testing.T) { var e1, e2 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if len(s.m) != 2 { t.Errorf("expected 2 entries, got %d", len(s.m)) } } func TestRemove(t *testing.T) { var e1, e2 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Remove(e1) if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if _, ok := s.m[e2]; !ok { t.Errorf("wrong entry %v removed, expected %v", e1, e2) } } func TestPop(t *testing.T) { var e1, e2 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } s := New() popped := s.Pop() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } s.Add(e1) s.Add(e2) s.Pop() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } } func TestPop2(t *testing.T) { var e1, e2 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } s := New() popped, found := s.Pop2() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } if found { t.Errorf("set is empty, no element should have been found") } s.Add(e1) s.Add(e2) _, found = s.Pop2() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if !found { t.Errorf("expected to find an entry") } } func TestHas(t *testing.T) { var e1, e2, e3 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.Has(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.Has(e2) { t.Errorf("expected the set to contain %v", e2) } if s.Has(e3) { t.Errorf("did not expect the set to contain %v", e3) } } func TestHasAny(t *testing.T) { var e1, e2, e3 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.HasAny(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.HasAny(e2) { t.Errorf("expected the set to contain %v", e2) } if s.HasAny(e3) { t.Errorf("did not expect the set to contain %v", e3) } if !s.HasAny(e1, e3) { t.Errorf("expected the set to contain %v", e1) } } func TestSize(t *testing.T) { var e1, e2 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if s.Size() != 2 { t.Errorf("expected the set size to be 2 but it was %d", s.Size()) } } func TestClear(t *testing.T) { var e1, e2 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Clear() if s.Size() != 0 { t.Errorf("expected the cleared set size to be 0 but it was %d", s.Size()) } } func TestIsEmpty(t *testing.T) { var e1, e2 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } s := New() if !s.IsEmpty() { t.Errorf("expected new set to be empty but it had %d elements", s.Size()) } s.Add(e1) s.Add(e2) if s.IsEmpty() { t.Error("expected a set with added items to not be empty") } } func TestIsEqual(t *testing.T) { var e1, e2 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } s1 := New() s2 := New() if !s1.IsEqual(s2) { t.Error("expected 2 new sets to be equal") } s1.Add(e1) s1.Add(e2) if s1.IsEqual(s2) { t.Errorf("expected 2 different sets to be equal, %v, %v", s1, s2) } s2.Add(e1) s2.Add(e2) if !s1.IsEqual(s2) { t.Error("expected 2 sets with the same items added to be equal") } } func TestIsSubset(t *testing.T) { var e1, e2, e3 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e3 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s1.IsSubset(s2) { t.Errorf("expected %v to be a subset of %v", s2, s1) } s2.Add(e2) s2.Add(e3) if s1.IsSubset(s2) { t.Errorf("expected %v not to be a subset of %v", s2, s1) } } func TestIsSuperset(t *testing.T) { var e1, e2 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s2.IsSuperset(s1) { t.Errorf("expected %v to be a super set of %v", s1, s2) } } func TestCopy(t *testing.T) { var e1, e2 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := s1.Copy() if !s2.IsEqual(s1) { t.Errorf("expected %v to be equal to %v after copy", s1, s2) } } func TestString(t *testing.T) { var e1 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } s1 := New() s1.Add(e1) s := s1.String() if s == "" { t.Errorf("expected string representation %v to exist", s) } if !strings.HasPrefix(s, "[") && !strings.HasSuffix(s, "]") { t.Errorf("expected string representation %v to start with '[' and end with ']'", s) } } func TestMerge(t *testing.T) { var e1, e2 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s2.Add(e2) s1.Merge(s2) if s1.Size() != 2 { t.Errorf("expected merged set %v have size 2 but it has %d", s1, s1.Size()) } } func TestList(t *testing.T) { var e1, e2 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) l := s.List() if len(l) != s.Size() { t.Errorf("expected a set of size %d to give a list of size 2 but it has %d", s.Size(), len(l)) } for _, e := range l { if !s.Has(e) { t.Errorf("listed entry %v not available in the set %s", e, s) } } } func TestSeparate(t *testing.T) { var e1, e2 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e2) s1.Separate(s2) if s1.Size() != 1 { t.Errorf("expected separated set %v have size 1 but it has %d", s1, s1.Size()) } if s1.Has(e2) { t.Errorf("separated set %v still contains %v", s1, e2) } } func TestEach(t *testing.T) { var e1, e2 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) found := make(map[uint16]bool) s1.Each(func(item uint16) bool { found[item] = true return true }) if len(found) != 2 { t.Errorf("not all items traversed only %v", found) } found = make(map[uint16]bool) count := 0 s1.Each(func(item uint16) bool { found[item] = true count++ if count > 0 { return false } return true }) if len(found) != 1 { t.Errorf("more than expected 1 items traversed %v", found) } } func TestIntersection(t *testing.T) { var e1, e2, e3 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint16); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Intersection(s1, s2) if s3.Size() != 1 || !s3.Has(e2) { t.Errorf("expected the intersection to only contain '%v' but it is %v", e2, s3.List()) } } func TestUnion(t *testing.T) { var e1, e2, e3 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint16); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Union(s1, s2) if s3.Size() != 3 || !(s3.Has(e1) && s3.Has(e2) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestDifference(t *testing.T) { var e1, e2, e3 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint16); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Difference(s1, s2) if s3.Size() != 1 || !s3.Has(e1) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestSymmetricDifference(t *testing.T) { var e1, e2, e3 uint16 e := createRandomObject(e1) if v, ok := e.(uint16); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint16); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint16); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := SymmetricDifference(s1, s2) if s3.Size() != 2 || !(s3.Has(e1) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func createRandomObject(i interface{}) interface{} { v, ok := quick.Value(reflect.TypeOf(i), rand.New(rand.NewSource(time.Now().UnixNano()))) if !ok { panic(fmt.Sprintf("unsupported type %v", i)) } return v.Interface() } scylladb-go-set-e560bb8/u32set/000077500000000000000000000000001337277605500162645ustar00rootroot00000000000000scylladb-go-set-e560bb8/u32set/u32set.go000066400000000000000000000142431337277605500177440ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package u32set import ( "fmt" "math" "strings" ) var ( // helpful to not write everywhere struct{}{} keyExists = struct{}{} nonExistent uint32 ) // Set is the main set structure that holds all the data // and methods used to working with the set. type Set struct { m map[uint32]struct{} } // New creates and initializes a new Set. func New(ts ...uint32) *Set { s := NewWithSize(len(ts)) s.Add(ts...) return s } // NewWithSize creates a new Set and gives make map a size hint. func NewWithSize(size int) *Set { return &Set{make(map[uint32]struct{}, size)} } // Add includes the specified items (one or more) to the Set. The underlying // Set s is modified. If passed nothing it silently returns. func (s *Set) Add(items ...uint32) { for _, item := range items { s.m[item] = keyExists } } // Remove deletes the specified items from the Set. The underlying Set s is // modified. If passed nothing it silently returns. func (s *Set) Remove(items ...uint32) { for _, item := range items { delete(s.m, item) } } // Pop deletes and returns an item from the Set. The underlying Set s is // modified. If Set is empty, the zero value is returned. func (s *Set) Pop() uint32 { for item := range s.m { delete(s.m, item) return item } return nonExistent } // Pop2 tries to delete and return an item from the Set. The underlying Set s // is modified. The second value is a bool that is true if the item existed in // the set, and false if not. If Set is empty, the zero value and false are // returned. func (s *Set) Pop2() (uint32, bool) { for item := range s.m { delete(s.m, item) return item, true } return nonExistent, false } // Has looks for the existence of items passed. It returns false if nothing is // passed. For multiple items it returns true only if all of the items exist. func (s *Set) Has(items ...uint32) bool { has := false for _, item := range items { if _, has = s.m[item]; !has { break } } return has } // HasAny looks for the existence of any of the items passed. // It returns false if nothing is passed. // For multiple items it returns true if any of the items exist. func (s *Set) HasAny(items ...uint32) bool { has := false for _, item := range items { if _, has = s.m[item]; has { break } } return has } // Size returns the number of items in a Set. func (s *Set) Size() int { return len(s.m) } // Clear removes all items from the Set. func (s *Set) Clear() { s.m = make(map[uint32]struct{}) } // IsEmpty reports whether the Set is empty. func (s *Set) IsEmpty() bool { return s.Size() == 0 } // IsEqual test whether s and t are the same in size and have the same items. func (s *Set) IsEqual(t *Set) bool { // return false if they are no the same size if s.Size() != t.Size() { return false } equal := true t.Each(func(item uint32) bool { _, equal = s.m[item] return equal // if false, Each() will end }) return equal } // IsSubset tests whether t is a subset of s. func (s *Set) IsSubset(t *Set) bool { if s.Size() < t.Size() { return false } subset := true t.Each(func(item uint32) bool { _, subset = s.m[item] return subset }) return subset } // IsSuperset tests whether t is a superset of s. func (s *Set) IsSuperset(t *Set) bool { return t.IsSubset(s) } // Each traverses the items in the Set, calling the provided function for each // Set member. Traversal will continue until all items in the Set have been // visited, or if the closure returns false. func (s *Set) Each(f func(item uint32) bool) { for item := range s.m { if !f(item) { break } } } // Copy returns a new Set with a copy of s. func (s *Set) Copy() *Set { u := NewWithSize(s.Size()) for item := range s.m { u.m[item] = keyExists } return u } // String returns a string representation of s func (s *Set) String() string { v := make([]string, 0, s.Size()) for item := range s.m { v = append(v, fmt.Sprintf("%v", item)) } return fmt.Sprintf("[%s]", strings.Join(v, ", ")) } // List returns a slice of all items. There is also StringSlice() and // IntSlice() methods for returning slices of type string or int. func (s *Set) List() []uint32 { v := make([]uint32, 0, s.Size()) for item := range s.m { v = append(v, item) } return v } // Merge is like Union, however it modifies the current Set it's applied on // with the given t Set. func (s *Set) Merge(t *Set) { for item := range t.m { s.m[item] = keyExists } } // Separate removes the Set items containing in t from Set s. Please aware that // it's not the opposite of Merge. func (s *Set) Separate(t *Set) { for item := range t.m { delete(s.m, item) } } // Union is the merger of multiple sets. It returns a new set with all the // elements present in all the sets that are passed. func Union(sets ...*Set) *Set { maxPos := -1 maxSize := 0 for i, set := range sets { if l := set.Size(); l > maxSize { maxSize = l maxPos = i } } if maxSize == 0 { return New() } u := sets[maxPos].Copy() for i, set := range sets { if i == maxPos { continue } for item := range set.m { u.m[item] = keyExists } } return u } // Difference returns a new set which contains items which are in in the first // set but not in the others. func Difference(set1 *Set, sets ...*Set) *Set { s := set1.Copy() for _, set := range sets { s.Separate(set) } return s } // Intersection returns a new set which contains items that only exist in all // given sets. func Intersection(sets ...*Set) *Set { minPos := -1 minSize := math.MaxInt64 for i, set := range sets { if l := set.Size(); l < minSize { minSize = l minPos = i } } if minSize == math.MaxInt64 || minSize == 0 { return New() } t := sets[minPos].Copy() for i, set := range sets { if i == minPos { continue } for item := range t.m { if _, has := set.m[item]; !has { delete(t.m, item) } } } return t } // SymmetricDifference returns a new set which s is the difference of items // which are in one of either, but not in both. func SymmetricDifference(s *Set, t *Set) *Set { u := Difference(s, t) v := Difference(t, s) return Union(u, v) } scylladb-go-set-e560bb8/u32set/u32set_bench_test.go000066400000000000000000000046531337277605500221460ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package u32set import ( "github.com/fatih/set" "testing" ) func BenchmarkTypeSafeSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } b.StartTimer() s := New() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExisting(b *testing.B) { b.StopTimer() var e1 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } b.StartTimer() s := New() s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExisting(b *testing.B) { b.StopTimer() var e1 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExistingMany(b *testing.B) { s := New() b.StopTimer() var e1 uint32 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(uint32); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExistingMany(b *testing.B) { s := set.New(set.NonThreadSafe) b.StopTimer() var e1 uint32 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(uint32); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetAdd(b *testing.B) { b.StopTimer() var e uint32 s := New() objs := make([]uint32, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(uint32); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } func BenchmarkInterfaceSetAdd(b *testing.B) { b.StopTimer() var e uint32 s := set.New(set.NonThreadSafe) objs := make([]uint32, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(uint32); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } scylladb-go-set-e560bb8/u32set/u32set_test.go000066400000000000000000000250361337277605500210050ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package u32set import ( "fmt" "math/rand" "reflect" "strings" "testing" "testing/quick" "time" ) func TestAdd(t *testing.T) { var e1, e2 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if len(s.m) != 2 { t.Errorf("expected 2 entries, got %d", len(s.m)) } } func TestRemove(t *testing.T) { var e1, e2 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Remove(e1) if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if _, ok := s.m[e2]; !ok { t.Errorf("wrong entry %v removed, expected %v", e1, e2) } } func TestPop(t *testing.T) { var e1, e2 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } s := New() popped := s.Pop() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } s.Add(e1) s.Add(e2) s.Pop() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } } func TestPop2(t *testing.T) { var e1, e2 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } s := New() popped, found := s.Pop2() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } if found { t.Errorf("set is empty, no element should have been found") } s.Add(e1) s.Add(e2) _, found = s.Pop2() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if !found { t.Errorf("expected to find an entry") } } func TestHas(t *testing.T) { var e1, e2, e3 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.Has(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.Has(e2) { t.Errorf("expected the set to contain %v", e2) } if s.Has(e3) { t.Errorf("did not expect the set to contain %v", e3) } } func TestHasAny(t *testing.T) { var e1, e2, e3 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.HasAny(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.HasAny(e2) { t.Errorf("expected the set to contain %v", e2) } if s.HasAny(e3) { t.Errorf("did not expect the set to contain %v", e3) } if !s.HasAny(e1, e3) { t.Errorf("expected the set to contain %v", e1) } } func TestSize(t *testing.T) { var e1, e2 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if s.Size() != 2 { t.Errorf("expected the set size to be 2 but it was %d", s.Size()) } } func TestClear(t *testing.T) { var e1, e2 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Clear() if s.Size() != 0 { t.Errorf("expected the cleared set size to be 0 but it was %d", s.Size()) } } func TestIsEmpty(t *testing.T) { var e1, e2 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } s := New() if !s.IsEmpty() { t.Errorf("expected new set to be empty but it had %d elements", s.Size()) } s.Add(e1) s.Add(e2) if s.IsEmpty() { t.Error("expected a set with added items to not be empty") } } func TestIsEqual(t *testing.T) { var e1, e2 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } s1 := New() s2 := New() if !s1.IsEqual(s2) { t.Error("expected 2 new sets to be equal") } s1.Add(e1) s1.Add(e2) if s1.IsEqual(s2) { t.Errorf("expected 2 different sets to be equal, %v, %v", s1, s2) } s2.Add(e1) s2.Add(e2) if !s1.IsEqual(s2) { t.Error("expected 2 sets with the same items added to be equal") } } func TestIsSubset(t *testing.T) { var e1, e2, e3 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e3 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s1.IsSubset(s2) { t.Errorf("expected %v to be a subset of %v", s2, s1) } s2.Add(e2) s2.Add(e3) if s1.IsSubset(s2) { t.Errorf("expected %v not to be a subset of %v", s2, s1) } } func TestIsSuperset(t *testing.T) { var e1, e2 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s2.IsSuperset(s1) { t.Errorf("expected %v to be a super set of %v", s1, s2) } } func TestCopy(t *testing.T) { var e1, e2 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := s1.Copy() if !s2.IsEqual(s1) { t.Errorf("expected %v to be equal to %v after copy", s1, s2) } } func TestString(t *testing.T) { var e1 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } s1 := New() s1.Add(e1) s := s1.String() if s == "" { t.Errorf("expected string representation %v to exist", s) } if !strings.HasPrefix(s, "[") && !strings.HasSuffix(s, "]") { t.Errorf("expected string representation %v to start with '[' and end with ']'", s) } } func TestMerge(t *testing.T) { var e1, e2 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s2.Add(e2) s1.Merge(s2) if s1.Size() != 2 { t.Errorf("expected merged set %v have size 2 but it has %d", s1, s1.Size()) } } func TestList(t *testing.T) { var e1, e2 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) l := s.List() if len(l) != s.Size() { t.Errorf("expected a set of size %d to give a list of size 2 but it has %d", s.Size(), len(l)) } for _, e := range l { if !s.Has(e) { t.Errorf("listed entry %v not available in the set %s", e, s) } } } func TestSeparate(t *testing.T) { var e1, e2 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e2) s1.Separate(s2) if s1.Size() != 1 { t.Errorf("expected separated set %v have size 1 but it has %d", s1, s1.Size()) } if s1.Has(e2) { t.Errorf("separated set %v still contains %v", s1, e2) } } func TestEach(t *testing.T) { var e1, e2 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) found := make(map[uint32]bool) s1.Each(func(item uint32) bool { found[item] = true return true }) if len(found) != 2 { t.Errorf("not all items traversed only %v", found) } found = make(map[uint32]bool) count := 0 s1.Each(func(item uint32) bool { found[item] = true count++ if count > 0 { return false } return true }) if len(found) != 1 { t.Errorf("more than expected 1 items traversed %v", found) } } func TestIntersection(t *testing.T) { var e1, e2, e3 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint32); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Intersection(s1, s2) if s3.Size() != 1 || !s3.Has(e2) { t.Errorf("expected the intersection to only contain '%v' but it is %v", e2, s3.List()) } } func TestUnion(t *testing.T) { var e1, e2, e3 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint32); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Union(s1, s2) if s3.Size() != 3 || !(s3.Has(e1) && s3.Has(e2) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestDifference(t *testing.T) { var e1, e2, e3 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint32); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Difference(s1, s2) if s3.Size() != 1 || !s3.Has(e1) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestSymmetricDifference(t *testing.T) { var e1, e2, e3 uint32 e := createRandomObject(e1) if v, ok := e.(uint32); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint32); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint32); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := SymmetricDifference(s1, s2) if s3.Size() != 2 || !(s3.Has(e1) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func createRandomObject(i interface{}) interface{} { v, ok := quick.Value(reflect.TypeOf(i), rand.New(rand.NewSource(time.Now().UnixNano()))) if !ok { panic(fmt.Sprintf("unsupported type %v", i)) } return v.Interface() } scylladb-go-set-e560bb8/u64set/000077500000000000000000000000001337277605500162715ustar00rootroot00000000000000scylladb-go-set-e560bb8/u64set/u64set.go000066400000000000000000000142431337277605500177560ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package u64set import ( "fmt" "math" "strings" ) var ( // helpful to not write everywhere struct{}{} keyExists = struct{}{} nonExistent uint64 ) // Set is the main set structure that holds all the data // and methods used to working with the set. type Set struct { m map[uint64]struct{} } // New creates and initializes a new Set. func New(ts ...uint64) *Set { s := NewWithSize(len(ts)) s.Add(ts...) return s } // NewWithSize creates a new Set and gives make map a size hint. func NewWithSize(size int) *Set { return &Set{make(map[uint64]struct{}, size)} } // Add includes the specified items (one or more) to the Set. The underlying // Set s is modified. If passed nothing it silently returns. func (s *Set) Add(items ...uint64) { for _, item := range items { s.m[item] = keyExists } } // Remove deletes the specified items from the Set. The underlying Set s is // modified. If passed nothing it silently returns. func (s *Set) Remove(items ...uint64) { for _, item := range items { delete(s.m, item) } } // Pop deletes and returns an item from the Set. The underlying Set s is // modified. If Set is empty, the zero value is returned. func (s *Set) Pop() uint64 { for item := range s.m { delete(s.m, item) return item } return nonExistent } // Pop2 tries to delete and return an item from the Set. The underlying Set s // is modified. The second value is a bool that is true if the item existed in // the set, and false if not. If Set is empty, the zero value and false are // returned. func (s *Set) Pop2() (uint64, bool) { for item := range s.m { delete(s.m, item) return item, true } return nonExistent, false } // Has looks for the existence of items passed. It returns false if nothing is // passed. For multiple items it returns true only if all of the items exist. func (s *Set) Has(items ...uint64) bool { has := false for _, item := range items { if _, has = s.m[item]; !has { break } } return has } // HasAny looks for the existence of any of the items passed. // It returns false if nothing is passed. // For multiple items it returns true if any of the items exist. func (s *Set) HasAny(items ...uint64) bool { has := false for _, item := range items { if _, has = s.m[item]; has { break } } return has } // Size returns the number of items in a Set. func (s *Set) Size() int { return len(s.m) } // Clear removes all items from the Set. func (s *Set) Clear() { s.m = make(map[uint64]struct{}) } // IsEmpty reports whether the Set is empty. func (s *Set) IsEmpty() bool { return s.Size() == 0 } // IsEqual test whether s and t are the same in size and have the same items. func (s *Set) IsEqual(t *Set) bool { // return false if they are no the same size if s.Size() != t.Size() { return false } equal := true t.Each(func(item uint64) bool { _, equal = s.m[item] return equal // if false, Each() will end }) return equal } // IsSubset tests whether t is a subset of s. func (s *Set) IsSubset(t *Set) bool { if s.Size() < t.Size() { return false } subset := true t.Each(func(item uint64) bool { _, subset = s.m[item] return subset }) return subset } // IsSuperset tests whether t is a superset of s. func (s *Set) IsSuperset(t *Set) bool { return t.IsSubset(s) } // Each traverses the items in the Set, calling the provided function for each // Set member. Traversal will continue until all items in the Set have been // visited, or if the closure returns false. func (s *Set) Each(f func(item uint64) bool) { for item := range s.m { if !f(item) { break } } } // Copy returns a new Set with a copy of s. func (s *Set) Copy() *Set { u := NewWithSize(s.Size()) for item := range s.m { u.m[item] = keyExists } return u } // String returns a string representation of s func (s *Set) String() string { v := make([]string, 0, s.Size()) for item := range s.m { v = append(v, fmt.Sprintf("%v", item)) } return fmt.Sprintf("[%s]", strings.Join(v, ", ")) } // List returns a slice of all items. There is also StringSlice() and // IntSlice() methods for returning slices of type string or int. func (s *Set) List() []uint64 { v := make([]uint64, 0, s.Size()) for item := range s.m { v = append(v, item) } return v } // Merge is like Union, however it modifies the current Set it's applied on // with the given t Set. func (s *Set) Merge(t *Set) { for item := range t.m { s.m[item] = keyExists } } // Separate removes the Set items containing in t from Set s. Please aware that // it's not the opposite of Merge. func (s *Set) Separate(t *Set) { for item := range t.m { delete(s.m, item) } } // Union is the merger of multiple sets. It returns a new set with all the // elements present in all the sets that are passed. func Union(sets ...*Set) *Set { maxPos := -1 maxSize := 0 for i, set := range sets { if l := set.Size(); l > maxSize { maxSize = l maxPos = i } } if maxSize == 0 { return New() } u := sets[maxPos].Copy() for i, set := range sets { if i == maxPos { continue } for item := range set.m { u.m[item] = keyExists } } return u } // Difference returns a new set which contains items which are in in the first // set but not in the others. func Difference(set1 *Set, sets ...*Set) *Set { s := set1.Copy() for _, set := range sets { s.Separate(set) } return s } // Intersection returns a new set which contains items that only exist in all // given sets. func Intersection(sets ...*Set) *Set { minPos := -1 minSize := math.MaxInt64 for i, set := range sets { if l := set.Size(); l < minSize { minSize = l minPos = i } } if minSize == math.MaxInt64 || minSize == 0 { return New() } t := sets[minPos].Copy() for i, set := range sets { if i == minPos { continue } for item := range t.m { if _, has := set.m[item]; !has { delete(t.m, item) } } } return t } // SymmetricDifference returns a new set which s is the difference of items // which are in one of either, but not in both. func SymmetricDifference(s *Set, t *Set) *Set { u := Difference(s, t) v := Difference(t, s) return Union(u, v) } scylladb-go-set-e560bb8/u64set/u64set_bench_test.go000066400000000000000000000046531337277605500221600ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package u64set import ( "github.com/fatih/set" "testing" ) func BenchmarkTypeSafeSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } b.StartTimer() s := New() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExisting(b *testing.B) { b.StopTimer() var e1 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } b.StartTimer() s := New() s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExisting(b *testing.B) { b.StopTimer() var e1 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExistingMany(b *testing.B) { s := New() b.StopTimer() var e1 uint64 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(uint64); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExistingMany(b *testing.B) { s := set.New(set.NonThreadSafe) b.StopTimer() var e1 uint64 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(uint64); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetAdd(b *testing.B) { b.StopTimer() var e uint64 s := New() objs := make([]uint64, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(uint64); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } func BenchmarkInterfaceSetAdd(b *testing.B) { b.StopTimer() var e uint64 s := set.New(set.NonThreadSafe) objs := make([]uint64, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(uint64); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } scylladb-go-set-e560bb8/u64set/u64set_test.go000066400000000000000000000250361337277605500210170ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package u64set import ( "fmt" "math/rand" "reflect" "strings" "testing" "testing/quick" "time" ) func TestAdd(t *testing.T) { var e1, e2 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if len(s.m) != 2 { t.Errorf("expected 2 entries, got %d", len(s.m)) } } func TestRemove(t *testing.T) { var e1, e2 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Remove(e1) if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if _, ok := s.m[e2]; !ok { t.Errorf("wrong entry %v removed, expected %v", e1, e2) } } func TestPop(t *testing.T) { var e1, e2 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } s := New() popped := s.Pop() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } s.Add(e1) s.Add(e2) s.Pop() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } } func TestPop2(t *testing.T) { var e1, e2 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } s := New() popped, found := s.Pop2() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } if found { t.Errorf("set is empty, no element should have been found") } s.Add(e1) s.Add(e2) _, found = s.Pop2() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if !found { t.Errorf("expected to find an entry") } } func TestHas(t *testing.T) { var e1, e2, e3 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.Has(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.Has(e2) { t.Errorf("expected the set to contain %v", e2) } if s.Has(e3) { t.Errorf("did not expect the set to contain %v", e3) } } func TestHasAny(t *testing.T) { var e1, e2, e3 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.HasAny(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.HasAny(e2) { t.Errorf("expected the set to contain %v", e2) } if s.HasAny(e3) { t.Errorf("did not expect the set to contain %v", e3) } if !s.HasAny(e1, e3) { t.Errorf("expected the set to contain %v", e1) } } func TestSize(t *testing.T) { var e1, e2 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if s.Size() != 2 { t.Errorf("expected the set size to be 2 but it was %d", s.Size()) } } func TestClear(t *testing.T) { var e1, e2 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Clear() if s.Size() != 0 { t.Errorf("expected the cleared set size to be 0 but it was %d", s.Size()) } } func TestIsEmpty(t *testing.T) { var e1, e2 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } s := New() if !s.IsEmpty() { t.Errorf("expected new set to be empty but it had %d elements", s.Size()) } s.Add(e1) s.Add(e2) if s.IsEmpty() { t.Error("expected a set with added items to not be empty") } } func TestIsEqual(t *testing.T) { var e1, e2 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } s1 := New() s2 := New() if !s1.IsEqual(s2) { t.Error("expected 2 new sets to be equal") } s1.Add(e1) s1.Add(e2) if s1.IsEqual(s2) { t.Errorf("expected 2 different sets to be equal, %v, %v", s1, s2) } s2.Add(e1) s2.Add(e2) if !s1.IsEqual(s2) { t.Error("expected 2 sets with the same items added to be equal") } } func TestIsSubset(t *testing.T) { var e1, e2, e3 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e3 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s1.IsSubset(s2) { t.Errorf("expected %v to be a subset of %v", s2, s1) } s2.Add(e2) s2.Add(e3) if s1.IsSubset(s2) { t.Errorf("expected %v not to be a subset of %v", s2, s1) } } func TestIsSuperset(t *testing.T) { var e1, e2 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s2.IsSuperset(s1) { t.Errorf("expected %v to be a super set of %v", s1, s2) } } func TestCopy(t *testing.T) { var e1, e2 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := s1.Copy() if !s2.IsEqual(s1) { t.Errorf("expected %v to be equal to %v after copy", s1, s2) } } func TestString(t *testing.T) { var e1 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } s1 := New() s1.Add(e1) s := s1.String() if s == "" { t.Errorf("expected string representation %v to exist", s) } if !strings.HasPrefix(s, "[") && !strings.HasSuffix(s, "]") { t.Errorf("expected string representation %v to start with '[' and end with ']'", s) } } func TestMerge(t *testing.T) { var e1, e2 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s2.Add(e2) s1.Merge(s2) if s1.Size() != 2 { t.Errorf("expected merged set %v have size 2 but it has %d", s1, s1.Size()) } } func TestList(t *testing.T) { var e1, e2 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) l := s.List() if len(l) != s.Size() { t.Errorf("expected a set of size %d to give a list of size 2 but it has %d", s.Size(), len(l)) } for _, e := range l { if !s.Has(e) { t.Errorf("listed entry %v not available in the set %s", e, s) } } } func TestSeparate(t *testing.T) { var e1, e2 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e2) s1.Separate(s2) if s1.Size() != 1 { t.Errorf("expected separated set %v have size 1 but it has %d", s1, s1.Size()) } if s1.Has(e2) { t.Errorf("separated set %v still contains %v", s1, e2) } } func TestEach(t *testing.T) { var e1, e2 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) found := make(map[uint64]bool) s1.Each(func(item uint64) bool { found[item] = true return true }) if len(found) != 2 { t.Errorf("not all items traversed only %v", found) } found = make(map[uint64]bool) count := 0 s1.Each(func(item uint64) bool { found[item] = true count++ if count > 0 { return false } return true }) if len(found) != 1 { t.Errorf("more than expected 1 items traversed %v", found) } } func TestIntersection(t *testing.T) { var e1, e2, e3 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint64); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Intersection(s1, s2) if s3.Size() != 1 || !s3.Has(e2) { t.Errorf("expected the intersection to only contain '%v' but it is %v", e2, s3.List()) } } func TestUnion(t *testing.T) { var e1, e2, e3 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint64); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Union(s1, s2) if s3.Size() != 3 || !(s3.Has(e1) && s3.Has(e2) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestDifference(t *testing.T) { var e1, e2, e3 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint64); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Difference(s1, s2) if s3.Size() != 1 || !s3.Has(e1) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestSymmetricDifference(t *testing.T) { var e1, e2, e3 uint64 e := createRandomObject(e1) if v, ok := e.(uint64); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint64); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint64); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := SymmetricDifference(s1, s2) if s3.Size() != 2 || !(s3.Has(e1) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func createRandomObject(i interface{}) interface{} { v, ok := quick.Value(reflect.TypeOf(i), rand.New(rand.NewSource(time.Now().UnixNano()))) if !ok { panic(fmt.Sprintf("unsupported type %v", i)) } return v.Interface() } scylladb-go-set-e560bb8/u8set/000077500000000000000000000000001337277605500162075ustar00rootroot00000000000000scylladb-go-set-e560bb8/u8set/u8set.go000066400000000000000000000142221337277605500176070ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package u8set import ( "fmt" "math" "strings" ) var ( // helpful to not write everywhere struct{}{} keyExists = struct{}{} nonExistent uint8 ) // Set is the main set structure that holds all the data // and methods used to working with the set. type Set struct { m map[uint8]struct{} } // New creates and initializes a new Set. func New(ts ...uint8) *Set { s := NewWithSize(len(ts)) s.Add(ts...) return s } // NewWithSize creates a new Set and gives make map a size hint. func NewWithSize(size int) *Set { return &Set{make(map[uint8]struct{}, size)} } // Add includes the specified items (one or more) to the Set. The underlying // Set s is modified. If passed nothing it silently returns. func (s *Set) Add(items ...uint8) { for _, item := range items { s.m[item] = keyExists } } // Remove deletes the specified items from the Set. The underlying Set s is // modified. If passed nothing it silently returns. func (s *Set) Remove(items ...uint8) { for _, item := range items { delete(s.m, item) } } // Pop deletes and returns an item from the Set. The underlying Set s is // modified. If Set is empty, the zero value is returned. func (s *Set) Pop() uint8 { for item := range s.m { delete(s.m, item) return item } return nonExistent } // Pop2 tries to delete and return an item from the Set. The underlying Set s // is modified. The second value is a bool that is true if the item existed in // the set, and false if not. If Set is empty, the zero value and false are // returned. func (s *Set) Pop2() (uint8, bool) { for item := range s.m { delete(s.m, item) return item, true } return nonExistent, false } // Has looks for the existence of items passed. It returns false if nothing is // passed. For multiple items it returns true only if all of the items exist. func (s *Set) Has(items ...uint8) bool { has := false for _, item := range items { if _, has = s.m[item]; !has { break } } return has } // HasAny looks for the existence of any of the items passed. // It returns false if nothing is passed. // For multiple items it returns true if any of the items exist. func (s *Set) HasAny(items ...uint8) bool { has := false for _, item := range items { if _, has = s.m[item]; has { break } } return has } // Size returns the number of items in a Set. func (s *Set) Size() int { return len(s.m) } // Clear removes all items from the Set. func (s *Set) Clear() { s.m = make(map[uint8]struct{}) } // IsEmpty reports whether the Set is empty. func (s *Set) IsEmpty() bool { return s.Size() == 0 } // IsEqual test whether s and t are the same in size and have the same items. func (s *Set) IsEqual(t *Set) bool { // return false if they are no the same size if s.Size() != t.Size() { return false } equal := true t.Each(func(item uint8) bool { _, equal = s.m[item] return equal // if false, Each() will end }) return equal } // IsSubset tests whether t is a subset of s. func (s *Set) IsSubset(t *Set) bool { if s.Size() < t.Size() { return false } subset := true t.Each(func(item uint8) bool { _, subset = s.m[item] return subset }) return subset } // IsSuperset tests whether t is a superset of s. func (s *Set) IsSuperset(t *Set) bool { return t.IsSubset(s) } // Each traverses the items in the Set, calling the provided function for each // Set member. Traversal will continue until all items in the Set have been // visited, or if the closure returns false. func (s *Set) Each(f func(item uint8) bool) { for item := range s.m { if !f(item) { break } } } // Copy returns a new Set with a copy of s. func (s *Set) Copy() *Set { u := NewWithSize(s.Size()) for item := range s.m { u.m[item] = keyExists } return u } // String returns a string representation of s func (s *Set) String() string { v := make([]string, 0, s.Size()) for item := range s.m { v = append(v, fmt.Sprintf("%v", item)) } return fmt.Sprintf("[%s]", strings.Join(v, ", ")) } // List returns a slice of all items. There is also StringSlice() and // IntSlice() methods for returning slices of type string or int. func (s *Set) List() []uint8 { v := make([]uint8, 0, s.Size()) for item := range s.m { v = append(v, item) } return v } // Merge is like Union, however it modifies the current Set it's applied on // with the given t Set. func (s *Set) Merge(t *Set) { for item := range t.m { s.m[item] = keyExists } } // Separate removes the Set items containing in t from Set s. Please aware that // it's not the opposite of Merge. func (s *Set) Separate(t *Set) { for item := range t.m { delete(s.m, item) } } // Union is the merger of multiple sets. It returns a new set with all the // elements present in all the sets that are passed. func Union(sets ...*Set) *Set { maxPos := -1 maxSize := 0 for i, set := range sets { if l := set.Size(); l > maxSize { maxSize = l maxPos = i } } if maxSize == 0 { return New() } u := sets[maxPos].Copy() for i, set := range sets { if i == maxPos { continue } for item := range set.m { u.m[item] = keyExists } } return u } // Difference returns a new set which contains items which are in in the first // set but not in the others. func Difference(set1 *Set, sets ...*Set) *Set { s := set1.Copy() for _, set := range sets { s.Separate(set) } return s } // Intersection returns a new set which contains items that only exist in all // given sets. func Intersection(sets ...*Set) *Set { minPos := -1 minSize := math.MaxInt64 for i, set := range sets { if l := set.Size(); l < minSize { minSize = l minPos = i } } if minSize == math.MaxInt64 || minSize == 0 { return New() } t := sets[minPos].Copy() for i, set := range sets { if i == minPos { continue } for item := range t.m { if _, has := set.m[item]; !has { delete(t.m, item) } } } return t } // SymmetricDifference returns a new set which s is the difference of items // which are in one of either, but not in both. func SymmetricDifference(s *Set, t *Set) *Set { u := Difference(s, t) v := Difference(t, s) return Union(u, v) } scylladb-go-set-e560bb8/u8set/u8set_bench_test.go000066400000000000000000000046301337277605500220070ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package u8set import ( "github.com/fatih/set" "testing" ) func BenchmarkTypeSafeSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } b.StartTimer() s := New() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExisting(b *testing.B) { b.StopTimer() var e1 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } b.StartTimer() s := New() s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExisting(b *testing.B) { b.StopTimer() var e1 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExistingMany(b *testing.B) { s := New() b.StopTimer() var e1 uint8 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(uint8); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExistingMany(b *testing.B) { s := set.New(set.NonThreadSafe) b.StopTimer() var e1 uint8 for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(uint8); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetAdd(b *testing.B) { b.StopTimer() var e uint8 s := New() objs := make([]uint8, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(uint8); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } func BenchmarkInterfaceSetAdd(b *testing.B) { b.StopTimer() var e uint8 s := set.New(set.NonThreadSafe) objs := make([]uint8, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(uint8); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } scylladb-go-set-e560bb8/u8set/u8set_test.go000066400000000000000000000247211337277605500206530ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package u8set import ( "fmt" "math/rand" "reflect" "strings" "testing" "testing/quick" "time" ) func TestAdd(t *testing.T) { var e1, e2 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if len(s.m) != 2 { t.Errorf("expected 2 entries, got %d", len(s.m)) } } func TestRemove(t *testing.T) { var e1, e2 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Remove(e1) if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if _, ok := s.m[e2]; !ok { t.Errorf("wrong entry %v removed, expected %v", e1, e2) } } func TestPop(t *testing.T) { var e1, e2 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } s := New() popped := s.Pop() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } s.Add(e1) s.Add(e2) s.Pop() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } } func TestPop2(t *testing.T) { var e1, e2 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } s := New() popped, found := s.Pop2() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } if found { t.Errorf("set is empty, no element should have been found") } s.Add(e1) s.Add(e2) _, found = s.Pop2() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if !found { t.Errorf("expected to find an entry") } } func TestHas(t *testing.T) { var e1, e2, e3 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.Has(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.Has(e2) { t.Errorf("expected the set to contain %v", e2) } if s.Has(e3) { t.Errorf("did not expect the set to contain %v", e3) } } func TestHasAny(t *testing.T) { var e1, e2, e3 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.HasAny(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.HasAny(e2) { t.Errorf("expected the set to contain %v", e2) } if s.HasAny(e3) { t.Errorf("did not expect the set to contain %v", e3) } if !s.HasAny(e1, e3) { t.Errorf("expected the set to contain %v", e1) } } func TestSize(t *testing.T) { var e1, e2 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if s.Size() != 2 { t.Errorf("expected the set size to be 2 but it was %d", s.Size()) } } func TestClear(t *testing.T) { var e1, e2 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Clear() if s.Size() != 0 { t.Errorf("expected the cleared set size to be 0 but it was %d", s.Size()) } } func TestIsEmpty(t *testing.T) { var e1, e2 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } s := New() if !s.IsEmpty() { t.Errorf("expected new set to be empty but it had %d elements", s.Size()) } s.Add(e1) s.Add(e2) if s.IsEmpty() { t.Error("expected a set with added items to not be empty") } } func TestIsEqual(t *testing.T) { var e1, e2 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } s1 := New() s2 := New() if !s1.IsEqual(s2) { t.Error("expected 2 new sets to be equal") } s1.Add(e1) s1.Add(e2) if s1.IsEqual(s2) { t.Errorf("expected 2 different sets to be equal, %v, %v", s1, s2) } s2.Add(e1) s2.Add(e2) if !s1.IsEqual(s2) { t.Error("expected 2 sets with the same items added to be equal") } } func TestIsSubset(t *testing.T) { var e1, e2, e3 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e3 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s1.IsSubset(s2) { t.Errorf("expected %v to be a subset of %v", s2, s1) } s2.Add(e2) s2.Add(e3) if s1.IsSubset(s2) { t.Errorf("expected %v not to be a subset of %v", s2, s1) } } func TestIsSuperset(t *testing.T) { var e1, e2 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s2.IsSuperset(s1) { t.Errorf("expected %v to be a super set of %v", s1, s2) } } func TestCopy(t *testing.T) { var e1, e2 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := s1.Copy() if !s2.IsEqual(s1) { t.Errorf("expected %v to be equal to %v after copy", s1, s2) } } func TestString(t *testing.T) { var e1 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } s1 := New() s1.Add(e1) s := s1.String() if s == "" { t.Errorf("expected string representation %v to exist", s) } if !strings.HasPrefix(s, "[") && !strings.HasSuffix(s, "]") { t.Errorf("expected string representation %v to start with '[' and end with ']'", s) } } func TestMerge(t *testing.T) { var e1, e2 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s2.Add(e2) s1.Merge(s2) if s1.Size() != 2 { t.Errorf("expected merged set %v have size 2 but it has %d", s1, s1.Size()) } } func TestList(t *testing.T) { var e1, e2 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) l := s.List() if len(l) != s.Size() { t.Errorf("expected a set of size %d to give a list of size 2 but it has %d", s.Size(), len(l)) } for _, e := range l { if !s.Has(e) { t.Errorf("listed entry %v not available in the set %s", e, s) } } } func TestSeparate(t *testing.T) { var e1, e2 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e2) s1.Separate(s2) if s1.Size() != 1 { t.Errorf("expected separated set %v have size 1 but it has %d", s1, s1.Size()) } if s1.Has(e2) { t.Errorf("separated set %v still contains %v", s1, e2) } } func TestEach(t *testing.T) { var e1, e2 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) found := make(map[uint8]bool) s1.Each(func(item uint8) bool { found[item] = true return true }) if len(found) != 2 { t.Errorf("not all items traversed only %v", found) } found = make(map[uint8]bool) count := 0 s1.Each(func(item uint8) bool { found[item] = true count++ if count > 0 { return false } return true }) if len(found) != 1 { t.Errorf("more than expected 1 items traversed %v", found) } } func TestIntersection(t *testing.T) { var e1, e2, e3 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint8); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Intersection(s1, s2) if s3.Size() != 1 || !s3.Has(e2) { t.Errorf("expected the intersection to only contain '%v' but it is %v", e2, s3.List()) } } func TestUnion(t *testing.T) { var e1, e2, e3 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint8); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Union(s1, s2) if s3.Size() != 3 || !(s3.Has(e1) && s3.Has(e2) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestDifference(t *testing.T) { var e1, e2, e3 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint8); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Difference(s1, s2) if s3.Size() != 1 || !s3.Has(e1) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestSymmetricDifference(t *testing.T) { var e1, e2, e3 uint8 e := createRandomObject(e1) if v, ok := e.(uint8); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint8); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint8); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := SymmetricDifference(s1, s2) if s3.Size() != 2 || !(s3.Has(e1) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func createRandomObject(i interface{}) interface{} { v, ok := quick.Value(reflect.TypeOf(i), rand.New(rand.NewSource(time.Now().UnixNano()))) if !ok { panic(fmt.Sprintf("unsupported type %v", i)) } return v.Interface() } scylladb-go-set-e560bb8/uset/000077500000000000000000000000001337277605500161175ustar00rootroot00000000000000scylladb-go-set-e560bb8/uset/uset.go000066400000000000000000000142011337277605500174240ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package uset import ( "fmt" "math" "strings" ) var ( // helpful to not write everywhere struct{}{} keyExists = struct{}{} nonExistent uint ) // Set is the main set structure that holds all the data // and methods used to working with the set. type Set struct { m map[uint]struct{} } // New creates and initializes a new Set. func New(ts ...uint) *Set { s := NewWithSize(len(ts)) s.Add(ts...) return s } // NewWithSize creates a new Set and gives make map a size hint. func NewWithSize(size int) *Set { return &Set{make(map[uint]struct{}, size)} } // Add includes the specified items (one or more) to the Set. The underlying // Set s is modified. If passed nothing it silently returns. func (s *Set) Add(items ...uint) { for _, item := range items { s.m[item] = keyExists } } // Remove deletes the specified items from the Set. The underlying Set s is // modified. If passed nothing it silently returns. func (s *Set) Remove(items ...uint) { for _, item := range items { delete(s.m, item) } } // Pop deletes and returns an item from the Set. The underlying Set s is // modified. If Set is empty, the zero value is returned. func (s *Set) Pop() uint { for item := range s.m { delete(s.m, item) return item } return nonExistent } // Pop2 tries to delete and return an item from the Set. The underlying Set s // is modified. The second value is a bool that is true if the item existed in // the set, and false if not. If Set is empty, the zero value and false are // returned. func (s *Set) Pop2() (uint, bool) { for item := range s.m { delete(s.m, item) return item, true } return nonExistent, false } // Has looks for the existence of items passed. It returns false if nothing is // passed. For multiple items it returns true only if all of the items exist. func (s *Set) Has(items ...uint) bool { has := false for _, item := range items { if _, has = s.m[item]; !has { break } } return has } // HasAny looks for the existence of any of the items passed. // It returns false if nothing is passed. // For multiple items it returns true if any of the items exist. func (s *Set) HasAny(items ...uint) bool { has := false for _, item := range items { if _, has = s.m[item]; has { break } } return has } // Size returns the number of items in a Set. func (s *Set) Size() int { return len(s.m) } // Clear removes all items from the Set. func (s *Set) Clear() { s.m = make(map[uint]struct{}) } // IsEmpty reports whether the Set is empty. func (s *Set) IsEmpty() bool { return s.Size() == 0 } // IsEqual test whether s and t are the same in size and have the same items. func (s *Set) IsEqual(t *Set) bool { // return false if they are no the same size if s.Size() != t.Size() { return false } equal := true t.Each(func(item uint) bool { _, equal = s.m[item] return equal // if false, Each() will end }) return equal } // IsSubset tests whether t is a subset of s. func (s *Set) IsSubset(t *Set) bool { if s.Size() < t.Size() { return false } subset := true t.Each(func(item uint) bool { _, subset = s.m[item] return subset }) return subset } // IsSuperset tests whether t is a superset of s. func (s *Set) IsSuperset(t *Set) bool { return t.IsSubset(s) } // Each traverses the items in the Set, calling the provided function for each // Set member. Traversal will continue until all items in the Set have been // visited, or if the closure returns false. func (s *Set) Each(f func(item uint) bool) { for item := range s.m { if !f(item) { break } } } // Copy returns a new Set with a copy of s. func (s *Set) Copy() *Set { u := NewWithSize(s.Size()) for item := range s.m { u.m[item] = keyExists } return u } // String returns a string representation of s func (s *Set) String() string { v := make([]string, 0, s.Size()) for item := range s.m { v = append(v, fmt.Sprintf("%v", item)) } return fmt.Sprintf("[%s]", strings.Join(v, ", ")) } // List returns a slice of all items. There is also StringSlice() and // IntSlice() methods for returning slices of type string or int. func (s *Set) List() []uint { v := make([]uint, 0, s.Size()) for item := range s.m { v = append(v, item) } return v } // Merge is like Union, however it modifies the current Set it's applied on // with the given t Set. func (s *Set) Merge(t *Set) { for item := range t.m { s.m[item] = keyExists } } // Separate removes the Set items containing in t from Set s. Please aware that // it's not the opposite of Merge. func (s *Set) Separate(t *Set) { for item := range t.m { delete(s.m, item) } } // Union is the merger of multiple sets. It returns a new set with all the // elements present in all the sets that are passed. func Union(sets ...*Set) *Set { maxPos := -1 maxSize := 0 for i, set := range sets { if l := set.Size(); l > maxSize { maxSize = l maxPos = i } } if maxSize == 0 { return New() } u := sets[maxPos].Copy() for i, set := range sets { if i == maxPos { continue } for item := range set.m { u.m[item] = keyExists } } return u } // Difference returns a new set which contains items which are in in the first // set but not in the others. func Difference(set1 *Set, sets ...*Set) *Set { s := set1.Copy() for _, set := range sets { s.Separate(set) } return s } // Intersection returns a new set which contains items that only exist in all // given sets. func Intersection(sets ...*Set) *Set { minPos := -1 minSize := math.MaxInt64 for i, set := range sets { if l := set.Size(); l < minSize { minSize = l minPos = i } } if minSize == math.MaxInt64 || minSize == 0 { return New() } t := sets[minPos].Copy() for i, set := range sets { if i == minPos { continue } for item := range t.m { if _, has := set.m[item]; !has { delete(t.m, item) } } } return t } // SymmetricDifference returns a new set which s is the difference of items // which are in one of either, but not in both. func SymmetricDifference(s *Set, t *Set) *Set { u := Difference(s, t) v := Difference(t, s) return Union(u, v) } scylladb-go-set-e560bb8/uset/uset_bench_test.go000066400000000000000000000046051337277605500216310ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package uset import ( "github.com/fatih/set" "testing" ) func BenchmarkTypeSafeSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } b.StartTimer() s := New() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasNonExisting(b *testing.B) { b.StopTimer() var e1 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExisting(b *testing.B) { b.StopTimer() var e1 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } b.StartTimer() s := New() s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExisting(b *testing.B) { b.StopTimer() var e1 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } b.StartTimer() s := set.New(set.NonThreadSafe) s.Add(e1) for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetHasExistingMany(b *testing.B) { s := New() b.StopTimer() var e1 uint for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(uint); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkInterfaceSetHasExistingMany(b *testing.B) { s := set.New(set.NonThreadSafe) b.StopTimer() var e1 uint for i := 0; i < 10000; i++ { e := createRandomObject(e1) if v, ok := e.(uint); ok { s.Add(v) if i == 5000 { e1 = v } } } b.StartTimer() for i := 0; i < b.N; i++ { s.Has(e1) } } func BenchmarkTypeSafeSetAdd(b *testing.B) { b.StopTimer() var e uint s := New() objs := make([]uint, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(uint); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } func BenchmarkInterfaceSetAdd(b *testing.B) { b.StopTimer() var e uint s := set.New(set.NonThreadSafe) objs := make([]uint, 0, b.N) for i := 0; i < b.N; i++ { e := createRandomObject(e) if v, ok := e.(uint); ok { objs = append(objs, v) } } b.StartTimer() for i := 0; i < b.N; i++ { s.Add(objs[i]) } } scylladb-go-set-e560bb8/uset/uset_test.go000066400000000000000000000246041337277605500204730ustar00rootroot00000000000000// Copyright (C) 2017 ScyllaDB // Use of this source code is governed by a ALv2-style // license that can be found at https://github.com/scylladb/go-set/LICENSE. package uset import ( "fmt" "math/rand" "reflect" "strings" "testing" "testing/quick" "time" ) func TestAdd(t *testing.T) { var e1, e2 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if len(s.m) != 2 { t.Errorf("expected 2 entries, got %d", len(s.m)) } } func TestRemove(t *testing.T) { var e1, e2 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Remove(e1) if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if _, ok := s.m[e2]; !ok { t.Errorf("wrong entry %v removed, expected %v", e1, e2) } } func TestPop(t *testing.T) { var e1, e2 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } s := New() popped := s.Pop() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } s.Add(e1) s.Add(e2) s.Pop() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } } func TestPop2(t *testing.T) { var e1, e2 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } s := New() popped, found := s.Pop2() if popped != nonExistent { t.Errorf("default non existent sentinel not returned, instead got %v", popped) } if found { t.Errorf("set is empty, no element should have been found") } s.Add(e1) s.Add(e2) _, found = s.Pop2() if len(s.m) != 1 { t.Errorf("expected 1 entries, got %d", len(s.m)) } if !found { t.Errorf("expected to find an entry") } } func TestHas(t *testing.T) { var e1, e2, e3 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.Has(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.Has(e2) { t.Errorf("expected the set to contain %v", e2) } if s.Has(e3) { t.Errorf("did not expect the set to contain %v", e3) } } func TestHasAny(t *testing.T) { var e1, e2, e3 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e3 = v } s := New() if s.Has(e1) { t.Errorf("expected a new set to not contain %v", e1) } s.Add(e1) s.Add(e2) if !s.HasAny(e1) { t.Errorf("expected the set to contain %v", e1) } if !s.HasAny(e2) { t.Errorf("expected the set to contain %v", e2) } if s.HasAny(e3) { t.Errorf("did not expect the set to contain %v", e3) } if !s.HasAny(e1, e3) { t.Errorf("expected the set to contain %v", e1) } } func TestSize(t *testing.T) { var e1, e2 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) if s.Size() != 2 { t.Errorf("expected the set size to be 2 but it was %d", s.Size()) } } func TestClear(t *testing.T) { var e1, e2 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) s.Clear() if s.Size() != 0 { t.Errorf("expected the cleared set size to be 0 but it was %d", s.Size()) } } func TestIsEmpty(t *testing.T) { var e1, e2 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } s := New() if !s.IsEmpty() { t.Errorf("expected new set to be empty but it had %d elements", s.Size()) } s.Add(e1) s.Add(e2) if s.IsEmpty() { t.Error("expected a set with added items to not be empty") } } func TestIsEqual(t *testing.T) { var e1, e2 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } s1 := New() s2 := New() if !s1.IsEqual(s2) { t.Error("expected 2 new sets to be equal") } s1.Add(e1) s1.Add(e2) if s1.IsEqual(s2) { t.Errorf("expected 2 different sets to be equal, %v, %v", s1, s2) } s2.Add(e1) s2.Add(e2) if !s1.IsEqual(s2) { t.Error("expected 2 sets with the same items added to be equal") } } func TestIsSubset(t *testing.T) { var e1, e2, e3 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e3 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s1.IsSubset(s2) { t.Errorf("expected %v to be a subset of %v", s2, s1) } s2.Add(e2) s2.Add(e3) if s1.IsSubset(s2) { t.Errorf("expected %v not to be a subset of %v", s2, s1) } } func TestIsSuperset(t *testing.T) { var e1, e2 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e1) if !s2.IsSuperset(s1) { t.Errorf("expected %v to be a super set of %v", s1, s2) } } func TestCopy(t *testing.T) { var e1, e2 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := s1.Copy() if !s2.IsEqual(s1) { t.Errorf("expected %v to be equal to %v after copy", s1, s2) } } func TestString(t *testing.T) { var e1 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } s1 := New() s1.Add(e1) s := s1.String() if s == "" { t.Errorf("expected string representation %v to exist", s) } if !strings.HasPrefix(s, "[") && !strings.HasSuffix(s, "]") { t.Errorf("expected string representation %v to start with '[' and end with ']'", s) } } func TestMerge(t *testing.T) { var e1, e2 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s2.Add(e2) s1.Merge(s2) if s1.Size() != 2 { t.Errorf("expected merged set %v have size 2 but it has %d", s1, s1.Size()) } } func TestList(t *testing.T) { var e1, e2 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } s := New() s.Add(e1) s.Add(e2) l := s.List() if len(l) != s.Size() { t.Errorf("expected a set of size %d to give a list of size 2 but it has %d", s.Size(), len(l)) } for _, e := range l { if !s.Has(e) { t.Errorf("listed entry %v not available in the set %s", e, s) } } } func TestSeparate(t *testing.T) { var e1, e2 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } s1 := New() s2 := New() s1.Add(e1) s1.Add(e2) s2.Add(e2) s1.Separate(s2) if s1.Size() != 1 { t.Errorf("expected separated set %v have size 1 but it has %d", s1, s1.Size()) } if s1.Has(e2) { t.Errorf("separated set %v still contains %v", s1, e2) } } func TestEach(t *testing.T) { var e1, e2 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } s1 := New() s1.Add(e1) s1.Add(e2) found := make(map[uint]bool) s1.Each(func(item uint) bool { found[item] = true return true }) if len(found) != 2 { t.Errorf("not all items traversed only %v", found) } found = make(map[uint]bool) count := 0 s1.Each(func(item uint) bool { found[item] = true count++ if count > 0 { return false } return true }) if len(found) != 1 { t.Errorf("more than expected 1 items traversed %v", found) } } func TestIntersection(t *testing.T) { var e1, e2, e3 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Intersection(s1, s2) if s3.Size() != 1 || !s3.Has(e2) { t.Errorf("expected the intersection to only contain '%v' but it is %v", e2, s3.List()) } } func TestUnion(t *testing.T) { var e1, e2, e3 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Union(s1, s2) if s3.Size() != 3 || !(s3.Has(e1) && s3.Has(e2) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestDifference(t *testing.T) { var e1, e2, e3 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := Difference(s1, s2) if s3.Size() != 1 || !s3.Has(e1) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func TestSymmetricDifference(t *testing.T) { var e1, e2, e3 uint e := createRandomObject(e1) if v, ok := e.(uint); ok { e1 = v } e = createRandomObject(e2) if v, ok := e.(uint); ok { e2 = v } e = createRandomObject(e3) if v, ok := e.(uint); ok { e3 = v } s1 := New() s1.Add(e1) s1.Add(e2) s2 := New() s2.Add(e2) s2.Add(e3) s3 := SymmetricDifference(s1, s2) if s3.Size() != 2 || !(s3.Has(e1) && s3.Has(e3)) { t.Errorf("expected the intersection to only contain %v but it is %v", e2, s3.List()) } } func createRandomObject(i interface{}) interface{} { v, ok := quick.Value(reflect.TypeOf(i), rand.New(rand.NewSource(time.Now().UnixNano()))) if !ok { panic(fmt.Sprintf("unsupported type %v", i)) } return v.Interface() }