summaryrefslogtreecommitdiff
path: root/src/ipa/libipa/pwl.h
blob: 8edb4d33dc71a346d56508398b8f65d953001e7c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/* SPDX-License-Identifier: BSD-2-Clause */
/*
 * Copyright (C) 2019, Raspberry Pi Ltd
 *
 * Piecewise linear functions interface
 */
#pragma once

#include <algorithm>
#include <cmath>
#include <functional>
#include <string>
#include <utility>
#include <vector>

#include "libcamera/internal/yaml_parser.h"

#include "vector.h"

namespace libcamera {

namespace ipa {

class Pwl
{
public:
	using Point = Vector<double, 2>;

	struct Interval {
		Interval(double _start, double _end)
			: start(_start), end(_end) {}

		bool contains(double value)
		{
			return value >= start && value <= end;
		}

		double clamp(double value)
		{
			return std::clamp(value, start, end);
		}

		double length() const { return end - start; }

		double start, end;
	};

	Pwl();
	Pwl(const std::vector<Point> &points);
	Pwl(std::vector<Point> &&points);

	int readYaml(const libcamera::YamlObject &params);

	void append(double x, double y, double eps = 1e-6);

	bool empty() const { return points_.empty(); }
	size_t size() const { return points_.size(); }

	Interval domain() const;
	Interval range() const;

	double eval(double x, int *span = nullptr,
		    bool updateSpan = true) const;

	std::pair<Pwl, bool> inverse(double eps = 1e-6) const;
	Pwl compose(const Pwl &other, double eps = 1e-6) const;

	void map(std::function<void(double x, double y)> f) const;

	static Pwl
	combine(const Pwl &pwl0, const Pwl &pwl1,
		std::function<double(double x, double y0, double y1)> f,
		double eps = 1e-6);

	Pwl &operator*=(double d);

	std::string toString() const;

private:
	static void map2(const Pwl &pwl0, const Pwl &pwl1,
			 std::function<void(double x, double y0, double y1)> f);
	void prepend(double x, double y, double eps = 1e-6);
	int findSpan(double x, int span) const;

	std::vector<Point> points_;
};

} /* namespace ipa */

} /* namespace libcamera */