In Fortran, is it possible to select certain parts of the an array by using some vector of logical values instead of the indices? For example like this:
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 an easy (fast) way to find the indices where iszero=0?
edit: I changed the example to present a more realistic case, in previous case I just changed some values to 100.0d0, where the elementwise handling would have been ok..
edit2: had one type on the fourth row of the code
where (mymatrix==0) mymatrix = 100.0d0
will set all elements in mymatrix which are 0 to 100. If you are actually trying to do something a little more sophisticated than that, perhaps setting a matrix to have a 'checkerboard' of 1s and 0s you could try something like;
mymatrix(1:m:2,2:n:2) = 100d0
where m,n are the numbers of rows and columns in mymatrix. I haven't tested this latter snippet, it's just a suggestion to consider array subscript triplets sometimes.
EDIT
If you actually want to use one matrix (or vector) as the mask in the where statement and another in the assignment part, ie something like this:
where(index_matrix==0) mymatrix = 100d0
then you have (I think) to ensure that index_matrix
has the same size as mymatrix
. In your case you might end up with a statement such as:
where(reshape([0,1],[3,3],pad=[0,1])==0) mymatrix = 100d0
again I haven't tested this and I don't expect that I've got the padded reshape quite right but you can probably figure out the details.
FURTHER EDIT
I'm now finding it difficult to follow the question. The statement
sum0 = sum(iszero==0)
will assign the value 1 to sum, so the statement
mysubmatrix(1:sum0,1:sum0) = mymatrix(iszero==0,iszero==0)
will, at run time, be something like this:
mysubmatrix(1:1,1:1) = mymatrix(iszero==0,iszero==0)
and I'm not sure that the rhs and lhs conform properly for Fortran. Does this compile ? If it does, does it execute correctly (with array-bounds checking) ?
Are you trying to create submatrix
which holds only the 0 elements of mymatrix
? If so then I think you are going to have a hard time of it, for the general case. Unless you can define the locations of the elements you want to select in terms of either indices or a vector of subscripts or a subscript triplet, then I don't see that you can make an array on the lhs from the array on the rhs.
If the locations of the 0s are arbitrary then you might be able to do what you want by flattening the original array to rank-1 and creating a rank-1 subarray of that, but you would lose the correspondence between 2D locations and their 1D counterparts.
FINALLY
Don't forget that you can, in Fortran 2003, use a pointer to refer to a sub-matrix defined by vector or triplet subscripts, for example
pointer_to_array => target_array(1:10:2,2:10:2)
and then pass pointer_to_array
around.
For rank-1 array, the array subset can be taken by a local array mask using the intrinsic function PACK
. For example (in Fortran 2003)
INTEGER :: X(5) = [1,2,0,3,0]
INTEGER, ALLOCATABLE :: XX(:)
XX = PACK(X,X/=0)
will pick out the non-zero elements from X, and store into XX (on return XX = [1,2,3]).
I think the answer is no, you cannot do what you are suggesting; at least upto FORTRAN 90 anyway. Having said that, I am 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 rapid! Even if you had a large number of these DO loops it would still be relatively fast (faster than doing it than any other language at least!).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.