Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

true_pos #568

Closed
Beliavsky opened this issue Nov 16, 2021 · 9 comments · Fixed by #603
Closed

true_pos #568

Beliavsky opened this issue Nov 16, 2021 · 9 comments · Fixed by #603
Labels
good first issue Good for newcomers topic: utilities containers, strings, files, OS/environment integration, unit testing, assertions, logging, ...

Comments

@Beliavsky
Copy link

In a Fortran Discourse thread Indexing arrays by an array of logicals I mentioned a true_pos function I had written to simulate logical indexing, and @ivan-pi suggested that it be considered for stdlib. To deal with the case of a lbound /= 1 mentioned by mecej4, I have added an optional lower_bound argument. If tf(:) has the same size as x(:), one can write x(true_pos(tf)) to refer to elements of x where tf is .true. One can also write pack(x,tf), but that cannot appear on the LHS of an assignment. I have used true_pos hundreds of times in my codes -- maybe it would be generally useful. Since Fortran has minloc, maxloc, and findloc, maybe true_pos should be renamed trueloc.

pure function true_pos(tf, lower_bound) result(ipos)
! return in ipos the positions of the true elements in tf(:)
logical, intent(in)           :: tf(:)
integer, intent(in), optional :: lower_bound 
integer                       :: ipos(count(tf))
integer                       :: i,j
j = 0
do i=1,size(tf)
   if (tf(i)) then
      j = j + 1
      ipos(j) = i
   end if
end do
if (present(lower_bound)) ipos = ipos + lower_bound - 1
end function true_pos
@milancurcic
Copy link
Member

I think it would be useful. I like the name trueloc better than true_pos.

Perhaps controversial, but consider calling this function where. I think it looks very nice in use:

a(where(b > 0)) = 0

which is similar to

where(b > 0) a = 0

A more concise form could be

a(at(b > 0)) = 0

Where would this function belong? Should we introduce a module for array helper functions, e.g. stdlib_array?

@milancurcic milancurcic added good first issue Good for newcomers topic: utilities containers, strings, files, OS/environment integration, unit testing, assertions, logging, ... labels Nov 17, 2021
@ivan-pi
Copy link
Member

ivan-pi commented Nov 17, 2021

I also like trueloc better than true_pos. In MATLAB the function is called find, and also has an optional argument for the number of elements to find.

If trueloc were to be the name, would it make sense to have falseloc too, or does the form:

trueloc(A > B) ! find indexes of true values
trueloc(.not. (A > B)) ! find indexes of false values

suffice?

@arjenmarkus
Copy link
Member

arjenmarkus commented Nov 17, 2021 via email

@awvwgk
Copy link
Member

awvwgk commented Dec 19, 2021

A quick test with GFortran 11 shows the following difference in timings for 1200 invocations of trueloc, where and merge (longest array tested is 120000 elements). Timings in seconds.

trueloc where merge
2.02 0.39 0.46

@jvdp1
Copy link
Member

jvdp1 commented Dec 20, 2021

A quick test with GFortran 11 shows the following difference in timings for 1200 invocations of trueloc, where and merge (longest array tested is 120000 elements). Timings in seconds.

trueloc where merge
2.02 0.39 0.46

Could you provide the details of your test prog, please? I wonder how would compare something like pack( [ (i, i = 1, size(array))], array > 1.0)?

@jvdp1
Copy link
Member

jvdp1 commented Dec 20, 2021

A quick test with GFortran 11 shows the following difference in timings for 1200 invocations of trueloc, where and merge (longest array tested is 120000 elements). Timings in seconds.

trueloc where merge
2.02 0.39 0.46

I don't know the details of the program, but trueloc has IMO a different goal than where and merge because it can returns a index vector that could be used for other purposes (which is not always possible with where and merge).

@awvwgk
Copy link
Member

awvwgk commented Dec 20, 2021

Could you provide the details of your test prog, please? I wonder how would compare something like pack( [ (i, i = 1, size(array))], array > 1.0)?

Added the timing routines in #603 as well as a comparison with pack. trueloc is a factor 2 slower than pack.

Also, included a pack based implementation in the statistic there (it gets slower).

@jvdp1
Copy link
Member

jvdp1 commented Dec 20, 2021

Actually, with the flags -O3 -fopenmp and GCC11, I got a ratio around 1 with where, ~3- with merge and <1 with pack.

@ivan-pi
Copy link
Member

ivan-pi commented Dec 20, 2021

A quick test with GFortran 11 shows the following difference in timings for 1200 invocations of trueloc, where and merge (longest array tested is 120000 elements). Timings in seconds.
trueloc where merge
2.02 0.39 0.46

I don't know the details of the program, but trueloc has IMO a different goal than where and merge because it can returns a index vector that could be used for other purposes (which is not always possible with where and merge).

I agree that trueloc has a different goal from the intrinsics. I can't recall the specifics now, but I think it was related to discretization in a PDE solver (e.g. boundary points require different handling the points in the bulk region). In this case I had to construct the index array so I could reference the right positions in the storage for a sparse matrix.

Therefore I wouldn't be too concerned with the performance penalty. For the case of "simple" assignment depending upon a condition, the specs could contain a note suggesting where or pack as the canonical way of doing this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers topic: utilities containers, strings, files, OS/environment integration, unit testing, assertions, logging, ...
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants