关闭警告:扩展:在 (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)
其中 A
和 B
都是大小为 (n,1)
的整数数组。 B
将填入范围从 0
到 3
的整数。我需要稍后再次使用这种类型的命令,比如 A = (B.eq.1)
并且我需要 A
是一个整数数组,当且仅当 B
是 1
请求整数,否则应为 0
。这些应该充当布尔值(1
代表 .true.
,0
代表 .false.
),但我将在矩阵运算和求和中使用它们,在那里它们将被转换到除法的浮点值(必要时),因此 logical
在这种情况下值不是最佳值。
具体来说,我正在寻找此命令的最快、最矢量化的版本。为测试元素编写包装器很容易,但我希望这是一个矢量化操作以提高效率。
我目前正在使用 gfortran
进行编译,但希望使用的任何方法也能在 ifort
中使用,因为我将在以后使用 intel
编译器进行编译。
更新:
merge
和 where
都非常适合所讨论的示例。我将研究这些方面的性能指标,select 最适合矢量化。我也对这将如何与矩阵一起工作感兴趣,而不仅仅是数组,但这不是我最初的问题所以我将 post 一个新问题,除非有人想扩展他们对如何适应矩阵的答案。
我还没有找到解决 (1) 的编译器选项。
但是,类型转换非常简单。 The documentation for gfortran
指定 .true.
映射到 1
,false
映射到 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
语句可以用同样的方式扩展。
既然你稍后将它们转换为浮点数,为什么不立即将它们指定为浮点数呢?假设 A
是 real
,这可能看起来像:
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_vec
的 true
元素的元素,并将 0 分配给其他元素。
where
结构适用于任何排名数组。
对于这个特定的示例,您可以一起避免逻辑:
A=1-(3-B)/3
当然在可读性方面不太好,但在性能方面可能还可以。
编辑,运行 性能测试这比 where
构造快 2-3 倍,当然绝对符合标准。事实上,你可以输入一个绝对值并归纳为:
integer,parameter :: h=huge(1)
A=1-(h-abs(B))/h
并且仍然击败 where
循环。
我有意将布尔值数组转换为整数,但收到此警告:
Warning: Extension: Conversion from LOGICAL(4) to INTEGER(4) at (1)
我不想要。我可以吗
(1) 在 Makefile 中关闭该警告?
或(更有利)
(2) 在代码中显式进行此转换,这样编译器就不需要担心了?
代码看起来像这样:
A = (B.eq.0)
其中 A
和 B
都是大小为 (n,1)
的整数数组。 B
将填入范围从 0
到 3
的整数。我需要稍后再次使用这种类型的命令,比如 A = (B.eq.1)
并且我需要 A
是一个整数数组,当且仅当 B
是 1
请求整数,否则应为 0
。这些应该充当布尔值(1
代表 .true.
,0
代表 .false.
),但我将在矩阵运算和求和中使用它们,在那里它们将被转换到除法的浮点值(必要时),因此 logical
在这种情况下值不是最佳值。
具体来说,我正在寻找此命令的最快、最矢量化的版本。为测试元素编写包装器很容易,但我希望这是一个矢量化操作以提高效率。
我目前正在使用 gfortran
进行编译,但希望使用的任何方法也能在 ifort
中使用,因为我将在以后使用 intel
编译器进行编译。
更新:
merge
和 where
都非常适合所讨论的示例。我将研究这些方面的性能指标,select 最适合矢量化。我也对这将如何与矩阵一起工作感兴趣,而不仅仅是数组,但这不是我最初的问题所以我将 post 一个新问题,除非有人想扩展他们对如何适应矩阵的答案。
我还没有找到解决 (1) 的编译器选项。
但是,类型转换非常简单。 The documentation for gfortran
指定 .true.
映射到 1
,false
映射到 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
语句可以用同样的方式扩展。
既然你稍后将它们转换为浮点数,为什么不立即将它们指定为浮点数呢?假设 A
是 real
,这可能看起来像:
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_vec
的 true
元素的元素,并将 0 分配给其他元素。
where
结构适用于任何排名数组。
对于这个特定的示例,您可以一起避免逻辑:
A=1-(3-B)/3
当然在可读性方面不太好,但在性能方面可能还可以。
编辑,运行 性能测试这比 where
构造快 2-3 倍,当然绝对符合标准。事实上,你可以输入一个绝对值并归纳为:
integer,parameter :: h=huge(1)
A=1-(h-abs(B))/h
并且仍然击败 where
循环。