1 module nxt.overlapping;
2 
3 @safe pure nothrow @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 {
46     auto x = [-11_111, 11, 22, 333_333].s;
47     const y = [-22_222, 441, 555, 66].s;
48 
49     assert(!overlaps(x, y));
50     assert(!overlaps(y, x));
51 
52     auto x01 = x[0..1];
53     auto x12 = x[1..2];
54     auto x23 = x[2..3];
55 
56     assert(overlaps(x, x12));
57     assert(overlaps(x, x01));
58     assert(overlaps(x, x23));
59     assert(overlaps(x01, x));
60     assert(overlaps(x12, x));
61     assert(overlaps(x23, x));
62 }
63 
64 /** Returns: Slice Overlap of $(D a) and $(D b) in any order.
65     Deprecated by: std.array.overlap
66  */
67 inout(T[]) overlap(T)(inout(T[]) a,
68                       inout(T[]) b) /* @safe pure nothrow */
69     @safe pure nothrow @nogc
70 {
71     if (inout(T[]) ab = overlapsInOrder(a, b))
72     {
73         return ab;
74     }
75     else if (inout(T[]) ba = overlapsInOrder(b, a))
76     {
77         return ba;
78     }
79     else
80     {
81         return [];
82     }
83 }
84 
85 ///
86 unittest
87 {
88     auto x = [-11_111, 11, 22, 333_333].s;
89     const y = [-22_222, 441, 555, 66].s;
90 
91     assert(!overlap(x, y));
92     assert(!overlap(y, x));
93 
94     auto x01 = x[0..1];
95     auto x12 = x[1..2];
96     auto x23 = x[2..3];
97 
98     // sub-ranges should overlap completely
99     assert(overlap(x, x12) == x12);
100     assert(overlap(x, x01) == x01);
101     assert(overlap(x, x23) == x23);
102     // and commutate f(a,b) == f(b,a)
103     assert(overlap(x01, x) == x01);
104     assert(overlap(x12, x) == x12);
105     assert(overlap(x23, x) == x23);
106 }
107 
108 version(unittest)
109 {
110     import nxt.array_help : s;
111 }