在Fortran 03/08(gfortran编译器)中使用无限多态类型用于数组操作 [英] Use of unlimited polymorphic type for array operation in Fortran 03/08 (gfortran compiler)

查看:584
本文介绍了在Fortran 03/08(gfortran编译器)中使用无限多态类型用于数组操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过 class(*)特性来实现有用的数组运算(添加元素,删除元素,可分配/指针/二叉树结构的不同实现)无限多态性)。我使用gfortran 5.0应该处理这样的功能。我需要它为不使用每种类型重复相同的代码。



这应该看起来像

  function add_element(array,element)
class(*),intent(in):: array(:)
class(*),intent
class(*):: add_element(size(array)+1)
add_element = [array,element]
end function

问题是,当我尝试使用这个函数有一个确定的类型,我有一个返回结果的错误。我不能将 class(*)赋给某个没有 select type 的确定类型变量,我肯定不想有选择类型结构每次我使用它。在一个子程序中,我不应该知道任何类型的东西,因为我会创建很多的。



我尝试了一些变体 move_alloc ,source,试图使用 intent(out)参数等子程序它没有工作。我认为它应该在参数属性中定义,与size(与源关键字?)相同,但没有找到一个示例或这种结构的标准定义。当然,我将学习这个标准更多(我不是一个专业程序员,但物理学家试图让我的程序可测试,可检查和更舒适的更改),并将简单地重复此代码现在等待更好的解决方案,但也许任何人知道在哪里在标准或一些书中搜索它?我认为这不仅仅是数组,但使用 class(*)在所有,因为我认为应该有不知道类型的方法...



不知道我是否应该添加这个子程序的其他不工作形式的示例或它对错误所说的话 - 或者一个问题将不会被重点关注。它可以被编译,但在所有情况下,分配给定义类型的调用不工作。对于参数 intent(out)(inout),它不能从虚拟参数转移到实际参数。从源重定位使一个对象的类型(和在我的例子中的分配结果),但类型是隐藏的...我不能使用子类型中的选择类型,因为我不知道类型。 / p>

此外,我不知道可以检查同一类型或在此上下文中的某些结构...

select type ,但Fortran没有像 type是(type_of(x))。另一方面,有 SAME_TYPE_AS() EXTENDS
TYPE_OF()
内在性,但你不能使用它们作为类型保护。



有必要确保 array code>元素是一样的。



我认为这是标准的缺陷。



但是,你的方法有一个错误。您应该使函数结果可分配,以便能够将其分配到正确的动态类型:



class(*),allocatable :: add_element :)



您可能会想到一些符合以下条件的内容:UNTESTED!与gfortran-4.9 ifort14一起编译



allocate(add_element(size(array)+1),mold = array)



但是如何实际传输的值我不知道,我担心,如果不诉诸一些肮脏的技巧可能是不可能的。



你甚至不能使用 transfer 这就是我看到的真正的不足。

  transfer(element,add_element(1))
 

code> add_element(1)= transfer(element,add_element(1))



是的,Fortran缺少类型保护的选项,只是确保两个变量具有相同的动态类型。



你可能会想到一些类似于:UNTESTED! with gfortran-4.9 ifort14)

 函数add_element(array,element)
使用iso_c_binding
implicit none
类(*),intent(in):: array(:)
class(*),intent(in):: element
class(*),allocatable :: add_element
类型(c_ptr):: tmp

接口
函数memcpy(dest,src,n)bind(c)
使用iso_c_binding
integer(c_intptr_t ),value :: dest,src
integer(c_size_t):: n
类型(c_ptr):: memcpy
结束函数
结束接口

alloc(add_element(size(array)+1),mold = array)

tmp = memcpy(loc(add_element(size(array)+1)),&
loc(array),&
size(array,kind = c_size_t)* storage_size(array,c_size_t)/ 8_c_size_t)
tmp = memcpy(loc(add_element(size(array)+1))&
loc (array(1)),&
storage_size(element,c_size_t)/ 8_c_size_t)

end函数


I'd like to realize useful array operations (add element, remove element, different realizations by allocatable/pointer/binary tree structures) by class(*) feature (unlimited polymorphism). I use gfortran 5.0 that should handle such a feature. I need it for not repeating identical code for each type I use.

This should look something like

function add_element(array,element)
  class(*),intent(in)::array(:)
  class(*),intent(in)::element
  class(*)::add_element(size(array)+1)
       add_element=[array,element]
end function

The problem is that when I try to use this function with some definite type, I have an error with returning result. I can not assign class(*) to some definite type variable without select type, and I surely don't want to have select type structures every time I use it. And inside a subroutine I should not know anything of types I want to use, because I will create many of them.

I tried some variants with move_alloc, source, tried to use subroutine with intent(out) argument etc. It didn't work. I think it should be defined in argument attributes, the same as size (with source keyword?) but didn't find an example or a definition of such structure in standard. Of course I will study this standard more (I'm not a professional programmer but physicist trying to make my programs testable, checkable and more comfortable to change) and will simply repeat this code now in waiting for better solution, but maybe anybody knows where to search it in the standard or some book? I think this is not only about arrays but use of class(*) at all as I think there should be methods that don't know of types...

Don't know if I should add examples of other not working forms of this subroutine or what it says about the error - or a question will be unfocused. It can be compiled, but in all cases assigning to definite type in call doesn't work. For argument intent(out) or (inout) it can not go from dummy argument to actual argument. Reallocation from source makes an object which has type (and a result of assigning in my example too), but the type is hidden... and I can't use the select type in subroutine because I don't know the type.

Also I don't know constructs that could check "the same type as" or something in this context...

解决方案

This is not an easy problem You can use select type, but Fortran doesn't have anything like type is(type_of(x)). On the other hand, there are the SAME_TYPE_AS() and EXTENDS TYPE_OF() intrinsics, but you cannot use them as type guards.

It is necessary to assure, that the dynamic types of both array and element are the same.

I think this is a deficiency in the standard.

But still, there is an error in your approach. You should make the function result allocatable, to be able to allocate it to correct dynamic type:

class(*), allocatable ::add_element(:)

You may think something along the lines of: (UNTESTED! compiles with gfortran-4.9 ifort14)

allocate(add_element(size(array)+1), mold=array)

But how to actually transfer the values I don't know and I am worried it might not be possible without resorting to some dirty tricks.

You cannot even use transfer and that is where I see real deficiency. Eventhough you can call transfer with polymorphic mold

transfer(element, add_element(1))

you have no way to assign it to the array element

add_element(1) = transfer(element, add_element(1))

My opinion is that Fortran lacks an option for the type guards that just ensures that two variables have the same dynamic type.

You may think something along the lines of: (UNTESTED! compiles with gfortran-4.9 ifort14)

function add_element(array,element)
  use iso_c_binding
  implicit none
  class(*),intent(in)::array(:)
  class(*),intent(in)::element
  class(*), allocatable ::add_element(:)
  type(c_ptr) :: tmp

  interface
    function memcpy(dest, src, n) bind(c)
      use iso_c_binding
      integer(c_intptr_t),value :: dest, src
      integer(c_size_t) :: n
      type(c_ptr) :: memcpy
    end function
  end interface

  allocate(add_element(size(array)+1), mold=array)

  tmp = memcpy(loc(add_element(size(array)+1)), &
               loc(array), &
               size(array, kind=c_size_t) * storage_size(array, c_size_t)/8_c_size_t )
  tmp = memcpy(loc(add_element(size(array)+1)), &
               loc(array(1)), &
               storage_size(element, c_size_t)/8_c_size_t )

end function

这篇关于在Fortran 03/08(gfortran编译器)中使用无限多态类型用于数组操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆