compute_real128 Subroutine

private elemental subroutine compute_real128(agm, x, y)

Safe wrapper for the arithmetic-geometric mean (AGM) computation.

This type-bound subroutine performs AGM computation with input validation, automatic ordering, and complete convergence history storage. Unlike arithmetic_geometric_mean_kernel, this subroutine retains all intermediate calculation results and can be retrieved later.

Note

  • If either input was NaN: returns NaN
  • If x and y had opposite signs (x * y .lt. 0): returns NaN
  • If either x or y is zero (x * y .eq. 0): returns 0
  • Otherwise: full AGM iteration using compute_kernel_real128

Warning

Calling this subroutine overwrites any previous computation stored in the object.

Type Bound

arithmetic_geometric_mean_real128_type

Arguments

Type IntentOptional Attributes Name
class(arithmetic_geometric_mean_real128_type), intent(inout) :: agm
real(kind=real128), intent(in) :: x
real(kind=real128), intent(in) :: y

Variables

Type Visibility Attributes Name Initial
real(kind=real128), private :: xy

Source Code

    elemental subroutine compute_real128(agm, x, y)
        !! Safe wrapper for the arithmetic-geometric mean (AGM) computation.
        !!
        !! This type-bound subroutine performs AGM computation
        !! with input validation, automatic ordering,
        !! and complete convergence history storage.
        !! Unlike [[arithmetic_geometric_mean_kernel]],
        !! this subroutine retains all intermediate calculation results
        !! and can be retrieved later.
        !!
        !! @note
        !! - If either input was NaN: returns NaN
        !! - If `x` and `y` had opposite signs (`x * y .lt. 0`): returns NaN
        !! - If either `x` or `y` is zero (`x * y .eq. 0`): returns 0
        !! - Otherwise: full AGM iteration using [[compute_kernel_real128]]
        !! @endnote
        !!
        !! @warning
        !! Calling this subroutine overwrites any previous computation
        !! stored in the object.
        !! @endwarning

        class(arithmetic_geometric_mean_real128_type), intent(inout) :: agm

        real(real128), intent(in) :: x, y



        real(real128) :: xy



        if ( ieee_unordered(x, y) ) then

            call initialize(agm)

            agm%n_iter_ = agm%n_iter_ + 1

            return

        end if



        xy = x * y



        if ( xy .lt. 0.0_real128 ) then

            call initialize(agm)

            agm%n_iter_ = agm%n_iter_ + 1

        else if ( xy .gt. 0.0_real128 ) then

            if (x .lt. y) then
                call agm%compute_kernel(init_a = y, init_g = x)
            else
                call agm%compute_kernel(init_a = x, init_g = y)
            end if

        else

            call initialize(agm)

            agm%n_iter_ = 0

            if (x .lt. y) then

                agm%list_a(agm%n_iter_) = y
                agm%list_g(agm%n_iter_) = x

            else

                agm%list_a(agm%n_iter_) = x
                agm%list_g(agm%n_iter_) = y
        
            end if

            agm%n_iter_ = agm%n_iter_ + 1

            agm%list_a(agm%n_iter_) = 0.0_real128
            agm%list_g(agm%n_iter_) = 0.0_real128

        end if

    end subroutine compute_real128