fitpack
Modern Fortran library for curve and surface fitting with splines
Loading...
Searching...
No Matches
fpCurve.hpp
Go to the documentation of this file.
1/***************************************************************************************************
2! ____________________ ___ ________ __
3! / ____/ _/_ __/ __ \/ | / ____/ //_/
4! / /_ / / / / / /_/ / /| |/ / / ,<
5! / __/ _/ / / / / ____/ ___ / /___/ /| |
6! /_/ /___/ /_/ /_/ /_/ |_\____/_/ |_|
7!
8! A Curve Fitting Package
9!
10! fpCurve.hpp (class fpCurve)
11!> @brief Standalone C++ wrapper for fitpack_curve (no fortran-arrays dependency)
12!
13! @author Federico Perini
14! @date 2026-08-27
15!
16! References :
17! - C. De Boor, "On calculating with b-splines", J Approx Theory 6 (1972) 50-62
18! - M. G. Cox, "The numerical evaluation of b-splines", J Inst Maths Applics 10 (1972) 134-149
19! - P. Dierckx, "Curve and surface fitting with splines", Monographs on numerical analysis,
20! Oxford university press, 1993.
21!
22! **************************************************************************************************/
23
24#ifndef FPCURVE_HPP_INCLUDED
25#define FPCURVE_HPP_INCLUDED
26
27#include "fitpack_config.h"
28
29#if HAVE_FXARRAY
30#include "fxArrays.hpp"
31#endif
32
33#include "fitpack_curve_c.h"
34#include "fpFitter.hpp"
35#include <string>
36#include <vector>
37#include <cstdint>
38#include <memory>
39#include <stdexcept>
40#include <variant>
41#include <optional>
42#include <array>
43#include "fpPoint.hpp"
44
45static_assert(sizeof(fitpack_curve_c) == sizeof(fitpack_fitter_c),
46 "C descriptor layout mismatch: fitpack_curve_c vs fitpack_fitter_c");
47
56class fpCurve : public fpFitter {
57public:
58 // ===========================================================================================
59 // Constructors and Destructor
60 // ===========================================================================================
61
66 fitpack_curve_c_allocate(as<fitpack_curve_c>(), nullptr);
67 }
68
72 ~fpCurve() override {
73 fitpack_curve_c_destroy(as<fitpack_curve_c>(), nullptr);
74 }
75
79 fpCurve(const fpCurve& other) : fpFitter(NoAlloc{}) {
80 *as<fitpack_curve_c>() = fitpack_curve_c_null;
81 fitpack_curve_c_copy(as<fitpack_curve_c>(), other.as<fitpack_curve_c>(), false, nullptr);
82 }
83
87 fpCurve& operator=(const fpCurve& other) {
88 if (this != &other) {
89 fitpack_curve_c_destroy(as<fitpack_curve_c>(), nullptr);
90 fitpack_curve_c_copy(as<fitpack_curve_c>(), other.as<fitpack_curve_c>(), false, nullptr);
91 }
92 return *this;
93 }
94
98 fpCurve(fpCurve&& other) noexcept : fpFitter(NoAlloc{}) {
99 *as<fitpack_curve_c>() = fitpack_curve_c_null;
100 fitpack_curve_c_move_alloc(as<fitpack_curve_c>(), other.as<fitpack_curve_c>(), nullptr);
101 }
102
106 fpCurve& operator=(fpCurve&& other) noexcept {
107 if (this != &other) {
108 fitpack_curve_c_destroy(as<fitpack_curve_c>(), nullptr);
109 fitpack_curve_c_move_alloc(as<fitpack_curve_c>(), other.as<fitpack_curve_c>(), nullptr);
110 }
111 return *this;
112 }
113
117 explicit fpCurve(fitpack_curve_c& c_wrapper, bool move = false) : fpFitter(NoAlloc{}) {
118 if (move) {
119 fitpack_curve_c_move_alloc(as<fitpack_curve_c>(), &c_wrapper, nullptr);
120 } else {
121 *as<fitpack_curve_c>() = fitpack_curve_c_null;
122 fitpack_curve_c_copy(as<fitpack_curve_c>(), &c_wrapper, false, nullptr);
123 }
124 }
125
131 explicit fpCurve(fitpack_curve_c& c_wrapper, ViewTag) : fpFitter(NoAlloc{}) {
132 *as<fitpack_curve_c>() = c_wrapper;
133 as<fitpack_curve_c>()->is_pointer = true;
134 }
135
136 // ===========================================================================================
137 // Utility Methods
138 // ===========================================================================================
139
143 bool is_allocated() const override {
144 return as<fitpack_curve_c>()->cptr != nullptr;
145 }
146
150 bool is_pointer() const override {
151 return as<fitpack_curve_c>()->is_pointer;
152 }
153
157 const char* c_type_name() const override {
158 return fitpack_curve_c_c_type_name(*as<fitpack_curve_c>());
159 }
160
165 const char* cpp_type_name() const override {
166 return "fpCurve";
167 }
168
172 fitpack_curve_c& c_handle() {
173 return *as<fitpack_curve_c>();
174 }
175
179 const fitpack_curve_c& c_handle() const {
180 return *as<fitpack_curve_c>();
181 }
182
192 return fpCurve(NoAlloc{});
193 }
194
199 return static_cast<fpFitter&>(*this);
200 }
201 const fpFitter& as_parent() const {
202 return static_cast<const fpFitter&>(*this);
203 }
204
205 // ===========================================================================================
206 // Method Wrappers (standalone — no fxArray dependency)
207 // ===========================================================================================
208
212 virtual void new_points(std::vector<double>& x, std::vector<double>& y, double* w = nullptr) {
213 int32_t n = static_cast<int32_t>(x.size());
214 fitpack_curve_c_new_points(as<fitpack_curve_c>(), n, x.data(), y.data(), w);
215 }
216
217
221 virtual int32_t new_fit(std::vector<double>& x, std::vector<double>& y, double* w = nullptr, double* smoothing = nullptr, int32_t* order = nullptr) {
222 int32_t n = static_cast<int32_t>(x.size());
223 return fitpack_curve_c_new_fit(as<fitpack_curve_c>(), n, x.data(), y.data(), w, smoothing, order);
224 }
225
226
227 virtual int32_t fit(double* smoothing = nullptr, int32_t* order = nullptr, bool* keep_knots = nullptr) {
228 return fitpack_curve_c_fit(as<fitpack_curve_c>(), smoothing, order, keep_knots);
229 }
230
231 virtual int32_t interpolate(int32_t* order = nullptr, bool* reset_knots = nullptr) {
232 return fitpack_curve_c_interpolate(as<fitpack_curve_c>(), order, reset_knots);
233 }
234
235 virtual int32_t least_squares(double* smoothing = nullptr, bool* reset_knots = nullptr) {
236 return fitpack_curve_c_least_squares(as<fitpack_curve_c>(), smoothing, reset_knots);
237 }
238
239 virtual double eval(double x, int32_t& ierr) {
240 return fitpack_curve_c_curve_eval_one(as<fitpack_curve_c>(), x, &ierr);
241 }
242
243 virtual double eval(double x) const {
244 return fitpack_curve_c_curve_eval_one_noerr(as<fitpack_curve_c>(), x);
245 }
246
250 virtual std::vector<double> eval(std::vector<double>& x, int32_t& ierr) {
251 int32_t n = static_cast<int32_t>(x.size());
252 std::vector<double> result(n);
253 int32_t n_result = 0;
254 fitpack_curve_c_curve_eval_many(as<fitpack_curve_c>(), n, x.data(), &ierr, result.data(), &n_result, n);
255 result.resize(n_result);
256 return result;
257 }
258
259
263 virtual std::vector<double> eval(std::vector<double>& x) {
264 int32_t n = static_cast<int32_t>(x.size());
265 std::vector<double> result(n);
266 int32_t n_result = 0;
267 fitpack_curve_c_curve_eval_many_pure(as<fitpack_curve_c>(), n, x.data(), result.data(), &n_result, n);
268 result.resize(n_result);
269 return result;
270 }
271
272
273 virtual double integral(double from, double to) {
274 return fitpack_curve_c_integral(as<fitpack_curve_c>(), from, to);
275 }
276
280 virtual void fourier_coefficients(std::vector<double>& alpha, std::vector<double>& a, std::vector<double>& b, int32_t* ierr = nullptr) {
281 int32_t n = static_cast<int32_t>(alpha.size());
282 fitpack_curve_c_fourier_coefficients(as<fitpack_curve_c>(), n, alpha.data(), a.data(), b.data(), ierr);
283 }
284
285
289 virtual std::vector<double> zeros(int32_t max_size, int32_t* ierr = nullptr) {
290 std::vector<double> result(max_size);
291 int32_t n_result = 0;
292 fitpack_curve_c_zeros(as<fitpack_curve_c>(), ierr, result.data(), &n_result, max_size);
293 result.resize(n_result);
294 return result;
295 }
296
297
298 virtual double dfdx(double x, int32_t order, int32_t* ierr = nullptr) {
299 return fitpack_curve_c_curve_derivative(as<fitpack_curve_c>(), x, order, ierr);
300 }
301
305 virtual std::vector<double> dfdx(std::vector<double>& x, int32_t order, int32_t* ierr = nullptr) {
306 int32_t n = static_cast<int32_t>(x.size());
307 std::vector<double> result(n);
308 int32_t n_result = 0;
309 fitpack_curve_c_curve_derivatives(as<fitpack_curve_c>(), n, x.data(), order, ierr, result.data(), &n_result, n);
310 result.resize(n_result);
311 return result;
312 }
313
314
318 virtual std::vector<double> dfdx_all(double x, int32_t& ierr, int32_t n_result) {
319 std::vector<double> result(n_result);
320 fitpack_curve_c_curve_all_derivatives(as<fitpack_curve_c>(), x, &ierr, result.data(), n_result);
321 return result;
322 }
323
324
328 virtual std::vector<double> dfdx_all(double x, int32_t n_result) {
329 std::vector<double> result(n_result);
330 fitpack_curve_c_curve_all_derivatives_pure(as<fitpack_curve_c>(), x, result.data(), n_result);
331 return result;
332 }
333
334
335 virtual void insert_knot(double x, int32_t* ierr = nullptr) {
336 fitpack_curve_c_curve_insert_knot_one(as<fitpack_curve_c>(), x, ierr);
337 }
338
342 virtual void insert_knot(std::vector<double>& x, int32_t* ierr = nullptr) {
343 int32_t n = static_cast<int32_t>(x.size());
344 fitpack_curve_c_curve_insert_knot_many(as<fitpack_curve_c>(), n, x.data(), ierr);
345 }
346
347
348 int32_t comm_size() const override {
349 return fitpack_curve_c_comm_size(as<fitpack_curve_c>());
350 }
351
355 void comm_pack(std::vector<double>& buffer) const override {
356 int32_t n = static_cast<int32_t>(buffer.size());
357 fitpack_curve_c_comm_pack(as<fitpack_curve_c>(), n, buffer.data());
358 }
359
360
364 void comm_expand(std::vector<double>& buffer) override {
365 int32_t n = static_cast<int32_t>(buffer.size());
366 fitpack_curve_c_comm_expand(as<fitpack_curve_c>(), n, buffer.data());
367 }
368
369
370 double mse() const override {
371 return fitpack_curve_c_mse(as<fitpack_curve_c>());
372 }
373
374 int32_t core_comm_size() const override {
375 return fitpack_curve_c_core_comm_size(as<fitpack_curve_c>());
376 }
377
381 void core_comm_pack(std::vector<double>& buffer) const override {
382 int32_t n = static_cast<int32_t>(buffer.size());
383 fitpack_curve_c_core_comm_pack(as<fitpack_curve_c>(), n, buffer.data());
384 }
385
386
390 void core_comm_expand(std::vector<double>& buffer) override {
391 int32_t n = static_cast<int32_t>(buffer.size());
392 fitpack_curve_c_core_comm_expand(as<fitpack_curve_c>(), n, buffer.data());
393 }
394
395
396 void destroy_base() override {
397 fitpack_curve_c_destroy_base(as<fitpack_curve_c>());
398 }
399
400 // ===========================================================================================
401 // Component Array Accessors
402 // ===========================================================================================
403
408 std::vector<double> x_vector() const {
409 double* raw = nullptr;
410 int64_t extents[1] = {0};
411 fitpack_curve_c_getcomp_x(as<fitpack_curve_c>(), &raw, extents);
412 const int64_t total = extents[0];
413 if (raw == nullptr || total <= 0) return {};
414 const double* first = reinterpret_cast<const double*>(raw);
415 return std::vector<double>(first, first + total);
416 }
417
418#if HAVE_FXARRAY
431 fxArray<double> x() const {
432 double* raw = nullptr;
433 int64_t extents[1] = {0};
434 fitpack_curve_c_getcomp_x(as<fitpack_curve_c>(), &raw, extents);
435 FX_SIZE bounds[2]; // (lower, upper) per dimension, Fortran lbound 1
436 for (int k = 0; k < 1; ++k) {
437 bounds[2 * k] = 1;
438 bounds[2 * k + 1] = static_cast<FX_SIZE>(extents[k]);
439 }
440 array_c descr = array_c_null;
441 array_c_from_ptr(&descr, "x", static_cast<void*>(raw),
442 getCFITypeFlag<double>(),
443 static_cast<FX_SIZE>(sizeof(double)),
444 static_cast<FX_RANK>(1), bounds);
445 return fxArray<double>(descr);
446 }
447#endif // HAVE_FXARRAY
448
453 std::vector<double> y_vector() const {
454 double* raw = nullptr;
455 int64_t extents[1] = {0};
456 fitpack_curve_c_getcomp_y(as<fitpack_curve_c>(), &raw, extents);
457 const int64_t total = extents[0];
458 if (raw == nullptr || total <= 0) return {};
459 const double* first = reinterpret_cast<const double*>(raw);
460 return std::vector<double>(first, first + total);
461 }
462
463#if HAVE_FXARRAY
476 fxArray<double> y() const {
477 double* raw = nullptr;
478 int64_t extents[1] = {0};
479 fitpack_curve_c_getcomp_y(as<fitpack_curve_c>(), &raw, extents);
480 FX_SIZE bounds[2]; // (lower, upper) per dimension, Fortran lbound 1
481 for (int k = 0; k < 1; ++k) {
482 bounds[2 * k] = 1;
483 bounds[2 * k + 1] = static_cast<FX_SIZE>(extents[k]);
484 }
485 array_c descr = array_c_null;
486 array_c_from_ptr(&descr, "y", static_cast<void*>(raw),
487 getCFITypeFlag<double>(),
488 static_cast<FX_SIZE>(sizeof(double)),
489 static_cast<FX_RANK>(1), bounds);
490 return fxArray<double>(descr);
491 }
492#endif // HAVE_FXARRAY
493
498 std::vector<double> sp_vector() const {
499 double* raw = nullptr;
500 int64_t extents[1] = {0};
501 fitpack_curve_c_getcomp_sp(as<fitpack_curve_c>(), &raw, extents);
502 const int64_t total = extents[0];
503 if (raw == nullptr || total <= 0) return {};
504 const double* first = reinterpret_cast<const double*>(raw);
505 return std::vector<double>(first, first + total);
506 }
507
508#if HAVE_FXARRAY
521 fxArray<double> sp() const {
522 double* raw = nullptr;
523 int64_t extents[1] = {0};
524 fitpack_curve_c_getcomp_sp(as<fitpack_curve_c>(), &raw, extents);
525 FX_SIZE bounds[2]; // (lower, upper) per dimension, Fortran lbound 1
526 for (int k = 0; k < 1; ++k) {
527 bounds[2 * k] = 1;
528 bounds[2 * k + 1] = static_cast<FX_SIZE>(extents[k]);
529 }
530 array_c descr = array_c_null;
531 array_c_from_ptr(&descr, "sp", static_cast<void*>(raw),
532 getCFITypeFlag<double>(),
533 static_cast<FX_SIZE>(sizeof(double)),
534 static_cast<FX_RANK>(1), bounds);
535 return fxArray<double>(descr);
536 }
537#endif // HAVE_FXARRAY
538
543 std::vector<double> w_vector() const {
544 double* raw = nullptr;
545 int64_t extents[1] = {0};
546 fitpack_curve_c_getcomp_w(as<fitpack_curve_c>(), &raw, extents);
547 const int64_t total = extents[0];
548 if (raw == nullptr || total <= 0) return {};
549 const double* first = reinterpret_cast<const double*>(raw);
550 return std::vector<double>(first, first + total);
551 }
552
553#if HAVE_FXARRAY
566 fxArray<double> w() const {
567 double* raw = nullptr;
568 int64_t extents[1] = {0};
569 fitpack_curve_c_getcomp_w(as<fitpack_curve_c>(), &raw, extents);
570 FX_SIZE bounds[2]; // (lower, upper) per dimension, Fortran lbound 1
571 for (int k = 0; k < 1; ++k) {
572 bounds[2 * k] = 1;
573 bounds[2 * k + 1] = static_cast<FX_SIZE>(extents[k]);
574 }
575 array_c descr = array_c_null;
576 array_c_from_ptr(&descr, "w", static_cast<void*>(raw),
577 getCFITypeFlag<double>(),
578 static_cast<FX_SIZE>(sizeof(double)),
579 static_cast<FX_RANK>(1), bounds);
580 return fxArray<double>(descr);
581 }
582#endif // HAVE_FXARRAY
583
592 std::vector<double> wrk_fou_vector() const {
593 double* raw = nullptr;
594 int64_t extents[2] = {0, 0};
595 fitpack_curve_c_getcomp_wrk_fou(as<fitpack_curve_c>(), &raw, extents);
596 const int64_t total = extents[0] * extents[1];
597 if (raw == nullptr || total <= 0) return {};
598 const double* first = reinterpret_cast<const double*>(raw);
599 return std::vector<double>(first, first + total);
600 }
601
606 std::array<int64_t, 2> wrk_fou_shape() const {
607 double* raw = nullptr;
608 int64_t extents[2] = {0, 0};
609 fitpack_curve_c_getcomp_wrk_fou(as<fitpack_curve_c>(), &raw, extents);
610 return { extents[0], extents[1] };
611 }
612
613#if HAVE_FXARRAY
626 fxArray<double> wrk_fou() const {
627 double* raw = nullptr;
628 int64_t extents[2] = {0, 0};
629 fitpack_curve_c_getcomp_wrk_fou(as<fitpack_curve_c>(), &raw, extents);
630 FX_SIZE bounds[4]; // (lower, upper) per dimension, Fortran lbound 1
631 for (int k = 0; k < 2; ++k) {
632 bounds[2 * k] = 1;
633 bounds[2 * k + 1] = static_cast<FX_SIZE>(extents[k]);
634 }
635 array_c descr = array_c_null;
636 array_c_from_ptr(&descr, "wrk_fou", static_cast<void*>(raw),
637 getCFITypeFlag<double>(),
638 static_cast<FX_SIZE>(sizeof(double)),
639 static_cast<FX_RANK>(2), bounds);
640 return fxArray<double>(descr);
641 }
642#endif // HAVE_FXARRAY
643
648 std::vector<double> t_vector() const {
649 double* raw = nullptr;
650 int64_t extents[1] = {0};
651 fitpack_curve_c_getcomp_t(as<fitpack_curve_c>(), &raw, extents);
652 const int64_t total = extents[0];
653 if (raw == nullptr || total <= 0) return {};
654 const double* first = reinterpret_cast<const double*>(raw);
655 return std::vector<double>(first, first + total);
656 }
657
658#if HAVE_FXARRAY
671 fxArray<double> t() const {
672 double* raw = nullptr;
673 int64_t extents[1] = {0};
674 fitpack_curve_c_getcomp_t(as<fitpack_curve_c>(), &raw, extents);
675 FX_SIZE bounds[2]; // (lower, upper) per dimension, Fortran lbound 1
676 for (int k = 0; k < 1; ++k) {
677 bounds[2 * k] = 1;
678 bounds[2 * k + 1] = static_cast<FX_SIZE>(extents[k]);
679 }
680 array_c descr = array_c_null;
681 array_c_from_ptr(&descr, "t", static_cast<void*>(raw),
682 getCFITypeFlag<double>(),
683 static_cast<FX_SIZE>(sizeof(double)),
684 static_cast<FX_RANK>(1), bounds);
685 return fxArray<double>(descr);
686 }
687#endif // HAVE_FXARRAY
688
689 // ===========================================================================================
690 // Scalar Property Accessors
691 // ===========================================================================================
692
693 int32_t& m() {
694 return *fitpack_curve_c_ref_m(as<fitpack_curve_c>());
695 }
696 const int32_t& m() const {
697 return *fitpack_curve_c_ref_m(as<fitpack_curve_c>());
698 }
699
700 int32_t& order() {
701 return *fitpack_curve_c_ref_order(as<fitpack_curve_c>());
702 }
703 const int32_t& order() const {
704 return *fitpack_curve_c_ref_order(as<fitpack_curve_c>());
705 }
706
707 double& xleft() {
708 return *fitpack_curve_c_ref_xleft(as<fitpack_curve_c>());
709 }
710 const double& xleft() const {
711 return *fitpack_curve_c_ref_xleft(as<fitpack_curve_c>());
712 }
713
714 double& xright() {
715 return *fitpack_curve_c_ref_xright(as<fitpack_curve_c>());
716 }
717 const double& xright() const {
718 return *fitpack_curve_c_ref_xright(as<fitpack_curve_c>());
719 }
720
721 int32_t& nest() {
722 return *fitpack_curve_c_ref_nest(as<fitpack_curve_c>());
723 }
724 const int32_t& nest() const {
725 return *fitpack_curve_c_ref_nest(as<fitpack_curve_c>());
726 }
727
728 int32_t& bc() {
729 return *fitpack_curve_c_ref_bc(as<fitpack_curve_c>());
730 }
731 const int32_t& bc() const {
732 return *fitpack_curve_c_ref_bc(as<fitpack_curve_c>());
733 }
734
735 int32_t& knots() {
736 return *fitpack_curve_c_ref_knots(as<fitpack_curve_c>());
737 }
738 const int32_t& knots() const {
739 return *fitpack_curve_c_ref_knots(as<fitpack_curve_c>());
740 }
741
742 // ===========================================================================================
743 // Ergonomic overloads — extra_methods/fpCurveErgonomics.hpp (hand-maintained)
744 //
745 // The call shapes of the pre-0.3.0 hand-written wrapper, on top of the generated raw entry
746 // points. Every one forwards to a virtual raw method, so fpPeriodicCurve inherits them and
747 // still reaches its own Fortran routines through dispatch.
748 // ===========================================================================================
749
751 FP_SIZE degree() const { return order(); }
752
754 FP_FLAG new_fit(const std::vector<FP_REAL>& x, const std::vector<FP_REAL>& y,
755 FP_REAL smoothing = 1000.0)
756 {
757 std::vector<FP_REAL> xw(x), yw(y);
758 return new_fit(xw, yw, nullptr, &smoothing, nullptr);
759 }
760
762 FP_FLAG new_fit(const std::vector<FP_REAL>& x, const std::vector<FP_REAL>& y,
763 const std::vector<FP_REAL>& w, FP_REAL smoothing = 1000.0)
764 {
765 std::vector<FP_REAL> xw(x), yw(y), ww(w);
766 return new_fit(xw, yw, ww.data(), &smoothing, nullptr);
767 }
768
770 FP_FLAG fit(FP_SIZE order) { return fit(nullptr, &order, nullptr); }
772 FP_FLAG fit(FP_REAL smoothing) { return fit(&smoothing, nullptr, nullptr); }
774 FP_FLAG fit(FP_REAL smoothing, FP_SIZE order) { return fit(&smoothing, &order, nullptr); }
775
777 FP_FLAG interpolate(FP_SIZE order) { return interpolate(&order, nullptr); }
778
780 FP_REAL eval(FP_REAL x, FP_FLAG* ierr)
781 {
782 FP_FLAG ierr0 = FITPACK_OK;
783 const FP_REAL y = eval(x, ierr0);
784 if (ierr) *ierr = ierr0;
785 return y;
786 }
787
789 std::vector<FP_REAL> eval(const std::vector<FP_REAL>& x, FP_FLAG* ierr)
790 {
791 std::vector<FP_REAL> xw(x);
792 FP_FLAG ierr0 = FITPACK_OK;
793 std::vector<FP_REAL> y = eval(xw, ierr0);
794 if (ierr) *ierr = ierr0;
795 return y;
796 }
797
802 std::vector<fpPoint<2>> eval(FP_REAL xmin, FP_REAL xmax, FP_SIZE npts, FP_FLAG* ierr = nullptr)
803 {
804 std::vector<FP_REAL> x(static_cast<std::size_t>(npts > 0 ? npts : 0));
805 if (npts > 1)
806 {
807 const FP_REAL dx = (xmax - xmin) / (npts - 1);
808 for (FP_SIZE i = 0; i < npts; ++i) x[static_cast<std::size_t>(i)] = xmin + i * dx;
809 }
810 else if (npts == 1) x[0] = xmin;
811
812 FP_FLAG ierr0 = FITPACK_OK;
813 std::vector<FP_REAL> y = eval(x, ierr0);
814 if (ierr) *ierr = ierr0;
815
816 std::vector<fpPoint<2>> xy(x.size());
817 for (std::size_t i = 0; i < x.size() && i < y.size(); ++i) xy[i] = {x[i], y[i]};
818 return xy;
819 }
820
823 FP_REAL ddx(FP_REAL x, FP_SIZE order, FP_FLAG* ierr = nullptr) { return dfdx(x, order, ierr); }
824
826 std::vector<FP_REAL> ddx(FP_REAL x, FP_FLAG* ierr = nullptr)
827 {
828 FP_FLAG ierr0 = FITPACK_OK;
829 std::vector<FP_REAL> d = dfdx_all(x, ierr0, degree() + 1);
830 if (ierr) *ierr = ierr0;
831 return d;
832 }
833
835 void set_bc(FP_FLAG value) { bc() = value; }
836 FP_FLAG get_bc() const { return bc(); }
837
840 FP_FLAG fourier(const std::vector<FP_REAL>& alpha, std::vector<FP_REAL>& A, std::vector<FP_REAL>& B)
841 {
842 std::vector<FP_REAL> aw(alpha);
843 A.resize(alpha.size());
844 B.resize(alpha.size());
845 FP_FLAG ierr = FITPACK_OK;
846 fourier_coefficients(aw, A, B, &ierr);
847 return ierr;
848 }
849
850protected:
851 explicit fpCurve(NoAlloc tag) : fpFitter(tag) {}
852
853};
854
855#endif /* FPCURVE_HPP_INCLUDED */
virtual void fourier_coefficients(std::vector< double > &alpha, std::vector< double > &a, std::vector< double > &b, int32_t *ierr=nullptr)
fourier_coefficients
Definition fpCurve.hpp:280
void comm_pack(std::vector< double > &buffer) const override
comm_pack
Definition fpCurve.hpp:355
virtual int32_t least_squares(double *smoothing=nullptr, bool *reset_knots=nullptr)
Definition fpCurve.hpp:235
virtual double integral(double from, double to)
Definition fpCurve.hpp:273
FP_FLAG new_fit(const std::vector< FP_REAL > &x, const std::vector< FP_REAL > &y, const std::vector< FP_REAL > &w, FP_REAL smoothing=1000.0)
Fit a new curve through (x, y) with per-point weights w.
Definition fpCurve.hpp:762
virtual std::vector< double > dfdx_all(double x, int32_t &ierr, int32_t n_result)
dfdx_all
Definition fpCurve.hpp:318
virtual void new_points(std::vector< double > &x, std::vector< double > &y, double *w=nullptr)
new_points
Definition fpCurve.hpp:212
const char * cpp_type_name() const override
Return the fully-qualified C++ class name for this class. Owned by the C++ layer — does not round-tri...
Definition fpCurve.hpp:165
virtual int32_t fit(double *smoothing=nullptr, int32_t *order=nullptr, bool *keep_knots=nullptr)
Definition fpCurve.hpp:227
int32_t & knots()
Definition fpCurve.hpp:735
std::vector< double > t_vector() const
Deep copy of component 't' as a std::vector.
Definition fpCurve.hpp:648
virtual double eval(double x) const
Definition fpCurve.hpp:243
double mse() const override
Definition fpCurve.hpp:370
~fpCurve() override
Destructor - deallocates if owned.
Definition fpCurve.hpp:72
fpCurve & operator=(const fpCurve &other)
Copy assignment - deep copy.
Definition fpCurve.hpp:87
fxArray< double > x() const
Zero-copy fxArray view of component 'x'.
Definition fpCurve.hpp:431
FP_FLAG fit(FP_REAL smoothing)
Refit the current points with a new smoothing.
Definition fpCurve.hpp:772
void core_comm_expand(std::vector< double > &buffer) override
core_comm_expand
Definition fpCurve.hpp:390
static fpCurve make_view()
Construct an empty (non-owning) wrapper, for use as a view target.
Definition fpCurve.hpp:191
virtual double eval(double x, int32_t &ierr)
Definition fpCurve.hpp:239
const int32_t & order() const
Definition fpCurve.hpp:703
int32_t & bc()
Definition fpCurve.hpp:728
double & xright()
Definition fpCurve.hpp:714
std::vector< FP_REAL > eval(const std::vector< FP_REAL > &x, FP_FLAG *ierr)
Evaluate the curve at every x, reporting the status through ierr.
Definition fpCurve.hpp:789
std::vector< fpPoint< 2 > > eval(FP_REAL xmin, FP_REAL xmax, FP_SIZE npts, FP_FLAG *ierr=nullptr)
Evaluate the curve at npts points evenly spaced over [xmin, xmax].
Definition fpCurve.hpp:802
FP_FLAG new_fit(const std::vector< FP_REAL > &x, const std::vector< FP_REAL > &y, FP_REAL smoothing=1000.0)
Fit a new curve through (x, y).
Definition fpCurve.hpp:754
int32_t & nest()
Definition fpCurve.hpp:721
void comm_expand(std::vector< double > &buffer) override
comm_expand
Definition fpCurve.hpp:364
bool is_pointer() const override
Check if this is a non-owning pointer.
Definition fpCurve.hpp:150
int32_t & order()
Definition fpCurve.hpp:700
virtual std::vector< double > zeros(int32_t max_size, int32_t *ierr=nullptr)
zeros
Definition fpCurve.hpp:289
FP_REAL ddx(FP_REAL x, FP_SIZE order, FP_FLAG *ierr=nullptr)
Derivative of the given order at x.
Definition fpCurve.hpp:823
const int32_t & m() const
Definition fpCurve.hpp:696
FP_SIZE degree() const
Spline degree k of the current fit.
Definition fpCurve.hpp:751
std::vector< double > w_vector() const
Deep copy of component 'w' as a std::vector.
Definition fpCurve.hpp:543
fpCurve(fpCurve &&other) noexcept
Move constructor - transfer ownership.
Definition fpCurve.hpp:98
int32_t core_comm_size() const override
Definition fpCurve.hpp:374
virtual std::vector< double > dfdx(std::vector< double > &x, int32_t order, int32_t *ierr=nullptr)
dfdx
Definition fpCurve.hpp:305
virtual std::vector< double > eval(std::vector< double > &x, int32_t &ierr)
eval
Definition fpCurve.hpp:250
fitpack_curve_c & c_handle()
Get underlying C wrapper (for interop)
Definition fpCurve.hpp:172
virtual void insert_knot(std::vector< double > &x, int32_t *ierr=nullptr)
insert_knot
Definition fpCurve.hpp:342
double & xleft()
Definition fpCurve.hpp:707
virtual int32_t interpolate(int32_t *order=nullptr, bool *reset_knots=nullptr)
Definition fpCurve.hpp:231
fxArray< double > t() const
Zero-copy fxArray view of component 't'.
Definition fpCurve.hpp:671
fpCurve(const fpCurve &other)
Copy constructor - deep copy.
Definition fpCurve.hpp:79
const int32_t & bc() const
Definition fpCurve.hpp:731
FP_FLAG fourier(const std::vector< FP_REAL > &alpha, std::vector< FP_REAL > &A, std::vector< FP_REAL > &B)
Fourier coefficients A, B of the curve at the given angular frequencies.
Definition fpCurve.hpp:840
fpCurve & operator=(fpCurve &&other) noexcept
Move assignment - transfer ownership.
Definition fpCurve.hpp:106
FP_FLAG get_bc() const
Definition fpCurve.hpp:836
std::vector< double > y_vector() const
Deep copy of component 'y' as a std::vector.
Definition fpCurve.hpp:453
FP_FLAG interpolate(FP_SIZE order)
Interpolating fit of the given spline order.
Definition fpCurve.hpp:777
int32_t & m()
Definition fpCurve.hpp:693
virtual int32_t new_fit(std::vector< double > &x, std::vector< double > &y, double *w=nullptr, double *smoothing=nullptr, int32_t *order=nullptr)
new_fit
Definition fpCurve.hpp:221
FP_FLAG fit(FP_SIZE order)
Refit the current points with a new spline order.
Definition fpCurve.hpp:770
int32_t comm_size() const override
Definition fpCurve.hpp:348
std::array< int64_t, 2 > wrk_fou_shape() const
Extents of component 'wrk_fou', leading dimension first.
Definition fpCurve.hpp:606
fpCurve(fitpack_curve_c &c_wrapper, bool move=false)
Construct from existing C wrapper (takes ownership if move=true)
Definition fpCurve.hpp:117
FP_FLAG fit(FP_REAL smoothing, FP_SIZE order)
Refit the current points with a new smoothing and spline order.
Definition fpCurve.hpp:774
const fitpack_curve_c & c_handle() const
Get underlying C wrapper (const, for interop)
Definition fpCurve.hpp:179
const int32_t & nest() const
Definition fpCurve.hpp:724
std::vector< double > sp_vector() const
Deep copy of component 'sp' as a std::vector.
Definition fpCurve.hpp:498
virtual double dfdx(double x, int32_t order, int32_t *ierr=nullptr)
Definition fpCurve.hpp:298
virtual std::vector< double > eval(std::vector< double > &x)
eval
Definition fpCurve.hpp:263
const char * c_type_name() const override
Return the C wrapper struct name for this class (e.g. "fitpack_curve_c").
Definition fpCurve.hpp:157
void core_comm_pack(std::vector< double > &buffer) const override
core_comm_pack
Definition fpCurve.hpp:381
const double & xleft() const
Definition fpCurve.hpp:710
const int32_t & knots() const
Definition fpCurve.hpp:738
const fpFitter & as_parent() const
Definition fpCurve.hpp:201
fpFitter & as_parent()
Upcast to parent type (reference, no copy)
Definition fpCurve.hpp:198
bool is_allocated() const override
Check if object is allocated.
Definition fpCurve.hpp:143
fxArray< double > y() const
Zero-copy fxArray view of component 'y'.
Definition fpCurve.hpp:476
std::vector< FP_REAL > ddx(FP_REAL x, FP_FLAG *ierr=nullptr)
All derivatives (orders 0..k) at x.
Definition fpCurve.hpp:826
virtual std::vector< double > dfdx_all(double x, int32_t n_result)
dfdx_all
Definition fpCurve.hpp:328
fxArray< double > wrk_fou() const
Zero-copy fxArray view of component 'wrk_fou'.
Definition fpCurve.hpp:626
fpCurve()
Default constructor - allocates new fitpack_curve.
Definition fpCurve.hpp:65
fpCurve(NoAlloc tag)
Definition fpCurve.hpp:851
fxArray< double > w() const
Zero-copy fxArray view of component 'w'.
Definition fpCurve.hpp:566
std::vector< double > x_vector() const
Deep copy of component 'x' as a std::vector.
Definition fpCurve.hpp:408
std::vector< double > wrk_fou_vector() const
Deep copy of component 'wrk_fou' as a std::vector.
Definition fpCurve.hpp:592
const double & xright() const
Definition fpCurve.hpp:717
fxArray< double > sp() const
Zero-copy fxArray view of component 'sp'.
Definition fpCurve.hpp:521
FP_REAL eval(FP_REAL x, FP_FLAG *ierr)
Evaluate the curve at x, reporting the status through ierr.
Definition fpCurve.hpp:780
void destroy_base() override
Definition fpCurve.hpp:396
void set_bc(FP_FLAG value)
Spline behaviour outside the support (one of the OUTSIDE_* flags).
Definition fpCurve.hpp:835
virtual void insert_knot(double x, int32_t *ierr=nullptr)
Definition fpCurve.hpp:335
fpCurve(fitpack_curve_c &c_wrapper, ViewTag)
Non-owning view ctor: bit-copy the C handle, mark is_pointer=true. Used by parent classes' polymorphi...
Definition fpCurve.hpp:131
double & smoothing()
Definition fpFitter.hpp:317
fpFitter(NoAlloc)
Protected constructor for derived classes (does not allocate)
Definition fpFitter.hpp:354
T * as()
Definition fpFitter.hpp:360
Tag type for derived class constructors (no allocation)
Definition fpFitter.hpp:349
Tag type for non-owning view constructors of polymorphic concrete subtypes. Declared on roots and abs...
Definition fpFitter.hpp:103