summaryrefslogtreecommitdiff
path: root/src/ipa/raspberrypi/controller
diff options
context:
space:
mode:
authorDavid Plowman <david.plowman@raspberrypi.com>2020-12-08 20:44:39 +0000
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2020-12-11 23:31:23 +0200
commit1a6a7d4a8e2b26caad00d30283ace1f7d2478270 (patch)
tree19d7e31a4c790e4e96e689468c4387d58fd1ae08 /src/ipa/raspberrypi/controller
parentdbcf4d82473936ce1cfaac0613fba99fb592c957 (diff)
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 <david.plowman@raspberrypi.com> Reviewed-by: Naushir Patuck <naush@raspberrypi.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'src/ipa/raspberrypi/controller')
-rw-r--r--src/ipa/raspberrypi/controller/pwl.cpp30
-rw-r--r--src/ipa/raspberrypi/controller/pwl.hpp3
2 files changed, 33 insertions, 0 deletions
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;
diff --git a/src/ipa/raspberrypi/controller/pwl.hpp b/src/ipa/raspberrypi/controller/pwl.hpp
index 4f168551..484672f6 100644
--- a/src/ipa/raspberrypi/controller/pwl.hpp
+++ b/src/ipa/raspberrypi/controller/pwl.hpp
@@ -80,6 +80,9 @@ public:
};
PerpType Invert(Point const &xy, Point &perp, int &span,
const double eps = 1e-6) const;
+ // Compute the inverse function. Indicate if it is a proper (true)
+ // inverse, or only a best effort (e.g. input was non-monotonic).
+ Pwl Inverse(bool *true_inverse = nullptr, const double eps = 1e-6) const;
// Compose two Pwls together, doing "this" first and "other" after.
Pwl Compose(Pwl const &other, const double eps = 1e-6) const;
// Apply function to (x,y) values at every control point.