rebase: bump the github-dependencies group with 3 updates

Bumps the github-dependencies group with 3 updates: [github.com/IBM/keyprotect-go-client](https://github.com/IBM/keyprotect-go-client), [github.com/aws/aws-sdk-go](https://github.com/aws/aws-sdk-go) and [github.com/onsi/gomega](https://github.com/onsi/gomega).


Updates `github.com/IBM/keyprotect-go-client` from 0.14.3 to 0.15.1
- [Release notes](https://github.com/IBM/keyprotect-go-client/releases)
- [Changelog](https://github.com/IBM/keyprotect-go-client/blob/master/CHANGELOG.md)
- [Commits](https://github.com/IBM/keyprotect-go-client/compare/v0.14.3...v0.15.1)

Updates `github.com/aws/aws-sdk-go` from 1.55.4 to 1.55.5
- [Release notes](https://github.com/aws/aws-sdk-go/releases)
- [Commits](https://github.com/aws/aws-sdk-go/compare/v1.55.4...v1.55.5)

Updates `github.com/onsi/gomega` from 1.34.0 to 1.34.1
- [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.0...v1.34.1)

---
updated-dependencies:
- dependency-name: github.com/IBM/keyprotect-go-client
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-dependencies
- dependency-name: github.com/aws/aws-sdk-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-dependencies
- dependency-name: github.com/onsi/gomega
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot] 2024-08-06 14:39:44 +00:00 committed by mergify[bot]
parent ee503fae54
commit dabf3c4099
17 changed files with 696 additions and 251 deletions

10
go.mod
View File

@ -3,8 +3,8 @@ module github.com/ceph/ceph-csi
go 1.22.0 go 1.22.0
require ( require (
github.com/IBM/keyprotect-go-client v0.14.3 github.com/IBM/keyprotect-go-client v0.15.1
github.com/aws/aws-sdk-go v1.55.4 github.com/aws/aws-sdk-go v1.55.5
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 github.com/aws/aws-sdk-go-v2/service/sts v1.30.3
github.com/ceph/ceph-csi/api v0.0.0-00010101000000-000000000000 github.com/ceph/ceph-csi/api v0.0.0-00010101000000-000000000000
github.com/ceph/go-ceph v0.28.0 github.com/ceph/go-ceph v0.28.0
@ -21,7 +21,7 @@ require (
github.com/kubernetes-csi/external-snapshotter/client/v7 v7.0.0 github.com/kubernetes-csi/external-snapshotter/client/v7 v7.0.0
github.com/libopenstorage/secrets v0.0.0-20231011182615-5f4b25ceede1 github.com/libopenstorage/secrets v0.0.0-20231011182615-5f4b25ceede1
github.com/onsi/ginkgo/v2 v2.19.1 github.com/onsi/ginkgo/v2 v2.19.1
github.com/onsi/gomega v1.34.0 github.com/onsi/gomega v1.34.1
github.com/pkg/xattr v0.4.10 github.com/pkg/xattr v0.4.10
github.com/prometheus/client_golang v1.19.1 github.com/prometheus/client_golang v1.19.1
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.9.0
@ -156,13 +156,13 @@ require (
go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.26.0 // indirect go.uber.org/zap v1.26.0 // indirect
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 // indirect golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/oauth2 v0.20.0 // indirect golang.org/x/oauth2 v0.20.0 // indirect
golang.org/x/sync v0.7.0 // indirect golang.org/x/sync v0.7.0 // indirect
golang.org/x/term v0.22.0 // indirect golang.org/x/term v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect golang.org/x/text v0.16.0 // indirect
golang.org/x/time v0.3.0 // indirect golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.org/x/tools v0.23.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect

32
go.sum
View File

@ -786,8 +786,8 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/IBM/keyprotect-go-client v0.5.1/go.mod h1:5TwDM/4FRJq1ZOlwQL1xFahLWQ3TveR88VmL1u3njyI= github.com/IBM/keyprotect-go-client v0.5.1/go.mod h1:5TwDM/4FRJq1ZOlwQL1xFahLWQ3TveR88VmL1u3njyI=
github.com/IBM/keyprotect-go-client v0.14.3 h1:OUKzRclUqY4zIOclx22b1rrbtrY13y5FyADRoq64AQw= github.com/IBM/keyprotect-go-client v0.15.1 h1:m4qzqF5zOumRxKZ8s7vtK7A/UV/D278L8xpRG+WgT0s=
github.com/IBM/keyprotect-go-client v0.14.3/go.mod h1:cAt714Vnwnd03mmkBHHSJlDNRVthdRmJB6RePd4/B8Q= github.com/IBM/keyprotect-go-client v0.15.1/go.mod h1:asXtHwL/4uCHA221Vd/7SkXEi2pcRHDzPyyksc1DthE=
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
@ -828,8 +828,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/aws/aws-sdk-go v1.44.164/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go v1.44.164/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.55.4 h1:u7sFWQQs5ivGuYvCxi7gJI8nN/P9Dq04huLaw39a4lg= github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU=
github.com/aws/aws-sdk-go v1.55.4/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
github.com/aws/aws-sdk-go-v2 v1.30.3 h1:jUeBtG0Ih+ZIFH0F4UkmL9w3cSpaMv9tYYDbzILP8dY= github.com/aws/aws-sdk-go-v2 v1.30.3 h1:jUeBtG0Ih+ZIFH0F4UkmL9w3cSpaMv9tYYDbzILP8dY=
github.com/aws/aws-sdk-go-v2 v1.30.3/go.mod h1:nIQjQVp5sfpQcTc9mPSr1B0PaWK5ByX9MOoDadSN4lc= github.com/aws/aws-sdk-go-v2 v1.30.3/go.mod h1:nIQjQVp5sfpQcTc9mPSr1B0PaWK5ByX9MOoDadSN4lc=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 h1:SoNJ4RlFEQEbtDcCEt+QG56MY4fm4W8rYirAmq+/DdU= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 h1:SoNJ4RlFEQEbtDcCEt+QG56MY4fm4W8rYirAmq+/DdU=
@ -961,6 +961,7 @@ github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi
github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
@ -1230,7 +1231,6 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-retryablehttp v0.6.2/go.mod h1:gEx6HMUGxYYhJScX7W1Il64m6cc2C1mDaW3NQ9sY1FY= github.com/hashicorp/go-retryablehttp v0.6.2/go.mod h1:gEx6HMUGxYYhJScX7W1Il64m6cc2C1mDaW3NQ9sY1FY=
github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
@ -1349,6 +1349,8 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
@ -1357,6 +1359,7 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
@ -1452,8 +1455,8 @@ github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3ev
github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk= github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk=
github.com/onsi/gomega v1.34.0 h1:eSSPsPNp6ZpsG8X1OVmOTxig+CblTc4AxpPBykhe2Os= github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
github.com/onsi/gomega v1.34.0/go.mod h1:MIKI8c+f+QLWk+hxbePD4i0LMJSExPaZOVfkoex4cAo= github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
@ -1569,6 +1572,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@ -1576,6 +1580,7 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
@ -1732,8 +1737,9 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 h1:tnebWN09GYg9OLPss1KXj8txwZc6X6uMr6VFdcGNbHw=
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
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/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@ -1784,8 +1790,8 @@ golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -1992,6 +1998,7 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -2035,6 +2042,7 @@ golang.org/x/sys v0.15.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.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ= golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ=
@ -2177,8 +2185,8 @@ golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -1,5 +1,5 @@
[bumpversion] [bumpversion]
current_version = 0.9.2 current_version = 0.15.1
commit = True commit = True
message = Update version {current_version} -> {new_version} [skip ci] message = Update version {current_version} -> {new_version} [skip ci]

View File

@ -1,3 +1,23 @@
## [0.15.1](https://github.com/IBM/keyprotect-go-client/compare/v0.15.0...v0.15.1) (2024-08-01)
### Bug Fixes
* **build:** upgrade dependencies ([#136](https://github.com/IBM/keyprotect-go-client/issues/136)) ([b0d13e2](https://github.com/IBM/keyprotect-go-client/commit/b0d13e27d42106e3be6153634228cdfb380514ec))
# [0.15.0](https://github.com/IBM/keyprotect-go-client/compare/v0.14.3...v0.15.0) (2024-08-01)
### Features
* **build:** re-sync release version ([#135](https://github.com/IBM/keyprotect-go-client/issues/135)) ([00a6c59](https://github.com/IBM/keyprotect-go-client/commit/00a6c59d7174800a0f2ff7be2c3966580b550671))
* **build:** upgrade dependencies ([#134](https://github.com/IBM/keyprotect-go-client/issues/134)) ([e621973](https://github.com/IBM/keyprotect-go-client/commit/e621973855455b4290afe46603f67d3da5be885a))
### Reverts
* Revert "upgrade dependencies ([#130](https://github.com/IBM/keyprotect-go-client/issues/130))" ([#133](https://github.com/IBM/keyprotect-go-client/issues/133)) ([2a3845f](https://github.com/IBM/keyprotect-go-client/commit/2a3845fb9e80698bebc0d983e230427a57d90f36))
## [0.9.2](https://github.com/IBM/keyprotect-go-client/compare/v0.9.1...v0.9.2) (2022-12-14) ## [0.9.2](https://github.com/IBM/keyprotect-go-client/compare/v0.9.1...v0.9.2) (2022-12-14)

View File

@ -1,4 +1,4 @@
# IBM Cloud Go SDK # IBM Cloud Go SDK Version 0.15.1
# keyprotect-go-client # keyprotect-go-client

View File

@ -9503,6 +9503,12 @@ var awsPartition = partition{
endpointKey{ endpointKey{
Region: "eu-central-1", Region: "eu-central-1",
}: endpoint{}, }: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-2",
}: endpoint{},
endpointKey{ endpointKey{
Region: "eu-west-1", Region: "eu-west-1",
}: endpoint{}, }: endpoint{},

View File

@ -5,4 +5,4 @@ package aws
const SDKName = "aws-sdk-go" const SDKName = "aws-sdk-go"
// SDKVersion is the version of this SDK // SDKVersion is the version of this SDK
const SDKVersion = "1.55.4" const SDKVersion = "1.55.5"

View File

@ -1,3 +1,8 @@
## 1.34.1
### Maintenance
- Use slices from exp/slices to keep golang 1.20 compat [5e71dcd]
## 1.34.0 ## 1.34.0
### Features ### Features

View File

@ -22,7 +22,7 @@ import (
"github.com/onsi/gomega/types" "github.com/onsi/gomega/types"
) )
const GOMEGA_VERSION = "1.34.0" const GOMEGA_VERSION = "1.34.1"
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().

View File

@ -1,7 +1,7 @@
package bipartitegraph package bipartitegraph
import ( import (
"slices" "golang.org/x/exp/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"

4
vendor/golang.org/x/exp/LICENSE generated vendored
View File

@ -1,4 +1,4 @@
Copyright (c) 2009 The Go Authors. All rights reserved. Copyright 2009 The Go Authors.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are modification, are permitted provided that the following conditions are
@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
copyright notice, this list of conditions and the following disclaimer copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the in the documentation and/or other materials provided with the
distribution. distribution.
* Neither the name of Google Inc. nor the names of its * Neither the name of Google LLC nor the names of its
contributors may be used to endorse or promote products derived from contributors may be used to endorse or promote products derived from
this software without specific prior written permission. this software without specific prior written permission.

44
vendor/golang.org/x/exp/slices/cmp.go generated vendored Normal file
View File

@ -0,0 +1,44 @@
// 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
}

View File

@ -3,23 +3,20 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Package slices defines various functions useful with slices of any type. // Package slices defines various functions useful with slices of any type.
// Unless otherwise specified, these functions all apply to the elements
// of a slice at index 0 <= i < len(s).
//
// Note that the less function in IsSortedFunc, SortFunc, SortStableFunc requires a
// strict weak ordering (https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings),
// or the sorting may fail to sort correctly. A common case is when sorting slices of
// floating-point numbers containing NaN values.
package slices package slices
import "golang.org/x/exp/constraints" import (
"unsafe"
"golang.org/x/exp/constraints"
)
// Equal reports whether two slices are equal: the same length and all // Equal reports whether two slices are equal: the same length and all
// elements equal. If the lengths are different, Equal returns false. // elements equal. If the lengths are different, Equal returns false.
// Otherwise, the elements are compared in increasing index order, and the // Otherwise, the elements are compared in increasing index order, and the
// comparison stops at the first unequal pair. // comparison stops at the first unequal pair.
// Floating point NaNs are not considered equal. // Floating point NaNs are not considered equal.
func Equal[E comparable](s1, s2 []E) bool { func Equal[S ~[]E, E comparable](s1, s2 S) bool {
if len(s1) != len(s2) { if len(s1) != len(s2) {
return false return false
} }
@ -31,12 +28,12 @@ func Equal[E comparable](s1, s2 []E) bool {
return true return true
} }
// EqualFunc reports whether two slices are equal using a comparison // EqualFunc reports whether two slices are equal using an equality
// function on each pair of elements. If the lengths are different, // function on each pair of elements. If the lengths are different,
// EqualFunc returns false. Otherwise, the elements are compared in // EqualFunc returns false. Otherwise, the elements are compared in
// increasing index order, and the comparison stops at the first index // increasing index order, and the comparison stops at the first index
// for which eq returns false. // for which eq returns false.
func EqualFunc[E1, E2 any](s1 []E1, s2 []E2, eq func(E1, E2) bool) bool { func EqualFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) bool) bool {
if len(s1) != len(s2) { if len(s1) != len(s2) {
return false return false
} }
@ -49,45 +46,37 @@ func EqualFunc[E1, E2 any](s1 []E1, s2 []E2, eq func(E1, E2) bool) bool {
return true return true
} }
// Compare compares the elements of s1 and s2. // Compare compares the elements of s1 and s2, using [cmp.Compare] on each pair
// The elements are compared sequentially, starting at index 0, // of elements. The elements are compared sequentially, starting at index 0,
// until one element is not equal to the other. // until one element is not equal to the other.
// The result of comparing the first non-matching elements is returned. // 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 // If both slices are equal until one of them ends, the shorter slice is
// considered less than the longer one. // considered less than the longer one.
// The result is 0 if s1 == s2, -1 if s1 < s2, and +1 if s1 > s2. // The result is 0 if s1 == s2, -1 if s1 < s2, and +1 if s1 > s2.
// Comparisons involving floating point NaNs are ignored. func Compare[S ~[]E, E constraints.Ordered](s1, s2 S) int {
func Compare[E constraints.Ordered](s1, s2 []E) int {
s2len := len(s2)
for i, v1 := range s1 { for i, v1 := range s1 {
if i >= s2len { if i >= len(s2) {
return +1 return +1
} }
v2 := s2[i] v2 := s2[i]
switch { if c := cmpCompare(v1, v2); c != 0 {
case v1 < v2: return c
return -1
case v1 > v2:
return +1
} }
} }
if len(s1) < s2len { if len(s1) < len(s2) {
return -1 return -1
} }
return 0 return 0
} }
// CompareFunc is like Compare but uses a comparison function // CompareFunc is like [Compare] but uses a custom comparison function on each
// on each pair of elements. The elements are compared in increasing // pair of elements.
// index order, and the comparisons stop after the first time cmp
// returns non-zero.
// The result is the first non-zero result of cmp; if cmp always // 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), // returns 0 the result is 0 if len(s1) == len(s2), -1 if len(s1) < len(s2),
// and +1 if len(s1) > len(s2). // and +1 if len(s1) > len(s2).
func CompareFunc[E1, E2 any](s1 []E1, s2 []E2, cmp func(E1, E2) int) int { func CompareFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, cmp func(E1, E2) int) int {
s2len := len(s2)
for i, v1 := range s1 { for i, v1 := range s1 {
if i >= s2len { if i >= len(s2) {
return +1 return +1
} }
v2 := s2[i] v2 := s2[i]
@ -95,7 +84,7 @@ func CompareFunc[E1, E2 any](s1 []E1, s2 []E2, cmp func(E1, E2) int) int {
return c return c
} }
} }
if len(s1) < s2len { if len(s1) < len(s2) {
return -1 return -1
} }
return 0 return 0
@ -103,9 +92,9 @@ func CompareFunc[E1, E2 any](s1 []E1, s2 []E2, cmp func(E1, E2) int) int {
// Index returns the index of the first occurrence of v in s, // Index returns the index of the first occurrence of v in s,
// or -1 if not present. // or -1 if not present.
func Index[E comparable](s []E, v E) int { func Index[S ~[]E, E comparable](s S, v E) int {
for i, vs := range s { for i := range s {
if v == vs { if v == s[i] {
return i return i
} }
} }
@ -114,9 +103,9 @@ func Index[E comparable](s []E, v E) int {
// IndexFunc returns the first index i satisfying f(s[i]), // IndexFunc returns the first index i satisfying f(s[i]),
// or -1 if none do. // or -1 if none do.
func IndexFunc[E any](s []E, f func(E) bool) int { func IndexFunc[S ~[]E, E any](s S, f func(E) bool) int {
for i, v := range s { for i := range s {
if f(v) { if f(s[i]) {
return i return i
} }
} }
@ -124,42 +113,237 @@ func IndexFunc[E any](s []E, f func(E) bool) int {
} }
// Contains reports whether v is present in s. // Contains reports whether v is present in s.
func Contains[E comparable](s []E, v E) bool { func Contains[S ~[]E, E comparable](s S, v E) bool {
return Index(s, v) >= 0 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, // Insert inserts the values v... into s at index i,
// returning the modified slice. // returning the modified slice.
// In the returned slice r, r[i] == v[0]. // 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. // Insert panics if i is out of range.
// This function is O(len(s) + len(v)). // This function is O(len(s) + len(v)).
func Insert[S ~[]E, E any](s S, i int, v ...E) S { func Insert[S ~[]E, E any](s S, i int, v ...E) S {
tot := len(s) + len(v) m := len(v)
if tot <= cap(s) { if m == 0 {
s2 := s[:tot] return s
copy(s2[i+len(v):], s[i:]) }
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:], v)
copy(s2[i+m:], s[i:])
return s2 return s2
} }
s2 := make(S, tot) s = s[:n+m]
copy(s2, s[:i])
copy(s2[i:], v) // before:
copy(s2[i+len(v):], s[i:]) // s: aaaaaaaabbbbccccccccdddd
return s2 // ^ ^ ^ ^
// 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 removes the elements s[i:j] from s, returning the modified slice.
// Delete panics if s[i:j] is not a valid slice of s. // Delete panics if j > len(s) or s[i:j] is not a valid slice of s.
// Delete modifies the contents of the slice s; it does not create a new slice. // Delete is O(len(s)-i), so if many items must be deleted, it is better to
// Delete is O(len(s)-j), 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. // make a single call deleting them all together than to delete one at a time.
// Delete might not modify the elements s[len(s)-(j-i):len(s)]. If those // Delete zeroes the elements s[len(s)-(j-i):len(s)].
// elements contain pointers you might consider zeroing those elements so that
// objects they reference can be garbage collected.
func Delete[S ~[]E, E any](s S, i, j int) S { func Delete[S ~[]E, E any](s S, i, j int) S {
_ = s[i:j] // bounds check _ = s[i:j:len(s)] // bounds check
return append(s[:i], s[j:]...) 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. // Clone returns a copy of the slice.
@ -174,50 +358,158 @@ func Clone[S ~[]E, E any](s S) S {
// Compact replaces consecutive runs of equal elements with a single copy. // Compact replaces consecutive runs of equal elements with a single copy.
// This is like the uniq command found on Unix. // This is like the uniq command found on Unix.
// Compact modifies the contents of the slice s; it does not create a new slice. // 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 { func Compact[S ~[]E, E comparable](s S) S {
if len(s) == 0 { if len(s) < 2 {
return s return s
} }
i := 1 i := 1
last := s[0] for k := 1; k < len(s); k++ {
for _, v := range s[1:] { if s[k] != s[k-1] {
if v != last { if i != k {
s[i] = v s[i] = s[k]
}
i++ i++
last = v
} }
} }
clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
return s[:i] return s[:i]
} }
// CompactFunc is like Compact but uses a comparison function. // 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 { func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
if len(s) == 0 { if len(s) < 2 {
return s return s
} }
i := 1 i := 1
last := s[0] for k := 1; k < len(s); k++ {
for _, v := range s[1:] { if !eq(s[k], s[k-1]) {
if !eq(v, last) { if i != k {
s[i] = v s[i] = s[k]
}
i++ i++
last = v
} }
} }
clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
return s[:i] return s[:i]
} }
// Grow increases the slice's capacity, if necessary, to guarantee space for // 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 // another n elements. After Grow(n), at least n elements can be appended
// to the slice without another allocation. Grow may modify elements of the // to the slice without another allocation. If n is negative or too large to
// slice between the length and the capacity. If n is negative or too large to
// allocate the memory, Grow panics. // allocate the memory, Grow panics.
func Grow[S ~[]E, E any](s S, n int) S { func Grow[S ~[]E, E any](s S, n int) S {
return append(s, make(S, n)...)[:len(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)]. // Clip removes unused capacity from the slice, returning s[:len(s):len(s)].
func Clip[S ~[]E, E any](s S) S { func Clip[S ~[]E, E any](s S) S {
return s[:len(s):len(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]
}
}

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:generate go run $GOROOT/src/sort/gen_sort_variants.go -exp
package slices package slices
import ( import (
@ -11,97 +13,159 @@ import (
) )
// Sort sorts a slice of any ordered type in ascending order. // Sort sorts a slice of any ordered type in ascending order.
// Sort may fail to sort correctly when sorting slices of floating-point // When sorting floating-point numbers, NaNs are ordered before other values.
// numbers containing Not-a-number (NaN) values. func Sort[S ~[]E, E constraints.Ordered](x S) {
// Use slices.SortFunc(x, func(a, b float64) bool {return a < b || (math.IsNaN(a) && !math.IsNaN(b))})
// instead if the input may contain NaNs.
func Sort[E constraints.Ordered](x []E) {
n := len(x) n := len(x)
pdqsortOrdered(x, 0, n, bits.Len(uint(n))) pdqsortOrdered(x, 0, n, bits.Len(uint(n)))
} }
// SortFunc sorts the slice x in ascending order as determined by the less function. // SortFunc sorts the slice x in ascending order as determined by the cmp
// This sort is not guaranteed to be stable. // 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 less is a strict weak ordering. // SortFunc requires that cmp is a strict weak ordering.
// See https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings. // See https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings.
func SortFunc[E any](x []E, less func(a, b E) bool) { // 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) n := len(x)
pdqsortLessFunc(x, 0, n, bits.Len(uint(n)), less) pdqsortCmpFunc(x, 0, n, bits.Len(uint(n)), cmp)
} }
// SortStable sorts the slice x while keeping the original order of equal // SortStableFunc sorts the slice x while keeping the original order of equal
// elements, using less to compare elements. // elements, using cmp to compare elements in the same way as [SortFunc].
func SortStableFunc[E any](x []E, less func(a, b E) bool) { func SortStableFunc[S ~[]E, E any](x S, cmp func(a, b E) int) {
stableLessFunc(x, len(x), less) stableCmpFunc(x, len(x), cmp)
} }
// IsSorted reports whether x is sorted in ascending order. // IsSorted reports whether x is sorted in ascending order.
func IsSorted[E constraints.Ordered](x []E) bool { func IsSorted[S ~[]E, E constraints.Ordered](x S) bool {
for i := len(x) - 1; i > 0; i-- { for i := len(x) - 1; i > 0; i-- {
if x[i] < x[i-1] { if cmpLess(x[i], x[i-1]) {
return false return false
} }
} }
return true return true
} }
// IsSortedFunc reports whether x is sorted in ascending order, with less as the // IsSortedFunc reports whether x is sorted in ascending order, with cmp as the
// comparison function. // comparison function as defined by [SortFunc].
func IsSortedFunc[E any](x []E, less func(a, b E) bool) bool { func IsSortedFunc[S ~[]E, E any](x S, cmp func(a, b E) int) bool {
for i := len(x) - 1; i > 0; i-- { for i := len(x) - 1; i > 0; i-- {
if less(x[i], x[i-1]) { if cmp(x[i], x[i-1]) < 0 {
return false return false
} }
} }
return true 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 // 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 // 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 // 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. // in the slice. The slice must be sorted in increasing order.
func BinarySearch[E constraints.Ordered](x []E, target E) (int, bool) { func BinarySearch[S ~[]E, E constraints.Ordered](x S, target E) (int, bool) {
// search returns the leftmost position where f returns true, or len(x) if f // Inlining is faster than calling BinarySearchFunc with a lambda.
// returns false for all x. This is the insertion position for target in x, n := len(x)
// and could point to an element that's either == target or not. // Define x[-1] < target and x[n] >= target.
pos := search(len(x), func(i int) bool { return x[i] >= target }) // Invariant: x[i-1] < target, x[j] >= target.
if pos >= len(x) || x[pos] != target {
return pos, false
} else {
return pos, true
}
}
// 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(a, b) is expected to return an integer comparing the two
// parameters: 0 if a == b, a negative number if a < b and a positive number if
// a > b.
func BinarySearchFunc[E any](x []E, target E, cmp func(E, E) int) (int, bool) {
pos := search(len(x), func(i int) bool { return cmp(x[i], target) >= 0 })
if pos >= len(x) || cmp(x[pos], target) != 0 {
return pos, false
} else {
return pos, true
}
}
func search(n int, f func(int) bool) int {
// Define f(-1) == false and f(n) == true.
// Invariant: f(i-1) == false, f(j) == true.
i, j := 0, n i, j := 0, n
for i < j { for i < j {
h := int(uint(i+j) >> 1) // avoid overflow when computing h h := int(uint(i+j) >> 1) // avoid overflow when computing h
// i ≤ h < j // i ≤ h < j
if !f(h) { if cmpLess(x[h], target) {
i = h + 1 // preserves f(i-1) == false i = h + 1 // preserves x[i-1] < target
} else { } else {
j = h // preserves f(j) == true j = h // preserves x[j] >= target
} }
} }
// i == j, f(i-1) == false, and f(j) (= f(i)) == true => answer is i. // i == j, x[i-1] < target, and x[j] (= x[i]) >= target => answer is i.
return 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 type sortedHint int // hint for pdqsort when choosing the pivot
@ -125,3 +189,9 @@ func (r *xorshift) Next() uint64 {
func nextPowerOfTwo(length int) uint { func nextPowerOfTwo(length int) uint {
return 1 << bits.Len(uint(length)) 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
}

View File

@ -6,28 +6,28 @@
package slices package slices
// insertionSortLessFunc sorts data[a:b] using insertion sort. // insertionSortCmpFunc sorts data[a:b] using insertion sort.
func insertionSortLessFunc[E any](data []E, a, b int, less func(a, b E) bool) { func insertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) {
for i := a + 1; i < b; i++ { for i := a + 1; i < b; i++ {
for j := i; j > a && less(data[j], data[j-1]); j-- { for j := i; j > a && (cmp(data[j], data[j-1]) < 0); j-- {
data[j], data[j-1] = data[j-1], data[j] data[j], data[j-1] = data[j-1], data[j]
} }
} }
} }
// siftDownLessFunc implements the heap property on data[lo:hi]. // siftDownCmpFunc implements the heap property on data[lo:hi].
// first is an offset into the array where the root of the heap lies. // first is an offset into the array where the root of the heap lies.
func siftDownLessFunc[E any](data []E, lo, hi, first int, less func(a, b E) bool) { func siftDownCmpFunc[E any](data []E, lo, hi, first int, cmp func(a, b E) int) {
root := lo root := lo
for { for {
child := 2*root + 1 child := 2*root + 1
if child >= hi { if child >= hi {
break break
} }
if child+1 < hi && less(data[first+child], data[first+child+1]) { if child+1 < hi && (cmp(data[first+child], data[first+child+1]) < 0) {
child++ child++
} }
if !less(data[first+root], data[first+child]) { if !(cmp(data[first+root], data[first+child]) < 0) {
return return
} }
data[first+root], data[first+child] = data[first+child], data[first+root] data[first+root], data[first+child] = data[first+child], data[first+root]
@ -35,30 +35,30 @@ func siftDownLessFunc[E any](data []E, lo, hi, first int, less func(a, b E) bool
} }
} }
func heapSortLessFunc[E any](data []E, a, b int, less func(a, b E) bool) { func heapSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) {
first := a first := a
lo := 0 lo := 0
hi := b - a hi := b - a
// Build heap with greatest element at top. // Build heap with greatest element at top.
for i := (hi - 1) / 2; i >= 0; i-- { for i := (hi - 1) / 2; i >= 0; i-- {
siftDownLessFunc(data, i, hi, first, less) siftDownCmpFunc(data, i, hi, first, cmp)
} }
// Pop elements, largest first, into end of data. // Pop elements, largest first, into end of data.
for i := hi - 1; i >= 0; i-- { for i := hi - 1; i >= 0; i-- {
data[first], data[first+i] = data[first+i], data[first] data[first], data[first+i] = data[first+i], data[first]
siftDownLessFunc(data, lo, i, first, less) siftDownCmpFunc(data, lo, i, first, cmp)
} }
} }
// pdqsortLessFunc sorts data[a:b]. // pdqsortCmpFunc sorts data[a:b].
// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort. // The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort.
// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf // pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf
// C++ implementation: https://github.com/orlp/pdqsort // C++ implementation: https://github.com/orlp/pdqsort
// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/ // Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/
// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort. // limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort.
func pdqsortLessFunc[E any](data []E, a, b, limit int, less func(a, b E) bool) { func pdqsortCmpFunc[E any](data []E, a, b, limit int, cmp func(a, b E) int) {
const maxInsertion = 12 const maxInsertion = 12
var ( var (
@ -70,25 +70,25 @@ func pdqsortLessFunc[E any](data []E, a, b, limit int, less func(a, b E) bool) {
length := b - a length := b - a
if length <= maxInsertion { if length <= maxInsertion {
insertionSortLessFunc(data, a, b, less) insertionSortCmpFunc(data, a, b, cmp)
return return
} }
// Fall back to heapsort if too many bad choices were made. // Fall back to heapsort if too many bad choices were made.
if limit == 0 { if limit == 0 {
heapSortLessFunc(data, a, b, less) heapSortCmpFunc(data, a, b, cmp)
return return
} }
// If the last partitioning was imbalanced, we need to breaking patterns. // If the last partitioning was imbalanced, we need to breaking patterns.
if !wasBalanced { if !wasBalanced {
breakPatternsLessFunc(data, a, b, less) breakPatternsCmpFunc(data, a, b, cmp)
limit-- limit--
} }
pivot, hint := choosePivotLessFunc(data, a, b, less) pivot, hint := choosePivotCmpFunc(data, a, b, cmp)
if hint == decreasingHint { if hint == decreasingHint {
reverseRangeLessFunc(data, a, b, less) reverseRangeCmpFunc(data, a, b, cmp)
// The chosen pivot was pivot-a elements after the start of the array. // 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. // After reversing it is pivot-a elements before the end of the array.
// The idea came from Rust's implementation. // The idea came from Rust's implementation.
@ -98,48 +98,48 @@ func pdqsortLessFunc[E any](data []E, a, b, limit int, less func(a, b E) bool) {
// The slice is likely already sorted. // The slice is likely already sorted.
if wasBalanced && wasPartitioned && hint == increasingHint { if wasBalanced && wasPartitioned && hint == increasingHint {
if partialInsertionSortLessFunc(data, a, b, less) { if partialInsertionSortCmpFunc(data, a, b, cmp) {
return return
} }
} }
// Probably the slice contains many duplicate elements, partition the slice into // Probably the slice contains many duplicate elements, partition the slice into
// elements equal to and elements greater than the pivot. // elements equal to and elements greater than the pivot.
if a > 0 && !less(data[a-1], data[pivot]) { if a > 0 && !(cmp(data[a-1], data[pivot]) < 0) {
mid := partitionEqualLessFunc(data, a, b, pivot, less) mid := partitionEqualCmpFunc(data, a, b, pivot, cmp)
a = mid a = mid
continue continue
} }
mid, alreadyPartitioned := partitionLessFunc(data, a, b, pivot, less) mid, alreadyPartitioned := partitionCmpFunc(data, a, b, pivot, cmp)
wasPartitioned = alreadyPartitioned wasPartitioned = alreadyPartitioned
leftLen, rightLen := mid-a, b-mid leftLen, rightLen := mid-a, b-mid
balanceThreshold := length / 8 balanceThreshold := length / 8
if leftLen < rightLen { if leftLen < rightLen {
wasBalanced = leftLen >= balanceThreshold wasBalanced = leftLen >= balanceThreshold
pdqsortLessFunc(data, a, mid, limit, less) pdqsortCmpFunc(data, a, mid, limit, cmp)
a = mid + 1 a = mid + 1
} else { } else {
wasBalanced = rightLen >= balanceThreshold wasBalanced = rightLen >= balanceThreshold
pdqsortLessFunc(data, mid+1, b, limit, less) pdqsortCmpFunc(data, mid+1, b, limit, cmp)
b = mid b = mid
} }
} }
} }
// partitionLessFunc does one quicksort partition. // partitionCmpFunc does one quicksort partition.
// Let p = data[pivot] // 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. // 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 // On return, data[newpivot] = p
func partitionLessFunc[E any](data []E, a, b, pivot int, less func(a, b E) bool) (newpivot int, alreadyPartitioned bool) { 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] 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 i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned
for i <= j && less(data[i], data[a]) { for i <= j && (cmp(data[i], data[a]) < 0) {
i++ i++
} }
for i <= j && !less(data[j], data[a]) { for i <= j && !(cmp(data[j], data[a]) < 0) {
j-- j--
} }
if i > j { if i > j {
@ -151,10 +151,10 @@ func partitionLessFunc[E any](data []E, a, b, pivot int, less func(a, b E) bool)
j-- j--
for { for {
for i <= j && less(data[i], data[a]) { for i <= j && (cmp(data[i], data[a]) < 0) {
i++ i++
} }
for i <= j && !less(data[j], data[a]) { for i <= j && !(cmp(data[j], data[a]) < 0) {
j-- j--
} }
if i > j { if i > j {
@ -168,17 +168,17 @@ func partitionLessFunc[E any](data []E, a, b, pivot int, less func(a, b E) bool)
return j, false return j, false
} }
// partitionEqualLessFunc partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot]. // 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]. // It assumed that data[a:b] does not contain elements smaller than the data[pivot].
func partitionEqualLessFunc[E any](data []E, a, b, pivot int, less func(a, b E) bool) (newpivot int) { 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] 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 i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned
for { for {
for i <= j && !less(data[a], data[i]) { for i <= j && !(cmp(data[a], data[i]) < 0) {
i++ i++
} }
for i <= j && less(data[a], data[j]) { for i <= j && (cmp(data[a], data[j]) < 0) {
j-- j--
} }
if i > j { if i > j {
@ -191,15 +191,15 @@ func partitionEqualLessFunc[E any](data []E, a, b, pivot int, less func(a, b E)
return i return i
} }
// partialInsertionSortLessFunc partially sorts a slice, returns true if the slice is sorted at the end. // partialInsertionSortCmpFunc partially sorts a slice, returns true if the slice is sorted at the end.
func partialInsertionSortLessFunc[E any](data []E, a, b int, less func(a, b E) bool) bool { func partialInsertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) bool {
const ( const (
maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted
shortestShifting = 50 // don't shift any elements on short arrays shortestShifting = 50 // don't shift any elements on short arrays
) )
i := a + 1 i := a + 1
for j := 0; j < maxSteps; j++ { for j := 0; j < maxSteps; j++ {
for i < b && !less(data[i], data[i-1]) { for i < b && !(cmp(data[i], data[i-1]) < 0) {
i++ i++
} }
@ -216,7 +216,7 @@ func partialInsertionSortLessFunc[E any](data []E, a, b int, less func(a, b E) b
// Shift the smaller one to the left. // Shift the smaller one to the left.
if i-a >= 2 { if i-a >= 2 {
for j := i - 1; j >= 1; j-- { for j := i - 1; j >= 1; j-- {
if !less(data[j], data[j-1]) { if !(cmp(data[j], data[j-1]) < 0) {
break break
} }
data[j], data[j-1] = data[j-1], data[j] data[j], data[j-1] = data[j-1], data[j]
@ -225,7 +225,7 @@ func partialInsertionSortLessFunc[E any](data []E, a, b int, less func(a, b E) b
// Shift the greater one to the right. // Shift the greater one to the right.
if b-i >= 2 { if b-i >= 2 {
for j := i + 1; j < b; j++ { for j := i + 1; j < b; j++ {
if !less(data[j], data[j-1]) { if !(cmp(data[j], data[j-1]) < 0) {
break break
} }
data[j], data[j-1] = data[j-1], data[j] data[j], data[j-1] = data[j-1], data[j]
@ -235,9 +235,9 @@ func partialInsertionSortLessFunc[E any](data []E, a, b int, less func(a, b E) b
return false return false
} }
// breakPatternsLessFunc scatters some elements around in an attempt to break some patterns // breakPatternsCmpFunc scatters some elements around in an attempt to break some patterns
// that might cause imbalanced partitions in quicksort. // that might cause imbalanced partitions in quicksort.
func breakPatternsLessFunc[E any](data []E, a, b int, less func(a, b E) bool) { func breakPatternsCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) {
length := b - a length := b - a
if length >= 8 { if length >= 8 {
random := xorshift(length) random := xorshift(length)
@ -253,12 +253,12 @@ func breakPatternsLessFunc[E any](data []E, a, b int, less func(a, b E) bool) {
} }
} }
// choosePivotLessFunc chooses a pivot in data[a:b]. // choosePivotCmpFunc chooses a pivot in data[a:b].
// //
// [0,8): chooses a static pivot. // [0,8): chooses a static pivot.
// [8,shortestNinther): uses the simple median-of-three method. // [8,shortestNinther): uses the simple median-of-three method.
// [shortestNinther,∞): uses the Tukey ninther method. // [shortestNinther,∞): uses the Tukey ninther method.
func choosePivotLessFunc[E any](data []E, a, b int, less func(a, b E) bool) (pivot int, hint sortedHint) { func choosePivotCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) (pivot int, hint sortedHint) {
const ( const (
shortestNinther = 50 shortestNinther = 50
maxSwaps = 4 * 3 maxSwaps = 4 * 3
@ -276,12 +276,12 @@ func choosePivotLessFunc[E any](data []E, a, b int, less func(a, b E) bool) (piv
if l >= 8 { if l >= 8 {
if l >= shortestNinther { if l >= shortestNinther {
// Tukey ninther method, the idea came from Rust's implementation. // Tukey ninther method, the idea came from Rust's implementation.
i = medianAdjacentLessFunc(data, i, &swaps, less) i = medianAdjacentCmpFunc(data, i, &swaps, cmp)
j = medianAdjacentLessFunc(data, j, &swaps, less) j = medianAdjacentCmpFunc(data, j, &swaps, cmp)
k = medianAdjacentLessFunc(data, k, &swaps, less) k = medianAdjacentCmpFunc(data, k, &swaps, cmp)
} }
// Find the median among i, j, k and stores it into j. // Find the median among i, j, k and stores it into j.
j = medianLessFunc(data, i, j, k, &swaps, less) j = medianCmpFunc(data, i, j, k, &swaps, cmp)
} }
switch swaps { switch swaps {
@ -294,29 +294,29 @@ func choosePivotLessFunc[E any](data []E, a, b int, less func(a, b E) bool) (piv
} }
} }
// order2LessFunc returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a. // order2CmpFunc returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a.
func order2LessFunc[E any](data []E, a, b int, swaps *int, less func(a, b E) bool) (int, int) { func order2CmpFunc[E any](data []E, a, b int, swaps *int, cmp func(a, b E) int) (int, int) {
if less(data[b], data[a]) { if cmp(data[b], data[a]) < 0 {
*swaps++ *swaps++
return b, a return b, a
} }
return a, b return a, b
} }
// medianLessFunc returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c. // medianCmpFunc returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c.
func medianLessFunc[E any](data []E, a, b, c int, swaps *int, less func(a, b E) bool) int { func medianCmpFunc[E any](data []E, a, b, c int, swaps *int, cmp func(a, b E) int) int {
a, b = order2LessFunc(data, a, b, swaps, less) a, b = order2CmpFunc(data, a, b, swaps, cmp)
b, c = order2LessFunc(data, b, c, swaps, less) b, c = order2CmpFunc(data, b, c, swaps, cmp)
a, b = order2LessFunc(data, a, b, swaps, less) a, b = order2CmpFunc(data, a, b, swaps, cmp)
return b return b
} }
// medianAdjacentLessFunc finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a. // medianAdjacentCmpFunc finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a.
func medianAdjacentLessFunc[E any](data []E, a int, swaps *int, less func(a, b E) bool) int { func medianAdjacentCmpFunc[E any](data []E, a int, swaps *int, cmp func(a, b E) int) int {
return medianLessFunc(data, a-1, a, a+1, swaps, less) return medianCmpFunc(data, a-1, a, a+1, swaps, cmp)
} }
func reverseRangeLessFunc[E any](data []E, a, b int, less func(a, b E) bool) { func reverseRangeCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) {
i := a i := a
j := b - 1 j := b - 1
for i < j { for i < j {
@ -326,37 +326,37 @@ func reverseRangeLessFunc[E any](data []E, a, b int, less func(a, b E) bool) {
} }
} }
func swapRangeLessFunc[E any](data []E, a, b, n int, less func(a, b E) bool) { func swapRangeCmpFunc[E any](data []E, a, b, n int, cmp func(a, b E) int) {
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
data[a+i], data[b+i] = data[b+i], data[a+i] data[a+i], data[b+i] = data[b+i], data[a+i]
} }
} }
func stableLessFunc[E any](data []E, n int, less func(a, b E) bool) { func stableCmpFunc[E any](data []E, n int, cmp func(a, b E) int) {
blockSize := 20 // must be > 0 blockSize := 20 // must be > 0
a, b := 0, blockSize a, b := 0, blockSize
for b <= n { for b <= n {
insertionSortLessFunc(data, a, b, less) insertionSortCmpFunc(data, a, b, cmp)
a = b a = b
b += blockSize b += blockSize
} }
insertionSortLessFunc(data, a, n, less) insertionSortCmpFunc(data, a, n, cmp)
for blockSize < n { for blockSize < n {
a, b = 0, 2*blockSize a, b = 0, 2*blockSize
for b <= n { for b <= n {
symMergeLessFunc(data, a, a+blockSize, b, less) symMergeCmpFunc(data, a, a+blockSize, b, cmp)
a = b a = b
b += 2 * blockSize b += 2 * blockSize
} }
if m := a + blockSize; m < n { if m := a + blockSize; m < n {
symMergeLessFunc(data, a, m, n, less) symMergeCmpFunc(data, a, m, n, cmp)
} }
blockSize *= 2 blockSize *= 2
} }
} }
// symMergeLessFunc merges the two sorted subsequences data[a:m] and data[m:b] using // 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 // the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum
// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz // Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz
// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in // Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in
@ -375,7 +375,7 @@ func stableLessFunc[E any](data []E, n int, less func(a, b E) bool) {
// symMerge assumes non-degenerate arguments: a < m && m < b. // symMerge assumes non-degenerate arguments: a < m && m < b.
// Having the caller check this condition eliminates many leaf recursion calls, // Having the caller check this condition eliminates many leaf recursion calls,
// which improves performance. // which improves performance.
func symMergeLessFunc[E any](data []E, a, m, b int, less func(a, b E) bool) { func symMergeCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) {
// Avoid unnecessary recursions of symMerge // Avoid unnecessary recursions of symMerge
// by direct insertion of data[a] into data[m:b] // by direct insertion of data[a] into data[m:b]
// if data[a:m] only contains one element. // if data[a:m] only contains one element.
@ -387,7 +387,7 @@ func symMergeLessFunc[E any](data []E, a, m, b int, less func(a, b E) bool) {
j := b j := b
for i < j { for i < j {
h := int(uint(i+j) >> 1) h := int(uint(i+j) >> 1)
if less(data[h], data[a]) { if cmp(data[h], data[a]) < 0 {
i = h + 1 i = h + 1
} else { } else {
j = h j = h
@ -411,7 +411,7 @@ func symMergeLessFunc[E any](data []E, a, m, b int, less func(a, b E) bool) {
j := m j := m
for i < j { for i < j {
h := int(uint(i+j) >> 1) h := int(uint(i+j) >> 1)
if !less(data[m], data[h]) { if !(cmp(data[m], data[h]) < 0) {
i = h + 1 i = h + 1
} else { } else {
j = h j = h
@ -438,7 +438,7 @@ func symMergeLessFunc[E any](data []E, a, m, b int, less func(a, b E) bool) {
for start < r { for start < r {
c := int(uint(start+r) >> 1) c := int(uint(start+r) >> 1)
if !less(data[p-c], data[c]) { if !(cmp(data[p-c], data[c]) < 0) {
start = c + 1 start = c + 1
} else { } else {
r = c r = c
@ -447,33 +447,33 @@ func symMergeLessFunc[E any](data []E, a, m, b int, less func(a, b E) bool) {
end := n - start end := n - start
if start < m && m < end { if start < m && m < end {
rotateLessFunc(data, start, m, end, less) rotateCmpFunc(data, start, m, end, cmp)
} }
if a < start && start < mid { if a < start && start < mid {
symMergeLessFunc(data, a, start, mid, less) symMergeCmpFunc(data, a, start, mid, cmp)
} }
if mid < end && end < b { if mid < end && end < b {
symMergeLessFunc(data, mid, end, b, less) symMergeCmpFunc(data, mid, end, b, cmp)
} }
} }
// rotateLessFunc rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data: // 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'. // 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, // rotate performs at most b-a many calls to data.Swap,
// and it assumes non-degenerate arguments: a < m && m < b. // and it assumes non-degenerate arguments: a < m && m < b.
func rotateLessFunc[E any](data []E, a, m, b int, less func(a, b E) bool) { func rotateCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) {
i := m - a i := m - a
j := b - m j := b - m
for i != j { for i != j {
if i > j { if i > j {
swapRangeLessFunc(data, m-i, m, j, less) swapRangeCmpFunc(data, m-i, m, j, cmp)
i -= j i -= j
} else { } else {
swapRangeLessFunc(data, m-i, m+j-i, i, less) swapRangeCmpFunc(data, m-i, m+j-i, i, cmp)
j -= i j -= i
} }
} }
// i == j // i == j
swapRangeLessFunc(data, m-i, m, i, less) swapRangeCmpFunc(data, m-i, m, i, cmp)
} }

View File

@ -11,7 +11,7 @@ import "golang.org/x/exp/constraints"
// insertionSortOrdered sorts data[a:b] using insertion sort. // insertionSortOrdered sorts data[a:b] using insertion sort.
func insertionSortOrdered[E constraints.Ordered](data []E, a, b int) { func insertionSortOrdered[E constraints.Ordered](data []E, a, b int) {
for i := a + 1; i < b; i++ { for i := a + 1; i < b; i++ {
for j := i; j > a && (data[j] < data[j-1]); j-- { for j := i; j > a && cmpLess(data[j], data[j-1]); j-- {
data[j], data[j-1] = data[j-1], data[j] data[j], data[j-1] = data[j-1], data[j]
} }
} }
@ -26,10 +26,10 @@ func siftDownOrdered[E constraints.Ordered](data []E, lo, hi, first int) {
if child >= hi { if child >= hi {
break break
} }
if child+1 < hi && (data[first+child] < data[first+child+1]) { if child+1 < hi && cmpLess(data[first+child], data[first+child+1]) {
child++ child++
} }
if !(data[first+root] < data[first+child]) { if !cmpLess(data[first+root], data[first+child]) {
return return
} }
data[first+root], data[first+child] = data[first+child], data[first+root] data[first+root], data[first+child] = data[first+child], data[first+root]
@ -107,7 +107,7 @@ func pdqsortOrdered[E constraints.Ordered](data []E, a, b, limit int) {
// Probably the slice contains many duplicate elements, partition the slice into // Probably the slice contains many duplicate elements, partition the slice into
// elements equal to and elements greater than the pivot. // elements equal to and elements greater than the pivot.
if a > 0 && !(data[a-1] < data[pivot]) { if a > 0 && !cmpLess(data[a-1], data[pivot]) {
mid := partitionEqualOrdered(data, a, b, pivot) mid := partitionEqualOrdered(data, a, b, pivot)
a = mid a = mid
continue continue
@ -138,10 +138,10 @@ func partitionOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivo
data[a], data[pivot] = data[pivot], data[a] 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 i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned
for i <= j && (data[i] < data[a]) { for i <= j && cmpLess(data[i], data[a]) {
i++ i++
} }
for i <= j && !(data[j] < data[a]) { for i <= j && !cmpLess(data[j], data[a]) {
j-- j--
} }
if i > j { if i > j {
@ -153,10 +153,10 @@ func partitionOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivo
j-- j--
for { for {
for i <= j && (data[i] < data[a]) { for i <= j && cmpLess(data[i], data[a]) {
i++ i++
} }
for i <= j && !(data[j] < data[a]) { for i <= j && !cmpLess(data[j], data[a]) {
j-- j--
} }
if i > j { if i > j {
@ -177,10 +177,10 @@ func partitionEqualOrdered[E constraints.Ordered](data []E, a, b, pivot int) (ne
i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned
for { for {
for i <= j && !(data[a] < data[i]) { for i <= j && !cmpLess(data[a], data[i]) {
i++ i++
} }
for i <= j && (data[a] < data[j]) { for i <= j && cmpLess(data[a], data[j]) {
j-- j--
} }
if i > j { if i > j {
@ -201,7 +201,7 @@ func partialInsertionSortOrdered[E constraints.Ordered](data []E, a, b int) bool
) )
i := a + 1 i := a + 1
for j := 0; j < maxSteps; j++ { for j := 0; j < maxSteps; j++ {
for i < b && !(data[i] < data[i-1]) { for i < b && !cmpLess(data[i], data[i-1]) {
i++ i++
} }
@ -218,7 +218,7 @@ func partialInsertionSortOrdered[E constraints.Ordered](data []E, a, b int) bool
// Shift the smaller one to the left. // Shift the smaller one to the left.
if i-a >= 2 { if i-a >= 2 {
for j := i - 1; j >= 1; j-- { for j := i - 1; j >= 1; j-- {
if !(data[j] < data[j-1]) { if !cmpLess(data[j], data[j-1]) {
break break
} }
data[j], data[j-1] = data[j-1], data[j] data[j], data[j-1] = data[j-1], data[j]
@ -227,7 +227,7 @@ func partialInsertionSortOrdered[E constraints.Ordered](data []E, a, b int) bool
// Shift the greater one to the right. // Shift the greater one to the right.
if b-i >= 2 { if b-i >= 2 {
for j := i + 1; j < b; j++ { for j := i + 1; j < b; j++ {
if !(data[j] < data[j-1]) { if !cmpLess(data[j], data[j-1]) {
break break
} }
data[j], data[j-1] = data[j-1], data[j] data[j], data[j-1] = data[j-1], data[j]
@ -298,7 +298,7 @@ func choosePivotOrdered[E constraints.Ordered](data []E, a, b int) (pivot int, h
// order2Ordered returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a. // 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) { func order2Ordered[E constraints.Ordered](data []E, a, b int, swaps *int) (int, int) {
if data[b] < data[a] { if cmpLess(data[b], data[a]) {
*swaps++ *swaps++
return b, a return b, a
} }
@ -389,7 +389,7 @@ func symMergeOrdered[E constraints.Ordered](data []E, a, m, b int) {
j := b j := b
for i < j { for i < j {
h := int(uint(i+j) >> 1) h := int(uint(i+j) >> 1)
if data[h] < data[a] { if cmpLess(data[h], data[a]) {
i = h + 1 i = h + 1
} else { } else {
j = h j = h
@ -413,7 +413,7 @@ func symMergeOrdered[E constraints.Ordered](data []E, a, m, b int) {
j := m j := m
for i < j { for i < j {
h := int(uint(i+j) >> 1) h := int(uint(i+j) >> 1)
if !(data[m] < data[h]) { if !cmpLess(data[m], data[h]) {
i = h + 1 i = h + 1
} else { } else {
j = h j = h
@ -440,7 +440,7 @@ func symMergeOrdered[E constraints.Ordered](data []E, a, m, b int) {
for start < r { for start < r {
c := int(uint(start+r) >> 1) c := int(uint(start+r) >> 1)
if !(data[p-c] < data[c]) { if !cmpLess(data[p-c], data[c]) {
start = c + 1 start = c + 1
} else { } else {
r = c r = c

12
vendor/modules.txt vendored
View File

@ -62,7 +62,7 @@ github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/options
github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/shared github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/shared
github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/version github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/version
github.com/AzureAD/microsoft-authentication-library-for-go/apps/public github.com/AzureAD/microsoft-authentication-library-for-go/apps/public
# github.com/IBM/keyprotect-go-client v0.14.3 # github.com/IBM/keyprotect-go-client v0.15.1
## explicit; go 1.15 ## explicit; go 1.15
github.com/IBM/keyprotect-go-client github.com/IBM/keyprotect-go-client
github.com/IBM/keyprotect-go-client/iam github.com/IBM/keyprotect-go-client/iam
@ -81,7 +81,7 @@ github.com/antlr/antlr4/runtime/Go/antlr/v4
# github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a # github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a
## explicit ## explicit
github.com/asaskevich/govalidator github.com/asaskevich/govalidator
# github.com/aws/aws-sdk-go v1.55.4 # github.com/aws/aws-sdk-go v1.55.5
## explicit; go 1.19 ## explicit; go 1.19
github.com/aws/aws-sdk-go/aws github.com/aws/aws-sdk-go/aws
github.com/aws/aws-sdk-go/aws/auth/bearer github.com/aws/aws-sdk-go/aws/auth/bearer
@ -538,7 +538,7 @@ 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.0 # github.com/onsi/gomega v1.34.1
## explicit; go 1.20 ## explicit; go 1.20
github.com/onsi/gomega github.com/onsi/gomega
github.com/onsi/gomega/format github.com/onsi/gomega/format
@ -729,8 +729,8 @@ golang.org/x/crypto/salsa20/salsa
golang.org/x/crypto/scrypt golang.org/x/crypto/scrypt
golang.org/x/crypto/ssh golang.org/x/crypto/ssh
golang.org/x/crypto/ssh/internal/bcrypt_pbkdf golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
# golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 # golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
## explicit; go 1.18 ## explicit; go 1.20
golang.org/x/exp/constraints golang.org/x/exp/constraints
golang.org/x/exp/maps golang.org/x/exp/maps
golang.org/x/exp/slices golang.org/x/exp/slices
@ -801,7 +801,7 @@ golang.org/x/text/width
# golang.org/x/time v0.3.0 # golang.org/x/time v0.3.0
## explicit ## explicit
golang.org/x/time/rate golang.org/x/time/rate
# golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d # golang.org/x/tools v0.23.0
## explicit; go 1.19 ## explicit; go 1.19
golang.org/x/tools/cover golang.org/x/tools/cover
golang.org/x/tools/go/ast/inspector golang.org/x/tools/go/ast/inspector