j3-fortran / fortran_proposals

Proposals for the Fortran Standard Committee
178 stars 15 forks source link

Constant Expression Value Arguments for Generic Resolution #320

Open everythingfunctional opened 1 year ago

everythingfunctional commented 1 year ago

It has so far been impossible to write user defined functions that can mimic the behavior of various intrinsic functions. I.e.

function real(A, KIND)
  real, intent(in) :: A
  integer, intent(in) :: KIND
  real(KIND) :: real
end function

But if we had some mechanism to define a constant expression value that must be one of the arguments we could do it. I.e. some suggestive syntax

interface real
  module function str_to_real128(A, KIND, STAT)
    character(len=*), intent(in) :: A
    integer, parameter, intent(in) :: KIND = real128
    integer, intent(out), optional :: STAT
    real(real128) :: str_to_real128
  end function
  ...
end interface
...
real(real128) :: my_val
my_val = real("1.234", KIND=real128)
certik commented 1 year ago

Nice idea. I modified your example to say interface str instead of interface real, since I think that's what you meant.

everythingfunctional commented 1 year ago

Actually I did mean real. The example is intending to extend the real intrinsic to work for converting strings to real numbers.

jacobwilliams commented 1 year ago

Same as #91 I think?

everythingfunctional commented 1 year ago

Same as #91 I think?

Very similar, yes, but I think the solution I propose is different.

certik commented 1 year ago

@everythingfunctional I see --- you had there "str" in the function call, but "real" as the interface. Everything is clear now after your edit.

shahmoradi commented 1 year ago

A mechanism like the optional kind type parameter (with kind attribute) of parameterized derived types would be ideal. So instead of

integer, parameter, intent(in) :: KIND = real128

we'd write,

integer, kind :: kind = real128

similar to PDTs. I have so far bypassed this issue by introducing a like dummy argument for type resolution. But then one has to live with endless compiler warnings about unused dummy arguments and, more importantly, an interface inconsistent with intrinsic procedures of the same name and functionality. There is a clear need for this facility in the language from a user's perspective.

everythingfunctional commented 1 year ago

My idea was more along the lines of that argument being required and required to have the given value (so the compiler can actually do the code generation), but it can then be used for generic resolution. This is a bit with an eye towards one of the generics features being worked on so you could do something like:

generic function real(A, KIND, STAT)
  use iso_fortran_env, only: real_kinds
  character(len=*, kind=*), intent(in) :: A
  integer, parameter, intent(in) :: KIND = real_kinds
  integer(*), intent(out), optional :: STAT
  real(KIND) :: real
  ...
end function
generic function real(A, STAT)
  character(len=*, kind=*), intent(in) :: A
  integer(*), intent(out), optional :: STAT
  real :: real
  real = real(A, kind(real), STAT)
end function

You could also use a feature like this to disambiguate between allocatable or not like a bunch of people seem to want to lately. I.e.

interface foo
  module subroutine foo_alloc(A, WHICH)
    integer, allocatable, intent(inout) :: A(:)
    character(len=*), parameter, intent(in) :: WHICH = "allocatable"
  end subroutine
  module subroutine foo_static(A, WHICH)
    integer, intent(inout) :: A(:)
    character(len=*), parameter, intent(in) :: WHICH = "static"
  end subroutine
end interface
integer, allocatable :: x(:)
call foo(x, "allocatable")
FortranFan commented 1 year ago

.. interface real module function str_to_real128(A, KIND, STAT) character(len=*), intent(in) :: A integer, parameter, intent(in) :: KIND = real128 integer, intent(out), optional :: STAT real(real128) :: str_to_real128 ..

A typo here? Was the following that was meant?


..
 real(KIND) :: str_to_real128
..
everythingfunctional commented 1 year ago

Given my idea, and that interface, they're equivalent.

FortranFan commented 1 year ago

So instead of

integer, parameter, intent(in) :: KIND = real128

we'd write,

integer, kind :: kind = real128

Agree totally.

The clause (or call it an attribute if one prefer) of , KIND implies compile-time semantics for the processor. The , parameter doesn't jive with what is in the language since the 2003 revision.

KHUSHIJAIN910 commented 11 months ago

user defined function can be achieved here by adding libraries of different languages here.

ivan-pi commented 1 day ago

I like this proposal. It would be helpful in writing numeric types which are closer to intrinsic floating and integer types (for instance big ints or emulate floats)

For instance if one implements quad-precision type using double-double:

type quad
   real(kind(1.0)) :: hi, lo
end type

it would make it easier to write generic code if it could be extended to work with the conversion routines:

type(quad) :: a 
real :: b
a = 1.0  ! overloaded assignment
print *, real(a,kind=kind(1.0)) ! convert to single

Would it make sense to also allow resolution using a (constant) enumerator?

everythingfunctional commented 8 hours ago

Would it make sense to also allow resolution using a (constant) enumerator?

I don't see why not. They're basically integers.