-1

So I was trying to make algorithm in fortran for solving simpsons 1/3rule. The code works for real kind=4 but not for real kind 16 it throws segmentation fault. So here I will give the code. Module file:-

   module simpsonsonethirdmod
   implicit none
   public::si
   contains
   subroutine si(f,A,B,i,e,d,s1,s2,sum_,s_even,s_odd,result_,s,k)
   real(kind=16),external::f
   real(kind=16),allocatable,dimension(:)::A,B
   real(kind=16):: i,e,d,s1,s2,sum_,s_even,s_odd,result_
   integer(kind=16)::s,k
   print *,"enter the starting value of integral"
   read(*,*) i
   print *,"enter the final value of the integral"
   read(*,*) e
   print *,"enter the number of intervals you want"
   read(*,*) s
   allocate(A(s+1),B(s+1))
   A(1)=f(0)
   d=(e-i)/real(s)
   s1=d
   s2=d
   sum_=0
   do k=2,s+1
   A(k)=f(d)
   d=s2+d
   end do
   do k=1,s+1
   B(k)=A(k)
   end do
   do k=2,s+1,2
   B(k+2)=B(k+2)+B(k)
   s_odd= B(k+2)
   end do
   do k=1,s+1
   sum_=sum_+A(k)
   end do
   s_even=sum_-s_odd-A(1)-A(s+1)
   d=s1
   result_=(d/3.0)*(A(1)+A(s+1)+2*s_even+4*s_odd)
   print *,"The integral by simpson's rule is",result_

   deallocate(A,B)
   end subroutine si

   end module simpsonsonethirdmod

Main program::-

 program simpsonsonethird
 use simpsonsonethirdmod
 real(kind=4),external::f
 real(kind=4)::i,e,d,s1,s2,sum_,s_even,s_odd,result_,start_time,end_time
 real(kind=4),allocatable,dimension(:)::A,B
 integer(kind=4)::s,k
 call cpu_time(start_time)
 call si(f,A,B,i,e,d,s1,s2,sum_,s_even,s_odd,result_,s,k)
 call cpu_time(end_time)
 print *,"Time taken in seconds =",end_time-start_time
 end program simpsonsonethird

 real(kind=4) function f(x)
 real(kind=4)::x
 f=x**2
 end function f

This gives the output as:- enter image description here

However when i run the program for kind 16. So the program becomes. Module file:-

       module simpsonsonethirdmod
       implicit none
       public::si
       contains
       subroutine si(f,A,B,i,e,d,s1,s2,sum_,s_even,s_odd,result_,s,k)
       real(kind=16),external::f
       real(kind=16),allocatable,dimension(:)::A,B
       real(kind=16):: i,e,d,s1,s2,sum_,s_even,s_odd,result_
       integer(kind=16)::s,k
       print *,"enter the starting value of integral"
       read(*,*) i
       print *,"enter the final value of the integral"
       read(*,*) e
       print *,"enter the number of intervals you want"
       read(*,*) s
       allocate(A(s+1),B(s+1))
       A(1)=f(0)
       d=(e-i)/real(s)
       s1=d
       s2=d
       sum_=0
       do k=2,s+1
       A(k)=f(d)
       d=s2+d
 end do
       do k=1,s+1
        B(k)=A(k)
        end do
        do k=2,s+1,2
        B(k+2)=B(k+2)+B(k)
       s_odd= B(k+2)
        end do
        do k=1,s+1
        sum_=sum_+A(k)
        end do
        s_even=sum_-s_odd-A(1)-A(s+1)
        d=s1
        result_=(d/3.0)*(A(1)+A(s+1)+2*s_even+4*s_odd)
        print *,"The integral by simpson's rule is",result_
  
        deallocate(A,B)
       
 
 
        end subroutine si
 
        end module simpsonsonethirdmod

Main file:-

 program simpsonsonethird
 use simpsonsonethirdmod
real(kind=16),external::f
 real(kind=16)::i,e,d,s1,s2,sum_,s_even,s_odd,result_,start_time,end_time
 real(kind=16),allocatable,dimension(:)::A,B
 integer(kind=16)::s,k
 call cpu_time(start_time)
 call si(f,A,B,i,e,d,s1,s2,sum_,s_even,s_odd,result_,s,k)
 call cpu_time(end_time)
print *,"Time taken in seconds =",end_time-start_time
end program simpsonsonethird

real(kind=16) function f(x)
real(kind=16)::x
  f=x**2
end function f

Then it throws me error as:- enter image description here

So I am working on windows 10 and i am working on 20.04.3 LTS. And I can assure you real 16 variables work for me .ie. they have worked for previous code. Please help me on how to modify this code for real 16.

Ian Bush
  • 6,996
  • 1
  • 21
  • 27
user187604
  • 148
  • 8
  • 1
    Try compiling with `-fcheck=all -g` and rerunning – Ian Bush Nov 01 '21 at 09:04
  • 2
    Also note kind values of 4, 8 and 16 are not guaranteed to be supported by your compiler, not portable and may not do what you expect. I would suggest using the values `real32`, `real64` and `real128` from the intrinsic `iso_fortran_env` module – Ian Bush Nov 01 '21 at 09:19
  • 2
    It would.really help if you used some indentation. Others would be able to see the structure of the program. Ragarding the `kind=4` notation, see https://stackoverflow.com/a/856243/721644 – Vladimir F Героям слава Nov 01 '21 at 09:23
  • 3
    Also look carefully at the actual and dummy arguments to your function f - are they the same type and kind? I would strongly recommend rather than using `external` you have an explicit interface block for functions which are dummy arguments. It will stop this kind of error. – Ian Bush Nov 01 '21 at 09:27
  • Vladimir F actually I am new to the site can you give some reference for identation . I.e. how should it be done? – user187604 Nov 01 '21 at 12:32
  • Ian Bush some reference would be helpful. – user187604 Nov 01 '21 at 12:33
  • Ian Bush real(kind=4) 8 kind of things work with my compiler however if your comment works for any compiler I'm going to try that. – user187604 Nov 01 '21 at 12:35
  • 3
    Some references to what? The immediate problem I have pointed out ( `f(0)` - `0` is an integer which is not the same as the declaration of the dummy argument ) and I've told you the way to find what I suspect will be the next problem you run into. I assume you have access to a good Fortran book, that should be enough for you to work out what I mean. – Ian Bush Nov 01 '21 at 13:44
  • I recommend putting the function `f(x)` after a `contains` keyword inside the program block. Otherwise you need an interface to use the function. – JAlex Nov 02 '21 at 14:31
  • Indentation can be done in several ways depwnding on the personal style or the project style. You can seesome modern Fortran projects on Github and mimick their style. You can start at https://github.com/Fortran-FOSS-Programmers The main idea is to increase the indentation level inside each procedure and each construct. – Vladimir F Героям слава Nov 02 '21 at 21:43

1 Answers1

1

Try this main program code

program simpsonsonethird
use simpsonsonethirdmod     
real(kind=16) :: i, e, d, s1, s2, sum_, s_even, s_odd, result_, &
                 start_time, end_time
real(kind=16),allocatable,dimension(:)::A,B
integer(kind=16)::s,k
    call cpu_time(start_time)
    call si(f,A,B,i,e,d,s1,s2,sum_,s_even,s_odd,result_,s,k)
    call cpu_time(end_time)
    print *,"Time taken in seconds =",end_time-start_time

contains

real(kind=16) function f(x)
real(kind=16)::x
    f=x**2
end function f

end program simpsonsonethird

The idea is that f(x) needs to be inside a module or after the contains keyword of a program for the compiler to know the argument types. Otherwise if the function expects and 128bit parameter and the program puts a 64bit value on the stack you get the segmentation fault.

Now inside simpsonsonethirdmod you need to specify an interface for f

  interface
    real(kind=16) function f(x)
    real(kind=16)::x
    end function f
  end interface

and remove the external declaration.

JAlex
  • 1,486
  • 8
  • 19