fitpack
Modern Fortran library for curve and surface fitting with splines
Loading...
Searching...
No Matches
fpParametricCurve.hpp
Go to the documentation of this file.
1/***************************************************************************************************
2! ____________________ ___ ________ __
3! / ____/ _/_ __/ __ \/ | / ____/ //_/
4! / /_ / / / / / /_/ / /| |/ / / ,<
5! / __/ _/ / / / / ____/ ___ / /___/ /| |
6! /_/ /___/ /_/ /_/ /_/ |_\____/_/ |_|
7!
8! A Curve Fitting Package
9!
10! fpParametricCurve.hpp (class fpParametricCurve)
11!> @brief Standalone C++ wrapper for fitpack_parametric_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 FPPARAMETRICCURVE_HPP_INCLUDED
25#define FPPARAMETRICCURVE_HPP_INCLUDED
26
27#include "fitpack_config.h"
28
29#if HAVE_FXARRAY
30#include "fxArrays.hpp"
31#endif
32
33#include "fitpack_parametric_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_parametric_curve_c) == sizeof(fitpack_fitter_c),
46 "C descriptor layout mismatch: fitpack_parametric_curve_c vs fitpack_fitter_c");
47
57public:
58 // ===========================================================================================
59 // Constructors and Destructor
60 // ===========================================================================================
61
66 fitpack_parametric_curve_c_allocate(as<fitpack_parametric_curve_c>(), nullptr);
67 }
68
72 ~fpParametricCurve() override {
73 fitpack_parametric_curve_c_destroy(as<fitpack_parametric_curve_c>(), nullptr);
74 }
75
80 *as<fitpack_parametric_curve_c>() = fitpack_parametric_curve_c_null;
81 fitpack_parametric_curve_c_copy(as<fitpack_parametric_curve_c>(), other.as<fitpack_parametric_curve_c>(), false, nullptr);
82 }
83
88 if (this != &other) {
89 fitpack_parametric_curve_c_destroy(as<fitpack_parametric_curve_c>(), nullptr);
90 fitpack_parametric_curve_c_copy(as<fitpack_parametric_curve_c>(), other.as<fitpack_parametric_curve_c>(), false, nullptr);
91 }
92 return *this;
93 }
94
99 *as<fitpack_parametric_curve_c>() = fitpack_parametric_curve_c_null;
100 fitpack_parametric_curve_c_move_alloc(as<fitpack_parametric_curve_c>(), other.as<fitpack_parametric_curve_c>(), nullptr);
101 }
102
107 if (this != &other) {
108 fitpack_parametric_curve_c_destroy(as<fitpack_parametric_curve_c>(), nullptr);
109 fitpack_parametric_curve_c_move_alloc(as<fitpack_parametric_curve_c>(), other.as<fitpack_parametric_curve_c>(), nullptr);
110 }
111 return *this;
112 }
113
117 explicit fpParametricCurve(fitpack_parametric_curve_c& c_wrapper, bool move = false) : fpFitter(NoAlloc{}) {
118 if (move) {
119 fitpack_parametric_curve_c_move_alloc(as<fitpack_parametric_curve_c>(), &c_wrapper, nullptr);
120 } else {
121 *as<fitpack_parametric_curve_c>() = fitpack_parametric_curve_c_null;
122 fitpack_parametric_curve_c_copy(as<fitpack_parametric_curve_c>(), &c_wrapper, false, nullptr);
123 }
124 }
125
131 explicit fpParametricCurve(fitpack_parametric_curve_c& c_wrapper, ViewTag) : fpFitter(NoAlloc{}) {
132 *as<fitpack_parametric_curve_c>() = c_wrapper;
133 as<fitpack_parametric_curve_c>()->is_pointer = true;
134 }
135
136 // ===========================================================================================
137 // Utility Methods
138 // ===========================================================================================
139
143 bool is_allocated() const override {
144 return as<fitpack_parametric_curve_c>()->cptr != nullptr;
145 }
146
150 bool is_pointer() const override {
151 return as<fitpack_parametric_curve_c>()->is_pointer;
152 }
153
157 const char* c_type_name() const override {
158 return fitpack_parametric_curve_c_c_type_name(*as<fitpack_parametric_curve_c>());
159 }
160
165 const char* cpp_type_name() const override {
166 return "fpParametricCurve";
167 }
168
172 fitpack_parametric_curve_c& c_handle() {
174 }
175
179 const fitpack_parametric_curve_c& c_handle() const {
181 }
182
192 return fpParametricCurve(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(int32_t x_n1, int32_t x_n2, std::vector<double>& x, double* u = nullptr, double* w = nullptr) {
213 fitpack_parametric_curve_c_new_points(as<fitpack_parametric_curve_c>(), x_n1, x_n2, x.data(), u, w);
214 }
215
216
217 virtual void set_default_parameters() {
218 fitpack_parametric_curve_c_set_default_parameters(as<fitpack_parametric_curve_c>());
219 }
220
224 virtual int32_t new_fit(int32_t x_n1, int32_t x_n2, std::vector<double>& x, double* u = nullptr, double* w = nullptr, double* smoothing = nullptr, int32_t* order = nullptr) {
225 return fitpack_parametric_curve_c_new_fit(as<fitpack_parametric_curve_c>(), x_n1, x_n2, x.data(), u, w, smoothing, order);
226 }
227
228
229 virtual int32_t fit(double* smoothing = nullptr, int32_t* order = nullptr, bool* keep_knots = nullptr) {
230 return fitpack_parametric_curve_c_fit(as<fitpack_parametric_curve_c>(), smoothing, order, keep_knots);
231 }
232
233 virtual int32_t interpolate(int32_t* order = nullptr, bool* reset_knots = nullptr) {
234 return fitpack_parametric_curve_c_interpolate(as<fitpack_parametric_curve_c>(), order, reset_knots);
235 }
236
237 virtual int32_t least_squares(double* smoothing = nullptr, bool* reset_knots = nullptr) {
238 return fitpack_parametric_curve_c_least_squares(as<fitpack_parametric_curve_c>(), smoothing, reset_knots);
239 }
240
244 virtual std::vector<double> eval_one(double u, int32_t n_result, int32_t* ierr = nullptr) {
245 std::vector<double> result(n_result);
246 fitpack_parametric_curve_c_eval_one(as<fitpack_parametric_curve_c>(), u, ierr, result.data(), n_result);
247 return result;
248 }
249
250
254 virtual std::vector<double> eval_many(std::vector<double>& u, int32_t n_result, int32_t* ierr = nullptr) {
255 int32_t n = static_cast<int32_t>(u.size());
256 std::vector<double> result(n_result);
257 fitpack_parametric_curve_c_eval_many(as<fitpack_parametric_curve_c>(), n, u.data(), ierr, result.data(), n_result);
258 return result;
259 }
260
261
265 virtual std::vector<double> dfdx(double u, int32_t order, int32_t n_result, int32_t* ierr = nullptr) {
266 std::vector<double> result(n_result);
267 fitpack_parametric_curve_c_curve_derivative(as<fitpack_parametric_curve_c>(), u, order, ierr, result.data(), n_result);
268 return result;
269 }
270
271
275 virtual std::vector<double> dfdx(std::vector<double>& u, int32_t order, int32_t n_result, int32_t* ierr = nullptr) {
276 int32_t n = static_cast<int32_t>(u.size());
277 std::vector<double> result(n_result);
278 fitpack_parametric_curve_c_curve_derivatives(as<fitpack_parametric_curve_c>(), n, u.data(), order, ierr, result.data(), n_result);
279 return result;
280 }
281
282
286 virtual std::vector<double> dfdx_all(double u, int32_t n_result, int32_t* ierr = nullptr) {
287 std::vector<double> result(n_result);
288 fitpack_parametric_curve_c_curve_all_derivatives(as<fitpack_parametric_curve_c>(), u, ierr, result.data(), n_result);
289 return result;
290 }
291
292
293 int32_t comm_size() const override {
294 return fitpack_parametric_curve_c_comm_size(as<fitpack_parametric_curve_c>());
295 }
296
300 void comm_pack(std::vector<double>& buffer) const override {
301 int32_t n = static_cast<int32_t>(buffer.size());
302 fitpack_parametric_curve_c_comm_pack(as<fitpack_parametric_curve_c>(), n, buffer.data());
303 }
304
305
309 void comm_expand(std::vector<double>& buffer) override {
310 int32_t n = static_cast<int32_t>(buffer.size());
311 fitpack_parametric_curve_c_comm_expand(as<fitpack_parametric_curve_c>(), n, buffer.data());
312 }
313
314
315 double mse() const override {
316 return fitpack_parametric_curve_c_mse(as<fitpack_parametric_curve_c>());
317 }
318
319 int32_t core_comm_size() const override {
320 return fitpack_parametric_curve_c_core_comm_size(as<fitpack_parametric_curve_c>());
321 }
322
326 void core_comm_pack(std::vector<double>& buffer) const override {
327 int32_t n = static_cast<int32_t>(buffer.size());
328 fitpack_parametric_curve_c_core_comm_pack(as<fitpack_parametric_curve_c>(), n, buffer.data());
329 }
330
331
335 void core_comm_expand(std::vector<double>& buffer) override {
336 int32_t n = static_cast<int32_t>(buffer.size());
337 fitpack_parametric_curve_c_core_comm_expand(as<fitpack_parametric_curve_c>(), n, buffer.data());
338 }
339
340
341 void destroy_base() override {
342 fitpack_parametric_curve_c_destroy_base(as<fitpack_parametric_curve_c>());
343 }
344
345 // ===========================================================================================
346 // Component Array Accessors
347 // ===========================================================================================
348
357 std::vector<double> x_vector() const {
358 double* raw = nullptr;
359 int64_t extents[2] = {0, 0};
360 fitpack_parametric_curve_c_getcomp_x(as<fitpack_parametric_curve_c>(), &raw, extents);
361 const int64_t total = extents[0] * extents[1];
362 if (raw == nullptr || total <= 0) return {};
363 const double* first = reinterpret_cast<const double*>(raw);
364 return std::vector<double>(first, first + total);
365 }
366
371 std::array<int64_t, 2> x_shape() const {
372 double* raw = nullptr;
373 int64_t extents[2] = {0, 0};
374 fitpack_parametric_curve_c_getcomp_x(as<fitpack_parametric_curve_c>(), &raw, extents);
375 return { extents[0], extents[1] };
376 }
377
378#if HAVE_FXARRAY
391 fxArray<double> x() const {
392 double* raw = nullptr;
393 int64_t extents[2] = {0, 0};
394 fitpack_parametric_curve_c_getcomp_x(as<fitpack_parametric_curve_c>(), &raw, extents);
395 FX_SIZE bounds[4]; // (lower, upper) per dimension, Fortran lbound 1
396 for (int k = 0; k < 2; ++k) {
397 bounds[2 * k] = 1;
398 bounds[2 * k + 1] = static_cast<FX_SIZE>(extents[k]);
399 }
400 array_c descr = array_c_null;
401 array_c_from_ptr(&descr, "x", static_cast<void*>(raw),
402 getCFITypeFlag<double>(),
403 static_cast<FX_SIZE>(sizeof(double)),
404 static_cast<FX_RANK>(2), bounds);
405 return fxArray<double>(descr);
406 }
407#endif // HAVE_FXARRAY
408
413 std::vector<double> u_vector() const {
414 double* raw = nullptr;
415 int64_t extents[1] = {0};
416 fitpack_parametric_curve_c_getcomp_u(as<fitpack_parametric_curve_c>(), &raw, extents);
417 const int64_t total = extents[0];
418 if (raw == nullptr || total <= 0) return {};
419 const double* first = reinterpret_cast<const double*>(raw);
420 return std::vector<double>(first, first + total);
421 }
422
423#if HAVE_FXARRAY
436 fxArray<double> u() const {
437 double* raw = nullptr;
438 int64_t extents[1] = {0};
439 fitpack_parametric_curve_c_getcomp_u(as<fitpack_parametric_curve_c>(), &raw, extents);
440 FX_SIZE bounds[2]; // (lower, upper) per dimension, Fortran lbound 1
441 for (int k = 0; k < 1; ++k) {
442 bounds[2 * k] = 1;
443 bounds[2 * k + 1] = static_cast<FX_SIZE>(extents[k]);
444 }
445 array_c descr = array_c_null;
446 array_c_from_ptr(&descr, "u", static_cast<void*>(raw),
447 getCFITypeFlag<double>(),
448 static_cast<FX_SIZE>(sizeof(double)),
449 static_cast<FX_RANK>(1), bounds);
450 return fxArray<double>(descr);
451 }
452#endif // HAVE_FXARRAY
453
458 std::vector<double> sp_vector() const {
459 double* raw = nullptr;
460 int64_t extents[1] = {0};
461 fitpack_parametric_curve_c_getcomp_sp(as<fitpack_parametric_curve_c>(), &raw, extents);
462 const int64_t total = extents[0];
463 if (raw == nullptr || total <= 0) return {};
464 const double* first = reinterpret_cast<const double*>(raw);
465 return std::vector<double>(first, first + total);
466 }
467
468#if HAVE_FXARRAY
481 fxArray<double> sp() const {
482 double* raw = nullptr;
483 int64_t extents[1] = {0};
484 fitpack_parametric_curve_c_getcomp_sp(as<fitpack_parametric_curve_c>(), &raw, extents);
485 FX_SIZE bounds[2]; // (lower, upper) per dimension, Fortran lbound 1
486 for (int k = 0; k < 1; ++k) {
487 bounds[2 * k] = 1;
488 bounds[2 * k + 1] = static_cast<FX_SIZE>(extents[k]);
489 }
490 array_c descr = array_c_null;
491 array_c_from_ptr(&descr, "sp", static_cast<void*>(raw),
492 getCFITypeFlag<double>(),
493 static_cast<FX_SIZE>(sizeof(double)),
494 static_cast<FX_RANK>(1), bounds);
495 return fxArray<double>(descr);
496 }
497#endif // HAVE_FXARRAY
498
503 std::vector<double> w_vector() const {
504 double* raw = nullptr;
505 int64_t extents[1] = {0};
506 fitpack_parametric_curve_c_getcomp_w(as<fitpack_parametric_curve_c>(), &raw, extents);
507 const int64_t total = extents[0];
508 if (raw == nullptr || total <= 0) return {};
509 const double* first = reinterpret_cast<const double*>(raw);
510 return std::vector<double>(first, first + total);
511 }
512
513#if HAVE_FXARRAY
526 fxArray<double> w() const {
527 double* raw = nullptr;
528 int64_t extents[1] = {0};
529 fitpack_parametric_curve_c_getcomp_w(as<fitpack_parametric_curve_c>(), &raw, extents);
530 FX_SIZE bounds[2]; // (lower, upper) per dimension, Fortran lbound 1
531 for (int k = 0; k < 1; ++k) {
532 bounds[2 * k] = 1;
533 bounds[2 * k + 1] = static_cast<FX_SIZE>(extents[k]);
534 }
535 array_c descr = array_c_null;
536 array_c_from_ptr(&descr, "w", static_cast<void*>(raw),
537 getCFITypeFlag<double>(),
538 static_cast<FX_SIZE>(sizeof(double)),
539 static_cast<FX_RANK>(1), bounds);
540 return fxArray<double>(descr);
541 }
542#endif // HAVE_FXARRAY
543
552 std::vector<double> dd_vector() const {
553 double* raw = nullptr;
554 int64_t extents[2] = {0, 0};
555 fitpack_parametric_curve_c_getcomp_dd(as<fitpack_parametric_curve_c>(), &raw, extents);
556 const int64_t total = extents[0] * extents[1];
557 if (raw == nullptr || total <= 0) return {};
558 const double* first = reinterpret_cast<const double*>(raw);
559 return std::vector<double>(first, first + total);
560 }
561
566 std::array<int64_t, 2> dd_shape() const {
567 double* raw = nullptr;
568 int64_t extents[2] = {0, 0};
569 fitpack_parametric_curve_c_getcomp_dd(as<fitpack_parametric_curve_c>(), &raw, extents);
570 return { extents[0], extents[1] };
571 }
572
573#if HAVE_FXARRAY
586 fxArray<double> dd() const {
587 double* raw = nullptr;
588 int64_t extents[2] = {0, 0};
589 fitpack_parametric_curve_c_getcomp_dd(as<fitpack_parametric_curve_c>(), &raw, extents);
590 FX_SIZE bounds[4]; // (lower, upper) per dimension, Fortran lbound 1
591 for (int k = 0; k < 2; ++k) {
592 bounds[2 * k] = 1;
593 bounds[2 * k + 1] = static_cast<FX_SIZE>(extents[k]);
594 }
595 array_c descr = array_c_null;
596 array_c_from_ptr(&descr, "dd", static_cast<void*>(raw),
597 getCFITypeFlag<double>(),
598 static_cast<FX_SIZE>(sizeof(double)),
599 static_cast<FX_RANK>(2), bounds);
600 return fxArray<double>(descr);
601 }
602#endif // HAVE_FXARRAY
603
608 std::vector<double> t_vector() const {
609 double* raw = nullptr;
610 int64_t extents[1] = {0};
611 fitpack_parametric_curve_c_getcomp_t(as<fitpack_parametric_curve_c>(), &raw, extents);
612 const int64_t total = extents[0];
613 if (raw == nullptr || total <= 0) return {};
614 const double* first = reinterpret_cast<const double*>(raw);
615 return std::vector<double>(first, first + total);
616 }
617
618#if HAVE_FXARRAY
631 fxArray<double> t() const {
632 double* raw = nullptr;
633 int64_t extents[1] = {0};
634 fitpack_parametric_curve_c_getcomp_t(as<fitpack_parametric_curve_c>(), &raw, extents);
635 FX_SIZE bounds[2]; // (lower, upper) per dimension, Fortran lbound 1
636 for (int k = 0; k < 1; ++k) {
637 bounds[2 * k] = 1;
638 bounds[2 * k + 1] = static_cast<FX_SIZE>(extents[k]);
639 }
640 array_c descr = array_c_null;
641 array_c_from_ptr(&descr, "t", static_cast<void*>(raw),
642 getCFITypeFlag<double>(),
643 static_cast<FX_SIZE>(sizeof(double)),
644 static_cast<FX_RANK>(1), bounds);
645 return fxArray<double>(descr);
646 }
647#endif // HAVE_FXARRAY
648
649 // ===========================================================================================
650 // Scalar Property Accessors
651 // ===========================================================================================
652
653 int32_t& m() {
654 return *fitpack_parametric_curve_c_ref_m(as<fitpack_parametric_curve_c>());
655 }
656 const int32_t& m() const {
657 return *fitpack_parametric_curve_c_ref_m(as<fitpack_parametric_curve_c>());
658 }
659
660 int32_t& idim() {
661 return *fitpack_parametric_curve_c_ref_idim(as<fitpack_parametric_curve_c>());
662 }
663 const int32_t& idim() const {
664 return *fitpack_parametric_curve_c_ref_idim(as<fitpack_parametric_curve_c>());
665 }
666
667 bool has_params() const {
668 return fitpack_parametric_curve_c_get_has_params(as<fitpack_parametric_curve_c>());
669 }
670 void set_has_params(bool value) {
671 fitpack_parametric_curve_c_set_has_params(as<fitpack_parametric_curve_c>(), value);
672 }
673
674 int32_t& order() {
675 return *fitpack_parametric_curve_c_ref_order(as<fitpack_parametric_curve_c>());
676 }
677 const int32_t& order() const {
678 return *fitpack_parametric_curve_c_ref_order(as<fitpack_parametric_curve_c>());
679 }
680
681 double& ubegin() {
682 return *fitpack_parametric_curve_c_ref_ubegin(as<fitpack_parametric_curve_c>());
683 }
684 const double& ubegin() const {
685 return *fitpack_parametric_curve_c_ref_ubegin(as<fitpack_parametric_curve_c>());
686 }
687
688 double& uend() {
689 return *fitpack_parametric_curve_c_ref_uend(as<fitpack_parametric_curve_c>());
690 }
691 const double& uend() const {
692 return *fitpack_parametric_curve_c_ref_uend(as<fitpack_parametric_curve_c>());
693 }
694
695 int32_t& nest() {
696 return *fitpack_parametric_curve_c_ref_nest(as<fitpack_parametric_curve_c>());
697 }
698 const int32_t& nest() const {
699 return *fitpack_parametric_curve_c_ref_nest(as<fitpack_parametric_curve_c>());
700 }
701
702 int32_t& knots() {
703 return *fitpack_parametric_curve_c_ref_knots(as<fitpack_parametric_curve_c>());
704 }
705 const int32_t& knots() const {
706 return *fitpack_parametric_curve_c_ref_knots(as<fitpack_parametric_curve_c>());
707 }
708
709 // ===========================================================================================
710 // fpPoint<dim> overloads — extra_methods/fpParametricPoints.hpp (hand-maintained)
711 //
712 // The dimension is a template argument, so a point is a fixed-size POD rather than a heap
713 // allocation, and a std::vector<fpPoint<dim>> is bit-identical to the Fortran x(dim,m) it
714 // feeds. Generalizes the idea of PR #61 (@illionj) to the whole parametric family.
715 //
716 // Everything here forwards to a virtual raw method, so fpClosedCurve and fpConstrainedCurve
717 // inherit these overloads and still reach their own Fortran routines through dispatch.
718 // Methods that read an existing fit check idim() against dim and report
719 // FITPACK_INPUT_ERROR on a mismatch rather than reading past the result buffer.
720 // ===========================================================================================
721
723 FP_SIZE degree() const { return order(); }
724
726 FP_SIZE ndim() const { return idim(); }
727
729 template <FP_SIZE dim>
730 FP_FLAG new_fit(const std::vector<fpPoint<dim>>& x, FP_REAL smoothing = 1000.0, FP_SIZE order = 3)
731 {
732 std::vector<FP_REAL> xw = fpPointFlatten<dim>(x);
733 return new_fit(dim, static_cast<FP_SIZE>(x.size()), xw, nullptr, nullptr, &smoothing, &order);
734 }
735
737 template <FP_SIZE dim>
738 FP_FLAG new_fit(const std::vector<fpPoint<dim>>& x, const std::vector<FP_REAL>& u,
739 FP_REAL smoothing = 1000.0, FP_SIZE order = 3)
740 {
741 std::vector<FP_REAL> xw = fpPointFlatten<dim>(x), uw(u);
742 return new_fit(dim, static_cast<FP_SIZE>(x.size()), xw, uw.data(), nullptr, &smoothing, &order);
743 }
744
746 template <FP_SIZE dim>
747 FP_FLAG new_fit(const std::vector<fpPoint<dim>>& x, const std::vector<FP_REAL>& u,
748 const std::vector<FP_REAL>& w, FP_REAL smoothing = 1000.0, FP_SIZE order = 3)
749 {
750 std::vector<FP_REAL> xw = fpPointFlatten<dim>(x), uw(u), ww(w);
751 return new_fit(dim, static_cast<FP_SIZE>(x.size()), xw, uw.data(), ww.data(), &smoothing, &order);
752 }
753
755 FP_FLAG fit(FP_SIZE order) { return fit(nullptr, &order, nullptr); }
757 FP_FLAG fit(FP_REAL smoothing) { return fit(&smoothing, nullptr, nullptr); }
759 FP_FLAG fit(FP_REAL smoothing, FP_SIZE order) { return fit(&smoothing, &order, nullptr); }
760
762 template <FP_SIZE dim>
763 fpPoint<dim> eval(FP_REAL u, FP_FLAG* ierr = nullptr)
764 {
765 fpPoint<dim> y{};
766 if (idim() != dim) { if (ierr) *ierr = FITPACK_INPUT_ERROR; return y; }
767
768 FP_FLAG ierr0 = FITPACK_OK;
769 const std::vector<FP_REAL> flat = eval_one(u, dim, &ierr0);
770 if (ierr) *ierr = ierr0;
771 for (FP_SIZE j = 0; j < dim; ++j) y[j] = flat[static_cast<std::size_t>(j)];
772 return y;
773 }
774
776 template <FP_SIZE dim>
777 std::vector<fpPoint<dim>> eval(const std::vector<FP_REAL>& u, FP_FLAG* ierr = nullptr)
778 {
779 if (idim() != dim) { if (ierr) *ierr = FITPACK_INPUT_ERROR; return {}; }
780
781 std::vector<FP_REAL> uw(u);
782 FP_FLAG ierr0 = FITPACK_OK;
783 const std::vector<FP_REAL> flat = eval_many(uw, dim * static_cast<FP_SIZE>(u.size()), &ierr0);
784 if (ierr) *ierr = ierr0;
785 return fpPointGather<dim>(flat);
786 }
787
789 template <FP_SIZE dim>
790 fpPoint<dim> ddu(FP_REAL u, FP_SIZE order, FP_FLAG* ierr = nullptr)
791 {
792 fpPoint<dim> d{};
793 if (idim() != dim) { if (ierr) *ierr = FITPACK_INPUT_ERROR; return d; }
794
795 FP_FLAG ierr0 = FITPACK_OK;
796 const std::vector<FP_REAL> flat = dfdx(u, order, dim, &ierr0);
797 if (ierr) *ierr = ierr0;
798 for (FP_SIZE j = 0; j < dim; ++j) d[j] = flat[static_cast<std::size_t>(j)];
799 return d;
800 }
801
803 template <FP_SIZE dim>
804 std::vector<fpPoint<dim>> ddu_all(FP_REAL u, FP_FLAG* ierr = nullptr)
805 {
806 if (idim() != dim) { if (ierr) *ierr = FITPACK_INPUT_ERROR; return {}; }
807
808 FP_FLAG ierr0 = FITPACK_OK;
809 const std::vector<FP_REAL> flat = dfdx_all(u, dim * (degree() + 1), &ierr0);
810 if (ierr) *ierr = ierr0;
811 return fpPointGather<dim>(flat);
812 }
813
814protected:
815 explicit fpParametricCurve(NoAlloc tag) : fpFitter(tag) {}
816
817};
818
819#endif /* FPPARAMETRICCURVE_HPP_INCLUDED */
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
const double & ubegin() const
Definition fpParametricCurve.hpp:684
const char * c_type_name() const override
Return the C wrapper struct name for this class (e.g. "fitpack_parametric_curve_c").
Definition fpParametricCurve.hpp:157
fxArray< double > dd() const
Zero-copy fxArray view of component 'dd'.
Definition fpParametricCurve.hpp:586
fpParametricCurve()
Default constructor - allocates new fitpack_parametric_curve.
Definition fpParametricCurve.hpp:65
int32_t & m()
Definition fpParametricCurve.hpp:653
void core_comm_expand(std::vector< double > &buffer) override
core_comm_expand
Definition fpParametricCurve.hpp:335
virtual int32_t fit(double *smoothing=nullptr, int32_t *order=nullptr, bool *keep_knots=nullptr)
Definition fpParametricCurve.hpp:229
FP_FLAG fit(FP_REAL smoothing)
Refit the current points with a new smoothing.
Definition fpParametricCurve.hpp:757
const fitpack_parametric_curve_c & c_handle() const
Get underlying C wrapper (const, for interop)
Definition fpParametricCurve.hpp:179
virtual void new_points(int32_t x_n1, int32_t x_n2, std::vector< double > &x, double *u=nullptr, double *w=nullptr)
new_points
Definition fpParametricCurve.hpp:212
const int32_t & order() const
Definition fpParametricCurve.hpp:677
int32_t core_comm_size() const override
Definition fpParametricCurve.hpp:319
const int32_t & knots() const
Definition fpParametricCurve.hpp:705
fpParametricCurve(const fpParametricCurve &other)
Copy constructor - deep copy.
Definition fpParametricCurve.hpp:79
std::vector< double > u_vector() const
Deep copy of component 'u' as a std::vector.
Definition fpParametricCurve.hpp:413
int32_t & knots()
Definition fpParametricCurve.hpp:702
static fpParametricCurve make_view()
Construct an empty (non-owning) wrapper, for use as a view target.
Definition fpParametricCurve.hpp:191
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 fpParametricCurve.hpp:165
std::vector< fpPoint< dim > > ddu_all(FP_REAL u, FP_FLAG *ierr=nullptr)
All derivatives (orders 0..k) at the parameter value u.
Definition fpParametricCurve.hpp:804
void destroy_base() override
Definition fpParametricCurve.hpp:341
std::vector< fpPoint< dim > > eval(const std::vector< FP_REAL > &u, FP_FLAG *ierr=nullptr)
Evaluate the curve at every parameter value in u.
Definition fpParametricCurve.hpp:777
const int32_t & nest() const
Definition fpParametricCurve.hpp:698
void comm_pack(std::vector< double > &buffer) const override
comm_pack
Definition fpParametricCurve.hpp:300
double & uend()
Definition fpParametricCurve.hpp:688
fxArray< double > t() const
Zero-copy fxArray view of component 't'.
Definition fpParametricCurve.hpp:631
int32_t & idim()
Definition fpParametricCurve.hpp:660
fxArray< double > u() const
Zero-copy fxArray view of component 'u'.
Definition fpParametricCurve.hpp:436
std::vector< double > sp_vector() const
Deep copy of component 'sp' as a std::vector.
Definition fpParametricCurve.hpp:458
virtual std::vector< double > eval_many(std::vector< double > &u, int32_t n_result, int32_t *ierr=nullptr)
eval_many
Definition fpParametricCurve.hpp:254
fxArray< double > x() const
Zero-copy fxArray view of component 'x'.
Definition fpParametricCurve.hpp:391
FP_FLAG new_fit(const std::vector< fpPoint< dim > > &x, FP_REAL smoothing=1000.0, FP_SIZE order=3)
Fit a new curve through the points, choosing u by cumulative Euclidean distance.
Definition fpParametricCurve.hpp:730
bool is_pointer() const override
Check if this is a non-owning pointer.
Definition fpParametricCurve.hpp:150
std::vector< double > dd_vector() const
Deep copy of component 'dd' as a std::vector.
Definition fpParametricCurve.hpp:552
std::array< int64_t, 2 > dd_shape() const
Extents of component 'dd', leading dimension first.
Definition fpParametricCurve.hpp:566
virtual std::vector< double > dfdx(double u, int32_t order, int32_t n_result, int32_t *ierr=nullptr)
dfdx
Definition fpParametricCurve.hpp:265
fpParametricCurve(fitpack_parametric_curve_c &c_wrapper, bool move=false)
Construct from existing C wrapper (takes ownership if move=true)
Definition fpParametricCurve.hpp:117
fpParametricCurve & operator=(fpParametricCurve &&other) noexcept
Move assignment - transfer ownership.
Definition fpParametricCurve.hpp:106
fpPoint< dim > ddu(FP_REAL u, FP_SIZE order, FP_FLAG *ierr=nullptr)
Derivative of the given order at the parameter value u.
Definition fpParametricCurve.hpp:790
virtual void set_default_parameters()
Definition fpParametricCurve.hpp:217
bool has_params() const
Definition fpParametricCurve.hpp:667
int32_t & nest()
Definition fpParametricCurve.hpp:695
const int32_t & idim() const
Definition fpParametricCurve.hpp:663
double & ubegin()
Definition fpParametricCurve.hpp:681
fxArray< double > sp() const
Zero-copy fxArray view of component 'sp'.
Definition fpParametricCurve.hpp:481
void core_comm_pack(std::vector< double > &buffer) const override
core_comm_pack
Definition fpParametricCurve.hpp:326
fitpack_parametric_curve_c & c_handle()
Get underlying C wrapper (for interop)
Definition fpParametricCurve.hpp:172
void set_has_params(bool value)
Definition fpParametricCurve.hpp:670
~fpParametricCurve() override
Destructor - deallocates if owned.
Definition fpParametricCurve.hpp:72
FP_FLAG new_fit(const std::vector< fpPoint< dim > > &x, const std::vector< FP_REAL > &u, FP_REAL smoothing=1000.0, FP_SIZE order=3)
Fit a new curve through the points at the given parameter values u.
Definition fpParametricCurve.hpp:738
virtual int32_t interpolate(int32_t *order=nullptr, bool *reset_knots=nullptr)
Definition fpParametricCurve.hpp:233
std::vector< double > t_vector() const
Deep copy of component 't' as a std::vector.
Definition fpParametricCurve.hpp:608
virtual std::vector< double > dfdx(std::vector< double > &u, int32_t order, int32_t n_result, int32_t *ierr=nullptr)
dfdx
Definition fpParametricCurve.hpp:275
std::array< int64_t, 2 > x_shape() const
Extents of component 'x', leading dimension first.
Definition fpParametricCurve.hpp:371
double mse() const override
Definition fpParametricCurve.hpp:315
virtual int32_t least_squares(double *smoothing=nullptr, bool *reset_knots=nullptr)
Definition fpParametricCurve.hpp:237
int32_t comm_size() const override
Definition fpParametricCurve.hpp:293
FP_FLAG fit(FP_REAL smoothing, FP_SIZE order)
Refit the current points with a new smoothing and spline order.
Definition fpParametricCurve.hpp:759
FP_SIZE degree() const
Spline degree k of the current fit.
Definition fpParametricCurve.hpp:723
fpParametricCurve(NoAlloc tag)
Definition fpParametricCurve.hpp:815
fpParametricCurve(fitpack_parametric_curve_c &c_wrapper, ViewTag)
Non-owning view ctor: bit-copy the C handle, mark is_pointer=true. Used by parent classes' polymorphi...
Definition fpParametricCurve.hpp:131
const int32_t & m() const
Definition fpParametricCurve.hpp:656
virtual std::vector< double > dfdx_all(double u, int32_t n_result, int32_t *ierr=nullptr)
dfdx_all
Definition fpParametricCurve.hpp:286
std::vector< double > x_vector() const
Deep copy of component 'x' as a std::vector.
Definition fpParametricCurve.hpp:357
bool is_allocated() const override
Check if object is allocated.
Definition fpParametricCurve.hpp:143
std::vector< double > w_vector() const
Deep copy of component 'w' as a std::vector.
Definition fpParametricCurve.hpp:503
fpParametricCurve & operator=(const fpParametricCurve &other)
Copy assignment - deep copy.
Definition fpParametricCurve.hpp:87
virtual int32_t new_fit(int32_t x_n1, int32_t x_n2, std::vector< double > &x, double *u=nullptr, double *w=nullptr, double *smoothing=nullptr, int32_t *order=nullptr)
new_fit
Definition fpParametricCurve.hpp:224
const fpFitter & as_parent() const
Definition fpParametricCurve.hpp:201
fpPoint< dim > eval(FP_REAL u, FP_FLAG *ierr=nullptr)
Evaluate the curve at the parameter value u.
Definition fpParametricCurve.hpp:763
FP_SIZE ndim() const
Number of space dimensions of the fitted curve.
Definition fpParametricCurve.hpp:726
fpFitter & as_parent()
Upcast to parent type (reference, no copy)
Definition fpParametricCurve.hpp:198
fxArray< double > w() const
Zero-copy fxArray view of component 'w'.
Definition fpParametricCurve.hpp:526
fpParametricCurve(fpParametricCurve &&other) noexcept
Move constructor - transfer ownership.
Definition fpParametricCurve.hpp:98
FP_FLAG fit(FP_SIZE order)
Refit the current points with a new spline order.
Definition fpParametricCurve.hpp:755
int32_t & order()
Definition fpParametricCurve.hpp:674
void comm_expand(std::vector< double > &buffer) override
comm_expand
Definition fpParametricCurve.hpp:309
FP_FLAG new_fit(const std::vector< fpPoint< dim > > &x, const std::vector< FP_REAL > &u, const std::vector< FP_REAL > &w, FP_REAL smoothing=1000.0, FP_SIZE order=3)
Fit a new curve through the points at parameter values u, with weights w.
Definition fpParametricCurve.hpp:747
virtual std::vector< double > eval_one(double u, int32_t n_result, int32_t *ierr=nullptr)
eval_one
Definition fpParametricCurve.hpp:244
const double & uend() const
Definition fpParametricCurve.hpp:691
std::vector< fpPoint< dims > > fpPointGather(const std::vector< FP_REAL > &flat)
Rebuild a vector of points from a Fortran x(dims,m) buffer.
Definition fpPoint.hpp:127
std::vector< FP_REAL > fpPointFlatten(const std::vector< fpPoint< dims > > &points)
Flatten a vector of points into Fortran x(dims,m) order. One contiguous copy.
Definition fpPoint.hpp:117
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
A point in dims-dimensional space.
Definition fpPoint.hpp:45