How to avoid overflow when multiplying real numbers?

I would like to know if there is a way to multiply or put together floating point numbers (or doubles) together without underflow error when compiling my Fortran code like

gfortran -ffpe-trap=invalid,zero,overflow,underflow ...

I know that a parameter is underflownot always a good idea, but I wonder if multiplication can be done with this option. In fact, in the following example, I know that under-execution may occur, but maybe I don't know another case in my codes. That is why I would like to keep this option, if possible.

Here is an example where I compute the vector u for each x, y matrix indices; The 2 values ​​that make up these vectors are between 0 and 1. Then I calculate the square of my norm.

So it’s logical that due to this square operation I will have unreachable values. Since these very small values ​​can be considered zero for me. Is there a underflowbetter way than comparison if?

implicit none
double  :: u(100,100,2), uSqr(100,100)
integer :: x,y

DO x= 1, 100
    DO y = 1, 100
                CALL Poisin( u(x,y,:), x, y )
    ENDDO
ENDDO

uSqr = u(:,:,1)*u(:,:,1) + u(:,:,2) * u(:,:,2) ! where comes the underflow errors
+4
source share
2 answers

You have an answer that addresses a specific way to avoid an unreasonable flaw in certain circumstances. It uses a function hypot. This is partly the answer: if you want to avoid underflow, there might be a way to rewrite the algorithm to avoid it.

(, ), , . .

- IEEE Fortran 2003. [ gfortran, 5.0, , .]

IEEE. . , , , underflow , underflow .

IEEE_UNDERFLOW. IEEE_GET_FLAG(IEEE_UNDERFLOW, value) IEEE_SET_FLAG(IEEE_UNDERFLOW, value). , , , . IEEE_SET_HALTING_MODE(IEEE_UNDERFLOW, value) .

, .

  use, intrinsic :: ieee_arithmetic, only : IEEE_SELECTED_REAL_KIND
  use, intrinsic :: ieee_exceptions

  implicit none

  ! We want an IEEE kind, but this doesn't ensure support for underflow control
  integer, parameter :: rk=IEEE_SELECTED_REAL_KIND(6, 70)

  ! State preservation/restoration
  logical should_halt, was_flagged

  real(rk) x

  ! Get the original halting mode and signal state 
  call ieee_get_halting_mode(IEEE_UNDERFLOW, should_halt)
  call ieee_get_flag(IEEE_UNDERFLOW, was_flagged)

  ! Ensure we aren't going to halt on underflow
  call ieee_set_halting_mode(IEEE_UNDERFLOW, .FALSE.)

  ! The irrelevant computation   
  x=TINY(x)
  x=x**2

  ! And restore our old state
  call ieee_set_halting_mode(IEEE_UNDERFLOW, should_halt)
  call ieee_set_flag(IEEE_UNDERFLOW, was_flagged)

end program
+3

, , , hypot ?

hypot / sqrt(x**2+y**2).

+1

Source: https://habr.com/ru/post/1674593/


All Articles