! Copyright (C) 2018-2021 Free Software Foundation, Inc. ! Contributed by Steven G. Kargl ! ! This file is part of the GNU Fortran runtime library (libgfortran). ! ! Libgfortran is free software; you can redistribute it and/or ! modify it under the terms of the GNU General Public ! License as published by the Free Software Foundation; either ! version 3 of the License, or (at your option) any later version. ! ! Libgfortran is distributed in the hope that it will be useful, ! but WITHOUT ANY WARRANTY; without even the implied warranty of ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! GNU General Public License for more details. ! ! Under Section 7 of GPL version 3, you are granted additional ! permissions described in the GCC Runtime Library Exception, version ! 3.1, as published by the Free Software Foundation. ! ! You should have received a copy of the GNU General Public License and ! a copy of the GCC Runtime Library Exception along with this program; ! see the files COPYING3 and COPYING.RUNTIME respectively. If not, see ! . ! ! WARNING: This file should never be compiled with an option that changes ! default logical kind from 4 to some other value or changes default integer ! kind from 4 to some other value. ! ! There are four combinations of repeatable and image_distinct. The ! language below is from the F2018 standard (actually, J3/18-007r1). ! ! This routine is only used for non-coarray programs or with programs ! compiled with -fcoarray=single. Use of -fcoarray=lib or -fcoarray=shared ! requires different routines due to the need for communication between ! images under case(iv). ! ! Technically, neither image_distinct nor image_num are now needed. The ! interface to _gfortran_random_init() is maintained for libgfortran ABI. ! Note, the Fortran standard requires the image_distinct argument, so ! it will always have a valid value, and the frontend generates an value ! of 0 for image_num. ! impure subroutine _gfortran_random_init(repeatable, image_distinct, image_num) implicit none logical, value, intent(in) :: repeatable logical, value, intent(in) :: image_distinct integer, value, intent(in) :: image_num logical, save :: once = .true. integer :: nseed, lcg_seed integer, save, allocatable :: seed(:) if (repeatable) then if (once) then once = .false. call random_seed(size=nseed) allocate(seed(nseed)) lcg_seed = 57911963 call _gfortran_lcg(seed) end if call random_seed(put=seed) else call random_seed() ! ! This cannot happen; but, prevent gfortran complaining about ! unused variables. ! if (image_num > 2) then block use iso_fortran_env, only : error_unit write(error_unit, '(A)') 'whoops: random_init(.false., .false.)' if (image_distinct) error stop image_num + 1 error stop image_num end block end if end if contains ! ! SK Park and KW Miller, ``Random number generators: good ones are hard ! to find,'' Comm. ACM, 31(10), 1192--1201, (1988). ! ! Implementation of a prime modulus multiplicative linear congruential ! generator, which avoids overflow and provides the full period. ! impure elemental subroutine _gfortran_lcg(i) implicit none integer, intent(out) :: i integer, parameter :: a = 16807 ! Multiplier integer, parameter :: m = huge(a) ! Modulus integer, parameter :: q = 127773 ! Quotient to avoid overflow integer, parameter :: r = 2836 ! Remainder to avoid overflow lcg_seed = a * mod(lcg_seed, q) - r * (lcg_seed / q) if (lcg_seed <= 0) lcg_seed = lcg_seed + m i = lcg_seed end subroutine _gfortran_lcg end subroutine _gfortran_random_init