# Selecting a subset of an array given by a boolean vector in Fortran

In Fortran, is it possible to select specific parts of an array using a vector of vector values ​​instead of indices? For example, for example:

``````iszero(1) = 0
iszero(2) = 1
iszero(3) = 0
sum0 = sum(iszero) !was  sum0 = sum(iszero==0)
!mymatrix is arbitary is 3 times 3 array
mysubmatrix(1:sum0,1:sum0) = mymatrix(iszero==0,iszero==0)
call dtrmv('l','n','u',sum0,mysubmatrix(1:sum0,1:sum0),sum0,x(1:sum0)),1)
```

```

If this is not possible directly, is there a simple (fast) way to find the indices where iszero = 0?

edit: I modified the example to present a more realistic case, in the previous case I just changed some values ​​to 100.0d0 where basic handling would be fine.

edit2: had one type in the fourth line of code

+3

source to share

``````where (mymatrix==0) mymatrix = 100.0d0
```

```

will set all the elements in mymatrix to be between 0 and 100. If you are actually trying to do something more complex than this, perhaps to set a checkerboard matrix of 1 and 0, you can try something like:

``````mymatrix(1:m:2,2:n:2) = 100d0
```

```

where m, n are the number of rows and columns in mymatrix. I have not tested this last snippet, it is just a suggestion to consider triplets of array indices sometimes.

EDIT

If you really want to use one matrix (or vector) as a mask in the where clause and another in the assignment part, then there is something like this:

``````where(index_matrix==0) mymatrix = 100d0
```

```

then you have (I think) to `index_matrix`

have the same size as `mymatrix`

. In your case, you can specify an operator, for example:

``````where(reshape([0,1],[3,3],pad=[0,1])==0) mymatrix = 100d0
```

```

again I have not tested this and I do not expect I have a fixed change, but you can perhaps figure out the details.

FURTHER PICTURE

Now I find it difficult to understand this question. Statement

``````sum0 = sum(iszero==0)
```

```

will assign the value 1, so the statement

``````mysubmatrix(1:sum0,1:sum0) = mymatrix(iszero==0,iszero==0)
```

```

at runtime it will look something like this:

``````mysubmatrix(1:1,1:1) = mymatrix(iszero==0,iszero==0)
```

```

and I'm not sure if rhs and lhs are Fortran correct. Will this compile? If so, is it being executed correctly (with array bounds checking)?

Are you trying to create `submatrix`

one that only contains 0 items `mymatrix`

? If so, I think it will be difficult for you to do it in general. If you can't figure out the locations of the elements you want to select in terms of indices or a vector of indices or an index triplet, then I don't see that you can make an array on lhs from an array on rhs.

If the 0s locations are arbitrary, then you can do what you want by flattening the original array to rank-1 and creating a subarray of rank-1, but you will lose alignment between the 2D locations and their 1D counterparts.

FINALLY

Don't forget that in Fortran 2003 you can use a pointer to refer to a submatrix defined by vector or triplet indices, for example

``````pointer_to_array => target_array(1:10:2,2:10:2)
```

```

and then walk `pointer_to_array`

around.

+7

source

For a rank-1 array, a subset of the array can be taken with a local array mask using the built-in function `PACK`

. For example (in Fortran 2003)

``````INTEGER :: X(5) = [1,2,0,3,0]
INTEGER, ALLOCATABLE :: XX(:)
XX = PACK(X,X/=0)
```

```

will select nonzero elements from X and store in XX (on return XX = [1,2,3]).

+6

source

I think the answer is no, you cannot do what you suggest; at least up to FORTRAN 90 anyway. Having said that, I'm not sure why something like

``````DO I = 1, 3
DO J = 1, 3
IF (iszero(I) == 0 .AND. iszero(J) == 0)
mymatrix(I, J) = 100.0d0
ENDIF
ENDDO
ENDDO
```

```

Something like this for a 3x3 array would be fast! Even if you had a large number of these DO loops, it would still be relatively fast (faster than doing this than any other language, at least!).

+1

source

All Articles