The main documentation of the Valid_State_Real Procedure contains additional explanation of this code listing.
! Turn off checking which involves division by zero for some compilers
! that allow error trapping.
! For Suns, you could either
! - not set DIVISION_BY_ZERO and use no compiler flags, or
! - set DIVISION_BY_ZERO and use -ftrap=%none.
! For Intel/NAGWare, you could either
! - not set DIVISION_BY_ZERO and use no compiler flags, or
! - set DIVISION_BY_ZERO and use -ieee=full.
ifelse(
ARCHITECTURE, Sun,
[],
ARCHITECTURE, SGI,
[define([DIVISION_BY_ZERO],1)],
ARCHITECTURE, Intel, [
ifelse(
COMPILER, NAGWare,
[],
[define([DIVISION_BY_ZERO],1)]
)],
ARCHITECTURE, Apple,
[define([DIVISION_BY_ZERO],1)]
)
define([REPLICATE_ROUTINE],[
ifelse(POINTER_TOGGLE, [TRUE], [
pushdef([TYPE], [real,$1])
pushdef([Valid_State_Real_P_DIM], expand(Valid_State_Real_P_$1))
pushdef([POINTER_ONLY], [])
],[
pushdef([TYPE], [real,$1,np])
pushdef([Valid_State_Real_P_DIM], expand(Valid_State_Real_NP_$1))
pushdef([POINTER_ONLY], [!])
])
function Valid_State_Real_P_DIM (R) result(Valid)
! Use association information.
SCALAR_ONLY use Caesar_Flags_Module, only: finalize_real_flag
SCALAR_ONLY use Caesar_Logical_Class, only: ALL
! Input variable.
type(TYPE) :: R ! Variable to be checked.
! Output variable.
type(logical) :: Valid ! Logical state.
! Internal variables.
type(real) :: one, ten, zero ! Numbers are not parameterized
! to fool smart compilers.
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Set numbers carefully (so that the compiler
! doesn't know that zero=0).
ten = 1.d1
one = 1.d0
zero = one - one
! Start out true.
Valid = .true.
! First, make sure that the variable has been allocated.
POINTER_ONLY ARRAY_ONLY Valid = Valid .and. ASSOCIATED(R)
POINTER_ONLY ARRAY_ONLY if (.not.Valid) return
! Make sure the variable has not been finalized.
SCALAR_ONLY Valid = Valid .and. R /= finalize_real_flag
! Check for Infs. This check determines whether R(1-e) = R, where e
! is a small number. This should only be true if R = 0 or if R is
! not a valid number.
!
! Pass Table:
! Intel Intel Intel Apple Sun SGI IBM
! Lahey Absoft NAGWare Absoft
! Infinity Fail Fail Fail Fail Fail Fail Fail
! -Infinity Fail Fail Fail Fail Fail Fail Fail
! NaN Pass Pass Pass Pass Pass Pass Pass
Valid = Valid .and. ALL(R == zero .or. R*(one - ten*EPSILON(one)) /= R)
TESTWRITE (6,100) 'Test 1, R(1-e) = R ==>', &
IF_UNIT_TEST ALL(R == zero .or. R*(one - ten*EPSILON(one)) /= R)
! For IEEE-conforming reals, the following is (supposedly) a check
! for NaNs. So far, it works on everything but SGIs.
!
! Pass Table (test 2):
! Intel Intel Intel Apple Sun SGI IBM
! Lahey Absoft NAGWare Absoft
! Infinity Pass Pass Pass Pass Pass Pass Pass
! -Infinity Pass Pass Pass Pass Pass Pass Pass
! NaN Pass Fail Fail Fail Fail Pass Fail
!
! NaN behavior details:
!
! Intel/Lahey (pre-L6.20c), Intel/Absoft, Intel/NAGWare
! (with -ieee=full), Apple/Absoft and Sun (with -ftrap=%none):
! Fail on tests 2 and 2a, but pass on 2b, for scalars.
! Fail on test 2, but pass on 2a and 2b, for arrays.
! Intel/Lahey:
! With the L6.20c compiler, the behavior is:
! Fail on test2a, but pass on 2 and 2b, for scalars.
! Passes on tests 2, 2a and 2b, for arrays.
! In other words, since test 2 passes for both scalars and arrays,
! this is not a good test for the Lahey compiler.
! Sun:
! Changed behavior after the 107356-02 patch; the new behavior
! is reflected here. So, with the Sun 5.0 compiler with 107377-02
! and 107356-02 patches, and the -ftrap=%none flag set to disable
! exception trapping, this now works as a check for NaNs.
! IBM:
! Fails on tests 2 and 2a, but passes on 2b. (Recheck behavior with
! arrays to see if it is the same as some other compilers above if
! IBM access is regained.)
Valid = Valid .and. ALL(R == R)
TESTWRITE (6,100) 'Test 2, R == R ==>', ALL(R == R)
TESTWRITE (6,100) 'Test 2a, .not.(R /= R) ==>', .not. ALL((R /= R))
TESTWRITE (6,100) 'Test 2b, .not.(R < R) ==>', .not. ALL((R < R))
! Create an infinity and check to verify inequality.
!
! Pass Table:
! Intel Intel Intel Apple Sun SGI IBM
! Lahey Absoft NAGWare Absoft
! Infinity Fail Fail Fail Fail Fail Fail Fail
! -Infinity Pass Pass Pass Pass Pass Pass Pass
! NaN Pass Pass Pass Pass Pass Pass Pass
ifdef([DIVISION_BY_ZERO],[
Valid = Valid .and. ALL(one/zero /= R)
TESTWRITE (6,100) 'Test 3, Infinity /= R ==>', ALL(one/zero /= R)
])
! Create a negative infinity and check to verify inequality.
!
! Pass Table:
! Intel Intel Intel Apple Sun SGI IBM
! Lahey Absoft NAGWare Absoft
! Infinity Pass Pass Pass Pass Pass Pass Pass
! -Infinity Fail Fail Fail Fail Fail Fail Fail
! NaN Pass Pass Pass Pass Pass Pass Pass
ifdef([DIVISION_BY_ZERO],[
Valid = Valid .and. ALL(-one/zero /= R)
TESTWRITE (6,100) 'Test 4, -Infinity /= R ==>', ALL(-one/zero /= R)
])
! Create a NaN and check to verify inequality.
!
! Pass Table:
! Intel Intel Intel Apple Sun SGI IBM
! Lahey Absoft NAGWare Absoft
! Infinity Pass Pass Pass Pass Pass Pass Pass
! -Infinity Pass Pass Pass Pass Pass Pass Pass
! NaN Pass Pass Pass Pass Pass Pass Pass
!
! This test doesn't seem to work, but it is retained in case it works
! on some machine in the future.
ifdef([DIVISION_BY_ZERO],[
Valid = Valid .and. ALL(zero/zero /= R)
TESTWRITE (6,100) 'Test 5, NaN /= R ==>', ALL(zero/zero /= R)
])
! Check the top of the range.
!
! Pass Table:
! Intel Intel Intel Apple Sun SGI IBM
! Lahey Absoft NAGWare Absoft
! Infinity Fail Fail Fail Fail Fail Fail Fail
! -Infinity Pass Pass Pass Pass Pass Pass Pass
! NaN Fail Fail Fail Fail Fail Fail Fail
Valid = Valid .and. ALL(R <= HUGE(R))
TESTWRITE (6,100) 'Test 6, R <= HUGE(R) ==>', ALL(R <= HUGE(R))
! Note that there is no explicit check for the bottom of the
! range, since there is no F90 intrinsic that returns the lowest
! negative number that a real can take.
! Format statement.
IF_UNIT_TEST 100 format (2x, a, 1x, l1)
return
end function Valid_State_Real_P_DIM
popdef([TYPE])
popdef([Valid_State_Real_P_DIM])
popdef([POINTER_ONLY])
])
define([POINTER_TOGGLE], [TRUE])
REPLICATE
define([POINTER_TOGGLE], [FALSE])
REPLICATE