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

Merge without temporary arrays

Eugene_S_1
Beginner
916 Views

Hello,

The MERGE function seems to use temporary arrays for both, tsource and fsource, arguments when the program is compiled in the Debug mode. Hence, the following simple code throws an exception:

real :: pos(3) = [.1, .2, .3]
real :: neg(2) = [.8, .9]
integer :: ptrs(5) = [1, 2, -1, -2, 3]   ! Index in (pos) if positive, minus index in (neg) if negative
real :: vals(5)

vals = merge(pos(ptrs), neg(-ptrs), ptrs > 0)

forrtl: severe (408): fort: (3): Subscript #1 of the array NEG has value -1 which is less than the lower bound of 1

This modification also doesn't work:

forall (i = 1:5) vals(i) = merge(pos(ptrs(i)), neg(-ptrs(i)), ptrs(i) > 0)

In the Release mode both work fine.

Why does MERGE need to compute both arguments in the Debug mode and is there an elegant way to rewrite this code without going into dumb for-if-else-then constructions?

Thank you.

0 Kudos
1 Solution
mecej4
Honored Contributor III
916 Views

MERGE is for merging two arrays of the same type, shape and size under the control of the mask expression. In other words, pos(ptrs) and neg(-ptrs) are expressions which the compiler should be able to evaluate (and store in registers or temporary arrays, at its discretion) before applying the mask. Whether you receive an error message or not, these two expressions contain invalid subscripts and the result is undefined.

How about the following?

where (ptrs > 0)
   vals=pos(ptrs)
elsewhere (ptrs < 0)
   vals=neg(-ptrs)
endwhere

Note that this code will leave some elements of vals undefined if some of the elements of ptrs have the value 0.

View solution in original post

0 Kudos
3 Replies
TimP
Honored Contributor III
916 Views

Evaluation of both branches is expected in release mode as well, apparently without checking for exceptions.

This case could be written with a single larger array to avoid branches and exceptions.

0 Kudos
mecej4
Honored Contributor III
917 Views

MERGE is for merging two arrays of the same type, shape and size under the control of the mask expression. In other words, pos(ptrs) and neg(-ptrs) are expressions which the compiler should be able to evaluate (and store in registers or temporary arrays, at its discretion) before applying the mask. Whether you receive an error message or not, these two expressions contain invalid subscripts and the result is undefined.

How about the following?

where (ptrs > 0)
   vals=pos(ptrs)
elsewhere (ptrs < 0)
   vals=neg(-ptrs)
endwhere

Note that this code will leave some elements of vals undefined if some of the elements of ptrs have the value 0.

0 Kudos
Eugene_S_1
Beginner
916 Views

mecej4 wrote:

How about the following?

Thank you. This code works. I should've tried WHERE before posting...

Note that this code will leave some elements of vals undefined if some of the elements of ptrs have the value 0.

Sure. This is acceptable, my ptrs contains non-zeros only.

0 Kudos
Reply