问题
For a programming exercise, I was given the lower triangular elements of a symmetric 3x3 matrix saved as an array
|1 * *|
|2 4 *| => [1,2,3,4,5,6]
|3 5 6|
I need to make the product C(i)=C(i)+M(i,j)V(j) where M is the symmetric matrix and V is a vector.
V =>[A,B,C]
C(1)=1*A + 2*B + 3*C
C(2)=2*A + 4*B + 5*C
C(3)=3*A + 5*B + 6*C
I am trying to make an efficient algorithm that can perform this product
I can easily generate all the product I need for C(3) However, I have a problem when I try to generate the values C(1), C(2) and I don't know how to get around this without using extra memory.
This is what I have done
k=6
n=3
DO 1 j = n,1,-1
l= k
DO 2 i = n,j + 1,-1
C(i) = C(i) + V(j)*M(l)
l = l - 1
2 enddo
C(j) = V(j)*M(k-n+j)
k = k - (n-j+1)
1 enddo
The problem I have is that I can no generate and add the 2*B for C(1) and the 5*C for C(2). The goal of the exercise is to use as few steps and as little array space as possible.
Any suggestions?
回答1:
There are multiple issues with your code:
- In the outer loop, you assign
C(n)
(probably the diagonal entries), so the computation of inner loop is not used at all - You are looping over the lower left triangle from back to front, if you would reverse that, the indexing inside the vectorized matrix would be much simpler
- The calculation of the position inside the matrix (
k
andl
) is wrong - You do not calculate the products of the mirrored elements
Here is my solution that honors above points:
! Loop over all elements in the lower left triangle
k = 0
do j=1,n
! Increment the position inside the unrolled matrix
k = k+1
! diagonal entries, i = j
c(j) = c(j) + v(j)*M(k)
! off-diagonal entries
do i=j+1,n
! Increment the position inside the unrolled matrix
k = k+1
! Original entry
c(i) = c(i) + v(j)*M(k)
! Mirrored one
c(j) = c(j) + v(i)*M(k)
enddo !i
enddo !j
来源:https://stackoverflow.com/questions/45093764/lower-triangular-matrix-vector-product