forked from twotwotwo/sorts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
types.go
338 lines (244 loc) · 12.9 KB
/
types.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
// Copyright 2009 The Go Authors.
// Copyright 2015 Randall Farmer.
// Copyright 2023 Rishabh Moudgil.
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package sortutil sorts and searches common slice types (and helps sort
// floats).
package sorts
import (
"bytes"
"math"
"sort"
)
// Float32Key generates a uint64 key from a float32. Use with Float32Less.
func Float32Key(f float32) uint64 {
b := uint64(math.Float32bits(f)) << 32
b ^= ^(b>>63 - 1) | (1 << 63)
return b
}
// Float32Less compares float32s, treating NaN as greater than all numbers.
func Float32Less(f, g float32) bool {
return Float32Key(f) < Float32Key(g)
}
// Float64Key generates a uint64 key from a float64. Use with Float64Less.
func Float64Key(f float64) uint64 {
b := math.Float64bits(f)
b ^= ^(b>>63 - 1) | (1 << 63)
return b
}
// Float64Less compares float64s, treating NaN as greater than all numbers.
func Float64Less(f, g float64) bool {
return Float64Key(f) < Float64Key(g)
}
// IntSlice attaches the methods of Int64Interface to []int, sorting in increasing order.
type IntSlice []int
func (p IntSlice) Len() int { return len(p) }
func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p IntSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Key produces a radix sort key for an integer item.
func (p IntSlice) Key(i int) int64 { return int64(p[i]) }
// Sort is a convenience method.
func (p IntSlice) Sort() { ByInt64(p) }
// Int32Slice attaches the methods of Uint64Interface to []int32, sorting in increasing order.
type Int32Slice []int32
func (p Int32Slice) Len() int { return len(p) }
func (p Int32Slice) Less(i, j int) bool { return p[i] < p[j] }
func (p Int32Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Key produces a radix sort key for an integer item.
func (p Int32Slice) Key(i int) int64 { return int64(p[i]) }
// Sort is a convenience method.
func (p Int32Slice) Sort() { ByInt64(p) }
// Int64Slice attaches the methods of Uint64Interface to []int64, sorting in increasing order.
type Int64Slice []int64
func (p Int64Slice) Len() int { return len(p) }
func (p Int64Slice) Less(i, j int) bool { return p[i] < p[j] }
func (p Int64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Key produces a radix sort key for an integer item.
func (p Int64Slice) Key(i int) int64 { return p[i] }
// Sort is a convenience method.
func (p Int64Slice) Sort() { ByInt64(p) }
// UintSlice attaches the methods of Uint64Interface to []uint, sorting in increasing order.
type UintSlice []uint
func (p UintSlice) Len() int { return len(p) }
func (p UintSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p UintSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Key produces a radix sort key for an unsigned integer item.
func (p UintSlice) Key(i int) uint64 { return uint64(p[i]) }
// Sort is a convenience method.
func (p UintSlice) Sort() { ByUint64(p) }
// Uint32Slice attaches the methods of Uint64Interface to []int32, sorting in increasing order.
type Uint32Slice []uint32
func (p Uint32Slice) Len() int { return len(p) }
func (p Uint32Slice) Less(i, j int) bool { return p[i] < p[j] }
func (p Uint32Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Key produces a radix sort key for an unsigned integer item.
func (p Uint32Slice) Key(i int) uint64 { return uint64(p[i]) }
// Sort is a convenience method.
func (p Uint32Slice) Sort() { ByUint64(p) }
// Uint64Slice attaches the methods of Uint64Interface to []uint64, sorting in increasing order.
type Uint64Slice []uint64
func (p Uint64Slice) Len() int { return len(p) }
func (p Uint64Slice) Less(i, j int) bool { return p[i] < p[j] }
func (p Uint64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Key produces a radix sort key for an unsigned integer item.
func (p Uint64Slice) Key(i int) uint64 { return p[i] }
// Sort is a convenience method.
func (p Uint64Slice) Sort() { ByUint64(p) }
type Uint128 struct{ Hi, Lo uint64 }
// Uint128Slice attaches the methods of Uint128Interface to []Uint128, sorting in increasing order.
type Uint128Slice []Uint128
func (p Uint128Slice) Len() int { return len(p) }
func (p Uint128Slice) Less(i, j int) bool {
pI := p[i]
pJ := p[j]
pIHi := pI.Hi
pJHi := pJ.Hi
return pIHi < pJHi || (pIHi == pJHi && pI.Lo < pJ.Lo)
}
func (p Uint128Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Key produces a radix sort key for an unsigned integer item.
func (p Uint128Slice) Key(i int) (uint64, uint64) { return p[i].Hi, p[i].Lo }
// Sort is a convenience method.
func (p Uint128Slice) Sort() { ByUint128(p) }
// Float32Slice attaches the methods of Uint64Interface to []uint32, sorting in increasing order, NaNs last.
type Float32Slice []float32
func (p Float32Slice) Len() int { return len(p) }
func (p Float32Slice) Less(i, j int) bool { return Float32Less(p[i], p[j]) }
func (p Float32Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Key produces a radix sort key for a floating-point value.
func (p Float32Slice) Key(i int) uint64 { return Float32Key(p[i]) }
// Sort is a convenience method.
func (p Float32Slice) Sort() { ByUint64(p) }
// Float64Slice attaches the methods of Uint64Interface to []float64, sorting in increasing order, NaNs last.
type Float64Slice []float64
func (p Float64Slice) Len() int { return len(p) }
func (p Float64Slice) Less(i, j int) bool { return Float64Less(p[i], p[j]) }
func (p Float64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Key produces a radix sort key for a floating-point value.
func (p Float64Slice) Key(i int) uint64 { return Float64Key(p[i]) }
// Sort is a convenience method.
func (p Float64Slice) Sort() { ByUint64(p) }
// StringSlice attaches the methods of StringInterface to []string, sorting in increasing order.
type StringSlice []string
func (p StringSlice) Len() int { return len(p) }
func (p StringSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p StringSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Key returns a string item in a collection.
func (p StringSlice) Key(i int) string { return p[i] }
// Sort is a convenience method.
func (p StringSlice) Sort() { ByString(p) }
// BytesSlice attaches the methods of BytesInterface to [][]byte, sorting in increasing order.
type BytesSlice [][]byte
func (p BytesSlice) Len() int { return len(p) }
func (p BytesSlice) Less(i, j int) bool { return bytes.Compare(p[i], p[j]) == -1 }
func (p BytesSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Key returns a []byte item in a collection.
func (p BytesSlice) Key(i int) []byte { return p[i] }
// Sort is a convenience method.
func (p BytesSlice) Sort() { ByBytes(p) }
// Ints sorts a slice of ints in increasing order.
func Ints(a []int) { IntSlice(a).Sort() }
// Int32s sorts a slice of int32s in increasing order.
func Int32s(a []int32) { Int32Slice(a).Sort() }
// Int64s sorts a slice of int64s in increasing order.
func Int64s(a []int64) { Int64Slice(a).Sort() }
// Uints sorts a slice of ints in increasing order.
func Uints(a []uint) { UintSlice(a).Sort() }
// Uint32s sorts a slice of uint64s in increasing order.
func Uint32s(a []uint32) { Uint32Slice(a).Sort() }
// Uint64s sorts a slice of uint64s in increasing order.
func Uint64s(a []uint64) { Uint64Slice(a).Sort() }
// Uint128s sorts a slice of uint128s in increasing order.
func Uint128s(a []Uint128) { Uint128Slice(a).Sort() }
// Float32s sorts a slice of uint64s in increasing order, NaNs last.
func Float32s(a []float32) { Float32Slice(a).Sort() }
// Float64s sorts a slice of uint64s in increasing order, NaNs last.
func Float64s(a []float64) { Float64Slice(a).Sort() }
// Strings sorts a slice of strings in increasing order.
func Strings(a []string) { StringSlice(a).Sort() }
// Bytes sorts a slice of byte slices in increasing order.
func Bytes(a [][]byte) { BytesSlice(a).Sort() }
// IntsAreSorted tests whether a slice of ints is sorted in increasing order.
func IntsAreSorted(a []int) bool { return sort.IsSorted(IntSlice(a)) }
// Int32sAreSorted tests whether a slice of int32s is sorted in increasing order.
func Int32sAreSorted(a []int32) bool { return sort.IsSorted(Int32Slice(a)) }
// Int64sAreSorted tests whether a slice of int64s is sorted in increasing order.
func Int64sAreSorted(a []int64) bool { return sort.IsSorted(Int64Slice(a)) }
// UintsAreSorted tests whether a slice of ints is sorted in increasing order.
func UintsAreSorted(a []uint) bool { return sort.IsSorted(UintSlice(a)) }
// Uint32sAreSorted tests whether a slice of uint32s is sorted in increasing order.
func Uint32sAreSorted(a []uint32) bool { return sort.IsSorted(Uint32Slice(a)) }
// Uint64sAreSorted tests whether a slice of uint64s is sorted in increasing order.
func Uint64sAreSorted(a []uint64) bool { return sort.IsSorted(Uint64Slice(a)) }
// Uint128sAreSorted tests whether a slice of uint128s is sorted in increasing order.
func Uint128sAreSorted(a []Uint128) bool { return sort.IsSorted(Uint128Slice(a)) }
// Float32sAreSorted tests whether a slice of float32s is sorted in increasing order, NaNs last.
func Float32sAreSorted(a []float32) bool { return sort.IsSorted(Float32Slice(a)) }
// Float64sAreSorted tests whether a slice of float64s is sorted in increasing order, NaNs last.
func Float64sAreSorted(a []float64) bool { return sort.IsSorted(Float64Slice(a)) }
// StringsAreSorted tests whether a slice of strings is sorted in increasing order.
func StringsAreSorted(a []string) bool { return sort.IsSorted(StringSlice(a)) }
// BytesAreSorted tests whether a slice of byte slices is sorted in increasing order.
func BytesAreSorted(a [][]byte) bool { return sort.IsSorted(BytesSlice(a)) }
// SearchInts searches ints; read about sort.Search for more.
func SearchInts(a []int, x int) int {
return sort.Search(len(a), func(i int) bool { return a[i] >= x })
}
// Search returns the result of applying SearchInts to the receiver and x.
func (p IntSlice) Search(x int) int { return SearchInts(p, x) }
// SearchInt32s searches int32s; read about sort.Search for more.
func SearchInt32s(a []int32, x int32) int {
return sort.Search(len(a), func(i int) bool { return a[i] >= x })
}
// Search returns the result of applying SearchInt32s to the receiver and x.
func (p Int32Slice) Search(x int32) int { return SearchInt32s(p, x) }
// SearchInt64s searches int64s; read about sort.Search for more.
func SearchInt64s(a []int64, x int64) int {
return sort.Search(len(a), func(i int) bool { return a[i] >= x })
}
// Search returns the result of applying SearchInt64s to the receiver and x.
func (p Int64Slice) Search(x int64) int { return SearchInt64s(p, x) }
// SearchUints searches uints; read about sort.Search for more.
func SearchUints(a []uint, x uint) int {
return sort.Search(len(a), func(i int) bool { return a[i] >= x })
}
// Search returns the result of applying SearchUints to the receiver and x.
func (p UintSlice) Search(x uint) int { return SearchUints(p, x) }
// SearchUint32s searches uint32s; read about sort.Search for more.
func SearchUint32s(a []uint32, x uint32) int {
return sort.Search(len(a), func(i int) bool { return a[i] >= x })
}
// Search returns the result of applying SearchUint32s to the receiver and x.
func (p Uint32Slice) Search(x uint32) int { return SearchUint32s(p, x) }
// SearchUint64s searches uint64s; read about sort.Search for more.
func SearchUint64s(a []uint64, x uint64) int {
return sort.Search(len(a), func(i int) bool { return a[i] >= x })
}
// Search returns the result of applying SearchUint64s to the receiver and x.
func (p Uint64Slice) Search(x uint64) int { return SearchUint64s(p, x) }
// SearchFloat32s searches float32s; read about sort.Search for more.
func SearchFloat32s(a []float32, x float32) int {
return sort.Search(len(a), func(i int) bool { return Float32Key(a[i]) >= Float32Key(x) })
}
// Search returns the result of applying SearchFloat32s to the receiver and x.
func (p Float32Slice) Search(x float32) int { return SearchFloat32s(p, x) }
// SearchFloat64s searches float64s; read about sort.Search for more.
func SearchFloat64s(a []float64, x float64) int {
return sort.Search(len(a), func(i int) bool { return Float64Key(a[i]) >= Float64Key(x) })
}
// Search returns the result of applying SearchFloat64s to the receiver and x.
func (p Float64Slice) Search(x float64) int { return SearchFloat64s(p, x) }
// SearchStrings searches strings; read about sort.Search for more.
func SearchStrings(a []string, x string) int {
return sort.Search(len(a), func(i int) bool { return a[i] >= x })
}
// Search returns the result of applying SearchStrings to the receiver and x.
func (p StringSlice) Search(x string) int { return SearchStrings(p, x) }
// SearchBytes searches []bytes; read about sort.Search for more.
func SearchBytes(a [][]byte, x []byte) int {
return sort.Search(len(a), func(i int) bool { return bytes.Compare(a[i], x) >= 0 })
}
// Search returns the result of applying SearchBytes to the receiver and x.
func (p BytesSlice) Search(x []byte) int { return SearchBytes(p, x) }