Convert an array of logical type to an array of integer/double type

Multi tool use
Convert an array of logical type to an array of integer/double type
I am using Silverfrost FTN95 and, since I am not an expert, I need your help to create a function which takes as input an array of logical variables and returns an array of integer variables, 0 for false and 1 for true.
I wrote this simple code just to semplify how I tried to implement it:
program main
logical, dimension(2,1) :: a
integer, dimension(2,1) :: b
integer, dimension(2,1) :: toInt
a(:,1)=.false.
b=toInt(a)
write(*,*)b
end program
function toInt(log) result(val)
logical, dimension(2,1), intent(in) :: log
integer, dimension(2,1) :: val
do i=1,2
if (log(i,1)) then
val(i,1) = 1
else
val(i,1) = 0
end if
end do
end function
This code gives me this error: INTEGER expression expected in array bounds subscript, variable 'A' does not have the INTEGER type (at line "b=toInt(a)"), and I can't find what the error is.
Any suggestions or other ways to solve my problem would be very helpful.
Thanks
implicit none
depending on the overall code, the most computationally efficient approach might be to not use the logical array at all. Replacing
if(a(i))
with if(b(i).ne.0)
probably costs nothing except code convenience.– agentp
Nov 13 '14 at 22:13
if(a(i))
if(b(i).ne.0)
2 Answers
2
The error message comes because in the program main
you've declared toint
to be an array, so the statement toint(a)
is interpreted as an attempt to index into that array using the logical a
. You probably think that you've declared toint
as an external function which returns an integer array, but you've not given the compiler enough information to make the connection with the function definition.
main
toint
toint(a)
a
toint
You could fix that by removing the misleading declaration of toint
from the program, by moving the line end program
to the end of your source file, and by inserting the line contains
where you currently have end program
. These steps will make toint
internal and the compiler will take care of matching your calls to the function itself.
toint
end program
contains
end program
toint
But I think that there are 3, possibly more, better ways, than what you currently have.
One would be to write something along the lines of
integer, dimension(x,y) :: a,b,r
logical, dimension(x,y) :: m
! set the elements of m as you wish
a = 1
b = 0
r = merge(a,b,m)
which will assign to r
the values from a
where m
is .true.
and from b
where m
is .false.
It doesn't matter what x
and y
are, just that the array arguments to merge
are conformable. It should be relatively easy to turn this into a function for repeated use.
r
a
m
.true.
b
m
.false.
x
y
merge
Secondly, you could use a where
statement, perhaps like this
where
r = 0 ! all elements are set to 0
where(m) r = 1 ! where m is true, r is set to 1
This approach dispenses with a
and b
.
a
b
Thirdly you could investigate writing an elemental
function which operates on scalars and on arrays of any rank. I'll leave this one as an exercise. It requires some modification to the function you already have, so that it operates on scalars and not on fixed-size arrays. This third approach is probably the best - most straightforward, most flexible, easiest to program.
elemental
Which of the three, in your opinion, is the most efficient in terms of computational time?
– user4246067
Nov 13 '14 at 13:34
Over and above Mark's 3 possibilities a 4th is the merge intrinsic function - actually this is essentially his 3rd suggestion, just that it is already in the language. Here's an example:
ian@ian-pc:~/test/stack$ cat merge.f90
Program m
Implicit None
Logical, Dimension( 1:3, 1:2 ) :: log
Integer, Dimension( 1:3, 1:2 ) :: val
log = .False.
log( 2, 1 ) = .True.
val = Merge( 1, 0, log )
Write( *, * ) val
End Program m
ian@ian-pc:~/test/stack$ nagfor -C=all -C=undefined merge.f90
NAG Fortran Compiler Release 5.3.1(907)
[NAG Fortran Compiler normal termination]
ian@ian-pc:~/test/stack$ ./a.out
0 1 0 0 0 0
Actually, using
merge
was my first suggestion. But my suggestion overlooked the much more straightforward use of scalars for the merge values that you illustrate here.– High Performance Mark
Nov 20 '14 at 17:07
merge
Yeah - sorry about my inability to read, Mark!
– Ian Bush
Nov 25 '14 at 17:04
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Always use
implicit none
before asking for help! Be sure to read why it is so dangerous not to use it. I could see some exceptions for old programs, but not here. I also suggest you to use modules wherever possible.– Vladimir F
Nov 13 '14 at 8:56