包 ranlib.f 中的子程序 ignpoi 已损坏

The subroutine ignpoi in the package ranlib.f is broken

我正在使用 gfortran:linux.

上的 GNU Fortran (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4

我正在尝试使用此来源 ranlib.f 中的 ignpoi http://www.netlib.org/random/ (http://www.netlib.org/random/ranlib.f.tar.gz)

我使用

编译库
   gfortran -O2 -c *.f
   ar cr libranlib.a *.o

当我编写简单的程序来测试 ignpoi(泊松偏差发生器)时

  program test
  implicit none
  integer seed1, seed2, i
  real av
  integer ignpoi

  seed1=123456
  seed2=654321
  call setall(seed1,seed2)

  av=8.0
  do i=1,10
     print *, ignpoi(av)
  enddo

  end

具有相同的平均值,但在一个或多个偏差后会出现分段错误。

          12
           7

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0x7F077F1D3E48
#1  0x7F077F1D2FD0
#2  0x7F077E9042EF
#3  0x401288 in ignpoi_
#4  0x400A3D in MAIN__ at test.f:?
Segmentation fault (core dumped)

我是这样编译测试的,没有编译错误。

gfortran test.f libranlib.a

奇怪的是,当我每次要求不同的号码时,都没有问题。当我评论第 104-105 行时

IF (mu.EQ.muprev) GO TO 10     
IF (mu.LT.10.0) GO TO 120

of ignpoi.f, 问题解决了。

这可以复制吗?

错误的原因是什么?

我知道第 104-105 行是为了节省计算时间。如何修改当前函数以从预计算中受益,而不会出现以相同的平均多次调用函数的问题?

好吧,那个特定的代码被破坏了......在 ignpoi.f,ll。 218:

      IF (mu.EQ.muold) GO TO 130
      muold = mu
      m = max0(1,ifix(mu))
      l = 0
      p = exp(-mu)
      q = p
      p0 = p
C
C     STEP U. UNIFORM SAMPLE FOR INVERSION METHOD
C
  130 u = ranf()

第一个条件为真,因此您跳过 mlpqp0 的初始化。在这些变量中,之前只有 l 被触及 - 但是 mu == muold 也被跳过了。

不幸的是,很多随后的 calculations/branches 取决于提到的变量,这导致 - 请原谅双关语 - 随机行为。

我不知道在你的情况下段错误发生在哪里,在我的机器上我最终陷入了无限循环。最简单的解决方案是禁用存储旧值。为此,注释掉(或删除)行 (144 & 219)

      muold = mu

或者,禁用跳过初始化 (l. 218):

C     IF (mu.EQ.muold) GO TO 130