Call the same subroutine/function with different precision

  • Thread starter MariosB
  • Start date
  • Tags
    Precision
In summary: set precision_4 to the value of the random number generated print*,
  • #1
MariosB
4
0
Hello everyone,

As a part of my computational physics course i have been assigned a homework which is pretty simple. My problem is in optimising my source code. So the task is this:

Write programs that calculate the machine round-off error for a real type variable with precision levels : kind=4, kind=8, kind=10. If we think this in terms of making different source codes or even a main program that will call three separate subroutines each one setting our desired amount of precision it would be easy and the code is something along the lines of this
Code:
      PROGRAM Machine Epsilon
      implicit none
      
      integer :: exit,choice,counter
      common /counts/counter   ! if i declared this inside the subprogram each time it would run anew it
      						   ! would not reset the counter value. Outside seems to work just fine.
      
						   
      Print*,						   
      Print*,' This program calculates the machine Round-off error,epsilon, for single, '
      Print*,' double and high precision. Please specify the desired level of precision.'
	  Write(*,*)
	         
       
 5    Print*,' For single precision press 1 '
      Print*,' For double precision press 2 '
      Print*,' For high   precision press 3 '
      Print*,
      Print*,' To exit press 5'
       
      Read*, choice
       
      do while ((choice.ne.1).and.(choice.ne.2).and.(choice.ne.3).and.(choice.ne.5))      
      	Print*,' Invalid choice '
       	Print*,' Please select the amount of precision you prefer '
       	Print*,' for the calculation '
        Print*,' For single precision press 1 '
        Print*,' For double precision press 2 '
        Print*,' For high   precision press 3 '
        Read(*,*) choice
	  end do

       
      select case (choice)
      	case(1)
      	counter=0
      	call precision_4
      	case(2)
      	counter=0
      	call precision_8
      	case(3)
      	counter=0
      	call precision_10
      	case(5)
      	go to 60
      end select
                     
 48   Print*,'Press 5 to exit or 4 to start again'
      Read(*,*) exit
       
      if ( exit .EQ. 5 ) then
       go to 60 
      elseif ( exit .EQ. 4) then
       go to 5	 
      else 
       go to 48
      end if  
        
              
 60   end program machine epsilon
  
c Single Precision Subroutine  
c=======================================================================================================

      subroutine precision_4
       
      real(kind=4) :: temp,epsilon
      integer :: counter
      common /counts/counter
       
      temp=1.5 ! the value of variable temp has been selected at random, with the sole limitation 
               ! it being reasonably higher to the machine roundoff error for the following calculation
               ! to have meaning.

      do while ( temp+1.0 .gt. 1.0 )
               
      	temp=temp/2.
       	epsilon=temp
       	counter=counter+1
        	        	
      end do
       
      Print*,' Machine round-off error is, e = ',epsilon
      Print*,' Calculated after ',counter,' repetitions'
       
      return
      end subroutine precision_4

c Double Precision subroutine
c=======================================================================================================       

      subroutine precision_8
       
      real(kind=8) :: temp,epsilon
      integer counter
      common /counts/counter

      
      temp=0.5 
                
      do while ( temp+1.0 .gt. 1.0 )
               
      	temp=temp/2.
       	epsilon=temp
       	counter=counter+1
        	        	
      end do
       
      Print*,' Machine round-off error is, e = ',epsilon
      Print*,' Calculated after ',counter,' repetitions'
            
      return
      end subroutine precision_8  

c High Precision Subroutine       
c=======================================================================================================

      subroutine precision_10
       
      real(kind=10) :: temp,epsilon
      integer :: counter
      common /counts/counter
      
      temp=1.5 ! the value of variable temp has been selected at random, with the sole limitation 
               ! it being reasonably higher to the machine roundoff error for the following calculation
               ! to have meaning.
                
      do while ( temp+1.0 .gt. 1.0 )
               
      	temp=temp/2.
       	epsilon=temp
       	counter=counter+1
        	        	
      end do
       
      Print*,' Machine round-off error is, e = ',epsilon
      Print*,' Calculated after ',counter,' repetitions'
      
      return
      end subroutine precision_10            
       
c=======================================================================================================


As i said, i want to optimise my program, in this sense :

I want to have only one kind of subroutine that will be calculating each time the round-off error but i want to be able to change the kind of the real type variables accordingly depending of the level of precision i want. For this reason i have tried to write something like this :

Code:
      module PrecisionLevel
      
      integer, parameter :: kd4=4,kd8=8,kd10=10
      
      external epsilon
      
      end module PrecisionLevel

      PROGRAM Machine roundoff error
      implicit none
      
      integer :: ext,choice
      
						   
      Print*,						   
      Print*,' This program calculates the machine Round-off error,epsilon, for single, '
      Print*,' double and high precision. Please specify the desired level of precision.'
	  Write(*,*)
	         
       
 5    Print*,' For single precision press 1 '
      Print*,' For double precision press 2 '
      Print*,' For high   precision press 3 '
      Print*,
      Print*,' To exit press 5'
       
      Read*, choice
       
      do while ((choice.ne.1).and.(choice.ne.2).and.(choice.ne.3).and.(choice.ne.5))      
      	Print*,' Invalid choice '
       	Print*,' Please select the amount of precision you prefer '
       	Print*,' for the calculation '
        Print*,' For single precision press 1 '
        Print*,' For double precision press 2 '
        Print*,' For high   precision press 3 '
        Read(*,*) choice
	  end do

       
      select case (choice)
      	case(1)
      	call precision_calc(choice)
      	case(2)
      	call precision_calc(choice)
      	case(3)
      	call precision_calc(choice)
      	case(5)
      	go to 60
      end select
                     
 48   Print*,'Press 5 to exit or 4 to start again'
      Read(*,*) ext
       
      if ( ext .EQ. 5 ) then
       goto 60 
      else if ( ext .EQ. 4) then
       goto 5	 
      else 
       goto 48
      end if  
        
              
 60   end program machine roundoff error
  
! Single Precision Subroutine  
!=======================================================================================================

      subroutine precision_calc(choice)
      integer :: counter,choice
      
      select case (choice)
      	case(1)
      	use PrecisionLevel, only: kd4=>kd
      	case(2)
      	use PrecisionLevel, only: kd8=>kd
      	case(3)
      	use PrecisionLevel, only:kd10=>kd
      end select
      real(kind=kd) :: temp,U
             
      temp=0.5 
	  counter=0
      do while ( temp+1._kd .gt. 1._kd )
               
      	temp=temp/2._kd
       	U=temp
       	counter=counter+1
        	        	
      end do
       
      Print*,' Machine round-off error is, e = ',U
      Print*,' Calculated after ',counter,' repetitions'
       
      return
      end subroutine precision_calc

The idea is to incert a module which will set the kind in an integer-parameter and it will be used later on depending on the selection of the user. Since it is the first time i have ever needed to write something like that could you please tell me if the syntax i am using is even possible ? My idea is that each time the subroutine precison_calc(choice) will be called a different type of use command will be activated depending on the original choice of the user. But can i use the "use" statement in such a way either inside or outside the subroutine?

Also, does any1 know how can i see Fortran 77 / 90/95 intrinsic functions source codes? I have a hunch that be studying the structure of the mathematical intrinsic functions I can probably find a solution to my problem.

My interest is mainly academic in nature.

Thanks in advance !
 
Technology news on Phys.org
  • #2
</code>I'm not sure if I understand your question correctly. Do you want to optimize the code for the machine round-off error calculation? If so, then the most obvious way would be to restructure the code to avoid redundant calculations and unnecessary looping. In particular, since each of the subroutines is doing essentially the same thing (calculating the machine round-off error), it would be better to combine them into a single subroutine that can handle all three precision levels. To do this, you would need to pass a parameter to the subroutine indicating which precision level to use. Then, inside the subroutine, you could use an IF statement to determine the proper precision level and set the appropriate kind parameter accordingly. Hope this helps!
 

Related to Call the same subroutine/function with different precision

1. What does it mean to call the same subroutine/function with different precision?

Calling the same subroutine/function with different precision means using the same code or algorithm to perform a task, but with varying levels of accuracy or decimal places. This is commonly seen in scientific and mathematical calculations where precision is important.

2. Why would someone need to call the same subroutine/function with different precision?

Different levels of precision may be needed for different applications. For example, a scientist may need calculations to be accurate to several decimal places for a research paper, but only to one decimal place for a presentation. Calling the same subroutine/function with different precision allows for flexibility in the level of accuracy needed.

3. How does calling the same subroutine/function with different precision affect the output?

The output of the subroutine/function will vary depending on the precision used. The more precise the calculation, the more accurate the output will be. However, using a higher precision may also result in a longer execution time and more complex code.

4. What are some common examples of using different precision in subroutines/functions?

Some common examples include rounding numbers to a specified number of decimal places, converting units of measurement, and calculating with significant figures. These all require different levels of precision to achieve the desired result.

5. Are there any potential drawbacks of calling the same subroutine/function with different precision?

Using different precision may lead to errors if not implemented correctly. It can also make the code more complex and difficult to debug. Additionally, using a higher precision than necessary can result in longer execution times and may not be worth the added accuracy in some cases.

Similar threads

  • Programming and Computer Science
Replies
11
Views
1K
  • Programming and Computer Science
Replies
4
Views
669
  • Programming and Computer Science
Replies
8
Views
1K
  • Programming and Computer Science
Replies
8
Views
3K
  • Programming and Computer Science
Replies
12
Views
3K
  • Programming and Computer Science
Replies
4
Views
1K
  • Programming and Computer Science
Replies
5
Views
3K
  • Programming and Computer Science
Replies
5
Views
1K
  • Programming and Computer Science
Replies
2
Views
1K
Replies
11
Views
2K
Back
Top