public inbox for fortran@gcc.gnu.org
 help / color / mirror / Atom feed
From: Paul Richard Thomas <paul.richard.thomas@gmail.com>
To: "fortran@gcc.gnu.org" <fortran@gcc.gnu.org>
Cc: Steve Lionel <steve@stevelionel.com>
Subject: Overriding intrinsic operators
Date: Fri, 1 Jan 2021 16:14:46 +0000	[thread overview]
Message-ID: <CAGkQGi+WB-vrx_G=k=V49WGo+orB6a52hAPowB2M1q7TOXpb6Q@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 1829 bytes --]

Hi All,

Happy New Year!

I took an interest in a recent clf thread, entitled "comparison between
class(*) instances", and submitted an example of a possible implementation.
I have attached a reduced version of it.

gfortran, back as far as version 7.4.1, gives the expected output:
a & b are type pvar
T
 a & b are type pvar
 F

ifort (IFORT) 2021.1 Beta 20201112 gives:
 a & b are type pvar
 class default: returning false
 class default: returning false
 F
 a & b are type pvar
 class default: returning false
 class default: returning false
 F

This comes about because ifort is using the defined operation to override
the intrinsic uses of the operator as defined in 10.1.5 of the standard.

I believe that gfortran has this one right, since the first paragraph of
15.4.3.4.2 Defined operations has:
"...If the operator is an intrinsic-operator (R608), the number of dummy
arguments shall be consistent with the intrinsic uses of that operator, and
the types, kind type parameters, or ranks of the dummy arguments shall
differ from those required for the intrinsic operation (10.1.5)."

ifort gives the expected result if the interface is moved to the main
program.

Steve, I would be grateful if you would pass this on because my Intel uid
seems to have expired. Of course, your thoughts would be welcome.

The second attachment does away with the select type constructs by
transferring the unlimited polymorphic payloads to deferred length
characters and comparing them. The use of unlimited polymorphic actual
arguments is leading to invalid reads and the loss of 8 bytes in two blocks
because realloc is being finickity about the casting of the arguments.
Also, when u and v carry strings, both storage_size and transfer fail
because the _len field is not used. I will raise PRs on these issues
tomorrow.

Regards

Paul

[-- Attachment #2: equals4.f90 --]
[-- Type: text/x-fortran, Size: 1086 bytes --]

MODULE mytypes
  IMPLICIT none

  TYPE pvar
     character(len=20) :: name
     integer           :: level
  end TYPE pvar

  interface operator (==)
     module procedure pvar_eq
  end interface

contains
  function pvar_eq(a,b)
    implicit none
    class(*), intent(in) ::a,b
    logical ::pvar_eq
    if (.not. same_type_as (a, b)) then
      pvar_eq = .false.
      return
    end if
    select type (a)
      type is (pvar)
      select type (b)
        type is (pvar)
          print *, "a & b are type pvar"
          if((a%level.eq. b%level) .and. (a%name .eq. b%name)) then
            pvar_eq = .true.
          else
            pvar_eq = .false.
          end if
      end select
      class default
        print *, "class default: returning false"
        pvar_eq = .false.
    end select
  end function pvar_eq
end MODULE mytypes

program test_eq
   use mytypes
   implicit none
   type(pvar) x, y
   x = pvar('test 1', 100)
   y = pvar('test 1', 100)
   write(*, *) x == y
   x = pvar('test 1', 100)
   y = pvar('test 2', 100)
   write(*, *) x == y
end program test_eq


[-- Attachment #3: equals5.f90 --]
[-- Type: text/x-fortran, Size: 1156 bytes --]

MODULE mytypes
  IMPLICIT none

  TYPE pvar
     character(len=20) :: name
     integer           :: level
  end TYPE pvar

  interface operator (==)
     module procedure star_eq
  end interface

contains
  function star_eq(a,b)
    implicit none
    class(*), intent(in) ::a,b
    character(len=:), allocatable :: c1, c2
    logical ::star_eq
    integer(8) :: sza, szb
    star_eq = same_type_as (a, b)
    if (.not. star_eq) return
    sza = storage_size (a)/8
    szb = storage_size (b)/8
    if (sza .ne. szb) then
      star_eq = .false.
    else
      allocate(character(len = sza) :: c1)
      allocate(character(len = szb) :: c2)
      c1 = transfer (a, c1)
      c2 = transfer (b, c2)
      star_eq = c1 .eq. c2
    end if
  end function star_eq
end MODULE mytypes

program test_eq
   use mytypes
   implicit none
   type(pvar) :: x, y
   class(*), allocatable :: u, v
   x = pvar('test 1', 100)
   y = pvar('test 1', 100)
   write(*, *) x == y
   u = pvar('test 1', 100)
   v = pvar('test 2', 100)
   write(*, *) u == v
   u = 1.0_4
   v = 2.0_4
   write(*, *) u == v
   v = 1.0_4
   write(*, *) u == v
   deallocate (u,v)
end program test_eq


             reply	other threads:[~2021-01-01 16:14 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-01 16:14 Paul Richard Thomas [this message]
     [not found] ` <a23a5712-8381-787e-4583-9ab54bed2a20@stevelionel.com>
2021-01-01 18:31   ` Paul Richard Thomas
2021-01-02  9:45   ` Paul Richard Thomas
2021-01-03 12:22   ` Paul Richard Thomas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAGkQGi+WB-vrx_G=k=V49WGo+orB6a52hAPowB2M1q7TOXpb6Q@mail.gmail.com' \
    --to=paul.richard.thomas@gmail.com \
    --cc=fortran@gcc.gnu.org \
    --cc=steve@stevelionel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).