-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sliceop{,/f64s}: introduce generics sliceop
Move and generalize code from sliceop/f64s into sliceop. name old time/op new time/op delta Take/Len=2-8 2.69ns ± 1% 2.71ns ± 2% +0.75% (p=0.043 n=18+18) Take/Len=4-8 3.18ns ± 1% 3.23ns ± 3% +1.27% (p=0.005 n=19+20) Take/Len=8-8 3.83ns ± 1% 3.73ns ± 1% -2.69% (p=0.000 n=20+19) Take/Len=128-8 44.1ns ± 4% 35.9ns ± 2% -18.61% (p=0.000 n=20+20) Take/Len=1024-8 337ns ± 2% 280ns ± 6% -16.73% (p=0.000 n=19+20) Take/Len=1048576-8 1.37ms ± 3% 1.31ms ± 5% -3.97% (p=0.000 n=19+20) name old alloc/op new alloc/op delta Take/Len=2-8 0.00B 0.00B ~ (all equal) Take/Len=4-8 0.00B 0.00B ~ (all equal) Take/Len=8-8 0.00B 0.00B ~ (all equal) Take/Len=128-8 0.00B 0.00B ~ (all equal) Take/Len=1024-8 0.00B 0.00B ~ (all equal) Take/Len=1048576-8 0.00B 0.00B ~ (all equal) name old allocs/op new allocs/op delta Take/Len=2-8 0.00 0.00 ~ (all equal) Take/Len=4-8 0.00 0.00 ~ (all equal) Take/Len=8-8 0.00 0.00 ~ (all equal) Take/Len=128-8 0.00 0.00 ~ (all equal) Take/Len=1024-8 0.00 0.00 ~ (all equal) Take/Len=1048576-8 0.00 0.00 ~ (all equal) Updates #868.
- Loading branch information
Showing
5 changed files
with
322 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
// Copyright ©2021 The go-hep Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
//go:build go1.18 | ||
|
||
// Package sliceop provides operations on slices not available in the stdlib | ||
// slices package. | ||
package sliceop // import "go-hep.org/x/hep/sliceop" | ||
|
||
import ( | ||
"fmt" | ||
) | ||
|
||
var ( | ||
errLength = fmt.Errorf("sliceop: length mismatch") | ||
errSortedIndices = fmt.Errorf("sliceop: indices not sorted") | ||
errDuplicateIndices = fmt.Errorf("sliceop: duplicate indices") | ||
) | ||
|
||
// Filter creates a slice with all the elements x_i of src for which f(x_i) is true. | ||
// Filter uses dst as work buffer, storing elements at the start of the slice. | ||
// Filter clears dst if a slice is passed, and allocates a new slice if dst is nil. | ||
func Filter[T any](dst, src []T, f func(v T) bool) []T { | ||
|
||
if dst == nil { | ||
dst = make([]T, 0, len(src)) | ||
} | ||
|
||
dst = dst[:0] | ||
for _, x := range src { | ||
if f(x) { | ||
dst = append(dst, x) | ||
} | ||
} | ||
|
||
return dst | ||
} | ||
|
||
// Map creates a slice with all the elements f(x_i) where x_i are elements from src. | ||
// Map uses dst as work buffer, storing elements at the start of the slice. | ||
// Map allocates a new slice if dst is nil. | ||
// Map will panic if the lengths of src and dst differ. | ||
func Map[T, U any](dst []U, src []T, f func(v T) U) []U { | ||
|
||
if dst == nil { | ||
dst = make([]U, len(src)) | ||
} | ||
|
||
if len(src) != len(dst) { | ||
panic(errLength) | ||
} | ||
|
||
for i, x := range src { | ||
dst[i] = f(x) | ||
} | ||
return dst | ||
} | ||
|
||
// Find creates a slice with all indices corresponding to elements for which f(x) is true. | ||
// Find uses dst as work buffer, storing indices at the start of the slice. | ||
// Find clears dst if a slice is passed, and allocates a new slice if dst is nil. | ||
func Find[T any](dst []int, src []T, f func(v T) bool) []int { | ||
|
||
if dst == nil { | ||
dst = make([]int, 0, len(src)) | ||
} | ||
|
||
dst = dst[:0] | ||
for i, x := range src { | ||
if f(x) { | ||
dst = append(dst, i) | ||
} | ||
} | ||
|
||
return dst | ||
} | ||
|
||
// Take creates a sub-slice of src with all elements indiced by the provided indices. | ||
// Take uses dst as work buffer, storing elements at the start of the slice. | ||
// Take clears dst if a slice is passed, and allocates a new slice if dst is nil. | ||
// Take will panic if indices is not sorted or has duplicates. | ||
// Take will panic if length of indices is larger than length of src. | ||
// Take will panic if length of indices is different from length of dst. | ||
func Take[T any](dst, src []T, indices []int) []T { | ||
|
||
if len(indices) > len(src) { | ||
panic(errLength) | ||
} | ||
|
||
if dst == nil { | ||
dst = make([]T, len(indices)) | ||
} | ||
|
||
if len(dst) != len(indices) { | ||
panic(errLength) | ||
} | ||
|
||
if len(indices) == 0 { | ||
return dst | ||
} | ||
|
||
dst[0] = src[indices[0]] | ||
for i := 1; i < len(indices); i++ { | ||
v0 := indices[i-1] | ||
v1 := indices[i] | ||
switch { | ||
case v0 < v1: | ||
// ok. | ||
case v0 == v1: | ||
panic(errDuplicateIndices) | ||
case v0 > v1: | ||
panic(errSortedIndices) | ||
} | ||
dst[i] = src[v1] | ||
} | ||
|
||
return dst | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// Copyright ©2022 The go-hep Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package sliceop_test | ||
|
||
import ( | ||
"fmt" | ||
|
||
f64s "go-hep.org/x/hep/sliceop" | ||
) | ||
|
||
// An example of slice filtering | ||
func ExampleFilter() { | ||
slice := []float64{1, 2, -99, 4, 5, -99, 7} | ||
condition := func(x float64) bool { return x > 0 } | ||
fmt.Println(f64s.Filter(nil, slice, condition)) | ||
|
||
// Output: | ||
// [1 2 4 5 7] | ||
} | ||
|
||
// An example of slice mapping | ||
func ExampleMap() { | ||
slice := []float64{1, 2, -99, 4, 5, -99, 7} | ||
operation := func(x float64) float64 { return x * x } | ||
fmt.Println(f64s.Map(nil, slice, operation)) | ||
|
||
// Output: | ||
// [1 4 9801 16 25 9801 49] | ||
} | ||
|
||
// An example of slice finding | ||
func ExampleFind() { | ||
slice := []float64{1, 2, -99, 4, 5, -99, 7} | ||
condition := func(x float64) bool { return x == -99 } | ||
fmt.Println(f64s.Find(nil, slice, condition)) | ||
|
||
// Output: | ||
// [2 5] | ||
} | ||
|
||
// An example of taking a sub-slice defined by indices | ||
func ExampleTake() { | ||
slice := []float64{1, 2, -99, 4, 5, -99, 7} | ||
indices := []int{2, 5} | ||
fmt.Println(f64s.Take(nil, slice, indices)) | ||
|
||
// Output: | ||
// [-99 -99] | ||
} |
Oops, something went wrong.