63 real(real64),
allocatable,
dimension(:) :: m_coeffs
66 generic,
public :: initialize => init_poly, init_poly_coeffs
68 procedure,
public :: order => get_poly_order
70 procedure,
public :: fit => poly_fit
73 procedure,
public :: fit_thru_zero => poly_fit_thru_zero
75 generic,
public :: evaluate => evaluate_real, evaluate_complex
77 procedure,
public :: companion_mtx => poly_companion_mtx
79 procedure,
public :: roots => poly_roots
81 procedure,
public :: get => get_poly_coefficient
83 procedure,
public :: get_all => get_poly_coefficients
85 procedure,
public :: set => set_poly_coefficient
87 procedure :: evaluate_real => poly_eval_double
88 procedure :: evaluate_complex => poly_eval_complex
89 procedure :: init_poly
90 procedure :: init_poly_coeffs
110 subroutine init_poly(this, order, err)
113 integer(int32),
intent(in) :: order
114 class(errors),
intent(inout),
optional,
target :: err
117 real(real64),
parameter :: zero = 0.0d0
120 integer(int32) :: n, istat
121 class(errors),
pointer :: errmgr
122 type(errors),
target :: deferr
126 if (
present(err))
then
135 call errmgr%report_error(
"init_polynomial", &
136 "A negative polynomial order is not supported.", &
137 nl_invalid_input_error)
142 if (
allocated(this%m_coeffs))
deallocate(this%m_coeffs)
143 allocate(this%m_coeffs(n), stat = istat)
146 call errmgr%report_error(
"init_polynomial", &
147 "Insufficient memory available.", nl_out_of_memory_error)
167 subroutine init_poly_coeffs(this, c, err)
170 real(real64),
intent(in),
dimension(:) :: c
171 class(errors),
intent(inout),
optional,
target :: err
174 integer(int32) :: i, n
175 class(errors),
pointer :: errmgr
176 type(errors),
target :: deferr
180 if (
present(err))
then
187 call init_poly(this, n - 1, errmgr)
188 if (errmgr%has_error_occurred())
return
192 call this%set(i, c(i))
284 subroutine poly_fit(this, x, y, order, err)
287 real(real64),
intent(in),
dimension(:) :: x
288 real(real64),
intent(inout),
dimension(:) :: y
289 integer(int32),
intent(in) :: order
290 class(errors),
intent(inout),
optional,
target :: err
293 real(real64),
parameter :: one = 1.0d0
296 integer(int32):: j, n, ncols, flag
297 real(real64),
pointer,
dimension(:,:) :: a
298 class(errors),
pointer :: errmgr
299 type(errors),
target :: deferr
304 if (
present(err))
then
311 if (
size(y) /= n)
then
313 call errmgr%report_error(
"polynomial_fit",
"Array size mismatch.", &
316 else if (order >= n .or. order < 1)
then
318 call errmgr%report_error(
"polynomial_fit",
"The requested " // &
319 "polynomial order is not valid for this data set.", &
320 nl_invalid_input_error)
325 allocate(a(n,ncols), stat = flag)
328 call errmgr%report_error(
"polynomial_fit", &
329 "Insufficient memory available.", nl_out_of_memory_error)
334 if (this%order() /= order)
then
335 call this%initialize(order, errmgr)
336 if (errmgr%has_error_occurred())
return
345 a(:,j) = a(:,j-1) * x
349 call solve_least_squares(a, y, err = errmgr)
350 if (errmgr%has_error_occurred())
return
353 this%m_coeffs = y(1:ncols)
375 subroutine poly_fit_thru_zero(this, x, y, order, err)
378 real(real64),
intent(in),
dimension(:) :: x
379 real(real64),
intent(inout),
dimension(:) :: y
380 integer(int32),
intent(in) :: order
381 class(errors),
intent(inout),
optional,
target :: err
384 real(real64),
parameter :: zero = 0.0d0
387 integer(int32):: j, n, ncols, flag
388 real(real64),
pointer,
dimension(:,:) :: a
389 class(errors),
pointer :: errmgr
390 type(errors),
target :: deferr
395 if (
present(err))
then
402 if (
size(y) /= n)
then
404 call errmgr%report_error(
"polynomial_fit_thru_zero", &
405 "Array size mismatch.", nl_array_size_error)
407 else if (order >= n .or. order < 1)
then
409 call errmgr%report_error(
"polynomial_fit_thru_zero", &
410 "The requested polynomial order is not valid for this " // &
411 "data set.", nl_invalid_input_error)
416 allocate(a(n,ncols), stat = flag)
419 call errmgr%report_error(
"polynomial_fit_thru_zero", &
420 "Insufficient memory available.", nl_out_of_memory_error)
425 if (this%order() /= order)
then
426 call this%initialize(order, errmgr)
427 if (errmgr%has_error_occurred())
return
433 a(:,j) = a(:,j-1) * x
437 call solve_least_squares(a, y, err = errmgr)
438 if (errmgr%has_error_occurred())
return
441 this%m_coeffs(1) = zero
442 this%m_coeffs(2:ncols+1) = y(1:ncols)
724 subroutine set_poly_coefficient(this, ind, c, err)
727 integer(int32),
intent(in) :: ind
728 real(real64),
intent(in) :: c
729 class(errors),
intent(inout),
optional,
target :: err
732 class(errors),
pointer :: errmgr
733 type(errors),
target :: deferr
736 if (
present(err))
then
743 if (this%order() == -1)
return
746 if (ind <= 0 .or. ind > this%order() + 1)
then
748 call errmgr%report_error(
"set_polynomial_coefficient", &
749 "The specified index is outside the bounds of the " // &
750 "coefficient array.", nl_invalid_input_error)
755 this%m_coeffs(ind) = c
820 function poly_poly_add(x, y)
result(z)
826 integer(int32) :: i, max_ord, x_ord, y_ord
831 max_ord = max(x_ord, y_ord)
832 call z%initialize(max_ord)
835 if (x_ord == -1 .and. y_ord == -1)
return
836 if (x_ord == -1 .and. y_ord /= -1)
then
837 do i = 1, max_ord + 1
838 call z%set(i, y%get(i))
841 else if (x_ord /= -1 .and. y_ord == -1)
then
842 do i = 1, max_ord + 1
843 call z%set(i, x%get(i))
849 if (x_ord > y_ord)
then
851 call z%set(i, x%get(i) + y%get(i))
853 do i = y_ord + 2, x_ord
854 call z%set(i, x%get(i))
856 else if (x_ord < y_ord)
then
858 call z%set(i, x%get(i) + y%get(i))
860 do i = x_ord + 2, y_ord + 1
861 call z%set(i, y%get(i))
864 do i = 1, max_ord + 1
865 call z%set(i, x%get(i) + y%get(i))
877 function poly_poly_subtract(x, y)
result(z)
883 integer(int32) :: i, max_ord, x_ord, y_ord
888 max_ord = max(x_ord, y_ord)
889 call z%initialize(max_ord)
892 if (x_ord == -1 .and. y_ord == -1)
return
893 if (x_ord == -1 .and. y_ord /= -1)
then
894 do i = 1, max_ord + 1
895 call z%set(i, y%get(i))
898 else if (x_ord /= -1 .and. y_ord == -1)
then
899 do i = 1, max_ord + 1
900 call z%set(i, x%get(i))
906 if (x_ord > y_ord)
then
908 call z%set(i, x%get(i) - y%get(i))
910 do i = y_ord + 2, x_ord
911 call z%set(i, x%get(i))
913 else if (x_ord < y_ord)
then
915 call z%set(i, x%get(i) - y%get(i))
917 do i = x_ord + 2, y_ord + 1
918 call z%set(i, -y%get(i))
921 do i = 1, max_ord + 1
922 call z%set(i, x%get(i) - y%get(i))