From 1a6a7d4a8e2b26caad00d30283ace1f7d2478270 Mon Sep 17 00:00:00 2001 From: David Plowman Date: Tue, 8 Dec 2020 20:44:39 +0000 Subject: ipa: raspberrypi: Compute inverse of piecewise linear function Add a method to the piecewise linear function (Pwl) class to compute the inverse of a given Pwl. If the input function is non-monotonic we can only produce a best effort "pseudo" inverse, and we signal this to the caller. Signed-off-by: David Plowman Reviewed-by: Naushir Patuck Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- src/ipa/raspberrypi/controller/pwl.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'src/ipa/raspberrypi/controller/pwl.cpp') diff --git a/src/ipa/raspberrypi/controller/pwl.cpp b/src/ipa/raspberrypi/controller/pwl.cpp index aa134a1f..130c820b 100644 --- a/src/ipa/raspberrypi/controller/pwl.cpp +++ b/src/ipa/raspberrypi/controller/pwl.cpp @@ -114,6 +114,36 @@ Pwl::PerpType Pwl::Invert(Point const &xy, Point &perp, int &span, return PerpType::None; } +Pwl Pwl::Inverse(bool *true_inverse, const double eps) const +{ + bool appended = false, prepended = false, neither = false; + Pwl inverse; + + for (Point const &p : points_) { + if (inverse.Empty()) + inverse.Append(p.y, p.x, eps); + else if (std::abs(inverse.points_.back().x - p.y) <= eps || + std::abs(inverse.points_.front().x - p.y) <= eps) + /* do nothing */; + else if (p.y > inverse.points_.back().x) { + inverse.Append(p.y, p.x, eps); + appended = true; + } else if (p.y < inverse.points_.front().x) { + inverse.Prepend(p.y, p.x, eps); + prepended = true; + } else + neither = true; + } + + // This is not a proper inverse if we found ourselves putting points + // onto both ends of the inverse, or if there were points that couldn't + // go on either. + if (true_inverse) + *true_inverse = !(neither || (appended && prepended)); + + return inverse; +} + Pwl Pwl::Compose(Pwl const &other, const double eps) const { double this_x = points_[0].x, this_y = points_[0].y; -- cgit v1.2.1