Showing preview only (859K chars total). Download the full file or copy to clipboard to get everything.
Repository: Workiva/go-datastructures
Branch: master
Commit: 89d15facb2e3
Files: 180
Total size: 812.0 KB
Directory structure:
gitextract_a5x2r3bc/
├── .github/
│ ├── CODEOWNERS
│ └── workflows/
│ └── tests.yaml
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── augmentedtree/
│ ├── atree.go
│ ├── atree_test.go
│ ├── interface.go
│ ├── intervals.go
│ ├── intervals_test.go
│ ├── mock_test.go
│ └── multidimensional_test.go
├── aviary.yaml
├── batcher/
│ ├── batcher.go
│ └── batcher_test.go
├── bitarray/
│ ├── and.go
│ ├── and_test.go
│ ├── bitarray.go
│ ├── bitarray_test.go
│ ├── bitmap.go
│ ├── bitmap_test.go
│ ├── block.go
│ ├── block_test.go
│ ├── encoding.go
│ ├── encoding_test.go
│ ├── error.go
│ ├── interface.go
│ ├── iterator.go
│ ├── nand.go
│ ├── nand_test.go
│ ├── or.go
│ ├── or_test.go
│ ├── sparse_bitarray.go
│ ├── sparse_bitarray_test.go
│ └── util.go
├── btree/
│ ├── _link/
│ │ ├── interface.go
│ │ ├── key.go
│ │ ├── mock_test.go
│ │ ├── node.go
│ │ ├── node_test.go
│ │ ├── tree.go
│ │ └── tree_test.go
│ ├── immutable/
│ │ ├── add.go
│ │ ├── cacher.go
│ │ ├── config.go
│ │ ├── delete.go
│ │ ├── error.go
│ │ ├── interface.go
│ │ ├── item.go
│ │ ├── node.go
│ │ ├── node_gen.go
│ │ ├── path.go
│ │ ├── query.go
│ │ ├── rt.go
│ │ ├── rt_gen.go
│ │ └── rt_test.go
│ ├── palm/
│ │ ├── action.go
│ │ ├── interface.go
│ │ ├── key.go
│ │ ├── mock_test.go
│ │ ├── node.go
│ │ ├── tree.go
│ │ └── tree_test.go
│ └── plus/
│ ├── btree.go
│ ├── btree_test.go
│ ├── interface.go
│ ├── iterator.go
│ ├── mock_test.go
│ ├── node.go
│ └── node_test.go
├── cache/
│ ├── cache.go
│ └── cache_test.go
├── common/
│ └── interface.go
├── datastructures.go
├── documentation.md
├── fibheap/
│ ├── Test Generator/
│ │ ├── EnqDecrKey.py
│ │ ├── EnqDelete.py
│ │ ├── EnqDeqMin.py
│ │ ├── Merge.py
│ │ └── README.md
│ ├── benchmarks.txt
│ ├── fibheap.go
│ ├── fibheap_examples_test.go
│ ├── fibheap_single_example_test.go
│ └── fibheap_test.go
├── futures/
│ ├── futures.go
│ ├── futures_test.go
│ ├── selectable.go
│ └── selectable_test.go
├── go.mod
├── go.sum
├── graph/
│ ├── simple.go
│ └── simple_test.go
├── hashmap/
│ └── fastinteger/
│ ├── hash.go
│ ├── hash_test.go
│ ├── hashmap.go
│ └── hashmap_test.go
├── list/
│ ├── persistent.go
│ └── persistent_test.go
├── mock/
│ ├── batcher.go
│ └── rangetree.go
├── numerics/
│ ├── hilbert/
│ │ ├── hilbert.go
│ │ └── hilbert_test.go
│ └── optimization/
│ ├── global.go
│ ├── nelder_mead.go
│ └── nelder_mead_test.go
├── queue/
│ ├── error.go
│ ├── mock_test.go
│ ├── priority_queue.go
│ ├── priority_queue_test.go
│ ├── queue.go
│ ├── queue_test.go
│ ├── ring.go
│ └── ring_test.go
├── rangetree/
│ ├── entries.go
│ ├── entries_test.go
│ ├── error.go
│ ├── immutable.go
│ ├── immutable_test.go
│ ├── interface.go
│ ├── mock_test.go
│ ├── node.go
│ ├── ordered.go
│ ├── ordered_test.go
│ ├── orderedtree.go
│ ├── orderedtree_test.go
│ └── skiplist/
│ ├── mock_test.go
│ ├── skiplist.go
│ └── skiplist_test.go
├── rtree/
│ ├── hilbert/
│ │ ├── action.go
│ │ ├── cpu.prof
│ │ ├── hilbert.go
│ │ ├── mock_test.go
│ │ ├── node.go
│ │ ├── rectangle.go
│ │ ├── tree.go
│ │ └── tree_test.go
│ └── interface.go
├── set/
│ ├── dict.go
│ └── dict_test.go
├── slice/
│ ├── int64.go
│ ├── int64_test.go
│ └── skip/
│ ├── interface.go
│ ├── iterator.go
│ ├── iterator_test.go
│ ├── mock_test.go
│ ├── node.go
│ ├── skip.go
│ └── skip_test.go
├── sort/
│ ├── interface.go
│ ├── sort.go
│ ├── sort_test.go
│ ├── symmerge.go
│ └── symmerge_test.go
├── threadsafe/
│ └── err/
│ ├── error.go
│ └── error_test.go
├── tree/
│ └── avl/
│ ├── avl.go
│ ├── avl_test.go
│ ├── interface.go
│ ├── mock_test.go
│ └── node.go
└── trie/
├── ctrie/
│ ├── ctrie.go
│ └── ctrie_test.go
├── dtrie/
│ ├── dtrie.go
│ ├── dtrie_test.go
│ ├── node.go
│ └── util.go
├── xfast/
│ ├── iterator.go
│ ├── iterator_test.go
│ ├── mock_test.go
│ ├── xfast.go
│ └── xfast_test.go
└── yfast/
├── entries.go
├── entries_test.go
├── interface.go
├── iterator.go
├── mock_test.go
├── yfast.go
└── yfast_test.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/CODEOWNERS
================================================
@Workiva/skreams
================================================
FILE: .github/workflows/tests.yaml
================================================
name: "Tests"
on:
pull_request:
push:
branches:
- 'master'
tags:
- '*'
permissions:
pull-requests: write
contents: write
id-token: write
jobs:
Tests:
runs-on: ubuntu-latest
strategy:
matrix:
go: [ '1.15', 'stable' ]
name: Tests on Go ${{ matrix.go }}
steps:
- name: Checkout Repo
uses: actions/checkout@v4
with:
path: go/src/github.com/Workiva/go-datastructures
- name: Setup Go
uses: actions/setup-go@v5.0.0
with:
go-version: ${{ matrix.go }}
# go install does not work because it needs credentials
- name: install go2xunit
run: |
git clone https://github.com/tebeka/go2xunit.git
cd go2xunit
git checkout v1.4.10
go install
cd ..
- name: Run Tests
timeout-minutes: 10
run: |
cd go/src/github.com/Workiva/go-datastructures
go test ./... | tee ${{github.workspace}}/go-test.txt
- name: XML output
run: |
mkdir artifacts
go2xunit -input ./go-test.txt -output ./artifacts/tests_go_version-${{ matrix.go }}.xml
- name: Upload Test Results
uses: actions/upload-artifact@v4
with:
name: go-datastructures test go ${{ matrix.go }}
path: ./artifacts/tests_go_version-${{ matrix.go }}.xml
retention-days: 7
- uses: anchore/sbom-action@v0
with:
path: ./
format: cyclonedx-json
artifact-name: ${{ matrix.go }}-sbom.spdx
================================================
FILE: .gitignore
================================================
*.out
*.test
.idea
================================================
FILE: Dockerfile
================================================
FROM golang:1.16-alpine3.13 AS build-go
ARG GIT_SSH_KEY
ARG KNOWN_HOSTS_CONTENT
WORKDIR /go/src/github.com/Workiva/go-datastructures/
ADD . /go/src/github.com/Workiva/go-datastructures/
ARG GOPATH=/go/
ENV PATH $GOPATH/bin:$PATH
RUN echo "Starting the script section" && \
go mod vendor && \
echo "script section completed"
ARG BUILD_ARTIFACTS_DEPENDENCIES=/go/src/github.com/Workiva/go-datastructures/go.mod
FROM scratch
================================================
FILE: LICENSE
================================================
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 CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
go-datastructures
=================
Go-datastructures is a collection of useful, performant, and threadsafe Go
datastructures.
### NOTE: only tested with Go 1.3+.
#### Augmented Tree
Interval tree for collision in n-dimensional ranges. Implemented via a
red-black augmented tree. Extra dimensions are handled in simultaneous
inserts/queries to save space although this may result in suboptimal time
complexity. Intersection determined using bit arrays. In a single dimension,
inserts, deletes, and queries should be in O(log n) time.
#### Bitarray
Bitarray used to detect existence without having to resort to hashing with
hashmaps. Requires entities have a uint64 unique identifier. Two
implementations exist, regular and sparse. Sparse saves a great deal of space
but insertions are O(log n). There are some useful functions on the BitArray
interface to detect intersection between two bitarrays. This package also
includes bitmaps of length 32 and 64 that provide increased speed and O(1) for
all operations by storing the bitmaps in unsigned integers rather than arrays.
#### Futures
A helpful tool to send a "broadcast" message to listeners. Channels have the
issue that once one listener takes a message from a channel the other listeners
aren't notified. There were many cases when I wanted to notify many listeners
of a single event and this package helps.
#### Queue
Package contains both a normal and priority queue. Both implementations never
block on send and grow as much as necessary. Both also only return errors if
you attempt to push to a disposed queue and will not panic like sending a
message on a closed channel. The priority queue also allows you to place items
in priority order inside the queue. If you give a useful hint to the regular
queue, it is actually faster than a channel. The priority queue is somewhat
slow currently and targeted for an update to a Fibonacci heap.
Also included in the queue package is a MPMC threadsafe ring buffer. This is a
block full/empty queue, but will return a blocked thread if the queue is
disposed while a thread is blocked. This can be used to synchronize goroutines
and ensure goroutines quit so objects can be GC'd. Threadsafety is achieved
using only CAS operations making this queue quite fast. Benchmarks can be found
in that package.
#### Fibonacci Heap
A standard Fibonacci heap providing the usual operations. Can be useful in executing Dijkstra or Prim's algorithms in the theoretically minimal time. Also useful as a general-purpose priority queue. The special thing about Fibonacci heaps versus other heap variants is the cheap decrease-key operation. This heap has a constant complexity for find minimum, insert and merge of two heaps, an amortized constant complexity for decrease key and O(log(n)) complexity for a deletion or dequeue minimum. In practice the constant factors are large, so Fibonacci heaps could be slower than Pairing heaps, depending on usage. Benchmarks - in the project subfolder. The heap has not been designed for thread-safety.
#### Range Tree
Useful to determine if n-dimensional points fall within an n-dimensional range.
Not a typical range tree however, as we are actually using an n-dimensional
sorted list of points as this proved to be simpler and faster than attempting a
traditional range tree while saving space on any dimension greater than one.
Inserts are typical BBST times at O(log n^d) where d is the number of
dimensions.
#### Set
Our Set implementation is very simple, accepts items of type `interface{}` and
includes only a few methods. If your application requires a richer Set
implementation over lists of type `sort.Interface`, see
[xtgo/set](https://github.com/xtgo/set) and
[goware/set](https://github.com/goware/set).
#### Threadsafe
A package that is meant to contain some commonly used items but in a threadsafe
way. Example: there's a threadsafe error in there as I commonly found myself
wanting to set an error in many threads at the same time (yes, I know, but
channels are slow).
#### AVL Tree
This is an example of a branch copy immutable AVL BBST. Any operation on a node
makes a copy of that node's branch. Because of this, this tree is inherently
threadsafe although the writes will likely still need to be serialized. This
structure is good if your use case is a large number of reads and infrequent
writes as reads will be highly available but writes somewhat slow due to the
copying. This structure serves as a basis for a large number of functional data
structures.
#### X-Fast Trie
An interesting design that treats integers as words and uses a trie structure to
reduce time complexities by matching prefixes. This structure is really fast
for finding values or making predecessor/successor types of queries, but also
results in greater than linear space consumption. The exact time complexities
can be found in that package.
#### Y-Fast Trie
An extension of the X-Fast trie in which an X-Fast trie is combined with some
other ordered data structure to reduce space consumption and improve CRUD types
of operations. These secondary structures are often BSTs, but our implementation
uses a simple ordered list as I believe this improves cache locality. We also
use fixed size buckets to aid in parallelization of operations. Exact time
complexities are in that package.
#### Fast integer hashmap
A datastructure used for checking existence but without knowing the bounds of
your data. If you have a limited small bounds, the bitarray package might be a
better choice. This implementation uses a fairly simple hashing algorithm
combined with linear probing and a flat datastructure to provide optimal
performance up to a few million integers (faster than the native Golang
implementation). Beyond that, the native implementation is faster (I believe
they are using a large -ary B-tree). In the future, this will be implemented
with a B-tree for scale.
#### Skiplist
An ordered structure that provides amortized logarithmic operations but without
the complication of rotations that are required by BSTs. In testing, however,
the performance of the skip list is often far worse than the guaranteed log n
time of a BBST. Tall nodes tend to "cast shadows", especially when large
bitsizes are required as the optimum maximum height for a node is often based on
this. More detailed performance characteristics are provided in that package.
#### Sort
The sort package implements a multithreaded bucket sort that can be up to 3x
faster than the native Golang sort package. These buckets are then merged using
a symmetrical merge, similar to the stable sort in the Golang package. However,
our algorithm is modified so that two sorted lists can be merged by using
symmetrical decomposition.
#### Numerics
Early work on some nonlinear optimization problems. The initial implementation
allows a simple use case with either linear or nonlinear constraints. You can
find min/max or target an optimal value. The package currently employs a
probabilistic global restart system in an attempt to avoid local critical points.
More details can be found in that package.
#### B+ Tree
Initial implementation of a B+ tree. Delete method still needs added as well as
some performance optimization. Specific performance characteristics can be
found in that package. Despite the theoretical superiority of BSTs, the B-tree
often has better all around performance due to cache locality. The current
implementation is mutable, but the immutable AVL tree can be used to build an
immutable version. Unfortunately, to make the B-tree generic we require an
interface and the most expensive operation in CPU profiling is the interface
method which in turn calls into runtime.assertI2T. We need generics.
#### Immutable B Tree
A btree based on two principles, immutability and concurrency.
Somewhat slow for single value lookups and puts, it is very fast for bulk operations.
A persister can be injected to make this index persistent.
#### Ctrie
A concurrent, lock-free hash array mapped trie with efficient non-blocking
snapshots. For lookups, Ctries have comparable performance to concurrent skip
lists and concurrent hashmaps. One key advantage of Ctries is they are
dynamically allocated. Memory consumption is always proportional to the number
of keys in the Ctrie, while hashmaps typically have to grow and shrink. Lookups,
inserts, and removes are O(logn).
One interesting advantage Ctries have over traditional concurrent data
structures is support for lock-free, linearizable, constant-time snapshots.
Most concurrent data structures do not support snapshots, instead opting for
locks or requiring a quiescent state. This allows Ctries to have O(1) iterator
creation and clear operations and O(logn) size retrieval.
#### Dtrie
A persistent hash trie that dynamically expands or shrinks to provide efficient
memory allocation. Being persistent, the Dtrie is immutable and any modification
yields a new version of the Dtrie rather than changing the original. Bitmapped
nodes allow for O(log32(n)) get, remove, and update operations. Insertions are
O(n) and iteration is O(1).
#### Persistent List
A persistent, immutable linked list. All write operations yield a new, updated
structure which preserve and reuse previous versions. This uses a very
functional, cons-style of list manipulation. Insert, get, remove, and size
operations are O(n) as you would expect.
#### Simple Graph
A mutable, non-persistent undirected graph where parallel edges and self-loops are
not permitted. Operations to add an edge as well as retrieve the total number of
vertices/edges are O(1) while the operation to retrieve the vertices adjacent to a
target is O(n). For more details see [wikipedia](https://en.wikipedia.org/wiki/Graph_(discrete_mathematics)#Simple_graph)
### Installation
1. Install Go 1.3 or higher.
2. Run `go get github.com/Workiva/go-datastructures/...`
### Updating
When new code is merged to master, you can use
go get -u github.com/Workiva/go-datastructures/...
To retrieve the latest version of go-datastructures.
### Testing
To run all the unit tests use these commands:
cd $GOPATH/src/github.com/Workiva/go-datastructures
go get -t -u ./...
go test ./...
Once you've done this once, you can simply use this command to run all unit tests:
go test ./...
### Contributing
Requirements to commit here:
- Branch off master, PR back to master.
- `gofmt`'d code.
- Compliance with [these guidelines](https://code.google.com/p/go-wiki/wiki/CodeReviewComments)
- Unit test coverage
- [Good commit messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
### Maintainers
- Alexander Campbell <[alexander.campbell@workiva.com](mailto:alexander.campbell@workiva.com)>
- Dustin Hiatt <[dustin.hiatt@workiva.com](mailto:dustin.hiatt@workiva.com)>
- Ryan Jackson <[ryan.jackson@workiva.com](mailto:ryan.jackson@workiva.com)>
================================================
FILE: augmentedtree/atree.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package augmentedtree
func intervalOverlaps(n *node, low, high int64, interval Interval, maxDimension uint64) bool {
if !overlaps(n.interval.HighAtDimension(1), high, n.interval.LowAtDimension(1), low) {
return false
}
if interval == nil {
return true
}
for i := uint64(2); i <= maxDimension; i++ {
if !n.interval.OverlapsAtDimension(interval, i) {
return false
}
}
return true
}
func overlaps(high, otherHigh, low, otherLow int64) bool {
return high >= otherLow && low <= otherHigh
}
// compare returns an int indicating which direction the node
// should go.
func compare(nodeLow, ivLow int64, nodeID, ivID uint64) int {
if ivLow > nodeLow {
return 1
}
if ivLow < nodeLow {
return 0
}
return intFromBool(ivID > nodeID)
}
type node struct {
interval Interval
max, min int64 // max value held by children
children [2]*node // array to hold left/right
red bool // indicates if this node is red
id uint64 // we store the id locally to reduce the number of calls to the method on the interface
}
func (n *node) query(low, high int64, interval Interval, maxDimension uint64, fn func(node *node)) {
if n.children[0] != nil && overlaps(n.children[0].max, high, n.children[0].min, low) {
n.children[0].query(low, high, interval, maxDimension, fn)
}
if intervalOverlaps(n, low, high, interval, maxDimension) {
fn(n)
}
if n.children[1] != nil && overlaps(n.children[1].max, high, n.children[1].min, low) {
n.children[1].query(low, high, interval, maxDimension, fn)
}
}
func (n *node) adjustRanges() {
for i := 0; i <= 1; i++ {
if n.children[i] != nil {
n.children[i].adjustRanges()
}
}
n.adjustRange()
}
func (n *node) adjustRange() {
setMin(n)
setMax(n)
}
func newDummy() node {
return node{
children: [2]*node{},
}
}
func newNode(interval Interval, min, max int64, dimension uint64) *node {
itn := &node{
interval: interval,
min: min,
max: max,
red: true,
children: [2]*node{},
}
if interval != nil {
itn.id = interval.ID()
}
return itn
}
type tree struct {
root *node
maxDimension, number uint64
dummy node
}
func (t *tree) Traverse(fn func(id Interval)) {
nodes := []*node{t.root}
for len(nodes) != 0 {
c := nodes[len(nodes)-1]
nodes = nodes[:len(nodes)-1]
if c != nil {
fn(c.interval)
if c.children[0] != nil {
nodes = append(nodes, c.children[0])
}
if c.children[1] != nil {
nodes = append(nodes, c.children[1])
}
}
}
}
func (tree *tree) resetDummy() {
tree.dummy.children[0], tree.dummy.children[1] = nil, nil
tree.dummy.red = false
}
// Len returns the number of items in this tree.
func (tree *tree) Len() uint64 {
return tree.number
}
// add will add the provided interval to the tree.
func (tree *tree) add(iv Interval) {
if tree.root == nil {
tree.root = newNode(
iv, iv.LowAtDimension(1),
iv.HighAtDimension(1),
1,
)
tree.root.red = false
tree.number++
return
}
tree.resetDummy()
var (
dummy = tree.dummy
parent, grandParent *node
node = tree.root
dir, last int
otherLast = 1
id = iv.ID()
max = iv.HighAtDimension(1)
ivLow = iv.LowAtDimension(1)
helper = &dummy
)
// set this AFTER clearing dummy
helper.children[1] = tree.root
for {
if node == nil {
node = newNode(iv, ivLow, max, 1)
parent.children[dir] = node
tree.number++
} else if isRed(node.children[0]) && isRed(node.children[1]) {
node.red = true
node.children[0].red = false
node.children[1].red = false
}
if max > node.max {
node.max = max
}
if ivLow < node.min {
node.min = ivLow
}
if isRed(parent) && isRed(node) {
localDir := intFromBool(helper.children[1] == grandParent)
if node == parent.children[last] {
helper.children[localDir] = rotate(grandParent, otherLast)
} else {
helper.children[localDir] = doubleRotate(grandParent, otherLast)
}
}
if node.id == id {
break
}
last = dir
otherLast = takeOpposite(last)
dir = compare(node.interval.LowAtDimension(1), ivLow, node.id, id)
if grandParent != nil {
helper = grandParent
}
grandParent, parent, node = parent, node, node.children[dir]
}
tree.root = dummy.children[1]
tree.root.red = false
}
// Add will add the provided intervals to this tree.
func (tree *tree) Add(intervals ...Interval) {
for _, iv := range intervals {
tree.add(iv)
}
}
// delete will remove the provided interval from the tree.
func (tree *tree) delete(iv Interval) {
if tree.root == nil {
return
}
tree.resetDummy()
var (
dummy = tree.dummy
found, parent, grandParent *node
last, otherDir, otherLast int // keeping track of last direction
id = iv.ID()
dir = 1
node = &dummy
ivLow = iv.LowAtDimension(1)
)
node.children[1] = tree.root
for node.children[dir] != nil {
last = dir
otherLast = takeOpposite(last)
grandParent, parent, node = parent, node, node.children[dir]
dir = compare(node.interval.LowAtDimension(1), ivLow, node.id, id)
otherDir = takeOpposite(dir)
if node.id == id {
found = node
}
if !isRed(node) && !isRed(node.children[dir]) {
if isRed(node.children[otherDir]) {
parent.children[last] = rotate(node, dir)
parent = parent.children[last]
} else if !isRed(node.children[otherDir]) {
t := parent.children[otherLast]
if t != nil {
if !isRed(t.children[otherLast]) && !isRed(t.children[last]) {
parent.red = false
node.red = true
t.red = true
} else {
localDir := intFromBool(grandParent.children[1] == parent)
if isRed(t.children[last]) {
grandParent.children[localDir] = doubleRotate(
parent, last,
)
} else if isRed(t.children[otherLast]) {
grandParent.children[localDir] = rotate(
parent, last,
)
}
node.red = true
grandParent.children[localDir].red = true
grandParent.children[localDir].children[0].red = false
grandParent.children[localDir].children[1].red = false
}
}
}
}
}
if found != nil {
tree.number--
found.interval, found.max, found.min, found.id = node.interval, node.max, node.min, node.id
parentDir := intFromBool(parent.children[1] == node)
childDir := intFromBool(node.children[0] == nil)
parent.children[parentDir] = node.children[childDir]
}
tree.root = dummy.children[1]
if tree.root != nil {
tree.root.red = false
}
}
// Delete will remove the provided intervals from this tree.
func (tree *tree) Delete(intervals ...Interval) {
for _, iv := range intervals {
tree.delete(iv)
}
if tree.root != nil {
tree.root.adjustRanges()
}
}
// Query will return a list of intervals that intersect the provided
// interval. The provided interval's ID method is ignored so the
// provided ID is irrelevant.
func (tree *tree) Query(interval Interval) Intervals {
if tree.root == nil {
return nil
}
var (
Intervals = intervalsPool.Get().(Intervals)
ivLow = interval.LowAtDimension(1)
ivHigh = interval.HighAtDimension(1)
)
tree.root.query(ivLow, ivHigh, interval, tree.maxDimension, func(node *node) {
Intervals = append(Intervals, node.interval)
})
return Intervals
}
func isRed(node *node) bool {
return node != nil && node.red
}
func setMax(parent *node) {
parent.max = parent.interval.HighAtDimension(1)
if parent.children[0] != nil && parent.children[0].max > parent.max {
parent.max = parent.children[0].max
}
if parent.children[1] != nil && parent.children[1].max > parent.max {
parent.max = parent.children[1].max
}
}
func setMin(parent *node) {
parent.min = parent.interval.LowAtDimension(1)
if parent.children[0] != nil && parent.children[0].min < parent.min {
parent.min = parent.children[0].min
}
if parent.children[1] != nil && parent.children[1].min < parent.min {
parent.min = parent.children[1].min
}
if parent.interval.LowAtDimension(1) < parent.min {
parent.min = parent.interval.LowAtDimension(1)
}
}
func rotate(parent *node, dir int) *node {
otherDir := takeOpposite(dir)
child := parent.children[otherDir]
parent.children[otherDir] = child.children[dir]
child.children[dir] = parent
parent.red = true
child.red = false
child.max = parent.max
setMax(child)
setMax(parent)
setMin(child)
setMin(parent)
return child
}
func doubleRotate(parent *node, dir int) *node {
otherDir := takeOpposite(dir)
parent.children[otherDir] = rotate(parent.children[otherDir], otherDir)
return rotate(parent, dir)
}
func intFromBool(value bool) int {
if value {
return 1
}
return 0
}
func takeOpposite(value int) int {
return 1 - value
}
func newTree(maxDimension uint64) *tree {
return &tree{
maxDimension: maxDimension,
dummy: newDummy(),
}
}
// New constructs and returns a new interval tree with the max
// dimensions provided.
func New(dimensions uint64) Tree {
return newTree(dimensions)
}
================================================
FILE: augmentedtree/atree_test.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package augmentedtree
import (
"testing"
"github.com/stretchr/testify/assert"
)
func min(one, two int64) int64 {
if one == -1 {
return two
}
if two == -1 {
return one
}
if one > two {
return two
}
return one
}
func max(one, two int64) int64 {
if one == -1 {
return two
}
if two == -1 {
return one
}
if one > two {
return one
}
return two
}
func checkRedBlack(tb testing.TB, node *node, dimension int) (int64, int64, int64) {
lh, rh := 0, 0
if node == nil {
return 1, -1, -1
}
if isRed(node) {
if isRed(node.children[0]) || isRed(node.children[1]) {
tb.Errorf(`Node is red and has red children: %+v`, node)
}
}
fn := func(min, max int64) {
if min != -1 && min < node.min {
tb.Errorf(`Min not set correctly: %+v, node: %+v`, min, node)
}
if max != -1 && max > node.max {
tb.Errorf(`Max not set correctly: %+v, node: %+v`, max, node)
}
}
left, minL, maxL := checkRedBlack(tb, node.children[0], dimension)
fn(minL, maxL)
right, minR, maxR := checkRedBlack(tb, node.children[1], dimension)
fn(minR, maxR)
min := min(minL, minR)
if min == -1 && node.min != node.interval.LowAtDimension(1) {
tb.Errorf(`Min not set correctly, node: %+v`, node)
} else if min != -1 && node.children[0] != nil && node.children[0].min != node.min {
tb.Errorf(`Min not set correctly: node: %+v, child: %+v`, node, node.children[0])
} else if min != -1 && node.children[0] == nil && node.min != node.interval.LowAtDimension(1) {
tb.Errorf(`Min not set correctly: %+v`, node)
}
max := max(maxL, maxR)
if max == -1 && node.max != node.interval.HighAtDimension(1) {
tb.Errorf(`Max not set correctly, node: %+v`, node)
} else if max > node.interval.HighAtDimension(1) && max != node.max {
tb.Errorf(`Max not set correctly, max: %+v, node: %+v`, max, node)
}
if left != 0 && right != 0 && lh != rh {
tb.Errorf(`Black violation: left: %d, right: %d`, left, right)
}
if left != 0 && right != 0 {
if isRed(node) {
return left, node.min, node.max
}
return left + 1, node.min, node.max
}
return 0, node.min, node.max
}
func constructSingleDimensionTestTree(number int) (*tree, Intervals) {
tree := newTree(1)
ivs := make(Intervals, 0, number)
for i := 0; i < number; i++ {
iv := constructSingleDimensionInterval(int64(i), int64(i)+10, uint64(i))
ivs = append(ivs, iv)
}
tree.Add(ivs...)
return tree, ivs
}
func TestSimpleAddNilRoot(t *testing.T) {
it := newTree(1)
iv := constructSingleDimensionInterval(5, 10, 0)
it.Add(iv)
expected := newNode(iv, 5, 10, 1)
expected.red = false
assert.Equal(t, expected, it.root)
assert.Equal(t, uint64(1), it.Len())
checkRedBlack(t, it.root, 1)
}
func TestSimpleAddRootLeft(t *testing.T) {
it := newTree(1)
iv := constructSingleDimensionInterval(5, 10, 0)
it.Add(iv)
expectedRoot := newNode(iv, 4, 11, 1)
expectedRoot.red = false
iv = constructSingleDimensionInterval(4, 11, 1)
it.Add(iv)
expectedChild := newNode(iv, 4, 11, 1)
expectedRoot.children[0] = expectedChild
assert.Equal(t, expectedRoot, it.root)
assert.Equal(t, uint64(2), it.Len())
checkRedBlack(t, it.root, 1)
}
func TestSimpleAddRootRight(t *testing.T) {
it := newTree(1)
iv := constructSingleDimensionInterval(5, 10, 0)
it.Add(iv)
expectedRoot := newNode(iv, 5, 11, 1)
expectedRoot.red = false
iv = constructSingleDimensionInterval(7, 11, 1)
it.Add(iv)
expectedChild := newNode(iv, 7, 11, 1)
expectedRoot.children[1] = expectedChild
assert.Equal(t, expectedRoot, it.root)
assert.Equal(t, uint64(2), it.Len())
checkRedBlack(t, it.root, 1)
}
func TestAddRootLeftAndRight(t *testing.T) {
it := newTree(1)
iv := constructSingleDimensionInterval(5, 10, 0)
it.Add(iv)
expectedRoot := newNode(iv, 4, 12, 1)
expectedRoot.red = false
iv = constructSingleDimensionInterval(4, 11, 1)
it.Add(iv)
expectedLeft := newNode(iv, 4, 11, 1)
expectedRoot.children[0] = expectedLeft
iv = constructSingleDimensionInterval(7, 12, 1)
it.Add(iv)
expectedRight := newNode(iv, 7, 12, 1)
expectedRoot.children[1] = expectedRight
assert.Equal(t, expectedRoot, it.root)
assert.Equal(t, uint64(3), it.Len())
checkRedBlack(t, it.root, 1)
}
func TestAddRebalanceInOrder(t *testing.T) {
it := newTree(1)
for i := int64(0); i < 10; i++ {
iv := constructSingleDimensionInterval(i, i+1, uint64(i))
it.add(iv)
}
checkRedBlack(t, it.root, 1)
result := it.Query(constructSingleDimensionInterval(0, 10, 0))
assert.Len(t, result, 10)
assert.Equal(t, uint64(10), it.Len())
}
func TestAddRebalanceOutOfOrder(t *testing.T) {
it := newTree(1)
for i := int64(9); i >= 0; i-- {
iv := constructSingleDimensionInterval(i, i+1, uint64(i))
it.add(iv)
}
checkRedBlack(t, it.root, 1)
result := it.Query(constructSingleDimensionInterval(0, 10, 0))
assert.Len(t, result, 10)
assert.Equal(t, uint64(10), it.Len())
}
func TestAddRebalanceRandomOrder(t *testing.T) {
it := newTree(1)
starts := []int64{0, 4, 2, 1, 3}
for _, start := range starts {
iv := constructSingleDimensionInterval(start, start+1, uint64(start))
it.add(iv)
}
checkRedBlack(t, it.root, 1)
result := it.Query(constructSingleDimensionInterval(0, 10, 0))
assert.Len(t, result, 5)
assert.Equal(t, uint64(5), it.Len())
}
func TestAddLargeNumberOfItems(t *testing.T) {
numItems := int64(1000)
it := newTree(1)
for i := int64(0); i < numItems; i++ {
iv := constructSingleDimensionInterval(i, i+1, uint64(i))
it.add(iv)
}
checkRedBlack(t, it.root, 1)
result := it.Query(constructSingleDimensionInterval(0, numItems, 0))
assert.Len(t, result, int(numItems))
assert.Equal(t, uint64(numItems), it.Len())
}
func BenchmarkAddItems(b *testing.B) {
numItems := int64(1000)
intervals := make(Intervals, 0, numItems)
for i := int64(0); i < numItems; i++ {
iv := constructSingleDimensionInterval(i, i+1, uint64(i))
intervals = append(intervals, iv)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
it := newTree(1)
it.Add(intervals...)
}
}
func BenchmarkQueryItems(b *testing.B) {
numItems := int64(1000)
intervals := make(Intervals, 0, numItems)
for i := int64(0); i < numItems; i++ {
iv := constructSingleDimensionInterval(i, i+1, uint64(i))
intervals = append(intervals, iv)
}
it := newTree(1)
it.Add(intervals...)
b.ResetTimer()
for i := 0; i < b.N; i++ {
it.Query(constructSingleDimensionInterval(0, numItems, 0))
}
}
func constructSingleDimensionQueryTestTree() (
*tree, Interval, Interval, Interval) {
it := newTree(1)
iv1 := constructSingleDimensionInterval(6, 10, 0)
it.Add(iv1)
iv2 := constructSingleDimensionInterval(4, 5, 1)
it.Add(iv2)
iv3 := constructSingleDimensionInterval(7, 12, 2)
it.Add(iv3)
return it, iv1, iv2, iv3
}
func TestSimpleQuery(t *testing.T) {
it, iv1, iv2, _ := constructSingleDimensionQueryTestTree()
result := it.Query(constructSingleDimensionInterval(3, 6, 0))
expected := Intervals{iv2, iv1}
assert.Equal(t, expected, result)
}
func TestRightQuery(t *testing.T) {
it, iv1, _, iv3 := constructSingleDimensionQueryTestTree()
result := it.Query(constructSingleDimensionInterval(6, 8, 0))
expected := Intervals{iv1, iv3}
assert.Equal(t, expected, result)
}
func TestLeftQuery(t *testing.T) {
it, _, iv2, _ := constructSingleDimensionQueryTestTree()
result := it.Query(constructSingleDimensionInterval(3, 5, 0))
expected := Intervals{iv2}
assert.Equal(t, expected, result)
}
func TestMatchingQuery(t *testing.T) {
it, _, iv2, _ := constructSingleDimensionQueryTestTree()
result := it.Query(constructSingleDimensionInterval(4, 5, 0))
expected := Intervals{iv2}
assert.Equal(t, expected, result)
}
func TestNoMatchLeft(t *testing.T) {
it, _, _, _ := constructSingleDimensionQueryTestTree()
result := it.Query(constructSingleDimensionInterval(1, 3, 0))
expected := Intervals{}
assert.Equal(t, expected, result)
}
func TestNoMatchRight(t *testing.T) {
it, _, _, _ := constructSingleDimensionQueryTestTree()
result := it.Query(constructSingleDimensionInterval(13, 13, 0))
expected := Intervals{}
assert.Equal(t, expected, result)
}
func TestAllQuery(t *testing.T) {
it, iv1, iv2, iv3 := constructSingleDimensionQueryTestTree()
result := it.Query(constructSingleDimensionInterval(1, 14, 0))
expected := Intervals{iv2, iv1, iv3}
assert.Equal(t, expected, result)
}
func TestQueryDuplicate(t *testing.T) {
it, _, iv2, _ := constructSingleDimensionQueryTestTree()
iv4 := constructSingleDimensionInterval(4, 5, 3)
it.Add(iv4)
result := it.Query(constructSingleDimensionInterval(4, 5, 0))
expected := Intervals{iv2, iv4}
assert.Equal(t, expected, result)
}
func TestRootDelete(t *testing.T) {
it := newTree(1)
iv := constructSingleDimensionInterval(1, 5, 1)
it.add(iv)
it.Delete(iv)
checkRedBlack(t, it.root, 1)
result := it.Query(constructSingleDimensionInterval(1, 10, 0))
assert.Len(t, result, 0)
assert.Equal(t, uint64(0), it.Len())
}
func TestDeleteLeft(t *testing.T) {
it, iv1, iv2, iv3 := constructSingleDimensionQueryTestTree()
it.Delete(iv2)
expected := Intervals{iv1, iv3}
result := it.Query(constructSingleDimensionInterval(0, 10, 0))
checkRedBlack(t, it.root, 1)
assert.Equal(t, expected, result)
assert.Equal(t, uint64(2), it.Len())
}
func TestDeleteRight(t *testing.T) {
it, iv1, iv2, iv3 := constructSingleDimensionQueryTestTree()
it.Delete(iv3)
expected := Intervals{iv2, iv1}
result := it.Query(constructSingleDimensionInterval(0, 10, 0))
checkRedBlack(t, it.root, 1)
assert.Equal(t, expected, result)
assert.Equal(t, uint64(2), it.Len())
}
func TestDeleteCenter(t *testing.T) {
it, iv1, iv2, iv3 := constructSingleDimensionQueryTestTree()
it.Delete(iv1)
expected := Intervals{iv2, iv3}
result := it.Query(constructSingleDimensionInterval(0, 10, 0))
checkRedBlack(t, it.root, 1)
assert.Equal(t, expected, result)
assert.Equal(t, uint64(2), it.Len())
}
func TestDeleteRebalanceInOrder(t *testing.T) {
it := newTree(1)
var toDelete *mockInterval
for i := int64(0); i < 10; i++ {
iv := constructSingleDimensionInterval(i, i+1, uint64(i))
it.add(iv)
if i == 5 {
toDelete = iv
}
}
it.Delete(toDelete)
checkRedBlack(t, it.root, 1)
result := it.Query(constructSingleDimensionInterval(0, 10, 0))
assert.Len(t, result, 9)
assert.Equal(t, uint64(9), it.Len())
}
func TestDeleteRebalanceOutOfOrder(t *testing.T) {
it := newTree(1)
var toDelete *mockInterval
for i := int64(9); i >= 0; i-- {
iv := constructSingleDimensionInterval(i, i+1, uint64(i))
it.add(iv)
if i == 5 {
toDelete = iv
}
}
it.Delete(toDelete)
checkRedBlack(t, it.root, 1)
result := it.Query(constructSingleDimensionInterval(0, 10, 0))
assert.Len(t, result, 9)
assert.Equal(t, uint64(9), it.Len())
}
func TestDeleteRebalanceRandomOrder(t *testing.T) {
it := newTree(1)
starts := []int64{0, 4, 2, 1, 3}
var toDelete *mockInterval
for _, start := range starts {
iv := constructSingleDimensionInterval(start, start+1, uint64(start))
it.add(iv)
if start == 1 {
toDelete = iv
}
}
it.Delete(toDelete)
checkRedBlack(t, it.root, 1)
result := it.Query(constructSingleDimensionInterval(0, 10, 0))
assert.Len(t, result, 4)
assert.Equal(t, uint64(4), it.Len())
}
func TestDeleteEmptyTree(t *testing.T) {
it := newTree(1)
it.Delete(constructSingleDimensionInterval(0, 1, 1))
assert.Equal(t, uint64(0), it.Len())
}
func BenchmarkDeleteItems(b *testing.B) {
numItems := int64(1000)
intervals := make(Intervals, 0, numItems)
for i := int64(0); i < numItems; i++ {
iv := constructSingleDimensionInterval(i, i+1, uint64(i))
intervals = append(intervals, iv)
}
trees := make([]*tree, 0, b.N)
for i := 0; i < b.N; i++ {
it := newTree(1)
it.Add(intervals...)
trees = append(trees, it)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
trees[i].Delete(intervals...)
}
}
func TestAddDuplicateRanges(t *testing.T) {
it := newTree(1)
iv1 := constructSingleDimensionInterval(0, 10, 1)
iv2 := constructSingleDimensionInterval(0, 10, 2)
iv3 := constructSingleDimensionInterval(0, 10, 3)
it.Add(iv1, iv2, iv3)
it.Delete(iv1, iv2, iv3)
assert.Equal(t, uint64(0), it.Len())
}
func TestAddDeleteDuplicatesRebalanceInOrder(t *testing.T) {
it := newTree(1)
intervals := make(Intervals, 0, 10)
for i := 0; i < 10; i++ {
iv := constructSingleDimensionInterval(0, 10, uint64(i))
intervals = append(intervals, iv)
}
it.Add(intervals...)
it.Delete(intervals...)
assert.Equal(t, uint64(0), it.Len())
}
func TestAddDeleteDuplicatesRebalanceReverseOrder(t *testing.T) {
it := newTree(1)
intervals := make(Intervals, 0, 10)
for i := 9; i >= 0; i-- {
iv := constructSingleDimensionInterval(0, 10, uint64(i))
intervals = append(intervals, iv)
}
it.Add(intervals...)
it.Delete(intervals...)
assert.Equal(t, uint64(0), it.Len())
}
func TestAddDeleteDuplicatesRebalanceRandomOrder(t *testing.T) {
it := newTree(1)
starts := []int{0, 4, 2, 1, 3}
intervals := make(Intervals, 0, 5)
for _, start := range starts {
iv := constructSingleDimensionInterval(0, 10, uint64(start))
intervals = append(intervals, iv)
}
it.Add(intervals...)
it.Delete(intervals...)
assert.Equal(t, uint64(0), it.Len())
}
func TestInsertDuplicateIntervalsToRoot(t *testing.T) {
tree := newTree(1)
iv1 := constructSingleDimensionInterval(0, 10, 1)
iv2 := constructSingleDimensionInterval(0, 10, 1)
iv3 := constructSingleDimensionInterval(0, 10, 1)
tree.Add(iv1, iv2, iv3)
checkRedBlack(t, tree.root, 1)
}
func TestInsertDuplicateIntervalChildren(t *testing.T) {
tree, _ := constructSingleDimensionTestTree(20)
iv1 := constructSingleDimensionInterval(0, 10, 21)
iv2 := constructSingleDimensionInterval(0, 10, 21)
tree.Add(iv1, iv2)
checkRedBlack(t, tree.root, 1)
result := tree.Query(constructSingleDimensionInterval(0, 10, 0))
assert.Contains(t, result, iv1)
}
func TestTraverse(t *testing.T) {
tree := newTree(1)
tree.Traverse(func(i Interval) {
assert.Fail(t, `traverse should not be called for empty tree`)
})
top := 30
for i := 0; i <= top; i++ {
tree.Add(constructSingleDimensionInterval(int64(i*10), int64((i+1)*10), uint64(i)))
}
found := map[uint64]bool{}
tree.Traverse(func(id Interval) {
found[id.ID()] = true
})
for i := 0; i <= top; i++ {
if found, _ := found[uint64(i)]; !found {
t.Errorf("could not find expected interval %d", i)
}
}
}
================================================
FILE: augmentedtree/interface.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Package augmentedtree is designed to be useful when checking
for intersection of ranges in n-dimensions. For instance, if you imagine
an xy plane then the augmented tree is for telling you if
plane defined by the points (0, 0) and (10, 10). The augmented
tree can tell you if that plane overlaps with a plane defined by
(-5, -5) and (5, 5) (true in this case). You can also check
intersections against a point by constructing a range of encompassed
solely if a single point.
The current tree is a simple top-down red-black binary search tree.
TODO: Add a bottom-up implementation to assist with duplicate
range handling.
*/
package augmentedtree
// Interval is the interface that must be implemented by any
// item added to the interval tree. This interface is similar to the
// interval found in the rangetree package and it should be possible
// for the same struct to implement both interfaces. Note that ranges
// here are inclusive. It is also expected that the provided interval
// is immutable and that the returned values never change. Doing so
// results in undefined behavior.
type Interval interface {
// LowAtDimension returns an integer representing the lower bound
// at the requested dimension.
LowAtDimension(uint64) int64
// HighAtDimension returns an integer representing the higher bound
// at the requested dimension.
HighAtDimension(uint64) int64
// OverlapsAtDimension should return a bool indicating if the provided
// interval overlaps this interval at the dimension requested.
OverlapsAtDimension(Interval, uint64) bool
// ID should be a unique ID representing this interval. This
// is used to identify which interval to delete from the tree if
// there are duplicates.
ID() uint64
}
// Tree defines the object that is returned from the
// tree constructor. We use a Tree interface here because
// the returned tree could be a single dimension or many
// dimensions.
type Tree interface {
// Add will add the provided intervals to the tree.
Add(intervals ...Interval)
// Len returns the number of intervals in the tree.
Len() uint64
// Delete will remove the provided intervals from the tree.
Delete(intervals ...Interval)
// Query will return a list of intervals that intersect the provided
// interval. The provided interval's ID method is ignored so the
// provided ID is irrelevant.
Query(interval Interval) Intervals
// Traverse will traverse tree and give alls intervals
// found in an undefined order
Traverse(func(Interval))
}
================================================
FILE: augmentedtree/intervals.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package augmentedtree
import "sync"
var intervalsPool = sync.Pool{
New: func() interface{} {
return make(Intervals, 0, 10)
},
}
// Intervals represents a list of Intervals.
type Intervals []Interval
// Dispose will free any consumed resources and allow this list to be
// re-allocated.
func (ivs *Intervals) Dispose() {
for i := 0; i < len(*ivs); i++ {
(*ivs)[i] = nil
}
*ivs = (*ivs)[:0]
intervalsPool.Put(*ivs)
}
================================================
FILE: augmentedtree/intervals_test.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package augmentedtree
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestIntervalsDispose(t *testing.T) {
intervals := intervalsPool.Get().(Intervals)
intervals = append(intervals, constructSingleDimensionInterval(0, 1, 0))
intervals.Dispose()
assert.Len(t, intervals, 0)
}
================================================
FILE: augmentedtree/mock_test.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package augmentedtree
import "fmt"
type dimension struct {
low, high int64
}
type mockInterval struct {
dimensions []*dimension
id uint64
}
func (mi *mockInterval) checkDimension(dimension uint64) {
if dimension > uint64(len(mi.dimensions)) {
panic(fmt.Sprintf(`Dimension: %d out of range.`, dimension))
}
}
func (mi *mockInterval) LowAtDimension(dimension uint64) int64 {
return mi.dimensions[dimension-1].low
}
func (mi *mockInterval) HighAtDimension(dimension uint64) int64 {
return mi.dimensions[dimension-1].high
}
func (mi *mockInterval) OverlapsAtDimension(iv Interval, dimension uint64) bool {
return mi.HighAtDimension(dimension) > iv.LowAtDimension(dimension) &&
mi.LowAtDimension(dimension) < iv.HighAtDimension(dimension)
}
func (mi mockInterval) ID() uint64 {
return mi.id
}
func constructSingleDimensionInterval(low, high int64, id uint64) *mockInterval {
return &mockInterval{[]*dimension{&dimension{low: low, high: high}}, id}
}
func constructMultiDimensionInterval(id uint64, dimensions ...*dimension) *mockInterval {
return &mockInterval{dimensions: dimensions, id: id}
}
================================================
FILE: augmentedtree/multidimensional_test.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package augmentedtree
import (
"testing"
"github.com/stretchr/testify/assert"
)
func constructMultiDimensionQueryTestTree() (
*tree, Interval, Interval, Interval) {
it := newTree(2)
iv1 := constructMultiDimensionInterval(
0, &dimension{low: 5, high: 10}, &dimension{low: 5, high: 10},
)
it.Add(iv1)
iv2 := constructMultiDimensionInterval(
1, &dimension{low: 4, high: 5}, &dimension{low: 4, high: 5},
)
it.Add(iv2)
iv3 := constructMultiDimensionInterval(
2, &dimension{low: 7, high: 12}, &dimension{low: 7, high: 12},
)
it.Add(iv3)
return it, iv1, iv2, iv3
}
func TestRootAddMultipleDimensions(t *testing.T) {
it := newTree(2)
iv := constructMultiDimensionInterval(
1, &dimension{low: 0, high: 5}, &dimension{low: 1, high: 6},
)
it.Add(iv)
checkRedBlack(t, it.root, 1)
result := it.Query(
constructMultiDimensionInterval(
0, &dimension{0, 10}, &dimension{0, 10},
),
)
assert.Equal(t, Intervals{iv}, result)
result = it.Query(
constructMultiDimensionInterval(
0, &dimension{100, 200}, &dimension{100, 200},
),
)
assert.Len(t, result, 0)
}
func TestMultipleAddMultipleDimensions(t *testing.T) {
it, iv1, iv2, iv3 := constructMultiDimensionQueryTestTree()
checkRedBlack(t, it.root, 1)
result := it.Query(
constructMultiDimensionInterval(
0, &dimension{0, 100}, &dimension{0, 100},
),
)
assert.Equal(t, Intervals{iv2, iv1, iv3}, result)
result = it.Query(
constructMultiDimensionInterval(
0, &dimension{3, 5}, &dimension{3, 5},
),
)
assert.Equal(t, Intervals{iv2}, result)
result = it.Query(
constructMultiDimensionInterval(
0, &dimension{5, 8}, &dimension{5, 8},
),
)
assert.Equal(t, Intervals{iv1, iv3}, result)
result = it.Query(
constructMultiDimensionInterval(
0, &dimension{11, 15}, &dimension{11, 15},
),
)
assert.Equal(t, Intervals{iv3}, result)
result = it.Query(
constructMultiDimensionInterval(
0, &dimension{15, 20}, &dimension{15, 20},
),
)
assert.Len(t, result, 0)
}
func TestAddRebalanceInOrderMultiDimensions(t *testing.T) {
it := newTree(2)
for i := int64(0); i < 10; i++ {
iv := constructMultiDimensionInterval(
uint64(i), &dimension{i, i + 1}, &dimension{i, i + 1},
)
it.Add(iv)
}
checkRedBlack(t, it.root, 1)
result := it.Query(
constructMultiDimensionInterval(
0, &dimension{0, 10}, &dimension{0, 10},
),
)
assert.Len(t, result, 10)
assert.Equal(t, uint64(10), it.Len())
}
func TestAddRebalanceReverseOrderMultiDimensions(t *testing.T) {
it := newTree(2)
for i := int64(9); i >= 0; i-- {
iv := constructMultiDimensionInterval(
uint64(i), &dimension{i, i + 1}, &dimension{i, i + 1},
)
it.Add(iv)
}
checkRedBlack(t, it.root, 1)
result := it.Query(
constructMultiDimensionInterval(
0, &dimension{0, 10}, &dimension{0, 10},
),
)
assert.Len(t, result, 10)
assert.Equal(t, uint64(10), it.Len())
}
func TestAddRebalanceRandomOrderMultiDimensions(t *testing.T) {
it := newTree(2)
starts := []int64{0, 4, 2, 1, 3}
for i, start := range starts {
iv := constructMultiDimensionInterval(
uint64(i), &dimension{start, start + 1}, &dimension{start, start + 1},
)
it.Add(iv)
}
checkRedBlack(t, it.root, 1)
result := it.Query(
constructMultiDimensionInterval(
0, &dimension{0, 10}, &dimension{0, 10},
),
)
assert.Len(t, result, 5)
assert.Equal(t, uint64(5), it.Len())
}
func TestAddLargeNumbersMultiDimensions(t *testing.T) {
numItems := int64(1000)
it := newTree(2)
for i := int64(0); i < numItems; i++ {
iv := constructMultiDimensionInterval(
uint64(i), &dimension{i, i + 1}, &dimension{i, i + 1},
)
it.Add(iv)
}
checkRedBlack(t, it.root, 1)
result := it.Query(
constructMultiDimensionInterval(
0, &dimension{0, numItems}, &dimension{0, numItems},
),
)
assert.Len(t, result, int(numItems))
assert.Equal(t, uint64(numItems), it.Len())
}
func BenchmarkAddItemsMultiDimensions(b *testing.B) {
numItems := int64(b.N)
intervals := make(Intervals, 0, numItems)
for i := int64(0); i < numItems; i++ {
iv := constructMultiDimensionInterval(
uint64(i), &dimension{i, i + 1}, &dimension{i, i + 1},
)
intervals = append(intervals, iv)
}
it := newTree(2)
b.ResetTimer()
for i := 0; i < b.N; i++ {
it.Add(intervals[int64(i)%numItems])
}
}
func BenchmarkQueryItemsMultiDimensions(b *testing.B) {
numItems := int64(1000)
intervals := make(Intervals, 0, numItems)
for i := int64(0); i < numItems; i++ {
iv := constructMultiDimensionInterval(
uint64(i), &dimension{i, i + 1}, &dimension{i, i + 1},
)
intervals = append(intervals, iv)
}
it := newTree(2)
it.Add(intervals...)
b.ResetTimer()
for i := 0; i < b.N; i++ {
it.Query(
constructMultiDimensionInterval(
0, &dimension{0, numItems}, &dimension{0, numItems},
),
)
}
}
func TestRootDeleteMultiDimensions(t *testing.T) {
it := newTree(2)
iv := constructMultiDimensionInterval(
0, &dimension{low: 5, high: 10}, &dimension{low: 5, high: 10},
)
it.Add(iv)
it.Delete(iv)
checkRedBlack(t, it.root, 1)
result := it.Query(
constructMultiDimensionInterval(
0, &dimension{0, 100}, &dimension{0, 100},
),
)
assert.Len(t, result, 0)
assert.Equal(t, uint64(0), it.Len())
}
func TestDeleteMultiDimensions(t *testing.T) {
it, iv1, iv2, iv3 := constructMultiDimensionQueryTestTree()
checkRedBlack(t, it.root, 1)
it.Delete(iv1)
result := it.Query(
constructMultiDimensionInterval(
0, &dimension{0, 100}, &dimension{0, 100},
),
)
assert.Equal(t, Intervals{iv2, iv3}, result)
result = it.Query(
constructMultiDimensionInterval(
0, &dimension{3, 5}, &dimension{3, 5},
),
)
assert.Equal(t, Intervals{iv2}, result)
result = it.Query(
constructMultiDimensionInterval(
0, &dimension{5, 8}, &dimension{5, 8},
),
)
assert.Equal(t, Intervals{iv3}, result)
result = it.Query(
constructMultiDimensionInterval(
0, &dimension{11, 15}, &dimension{11, 15},
),
)
assert.Equal(t, Intervals{iv3}, result)
result = it.Query(
constructMultiDimensionInterval(
0, &dimension{15, 20}, &dimension{15, 20},
),
)
assert.Len(t, result, 0)
}
func TestDeleteRebalanceInOrderMultiDimensions(t *testing.T) {
it := newTree(2)
var toDelete *mockInterval
for i := int64(0); i < 10; i++ {
iv := constructMultiDimensionInterval(
uint64(i), &dimension{i, i + 1}, &dimension{i, i + 1},
)
it.Add(iv)
if i == 5 {
toDelete = iv
}
}
it.Delete(toDelete)
checkRedBlack(t, it.root, 1)
result := it.Query(
constructMultiDimensionInterval(
0, &dimension{0, 10}, &dimension{0, 10},
),
)
assert.Len(t, result, 9)
assert.Equal(t, uint64(9), it.Len())
}
func TestDeleteRebalanceReverseOrderMultiDimensions(t *testing.T) {
it := newTree(2)
var toDelete *mockInterval
for i := int64(9); i >= 0; i-- {
iv := constructMultiDimensionInterval(
uint64(i), &dimension{i, i + 1}, &dimension{i, i + 1},
)
it.Add(iv)
if i == 5 {
toDelete = iv
}
}
it.Delete(toDelete)
checkRedBlack(t, it.root, 1)
result := it.Query(
constructMultiDimensionInterval(
0, &dimension{0, 10}, &dimension{0, 10},
),
)
assert.Len(t, result, 9)
assert.Equal(t, uint64(9), it.Len())
}
func TestDeleteRebalanceRandomOrderMultiDimensions(t *testing.T) {
it := newTree(2)
starts := []int64{0, 4, 2, 1, 3}
var toDelete *mockInterval
for i, start := range starts {
iv := constructMultiDimensionInterval(
uint64(i), &dimension{start, start + 1}, &dimension{start, start + 1},
)
it.Add(iv)
if start == 1 {
toDelete = iv
}
}
it.Delete(toDelete)
checkRedBlack(t, it.root, 1)
result := it.Query(
constructMultiDimensionInterval(
0, &dimension{0, 10}, &dimension{0, 10},
),
)
assert.Len(t, result, 4)
assert.Equal(t, uint64(4), it.Len())
}
func TestDeleteEmptyTreeMultiDimensions(t *testing.T) {
it := newTree(2)
it.Delete(
constructMultiDimensionInterval(
0, &dimension{0, 10}, &dimension{0, 10},
),
)
assert.Equal(t, uint64(0), it.Len())
}
func BenchmarkDeleteItemsMultiDimensions(b *testing.B) {
numItems := int64(1000)
intervals := make(Intervals, 0, numItems)
for i := int64(0); i < numItems; i++ {
iv := constructMultiDimensionInterval(
uint64(i), &dimension{i, i + 1}, &dimension{i, i + 1},
)
intervals = append(intervals, iv)
}
trees := make([]*tree, 0, b.N)
for i := 0; i < b.N; i++ {
it := newTree(2)
it.Add(intervals...)
trees = append(trees, it)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
trees[i].Delete(intervals...)
}
}
func TestAddDeleteDuplicatesRebalanceInOrderMultiDimensions(t *testing.T) {
it := newTree(2)
intervals := make(Intervals, 0, 10)
for i := 0; i < 10; i++ {
iv := constructMultiDimensionInterval(
uint64(i), &dimension{0, 10}, &dimension{0, 10},
)
intervals = append(intervals, iv)
}
it.Add(intervals...)
it.Delete(intervals...)
assert.Equal(t, uint64(0), it.Len())
}
func TestAddDeleteDuplicatesRebalanceReverseOrderMultiDimensions(t *testing.T) {
it := newTree(2)
intervals := make(Intervals, 0, 10)
for i := 9; i >= 0; i-- {
iv := constructMultiDimensionInterval(
uint64(i), &dimension{0, 10}, &dimension{0, 10},
)
intervals = append(intervals, iv)
}
it.Add(intervals...)
it.Delete(intervals...)
assert.Equal(t, uint64(0), it.Len())
}
func TestAddDeleteDuplicatesRebalanceRandomOrderMultiDimensions(t *testing.T) {
it := newTree(2)
intervals := make(Intervals, 0, 5)
starts := []int{0, 4, 2, 1, 3}
for _, start := range starts {
iv := constructMultiDimensionInterval(
uint64(start), &dimension{0, 10}, &dimension{0, 10},
)
intervals = append(intervals, iv)
}
it.Add(intervals...)
it.Delete(intervals...)
assert.Equal(t, uint64(0), it.Len())
}
================================================
FILE: aviary.yaml
================================================
version: 1
exclude:
- tests?/
raven_monitored_classes: null
raven_monitored_files: null
raven_monitored_functions: null
raven_monitored_keywords: null
================================================
FILE: batcher/batcher.go
================================================
/*
Copyright 2015 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package batcher
import (
"errors"
"time"
)
// I honestly can't believe I'm doing this, but go's sync package doesn't
// have a TryLock function.
// Could probably do this with atomics
type mutex struct {
// This is really more of a semaphore design, but eh
// Full -> locked, empty -> unlocked
lock chan struct{}
}
func newMutex() *mutex {
return &mutex{lock: make(chan struct{}, 1)}
}
func (m *mutex) Lock() {
m.lock <- struct{}{}
}
func (m *mutex) Unlock() {
<-m.lock
}
func (m *mutex) TryLock() bool {
select {
case m.lock <- struct{}{}:
return true
default:
return false
}
}
// Batcher provides an API for accumulating items into a batch for processing.
type Batcher interface {
// Put adds items to the batcher.
Put(interface{}) error
// Get retrieves a batch from the batcher. This call will block until
// one of the conditions for a "complete" batch is reached.
Get() ([]interface{}, error)
// Flush forcibly completes the batch currently being built
Flush() error
// Dispose will dispose of the batcher. Any calls to Put or Flush
// will return ErrDisposed, calls to Get will return an error iff
// there are no more ready batches.
Dispose()
// IsDisposed will determine if the batcher is disposed
IsDisposed() bool
}
// ErrDisposed is the error returned for a disposed Batcher
var ErrDisposed = errors.New("batcher: disposed")
// CalculateBytes evaluates the number of bytes in an item added to a Batcher.
type CalculateBytes func(interface{}) uint
type basicBatcher struct {
maxTime time.Duration
maxItems uint
maxBytes uint
calculateBytes CalculateBytes
disposed bool
items []interface{}
batchChan chan []interface{}
availableBytes uint
lock *mutex
}
// New creates a new Batcher using the provided arguments.
// Batch readiness can be determined in three ways:
// - Maximum number of bytes per batch
// - Maximum number of items per batch
// - Maximum amount of time waiting for a batch
// Values of zero for one of these fields indicate they should not be
// taken into account when evaluating the readiness of a batch.
// This provides an ordering guarantee for any given thread such that if a
// thread places two items in the batcher, Get will guarantee the first
// item is returned before the second, whether before the second in the same
// batch, or in an earlier batch.
func New(maxTime time.Duration, maxItems, maxBytes, queueLen uint, calculate CalculateBytes) (Batcher, error) {
if maxBytes > 0 && calculate == nil {
return nil, errors.New("batcher: must provide CalculateBytes function")
}
return &basicBatcher{
maxTime: maxTime,
maxItems: maxItems,
maxBytes: maxBytes,
calculateBytes: calculate,
items: make([]interface{}, 0, maxItems),
batchChan: make(chan []interface{}, queueLen),
lock: newMutex(),
}, nil
}
// Put adds items to the batcher.
func (b *basicBatcher) Put(item interface{}) error {
b.lock.Lock()
if b.disposed {
b.lock.Unlock()
return ErrDisposed
}
b.items = append(b.items, item)
if b.calculateBytes != nil {
b.availableBytes += b.calculateBytes(item)
}
if b.ready() {
// To guarantee ordering this MUST be in the lock, otherwise multiple
// flush calls could be blocked at the same time, in which case
// there's no guarantee each batch is placed into the channel in
// the proper order
b.flush()
}
b.lock.Unlock()
return nil
}
// Get retrieves a batch from the batcher. This call will block until
// one of the conditions for a "complete" batch is reached.
func (b *basicBatcher) Get() ([]interface{}, error) {
// Don't check disposed yet so any items remaining in the queue
// will be returned properly.
var timeout <-chan time.Time
if b.maxTime > 0 {
timeout = time.After(b.maxTime)
}
select {
case items, ok := <-b.batchChan:
// If there's something on the batch channel, we definitely want that.
if !ok {
return nil, ErrDisposed
}
return items, nil
case <-timeout:
// It's possible something was added to the channel after something
// was received on the timeout channel, in which case that must
// be returned first to satisfy our ordering guarantees.
// We can't just grab the lock here in case the batch channel is full,
// in which case a Put or Flush will be blocked and holding
// onto the lock. In that case, there should be something on the
// batch channel
for {
if b.lock.TryLock() {
// We have a lock, try to read from channel first in case
// something snuck in
select {
case items, ok := <-b.batchChan:
b.lock.Unlock()
if !ok {
return nil, ErrDisposed
}
return items, nil
default:
}
// If that is unsuccessful, nothing was added to the channel,
// and the temp buffer can't have changed because of the lock,
// so grab that
items := b.items
b.items = make([]interface{}, 0, b.maxItems)
b.availableBytes = 0
b.lock.Unlock()
return items, nil
} else {
// If we didn't get a lock, there are two cases:
// 1) The batch chan is full.
// 2) A Put or Flush temporarily has the lock.
// In either case, trying to read something off the batch chan,
// and going back to trying to get a lock if unsuccessful
// works.
select {
case items, ok := <-b.batchChan:
if !ok {
return nil, ErrDisposed
}
return items, nil
default:
}
}
}
}
}
// Flush forcibly completes the batch currently being built
func (b *basicBatcher) Flush() error {
// This is the same pattern as a Put
b.lock.Lock()
if b.disposed {
b.lock.Unlock()
return ErrDisposed
}
b.flush()
b.lock.Unlock()
return nil
}
// Dispose will dispose of the batcher. Any calls to Put or Flush
// will return ErrDisposed, calls to Get will return an error iff
// there are no more ready batches. Any items not flushed and retrieved
// by a Get may or may not be retrievable after calling this.
func (b *basicBatcher) Dispose() {
for {
if b.lock.TryLock() {
// We've got a lock
if b.disposed {
b.lock.Unlock()
return
}
b.disposed = true
b.items = nil
b.drainBatchChan()
close(b.batchChan)
b.lock.Unlock()
} else {
// Two cases here:
// 1) Something is blocked and holding onto the lock
// 2) Something temporarily has a lock
// For case 1, we have to clear at least some space so the blocked
// Put/Flush can release the lock. For case 2, nothing bad
// will happen here
b.drainBatchChan()
}
}
}
// IsDisposed will determine if the batcher is disposed
func (b *basicBatcher) IsDisposed() bool {
b.lock.Lock()
disposed := b.disposed
b.lock.Unlock()
return disposed
}
// flush adds the batch currently being built to the queue of completed batches.
// flush is not threadsafe, so should be synchronized externally.
func (b *basicBatcher) flush() {
b.batchChan <- b.items
b.items = make([]interface{}, 0, b.maxItems)
b.availableBytes = 0
}
func (b *basicBatcher) ready() bool {
if b.maxItems != 0 && uint(len(b.items)) >= b.maxItems {
return true
}
if b.maxBytes != 0 && b.availableBytes >= b.maxBytes {
return true
}
return false
}
func (b *basicBatcher) drainBatchChan() {
for {
select {
case <-b.batchChan:
default:
return
}
}
}
================================================
FILE: batcher/batcher_test.go
================================================
/*
Copyright 2015 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package batcher
import (
"sync"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestNoCalculateBytes(t *testing.T) {
_, err := New(0, 0, 100, 5, nil)
assert.Error(t, err)
}
func TestMaxItems(t *testing.T) {
assert := assert.New(t)
b, err := New(0, 100, 100000, 10, func(str interface{}) uint {
return uint(len(str.(string)))
})
assert.Nil(err)
for i := 0; i < 1000; i++ {
assert.Nil(b.Put("foo bar baz"))
}
batch, err := b.Get()
assert.Len(batch, 100)
assert.Nil(err)
}
func TestMaxBytes(t *testing.T) {
assert := assert.New(t)
b, err := New(0, 10000, 100, 10, func(str interface{}) uint {
return uint(len(str.(string)))
})
assert.Nil(err)
go func() {
for i := 0; i < 1000; i++ {
b.Put("a")
}
}()
batch, err := b.Get()
assert.Len(batch, 100)
assert.Nil(err)
}
func TestMaxTime(t *testing.T) {
assert := assert.New(t)
b, err := New(time.Millisecond*200, 100000, 100000, 10,
func(str interface{}) uint {
return uint(len(str.(string)))
},
)
assert.Nil(err)
go func() {
for i := 0; i < 10000; i++ {
b.Put("a")
time.Sleep(time.Millisecond)
}
}()
before := time.Now()
batch, err := b.Get()
// This delta is normally 1-3 ms but running tests in CI with -race causes
// this to run much slower. For now, just bump up the threshold.
assert.InDelta(200, time.Since(before).Seconds()*1000, 100)
assert.True(len(batch) > 0)
assert.Nil(err)
}
func TestFlush(t *testing.T) {
assert := assert.New(t)
b, err := New(0, 10, 10, 10, func(str interface{}) uint {
return uint(len(str.(string)))
})
assert.Nil(err)
b.Put("a")
wait := make(chan bool)
go func() {
batch, err := b.Get()
assert.Equal([]interface{}{"a"}, batch)
assert.Nil(err)
wait <- true
}()
b.Flush()
<-wait
}
func TestMultiConsumer(t *testing.T) {
assert := assert.New(t)
b, err := New(0, 100, 100000, 10, func(str interface{}) uint {
return uint(len(str.(string)))
})
assert.Nil(err)
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
go func() {
batch, err := b.Get()
assert.Len(batch, 100)
assert.Nil(err)
wg.Done()
}()
}
go func() {
for i := 0; i < 500; i++ {
b.Put("a")
}
}()
wg.Wait()
}
func TestDispose(t *testing.T) {
assert := assert.New(t)
b, err := New(1, 2, 100000, 2, func(str interface{}) uint {
return uint(len(str.(string)))
})
assert.Nil(err)
b.Put("a")
b.Put("b")
b.Put("c")
batch1, err := b.Get()
assert.Equal([]interface{}{"a", "b"}, batch1)
assert.Nil(err)
batch2, err := b.Get()
assert.Equal([]interface{}{"c"}, batch2)
assert.Nil(err)
b.Put("d")
b.Put("e")
b.Put("f")
b.Dispose()
_, err = b.Get()
assert.Equal(ErrDisposed, err)
assert.Equal(ErrDisposed, b.Put("j"))
assert.Equal(ErrDisposed, b.Flush())
}
func TestIsDisposed(t *testing.T) {
assert := assert.New(t)
b, err := New(0, 10, 10, 10, func(str interface{}) uint {
return uint(len(str.(string)))
})
assert.Nil(err)
assert.False(b.IsDisposed())
b.Dispose()
assert.True(b.IsDisposed())
}
================================================
FILE: bitarray/and.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package bitarray
func andSparseWithSparseBitArray(sba, other *sparseBitArray) BitArray {
max := maxInt64(int64(len(sba.indices)), int64(len(other.indices)))
indices := make(uintSlice, 0, max)
blocks := make(blocks, 0, max)
selfIndex := 0
otherIndex := 0
var resultBlock block
// move through the array and compare the blocks if they happen to
// intersect
for {
if selfIndex == len(sba.indices) || otherIndex == len(other.indices) {
// One of the arrays has been exhausted. We don't need
// to compare anything else for a bitwise and; the
// operation is complete.
break
}
selfValue := sba.indices[selfIndex]
otherValue := other.indices[otherIndex]
switch {
case otherValue < selfValue:
// The `sba` bitarray has a block with a index position
// greater than us. We want to compare with that block
// if possible, so move our `other` index closer to that
// block's index.
otherIndex++
case otherValue > selfValue:
// This is the exact logical inverse of the above case.
selfIndex++
default:
// Here, our indices match for both `sba` and `other`.
// Time to do the bitwise AND operation and add a block
// to our result list if the block has values in it.
resultBlock = sba.blocks[selfIndex].and(other.blocks[otherIndex])
if resultBlock > 0 {
indices = append(indices, selfValue)
blocks = append(blocks, resultBlock)
}
selfIndex++
otherIndex++
}
}
return &sparseBitArray{
indices: indices,
blocks: blocks,
}
}
func andSparseWithDenseBitArray(sba *sparseBitArray, other *bitArray) BitArray {
if other.IsEmpty() {
return newSparseBitArray()
}
// Use a duplicate of the sparse array to store the results of the
// bitwise and. More memory-efficient than allocating a new dense bit
// array.
//
// NOTE: this could be faster if we didn't copy the values as well
// (since they are overwritten), but I don't want this method to know
// too much about the internals of sparseBitArray. The performance hit
// should be minor anyway.
ba := sba.copy()
// Run through the sparse array and attempt comparisons wherever
// possible against the dense bit array.
for selfIndex, selfValue := range ba.indices {
if selfValue >= uint64(len(other.blocks)) {
// The dense bit array has been exhausted. This is the
// annoying case because we have to trim the sparse
// array to the size of the dense array.
ba.blocks = ba.blocks[:selfIndex-1]
ba.indices = ba.indices[:selfIndex-1]
// once this is done, there are no more comparisons.
// We're ready to return
break
}
ba.blocks[selfIndex] = ba.blocks[selfIndex].and(
other.blocks[selfValue])
}
// Ensure any zero'd blocks in the resulting sparse
// array are deleted
for i := 0; i < len(ba.blocks); i++ {
if ba.blocks[i] == 0 {
ba.blocks.deleteAtIndex(int64(i))
ba.indices.deleteAtIndex(int64(i))
i--
}
}
return ba
}
func andDenseWithDenseBitArray(dba, other *bitArray) BitArray {
min := minUint64(uint64(len(dba.blocks)), uint64(len(other.blocks)))
ba := newBitArray(min * s)
for i := uint64(0); i < min; i++ {
ba.blocks[i] = dba.blocks[i].and(other.blocks[i])
}
ba.setLowest()
ba.setHighest()
return ba
}
================================================
FILE: bitarray/and_test.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package bitarray
import (
"testing"
"github.com/stretchr/testify/assert"
)
// checkBit is a helper method for these unit tests
func checkBit(t *testing.T, ba BitArray, position uint64, expected bool) {
ok, err := ba.GetBit(position)
if assert.NoError(t, err) {
if expected {
assert.True(t, ok, "Bitarray at position %d should be set", position)
} else {
assert.False(t, ok, "Bitarray at position %d should be unset", position)
}
}
}
func TestAndSparseWithSparseBitArray(t *testing.T) {
sba := newSparseBitArray()
other := newSparseBitArray()
// bits for which only one of the arrays is set
sba.SetBit(3)
sba.SetBit(280)
other.SetBit(9)
other.SetBit(100)
sba.SetBit(1000)
other.SetBit(1001)
// bits for which both arrays are set
sba.SetBit(1)
other.SetBit(1)
sba.SetBit(2680)
other.SetBit(2680)
sba.SetBit(30)
other.SetBit(30)
ba := andSparseWithSparseBitArray(sba, other)
// Bits in both
checkBit(t, ba, 1, true)
checkBit(t, ba, 30, true)
checkBit(t, ba, 2680, true)
// Bits in sba but not other
checkBit(t, ba, 3, false)
checkBit(t, ba, 280, false)
checkBit(t, ba, 1000, false)
// Bits in other but not sba
checkBit(t, ba, 9, false)
checkBit(t, ba, 100, false)
checkBit(t, ba, 2, false)
nums := ba.ToNums()
assert.Equal(t, []uint64{1, 30, 2680}, nums)
}
func TestAndSparseWithDenseBitArray(t *testing.T) {
sba := newSparseBitArray()
other := newBitArray(300)
other.SetBit(1)
sba.SetBit(1)
other.SetBit(150)
sba.SetBit(150)
sba.SetBit(155)
other.SetBit(156)
sba.SetBit(300)
other.SetBit(300)
ba := andSparseWithDenseBitArray(sba, other)
// Bits in both
checkBit(t, ba, 1, true)
checkBit(t, ba, 150, true)
checkBit(t, ba, 300, true)
// Bits in sba but not other
checkBit(t, ba, 155, false)
// Bits in other but not sba
checkBit(t, ba, 156, false)
}
// Make sure that the sparse array is trimmed correctly if compared against a
// smaller dense bit array.
func TestAndSparseWithSmallerDenseBitArray(t *testing.T) {
sba := newSparseBitArray()
other := newBitArray(512)
other.SetBit(1)
sba.SetBit(1)
other.SetBit(150)
sba.SetBit(150)
sba.SetBit(155)
sba.SetBit(500)
other.SetBit(128)
sba.SetBit(1500)
sba.SetBit(1200)
ba := andSparseWithDenseBitArray(sba, other)
// Bits in both
checkBit(t, ba, 1, true)
checkBit(t, ba, 150, true)
// Bits in sba but not other
checkBit(t, ba, 155, false)
checkBit(t, ba, 500, false)
checkBit(t, ba, 1200, false)
checkBit(t, ba, 1500, false)
// Bits in other but not sba
checkBit(t, ba, 128, false)
}
func TestAndDenseWithDenseBitArray(t *testing.T) {
dba := newBitArray(1000)
other := newBitArray(2000)
dba.SetBit(1)
other.SetBit(18)
dba.SetBit(222)
other.SetBit(222)
other.SetBit(1501)
ba := andDenseWithDenseBitArray(dba, other)
checkBit(t, ba, 0, false)
checkBit(t, ba, 1, false)
checkBit(t, ba, 3, false)
checkBit(t, ba, 18, false)
checkBit(t, ba, 222, true)
// check that the ba is the minimum of the size of `dba` and `other`
// (dense bitarrays return an error on an out-of-bounds access)
_, err := ba.GetBit(1500)
assert.Equal(t, OutOfRangeError(1500), err)
_, err = ba.GetBit(1501)
assert.Equal(t, OutOfRangeError(1501), err)
}
func TestAndSparseWithEmptySparse(t *testing.T) {
sba := newSparseBitArray()
other := newSparseBitArray()
sba.SetBit(5)
ba := andSparseWithSparseBitArray(sba, other)
checkBit(t, ba, 0, false)
checkBit(t, ba, 5, false)
checkBit(t, ba, 100, false)
}
func TestAndSparseWithEmptyDense(t *testing.T) {
sba := newSparseBitArray()
other := newBitArray(1000)
sba.SetBit(5)
ba := andSparseWithDenseBitArray(sba, other)
checkBit(t, ba, 5, false)
sba.Reset()
other.SetBit(5)
ba = andSparseWithDenseBitArray(sba, other)
checkBit(t, ba, 5, false)
}
func TestAndDenseWithEmptyDense(t *testing.T) {
dba := newBitArray(1000)
other := newBitArray(1000)
dba.SetBit(5)
ba := andDenseWithDenseBitArray(dba, other)
checkBit(t, ba, 5, false)
dba.Reset()
other.SetBit(5)
ba = andDenseWithDenseBitArray(dba, other)
checkBit(t, ba, 5, false)
}
================================================
FILE: bitarray/bitarray.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Package bitarray implements a bit array. Useful for tracking bool type values in a space
efficient way. This is *NOT* a threadsafe package.
*/
package bitarray
import "math/bits"
// bitArray is a struct that maintains state of a bit array.
type bitArray struct {
blocks []block
lowest uint64
highest uint64
anyset bool
}
func getIndexAndRemainder(k uint64) (uint64, uint64) {
return k / s, k % s
}
func (ba *bitArray) setLowest() {
for i := uint64(0); i < uint64(len(ba.blocks)); i++ {
if ba.blocks[i] == 0 {
continue
}
pos := ba.blocks[i].findRightPosition()
ba.lowest = (i * s) + pos
ba.anyset = true
return
}
ba.anyset = false
ba.lowest = 0
ba.highest = 0
}
func (ba *bitArray) setHighest() {
for i := len(ba.blocks) - 1; i >= 0; i-- {
if ba.blocks[i] == 0 {
continue
}
pos := ba.blocks[i].findLeftPosition()
ba.highest = (uint64(i) * s) + pos
ba.anyset = true
return
}
ba.anyset = false
ba.highest = 0
ba.lowest = 0
}
// capacity returns the total capacity of the bit array.
func (ba *bitArray) Capacity() uint64 {
return uint64(len(ba.blocks)) * s
}
// ToNums converts this bitarray to a list of numbers contained within it.
func (ba *bitArray) ToNums() []uint64 {
nums := make([]uint64, 0, ba.highest-ba.lowest/4)
for i, block := range ba.blocks {
block.toNums(uint64(i)*s, &nums)
}
return nums
}
// SetBit sets a bit at the given index to true.
func (ba *bitArray) SetBit(k uint64) error {
if k >= ba.Capacity() {
return OutOfRangeError(k)
}
if !ba.anyset {
ba.lowest = k
ba.highest = k
ba.anyset = true
} else {
if k < ba.lowest {
ba.lowest = k
} else if k > ba.highest {
ba.highest = k
}
}
i, pos := getIndexAndRemainder(k)
ba.blocks[i] = ba.blocks[i].insert(pos)
return nil
}
// GetBit returns a bool indicating if the value at the given
// index has been set.
func (ba *bitArray) GetBit(k uint64) (bool, error) {
if k >= ba.Capacity() {
return false, OutOfRangeError(k)
}
i, pos := getIndexAndRemainder(k)
result := ba.blocks[i]&block(1<<pos) != 0
return result, nil
}
// GetSetBits gets the position of bits set in the array.
func (ba *bitArray) GetSetBits(from uint64, buffer []uint64) []uint64 {
fromBlockIndex, fromOffset := getIndexAndRemainder(from)
return getSetBitsInBlocks(
fromBlockIndex,
fromOffset,
ba.blocks[fromBlockIndex:],
nil,
buffer,
)
}
// getSetBitsInBlocks fills a buffer with positions of set bits in the provided blocks. Optionally, indices may be
// provided for sparse/non-consecutive blocks.
func getSetBitsInBlocks(
fromBlockIndex, fromOffset uint64,
blocks []block,
indices []uint64,
buffer []uint64,
) []uint64 {
bufferCapacity := cap(buffer)
if bufferCapacity == 0 {
return buffer[:0]
}
results := buffer[:bufferCapacity]
resultSize := 0
for i, block := range blocks {
blockIndex := fromBlockIndex + uint64(i)
if indices != nil {
blockIndex = indices[i]
}
isFirstBlock := blockIndex == fromBlockIndex
if isFirstBlock {
block >>= fromOffset
}
for block != 0 {
trailing := bits.TrailingZeros64(uint64(block))
if isFirstBlock {
results[resultSize] = uint64(trailing) + (blockIndex << 6) + fromOffset
} else {
results[resultSize] = uint64(trailing) + (blockIndex << 6)
}
resultSize++
if resultSize == cap(results) {
return results[:resultSize]
}
// Clear the bit we just added to the result, which is the last bit set in the block. Ex.:
// block 01001100
// ^block 10110011
// (^block) + 1 10110100
// block & (^block) + 1 00000100
// block ^ mask 01001000
mask := block & ((^block) + 1)
block = block ^ mask
}
}
return results[:resultSize]
}
// ClearBit will unset a bit at the given index if it is set.
func (ba *bitArray) ClearBit(k uint64) error {
if k >= ba.Capacity() {
return OutOfRangeError(k)
}
if !ba.anyset { // nothing is set, might as well bail
return nil
}
i, pos := getIndexAndRemainder(k)
ba.blocks[i] &^= block(1 << pos)
if k == ba.highest {
ba.setHighest()
} else if k == ba.lowest {
ba.setLowest()
}
return nil
}
// Count returns the number of set bits in this array.
func (ba *bitArray) Count() int {
count := 0
for _, block := range ba.blocks {
count += bits.OnesCount64(uint64(block))
}
return count
}
// Or will bitwise or two bit arrays and return a new bit array
// representing the result.
func (ba *bitArray) Or(other BitArray) BitArray {
if dba, ok := other.(*bitArray); ok {
return orDenseWithDenseBitArray(ba, dba)
}
return orSparseWithDenseBitArray(other.(*sparseBitArray), ba)
}
// And will bitwise and two bit arrays and return a new bit array
// representing the result.
func (ba *bitArray) And(other BitArray) BitArray {
if dba, ok := other.(*bitArray); ok {
return andDenseWithDenseBitArray(ba, dba)
}
return andSparseWithDenseBitArray(other.(*sparseBitArray), ba)
}
// Nand will return the result of doing a bitwise and not of the bit array
// with the other bit array on each block.
func (ba *bitArray) Nand(other BitArray) BitArray {
if dba, ok := other.(*bitArray); ok {
return nandDenseWithDenseBitArray(ba, dba)
}
return nandDenseWithSparseBitArray(ba, other.(*sparseBitArray))
}
// Reset clears out the bit array.
func (ba *bitArray) Reset() {
for i := uint64(0); i < uint64(len(ba.blocks)); i++ {
ba.blocks[i] &= block(0)
}
ba.anyset = false
}
// Equals returns a bool indicating if these two bit arrays are equal.
func (ba *bitArray) Equals(other BitArray) bool {
if other.Capacity() == 0 && ba.highest > 0 {
return false
}
if other.Capacity() == 0 && !ba.anyset {
return true
}
var selfIndex uint64
for iter := other.Blocks(); iter.Next(); {
toIndex, otherBlock := iter.Value()
if toIndex > selfIndex {
for i := selfIndex; i < toIndex; i++ {
if ba.blocks[i] > 0 {
return false
}
}
}
selfIndex = toIndex
if !ba.blocks[selfIndex].equals(otherBlock) {
return false
}
selfIndex++
}
lastIndex, _ := getIndexAndRemainder(ba.highest)
if lastIndex >= selfIndex {
return false
}
return true
}
// Intersects returns a bool indicating if the supplied bitarray intersects
// this bitarray. This will check for intersection up to the length of the supplied
// bitarray. If the supplied bitarray is longer than this bitarray, this
// function returns false.
func (ba *bitArray) Intersects(other BitArray) bool {
if other.Capacity() > ba.Capacity() {
return false
}
if sba, ok := other.(*sparseBitArray); ok {
return ba.intersectsSparseBitArray(sba)
}
return ba.intersectsDenseBitArray(other.(*bitArray))
}
// Blocks will return an iterator over this bit array.
func (ba *bitArray) Blocks() Iterator {
return newBitArrayIterator(ba)
}
func (ba *bitArray) IsEmpty() bool {
return !ba.anyset
}
// complement flips all bits in this array.
func (ba *bitArray) complement() {
for i := uint64(0); i < uint64(len(ba.blocks)); i++ {
ba.blocks[i] = ^ba.blocks[i]
}
ba.setLowest()
if ba.anyset {
ba.setHighest()
}
}
func (ba *bitArray) intersectsSparseBitArray(other *sparseBitArray) bool {
for i, index := range other.indices {
if !ba.blocks[index].intersects(other.blocks[i]) {
return false
}
}
return true
}
func (ba *bitArray) intersectsDenseBitArray(other *bitArray) bool {
for i, block := range other.blocks {
if !ba.blocks[i].intersects(block) {
return false
}
}
return true
}
func (ba *bitArray) copy() BitArray {
blocks := make(blocks, len(ba.blocks))
copy(blocks, ba.blocks)
return &bitArray{
blocks: blocks,
lowest: ba.lowest,
highest: ba.highest,
anyset: ba.anyset,
}
}
// newBitArray returns a new dense BitArray at the specified size. This is a
// separate private constructor so unit tests don't have to constantly cast the
// BitArray interface to the concrete type.
func newBitArray(size uint64, args ...bool) *bitArray {
i, r := getIndexAndRemainder(size)
if r > 0 {
i++
}
ba := &bitArray{
blocks: make([]block, i),
anyset: false,
}
if len(args) > 0 && args[0] == true {
for i := uint64(0); i < uint64(len(ba.blocks)); i++ {
ba.blocks[i] = maximumBlock
}
ba.lowest = 0
ba.highest = i*s - 1
ba.anyset = true
}
return ba
}
// NewBitArray returns a new BitArray at the specified size. The
// optional arg denotes whether this bitarray should be set to the
// bitwise complement of the empty array, ie. sets all bits.
func NewBitArray(size uint64, args ...bool) BitArray {
return newBitArray(size, args...)
}
================================================
FILE: bitarray/bitarray_test.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package bitarray
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestBitOperations(t *testing.T) {
ba := newBitArray(10)
err := ba.SetBit(5)
if err != nil {
t.Fatal(err)
}
result, err := ba.GetBit(5)
if err != nil {
t.Fatal(err)
}
if !result {
t.Errorf(`Expected true at position: %d`, 5)
}
result, err = ba.GetBit(3)
if err != nil {
t.Fatal(err)
}
if result {
t.Errorf(`Expected false at position %d`, 3)
}
err = ba.ClearBit(5)
if err != nil {
t.Fatal(err)
}
result, err = ba.GetBit(5)
if err != nil {
t.Fatal(err)
}
if result {
t.Errorf(`Expected false at position: %d`, 5)
}
ba = newBitArray(24)
err = ba.SetBit(16)
if err != nil {
t.Fatal(err)
}
result, err = ba.GetBit(16)
if err != nil {
t.Fatal(err)
}
if !result {
t.Errorf(`Expected true at position: %d`, 16)
}
}
func TestDuplicateOperation(t *testing.T) {
ba := newBitArray(10)
err := ba.SetBit(5)
if err != nil {
t.Fatal(err)
}
err = ba.SetBit(5)
if err != nil {
t.Fatal(err)
}
result, err := ba.GetBit(5)
if err != nil {
t.Fatal(err)
}
if !result {
t.Errorf(`Expected true at position: %d`, 5)
}
err = ba.ClearBit(5)
if err != nil {
t.Fatal(err)
}
err = ba.ClearBit(5)
if err != nil {
t.Fatal(err)
}
result, err = ba.GetBit(5)
if err != nil {
t.Fatal(err)
}
if result {
t.Errorf(`Expected false at position: %d`, 5)
}
}
func TestOutOfBounds(t *testing.T) {
ba := newBitArray(4)
err := ba.SetBit(s + 1)
if _, ok := err.(OutOfRangeError); !ok {
t.Errorf(`Expected out of range error.`)
}
_, err = ba.GetBit(s + 1)
if _, ok := err.(OutOfRangeError); !ok {
t.Errorf(`Expected out of range error.`)
}
}
func TestIsEmpty(t *testing.T) {
ba := newBitArray(10)
assert.True(t, ba.IsEmpty())
ba.SetBit(5)
assert.False(t, ba.IsEmpty())
}
func TestCount(t *testing.T) {
ba := newBitArray(500)
assert.Equal(t, 0, ba.Count())
require.NoError(t, ba.SetBit(0))
assert.Equal(t, 1, ba.Count())
require.NoError(t, ba.SetBit(40))
require.NoError(t, ba.SetBit(64))
require.NoError(t, ba.SetBit(100))
require.NoError(t, ba.SetBit(200))
require.NoError(t, ba.SetBit(469))
require.NoError(t, ba.SetBit(500))
assert.Equal(t, 7, ba.Count())
require.NoError(t, ba.ClearBit(200))
assert.Equal(t, 6, ba.Count())
ba.Reset()
assert.Equal(t, 0, ba.Count())
}
func TestClear(t *testing.T) {
ba := newBitArray(10)
err := ba.SetBit(5)
if err != nil {
t.Fatal(err)
}
err = ba.SetBit(9)
if err != nil {
t.Fatal(err)
}
ba.Reset()
assert.False(t, ba.anyset)
result, err := ba.GetBit(5)
if err != nil {
t.Fatal(err)
}
if result {
t.Errorf(`BA not reset.`)
}
result, err = ba.GetBit(9)
if err != nil {
t.Fatal(err)
}
if result {
t.Errorf(`BA not reset.`)
}
}
func BenchmarkGetBit(b *testing.B) {
numItems := uint64(168000)
ba := newBitArray(numItems)
for i := uint64(0); i < numItems; i++ {
ba.SetBit(i)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
for j := uint64(0); j < numItems; j++ {
ba.GetBit(j)
}
}
}
func TestGetSetBits(t *testing.T) {
ba := newBitArray(1000)
buf := make([]uint64, 0, 5)
require.NoError(t, ba.SetBit(1))
require.NoError(t, ba.SetBit(4))
require.NoError(t, ba.SetBit(8))
require.NoError(t, ba.SetBit(63))
require.NoError(t, ba.SetBit(64))
require.NoError(t, ba.SetBit(200))
require.NoError(t, ba.SetBit(1000))
assert.Equal(t, []uint64(nil), ba.GetSetBits(0, nil))
assert.Equal(t, []uint64{}, ba.GetSetBits(0, []uint64{}))
assert.Equal(t, []uint64{1, 4, 8, 63, 64}, ba.GetSetBits(0, buf))
assert.Equal(t, []uint64{63, 64, 200, 1000}, ba.GetSetBits(10, buf))
assert.Equal(t, []uint64{63, 64, 200, 1000}, ba.GetSetBits(63, buf))
assert.Equal(t, []uint64{200, 1000}, ba.GetSetBits(128, buf))
require.NoError(t, ba.ClearBit(4))
require.NoError(t, ba.ClearBit(64))
assert.Equal(t, []uint64{1, 8, 63, 200, 1000}, ba.GetSetBits(0, buf))
assert.Empty(t, ba.GetSetBits(1001, buf))
ba.Reset()
assert.Empty(t, ba.GetSetBits(0, buf))
}
func BenchmarkGetSetBits(b *testing.B) {
numItems := uint64(168000)
ba := newBitArray(numItems)
for i := uint64(0); i < numItems; i++ {
if i%13 == 0 || i%5 == 0 {
require.NoError(b, ba.SetBit(i))
}
}
buf := make([]uint64, 0, ba.Capacity())
b.ResetTimer()
for i := 0; i < b.N; i++ {
ba.GetSetBits(0, buf)
}
}
func TestEquality(t *testing.T) {
ba := newBitArray(s + 1)
other := newBitArray(s + 1)
if !ba.Equals(other) {
t.Errorf(`Expected equality.`)
}
ba.SetBit(s + 1)
other.SetBit(s + 1)
if !ba.Equals(other) {
t.Errorf(`Expected equality.`)
}
other.SetBit(0)
if ba.Equals(other) {
t.Errorf(`Expected inequality.`)
}
}
func BenchmarkEquality(b *testing.B) {
ba := newBitArray(160000)
other := newBitArray(ba.Capacity())
b.ResetTimer()
for i := 0; i < b.N; i++ {
ba.Equals(other)
}
}
func TestIntersects(t *testing.T) {
ba := newBitArray(10)
other := newBitArray(ba.Capacity())
ba.SetBit(1)
ba.SetBit(2)
other.SetBit(1)
if !ba.Intersects(other) {
t.Errorf(`Is intersecting.`)
}
other.SetBit(5)
if ba.Intersects(other) {
t.Errorf(`Is not intersecting.`)
}
other = newBitArray(ba.Capacity() + 1)
other.SetBit(1)
if ba.Intersects(other) {
t.Errorf(`Is not intersecting.`)
}
}
func BenchmarkIntersects(b *testing.B) {
ba := newBitArray(162432)
other := newBitArray(ba.Capacity())
ba.SetBit(159999)
other.SetBit(159999)
b.ResetTimer()
for i := 0; i < b.N; i++ {
ba.Intersects(other)
}
}
func TestComplement(t *testing.T) {
ba := newBitArray(10)
ba.SetBit(5)
ba.complement()
if ok, _ := ba.GetBit(5); ok {
t.Errorf(`Expected clear.`)
}
if ok, _ := ba.GetBit(4); !ok {
t.Errorf(`Expected set.`)
}
}
func BenchmarkComplement(b *testing.B) {
ba := newBitArray(160000)
b.ResetTimer()
for i := 0; i < b.N; i++ {
ba.complement()
}
}
func TestSetHighestLowest(t *testing.T) {
ba := newBitArray(10)
assert.False(t, ba.anyset)
assert.Equal(t, uint64(0), ba.lowest)
assert.Equal(t, uint64(0), ba.highest)
ba.SetBit(5)
assert.True(t, ba.anyset)
assert.Equal(t, uint64(5), ba.lowest)
assert.Equal(t, uint64(5), ba.highest)
ba.SetBit(8)
assert.Equal(t, uint64(5), ba.lowest)
assert.Equal(t, uint64(8), ba.highest)
}
func TestGetBitAtCapacity(t *testing.T) {
ba := newBitArray(s * 2)
_, err := ba.GetBit(s * 2)
assert.Error(t, err)
}
func TestSetBitAtCapacity(t *testing.T) {
ba := newBitArray(s * 2)
err := ba.SetBit(s * 2)
assert.Error(t, err)
}
func TestClearBitAtCapacity(t *testing.T) {
ba := newBitArray(s * 2)
err := ba.ClearBit(s * 2)
assert.Error(t, err)
}
func TestClearHighestLowest(t *testing.T) {
ba := newBitArray(10)
ba.SetBit(5)
ba.ClearBit(5)
assert.False(t, ba.anyset)
assert.Equal(t, uint64(0), ba.lowest)
assert.Equal(t, uint64(0), ba.highest)
ba.SetBit(3)
ba.SetBit(5)
ba.SetBit(7)
ba.ClearBit(7)
assert.True(t, ba.anyset)
assert.Equal(t, uint64(5), ba.highest)
assert.Equal(t, uint64(3), ba.lowest)
ba.SetBit(7)
ba.ClearBit(3)
assert.True(t, ba.anyset)
assert.Equal(t, uint64(5), ba.lowest)
assert.Equal(t, uint64(7), ba.highest)
ba.ClearBit(7)
assert.True(t, ba.anyset)
assert.Equal(t, uint64(5), ba.lowest)
assert.Equal(t, uint64(5), ba.highest)
ba.ClearBit(5)
assert.False(t, ba.anyset)
assert.Equal(t, uint64(0), ba.lowest)
assert.Equal(t, uint64(0), ba.highest)
}
func TestComplementResetsBounds(t *testing.T) {
ba := newBitArray(5)
ba.complement()
assert.True(t, ba.anyset)
assert.Equal(t, uint64(0), ba.lowest)
assert.Equal(t, uint64(s-1), ba.highest)
}
func TestBitArrayIntersectsSparse(t *testing.T) {
ba := newBitArray(s * 2)
cba := newSparseBitArray()
assert.True(t, ba.Intersects(cba))
cba.SetBit(5)
assert.False(t, ba.Intersects(cba))
ba.SetBit(5)
assert.True(t, ba.Intersects(cba))
cba.SetBit(s + 1)
assert.False(t, ba.Intersects(cba))
ba.SetBit(s + 1)
assert.True(t, ba.Intersects(cba))
}
func TestBitArrayEqualsSparse(t *testing.T) {
ba := newBitArray(s * 2)
cba := newSparseBitArray()
assert.True(t, ba.Equals(cba))
ba.SetBit(5)
assert.False(t, ba.Equals(cba))
cba.SetBit(5)
assert.True(t, ba.Equals(cba))
ba.SetBit(s + 1)
assert.False(t, ba.Equals(cba))
cba.SetBit(s + 1)
assert.True(t, ba.Equals(cba))
}
func TestConstructorSetBitArray(t *testing.T) {
ba := newBitArray(8, true)
result, err := ba.GetBit(7)
assert.Nil(t, err)
assert.True(t, result)
assert.Equal(t, s-1, ba.highest)
assert.Equal(t, uint64(0), ba.lowest)
assert.True(t, ba.anyset)
}
func TestCopyBitArray(t *testing.T) {
ba := newBitArray(10)
ba.SetBit(5)
ba.SetBit(1)
result := ba.copy().(*bitArray)
assert.Equal(t, ba.anyset, result.anyset)
assert.Equal(t, ba.lowest, result.lowest)
assert.Equal(t, ba.highest, result.highest)
assert.Equal(t, ba.blocks, result.blocks)
}
func BenchmarkDenseIntersectsCompressed(b *testing.B) {
numBits := uint64(162432)
ba := newBitArray(numBits)
other := newSparseBitArray()
for i := uint64(0); i < numBits; i++ {
ba.SetBit(i)
other.SetBit(i)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
ba.intersectsSparseBitArray(other)
}
}
func TestBitArrayToNums(t *testing.T) {
ba := newBitArray(s * 2)
ba.SetBit(s - 1)
ba.SetBit(s + 1)
expected := []uint64{s - 1, s + 1}
result := ba.ToNums()
assert.Equal(t, expected, result)
}
func BenchmarkBitArrayToNums(b *testing.B) {
numItems := uint64(1000)
ba := newBitArray(numItems)
for i := uint64(0); i < numItems; i++ {
ba.SetBit(i)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
ba.ToNums()
}
}
================================================
FILE: bitarray/bitmap.go
================================================
/*
Copyright (c) 2016, Theodore Butler
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Package bitmap contains bitmaps of length 32 and 64 for tracking bool
// values without the need for arrays or hashing.
package bitarray
// Bitmap32 tracks 32 bool values within a uint32
type Bitmap32 uint32
// SetBit returns a Bitmap32 with the bit at the given position set to 1
func (b Bitmap32) SetBit(pos uint) Bitmap32 {
return b | (1 << pos)
}
// ClearBit returns a Bitmap32 with the bit at the given position set to 0
func (b Bitmap32) ClearBit(pos uint) Bitmap32 {
return b & ^(1 << pos)
}
// GetBit returns true if the bit at the given position in the Bitmap32 is 1
func (b Bitmap32) GetBit(pos uint) bool {
return (b & (1 << pos)) != 0
}
// PopCount returns the amount of bits set to 1 in the Bitmap32
func (b Bitmap32) PopCount() int {
// http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
b -= (b >> 1) & 0x55555555
b = (b>>2)&0x33333333 + b&0x33333333
b += b >> 4
b &= 0x0f0f0f0f
b *= 0x01010101
return int(byte(b >> 24))
}
// Bitmap64 tracks 64 bool values within a uint64
type Bitmap64 uint64
// SetBit returns a Bitmap64 with the bit at the given position set to 1
func (b Bitmap64) SetBit(pos uint) Bitmap64 {
return b | (1 << pos)
}
// ClearBit returns a Bitmap64 with the bit at the given position set to 0
func (b Bitmap64) ClearBit(pos uint) Bitmap64 {
return b & ^(1 << pos)
}
// GetBit returns true if the bit at the given position in the Bitmap64 is 1
func (b Bitmap64) GetBit(pos uint) bool {
return (b & (1 << pos)) != 0
}
// PopCount returns the amount of bits set to 1 in the Bitmap64
func (b Bitmap64) PopCount() int {
// http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
b -= (b >> 1) & 0x5555555555555555
b = (b>>2)&0x3333333333333333 + b&0x3333333333333333
b += b >> 4
b &= 0x0f0f0f0f0f0f0f0f
b *= 0x0101010101010101
return int(byte(b >> 56))
}
================================================
FILE: bitarray/bitmap_test.go
================================================
/*
Copyright (c) 2016, Theodore Butler
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package bitarray
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestBitmap32_PopCount(t *testing.T) {
b := []uint32{
uint32(0x55555555), // 0x55555555 = 01010101 01010101 01010101 01010101
uint32(0x33333333), // 0x33333333 = 00110011 00110011 00110011 00110011
uint32(0x0F0F0F0F), // 0x0F0F0F0F = 00001111 00001111 00001111 00001111
uint32(0x00FF00FF), // 0x00FF00FF = 00000000 11111111 00000000 11111111
uint32(0x0000FFFF), // 0x0000FFFF = 00000000 00000000 11111111 11111111
}
for _, x := range b {
assert.Equal(t, 16, Bitmap32(x).PopCount())
}
}
func TestBitmap64_PopCount(t *testing.T) {
b := []uint64{
uint64(0x5555555555555555),
uint64(0x3333333333333333),
uint64(0x0F0F0F0F0F0F0F0F),
uint64(0x00FF00FF00FF00FF),
uint64(0x0000FFFF0000FFFF),
}
for _, x := range b {
assert.Equal(t, 32, Bitmap64(x).PopCount())
}
}
func TestBitmap32_SetBit(t *testing.T) {
m := Bitmap32(0)
assert.Equal(t, Bitmap32(0x4), m.SetBit(2))
}
func TestBitmap32_ClearBit(t *testing.T) {
m := Bitmap32(0x4)
assert.Equal(t, Bitmap32(0), m.ClearBit(2))
}
func TestBitmap32_zGetBit(t *testing.T) {
m := Bitmap32(0x55555555)
assert.Equal(t, true, m.GetBit(2))
}
func TestBitmap64_SetBit(t *testing.T) {
m := Bitmap64(0)
assert.Equal(t, Bitmap64(0x4), m.SetBit(2))
}
func TestBitmap64_ClearBit(t *testing.T) {
m := Bitmap64(0x4)
assert.Equal(t, Bitmap64(0), m.ClearBit(2))
}
func TestBitmap64_GetBit(t *testing.T) {
m := Bitmap64(0x55555555)
assert.Equal(t, true, m.GetBit(2))
}
func BenchmarkBitmap32_PopCount(b *testing.B) {
m := Bitmap32(0x33333333)
b.ResetTimer()
for i := b.N; i > 0; i-- {
m.PopCount()
}
}
func BenchmarkBitmap64_PopCount(b *testing.B) {
m := Bitmap64(0x3333333333333333)
b.ResetTimer()
for i := b.N; i > 0; i-- {
m.PopCount()
}
}
================================================
FILE: bitarray/block.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package bitarray
import (
"fmt"
"unsafe"
)
// block defines how we split apart the bit array. This also determines the size
// of s. This can be changed to any unsigned integer type: uint8, uint16,
// uint32, and so on.
type block uint64
// s denotes the size of any element in the block array.
// For a block of uint64, s will be equal to 64
// For a block of uint32, s will be equal to 32
// and so on...
const s = uint64(unsafe.Sizeof(block(0)) * 8)
// maximumBlock represents a block of all 1s and is used in the constructors.
const maximumBlock = block(0) | ^block(0)
func (b block) toNums(offset uint64, nums *[]uint64) {
for i := uint64(0); i < s; i++ {
if b&block(1<<i) > 0 {
*nums = append(*nums, i+offset)
}
}
}
func (b block) findLeftPosition() uint64 {
for i := s - 1; i < s; i-- {
test := block(1 << i)
if b&test == test {
return i
}
}
return s
}
func (b block) findRightPosition() uint64 {
for i := uint64(0); i < s; i++ {
test := block(1 << i)
if b&test == test {
return i
}
}
return s
}
func (b block) insert(position uint64) block {
return b | block(1<<position)
}
func (b block) remove(position uint64) block {
return b & ^block(1<<position)
}
func (b block) or(other block) block {
return b | other
}
func (b block) and(other block) block {
return b & other
}
func (b block) nand(other block) block {
return b &^ other
}
func (b block) get(position uint64) bool {
return b&block(1<<position) != 0
}
func (b block) equals(other block) bool {
return b == other
}
func (b block) intersects(other block) bool {
return b&other == other
}
func (b block) String() string {
return fmt.Sprintf(fmt.Sprintf("%%0%db", s), uint64(b))
}
================================================
FILE: bitarray/block_test.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package bitarray
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestBlockToNums(t *testing.T) {
b := block(0)
b = b.insert(s - 2)
b = b.insert(s - 6)
expected := []uint64{s - 6, s - 2}
result := make([]uint64, 0, 0)
b.toNums(0, &result)
assert.Equal(t, expected, result)
}
func BenchmarkBlockToNums(b *testing.B) {
block := block(0)
for i := uint64(0); i < s; i++ {
block = block.insert(i)
}
nums := make([]uint64, 0, 0)
b.ResetTimer()
for i := 0; i < b.N; i++ {
block.toNums(0, &nums)
}
}
================================================
FILE: bitarray/encoding.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package bitarray
import (
"bytes"
"encoding/binary"
"errors"
"io"
)
// Marshal takes a dense or sparse bit array and serializes it to a
// byte slice.
func Marshal(ba BitArray) ([]byte, error) {
if eba, ok := ba.(*bitArray); ok {
return eba.Serialize()
} else if sba, ok := ba.(*sparseBitArray); ok {
return sba.Serialize()
} else {
return nil, errors.New("not a valid BitArray")
}
}
// Unmarshal takes a byte slice, of the same format produced by Marshal,
// and returns a BitArray.
func Unmarshal(input []byte) (BitArray, error) {
if len(input) == 0 {
return nil, errors.New("no data in input")
}
if input[0] == 'B' {
ret := newBitArray(0)
err := ret.Deserialize(input)
if err != nil {
return nil, err
}
return ret, nil
} else if input[0] == 'S' {
ret := newSparseBitArray()
err := ret.Deserialize(input)
if err != nil {
return nil, err
}
return ret, nil
} else {
return nil, errors.New("unrecognized encoding")
}
}
// Serialize converts the sparseBitArray to a byte slice
func (ba *sparseBitArray) Serialize() ([]byte, error) {
w := new(bytes.Buffer)
var identifier uint8 = 'S'
err := binary.Write(w, binary.LittleEndian, identifier)
if err != nil {
return nil, err
}
blocksLen := uint64(len(ba.blocks))
indexLen := uint64(len(ba.indices))
err = binary.Write(w, binary.LittleEndian, blocksLen)
if err != nil {
return nil, err
}
err = binary.Write(w, binary.LittleEndian, ba.blocks)
if err != nil {
return nil, err
}
err = binary.Write(w, binary.LittleEndian, indexLen)
if err != nil {
return nil, err
}
err = binary.Write(w, binary.LittleEndian, ba.indices)
if err != nil {
return nil, err
}
return w.Bytes(), nil
}
// This function is a copy from the binary package, with some added error
// checking to avoid panics. The function will return the value, and the number
// of bytes read from the buffer. If the number of bytes is negative, then
// not enough bytes were passed in and the return value will be zero.
func Uint64FromBytes(b []byte) (uint64, int) {
if len(b) < 8 {
return 0, -1
}
val := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
return val, 8
}
// Deserialize takes the incoming byte slice, and populates the sparseBitArray
// with data in the bytes. Note that this will overwrite any capacity
// specified when creating the sparseBitArray. Also note that if an error
// is returned, the sparseBitArray this is called on might be populated
// with partial data.
func (ret *sparseBitArray) Deserialize(incoming []byte) error {
var intsize = uint64(s / 8)
var curLoc = uint64(1) // Ignore the identifier byte
var intsToRead uint64
var bytesRead int
intsToRead, bytesRead = Uint64FromBytes(incoming[curLoc : curLoc+intsize])
if bytesRead < 0 {
return errors.New("Invalid data for BitArray")
}
curLoc += intsize
var nextblock uint64
ret.blocks = make([]block, intsToRead)
for i := uint64(0); i < intsToRead; i++ {
nextblock, bytesRead = Uint64FromBytes(incoming[curLoc : curLoc+intsize])
if bytesRead < 0 {
return errors.New("Invalid data for BitArray")
}
ret.blocks[i] = block(nextblock)
curLoc += intsize
}
intsToRead, bytesRead = Uint64FromBytes(incoming[curLoc : curLoc+intsize])
if bytesRead < 0 {
return errors.New("Invalid data for BitArray")
}
curLoc += intsize
var nextuint uint64
ret.indices = make(uintSlice, intsToRead)
for i := uint64(0); i < intsToRead; i++ {
nextuint, bytesRead = Uint64FromBytes(incoming[curLoc : curLoc+intsize])
if bytesRead < 0 {
return errors.New("Invalid data for BitArray")
}
ret.indices[i] = nextuint
curLoc += intsize
}
return nil
}
// Serialize converts the bitArray to a byte slice.
func (ba *bitArray) Serialize() ([]byte, error) {
w := new(bytes.Buffer)
var identifier uint8 = 'B'
err := binary.Write(w, binary.LittleEndian, identifier)
if err != nil {
return nil, err
}
err = binary.Write(w, binary.LittleEndian, ba.lowest)
if err != nil {
return nil, err
}
err = binary.Write(w, binary.LittleEndian, ba.highest)
if err != nil {
return nil, err
}
var encodedanyset uint8
if ba.anyset {
encodedanyset = 1
} else {
encodedanyset = 0
}
err = binary.Write(w, binary.LittleEndian, encodedanyset)
if err != nil {
return nil, err
}
err = binary.Write(w, binary.LittleEndian, ba.blocks)
if err != nil {
return nil, err
}
return w.Bytes(), nil
}
// Deserialize takes the incoming byte slice, and populates the bitArray
// with data in the bytes. Note that this will overwrite any capacity
// specified when creating the bitArray. Also note that if an error is returned,
// the bitArray this is called on might be populated with partial data.
func (ret *bitArray) Deserialize(incoming []byte) error {
r := bytes.NewReader(incoming[1:]) // Discard identifier
err := binary.Read(r, binary.LittleEndian, &ret.lowest)
if err != nil {
return err
}
err = binary.Read(r, binary.LittleEndian, &ret.highest)
if err != nil {
return err
}
var encodedanyset uint8
err = binary.Read(r, binary.LittleEndian, &encodedanyset)
if err != nil {
return err
}
// anyset defaults to false so we don't need an else statement
if encodedanyset == 1 {
ret.anyset = true
}
var nextblock block
err = binary.Read(r, binary.LittleEndian, &nextblock)
for err == nil {
ret.blocks = append(ret.blocks, nextblock)
err = binary.Read(r, binary.LittleEndian, &nextblock)
}
if err != io.EOF {
return err
}
return nil
}
================================================
FILE: bitarray/encoding_test.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package bitarray
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestSparseBitArraySerialization(t *testing.T) {
numItems := uint64(1280)
input := newSparseBitArray()
for i := uint64(0); i < numItems; i++ {
if i%3 == 0 {
input.SetBit(i)
}
}
outBytes, err := input.Serialize()
assert.Equal(t, err, nil)
assert.Equal(t, len(outBytes), 337)
assert.True(t, outBytes[0] == 'S')
expected := []byte{83, 20, 0, 0, 0, 0, 0, 0, 0, 73}
assert.Equal(t, expected, outBytes[:10])
output := newSparseBitArray()
err = output.Deserialize(outBytes)
assert.Equal(t, err, nil)
assert.True(t, input.Equals(output))
}
func TestBitArraySerialization(t *testing.T) {
numItems := uint64(1280)
input := newBitArray(numItems)
for i := uint64(0); i < numItems; i++ {
if i%3 == 0 {
input.SetBit(i)
}
}
outBytes, err := input.Serialize()
assert.Equal(t, err, nil)
// 1280 bits = 20 blocks = 160 bytes, plus lowest and highest at
// 128 bits = 16 bytes plus 1 byte for the anyset param and the identifer
assert.Equal(t, len(outBytes), 178)
expected := []byte{66, 0, 0, 0, 0, 0, 0, 0, 0, 254}
assert.Equal(t, expected, outBytes[:10])
output := newBitArray(0)
err = output.Deserialize(outBytes)
assert.Equal(t, err, nil)
assert.True(t, input.Equals(output))
}
func TestBitArrayMarshalUnmarshal(t *testing.T) {
numItems := uint64(1280)
input := newBitArray(numItems)
for i := uint64(0); i < numItems; i++ {
if i%3 == 0 {
input.SetBit(i)
}
}
outputBytes, err := Marshal(input)
assert.Equal(t, err, nil)
assert.Equal(t, outputBytes[0], byte('B'))
assert.Equal(t, len(outputBytes), 178)
output, err := Unmarshal(outputBytes)
assert.Equal(t, err, nil)
assert.True(t, input.Equals(output))
}
func TestSparseBitArrayMarshalUnmarshal(t *testing.T) {
numItems := uint64(1280)
input := newSparseBitArray()
for i := uint64(0); i < numItems; i++ {
if i%3 == 0 {
input.SetBit(i)
}
}
outputBytes, err := Marshal(input)
assert.Equal(t, err, nil)
assert.Equal(t, outputBytes[0], byte('S'))
assert.Equal(t, len(outputBytes), 337)
output, err := Unmarshal(outputBytes)
assert.Equal(t, err, nil)
assert.True(t, input.Equals(output))
}
func TestUnmarshalErrors(t *testing.T) {
numItems := uint64(1280)
input := newBitArray(numItems)
for i := uint64(0); i < numItems; i++ {
if i%3 == 0 {
input.SetBit(i)
}
}
outputBytes, err := Marshal(input)
outputBytes[0] = 'C'
output, err := Unmarshal(outputBytes)
assert.Error(t, err)
assert.Equal(t, output, nil)
output, err = Unmarshal(nil)
assert.Error(t, err)
assert.Equal(t, output, nil)
}
================================================
FILE: bitarray/error.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package bitarray
import "fmt"
// OutOfRangeError is an error caused by trying to access a bitarray past the end of its
// capacity.
type OutOfRangeError uint64
// Error returns a human readable description of the out-of-range error.
func (err OutOfRangeError) Error() string {
return fmt.Sprintf(`Index %d is out of range.`, err)
}
================================================
FILE: bitarray/interface.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Package bitarray or bitmap is useful when comparing large amounts of structured
data if the data can be represented as integers. For instance, set
intersection of {1, 3, 5} and {3, 5, 7} represented as bitarrays can
be done in a single clock cycle (not counting the time it takes to convert)
the resultant array back into integers). When Go implements a command
to get trailing zeroes, the reconversion back into integers should be much faster.
*/
package bitarray
// BitArray represents a structure that can be used to
// quickly check for existence when using a large number
// of items in a very memory efficient way.
type BitArray interface {
// SetBit sets the bit at the given position. This
// function returns an error if the position is out
// of range. A sparse bit array never returns an error.
SetBit(k uint64) error
// GetBit gets the bit at the given position. This
// function returns an error if the position is out
// of range. A sparse bit array never returns an error.
GetBit(k uint64) (bool, error)
// GetSetBits gets the position of bits set in the array. Will
// return as many set bits as can fit in the provided buffer
// starting from the specified position in the array.
GetSetBits(from uint64, buffer []uint64) []uint64
// ClearBit clears the bit at the given position. This
// function returns an error if the position is out
// of range. A sparse bit array never returns an error.
ClearBit(k uint64) error
// Reset sets all values to zero.
Reset()
// Blocks returns an iterator to be used to iterate
// over the bit array.
Blocks() Iterator
// Equals returns a bool indicating equality between the
// two bit arrays.
Equals(other BitArray) bool
// Intersects returns a bool indicating if the other bit
// array intersects with this bit array.
Intersects(other BitArray) bool
// Capacity returns either the given capacity of the bit array
// in the case of a dense bit array or the highest possible
// seen capacity of the sparse array.
Capacity() uint64
// Count returns the number of set bits in this array.
Count() int
// Or will bitwise or the two bitarrays and return a new bitarray
// representing the result.
Or(other BitArray) BitArray
// And will bitwise and the two bitarrays and return a new bitarray
// representing the result.
And(other BitArray) BitArray
// Nand will bitwise nand the two bitarrays and return a new bitarray
// representing the result.
Nand(other BitArray) BitArray
// ToNums converts this bit array to the list of numbers contained
// within it.
ToNums() []uint64
// IsEmpty checks to see if any values are set on the bitarray
IsEmpty() bool
}
// Iterator defines methods used to iterate over a bit array.
type Iterator interface {
// Next moves the pointer to the next block. Returns
// false when no blocks remain.
Next() bool
// Value returns the next block and its index
Value() (uint64, block)
}
================================================
FILE: bitarray/iterator.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package bitarray
type sparseBitArrayIterator struct {
index int64
sba *sparseBitArray
}
// Next increments the index and returns a bool indicating
// if any further items exist.
func (iter *sparseBitArrayIterator) Next() bool {
iter.index++
return iter.index < int64(len(iter.sba.indices))
}
// Value returns the index and block at the given index.
func (iter *sparseBitArrayIterator) Value() (uint64, block) {
return iter.sba.indices[iter.index], iter.sba.blocks[iter.index]
}
func newCompressedBitArrayIterator(sba *sparseBitArray) *sparseBitArrayIterator {
return &sparseBitArrayIterator{
sba: sba,
index: -1,
}
}
type bitArrayIterator struct {
index int64
stopIndex uint64
ba *bitArray
}
// Next increments the index and returns a bool indicating if any further
// items exist.
func (iter *bitArrayIterator) Next() bool {
iter.index++
return uint64(iter.index) <= iter.stopIndex
}
// Value returns an index and the block at this index.
func (iter *bitArrayIterator) Value() (uint64, block) {
return uint64(iter.index), iter.ba.blocks[iter.index]
}
func newBitArrayIterator(ba *bitArray) *bitArrayIterator {
stop, _ := getIndexAndRemainder(ba.highest)
start, _ := getIndexAndRemainder(ba.lowest)
return &bitArrayIterator{
ba: ba,
index: int64(start) - 1,
stopIndex: stop,
}
}
================================================
FILE: bitarray/nand.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package bitarray
func nandSparseWithSparseBitArray(sba, other *sparseBitArray) BitArray {
// nand is an operation on the incoming array only, so the size will never
// be more than the incoming array, regardless of the size of the other
max := len(sba.indices)
indices := make(uintSlice, 0, max)
blocks := make(blocks, 0, max)
selfIndex := 0
otherIndex := 0
var resultBlock block
// move through the array and compare the blocks if they happen to
// intersect
for {
if selfIndex == len(sba.indices) {
// The bitarray being operated on is exhausted, so just return
break
} else if otherIndex == len(other.indices) {
// The other array is exhausted. In this case, we assume that we
// are calling nand on empty bit arrays, which is the same as just
// copying the value in the sba array
indices = append(indices, sba.indices[selfIndex])
blocks = append(blocks, sba.blocks[selfIndex])
selfIndex++
continue
}
selfValue := sba.indices[selfIndex]
otherValue := other.indices[otherIndex]
switch {
case otherValue < selfValue:
// The `sba` bitarray has a block with a index position
// greater than us. We want to compare with that block
// if possible, so move our `other` index closer to that
// block's index.
otherIndex++
case otherValue > selfValue:
// Here, the sba array has blocks that the other array doesn't
// have. In this case, we just copy exactly the sba array values
indices = append(indices, selfValue)
blocks = append(blocks, sba.blocks[selfIndex])
// This is the exact logical inverse of the above case.
selfIndex++
default:
// Here, our indices match for both `sba` and `other`.
// Time to do the bitwise AND operation and add a block
// to our result list if the block has values in it.
resultBlock = sba.blocks[selfIndex].nand(other.blocks[otherIndex])
if resultBlock > 0 {
indices = append(indices, selfValue)
blocks = append(blocks, resultBlock)
}
selfIndex++
otherIndex++
}
}
return &sparseBitArray{
indices: indices,
blocks: blocks,
}
}
func nandSparseWithDenseBitArray(sba *sparseBitArray, other *bitArray) BitArray {
// Since nand is non-commutative, the resulting array should be sparse,
// and the same length or less than the sparse array
indices := make(uintSlice, 0, len(sba.indices))
blocks := make(blocks, 0, len(sba.indices))
var resultBlock block
// Loop through the sparse array and match it with the dense array.
for selfIndex, selfValue := range sba.indices {
if selfValue >= uint64(len(other.blocks)) {
// Since the dense array is exhausted, just copy over the data
// from the sparse array
resultBlock = sba.blocks[selfIndex]
indices = append(indices, selfValue)
blocks = append(blocks, resultBlock)
continue
}
resultBlock = sba.blocks[selfIndex].nand(other.blocks[selfValue])
if resultBlock > 0 {
indices = append(indices, selfValue)
blocks = append(blocks, resultBlock)
}
}
return &sparseBitArray{
indices: indices,
blocks: blocks,
}
}
func nandDenseWithSparseBitArray(sba *bitArray, other *sparseBitArray) BitArray {
// Since nand is non-commutative, the resulting array should be dense,
// and the same length or less than the dense array
tmp := sba.copy()
ret := tmp.(*bitArray)
// Loop through the other array and match it with the sba array.
for otherIndex, otherValue := range other.indices {
if otherValue >= uint64(len(ret.blocks)) {
break
}
ret.blocks[otherValue] = sba.blocks[otherValue].nand(other.blocks[otherIndex])
}
ret.setLowest()
ret.setHighest()
return ret
}
func nandDenseWithDenseBitArray(dba, other *bitArray) BitArray {
min := uint64(len(dba.blocks))
ba := newBitArray(min * s)
for i := uint64(0); i < min; i++ {
ba.blocks[i] = dba.blocks[i].nand(other.blocks[i])
}
ba.setLowest()
ba.setHighest()
return ba
}
================================================
FILE: bitarray/nand_test.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package bitarray
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNandSparseWithSparseBitArray(t *testing.T) {
sba := newSparseBitArray()
other := newSparseBitArray()
// bits for which only one of the arrays is set
sba.SetBit(3)
sba.SetBit(280)
other.SetBit(9)
other.SetBit(100)
sba.SetBit(1000)
other.SetBit(1001)
// bits for which both arrays are set
sba.SetBit(1)
other.SetBit(1)
sba.SetBit(2680)
other.SetBit(2680)
sba.SetBit(30)
other.SetBit(30)
ba := nandSparseWithSparseBitArray(sba, other)
// Bits in both
checkBit(t, ba, 1, false)
checkBit(t, ba, 30, false)
checkBit(t, ba, 2680, false)
// Bits in sba but not other
checkBit(t, ba, 3, true)
checkBit(t, ba, 280, true)
checkBit(t, ba, 1000, true)
// Bits in other but not sba
checkBit(t, ba, 9, false)
checkBit(t, ba, 100, false)
checkBit(t, ba, 2, false)
nums := ba.ToNums()
assert.Equal(t, []uint64{3, 280, 1000}, nums)
}
func TestNandSparseWithDenseBitArray(t *testing.T) {
sba := newSparseBitArray()
other := newBitArray(300)
other.SetBit(1)
sba.SetBit(1)
other.SetBit(150)
sba.SetBit(150)
sba.SetBit(155)
other.SetBit(156)
sba.SetBit(300)
other.SetBit(300)
ba := nandSparseWithDenseBitArray(sba, other)
// Bits in both
checkBit(t, ba, 1, false)
checkBit(t, ba, 150, false)
checkBit(t, ba, 300, false)
// Bits in sba but not other
checkBit(t, ba, 155, true)
// Bits in other but not sba
checkBit(t, ba, 156, false)
nums := ba.ToNums()
assert.Equal(t, []uint64{155}, nums)
}
func TestNandDenseWithSparseBitArray(t *testing.T) {
sba := newBitArray(300)
other := newSparseBitArray()
other.SetBit(1)
sba.SetBit(1)
other.SetBit(150)
sba.SetBit(150)
sba.SetBit(155)
other.SetBit(156)
sba.SetBit(300)
other.SetBit(300)
ba := nandDenseWithSparseBitArray(sba, other)
// Bits in both
checkBit(t, ba, 1, false)
checkBit(t, ba, 150, false)
checkBit(t, ba, 300, false)
// Bits in sba but not other
checkBit(t, ba, 155, true)
// Bits in other but not sba
checkBit(t, ba, 156, false)
nums := ba.ToNums()
assert.Equal(t, []uint64{155}, nums)
}
func TestNandSparseWithSmallerDenseBitArray(t *testing.T) {
sba := newSparseBitArray()
other := newBitArray(512)
other.SetBit(1)
sba.SetBit(1)
other.SetBit(150)
sba.SetBit(150)
sba.SetBit(155)
sba.SetBit(500)
other.SetBit(128)
sba.SetBit(1500)
sba.SetBit(1200)
ba := nandSparseWithDenseBitArray(sba, other)
// Bits in both
checkBit(t, ba, 1, false)
checkBit(t, ba, 150, false)
// Bits in sba but not other
checkBit(t, ba, 155, true)
checkBit(t, ba, 500, true)
checkBit(t, ba, 1200, true)
checkBit(t, ba, 1500, true)
// Bits in other but not sba
checkBit(t, ba, 128, false)
nums := ba.ToNums()
assert.Equal(t, []uint64{155, 500, 1200, 1500}, nums)
}
func TestNandDenseWithDenseBitArray(t *testing.T) {
dba := newBitArray(1000)
other := newBitArray(2000)
dba.SetBit(1)
other.SetBit(18)
dba.SetBit(222)
other.SetBit(222)
other.SetBit(1501)
ba := nandDenseWithDenseBitArray(dba, other)
// Bits in both
checkBit(t, ba, 222, false)
// Bits in dba and not other
checkBit(t, ba, 1, true)
// Bits in other
checkBit(t, ba, 18, false)
// Bits in neither
checkBit(t, ba, 0, false)
checkBit(t, ba, 3, false)
// check that the ba is the minimum of the size of `dba` and `other`
// (dense bitarrays return an error on an out-of-bounds access)
_, err := ba.GetBit(1500)
assert.Equal(t, OutOfRangeError(1500), err)
_, err = ba.GetBit(1501)
assert.Equal(t, OutOfRangeError(1501), err)
nums := ba.ToNums()
assert.Equal(t, []uint64{1}, nums)
}
func TestNandSparseWithEmptySparse(t *testing.T) {
sba := newSparseBitArray()
other := newSparseBitArray()
sba.SetBit(5)
ba := nandSparseWithSparseBitArray(sba, other)
checkBit(t, ba, 0, false)
checkBit(t, ba, 5, true)
checkBit(t, ba, 100, false)
}
func TestNandSparseWithEmptyDense(t *testing.T) {
sba := newSparseBitArray()
other := newBitArray(1000)
sba.SetBit(5)
ba := nandSparseWithDenseBitArray(sba, other)
checkBit(t, ba, 5, true)
sba.Reset()
other.SetBit(5)
ba = nandSparseWithDenseBitArray(sba, other)
checkBit(t, ba, 5, false)
}
func TestNandDenseWithEmptyDense(t *testing.T) {
dba := newBitArray(1000)
other := newBitArray(1000)
dba.SetBit(5)
ba := nandDenseWithDenseBitArray(dba, other)
checkBit(t, ba, 5, true)
dba.Reset()
other.SetBit(5)
ba = nandDenseWithDenseBitArray(dba, other)
checkBit(t, ba, 5, false)
}
func BenchmarkNandSparseWithSparse(b *testing.B) {
numItems := uint64(160000)
sba := newSparseBitArray()
other := newSparseBitArray()
for i := uint64(0); i < numItems; i += s {
if i%200 == 0 {
sba.SetBit(i)
} else if i%300 == 0 {
other.SetBit(i)
}
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
nandSparseWithSparseBitArray(sba, other)
}
}
func BenchmarkNandSparseWithDense(b *testing.B) {
numItems := uint64(160000)
sba := newSparseBitArray()
other := newBitArray(numItems)
for i := uint64(0); i < numItems; i += s {
if i%2 == 0 {
sba.SetBit(i)
} else if i%3 == 0 {
other.SetBit(i)
}
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
nandSparseWithDenseBitArray(sba, other)
}
}
func BenchmarkNandDenseWithSparse(b *testing.B) {
numItems := uint64(160000)
ba := newBitArray(numItems)
other := newSparseBitArray()
for i := uint64(0); i < numItems; i += s {
if i%2 == 0 {
ba.SetBit(i)
} else if i%3 == 0 {
other.SetBit(i)
}
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
nandDenseWithSparseBitArray(ba, other)
}
}
func BenchmarkNandDenseWithDense(b *testing.B) {
numItems := uint64(160000)
dba := newBitArray(numItems)
other := newBitArray(numItems)
for i := uint64(0); i < numItems; i += s {
if i%2 == 0 {
dba.SetBit(i)
} else if i%3 == 0 {
other.SetBit(i)
}
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
nandDenseWithDenseBitArray(dba, other)
}
}
================================================
FILE: bitarray/or.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package bitarray
func orSparseWithSparseBitArray(sba *sparseBitArray,
other *sparseBitArray) BitArray {
if len(other.indices) == 0 {
return sba.copy()
}
if len(sba.indices) == 0 {
return other.copy()
}
max := maxInt64(int64(len(sba.indices)), int64(len(other.indices)))
indices := make(uintSlice, 0, max)
blocks := make(blocks, 0, max)
selfIndex := 0
otherIndex := 0
for {
// last comparison was a real or, we are both exhausted now
if selfIndex == len(sba.indices) && otherIndex == len(other.indices) {
break
} else if selfIndex == len(sba.indices) {
indices = append(indices, other.indices[otherIndex:]...)
blocks = append(blocks, other.blocks[otherIndex:]...)
break
} else if otherIndex == len(other.indices) {
indices = append(indices, sba.indices[selfIndex:]...)
blocks = append(blocks, sba.blocks[selfIndex:]...)
break
}
selfValue := sba.indices[selfIndex]
otherValue := other.indices[otherIndex]
switch diff := int(otherValue) - int(selfValue); {
case diff > 0:
indices = append(indices, selfValue)
blocks = append(blocks, sba.blocks[selfIndex])
selfIndex++
case diff < 0:
indices = append(indices, otherValue)
blocks = append(blocks, other.blocks[otherIndex])
otherIndex++
default:
indices = append(indices, otherValue)
blocks = append(blocks, sba.blocks[selfIndex].or(other.blocks[otherIndex]))
selfIndex++
otherIndex++
}
}
return &sparseBitArray{
indices: indices,
blocks: blocks,
}
}
func orSparseWithDenseBitArray(sba *sparseBitArray, other *bitArray) BitArray {
if other.Capacity() == 0 || !other.anyset {
return sba.copy()
}
if sba.Capacity() == 0 {
return other.copy()
}
max := maxUint64(uint64(sba.Capacity()), uint64(other.Capacity()))
ba := newBitArray(max * s)
selfIndex := 0
otherIndex := 0
for {
if selfIndex == len(sba.indices) && otherIndex == len(other.blocks) {
break
} else if selfIndex == len(sba.indices) {
copy(ba.blocks[otherIndex:], other.blocks[otherIndex:])
break
} else if otherIndex == len(other.blocks) {
for i, value := range sba.indices[selfIndex:] {
ba.blocks[value] = sba.blocks[i+selfIndex]
}
break
}
selfValue := sba.indices[selfIndex]
if selfValue == uint64(otherIndex) {
ba.blocks[otherIndex] = sba.blocks[selfIndex].or(other.blocks[otherIndex])
selfIndex++
otherIndex++
continue
}
ba.blocks[otherIndex] = other.blocks[otherIndex]
otherIndex++
}
ba.setHighest()
ba.setLowest()
return ba
}
func orDenseWithDenseBitArray(dba *bitArray, other *bitArray) BitArray {
if dba.Capacity() == 0 || !dba.anyset {
return other.copy()
}
if other.Capacity() == 0 || !other.anyset {
return dba.copy()
}
max := maxUint64(uint64(len(dba.blocks)), uint64(len(other.blocks)))
ba := newBitArray(max * s)
for i := uint64(0); i < max; i++ {
if i == uint64(len(dba.blocks)) {
copy(ba.blocks[i:], other.blocks[i:])
break
}
if i == uint64(len(other.blocks)) {
copy(ba.blocks[i:], dba.blocks[i:])
break
}
ba.blocks[i] = dba.blocks[i].or(other.blocks[i])
}
ba.setLowest()
ba.setHighest()
return ba
}
================================================
FILE: bitarray/or_test.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package bitarray
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestOrSparseWithSparseBitArray(t *testing.T) {
sba := newSparseBitArray()
other := newSparseBitArray()
ctx := false
for i := uint64(0); i < 1000; i += s {
if ctx {
sba.SetBit(i)
} else {
other.SetBit(i)
}
ctx = !ctx
}
sba.SetBit(s - 1)
other.SetBit(s - 1)
result := orSparseWithSparseBitArray(sba, other)
for i := uint64(0); i < 1000; i += s {
ok, err := result.GetBit(i)
assert.Nil(t, err)
assert.True(t, ok)
}
ok, err := result.GetBit(s - 1)
assert.Nil(t, err)
assert.True(t, ok)
ok, err = result.GetBit(s - 2)
assert.Nil(t, err)
assert.False(t, ok)
other.SetBit(2000)
result = orSparseWithSparseBitArray(sba, other)
ok, err = result.GetBit(2000)
assert.Nil(t, err)
assert.True(t, ok)
sba.SetBit(2000)
result = orSparseWithSparseBitArray(sba, other)
ok, err = result.GetBit(2000)
assert.Nil(t, err)
assert.True(t, ok)
}
func BenchmarkOrSparseWithSparse(b *testing.B) {
numItems := uint64(160000)
sba := newSparseBitArray()
other := newSparseBitArray()
ctx := false
for i := uint64(0); i < numItems; i += s {
if ctx {
sba.SetBit(i)
} else {
other.SetBit(i)
}
ctx = !ctx
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
orSparseWithSparseBitArray(sba, other)
}
}
func TestOrSparseWithDenseBitArray(t *testing.T) {
sba := newSparseBitArray()
other := newBitArray(2000)
ctx := false
for i := uint64(0); i < 1000; i += s {
if ctx {
sba.SetBit(i)
} else {
other.SetBit(i)
}
ctx = !ctx
}
other.SetBit(1500)
other.SetBit(s - 1)
sba.SetBit(s - 1)
result := orSparseWithDenseBitArray(sba, other)
for i := uint64(0); i < 1000; i += s {
ok, err := result.GetBit(i)
assert.Nil(t, err)
assert.True(t, ok)
}
ok, err := result.GetBit(1500)
assert.Nil(t, err)
assert.True(t, ok)
ok, err = result.GetBit(s - 1)
assert.Nil(t, err)
assert.True(t, ok)
ok, err = result.GetBit(s - 2)
assert.Nil(t, err)
assert.False(t, ok)
sba.SetBit(2500)
result = orSparseWithDenseBitArray(sba, other)
ok, err = result.GetBit(2500)
assert.Nil(t, err)
assert.True(t, ok)
}
func BenchmarkOrSparseWithDense(b *testing.B) {
numItems := uint64(160000)
sba := newSparseBitArray()
other := newBitArray(numItems)
ctx := false
for i := uint64(0); i < numItems; i += s {
if ctx {
sba.SetBit(i)
} else {
other.SetBit(i)
}
ctx = !ctx
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
orSparseWithDenseBitArray(sba, other)
}
}
func TestOrDenseWithDenseBitArray(t *testing.T) {
dba := newBitArray(1000)
other := newBitArray(2000)
ctx := false
for i := uint64(0); i < 1000; i += s {
if ctx {
dba.SetBit(i)
} else {
other.SetBit(i)
}
ctx = !ctx
}
other.SetBit(1500)
other.SetBit(s - 1)
dba.SetBit(s - 1)
result := orDenseWithDenseBitArray(dba, other)
for i := uint64(0); i < 1000; i += s {
ok, err := result.GetBit(i)
assert.Nil(t, err)
assert.True(t, ok)
}
ok, err := result.GetBit(s - 1)
assert.Nil(t, err)
assert.True(t, ok)
ok, err = result.GetBit(1500)
assert.Nil(t, err)
assert.True(t, ok)
ok, err = result.GetBit(1700)
assert.Nil(t, err)
assert.False(t, ok)
}
func BenchmarkOrDenseWithDense(b *testing.B) {
numItems := uint64(160000)
dba := newBitArray(numItems)
other := newBitArray(numItems)
ctx := false
for i := uint64(0); i < numItems; i += s {
if ctx {
dba.SetBit(i)
} else {
other.SetBit(i)
}
ctx = !ctx
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
orDenseWithDenseBitArray(dba, other)
}
}
func TestOrSparseWithEmptySparse(t *testing.T) {
sba := newSparseBitArray()
other := newSparseBitArray()
sba.SetBit(5)
result := orSparseWithSparseBitArray(sba, other)
assert.Equal(t, sba, result)
sba.Reset()
other.SetBit(5)
result = orSparseWithSparseBitArray(sba, other)
assert.Equal(t, other, result)
}
func TestOrSparseWithEmptyDense(t *testing.T) {
sba := newSparseBitArray()
other := newBitArray(1000)
sba.SetBit(5)
result := orSparseWithDenseBitArray(sba, other)
assert.Equal(t, sba, result)
sba.Reset()
other.SetBit(5)
result = orSparseWithDenseBitArray(sba, other)
assert.Equal(t, other, result)
}
func TestOrDenseWithEmptyDense(t *testing.T) {
dba := newBitArray(1000)
other := newBitArray(1000)
dba.SetBit(5)
result := orDenseWithDenseBitArray(dba, other)
assert.Equal(t, dba, result)
dba.Reset()
other.SetBit(5)
result = orDenseWithDenseBitArray(dba, other)
assert.Equal(t, other, result)
}
================================================
FILE: bitarray/sparse_bitarray.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package bitarray
import (
"math/bits"
"sort"
)
// uintSlice is an alias for a slice of ints. Len, Swap, and Less
// are exported to fulfill an interface needed for the search
// function in the sort library.
type uintSlice []uint64
// Len returns the length of the slice.
func (u uintSlice) Len() int64 {
return int64(len(u))
}
// Swap swaps values in this slice at the positions given.
func (u uintSlice) Swap(i, j int64) {
u[i], u[j] = u[j], u[i]
}
// Less returns a bool indicating if the value at position i is
// less than position j.
func (u uintSlice) Less(i, j int64) bool {
return u[i] < u[j]
}
func (u uintSlice) search(x uint64) int64 {
return int64(sort.Search(len(u), func(i int) bool { return uint64(u[i]) >= x }))
}
func (u *uintSlice) insert(x uint64) (int64, bool) {
i := u.search(x)
if i == int64(len(*u)) {
*u = append(*u, x)
return i, true
}
if (*u)[i] == x {
return i, false
}
*u = append(*u, 0)
copy((*u)[i+1:], (*u)[i:])
(*u)[i] = x
return i, true
}
func (u *uintSlice) deleteAtIndex(i int64) {
copy((*u)[i:], (*u)[i+1:])
(*u)[len(*u)-1] = 0
*u = (*u)[:len(*u)-1]
}
func (u uintSlice) get(x uint64) int64 {
i := u.search(x)
if i == int64(len(u)) {
return -1
}
if u[i] == x {
return i
}
return -1
}
type blocks []block
func (b *blocks) insert(index int64) {
if index == int64(len(*b)) {
*b = append(*b, block(0))
return
}
*b = append(*b, block(0))
copy((*b)[index+1:], (*b)[index:])
(*b)[index] = block(0)
}
func (b *blocks) deleteAtIndex(i int64) {
copy((*b)[i:], (*b)[i+1:])
(*b)[len(*b)-1] = block(0)
*b = (*b)[:len(*b)-1]
}
type sparseBitArray struct {
blocks blocks
indices uintSlice
}
// SetBit sets the bit at the given position.
func (sba *sparseBitArray) SetBit(k uint64) error {
index, position := getIndexAndRemainder(k)
i, inserted := sba.indices.insert(index)
if inserted {
sba.blocks.insert(i)
}
sba.blocks[i] = sba.blocks[i].insert(position)
return nil
}
// GetBit gets the bit at the given position.
func (sba *sparseBitArray) GetBit(k uint64) (bool, error) {
index, position := getIndexAndRemainder(k)
i := sba.indices.get(index)
if i == -1 {
return false, nil
}
return sba.blocks[i].get(position), nil
}
// GetSetBits gets the position of bits set in the array.
func (sba *sparseBitArray) GetSetBits(from uint64, buffer []uint64) []uint64 {
fromBlockIndex, fromOffset := getIndexAndRemainder(from)
fromBlockLocation := sba.indices.search(fromBlockIndex)
if int(fromBlockLocation) == len(sba.indices) {
return buffer[:0]
}
return getSetBitsInBlocks(
fromBlockIndex,
fromOffset,
sba.blocks[fromBlockLocation:],
sba.indices[fromBlockLocation:],
buffer,
)
}
// ToNums converts this sparse bitarray to a list of numbers contained
// within it.
func (sba *sparseBitArray) ToNums() []uint64 {
if len(sba.indices) == 0 {
return nil
}
diff := uint64(len(sba.indices)) * s
nums := make([]uint64, 0, diff/4)
for i, offset := range sba.indices {
sba.blocks[i].toNums(offset*s, &nums)
}
return nums
}
// ClearBit clears the bit at the given position.
func (sba *sparseBitArray) ClearBit(k uint64) error {
index, position := getIndexAndRemainder(k)
i := sba.indices.get(index)
if i == -1 {
return nil
}
sba.blocks[i] = sba.blocks[i].remove(position)
if sba.blocks[i] == 0 {
sba.blocks.deleteAtIndex(i)
sba.indices.deleteAtIndex(i)
}
return nil
}
// Reset erases all values from this bitarray.
func (sba *sparseBitArray) Reset() {
sba.blocks = sba.blocks[:0]
sba.indices = sba.indices[:0]
}
// Blocks returns an iterator to iterator of this bitarray's blocks.
func (sba *sparseBitArray) Blocks() Iterator {
return newCompressedBitArrayIterator(sba)
}
// Capacity returns the value of the highest possible *seen* value
// in this sparse bitarray.
func (sba *sparseBitArray) Capacity() uint64 {
if len(sba.indices) == 0 {
return 0
}
return (sba.indices[len(sba.indices)-1] + 1) * s
}
// Equals returns a bool indicating if the provided bit array
// equals this bitarray.
func (sba *sparseBitArray) Equals(other BitArray) bool {
if other.Capacity() == 0 && sba.Capacity() > 0 {
return false
}
var selfIndex uint64
for iter := other.Blocks(); iter.Next(); {
otherIndex, otherBlock := iter.Value()
if len(sba.indices) == 0 {
if otherBlock > 0 {
return false
}
continue
}
if selfIndex >= uint64(len(sba.indices)) {
return false
}
if otherIndex < sba.indices[selfIndex] {
if otherBlock > 0 {
return false
}
continue
}
if otherIndex > sba.indices[selfIndex] {
return false
}
if !sba.blocks[selfIndex].equals(otherBlock) {
return false
}
selfIndex++
}
return true
}
// Count returns the number of set bits in this array.
func (sba *sparseBitArray) Count() int {
count := 0
for _, block := range sba.blocks {
count += bits.OnesCount64(uint64(block))
}
return count
}
// Or will perform a bitwise or operation with the provided bitarray and
// return a new result bitarray.
func (sba *sparseBitArray) Or(other BitArray) BitArray {
if ba, ok := other.(*sparseBitArray); ok {
return orSparseWithSparseBitArray(sba, ba)
}
return orSparseWithDenseBitArray(sba, other.(*bitArray))
}
// And will perform a bitwise and operation with the provided bitarray and
// return a new result bitarray.
func (sba *sparseBitArray) And(other BitArray) BitArray {
if ba, ok := other.(*sparseBitArray); ok {
return andSparseWithSparseBitArray(sba, ba)
}
return andSparseWithDenseBitArray(sba, other.(*bitArray))
}
// Nand will return the result of doing a bitwise and not of the bit array
// with the other bit array on each block.
func (sba *sparseBitArray) Nand(other BitArray) BitArray {
if ba, ok := other.(*sparseBitArray); ok {
return nandSparseWithSparseBitArray(sba, ba)
}
return nandSparseWithDenseBitArray(sba, other.(*bitArray))
}
func (sba *sparseBitArray) IsEmpty() bool {
// This works because the and, nand and delete functions only
// keep values that have a non-zero block.
return len(sba.indices) == 0
}
func (sba *sparseBitArray) copy() *sparseBitArray {
blocks := make(blocks, len(sba.blocks))
copy(blocks, sba.blocks)
indices := make(uintSlice, len(sba.indices))
copy(indices, sba.indices)
return &sparseBitArray{
blocks: blocks,
indices: indices,
}
}
// Intersects returns a bool indicating if the provided bit array
// intersects with this bitarray.
func (sba *sparseBitArray) Intersects(other BitArray) bool {
if other.Capacity() == 0 {
return true
}
var selfIndex int64
for iter := other.Blocks(); iter.Next(); {
otherI, otherBlock := iter.Value()
if len(sba.indices) == 0 {
if otherBlock > 0 {
return false
}
continue
}
// here we grab where the block should live in ourselves
i := uintSlice(sba.indices[selfIndex:]).search(otherI)
// this is a block we don't have, doesn't intersect
if i == int64(len(sba.indices)) {
return false
}
if sba.indices[i] != otherI {
return false
}
if !sba.blocks[i].intersects(otherBlock) {
return false
}
selfIndex = i
}
return true
}
func (sba *sparseBitArray) IntersectsBetween(other BitArray, start, stop uint64) bool {
return true
}
func newSparseBitArray() *sparseBitArray {
return &sparseBitArray{}
}
// NewSparseBitArray will create a bit array that consumes a great
// deal less memory at the expense of longer sets and gets.
func NewSparseBitArray() BitArray {
return newSparseBitArray()
}
================================================
FILE: bitarray/sparse_bitarray_test.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package bitarray
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGetCompressedBit(t *testing.T) {
ba := newSparseBitArray()
result, err := ba.GetBit(5)
assert.Nil(t, err)
assert.False(t, result)
}
func BenchmarkGetCompressedBit(b *testing.B) {
numItems := 1000
ba := newSparseBitArray()
for i := 0; i < numItems; i++ {
ba.SetBit(uint64(i))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
ba.GetBit(s)
}
}
func TestGetSetCompressedBit(t *testing.T) {
ba := newSparseBitArray()
ba.SetBit(5)
result, err := ba.GetBit(5)
assert.Nil(t, err)
assert.True(t, result)
result, err = ba.GetBit(7)
assert.Nil(t, err)
assert.False(t, result)
ba.SetBit(s * 2)
result, _ = ba.GetBit(s * 2)
assert.True(t, result)
result, _ = ba.GetBit(s*2 + 1)
assert.False(t, result)
}
func BenchmarkSetCompressedBit(b *testing.B) {
numItems := 1000
ba := newSparseBitArray()
b.ResetTimer()
for i := 0; i < b.N; i++ {
for j := 0; j < numItems; j++ {
ba.SetBit(uint64(j))
}
}
}
func TestGetSetCompressedBits(t *testing.T) {
ba := newSparseBitArray()
buf := make([]uint64, 0, 5)
require.NoError(t, ba.SetBit(1))
require.NoError(t, ba.SetBit(4))
require.NoError(t, ba.SetBit(8))
require.NoError(t, ba.SetBit(63))
require.NoError(t, ba.SetBit(64))
require.NoError(t, ba.SetBit(200))
require.NoError(t, ba.SetBit(1000))
assert.Equal(t, []uint64(nil), ba.GetSetBits(0, nil))
assert.Equal(t, []uint64{}, ba.GetSetBits(0, []uint64{}))
assert.Equal(t, []uint64{1, 4, 8, 63, 64}, ba.GetSetBits(0, buf))
assert.Equal(t, []uint64{63, 64, 200, 1000}, ba.GetSetBits(10, buf))
assert.Equal(t, []uint64{63, 64, 200, 1000}, ba.GetSetBits(63, buf))
assert.Equal(t, []uint64{200, 1000}, ba.GetSetBits(128, buf))
require.NoError(t, ba.ClearBit(4))
require.NoError(t, ba.ClearBit(64))
assert.Equal(t, []uint64{1, 8, 63, 200, 1000}, ba.GetSetBits(0, buf))
assert.Empty(t, ba.GetSetBits(1001, buf))
ba.Reset()
assert.Empty(t, ba.GetSetBits(0, buf))
}
func BenchmarkGetSetCompressedBits(b *testing.B) {
ba := newSparseBitArray()
for i := uint64(0); i < 168000; i++ {
if i%13 == 0 || i%5 == 0 {
require.NoError(b, ba.SetBit(i))
}
}
buf := make([]uint64, 0, ba.Capacity())
b.ResetTimer()
for i := 0; i < b.N; i++ {
ba.GetSetBits(0, buf)
}
}
func TestCompressedCount(t *testing.T) {
ba := newSparseBitArray()
assert.Equal(t, 0, ba.Count())
require.NoError(t, ba.SetBit(0))
assert.Equal(t, 1, ba.Count())
require.NoError(t, ba.SetBit(40))
require.NoError(t, ba.SetBit(64))
require.NoError(t, ba.SetBit(100))
require.NoError(t, ba.SetBit(200))
require.NoError(t, ba.SetBit(469))
require.NoError(t, ba.SetBit(500))
assert.Equal(t, 7, ba.Count())
require.NoError(t, ba.ClearBit(200))
assert.Equal(t, 6, ba.Count())
ba.Reset()
assert.Equal(t, 0, ba.Count())
}
func TestClearCompressedBit(t *testing.T) {
ba := newSparseBitArray()
ba.SetBit(5)
ba.ClearBit(5)
result, err := ba.GetBit(5)
assert.Nil(t, err)
assert.False(t, result)
assert.Len(t, ba.blocks, 0)
assert.Len(t, ba.indices, 0)
ba.SetBit(s * 2)
ba.ClearBit(s * 2)
result, _ = ba.GetBit(s * 2)
assert.False(t, result)
assert.Len(t, ba.indices, 0)
assert.Len(t, ba.blocks, 0)
}
func BenchmarkClearCompressedBit(b *testing.B) {
numItems := 1000
ba := newSparseBitArray()
for i := 0; i < numItems; i++ {
ba.SetBit(uint64(i))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
ba.ClearBit(uint64(i))
}
}
func TestClearCompressedBitArray(t *testing.T) {
ba := newSparseBitArray()
ba.SetBit(5)
ba.SetBit(s * 2)
result, err := ba.GetBit(5)
assert.Nil(t, err)
assert.True(t, result)
result, _ = ba.GetBit(s * 2)
assert.True(t, result)
ba.Reset()
result, err = ba.GetBit(5)
assert.Nil(t, err)
assert.False(t, result)
result, _ = ba.GetBit(s * 2)
assert.False(t, result)
}
func TestCompressedEquals(t *testing.T) {
ba := newSparseBitArray()
other := newSparseBitArray()
assert.True(t, ba.Equals(other))
ba.SetBit(5)
assert.False(t, ba.Equals(other))
other.SetBit(5)
assert.True(t, ba.Equals(other))
ba.ClearBit(5)
assert.False(t, ba.Equals(other))
}
func TestCompressedIntersects(t *testing.T) {
ba := newSparseBitArray()
other := newSparseBitArray()
assert.True(t, ba.Intersects(other))
other.SetBit(5)
assert.False(t, ba.Intersects(other))
assert.True(t, other.Intersects(ba))
ba.SetBit(5)
assert.True(t, ba.Intersects(other))
assert.True(t, other.Intersects(ba))
other.SetBit(10)
assert.False(t, ba.Intersects(other))
assert.True(t, other.Intersects(ba))
}
func TestLongCompressedIntersects(t *testing.T) {
ba := newSparseBitArray()
other := newSparseBitArray()
ba.SetBit(5)
other.SetBit(5)
assert.True(t, ba.Intersects(other))
other.SetBit(s * 2)
assert.False(t, ba.Intersects(other))
assert.True(t, other.Intersects(ba))
ba.SetBit(s * 2)
assert.True(t, ba.Intersects(other))
assert.True(t, other.Intersects(ba))
other.SetBit(s*2 + 1)
assert.False(t, ba.Intersects(other))
assert.True(t, other.Intersects(ba))
}
func BenchmarkCompressedIntersects(b *testing.B) {
numItems := uint64(1000)
ba := newSparseBitArray()
other := newSparseBitArray()
for i := uint64(0); i < numItems; i++ {
ba.SetBit(i)
other.SetBit(i)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
ba.Intersects(other)
}
}
func TestSparseIntersectsBitArray(t *testing.T) {
cba := newSparseBitArray()
ba := newBitArray(s * 2)
assert.True(t, cba.Intersects(ba))
ba.SetBit(5)
assert.False(t, cba.Intersects(ba))
cba.SetBit(5)
assert.True(t, cba.Intersects(ba))
cba.SetBit(10)
assert.True(t, cba.Intersects(ba))
ba.SetBit(s + 1)
assert.False(t, cba.Intersects(ba))
cba.SetBit(s + 1)
assert.True(t, cba.Intersects(ba))
cba.SetBit(s * 3)
assert.True(t, cba.Intersects(ba))
}
func TestSparseEqualsBitArray(t *testing.T) {
cba := newSparseBitArray()
ba := newBitArray(s * 2)
assert.True(t, cba.Equals(ba))
ba.SetBit(5)
assert.False(t, cba.Equals(ba))
cba.SetBit(5)
assert.True(t, cba.Equals(ba))
ba.SetBit(s + 1)
assert.False(t, cba.Equals(ba))
cba.SetBit(s + 1)
assert.True(t, cba.Equals(ba))
}
func BenchmarkCompressedEquals(b *testing.B) {
numItems := uint64(1000)
cba := newSparseBitArray()
other := newSparseBitArray()
for i := uint64(0); i < numItems; i++ {
cba.SetBit(i)
other.SetBit(i)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
cba.Equals(other)
}
}
func TestInsertPreviousBlockInSparse(t *testing.T) {
sba := newSparseBitArray()
sba.SetBit(s * 2)
sba.SetBit(s - 1)
result, err := sba.GetBit(s - 1)
assert.Nil(t, err)
assert.True(t, result)
}
func TestSparseBitArrayToNums(t *testing.T) {
sba := newSparseBitArray()
sba.SetBit(s - 1)
sba.SetBit(s + 1)
expected := []uint64{s - 1, s + 1}
results := sba.ToNums()
assert.Equal(t, expected, results)
}
func BenchmarkSparseBitArrayToNums(b *testing.B) {
numItems := uint64(1000)
sba := newSparseBitArray()
for i := uint64(0); i < numItems; i++ {
sba.SetBit(i)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
sba.ToNums()
}
}
================================================
FILE: bitarray/util.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package bitarray
// maxInt64 returns the highest integer in the provided list of int64s
func maxInt64(ints ...int64) int64 {
maxInt := ints[0]
for i := 1; i < len(ints); i++ {
if ints[i] > maxInt {
maxInt = ints[i]
}
}
return maxInt
}
// maxUint64 returns the highest integer in the provided list of uint64s
func maxUint64(ints ...uint64) uint64 {
maxInt := ints[0]
for i := 1; i < len(ints); i++ {
if ints[i] > maxInt {
maxInt = ints[i]
}
}
return maxInt
}
// minUint64 returns the lowest integer in the provided list of int32s
func minUint64(ints ...uint64) uint64 {
minInt := ints[0]
for i := 1; i < len(ints); i++ {
if ints[i] < minInt {
minInt = ints[i]
}
}
return minInt
}
================================================
FILE: btree/_link/interface.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package link
// Keys is a typed list of Key interfaces.
type Keys []Key
type Key interface {
// Compare should return an int indicating how this key relates
// to the provided key. -1 will indicate less than, 0 will indicate
// equality, and 1 will indicate greater than. Duplicate keys
// are allowed, but duplicate IDs are not.
Compare(Key) int
}
================================================
FILE: btree/_link/key.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package link
import "sort"
func (keys Keys) search(key Key) int {
return sort.Search(len(keys), func(i int) bool {
return keys[i].Compare(key) >= 0
})
}
func (keys *Keys) insert(key Key) Key {
i := keys.search(key)
return keys.insertAt(key, i)
}
func (keys *Keys) insertAt(key Key, i int) Key {
if i == len(*keys) {
*keys = append(*keys, key)
return nil
}
if (*keys)[i].Compare(key) == 0 { //overwrite case
oldKey := (*keys)[i]
(*keys)[i] = key
return oldKey
}
*keys = append(*keys, nil)
copy((*keys)[i+1:], (*keys)[i:])
(*keys)[i] = key
return nil
}
func (keys *Keys) split() (Key, Keys, Keys) {
i := (len(*keys) / 2) - 1
middle := (*keys)[i]
left, right := keys.splitAt(i)
return middle, left, right
}
func (keys *Keys) splitAt(i int) (Keys, Keys) {
right := make(Keys, len(*keys)-i-1, cap(*keys))
copy(right, (*keys)[i+1:])
for j := i + 1; j < len(*keys); j++ {
(*keys)[j] = nil
}
*keys = (*keys)[:i+1]
return *keys, right
}
func (keys Keys) last() Key {
return keys[len(keys)-1]
}
func (keys Keys) first() Key {
return keys[0]
}
func (keys Keys) needsSplit() bool {
return cap(keys) == len(keys)
}
func (keys Keys) reverse() Keys {
reversed := make(Keys, len(keys))
for i := len(keys) - 1; i >= 0; i-- {
reversed[len(keys)-1-i] = keys[i]
}
return reversed
}
func chunkKeys(keys Keys, numParts int64) []Keys {
parts := make([]Keys, numParts)
for i := int64(0); i < numParts; i++ {
parts[i] = keys[i*int64(len(keys))/numParts : (i+1)*int64(len(keys))/numParts]
}
return parts
}
================================================
FILE: btree/_link/mock_test.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package link
type mockKey uint64
func (mk mockKey) Compare(other Key) int {
otherK := other.(mockKey)
if mk < otherK {
return -1
}
if mk > otherK {
return 1
}
return 0
}
================================================
FILE: btree/_link/node.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package link
import (
"log"
"sync"
)
func search(parent *node, key Key) Key {
parent = getParent(parent, nil, key)
parent.lock.RLock()
parent = moveRight(parent, key, false)
defer parent.lock.RUnlock()
i := parent.search(key)
if i == len(parent.keys) {
return nil
}
return parent.keys[i]
}
func getParent(parent *node, stack *nodes, key Key) *node {
var n *node
for parent != nil && !parent.isLeaf {
parent.lock.RLock()
parent = moveRight(parent, key, false) // if this happens on the root this should always just return
n = parent.searchNode(key)
if stack != nil {
stack.push(parent)
}
parent.lock.RUnlock()
parent = n
}
return parent
}
func insert(tree *blink, parent *node, stack *nodes, key Key) Key {
parent = getParent(parent, stack, key)
parent.lock.Lock()
parent = moveRight(parent, key, true)
result := parent.insert(key)
if result != nil { // overwrite
parent.lock.Unlock()
return result
}
if !parent.needsSplit() {
parent.lock.Unlock()
return nil
}
split(tree, parent, stack)
return nil
}
func split(tree *blink, n *node, stack *nodes) {
var l, r *node
var k Key
var parent *node
for n.needsSplit() {
k, l, r = n.split()
parent = stack.pop()
if parent == nil {
tree.lock.Lock()
if tree.root == nil || tree.root == n {
parent = newNode(false, make(Keys, 0, tree.ary), make(nodes, 0, tree.ary+1))
parent.maxSeen = r.max()
parent.keys.insert(k)
parent.nodes.push(l)
parent.nodes.push(r)
tree.root = parent
n.lock.Unlock()
tree.lock.Unlock()
return
}
parent = tree.root
tree.lock.Unlock()
}
parent.lock.Lock()
parent = moveRight(parent, r.key(), true)
i := parent.search(k)
parent.keys.insertAt(k, i)
parent.nodes[i] = l
parent.nodes.insertAt(r, i+1)
n.lock.Unlock()
n = parent
}
n.lock.Unlock()
}
func moveRight(n *node, key Key, getLock bool) *node {
var right *node
for {
if len(n.keys) == 0 || n.right == nil { // this is either the node or the rightmost node
return n
}
if key.Compare(n.max()) < 1 {
return n
}
if getLock {
n.right.lock.Lock()
right = n.right
n.lock.Unlock()
} else {
n.right.lock.RLock()
right = n.right
n.lock.RUnlock()
}
n = right
}
}
type nodes []*node
func (ns *nodes) reset() {
for i := range *ns {
(*ns)[i] = nil
}
*ns = (*ns)[:0]
}
func (ns *nodes) push(n *node) {
*ns = append(*ns, n)
}
func (ns *nodes) pop() *node {
if len(*ns) == 0 {
return nil
}
n := (*ns)[len(*ns)-1]
(*ns)[len(*ns)-1] = nil
*ns = (*ns)[:len(*ns)-1]
return n
}
func (ns *nodes) insertAt(n *node, i int) {
if i == len(*ns) {
*ns = append(*ns, n)
return
}
*ns = append(*ns, nil)
copy((*ns)[i+1:], (*ns)[i:])
(*ns)[i] = n
}
func (ns *nodes) splitAt(i int) (nodes, nodes) {
length := len(*ns) - i
right := make(nodes, length, cap(*ns))
copy(right, (*ns)[i+1:])
for j := i + 1; j < len(*ns); j++ {
(*ns)[j] = nil
}
*ns = (*ns)[:i+1]
return *ns, right
}
type node struct {
keys Keys
nodes nodes
right *node
lock sync.RWMutex
isLeaf bool
maxSeen Key
}
func (n *node) key() Key {
return n.keys.last()
}
func (n *node) insert(key Key) Key {
if !n.isLeaf {
panic(`Can't only insert key in an internal node.`)
}
overwritten := n.keys.insert(key)
return overwritten
}
func (n *node) insertNode(other *node) {
key := other.key()
i := n.keys.search(key)
n.keys.insertAt(key, i)
n.nodes.insertAt(other, i)
}
func (n *node) needsSplit() bool {
return n.keys.needsSplit()
}
func (n *node) max() Key {
if n.isLeaf {
return n.keys.last()
}
return n.maxSeen
}
func (n *node) splitLeaf() (Key, *node, *node) {
i := (len(n.keys) / 2)
key := n.keys[i]
_, rightKeys := n.keys.splitAt(i)
nn := &node{
keys: rightKeys,
right: n.right,
isLeaf: true,
}
n.right = nn
return key, n, nn
}
func (n *node) splitInternal() (Key, *node, *node) {
i := (len(n.keys) / 2)
key := n.keys[i]
rightKeys := make(Keys, len(n.keys)-1-i, cap(n.keys))
rightNodes := make(nodes, len(rightKeys)+1, cap(n.nodes))
copy(rightKeys, n.keys[i+1:])
copy(rightNodes, n.nodes[i+1:])
// for garbage collection
for j := i + 1; j < len(n.nodes); j++ {
if j != len(n.keys) {
n.keys[j] = nil
}
n.nodes[j] = nil
}
nn := newNode(false, rightKeys, rightNodes)
nn.maxSeen = n.max()
n.maxSeen = key
n.keys = n.keys[:i]
n.nodes = n.nodes[:i+1]
n.right = nn
return key, n, nn
}
func (n *node) split() (Key, *node, *node) {
if n.isLeaf {
return n.splitLeaf()
}
return n.splitInternal()
}
func (n *node) search(key Key) int {
return n.keys.search(key)
}
func (n *node) searchNode(key Key) *node {
i := n.search(key)
return n.nodes[i]
}
func (n *node) print(output *log.Logger) {
output.Printf(`NODE: %+v, %p`, n, n)
if !n.isLeaf {
for _, n := range n.nodes {
if n == nil {
output.Println(`NIL NODE`)
continue
}
n.print(output)
}
}
}
func newNode(isLeaf bool, keys Keys, ns nodes) *node {
return &node{
isLeaf: isLeaf,
keys: keys,
nodes: ns,
}
}
================================================
FILE: btree/_link/node_test.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package link
import (
"testing"
"github.com/stretchr/testify/assert"
)
func newTestNode(isLeaf bool, ary int) *node {
return &node{
isLeaf: isLeaf,
keys: make(Keys, 0, ary),
nodes: make(nodes, 0, ary+1),
}
}
func checkTree(t testing.TB, tree *blink) bool {
if tree.root == nil {
return true
}
return checkNode(t, tree.root)
}
func checkNode(t testing.TB, n *node) bool {
if len(n.keys) == 0 {
assert.Len(t, n.nodes, 0)
return false
}
if n.isLeaf {
assert.Len(t, n.nodes, 0)
return false
}
if !assert.Len(t, n.nodes, len(n.keys)+1) {
return false
}
for i := 0; i < len(n.keys); i++ {
if !assert.True(t, n.keys[i].Compare(n.nodes[i].key()) >= 0) {
t.Logf(`N: %+v %p, n.keys[i]: %+v, n.nodes[i]: %+v`, n, n, n.keys[i], n.nodes[i])
return false
}
}
if !assert.True(t, n.nodes[len(n.nodes)-1].key().Compare(n.keys.last()) > 0) {
t.Logf(`m: %+v, %p, n.nodes[len(n.nodes)-1].key(): %+v, n.keys.last(): %+v`, n, n, n.nodes[len(n.nodes)-1].key(), n.keys.last())
return false
}
for _, child := range n.nodes {
if !assert.NotNil(t, child) {
return false
}
if !checkNode(t, child) {
return false
}
}
return true
}
func TestSplitInternalNodeOddAry(t *testing.T) {
parent := newTestNode(false, 3)
n1 := newTestNode(true, 3)
n1.keys.insert(mockKey(1))
n2 := newTestNode(true, 3)
n2.keys.insert(mockKey(5))
n3 := newTestNode(true, 3)
n3.keys.insert(mockKey(10))
n4 := newTestNode(true, 3)
n4.keys.insert(mockKey(15))
parent.nodes = nodes{n1, n2, n3, n4}
parent.keys = Keys{mockKey(5), mockKey(10), mockKey(15)}
key, l, r := parent.split()
assert.Equal(t, mockKey(10), key)
assert.Equal(t, Keys{mockKey(5)}, l.keys)
assert.Equal(t, Keys{mockKey(15)}, r.keys)
assert.Equal(t, nodes{n1, n2}, l.nodes)
assert.Equal(t, nodes{n3, n4}, r.nodes)
assert.Equal(t, l.right, r)
assert.False(t, l.isLeaf)
assert.False(t, r.isLeaf)
}
func TestSplitInternalNodeEvenAry(t *testing.T) {
parent := newTestNode(false, 4)
n1 := newTestNode(true, 4)
n1.keys.insert(mockKey(1))
n2 := newTestNode(true, 4)
n2.keys.insert(mockKey(5))
n3 := newTestNode(true, 4)
n3.keys.insert(mockKey(10))
n4 := newTestNode(true, 4)
n4.keys.insert(mockKey(15))
n5 := newTestNode(true, 4)
n5.keys.insert(mockKey(20))
parent.nodes = nodes{n1, n2, n3, n4, n5}
parent.keys = Keys{mockKey(5), mockKey(10), mockKey(15), mockKey(20)}
key, l, r := parent.split()
assert.Equal(t, mockKey(15), key)
assert.Equal(t, Keys{mockKey(5), mockKey(10)}, l.keys)
assert.Equal(t, Keys{mockKey(20)}, r.keys)
assert.Equal(t, nodes{n1, n2, n3}, l.nodes)
assert.Equal(t, nodes{n4, n5}, r.nodes)
assert.Equal(t, l.right, r)
assert.False(t, l.isLeaf)
assert.False(t, r.isLeaf)
}
func TestSplitLeafNodeOddAry(t *testing.T) {
parent := newTestNode(true, 3)
k1 := mockKey(5)
k2 := mockKey(15)
k3 := mockKey(20)
parent.keys = Keys{k1, k2, k3}
key, l, r := parent.split()
assert.Equal(t, k2, key)
assert.Equal(t, Keys{k1, k2}, l.keys)
assert.Equal(t, Keys{k3}, r.keys)
assert.True(t, l.isLeaf)
assert.True(t, r.isLeaf)
assert.Equal(t, r, l.right)
}
func TestSplitLeafNodeEvenAry(t *testing.T) {
parent := newTestNode(true, 4)
k1 := mockKey(5)
k2 := mockKey(15)
k3 := mockKey(20)
k4 := mockKey(25)
parent.keys = Keys{k1, k2, k3, k4}
key, l, r := parent.split()
assert.Equal(t, k3, key)
assert.Equal(t, Keys{k1, k2, k3}, l.keys)
assert.Equal(t, Keys{k4}, r.keys)
assert.True(t, l.isLeaf)
assert.True(t, r.isLeaf)
assert.Equal(t, r, l.right)
}
================================================
FILE: btree/_link/tree.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
This is a b-link tree in progress from the following paper:
http://www.csd.uoc.gr/~hy460/pdf/p650-lehman.pdf
This is still a work in progress and the CRUD methods on the tree
need to be parallelized. Until this is complete, there is no
constructor method for this package.
Time complexities:
Space: O(n)
Search: O(log n)
Insert: O(log n)
Delete: O(log n)
Current benchmarks with 16 ary:
BenchmarkSimpleAdd-8 1000000 1455 ns/op
BenchmarkGet-8 2000000 704 ns/op
B-link was chosen after examining this paper:
http://www.vldb.org/journal/VLDBJ2/P361.pdf
*/
package link
import (
"log"
"sync"
"sync/atomic"
)
// numberOfItemsBeforeMultithread defines the number of items that have
// to be called with a method before we multithread.
const numberOfItemsBeforeMultithread = 10
type blink struct {
root *node
lock sync.RWMutex
number, ary, numRoutines uint64
}
func (blink *blink) insert(key Key, stack *nodes) Key {
var parent *node
blink.lock.Lock()
if blink.root == nil {
blink.root = newNode(
true, make(Keys, 0, blink.ary), make(nodes, 0, blink.ary+1),
)
blink.root.keys = make(Keys, 0, blink.ary)
blink.root.isLeaf = true
}
parent = blink.root
blink.lock.Unlock()
result := insert(blink, parent, stack, key)
if result == nil {
atomic.AddUint64(&blink.number, 1)
return nil
}
return result
}
func (blink *blink) multithreadedInsert(keys Keys) Keys {
chunks := chunkKeys(keys, int64(blink.numRoutines))
overwritten := make(Keys, len(keys))
var offset uint64
var wg sync.WaitGroup
wg.Add(len(chunks))
for _, chunk := range chunks {
go func(chunk Keys, offset uint64) {
defer wg.Done()
stack := make(nodes, 0, blink.ary)
for i := 0; i < len(chunk); i++ {
result := blink.insert(chunk[i], &stack)
stack.reset()
overwritten[offset+uint64(i)] = result
}
}(chunk, offset)
offset += uint64(len(chunk))
}
wg.Wait()
return overwritten
}
// Insert will insert the provided keys into the b-tree and return
// a list of keys overwritten, if any. Each insert is an O(log n)
// operation.
func (blink *blink) Insert(keys ...Key) Keys {
if len(keys) > numberOfItemsBeforeMultithread {
return blink.multithreadedInsert(keys)
}
overwritten := make(Keys, 0, len(keys))
stack := make(nodes, 0, blink.ary)
for _, k := range keys {
overwritten = append(overwritten, blink.insert(k, &stack))
stack.reset()
}
return overwritten
}
// Len returns the number of items in this b-link tree.
func (blink *blink) Len() uint64 {
return atomic.LoadUint64(&blink.number)
}
func (blink *blink) get(key Key) Key {
var parent *node
blink.lock.RLock()
parent = blink.root
blink.lock.RUnlock()
k := search(parent, key)
if k == nil {
return nil
}
if k.Compare(key) == 0 {
return k
}
return nil
}
// Get will retrieve the keys if they exist in this tree. If not,
// a nil is returned in the proper place in the list of keys. Each
// lookup is O(log n) time complexity.
func (blink *blink) Get(keys ...Key) Keys {
found := make(Keys, 0, len(keys))
for _, k := range keys {
found = append(found, blink.get(k))
}
return found
}
func (blink *blink) print(output *log.Logger) {
output.Println(`PRINTING B-LINK`)
if blink.root == nil {
return
}
blink.root.print(output)
}
func newTree(ary, numRoutines uint64) *blink {
return &blink{ary: ary, numRoutines: numRoutines}
}
================================================
FILE: btree/_link/tree_test.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package link
import (
"log"
"math/rand"
"os"
"testing"
"github.com/stretchr/testify/assert"
)
func getConsoleLogger() *log.Logger {
return log.New(os.Stderr, "", log.LstdFlags)
}
func generateRandomKeys(num int) Keys {
keys := make(Keys, 0, num)
for i := 0; i < num; i++ {
keys = append(keys, mockKey(uint64(rand.Uint32()%uint32(100))))
}
return keys
}
func generateKeys(num int) Keys {
keys := make(Keys, 0, num)
for i := 0; i < num; i++ {
keys = append(keys, mockKey(uint64(i)))
}
return keys
}
func TestSimpleInsert(t *testing.T) {
k1 := mockKey(5)
tree := newTree(8, 1)
result := tree.Insert(k1)
assert.Equal(t, Keys{nil}, result)
assert.Equal(t, uint64(1), tree.Len())
if !assert.Equal(t, Keys{k1}, tree.Get(k1)) {
tree.print(getConsoleLogger())
}
}
func TestMultipleInsert(t *testing.T) {
k1 := mockKey(10)
k2 := mockKey(5)
tree := newTree(8, 1)
result := tree.Insert(k1, k2)
assert.Equal(t, Keys{nil, nil}, result)
assert.Equal(t, uint64(2), tree.Len())
assert.Equal(t, Keys{k1, k2}, tree.Get(k1, k2))
checkTree(t, tree)
}
func TestMultipleInsertCausesSplitOddAryReverseOrder(t *testing.T) {
k1, k2, k3 := mockKey(15), mockKey(10), mockKey(5)
tree := newTree(3, 1)
result := tree.Insert(k1, k2, k3)
assert.Equal(t, Keys{nil, nil, nil}, result)
assert.Equal(t, uint64(3), tree.Len())
if !assert.Equal(t, Keys{k1, k2, k3}, tree.Get(k1, k2, k3)) {
tree.print(getConsoleLogger())
}
checkTree(t, tree)
}
func TestMultipleInsertCausesSplitOddAry(t *testing.T) {
k1, k2, k3 := mockKey(5), mockKey(10), mockKey(15)
tree := newTree(3, 1)
result := tree.Insert(k1, k2, k3)
assert.Equal(t, Keys{nil, nil, nil}, result)
assert.Equal(t, uint64(3), tree.Len())
if !assert.Equal(t, Keys{k1, k2, k3}, tree.Get(k1, k2, k3)) {
tree.print(getConsoleLogger())
}
checkTree(t, tree)
}
func TestMultipleInsertCausesSplitOddAryRandomOrder(t *testing.T) {
k1, k2, k3 := mockKey(10), mockKey(5), mockKey(15)
tree := newTree(3, 1)
result := tree.Insert(k1, k2, k3)
assert.Equal(t, Keys{nil, nil, nil}, result)
assert.Equal(t, uint64(3), tree.Len())
if !assert.Equal(t, Keys{k1, k2, k3}, tree.Get(k1, k2, k3)) {
tree.print(getConsoleLogger())
}
checkTree(t, tree)
}
func TestMultipleInsertCausesSplitEvenAryReverseOrder(t *testing.T) {
k1, k2, k3, k4 := mockKey(20), mockKey(15), mockKey(10), mockKey(5)
tree := newTree(4, 1)
result := tree.Insert(k1, k2, k3, k4)
assert.Equal(t, Keys{nil, nil, nil, nil}, result)
assert.Equal(t, uint64(4), tree.Len())
if !assert.Equal(t, Keys{k1, k2, k3, k4}, tree.Get(k1, k2, k3, k4)) {
tree.print(getConsoleLogger())
}
checkTree(t, tree)
}
func TestMultipleInsertCausesSplitEvenAry(t *testing.T) {
k1, k2, k3, k4 := mockKey(5), mockKey(10), mockKey(15), mockKey(20)
tree := newTree(4, 1)
result := tree.Insert(k1, k2, k3, k4)
assert.Equal(t, Keys{nil, nil, nil, nil}, result)
assert.Equal(t, uint64(4), tree.Len())
if !assert.Equal(t, Keys{k1, k2, k3, k4}, tree.Get(k1, k2, k3, k4)) {
tree.print(getConsoleLogger())
}
checkTree(t, tree)
}
func TestMultipleInsertCausesSplitEvenAryRandomOrder(t *testing.T) {
k1, k2, k3, k4 := mockKey(10), mockKey(15), mockKey(20), mockKey(5)
tree := newTree(4, 1)
result := tree.Insert(k1, k2, k3, k4)
assert.Equal(t, Keys{nil, nil, nil, nil}, result)
assert.Equal(t, uint64(4), tree.Len())
if !assert.Equal(t, Keys{k1, k2, k3, k4}, tree.Get(k1, k2, k3, k4)) {
tree.print(getConsoleLogger())
}
checkTree(t, tree)
}
func TestMultipleInsertCausesSplitEvenAryMultiThreaded(t *testing.T) {
keys := generateRandomKeys(16)
tree := newTree(16, 8)
result := tree.Insert(keys...)
assert.Len(t, result, len(keys))
if !assert.Equal(t, keys, tree.Get(keys...)) {
tree.print(getConsoleLogger())
}
checkTree(t, tree)
}
func TestMultipleInsertCausesCascadingSplitsOddAry(t *testing.T) {
keys := generateRandomKeys(1600)
tree := newTree(9, 8)
result := tree.Insert(keys...)
assert.Len(t, result, len(keys)) // about all we can assert, random may produce duplicates
checkTree(t, tree)
if !assert.Equal(t, keys, tree.Get(keys...)) {
tree.print(getConsoleLogger())
}
checkTree(t, tree)
}
func TestMultipleInsertCausesCascadingSplitsOddAryReverseOrder(t *testing.T) {
keys := generateKeys(30000)
tree := newTree(17, 8)
reversed := keys.reverse()
result := tree.Insert(reversed...)
assert.Len(t, result, len(keys)) // about all we can assert, random may produce duplicates
if !assert.Equal(t, keys, tree.Get(keys...)) {
//tree.print(getConsoleLogger())
}
checkTree(t, tree)
}
func TestMultipleInsertCausesCascadingSplitsEvenAry(t *testing.T) {
keys := generateRandomKeys(200)
tree := newTree(12, 8)
result := tree.Insert(keys...)
assert.Len(t, result, len(keys)) // about all we can assert, random may produce duplicates
if !assert.Equal(t, keys, tree.Get(keys...)) {
tree.print(getConsoleLogger())
}
}
func TestOverwriteOddAry(t *testing.T) {
keys := generateRandomKeys(15)
tree := newTree(3, 8)
duplicate := mockKey(uint64(keys[0].(mockKey)))
result := tree.Insert(keys...)
assert.Len(t, result, len(keys))
oldLength := tree.Len()
result = tree.Insert(duplicate)
assert.Equal(t, Keys{keys[0]}, result)
assert.Equal(t, oldLength, tree.Len())
}
func TestOverwriteEvenAry(t *testing.T) {
keys := generateRandomKeys(15)
tree := newTree(12, 8)
duplicate := mockKey(uint64(keys[0].(mockKey)))
result := tree.Insert(keys...)
assert.Len(t, result, len(keys))
oldLength := tree.Len()
result = tree.Insert(duplicate)
assert.Equal(t, Keys{keys[0]}, result)
assert.Equal(t, oldLength, tree.Len())
}
func BenchmarkSimpleAdd(b *testing.B) {
numItems := 1000
keys := generateRandomKeys(numItems)
tree := newTree(16, 8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
tree.Insert(keys[i%numItems])
}
}
func BenchmarkGet(b *testing.B) {
numItems := 1000
keys := generateRandomKeys(numItems)
tree := newTree(16, 4)
tree.Insert(keys...)
b.ResetTimer()
for i := 0; i < b.N; i++ {
tree.Get(keys[i%numItems])
}
}
func BenchmarkBulkAdd(b *testing.B) {
numItems := b.N
keys := generateRandomKeys(numItems)
b.ResetTimer()
for i := 0; i < b.N; i++ {
tree := newTree(64, 1)
tree.Insert(keys...)
}
}
================================================
FILE: btree/immutable/add.go
================================================
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package btree
import (
"runtime"
"sort"
"sync"
terr "github.com/Workiva/go-datastructures/threadsafe/err"
)
func (t *Tr) AddItems(its ...*Item) ([]*Item, error) {
if len(its) == 0 {
return nil, nil
}
keys := make(Keys, 0, len(its))
for _, item := range its {
keys = append(keys, &Key{Value: item.Value, Payload: item.Payload})
}
overwrittens, err := t.add(keys)
if err != nil {
return nil, err
}
return overwrittens.toItems(), nil
}
func (t *Tr) add(keys Keys) (Keys, error) {
if t.Root == nil {
n := t.createRoot()
t.Root = n.ID
t.context.addNode(n)
}
nodes, err := t.determinePaths(keys)
if err != nil {
return nil, err
}
var overwrittens Keys
var wg sync.WaitGroup
wg.Add(len(nodes))
var treeLock sync.Mutex
localOverwrittens := make([]Keys, len(nodes))
tree := make(map[string]*path, runtime.NumCPU())
lerr := terr.New()
i := 0
for id, bundles := range nodes {
go func(i int, id string, bundles []*nodeBundle) {
defer wg.Done()
if len(bundles) == 0 {
return
}
n, err := t.contextOrCachedNode(ID(id), true)
if err != nil {
lerr.Set(err)
return
}
if !t.context.nodeExists(n.ID) {
n = n.copy()
t.context.addNode(n)
}
overwrittens, err := insertLastDimension(t, n, bundles)
if err != nil {
lerr.Set(err)
return
}
localOverwrittens[i] = overwrittens
path := bundles[0].path
treeLock.Lock()
tree[string(n.ID)] = path
treeLock.Unlock()
}(i, id, bundles)
i++
}
wg.Wait()
if lerr.Get() != nil {
return nil, lerr.Get()
}
t.walkupInsert(tree)
for _, chunk := range localOverwrittens {
overwrittens = append(overwrittens, chunk...)
}
t.Count += len(keys) - len(overwrittens)
return overwrittens, nil
}
func (t *Tr) determinePaths(keys Keys) (map[string][]*nodeBundle, error) {
chunks := splitKeys(keys, runtime.NumCPU())
var wg sync.WaitGroup
wg.Add(len(chunks))
chunkPaths := make([]map[interface{}]*nodeBundle, len(chunks))
lerr := terr.New()
for i := range chunks {
go func(i int) {
defer wg.Done()
keys := chunks[i]
if len(keys) == 0 {
return
}
mp := make(map[interface{}]*nodeBundle, len(keys))
for _, key := range keys {
path, err := t.iterativeFind(
key.Value, t.Root,
)
if err != nil {
lerr.Set(err)
return
}
mp[key.Value] = &nodeBundle{path: path, k: key}
}
chunkPaths[i] = mp
}(i)
}
wg.Wait()
if lerr.Get() != nil {
return nil, lerr.Get()
}
nodes := make(map[string][]*nodeBundle, 10)
for _, chunk := range chunkPaths {
for _, pb := range chu
gitextract_a5x2r3bc/
├── .github/
│ ├── CODEOWNERS
│ └── workflows/
│ └── tests.yaml
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── augmentedtree/
│ ├── atree.go
│ ├── atree_test.go
│ ├── interface.go
│ ├── intervals.go
│ ├── intervals_test.go
│ ├── mock_test.go
│ └── multidimensional_test.go
├── aviary.yaml
├── batcher/
│ ├── batcher.go
│ └── batcher_test.go
├── bitarray/
│ ├── and.go
│ ├── and_test.go
│ ├── bitarray.go
│ ├── bitarray_test.go
│ ├── bitmap.go
│ ├── bitmap_test.go
│ ├── block.go
│ ├── block_test.go
│ ├── encoding.go
│ ├── encoding_test.go
│ ├── error.go
│ ├── interface.go
│ ├── iterator.go
│ ├── nand.go
│ ├── nand_test.go
│ ├── or.go
│ ├── or_test.go
│ ├── sparse_bitarray.go
│ ├── sparse_bitarray_test.go
│ └── util.go
├── btree/
│ ├── _link/
│ │ ├── interface.go
│ │ ├── key.go
│ │ ├── mock_test.go
│ │ ├── node.go
│ │ ├── node_test.go
│ │ ├── tree.go
│ │ └── tree_test.go
│ ├── immutable/
│ │ ├── add.go
│ │ ├── cacher.go
│ │ ├── config.go
│ │ ├── delete.go
│ │ ├── error.go
│ │ ├── interface.go
│ │ ├── item.go
│ │ ├── node.go
│ │ ├── node_gen.go
│ │ ├── path.go
│ │ ├── query.go
│ │ ├── rt.go
│ │ ├── rt_gen.go
│ │ └── rt_test.go
│ ├── palm/
│ │ ├── action.go
│ │ ├── interface.go
│ │ ├── key.go
│ │ ├── mock_test.go
│ │ ├── node.go
│ │ ├── tree.go
│ │ └── tree_test.go
│ └── plus/
│ ├── btree.go
│ ├── btree_test.go
│ ├── interface.go
│ ├── iterator.go
│ ├── mock_test.go
│ ├── node.go
│ └── node_test.go
├── cache/
│ ├── cache.go
│ └── cache_test.go
├── common/
│ └── interface.go
├── datastructures.go
├── documentation.md
├── fibheap/
│ ├── Test Generator/
│ │ ├── EnqDecrKey.py
│ │ ├── EnqDelete.py
│ │ ├── EnqDeqMin.py
│ │ ├── Merge.py
│ │ └── README.md
│ ├── benchmarks.txt
│ ├── fibheap.go
│ ├── fibheap_examples_test.go
│ ├── fibheap_single_example_test.go
│ └── fibheap_test.go
├── futures/
│ ├── futures.go
│ ├── futures_test.go
│ ├── selectable.go
│ └── selectable_test.go
├── go.mod
├── go.sum
├── graph/
│ ├── simple.go
│ └── simple_test.go
├── hashmap/
│ └── fastinteger/
│ ├── hash.go
│ ├── hash_test.go
│ ├── hashmap.go
│ └── hashmap_test.go
├── list/
│ ├── persistent.go
│ └── persistent_test.go
├── mock/
│ ├── batcher.go
│ └── rangetree.go
├── numerics/
│ ├── hilbert/
│ │ ├── hilbert.go
│ │ └── hilbert_test.go
│ └── optimization/
│ ├── global.go
│ ├── nelder_mead.go
│ └── nelder_mead_test.go
├── queue/
│ ├── error.go
│ ├── mock_test.go
│ ├── priority_queue.go
│ ├── priority_queue_test.go
│ ├── queue.go
│ ├── queue_test.go
│ ├── ring.go
│ └── ring_test.go
├── rangetree/
│ ├── entries.go
│ ├── entries_test.go
│ ├── error.go
│ ├── immutable.go
│ ├── immutable_test.go
│ ├── interface.go
│ ├── mock_test.go
│ ├── node.go
│ ├── ordered.go
│ ├── ordered_test.go
│ ├── orderedtree.go
│ ├── orderedtree_test.go
│ └── skiplist/
│ ├── mock_test.go
│ ├── skiplist.go
│ └── skiplist_test.go
├── rtree/
│ ├── hilbert/
│ │ ├── action.go
│ │ ├── cpu.prof
│ │ ├── hilbert.go
│ │ ├── mock_test.go
│ │ ├── node.go
│ │ ├── rectangle.go
│ │ ├── tree.go
│ │ └── tree_test.go
│ └── interface.go
├── set/
│ ├── dict.go
│ └── dict_test.go
├── slice/
│ ├── int64.go
│ ├── int64_test.go
│ └── skip/
│ ├── interface.go
│ ├── iterator.go
│ ├── iterator_test.go
│ ├── mock_test.go
│ ├── node.go
│ ├── skip.go
│ └── skip_test.go
├── sort/
│ ├── interface.go
│ ├── sort.go
│ ├── sort_test.go
│ ├── symmerge.go
│ └── symmerge_test.go
├── threadsafe/
│ └── err/
│ ├── error.go
│ └── error_test.go
├── tree/
│ └── avl/
│ ├── avl.go
│ ├── avl_test.go
│ ├── interface.go
│ ├── mock_test.go
│ └── node.go
└── trie/
├── ctrie/
│ ├── ctrie.go
│ └── ctrie_test.go
├── dtrie/
│ ├── dtrie.go
│ ├── dtrie_test.go
│ ├── node.go
│ └── util.go
├── xfast/
│ ├── iterator.go
│ ├── iterator_test.go
│ ├── mock_test.go
│ ├── xfast.go
│ └── xfast_test.go
└── yfast/
├── entries.go
├── entries_test.go
├── interface.go
├── iterator.go
├── mock_test.go
├── yfast.go
└── yfast_test.go
SYMBOL INDEX (2051 symbols across 160 files)
FILE: augmentedtree/atree.go
function intervalOverlaps (line 19) | func intervalOverlaps(n *node, low, high int64, interval Interval, maxDi...
function overlaps (line 37) | func overlaps(high, otherHigh, low, otherLow int64) bool {
function compare (line 43) | func compare(nodeLow, ivLow int64, nodeID, ivID uint64) int {
type node (line 55) | type node struct
method query (line 63) | func (n *node) query(low, high int64, interval Interval, maxDimension ...
method adjustRanges (line 77) | func (n *node) adjustRanges() {
method adjustRange (line 87) | func (n *node) adjustRange() {
function newDummy (line 92) | func newDummy() node {
function newNode (line 98) | func newNode(interval Interval, min, max int64, dimension uint64) *node {
type tree (line 113) | type tree struct
method Traverse (line 119) | func (t *tree) Traverse(fn func(id Interval)) {
method resetDummy (line 137) | func (tree *tree) resetDummy() {
method Len (line 143) | func (tree *tree) Len() uint64 {
method add (line 148) | func (tree *tree) add(iv Interval) {
method Add (line 222) | func (tree *tree) Add(intervals ...Interval) {
method delete (line 229) | func (tree *tree) delete(iv Interval) {
method Delete (line 310) | func (tree *tree) Delete(intervals ...Interval) {
method Query (line 322) | func (tree *tree) Query(interval Interval) Intervals {
function isRed (line 340) | func isRed(node *node) bool {
function setMax (line 344) | func setMax(parent *node) {
function setMin (line 356) | func setMin(parent *node) {
function rotate (line 371) | func rotate(parent *node, dir int) *node {
function doubleRotate (line 388) | func doubleRotate(parent *node, dir int) *node {
function intFromBool (line 395) | func intFromBool(value bool) int {
function takeOpposite (line 403) | func takeOpposite(value int) int {
function newTree (line 407) | func newTree(maxDimension uint64) *tree {
function New (line 416) | func New(dimensions uint64) Tree {
FILE: augmentedtree/atree_test.go
function min (line 25) | func min(one, two int64) int64 {
function max (line 41) | func max(one, two int64) int64 {
function checkRedBlack (line 57) | func checkRedBlack(tb testing.TB, node *node, dimension int) (int64, int...
function constructSingleDimensionTestTree (line 115) | func constructSingleDimensionTestTree(number int) (*tree, Intervals) {
function TestSimpleAddNilRoot (line 128) | func TestSimpleAddNilRoot(t *testing.T) {
function TestSimpleAddRootLeft (line 143) | func TestSimpleAddRootLeft(t *testing.T) {
function TestSimpleAddRootRight (line 163) | func TestSimpleAddRootRight(t *testing.T) {
function TestAddRootLeftAndRight (line 183) | func TestAddRootLeftAndRight(t *testing.T) {
function TestAddRebalanceInOrder (line 209) | func TestAddRebalanceInOrder(t *testing.T) {
function TestAddRebalanceOutOfOrder (line 223) | func TestAddRebalanceOutOfOrder(t *testing.T) {
function TestAddRebalanceRandomOrder (line 237) | func TestAddRebalanceRandomOrder(t *testing.T) {
function TestAddLargeNumberOfItems (line 253) | func TestAddLargeNumberOfItems(t *testing.T) {
function BenchmarkAddItems (line 268) | func BenchmarkAddItems(b *testing.B) {
function BenchmarkQueryItems (line 285) | func BenchmarkQueryItems(b *testing.B) {
function constructSingleDimensionQueryTestTree (line 303) | func constructSingleDimensionQueryTestTree() (
function TestSimpleQuery (line 320) | func TestSimpleQuery(t *testing.T) {
function TestRightQuery (line 329) | func TestRightQuery(t *testing.T) {
function TestLeftQuery (line 338) | func TestLeftQuery(t *testing.T) {
function TestMatchingQuery (line 347) | func TestMatchingQuery(t *testing.T) {
function TestNoMatchLeft (line 356) | func TestNoMatchLeft(t *testing.T) {
function TestNoMatchRight (line 365) | func TestNoMatchRight(t *testing.T) {
function TestAllQuery (line 374) | func TestAllQuery(t *testing.T) {
function TestQueryDuplicate (line 383) | func TestQueryDuplicate(t *testing.T) {
function TestRootDelete (line 394) | func TestRootDelete(t *testing.T) {
function TestDeleteLeft (line 407) | func TestDeleteLeft(t *testing.T) {
function TestDeleteRight (line 420) | func TestDeleteRight(t *testing.T) {
function TestDeleteCenter (line 433) | func TestDeleteCenter(t *testing.T) {
function TestDeleteRebalanceInOrder (line 446) | func TestDeleteRebalanceInOrder(t *testing.T) {
function TestDeleteRebalanceOutOfOrder (line 467) | func TestDeleteRebalanceOutOfOrder(t *testing.T) {
function TestDeleteRebalanceRandomOrder (line 487) | func TestDeleteRebalanceRandomOrder(t *testing.T) {
function TestDeleteEmptyTree (line 509) | func TestDeleteEmptyTree(t *testing.T) {
function BenchmarkDeleteItems (line 517) | func BenchmarkDeleteItems(b *testing.B) {
function TestAddDuplicateRanges (line 540) | func TestAddDuplicateRanges(t *testing.T) {
function TestAddDeleteDuplicatesRebalanceInOrder (line 552) | func TestAddDeleteDuplicatesRebalanceInOrder(t *testing.T) {
function TestAddDeleteDuplicatesRebalanceReverseOrder (line 568) | func TestAddDeleteDuplicatesRebalanceReverseOrder(t *testing.T) {
function TestAddDeleteDuplicatesRebalanceRandomOrder (line 584) | func TestAddDeleteDuplicatesRebalanceRandomOrder(t *testing.T) {
function TestInsertDuplicateIntervalsToRoot (line 601) | func TestInsertDuplicateIntervalsToRoot(t *testing.T) {
function TestInsertDuplicateIntervalChildren (line 612) | func TestInsertDuplicateIntervalChildren(t *testing.T) {
function TestTraverse (line 626) | func TestTraverse(t *testing.T) {
FILE: augmentedtree/interface.go
type Interval (line 41) | type Interval interface
type Tree (line 61) | type Tree interface
FILE: augmentedtree/intervals.go
type Intervals (line 28) | type Intervals
method Dispose (line 32) | func (ivs *Intervals) Dispose() {
FILE: augmentedtree/intervals_test.go
function TestIntervalsDispose (line 25) | func TestIntervalsDispose(t *testing.T) {
FILE: augmentedtree/mock_test.go
type dimension (line 21) | type dimension struct
type mockInterval (line 25) | type mockInterval struct
method checkDimension (line 30) | func (mi *mockInterval) checkDimension(dimension uint64) {
method LowAtDimension (line 36) | func (mi *mockInterval) LowAtDimension(dimension uint64) int64 {
method HighAtDimension (line 40) | func (mi *mockInterval) HighAtDimension(dimension uint64) int64 {
method OverlapsAtDimension (line 44) | func (mi *mockInterval) OverlapsAtDimension(iv Interval, dimension uin...
method ID (line 49) | func (mi mockInterval) ID() uint64 {
function constructSingleDimensionInterval (line 53) | func constructSingleDimensionInterval(low, high int64, id uint64) *mockI...
function constructMultiDimensionInterval (line 57) | func constructMultiDimensionInterval(id uint64, dimensions ...*dimension...
FILE: augmentedtree/multidimensional_test.go
function constructMultiDimensionQueryTestTree (line 25) | func constructMultiDimensionQueryTestTree() (
function TestRootAddMultipleDimensions (line 48) | func TestRootAddMultipleDimensions(t *testing.T) {
function TestMultipleAddMultipleDimensions (line 72) | func TestMultipleAddMultipleDimensions(t *testing.T) {
function TestAddRebalanceInOrderMultiDimensions (line 113) | func TestAddRebalanceInOrderMultiDimensions(t *testing.T) {
function TestAddRebalanceReverseOrderMultiDimensions (line 133) | func TestAddRebalanceReverseOrderMultiDimensions(t *testing.T) {
function TestAddRebalanceRandomOrderMultiDimensions (line 153) | func TestAddRebalanceRandomOrderMultiDimensions(t *testing.T) {
function TestAddLargeNumbersMultiDimensions (line 175) | func TestAddLargeNumbersMultiDimensions(t *testing.T) {
function BenchmarkAddItemsMultiDimensions (line 196) | func BenchmarkAddItemsMultiDimensions(b *testing.B) {
function BenchmarkQueryItemsMultiDimensions (line 215) | func BenchmarkQueryItemsMultiDimensions(b *testing.B) {
function TestRootDeleteMultiDimensions (line 239) | func TestRootDeleteMultiDimensions(t *testing.T) {
function TestDeleteMultiDimensions (line 258) | func TestDeleteMultiDimensions(t *testing.T) {
function TestDeleteRebalanceInOrderMultiDimensions (line 301) | func TestDeleteRebalanceInOrderMultiDimensions(t *testing.T) {
function TestDeleteRebalanceReverseOrderMultiDimensions (line 328) | func TestDeleteRebalanceReverseOrderMultiDimensions(t *testing.T) {
function TestDeleteRebalanceRandomOrderMultiDimensions (line 355) | func TestDeleteRebalanceRandomOrderMultiDimensions(t *testing.T) {
function TestDeleteEmptyTreeMultiDimensions (line 384) | func TestDeleteEmptyTreeMultiDimensions(t *testing.T) {
function BenchmarkDeleteItemsMultiDimensions (line 395) | func BenchmarkDeleteItemsMultiDimensions(b *testing.B) {
function TestAddDeleteDuplicatesRebalanceInOrderMultiDimensions (line 420) | func TestAddDeleteDuplicatesRebalanceInOrderMultiDimensions(t *testing.T) {
function TestAddDeleteDuplicatesRebalanceReverseOrderMultiDimensions (line 437) | func TestAddDeleteDuplicatesRebalanceReverseOrderMultiDimensions(t *test...
function TestAddDeleteDuplicatesRebalanceRandomOrderMultiDimensions (line 454) | func TestAddDeleteDuplicatesRebalanceRandomOrderMultiDimensions(t *testi...
FILE: batcher/batcher.go
type mutex (line 27) | type mutex struct
method Lock (line 37) | func (m *mutex) Lock() {
method Unlock (line 41) | func (m *mutex) Unlock() {
method TryLock (line 45) | func (m *mutex) TryLock() bool {
function newMutex (line 33) | func newMutex() *mutex {
type Batcher (line 55) | type Batcher interface
type CalculateBytes (line 79) | type CalculateBytes
type basicBatcher (line 81) | type basicBatcher struct
method Put (line 121) | func (b *basicBatcher) Put(item interface{}) error {
method Get (line 146) | func (b *basicBatcher) Get() ([]interface{}, error) {
method Flush (line 213) | func (b *basicBatcher) Flush() error {
method Dispose (line 229) | func (b *basicBatcher) Dispose() {
method IsDisposed (line 257) | func (b *basicBatcher) IsDisposed() bool {
method flush (line 266) | func (b *basicBatcher) flush() {
method ready (line 272) | func (b *basicBatcher) ready() bool {
method drainBatchChan (line 282) | func (b *basicBatcher) drainBatchChan() {
function New (line 104) | func New(maxTime time.Duration, maxItems, maxBytes, queueLen uint, calcu...
FILE: batcher/batcher_test.go
function TestNoCalculateBytes (line 27) | func TestNoCalculateBytes(t *testing.T) {
function TestMaxItems (line 32) | func TestMaxItems(t *testing.T) {
function TestMaxBytes (line 48) | func TestMaxBytes(t *testing.T) {
function TestMaxTime (line 66) | func TestMaxTime(t *testing.T) {
function TestFlush (line 92) | func TestFlush(t *testing.T) {
function TestMultiConsumer (line 111) | func TestMultiConsumer(t *testing.T) {
function TestDispose (line 138) | func TestDispose(t *testing.T) {
function TestIsDisposed (line 170) | func TestIsDisposed(t *testing.T) {
FILE: bitarray/and.go
function andSparseWithSparseBitArray (line 19) | func andSparseWithSparseBitArray(sba, other *sparseBitArray) BitArray {
function andSparseWithDenseBitArray (line 73) | func andSparseWithDenseBitArray(sba *sparseBitArray, other *bitArray) Bi...
function andDenseWithDenseBitArray (line 121) | func andDenseWithDenseBitArray(dba, other *bitArray) BitArray {
FILE: bitarray/and_test.go
function checkBit (line 26) | func checkBit(t *testing.T, ba BitArray, position uint64, expected bool) {
function TestAndSparseWithSparseBitArray (line 37) | func TestAndSparseWithSparseBitArray(t *testing.T) {
function TestAndSparseWithDenseBitArray (line 78) | func TestAndSparseWithDenseBitArray(t *testing.T) {
function TestAndSparseWithSmallerDenseBitArray (line 108) | func TestAndSparseWithSmallerDenseBitArray(t *testing.T) {
function TestAndDenseWithDenseBitArray (line 139) | func TestAndDenseWithDenseBitArray(t *testing.T) {
function TestAndSparseWithEmptySparse (line 165) | func TestAndSparseWithEmptySparse(t *testing.T) {
function TestAndSparseWithEmptyDense (line 178) | func TestAndSparseWithEmptyDense(t *testing.T) {
function TestAndDenseWithEmptyDense (line 193) | func TestAndDenseWithEmptyDense(t *testing.T) {
FILE: bitarray/bitarray.go
type bitArray (line 26) | type bitArray struct
method setLowest (line 37) | func (ba *bitArray) setLowest() {
method setHighest (line 54) | func (ba *bitArray) setHighest() {
method Capacity (line 72) | func (ba *bitArray) Capacity() uint64 {
method ToNums (line 77) | func (ba *bitArray) ToNums() []uint64 {
method SetBit (line 87) | func (ba *bitArray) SetBit(k uint64) error {
method GetBit (line 111) | func (ba *bitArray) GetBit(k uint64) (bool, error) {
method GetSetBits (line 122) | func (ba *bitArray) GetSetBits(from uint64, buffer []uint64) []uint64 {
method ClearBit (line 189) | func (ba *bitArray) ClearBit(k uint64) error {
method Count (line 210) | func (ba *bitArray) Count() int {
method Or (line 220) | func (ba *bitArray) Or(other BitArray) BitArray {
method And (line 230) | func (ba *bitArray) And(other BitArray) BitArray {
method Nand (line 240) | func (ba *bitArray) Nand(other BitArray) BitArray {
method Reset (line 249) | func (ba *bitArray) Reset() {
method Equals (line 257) | func (ba *bitArray) Equals(other BitArray) bool {
method Intersects (line 296) | func (ba *bitArray) Intersects(other BitArray) bool {
method Blocks (line 309) | func (ba *bitArray) Blocks() Iterator {
method IsEmpty (line 313) | func (ba *bitArray) IsEmpty() bool {
method complement (line 318) | func (ba *bitArray) complement() {
method intersectsSparseBitArray (line 329) | func (ba *bitArray) intersectsSparseBitArray(other *sparseBitArray) bo...
method intersectsDenseBitArray (line 339) | func (ba *bitArray) intersectsDenseBitArray(other *bitArray) bool {
method copy (line 349) | func (ba *bitArray) copy() BitArray {
function getIndexAndRemainder (line 33) | func getIndexAndRemainder(k uint64) (uint64, uint64) {
function getSetBitsInBlocks (line 135) | func getSetBitsInBlocks(
function newBitArray (line 363) | func newBitArray(size uint64, args ...bool) *bitArray {
function NewBitArray (line 390) | func NewBitArray(size uint64, args ...bool) BitArray {
FILE: bitarray/bitarray_test.go
function TestBitOperations (line 26) | func TestBitOperations(t *testing.T) {
function TestDuplicateOperation (line 81) | func TestDuplicateOperation(t *testing.T) {
function TestOutOfBounds (line 123) | func TestOutOfBounds(t *testing.T) {
function TestIsEmpty (line 138) | func TestIsEmpty(t *testing.T) {
function TestCount (line 146) | func TestCount(t *testing.T) {
function TestClear (line 168) | func TestClear(t *testing.T) {
function BenchmarkGetBit (line 203) | func BenchmarkGetBit(b *testing.B) {
function TestGetSetBits (line 221) | func TestGetSetBits(t *testing.T) {
function BenchmarkGetSetBits (line 250) | func BenchmarkGetSetBits(b *testing.B) {
function TestEquality (line 268) | func TestEquality(t *testing.T) {
function BenchmarkEquality (line 290) | func BenchmarkEquality(b *testing.B) {
function TestIntersects (line 301) | func TestIntersects(t *testing.T) {
function BenchmarkIntersects (line 328) | func BenchmarkIntersects(b *testing.B) {
function TestComplement (line 342) | func TestComplement(t *testing.T) {
function BenchmarkComplement (line 358) | func BenchmarkComplement(b *testing.B) {
function TestSetHighestLowest (line 368) | func TestSetHighestLowest(t *testing.T) {
function TestGetBitAtCapacity (line 386) | func TestGetBitAtCapacity(t *testing.T) {
function TestSetBitAtCapacity (line 392) | func TestSetBitAtCapacity(t *testing.T) {
function TestClearBitAtCapacity (line 398) | func TestClearBitAtCapacity(t *testing.T) {
function TestClearHighestLowest (line 404) | func TestClearHighestLowest(t *testing.T) {
function TestComplementResetsBounds (line 440) | func TestComplementResetsBounds(t *testing.T) {
function TestBitArrayIntersectsSparse (line 449) | func TestBitArrayIntersectsSparse(t *testing.T) {
function TestBitArrayEqualsSparse (line 468) | func TestBitArrayEqualsSparse(t *testing.T) {
function TestConstructorSetBitArray (line 487) | func TestConstructorSetBitArray(t *testing.T) {
function TestCopyBitArray (line 498) | func TestCopyBitArray(t *testing.T) {
function BenchmarkDenseIntersectsCompressed (line 510) | func BenchmarkDenseIntersectsCompressed(b *testing.B) {
function TestBitArrayToNums (line 527) | func TestBitArrayToNums(t *testing.T) {
function BenchmarkBitArrayToNums (line 540) | func BenchmarkBitArrayToNums(b *testing.B) {
FILE: bitarray/bitmap.go
type Bitmap32 (line 32) | type Bitmap32
method SetBit (line 35) | func (b Bitmap32) SetBit(pos uint) Bitmap32 {
method ClearBit (line 40) | func (b Bitmap32) ClearBit(pos uint) Bitmap32 {
method GetBit (line 45) | func (b Bitmap32) GetBit(pos uint) bool {
method PopCount (line 50) | func (b Bitmap32) PopCount() int {
type Bitmap64 (line 61) | type Bitmap64
method SetBit (line 64) | func (b Bitmap64) SetBit(pos uint) Bitmap64 {
method ClearBit (line 69) | func (b Bitmap64) ClearBit(pos uint) Bitmap64 {
method GetBit (line 74) | func (b Bitmap64) GetBit(pos uint) bool {
method PopCount (line 79) | func (b Bitmap64) PopCount() int {
FILE: bitarray/bitmap_test.go
function TestBitmap32_PopCount (line 35) | func TestBitmap32_PopCount(t *testing.T) {
function TestBitmap64_PopCount (line 48) | func TestBitmap64_PopCount(t *testing.T) {
function TestBitmap32_SetBit (line 61) | func TestBitmap32_SetBit(t *testing.T) {
function TestBitmap32_ClearBit (line 66) | func TestBitmap32_ClearBit(t *testing.T) {
function TestBitmap32_zGetBit (line 71) | func TestBitmap32_zGetBit(t *testing.T) {
function TestBitmap64_SetBit (line 76) | func TestBitmap64_SetBit(t *testing.T) {
function TestBitmap64_ClearBit (line 81) | func TestBitmap64_ClearBit(t *testing.T) {
function TestBitmap64_GetBit (line 86) | func TestBitmap64_GetBit(t *testing.T) {
function BenchmarkBitmap32_PopCount (line 91) | func BenchmarkBitmap32_PopCount(b *testing.B) {
function BenchmarkBitmap64_PopCount (line 99) | func BenchmarkBitmap64_PopCount(b *testing.B) {
FILE: bitarray/block.go
type block (line 27) | type block
method toNums (line 38) | func (b block) toNums(offset uint64, nums *[]uint64) {
method findLeftPosition (line 46) | func (b block) findLeftPosition() uint64 {
method findRightPosition (line 57) | func (b block) findRightPosition() uint64 {
method insert (line 68) | func (b block) insert(position uint64) block {
method remove (line 72) | func (b block) remove(position uint64) block {
method or (line 76) | func (b block) or(other block) block {
method and (line 80) | func (b block) and(other block) block {
method nand (line 84) | func (b block) nand(other block) block {
method get (line 88) | func (b block) get(position uint64) bool {
method equals (line 92) | func (b block) equals(other block) bool {
method intersects (line 96) | func (b block) intersects(other block) bool {
method String (line 100) | func (b block) String() string {
constant s (line 33) | s = uint64(unsafe.Sizeof(block(0)) * 8)
constant maximumBlock (line 36) | maximumBlock = block(0) | ^block(0)
FILE: bitarray/block_test.go
function TestBlockToNums (line 25) | func TestBlockToNums(t *testing.T) {
function BenchmarkBlockToNums (line 38) | func BenchmarkBlockToNums(b *testing.B) {
FILE: bitarray/encoding.go
function Marshal (line 28) | func Marshal(ba BitArray) ([]byte, error) {
function Unmarshal (line 40) | func Unmarshal(input []byte) (BitArray, error) {
method Serialize (line 64) | func (ba *sparseBitArray) Serialize() ([]byte, error) {
function Uint64FromBytes (line 102) | func Uint64FromBytes(b []byte) (uint64, int) {
method Deserialize (line 117) | func (ret *sparseBitArray) Deserialize(incoming []byte) error {
method Serialize (line 160) | func (ba *bitArray) Serialize() ([]byte, error) {
method Deserialize (line 200) | func (ret *bitArray) Deserialize(incoming []byte) error {
FILE: bitarray/encoding_test.go
function TestSparseBitArraySerialization (line 25) | func TestSparseBitArraySerialization(t *testing.T) {
function TestBitArraySerialization (line 49) | func TestBitArraySerialization(t *testing.T) {
function TestBitArrayMarshalUnmarshal (line 75) | func TestBitArrayMarshalUnmarshal(t *testing.T) {
function TestSparseBitArrayMarshalUnmarshal (line 96) | func TestSparseBitArrayMarshalUnmarshal(t *testing.T) {
function TestUnmarshalErrors (line 117) | func TestUnmarshalErrors(t *testing.T) {
FILE: bitarray/error.go
type OutOfRangeError (line 23) | type OutOfRangeError
method Error (line 26) | func (err OutOfRangeError) Error() string {
FILE: bitarray/interface.go
type BitArray (line 30) | type BitArray interface
type Iterator (line 81) | type Iterator interface
FILE: bitarray/iterator.go
type sparseBitArrayIterator (line 19) | type sparseBitArrayIterator struct
method Next (line 26) | func (iter *sparseBitArrayIterator) Next() bool {
method Value (line 32) | func (iter *sparseBitArrayIterator) Value() (uint64, block) {
function newCompressedBitArrayIterator (line 36) | func newCompressedBitArrayIterator(sba *sparseBitArray) *sparseBitArrayI...
type bitArrayIterator (line 43) | type bitArrayIterator struct
method Next (line 51) | func (iter *bitArrayIterator) Next() bool {
method Value (line 57) | func (iter *bitArrayIterator) Value() (uint64, block) {
function newBitArrayIterator (line 61) | func newBitArrayIterator(ba *bitArray) *bitArrayIterator {
FILE: bitarray/nand.go
function nandSparseWithSparseBitArray (line 19) | func nandSparseWithSparseBitArray(sba, other *sparseBitArray) BitArray {
function nandSparseWithDenseBitArray (line 86) | func nandSparseWithDenseBitArray(sba *sparseBitArray, other *bitArray) B...
function nandDenseWithSparseBitArray (line 118) | func nandDenseWithSparseBitArray(sba *bitArray, other *sparseBitArray) B...
function nandDenseWithDenseBitArray (line 139) | func nandDenseWithDenseBitArray(dba, other *bitArray) BitArray {
FILE: bitarray/nand_test.go
function TestNandSparseWithSparseBitArray (line 25) | func TestNandSparseWithSparseBitArray(t *testing.T) {
function TestNandSparseWithDenseBitArray (line 66) | func TestNandSparseWithDenseBitArray(t *testing.T) {
function TestNandDenseWithSparseBitArray (line 96) | func TestNandDenseWithSparseBitArray(t *testing.T) {
function TestNandSparseWithSmallerDenseBitArray (line 126) | func TestNandSparseWithSmallerDenseBitArray(t *testing.T) {
function TestNandDenseWithDenseBitArray (line 160) | func TestNandDenseWithDenseBitArray(t *testing.T) {
function TestNandSparseWithEmptySparse (line 196) | func TestNandSparseWithEmptySparse(t *testing.T) {
function TestNandSparseWithEmptyDense (line 209) | func TestNandSparseWithEmptyDense(t *testing.T) {
function TestNandDenseWithEmptyDense (line 224) | func TestNandDenseWithEmptyDense(t *testing.T) {
function BenchmarkNandSparseWithSparse (line 238) | func BenchmarkNandSparseWithSparse(b *testing.B) {
function BenchmarkNandSparseWithDense (line 258) | func BenchmarkNandSparseWithDense(b *testing.B) {
function BenchmarkNandDenseWithSparse (line 278) | func BenchmarkNandDenseWithSparse(b *testing.B) {
function BenchmarkNandDenseWithDense (line 298) | func BenchmarkNandDenseWithDense(b *testing.B) {
FILE: bitarray/or.go
function orSparseWithSparseBitArray (line 19) | func orSparseWithSparseBitArray(sba *sparseBitArray,
function orSparseWithDenseBitArray (line 76) | func orSparseWithDenseBitArray(sba *sparseBitArray, other *bitArray) Bit...
function orDenseWithDenseBitArray (line 121) | func orDenseWithDenseBitArray(dba *bitArray, other *bitArray) BitArray {
FILE: bitarray/or_test.go
function TestOrSparseWithSparseBitArray (line 25) | func TestOrSparseWithSparseBitArray(t *testing.T) {
function BenchmarkOrSparseWithSparse (line 74) | func BenchmarkOrSparseWithSparse(b *testing.B) {
function TestOrSparseWithDenseBitArray (line 97) | func TestOrSparseWithDenseBitArray(t *testing.T) {
function BenchmarkOrSparseWithDense (line 144) | func BenchmarkOrSparseWithDense(b *testing.B) {
function TestOrDenseWithDenseBitArray (line 167) | func TestOrDenseWithDenseBitArray(t *testing.T) {
function BenchmarkOrDenseWithDense (line 207) | func BenchmarkOrDenseWithDense(b *testing.B) {
function TestOrSparseWithEmptySparse (line 230) | func TestOrSparseWithEmptySparse(t *testing.T) {
function TestOrSparseWithEmptyDense (line 246) | func TestOrSparseWithEmptyDense(t *testing.T) {
function TestOrDenseWithEmptyDense (line 261) | func TestOrDenseWithEmptyDense(t *testing.T) {
FILE: bitarray/sparse_bitarray.go
type uintSlice (line 27) | type uintSlice
method Len (line 30) | func (u uintSlice) Len() int64 {
method Swap (line 35) | func (u uintSlice) Swap(i, j int64) {
method Less (line 41) | func (u uintSlice) Less(i, j int64) bool {
method search (line 45) | func (u uintSlice) search(x uint64) int64 {
method insert (line 49) | func (u *uintSlice) insert(x uint64) (int64, bool) {
method deleteAtIndex (line 67) | func (u *uintSlice) deleteAtIndex(i int64) {
method get (line 73) | func (u uintSlice) get(x uint64) int64 {
type blocks (line 86) | type blocks
method insert (line 88) | func (b *blocks) insert(index int64) {
method deleteAtIndex (line 99) | func (b *blocks) deleteAtIndex(i int64) {
type sparseBitArray (line 105) | type sparseBitArray struct
method SetBit (line 111) | func (sba *sparseBitArray) SetBit(k uint64) error {
method GetBit (line 123) | func (sba *sparseBitArray) GetBit(k uint64) (bool, error) {
method GetSetBits (line 134) | func (sba *sparseBitArray) GetSetBits(from uint64, buffer []uint64) []...
method ToNums (line 153) | func (sba *sparseBitArray) ToNums() []uint64 {
method ClearBit (line 169) | func (sba *sparseBitArray) ClearBit(k uint64) error {
method Reset (line 186) | func (sba *sparseBitArray) Reset() {
method Blocks (line 192) | func (sba *sparseBitArray) Blocks() Iterator {
method Capacity (line 198) | func (sba *sparseBitArray) Capacity() uint64 {
method Equals (line 208) | func (sba *sparseBitArray) Equals(other BitArray) bool {
method Count (line 250) | func (sba *sparseBitArray) Count() int {
method Or (line 260) | func (sba *sparseBitArray) Or(other BitArray) BitArray {
method And (line 270) | func (sba *sparseBitArray) And(other BitArray) BitArray {
method Nand (line 280) | func (sba *sparseBitArray) Nand(other BitArray) BitArray {
method IsEmpty (line 288) | func (sba *sparseBitArray) IsEmpty() bool {
method copy (line 294) | func (sba *sparseBitArray) copy() *sparseBitArray {
method Intersects (line 307) | func (sba *sparseBitArray) Intersects(other BitArray) bool {
method IntersectsBetween (line 342) | func (sba *sparseBitArray) IntersectsBetween(other BitArray, start, st...
function newSparseBitArray (line 346) | func newSparseBitArray() *sparseBitArray {
function NewSparseBitArray (line 352) | func NewSparseBitArray() BitArray {
FILE: bitarray/sparse_bitarray_test.go
function TestGetCompressedBit (line 26) | func TestGetCompressedBit(t *testing.T) {
function BenchmarkGetCompressedBit (line 34) | func BenchmarkGetCompressedBit(b *testing.B) {
function TestGetSetCompressedBit (line 49) | func TestGetSetCompressedBit(t *testing.T) {
function BenchmarkSetCompressedBit (line 68) | func BenchmarkSetCompressedBit(b *testing.B) {
function TestGetSetCompressedBits (line 80) | func TestGetSetCompressedBits(t *testing.T) {
function BenchmarkGetSetCompressedBits (line 109) | func BenchmarkGetSetCompressedBits(b *testing.B) {
function TestCompressedCount (line 125) | func TestCompressedCount(t *testing.T) {
function TestClearCompressedBit (line 147) | func TestClearCompressedBit(t *testing.T) {
function BenchmarkClearCompressedBit (line 167) | func BenchmarkClearCompressedBit(b *testing.B) {
function TestClearCompressedBitArray (line 181) | func TestClearCompressedBitArray(t *testing.T) {
function TestCompressedEquals (line 201) | func TestCompressedEquals(t *testing.T) {
function TestCompressedIntersects (line 217) | func TestCompressedIntersects(t *testing.T) {
function TestLongCompressedIntersects (line 239) | func TestLongCompressedIntersects(t *testing.T) {
function BenchmarkCompressedIntersects (line 264) | func BenchmarkCompressedIntersects(b *testing.B) {
function TestSparseIntersectsBitArray (line 282) | func TestSparseIntersectsBitArray(t *testing.T) {
function TestSparseEqualsBitArray (line 307) | func TestSparseEqualsBitArray(t *testing.T) {
function BenchmarkCompressedEquals (line 326) | func BenchmarkCompressedEquals(b *testing.B) {
function TestInsertPreviousBlockInSparse (line 343) | func TestInsertPreviousBlockInSparse(t *testing.T) {
function TestSparseBitArrayToNums (line 354) | func TestSparseBitArrayToNums(t *testing.T) {
function BenchmarkSparseBitArrayToNums (line 366) | func BenchmarkSparseBitArrayToNums(b *testing.B) {
FILE: bitarray/util.go
function maxInt64 (line 20) | func maxInt64(ints ...int64) int64 {
function maxUint64 (line 32) | func maxUint64(ints ...uint64) uint64 {
function minUint64 (line 44) | func minUint64(ints ...uint64) uint64 {
FILE: btree/_link/interface.go
type Keys (line 20) | type Keys
type Key (line 22) | type Key interface
FILE: btree/_link/key.go
method search (line 21) | func (keys Keys) search(key Key) int {
method insert (line 27) | func (keys *Keys) insert(key Key) Key {
method insertAt (line 32) | func (keys *Keys) insertAt(key Key, i int) Key {
method split (line 50) | func (keys *Keys) split() (Key, Keys, Keys) {
method splitAt (line 58) | func (keys *Keys) splitAt(i int) (Keys, Keys) {
method last (line 69) | func (keys Keys) last() Key {
method first (line 73) | func (keys Keys) first() Key {
method needsSplit (line 77) | func (keys Keys) needsSplit() bool {
method reverse (line 81) | func (keys Keys) reverse() Keys {
function chunkKeys (line 90) | func chunkKeys(keys Keys, numParts int64) []Keys {
FILE: btree/_link/mock_test.go
type mockKey (line 19) | type mockKey
method Compare (line 21) | func (mk mockKey) Compare(other Key) int {
FILE: btree/_link/node.go
function search (line 24) | func search(parent *node, key Key) Key {
function getParent (line 38) | func getParent(parent *node, stack *nodes, key Key) *node {
function insert (line 55) | func insert(tree *blink, parent *node, stack *nodes, key Key) Key {
function split (line 77) | func split(tree *blink, n *node, stack *nodes) {
function moveRight (line 116) | func moveRight(n *node, key Key, getLock bool) *node {
type nodes (line 139) | type nodes
method reset (line 141) | func (ns *nodes) reset() {
method push (line 149) | func (ns *nodes) push(n *node) {
method pop (line 153) | func (ns *nodes) pop() *node {
method insertAt (line 164) | func (ns *nodes) insertAt(n *node, i int) {
method splitAt (line 175) | func (ns *nodes) splitAt(i int) (nodes, nodes) {
type node (line 186) | type node struct
method key (line 195) | func (n *node) key() Key {
method insert (line 199) | func (n *node) insert(key Key) Key {
method insertNode (line 208) | func (n *node) insertNode(other *node) {
method needsSplit (line 215) | func (n *node) needsSplit() bool {
method max (line 219) | func (n *node) max() Key {
method splitLeaf (line 227) | func (n *node) splitLeaf() (Key, *node, *node) {
method splitInternal (line 240) | func (n *node) splitInternal() (Key, *node, *node) {
method split (line 269) | func (n *node) split() (Key, *node, *node) {
method search (line 277) | func (n *node) search(key Key) int {
method searchNode (line 281) | func (n *node) searchNode(key Key) *node {
method print (line 287) | func (n *node) print(output *log.Logger) {
function newNode (line 300) | func newNode(isLeaf bool, keys Keys, ns nodes) *node {
FILE: btree/_link/node_test.go
function newTestNode (line 25) | func newTestNode(isLeaf bool, ary int) *node {
function checkTree (line 33) | func checkTree(t testing.TB, tree *blink) bool {
function checkNode (line 41) | func checkNode(t testing.TB, n *node) bool {
function TestSplitInternalNodeOddAry (line 79) | func TestSplitInternalNodeOddAry(t *testing.T) {
function TestSplitInternalNodeEvenAry (line 105) | func TestSplitInternalNodeEvenAry(t *testing.T) {
function TestSplitLeafNodeOddAry (line 133) | func TestSplitLeafNodeOddAry(t *testing.T) {
function TestSplitLeafNodeEvenAry (line 149) | func TestSplitLeafNodeEvenAry(t *testing.T) {
FILE: btree/_link/tree.go
constant numberOfItemsBeforeMultithread (line 49) | numberOfItemsBeforeMultithread = 10
type blink (line 51) | type blink struct
method insert (line 57) | func (blink *blink) insert(key Key, stack *nodes) Key {
method multithreadedInsert (line 79) | func (blink *blink) multithreadedInsert(keys Keys) Keys {
method Insert (line 108) | func (blink *blink) Insert(keys ...Key) Keys {
method Len (line 123) | func (blink *blink) Len() uint64 {
method get (line 127) | func (blink *blink) get(key Key) Key {
method Get (line 147) | func (blink *blink) Get(keys ...Key) Keys {
method print (line 156) | func (blink *blink) print(output *log.Logger) {
function newTree (line 165) | func newTree(ary, numRoutines uint64) *blink {
FILE: btree/_link/tree_test.go
function getConsoleLogger (line 28) | func getConsoleLogger() *log.Logger {
function generateRandomKeys (line 32) | func generateRandomKeys(num int) Keys {
function generateKeys (line 41) | func generateKeys(num int) Keys {
function TestSimpleInsert (line 50) | func TestSimpleInsert(t *testing.T) {
function TestMultipleInsert (line 62) | func TestMultipleInsert(t *testing.T) {
function TestMultipleInsertCausesSplitOddAryReverseOrder (line 74) | func TestMultipleInsertCausesSplitOddAryReverseOrder(t *testing.T) {
function TestMultipleInsertCausesSplitOddAry (line 87) | func TestMultipleInsertCausesSplitOddAry(t *testing.T) {
function TestMultipleInsertCausesSplitOddAryRandomOrder (line 100) | func TestMultipleInsertCausesSplitOddAryRandomOrder(t *testing.T) {
function TestMultipleInsertCausesSplitEvenAryReverseOrder (line 113) | func TestMultipleInsertCausesSplitEvenAryReverseOrder(t *testing.T) {
function TestMultipleInsertCausesSplitEvenAry (line 127) | func TestMultipleInsertCausesSplitEvenAry(t *testing.T) {
function TestMultipleInsertCausesSplitEvenAryRandomOrder (line 140) | func TestMultipleInsertCausesSplitEvenAryRandomOrder(t *testing.T) {
function TestMultipleInsertCausesSplitEvenAryMultiThreaded (line 153) | func TestMultipleInsertCausesSplitEvenAryMultiThreaded(t *testing.T) {
function TestMultipleInsertCausesCascadingSplitsOddAry (line 165) | func TestMultipleInsertCausesCascadingSplitsOddAry(t *testing.T) {
function TestMultipleInsertCausesCascadingSplitsOddAryReverseOrder (line 179) | func TestMultipleInsertCausesCascadingSplitsOddAryReverseOrder(t *testin...
function TestMultipleInsertCausesCascadingSplitsEvenAry (line 195) | func TestMultipleInsertCausesCascadingSplitsEvenAry(t *testing.T) {
function TestOverwriteOddAry (line 206) | func TestOverwriteOddAry(t *testing.T) {
function TestOverwriteEvenAry (line 220) | func TestOverwriteEvenAry(t *testing.T) {
function BenchmarkSimpleAdd (line 234) | func BenchmarkSimpleAdd(b *testing.B) {
function BenchmarkGet (line 246) | func BenchmarkGet(b *testing.B) {
function BenchmarkBulkAdd (line 259) | func BenchmarkBulkAdd(b *testing.B) {
FILE: btree/immutable/add.go
method AddItems (line 27) | func (t *Tr) AddItems(its ...*Item) ([]*Item, error) {
method add (line 45) | func (t *Tr) add(keys Keys) (Keys, error) {
method determinePaths (line 118) | func (t *Tr) determinePaths(keys Keys) (map[string][]*nodeBundle, error) {
function insertByMerge (line 164) | func insertByMerge(comparator Comparator, n *Node, bundles []*nodeBundle...
function insertLastDimension (line 205) | func insertLastDimension(t *Tr, n *Node, bundles []*nodeBundle) (Keys, e...
method iterativeSplit (line 221) | func (t *Tr) iterativeSplit(n *Node) Keys {
method walkupInsert (line 235) | func (t *Tr) walkupInsert(nodes map[string]*path) error {
FILE: btree/immutable/cacher.go
type cacher (line 32) | type cacher struct
method asyncLoadNode (line 38) | func (c *cacher) asyncLoadNode(t *Tr, key ID, completer chan interface...
method clear (line 54) | func (c *cacher) clear() {
method deleteFromCache (line 63) | func (c *cacher) deleteFromCache(id ID) {
method loadNode (line 70) | func (c *cacher) loadNode(t *Tr, key ID) (*Node, error) {
method getNode (line 88) | func (c *cacher) getNode(t *Tr, key ID, useCache bool) (*Node, error) {
function newCacher (line 128) | func newCacher(persister Persister) *cacher {
FILE: btree/immutable/config.go
type Config (line 22) | type Config struct
function DefaultConfig (line 37) | func DefaultConfig(persister Persister, comparator Comparator) Config {
FILE: btree/immutable/delete.go
method DeleteItems (line 21) | func (t *Tr) DeleteItems(values ...interface{}) ([]*Item, error) {
method delete (line 49) | func (t *Tr) delete(keys Keys) error {
method walkupDelete (line 145) | func (t *Tr) walkupDelete(key *Key, node *Node, path *path, mapping map[...
FILE: btree/immutable/interface.go
type Tree (line 46) | type Tree interface
type ReadableTree (line 62) | type ReadableTree interface
type MutableTree (line 72) | type MutableTree interface
type Comparator (line 90) | type Comparator
type Payload (line 93) | type Payload struct
type Persister (line 101) | type Persister interface
FILE: btree/immutable/item.go
type Item (line 19) | type Item struct
type items (line 24) | type items
method split (line 26) | func (its items) split(numParts int) []items {
FILE: btree/immutable/node.go
function newID (line 27) | func newID() []byte {
type ID (line 39) | type ID
type Key (line 44) | type Key struct
method ID (line 51) | func (k Key) ID() []byte {
method ToItem (line 55) | func (k Key) ToItem() *Item {
type Keys (line 62) | type Keys
method toItems (line 64) | func (k Keys) toItems() items {
method sort (line 73) | func (k Keys) sort(comparator Comparator) Keys {
type keySortWrapper (line 77) | type keySortWrapper struct
method Len (line 82) | func (sw *keySortWrapper) Len() int {
method Swap (line 86) | func (sw *keySortWrapper) Swap(i, j int) {
method Less (line 90) | func (sw *keySortWrapper) Less(i, j int) bool {
method sort (line 94) | func (sw *keySortWrapper) sort() Keys {
function splitKeys (line 99) | func splitKeys(keys Keys, numParts int) []Keys {
type Node (line 111) | type Node struct
method copy (line 127) | func (n *Node) copy() *Node {
method searchKey (line 145) | func (n *Node) searchKey(comparator Comparator, value interface{}) (*K...
method insert (line 165) | func (n *Node) insert(comparator Comparator, key *Key) *Key {
method delete (line 195) | func (n *Node) delete(comparator Comparator, key *Key) *Key {
method multiDelete (line 207) | func (n *Node) multiDelete(comparator Comparator, keys ...*Key) {
method replaceKeyAt (line 245) | func (n *Node) replaceKeyAt(key *Key, i int) {
method flatten (line 250) | func (n *Node) flatten() ([]interface{}, Keys) {
method iter (line 256) | func (n *Node) iter(comparator Comparator, start, stop interface{}) it...
method valueAt (line 267) | func (n *Node) valueAt(i int) interface{} {
method keyAt (line 271) | func (n *Node) keyAt(i int) *Key {
method needsSplit (line 275) | func (n *Node) needsSplit(max int) bool {
method lastValue (line 279) | func (n *Node) lastValue() interface{} {
method firstValue (line 283) | func (n *Node) firstValue() interface{} {
method append (line 287) | func (n *Node) append(other *Node) {
method replaceValueAt (line 292) | func (n *Node) replaceValueAt(i int, value interface{}) {
method deleteValueAt (line 296) | func (n *Node) deleteValueAt(i int) {
method deleteKeyAt (line 302) | func (n *Node) deleteKeyAt(i int) {
method splitLeafAt (line 308) | func (n *Node) splitLeafAt(i int) (interface{}, *Node) {
method splitInternalAt (line 331) | func (n *Node) splitInternalAt(i int) (interface{}, *Node) {
method splitAt (line 352) | func (n *Node) splitAt(i int) (interface{}, *Node) {
method lenKeys (line 360) | func (n *Node) lenKeys() int {
method lenValues (line 364) | func (n *Node) lenValues() int {
method appendChild (line 368) | func (n *Node) appendChild(key *Key) {
method appendValue (line 372) | func (n *Node) appendValue(value interface{}) {
method popFirstKey (line 376) | func (n *Node) popFirstKey() *Key {
method popFirstValue (line 382) | func (n *Node) popFirstValue() interface{} {
method popKey (line 388) | func (n *Node) popKey() *Key {
method popValue (line 394) | func (n *Node) popValue() interface{} {
method prependKey (line 400) | func (n *Node) prependKey(key *Key) {
method prependValue (line 406) | func (n *Node) prependValue(value interface{}) {
method search (line 412) | func (n *Node) search(comparator Comparator, value interface{}) int {
function nodeFromBytes (line 420) | func nodeFromBytes(t *Tr, data []byte) (*Node, error) {
function newNode (line 433) | func newNode() *Node {
type sliceIterator (line 439) | type sliceIterator struct
method next (line 446) | func (s *sliceIterator) next() bool {
method value (line 466) | func (s *sliceIterator) value() (*Key, int) {
type iterator (line 470) | type iterator interface
type nodeBundle (line 475) | type nodeBundle struct
type nodeSortWrapper (line 480) | type nodeSortWrapper struct
method Len (line 486) | func (n *nodeSortWrapper) Len() int {
method Swap (line 490) | func (n *nodeSortWrapper) Swap(i, j int) {
method Less (line 495) | func (n *nodeSortWrapper) Less(i, j int) bool {
function splitValues (line 499) | func splitValues(values []interface{}, numParts int) [][]interface{} {
FILE: btree/immutable/node_gen.go
method MarshalMsg (line 12) | func (z ID) MarshalMsg(b []byte) (o []byte, err error) {
method UnmarshalMsg (line 19) | func (z *ID) UnmarshalMsg(bts []byte) (o []byte, err error) {
method Msgsize (line 32) | func (z ID) Msgsize() (s int) {
method MarshalMsg (line 38) | func (z *Key) MarshalMsg(b []byte) (o []byte, err error) {
method UnmarshalMsg (line 57) | func (z *Key) UnmarshalMsg(bts []byte) (o []byte, err error) {
method Msgsize (line 102) | func (z *Key) Msgsize() (s int) {
method MarshalMsg (line 108) | func (z Keys) MarshalMsg(b []byte) (o []byte, err error) {
method UnmarshalMsg (line 125) | func (z *Keys) UnmarshalMsg(bts []byte) (o []byte, err error) {
method Msgsize (line 157) | func (z Keys) Msgsize() (s int) {
method MarshalMsg (line 170) | func (z *Node) MarshalMsg(b []byte) (o []byte, err error) {
method UnmarshalMsg (line 205) | func (z *Node) UnmarshalMsg(bts []byte) (o []byte, err error) {
method Msgsize (line 290) | func (z *Node) Msgsize() (s int) {
FILE: btree/immutable/path.go
type pathBundle (line 24) | type pathBundle struct
type path (line 34) | type path struct
method append (line 39) | func (p *path) append(pb *pathBundle) {
method pop (line 53) | func (p *path) pop() *pathBundle {
method peek (line 63) | func (p *path) peek() *pathBundle {
FILE: btree/immutable/query.go
method Apply (line 26) | func (t *Tr) Apply(fn func(item *Item), keys ...interface{}) error {
method filter (line 92) | func (t *Tr) filter(start, stop interface{}, n *Node, fn func(key *Key) ...
method iter (line 103) | func (t *Tr) iter(start, stop interface{}, fn func(*Key) bool) error {
method iterativeFind (line 138) | func (t *Tr) iterativeFind(value interface{}, id ID) (*path, error) {
method iterativeFindWithoutPath (line 168) | func (t *Tr) iterativeFindWithoutPath(value interface{}, id ID) (*Node, ...
FILE: btree/immutable/rt.go
type context (line 28) | type context struct
method nodeExists (line 33) | func (c *context) nodeExists(id ID) bool {
method addNode (line 40) | func (c *context) addNode(n *Node) {
method getNode (line 46) | func (c *context) getNode(id ID) *Node {
function newContext (line 52) | func newContext() *context {
type Tr (line 61) | type Tr struct
method createRoot (line 72) | func (t *Tr) createRoot() *Node {
method contextOrCachedNode (line 80) | func (t *Tr) contextOrCachedNode(id ID, cache bool) (*Node, error) {
method ID (line 91) | func (t *Tr) ID() ID {
method toBytes (line 97) | func (t *Tr) toBytes() []byte {
method reset (line 107) | func (t *Tr) reset() {
method commit (line 114) | func (t *Tr) commit() []*Payload {
method copyNode (line 131) | func (t *Tr) copyNode(n *Node) *Node {
method Len (line 141) | func (t *Tr) Len() int {
method AsMutable (line 145) | func (t *Tr) AsMutable() MutableTree {
method Commit (line 158) | func (t *Tr) Commit() (ReadableTree, error) {
function treeFromBytes (line 176) | func treeFromBytes(p Persister, data []byte, comparator Comparator) (*Tr...
function newTree (line 193) | func newTree(cfg Config) *Tr {
function New (line 202) | func New(cfg Config) ReadableTree {
function Load (line 210) | func Load(p Persister, id []byte, comparator Comparator) (ReadableTree, ...
FILE: btree/immutable/rt_gen.go
method MarshalMsg (line 12) | func (z *Tr) MarshalMsg(b []byte) (o []byte, err error) {
method UnmarshalMsg (line 37) | func (z *Tr) UnmarshalMsg(bts []byte) (o []byte, err error) {
method Msgsize (line 83) | func (z *Tr) Msgsize() (s int) {
FILE: btree/immutable/rt_test.go
type ephemeral (line 31) | type ephemeral struct
method Save (line 36) | func (e *ephemeral) Save(items ...*Payload) error {
method Load (line 51) | func (e *ephemeral) Load(keys ...[]byte) ([]*Payload, error) {
constant maxValue (line 68) | maxValue = int64(100000)
function init (line 71) | func init() {
type valueSortWrapper (line 75) | type valueSortWrapper struct
method Len (line 80) | func (v *valueSortWrapper) Len() int {
method Swap (line 84) | func (v *valueSortWrapper) Swap(i, j int) {
method Less (line 88) | func (v *valueSortWrapper) Less(i, j int) bool {
method sort (line 92) | func (v *valueSortWrapper) sort() {
function reverse (line 96) | func reverse(items items) items {
type orderedItems (line 121) | type orderedItems
method Len (line 123) | func (o orderedItems) Len() int {
method Swap (line 127) | func (o orderedItems) Swap(i, j int) {
method Less (line 131) | func (o orderedItems) Less(i, j int) bool {
method equal (line 135) | func (o orderedItems) equal(item1, item2 *Item) bool {
method copy (line 139) | func (o orderedItems) copy() orderedItems {
method search (line 145) | func (o orderedItems) search(value interface{}) int {
method add (line 151) | func (o orderedItems) add(item *Item) orderedItems {
method delete (line 171) | func (o orderedItems) delete(item *Item) orderedItems {
method toItems (line 190) | func (o orderedItems) toItems() items {
method query (line 199) | func (o orderedItems) query(start, stop interface{}) items {
function generateRandomQuery (line 213) | func generateRandomQuery() (interface{}, interface{}) {
function newItem (line 219) | func newItem(value interface{}) *Item {
function newEphemeral (line 226) | func newEphemeral() Persister {
type delayedPersister (line 232) | type delayedPersister struct
method Load (line 236) | func (d *delayedPersister) Load(keys ...[]byte) ([]*Payload, error) {
function newDelayed (line 241) | func newDelayed() Persister {
function defaultConfig (line 245) | func defaultConfig() Config {
function generateRandomItem (line 253) | func generateRandomItem() *Item {
function generateRandomItems (line 259) | func generateRandomItems(num int) items {
function generateLinearItems (line 276) | func generateLinearItems(num int) items {
function toOrdered (line 286) | func toOrdered(items items) orderedItems {
method toList (line 297) | func (t *Tr) toList(values ...interface{}) (items, error) {
method pprint (line 306) | func (t *Tr) pprint(id ID) {
method verify (line 330) | func (t *Tr) verify(id ID, tb testing.TB) (interface{}, interface{}) {
function itemsToValues (line 371) | func itemsToValues(items ...*Item) []interface{} {
function TestNodeSplit (line 380) | func TestNodeSplit(t *testing.T) {
function TestReverseNodeSplit (line 423) | func TestReverseNodeSplit(t *testing.T) {
function TestDuplicate (line 455) | func TestDuplicate(t *testing.T) {
function TestCommit (line 474) | func TestCommit(t *testing.T) {
function TestRandom (line 498) | func TestRandom(t *testing.T) {
function TestLoad (line 517) | func TestLoad(t *testing.T) {
function TestDeleteFromRoot (line 538) | func TestDeleteFromRoot(t *testing.T) {
function TestDeleteAllFromRoot (line 556) | func TestDeleteAllFromRoot(t *testing.T) {
function TestDeleteAfterSplitIncreasing (line 572) | func TestDeleteAfterSplitIncreasing(t *testing.T) {
function TestDeleteMultipleLevelsRandomlyBulk (line 589) | func TestDeleteMultipleLevelsRandomlyBulk(t *testing.T) {
function TestDeleteAfterSplitDecreasing (line 601) | func TestDeleteAfterSplitDecreasing(t *testing.T) {
function TestDeleteMultipleLevels (line 620) | func TestDeleteMultipleLevels(t *testing.T) {
function TestDeleteMultipleLevelsRandomly (line 654) | func TestDeleteMultipleLevelsRandomly(t *testing.T) {
function TestDeleteMultipleLevelsWithCommit (line 679) | func TestDeleteMultipleLevelsWithCommit(t *testing.T) {
function TestCommitAfterDelete (line 710) | func TestCommitAfterDelete(t *testing.T) {
function TestSecondCommitSplitsRoot (line 731) | func TestSecondCommitSplitsRoot(t *testing.T) {
function TestSecondCommitMultipleSplits (line 756) | func TestSecondCommitMultipleSplits(t *testing.T) {
function TestLargeAdd (line 784) | func TestLargeAdd(t *testing.T) {
function TestNodeInfiniteLoop (line 809) | func TestNodeInfiniteLoop(t *testing.T) {
function TestGenerativeAdds (line 826) | func TestGenerativeAdds(t *testing.T) {
function TestGenerativeDeletes (line 878) | func TestGenerativeDeletes(t *testing.T) {
function TestGenerativeOperations (line 918) | func TestGenerativeOperations(t *testing.T) {
function BenchmarkGetitems (line 971) | func BenchmarkGetitems(b *testing.B) {
function BenchmarkBulkAdd (line 996) | func BenchmarkBulkAdd(b *testing.B) {
FILE: btree/palm/action.go
type actions (line 27) | type actions
type action (line 29) | type action interface
type getAction (line 37) | type getAction struct
method complete (line 42) | func (ga *getAction) complete() {
method operation (line 46) | func (ga *getAction) operation() operation {
method keys (line 50) | func (ga *getAction) keys() common.Comparators {
method addNode (line 54) | func (ga *getAction) addNode(i int64, n *node) {
method nodes (line 58) | func (ga *getAction) nodes() []*node {
function newGetAction (line 62) | func newGetAction(keys common.Comparators) *getAction {
type insertAction (line 73) | type insertAction struct
method complete (line 79) | func (ia *insertAction) complete() {
method operation (line 83) | func (ia *insertAction) operation() operation {
method keys (line 87) | func (ia *insertAction) keys() common.Comparators {
method addNode (line 91) | func (ia *insertAction) addNode(i int64, n *node) {
method nodes (line 95) | func (ia *insertAction) nodes() []*node {
function newInsertAction (line 99) | func newInsertAction(keys common.Comparators) *insertAction {
type removeAction (line 111) | type removeAction struct
method operation (line 115) | func (ra *removeAction) operation() operation {
function newRemoveAction (line 119) | func newRemoveAction(keys common.Comparators) *removeAction {
type applyAction (line 125) | type applyAction struct
method operation (line 131) | func (aa *applyAction) operation() operation {
method nodes (line 135) | func (aa *applyAction) nodes() []*node {
method addNode (line 139) | func (aa *applyAction) addNode(i int64, n *node) {}
method keys (line 141) | func (aa *applyAction) keys() common.Comparators {
method complete (line 145) | func (aa *applyAction) complete() {
function newApplyAction (line 149) | func newApplyAction(fn func(common.Comparator) bool, start, stop common....
function minUint64 (line 160) | func minUint64(choices ...uint64) uint64 {
type interfaces (line 171) | type interfaces
function executeInterfacesInParallel (line 173) | func executeInterfacesInParallel(ifs interfaces, fn func(interface{})) {
function executeInterfacesInSerial (line 207) | func executeInterfacesInSerial(ifs interfaces, fn func(interface{})) {
FILE: btree/palm/interface.go
type BTree (line 51) | type BTree interface
FILE: btree/palm/key.go
function reverseKeys (line 21) | func reverseKeys(cmps common.Comparators) common.Comparators {
function chunkKeys (line 30) | func chunkKeys(keys common.Comparators, numParts int64) []common.Compara...
FILE: btree/palm/mock_test.go
type mockKey (line 20) | type mockKey
method Compare (line 22) | func (mk mockKey) Compare(other common.Comparator) int {
FILE: btree/palm/node.go
function getParent (line 26) | func getParent(parent *node, key common.Comparator) *node {
type nodes (line 36) | type nodes struct
method push (line 40) | func (ns *nodes) push(n *node) {
method splitAt (line 44) | func (ns *nodes) splitAt(i, capacity uint64) (*nodes, *nodes) {
method byPosition (line 55) | func (ns *nodes) byPosition(pos uint64) *node {
method insertAt (line 63) | func (ns *nodes) insertAt(i uint64, n *node) {
method replaceAt (line 69) | func (ns *nodes) replaceAt(i uint64, n *node) {
method len (line 73) | func (ns *nodes) len() uint64 {
function newNodes (line 77) | func newNodes(size uint64) *nodes {
type keys (line 83) | type keys struct
method splitAt (line 87) | func (ks *keys) splitAt(i, capacity uint64) (*keys, *keys) {
method len (line 98) | func (ks *keys) len() uint64 {
method byPosition (line 102) | func (ks *keys) byPosition(i uint64) common.Comparator {
method delete (line 109) | func (ks *keys) delete(k common.Comparator) common.Comparator {
method search (line 126) | func (ks *keys) search(key common.Comparator) uint64 {
method insert (line 134) | func (ks *keys) insert(key common.Comparator) (common.Comparator, uint...
method last (line 152) | func (ks *keys) last() common.Comparator {
method insertAt (line 156) | func (ks *keys) insertAt(i uint64, k common.Comparator) {
method withPosition (line 162) | func (ks *keys) withPosition(k common.Comparator) (common.Comparator, ...
function newKeys (line 174) | func newKeys(size uint64) *keys {
type node (line 180) | type node struct
method needsSplit (line 187) | func (n *node) needsSplit(ary uint64) bool {
method splitLeaf (line 191) | func (n *node) splitLeaf(i, capacity uint64) (common.Comparator, *node...
method splitInternal (line 204) | func (n *node) splitInternal(i, capacity uint64) (common.Comparator, *...
method split (line 219) | func (n *node) split(i, capacity uint64) (common.Comparator, *node, *n...
method search (line 227) | func (n *node) search(key common.Comparator) uint64 {
method searchNode (line 231) | func (n *node) searchNode(key common.Comparator) *node {
method key (line 237) | func (n *node) key() common.Comparator {
method print (line 241) | func (n *node) print(output *log.Logger) {
method Compare (line 261) | func (n *node) Compare(e common.Comparator) int {
function newNode (line 265) | func newNode(isLeaf bool, keys *keys, ns *nodes) *node {
FILE: btree/palm/tree.go
type operation (line 29) | type operation
constant get (line 32) | get operation = iota
constant add (line 33) | add
constant remove (line 34) | remove
constant apply (line 35) | apply
constant multiThreadAt (line 38) | multiThreadAt = 400
type keyBundle (line 40) | type keyBundle struct
method dispose (line 45) | func (kb *keyBundle) dispose(ptree *ptree) {
type ptree (line 53) | type ptree struct
method checkAndRun (line 71) | func (ptree *ptree) checkAndRun(action action) {
method init (line 119) | func (ptree *ptree) init(bufferSize, ary uint64) {
method newKeyBundle (line 137) | func (ptree *ptree) newKeyBundle(key common.Comparator) *keyBundle {
method operationRunner (line 150) | func (ptree *ptree) operationRunner(xns interfaces, threaded bool) {
method read (line 160) | func (ptree *ptree) read(action action) {
method fetchKeys (line 176) | func (ptree *ptree) fetchKeys(xns interfaces, inParallel bool) (map[*n...
method apply (line 207) | func (ptree *ptree) apply(n *node, aa *applyAction) {
method disposer (line 226) | func (ptree *ptree) disposer(wg *sync.WaitGroup) {
method fetchKeysInSerial (line 239) | func (ptree *ptree) fetchKeysInSerial(xns interfaces) {
method reset (line 266) | func (ptree *ptree) reset() {
method fetchKeysInParallel (line 276) | func (ptree *ptree) fetchKeysInParallel(xns []interface{}) {
method splitNode (line 336) | func (ptree *ptree) splitNode(n, parent *node, nodes *[]*node, keys *c...
method applyNode (line 355) | func (ptree *ptree) applyNode(n *node, adds, deletes []*keyBundle) {
method cleanMap (line 391) | func (ptree *ptree) cleanMap(op map[*node][]*keyBundle) {
method recursiveMutate (line 399) | func (ptree *ptree) recursiveMutate(adds, deletes map[*node][]*keyBund...
method Insert (line 488) | func (ptree *ptree) Insert(keys ...common.Comparator) {
method Delete (line 496) | func (ptree *ptree) Delete(keys ...common.Comparator) {
method Get (line 503) | func (ptree *ptree) Get(keys ...common.Comparator) common.Comparators {
method Len (line 511) | func (ptree *ptree) Len() uint64 {
method Query (line 518) | func (ptree *ptree) Query(start, stop common.Comparator) common.Compar...
method Dispose (line 531) | func (ptree *ptree) Dispose() {
method print (line 540) | func (ptree *ptree) print(output *log.Logger) {
function newTree (line 549) | func newTree(bufferSize, ary uint64) *ptree {
function New (line 558) | func New(bufferSize, ary uint64) BTree {
FILE: btree/palm/tree_test.go
function checkTree (line 31) | func checkTree(t testing.TB, tree *ptree) bool {
function checkNode (line 41) | func checkNode(t testing.TB, n *node) bool {
function getConsoleLogger (line 86) | func getConsoleLogger() *log.Logger {
function generateRandomKeys (line 90) | func generateRandomKeys(num int) common.Comparators {
function generateKeys (line 99) | func generateKeys(num int) common.Comparators {
function TestSimpleInsert (line 108) | func TestSimpleInsert(t *testing.T) {
function TestSimpleDelete (line 119) | func TestSimpleDelete(t *testing.T) {
function TestMultipleAdd (line 131) | func TestMultipleAdd(t *testing.T) {
function TestMultipleDelete (line 145) | func TestMultipleDelete(t *testing.T) {
function TestMultipleInsertCausesSplitOddAryReverseOrder (line 158) | func TestMultipleInsertCausesSplitOddAryReverseOrder(t *testing.T) {
function TestMultipleDeleteOddAryReverseOrder (line 171) | func TestMultipleDeleteOddAryReverseOrder(t *testing.T) {
function TestMultipleInsertCausesSplitOddAry (line 187) | func TestMultipleInsertCausesSplitOddAry(t *testing.T) {
function TestMultipleInsertCausesSplitOddAryRandomOrder (line 199) | func TestMultipleInsertCausesSplitOddAryRandomOrder(t *testing.T) {
function TestMultipleBulkInsertOddAry (line 211) | func TestMultipleBulkInsertOddAry(t *testing.T) {
function TestMultipleBulkInsertEvenAry (line 231) | func TestMultipleBulkInsertEvenAry(t *testing.T) {
function TestMultipleInsertCausesSplitEvenAryReverseOrder (line 250) | func TestMultipleInsertCausesSplitEvenAryReverseOrder(t *testing.T) {
function TestMultipleInsertCausesSplitEvenAry (line 263) | func TestMultipleInsertCausesSplitEvenAry(t *testing.T) {
function TestMultipleInsertCausesSplitEvenAryRandomOrder (line 275) | func TestMultipleInsertCausesSplitEvenAryRandomOrder(t *testing.T) {
function TestInsertOverwrite (line 287) | func TestInsertOverwrite(t *testing.T) {
function TestSimultaneousReadsAndWrites (line 299) | func TestSimultaneousReadsAndWrites(t *testing.T) {
function TestInsertAndDelete (line 326) | func TestInsertAndDelete(t *testing.T) {
function TestInsertAndDeletesWithSplits (line 354) | func TestInsertAndDeletesWithSplits(t *testing.T) {
function TestSimpleQuery (line 382) | func TestSimpleQuery(t *testing.T) {
function TestMultipleQuery (line 401) | func TestMultipleQuery(t *testing.T) {
function TestCrossNodeQuery (line 421) | func TestCrossNodeQuery(t *testing.T) {
function BenchmarkReadAndWrites (line 433) | func BenchmarkReadAndWrites(b *testing.B) {
function BenchmarkSimultaneousReadsAndWrites (line 449) | func BenchmarkSimultaneousReadsAndWrites(b *testing.B) {
function BenchmarkBulkAdd (line 477) | func BenchmarkBulkAdd(b *testing.B) {
function BenchmarkAdd (line 492) | func BenchmarkAdd(b *testing.B) {
function BenchmarkBulkAddToExisting (line 504) | func BenchmarkBulkAddToExisting(b *testing.B) {
function BenchmarkGet (line 520) | func BenchmarkGet(b *testing.B) {
function BenchmarkBulkGet (line 533) | func BenchmarkBulkGet(b *testing.B) {
function BenchmarkDelete (line 546) | func BenchmarkDelete(b *testing.B) {
function BenchmarkBulkDelete (line 559) | func BenchmarkBulkDelete(b *testing.B) {
function BenchmarkFindQuery (line 576) | func BenchmarkFindQuery(b *testing.B) {
function BenchmarkExecuteQuery (line 589) | func BenchmarkExecuteQuery(b *testing.B) {
FILE: btree/plus/btree.go
function keySearch (line 36) | func keySearch(keys keys, key Key) int {
type btree (line 53) | type btree struct
method insert (line 58) | func (tree *btree) insert(key Key) {
method Insert (line 79) | func (tree *btree) Insert(keys ...Key) {
method Iter (line 87) | func (tree *btree) Iter(key Key) Iterator {
method get (line 95) | func (tree *btree) get(key Key) Key {
method Get (line 111) | func (tree *btree) Get(keys ...Key) Keys {
method Len (line 121) | func (tree *btree) Len() uint64 {
function newBTree (line 125) | func newBTree(nodeSize uint64) *btree {
FILE: btree/plus/btree_test.go
function TestSearchKeys (line 26) | func TestSearchKeys(t *testing.T) {
function TestTreeInsert2_3_4 (line 44) | func TestTreeInsert2_3_4(t *testing.T) {
function TestTreeInsert3_4_5 (line 55) | func TestTreeInsert3_4_5(t *testing.T) {
function TestTreeInsertQuery2_3_4 (line 66) | func TestTreeInsertQuery2_3_4(t *testing.T) {
function TestTreeInsertQuery3_4_5 (line 78) | func TestTreeInsertQuery3_4_5(t *testing.T) {
function TestTreeInsertReverseOrder2_3_4 (line 90) | func TestTreeInsertReverseOrder2_3_4(t *testing.T) {
function TestTreeInsertReverseOrder3_4_5 (line 105) | func TestTreeInsertReverseOrder3_4_5(t *testing.T) {
function TestTreeInsert3_4_5_WithEndDuplicate (line 120) | func TestTreeInsert3_4_5_WithEndDuplicate(t *testing.T) {
function TestTreeInsert3_4_5_WithMiddleDuplicate (line 135) | func TestTreeInsert3_4_5_WithMiddleDuplicate(t *testing.T) {
function TestTreeInsert3_4_5WithEarlyDuplicate (line 150) | func TestTreeInsert3_4_5WithEarlyDuplicate(t *testing.T) {
function TestTreeInsert3_4_5WithDuplicateID (line 165) | func TestTreeInsert3_4_5WithDuplicateID(t *testing.T) {
function TestTreeInsert3_4_5MiddleQuery (line 179) | func TestTreeInsert3_4_5MiddleQuery(t *testing.T) {
function TestTreeInsert3_4_5LateQuery (line 191) | func TestTreeInsert3_4_5LateQuery(t *testing.T) {
function TestTreeInsert3_4_5AfterQuery (line 203) | func TestTreeInsert3_4_5AfterQuery(t *testing.T) {
function TestTreeInternalNodeSplit (line 215) | func TestTreeInternalNodeSplit(t *testing.T) {
function TestTreeInternalNodeSplitReverseOrder (line 227) | func TestTreeInternalNodeSplitReverseOrder(t *testing.T) {
function TestTreeInternalNodeSplitRandomOrder (line 241) | func TestTreeInternalNodeSplitRandomOrder(t *testing.T) {
function TestTreeRandomOrderQuery (line 261) | func TestTreeRandomOrderQuery(t *testing.T) {
function TestTreeGet (line 281) | func TestTreeGet(t *testing.T) {
function TestTreeGetNotFound (line 293) | func TestTreeGetNotFound(t *testing.T) {
function TestGetExactMatchesOnly (line 301) | func TestGetExactMatchesOnly(t *testing.T) {
function BenchmarkIteration (line 310) | func BenchmarkIteration(b *testing.B) {
function BenchmarkInsert (line 327) | func BenchmarkInsert(b *testing.B) {
function BenchmarkBulkAdd (line 340) | func BenchmarkBulkAdd(b *testing.B) {
function BenchmarkGet (line 352) | func BenchmarkGet(b *testing.B) {
function BenchmarkBulkAddToExisting (line 367) | func BenchmarkBulkAddToExisting(b *testing.B) {
function BenchmarkReadAndWrites (line 383) | func BenchmarkReadAndWrites(b *testing.B) {
function BenchmarkSimultaneousReadsAndWrites (line 399) | func BenchmarkSimultaneousReadsAndWrites(b *testing.B) {
FILE: btree/plus/interface.go
type Keys (line 20) | type Keys
type Key (line 22) | type Key interface
type Iterator (line 32) | type Iterator interface
FILE: btree/plus/iterator.go
constant iteratorExhausted (line 19) | iteratorExhausted = -2
type iterator (line 21) | type iterator struct
method Next (line 26) | func (iter *iterator) Next() bool {
method Value (line 44) | func (iter *iterator) Value() Key {
method exhaust (line 55) | func (iter *iterator) exhaust() keys {
function nilIterator (line 64) | func nilIterator() *iterator {
FILE: btree/plus/mock_test.go
function chunkKeys (line 19) | func chunkKeys(ks keys, numParts int64) []keys {
type mockKey (line 27) | type mockKey struct
method Compare (line 31) | func (mk *mockKey) Compare(other Key) int {
function newMockKey (line 43) | func newMockKey(value int) *mockKey {
FILE: btree/plus/node.go
function split (line 19) | func split(tree *btree, parent, child node) node {
type node (line 49) | type node interface
type nodes (line 59) | type nodes
method insertAt (line 61) | func (nodes *nodes) insertAt(i int, node node) {
method splitAt (line 72) | func (ns nodes) splitAt(i int) (nodes, nodes) {
type inode (line 80) | type inode struct
method search (line 85) | func (node *inode) search(key Key) int {
method find (line 89) | func (node *inode) find(key Key) *iterator {
method insert (line 104) | func (n *inode) insert(tree *btree, key Key) bool {
method needsSplit (line 131) | func (n *inode) needsSplit(nodeSize uint64) bool {
method split (line 135) | func (n *inode) split() (Key, node, node) {
function newInternalNode (line 157) | func newInternalNode(size uint64) *inode {
type lnode (line 164) | type lnode struct
method search (line 170) | func (node *lnode) search(key Key) int {
method insert (line 174) | func (lnode *lnode) insert(tree *btree, key Key) bool {
method find (line 196) | func (node *lnode) find(key Key) *iterator {
method split (line 216) | func (node *lnode) split() (Key, node, node) {
method needsSplit (line 239) | func (lnode *lnode) needsSplit(nodeSize uint64) bool {
function newLeafNode (line 243) | func newLeafNode(size uint64) *lnode {
type keys (line 249) | type keys
method search (line 251) | func (keys keys) search(key Key) int {
method insertAt (line 255) | func (keys *keys) insertAt(i int, key Key) {
method reverse (line 266) | func (keys keys) reverse() {
FILE: btree/plus/node_test.go
function constructMockPayloads (line 26) | func constructMockPayloads(num int) keys {
function constructMockKeys (line 35) | func constructMockKeys(num int) keys {
function constructRandomMockKeys (line 45) | func constructRandomMockKeys(num int) keys {
function constructMockNodes (line 54) | func constructMockNodes(num int) nodes {
function constructMockInternalNode (line 74) | func constructMockInternalNode(nodes nodes) *inode {
function TestLeafNodeInsert (line 91) | func TestLeafNodeInsert(t *testing.T) {
function TestDuplicateLeafNodeInsert (line 104) | func TestDuplicateLeafNodeInsert(t *testing.T) {
function TestMultipleLeafNodeInsert (line 115) | func TestMultipleLeafNodeInsert(t *testing.T) {
function TestLeafNodeSplitEvenNumber (line 133) | func TestLeafNodeSplitEvenNumber(t *testing.T) {
function TestLeafNodeSplitOddNumber (line 147) | func TestLeafNodeSplitOddNumber(t *testing.T) {
function TestTwoKeysLeafNodeSplit (line 161) | func TestTwoKeysLeafNodeSplit(t *testing.T) {
function TestLessThanTwoKeysSplit (line 175) | func TestLessThanTwoKeysSplit(t *testing.T) {
function TestInternalNodeSplit2_3_4 (line 188) | func TestInternalNodeSplit2_3_4(t *testing.T) {
function TestInternalNodeSplit3_4_5 (line 200) | func TestInternalNodeSplit3_4_5(t *testing.T) {
function TestInternalNodeLessThan3Keys (line 212) | func TestInternalNodeLessThan3Keys(t *testing.T) {
FILE: cache/cache.go
type Cache (line 9) | type Cache interface
type Item (line 25) | type Item interface
type cached (line 31) | type cached struct
method setElementIfNotNil (line 37) | func (c *cached) setElementIfNotNil(element *list.Element) {
type cache (line 44) | type cache struct
method Get (line 101) | func (c *cache) Get(keys ...string) []Item {
method Put (line 119) | func (c *cache) Put(key string, item Item) {
method Remove (line 137) | func (c *cache) Remove(keys ...string) {
method Size (line 146) | func (c *cache) Size() uint64 {
method ensureCapacity (line 156) | func (c *cache) ensureCapacity(toAdd uint64) {
method remove (line 167) | func (c *cache) remove(key string) {
method noop (line 176) | func (c *cache) noop(string) *list.Element { return nil }
method record (line 179) | func (c *cache) record(key string) *list.Element {
type CacheOption (line 55) | type CacheOption
type Policy (line 58) | type Policy
constant LeastRecentlyAdded (line 62) | LeastRecentlyAdded Policy = iota
constant LeastRecentlyUsed (line 64) | LeastRecentlyUsed
function EvictionPolicy (line 69) | func EvictionPolicy(policy Policy) CacheOption {
function New (line 85) | func New(capacity uint64, options ...CacheOption) Cache {
FILE: cache/cache_test.go
function TestEvictionPolicy (line 10) | func TestEvictionPolicy(t *testing.T) {
function TestNew (line 24) | func TestNew(t *testing.T) {
type testItem (line 43) | type testItem
method Size (line 45) | func (ti testItem) Size() uint64 {
function TestPutGetRemoveSize (line 49) | func TestPutGetRemoveSize(t *testing.T) {
FILE: common/interface.go
type Comparator (line 21) | type Comparator interface
type Comparators (line 29) | type Comparators
FILE: fibheap/fibheap.go
type FloatingFibonacciHeap (line 83) | type FloatingFibonacciHeap struct
method Enqueue (line 118) | func (heap *FloatingFibonacciHeap) Enqueue(priority float64) *Entry {
method Min (line 128) | func (heap *FloatingFibonacciHeap) Min() (*Entry, error) {
method IsEmpty (line 136) | func (heap *FloatingFibonacciHeap) IsEmpty() bool {
method Size (line 141) | func (heap *FloatingFibonacciHeap) Size() uint {
method DequeueMin (line 147) | func (heap *FloatingFibonacciHeap) DequeueMin() (*Entry, error) {
method DecreaseKey (line 251) | func (heap *FloatingFibonacciHeap) DecreaseKey(node *Entry, newPriorit...
method Delete (line 271) | func (heap *FloatingFibonacciHeap) Delete(node *Entry) error {
method Merge (line 291) | func (heap *FloatingFibonacciHeap) Merge(other *FloatingFibonacciHeap)...
type Entry (line 90) | type Entry struct
type EmptyHeapError (line 100) | type EmptyHeapError
method Error (line 102) | func (e EmptyHeapError) Error() string {
type NilError (line 108) | type NilError
method Error (line 110) | func (e NilError) Error() string {
function NewFloatFibHeap (line 115) | func NewFloatFibHeap() FloatingFibonacciHeap { return FloatingFibonacciH...
function newEntry (line 317) | func newEntry(priority float64) *Entry {
function mergeLists (line 329) | func mergeLists(one, two *Entry) *Entry {
function decreaseKeyUnchecked (line 351) | func decreaseKeyUnchecked(heap *FloatingFibonacciHeap, node *Entry, prio...
function cutNode (line 363) | func cutNode(heap *FloatingFibonacciHeap, node *Entry) {
FILE: fibheap/fibheap_examples_test.go
constant SomeNumber (line 9) | SomeNumber float64 = 15.5
constant SomeSmallerNumber (line 10) | SomeSmallerNumber float64 = -10.1
constant SomeLargerNumber (line 11) | SomeLargerNumber float64 = 112.211
function ExampleFloatingFibonacciHeap_Enqueue (line 13) | func ExampleFloatingFibonacciHeap_Enqueue() {
function ExampleFloatingFibonacciHeap_Min (line 22) | func ExampleFloatingFibonacciHeap_Min() {
function ExampleFloatingFibonacciHeap_IsEmpty (line 31) | func ExampleFloatingFibonacciHeap_IsEmpty() {
function ExampleFloatingFibonacciHeap_Size (line 41) | func ExampleFloatingFibonacciHeap_Size() {
function ExampleFloatingFibonacciHeap_DequeueMin (line 51) | func ExampleFloatingFibonacciHeap_DequeueMin() {
function ExampleFloatingFibonacciHeap_DecreaseKey (line 60) | func ExampleFloatingFibonacciHeap_DecreaseKey() {
function ExampleFloatingFibonacciHeap_Delete (line 73) | func ExampleFloatingFibonacciHeap_Delete() {
function ExampleFloatingFibonacciHeap_Merge (line 87) | func ExampleFloatingFibonacciHeap_Merge() {
FILE: fibheap/fibheap_single_example_test.go
constant SomeNumberAround0 (line 9) | SomeNumberAround0 float64 = -0.001
constant SomeLargerNumberAround15 (line 10) | SomeLargerNumberAround15 float64 = 15.77
constant SomeNumberAroundMinus1000 (line 11) | SomeNumberAroundMinus1000 float64 = -1002.2001
constant SomeNumberAroundMinus1003 (line 12) | SomeNumberAroundMinus1003 float64 = -1003.4
function Example (line 14) | func Example() {
FILE: fibheap/fibheap_test.go
constant Seq1FirstMinimum (line 68) | Seq1FirstMinimum float64 = -9990847539.012056
constant Seq1ThirdMinimum (line 69) | Seq1ThirdMinimum float64 = -9969381716.563528
constant Seq1FifthMinimum (line 70) | Seq1FifthMinimum float64 = -9453697711.29756
constant Seq1LastMinimum (line 71) | Seq1LastMinimum float64 = 9981219597.001732
constant Seq2DecreaseKey1Orig (line 80) | Seq2DecreaseKey1Orig float64 = 9913821013.519611
constant Seq2DecreaseKey1Trgt (line 81) | Seq2DecreaseKey1Trgt float64 = -8722989752.449871
constant Seq2DecreaseKey2Orig (line 82) | Seq2DecreaseKey2Orig float64 = 9866088144.060883
constant Seq2DecreaseKey2Trgt (line 83) | Seq2DecreaseKey2Trgt float64 = -9698869735.322557
constant Seq2DecreaseKey3Orig (line 84) | Seq2DecreaseKey3Orig float64 = 9204710651.257133
constant Seq2DecreaseKey3Trgt (line 85) | Seq2DecreaseKey3Trgt float64 = -9804710651.257133
function TestEnqueueDequeueMin (line 126) | func TestEnqueueDequeueMin(t *testing.T) {
function TestFibHeap_Enqueue_Min (line 152) | func TestFibHeap_Enqueue_Min(t *testing.T) {
function TestFibHeap_Min_EmptyHeap (line 163) | func TestFibHeap_Min_EmptyHeap(t *testing.T) {
function TestFibHeap_DequeueMin_EmptyHeap (line 178) | func TestFibHeap_DequeueMin_EmptyHeap(t *testing.T) {
function TestEnqueueDecreaseKey (line 187) | func TestEnqueueDecreaseKey(t *testing.T) {
function TestFibHeap_DecreaseKey_EmptyHeap (line 221) | func TestFibHeap_DecreaseKey_EmptyHeap(t *testing.T) {
function TestFibHeap_DecreaseKey_NilNode (line 235) | func TestFibHeap_DecreaseKey_NilNode(t *testing.T) {
function TestFibHeap_DecreaseKey_LargerNewPriority (line 245) | func TestFibHeap_DecreaseKey_LargerNewPriority(t *testing.T) {
function TestEnqueueDelete (line 254) | func TestEnqueueDelete(t *testing.T) {
function TestFibHeap_Delete_EmptyHeap (line 290) | func TestFibHeap_Delete_EmptyHeap(t *testing.T) {
function TestFibHeap_Delete_NilNode (line 302) | func TestFibHeap_Delete_NilNode(t *testing.T) {
function TestMerge (line 310) | func TestMerge(t *testing.T) {
function TestFibHeap_Merge_NilHeap (line 332) | func TestFibHeap_Merge_NilHeap(t *testing.T) {
function BenchmarkFibHeap_Enqueue (line 361) | func BenchmarkFibHeap_Enqueue(b *testing.B) {
function BenchmarkFibHeap_DequeueMin (line 371) | func BenchmarkFibHeap_DequeueMin(b *testing.B) {
function BenchmarkFibHeap_DecreaseKey (line 389) | func BenchmarkFibHeap_DecreaseKey(b *testing.B) {
function BenchmarkFibHeap_Delete (line 413) | func BenchmarkFibHeap_Delete(b *testing.B) {
function BenchmarkFibHeap_Merge (line 434) | func BenchmarkFibHeap_Merge(b *testing.B) {
FILE: futures/futures.go
type Completer (line 34) | type Completer
type Future (line 42) | type Future struct
method GetResult (line 52) | func (f *Future) GetResult() (interface{}, error) {
method HasResult (line 65) | func (f *Future) HasResult() bool {
method setItem (line 72) | func (f *Future) setItem(item interface{}, err error) {
function listenForResult (line 81) | func listenForResult(f *Future, ch Completer, timeout time.Duration, wg ...
function New (line 97) | func New(completer Completer, timeout time.Duration) *Future {
FILE: futures/futures_test.go
function TestWaitOnGetResult (line 27) | func TestWaitOnGetResult(t *testing.T) {
function TestHasResult (line 52) | func TestHasResult(t *testing.T) {
function TestTimeout (line 71) | func TestTimeout(t *testing.T) {
function BenchmarkFuture (line 81) | func BenchmarkFuture(b *testing.B) {
FILE: futures/selectable.go
type Selectable (line 34) | type Selectable struct
method wchan (line 49) | func (f *Selectable) wchan() <-chan struct{} {
method WaitChan (line 60) | func (f *Selectable) WaitChan() <-chan struct{} {
method GetResult (line 69) | func (f *Selectable) GetResult() (interface{}, error) {
method Fill (line 78) | func (f *Selectable) Fill(v interface{}, e error) error {
method SetValue (line 95) | func (f *Selectable) SetValue(v interface{}) error {
method SetError (line 100) | func (f *Selectable) SetError(e error) {
method Cancel (line 105) | func (f *Selectable) Cancel() {
function NewSelectable (line 45) | func NewSelectable() *Selectable {
function init (line 111) | func init() {
FILE: futures/selectable_test.go
function TestSelectableGetResult (line 29) | func TestSelectableGetResult(t *testing.T) {
function TestSelectableSetError (line 53) | func TestSelectableSetError(t *testing.T) {
function BenchmarkSelectable (line 67) | func BenchmarkSelectable(b *testing.B) {
FILE: graph/simple.go
type SimpleGraph (line 45) | type SimpleGraph struct
method V (line 52) | func (g *SimpleGraph) V() int {
method E (line 60) | func (g *SimpleGraph) E() int {
method AddEdge (line 68) | func (g *SimpleGraph) AddEdge(v, w interface{}) error {
method Adj (line 90) | func (g *SimpleGraph) Adj(v interface{}) ([]interface{}, error) {
method Degree (line 109) | func (g *SimpleGraph) Degree(v interface{}) (int, error) {
method addVertex (line 120) | func (g *SimpleGraph) addVertex(v interface{}) {
function NewSimpleGraph (line 130) | func NewSimpleGraph() *SimpleGraph {
FILE: graph/simple_test.go
function TestV (line 25) | func TestV(t *testing.T) {
function TestE (line 52) | func TestE(t *testing.T) {
function TestDegree (line 80) | func TestDegree(t *testing.T) {
function TestAddEdge (line 146) | func TestAddEdge(t *testing.T) {
function TestAdj (line 170) | func TestAdj(t *testing.T) {
FILE: hashmap/fastinteger/hash.go
function hash (line 6) | func hash(key uint64) uint64 {
FILE: hashmap/fastinteger/hash_test.go
function TestHash (line 13) | func TestHash(t *testing.T) {
function BenchmarkHash (line 20) | func BenchmarkHash(b *testing.B) {
function BenchmarkFnvHash (line 38) | func BenchmarkFnvHash(b *testing.B) {
FILE: hashmap/fastinteger/hashmap.go
constant ratio (line 23) | ratio = .75
function roundUp (line 27) | func roundUp(v uint64) uint64 {
type packet (line 39) | type packet struct
type packets (line 43) | type packets
method find (line 45) | func (packets packets) find(key uint64) uint64 {
method set (line 55) | func (packets packets) set(packet *packet) {
method get (line 65) | func (packets packets) get(key uint64) (uint64, bool) {
method delete (line 74) | func (packets packets) delete(key uint64) bool {
method exists (line 90) | func (packets packets) exists(key uint64) bool {
type FastIntegerHashMap (line 100) | type FastIntegerHashMap struct
method rebuild (line 109) | func (fi *FastIntegerHashMap) rebuild() {
method Get (line 123) | func (fi *FastIntegerHashMap) Get(key uint64) (uint64, bool) {
method Set (line 128) | func (fi *FastIntegerHashMap) Set(key, value uint64) {
method Exists (line 139) | func (fi *FastIntegerHashMap) Exists(key uint64) bool {
method Delete (line 145) | func (fi *FastIntegerHashMap) Delete(key uint64) {
method Len (line 152) | func (fi *FastIntegerHashMap) Len() uint64 {
method Cap (line 157) | func (fi *FastIntegerHashMap) Cap() uint64 {
function New (line 163) | func New(hint uint64) *FastIntegerHashMap {
FILE: hashmap/fastinteger/hashmap_test.go
function generateKeys (line 11) | func generateKeys(num int) []uint64 {
function TestRoundUp (line 23) | func TestRoundUp(t *testing.T) {
function TestInsert (line 34) | func TestInsert(t *testing.T) {
function TestInsertOverwrite (line 46) | func TestInsertOverwrite(t *testing.T) {
function TestGet (line 58) | func TestGet(t *testing.T) {
function TestMultipleInserts (line 66) | func TestMultipleInserts(t *testing.T) {
function TestRebuild (line 78) | func TestRebuild(t *testing.T) {
function TestDelete (line 93) | func TestDelete(t *testing.T) {
function TestDeleteAll (line 109) | func TestDeleteAll(t *testing.T) {
function TestDeleteCollision (line 124) | func TestDeleteCollision(t *testing.T) {
function BenchmarkInsert (line 141) | func BenchmarkInsert(b *testing.B) {
function BenchmarkGoMapInsert (line 156) | func BenchmarkGoMapInsert(b *testing.B) {
function BenchmarkExists (line 171) | func BenchmarkExists(b *testing.B) {
function BenchmarkGoMapExists (line 189) | func BenchmarkGoMapExists(b *testing.B) {
function BenchmarkDelete (line 212) | func BenchmarkDelete(b *testing.B) {
function BenchmarkGoDelete (line 234) | func BenchmarkGoDelete(b *testing.B) {
function BenchmarkInsertWithExpand (line 256) | func BenchmarkInsertWithExpand(b *testing.B) {
function BenchmarkGoInsertWithExpand (line 275) | func BenchmarkGoInsertWithExpand(b *testing.B) {
FILE: list/persistent.go
type PersistentList (line 35) | type PersistentList interface
type emptyList (line 78) | type emptyList struct
method Head (line 82) | func (e *emptyList) Head() (interface{}, bool) {
method Tail (line 88) | func (e *emptyList) Tail() (PersistentList, bool) {
method IsEmpty (line 93) | func (e *emptyList) IsEmpty() bool {
method Length (line 98) | func (e *emptyList) Length() uint {
method Add (line 103) | func (e *emptyList) Add(head interface{}) PersistentList {
method Insert (line 109) | func (e *emptyList) Insert(val interface{}, pos uint) (PersistentList,...
method Get (line 118) | func (e *emptyList) Get(pos uint) (interface{}, bool) {
method Remove (line 124) | func (e *emptyList) Remove(pos uint) (PersistentList, error) {
method Find (line 130) | func (e *emptyList) Find(func(interface{}) bool) (interface{}, bool) {
method FindIndex (line 136) | func (e *emptyList) FindIndex(func(interface{}) bool) int {
method Map (line 142) | func (e *emptyList) Map(func(interface{}) interface{}) []interface{} {
type list (line 146) | type list struct
method Head (line 153) | func (l *list) Head() (interface{}, bool) {
method Tail (line 159) | func (l *list) Tail() (PersistentList, bool) {
method IsEmpty (line 164) | func (l *list) IsEmpty() bool {
method Length (line 169) | func (l *list) Length() uint {
method Add (line 183) | func (l *list) Add(head interface{}) PersistentList {
method Insert (line 189) | func (l *list) Insert(val interface{}, pos uint) (PersistentList, erro...
method Get (line 202) | func (l *list) Get(pos uint) (interface{}, bool) {
method Remove (line 211) | func (l *list) Remove(pos uint) (PersistentList, error) {
method Find (line 226) | func (l *list) Find(pred func(interface{}) bool) (interface{}, bool) {
method FindIndex (line 235) | func (l *list) FindIndex(pred func(interface{}) bool) int {
method Map (line 253) | func (l *list) Map(f func(interface{}) interface{}) []interface{} {
FILE: list/persistent_test.go
function TestEmptyList (line 25) | func TestEmptyList(t *testing.T) {
function TestAdd (line 38) | func TestAdd(t *testing.T) {
function TestInsertAndGet (line 92) | func TestInsertAndGet(t *testing.T) {
function TestRemove (line 124) | func TestRemove(t *testing.T) {
function TestFind (line 227) | func TestFind(t *testing.T) {
function TestFindIndex (line 250) | func TestFindIndex(t *testing.T) {
function TestLength (line 270) | func TestLength(t *testing.T) {
function TestMap (line 280) | func TestMap(t *testing.T) {
FILE: mock/batcher.go
type Batcher (line 27) | type Batcher struct
method Put (line 32) | func (m *Batcher) Put(items interface{}) error {
method Get (line 40) | func (m *Batcher) Get() ([]interface{}, error) {
method Flush (line 45) | func (m *Batcher) Flush() error {
method Dispose (line 50) | func (m *Batcher) Dispose() {
method IsDisposed (line 54) | func (m *Batcher) IsDisposed() bool {
FILE: mock/rangetree.go
type RangeTree (line 9) | type RangeTree struct
method Add (line 15) | func (m *RangeTree) Add(entries ...rangetree.Entry) rangetree.Entries {
method Len (line 25) | func (m *RangeTree) Len() uint64 {
method Delete (line 29) | func (m *RangeTree) Delete(entries ...rangetree.Entry) rangetree.Entri...
method Query (line 33) | func (m *RangeTree) Query(interval rangetree.Interval) rangetree.Entri...
method InsertAtDimension (line 43) | func (m *RangeTree) InsertAtDimension(dimension uint64, index,
method Apply (line 50) | func (m *RangeTree) Apply(interval rangetree.Interval, fn func(rangetr...
method Get (line 54) | func (m *RangeTree) Get(entries ...rangetree.Entry) rangetree.Entries {
FILE: numerics/hilbert/hilbert.go
constant n (line 37) | n = 1 << 31
function boolToInt (line 39) | func boolToInt(value bool) int32 {
function rotate (line 47) | func rotate(n, rx, ry int32, x, y *int32) {
function Encode (line 62) | func Encode(x, y int32) int64 {
function Decode (line 77) | func Decode(h int64) (int32, int32) {
FILE: numerics/hilbert/hilbert_test.go
function TestHilbert (line 25) | func TestHilbert(t *testing.T) {
function TestHilbertAtMaxRange (line 51) | func TestHilbertAtMaxRange(t *testing.T) {
function BenchmarkEncode (line 59) | func BenchmarkEncode(b *testing.B) {
function BenchmarkDecode (line 65) | func BenchmarkDecode(b *testing.B) {
FILE: numerics/optimization/global.go
type pbs (line 8) | type pbs
method calculateProbabilities (line 43) | func (pbs pbs) calculateProbabilities(bestGuess *nmVertex, sigma float...
method sort (line 49) | func (pbs pbs) sort() {
method Less (line 53) | func (pbs pbs) Less(i, j int) bool {
method Swap (line 57) | func (pbs pbs) Swap(i, j int) {
method Len (line 61) | func (pbs pbs) Len() int {
type vertexProbabilityBundle (line 10) | type vertexProbabilityBundle struct
function calculateVVP (line 26) | func calculateVVP(guess, vertex *nmVertex, sigma float64) float64 {
function calculateSigma (line 39) | func calculateSigma(dimensions, guesses int) float64 {
type results (line 67) | type results struct
method search (line 79) | func (results *results) search(result *nmVertex) int {
method exists (line 85) | func (results *results) exists(result *nmVertex, hint int) bool {
method insert (line 104) | func (results *results) insert(vertex *nmVertex) {
method grab (line 120) | func (results *results) grab(num int) vertices {
method reSort (line 145) | func (results *results) reSort(vertex *nmVertex) {
function newResults (line 154) | func newResults(guess *nmVertex, config NelderMeadConfiguration, num int...
FILE: numerics/optimization/nelder_mead.go
constant alpha (line 12) | alpha = 1
constant beta (line 13) | beta = 2
constant gamma (line 14) | gamma = .5
constant sigma (line 15) | sigma = .5
constant delta (line 16) | delta = .0001
constant maxRuns (line 17) | maxRuns = 130
constant maxIterations (line 18) | maxIterations = 5
function generateRandomVerticesFromGuess (line 29) | func generateRandomVerticesFromGuess(guess *nmVertex, num int) vertices {
function isInf (line 84) | func isInf(num float64) bool {
function findMin (line 88) | func findMin(vertices ...*nmVertex) *nmVertex {
function findMidpoint (line 101) | func findMidpoint(vertices ...*nmVertex) *nmVertex {
function determineDistance (line 121) | func determineDistance(value, target float64) float64 {
type vertices (line 131) | type vertices
method evaluate (line 135) | func (vertices vertices) evaluate(config NelderMeadConfiguration) {
method sort (line 143) | func (vertices vertices) sort(config NelderMeadConfiguration) {
method String (line 180) | func (vertices vertices) String() string {
type sorter (line 151) | type sorter struct
method sort (line 156) | func (sorter sorter) sort() {
method Less (line 166) | func (sorter sorter) Less(i, j int) bool {
method Len (line 170) | func (sorter sorter) Len() int {
method Swap (line 174) | func (sorter sorter) Swap(i, j int) {
type NelderMeadConfiguration (line 194) | type NelderMeadConfiguration struct
type nmVertex (line 215) | type nmVertex struct
method evaluate (line 231) | func (nm *nmVertex) evaluate(config NelderMeadConfiguration) {
method add (line 236) | func (nm *nmVertex) add(other *nmVertex) *nmVertex {
method multiply (line 247) | func (nm *nmVertex) multiply(scalar float64) *nmVertex {
method subtract (line 258) | func (nm *nmVertex) subtract(other *nmVertex) *nmVertex {
method less (line 279) | func (nm *nmVertex) less(config NelderMeadConfiguration, other *nmVert...
method equal (line 290) | func (nm *nmVertex) equal(config NelderMeadConfiguration, other *nmVer...
method euclideanDistance (line 301) | func (nm *nmVertex) euclideanDistance(other *nmVertex) float64 {
method equalToVertex (line 315) | func (nm *nmVertex) equalToVertex(other *nmVertex) bool {
method approximatelyEqualToVertex (line 331) | func (nm *nmVertex) approximatelyEqualToVertex(other *nmVertex) bool {
type nelderMead (line 335) | type nelderMead struct
method evaluateWithConstraints (line 346) | func (nm *nelderMead) evaluateWithConstraints(vertices vertices, verte...
method reflect (line 365) | func (nm *nelderMead) reflect(vertices vertices, midpoint *nmVertex) *...
method expand (line 372) | func (nm *nelderMead) expand(vertices vertices, midpoint, reflection *...
method lastDimensionVertex (line 382) | func (nm *nelderMead) lastDimensionVertex(vertices vertices) *nmVertex {
method lastVertex (line 389) | func (nm *nelderMead) lastVertex(vertices vertices) *nmVertex {
method outsideContract (line 393) | func (nm *nelderMead) outsideContract(vertices vertices, midpoint, ref...
method insideContract (line 400) | func (nm *nelderMead) insideContract(vertices vertices, midpoint, refl...
method shrink (line 407) | func (nm *nelderMead) shrink(vertices vertices) {
method checkIteration (line 419) | func (nm *nelderMead) checkIteration(vertices vertices) bool {
method evaluate (line 454) | func (nm *nelderMead) evaluate() {
function newNelderMead (line 542) | func newNelderMead(config NelderMeadConfiguration) *nelderMead {
function NelderMead (line 555) | func NelderMead(config NelderMeadConfiguration) []float64 {
FILE: numerics/optimization/nelder_mead_test.go
function TestNelderMead (line 10) | func TestNelderMead(t *testing.T) {
function TestNelderMeadPolynomial (line 24) | func TestNelderMeadPolynomial(t *testing.T) {
function TestNelderMeadPolynomialMin (line 42) | func TestNelderMeadPolynomialMin(t *testing.T) {
function TestNelderMeadPolynomialMax (line 60) | func TestNelderMeadPolynomialMax(t *testing.T) {
function TestNelderMeadConstrained (line 77) | func TestNelderMeadConstrained(t *testing.T) {
function TestNelderMeadConstrainedBadGuess (line 125) | func TestNelderMeadConstrainedBadGuess(t *testing.T) {
FILE: queue/mock_test.go
type mockItem (line 19) | type mockItem
method Compare (line 21) | func (mi mockItem) Compare(other Item) int {
FILE: queue/priority_queue.go
type Item (line 30) | type Item interface
type priorityItems (line 40) | type priorityItems
method swap (line 42) | func (items *priorityItems) swap(i, j int) {
method pop (line 46) | func (items *priorityItems) pop() Item {
method get (line 76) | func (items *priorityItems) get(number int) []Item {
method push (line 89) | func (items *priorityItems) push(item Item) {
type PriorityQueue (line 107) | type PriorityQueue struct
method Put (line 118) | func (pq *PriorityQueue) Put(items ...Item) error {
method Get (line 159) | func (pq *PriorityQueue) Get(number int) ([]Item, error) {
method Peek (line 206) | func (pq *PriorityQueue) Peek() Item {
method Empty (line 217) | func (pq *PriorityQueue) Empty() bool {
method Len (line 225) | func (pq *PriorityQueue) Len() int {
method Disposed (line 233) | func (pq *PriorityQueue) Disposed() bool {
method Dispose (line 242) | func (pq *PriorityQueue) Dispose() {
function NewPriorityQueue (line 260) | func NewPriorityQueue(hint int, allowDuplicates bool) *PriorityQueue {
FILE: queue/priority_queue_test.go
function TestPriorityPut (line 26) | func TestPriorityPut(t *testing.T) {
function TestPriorityGet (line 43) | func TestPriorityGet(t *testing.T) {
function TestAddEmptyPriorityPut (line 86) | func TestAddEmptyPriorityPut(t *testing.T) {
function TestPriorityGetNonPositiveNumber (line 94) | func TestPriorityGetNonPositiveNumber(t *testing.T) {
function TestPriorityEmpty (line 114) | func TestPriorityEmpty(t *testing.T) {
function TestPriorityGetEmpty (line 123) | func TestPriorityGetEmpty(t *testing.T) {
function TestMultiplePriorityGetEmpty (line 141) | func TestMultiplePriorityGetEmpty(t *testing.T) {
function TestEmptyPriorityGetWithDispose (line 177) | func TestEmptyPriorityGetWithDispose(t *testing.T) {
function TestPriorityGetPutDisposed (line 199) | func TestPriorityGetPutDisposed(t *testing.T) {
function BenchmarkPriorityQueue (line 210) | func BenchmarkPriorityQueue(b *testing.B) {
function TestPriorityPeek (line 234) | func TestPriorityPeek(t *testing.T) {
function TestInsertDuplicate (line 241) | func TestInsertDuplicate(t *testing.T) {
function TestAllowDuplicates (line 249) | func TestAllowDuplicates(t *testing.T) {
FILE: queue/queue.go
type waiters (line 61) | type waiters
method get (line 63) | func (w *waiters) get() *sema {
method put (line 75) | func (w *waiters) put(sema *sema) {
method remove (line 79) | func (w *waiters) remove(sema *sema) {
type items (line 94) | type items
method get (line 96) | func (items *items) get(number int64) []interface{} {
method peek (line 113) | func (items *items) peek() (interface{}, bool) {
method getUntil (line 123) | func (items *items) getUntil(checker func(item interface{}) bool) []in...
type sema (line 148) | type sema struct
function newSema (line 153) | func newSema() *sema {
type Queue (line 162) | type Queue struct
method Put (line 170) | func (q *Queue) Put(items ...interface{}) error {
method Get (line 208) | func (q *Queue) Get(number int64) ([]interface{}, error) {
method Poll (line 217) | func (q *Queue) Poll(number int64, timeout time.Duration) ([]interface...
method Peek (line 274) | func (q *Queue) Peek() (interface{}, error) {
method TakeUntil (line 293) | func (q *Queue) TakeUntil(checker func(item interface{}) bool) ([]inte...
method Empty (line 311) | func (q *Queue) Empty() bool {
method Len (line 319) | func (q *Queue) Len() int64 {
method Disposed (line 328) | func (q *Queue) Disposed() bool {
method Dispose (line 338) | func (q *Queue) Dispose() []interface{} {
function New (line 362) | func New(hint int64) *Queue {
function ExecuteInParallel (line 372) | func ExecuteInParallel(q *Queue, fn func(interface{})) {
FILE: queue/queue_test.go
function TestPut (line 28) | func TestPut(t *testing.T) {
function TestGet (line 52) | func TestGet(t *testing.T) {
function TestPoll (line 85) | func TestPoll(t *testing.T) {
function TestPollNoMemoryLeak (line 128) | func TestPollNoMemoryLeak(t *testing.T) {
function TestAddEmptyPut (line 140) | func TestAddEmptyPut(t *testing.T) {
function TestGetNonPositiveNumber (line 150) | func TestGetNonPositiveNumber(t *testing.T) {
function TestEmpty (line 164) | func TestEmpty(t *testing.T) {
function TestGetEmpty (line 177) | func TestGetEmpty(t *testing.T) {
function TestMultipleGetEmpty (line 193) | func TestMultipleGetEmpty(t *testing.T) {
function TestDispose (line 228) | func TestDispose(t *testing.T) {
function TestEmptyGetWithDispose (line 248) | func TestEmptyGetWithDispose(t *testing.T) {
function TestDisposeAfterEmptyPoll (line 271) | func TestDisposeAfterEmptyPoll(t *testing.T) {
function TestGetPutDisposed (line 284) | func TestGetPutDisposed(t *testing.T) {
function BenchmarkQueue (line 296) | func BenchmarkQueue(b *testing.B) {
function BenchmarkChannel (line 320) | func BenchmarkChannel(b *testing.B) {
function TestPeek (line 344) | func TestPeek(t *testing.T) {
function TestPeekOnDisposedQueue (line 361) | func TestPeekOnDisposedQueue(t *testing.T) {
function TestTakeUntil (line 370) | func TestTakeUntil(t *testing.T) {
function TestTakeUntilEmptyQueue (line 385) | func TestTakeUntilEmptyQueue(t *testing.T) {
function TestTakeUntilThenGet (line 399) | func TestTakeUntilThenGet(t *testing.T) {
function TestTakeUntilNoMatches (line 411) | func TestTakeUntilNoMatches(t *testing.T) {
function TestTakeUntilOnDisposedQueue (line 423) | func TestTakeUntilOnDisposedQueue(t *testing.T) {
function TestWaiters (line 434) | func TestWaiters(t *testing.T) {
function TestExecuteInParallel (line 496) | func TestExecuteInParallel(t *testing.T) {
function TestExecuteInParallelEmptyQueue (line 513) | func TestExecuteInParallelEmptyQueue(t *testing.T) {
function BenchmarkQueuePut (line 522) | func BenchmarkQueuePut(b *testing.B) {
function BenchmarkQueueGet (line 541) | func BenchmarkQueueGet(b *testing.B) {
function BenchmarkQueuePoll (line 564) | func BenchmarkQueuePoll(b *testing.B) {
function BenchmarkExecuteInParallel (line 586) | func BenchmarkExecuteInParallel(b *testing.B) {
FILE: queue/ring.go
function roundUp (line 27) | func roundUp(v uint64) uint64 {
type node (line 39) | type node struct
type nodes (line 44) | type nodes
type RingBuffer (line 52) | type RingBuffer struct
method init (line 63) | func (rb *RingBuffer) init(size uint64) {
method Put (line 75) | func (rb *RingBuffer) Put(item interface{}) error {
method Offer (line 83) | func (rb *RingBuffer) Offer(item interface{}) (bool, error) {
method put (line 87) | func (rb *RingBuffer) put(item interface{}, offer bool) (bool, error) {
method Get (line 125) | func (rb *RingBuffer) Get() (interface{}, error) {
method Poll (line 134) | func (rb *RingBuffer) Poll(timeout time.Duration) (interface{}, error) {
method Len (line 175) | func (rb *RingBuffer) Len() uint64 {
method Cap (line 180) | func (rb *RingBuffer) Cap() uint64 {
method Dispose (line 187) | func (rb *RingBuffer) Dispose() {
method IsDisposed (line 193) | func (rb *RingBuffer) IsDisposed() bool {
function NewRingBuffer (line 199) | func NewRingBuffer(size uint64) *RingBuffer {
FILE: queue/ring_test.go
function TestRingInsert (line 28) | func TestRingInsert(t *testing.T) {
function TestRingMultipleInserts (line 45) | func TestRingMultipleInserts(t *testing.T) {
function TestIntertwinedGetAndPut (line 73) | func TestIntertwinedGetAndPut(t *testing.T) {
function TestPutToFull (line 100) | func TestPutToFull(t *testing.T) {
function TestOffer (line 132) | func TestOffer(t *testing.T) {
function TestRingGetEmpty (line 153) | func TestRingGetEmpty(t *testing.T) {
function TestRingPollEmpty (line 180) | func TestRingPollEmpty(t *testing.T) {
function TestRingPoll (line 187) | func TestRingPoll(t *testing.T) {
function TestRingLen (line 228) | func TestRingLen(t *testing.T) {
function TestDisposeOnGet (line 247) | func TestDisposeOnGet(t *testing.T) {
function TestDisposeOnPut (line 271) | func TestDisposeOnPut(t *testing.T) {
function BenchmarkRBLifeCycle (line 303) | func BenchmarkRBLifeCycle(b *testing.B) {
function BenchmarkRBLifeCycleContention (line 331) | func BenchmarkRBLifeCycleContention(b *testing.B) {
function BenchmarkRBPut (line 369) | func BenchmarkRBPut(b *testing.B) {
function BenchmarkRBGet (line 386) | func BenchmarkRBGet(b *testing.B) {
function BenchmarkRBAllocation (line 400) | func BenchmarkRBAllocation(b *testing.B) {
FILE: rangetree/entries.go
type Entries (line 29) | type Entries
method Dispose (line 33) | func (entries *Entries) Dispose() {
function NewEntries (line 43) | func NewEntries() Entries {
FILE: rangetree/entries_test.go
function TestDisposeEntries (line 25) | func TestDisposeEntries(t *testing.T) {
FILE: rangetree/error.go
type NoEntriesError (line 23) | type NoEntriesError struct
method Error (line 25) | func (nee NoEntriesError) Error() string {
type OutOfDimensionError (line 31) | type OutOfDimensionError struct
method Error (line 35) | func (oode OutOfDimensionError) Error() string {
FILE: rangetree/immutable.go
type immutableRangeTree (line 21) | type immutableRangeTree struct
method needNextDimension (line 35) | func (irt *immutableRangeTree) needNextDimension() bool {
method add (line 39) | func (irt *immutableRangeTree) add(nodes *orderedNodes, cache []slice....
method Add (line 78) | func (irt *immutableRangeTree) Add(entries ...Entry) *immutableRangeTr...
method InsertAtDimension (line 102) | func (irt *immutableRangeTree) InsertAtDimension(dimension uint64,
method Delete (line 129) | func (irt *immutableRangeTree) Delete(entries ...Entry) *immutableRang...
method delete (line 144) | func (irt *immutableRangeTree) delete(top *orderedNodes,
method apply (line 200) | func (irt *immutableRangeTree) apply(list orderedNodes, interval Inter...
method Query (line 226) | func (irt *immutableRangeTree) Query(interval Interval) Entries {
method get (line 237) | func (irt *immutableRangeTree) get(entry Entry) Entry {
method Get (line 257) | func (irt *immutableRangeTree) Get(entries ...Entry) Entries {
method Len (line 267) | func (irt *immutableRangeTree) Len() uint64 {
function newCache (line 27) | func newCache(dimensions uint64) []slice.Int64Slice {
type immutableNodeBundle (line 122) | type immutableNodeBundle struct
function newImmutableRangeTree (line 271) | func newImmutableRangeTree(dimensions uint64) *immutableRangeTree {
FILE: rangetree/immutable_test.go
function TestImmutableSingleDimensionAdd (line 25) | func TestImmutableSingleDimensionAdd(t *testing.T) {
function TestImmutableSingleDimensionMultipleAdds (line 41) | func TestImmutableSingleDimensionMultipleAdds(t *testing.T) {
function TestImmutableSingleDimensionBulkAdd (line 66) | func TestImmutableSingleDimensionBulkAdd(t *testing.T) {
function TestImmutableMultiDimensionAdd (line 81) | func TestImmutableMultiDimensionAdd(t *testing.T) {
function TestImmutableMultiDimensionMultipleAdds (line 97) | func TestImmutableMultiDimensionMultipleAdds(t *testing.T) {
function TestImmutableMultiDimensionBulkAdd (line 122) | func TestImmutableMultiDimensionBulkAdd(t *testing.T) {
function BenchmarkImmutableMultiDimensionInserts (line 137) | func BenchmarkImmutableMultiDimensionInserts(b *testing.B) {
function BenchmarkImmutableMultiDimensionBulkInsert (line 156) | func BenchmarkImmutableMultiDimensionBulkInsert(b *testing.B) {
function BenchmarkMultiDimensionBulkInsert (line 173) | func BenchmarkMultiDimensionBulkInsert(b *testing.B) {
function TestImmutableSingleDimensionDelete (line 190) | func TestImmutableSingleDimensionDelete(t *testing.T) {
function TestImmutableSingleDimensionMultipleDeletes (line 202) | func TestImmutableSingleDimensionMultipleDeletes(t *testing.T) {
function TestImmutableSingleDimensionBulkDeletes (line 237) | func TestImmutableSingleDimensionBulkDeletes(t *testing.T) {
function TestImmutableMultiDimensionDelete (line 259) | func TestImmutableMultiDimensionDelete(t *testing.T) {
function TestImmutableMultiDimensionMultipleDeletes (line 272) | func TestImmutableMultiDimensionMultipleDeletes(t *testing.T) {
function TestImmutableMultiDimensionBulkDeletes (line 307) | func TestImmutableMultiDimensionBulkDeletes(t *testing.T) {
function constructMultiDimensionalImmutableTree (line 329) | func constructMultiDimensionalImmutableTree(number int64) (*immutableRan...
function TestImmutableInsertPositiveIndexFirstDimension (line 339) | func TestImmutableInsertPositiveIndexFirstDimension(t *testing.T) {
function TestImmutableInsertPositiveIndexSecondDimension (line 353) | func TestImmutableInsertPositiveIndexSecondDimension(t *testing.T) {
function TestImmutableInsertPositiveIndexOutOfBoundsFirstDimension (line 367) | func TestImmutableInsertPositiveIndexOutOfBoundsFirstDimension(t *testin...
function TestImmutableInsertPositiveIndexOutOfBoundsSecondDimension (line 376) | func TestImmutableInsertPositiveIndexOutOfBoundsSecondDimension(t *testi...
function TestImmutableInsertMultiplePositiveIndexFirstDimension (line 385) | func TestImmutableInsertMultiplePositiveIndexFirstDimension(t *testing.T) {
function TestImmutableInsertMultiplePositiveIndexSecondDimension (line 399) | func TestImmutableInsertMultiplePositiveIndexSecondDimension(t *testing....
function TestImmutableInsertNegativeIndexFirstDimension (line 413) | func TestImmutableInsertNegativeIndexFirstDimension(t *testing.T) {
function TestImmutableInsertNegativeIndexSecondDimension (line 432) | func TestImmutableInsertNegativeIndexSecondDimension(t *testing.T) {
function TestImmutableInsertNegativeIndexOutOfBoundsFirstDimension (line 451) | func TestImmutableInsertNegativeIndexOutOfBoundsFirstDimension(t *testin...
function TestImmutableInsertNegativeIndexOutOfBoundsSecondDimension (line 460) | func TestImmutableInsertNegativeIndexOutOfBoundsSecondDimension(t *testi...
function TestImmutableInsertMultipleNegativeIndexFirstDimension (line 469) | func TestImmutableInsertMultipleNegativeIndexFirstDimension(t *testing.T) {
function TestImmutableInsertMultipleNegativeIndexSecondDimension (line 484) | func TestImmutableInsertMultipleNegativeIndexSecondDimension(t *testing....
function TestImmutableInsertInvalidDimension (line 499) | func TestImmutableInsertInvalidDimension(t *testing.T) {
function TestImmutableInsertInvalidNumber (line 508) | func TestImmutableInsertInvalidNumber(t *testing.T) {
function TestImmutableGet (line 517) | func TestImmutableGet(t *testing.T) {
function BenchmarkImmutableInsertFirstDimension (line 527) | func BenchmarkImmutableInsertFirstDimension(b *testing.B) {
function BenchmarkImmutableInsertSecondDimension (line 539) | func BenchmarkImmutableInsertSecondDimension(b *testing.B) {
FILE: rangetree/interface.go
type Entry (line 32) | type Entry interface
type Interval (line 40) | type Interval interface
type RangeTree (line 50) | type RangeTree interface
FILE: rangetree/mock_test.go
type mockEntry (line 19) | type mockEntry struct
method ID (line 24) | func (me *mockEntry) ID() uint64 {
method ValueAtDimension (line 28) | func (me *mockEntry) ValueAtDimension(dimension uint64) int64 {
function constructMockEntry (line 32) | func constructMockEntry(id uint64, values ...int64) *mockEntry {
type dimension (line 39) | type dimension struct
type mockInterval (line 43) | type mockInterval struct
method LowAtDimension (line 47) | func (mi *mockInterval) LowAtDimension(dimension uint64) int64 {
method HighAtDimension (line 51) | func (mi *mockInterval) HighAtDimension(dimension uint64) int64 {
function constructMockInterval (line 55) | func constructMockInterval(dimensions ...dimension) *mockInterval {
FILE: rangetree/node.go
type nodes (line 19) | type nodes
type node (line 21) | type node struct
function newNode (line 27) | func newNode(value int64, entry Entry, needNextDimension bool) *node {
FILE: rangetree/ordered.go
type orderedNodes (line 23) | type orderedNodes
method search (line 25) | func (nodes orderedNodes) search(value int64) int {
method addAt (line 34) | func (nodes *orderedNodes) addAt(i int, node *node) *node {
method add (line 54) | func (nodes *orderedNodes) add(node *node) *node {
method deleteAt (line 59) | func (nodes *orderedNodes) deleteAt(i int) *node {
method delete (line 71) | func (nodes *orderedNodes) delete(value int64) *node {
method apply (line 81) | func (nodes orderedNodes) apply(low, high int64, fn func(*node) bool) ...
method get (line 100) | func (nodes orderedNodes) get(value int64) (*node, int) {
method getOrAdd (line 113) | func (nodes *orderedNodes) getOrAdd(entry Entry,
method flatten (line 137) | func (nodes orderedNodes) flatten(entries *Entries) {
method insert (line 147) | func (nodes *orderedNodes) insert(insertDimension, dimension, maxDimen...
method immutableInsert (line 189) | func (nodes orderedNodes) immutableInsert(insertDimension, dimension, ...
FILE: rangetree/ordered_test.go
function TestOrderedAdd (line 25) | func TestOrderedAdd(t *testing.T) {
function TestOrderedDelete (line 47) | func TestOrderedDelete(t *testing.T) {
function TestApply (line 73) | func TestApply(t *testing.T) {
function TestInsertDelete (line 141) | func TestInsertDelete(t *testing.T) {
function BenchmarkPrepend (line 161) | func BenchmarkPrepend(b *testing.B) {
FILE: rangetree/orderedtree.go
function isLastDimension (line 18) | func isLastDimension(value, test uint64) bool {
type nodeBundle (line 22) | type nodeBundle struct
type orderedTree (line 27) | type orderedTree struct
method resetPath (line 34) | func (ot *orderedTree) resetPath() {
method needNextDimension (line 38) | func (ot *orderedTree) needNextDimension() bool {
method add (line 44) | func (ot *orderedTree) add(entry Entry) *node {
method Add (line 70) | func (ot *orderedTree) Add(entries ...Entry) Entries {
method delete (line 90) | func (ot *orderedTree) delete(entry Entry) *node {
method get (line 122) | func (ot *orderedTree) get(entry Entry) Entry {
method Get (line 142) | func (ot *orderedTree) Get(entries ...Entry) Entries {
method Delete (line 155) | func (ot *orderedTree) Delete(entries ...Entry) Entries {
method Len (line 176) | func (ot *orderedTree) Len() uint64 {
method apply (line 180) | func (ot *orderedTree) apply(list orderedNodes, interval Interval,
method Apply (line 208) | func (ot *orderedTree) Apply(interval Interval, fn func(Entry) bool) {
method Query (line 216) | func (ot *orderedTree) Query(interval Interval) Entries {
method InsertAtDimension (line 232) | func (ot *orderedTree) InsertAtDimension(dimension uint64,
function newOrderedTree (line 252) | func newOrderedTree(dimensions uint64) *orderedTree {
function New (line 261) | func New(dimensions uint64) RangeTree {
FILE: rangetree/orderedtree_test.go
function constructMultiDimensionalOrderedTree (line 26) | func constructMultiDimensionalOrderedTree(number uint64) (
function TestOTRootAddMultipleDimensions (line 41) | func TestOTRootAddMultipleDimensions(t *testing.T) {
function TestOTMultipleAddMultipleDimensions (line 50) | func TestOTMultipleAddMultipleDimensions(t *testing.T) {
function TestOTAddInOrderMultiDimensions (line 80) | func TestOTAddInOrderMultiDimensions(t *testing.T) {
function TestOTAddReverseOrderMultiDimensions (line 89) | func TestOTAddReverseOrderMultiDimensions(t *testing.T) {
function TestOTAddRandomOrderMultiDimensions (line 101) | func TestOTAddRandomOrderMultiDimensions(t *testing.T) {
function TestOTAddLargeNumbersMultiDimension (line 115) | func TestOTAddLargeNumbersMultiDimension(t *testing.T) {
function TestOTAddReturnsOverwritten (line 133) | func TestOTAddReturnsOverwritten(t *testing.T) {
function BenchmarkOTAddItemsMultiDimensions (line 159) | func BenchmarkOTAddItemsMultiDimensions(b *testing.B) {
function BenchmarkOTQueryItemsMultiDimensions (line 176) | func BenchmarkOTQueryItemsMultiDimensions(b *testing.B) {
function TestOTRootDeleteMultiDimensions (line 198) | func TestOTRootDeleteMultiDimensions(t *testing.T) {
function TestOTDeleteMultiDimensions (line 208) | func TestOTDeleteMultiDimensions(t *testing.T) {
function TestOTDeleteInOrderMultiDimensions (line 225) | func TestOTDeleteInOrderMultiDimensions(t *testing.T) {
function TestOTDeleteReverseOrderMultiDimensions (line 237) | func TestOTDeleteReverseOrderMultiDimensions(t *testing.T) {
function TestOTDeleteRandomOrderMultiDimensions (line 256) | func TestOTDeleteRandomOrderMultiDimensions(t *testing.T) {
function TestOTDeleteEmptyTreeMultiDimensions (line 277) | func TestOTDeleteEmptyTreeMultiDimensions(t *testing.T) {
function TestOTDeleteReturnsDeleted (line 285) | func TestOTDeleteReturnsDeleted(t *testing.T) {
function BenchmarkOTDeleteItemsMultiDimensions (line 308) | func BenchmarkOTDeleteItemsMultiDimensions(b *testing.B) {
function TestOverwrites (line 330) | func TestOverwrites(t *testing.T) {
function TestGet (line 349) | func TestGet(t *testing.T) {
function TestTreeApply (line 359) | func TestTreeApply(t *testing.T) {
function TestApplyWithBail (line 374) | func TestApplyWithBail(t *testing.T) {
function BenchmarkApply (line 389) | func BenchmarkApply(b *testing.B) {
function TestInsertPositiveIndexFirstDimension (line 406) | func TestInsertPositiveIndexFirstDimension(t *testing.T) {
function TestInsertPositiveIndexSecondDimension (line 417) | func TestInsertPositiveIndexSecondDimension(t *testing.T) {
function TestInsertPositiveIndexOutOfBoundsFirstDimension (line 428) | func TestInsertPositiveIndexOutOfBoundsFirstDimension(t *testing.T) {
function TestInsertPositiveIndexOutOfBoundsSecondDimension (line 440) | func TestInsertPositiveIndexOutOfBoundsSecondDimension(t *testing.T) {
function TestInsertMultiplePositiveIndexFirstDimension (line 452) | func TestInsertMultiplePositiveIndexFirstDimension(t *testing.T) {
function TestInsertMultiplePositiveIndexSecondDimension (line 463) | func TestInsertMultiplePositiveIndexSecondDimension(t *testing.T) {
function TestInsertNegativeIndexFirstDimension (line 474) | func TestInsertNegativeIndexFirstDimension(t *testing.T) {
function TestInsertNegativeIndexSecondDimension (line 489) | func TestInsertNegativeIndexSecondDimension(t *testing.T) {
function TestInsertNegativeIndexOutOfBoundsFirstDimension (line 504) | func TestInsertNegativeIndexOutOfBoundsFirstDimension(t *testing.T) {
function TestInsertNegativeIndexOutOfBoundsSecondDimension (line 517) | func TestInsertNegativeIndexOutOfBoundsSecondDimension(t *testing.T) {
function TestInsertMultipleNegativeIndexFirstDimension (line 530) | func TestInsertMultipleNegativeIndexFirstDimension(t *testing.T) {
function TestInsertMultipleNegativeIndexSecondDimension (line 542) | func TestInsertMultipleNegativeIndexSecondDimension(t *testing.T) {
function TestInsertInvalidDimension (line 554) | func TestInsertInvalidDimension(t *testing.T) {
function TestInsertInvalidNumber (line 565) | func TestInsertInvalidNumber(t *testing.T) {
function BenchmarkInsertFirstDimension (line 576) | func BenchmarkInsertFirstDimension(b *testing.B) {
function BenchmarkInsertSecondDimension (line 588) | func BenchmarkInsertSecondDimension(b *testing.B) {
function BenchmarkDeleteFirstDimension (line 600) | func BenchmarkDeleteFirstDimension(b *testing.B) {
function BenchmarkDeleteSecondDimension (line 612) | func BenchmarkDeleteSecondDimension(b *testing.B) {
function BenchmarkGetMultiDimensions (line 624) | func BenchmarkGetMultiDimensions(b *testing.B) {
FILE: rangetree/skiplist/mock_test.go
type mockEntry (line 19) | type mockEntry struct
method ValueAtDimension (line 23) | func (me *mockEntry) ValueAtDimension(dimension uint64) int64 {
function newMockEntry (line 27) | func newMockEntry(values ...int64) *mockEntry {
type mockInterval (line 31) | type mockInterval struct
method LowAtDimension (line 35) | func (mi *mockInterval) LowAtDimension(dimension uint64) int64 {
method HighAtDimension (line 39) | func (mi *mockInterval) HighAtDimension(dimension uint64) int64 {
function newMockInterval (line 43) | func newMockInterval(lows, highs []int64) *mockInterval {
FILE: rangetree/skiplist/skiplist.go
type keyed (line 44) | type keyed interface
type skipEntry (line 48) | type skipEntry
method Compare (line 51) | func (se skipEntry) Compare(other common.Comparator) int {
method key (line 64) | func (se skipEntry) key() uint64 {
function isLastDimension (line 70) | func isLastDimension(dimension, lastDimension uint64) bool {
function needsDeletion (line 80) | func needsDeletion(value, index, number int64) bool {
type dimensionalBundle (line 93) | type dimensionalBundle struct
method Compare (line 100) | func (db *dimensionalBundle) Compare(e common.Comparator) int {
method key (line 114) | func (db *dimensionalBundle) key() uint64 {
type lastBundle (line 120) | type lastBundle struct
method Compare (line 127) | func (lb *lastBundle) Compare(e common.Comparator) int {
method key (line 141) | func (lb *lastBundle) key() uint64 {
type skipListRT (line 145) | type skipListRT struct
method init (line 150) | func (rt *skipListRT) init(dimensions uint64) {
method add (line 155) | func (rt *skipListRT) add(entry rangetree.Entry) rangetree.Entry {
method Add (line 200) | func (rt *skipListRT) Add(entries ...rangetree.Entry) rangetree.Entries {
method get (line 209) | func (rt *skipListRT) get(entry rangetree.Entry) rangetree.Entry {
method Get (line 235) | func (rt *skipListRT) Get(entries ...rangetree.Entry) rangetree.Entries {
method Len (line 245) | func (rt *skipListRT) Len() uint64 {
method deleteRecursive (line 252) | func (rt *skipListRT) deleteRecursive(sl *skip.SkipList, dimension uin...
method delete (line 283) | func (rt *skipListRT) delete(entry rangetree.Entry) rangetree.Entry {
method Delete (line 291) | func (rt *skipListRT) Delete(entries ...rangetree.Entry) rangetree.Ent...
method apply (line 300) | func (rt *skipListRT) apply(sl *skip.SkipList, dimension uint64,
method Apply (line 332) | func (rt *skipListRT) Apply(interval rangetree.Interval, fn func(range...
method Query (line 338) | func (rt *skipListRT) Query(interval rangetree.Interval) rangetree.Ent...
method flatten (line 348) | func (rt *skipListRT) flatten(sl *skip.SkipList, dimension uint64, ent...
method insert (line 359) | func (rt *skipListRT) insert(sl *skip.SkipList, dimension, insertDimen...
method InsertAtDimension (line 417) | func (rt *skipListRT) InsertAtDimension(dimension uint64,
function new (line 435) | func new(dimensions uint64) *skipListRT {
function New (line 443) | func New(dimensions uint64) rangetree.RangeTree {
FILE: rangetree/skiplist/skiplist_test.go
function generateMultiDimensionalEntries (line 29) | func generateMultiDimensionalEntries(num int) rangetree.Entries {
function generateRandomMultiDimensionalEntries (line 38) | func generateRandomMultiDimensionalEntries(num int) rangetree.Entries {
function TestRTSingleDimensionAdd (line 48) | func TestRTSingleDimensionAdd(t *testing.T) {
function TestRTMultiDimensionAdd (line 59) | func TestRTMultiDimensionAdd(t *testing.T) {
function TestRTSingleDimensionOverwrite (line 70) | func TestRTSingleDimensionOverwrite(t *testing.T) {
function TestRTMultiDimensionOverwrite (line 85) | func TestRTMultiDimensionOverwrite(t *testing.T) {
function TestRTSingleDimensionDelete (line 100) | func TestRTSingleDimensionDelete(t *testing.T) {
function TestRTMultiDimensionDelete (line 112) | func TestRTMultiDimensionDelete(t *testing.T) {
function TestRTSingleDimensionQuery (line 124) | func TestRTSingleDimensionQuery(t *testing.T) {
function TestRTMultiDimensionQuery (line 147) | func TestRTMultiDimensionQuery(t *testing.T) {
function TestRTSingleDimensionInsert (line 179) | func TestRTSingleDimensionInsert(t *testing.T) {
function TestRTSingleDimensionInsertNegative (line 197) | func TestRTSingleDimensionInsertNegative(t *testing.T) {
function TestRTMultiDimensionInsert (line 215) | func TestRTMultiDimensionInsert(t *testing.T) {
function TestRTMultiDimensionInsertNegative (line 233) | func TestRTMultiDimensionInsertNegative(t *testing.T) {
function TestRTInsertInZeroDimensionMultiDimensionList (line 251) | func TestRTInsertInZeroDimensionMultiDimensionList(t *testing.T) {
function TestRTInsertNegativeInZeroDimensionMultiDimensionList (line 269) | func TestRTInsertNegativeInZeroDimensionMultiDimensionList(t *testing.T) {
function TestRTInsertBeyondDimension (line 287) | func TestRTInsertBeyondDimension(t *testing.T) {
function TestRTInsertZero (line 298) | func TestRTInsertZero(t *testing.T) {
function BenchmarkMultiDimensionInsert (line 309) | func BenchmarkMultiDimensionInsert(b *testing.B) {
function BenchmarkMultiDimensionInsertReverse (line 321) | func BenchmarkMultiDimensionInsertReverse(b *testing.B) {
function BenchmarkMultiDimensionRandomInsert (line 334) | func BenchmarkMultiDimensionRandomInsert(b *testing.B) {
function BenchmarkMultiDimensionalGet (line 346) | func BenchmarkMultiDimensionalGet(b *testing.B) {
function BenchmarkMultiDimensionDelete (line 359) | func BenchmarkMultiDimensionDelete(b *testing.B) {
function BenchmarkMultiDimensionQuery (line 372) | func BenchmarkMultiDimensionQuery(b *testing.B) {
function BenchmarkMultiDimensionInsertAtZeroDimension (line 389) | func BenchmarkMultiDimensionInsertAtZeroDimension(b *testing.B) {
function BenchmarkMultiDimensionInsertNegativeAtZeroDimension (line 402) | func BenchmarkMultiDimensionInsertNegativeAtZeroDimension(b *testing.B) {
FILE: rtree/hilbert/action.go
type actions (line 27) | type actions
type action (line 29) | type action interface
type getAction (line 38) | type getAction struct
method complete (line 44) | func (ga *getAction) complete() {
method operation (line 48) | func (ga *getAction) operation() operation {
method keys (line 52) | func (ga *getAction) keys() hilberts {
method addNode (line 56) | func (ga *getAction) addNode(i int64, n *node) {
method nodes (line 60) | func (ga *getAction) nodes() []*node {
method rects (line 64) | func (ga *getAction) rects() []*hilbertBundle {
function newGetAction (line 68) | func newGetAction(rect rtree.Rectangle) *getAction {
type insertAction (line 78) | type insertAction struct
method complete (line 84) | func (ia *insertAction) complete() {
method operation (line 88) | func (ia *insertAction) operation() operation {
method keys (line 92) | func (ia *insertAction) keys() hilberts {
method addNode (line 96) | func (ia *insertAction) addNode(i int64, n *node) {
method nodes (line 100) | func (ia *insertAction) nodes() []*node {
method rects (line 104) | func (ia *insertAction) rects() []*hilbertBundle {
function newInsertAction (line 108) | func newInsertAction(rects rtree.Rectangles) *insertAction {
type removeAction (line 118) | type removeAction struct
method operation (line 122) | func (ra *removeAction) operation() operation {
function newRemoveAction (line 126) | func newRemoveAction(rects rtree.Rectangles) *removeAction {
function minUint64 (line 132) | func minUint64(choices ...uint64) uint64 {
type interfaces (line 143) | type interfaces
function executeInterfacesInParallel (line 145) | func executeInterfacesInParallel(ifs interfaces, fn func(interface{})) {
function executeInterfacesInSerial (line 179) | func executeInterfacesInSerial(ifs interfaces, fn func(interface{})) {
FILE: rtree/hilbert/hilbert.go
function getCenter (line 27) | func getCenter(rect rtree.Rectangle) (int32, int32) {
type hilbertBundle (line 34) | type hilbertBundle struct
function bundlesFromRects (line 39) | func bundlesFromRects(rects ...rtree.Rectangle) []*hilbertBundle {
function chunkRectangles (line 73) | func chunkRectangles(slice rtree.Rectangles, numParts int64) []rtree.Rec...
FILE: rtree/hilbert/mock_test.go
type mockRectangle (line 19) | type mockRectangle struct
method LowerLeft (line 23) | func (mr *mockRectangle) LowerLeft() (int32, int32) {
method UpperRight (line 27) | func (mr *mockRectangle) UpperRight() (int32, int32) {
function newMockRectangle (line 31) | func newMockRectangle(xlow, ylow, xhigh, yhigh int32) *mockRectangle {
FILE: rtree/hilbert/node.go
type hilbert (line 25) | type hilbert
type hilberts (line 27) | type hilberts
function getParent (line 29) | func getParent(parent *node, key hilbert, r1 rtree.Rectangle) *node {
type nodes (line 63) | type nodes struct
method push (line 67) | func (ns *nodes) push(n rtree.Rectangle) {
method splitAt (line 71) | func (ns *nodes) splitAt(i, capacity uint64) (*nodes, *nodes) {
method byPosition (line 82) | func (ns *nodes) byPosition(pos uint64) *node {
method insertAt (line 90) | func (ns *nodes) insertAt(i uint64, n rtree.Rectangle) {
method replaceAt (line 96) | func (ns *nodes) replaceAt(i uint64, n rtree.Rectangle) {
method len (line 100) | func (ns *nodes) len() uint64 {
method deleteAt (line 104) | func (ns *nodes) deleteAt(i uint64) {
function newNodes (line 109) | func newNodes(size uint64) *nodes {
type keys (line 115) | type keys struct
method splitAt (line 119) | func (ks *keys) splitAt(i, capacity uint64) (*keys, *keys) {
method len (line 127) | func (ks *keys) len() uint64 {
method byPosition (line 131) | func (ks *keys) byPosition(i uint64) hilbert {
method deleteAt (line 138) | func (ks *keys) deleteAt(i uint64) {
method delete (line 143) | func (ks *keys) delete(k hilbert) hilbert {
method search (line 157) | func (ks *keys) search(key hilbert) uint64 {
method insert (line 165) | func (ks *keys) insert(key hilbert) (hilbert, uint64) {
method last (line 183) | func (ks *keys) last() hilbert {
method insertAt (line 187) | func (ks *keys) insertAt(i uint64, k hilbert) {
method withPosition (line 193) | func (ks *keys) withPosition(k hilbert) (hilbert, uint64) {
function newKeys (line 205) | func newKeys(size uint64) *keys {
type node (line 211) | type node struct
method insert (line 220) | func (n *node) insert(kb *keyBundle) rtree.Rectangle {
method delete (line 258) | func (n *node) delete(kb *keyBundle) rtree.Rectangle {
method LowerLeft (line 274) | func (n *node) LowerLeft() (int32, int32) {
method UpperRight (line 278) | func (n *node) UpperRight() (int32, int32) {
method needsSplit (line 282) | func (n *node) needsSplit(ary uint64) bool {
method splitLeaf (line 286) | func (n *node) splitLeaf(i, capacity uint64) (hilbert, *node, *node) {
method splitInternal (line 305) | func (n *node) splitInternal(i, capacity uint64) (hilbert, *node, *nod...
method split (line 324) | func (n *node) split(i, capacity uint64) (hilbert, *node, *node) {
method search (line 332) | func (n *node) search(key hilbert) uint64 {
method searchNode (line 336) | func (n *node) searchNode(key hilbert) *node {
method searchRects (line 342) | func (n *node) searchRects(r *rectangle) rtree.Rectangles {
method key (line 353) | func (n *node) key() hilbert {
function newNode (line 357) | func newNode(isLeaf bool, keys *keys, ns *nodes) *node {
FILE: rtree/hilbert/rectangle.go
type rectangle (line 21) | type rectangle struct
method adjust (line 25) | func (r *rectangle) adjust(rect rtree.Rectangle) {
function equal (line 44) | func equal(r1, r2 rtree.Rectangle) bool {
function intersect (line 54) | func intersect(rect1 *rectangle, rect2 rtree.Rectangle) bool {
function newRectangeFromRect (line 61) | func newRectangeFromRect(rect rtree.Rectangle) *rectangle {
function newRectangleFromRects (line 74) | func newRectangleFromRects(rects rtree.Rectangles) *rectangle {
FILE: rtree/hilbert/tree.go
type operation (line 43) | type operation
constant get (line 46) | get operation = iota
constant add (line 47) | add
constant remove (line 48) | remove
constant multiThreadAt (line 51) | multiThreadAt = 1000
type keyBundle (line 53) | type keyBundle struct
type tree (line 58) | type tree struct
method checkAndRun (line 72) | func (tree *tree) checkAndRun(action action) {
method init (line 116) | func (tree *tree) init(bufferSize, ary uint64) {
method operationRunner (line 125) | func (tree *tree) operationRunner(xns interfaces, threaded bool) {
method fetchKeys (line 135) | func (tree *tree) fetchKeys(xns interfaces, inParallel bool) (map[*nod...
method fetchKeysInSerial (line 166) | func (tree *tree) fetchKeysInSerial(xns interfaces) {
method reset (line 183) | func (tree *tree) reset() {
method fetchKeysInParallel (line 193) | func (tree *tree) fetchKeysInParallel(xns []interface{}) {
method splitNode (line 244) | func (tree *tree) splitNode(n, parent *node, nodes *[]*node, keys *hil...
method applyNode (line 263) | func (tree *tree) applyNode(n *node, adds, deletes []*keyBundle) {
method recursiveMutate (line 283) | func (tree *tree) recursiveMutate(adds, deletes map[*node][]*keyBundle...
method Insert (line 367) | func (tree *tree) Insert(rects ...rtree.Rectangle) {
method Delete (line 375) | func (tree *tree) Delete(rects ...rtree.Rectangle) {
method search (line 381) | func (tree *tree) search(r *rectangle) rtree.Rectangles {
method Search (line 403) | func (tree *tree) Search(rect rtree.Rectangle) rtree.Rectangles {
method Len (line 411) | func (tree *tree) Len() uint64 {
method Dispose (line 417) | func (tree *tree) Dispose() {
function newTree (line 422) | func newTree(bufferSize, ary uint64) *tree {
function New (line 429) | func New(bufferSize, ary uint64) rtree.RTree {
FILE: rtree/hilbert/tree_test.go
function getConsoleLogger (line 31) | func getConsoleLogger() *log.Logger {
method print (line 35) | func (n *node) print(log *log.Logger) {
method print (line 50) | func (t *tree) print(log *log.Logger) {
function constructMockPoints (line 60) | func constructMockPoints(num int) rtree.Rectangles {
function constructRandomMockPoints (line 68) | func constructRandomMockPoints(num int) rtree.Rectangles {
function constructInfiniteRect (line 78) | func constructInfiniteRect() rtree.Rectangle {
function TestSimpleInsert (line 82) | func TestSimpleInsert(t *testing.T) {
function TestSimpleDelete (line 94) | func TestSimpleDelete(t *testing.T) {
function TestDeleteIdenticalHilbergNumber (line 106) | func TestDeleteIdenticalHilbergNumber(t *testing.T) {
function TestDeleteAll (line 123) | func TestDeleteAll(t *testing.T) {
function TestTwoInsert (line 135) | func TestTwoInsert(t *testing.T) {
function TestInsertCausesRootSplitOddAry (line 156) | func TestInsertCausesRootSplitOddAry(t *testing.T) {
function TestInsertCausesRootSplitEvenAry (line 172) | func TestInsertCausesRootSplitEvenAry(t *testing.T) {
function TestQueryWithLine (line 190) | func TestQueryWithLine(t *testing.T) {
function TestQueryForPoint (line 237) | func TestQueryForPoint(t *testing.T) {
function TestMultipleInsertsCauseInternalSplitOddAry (line 261) | func TestMultipleInsertsCauseInternalSplitOddAry(t *testing.T) {
function TestMultipleInsertsCauseInternalSplitOddAryRandomPoints (line 283) | func TestMultipleInsertsCauseInternalSplitOddAryRandomPoints(t *testing....
function TestMultipleInsertsCauseInternalSplitEvenAry (line 305) | func TestMultipleInsertsCauseInternalSplitEvenAry(t *testing.T) {
function TestMultipleInsertsCauseInternalSplitEvenAryRandomOrder (line 327) | func TestMultipleInsertsCauseInternalSplitEvenAryRandomOrder(t *testing....
function TestInsertDuplicateHilbert (line 349) | func TestInsertDuplicateHilbert(t *testing.T) {
function TestDeleteAllDuplicateHilbert (line 370) | func TestDeleteAllDuplicateHilbert(t *testing.T) {
function TestInsertDuplicateRect (line 387) | func TestInsertDuplicateRect(t *testing.T) {
function BenchmarkBulkAddPoints (line 399) | func BenchmarkBulkAddPoints(b *testing.B) {
function BenchmarkBulkUpdatePoints (line 411) | func BenchmarkBulkUpdatePoints(b *testing.B) {
function BenchmarkPointInsertion (line 424) | func BenchmarkPointInsertion(b *testing.B) {
function BenchmarkQueryPoints (line 436) | func BenchmarkQueryPoints(b *testing.B) {
function BenchmarkQueryBulkPoints (line 449) | func BenchmarkQueryBulkPoints(b *testing.B) {
function BenchmarkDelete (line 462) | func BenchmarkDelete(b *testing.B) {
FILE: rtree/interface.go
type Rectangles (line 20) | type Rectangles
type Rectangle (line 23) | type Rectangle interface
type RTree (line 32) | type RTree interface
FILE: set/dict.go
type Set (line 35) | type Set struct
method Add (line 42) | func (set *Set) Add(items ...interface{}) {
method Remove (line 53) | func (set *Set) Remove(items ...interface{}) {
method Exists (line 64) | func (set *Set) Exists(item interface{}) bool {
method Flatten (line 75) | func (set *Set) Flatten() []interface{} {
method Len (line 91) | func (set *Set) Len() int64 {
method Clear (line 102) | func (set *Set) Clear() {
method All (line 111) | func (set *Set) All(items ...interface{}) bool {
method Dispose (line 125) | func (set *Set) Dispose() {
function New (line 144) | func New(items ...interface{}) *Set {
function init (line 157) | func init() {
FILE: set/dict_test.go
function TestAddDuplicateItem (line 25) | func TestAddDuplicateItem(t *testing.T) {
function TestAddItems (line 35) | func TestAddItems(t *testing.T) {
function TestRemove (line 56) | func TestRemove(t *testing.T) {
function TestExists (line 66) | func TestExists(t *testing.T) {
function TestExists_WithNewItems (line 79) | func TestExists_WithNewItems(t *testing.T) {
function TestLen (line 95) | func TestLen(t *testing.T) {
function TestFlattenCaches (line 109) | func TestFlattenCaches(t *testing.T) {
function TestFlattenCaches_CacheReturn (line 121) | func TestFlattenCaches_CacheReturn(t *testing.T) {
function TestAddClearsCache (line 134) | func TestAddClearsCache(t *testing.T) {
function TestDeleteClearsCache (line 154) | func TestDeleteClearsCache(t *testing.T) {
function TestAll (line 167) | func TestAll(t *testing.T) {
function TestClear (line 185) | func TestClear(t *testing.T) {
function BenchmarkFlatten (line 196) | func BenchmarkFlatten(b *testing.B) {
function BenchmarkLen (line 209) | func BenchmarkLen(b *testing.B) {
function BenchmarkExists (line 222) | func BenchmarkExists(b *testing.B) {
function BenchmarkClear (line 232) | func BenchmarkClear(b *testing.B) {
FILE: slice/int64.go
type Int64Slice (line 28) | type Int64Slice
method Len (line 31) | func (s Int64Slice) Len() int {
method Less (line 37) | func (s Int64Slice) Less(i, j int) bool {
method Search (line 45) | func (s Int64Slice) Search(x int64) int {
method Sort (line 52) | func (s Int64Slice) Sort() {
method Swap (line 58) | func (s Int64Slice) Swap(i, j int) {
method Exists (line 65) | func (s Int64Slice) Exists(x int64) bool {
method Insert (line 77) | func (s Int64Slice) Insert(x int64) Int64Slice {
FILE: slice/int64_test.go
function TestSort (line 25) | func TestSort(t *testing.T) {
function TestSearch (line 32) | func TestSearch(t *testing.T) {
function TestExists (line 40) | func TestExists(t *testing.T) {
function TestInsert (line 47) | func TestInsert(t *testing.T) {
FILE: slice/skip/interface.go
type Iterator (line 23) | type Iterator interface
FILE: slice/skip/iterator.go
constant iteratorExhausted (line 21) | iteratorExhausted = -2
type iterator (line 26) | type iterator struct
method Next (line 33) | func (iter *iterator) Next() bool {
method Value (line 49) | func (iter *iterator) Value() common.Comparator {
method exhaust (line 59) | func (iter *iterator) exhaust() common.Comparators {
function nilIterator (line 70) | func nilIterator() *iterator {
FILE: slice/skip/iterator_test.go
function TestIterate (line 25) | func TestIterate(t *testing.T) {
FILE: slice/skip/mock_test.go
type mockEntry (line 25) | type mockEntry
method Compare (line 27) | func (me mockEntry) Compare(other common.Comparator) int {
function newMockEntry (line 40) | func newMockEntry(key uint64) mockEntry {
type mockIterator (line 44) | type mockIterator struct
method Next (line 48) | func (mi *mockIterator) Next() bool {
method Value (line 53) | func (mi *mockIterator) Value() common.Comparator {
method exhaust (line 63) | func (mi *mockIterator) exhaust() common.Comparators {
FILE: slice/skip/node.go
type widths (line 21) | type widths
type nodes (line 23) | type nodes
type node (line 25) | type node struct
method Compare (line 37) | func (n *node) Compare(e common.Comparator) int {
function newNode (line 44) | func newNode(cmp common.Comparator, maxLevels uint8) *node {
FILE: slice/skip/skip.go
constant p (line 69) | p = .5
type lockedSource (line 80) | type lockedSource struct
method Int63 (line 86) | func (ls *lockedSource) Int63() (n int64) {
method Seed (line 94) | func (ls *lockedSource) Seed(seed int64) {
function generateLevel (line 106) | func generateLevel(maxLevel uint8) uint8 {
function insertNode (line 118) | func insertNode(sl *SkipList, n *node, cmp common.Comparator, pos uint64...
function splitAt (line 160) | func splitAt(sl *SkipList, index uint64) (*SkipList, *SkipList) {
type SkipList (line 191) | type SkipList struct
method init (line 204) | func (sl *SkipList) init(ifc interface{}) {
method search (line 220) | func (sl *SkipList) search(cmp common.Comparator, update nodes, widths...
method resetMaxLevel (line 246) | func (sl *SkipList) resetMaxLevel() {
method searchByPosition (line 256) | func (sl *SkipList) searchByPosition(position uint64, update nodes, wi...
method Get (line 287) | func (sl *SkipList) Get(comparators ...common.Comparator) common.Compa...
method GetWithPosition (line 306) | func (sl *SkipList) GetWithPosition(cmp common.Comparator) (common.Com...
method ByPosition (line 316) | func (sl *SkipList) ByPosition(position uint64) common.Comparator {
method insert (line 325) | func (sl *SkipList) insert(cmp common.Comparator) common.Comparator {
method Insert (line 333) | func (sl *SkipList) Insert(comparators ...common.Comparator) common.Co...
method insertAtPosition (line 342) | func (sl *SkipList) insertAtPosition(position uint64, cmp common.Compa...
method InsertAtPosition (line 354) | func (sl *SkipList) InsertAtPosition(position uint64, cmp common.Compa...
method replaceAtPosition (line 358) | func (sl *SkipList) replaceAtPosition(position uint64, cmp common.Comp...
method ReplaceAtPosition (line 370) | func (sl *SkipList) ReplaceAtPosition(position uint64, cmp common.Comp...
method delete (line 374) | func (sl *SkipList) delete(cmp common.Comparator) common.Comparator {
method Delete (line 406) | func (sl *SkipList) Delete(comparators ...common.Comparator) common.Co...
method Len (line 417) | func (sl *SkipList) Len() uint64 {
method iterAtPosition (line 421) | func (sl *SkipList) iterAtPosition(pos uint64) *iterator {
method IterAtPosition (line 435) | func (sl *SkipList) IterAtPosition(pos uint64) Iterator {
method iter (line 439) | func (sl *SkipList) iter(cmp common.Comparator) *iterator {
method Iter (line 454) | func (sl *SkipList) Iter(cmp common.Comparator) Iterator {
method SplitAt (line 464) | func (sl *SkipList) SplitAt(index uint64) (*SkipList, *SkipList) {
function New (line 477) | func New(ifc interface{}) *SkipList {
FILE: slice/skip/skip_test.go
function generateMockEntries (line 28) | func generateMockEntries(num int) common.Comparators {
function generateRandomMockEntries (line 37) | func generateRandomMockEntries(num int) common.Comparators {
function TestInsertByPosition (line 46) | func TestInsertByPosition(t *testing.T) {
function TestGetByPosition (line 61) | func TestGetByPosition(t *testing.T) {
function TestSplitAt (line 72) | func TestSplitAt(t *testing.T) {
function TestSplitLargeSkipList (line 91) | func TestSplitLargeSkipList(t *testing.T) {
function TestSplitLargeSkipListOddNumber (line 114) | func TestSplitLargeSkipListOddNumber(t *testing.T) {
function TestSplitAtSkipListLength (line 137) | func TestSplitAtSkipListLength(t *testing.T) {
function TestGetWithPosition (line 147) | func TestGetWithPosition(t *testing.T) {
function TestReplaceAtPosition (line 162) | func TestReplaceAtPosition(t *testing.T) {
function TestInsertRandomGetByPosition (line 174) | func TestInsertRandomGetByPosition(t *testing.T) {
function TestGetManyByPosition (line 185) | func TestGetManyByPosition(t *testing.T) {
function TestGetPositionAfterDelete (line 195) | func TestGetPositionAfterDelete(t *testing.T) {
function TestGetPositionBulkDelete (line 210) | func TestGetPositionBulkDelete(t *testing.T) {
function TestSimpleInsert (line 226) | func TestSimpleInsert(t *testing.T) {
function TestSimpleOverwrite (line 245) | func TestSimpleOverwrite(t *testing.T) {
function TestInsertOutOfOrder (line 260) | func TestInsertOutOfOrder(t *testing.T) {
function TestSimpleDelete (line 272) | func TestSimpleDelete(t *testing.T) {
function TestDeleteAll (line 286) | func TestDeleteAll(t *testing.T) {
function TestIter (line 298) | func TestIter(t *testing.T) {
function TestIterAtPosition (line 321) | func TestIterAtPosition(t *testing.T) {
function BenchmarkInsert (line 338) | func BenchmarkInsert(b *testing.B) {
function BenchmarkGet (line 351) | func BenchmarkGet(b *testing.B) {
function BenchmarkDelete (line 365) | func BenchmarkDelete(b *testing.B) {
function BenchmarkPrepend (line 379) | func BenchmarkPrepend(b *testing.B) {
function BenchmarkByPosition (line 397) | func BenchmarkByPosition(b *testing.B) {
function BenchmarkInsertAtPosition (line 410) | func BenchmarkInsertAtPosition(b *testing.B) {
FILE: sort/interface.go
type Comparators (line 4) | type Comparators
method Less (line 8) | func (c Comparators) Less(i, j int) bool {
method Len (line 14) | func (c Comparators) Len() int {
method Swap (line 19) | func (c Comparators) Swap(i, j int) {
type Comparator (line 26) | type Comparator interface
FILE: sort/sort.go
function sortBucket (line 9) | func sortBucket(comparators Comparators) {
function copyChunk (line 13) | func copyChunk(chunk []Comparators) []Comparators {
function MultithreadedSortComparators (line 23) | func MultithreadedSortComparators(comparators Comparators) Comparators {
function chunk (line 69) | func chunk(comparators Comparators, numParts int64) []Comparators {
function prevPowerOfTwo (line 77) | func prevPowerOfTwo(x uint64) uint64 {
FILE: sort/sort_test.go
function TestMultiThreadedSortEvenNumber (line 9) | func TestMultiThreadedSortEvenNumber(t *testing.T) {
function TestMultiThreadedSortOddNumber (line 19) | func TestMultiThreadedSortOddNumber(t *testing.T) {
function BenchmarkMultiThreadedSort (line 29) | func BenchmarkMultiThreadedSort(b *testing.B) {
FILE: sort/symmerge.go
function symSearch (line 11) | func symSearch(u, w Comparators) int {
function swap (line 28) | func swap(u, w Comparators, index int) {
function decomposeForSymMerge (line 38) | func decomposeForSymMerge(length int,
function symBinarySearch (line 55) | func symBinarySearch(u Comparators, start, stop, total int) int {
function symSwap (line 71) | func symSwap(u Comparators, start1, start2, end int) {
function symRotate (line 79) | func symRotate(u Comparators, start1, start2, end int) {
function symMerge (line 109) | func symMerge(u Comparators, start1, start2, last int) {
function SymMerge (line 133) | func SymMerge(u, w Comparators) Comparators {
function prepareForSymMerge (line 179) | func prepareForSymMerge(u, w Comparators) (u1, w1, u2, w2 Comparators) {
FILE: sort/symmerge_test.go
type mockComparator (line 9) | type mockComparator
method Compare (line 11) | func (mc mockComparator) Compare(other Comparator) int {
function constructMockComparators (line 23) | func constructMockComparators(values ...int) Comparators {
function constructOrderedMockComparators (line 32) | func constructOrderedMockComparators(upTo int) Comparators {
function reverseComparators (line 41) | func reverseComparators(comparators Comparators) Comparators {
function TestDecomposeForSymMergeOddNumber (line 49) | func TestDecomposeForSymMergeOddNumber(t *testing.T) {
function TestDecomposeForSymMergeEvenNumber (line 58) | func TestDecomposeForSymMergeEvenNumber(t *testing.T) {
function TestNearCompleteDecomposeForSymMerge (line 67) | func TestNearCompleteDecomposeForSymMerge(t *testing.T) {
function TestDecomposePanicsWithWrongLength (line 76) | func TestDecomposePanicsWithWrongLength(t *testing.T) {
function TestSymSearch (line 83) | func TestSymSearch(t *testing.T) {
function TestSwap (line 97) | func TestSwap(t *testing.T) {
function TestSymMergeSmallLists (line 109) | func TestSymMergeSmallLists(t *testing.T) {
function TestSymMergeAlreadySorted (line 118) | func TestSymMergeAlreadySorted(t *testing.T) {
function TestSymMergeAlreadySortedReverseOrder (line 127) | func TestSymMergeAlreadySortedReverseOrder(t *testing.T) {
function TestSymMergeUnevenLists (line 136) | func TestSymMergeUnevenLists(t *testing.T) {
function TestSymMergeUnevenListsWrongOrder (line 145) | func TestSymMergeUnevenListsWrongOrder(t *testing.T) {
function TestMergeVeryUnevenLists (line 154) | func TestMergeVeryUnevenLists(t *testing.T) {
function TestMergeVeryUnevenListsWrongOrder (line 163) | func TestMergeVeryUnevenListsWrongOrder(t *testing.T) {
function TestMergeVeryUnevenListsAlreadySorted (line 172) | func TestMergeVeryUnevenListsAlreadySorted(t *testing.T) {
function TestMergeVeryUnevenListsAlreadySortedWrongOrder (line 181) | func TestMergeVeryUnevenListsAlreadySortedWrongOrder(t *testing.T) {
function TestMergeVeryUnevenListIsSubset (line 190) | func TestMergeVeryUnevenListIsSubset(t *testing.T) {
function TestMergeVeryUnevenListIsSubsetReverseOrder (line 199) | func TestMergeVeryUnevenListIsSubsetReverseOrder(t *testing.T) {
function TestMergeUnevenOneListIsOne (line 208) | func TestMergeUnevenOneListIsOne(t *testing.T) {
function TestMergeEmptyList (line 217) | func TestMergeEmptyList(t *testing.T) {
FILE: threadsafe/err/error.go
type Error (line 29) | type Error struct
method Set (line 36) | func (e *Error) Set(err error) {
method Get (line 44) | func (e *Error) Get() error {
function New (line 53) | func New() *Error {
FILE: threadsafe/err/error_test.go
function TestGetSetError (line 26) | func TestGetSetError(t *testing.T) {
FILE: tree/avl/avl.go
type Immutable (line 39) | type Immutable struct
method copy (line 47) | func (immutable *Immutable) copy() *Immutable {
method resetDummy (line 60) | func (immutable *Immutable) resetDummy() {
method init (line 65) | func (immutable *Immutable) init() {
method get (line 71) | func (immutable *Immutable) get(entry Entry) Entry {
method Get (line 90) | func (immutable *Immutable) Get(entries ...Entry) Entries {
method Len (line 100) | func (immutable *Immutable) Len() uint64 {
method insert (line 104) | func (immutable *Immutable) insert(entry Entry) Entry {
method Insert (line 190) | func (immutable *Immutable) Insert(entries ...Entry) (*Immutable, Entr...
method delete (line 204) | func (immutable *Immutable) delete(entry Entry) Entry {
method Delete (line 314) | func (immutable *Immutable) Delete(entries ...Entry) (*Immutable, Entr...
function insertBalance (line 328) | func insertBalance(root *node, dir int) *node {
function removeBalance (line 348) | func removeBalance(root *node, dir int, done *int) *node {
function intFromBool (line 374) | func intFromBool(value bool) int {
function takeOpposite (line 382) | func takeOpposite(value int) int {
function adjustBalance (line 386) | func adjustBalance(root *node, dir, bal int) {
function rotate (line 402) | func rotate(parent *node, dir int) *node {
function doubleRotate (line 412) | func doubleRotate(parent *node, dir int) *node {
function normalizeComparison (line 421) | func normalizeComparison(i int) int {
function NewImmutable (line 435) | func NewImmutable() *Immutable {
FILE: tree/avl/avl_test.go
function generateMockEntries (line 25) | func generateMockEntries(num int) Entries {
function TestAVLSimpleInsert (line 34) | func TestAVLSimpleInsert(t *testing.T) {
function TestAVLInsertRightLeaning (line 56) | func TestAVLInsertRightLeaning(t *testing.T) {
function TestAVLInsertRightLeaningDoubleRotation (line 80) | func TestAVLInsertRightLeaningDoubleRotation(t *testing.T) {
function TestAVLInsertLeftLeaning (line 103) | func TestAVLInsertLeftLeaning(t *testing.T) {
function TestAVLInsertLeftLeaningDoubleRotation (line 127) | func TestAVLInsertLeftLeaningDoubleRotation(t *testing.T) {
function TestAVLInsertOverwrite (line 152) | func TestAVLInsertOverwrite(t *testing.T) {
function TestAVLSimpleDelete (line 169) | func TestAVLSimpleDelete(t *testing.T) {
function TestAVLDeleteWithRotation (line 199) | func TestAVLDeleteWithRotation(t *testing.T) {
function TestAVLDeleteWithDoubleRotation (line 217) | func TestAVLDeleteWithDoubleRotation(t *testing.T) {
function TestAVLDeleteAll (line 234) | func TestAVLDeleteAll(t *testing.T) {
function TestAVLDeleteNotLeaf (line 251) | func TestAVLDeleteNotLeaf(t *testing.T) {
function TestAVLBulkDeleteAll (line 264) | func TestAVLBulkDeleteAll(t *testing.T) {
function TestAVLDeleteReplay (line 278) | func TestAVLDeleteReplay(t *testing.T) {
function TestAVLFails (line 298) | func TestAVLFails(t *testing.T) {
function BenchmarkImmutableInsert (line 321) | func BenchmarkImmutableInsert(b *testing.B) {
function BenchmarkImmutableGet (line 335) | func BenchmarkImmutableGet(b *testing.B) {
function BenchmarkImmutableBulkInsert (line 349) | func BenchmarkImmutableBulkInsert(b *testing.B) {
function BenchmarkImmutableDelete (line 362) | func BenchmarkImmutableDelete(b *testing.B) {
function BenchmarkImmutableBulkDelete (line 376) | func BenchmarkImmutableBulkDelete(b *testing.B) {
FILE: tree/avl/interface.go
type Entries (line 20) | type Entries
type Entry (line 26) | type Entry interface
FILE: tree/avl/mock_test.go
type mockEntry (line 19) | type mockEntry
method Compare (line 21) | func (me mockEntry) Compare(other Entry) int {
FILE: tree/avl/node.go
type nodes (line 19) | type nodes
method reset (line 21) | func (ns nodes) reset() {
type node (line 27) | type node struct
method copy (line 35) | func (n *node) copy() *node {
function newNode (line 45) | func newNode(entry Entry) *node {
FILE: trie/ctrie/ctrie.go
constant w (line 39) | w = 5
constant exp2 (line 42) | exp2 = 32
type HashFactory (line 46) | type HashFactory
function defaultHashFactory (line 48) | func defaultHashFactory() hash.Hash32 {
type Ctrie (line 54) | type Ctrie struct
method Insert (line 287) | func (c *Ctrie) Insert(key []byte, value interface{}) {
method Lookup (line 298) | func (c *Ctrie) Lookup(key []byte) (interface{}, bool) {
method Remove (line 304) | func (c *Ctrie) Remove(key []byte) (interface{}, bool) {
method Snapshot (line 311) | func (c *Ctrie) Snapshot() *Ctrie {
method ReadOnlySnapshot (line 317) | func (c *Ctrie) ReadOnlySnapshot() *Ctrie {
method snapshot (line 322) | func (c *Ctrie) snapshot(readOnly bool) *Ctrie {
method Clear (line 343) | func (c *Ctrie) Clear() {
method Iterator (line 361) | func (c *Ctrie) Iterator(cancel <-chan struct{}) <-chan *Entry {
method Size (line 372) | func (c *Ctrie) Size() uint {
method traverse (line 387) | func (c *Ctrie) traverse(i *iNode, ch chan<- *Entry, cancel <-chan str...
method assertReadWrite (line 425) | func (c *Ctrie) assertReadWrite() {
method insert (line 431) | func (c *Ctrie) insert(entry *Entry) {
method lookup (line 438) | func (c *Ctrie) lookup(entry *Entry) (interface{}, bool) {
method remove (line 447) | func (c *Ctrie) remove(entry *Entry) (interface{}, bool) {
method hash (line 456) | func (c *Ctrie) hash(k []byte) uint32 {
method iinsert (line 464) | func (c *Ctrie) iinsert(i *iNode, entry *Entry, lev uint, parent *iNod...
method ilookup (line 538) | func (c *Ctrie) ilookup(i *iNode, entry *Entry, lev uint, parent *iNod...
method iremove (line 594) | func (c *Ctrie) iremove(i *iNode, entry *Entry, lev uint, parent *iNod...
method readRoot (line 856) | func (c *Ctrie) readRoot() *iNode {
method rdcssReadRoot (line 862) | func (c *Ctrie) rdcssReadRoot(abort bool) *iNode {
method rdcssRoot (line 873) | func (c *Ctrie) rdcssRoot(old *iNode, expected *mainNode, nv *iNode) b...
method rdcssComplete (line 889) | func (c *Ctrie) rdcssComplete(abort bool) *iNode {
method casRoot (line 927) | func (c *Ctrie) casRoot(ov, nv *iNode) bool {
type generation (line 64) | type generation struct
type iNode (line 69) | type iNode struct
method copyToGen (line 80) | func (i *iNode) copyToGen(gen *generation, ctrie *Ctrie) *iNode {
type mainNode (line 90) | type mainNode struct
type cNode (line 106) | type cNode struct
method inserted (line 139) | func (c *cNode) inserted(pos, flag uint32, br branch, gen *generation)...
method updated (line 155) | func (c *cNode) updated(pos uint32, br branch, gen *generation) *cNode {
method removed (line 165) | func (c *cNode) removed(pos, flag uint32, gen *generation) *cNode {
method renewed (line 182) | func (c *cNode) renewed(gen *generation, ctrie *Ctrie) *cNode {
function newMainNode (line 116) | func newMainNode(x *sNode, xhc uint32, y *sNode, yhc uint32, lev uint, g...
type tNode (line 197) | type tNode struct
method untombed (line 202) | func (t *tNode) untombed() *sNode {
type lNode (line 208) | type lNode struct
method entry (line 213) | func (l *lNode) entry() *sNode {
method lookup (line 220) | func (l *lNode) lookup(e *Entry) (interface{}, bool) {
method inserted (line 231) | func (l *lNode) inserted(entry *Entry) *lNode {
method removed (line 236) | func (l *lNode) removed(e *Entry) *lNode {
method length (line 248) | func (l *lNode) length() uint {
type branch (line 253) | type branch interface
type Entry (line 256) | type Entry struct
type sNode (line 263) | type sNode struct
function New (line 269) | func New(hashFactory HashFactory) *Ctrie {
function newCtrie (line 277) | func newCtrie(root *iNode, hashFactory HashFactory, readOnly bool) *Ctrie {
function toContracted (line 671) | func toContracted(cn *cNode, lev uint) *mainNode {
function toCompressed (line 685) | func toCompressed(cn *cNode, lev uint) *mainNode {
function entomb (line 704) | func entomb(m *sNode) *mainNode {
function resurrect (line 708) | func resurrect(iNode *iNode, main *mainNode) branch {
function clean (line 715) | func clean(i *iNode, lev uint, ctrie *Ctrie) bool {
function cleanReadOnly (line 723) | func cleanReadOnly(tn *tNode, lev uint, p *iNode, ctrie *Ctrie, entry *E...
function cleanParent (line 734) | func cleanParent(p, i *iNode, hc uint32, lev uint, ctrie *Ctrie, startGe...
function flagPos (line 755) | func flagPos(hashcode uint32, lev uint, bmp uint32) (uint32, uint32) {
function bitCount (line 763) | func bitCount(x uint32) uint32 {
function gcas (line 776) | func gcas(in *iNode, old, n *mainNode, ct *Ctrie) bool {
function gcasRead (line 789) | func gcasRead(in *iNode, ctrie *Ctrie) *mainNode {
function gcasComplete (line 799) | func gcasComplete(i *iNode, m *mainNode, ctrie *Ctrie) *mainNode {
type rdcssDescriptor (line 846) | type rdcssDescriptor struct
FILE: trie/ctrie/ctrie_test.go
function TestCtrie (line 30) | func TestCtrie(t *testing.T) {
type mockHash32 (line 83) | type mockHash32 struct
method Sum32 (line 87) | func (m *mockHash32) Sum32() uint32 {
function mockHashFactory (line 91) | func mockHashFactory() hash.Hash32 {
function TestInsertLNode (line 95) | func TestInsertLNode(t *testing.T) {
function TestInsertTNode (line 118) | func TestInsertTNode(t *testing.T) {
function TestConcurrency (line 141) | func TestConcurrency(t *testing.T) {
function TestConcurrency2 (line 172) | func TestConcurrency2(t *testing.T) {
function TestSnapshot (line 213) | func TestSnapshot(t *testing.T) {
function TestReadOnlySnapshot (line 289) | func TestReadOnlySnapshot(t *testing.T) {
function TestIterator (line 344) | func TestIterator(t *testing.T) {
function TestIteratorCoversTNodes (line 392) | func TestIteratorCoversTNodes(t *testing.T) {
function TestSize (line 409) | func TestSize(t *testing.T) {
function TestClear (line 417) | func TestClear(t *testing.T) {
type fakehash (line 432) | type fakehash struct
method Sum32 (line 434) | func (h *fakehash) Sum32() uint32 {
method Sum (line 438) | func (h *fakehash) Sum(b []byte) []byte {
method Size (line 442) | func (h *fakehash) Size() int {
method BlockSize (line 446) | func (h *fakehash) BlockSize() int {
method Reset (line 450) | func (h *fakehash) Reset() {
method Write (line 454) | func (h *fakehash) Write(b []byte) (int, error) {
function factory (line 458) | func factory() hash.Hash32 {
function TestHashCollision (line 462) | func TestHashCollision(t *testing.T) {
function BenchmarkInsert (line 477) | func BenchmarkInsert(b *testing.B) {
function BenchmarkLookup (line 485) | func BenchmarkLookup(b *testing.B) {
function BenchmarkRemove (line 499) | func BenchmarkRemove(b *testing.B) {
function BenchmarkSnapshot (line 513) | func BenchmarkSnapshot(b *testing.B) {
function BenchmarkReadOnlySnapshot (line 526) | func BenchmarkReadOnlySnapshot(b *testing.B) {
FILE: trie/dtrie/dtrie.go
type Dtrie (line 37) | type Dtrie struct
method Size (line 73) | func (d *Dtrie) Size() (size int) {
method Get (line 82) | func (d *Dtrie) Get(key interface{}) interface{} {
method Insert (line 92) | func (d *Dtrie) Insert(key, value interface{}) *Dtrie {
method Remove (line 99) | func (d *Dtrie) Remove(key interface{}) *Dtrie {
method Iterator (line 108) | func (d *Dtrie) Iterator(stop <-chan struct{}) <-chan Entry {
type entry (line 42) | type entry struct
method KeyHash (line 48) | func (e *entry) KeyHash() uint32 {
method Key (line 52) | func (e *entry) Key() interface{} {
method Value (line 56) | func (e *entry) Value() interface{} {
function New (line 62) | func New(hasher func(v interface{}) uint32) *Dtrie {
FILE: trie/dtrie/dtrie_test.go
function TestDefaultHasher (line 35) | func TestDefaultHasher(t *testing.T) {
function collisionHash (line 42) | func collisionHash(key interface{}) uint32 {
function TestInsert (line 46) | func TestInsert(t *testing.T) {
function insertTest (line 51) | func insertTest(t *testing.T, hashfunc func(interface{}) uint32, count i...
function TestGet (line 59) | func TestGet(t *testing.T) {
function getTest (line 64) | func getTest(t *testing.T, hashfunc func(interface{}) uint32, count int) {
function TestRemove (line 72) | func TestRemove(t *testing.T) {
function removeTest (line 77) | func removeTest(t *testing.T, hashfunc func(interface{}) uint32, count i...
function TestUpdate (line 89) | func TestUpdate(t *testing.T) {
function updateTest (line 94) | func updateTest(t *testing.T, hashfunc func(interface{}) uint32, count i...
function TestIterate (line 101) | func TestIterate(t *testing.T) {
function TestSize (line 131) | func TestSize(t *testing.T) {
function BenchmarkInsert (line 137) | func BenchmarkInsert(b *testing.B) {
function BenchmarkGet (line 146) | func BenchmarkGet(b *testing.B) {
function BenchmarkRemove (line 155) | func BenchmarkRemove(b *testing.B) {
function BenchmarkUpdate (line 164) | func BenchmarkUpdate(b *testing.B) {
FILE: trie/dtrie/node.go
type node (line 36) | type node struct
method KeyHash (line 43) | func (n *node) KeyHash() uint32 { return 0 }
method Key (line 44) | func (n *node) Key() interface{} { return nil }
method Value (line 45) | func (n *node) Value() interface{} { return nil }
method String (line 47) | func (n *node) String() string {
type collisionNode (line 51) | type collisionNode struct
method KeyHash (line 55) | func (n *collisionNode) KeyHash() uint32 { return 0 }
method Key (line 56) | func (n *collisionNode) Key() interface{} { return nil }
method Value (line 57) | func (n *collisionNode) Value() interface{} { return nil }
method String (line 59) | func (n *collisionNode) String() string {
type Entry (line 64) | type Entry interface
function emptyNode (line 70) | func emptyNode(level uint8, capacity int) *node {
function insert (line 74) | func insert(n *node, entry Entry) *node {
function get (line 128) | func get(n *node, keyHash uint32, key interface{}) Entry {
function remove (line 150) | func remove(n *node, keyHash uint32, key interface{}) *node {
function iterate (line 195) | func iterate(n *node, stop <-chan struct{}) <-chan Entry {
function pushEntries (line 204) | func pushEntries(n *node, stop <-chan struct{}, out chan Entry) {
FILE: trie/dtrie/util.go
function mask (line 34) | func mask(hash uint32, level uint8) uint32 {
function defaultHasher (line 38) | func defaultHasher(value interface{}) uint32 {
FILE: trie/xfast/iterator.go
type Entries (line 20) | type Entries
type Iterator (line 23) | type Iterator struct
method Next (line 30) | func (iter *Iterator) Next() bool {
method Value (line 43) | func (iter *Iterator) Value() Entry {
method exhaust (line 53) | func (iter *Iterator) exhaust() Entries {
FILE: trie/xfast/iterator_test.go
function TestIterator (line 25) | func TestIterator(t *testing.T) {
FILE: trie/xfast/mock_test.go
type mockEntry (line 21) | type mockEntry struct
method Key (line 25) | func (me *mockEntry) Key() uint64 {
function newMockEntry (line 30) | func newMockEntry(key uint64) *mockEntry {
FILE: trie/xfast/xfast.go
function isInternal (line 51) | func isInternal(n *node) bool {
function hasInternal (line 60) | func hasInternal(n *node) bool {
function isLeaf (line 66) | func isLeaf(n *node) bool {
type Entry (line 75) | type Entry interface
type node (line 113) | type node struct
function newNode (line 131) | func newNode(parent *node, entry Entry) *node {
function binarySearchHashMaps (line 144) | func binarySearchHashMaps(layers []map[uint64]*node, key uint64) (int, *...
function whichSide (line 168) | func whichSide(n, parent *node) int {
type XFastTrie (line 185) | type XFastTrie struct
method init (line 216) | func (xft *XFastTrie) init(intType interface{}) {
method Exists (line 244) | func (xft *XFastTrie) Exists(key uint64) bool {
method Len (line 253) | func (xft *XFastTrie) Len() uint64 {
method Max (line 259) | func (xft *XFastTrie) Max() Entry {
method Min (line 269) | func (xft *XFastTrie) Min() Entry {
method insert (line 279) | func (xft *XFastTrie) insert(entry Entry) {
method walkUpSuccessor (line 383) | func (xft *XFastTrie) walkUpSuccessor(root, node, successor *node) {
method walkUpPredecessor (line 398) | func (xft *XFastTrie) walkUpPredecessor(root, node, predecessor *node) {
method walkUpNode (line 411) | func (xft *XFastTrie) walkUpNode(root, node, predecessor, successor *n...
method Insert (line 427) | func (xft *XFastTrie) Insert(entries ...Entry) {
method delete (line 433) | func (xft *XFastTrie) delete(key uint64) {
method Delete (line 502) | func (xft *XFastTrie) Delete(keys ...uint64) {
method predecessor (line 510) | func (xft *XFastTrie) predecessor(key uint64) *node {
method successor (line 543) | func (xft *XFastTrie) successor(key uint64) *node {
method Successor (line 577) | func (xft *XFastTrie) Successor(key uint64) Entry {
method Predecessor (line 589) | func (xft *XFastTrie) Predecessor(key uint64) Entry {
method Iter (line 601) | func (xft *XFastTrie) Iter(key uint64) *Iterator {
method Get (line 611) | func (xft *XFastTrie) Get(key uint64) Entry {
function New (line 627) | func New(ifc interface{}) *XFastTrie {
FILE: trie/xfast/xfast_test.go
function checkTrie (line 29) | func checkTrie(t *testing.T, xft *XFastTrie) {
function checkSuccessor (line 35) | func checkSuccessor(t *testing.T, xft *XFastTrie) {
function checkPredecessor (line 68) | func checkPredecessor(t *testing.T, xft *XFastTrie) {
function checkNodes (line 100) | func checkNodes(t *testing.T, xft *XFastTrie) {
function checkNode (line 112) | func checkNode(t *testing.T, xft *XFastTrie, n *node) {
function dumpNode (line 127) | func dumpNode(t *testing.T, n *node) {
function checkPattern (line 134) | func checkPattern(t *testing.T, n *node, pattern []int) {
function TestEmptyMinMax (line 150) | func TestEmptyMinMax(t *testing.T) {
function TestMask (line 157) | func TestMask(t *testing.T) {
function TestInsert (line 161) | func TestInsert(t *testing.T) {
function TestGet (line 181) | func TestGet(t *testing.T) {
function TestInsertOverwrite (line 190) | func TestInsertOverwrite(t *testing.T) {
function TestInsertBetween (line 203) | func TestInsertBetween(t *testing.T) {
function TestSuccessorDoesNotExist (line 246) | func TestSuccessorDoesNotExist(t *testing.T) {
function TestSuccessorIsExactValue (line 255) | func TestSuccessorIsExactValue(t *testing.T) {
function TestSuccessorGreaterThanKey (line 264) | func TestSuccessorGreaterThanKey(t *testing.T) {
function TestSuccessorCloseToKey (line 273) | func TestSuccessorCloseToKey(t *testing.T) {
function TestSuccessorBetweenTwoKeys (line 282) | func TestSuccessorBetweenTwoKeys(t *testing.T) {
function TestPredecessorDoesNotExist (line 301) | func TestPredecessorDoesNotExist(t *testing.T) {
function TestPredecessorIsExactValue (line 310) | func TestPredecessorIsExactValue(t *testing.T) {
function TestPredecessorLessThanKey (line 319) | func TestPredecessorLessThanKey(t *testing.T) {
function TestPredecessorCloseToKey (line 328) | func TestPredecessorCloseToKey(t *testing.T) {
function TestPredecessorBetweenTwoKeys (line 337) | func TestPredecessorBetweenTwoKeys(t *testing.T) {
function TestInsertPredecessor (line 356) | func TestInsertPredecessor(t *testing.T) {
function TestDeleteOnlyBranch (line 381) | func TestDeleteOnlyBranch(t *testing.T) {
function TestDeleteLargeBranch (line 403) | func TestDeleteLargeBranch(t *testing.T) {
function TestDeleteLateBranching (line 428) | func TestDeleteLateBranching(t *testing.T) {
function TestDeleteLateBranchingMin (line 451) | func TestDeleteLateBranchingMin(t *testing.T) {
function TestDeleteMiddleBranch (line 477) | func TestDeleteMiddleBranch(t *testing.T) {
function TestDeleteMiddleBranchOtherSide (line 495) | func TestDeleteMiddleBranchOtherSide(t *testing.T) {
function TestDeleteNotFound (line 513) | func TestDeleteNotFound(t *testing.T) {
function BenchmarkSuccessor (line 525) | func BenchmarkSuccessor(b *testing.B) {
function BenchmarkDelete (line 540) | func BenchmarkDelete(b *testing.B) {
function BenchmarkInsert (line 558) | func BenchmarkInsert(b *testing.B) {
function BenchmarkListInsert (line 567) | func BenchmarkListInsert(b *testing.B) {
function BenchmarkListSearch (line 582) | func BenchmarkListSearch(b *testing.B) {
FILE: trie/yfast/entries.go
type entriesWrapper (line 21) | type entriesWrapper struct
method Key (line 29) | func (ew *entriesWrapper) Key() uint64 {
type Entries (line 36) | type Entries
method search (line 43) | func (entries Entries) search(key uint64) int {
method insert (line 53) | func (entries *Entries) insert(entry Entry) Entry {
method delete (line 76) | func (entries *Entries) delete(key uint64) Entry {
method max (line 96) | func (entries Entries) max() (uint64, bool) {
method get (line 107) | func (entries Entries) get(key uint64) Entry {
method successor (line 124) | func (entries Entries) successor(key uint64) (Entry, int) {
method predecessor (line 137) | func (entries Entries) predecessor(key uint64) (Entry, int) {
FILE: trie/yfast/entries_test.go
function TestEntriesInsert (line 25) | func TestEntriesInsert(t *testing.T) {
function TestEntriesDelete (line 42) | func TestEntriesDelete(t *testing.T) {
function TestEntriesMax (line 57) | func TestEntriesMax(t *testing.T) {
function TestEntriesGet (line 76) | func TestEntriesGet(t *testing.T) {
function TestEntriesSuccessor (line 94) | func TestEntriesSuccessor(t *testing.T) {
function TestEntriesPredecessor (line 123) | func TestEntriesPredecessor(t *testing.T) {
FILE: trie/yfast/interface.go
type Entry (line 21) | type Entry interface
FILE: trie/yfast/iterator.go
constant iteratorExhausted (line 23) | iteratorExhausted = -2
function iterExhausted (line 27) | func iterExhausted(iter *Iterator) bool {
type Iterator (line 32) | type Iterator struct
method Next (line 40) | func (iter *Iterator) Next() bool {
method Value (line 66) | func (iter *Iterator) Value() Entry {
method exhaust (line 80) | func (iter *Iterator) exhaust() Entries {
function nilIterator (line 91) | func nilIterator() *Iterator {
FILE: trie/yfast/mock_test.go
type mockEntry (line 19) | type mockEntry struct
method Key (line 24) | func (me *mockEntry) Key() uint64 {
function newMockEntry (line 28) | func newMockEntry(key uint64) *mockEntry {
FILE: trie/yfast/yfast.go
type YFastTrie (line 45) | type YFastTrie struct
method init (line 51) | func (yfast *YFastTrie) init(intType interface{}) {
method getBucketKey (line 71) | func (yfast *YFastTrie) getBucketKey(key uint64) uint64 {
method insert (line 76) | func (yfast *YFastTrie) insert(entry Entry) Entry {
method Insert (line 107) | func (yfast *YFastTrie) Insert(entries ...Entry) Entries {
method delete (line 116) | func (yfast *YFastTrie) delete(key uint64) Entry {
method Delete (line 141) | func (yfast *YFastTrie) Delete(keys ...uint64) Entries {
method get (line 150) | func (yfast *YFastTrie) get(key uint64) Entry {
method Get (line 168) | func (yfast *YFastTrie) Get(key uint64) Entry {
method Len (line 178) | func (yfast *YFastTrie) Len() uint64 {
method successor (line 182) | func (yfast *YFastTrie) successor(key uint64) Entry {
method Successor (line 199) | func (yfast *YFastTrie) Successor(key uint64) Entry {
method predecessor (line 208) | func (yfast *YFastTrie) predecessor(key uint64) Entry {
method Predecessor (line 242) | func (yfast *YFastTrie) Predecessor(key uint64) Entry {
method iter (line 251) | func (yfast *YFastTrie) iter(key uint64) *Iterator {
method Iter (line 270) | func (yfast *YFastTrie) Iter(key uint64) *Iterator {
function New (line 278) | func New(ifc interface{}) *YFastTrie {
FILE: trie/yfast/yfast_test.go
function generateEntries (line 25) | func generateEntries(num int) Entries {
function TestTrieSimpleInsert (line 34) | func TestTrieSimpleInsert(t *testing.T) {
function TestTrieOverwriteInsert (line 58) | func TestTrieOverwriteInsert(t *testing.T) {
function TestTrieDelete (line 70) | func TestTrieDelete(t *testing.T) {
function TestTrieSuccessor (line 99) | func TestTrieSuccessor(t *testing.T) {
function TestTriePredecessor (line 132) | func TestTriePredecessor(t *testing.T) {
function TestTrieIterator (line 160) | func TestTrieIterator(t *testing.T) {
function BenchmarkInsert (line 194) | func BenchmarkInsert(b *testing.B) {
function BenchmarkGet (line 205) | func BenchmarkGet(b *testing.B) {
function BenchmarkDelete (line 220) | func BenchmarkDelete(b *testing.B) {
function BenchmarkSuccessor (line 232) | func BenchmarkSuccessor(b *testing.B) {
function BenchmarkPredecessor (line 250) | func BenchmarkPredecessor(b *testing.B) {
function BenchmarkIterator (line 268) | func BenchmarkIterator(b *testing.B) {
Condensed preview — 180 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (904K chars).
[
{
"path": ".github/CODEOWNERS",
"chars": 17,
"preview": "@Workiva/skreams\n"
},
{
"path": ".github/workflows/tests.yaml",
"chars": 1589,
"preview": "name: \"Tests\"\n\non:\n pull_request:\n push:\n branches:\n - 'master'\n tags:\n - '*'\n\npermissions:\n pull-req"
},
{
"path": ".gitignore",
"chars": 19,
"preview": "*.out\n*.test\n.idea\n"
},
{
"path": "Dockerfile",
"chars": 434,
"preview": "FROM golang:1.16-alpine3.13 AS build-go\n\nARG GIT_SSH_KEY\nARG KNOWN_HOSTS_CONTENT\nWORKDIR /go/src/github.com/Workiva/go-d"
},
{
"path": "LICENSE",
"chars": 11357,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 10976,
"preview": "go-datastructures\n=================\n\nGo-datastructures is a collection of useful, performant, and threadsafe Go\ndatastru"
},
{
"path": "augmentedtree/atree.go",
"chars": 9684,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "augmentedtree/atree_test.go",
"chars": 14899,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "augmentedtree/interface.go",
"chars": 3061,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "augmentedtree/intervals.go",
"chars": 987,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "augmentedtree/intervals_test.go",
"chars": 858,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "augmentedtree/mock_test.go",
"chars": 1680,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "augmentedtree/multidimensional_test.go",
"chars": 10248,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "aviary.yaml",
"chars": 159,
"preview": "version: 1\n\nexclude:\n - tests?/\n\nraven_monitored_classes: null\n\nraven_monitored_files: null\n\nraven_monitored_functions:"
},
{
"path": "batcher/batcher.go",
"chars": 7891,
"preview": "/*\nCopyright 2015 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "batcher/batcher_test.go",
"chars": 3571,
"preview": "/*\nCopyright 2015 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "bitarray/and.go",
"chars": 3792,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "bitarray/and_test.go",
"chars": 4616,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "bitarray/bitarray.go",
"chars": 9150,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "bitarray/bitarray_test.go",
"chars": 10157,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "bitarray/bitmap.go",
"chars": 3161,
"preview": "/*\nCopyright (c) 2016, Theodore Butler\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or "
},
{
"path": "bitarray/bitmap_test.go",
"chars": 3117,
"preview": "/*\nCopyright (c) 2016, Theodore Butler\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or "
},
{
"path": "bitarray/block.go",
"chars": 2262,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "bitarray/block_test.go",
"chars": 1092,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "bitarray/encoding.go",
"chars": 6127,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "bitarray/encoding_test.go",
"chars": 3180,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "bitarray/error.go",
"chars": 893,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "bitarray/interface.go",
"chars": 3484,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "bitarray/iterator.go",
"chars": 1897,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "bitarray/nand.go",
"chars": 4456,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "bitarray/nand_test.go",
"chars": 6451,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "bitarray/or.go",
"chars": 3703,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "bitarray/or_test.go",
"chars": 5077,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "bitarray/sparse_bitarray.go",
"chars": 8047,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "bitarray/sparse_bitarray_test.go",
"chars": 7657,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "bitarray/util.go",
"chars": 1275,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/_link/interface.go",
"chars": 915,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/_link/key.go",
"chars": 2104,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/_link/mock_test.go",
"chars": 741,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/_link/node.go",
"chars": 5617,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/_link/node_test.go",
"chars": 4069,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/_link/tree.go",
"chars": 3983,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/_link/tree_test.go",
"chars": 6781,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/immutable/add.go",
"chars": 7040,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/immutable/cacher.go",
"chars": 3181,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/immutable/config.go",
"chars": 1533,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/immutable/delete.go",
"chars": 6450,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/immutable/error.go",
"chars": 851,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/immutable/interface.go",
"chars": 3603,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/immutable/item.go",
"chars": 890,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/immutable/node.go",
"chars": 12690,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/immutable/node_gen.go",
"chars": 6206,
"preview": "package btree\n\n// NOTE: THIS FILE WAS PRODUCED BY THE\n// MSGP CODE GENERATION TOOL (github.com/tinylib/msgp)\n// DO NOT E"
},
{
"path": "btree/immutable/path.go",
"chars": 1488,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/immutable/query.go",
"chars": 4057,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/immutable/rt.go",
"chars": 5037,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/immutable/rt_gen.go",
"chars": 1663,
"preview": "package btree\n\n// NOTE: THIS FILE WAS PRODUCED BY THE\n// MSGP CODE GENERATION TOOL (github.com/tinylib/msgp)\n// DO NOT E"
},
{
"path": "btree/immutable/rt_test.go",
"chars": 23770,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/palm/action.go",
"chars": 3960,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/palm/interface.go",
"chars": 2551,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/palm/key.go",
"chars": 1102,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/palm/mock_test.go",
"chars": 813,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/palm/node.go",
"chars": 5518,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/palm/tree.go",
"chars": 12634,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/palm/tree_test.go",
"chars": 12376,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/plus/btree.go",
"chars": 3033,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/plus/btree_test.go",
"chars": 8515,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/plus/interface.go",
"chars": 1466,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/plus/iterator.go",
"chars": 1422,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/plus/mock_test.go",
"chars": 1055,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/plus/node.go",
"chars": 5637,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "btree/plus/node_test.go",
"chars": 4764,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "cache/cache.go",
"chars": 4871,
"preview": "package cache\n\nimport (\n\t\"container/list\"\n\t\"sync\"\n)\n\n// Cache is a bounded-size in-memory cache of sized items with a co"
},
{
"path": "cache/cache_test.go",
"chars": 2944,
"preview": "package cache\n\nimport (\n\t\"container/list\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestEvictionPolicy(t"
},
{
"path": "common/interface.go",
"chars": 946,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "datastructures.go",
"chars": 1429,
"preview": "/*\nPackage datastructures exists solely to aid consumers of the go-datastructures\nlibrary when using dependency managers"
},
{
"path": "documentation.md",
"chars": 7276,
"preview": "# Introducing go-datastructures\n\nThe goal of the go-datastructures library is to port implementations of some common dat"
},
{
"path": "fibheap/Test Generator/EnqDecrKey.py",
"chars": 725,
"preview": "l = [-2901939070.965906, 4539462982.372177, -6222008480.049856,\n -1400427921.5968666, 9866088144.060883,\n -2943107"
},
{
"path": "fibheap/Test Generator/EnqDelete.py",
"chars": 678,
"preview": "l = [-2901939070.965906, 4539462982.372177, -6222008480.049856,\n -1400427921.5968666, 9866088144.060883, -2943107"
},
{
"path": "fibheap/Test Generator/EnqDeqMin.py",
"chars": 137,
"preview": "#!/usr/bin/python3\n\nimport random\n\nl = []\nfor i in range(20):\n l.append(random.uniform(-1E10, 1E10))\n\nprint(l)\nl = so"
},
{
"path": "fibheap/Test Generator/Merge.py",
"chars": 1791,
"preview": "import random\n\nl1 = []\nl2 = []\nfor i in range(20):\n l1.append(random.uniform(-1E10, 1E10))\n l2.append(rand"
},
{
"path": "fibheap/Test Generator/README.md",
"chars": 74,
"preview": "These are some Python helper scripts to help generate sample test arrays.\n"
},
{
"path": "fibheap/benchmarks.txt",
"chars": 557,
"preview": "BenchmarkFibHeap_Enqueue-4 \t10000000\t 280 ns/op\t 64 B/op\t 1 allocs/op\nBenchmarkFibHeap_DequeueMin"
},
{
"path": "fibheap/fibheap.go",
"chars": 11996,
"preview": "/*\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with t"
},
{
"path": "fibheap/fibheap_examples_test.go",
"chars": 2948,
"preview": "package fibheap\n\n// Tests for the Fibonacci heap with floating point number priorities\n\nimport (\n\t\"fmt\"\n)\n\nconst SomeNum"
},
{
"path": "fibheap/fibheap_single_example_test.go",
"chars": 2430,
"preview": "package fibheap\n\n// Example usage of the Fibonacci heap\n\nimport (\n\t\"fmt\"\n)\n\nconst SomeNumberAround0 float64 = -0.001\ncon"
},
{
"path": "fibheap/fibheap_test.go",
"chars": 15833,
"preview": "package fibheap\n\n// Tests for the Fibonacci heap with floating point number priorities\n\nimport (\n\t\"testing\"\n\n\t\"math/rand"
},
{
"path": "futures/futures.go",
"chars": 3060,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "futures/futures_test.go",
"chars": 1959,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "futures/selectable.go",
"chars": 2807,
"preview": "/*\nCopyright 2016 Workiva, LLC\nCopyright 2016 Sokolov Yura aka funny_falcon\n\nLicensed under the Apache License, Version "
},
{
"path": "futures/selectable_test.go",
"chars": 1728,
"preview": "/*\nCopyright 2016 Workiva, LLC\nCopyright 2016 Sokolov Yura aka funny_falcon\n\nLicensed under the Apache License, Version "
},
{
"path": "go.mod",
"chars": 134,
"preview": "module github.com/Workiva/go-datastructures\n\ngo 1.15\n\nrequire (\n\tgithub.com/stretchr/testify v1.7.0\n\tgithub.com/tinylib/"
},
{
"path": "go.sum",
"chars": 3724,
"preview": "github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=\ngithub.com/davecgh/go-spew v1.1.0/go.m"
},
{
"path": "graph/simple.go",
"chars": 3205,
"preview": "/*\nCopyright 2017 Julian Griggs\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fi"
},
{
"path": "graph/simple_test.go",
"chars": 5023,
"preview": "/*\nCopyright 2017 Julian Griggs\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fi"
},
{
"path": "hashmap/fastinteger/hash.go",
"chars": 339,
"preview": "package fastinteger\n\n// hash will convert the uint64 key into a hash based on Murmur3's 64-bit\n// integer finalizer.\n// "
},
{
"path": "hashmap/fastinteger/hash_test.go",
"chars": 977,
"preview": "package fastinteger\n\nimport (\n\t\"encoding/binary\"\n\t\"hash/fnv\"\n\t\"math/rand\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/test"
},
{
"path": "hashmap/fastinteger/hashmap.go",
"chars": 4439,
"preview": "// Package fastinteger is designed to provide a very primitive\n// implementation of a hash map for unsigned integer keys"
},
{
"path": "hashmap/fastinteger/hashmap_test.go",
"chars": 5099,
"preview": "package fastinteger\n\nimport (\n\t\"math/rand\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc generateKey"
},
{
"path": "list/persistent.go",
"chars": 6888,
"preview": "/*\nCopyright 2015 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "list/persistent_test.go",
"chars": 5338,
"preview": "/*\nCopyright 2015 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "mock/batcher.go",
"chars": 1234,
"preview": "/*\nCopyright 2015 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "mock/rangetree.go",
"chars": 1307,
"preview": "package mock\n\nimport (\n\t\"github.com/stretchr/testify/mock\"\n\n\t\"github.com/Workiva/go-datastructures/rangetree\"\n)\n\ntype Ra"
},
{
"path": "numerics/hilbert/hilbert.go",
"chars": 2246,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "numerics/hilbert/hilbert_test.go",
"chars": 1583,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "numerics/optimization/global.go",
"chars": 4644,
"preview": "package optimization\n\nimport (\n\t\"math\"\n\t\"sort\"\n)\n\ntype pbs []*vertexProbabilityBundle\n\ntype vertexProbabilityBundle stru"
},
{
"path": "numerics/optimization/nelder_mead.go",
"chars": 16910,
"preview": "package optimization\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"math/rand\"\n\t\"sort\"\n\t\"time\"\n)\n\nconst (\n\talpha = 1 // reflecti"
},
{
"path": "numerics/optimization/nelder_mead_test.go",
"chars": 4832,
"preview": "package optimization\n\nimport (\n\t\"math\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestNelderMead(t *testi"
},
{
"path": "queue/error.go",
"chars": 1021,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "queue/mock_test.go",
"chars": 737,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "queue/priority_queue.go",
"chars": 5986,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "queue/priority_queue_test.go",
"chars": 4285,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "queue/queue.go",
"chars": 9430,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "queue/queue_test.go",
"chars": 10700,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "queue/ring.go",
"chars": 5556,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "queue/ring_test.go",
"chars": 6467,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rangetree/entries.go",
"chars": 1154,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rangetree/entries_test.go",
"chars": 806,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rangetree/error.go",
"chars": 1131,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rangetree/immutable.go",
"chars": 6730,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rangetree/immutable_test.go",
"chars": 15937,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rangetree/interface.go",
"chars": 3717,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rangetree/mock_test.go",
"chars": 1363,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rangetree/node.go",
"chars": 900,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rangetree/ordered.go",
"chars": 5452,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rangetree/ordered_test.go",
"chars": 3700,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rangetree/orderedtree.go",
"chars": 6343,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rangetree/orderedtree_test.go",
"chars": 17359,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rangetree/skiplist/mock_test.go",
"chars": 1160,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rangetree/skiplist/skiplist.go",
"chars": 11662,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rangetree/skiplist/skiplist_test.go",
"chars": 10808,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rtree/hilbert/action.go",
"chars": 3319,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rtree/hilbert/hilbert.go",
"chars": 2103,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rtree/hilbert/mock_test.go",
"chars": 966,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rtree/hilbert/node.go",
"chars": 7287,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rtree/hilbert/rectangle.go",
"chars": 2008,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rtree/hilbert/tree.go",
"chars": 10053,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rtree/hilbert/tree_test.go",
"chars": 11141,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "rtree/interface.go",
"chars": 1479,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "set/dict.go",
"chars": 3596,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "set/dict_test.go",
"chars": 4251,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "slice/int64.go",
"chars": 2401,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "slice/int64_test.go",
"chars": 1227,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "slice/skip/interface.go",
"chars": 1229,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "slice/skip/iterator.go",
"chars": 1817,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "slice/skip/iterator_test.go",
"chars": 1275,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "slice/skip/mock_test.go",
"chars": 1285,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "slice/skip/node.go",
"chars": 1440,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "slice/skip/skip.go",
"chars": 13634,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "slice/skip/skip_test.go",
"chars": 9721,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "sort/interface.go",
"chars": 1042,
"preview": "package merge\n\n// Comparators defines a typed list of type Comparator.\ntype Comparators []Comparator\n\n// Less returns a "
},
{
"path": "sort/sort.go",
"chars": 1813,
"preview": "package merge\n\nimport (\n\t\"runtime\"\n\t\"sort\"\n\t\"sync\"\n)\n\nfunc sortBucket(comparators Comparators) {\n\tsort.Sort(comparators)"
},
{
"path": "sort/sort_test.go",
"chars": 933,
"preview": "package merge\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestMultiThreadedSortEvenNumber(t *tes"
},
{
"path": "sort/symmerge.go",
"chars": 4656,
"preview": "package merge\n\nimport (\n\t\"math\"\n\t\"sync\"\n)\n\n// symSearch is like symBinarySearch but operates\n// on two sorted lists inst"
},
{
"path": "sort/symmerge_test.go",
"chars": 5649,
"preview": "package merge\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\ntype mockComparator int\n\nfunc (mc mockCompa"
},
{
"path": "threadsafe/err/error.go",
"chars": 1466,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "threadsafe/err/error_test.go",
"chars": 786,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "tree/avl/avl.go",
"chars": 9761,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "tree/avl/avl_test.go",
"chars": 9984,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "tree/avl/interface.go",
"chars": 1079,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "tree/avl/mock_test.go",
"chars": 748,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "tree/avl/node.go",
"chars": 1196,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "trie/ctrie/ctrie.go",
"chars": 27435,
"preview": "/*\nCopyright 2015 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "trie/ctrie/ctrie_test.go",
"chars": 11044,
"preview": "/*\nCopyright 2015 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "trie/dtrie/dtrie.go",
"chars": 3740,
"preview": "/*\nCopyright (c) 2016, Theodore Butler\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or "
},
{
"path": "trie/dtrie/dtrie_test.go",
"chars": 4382,
"preview": "/*\nCopyright (c) 2016, Theodore Butler\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or "
},
{
"path": "trie/dtrie/node.go",
"chars": 6628,
"preview": "/*\nCopyright (c) 2016, Theodore Butler\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or "
},
{
"path": "trie/dtrie/util.go",
"chars": 2026,
"preview": "/*\nCopyright (c) 2016, Theodore Butler\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or "
},
{
"path": "trie/xfast/iterator.go",
"chars": 1565,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "trie/xfast/iterator_test.go",
"chars": 1264,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "trie/xfast/mock_test.go",
"chars": 846,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "trie/xfast/xfast.go",
"chars": 18414,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "trie/xfast/xfast_test.go",
"chars": 12121,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "trie/yfast/entries.go",
"chars": 4050,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "trie/yfast/entries_test.go",
"chars": 2931,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "trie/yfast/interface.go",
"chars": 862,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "trie/yfast/iterator.go",
"chars": 2494,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "trie/yfast/mock_test.go",
"chars": 788,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "trie/yfast/yfast.go",
"chars": 6955,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
},
{
"path": "trie/yfast/yfast_test.go",
"chars": 5581,
"preview": "/*\nCopyright 2014 Workiva, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fil"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the Workiva/go-datastructures GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 180 files (812.0 KB), approximately 244.2k tokens, and a symbol index with 2051 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.