1 module nxt.overlapping;
2 
3 pure nothrow @safe @nogc:
4 
5 /** Returns: Slice Overlap of $(D a) and $(D b) in order given by arguments.
6  */
7 inout(T)[] overlapsInOrder(T)(inout(T)[] a,
8 							  inout(T)[] b)
9 	@trusted pure nothrow @nogc
10 {
11 	if (a.ptr <= b.ptr &&	   // if a-start lies at or before b-start
12 		b.ptr < a.ptr + a.length) // if b-start lies before b-end
13 	{
14 		import std.algorithm: min, max;
15 		immutable low = max(a.ptr, b.ptr) - a.ptr;
16 		const n = min(b.length,
17 					  (b.ptr - a.ptr + 1)); // overlap length
18 		return a[low..low + n];
19 	}
20 	else
21 	{
22 		return [];
23 	}
24 }
25 
26 /** Helper for overlap().
27 	Copied from std.array with simplified return expression.
28  */
29 bool overlaps(T)(in T[] r1,
30 				 in T[] r2)
31 	@trusted pure nothrow @nogc
32 {
33 	alias U = inout(T);
34 	static U* max(U* a, U* b) nothrow { return a > b ? a : b; }
35 	static U* min(U* a, U* b) nothrow { return a < b ? a : b; }
36 
37 	auto b = max(r1.ptr, r2.ptr);
38 	auto e = min(r1.ptr + r1.length,
39 				 r2.ptr + r2.length);
40 	return b < e;
41 }
42 
43 ///
44 unittest {
45 	auto x = [-11_111, 11, 22, 333_333].s;
46 	const y = [-22_222, 441, 555, 66].s;
47 
48 	assert(!overlaps(x, y));
49 	assert(!overlaps(y, x));
50 
51 	auto x01 = x[0..1];
52 	auto x12 = x[1..2];
53 	auto x23 = x[2..3];
54 
55 	assert(overlaps(x, x12));
56 	assert(overlaps(x, x01));
57 	assert(overlaps(x, x23));
58 	assert(overlaps(x01, x));
59 	assert(overlaps(x12, x));
60 	assert(overlaps(x23, x));
61 }
62 
63 /** Returns: Slice Overlap of $(D a) and $(D b) in any order.
64 	Deprecated by: std.array.overlap
65  */
66 inout(T[]) overlap(T)(inout(T[]) a,
67 					  inout(T[]) b) /* @safe pure nothrow */
68 	pure nothrow @safe @nogc
69 {
70 	if (inout(T[]) ab = overlapsInOrder(a, b))
71 	{
72 		return ab;
73 	}
74 	else if (inout(T[]) ba = overlapsInOrder(b, a))
75 	{
76 		return ba;
77 	}
78 	else
79 	{
80 		return [];
81 	}
82 }
83 
84 ///
85 unittest {
86 	auto x = [-11_111, 11, 22, 333_333].s;
87 	const y = [-22_222, 441, 555, 66].s;
88 
89 	assert(!overlap(x, y));
90 	assert(!overlap(y, x));
91 
92 	auto x01 = x[0..1];
93 	auto x12 = x[1..2];
94 	auto x23 = x[2..3];
95 
96 	// sub-ranges should overlap completely
97 	assert(overlap(x, x12) == x12);
98 	assert(overlap(x, x01) == x01);
99 	assert(overlap(x, x23) == x23);
100 	// and commutate f(a,b) == f(b,a)
101 	assert(overlap(x01, x) == x01);
102 	assert(overlap(x12, x) == x12);
103 	assert(overlap(x23, x) == x23);
104 }
105 
106 version (unittest)
107 {
108 	import nxt.array_help : s;
109 }