Search code examples
pythonnumpyfortran

Fortran equivalent of numpy.roll function


Python's numpy.roll function rolls arrays along an axis. Example:

from numpy import roll, array
x = array([[1,0,2],[2,1,9],[5,5,1]])
print(roll(x, 1, axis=0))

transforms the matrix x into

array([[5, 5, 1],
       [1, 0, 2],
       [2, 1, 9]])

I try to do this in Fortran by slicing a matrix row and attaching it to the existing matrix:

program myfun

implicit none
integer, parameter :: N=3
real, dimension(N,N) :: m
integer :: i, j

m = 0
do i = 1, N
    m(i, i) = 1.0
enddo
m(3,1) = 2
m(3,2) = 9
m(1,3) = 5
m(1,2) = 2
m(2,3) = 5

print *, '', [m(:,N), m]

end program myfun

This produces matrix

[5, 5, 1]
[1, 0, 2]
[2, 1, 9]
[5, 5, 1]  <- need to remove this row (how?)

Is this the best way to perform numpy.roll in Fortran? If so, how do I delete the last row of the matrix?


Solution

  • If I understand what you are asking cshift is what you want. Below is an example, and you can find more details here

    Program:

    Program test_cshift
    
      Use iso_fortran_env, Only : stdout => output_unit
      
      Implicit None
    
      Integer, Dimension( 1:3, 1:3 ) :: m = Reshape( [ 1, 0, 2,   &
                                                       2, 1, 9,   &
                                                       5, 5, 1 ], &
                                                       Shape( m ) )
    
      Write( stdout, * ) 'Original'
      Write( stdout, '( 3( 3( i1, 1x ), / ) )' ) m
      Write( stdout, * ) 'After cshift'
      Write( stdout, '( 3( 3( i1, 1x ), / ) )' ) Cshift( m, -1, 2 )
    
    End Program test_cshift
    

    Compilation and linking:

    ijb@ijb-Latitude-5410:~/work/stack$ gfortran --version
    GNU Fortran (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
    Copyright (C) 2019 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    
    ijb@ijb-Latitude-5410:~/work/stack$ gfortran -Wall -Wextra -pedantic -fcheck=all -std=f2018 -O -g cshift.f90
    

    Testing:

    ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
     Original
    1 0 2
    2 1 9
    5 5 1
    
     After cshift
    5 5 1
    1 0 2
    2 1 9
    
    ijb@ijb-Latitude-5410:~/work/stack$