masker

ditto

  1. auto masker(R1 intervals, R2 boundaries)
  2. auto masker(R1 intervals, R2 boundaries)
  3. auto masker(R1 intervals, R2 boundaries)
    @safe
    masker
    (
    alias begin
    alias end
    R1
    R2 = R1
    )
    (,
    R2 boundaries = R2.init
    )
    if (
    isInputRange!R1 &&
    isInputRange!R2
    &&
    is(ElementType!R1 == ElementType!R2)
    )

Examples

alias Interval = Tuple!(size_t, "begin", size_t, "end");

auto mask = masker!(
    "a.begin",
    "a.end",
)(
    [
        Interval(1, 5),
        Interval(2, 6),
        Interval(3, 6),
        Interval(2, 4),
        Interval(8, 9),
    ],
    [Interval(0, 10)],
);

alias I = mask.FrontType;
assert(equal(mask, [
    I(0, 1, 0),
    I(1, 6, 1),
    I(6, 8, 0),
    I(8, 9, 1),
    I(9, 10, 0),
]), investigateMask(mask, "mask does not match"));

Custom category function:

alias Interval = Tuple!(size_t, "begin", size_t, "end");

enum Coverage
{
    zero,
    normal,
    high,
}
auto mask = masker!(
    "a.begin",
    "a.end",
    level => level >= 3
        ? Coverage.high
        : (level > 0
            ? Coverage.normal
            : Coverage.zero
        )
)(
    [
        Interval(1, 5),
        Interval(2, 6),
        Interval(3, 6),
        Interval(2, 4),
        Interval(8, 9),
    ],
    [Interval(0, 10)],
);

alias I = mask.FrontType;
assert(equal(mask, [
    I(0, 1, Coverage.zero),
    I(1, 2, Coverage.normal),
    I(2, 5, Coverage.high),
    I(5, 6, Coverage.normal),
    I(6, 8, Coverage.zero),
    I(8, 9, Coverage.normal),
    I(9, 10, Coverage.zero),
]), investigateMask(mask, "mask does not match"));

The acc function is called once for every opening interval:

alias Interval = Tuple!(size_t, "begin", size_t, "end");

auto mask = masker!(
    "a.begin",
    "a.end",
    sgn,
    "++a",
    size_t
)(
    [
        Interval(1, 5),
        Interval(2, 6),
        Interval(3, 6),
        Interval(2, 4),
        Interval(8, 9),
    ],
    [Interval(0, 10)],
);

alias I = mask.FrontType;
assert(equal(mask, [
    I(0, 1, 0, 0),
    I(1, 6, 1, 4),
    I(6, 8, 0, 0),
    I(8, 9, 1, 1),
    I(9, 10, 0, 0),
]), investigateMask(mask, "mask does not match"));

If the intervals range has pointer type elements then the accumulator may access them:payloadSum

alias Interval = Tuple!(size_t, "begin", size_t, "end", int, "payload");

int payloadSum(int acc, const Interval* interval)
{
    return acc + interval.payload;
}

auto mask = masker!(
    "a.begin",
    "a.end",
    sgn,
    payloadSum,
    int,
)(
    [
        new Interval(1, 5, 1),
        new Interval(2, 6, -2),
        new Interval(3, 6, 3),
        new Interval(2, 4, -4),
        new Interval(8, 9, 5),
    ],
    [new Interval(0, 10, 0)],
);

alias I = mask.FrontType;
assert(equal(mask, [
    I(0, 1, 0, 0),
    I(1, 6, 1, -2),
    I(6, 8, 0, 0),
    I(8, 9, 1, 5),
    I(9, 10, 0, 0),
]), investigateMask(mask, "mask does not match"));

Meta