build(deps): bump the golang group with 3 updates
Bumps the golang group with 3 updates: [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo), [github.com/onsi/gomega](https://github.com/onsi/gomega) and [golang.org/x/sys](https://github.com/golang/sys). Updates `github.com/onsi/ginkgo/v2` from 2.20.1 to 2.20.2 - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.20.1...v2.20.2) Updates `github.com/onsi/gomega` from 1.34.1 to 1.34.2 - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.34.1...v1.34.2) Updates `golang.org/x/sys` from 0.23.0 to 0.24.0 - [Commits](https://github.com/golang/sys/compare/v0.23.0...v0.24.0) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: golang - dependency-name: github.com/onsi/gomega dependency-type: direct:production update-type: version-update:semver-patch dependency-group: golang - dependency-name: golang.org/x/sys dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
parent
e5df283ab3
commit
fa737f82b2
9
go.mod
9
go.mod
@ -15,12 +15,12 @@ require (
|
|||||||
github.com/godbus/dbus/v5 v5.1.0
|
github.com/godbus/dbus/v5 v5.1.0
|
||||||
github.com/mattn/go-shellwords v1.0.12
|
github.com/mattn/go-shellwords v1.0.12
|
||||||
github.com/networkplumbing/go-nft v0.4.0
|
github.com/networkplumbing/go-nft v0.4.0
|
||||||
github.com/onsi/ginkgo/v2 v2.20.1
|
github.com/onsi/ginkgo/v2 v2.20.2
|
||||||
github.com/onsi/gomega v1.34.1
|
github.com/onsi/gomega v1.34.2
|
||||||
github.com/opencontainers/selinux v1.11.0
|
github.com/opencontainers/selinux v1.11.0
|
||||||
github.com/safchain/ethtool v0.4.1
|
github.com/safchain/ethtool v0.4.1
|
||||||
github.com/vishvananda/netlink v1.3.0
|
github.com/vishvananda/netlink v1.3.0
|
||||||
golang.org/x/sys v0.23.0
|
golang.org/x/sys v0.24.0
|
||||||
sigs.k8s.io/knftables v0.0.17
|
sigs.k8s.io/knftables v0.0.17
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,12 +33,11 @@ require (
|
|||||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/google/go-cmp v0.6.0 // indirect
|
github.com/google/go-cmp v0.6.0 // indirect
|
||||||
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect
|
github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
github.com/vishvananda/netns v0.0.4 // indirect
|
github.com/vishvananda/netns v0.0.4 // indirect
|
||||||
go.opencensus.io v0.24.0 // indirect
|
go.opencensus.io v0.24.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
|
|
||||||
golang.org/x/net v0.28.0 // indirect
|
golang.org/x/net v0.28.0 // indirect
|
||||||
golang.org/x/text v0.17.0 // indirect
|
golang.org/x/text v0.17.0 // indirect
|
||||||
golang.org/x/tools v0.24.0 // indirect
|
golang.org/x/tools v0.24.0 // indirect
|
||||||
|
18
go.sum
18
go.sum
@ -65,8 +65,8 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k=
|
github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA=
|
||||||
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY=
|
github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY=
|
||||||
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
|
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
|
||||||
@ -74,10 +74,10 @@ github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebG
|
|||||||
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||||
github.com/networkplumbing/go-nft v0.4.0 h1:kExVMwXW48DOAukkBwyI16h4uhE5lN9iMvQd52lpTyU=
|
github.com/networkplumbing/go-nft v0.4.0 h1:kExVMwXW48DOAukkBwyI16h4uhE5lN9iMvQd52lpTyU=
|
||||||
github.com/networkplumbing/go-nft v0.4.0/go.mod h1:HnnM+tYvlGAsMU7yoYwXEVLLiDW9gdMmb5HoGcwpuQs=
|
github.com/networkplumbing/go-nft v0.4.0/go.mod h1:HnnM+tYvlGAsMU7yoYwXEVLLiDW9gdMmb5HoGcwpuQs=
|
||||||
github.com/onsi/ginkgo/v2 v2.20.1 h1:YlVIbqct+ZmnEph770q9Q7NVAz4wwIiVNahee6JyUzo=
|
github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4=
|
||||||
github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI=
|
github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag=
|
||||||
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
|
||||||
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
|
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc=
|
||||||
github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
|
github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
|
||||||
github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
|
github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
@ -110,8 +110,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
@ -143,8 +141,8 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
|
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
||||||
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
7
vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md
generated
vendored
7
vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md
generated
vendored
@ -1,3 +1,10 @@
|
|||||||
|
## 2.20.2
|
||||||
|
|
||||||
|
Require Go 1.22+
|
||||||
|
|
||||||
|
### Maintenance
|
||||||
|
- bump go to v1.22 [a671816]
|
||||||
|
|
||||||
## 2.20.1
|
## 2.20.1
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
2
vendor/github.com/onsi/ginkgo/v2/types/version.go
generated
vendored
2
vendor/github.com/onsi/ginkgo/v2/types/version.go
generated
vendored
@ -1,3 +1,3 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
const VERSION = "2.20.1"
|
const VERSION = "2.20.2"
|
||||||
|
8
vendor/github.com/onsi/gomega/CHANGELOG.md
generated
vendored
8
vendor/github.com/onsi/gomega/CHANGELOG.md
generated
vendored
@ -1,3 +1,11 @@
|
|||||||
|
## 1.34.2
|
||||||
|
|
||||||
|
Require Go 1.22+
|
||||||
|
|
||||||
|
### Maintenance
|
||||||
|
- bump ginkgo as well [c59c6dc]
|
||||||
|
- bump to go 1.22 - remove x/exp dependency [8158b99]
|
||||||
|
|
||||||
## 1.34.1
|
## 1.34.1
|
||||||
|
|
||||||
### Maintenance
|
### Maintenance
|
||||||
|
2
vendor/github.com/onsi/gomega/gomega_dsl.go
generated
vendored
2
vendor/github.com/onsi/gomega/gomega_dsl.go
generated
vendored
@ -22,7 +22,7 @@ import (
|
|||||||
"github.com/onsi/gomega/types"
|
"github.com/onsi/gomega/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
const GOMEGA_VERSION = "1.34.1"
|
const GOMEGA_VERSION = "1.34.2"
|
||||||
|
|
||||||
const nilGomegaPanic = `You are trying to make an assertion, but haven't registered Gomega's fail handler.
|
const nilGomegaPanic = `You are trying to make an assertion, but haven't registered Gomega's fail handler.
|
||||||
If you're using Ginkgo then you probably forgot to put your assertion in an It().
|
If you're using Ginkgo then you probably forgot to put your assertion in an It().
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package bipartitegraph
|
package bipartitegraph
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"golang.org/x/exp/slices"
|
"slices"
|
||||||
|
|
||||||
. "github.com/onsi/gomega/matchers/support/goraph/edge"
|
. "github.com/onsi/gomega/matchers/support/goraph/edge"
|
||||||
. "github.com/onsi/gomega/matchers/support/goraph/node"
|
. "github.com/onsi/gomega/matchers/support/goraph/node"
|
||||||
|
27
vendor/golang.org/x/exp/LICENSE
generated
vendored
27
vendor/golang.org/x/exp/LICENSE
generated
vendored
@ -1,27 +0,0 @@
|
|||||||
Copyright 2009 The Go Authors.
|
|
||||||
|
|
||||||
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.
|
|
||||||
* Neither the name of Google LLC nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
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
|
|
||||||
OWNER 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.
|
|
22
vendor/golang.org/x/exp/PATENTS
generated
vendored
22
vendor/golang.org/x/exp/PATENTS
generated
vendored
@ -1,22 +0,0 @@
|
|||||||
Additional IP Rights Grant (Patents)
|
|
||||||
|
|
||||||
"This implementation" means the copyrightable works distributed by
|
|
||||||
Google as part of the Go project.
|
|
||||||
|
|
||||||
Google 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,
|
|
||||||
transfer and otherwise run, modify and propagate the contents of this
|
|
||||||
implementation of Go, where such license applies only to those patent
|
|
||||||
claims, both currently owned or controlled by Google and acquired in
|
|
||||||
the future, licensable by Google that are necessarily infringed by this
|
|
||||||
implementation of Go. This grant does not include claims that would be
|
|
||||||
infringed only as a consequence of further modification of this
|
|
||||||
implementation. If you or your agent or exclusive licensee institute or
|
|
||||||
order or agree to the institution of patent litigation against any
|
|
||||||
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
|
||||||
that this implementation of Go or any code incorporated within this
|
|
||||||
implementation of Go constitutes direct or contributory patent
|
|
||||||
infringement, or inducement of patent infringement, then any patent
|
|
||||||
rights granted to you under this License for this implementation of Go
|
|
||||||
shall terminate as of the date such litigation is filed.
|
|
50
vendor/golang.org/x/exp/constraints/constraints.go
generated
vendored
50
vendor/golang.org/x/exp/constraints/constraints.go
generated
vendored
@ -1,50 +0,0 @@
|
|||||||
// Copyright 2021 The Go 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 constraints defines a set of useful constraints to be used
|
|
||||||
// with type parameters.
|
|
||||||
package constraints
|
|
||||||
|
|
||||||
// Signed is a constraint that permits any signed integer type.
|
|
||||||
// If future releases of Go add new predeclared signed integer types,
|
|
||||||
// this constraint will be modified to include them.
|
|
||||||
type Signed interface {
|
|
||||||
~int | ~int8 | ~int16 | ~int32 | ~int64
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unsigned is a constraint that permits any unsigned integer type.
|
|
||||||
// If future releases of Go add new predeclared unsigned integer types,
|
|
||||||
// this constraint will be modified to include them.
|
|
||||||
type Unsigned interface {
|
|
||||||
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
|
|
||||||
}
|
|
||||||
|
|
||||||
// Integer is a constraint that permits any integer type.
|
|
||||||
// If future releases of Go add new predeclared integer types,
|
|
||||||
// this constraint will be modified to include them.
|
|
||||||
type Integer interface {
|
|
||||||
Signed | Unsigned
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float is a constraint that permits any floating-point type.
|
|
||||||
// If future releases of Go add new predeclared floating-point types,
|
|
||||||
// this constraint will be modified to include them.
|
|
||||||
type Float interface {
|
|
||||||
~float32 | ~float64
|
|
||||||
}
|
|
||||||
|
|
||||||
// Complex is a constraint that permits any complex numeric type.
|
|
||||||
// If future releases of Go add new predeclared complex numeric types,
|
|
||||||
// this constraint will be modified to include them.
|
|
||||||
type Complex interface {
|
|
||||||
~complex64 | ~complex128
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ordered is a constraint that permits any ordered type: any type
|
|
||||||
// that supports the operators < <= >= >.
|
|
||||||
// If future releases of Go add new ordered types,
|
|
||||||
// this constraint will be modified to include them.
|
|
||||||
type Ordered interface {
|
|
||||||
Integer | Float | ~string
|
|
||||||
}
|
|
44
vendor/golang.org/x/exp/slices/cmp.go
generated
vendored
44
vendor/golang.org/x/exp/slices/cmp.go
generated
vendored
@ -1,44 +0,0 @@
|
|||||||
// Copyright 2023 The Go 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 slices
|
|
||||||
|
|
||||||
import "golang.org/x/exp/constraints"
|
|
||||||
|
|
||||||
// min is a version of the predeclared function from the Go 1.21 release.
|
|
||||||
func min[T constraints.Ordered](a, b T) T {
|
|
||||||
if a < b || isNaN(a) {
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// max is a version of the predeclared function from the Go 1.21 release.
|
|
||||||
func max[T constraints.Ordered](a, b T) T {
|
|
||||||
if a > b || isNaN(a) {
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// cmpLess is a copy of cmp.Less from the Go 1.21 release.
|
|
||||||
func cmpLess[T constraints.Ordered](x, y T) bool {
|
|
||||||
return (isNaN(x) && !isNaN(y)) || x < y
|
|
||||||
}
|
|
||||||
|
|
||||||
// cmpCompare is a copy of cmp.Compare from the Go 1.21 release.
|
|
||||||
func cmpCompare[T constraints.Ordered](x, y T) int {
|
|
||||||
xNaN := isNaN(x)
|
|
||||||
yNaN := isNaN(y)
|
|
||||||
if xNaN && yNaN {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if xNaN || x < y {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
if yNaN || x > y {
|
|
||||||
return +1
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
515
vendor/golang.org/x/exp/slices/slices.go
generated
vendored
515
vendor/golang.org/x/exp/slices/slices.go
generated
vendored
@ -1,515 +0,0 @@
|
|||||||
// Copyright 2021 The Go 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 slices defines various functions useful with slices of any type.
|
|
||||||
package slices
|
|
||||||
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"golang.org/x/exp/constraints"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Equal reports whether two slices are equal: the same length and all
|
|
||||||
// elements equal. If the lengths are different, Equal returns false.
|
|
||||||
// Otherwise, the elements are compared in increasing index order, and the
|
|
||||||
// comparison stops at the first unequal pair.
|
|
||||||
// Floating point NaNs are not considered equal.
|
|
||||||
func Equal[S ~[]E, E comparable](s1, s2 S) bool {
|
|
||||||
if len(s1) != len(s2) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i := range s1 {
|
|
||||||
if s1[i] != s2[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// EqualFunc reports whether two slices are equal using an equality
|
|
||||||
// function on each pair of elements. If the lengths are different,
|
|
||||||
// EqualFunc returns false. Otherwise, the elements are compared in
|
|
||||||
// increasing index order, and the comparison stops at the first index
|
|
||||||
// for which eq returns false.
|
|
||||||
func EqualFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) bool) bool {
|
|
||||||
if len(s1) != len(s2) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i, v1 := range s1 {
|
|
||||||
v2 := s2[i]
|
|
||||||
if !eq(v1, v2) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare compares the elements of s1 and s2, using [cmp.Compare] on each pair
|
|
||||||
// of elements. The elements are compared sequentially, starting at index 0,
|
|
||||||
// until one element is not equal to the other.
|
|
||||||
// The result of comparing the first non-matching elements is returned.
|
|
||||||
// If both slices are equal until one of them ends, the shorter slice is
|
|
||||||
// considered less than the longer one.
|
|
||||||
// The result is 0 if s1 == s2, -1 if s1 < s2, and +1 if s1 > s2.
|
|
||||||
func Compare[S ~[]E, E constraints.Ordered](s1, s2 S) int {
|
|
||||||
for i, v1 := range s1 {
|
|
||||||
if i >= len(s2) {
|
|
||||||
return +1
|
|
||||||
}
|
|
||||||
v2 := s2[i]
|
|
||||||
if c := cmpCompare(v1, v2); c != 0 {
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(s1) < len(s2) {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// CompareFunc is like [Compare] but uses a custom comparison function on each
|
|
||||||
// pair of elements.
|
|
||||||
// The result is the first non-zero result of cmp; if cmp always
|
|
||||||
// returns 0 the result is 0 if len(s1) == len(s2), -1 if len(s1) < len(s2),
|
|
||||||
// and +1 if len(s1) > len(s2).
|
|
||||||
func CompareFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, cmp func(E1, E2) int) int {
|
|
||||||
for i, v1 := range s1 {
|
|
||||||
if i >= len(s2) {
|
|
||||||
return +1
|
|
||||||
}
|
|
||||||
v2 := s2[i]
|
|
||||||
if c := cmp(v1, v2); c != 0 {
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(s1) < len(s2) {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Index returns the index of the first occurrence of v in s,
|
|
||||||
// or -1 if not present.
|
|
||||||
func Index[S ~[]E, E comparable](s S, v E) int {
|
|
||||||
for i := range s {
|
|
||||||
if v == s[i] {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
// IndexFunc returns the first index i satisfying f(s[i]),
|
|
||||||
// or -1 if none do.
|
|
||||||
func IndexFunc[S ~[]E, E any](s S, f func(E) bool) int {
|
|
||||||
for i := range s {
|
|
||||||
if f(s[i]) {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contains reports whether v is present in s.
|
|
||||||
func Contains[S ~[]E, E comparable](s S, v E) bool {
|
|
||||||
return Index(s, v) >= 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContainsFunc reports whether at least one
|
|
||||||
// element e of s satisfies f(e).
|
|
||||||
func ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool {
|
|
||||||
return IndexFunc(s, f) >= 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert inserts the values v... into s at index i,
|
|
||||||
// returning the modified slice.
|
|
||||||
// The elements at s[i:] are shifted up to make room.
|
|
||||||
// In the returned slice r, r[i] == v[0],
|
|
||||||
// and r[i+len(v)] == value originally at r[i].
|
|
||||||
// Insert panics if i is out of range.
|
|
||||||
// This function is O(len(s) + len(v)).
|
|
||||||
func Insert[S ~[]E, E any](s S, i int, v ...E) S {
|
|
||||||
m := len(v)
|
|
||||||
if m == 0 {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
n := len(s)
|
|
||||||
if i == n {
|
|
||||||
return append(s, v...)
|
|
||||||
}
|
|
||||||
if n+m > cap(s) {
|
|
||||||
// Use append rather than make so that we bump the size of
|
|
||||||
// the slice up to the next storage class.
|
|
||||||
// This is what Grow does but we don't call Grow because
|
|
||||||
// that might copy the values twice.
|
|
||||||
s2 := append(s[:i], make(S, n+m-i)...)
|
|
||||||
copy(s2[i:], v)
|
|
||||||
copy(s2[i+m:], s[i:])
|
|
||||||
return s2
|
|
||||||
}
|
|
||||||
s = s[:n+m]
|
|
||||||
|
|
||||||
// before:
|
|
||||||
// s: aaaaaaaabbbbccccccccdddd
|
|
||||||
// ^ ^ ^ ^
|
|
||||||
// i i+m n n+m
|
|
||||||
// after:
|
|
||||||
// s: aaaaaaaavvvvbbbbcccccccc
|
|
||||||
// ^ ^ ^ ^
|
|
||||||
// i i+m n n+m
|
|
||||||
//
|
|
||||||
// a are the values that don't move in s.
|
|
||||||
// v are the values copied in from v.
|
|
||||||
// b and c are the values from s that are shifted up in index.
|
|
||||||
// d are the values that get overwritten, never to be seen again.
|
|
||||||
|
|
||||||
if !overlaps(v, s[i+m:]) {
|
|
||||||
// Easy case - v does not overlap either the c or d regions.
|
|
||||||
// (It might be in some of a or b, or elsewhere entirely.)
|
|
||||||
// The data we copy up doesn't write to v at all, so just do it.
|
|
||||||
|
|
||||||
copy(s[i+m:], s[i:])
|
|
||||||
|
|
||||||
// Now we have
|
|
||||||
// s: aaaaaaaabbbbbbbbcccccccc
|
|
||||||
// ^ ^ ^ ^
|
|
||||||
// i i+m n n+m
|
|
||||||
// Note the b values are duplicated.
|
|
||||||
|
|
||||||
copy(s[i:], v)
|
|
||||||
|
|
||||||
// Now we have
|
|
||||||
// s: aaaaaaaavvvvbbbbcccccccc
|
|
||||||
// ^ ^ ^ ^
|
|
||||||
// i i+m n n+m
|
|
||||||
// That's the result we want.
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// The hard case - v overlaps c or d. We can't just shift up
|
|
||||||
// the data because we'd move or clobber the values we're trying
|
|
||||||
// to insert.
|
|
||||||
// So instead, write v on top of d, then rotate.
|
|
||||||
copy(s[n:], v)
|
|
||||||
|
|
||||||
// Now we have
|
|
||||||
// s: aaaaaaaabbbbccccccccvvvv
|
|
||||||
// ^ ^ ^ ^
|
|
||||||
// i i+m n n+m
|
|
||||||
|
|
||||||
rotateRight(s[i:], m)
|
|
||||||
|
|
||||||
// Now we have
|
|
||||||
// s: aaaaaaaavvvvbbbbcccccccc
|
|
||||||
// ^ ^ ^ ^
|
|
||||||
// i i+m n n+m
|
|
||||||
// That's the result we want.
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// clearSlice sets all elements up to the length of s to the zero value of E.
|
|
||||||
// We may use the builtin clear func instead, and remove clearSlice, when upgrading
|
|
||||||
// to Go 1.21+.
|
|
||||||
func clearSlice[S ~[]E, E any](s S) {
|
|
||||||
var zero E
|
|
||||||
for i := range s {
|
|
||||||
s[i] = zero
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete removes the elements s[i:j] from s, returning the modified slice.
|
|
||||||
// Delete panics if j > len(s) or s[i:j] is not a valid slice of s.
|
|
||||||
// Delete is O(len(s)-i), so if many items must be deleted, it is better to
|
|
||||||
// make a single call deleting them all together than to delete one at a time.
|
|
||||||
// Delete zeroes the elements s[len(s)-(j-i):len(s)].
|
|
||||||
func Delete[S ~[]E, E any](s S, i, j int) S {
|
|
||||||
_ = s[i:j:len(s)] // bounds check
|
|
||||||
|
|
||||||
if i == j {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
oldlen := len(s)
|
|
||||||
s = append(s[:i], s[j:]...)
|
|
||||||
clearSlice(s[len(s):oldlen]) // zero/nil out the obsolete elements, for GC
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteFunc removes any elements from s for which del returns true,
|
|
||||||
// returning the modified slice.
|
|
||||||
// DeleteFunc zeroes the elements between the new length and the original length.
|
|
||||||
func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
|
|
||||||
i := IndexFunc(s, del)
|
|
||||||
if i == -1 {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
// Don't start copying elements until we find one to delete.
|
|
||||||
for j := i + 1; j < len(s); j++ {
|
|
||||||
if v := s[j]; !del(v) {
|
|
||||||
s[i] = v
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
|
|
||||||
return s[:i]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace replaces the elements s[i:j] by the given v, and returns the
|
|
||||||
// modified slice. Replace panics if s[i:j] is not a valid slice of s.
|
|
||||||
// When len(v) < (j-i), Replace zeroes the elements between the new length and the original length.
|
|
||||||
func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
|
|
||||||
_ = s[i:j] // verify that i:j is a valid subslice
|
|
||||||
|
|
||||||
if i == j {
|
|
||||||
return Insert(s, i, v...)
|
|
||||||
}
|
|
||||||
if j == len(s) {
|
|
||||||
return append(s[:i], v...)
|
|
||||||
}
|
|
||||||
|
|
||||||
tot := len(s[:i]) + len(v) + len(s[j:])
|
|
||||||
if tot > cap(s) {
|
|
||||||
// Too big to fit, allocate and copy over.
|
|
||||||
s2 := append(s[:i], make(S, tot-i)...) // See Insert
|
|
||||||
copy(s2[i:], v)
|
|
||||||
copy(s2[i+len(v):], s[j:])
|
|
||||||
return s2
|
|
||||||
}
|
|
||||||
|
|
||||||
r := s[:tot]
|
|
||||||
|
|
||||||
if i+len(v) <= j {
|
|
||||||
// Easy, as v fits in the deleted portion.
|
|
||||||
copy(r[i:], v)
|
|
||||||
if i+len(v) != j {
|
|
||||||
copy(r[i+len(v):], s[j:])
|
|
||||||
}
|
|
||||||
clearSlice(s[tot:]) // zero/nil out the obsolete elements, for GC
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// We are expanding (v is bigger than j-i).
|
|
||||||
// The situation is something like this:
|
|
||||||
// (example has i=4,j=8,len(s)=16,len(v)=6)
|
|
||||||
// s: aaaaxxxxbbbbbbbbyy
|
|
||||||
// ^ ^ ^ ^
|
|
||||||
// i j len(s) tot
|
|
||||||
// a: prefix of s
|
|
||||||
// x: deleted range
|
|
||||||
// b: more of s
|
|
||||||
// y: area to expand into
|
|
||||||
|
|
||||||
if !overlaps(r[i+len(v):], v) {
|
|
||||||
// Easy, as v is not clobbered by the first copy.
|
|
||||||
copy(r[i+len(v):], s[j:])
|
|
||||||
copy(r[i:], v)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a situation where we don't have a single place to which
|
|
||||||
// we can copy v. Parts of it need to go to two different places.
|
|
||||||
// We want to copy the prefix of v into y and the suffix into x, then
|
|
||||||
// rotate |y| spots to the right.
|
|
||||||
//
|
|
||||||
// v[2:] v[:2]
|
|
||||||
// | |
|
|
||||||
// s: aaaavvvvbbbbbbbbvv
|
|
||||||
// ^ ^ ^ ^
|
|
||||||
// i j len(s) tot
|
|
||||||
//
|
|
||||||
// If either of those two destinations don't alias v, then we're good.
|
|
||||||
y := len(v) - (j - i) // length of y portion
|
|
||||||
|
|
||||||
if !overlaps(r[i:j], v) {
|
|
||||||
copy(r[i:j], v[y:])
|
|
||||||
copy(r[len(s):], v[:y])
|
|
||||||
rotateRight(r[i:], y)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
if !overlaps(r[len(s):], v) {
|
|
||||||
copy(r[len(s):], v[:y])
|
|
||||||
copy(r[i:j], v[y:])
|
|
||||||
rotateRight(r[i:], y)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now we know that v overlaps both x and y.
|
|
||||||
// That means that the entirety of b is *inside* v.
|
|
||||||
// So we don't need to preserve b at all; instead we
|
|
||||||
// can copy v first, then copy the b part of v out of
|
|
||||||
// v to the right destination.
|
|
||||||
k := startIdx(v, s[j:])
|
|
||||||
copy(r[i:], v)
|
|
||||||
copy(r[i+len(v):], r[i+k:])
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clone returns a copy of the slice.
|
|
||||||
// The elements are copied using assignment, so this is a shallow clone.
|
|
||||||
func Clone[S ~[]E, E any](s S) S {
|
|
||||||
// Preserve nil in case it matters.
|
|
||||||
if s == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return append(S([]E{}), s...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compact replaces consecutive runs of equal elements with a single copy.
|
|
||||||
// This is like the uniq command found on Unix.
|
|
||||||
// Compact modifies the contents of the slice s and returns the modified slice,
|
|
||||||
// which may have a smaller length.
|
|
||||||
// Compact zeroes the elements between the new length and the original length.
|
|
||||||
func Compact[S ~[]E, E comparable](s S) S {
|
|
||||||
if len(s) < 2 {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
i := 1
|
|
||||||
for k := 1; k < len(s); k++ {
|
|
||||||
if s[k] != s[k-1] {
|
|
||||||
if i != k {
|
|
||||||
s[i] = s[k]
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
|
|
||||||
return s[:i]
|
|
||||||
}
|
|
||||||
|
|
||||||
// CompactFunc is like [Compact] but uses an equality function to compare elements.
|
|
||||||
// For runs of elements that compare equal, CompactFunc keeps the first one.
|
|
||||||
// CompactFunc zeroes the elements between the new length and the original length.
|
|
||||||
func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
|
|
||||||
if len(s) < 2 {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
i := 1
|
|
||||||
for k := 1; k < len(s); k++ {
|
|
||||||
if !eq(s[k], s[k-1]) {
|
|
||||||
if i != k {
|
|
||||||
s[i] = s[k]
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
|
|
||||||
return s[:i]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Grow increases the slice's capacity, if necessary, to guarantee space for
|
|
||||||
// another n elements. After Grow(n), at least n elements can be appended
|
|
||||||
// to the slice without another allocation. If n is negative or too large to
|
|
||||||
// allocate the memory, Grow panics.
|
|
||||||
func Grow[S ~[]E, E any](s S, n int) S {
|
|
||||||
if n < 0 {
|
|
||||||
panic("cannot be negative")
|
|
||||||
}
|
|
||||||
if n -= cap(s) - len(s); n > 0 {
|
|
||||||
// TODO(https://go.dev/issue/53888): Make using []E instead of S
|
|
||||||
// to workaround a compiler bug where the runtime.growslice optimization
|
|
||||||
// does not take effect. Revert when the compiler is fixed.
|
|
||||||
s = append([]E(s)[:cap(s)], make([]E, n)...)[:len(s)]
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clip removes unused capacity from the slice, returning s[:len(s):len(s)].
|
|
||||||
func Clip[S ~[]E, E any](s S) S {
|
|
||||||
return s[:len(s):len(s)]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rotation algorithm explanation:
|
|
||||||
//
|
|
||||||
// rotate left by 2
|
|
||||||
// start with
|
|
||||||
// 0123456789
|
|
||||||
// split up like this
|
|
||||||
// 01 234567 89
|
|
||||||
// swap first 2 and last 2
|
|
||||||
// 89 234567 01
|
|
||||||
// join first parts
|
|
||||||
// 89234567 01
|
|
||||||
// recursively rotate first left part by 2
|
|
||||||
// 23456789 01
|
|
||||||
// join at the end
|
|
||||||
// 2345678901
|
|
||||||
//
|
|
||||||
// rotate left by 8
|
|
||||||
// start with
|
|
||||||
// 0123456789
|
|
||||||
// split up like this
|
|
||||||
// 01 234567 89
|
|
||||||
// swap first 2 and last 2
|
|
||||||
// 89 234567 01
|
|
||||||
// join last parts
|
|
||||||
// 89 23456701
|
|
||||||
// recursively rotate second part left by 6
|
|
||||||
// 89 01234567
|
|
||||||
// join at the end
|
|
||||||
// 8901234567
|
|
||||||
|
|
||||||
// TODO: There are other rotate algorithms.
|
|
||||||
// This algorithm has the desirable property that it moves each element exactly twice.
|
|
||||||
// The triple-reverse algorithm is simpler and more cache friendly, but takes more writes.
|
|
||||||
// The follow-cycles algorithm can be 1-write but it is not very cache friendly.
|
|
||||||
|
|
||||||
// rotateLeft rotates b left by n spaces.
|
|
||||||
// s_final[i] = s_orig[i+r], wrapping around.
|
|
||||||
func rotateLeft[E any](s []E, r int) {
|
|
||||||
for r != 0 && r != len(s) {
|
|
||||||
if r*2 <= len(s) {
|
|
||||||
swap(s[:r], s[len(s)-r:])
|
|
||||||
s = s[:len(s)-r]
|
|
||||||
} else {
|
|
||||||
swap(s[:len(s)-r], s[r:])
|
|
||||||
s, r = s[len(s)-r:], r*2-len(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func rotateRight[E any](s []E, r int) {
|
|
||||||
rotateLeft(s, len(s)-r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// swap swaps the contents of x and y. x and y must be equal length and disjoint.
|
|
||||||
func swap[E any](x, y []E) {
|
|
||||||
for i := 0; i < len(x); i++ {
|
|
||||||
x[i], y[i] = y[i], x[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// overlaps reports whether the memory ranges a[0:len(a)] and b[0:len(b)] overlap.
|
|
||||||
func overlaps[E any](a, b []E) bool {
|
|
||||||
if len(a) == 0 || len(b) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
elemSize := unsafe.Sizeof(a[0])
|
|
||||||
if elemSize == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// TODO: use a runtime/unsafe facility once one becomes available. See issue 12445.
|
|
||||||
// Also see crypto/internal/alias/alias.go:AnyOverlap
|
|
||||||
return uintptr(unsafe.Pointer(&a[0])) <= uintptr(unsafe.Pointer(&b[len(b)-1]))+(elemSize-1) &&
|
|
||||||
uintptr(unsafe.Pointer(&b[0])) <= uintptr(unsafe.Pointer(&a[len(a)-1]))+(elemSize-1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// startIdx returns the index in haystack where the needle starts.
|
|
||||||
// prerequisite: the needle must be aliased entirely inside the haystack.
|
|
||||||
func startIdx[E any](haystack, needle []E) int {
|
|
||||||
p := &needle[0]
|
|
||||||
for i := range haystack {
|
|
||||||
if p == &haystack[i] {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO: what if the overlap is by a non-integral number of Es?
|
|
||||||
panic("needle not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reverse reverses the elements of the slice in place.
|
|
||||||
func Reverse[S ~[]E, E any](s S) {
|
|
||||||
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
|
|
||||||
s[i], s[j] = s[j], s[i]
|
|
||||||
}
|
|
||||||
}
|
|
197
vendor/golang.org/x/exp/slices/sort.go
generated
vendored
197
vendor/golang.org/x/exp/slices/sort.go
generated
vendored
@ -1,197 +0,0 @@
|
|||||||
// Copyright 2022 The Go 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:generate go run $GOROOT/src/sort/gen_sort_variants.go -exp
|
|
||||||
|
|
||||||
package slices
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/bits"
|
|
||||||
|
|
||||||
"golang.org/x/exp/constraints"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Sort sorts a slice of any ordered type in ascending order.
|
|
||||||
// When sorting floating-point numbers, NaNs are ordered before other values.
|
|
||||||
func Sort[S ~[]E, E constraints.Ordered](x S) {
|
|
||||||
n := len(x)
|
|
||||||
pdqsortOrdered(x, 0, n, bits.Len(uint(n)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// SortFunc sorts the slice x in ascending order as determined by the cmp
|
|
||||||
// function. This sort is not guaranteed to be stable.
|
|
||||||
// cmp(a, b) should return a negative number when a < b, a positive number when
|
|
||||||
// a > b and zero when a == b or when a is not comparable to b in the sense
|
|
||||||
// of the formal definition of Strict Weak Ordering.
|
|
||||||
//
|
|
||||||
// SortFunc requires that cmp is a strict weak ordering.
|
|
||||||
// See https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings.
|
|
||||||
// To indicate 'uncomparable', return 0 from the function.
|
|
||||||
func SortFunc[S ~[]E, E any](x S, cmp func(a, b E) int) {
|
|
||||||
n := len(x)
|
|
||||||
pdqsortCmpFunc(x, 0, n, bits.Len(uint(n)), cmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SortStableFunc sorts the slice x while keeping the original order of equal
|
|
||||||
// elements, using cmp to compare elements in the same way as [SortFunc].
|
|
||||||
func SortStableFunc[S ~[]E, E any](x S, cmp func(a, b E) int) {
|
|
||||||
stableCmpFunc(x, len(x), cmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsSorted reports whether x is sorted in ascending order.
|
|
||||||
func IsSorted[S ~[]E, E constraints.Ordered](x S) bool {
|
|
||||||
for i := len(x) - 1; i > 0; i-- {
|
|
||||||
if cmpLess(x[i], x[i-1]) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsSortedFunc reports whether x is sorted in ascending order, with cmp as the
|
|
||||||
// comparison function as defined by [SortFunc].
|
|
||||||
func IsSortedFunc[S ~[]E, E any](x S, cmp func(a, b E) int) bool {
|
|
||||||
for i := len(x) - 1; i > 0; i-- {
|
|
||||||
if cmp(x[i], x[i-1]) < 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Min returns the minimal value in x. It panics if x is empty.
|
|
||||||
// For floating-point numbers, Min propagates NaNs (any NaN value in x
|
|
||||||
// forces the output to be NaN).
|
|
||||||
func Min[S ~[]E, E constraints.Ordered](x S) E {
|
|
||||||
if len(x) < 1 {
|
|
||||||
panic("slices.Min: empty list")
|
|
||||||
}
|
|
||||||
m := x[0]
|
|
||||||
for i := 1; i < len(x); i++ {
|
|
||||||
m = min(m, x[i])
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
// MinFunc returns the minimal value in x, using cmp to compare elements.
|
|
||||||
// It panics if x is empty. If there is more than one minimal element
|
|
||||||
// according to the cmp function, MinFunc returns the first one.
|
|
||||||
func MinFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E {
|
|
||||||
if len(x) < 1 {
|
|
||||||
panic("slices.MinFunc: empty list")
|
|
||||||
}
|
|
||||||
m := x[0]
|
|
||||||
for i := 1; i < len(x); i++ {
|
|
||||||
if cmp(x[i], m) < 0 {
|
|
||||||
m = x[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
// Max returns the maximal value in x. It panics if x is empty.
|
|
||||||
// For floating-point E, Max propagates NaNs (any NaN value in x
|
|
||||||
// forces the output to be NaN).
|
|
||||||
func Max[S ~[]E, E constraints.Ordered](x S) E {
|
|
||||||
if len(x) < 1 {
|
|
||||||
panic("slices.Max: empty list")
|
|
||||||
}
|
|
||||||
m := x[0]
|
|
||||||
for i := 1; i < len(x); i++ {
|
|
||||||
m = max(m, x[i])
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
// MaxFunc returns the maximal value in x, using cmp to compare elements.
|
|
||||||
// It panics if x is empty. If there is more than one maximal element
|
|
||||||
// according to the cmp function, MaxFunc returns the first one.
|
|
||||||
func MaxFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E {
|
|
||||||
if len(x) < 1 {
|
|
||||||
panic("slices.MaxFunc: empty list")
|
|
||||||
}
|
|
||||||
m := x[0]
|
|
||||||
for i := 1; i < len(x); i++ {
|
|
||||||
if cmp(x[i], m) > 0 {
|
|
||||||
m = x[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
// BinarySearch searches for target in a sorted slice and returns the position
|
|
||||||
// where target is found, or the position where target would appear in the
|
|
||||||
// sort order; it also returns a bool saying whether the target is really found
|
|
||||||
// in the slice. The slice must be sorted in increasing order.
|
|
||||||
func BinarySearch[S ~[]E, E constraints.Ordered](x S, target E) (int, bool) {
|
|
||||||
// Inlining is faster than calling BinarySearchFunc with a lambda.
|
|
||||||
n := len(x)
|
|
||||||
// Define x[-1] < target and x[n] >= target.
|
|
||||||
// Invariant: x[i-1] < target, x[j] >= target.
|
|
||||||
i, j := 0, n
|
|
||||||
for i < j {
|
|
||||||
h := int(uint(i+j) >> 1) // avoid overflow when computing h
|
|
||||||
// i ≤ h < j
|
|
||||||
if cmpLess(x[h], target) {
|
|
||||||
i = h + 1 // preserves x[i-1] < target
|
|
||||||
} else {
|
|
||||||
j = h // preserves x[j] >= target
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// i == j, x[i-1] < target, and x[j] (= x[i]) >= target => answer is i.
|
|
||||||
return i, i < n && (x[i] == target || (isNaN(x[i]) && isNaN(target)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// BinarySearchFunc works like [BinarySearch], but uses a custom comparison
|
|
||||||
// function. The slice must be sorted in increasing order, where "increasing"
|
|
||||||
// is defined by cmp. cmp should return 0 if the slice element matches
|
|
||||||
// the target, a negative number if the slice element precedes the target,
|
|
||||||
// or a positive number if the slice element follows the target.
|
|
||||||
// cmp must implement the same ordering as the slice, such that if
|
|
||||||
// cmp(a, t) < 0 and cmp(b, t) >= 0, then a must precede b in the slice.
|
|
||||||
func BinarySearchFunc[S ~[]E, E, T any](x S, target T, cmp func(E, T) int) (int, bool) {
|
|
||||||
n := len(x)
|
|
||||||
// Define cmp(x[-1], target) < 0 and cmp(x[n], target) >= 0 .
|
|
||||||
// Invariant: cmp(x[i - 1], target) < 0, cmp(x[j], target) >= 0.
|
|
||||||
i, j := 0, n
|
|
||||||
for i < j {
|
|
||||||
h := int(uint(i+j) >> 1) // avoid overflow when computing h
|
|
||||||
// i ≤ h < j
|
|
||||||
if cmp(x[h], target) < 0 {
|
|
||||||
i = h + 1 // preserves cmp(x[i - 1], target) < 0
|
|
||||||
} else {
|
|
||||||
j = h // preserves cmp(x[j], target) >= 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// i == j, cmp(x[i-1], target) < 0, and cmp(x[j], target) (= cmp(x[i], target)) >= 0 => answer is i.
|
|
||||||
return i, i < n && cmp(x[i], target) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type sortedHint int // hint for pdqsort when choosing the pivot
|
|
||||||
|
|
||||||
const (
|
|
||||||
unknownHint sortedHint = iota
|
|
||||||
increasingHint
|
|
||||||
decreasingHint
|
|
||||||
)
|
|
||||||
|
|
||||||
// xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf
|
|
||||||
type xorshift uint64
|
|
||||||
|
|
||||||
func (r *xorshift) Next() uint64 {
|
|
||||||
*r ^= *r << 13
|
|
||||||
*r ^= *r >> 17
|
|
||||||
*r ^= *r << 5
|
|
||||||
return uint64(*r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func nextPowerOfTwo(length int) uint {
|
|
||||||
return 1 << bits.Len(uint(length))
|
|
||||||
}
|
|
||||||
|
|
||||||
// isNaN reports whether x is a NaN without requiring the math package.
|
|
||||||
// This will always return false if T is not floating-point.
|
|
||||||
func isNaN[T constraints.Ordered](x T) bool {
|
|
||||||
return x != x
|
|
||||||
}
|
|
479
vendor/golang.org/x/exp/slices/zsortanyfunc.go
generated
vendored
479
vendor/golang.org/x/exp/slices/zsortanyfunc.go
generated
vendored
@ -1,479 +0,0 @@
|
|||||||
// Code generated by gen_sort_variants.go; DO NOT EDIT.
|
|
||||||
|
|
||||||
// Copyright 2022 The Go 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 slices
|
|
||||||
|
|
||||||
// insertionSortCmpFunc sorts data[a:b] using insertion sort.
|
|
||||||
func insertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) {
|
|
||||||
for i := a + 1; i < b; i++ {
|
|
||||||
for j := i; j > a && (cmp(data[j], data[j-1]) < 0); j-- {
|
|
||||||
data[j], data[j-1] = data[j-1], data[j]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// siftDownCmpFunc implements the heap property on data[lo:hi].
|
|
||||||
// first is an offset into the array where the root of the heap lies.
|
|
||||||
func siftDownCmpFunc[E any](data []E, lo, hi, first int, cmp func(a, b E) int) {
|
|
||||||
root := lo
|
|
||||||
for {
|
|
||||||
child := 2*root + 1
|
|
||||||
if child >= hi {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if child+1 < hi && (cmp(data[first+child], data[first+child+1]) < 0) {
|
|
||||||
child++
|
|
||||||
}
|
|
||||||
if !(cmp(data[first+root], data[first+child]) < 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
data[first+root], data[first+child] = data[first+child], data[first+root]
|
|
||||||
root = child
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func heapSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) {
|
|
||||||
first := a
|
|
||||||
lo := 0
|
|
||||||
hi := b - a
|
|
||||||
|
|
||||||
// Build heap with greatest element at top.
|
|
||||||
for i := (hi - 1) / 2; i >= 0; i-- {
|
|
||||||
siftDownCmpFunc(data, i, hi, first, cmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pop elements, largest first, into end of data.
|
|
||||||
for i := hi - 1; i >= 0; i-- {
|
|
||||||
data[first], data[first+i] = data[first+i], data[first]
|
|
||||||
siftDownCmpFunc(data, lo, i, first, cmp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// pdqsortCmpFunc sorts data[a:b].
|
|
||||||
// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort.
|
|
||||||
// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf
|
|
||||||
// C++ implementation: https://github.com/orlp/pdqsort
|
|
||||||
// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/
|
|
||||||
// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort.
|
|
||||||
func pdqsortCmpFunc[E any](data []E, a, b, limit int, cmp func(a, b E) int) {
|
|
||||||
const maxInsertion = 12
|
|
||||||
|
|
||||||
var (
|
|
||||||
wasBalanced = true // whether the last partitioning was reasonably balanced
|
|
||||||
wasPartitioned = true // whether the slice was already partitioned
|
|
||||||
)
|
|
||||||
|
|
||||||
for {
|
|
||||||
length := b - a
|
|
||||||
|
|
||||||
if length <= maxInsertion {
|
|
||||||
insertionSortCmpFunc(data, a, b, cmp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fall back to heapsort if too many bad choices were made.
|
|
||||||
if limit == 0 {
|
|
||||||
heapSortCmpFunc(data, a, b, cmp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the last partitioning was imbalanced, we need to breaking patterns.
|
|
||||||
if !wasBalanced {
|
|
||||||
breakPatternsCmpFunc(data, a, b, cmp)
|
|
||||||
limit--
|
|
||||||
}
|
|
||||||
|
|
||||||
pivot, hint := choosePivotCmpFunc(data, a, b, cmp)
|
|
||||||
if hint == decreasingHint {
|
|
||||||
reverseRangeCmpFunc(data, a, b, cmp)
|
|
||||||
// The chosen pivot was pivot-a elements after the start of the array.
|
|
||||||
// After reversing it is pivot-a elements before the end of the array.
|
|
||||||
// The idea came from Rust's implementation.
|
|
||||||
pivot = (b - 1) - (pivot - a)
|
|
||||||
hint = increasingHint
|
|
||||||
}
|
|
||||||
|
|
||||||
// The slice is likely already sorted.
|
|
||||||
if wasBalanced && wasPartitioned && hint == increasingHint {
|
|
||||||
if partialInsertionSortCmpFunc(data, a, b, cmp) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Probably the slice contains many duplicate elements, partition the slice into
|
|
||||||
// elements equal to and elements greater than the pivot.
|
|
||||||
if a > 0 && !(cmp(data[a-1], data[pivot]) < 0) {
|
|
||||||
mid := partitionEqualCmpFunc(data, a, b, pivot, cmp)
|
|
||||||
a = mid
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
mid, alreadyPartitioned := partitionCmpFunc(data, a, b, pivot, cmp)
|
|
||||||
wasPartitioned = alreadyPartitioned
|
|
||||||
|
|
||||||
leftLen, rightLen := mid-a, b-mid
|
|
||||||
balanceThreshold := length / 8
|
|
||||||
if leftLen < rightLen {
|
|
||||||
wasBalanced = leftLen >= balanceThreshold
|
|
||||||
pdqsortCmpFunc(data, a, mid, limit, cmp)
|
|
||||||
a = mid + 1
|
|
||||||
} else {
|
|
||||||
wasBalanced = rightLen >= balanceThreshold
|
|
||||||
pdqsortCmpFunc(data, mid+1, b, limit, cmp)
|
|
||||||
b = mid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// partitionCmpFunc does one quicksort partition.
|
|
||||||
// Let p = data[pivot]
|
|
||||||
// Moves elements in data[a:b] around, so that data[i]<p and data[j]>=p for i<newpivot and j>newpivot.
|
|
||||||
// On return, data[newpivot] = p
|
|
||||||
func partitionCmpFunc[E any](data []E, a, b, pivot int, cmp func(a, b E) int) (newpivot int, alreadyPartitioned bool) {
|
|
||||||
data[a], data[pivot] = data[pivot], data[a]
|
|
||||||
i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned
|
|
||||||
|
|
||||||
for i <= j && (cmp(data[i], data[a]) < 0) {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
for i <= j && !(cmp(data[j], data[a]) < 0) {
|
|
||||||
j--
|
|
||||||
}
|
|
||||||
if i > j {
|
|
||||||
data[j], data[a] = data[a], data[j]
|
|
||||||
return j, true
|
|
||||||
}
|
|
||||||
data[i], data[j] = data[j], data[i]
|
|
||||||
i++
|
|
||||||
j--
|
|
||||||
|
|
||||||
for {
|
|
||||||
for i <= j && (cmp(data[i], data[a]) < 0) {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
for i <= j && !(cmp(data[j], data[a]) < 0) {
|
|
||||||
j--
|
|
||||||
}
|
|
||||||
if i > j {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
data[i], data[j] = data[j], data[i]
|
|
||||||
i++
|
|
||||||
j--
|
|
||||||
}
|
|
||||||
data[j], data[a] = data[a], data[j]
|
|
||||||
return j, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// partitionEqualCmpFunc partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot].
|
|
||||||
// It assumed that data[a:b] does not contain elements smaller than the data[pivot].
|
|
||||||
func partitionEqualCmpFunc[E any](data []E, a, b, pivot int, cmp func(a, b E) int) (newpivot int) {
|
|
||||||
data[a], data[pivot] = data[pivot], data[a]
|
|
||||||
i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned
|
|
||||||
|
|
||||||
for {
|
|
||||||
for i <= j && !(cmp(data[a], data[i]) < 0) {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
for i <= j && (cmp(data[a], data[j]) < 0) {
|
|
||||||
j--
|
|
||||||
}
|
|
||||||
if i > j {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
data[i], data[j] = data[j], data[i]
|
|
||||||
i++
|
|
||||||
j--
|
|
||||||
}
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
|
|
||||||
// partialInsertionSortCmpFunc partially sorts a slice, returns true if the slice is sorted at the end.
|
|
||||||
func partialInsertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) bool {
|
|
||||||
const (
|
|
||||||
maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted
|
|
||||||
shortestShifting = 50 // don't shift any elements on short arrays
|
|
||||||
)
|
|
||||||
i := a + 1
|
|
||||||
for j := 0; j < maxSteps; j++ {
|
|
||||||
for i < b && !(cmp(data[i], data[i-1]) < 0) {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
if i == b {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if b-a < shortestShifting {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
data[i], data[i-1] = data[i-1], data[i]
|
|
||||||
|
|
||||||
// Shift the smaller one to the left.
|
|
||||||
if i-a >= 2 {
|
|
||||||
for j := i - 1; j >= 1; j-- {
|
|
||||||
if !(cmp(data[j], data[j-1]) < 0) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
data[j], data[j-1] = data[j-1], data[j]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Shift the greater one to the right.
|
|
||||||
if b-i >= 2 {
|
|
||||||
for j := i + 1; j < b; j++ {
|
|
||||||
if !(cmp(data[j], data[j-1]) < 0) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
data[j], data[j-1] = data[j-1], data[j]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// breakPatternsCmpFunc scatters some elements around in an attempt to break some patterns
|
|
||||||
// that might cause imbalanced partitions in quicksort.
|
|
||||||
func breakPatternsCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) {
|
|
||||||
length := b - a
|
|
||||||
if length >= 8 {
|
|
||||||
random := xorshift(length)
|
|
||||||
modulus := nextPowerOfTwo(length)
|
|
||||||
|
|
||||||
for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ {
|
|
||||||
other := int(uint(random.Next()) & (modulus - 1))
|
|
||||||
if other >= length {
|
|
||||||
other -= length
|
|
||||||
}
|
|
||||||
data[idx], data[a+other] = data[a+other], data[idx]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// choosePivotCmpFunc chooses a pivot in data[a:b].
|
|
||||||
//
|
|
||||||
// [0,8): chooses a static pivot.
|
|
||||||
// [8,shortestNinther): uses the simple median-of-three method.
|
|
||||||
// [shortestNinther,∞): uses the Tukey ninther method.
|
|
||||||
func choosePivotCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) (pivot int, hint sortedHint) {
|
|
||||||
const (
|
|
||||||
shortestNinther = 50
|
|
||||||
maxSwaps = 4 * 3
|
|
||||||
)
|
|
||||||
|
|
||||||
l := b - a
|
|
||||||
|
|
||||||
var (
|
|
||||||
swaps int
|
|
||||||
i = a + l/4*1
|
|
||||||
j = a + l/4*2
|
|
||||||
k = a + l/4*3
|
|
||||||
)
|
|
||||||
|
|
||||||
if l >= 8 {
|
|
||||||
if l >= shortestNinther {
|
|
||||||
// Tukey ninther method, the idea came from Rust's implementation.
|
|
||||||
i = medianAdjacentCmpFunc(data, i, &swaps, cmp)
|
|
||||||
j = medianAdjacentCmpFunc(data, j, &swaps, cmp)
|
|
||||||
k = medianAdjacentCmpFunc(data, k, &swaps, cmp)
|
|
||||||
}
|
|
||||||
// Find the median among i, j, k and stores it into j.
|
|
||||||
j = medianCmpFunc(data, i, j, k, &swaps, cmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch swaps {
|
|
||||||
case 0:
|
|
||||||
return j, increasingHint
|
|
||||||
case maxSwaps:
|
|
||||||
return j, decreasingHint
|
|
||||||
default:
|
|
||||||
return j, unknownHint
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// order2CmpFunc returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a.
|
|
||||||
func order2CmpFunc[E any](data []E, a, b int, swaps *int, cmp func(a, b E) int) (int, int) {
|
|
||||||
if cmp(data[b], data[a]) < 0 {
|
|
||||||
*swaps++
|
|
||||||
return b, a
|
|
||||||
}
|
|
||||||
return a, b
|
|
||||||
}
|
|
||||||
|
|
||||||
// medianCmpFunc returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c.
|
|
||||||
func medianCmpFunc[E any](data []E, a, b, c int, swaps *int, cmp func(a, b E) int) int {
|
|
||||||
a, b = order2CmpFunc(data, a, b, swaps, cmp)
|
|
||||||
b, c = order2CmpFunc(data, b, c, swaps, cmp)
|
|
||||||
a, b = order2CmpFunc(data, a, b, swaps, cmp)
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// medianAdjacentCmpFunc finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a.
|
|
||||||
func medianAdjacentCmpFunc[E any](data []E, a int, swaps *int, cmp func(a, b E) int) int {
|
|
||||||
return medianCmpFunc(data, a-1, a, a+1, swaps, cmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
func reverseRangeCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) {
|
|
||||||
i := a
|
|
||||||
j := b - 1
|
|
||||||
for i < j {
|
|
||||||
data[i], data[j] = data[j], data[i]
|
|
||||||
i++
|
|
||||||
j--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func swapRangeCmpFunc[E any](data []E, a, b, n int, cmp func(a, b E) int) {
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
data[a+i], data[b+i] = data[b+i], data[a+i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func stableCmpFunc[E any](data []E, n int, cmp func(a, b E) int) {
|
|
||||||
blockSize := 20 // must be > 0
|
|
||||||
a, b := 0, blockSize
|
|
||||||
for b <= n {
|
|
||||||
insertionSortCmpFunc(data, a, b, cmp)
|
|
||||||
a = b
|
|
||||||
b += blockSize
|
|
||||||
}
|
|
||||||
insertionSortCmpFunc(data, a, n, cmp)
|
|
||||||
|
|
||||||
for blockSize < n {
|
|
||||||
a, b = 0, 2*blockSize
|
|
||||||
for b <= n {
|
|
||||||
symMergeCmpFunc(data, a, a+blockSize, b, cmp)
|
|
||||||
a = b
|
|
||||||
b += 2 * blockSize
|
|
||||||
}
|
|
||||||
if m := a + blockSize; m < n {
|
|
||||||
symMergeCmpFunc(data, a, m, n, cmp)
|
|
||||||
}
|
|
||||||
blockSize *= 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// symMergeCmpFunc merges the two sorted subsequences data[a:m] and data[m:b] using
|
|
||||||
// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum
|
|
||||||
// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz
|
|
||||||
// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in
|
|
||||||
// Computer Science, pages 714-723. Springer, 2004.
|
|
||||||
//
|
|
||||||
// Let M = m-a and N = b-n. Wolog M < N.
|
|
||||||
// The recursion depth is bound by ceil(log(N+M)).
|
|
||||||
// The algorithm needs O(M*log(N/M + 1)) calls to data.Less.
|
|
||||||
// The algorithm needs O((M+N)*log(M)) calls to data.Swap.
|
|
||||||
//
|
|
||||||
// The paper gives O((M+N)*log(M)) as the number of assignments assuming a
|
|
||||||
// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation
|
|
||||||
// in the paper carries through for Swap operations, especially as the block
|
|
||||||
// swapping rotate uses only O(M+N) Swaps.
|
|
||||||
//
|
|
||||||
// symMerge assumes non-degenerate arguments: a < m && m < b.
|
|
||||||
// Having the caller check this condition eliminates many leaf recursion calls,
|
|
||||||
// which improves performance.
|
|
||||||
func symMergeCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) {
|
|
||||||
// Avoid unnecessary recursions of symMerge
|
|
||||||
// by direct insertion of data[a] into data[m:b]
|
|
||||||
// if data[a:m] only contains one element.
|
|
||||||
if m-a == 1 {
|
|
||||||
// Use binary search to find the lowest index i
|
|
||||||
// such that data[i] >= data[a] for m <= i < b.
|
|
||||||
// Exit the search loop with i == b in case no such index exists.
|
|
||||||
i := m
|
|
||||||
j := b
|
|
||||||
for i < j {
|
|
||||||
h := int(uint(i+j) >> 1)
|
|
||||||
if cmp(data[h], data[a]) < 0 {
|
|
||||||
i = h + 1
|
|
||||||
} else {
|
|
||||||
j = h
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Swap values until data[a] reaches the position before i.
|
|
||||||
for k := a; k < i-1; k++ {
|
|
||||||
data[k], data[k+1] = data[k+1], data[k]
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Avoid unnecessary recursions of symMerge
|
|
||||||
// by direct insertion of data[m] into data[a:m]
|
|
||||||
// if data[m:b] only contains one element.
|
|
||||||
if b-m == 1 {
|
|
||||||
// Use binary search to find the lowest index i
|
|
||||||
// such that data[i] > data[m] for a <= i < m.
|
|
||||||
// Exit the search loop with i == m in case no such index exists.
|
|
||||||
i := a
|
|
||||||
j := m
|
|
||||||
for i < j {
|
|
||||||
h := int(uint(i+j) >> 1)
|
|
||||||
if !(cmp(data[m], data[h]) < 0) {
|
|
||||||
i = h + 1
|
|
||||||
} else {
|
|
||||||
j = h
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Swap values until data[m] reaches the position i.
|
|
||||||
for k := m; k > i; k-- {
|
|
||||||
data[k], data[k-1] = data[k-1], data[k]
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
mid := int(uint(a+b) >> 1)
|
|
||||||
n := mid + m
|
|
||||||
var start, r int
|
|
||||||
if m > mid {
|
|
||||||
start = n - b
|
|
||||||
r = mid
|
|
||||||
} else {
|
|
||||||
start = a
|
|
||||||
r = m
|
|
||||||
}
|
|
||||||
p := n - 1
|
|
||||||
|
|
||||||
for start < r {
|
|
||||||
c := int(uint(start+r) >> 1)
|
|
||||||
if !(cmp(data[p-c], data[c]) < 0) {
|
|
||||||
start = c + 1
|
|
||||||
} else {
|
|
||||||
r = c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
end := n - start
|
|
||||||
if start < m && m < end {
|
|
||||||
rotateCmpFunc(data, start, m, end, cmp)
|
|
||||||
}
|
|
||||||
if a < start && start < mid {
|
|
||||||
symMergeCmpFunc(data, a, start, mid, cmp)
|
|
||||||
}
|
|
||||||
if mid < end && end < b {
|
|
||||||
symMergeCmpFunc(data, mid, end, b, cmp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rotateCmpFunc rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data:
|
|
||||||
// Data of the form 'x u v y' is changed to 'x v u y'.
|
|
||||||
// rotate performs at most b-a many calls to data.Swap,
|
|
||||||
// and it assumes non-degenerate arguments: a < m && m < b.
|
|
||||||
func rotateCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) {
|
|
||||||
i := m - a
|
|
||||||
j := b - m
|
|
||||||
|
|
||||||
for i != j {
|
|
||||||
if i > j {
|
|
||||||
swapRangeCmpFunc(data, m-i, m, j, cmp)
|
|
||||||
i -= j
|
|
||||||
} else {
|
|
||||||
swapRangeCmpFunc(data, m-i, m+j-i, i, cmp)
|
|
||||||
j -= i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// i == j
|
|
||||||
swapRangeCmpFunc(data, m-i, m, i, cmp)
|
|
||||||
}
|
|
481
vendor/golang.org/x/exp/slices/zsortordered.go
generated
vendored
481
vendor/golang.org/x/exp/slices/zsortordered.go
generated
vendored
@ -1,481 +0,0 @@
|
|||||||
// Code generated by gen_sort_variants.go; DO NOT EDIT.
|
|
||||||
|
|
||||||
// Copyright 2022 The Go 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 slices
|
|
||||||
|
|
||||||
import "golang.org/x/exp/constraints"
|
|
||||||
|
|
||||||
// insertionSortOrdered sorts data[a:b] using insertion sort.
|
|
||||||
func insertionSortOrdered[E constraints.Ordered](data []E, a, b int) {
|
|
||||||
for i := a + 1; i < b; i++ {
|
|
||||||
for j := i; j > a && cmpLess(data[j], data[j-1]); j-- {
|
|
||||||
data[j], data[j-1] = data[j-1], data[j]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// siftDownOrdered implements the heap property on data[lo:hi].
|
|
||||||
// first is an offset into the array where the root of the heap lies.
|
|
||||||
func siftDownOrdered[E constraints.Ordered](data []E, lo, hi, first int) {
|
|
||||||
root := lo
|
|
||||||
for {
|
|
||||||
child := 2*root + 1
|
|
||||||
if child >= hi {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if child+1 < hi && cmpLess(data[first+child], data[first+child+1]) {
|
|
||||||
child++
|
|
||||||
}
|
|
||||||
if !cmpLess(data[first+root], data[first+child]) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
data[first+root], data[first+child] = data[first+child], data[first+root]
|
|
||||||
root = child
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func heapSortOrdered[E constraints.Ordered](data []E, a, b int) {
|
|
||||||
first := a
|
|
||||||
lo := 0
|
|
||||||
hi := b - a
|
|
||||||
|
|
||||||
// Build heap with greatest element at top.
|
|
||||||
for i := (hi - 1) / 2; i >= 0; i-- {
|
|
||||||
siftDownOrdered(data, i, hi, first)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pop elements, largest first, into end of data.
|
|
||||||
for i := hi - 1; i >= 0; i-- {
|
|
||||||
data[first], data[first+i] = data[first+i], data[first]
|
|
||||||
siftDownOrdered(data, lo, i, first)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// pdqsortOrdered sorts data[a:b].
|
|
||||||
// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort.
|
|
||||||
// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf
|
|
||||||
// C++ implementation: https://github.com/orlp/pdqsort
|
|
||||||
// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/
|
|
||||||
// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort.
|
|
||||||
func pdqsortOrdered[E constraints.Ordered](data []E, a, b, limit int) {
|
|
||||||
const maxInsertion = 12
|
|
||||||
|
|
||||||
var (
|
|
||||||
wasBalanced = true // whether the last partitioning was reasonably balanced
|
|
||||||
wasPartitioned = true // whether the slice was already partitioned
|
|
||||||
)
|
|
||||||
|
|
||||||
for {
|
|
||||||
length := b - a
|
|
||||||
|
|
||||||
if length <= maxInsertion {
|
|
||||||
insertionSortOrdered(data, a, b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fall back to heapsort if too many bad choices were made.
|
|
||||||
if limit == 0 {
|
|
||||||
heapSortOrdered(data, a, b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the last partitioning was imbalanced, we need to breaking patterns.
|
|
||||||
if !wasBalanced {
|
|
||||||
breakPatternsOrdered(data, a, b)
|
|
||||||
limit--
|
|
||||||
}
|
|
||||||
|
|
||||||
pivot, hint := choosePivotOrdered(data, a, b)
|
|
||||||
if hint == decreasingHint {
|
|
||||||
reverseRangeOrdered(data, a, b)
|
|
||||||
// The chosen pivot was pivot-a elements after the start of the array.
|
|
||||||
// After reversing it is pivot-a elements before the end of the array.
|
|
||||||
// The idea came from Rust's implementation.
|
|
||||||
pivot = (b - 1) - (pivot - a)
|
|
||||||
hint = increasingHint
|
|
||||||
}
|
|
||||||
|
|
||||||
// The slice is likely already sorted.
|
|
||||||
if wasBalanced && wasPartitioned && hint == increasingHint {
|
|
||||||
if partialInsertionSortOrdered(data, a, b) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Probably the slice contains many duplicate elements, partition the slice into
|
|
||||||
// elements equal to and elements greater than the pivot.
|
|
||||||
if a > 0 && !cmpLess(data[a-1], data[pivot]) {
|
|
||||||
mid := partitionEqualOrdered(data, a, b, pivot)
|
|
||||||
a = mid
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
mid, alreadyPartitioned := partitionOrdered(data, a, b, pivot)
|
|
||||||
wasPartitioned = alreadyPartitioned
|
|
||||||
|
|
||||||
leftLen, rightLen := mid-a, b-mid
|
|
||||||
balanceThreshold := length / 8
|
|
||||||
if leftLen < rightLen {
|
|
||||||
wasBalanced = leftLen >= balanceThreshold
|
|
||||||
pdqsortOrdered(data, a, mid, limit)
|
|
||||||
a = mid + 1
|
|
||||||
} else {
|
|
||||||
wasBalanced = rightLen >= balanceThreshold
|
|
||||||
pdqsortOrdered(data, mid+1, b, limit)
|
|
||||||
b = mid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// partitionOrdered does one quicksort partition.
|
|
||||||
// Let p = data[pivot]
|
|
||||||
// Moves elements in data[a:b] around, so that data[i]<p and data[j]>=p for i<newpivot and j>newpivot.
|
|
||||||
// On return, data[newpivot] = p
|
|
||||||
func partitionOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivot int, alreadyPartitioned bool) {
|
|
||||||
data[a], data[pivot] = data[pivot], data[a]
|
|
||||||
i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned
|
|
||||||
|
|
||||||
for i <= j && cmpLess(data[i], data[a]) {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
for i <= j && !cmpLess(data[j], data[a]) {
|
|
||||||
j--
|
|
||||||
}
|
|
||||||
if i > j {
|
|
||||||
data[j], data[a] = data[a], data[j]
|
|
||||||
return j, true
|
|
||||||
}
|
|
||||||
data[i], data[j] = data[j], data[i]
|
|
||||||
i++
|
|
||||||
j--
|
|
||||||
|
|
||||||
for {
|
|
||||||
for i <= j && cmpLess(data[i], data[a]) {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
for i <= j && !cmpLess(data[j], data[a]) {
|
|
||||||
j--
|
|
||||||
}
|
|
||||||
if i > j {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
data[i], data[j] = data[j], data[i]
|
|
||||||
i++
|
|
||||||
j--
|
|
||||||
}
|
|
||||||
data[j], data[a] = data[a], data[j]
|
|
||||||
return j, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// partitionEqualOrdered partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot].
|
|
||||||
// It assumed that data[a:b] does not contain elements smaller than the data[pivot].
|
|
||||||
func partitionEqualOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivot int) {
|
|
||||||
data[a], data[pivot] = data[pivot], data[a]
|
|
||||||
i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned
|
|
||||||
|
|
||||||
for {
|
|
||||||
for i <= j && !cmpLess(data[a], data[i]) {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
for i <= j && cmpLess(data[a], data[j]) {
|
|
||||||
j--
|
|
||||||
}
|
|
||||||
if i > j {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
data[i], data[j] = data[j], data[i]
|
|
||||||
i++
|
|
||||||
j--
|
|
||||||
}
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
|
|
||||||
// partialInsertionSortOrdered partially sorts a slice, returns true if the slice is sorted at the end.
|
|
||||||
func partialInsertionSortOrdered[E constraints.Ordered](data []E, a, b int) bool {
|
|
||||||
const (
|
|
||||||
maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted
|
|
||||||
shortestShifting = 50 // don't shift any elements on short arrays
|
|
||||||
)
|
|
||||||
i := a + 1
|
|
||||||
for j := 0; j < maxSteps; j++ {
|
|
||||||
for i < b && !cmpLess(data[i], data[i-1]) {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
if i == b {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if b-a < shortestShifting {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
data[i], data[i-1] = data[i-1], data[i]
|
|
||||||
|
|
||||||
// Shift the smaller one to the left.
|
|
||||||
if i-a >= 2 {
|
|
||||||
for j := i - 1; j >= 1; j-- {
|
|
||||||
if !cmpLess(data[j], data[j-1]) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
data[j], data[j-1] = data[j-1], data[j]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Shift the greater one to the right.
|
|
||||||
if b-i >= 2 {
|
|
||||||
for j := i + 1; j < b; j++ {
|
|
||||||
if !cmpLess(data[j], data[j-1]) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
data[j], data[j-1] = data[j-1], data[j]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// breakPatternsOrdered scatters some elements around in an attempt to break some patterns
|
|
||||||
// that might cause imbalanced partitions in quicksort.
|
|
||||||
func breakPatternsOrdered[E constraints.Ordered](data []E, a, b int) {
|
|
||||||
length := b - a
|
|
||||||
if length >= 8 {
|
|
||||||
random := xorshift(length)
|
|
||||||
modulus := nextPowerOfTwo(length)
|
|
||||||
|
|
||||||
for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ {
|
|
||||||
other := int(uint(random.Next()) & (modulus - 1))
|
|
||||||
if other >= length {
|
|
||||||
other -= length
|
|
||||||
}
|
|
||||||
data[idx], data[a+other] = data[a+other], data[idx]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// choosePivotOrdered chooses a pivot in data[a:b].
|
|
||||||
//
|
|
||||||
// [0,8): chooses a static pivot.
|
|
||||||
// [8,shortestNinther): uses the simple median-of-three method.
|
|
||||||
// [shortestNinther,∞): uses the Tukey ninther method.
|
|
||||||
func choosePivotOrdered[E constraints.Ordered](data []E, a, b int) (pivot int, hint sortedHint) {
|
|
||||||
const (
|
|
||||||
shortestNinther = 50
|
|
||||||
maxSwaps = 4 * 3
|
|
||||||
)
|
|
||||||
|
|
||||||
l := b - a
|
|
||||||
|
|
||||||
var (
|
|
||||||
swaps int
|
|
||||||
i = a + l/4*1
|
|
||||||
j = a + l/4*2
|
|
||||||
k = a + l/4*3
|
|
||||||
)
|
|
||||||
|
|
||||||
if l >= 8 {
|
|
||||||
if l >= shortestNinther {
|
|
||||||
// Tukey ninther method, the idea came from Rust's implementation.
|
|
||||||
i = medianAdjacentOrdered(data, i, &swaps)
|
|
||||||
j = medianAdjacentOrdered(data, j, &swaps)
|
|
||||||
k = medianAdjacentOrdered(data, k, &swaps)
|
|
||||||
}
|
|
||||||
// Find the median among i, j, k and stores it into j.
|
|
||||||
j = medianOrdered(data, i, j, k, &swaps)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch swaps {
|
|
||||||
case 0:
|
|
||||||
return j, increasingHint
|
|
||||||
case maxSwaps:
|
|
||||||
return j, decreasingHint
|
|
||||||
default:
|
|
||||||
return j, unknownHint
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// order2Ordered returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a.
|
|
||||||
func order2Ordered[E constraints.Ordered](data []E, a, b int, swaps *int) (int, int) {
|
|
||||||
if cmpLess(data[b], data[a]) {
|
|
||||||
*swaps++
|
|
||||||
return b, a
|
|
||||||
}
|
|
||||||
return a, b
|
|
||||||
}
|
|
||||||
|
|
||||||
// medianOrdered returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c.
|
|
||||||
func medianOrdered[E constraints.Ordered](data []E, a, b, c int, swaps *int) int {
|
|
||||||
a, b = order2Ordered(data, a, b, swaps)
|
|
||||||
b, c = order2Ordered(data, b, c, swaps)
|
|
||||||
a, b = order2Ordered(data, a, b, swaps)
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// medianAdjacentOrdered finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a.
|
|
||||||
func medianAdjacentOrdered[E constraints.Ordered](data []E, a int, swaps *int) int {
|
|
||||||
return medianOrdered(data, a-1, a, a+1, swaps)
|
|
||||||
}
|
|
||||||
|
|
||||||
func reverseRangeOrdered[E constraints.Ordered](data []E, a, b int) {
|
|
||||||
i := a
|
|
||||||
j := b - 1
|
|
||||||
for i < j {
|
|
||||||
data[i], data[j] = data[j], data[i]
|
|
||||||
i++
|
|
||||||
j--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func swapRangeOrdered[E constraints.Ordered](data []E, a, b, n int) {
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
data[a+i], data[b+i] = data[b+i], data[a+i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func stableOrdered[E constraints.Ordered](data []E, n int) {
|
|
||||||
blockSize := 20 // must be > 0
|
|
||||||
a, b := 0, blockSize
|
|
||||||
for b <= n {
|
|
||||||
insertionSortOrdered(data, a, b)
|
|
||||||
a = b
|
|
||||||
b += blockSize
|
|
||||||
}
|
|
||||||
insertionSortOrdered(data, a, n)
|
|
||||||
|
|
||||||
for blockSize < n {
|
|
||||||
a, b = 0, 2*blockSize
|
|
||||||
for b <= n {
|
|
||||||
symMergeOrdered(data, a, a+blockSize, b)
|
|
||||||
a = b
|
|
||||||
b += 2 * blockSize
|
|
||||||
}
|
|
||||||
if m := a + blockSize; m < n {
|
|
||||||
symMergeOrdered(data, a, m, n)
|
|
||||||
}
|
|
||||||
blockSize *= 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// symMergeOrdered merges the two sorted subsequences data[a:m] and data[m:b] using
|
|
||||||
// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum
|
|
||||||
// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz
|
|
||||||
// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in
|
|
||||||
// Computer Science, pages 714-723. Springer, 2004.
|
|
||||||
//
|
|
||||||
// Let M = m-a and N = b-n. Wolog M < N.
|
|
||||||
// The recursion depth is bound by ceil(log(N+M)).
|
|
||||||
// The algorithm needs O(M*log(N/M + 1)) calls to data.Less.
|
|
||||||
// The algorithm needs O((M+N)*log(M)) calls to data.Swap.
|
|
||||||
//
|
|
||||||
// The paper gives O((M+N)*log(M)) as the number of assignments assuming a
|
|
||||||
// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation
|
|
||||||
// in the paper carries through for Swap operations, especially as the block
|
|
||||||
// swapping rotate uses only O(M+N) Swaps.
|
|
||||||
//
|
|
||||||
// symMerge assumes non-degenerate arguments: a < m && m < b.
|
|
||||||
// Having the caller check this condition eliminates many leaf recursion calls,
|
|
||||||
// which improves performance.
|
|
||||||
func symMergeOrdered[E constraints.Ordered](data []E, a, m, b int) {
|
|
||||||
// Avoid unnecessary recursions of symMerge
|
|
||||||
// by direct insertion of data[a] into data[m:b]
|
|
||||||
// if data[a:m] only contains one element.
|
|
||||||
if m-a == 1 {
|
|
||||||
// Use binary search to find the lowest index i
|
|
||||||
// such that data[i] >= data[a] for m <= i < b.
|
|
||||||
// Exit the search loop with i == b in case no such index exists.
|
|
||||||
i := m
|
|
||||||
j := b
|
|
||||||
for i < j {
|
|
||||||
h := int(uint(i+j) >> 1)
|
|
||||||
if cmpLess(data[h], data[a]) {
|
|
||||||
i = h + 1
|
|
||||||
} else {
|
|
||||||
j = h
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Swap values until data[a] reaches the position before i.
|
|
||||||
for k := a; k < i-1; k++ {
|
|
||||||
data[k], data[k+1] = data[k+1], data[k]
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Avoid unnecessary recursions of symMerge
|
|
||||||
// by direct insertion of data[m] into data[a:m]
|
|
||||||
// if data[m:b] only contains one element.
|
|
||||||
if b-m == 1 {
|
|
||||||
// Use binary search to find the lowest index i
|
|
||||||
// such that data[i] > data[m] for a <= i < m.
|
|
||||||
// Exit the search loop with i == m in case no such index exists.
|
|
||||||
i := a
|
|
||||||
j := m
|
|
||||||
for i < j {
|
|
||||||
h := int(uint(i+j) >> 1)
|
|
||||||
if !cmpLess(data[m], data[h]) {
|
|
||||||
i = h + 1
|
|
||||||
} else {
|
|
||||||
j = h
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Swap values until data[m] reaches the position i.
|
|
||||||
for k := m; k > i; k-- {
|
|
||||||
data[k], data[k-1] = data[k-1], data[k]
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
mid := int(uint(a+b) >> 1)
|
|
||||||
n := mid + m
|
|
||||||
var start, r int
|
|
||||||
if m > mid {
|
|
||||||
start = n - b
|
|
||||||
r = mid
|
|
||||||
} else {
|
|
||||||
start = a
|
|
||||||
r = m
|
|
||||||
}
|
|
||||||
p := n - 1
|
|
||||||
|
|
||||||
for start < r {
|
|
||||||
c := int(uint(start+r) >> 1)
|
|
||||||
if !cmpLess(data[p-c], data[c]) {
|
|
||||||
start = c + 1
|
|
||||||
} else {
|
|
||||||
r = c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
end := n - start
|
|
||||||
if start < m && m < end {
|
|
||||||
rotateOrdered(data, start, m, end)
|
|
||||||
}
|
|
||||||
if a < start && start < mid {
|
|
||||||
symMergeOrdered(data, a, start, mid)
|
|
||||||
}
|
|
||||||
if mid < end && end < b {
|
|
||||||
symMergeOrdered(data, mid, end, b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rotateOrdered rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data:
|
|
||||||
// Data of the form 'x u v y' is changed to 'x v u y'.
|
|
||||||
// rotate performs at most b-a many calls to data.Swap,
|
|
||||||
// and it assumes non-degenerate arguments: a < m && m < b.
|
|
||||||
func rotateOrdered[E constraints.Ordered](data []E, a, m, b int) {
|
|
||||||
i := m - a
|
|
||||||
j := b - m
|
|
||||||
|
|
||||||
for i != j {
|
|
||||||
if i > j {
|
|
||||||
swapRangeOrdered(data, m-i, m, j)
|
|
||||||
i -= j
|
|
||||||
} else {
|
|
||||||
swapRangeOrdered(data, m-i, m+j-i, i)
|
|
||||||
j -= i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// i == j
|
|
||||||
swapRangeOrdered(data, m-i, m, i)
|
|
||||||
}
|
|
3
vendor/golang.org/x/sys/unix/ztypes_linux.go
generated
vendored
3
vendor/golang.org/x/sys/unix/ztypes_linux.go
generated
vendored
@ -3807,6 +3807,9 @@ const (
|
|||||||
ETHTOOL_MSG_PSE_GET_REPLY = 0x25
|
ETHTOOL_MSG_PSE_GET_REPLY = 0x25
|
||||||
ETHTOOL_MSG_RSS_GET_REPLY = 0x26
|
ETHTOOL_MSG_RSS_GET_REPLY = 0x26
|
||||||
ETHTOOL_MSG_KERNEL_MAX = 0x2b
|
ETHTOOL_MSG_KERNEL_MAX = 0x2b
|
||||||
|
ETHTOOL_FLAG_COMPACT_BITSETS = 0x1
|
||||||
|
ETHTOOL_FLAG_OMIT_REPLY = 0x2
|
||||||
|
ETHTOOL_FLAG_STATS = 0x4
|
||||||
ETHTOOL_A_HEADER_UNSPEC = 0x0
|
ETHTOOL_A_HEADER_UNSPEC = 0x0
|
||||||
ETHTOOL_A_HEADER_DEV_INDEX = 0x1
|
ETHTOOL_A_HEADER_DEV_INDEX = 0x1
|
||||||
ETHTOOL_A_HEADER_DEV_NAME = 0x2
|
ETHTOOL_A_HEADER_DEV_NAME = 0x2
|
||||||
|
44
vendor/golang.org/x/sys/windows/types_windows.go
generated
vendored
44
vendor/golang.org/x/sys/windows/types_windows.go
generated
vendored
@ -2031,6 +2031,50 @@ const (
|
|||||||
IF_TYPE_IEEE1394 = 144
|
IF_TYPE_IEEE1394 = 144
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Enum NL_PREFIX_ORIGIN for [IpAdapterUnicastAddress], see
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_prefix_origin
|
||||||
|
const (
|
||||||
|
IpPrefixOriginOther = 0
|
||||||
|
IpPrefixOriginManual = 1
|
||||||
|
IpPrefixOriginWellKnown = 2
|
||||||
|
IpPrefixOriginDhcp = 3
|
||||||
|
IpPrefixOriginRouterAdvertisement = 4
|
||||||
|
IpPrefixOriginUnchanged = 1 << 4
|
||||||
|
)
|
||||||
|
|
||||||
|
// Enum NL_SUFFIX_ORIGIN for [IpAdapterUnicastAddress], see
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_suffix_origin
|
||||||
|
const (
|
||||||
|
NlsoOther = 0
|
||||||
|
NlsoManual = 1
|
||||||
|
NlsoWellKnown = 2
|
||||||
|
NlsoDhcp = 3
|
||||||
|
NlsoLinkLayerAddress = 4
|
||||||
|
NlsoRandom = 5
|
||||||
|
IpSuffixOriginOther = 0
|
||||||
|
IpSuffixOriginManual = 1
|
||||||
|
IpSuffixOriginWellKnown = 2
|
||||||
|
IpSuffixOriginDhcp = 3
|
||||||
|
IpSuffixOriginLinkLayerAddress = 4
|
||||||
|
IpSuffixOriginRandom = 5
|
||||||
|
IpSuffixOriginUnchanged = 1 << 4
|
||||||
|
)
|
||||||
|
|
||||||
|
// Enum NL_DAD_STATE for [IpAdapterUnicastAddress], see
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_dad_state
|
||||||
|
const (
|
||||||
|
NldsInvalid = 0
|
||||||
|
NldsTentative = 1
|
||||||
|
NldsDuplicate = 2
|
||||||
|
NldsDeprecated = 3
|
||||||
|
NldsPreferred = 4
|
||||||
|
IpDadStateInvalid = 0
|
||||||
|
IpDadStateTentative = 1
|
||||||
|
IpDadStateDuplicate = 2
|
||||||
|
IpDadStateDeprecated = 3
|
||||||
|
IpDadStatePreferred = 4
|
||||||
|
)
|
||||||
|
|
||||||
type SocketAddress struct {
|
type SocketAddress struct {
|
||||||
Sockaddr *syscall.RawSockaddrAny
|
Sockaddr *syscall.RawSockaddrAny
|
||||||
SockaddrLength int32
|
SockaddrLength int32
|
||||||
|
18
vendor/modules.txt
vendored
18
vendor/modules.txt
vendored
@ -102,8 +102,8 @@ github.com/google/go-cmp/cmp/internal/diff
|
|||||||
github.com/google/go-cmp/cmp/internal/flags
|
github.com/google/go-cmp/cmp/internal/flags
|
||||||
github.com/google/go-cmp/cmp/internal/function
|
github.com/google/go-cmp/cmp/internal/function
|
||||||
github.com/google/go-cmp/cmp/internal/value
|
github.com/google/go-cmp/cmp/internal/value
|
||||||
# github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8
|
# github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5
|
||||||
## explicit; go 1.19
|
## explicit; go 1.22
|
||||||
github.com/google/pprof/profile
|
github.com/google/pprof/profile
|
||||||
# github.com/mattn/go-shellwords v1.0.12
|
# github.com/mattn/go-shellwords v1.0.12
|
||||||
## explicit; go 1.13
|
## explicit; go 1.13
|
||||||
@ -114,8 +114,8 @@ github.com/networkplumbing/go-nft/nft
|
|||||||
github.com/networkplumbing/go-nft/nft/config
|
github.com/networkplumbing/go-nft/nft/config
|
||||||
github.com/networkplumbing/go-nft/nft/exec
|
github.com/networkplumbing/go-nft/nft/exec
|
||||||
github.com/networkplumbing/go-nft/nft/schema
|
github.com/networkplumbing/go-nft/nft/schema
|
||||||
# github.com/onsi/ginkgo/v2 v2.20.1
|
# github.com/onsi/ginkgo/v2 v2.20.2
|
||||||
## explicit; go 1.20
|
## explicit; go 1.22
|
||||||
github.com/onsi/ginkgo/v2
|
github.com/onsi/ginkgo/v2
|
||||||
github.com/onsi/ginkgo/v2/config
|
github.com/onsi/ginkgo/v2/config
|
||||||
github.com/onsi/ginkgo/v2/formatter
|
github.com/onsi/ginkgo/v2/formatter
|
||||||
@ -136,8 +136,8 @@ github.com/onsi/ginkgo/v2/internal/parallel_support
|
|||||||
github.com/onsi/ginkgo/v2/internal/testingtproxy
|
github.com/onsi/ginkgo/v2/internal/testingtproxy
|
||||||
github.com/onsi/ginkgo/v2/reporters
|
github.com/onsi/ginkgo/v2/reporters
|
||||||
github.com/onsi/ginkgo/v2/types
|
github.com/onsi/ginkgo/v2/types
|
||||||
# github.com/onsi/gomega v1.34.1
|
# github.com/onsi/gomega v1.34.2
|
||||||
## explicit; go 1.20
|
## explicit; go 1.22
|
||||||
github.com/onsi/gomega
|
github.com/onsi/gomega
|
||||||
github.com/onsi/gomega/format
|
github.com/onsi/gomega/format
|
||||||
github.com/onsi/gomega/gbytes
|
github.com/onsi/gomega/gbytes
|
||||||
@ -177,10 +177,6 @@ go.opencensus.io/internal
|
|||||||
go.opencensus.io/trace
|
go.opencensus.io/trace
|
||||||
go.opencensus.io/trace/internal
|
go.opencensus.io/trace/internal
|
||||||
go.opencensus.io/trace/tracestate
|
go.opencensus.io/trace/tracestate
|
||||||
# golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
|
|
||||||
## explicit; go 1.20
|
|
||||||
golang.org/x/exp/constraints
|
|
||||||
golang.org/x/exp/slices
|
|
||||||
# golang.org/x/net v0.28.0
|
# golang.org/x/net v0.28.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
golang.org/x/net/bpf
|
golang.org/x/net/bpf
|
||||||
@ -191,7 +187,7 @@ golang.org/x/net/html/charset
|
|||||||
golang.org/x/net/internal/iana
|
golang.org/x/net/internal/iana
|
||||||
golang.org/x/net/internal/socket
|
golang.org/x/net/internal/socket
|
||||||
golang.org/x/net/ipv4
|
golang.org/x/net/ipv4
|
||||||
# golang.org/x/sys v0.23.0
|
# golang.org/x/sys v0.24.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
golang.org/x/sys/unix
|
golang.org/x/sys/unix
|
||||||
golang.org/x/sys/windows
|
golang.org/x/sys/windows
|
||||||
|
Loading…
x
Reference in New Issue
Block a user