138 if (
X.size() != Y.size()) {
139 std::cerr <<
"Error in function " << __FUNCTION__
140 <<
": Vectors X (of size " <<
X.size()
141 <<
") and Y (of size " << Y.size()
142 <<
") are not the same size. Returning an empty array..." << std::endl;
152 if (std::holds_alternative<typename Types::NotAKnotStart>(
type)) {
154 }
else if (std::holds_alternative<typename Types::NotAKnotEnd>(
type)) {
156 }
else if (std::holds_alternative<typename Types::SemiNotAKnot>(
type)) {
158 }
else if (std::holds_alternative<typename Types::NaturalStart>(
type)) {
160 }
else if (std::holds_alternative<typename Types::NaturalEnd>(
type)) {
162 }
else if (std::holds_alternative<typename Types::SemiNatural>(
type)) {
164 }
else if (std::holds_alternative<typename Types::SemiSemi>(
type)) {
166 }
else if (
const auto* cs = std::get_if<typename Types::ClampedStart>(&
type)) {
168 }
else if (
const auto* ce = std::get_if<typename Types::ClampedEnd>(&
type)) {
170 }
else if (
const auto* sc = std::get_if<typename Types::SemiClamped>(&
type)) {
172 }
else if (
const auto* fss = std::get_if<typename Types::FixedSecondStart>(&
type)) {
174 }
else if (
const auto* fse = std::get_if<typename Types::FixedSecondEnd>(&
type)) {
176 }
else if (
const auto* sfs = std::get_if<typename Types::SemiFixedSecond>(&
type)) {
180 Container<Number>
coeffs(3 * (n - 1));
184 SizeT i1 = 0, i2 = n - 1;
186 if (
const auto* clamped = std::get_if<typename Types::Clamped>(&
type)) {
187 const auto i = clamped->point_idx;
188 if (i < 0 || i >= n) {
189 std::cerr <<
"Error in function " << __FUNCTION__
190 <<
": point index for type 'Clamped' is out of bounds: "
191 <<
"expected to be non-negative and less than " << n <<
", but got " << i
192 <<
". Returning an empty array..." << std::endl;
196 const auto dx1 =
X[i] -
X[i-1], dy1 = Y[i] - Y[i-1];
197 coeffs[3*(i-1)+2] = Y[i-1];
198 coeffs[3*(i-1)+1] = 2*dy1/dx1 - clamped->df;
203 const auto dx =
X[i+1] -
X[i], dy = Y[i+1] - Y[i];
205 coeffs[3*i+1] = clamped->df;
209 }
else if (
const auto* fixed_second = std::get_if<typename Types::FixedSecond>(&
type)) {
210 const auto i = fixed_second->segment_idx;
211 if (i < 0 || i >= n - 1) {
212 std::cerr <<
"Error in function " << __FUNCTION__
213 <<
": segment index for type 'FixedSecond' is out of bounds: "
214 <<
"expected to be non-negative and less than " << n - 1 <<
", but got " << i
215 <<
". Returning an empty array..." << std::endl;
218 coeffs[3*i] = fixed_second->d2f / 2;
223 }
else if (
const auto* not_a_knot = std::get_if<typename Types::NotAKnot>(&
type)) {
227 const auto i = not_a_knot->point_idx;
228 if (i < 1 || i >= n - 1) {
229 std::cerr <<
"Error in function " << __FUNCTION__
230 <<
": point index for type 'NotAKnot' is out of bounds: "
231 <<
"expected to be positive and less than " << n - 1 <<
", but got " << i
232 <<
". Returning an empty array..." << std::endl;
235 const auto dx1 =
X[i] -
X[i-1], dy1 = Y[i] - Y[i-1];
236 const auto dx =
X[i+1] -
X[i], dy = Y[i+1] - Y[i];
237 coeffs[3*(i-1)+2] = Y[i-1];
239 coeffs[3*(i-1)] =
coeffs[3*i] = (dy/dx - dy1/dx1) / (dx1 + dx);
245 std::cerr <<
"Error in function " << __FUNCTION__ <<
": Unknown type. This should not have happened. "
246 <<
"Please report this to the developers. Returning an empty array..." << std::endl;
250 for (
SizeT iter = 0; iter < i1; ++iter) {
251 const auto i = i1 - 1 - iter;
252 const auto dx =
X[i+1] -
X[i], dy = Y[i+1] - Y[i];
258 for (
SizeT i = i2; i < n - 1; ++i) {
259 const auto dx =
X[i+1] -
X[i], dy = Y[i+1] - Y[i];
270 template <
typename ContainerXType>
281 template <
typename ContainerXType>
283 if (
X.size() != Y.size()) {
284 std::cerr <<
"Error in function " << __FUNCTION__
285 <<
": Vectors X (of size " <<
X.size()
286 <<
") and Y (of size " << Y.size()
287 <<
") are not the same size. Doing nothing..." << std::endl;
291 if (
coeffs.empty() && !
X.empty()) {
292 std::cerr <<
"Error in function " << __FUNCTION__
293 <<
": failed to construct coefficients. Not changing the object..." << std::endl;
297 _X = std::forward<ContainerXType>(
X);
298 _coeffs = std::move(
coeffs);
305 if (_coeffs.empty()) {
307 }
else if (_coeffs.size() == 1) {
315 Container<Number>
eval(
const Container<Number>& xx,
bool sorted =
true)
const {
316 Container<Number> result(xx.size());
318 for (
SizeT i = 0, i_x = 0; i < xx.size(); ++i) {
319 const Number x = xx[i];
320 while (i_x + 1 < _X.size() && x >= _X[i_x+1])
322 result[i] =
eval(x, i_x);
325 for (
SizeT i = 0; i < xx.size(); ++i) {
326 result[i] =
eval(xx[i]);
335 Container<Number>
operator()(
const Container<Number>& xx)
const {
343 const Container<Number>&
X() const & {
346 Container<Number>&&
X() && {
347 return std::move(_X);
350 const Container<Number>&
coeffs() const & {
354 return std::move(_coeffs);
358 return {3*index, 3*(index+1)};
363 Container<Number> _X = {};
364 Container<Number> _coeffs = {};
QuadraticSpline(ContainerXType &&X, const Container< Number > &Y, Type type=typename Types::Default{})
Definition quadratic.h:271
Number eval(Number x) const
Definition quadratic.h:301
Container< Number > && X() &&
Definition quadratic.h:346
static Container< Number > compute_coeffs(const Container< Number > &X, const Container< Number > &Y, Type type=typename Types::Default{})
Definition quadratic.h:137
Container< Number > operator()(const Container< Number > &xx) const
Definition quadratic.h:335
const Container< Number > & X() const &
Definition quadratic.h:343
Container< Number > && coeffs() &&
Definition quadratic.h:353
QuadraticSpline & operator=(const QuadraticSpline &other)=default
void construct(ContainerXType &&X, const Container< Number > &Y, Type type=typename Types::Default{})
Definition quadratic.h:282
std::variant< typename Types::NotAKnotStart, typename Types::NotAKnotEnd, typename Types::SemiNotAKnot, typename Types::NaturalStart, typename Types::NaturalEnd, typename Types::SemiNatural, typename Types::SemiSemi, typename Types::ClampedStart, typename Types::ClampedEnd, typename Types::SemiClamped, typename Types::FixedSecondStart, typename Types::FixedSecondEnd, typename Types::SemiFixedSecond, typename Types::Clamped, typename Types::FixedSecond, typename Types::NotAKnot > Type
Definition quadratic.h:120
QuadraticSpline & operator=(QuadraticSpline &&other) noexcept=default
Number operator()(Number x) const
Definition quadratic.h:332
Container< Number > eval(const Container< Number > &xx, bool sorted=true) const
Definition quadratic.h:315
QuadraticSpline()=default
QuadraticSpline(const QuadraticSpline &other)=default
static std::pair< SizeT, SizeT > segment(SizeT index)
Definition quadratic.h:357
const Container< Number > & coeffs() const &
Definition quadratic.h:350
QuadraticSpline(QuadraticSpline &&other) noexcept=default
Number eval(Number x, SizeT segment) const
Definition quadratic.h:304
Type type() const
Definition quadratic.h:339
Container< Number > mean(const Container< Number > &container1, const Container< Number > &container2)
Definition arrays.h:55
Iterator first_leq_or_begin(Iterator begin, Iterator end, const T &value)
Definition misc.h:27
Container< Number > simple_spline(const Container< Number > &X, const Container< Number > &Y, SizeT degree)
Definition spline.h:10
ALFI_DEFAULT_NUMBER DefaultNumber
Definition config.h:17
ALFI_SIZE_TYPE SizeT
Definition config.h:22
ALFI_DEFAULT_CONTAINER< Number > DefaultContainer
Definition config.h:20
Definition quadratic.h:60
ClampedEnd(Number df)
Definition quadratic.h:61
Number df
Definition quadratic.h:62
Definition quadratic.h:53
Number df
Definition quadratic.h:55
ClampedStart(Number df)
Definition quadratic.h:54
Definition quadratic.h:95
Clamped(SizeT point_idx, Number df)
Definition quadratic.h:96
SizeT point_idx
Definition quadratic.h:97
Number df
Definition quadratic.h:98
Definition quadratic.h:81
Number d2f
Definition quadratic.h:83
FixedSecondEnd(Number d2f)
Definition quadratic.h:82
Definition quadratic.h:74
Number d2f
Definition quadratic.h:76
FixedSecondStart(Number d2f)
Definition quadratic.h:75
Definition quadratic.h:103
Number d2f
Definition quadratic.h:106
SizeT segment_idx
Definition quadratic.h:105
FixedSecond(SizeT segment_idx, Number d2f)
Definition quadratic.h:104
Definition quadratic.h:41
Definition quadratic.h:37
Definition quadratic.h:29
Definition quadratic.h:23
Definition quadratic.h:113
SizeT point_idx
Definition quadratic.h:115
NotAKnot(SizeT point_idx)
Definition quadratic.h:114
Definition quadratic.h:67
Number df_1
Definition quadratic.h:69
Number df_n
Definition quadratic.h:69
SemiClamped(Number df_1, Number df_n)
Definition quadratic.h:68
Definition quadratic.h:88
Number d2f_1
Definition quadratic.h:90
SemiFixedSecond(Number d2f_1, Number d2f_n)
Definition quadratic.h:89
Number d2f_n
Definition quadratic.h:90
Definition quadratic.h:45
Definition quadratic.h:33
Definition quadratic.h:49
Definition quadratic.h:17
SemiNotAKnot Default
Definition quadratic.h:117