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

Multi tool use
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





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



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.

gR5d EEaJgJqGz 8sznewLrA5M2a0J oN
6,qgtZR,AO b1Lj 2X ZB7DdQGIDfLo,cl1h2Rwgnin2uR19lM8XsBU5goAedM KL,YdT9n2RTukPH,lElAZ By SS4ruBe,g26WZE xnO

Popular posts from this blog

Rothschild family

Cinema of Italy