Directory: | ./ |
---|---|
File: | include/ndcurves/bernstein.h |
Date: | 2025-03-05 17:18:30 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 26 | 29 | 89.7% |
Branches: | 17 | 32 | 53.1% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /** | ||
2 | * \file bezier_curve.h | ||
3 | * \brief class allowing to create a Bezier curve of dimension 1 <= n <= 3. | ||
4 | * \author Steve T. | ||
5 | * \version 0.1 | ||
6 | * \date 06/17/2013 | ||
7 | */ | ||
8 | |||
9 | #ifndef _CLASS_BERNSTEIN | ||
10 | #define _CLASS_BERNSTEIN | ||
11 | |||
12 | #include <math.h> | ||
13 | |||
14 | #include <stdexcept> | ||
15 | #include <vector> | ||
16 | |||
17 | #include "MathDefs.h" | ||
18 | #include "curve_abc.h" | ||
19 | |||
20 | namespace ndcurves { | ||
21 | /// \brief Computes a binomial coefficient . | ||
22 | /// \param n : an unsigned integer. | ||
23 | /// \param k : an unsigned integer. | ||
24 | /// \return \f$\binom{n}{k}f$ | ||
25 | /// | ||
26 | 50016 | inline unsigned int bin(const unsigned int n, const unsigned int k) { | |
27 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 50016 times.
|
50016 | if (k > n) |
28 | ✗ | throw std::runtime_error("binomial coefficient higher than degree"); | |
29 |
2/2✓ Branch 0 taken 22498 times.
✓ Branch 1 taken 27518 times.
|
50016 | if (k == 0) return 1; |
30 |
2/2✓ Branch 0 taken 10345 times.
✓ Branch 1 taken 17173 times.
|
27518 | if (k > n / 2) return bin(n, n - k); |
31 | 17173 | return n * bin(n - 1, k - 1) / k; | |
32 | } | ||
33 | |||
34 | /// \class Bernstein. | ||
35 | /// \brief Computes a Bernstein polynomial. | ||
36 | /// | ||
37 | template <typename Numeric = double> | ||
38 | struct Bern { | ||
39 | 92 | Bern() {} | |
40 | 22192 | Bern(const unsigned int m, const unsigned int i) | |
41 | 22192 | : m_minus_i(m - i), i_(i), bin_m_i_(bin(m, i)) {} | |
42 | |||
43 | 139182 | virtual ~Bern() {} | |
44 | |||
45 | /// \brief Evaluation of Bernstein polynomial at value u. | ||
46 | /// \param u : value between 0 and 1. | ||
47 | /// \return Evaluation corresponding at value u. | ||
48 | 1200070 | Numeric operator()(const Numeric u) const { | |
49 |
2/4✓ Branch 0 taken 1200070 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1200070 times.
|
1200070 | if (!(u >= 0. && u <= 1.)) { |
50 | ✗ | throw std::invalid_argument("u needs to be betwen 0 and 1."); | |
51 | } | ||
52 | 1200070 | return bin_m_i_ * (pow(u, i_))*pow((1 - u), m_minus_i); | |
53 | } | ||
54 | |||
55 | /// \brief Check if actual Bernstein polynomial and other are approximately | ||
56 | /// equal. \param other : the other Bernstein polynomial to check. \return | ||
57 | /// true if the two Bernstein polynomials are approximately equals. | ||
58 | 110 | virtual bool operator==(const Bern& other) const { | |
59 |
1/2✓ Branch 1 taken 110 times.
✗ Branch 2 not taken.
|
220 | return ndcurves::isApprox<Numeric>(m_minus_i, other.m_minus_i) && |
60 |
2/4✓ Branch 0 taken 110 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 110 times.
✗ Branch 4 not taken.
|
220 | ndcurves::isApprox<Numeric>(i_, other.i_) && |
61 | 220 | ndcurves::isApprox<Numeric>(bin_m_i_, other.bin_m_i_); | |
62 | } | ||
63 | |||
64 | /// \brief Check if actual Bernstein polynomial and other are different. | ||
65 | /// \param other : the other Bernstein polynomial to check. | ||
66 | /// \return true if the two Bernstein polynomials are different. | ||
67 | ✗ | virtual bool operator!=(const Bern& other) const { return !(*this == other); } | |
68 | |||
69 | /* Attributes */ | ||
70 | Numeric m_minus_i; | ||
71 | Numeric i_; | ||
72 | Numeric bin_m_i_; | ||
73 | /* Attributes */ | ||
74 | |||
75 | // Serialization of the class | ||
76 | friend class boost::serialization::access; | ||
77 | template <class Archive> | ||
78 | 368 | void serialize(Archive& ar, const unsigned int version) { | |
79 | if (version) { | ||
80 | // Do something depending on version ? | ||
81 | } | ||
82 |
1/2✓ Branch 2 taken 184 times.
✗ Branch 3 not taken.
|
368 | ar& boost::serialization::make_nvp("m_minus_i", m_minus_i); |
83 |
1/2✓ Branch 2 taken 184 times.
✗ Branch 3 not taken.
|
368 | ar& boost::serialization::make_nvp("i", i_); |
84 |
1/2✓ Branch 2 taken 184 times.
✗ Branch 3 not taken.
|
368 | ar& boost::serialization::make_nvp("bin_m_i", bin_m_i_); |
85 | 368 | } | |
86 | }; // End struct Bern | ||
87 | |||
88 | /// \brief Computes all Bernstein polynomes for a certain degree. | ||
89 | /// | ||
90 | template <typename Numeric> | ||
91 | 6045 | std::vector<Bern<Numeric> > makeBernstein(const unsigned int n) { | |
92 | 6045 | std::vector<Bern<Numeric> > res; | |
93 |
2/2✓ Branch 0 taken 22192 times.
✓ Branch 1 taken 6045 times.
|
28237 | for (unsigned int i = 0; i <= n; ++i) { |
94 |
2/4✓ Branch 1 taken 22192 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 22192 times.
✗ Branch 5 not taken.
|
22192 | res.push_back(Bern<Numeric>(n, i)); |
95 | } | ||
96 | 6045 | return res; | |
97 | } | ||
98 | } // namespace ndcurves | ||
99 | |||
100 | DEFINE_CLASS_TEMPLATE_VERSION(typename Numeric, ndcurves::Bern<Numeric>) | ||
101 | |||
102 | #endif //_CLASS_BERNSTEIN | ||
103 |