Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

my first program

luvfort
Beginner
1,185 Views
Hello all,

i've been watching this forum for a while. I took some suggestions and wrote a program to add/subtract two any size matrix prescribed by the user! please take a look at it and give suggestions for improvement.

[cpp]!** This program adds two matrices of any size
!   The user inputs the size of matrix
!   The matrix has to be input in normal way [1 2]
!                                            [3 4]
!   output will be in the same way
!*******************************
! subroutine that adds matrices*
!*******************************
module m_add
implicit real*8(a-h, o-z)
contains
subroutine matrixadd(s,d,m,n)
dimension a(m,n),b(m,n),s(m,n),d(m,n)
write(*,*) 'enter the 1st matrix'
read(*,*) a
write(*,*)'enter the 2nd matrix'
read(*,*) b
s=a+b
d=a-b
end subroutine
end module 
!***************************!
! Main program              !
!***************************!
program addm
use m_add
implicit real*8 (a-h, o-z)
real*8, allocatable :: a(:,:),b(:,:),s(:,:),d(:,:)
write(*,*) 'enter the size of the matrix'
read(*,*) m,n
allocate(a(m,n),b(m,n),s(m,n),d(m,n))
call matrixadd(s,d,m,n)
print*, 'Matrix Addition'
do j=1,n; print 10,(s(i,j),i=1,m)
enddo
print*, 'Matrix subtraction'
do j=1,n; print 10, (d(i,j),i=1,m)
enddo
10 format(10f10.1/)
end program ! addm[/cpp]

0 Kudos
10 Replies
Les_Neilson
Valued Contributor II
1,185 Views

Welcome to the forum.
Just some minor comments, only on style - but style is a personal preference anyway, others may have different opinions.

I prefer to use "implicit none" and then specify variables explicitly. That way spelling errors (typos) may be caught more easily.
I also prefer, when possible, to declare one variable per line - often makes future edits easier to do. When used witha source control system it is also easier to see what has changed when comparing the histories of a file.
The same with executable statements
do j=1,n; print 10, etc
I would write as two lines.

I allocate one array at a time with error checking - when working on commercial projects a "graceful error trap" is better than a program failure. (with consequent loss of user data. This is A Bad Thing !)

Using modules isA Good Thing.
I often code modules as follows :

module X
Putthe data variables including allocatables here

contains

Initialise routine(s) to allocate the arrays andassign initial values to all variables

Asubroutine to reallocate_arrays.For dynamic programs where the size of the data "grows"- retaining the original values if necessary.

Routines tomanipulate the data,e.g. perform some calculations as you have done.

Maybe Get and Set routines to get the value of a variable or assign a value to a variable - helps prevent accidental overwrite of values.

and so on.

As I say a personal style preference.

Les
0 Kudos
John4
Valued Contributor I
1,185 Views
IMPLICIT NONE is always a good idea. Also, since you're using modules, you might consider dropping the last two arguments in matrixadd (using, for example, "s(:,:),d(:,:)" instead of "s(m,n),d(m,n)"). Your subroutine only has four arguments, so those arguments might not be a problem, but as the number of arguments increases, it could give you some headaches.

Also, try to always use the INTENT attribute for your function/subroutine arguments and avoid declarations like real*8 (for portability purposes). So, in my opinion, the beginning of your subroutine would look better this way:

subroutinematrixadd(s, d)
integer, parameter :: wp = KIND(1.d0)
real(wp), intent(OUT) :: s(:,:), d(:,:)
real(wp), allocatable :: a(:,:), b(:,:)
integer :: m, n
...
m = SIZE(s, 1)
n = SIZE(s, 2)
allocate (a(m, n), b(m, n))
...


0 Kudos
luvfort
Beginner
1,185 Views
Hi Les , John

Thank you very much for you feedback !!!!
this really helps me improve my programming skills, sorry I was busy with other works, so I couldn't reply soon

So I combined both of your suggestion and here is the improvised code, i guess :)

[cpp]program main1
use m_add_sub
implicit none
real(suf), allocatable :: a(:,:),b(:,:)
real(suf), allocatable :: s(:,:),d(:,:)
print*, 'Enter the size of matrix'
read(*,*) m,n
allocate(a(m,n),b(m,n),s(m,n),d(m,n))
write(*,*) 'enter the 1st matrix'
do j=1,n 
read(*,*) (a(i,j),i =1,m)  
enddo 
write(*,*)'enter the 2nd matrix'
do j=1,n
read(*,*) (b(i,j),i=1,m)
enddo
call matrixadd(a,b)
end program ! addm

module m_add_sub

implicit none
integer , parameter :: suff =selected_real_kind(10,99)
integer i,j, m,n

contains

subroutine matrixadd(a,b)
real(suff), dimension(m,n), intent(in):: a,b
real(suff), dimension(m,n):: s,d
s=a+b
d=a-b
print*, 'Sum'
do j=1,n
print 10,(s(i,j),i=1,m)
enddo
print*, 'Difference'
do j=1,n
print 10,(d(i,j),i=1,m)
enddo
10 format(10f10.1,/)
return
end subroutine
end module
[/cpp]

0 Kudos
luvfort
Beginner
1,185 Views
Les,

I still have to look into reallocate arrays, thanq very much
0 Kudos
luvfort
Beginner
1,185 Views
John,
thanks
intent looks lil tricky. It can be used only for dummy variables. So if i want to use intent(in) and intent(out), in my case i have to use matrixadd(a,b,s,d). I still have to look deeper into 'intent' attribute !
0 Kudos
Les_Neilson
Valued Contributor II
1,185 Views
Quoting - luvfort
John,
thanks
intent looks lil tricky. It can be used only for dummy variables. So if i want to use intent(in) and intent(out), in my case i have to use matrixadd(a,b,s,d). I still have to look deeper into 'intent' attribute !

consider :
subroutine foo(M)
M is a dummy argumentIt is associated with whatever *actual* argument is used in thecall to the subroutine
call foo(5) M will have the value 5 (the actual argument)on entry to subroutine foo.
call foo(J) M will have whatever the valueof J (the actual argument) is.

integer, INTENT(IN) :: M implies the programmerpromises not tochange the value of M
M= 42would becaught by the compiler as a codingerror
foo can be called with literal numbers as well as variables as an actual argument.

INTENT(OUT) implies the value of M might change within the subroutine
M = 42 is acceptible
foo should never be called with literal numbers as actual arguments
(In theGood Old Days of many years ago I once chased a bug where someone called a subroutine with a literal value 1 instead of variable l (lower case L) which got assigned another value.Later in the code there was K = K+ 1 increment a counter but "1"no longer had the value "1" Fortunately todays compilersdon't let that happen.)

INTENT(INOUT) implies the value of M initially might be used within the subroutine AND its value might change
M = M + 42


There are complications involving aliasing and "side effects"where theINTENT(IN) may be bypassedbut you don't want to go there.

Les
0 Kudos
gib
New Contributor II
1,185 Views
Quoting - Les Neilson
(In theGood Old Days of many years ago I once chased a bug where someone called a subroutine with a literal value 1 instead of variable l (lower case L) which got assigned another value.Later in the code there was K = K+ 1 increment a counter but "1"no longer had the value "1" Fortunately todays compilersdon't let that happen.)
Ah, it takes me back! The old changed-value-of-a-constant bug. Character-building.
0 Kudos
Les_Neilson
Valued Contributor II
1,185 Views
Quoting - gib
Ah, it takes me back! The old changed-value-of-a-constant bug. Character-building.

And the source of some of my grey hairs :-)
Les
0 Kudos
luvfort
Beginner
1,185 Views
Quoting - Les Neilson

And the source of some of my grey hairs :-)
Les
thanks Les for lil bit more explanation on intent attribute

grey hair is the sign of wisdom :)
0 Kudos
wolfgang_knott
Beginner
1,185 Views
Quoting - luvfort
thanks Les for lil bit more explanation on intent attribute

grey hair is the sign of wisdom :)

When my hair was blond I had the constant "2" with a value of 3 (for weeks!).
0 Kudos
Reply