Skip to content

Commit

Permalink
MOM_random: Set mask with bits rather than integer
Browse files Browse the repository at this point in the history
The MOM_random generator used bit masks which were set with integer
values.  This is problematic for the sequence 0x8000 0000, because it
must be set with a value of -2**31.

In 4-byte integers, this is strictly not representable in Fortran, which
requires symmetric signed domains for its variables.  Since the upper
bound is 2**31 - 1, the lower bound must be -2**31 + 1, which is larger
than -2**31.  Any value assigned to the 0x80000000 bit sequence is
considered a noncompliant compiler extension.

The current implementation seems to resolve this by using a kind=8 value
(itself problematic, since 8-byte is not assured), but it still requires
assigning this value to a 4-byte integer which cannot (strictly)
represent the value.

This patch averts the whole issue by explicitly setting the bits, and
makes no reference to its integer value.  It leaves the compiler to
decide its interpretation.  And since the variable is only used in bit
operations, there is no ambiguity in behavior.

Note that GCC 9 does not support BOZ conversion from z'80000000' to int,
since it still expects BOZ literals to be within the bounds.  This is
why we use ibset() in place of a literal.  Later GCC versions do not
have this objection.
  • Loading branch information
marshallward committed Apr 7, 2022
1 parent a535021 commit d2fb2d0
Showing 1 changed file with 8 additions and 5 deletions.
13 changes: 8 additions & 5 deletions src/framework/MOM_random.F90
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module MOM_random
use MOM_time_manager, only : time_type, set_date, get_date

use iso_fortran_env, only : stdout=>output_unit, stderr=>error_unit
use iso_fortran_env, only : int32

implicit none ; private

Expand All @@ -20,11 +21,13 @@ module MOM_random
public :: random_unit_tests

! Private period parameters for the Mersenne Twister
integer, parameter :: blockSize = 624, & !< Size of the state vector
M = 397, & !< Pivot element in state vector
MATRIX_A = -1727483681, & !< constant vector a (0x9908b0dfUL)
UMASK = -2147483648_8, & !< most significant w-r bits (0x80000000UL)
LMASK = 2147483647 !< least significant r bits (0x7fffffffUL)
integer, parameter :: &
blockSize = 624, & !< Size of the state vector
M = 397, & !< Pivot element in state vector
MATRIX_A = -1727483681, & !< constant vector a (0x9908b0dfUL)
UMASK = ibset(0, 31), & !< most significant w-r bits (0x80000000UL)
LMASK = 2147483647 !< least significant r bits (0x7fffffffUL)

! Private tempering parameters for the Mersenne Twister
integer, parameter :: TMASKB= -1658038656, & !< (0x9d2c5680UL)
TMASKC= -272236544 !< (0xefc60000UL)
Expand Down

0 comments on commit d2fb2d0

Please sign in to comment.