diff --git a/Packages/MIES/MIES_Utilities.ipf b/Packages/MIES/MIES_Utilities.ipf index 9193745d82..92c78b992a 100644 --- a/Packages/MIES/MIES_Utilities.ipf +++ b/Packages/MIES/MIES_Utilities.ipf @@ -6876,3 +6876,39 @@ Function/WAVE FlattenWaves(WAVE/WAVE input, [variable sdim]) return output End + +/// @brief Return the truth if any of the given intervals [A, B] intersect. +/// +/// Intervals only "touching" are not considered intersecting. +threadsafe Function AreIntervalsIntersecting(WAVE rangesParam) + + variable numRows, i + + ASSERT_TS(IsNumericWave(rangesParam), "Expected a numeric wave") + + numRows = DimSize(rangesParam, ROWS) + // two columns: start, end + ASSERT_TS(DimSize(rangesParam, COLS) == 2, "Expected exactly two columns") + + if(numRows <= 1) + return 0 + endif + + // sort start column in ascending order + Duplicate/FREE rangesParam, ranges + WaveClear rangesParam + SortColumns/KNDX={0} sortWaves=ranges + + for(i = 0; i < numRows; i += 1) + ASSERT_TS(IsFinite(ranges[i][0]) && IsFinite(ranges[i][1]), "Expected finite entries") + ASSERT_TS(ranges[i][0] < ranges[i][1], "Invalid entry sorting") + + // check that every interval, starting from the second interval + // starts later than the previous one ends + if(i > 0 && ranges[i][0] < ranges[i - 1][1]) + return 1 + endif + endfor + + return 0 +End diff --git a/Packages/tests/Basic/UTF_Utils.ipf b/Packages/tests/Basic/UTF_Utils.ipf index 42b5d3c6a2..3a540c0633 100644 --- a/Packages/tests/Basic/UTF_Utils.ipf +++ b/Packages/tests/Basic/UTF_Utils.ipf @@ -7580,3 +7580,76 @@ static Function TestFlattenWaves() CHECK_EMPTY_FOLDER() End + +static Function TestAreIntervalsIntersecting() + + // wrong wave type + try + Make/FREE/T wvText + AreIntervalsIntersecting(wvText) + FAIL() + catch + CHECK_NO_RTE() + endtry + + // 1D wave + try + Make/FREE wv + AreIntervalsIntersecting(wv) + FAIL() + catch + CHECK_NO_RTE() + endtry + + // trivial case #1: empty + Make/FREE/N=(0, 2) empty + CHECK_EQUAL_VAR(0, AreIntervalsIntersecting(empty)) + + // trivial case #2: only one interval + Make/FREE single = {{1}, {2}} + CHECK_EQUAL_VAR(0, AreIntervalsIntersecting(single)) + + // contains infinite values (start) + Make/FREE infValues = {{1, inf}, {2, 4}} + + try + AreIntervalsIntersecting(infValues) + FAIL() + catch + CHECK_NO_RTE() + endtry + + // contains infinite values (end) + Make/FREE infValues = {{1, 3}, {2, inf}} + + try + AreIntervalsIntersecting(infValues) + FAIL() + catch + CHECK_NO_RTE() + endtry + + // invalid ordering + Make/FREE invalidOrder = {{2, 3}, {1, 4}} + + try + AreIntervalsIntersecting(invalidOrder) + FAIL() + catch + CHECK_NO_RTE() + endtry + + // works + Make/FREE data = {{1, 3}, {2, 4}} + CHECK(!AreIntervalsIntersecting(data)) + + // intervals which have start == end is okay + Make/FREE data = {{1, 2}, {2, 3}} + CHECK(!AreIntervalsIntersecting(data)) + + Make/FREE data = {{2.5, 1, 2.7}, {2.6, 2.4, 4}} + CHECK(!AreIntervalsIntersecting(data)) + + Make/FREE data = {{2, 1}, {3, 4}} + CHECK(AreIntervalsIntersecting(data)) +End