关闭警告:扩展:在 (1) 处从 LOGICAL(4) 转换为 INTEGER(4) for gfortran?

Turn off Warning: Extension: Conversion from LOGICAL(4) to INTEGER(4) at (1) for gfortran?

我有意将布尔值数组转换为整数,但收到此警告:

Warning: Extension: Conversion from LOGICAL(4) to INTEGER(4) at (1)

我不想要。我可以吗

(1) 在 Makefile 中关闭该警告?

或(更有利)

(2) 在代码中显式进行此转换,这样编译器就不需要担心了?

代码看起来像这样:

A = (B.eq.0)

其中 AB 都是大小为 (n,1) 的整数数组。 B 将填入范围从 03 的整数。我需要稍后再次使用这种类型的命令,比如 A = (B.eq.1) 并且我需要 A 是一个整数数组,当且仅当 B1请求整数,否则应为 0。这些应该充当布尔值(1 代表 .true.0 代表 .false.),但我将在矩阵运算和求和中使用它们,在那里它们将被转换到除法的浮点值(必要时),因此 logical 在这种情况下值不是最佳值。

具体来说,我正在寻找此命令的最快、最矢量化的版本。为测试元素编写包装器很容易,但我希望这是一个矢量化操作以提高效率。

我目前正在使用 gfortran 进行编译,但希望使用的任何方法也能在 ifort 中使用,因为我将在以后使用 intel 编译器进行编译。

更新:

mergewhere 都非常适合所讨论的示例。我将研究这些方面的性能指标,select 最适合矢量化。我也对这将如何与矩阵一起工作感兴趣,而不仅仅是数组,但这不是我最初的问题所以我将 post 一个新问题,除非有人想扩展他们对如何适应矩阵的答案。

我还没有找到解决 (1) 的编译器选项。

但是,类型转换非常简单。 The documentation for gfortran 指定 .true. 映射到 1false 映射到 0

请注意,标准未指定转换,其他编译器可以使用不同的值。具体来说,您不应依赖于确切的值。

一个简单的 merge 就可以解决标量和数组的问题:

program test
  integer :: int_sca, int_vec(3)
  logical :: log_sca, log_vec(3)

  log_sca = .true.
  log_vec = [ .true., .false., .true. ]

  int_sca = merge( 1, 0, log_sca )
  int_vec = merge( 1, 0, log_vec )

  print *, int_sca
  print *, int_vec
end program

要解决您更新后的问题,这对 merge:

来说很简单
A = merge(1, 0, B == 0)

这可以在任意维度的标量和数组上执行。对于后者,这可以很容易地被编译器矢量化。不过,您应该为此查阅编译器的手册。

中的where语句可以用同样的方式扩展。


既然你稍后将它们转换为浮点数,为什么不立即将它们指定为浮点数呢?假设 Areal,这可能看起来像:

A = merge(1., 0., B == 0)

另一种赞美@AlexanderVogt 的方法是使用 where 结构。

program test
  implicit none
  integer :: int_vec(5)
  logical :: log_vec(5)

  log_vec = [ .true., .true., .false., .true., .false. ]

  where (log_vec)
     int_vec = 1
  elsewhere
     int_vec = 0
  end where

  print *, log_vec
  print *, int_vec
end program test

这会将 1 分配给 int_vec 中对应于 log_vectrue 元素的元素,并将 0 分配给其他元素。

where 结构适用于任何排名数组。

对于这个特定的示例,您可以一起避免逻辑:

 A=1-(3-B)/3

当然在可读性方面不太好,但在性能方面可能还可以。

编辑,运行 性能测试这比 where 构造快 2-3 倍,当然绝对符合标准。事实上,你可以输入一个绝对值并归纳为:

 integer,parameter :: h=huge(1)
 A=1-(h-abs(B))/h

并且仍然击败 where 循环。