Merging arrays in Fortran 77 - fortran

I have two arrays: A = [1 2 3 4] and B = [5 6 7 8]. How can I merge A & B into one array, C, and then sort C in ascending order? I need to do this in fortran 77.

Here is a naive implementation of the concatenation/sorting algorithm:
program sort
integer size1, size2, sizeout
parameter (size1 = 4, size2 = 4)
parameter (sizeout = size1 + size2)
integer in1(size1), in2(size1)
data in1/1,2,4,4/, in2/5,8,7,5/
integer out(sizeout)
c concatenate arrays
do j=1,size1
out(j)=in1(j)
enddo
do j=1,size2
out(j+size1)=in2(j)
enddo
c sort the elements of the output array
4 do j=2,sizeout
if(out(j).lt.out(j-1)) then
temp =out(j-1)
out(j-1)=out(j )
out(j )=temp
goto 4
endif
enddo
end

Related

Search for odd indices using the section method

I don't understand how I can implement the search for even elements using the section method.
I did a search for odd elements, but I need to find even ones
I need it to output 2 4 6 8, but my program outputs 1 3 5 7 9
program main
implicit none
integer, DIMENSION(3, 3) :: array = reshape((/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), shape(array))
integer :: i = 0
integer, allocatable :: B(:)
B = [(Array(::2,i), i=1, 3)]
print *, B
end program main
If you're interested in the elements with odd indices, you want
B = [(Array(modulo(i,2)+1::2, i), i=1, 3)]
modulo(i,2)+1 is 2 when i is odd, and 1 when i is even. This means that for columns with odd i you select every other element starting at the second element, and for columns with even i you select every other element starting at the first element.
If instead you're interested in selecting the odd values from an arbitrary array, you can't do this with a simple slice, and you instead need a conditional filter. For example,
B = [integer::]
do i=1,3
do j=1,3
if (modulo(Array(j,i),2)==0) then
B = [B, Array(j,i)]
endif
enddo
enddo

OMP Parallel Fortran : Swapping array element values, getting random results

First of all, Happy New Year 2022.
I am new in learning OMP Parallel programming in Fortran.
Need HELP with my codes below, which produces a correct result if run in serial,
but produces a random (incorrect) result if run in parallel (multi-threads).
Purpose is to swap the values of some array elements in global shared array A(N:N).
Cannot figure out or identify what is wrong in my code below
(i.e. any race conditions in updating elements of Array A ?)
SUBROUTINE SWAP_COLUMNS (IS)
INTEGER :: IS, L, LH, KK
INTEGER :: I, J
L = (IS - 1) / 2
LH = L + 1
!$OMP PARALLEL DEFAULT(PRIVATE) SHARED(A,IS,L,LH)
!$OMP DO
DO J = 1, L
DO I = 1, IS
KK = I + IS
IF (I == LH) THEN
CALL SWAP_VALUES (I, J+1, KK, J+1)
ELSE
CALL SWAP_VALUES (I, J, KK, J)
END IF
END DO
END DO
!$OMP END DO
!$OMP END PARALEL
SUBROUTINE SWAP_VALUES (I3, K1, I4, K2)
INTEGER :: IT, I3,K1, I4,K2
IT = A(I3, K1)
A(I3, K1) = A(I4,K2)
A(I4, K2) = IT
END SUBROUTINE
Example :
Array A (6,6) :
8 1 6 ….
3 5 7 ….
4 9 2 …
35 28 33 …
30 32 34 …
31 36 29 …
I would expect that the result would always be correct (as run with single thread)
with IS = 3 , the correct expected result :
35 1 6 ….
3 32 7 ….
31 9 2 …..
8 28 33 ….
30 5 34 ….
4 36 29 ...
I tried a manual calculation :
IS = 3
Iteration 1 : J = 1, I = 1, KK = 4
CALL SWAP_VALUES (1, 1, 4, 1) ----> Swap A(1,1) & A(4,1)
Iteration 2 : J = 1, I = 2, KK = 5
CALL SWAP_VALUES (2, 2, 5, 2) -----> Swap A(2,2) & A(5,2)
Last Iteration 3 : J =1, I = 3, KK = 6
CALL SWAP_VALUES( 3,1, 6,1) -----> A(3,1) & A(6,1)
I would expect that even run in parallel (multi threads), as each element of array A
is accessed or updated independently (not dependent on the loop iteration
(before or after), there should be no issue of race condition, and the local variable IT
is a private variable in subroutine SWAP_VALUES.
But instead, I get a random result, sometimes correct and sometimes incorrect,
and sometimes the element value does not swap, or sometimes it is copied but
not swapped so the value becomes duplicated ( e.g. A(1,1) = 35 and A(4,1) = 35
instead of 8)

Extract the minor matrix from a 3x3 based on input i,j

For a given 3x3 matrix, for example:
A = [3 1 -4 ; 2 5 6 ; 1 4 8]
If I need the minor matrix for entry (1,2)
Minor = [2 6 ; 1 8]
I already wrote a program to read in the matrix from a text file, and I am supposed to write a subroutine to extract the minor matrix from the main matrix A based on the user inputs for i,j. I am very new to Fortran and have no clue how to do that. I made some very desperate attempts but I am sure there is a cleaner way to do that.
I got so desperate I wrote 9 if functions for each possible combination of i and j but that clearly is not a smart way for doing this. Any help is appreciated!
One way to do this is, as #HighPerformanceMark said in the comment, with vector subscripts. You can declare an array with the rows you want to keep, and the same for columns, and pass them as indices to your matrix. Like this:
function minor(matrix, i, j)
integer, intent(in) :: matrix(:,:), i, j
integer :: minor(size(matrix, 1) - 1, size(matrix, 2) - 1)
integer :: rows(size(matrix, 1) - 1), cols(size(matrix, 2) - 1), k
rows = [(k, k = 1, i - 1), (k, k = i + 1, size(rows))]
cols = [(k, k = 1, j - 1), (k, k = j + 1, size(cols))]
minor = matrix(rows, cols)
end
(I didn't test it yet, so tell me if there is any error)
Another option would be constructing a new matrix from 4 assignments, one for each quadrant of the result (limited by the excluded row/column).
I like the first option more because it is more scalable. You could easily extend the function to remove multiple rows/columns by passing arrays as arguments, or adapt it to work on higher dimensions.
You can use an ac-implied-do and RESHAPE to construct a mask of the parts of the matrix you want to preserve and then zap the rest with pack and reassemble with RESHAPE.
program minor
implicit none
integer A(3,3)
integer, allocatable :: B(:,:)
character(20) fmt
integer i, j
A = reshape([ &
3, 1, -4, &
2, 5, 6, &
1, 4, 8], &
shape(A), order = [2,1])
write(fmt,'(*(g0))') '(a/',size(A,2),'(i3))'
write(*,fmt) 'A =',transpose(A)
B = reshape(pack(A,reshape([((all([i,j]/=[1,2]),i=1,size(A,1)), &
j=1,size(A,2))],shape(A))),shape(A)-1)
write(fmt,'(*(g0))') '(a/',size(B,2),'(i3))'
write(*,fmt) 'B =',transpose(B)
end program minor
Output:
A =
3 1 -4
2 5 6
1 4 8
B =
2 6
1 8

Population of vector with matrix elements column by column

My IDE is CodeBlocks 16.01.
This is my code:
Program Matrix_To_Vector
Implicit none
Integer::i,j
Integer, parameter :: M = 3 , N = 2
Integer, dimension ( M , N ) :: Matrix_0
Integer, dimension ( M*N ) :: Vector_0
! Population of matrix
Do i = 1 , 3
Do j = 1 , 2
Matrix_0(i,j) = i+j
End Do
End Do
Open (15, File = 'Result.txt', Status = 'Unknown', Action = 'Write')
Do i = 1 , 3
Write(15,*) Matrix_0(i,:)
End Do
Write(15,*) ( Vector_0(i), i =1 , size(Vector_0))
Close (15)
End Program Matrix_To_Vector
The result of matrix population is:
2 3
3 4
4 5
My intention is to make vector Vector_0 with elements from matrix Matrix_0. The size of vector is M*N. First element of vector is (1,1) from matrix and last is (3,2) - i want to do that column by column.
Is there way for doing that with do loops?
The contetn of wanted vector is:
2 3 4 3 4 5
like this?
do j=1,2
vector_0(3*(j-1)+1:3*(j-1)+3)=Matrix_0(:,j)
enddo
of course you could just do
vector_0=reshape(matrix_0,shape(vector_0))
as well

-fortran : reading numbers from a text file

I have a text file of numbers containing several columns and several lines. I have tried several ways including arrays but in the best result I could get only 3 columns of the whole. Any ideas how I can read all the data in Fortran 77?
open(unit=1, file='f', status='old')
do i = 1, 100
read(1, *) x(i), y(i), z(i)
write(6, * ) x(i), y(i), z(i)
enddo
or even 2 dimensional arrays:
do i = 1, 100
do j = 1, 50
read(1, *) x(i, j)
write(6, *) x(i, j)
enddo
enddo
or changing the open(..., access='direct')
none of them worked out since i have a file like this:
1 2 4.5 77 89 4 3 2...
2 4 4 5 6 73 5 3.4 ...
1 2 4 5 67 8 99...
...
The data does not seem to have any particular structure.
You can use list-directed input for this:
program main
real a(100)
read (*,*) a
print *,a
end
I would advise you against using any unit number smaller than 10 in your code for your own purposes.