Fortran相当于matlab find - 应用于切片矩阵而没有内存重复

e-m*_*ito 5 arrays matlab fortran

我在matlab中使用命令发现了很多,我想知道如何在fortran中巧妙地翻译它来提取一个数组的片段.在matlab中,您可以使用逻辑或索引进行切片,但在fortran中,您需要索引进行切片.我知道内在的子程序包等,但从未使用它们.此外,由于我正在处理大型矩阵,我想避免重复内存.我希望在子程序中操作切片矩阵.我已经在某处读过那些没有重复的数组.我不知道如何在matlab中完成切片.我也很困惑,因为在matlab中,一些分配对你来说是透明的.

我想知道如何重现下面的例子,并确保我没有复制内存中的东西,这样做实际上很优雅.否则,我会忘记切片并只发送整个矩阵(因为它是通过引用)并循环通过索引数组我...

Matlab示例1:简单地再现查找

  v=[1 2 3 4];
  I=find(v==3);
Run Code Online (Sandbox Code Playgroud)

Matlab示例2:

m=rand(4,4);
bools=logical([ 1 0 0 1]);
I=find(bools==1); 
% which I could also do like: 
I=1:size(m,1); 
I=I(bools);

  for i=1:length(I)
      % here dealing with m(I(i)),:)  and do some computation
      % etc.
Run Code Online (Sandbox Code Playgroud)

示例3:只需在m(I,:)上调用子例程,但直接使用布尔值进行切片

   foo( m(bools, :) , arg2, arg3 )
Run Code Online (Sandbox Code Playgroud)

提前谢谢你的帮助!

Hig*_*ark 10

Fortran语言不具有Matlab的精确匹配find,但你通常可以使用whereforall,有时两者,以取代其功能.

例如,给定一个数组,v例如您在第一个示例中使用的Fortran语句

where (v==3) do_stuff
Run Code Online (Sandbox Code Playgroud)

只会在元素v等于3的情况下运行.这不会像你那样得到那些元素的索引find,但是大部分的用法find是选择元素来完成它们,并且在大多数情况下该where结构适用.

鉴于v以前一样,和索引阵列ix,其在Fortran的,是这样的逻辑值的数组:

[.true., .false., .false., .true.]
Run Code Online (Sandbox Code Playgroud)

你可以使用ix,只要它的形状与v掩码数组中的相同,例如

where (ix) v = some_value
Run Code Online (Sandbox Code Playgroud)

ix 不必是一个逻辑数组,它可以是任何类型的数组,如果它是一个reals数组,你可能有一个表达式,如

where (ix>=0.0) v = some_value
Run Code Online (Sandbox Code Playgroud)

我不认为任何当前的Fortran编译器都会使用数组副本来实现where构造.我会让你读一下这个forall结构.

不要忘记,你可以使用数组作为Fortran数组的索引,所以表达式

v([1,3]) = 0
Run Code Online (Sandbox Code Playgroud)

将元素1和3设置v为0.当然,如果数组的排名大于1,则可以使用多个数组索引.

当您开始使用这种索引将数组的非连续部分传递给子程序时,您必须开始担心复制到临时数组(如果这是您想要担心的事情).我相信如果你做类似的事情,编译器可能会制作临时副本

call my_subroutine(array(1:12:3, 2:12:4))
Run Code Online (Sandbox Code Playgroud)

启用子程序,该子程序在运行时不知道数组部分的元素的索引,对它"看到"的连续数组进行操作.


小智 5

您可以使用带有隐含do循环的“pack” :

I = pack([(j,j=1,size(v))],v==3)
Run Code Online (Sandbox Code Playgroud)