From afa5d01a311bb27d09571b84c91c2e5909dd7c75 Mon Sep 17 00:00:00 2001 From: Mark Liversedge Date: Thu, 26 Mar 2020 10:00:52 +0000 Subject: [PATCH] Datafilter vectors - lowerbound() .. lowerbound(v, value) - returns the index into v for the first element that does not evaluate to < value. This is a binary search modelled after std::lower_bound (and uses it in the implementation too) --- src/Core/DataFilter.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/Core/DataFilter.cpp b/src/Core/DataFilter.cpp index 0ea4a349b..2d3812f22 100644 --- a/src/Core/DataFilter.cpp +++ b/src/Core/DataFilter.cpp @@ -209,6 +209,10 @@ static struct { // will need to be on a user chart, and the series will need to have already // been computed. + { "lowerbound", 2 }, // lowerbound(list, value) - returns the index of the first entry in list + // that does not compare less than value, analogous to std::lower_bound + // will return -1 if no value found. + // add new ones above this line { "", -1 } @@ -357,6 +361,10 @@ DataFilter::builtins() returning << "curve(series, x|y|z|d|t)"; + } else if (i == 72) { + + returning << "lowerbound(list, value"; + } else { QString function; @@ -1701,6 +1709,17 @@ void Leaf::validateFilter(Context *context, DataFilterRuntime *df, Leaf *leaf) } } + } else if (leaf->function == "lowerbound") { + + if (leaf->fparms.count() != 2) { + leaf->inerror = true; + DataFiltererrors << QString(tr("lowerbound(list, value), need list and value to find")); + + } else { + validateFilter(context, df, leaf->fparms[0]); + validateFilter(context, df, leaf->fparms[1]); + } + } else if (leaf->function == "lr") { if (leaf->fparms.count() != 2) { @@ -2383,6 +2402,9 @@ Result::vectorize(int count) } } +// used by lowerbound +struct comparedouble { bool operator()(const double p1, const double p2) { return p1 < p2; } }; + Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem *m, RideFilePoint *p, const QHash *c, Specification s, DateRange d) { // if error state all bets are off @@ -3070,6 +3092,24 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem return returning; } + // lowerbound + if (leaf->function == "lowerbound") { + + Result returning(-1); + + Result list= eval(df, leaf->fparms[0],x, it, m, p, c, s, d); + Result value= eval(df, leaf->fparms[1],x, it, m, p, c, s, d); + + // empty list - error + if (list.vector.count() == 0) return returning; + + // lets do it with std::lower_bound then + QVector::const_iterator i = std::lower_bound(list.vector.begin(), list.vector.end(), value.number, comparedouble()); + + if (i == list.vector.end()) return Result(list.vector.size()); + return Result(i - list.vector.begin()); + } + // sort if (leaf->function == "sort") {