module eml_class_fortran
    !! [All elementary functions from a single operator](https://arxiv.org/html/2603.21852)
    !! [SupplementaryInformation.pdf](https://arxiv.org/src/2603.21852v2/anc/SupplementaryInformation.pdf)

    use, intrinsic :: iso_fortran_env, only: real64

    use, intrinsic :: ieee_arithmetic, only: ieee_is_nan



    implicit none



    private

    public :: eml_real64_class
    public :: real64

    public :: assignment(=)

    public :: cmplx
    public :: eml_operator
    public :: ieee_is_nan
    public :: imag
    public :: real



    type, abstract :: eml_real64_class

        complex(real64), private :: hidden

        contains

        procedure, pass, private, non_overridable :: set_p1_real64

        generic, public :: set_p1 => set_p1_real64

    end type



    interface assignment(=)
        module procedure :: assign_eml_real64
        module procedure :: assign_complex64_to_eml_real64
        module procedure :: assign_real64_to_eml_real64
    end interface

    interface cmplx
        module procedure :: eml_cmplx_real64
    end interface

    interface eml_operator
        module procedure :: eml_operator_real64
    end interface

    interface ieee_is_nan
        module procedure :: ieee_is_nan_eml_real64
    end interface

    interface imag
        module procedure :: eml_imag_real64
    end interface

    interface real
        module procedure :: eml_real_real64
    end interface



    contains



    elemental complex(real64) function eml_cmplx_real64(x)

        class(eml_real64_class), intent(in) :: x

        eml_cmplx_real64 = x%hidden

    end function



    elemental real(real64) function eml_imag_real64(x)

        class(eml_real64_class), intent(in) :: x

        eml_imag_real64 = x%hidden%im

    end function



    elemental complex(real64) function eml_operator_real64(x, y)
        !! \( \operatorname{eml} (x,y) = \exp (x) - \ln (y) \)

        class(eml_real64_class), intent(in) :: x, y

        eml_operator_real64 = exp(x%hidden) - log(y%hidden)

    end function



    elemental real(real64) function eml_real_real64(x)

        class(eml_real64_class), intent(in) :: x

        eml_real_real64 = x%hidden%re

    end function



    elemental logical function ieee_is_nan_eml_real64(x)

        class(eml_real64_class), intent(in) :: x

        ieee_is_nan_eml_real64 = &!
            ieee_is_nan(x%hidden%re) .and. &!
            ieee_is_nan(x%hidden%im)

    end function



    elemental subroutine assign_eml_real64(dst, src)

        class(eml_real64_class), intent(inout) :: dst

        class(eml_real64_class), intent(in) :: src

        dst%hidden = src%hidden

    end subroutine



    elemental subroutine assign_complex64_to_eml_real64(dst, src)

        class(eml_real64_class), intent(inout) :: dst

        complex(real64), intent(in) :: src

        dst%hidden = src

    end subroutine



    elemental subroutine assign_real64_to_eml_real64(dst, src)

        class(eml_real64_class), intent(inout) :: dst

        real(real64), intent(in) :: src

        dst%hidden = src

    end subroutine



    elemental subroutine set_p1_real64(self)

        class(eml_real64_class), intent(inout) :: self

        self = 1.0_real64

    end subroutine

end module
