Clinton Winant
Clinton Winant

Reputation: 734

How to form a 3d array by spreading a 1d vector

A frequent task is to form an array that contains a variable raised to a combination of powers. If p is the sequence 1,2,3 then I could want X^{p(k)+p(l)} for k,l=1,2,3 This MWE does just that:

Program Main
use, intrinsic :: iso_c_binding
implicit none
integer(c_int) :: p(3)=(/0,1,0/)
integer(c_int) :: arrayP(3,3)
integer(c_int) :: krow,kcol
real(c_double) :: arrayR(3,3)
arrayP=spread(p,1,3)+spread(p,2,3)
do krow=1,3
   write(*,*)(arrayP(kcol,krow),kcol=1,3)
end do
arrayR=2.0d0**arrayP
! write array as three frames side by side
do krow=1,3
   write(*,fmt="(3(1pe10.2))")(arrayR(kcol,krow),kcol=1,3)
end do
End Program Main

The output is:

       0           1           0
       1           2           1
       0           1           0
1.00E+00  2.00E+00  1.00E+00
2.00E+00  4.00E+00  2.00E+00
1.00E+00  2.00E+00  1.00E+00

I need to extend this to a 3d array, in order to find X^{p(k)+p(l)}+p(m)} for k,l,m=1,2,3 The obvious extension of what I have in the MWE:

integer(c_int) :: arrayP(3,3,3)
arrayP=spread(p,1,3)+spread(p,2,3)+spread(p,3,3)

doesn't work, because you cant spread an array in more than n+1 dimensions, where n is the rank of p, in this case 1. Neither questions 21010295 or 31573252 address this issue. Suggestions?

Upvotes: 0

Views: 259

Answers (1)

Alex338207
Alex338207

Reputation: 1905

You can chain spread as mentioned by francescalus to obtain a 3D array (see below) The 3 first writes produce all the sequence 1, 2 and 3. However, you might consider to just 3 nested loop which is my opinion is easier to read.

program test_spread
  implicit none
  integer :: a(3) = (/ 1, 2, 3 /)
  integer :: array(3,3,3)
  real    :: arrayR(3,3,3)
  integer :: i,j,k

  array = spread(spread(a, 2, 3),3,3)
  write(6,*) array(:,1,1)

  array = spread(spread(a, 1, 3),3,3)
  write(6,*) array(1,:,1)

  array = spread(spread(a, 1, 3),2,3)
  write(6,*) array(1,1,:)

  arrayR = 2.0**(                           &
     spread(spread(a, 2, 3),3,3) +           &
     spread(spread(a, 1, 3),3,3) +           &
     spread(spread(a, 1, 3),2,3))

  write(6,*) 'arrayR (1)',arrayR
  do k = 1,3
    do j = 1,3
      do i = 1,3
        arrayR(i,j,k) = 2.0**(a(i)+a(j)+a(k))
      end do
    end do
  end do

  write(6,*) 'arrayR (2)',arrayR

 end program test_spread

Upvotes: 1

Related Questions