1// Copyright 2021 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package slices defines various functions useful with slices of any type.
6package slices
7
8import (
9	"cmp"
10	"math/bits"
11	"unsafe"
12)
13
14// Equal reports whether two slices are equal: the same length and all
15// elements equal. If the lengths are different, Equal returns false.
16// Otherwise, the elements are compared in increasing index order, and the
17// comparison stops at the first unequal pair.
18// Empty and nil slices are considered equal.
19// Floating point NaNs are not considered equal.
20func Equal[S ~[]E, E comparable](s1, s2 S) bool {
21	if len(s1) != len(s2) {
22		return false
23	}
24	for i := range s1 {
25		if s1[i] != s2[i] {
26			return false
27		}
28	}
29	return true
30}
31
32// EqualFunc reports whether two slices are equal using an equality
33// function on each pair of elements. If the lengths are different,
34// EqualFunc returns false. Otherwise, the elements are compared in
35// increasing index order, and the comparison stops at the first index
36// for which eq returns false.
37func EqualFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) bool) bool {
38	if len(s1) != len(s2) {
39		return false
40	}
41	for i, v1 := range s1 {
42		v2 := s2[i]
43		if !eq(v1, v2) {
44			return false
45		}
46	}
47	return true
48}
49
50// Compare compares the elements of s1 and s2, using [cmp.Compare] on each pair
51// of elements. The elements are compared sequentially, starting at index 0,
52// until one element is not equal to the other.
53// The result of comparing the first non-matching elements is returned.
54// If both slices are equal until one of them ends, the shorter slice is
55// considered less than the longer one.
56// The result is 0 if s1 == s2, -1 if s1 < s2, and +1 if s1 > s2.
57func Compare[S ~[]E, E cmp.Ordered](s1, s2 S) int {
58	for i, v1 := range s1 {
59		if i >= len(s2) {
60			return +1
61		}
62		v2 := s2[i]
63		if c := cmp.Compare(v1, v2); c != 0 {
64			return c
65		}
66	}
67	if len(s1) < len(s2) {
68		return -1
69	}
70	return 0
71}
72
73// CompareFunc is like [Compare] but uses a custom comparison function on each
74// pair of elements.
75// The result is the first non-zero result of cmp; if cmp always
76// returns 0 the result is 0 if len(s1) == len(s2), -1 if len(s1) < len(s2),
77// and +1 if len(s1) > len(s2).
78func CompareFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, cmp func(E1, E2) int) int {
79	for i, v1 := range s1 {
80		if i >= len(s2) {
81			return +1
82		}
83		v2 := s2[i]
84		if c := cmp(v1, v2); c != 0 {
85			return c
86		}
87	}
88	if len(s1) < len(s2) {
89		return -1
90	}
91	return 0
92}
93
94// Index returns the index of the first occurrence of v in s,
95// or -1 if not present.
96func Index[S ~[]E, E comparable](s S, v E) int {
97	for i := range s {
98		if v == s[i] {
99			return i
100		}
101	}
102	return -1
103}
104
105// IndexFunc returns the first index i satisfying f(s[i]),
106// or -1 if none do.
107func IndexFunc[S ~[]E, E any](s S, f func(E) bool) int {
108	for i := range s {
109		if f(s[i]) {
110			return i
111		}
112	}
113	return -1
114}
115
116// Contains reports whether v is present in s.
117func Contains[S ~[]E, E comparable](s S, v E) bool {
118	return Index(s, v) >= 0
119}
120
121// ContainsFunc reports whether at least one
122// element e of s satisfies f(e).
123func ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool {
124	return IndexFunc(s, f) >= 0
125}
126
127// Insert inserts the values v... into s at index i,
128// returning the modified slice.
129// The elements at s[i:] are shifted up to make room.
130// In the returned slice r, r[i] == v[0],
131// and r[i+len(v)] == value originally at r[i].
132// Insert panics if i is out of range.
133// This function is O(len(s) + len(v)).
134func Insert[S ~[]E, E any](s S, i int, v ...E) S {
135	_ = s[i:] // bounds check
136
137	m := len(v)
138	if m == 0 {
139		return s
140	}
141	n := len(s)
142	if i == n {
143		return append(s, v...)
144	}
145	if n+m > cap(s) {
146		// Use append rather than make so that we bump the size of
147		// the slice up to the next storage class.
148		// This is what Grow does but we don't call Grow because
149		// that might copy the values twice.
150		s2 := append(s[:i], make(S, n+m-i)...)
151		copy(s2[i:], v)
152		copy(s2[i+m:], s[i:])
153		return s2
154	}
155	s = s[:n+m]
156
157	// before:
158	// s: aaaaaaaabbbbccccccccdddd
159	//            ^   ^       ^   ^
160	//            i  i+m      n  n+m
161	// after:
162	// s: aaaaaaaavvvvbbbbcccccccc
163	//            ^   ^       ^   ^
164	//            i  i+m      n  n+m
165	//
166	// a are the values that don't move in s.
167	// v are the values copied in from v.
168	// b and c are the values from s that are shifted up in index.
169	// d are the values that get overwritten, never to be seen again.
170
171	if !overlaps(v, s[i+m:]) {
172		// Easy case - v does not overlap either the c or d regions.
173		// (It might be in some of a or b, or elsewhere entirely.)
174		// The data we copy up doesn't write to v at all, so just do it.
175
176		copy(s[i+m:], s[i:])
177
178		// Now we have
179		// s: aaaaaaaabbbbbbbbcccccccc
180		//            ^   ^       ^   ^
181		//            i  i+m      n  n+m
182		// Note the b values are duplicated.
183
184		copy(s[i:], v)
185
186		// Now we have
187		// s: aaaaaaaavvvvbbbbcccccccc
188		//            ^   ^       ^   ^
189		//            i  i+m      n  n+m
190		// That's the result we want.
191		return s
192	}
193
194	// The hard case - v overlaps c or d. We can't just shift up
195	// the data because we'd move or clobber the values we're trying
196	// to insert.
197	// So instead, write v on top of d, then rotate.
198	copy(s[n:], v)
199
200	// Now we have
201	// s: aaaaaaaabbbbccccccccvvvv
202	//            ^   ^       ^   ^
203	//            i  i+m      n  n+m
204
205	rotateRight(s[i:], m)
206
207	// Now we have
208	// s: aaaaaaaavvvvbbbbcccccccc
209	//            ^   ^       ^   ^
210	//            i  i+m      n  n+m
211	// That's the result we want.
212	return s
213}
214
215// Delete removes the elements s[i:j] from s, returning the modified slice.
216// Delete panics if j > len(s) or s[i:j] is not a valid slice of s.
217// Delete is O(len(s)-i), so if many items must be deleted, it is better to
218// make a single call deleting them all together than to delete one at a time.
219// Delete zeroes the elements s[len(s)-(j-i):len(s)].
220func Delete[S ~[]E, E any](s S, i, j int) S {
221	_ = s[i:j:len(s)] // bounds check
222
223	if i == j {
224		return s
225	}
226
227	oldlen := len(s)
228	s = append(s[:i], s[j:]...)
229	clear(s[len(s):oldlen]) // zero/nil out the obsolete elements, for GC
230	return s
231}
232
233// DeleteFunc removes any elements from s for which del returns true,
234// returning the modified slice.
235// DeleteFunc zeroes the elements between the new length and the original length.
236func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
237	i := IndexFunc(s, del)
238	if i == -1 {
239		return s
240	}
241	// Don't start copying elements until we find one to delete.
242	for j := i + 1; j < len(s); j++ {
243		if v := s[j]; !del(v) {
244			s[i] = v
245			i++
246		}
247	}
248	clear(s[i:]) // zero/nil out the obsolete elements, for GC
249	return s[:i]
250}
251
252// Replace replaces the elements s[i:j] by the given v, and returns the
253// modified slice.
254// Replace panics if j > len(s) or s[i:j] is not a valid slice of s.
255// When len(v) < (j-i), Replace zeroes the elements between the new length and the original length.
256func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
257	_ = s[i:j] // bounds check
258
259	if i == j {
260		return Insert(s, i, v...)
261	}
262	if j == len(s) {
263		s2 := append(s[:i], v...)
264		if len(s2) < len(s) {
265			clear(s[len(s2):]) // zero/nil out the obsolete elements, for GC
266		}
267		return s2
268	}
269
270	tot := len(s[:i]) + len(v) + len(s[j:])
271	if tot > cap(s) {
272		// Too big to fit, allocate and copy over.
273		s2 := append(s[:i], make(S, tot-i)...) // See Insert
274		copy(s2[i:], v)
275		copy(s2[i+len(v):], s[j:])
276		return s2
277	}
278
279	r := s[:tot]
280
281	if i+len(v) <= j {
282		// Easy, as v fits in the deleted portion.
283		copy(r[i:], v)
284		copy(r[i+len(v):], s[j:])
285		clear(s[tot:]) // zero/nil out the obsolete elements, for GC
286		return r
287	}
288
289	// We are expanding (v is bigger than j-i).
290	// The situation is something like this:
291	// (example has i=4,j=8,len(s)=16,len(v)=6)
292	// s: aaaaxxxxbbbbbbbbyy
293	//        ^   ^       ^ ^
294	//        i   j  len(s) tot
295	// a: prefix of s
296	// x: deleted range
297	// b: more of s
298	// y: area to expand into
299
300	if !overlaps(r[i+len(v):], v) {
301		// Easy, as v is not clobbered by the first copy.
302		copy(r[i+len(v):], s[j:])
303		copy(r[i:], v)
304		return r
305	}
306
307	// This is a situation where we don't have a single place to which
308	// we can copy v. Parts of it need to go to two different places.
309	// We want to copy the prefix of v into y and the suffix into x, then
310	// rotate |y| spots to the right.
311	//
312	//        v[2:]      v[:2]
313	//         |           |
314	// s: aaaavvvvbbbbbbbbvv
315	//        ^   ^       ^ ^
316	//        i   j  len(s) tot
317	//
318	// If either of those two destinations don't alias v, then we're good.
319	y := len(v) - (j - i) // length of y portion
320
321	if !overlaps(r[i:j], v) {
322		copy(r[i:j], v[y:])
323		copy(r[len(s):], v[:y])
324		rotateRight(r[i:], y)
325		return r
326	}
327	if !overlaps(r[len(s):], v) {
328		copy(r[len(s):], v[:y])
329		copy(r[i:j], v[y:])
330		rotateRight(r[i:], y)
331		return r
332	}
333
334	// Now we know that v overlaps both x and y.
335	// That means that the entirety of b is *inside* v.
336	// So we don't need to preserve b at all; instead we
337	// can copy v first, then copy the b part of v out of
338	// v to the right destination.
339	k := startIdx(v, s[j:])
340	copy(r[i:], v)
341	copy(r[i+len(v):], r[i+k:])
342	return r
343}
344
345// Clone returns a copy of the slice.
346// The elements are copied using assignment, so this is a shallow clone.
347// The result may have additional unused capacity.
348func Clone[S ~[]E, E any](s S) S {
349	// The s[:0:0] preserves nil in case it matters.
350	return append(s[:0:0], s...)
351}
352
353// Compact replaces consecutive runs of equal elements with a single copy.
354// This is like the uniq command found on Unix.
355// Compact modifies the contents of the slice s and returns the modified slice,
356// which may have a smaller length.
357// Compact zeroes the elements between the new length and the original length.
358func Compact[S ~[]E, E comparable](s S) S {
359	if len(s) < 2 {
360		return s
361	}
362	for k := 1; k < len(s); k++ {
363		if s[k] == s[k-1] {
364			s2 := s[k:]
365			for k2 := 1; k2 < len(s2); k2++ {
366				if s2[k2] != s2[k2-1] {
367					s[k] = s2[k2]
368					k++
369				}
370			}
371
372			clear(s[k:]) // zero/nil out the obsolete elements, for GC
373			return s[:k]
374		}
375	}
376	return s
377}
378
379// CompactFunc is like [Compact] but uses an equality function to compare elements.
380// For runs of elements that compare equal, CompactFunc keeps the first one.
381// CompactFunc zeroes the elements between the new length and the original length.
382func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
383	if len(s) < 2 {
384		return s
385	}
386	for k := 1; k < len(s); k++ {
387		if eq(s[k], s[k-1]) {
388			s2 := s[k:]
389			for k2 := 1; k2 < len(s2); k2++ {
390				if !eq(s2[k2], s2[k2-1]) {
391					s[k] = s2[k2]
392					k++
393				}
394			}
395
396			clear(s[k:]) // zero/nil out the obsolete elements, for GC
397			return s[:k]
398		}
399	}
400	return s
401}
402
403// Grow increases the slice's capacity, if necessary, to guarantee space for
404// another n elements. After Grow(n), at least n elements can be appended
405// to the slice without another allocation. If n is negative or too large to
406// allocate the memory, Grow panics.
407func Grow[S ~[]E, E any](s S, n int) S {
408	if n < 0 {
409		panic("cannot be negative")
410	}
411	if n -= cap(s) - len(s); n > 0 {
412		s = append(s[:cap(s)], make([]E, n)...)[:len(s)]
413	}
414	return s
415}
416
417// Clip removes unused capacity from the slice, returning s[:len(s):len(s)].
418func Clip[S ~[]E, E any](s S) S {
419	return s[:len(s):len(s)]
420}
421
422// TODO: There are other rotate algorithms.
423// This algorithm has the desirable property that it moves each element at most twice.
424// The follow-cycles algorithm can be 1-write but it is not very cache friendly.
425
426// rotateLeft rotates s left by r spaces.
427// s_final[i] = s_orig[i+r], wrapping around.
428func rotateLeft[E any](s []E, r int) {
429	Reverse(s[:r])
430	Reverse(s[r:])
431	Reverse(s)
432}
433func rotateRight[E any](s []E, r int) {
434	rotateLeft(s, len(s)-r)
435}
436
437// overlaps reports whether the memory ranges a[0:len(a)] and b[0:len(b)] overlap.
438func overlaps[E any](a, b []E) bool {
439	if len(a) == 0 || len(b) == 0 {
440		return false
441	}
442	elemSize := unsafe.Sizeof(a[0])
443	if elemSize == 0 {
444		return false
445	}
446	// TODO: use a runtime/unsafe facility once one becomes available. See issue 12445.
447	// Also see crypto/internal/alias/alias.go:AnyOverlap
448	return uintptr(unsafe.Pointer(&a[0])) <= uintptr(unsafe.Pointer(&b[len(b)-1]))+(elemSize-1) &&
449		uintptr(unsafe.Pointer(&b[0])) <= uintptr(unsafe.Pointer(&a[len(a)-1]))+(elemSize-1)
450}
451
452// startIdx returns the index in haystack where the needle starts.
453// prerequisite: the needle must be aliased entirely inside the haystack.
454func startIdx[E any](haystack, needle []E) int {
455	p := &needle[0]
456	for i := range haystack {
457		if p == &haystack[i] {
458			return i
459		}
460	}
461	// TODO: what if the overlap is by a non-integral number of Es?
462	panic("needle not found")
463}
464
465// Reverse reverses the elements of the slice in place.
466func Reverse[S ~[]E, E any](s S) {
467	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
468		s[i], s[j] = s[j], s[i]
469	}
470}
471
472// Concat returns a new slice concatenating the passed in slices.
473func Concat[S ~[]E, E any](slices ...S) S {
474	size := 0
475	for _, s := range slices {
476		size += len(s)
477		if size < 0 {
478			panic("len out of range")
479		}
480	}
481	newslice := Grow[S](nil, size)
482	for _, s := range slices {
483		newslice = append(newslice, s...)
484	}
485	return newslice
486}
487
488// Repeat returns a new slice that repeats the provided slice the given number of times.
489// The result has length and capacity (len(x) * count).
490// The result is never nil.
491// Repeat panics if count is negative or if the result of (len(x) * count)
492// overflows.
493func Repeat[S ~[]E, E any](x S, count int) S {
494	if count < 0 {
495		panic("cannot be negative")
496	}
497
498	const maxInt = ^uint(0) >> 1
499	if hi, lo := bits.Mul(uint(len(x)), uint(count)); hi > 0 || lo > maxInt {
500		panic("the result of (len(x) * count) overflows")
501	}
502
503	newslice := make(S, len(x)*count)
504	n := copy(newslice, x)
505	for n < len(newslice) {
506		n += copy(newslice[n:], newslice[:n])
507	}
508	return newslice
509}
510