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>
This commit is contained in:
David Plowman 2020-12-08 20:44:39 +00:00 committed by Laurent Pinchart
parent dbcf4d8247
commit 1a6a7d4a8e
2 changed files with 33 additions and 0 deletions

View file

@ -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;

View file

@ -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.