Vendor main dependencies.
This commit is contained in:
parent
49a09ab7dd
commit
dd5e3fba01
2738 changed files with 1045689 additions and 0 deletions
84
vendor/github.com/BurntSushi/ty/fun/chan.go
generated
vendored
Normal file
84
vendor/github.com/BurntSushi/ty/fun/chan.go
generated
vendored
Normal file
|
@ -0,0 +1,84 @@
|
|||
package fun
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/BurntSushi/ty"
|
||||
)
|
||||
|
||||
// AsyncChan has a parametric type:
|
||||
//
|
||||
// func AsyncChan(chan A) (send chan<- A, recv <-chan A)
|
||||
//
|
||||
// AsyncChan provides a channel abstraction without a fixed size buffer.
|
||||
// The input should be a pointer to a channel that has a type without a
|
||||
// direction, e.g., `new(chan int)`. Two new channels are returned: `send` and
|
||||
// `recv`. The caller must send data on the `send` channel and receive data on
|
||||
// the `recv` channel.
|
||||
//
|
||||
// Implementation is inspired by Kyle Lemons' work:
|
||||
// https://github.com/kylelemons/iq/blob/master/iq_slice.go
|
||||
func AsyncChan(baseChan interface{}) (send, recv interface{}) {
|
||||
chk := ty.Check(
|
||||
new(func(*chan ty.A) (chan ty.A, chan ty.A)),
|
||||
baseChan)
|
||||
|
||||
// We don't care about the baseChan---it is only used to construct
|
||||
// the return types.
|
||||
tsend, trecv := chk.Returns[0], chk.Returns[1]
|
||||
|
||||
buf := make([]reflect.Value, 0, 10)
|
||||
rsend := reflect.MakeChan(tsend, 0)
|
||||
rrecv := reflect.MakeChan(trecv, 0)
|
||||
|
||||
go func() {
|
||||
defer rrecv.Close()
|
||||
|
||||
BUFLOOP:
|
||||
for {
|
||||
if len(buf) == 0 {
|
||||
rv, ok := rsend.Recv()
|
||||
if !ok {
|
||||
break BUFLOOP
|
||||
}
|
||||
buf = append(buf, rv)
|
||||
}
|
||||
|
||||
cases := []reflect.SelectCase{
|
||||
// case v, ok := <-send
|
||||
{
|
||||
Dir: reflect.SelectRecv,
|
||||
Chan: rsend,
|
||||
},
|
||||
// case recv <- buf[0]
|
||||
{
|
||||
Dir: reflect.SelectSend,
|
||||
Chan: rrecv,
|
||||
Send: buf[0],
|
||||
},
|
||||
}
|
||||
choice, rval, rok := reflect.Select(cases)
|
||||
switch choice {
|
||||
case 0:
|
||||
// case v, ok := <-send
|
||||
if !rok {
|
||||
break BUFLOOP
|
||||
}
|
||||
buf = append(buf, rval)
|
||||
case 1:
|
||||
// case recv <- buf[0]
|
||||
buf = buf[1:]
|
||||
default:
|
||||
panic("bug")
|
||||
}
|
||||
}
|
||||
for _, rv := range buf {
|
||||
rrecv.Send(rv)
|
||||
}
|
||||
}()
|
||||
|
||||
// Create the directional channel types.
|
||||
tsDir := reflect.ChanOf(reflect.SendDir, tsend.Elem())
|
||||
trDir := reflect.ChanOf(reflect.RecvDir, trecv.Elem())
|
||||
return rsend.Convert(tsDir).Interface(), rrecv.Convert(trDir).Interface()
|
||||
}
|
118
vendor/github.com/BurntSushi/ty/fun/doc.go
generated
vendored
Normal file
118
vendor/github.com/BurntSushi/ty/fun/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
Package fun provides type parametric utility functions for lists, sets,
|
||||
channels and maps.
|
||||
|
||||
The central contribution of this package is a set of functions that operate
|
||||
on values without depending on their types while maintaining type safety at
|
||||
run time using the `reflect` package.
|
||||
|
||||
There are two primary concerns when deciding whether to use this package
|
||||
or not: the loss of compile time type safety and performance. In particular,
|
||||
with regard to performance, most functions here are much slower than their
|
||||
built-in counter parts. However, there are a couple where the overhead of
|
||||
reflection is relatively insignificant: AsyncChan and ParMap.
|
||||
|
||||
In terms of code structure and organization, the price is mostly paid inside
|
||||
of the package due to the annoyances of operating with `reflect`. The caller
|
||||
usually only has one obligation other than to provide values consistent with
|
||||
the type of the function: type assert the result to the desired type.
|
||||
|
||||
When the caller provides values that are inconsistent with the parametric type
|
||||
of the function, the function will panic with a `TypeError`. (Either because
|
||||
the types cannot be unified or because they cannot be constructed due to
|
||||
limitations of the `reflect` package. See the `github.com/BurntSushi/ty`
|
||||
package for more details.)
|
||||
|
||||
Requirements
|
||||
|
||||
Go tip (or 1.1 when it's released) is required. This package will not work
|
||||
with Go 1.0.x or earlier.
|
||||
|
||||
The very foundation of this package only recently became possible with the
|
||||
addition of 3 new functions in the standard library `reflect` package:
|
||||
SliceOf, MapOf and ChanOf. In particular, it provides the ability to
|
||||
dynamically construct types at run time from component types.
|
||||
|
||||
Further extensions to this package can be made if similar functions are added
|
||||
for structs and functions(?).
|
||||
|
||||
Examples
|
||||
|
||||
Squaring each integer in a slice:
|
||||
|
||||
square := func(x int) int { return x * x }
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
squares := Map(square, nums).([]int)
|
||||
|
||||
Reversing any slice:
|
||||
|
||||
slice := []string{"a", "b", "c"}
|
||||
reversed := Reverse(slice).([]string)
|
||||
|
||||
Sorting any slice:
|
||||
|
||||
// Sort a slice of structs with first class functions.
|
||||
type Album struct {
|
||||
Title string
|
||||
Year int
|
||||
}
|
||||
albums := []Album{
|
||||
{"Born to Run", 1975},
|
||||
{"WIESS", 1973},
|
||||
{"Darkness", 1978},
|
||||
{"Greetings", 1973},
|
||||
}
|
||||
|
||||
less := func(a, b Album) bool { return a.Year < b.Year },
|
||||
sorted := QuickSort(less, albums).([]Album)
|
||||
|
||||
Parallel map:
|
||||
|
||||
// Compute the prime factorization concurrently
|
||||
// for every integer in [1000, 10000].
|
||||
primeFactors := func(n int) []int { // compute prime factors }
|
||||
factors := ParMap(primeFactors, Range(1000, 10001)).([]int)
|
||||
|
||||
Asynchronous channel without a fixed size buffer:
|
||||
|
||||
s, r := AsyncChan(new(chan int))
|
||||
send, recv := s.(chan<- int), r.(<-chan int)
|
||||
|
||||
// Send as much as you want.
|
||||
for i := 0; i < 100; i++ {
|
||||
s <- i
|
||||
}
|
||||
close(s)
|
||||
for i := range recv {
|
||||
// do something with `i`
|
||||
}
|
||||
|
||||
Shuffle any slice in place:
|
||||
|
||||
jumbleMe := []string{"The", "quick", "brown", "fox"}
|
||||
Shuffle(jumbleMe)
|
||||
|
||||
Function memoization:
|
||||
|
||||
// Memoizing a recursive function like `fibonacci`.
|
||||
// Write it like normal:
|
||||
var fib func(n int64) int64
|
||||
fib = func(n int64) int64 {
|
||||
switch n {
|
||||
case 0:
|
||||
return 0
|
||||
case 1:
|
||||
return 1
|
||||
}
|
||||
return fib(n - 1) + fib(n - 2)
|
||||
}
|
||||
|
||||
// And wrap it with `Memo`.
|
||||
fib = Memo(fib).(func(int64) int64)
|
||||
|
||||
// Will keep your CPU busy for a long time
|
||||
// without memoization.
|
||||
fmt.Println(fib(80))
|
||||
|
||||
*/
|
||||
package fun
|
35
vendor/github.com/BurntSushi/ty/fun/func.go
generated
vendored
Normal file
35
vendor/github.com/BurntSushi/ty/fun/func.go
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
package fun
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/BurntSushi/ty"
|
||||
)
|
||||
|
||||
// Memo has a parametric type:
|
||||
//
|
||||
// func Memo(f func(A) B) func(A) B
|
||||
//
|
||||
// Memo memoizes any function of a single argument that returns a single value.
|
||||
// The type `A` must be a Go type for which the comparison operators `==` and
|
||||
// `!=` are fully defined (this rules out functions, maps and slices).
|
||||
func Memo(f interface{}) interface{} {
|
||||
chk := ty.Check(
|
||||
new(func(func(ty.A) ty.B)),
|
||||
f)
|
||||
vf := chk.Args[0]
|
||||
|
||||
saved := make(map[interface{}]reflect.Value)
|
||||
memo := func(in []reflect.Value) []reflect.Value {
|
||||
val := in[0].Interface()
|
||||
ret, ok := saved[val]
|
||||
if ok {
|
||||
return []reflect.Value{ret}
|
||||
}
|
||||
|
||||
ret = call1(vf, in[0])
|
||||
saved[val] = ret
|
||||
return []reflect.Value{ret}
|
||||
}
|
||||
return reflect.MakeFunc(vf.Type(), memo).Interface()
|
||||
}
|
303
vendor/github.com/BurntSushi/ty/fun/list.go
generated
vendored
Normal file
303
vendor/github.com/BurntSushi/ty/fun/list.go
generated
vendored
Normal file
|
@ -0,0 +1,303 @@
|
|||
package fun
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sync"
|
||||
|
||||
"github.com/BurntSushi/ty"
|
||||
)
|
||||
|
||||
// All has a parametric type:
|
||||
//
|
||||
// func All(p func(A) bool, xs []A) bool
|
||||
//
|
||||
// All returns `true` if and only if every element in `xs` satisfies `p`.
|
||||
func All(f, xs interface{}) bool {
|
||||
chk := ty.Check(
|
||||
new(func(func(ty.A) bool, []ty.A) bool),
|
||||
f, xs)
|
||||
vf, vxs := chk.Args[0], chk.Args[1]
|
||||
|
||||
xsLen := vxs.Len()
|
||||
for i := 0; i < xsLen; i++ {
|
||||
if !call1(vf, vxs.Index(i)).Interface().(bool) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Exists has a parametric type:
|
||||
//
|
||||
// func Exists(p func(A) bool, xs []A) bool
|
||||
//
|
||||
// Exists returns `true` if and only if an element in `xs` satisfies `p`.
|
||||
func Exists(f, xs interface{}) bool {
|
||||
chk := ty.Check(
|
||||
new(func(func(ty.A) bool, []ty.A) bool),
|
||||
f, xs)
|
||||
vf, vxs := chk.Args[0], chk.Args[1]
|
||||
|
||||
xsLen := vxs.Len()
|
||||
for i := 0; i < xsLen; i++ {
|
||||
if call1(vf, vxs.Index(i)).Interface().(bool) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// In has a parametric type:
|
||||
//
|
||||
// func In(needle A, haystack []A) bool
|
||||
//
|
||||
// In returns `true` if and only if `v` can be found in `xs`. The equality test
|
||||
// used is Go's standard `==` equality and NOT deep equality.
|
||||
//
|
||||
// Note that this requires that `A` be a type that can be meaningfully compared.
|
||||
func In(needle, haystack interface{}) bool {
|
||||
chk := ty.Check(
|
||||
new(func(ty.A, []ty.A) bool),
|
||||
needle, haystack)
|
||||
vhaystack := chk.Args[1]
|
||||
|
||||
length := vhaystack.Len()
|
||||
for i := 0; i < length; i++ {
|
||||
if vhaystack.Index(i).Interface() == needle {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Map has a parametric type:
|
||||
//
|
||||
// func Map(f func(A) B, xs []A) []B
|
||||
//
|
||||
// Map returns the list corresponding to the return value of applying
|
||||
// `f` to each element in `xs`.
|
||||
func Map(f, xs interface{}) interface{} {
|
||||
chk := ty.Check(
|
||||
new(func(func(ty.A) ty.B, []ty.A) []ty.B),
|
||||
f, xs)
|
||||
vf, vxs, tys := chk.Args[0], chk.Args[1], chk.Returns[0]
|
||||
|
||||
xsLen := vxs.Len()
|
||||
vys := reflect.MakeSlice(tys, xsLen, xsLen)
|
||||
for i := 0; i < xsLen; i++ {
|
||||
vy := call1(vf, vxs.Index(i))
|
||||
vys.Index(i).Set(vy)
|
||||
}
|
||||
return vys.Interface()
|
||||
}
|
||||
|
||||
// Filter has a parametric type:
|
||||
//
|
||||
// func Filter(p func(A) bool, xs []A) []A
|
||||
//
|
||||
// Filter returns a new list only containing the elements of `xs` that satisfy
|
||||
// the predicate `p`.
|
||||
func Filter(p, xs interface{}) interface{} {
|
||||
chk := ty.Check(
|
||||
new(func(func(ty.A) bool, []ty.A) []ty.A),
|
||||
p, xs)
|
||||
vp, vxs, tys := chk.Args[0], chk.Args[1], chk.Returns[0]
|
||||
|
||||
xsLen := vxs.Len()
|
||||
vys := reflect.MakeSlice(tys, 0, xsLen)
|
||||
for i := 0; i < xsLen; i++ {
|
||||
vx := vxs.Index(i)
|
||||
if call1(vp, vx).Bool() {
|
||||
vys = reflect.Append(vys, vx)
|
||||
}
|
||||
}
|
||||
return vys.Interface()
|
||||
}
|
||||
|
||||
// Foldl has a parametric type:
|
||||
//
|
||||
// func Foldl(f func(A, B) B, init B, xs []A) B
|
||||
//
|
||||
// Foldl reduces a list of A to a single element B using a left fold with
|
||||
// an initial value `init`.
|
||||
func Foldl(f, init, xs interface{}) interface{} {
|
||||
chk := ty.Check(
|
||||
new(func(func(ty.A, ty.B) ty.B, ty.B, []ty.A) ty.B),
|
||||
f, init, xs)
|
||||
vf, vinit, vxs, tb := chk.Args[0], chk.Args[1], chk.Args[2], chk.Returns[0]
|
||||
|
||||
xsLen := vxs.Len()
|
||||
vb := zeroValue(tb)
|
||||
vb.Set(vinit)
|
||||
if xsLen == 0 {
|
||||
return vb.Interface()
|
||||
}
|
||||
|
||||
vb.Set(call1(vf, vxs.Index(0), vb))
|
||||
for i := 1; i < xsLen; i++ {
|
||||
vb.Set(call1(vf, vxs.Index(i), vb))
|
||||
}
|
||||
return vb.Interface()
|
||||
}
|
||||
|
||||
// Foldr has a parametric type:
|
||||
//
|
||||
// func Foldr(f func(A, B) B, init B, xs []A) B
|
||||
//
|
||||
// Foldr reduces a list of A to a single element B using a right fold with
|
||||
// an initial value `init`.
|
||||
func Foldr(f, init, xs interface{}) interface{} {
|
||||
chk := ty.Check(
|
||||
new(func(func(ty.A, ty.B) ty.B, ty.B, []ty.A) ty.B),
|
||||
f, init, xs)
|
||||
vf, vinit, vxs, tb := chk.Args[0], chk.Args[1], chk.Args[2], chk.Returns[0]
|
||||
|
||||
xsLen := vxs.Len()
|
||||
vb := zeroValue(tb)
|
||||
vb.Set(vinit)
|
||||
if xsLen == 0 {
|
||||
return vb.Interface()
|
||||
}
|
||||
|
||||
vb.Set(call1(vf, vxs.Index(xsLen-1), vb))
|
||||
for i := xsLen - 2; i >= 0; i-- {
|
||||
vb.Set(call1(vf, vxs.Index(i), vb))
|
||||
}
|
||||
return vb.Interface()
|
||||
}
|
||||
|
||||
// Concat has a parametric type:
|
||||
//
|
||||
// func Concat(xs [][]A) []A
|
||||
//
|
||||
// Concat returns a new flattened list by appending all elements of `xs`.
|
||||
func Concat(xs interface{}) interface{} {
|
||||
chk := ty.Check(
|
||||
new(func([][]ty.A) []ty.A),
|
||||
xs)
|
||||
vxs, tflat := chk.Args[0], chk.Returns[0]
|
||||
|
||||
xsLen := vxs.Len()
|
||||
vflat := reflect.MakeSlice(tflat, 0, xsLen*3)
|
||||
for i := 0; i < xsLen; i++ {
|
||||
vflat = reflect.AppendSlice(vflat, vxs.Index(i))
|
||||
}
|
||||
return vflat.Interface()
|
||||
}
|
||||
|
||||
// Reverse has a parametric type:
|
||||
//
|
||||
// func Reverse(xs []A) []A
|
||||
//
|
||||
// Reverse returns a new slice that is the reverse of `xs`.
|
||||
func Reverse(xs interface{}) interface{} {
|
||||
chk := ty.Check(
|
||||
new(func([]ty.A) []ty.A),
|
||||
xs)
|
||||
vxs, tys := chk.Args[0], chk.Returns[0]
|
||||
|
||||
xsLen := vxs.Len()
|
||||
vys := reflect.MakeSlice(tys, xsLen, xsLen)
|
||||
for i := 0; i < xsLen; i++ {
|
||||
vys.Index(i).Set(vxs.Index(xsLen - 1 - i))
|
||||
}
|
||||
return vys.Interface()
|
||||
}
|
||||
|
||||
// Copy has a parametric type:
|
||||
//
|
||||
// func Copy(xs []A) []A
|
||||
//
|
||||
// Copy returns a copy of `xs` using Go's `copy` operation.
|
||||
func Copy(xs interface{}) interface{} {
|
||||
chk := ty.Check(
|
||||
new(func([]ty.A) []ty.A),
|
||||
xs)
|
||||
vxs, tys := chk.Args[0], chk.Returns[0]
|
||||
|
||||
xsLen := vxs.Len()
|
||||
vys := reflect.MakeSlice(tys, xsLen, xsLen)
|
||||
reflect.Copy(vys, vxs)
|
||||
return vys.Interface()
|
||||
}
|
||||
|
||||
// ParMap has a parametric type:
|
||||
//
|
||||
// func ParMap(f func(A) B, xs []A) []B
|
||||
//
|
||||
// ParMap is just like Map, except it applies `f` to each element in `xs`
|
||||
// concurrently using N worker goroutines (where N is the number of CPUs
|
||||
// available reported by the Go runtime). If you want to control the number
|
||||
// of goroutines spawned, use `ParMapN`.
|
||||
//
|
||||
// It is important that `f` not be a trivial operation, otherwise the overhead
|
||||
// of executing it concurrently will result in worse performance than using
|
||||
// a `Map`.
|
||||
func ParMap(f, xs interface{}) interface{} {
|
||||
n := runtime.NumCPU()
|
||||
if n < 1 {
|
||||
n = 1
|
||||
}
|
||||
return ParMapN(f, xs, n)
|
||||
}
|
||||
|
||||
// ParMapN has a parametric type:
|
||||
//
|
||||
// func ParMapN(f func(A) B, xs []A, n int) []B
|
||||
//
|
||||
// ParMapN is just like Map, except it applies `f` to each element in `xs`
|
||||
// concurrently using `n` worker goroutines.
|
||||
//
|
||||
// It is important that `f` not be a trivial operation, otherwise the overhead
|
||||
// of executing it concurrently will result in worse performance than using
|
||||
// a `Map`.
|
||||
func ParMapN(f, xs interface{}, n int) interface{} {
|
||||
chk := ty.Check(
|
||||
new(func(func(ty.A) ty.B, []ty.A) []ty.B),
|
||||
f, xs)
|
||||
vf, vxs, tys := chk.Args[0], chk.Args[1], chk.Returns[0]
|
||||
|
||||
xsLen := vxs.Len()
|
||||
ys := reflect.MakeSlice(tys, xsLen, xsLen)
|
||||
|
||||
if n < 1 {
|
||||
n = 1
|
||||
}
|
||||
work := make(chan int, n)
|
||||
wg := new(sync.WaitGroup)
|
||||
for i := 0; i < n; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
for j := range work {
|
||||
// Good golly miss molly. Is `reflect.Value.Index`
|
||||
// safe to access/set from multiple goroutines?
|
||||
// XXX: If not, we'll need an extra wave of allocation to
|
||||
// use real slices of `reflect.Value`.
|
||||
ys.Index(j).Set(call1(vf, vxs.Index(j)))
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
for i := 0; i < xsLen; i++ {
|
||||
work <- i
|
||||
}
|
||||
close(work)
|
||||
wg.Wait()
|
||||
return ys.Interface()
|
||||
}
|
||||
|
||||
// Range generates a list of integers corresponding to every integer in
|
||||
// the half-open interval [x, y).
|
||||
//
|
||||
// Range will panic if `end < start`.
|
||||
func Range(start, end int) []int {
|
||||
if end < start {
|
||||
panic("range must have end greater than or equal to start")
|
||||
}
|
||||
r := make([]int, end-start)
|
||||
for i := start; i < end; i++ {
|
||||
r[i-start] = i
|
||||
}
|
||||
return r
|
||||
}
|
46
vendor/github.com/BurntSushi/ty/fun/map.go
generated
vendored
Normal file
46
vendor/github.com/BurntSushi/ty/fun/map.go
generated
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
package fun
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/BurntSushi/ty"
|
||||
)
|
||||
|
||||
// Keys has a parametric type:
|
||||
//
|
||||
// func Keys(m map[A]B) []A
|
||||
//
|
||||
// Keys returns a list of the keys of `m` in an unspecified order.
|
||||
func Keys(m interface{}) interface{} {
|
||||
chk := ty.Check(
|
||||
new(func(map[ty.A]ty.B) []ty.A),
|
||||
m)
|
||||
vm, tkeys := chk.Args[0], chk.Returns[0]
|
||||
|
||||
vkeys := reflect.MakeSlice(tkeys, vm.Len(), vm.Len())
|
||||
for i, vkey := range vm.MapKeys() {
|
||||
vkeys.Index(i).Set(vkey)
|
||||
}
|
||||
return vkeys.Interface()
|
||||
}
|
||||
|
||||
// Values has a parametric type:
|
||||
//
|
||||
// func Values(m map[A]B) []B
|
||||
//
|
||||
// Values returns a list of the values of `m` in an unspecified order.
|
||||
func Values(m interface{}) interface{} {
|
||||
chk := ty.Check(
|
||||
new(func(map[ty.A]ty.B) []ty.B),
|
||||
m)
|
||||
vm, tvals := chk.Args[0], chk.Returns[0]
|
||||
|
||||
vvals := reflect.MakeSlice(tvals, vm.Len(), vm.Len())
|
||||
for i, vkey := range vm.MapKeys() {
|
||||
vvals.Index(i).Set(vm.MapIndex(vkey))
|
||||
}
|
||||
return vvals.Interface()
|
||||
}
|
||||
|
||||
// func MapMerge(m1, m2 interface{}) interface{} {
|
||||
// }
|
94
vendor/github.com/BurntSushi/ty/fun/rand.go
generated
vendored
Normal file
94
vendor/github.com/BurntSushi/ty/fun/rand.go
generated
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
package fun
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/BurntSushi/ty"
|
||||
)
|
||||
|
||||
var randNumGen *rand.Rand
|
||||
|
||||
func init() {
|
||||
randNumGen = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
}
|
||||
|
||||
// ShuffleGen has a parametric type:
|
||||
//
|
||||
// func ShuffleGen(xs []A, rng *rand.Rand)
|
||||
//
|
||||
// ShuffleGen shuffles `xs` in place using the given random number
|
||||
// generator `rng`.
|
||||
func ShuffleGen(xs interface{}, rng *rand.Rand) {
|
||||
chk := ty.Check(
|
||||
new(func([]ty.A, *rand.Rand)),
|
||||
xs, rng)
|
||||
vxs := chk.Args[0]
|
||||
|
||||
// Implements the Fisher-Yates shuffle: http://goo.gl/Hb9vg
|
||||
xsLen := vxs.Len()
|
||||
swapper := swapperOf(vxs.Type().Elem())
|
||||
for i := xsLen - 1; i >= 1; i-- {
|
||||
j := rng.Intn(i + 1)
|
||||
swapper.swap(vxs.Index(i), vxs.Index(j))
|
||||
}
|
||||
}
|
||||
|
||||
// Shuffle has a parametric type:
|
||||
//
|
||||
// func Shuffle(xs []A)
|
||||
//
|
||||
// Shuffle shuffles `xs` in place using a default random number
|
||||
// generator seeded once at program initialization.
|
||||
func Shuffle(xs interface{}) {
|
||||
ShuffleGen(xs, randNumGen)
|
||||
}
|
||||
|
||||
// Sample has a parametric type:
|
||||
//
|
||||
// func Sample(population []A, n int) []A
|
||||
//
|
||||
// Sample returns a random sample of size `n` from a list
|
||||
// `population` using a default random number generator seeded once at
|
||||
// program initialization.
|
||||
// All elements in `population` have an equal chance of being selected.
|
||||
// If `n` is greater than the size of `population`, then `n` is set to
|
||||
// the size of the population.
|
||||
func Sample(population interface{}, n int) interface{} {
|
||||
return SampleGen(population, n, randNumGen)
|
||||
}
|
||||
|
||||
// SampleGen has a parametric type:
|
||||
//
|
||||
// func SampleGen(population []A, n int, rng *rand.Rand) []A
|
||||
//
|
||||
// SampleGen returns a random sample of size `n` from a list
|
||||
// `population` using a given random number generator `rng`.
|
||||
// All elements in `population` have an equal chance of being selected.
|
||||
// If `n` is greater than the size of `population`, then `n` is set to
|
||||
// the size of the population.
|
||||
func SampleGen(population interface{}, n int, rng *rand.Rand) interface{} {
|
||||
chk := ty.Check(
|
||||
new(func([]ty.A, int, *rand.Rand) []ty.A),
|
||||
population, n, rng)
|
||||
rpop, tsamp := chk.Args[0], chk.Returns[0]
|
||||
|
||||
popLen := rpop.Len()
|
||||
if n == 0 {
|
||||
return reflect.MakeSlice(tsamp, 0, 0).Interface()
|
||||
}
|
||||
if n > popLen {
|
||||
n = popLen
|
||||
}
|
||||
|
||||
// TODO(burntsushi): Implement an algorithm that doesn't depend on
|
||||
// the size of the population.
|
||||
|
||||
rsamp := reflect.MakeSlice(tsamp, n, n)
|
||||
choices := rng.Perm(popLen)
|
||||
for i := 0; i < n; i++ {
|
||||
rsamp.Index(i).Set(rpop.Index(choices[i]))
|
||||
}
|
||||
return rsamp.Interface()
|
||||
}
|
99
vendor/github.com/BurntSushi/ty/fun/set.go
generated
vendored
Normal file
99
vendor/github.com/BurntSushi/ty/fun/set.go
generated
vendored
Normal file
|
@ -0,0 +1,99 @@
|
|||
package fun
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/BurntSushi/ty"
|
||||
)
|
||||
|
||||
// Set has a parametric type:
|
||||
//
|
||||
// func Set(xs []A) map[A]bool
|
||||
//
|
||||
// Set creates a set from a list.
|
||||
func Set(xs interface{}) interface{} {
|
||||
chk := ty.Check(
|
||||
new(func([]ty.A) map[ty.A]bool),
|
||||
xs)
|
||||
vxs, tset := chk.Args[0], chk.Returns[0]
|
||||
|
||||
vtrue := reflect.ValueOf(true)
|
||||
vset := reflect.MakeMap(tset)
|
||||
xsLen := vxs.Len()
|
||||
for i := 0; i < xsLen; i++ {
|
||||
vset.SetMapIndex(vxs.Index(i), vtrue)
|
||||
}
|
||||
return vset.Interface()
|
||||
}
|
||||
|
||||
// Union has a parametric type:
|
||||
//
|
||||
// func Union(a map[A]bool, b map[A]bool) map[A]bool
|
||||
//
|
||||
// Union returns the union of two sets, where a set is represented as a
|
||||
// `map[A]bool`. The sets `a` and `b` are not modified.
|
||||
func Union(a, b interface{}) interface{} {
|
||||
chk := ty.Check(
|
||||
new(func(map[ty.A]bool, map[ty.A]bool) map[ty.A]bool),
|
||||
a, b)
|
||||
va, vb, tc := chk.Args[0], chk.Args[1], chk.Returns[0]
|
||||
|
||||
vtrue := reflect.ValueOf(true)
|
||||
vc := reflect.MakeMap(tc)
|
||||
for _, vkey := range va.MapKeys() {
|
||||
vc.SetMapIndex(vkey, vtrue)
|
||||
}
|
||||
for _, vkey := range vb.MapKeys() {
|
||||
vc.SetMapIndex(vkey, vtrue)
|
||||
}
|
||||
return vc.Interface()
|
||||
}
|
||||
|
||||
// Intersection has a parametric type:
|
||||
//
|
||||
// func Intersection(a map[A]bool, b map[A]bool) map[A]bool
|
||||
//
|
||||
// Intersection returns the intersection of two sets, where a set is
|
||||
// represented as a `map[A]bool`. The sets `a` and `b` are not modified.
|
||||
func Intersection(a, b interface{}) interface{} {
|
||||
chk := ty.Check(
|
||||
new(func(map[ty.A]bool, map[ty.A]bool) map[ty.A]bool),
|
||||
a, b)
|
||||
va, vb, tc := chk.Args[0], chk.Args[1], chk.Returns[0]
|
||||
|
||||
vtrue := reflect.ValueOf(true)
|
||||
vc := reflect.MakeMap(tc)
|
||||
for _, vkey := range va.MapKeys() {
|
||||
if vb.MapIndex(vkey).IsValid() {
|
||||
vc.SetMapIndex(vkey, vtrue)
|
||||
}
|
||||
}
|
||||
for _, vkey := range vb.MapKeys() {
|
||||
if va.MapIndex(vkey).IsValid() {
|
||||
vc.SetMapIndex(vkey, vtrue)
|
||||
}
|
||||
}
|
||||
return vc.Interface()
|
||||
}
|
||||
|
||||
// Difference has a parametric type:
|
||||
//
|
||||
// func Difference(a map[A]bool, b map[A]bool) map[A]bool
|
||||
//
|
||||
// Difference returns a set with all elements in `a` that are not in `b`.
|
||||
// The sets `a` and `b` are not modified.
|
||||
func Difference(a, b interface{}) interface{} {
|
||||
chk := ty.Check(
|
||||
new(func(map[ty.A]bool, map[ty.A]bool) map[ty.A]bool),
|
||||
a, b)
|
||||
va, vb, tc := chk.Args[0], chk.Args[1], chk.Returns[0]
|
||||
|
||||
vtrue := reflect.ValueOf(true)
|
||||
vc := reflect.MakeMap(tc)
|
||||
for _, vkey := range va.MapKeys() {
|
||||
if !vb.MapIndex(vkey).IsValid() {
|
||||
vc.SetMapIndex(vkey, vtrue)
|
||||
}
|
||||
}
|
||||
return vc.Interface()
|
||||
}
|
98
vendor/github.com/BurntSushi/ty/fun/sort.go
generated
vendored
Normal file
98
vendor/github.com/BurntSushi/ty/fun/sort.go
generated
vendored
Normal file
|
@ -0,0 +1,98 @@
|
|||
package fun
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
|
||||
"github.com/BurntSushi/ty"
|
||||
)
|
||||
|
||||
// QuickSort has a parametric type:
|
||||
//
|
||||
// func QuickSort(less func(x1 A, x2 A) bool, []A) []A
|
||||
//
|
||||
// QuickSort applies the "quicksort" algorithm to return a new sorted list
|
||||
// of `xs`, where `xs` is not modified.
|
||||
//
|
||||
// `less` should be a function that returns true if and only if `x1` is less
|
||||
// than `x2`.
|
||||
func QuickSort(less, xs interface{}) interface{} {
|
||||
chk := ty.Check(
|
||||
new(func(func(ty.A, ty.A) bool, []ty.A) []ty.A),
|
||||
less, xs)
|
||||
vless, vxs, tys := chk.Args[0], chk.Args[1], chk.Returns[0]
|
||||
|
||||
var qsort func(left, right int)
|
||||
var partition func(left, right, pivot int) int
|
||||
xsind := Range(0, vxs.Len())
|
||||
|
||||
qsort = func(left, right int) {
|
||||
if left >= right {
|
||||
return
|
||||
}
|
||||
pivot := (left + right) / 2
|
||||
pivot = partition(left, right, pivot)
|
||||
|
||||
qsort(left, pivot-1)
|
||||
qsort(pivot+1, right)
|
||||
}
|
||||
partition = func(left, right, pivot int) int {
|
||||
vpivot := xsind[pivot]
|
||||
xsind[pivot], xsind[right] = xsind[right], xsind[pivot]
|
||||
|
||||
ind := left
|
||||
for i := left; i < right; i++ {
|
||||
if call1(vless, vxs.Index(xsind[i]), vxs.Index(vpivot)).Bool() {
|
||||
xsind[i], xsind[ind] = xsind[ind], xsind[i]
|
||||
ind++
|
||||
}
|
||||
}
|
||||
xsind[ind], xsind[right] = xsind[right], xsind[ind]
|
||||
return ind
|
||||
}
|
||||
|
||||
// Sort `xsind` in place.
|
||||
qsort(0, len(xsind)-1)
|
||||
|
||||
vys := reflect.MakeSlice(tys, len(xsind), len(xsind))
|
||||
for i, xsIndex := range xsind {
|
||||
vys.Index(i).Set(vxs.Index(xsIndex))
|
||||
}
|
||||
return vys.Interface()
|
||||
}
|
||||
|
||||
// Sort has a parametric type:
|
||||
//
|
||||
// func Sort(less func(x1 A, x2 A) bool, []A)
|
||||
//
|
||||
// Sort uses the standard library `sort` package to sort `xs` in place.
|
||||
//
|
||||
// `less` should be a function that returns true if and only if `x1` is less
|
||||
// than `x2`.
|
||||
func Sort(less, xs interface{}) {
|
||||
chk := ty.Check(
|
||||
new(func(func(ty.A, ty.A) bool, []ty.A)),
|
||||
less, xs)
|
||||
|
||||
vless, vxs := chk.Args[0], chk.Args[1]
|
||||
sort.Sort(&sortable{vless, vxs, swapperOf(vxs.Type().Elem())})
|
||||
}
|
||||
|
||||
type sortable struct {
|
||||
less reflect.Value
|
||||
xs reflect.Value
|
||||
swapper swapper
|
||||
}
|
||||
|
||||
func (s *sortable) Less(i, j int) bool {
|
||||
ith, jth := s.xs.Index(i), s.xs.Index(j)
|
||||
return call1(s.less, ith, jth).Bool()
|
||||
}
|
||||
|
||||
func (s *sortable) Swap(i, j int) {
|
||||
s.swapper.swap(s.xs.Index(i), s.xs.Index(j))
|
||||
}
|
||||
|
||||
func (s *sortable) Len() int {
|
||||
return s.xs.Len()
|
||||
}
|
37
vendor/github.com/BurntSushi/ty/fun/util.go
generated
vendored
Normal file
37
vendor/github.com/BurntSushi/ty/fun/util.go
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
package fun
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func zeroValue(typ reflect.Type) reflect.Value {
|
||||
return reflect.New(typ).Elem()
|
||||
}
|
||||
|
||||
type swapper reflect.Value
|
||||
|
||||
func swapperOf(typ reflect.Type) swapper {
|
||||
return swapper(zeroValue(typ))
|
||||
}
|
||||
|
||||
func (s swapper) swap(a, b reflect.Value) {
|
||||
vs := reflect.Value(s)
|
||||
vs.Set(a)
|
||||
a.Set(b)
|
||||
b.Set(vs)
|
||||
}
|
||||
|
||||
func call(f reflect.Value, args ...reflect.Value) {
|
||||
f.Call(args)
|
||||
}
|
||||
|
||||
func call1(f reflect.Value, args ...reflect.Value) reflect.Value {
|
||||
return f.Call(args)[0]
|
||||
}
|
||||
|
||||
func call2(f reflect.Value, args ...reflect.Value) (
|
||||
reflect.Value, reflect.Value) {
|
||||
|
||||
ret := f.Call(args)
|
||||
return ret[0], ret[1]
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue