0

Below code was adopted from prng written in Fortran 77.

    double precision function usran(ir)
c
c   this subroutine generates random values between 0.0 and 1.0 using
c   an integer seed
c   it is based on the imsl routine ggubs.
c
c   double precision version
c
    implicit double precision (a-h,o-z)
    parameter(da=16807.d0,db=2147483647.d0,dc=2147483648.d0)
    ir=abs(mod(da*ir,db)+0.5d0)
    usran=dfloat(ir)/dc
    return
    end

It seems to me that ir is the seed input which is a reassigned integer, ideally it's returns a random number in between 0 and 1, which is then used as the next seed value. But I don't see how it works?

I mean if I have an initial random value as my seed, then input usran(seed) returns a value in (0,1), then how to call the next value in the current sequence?

I can't think of a more specific title for this thread.

Gvxfjørt
  • 99
  • 2
  • 7
  • I don't quite follow your question. Are you aware that `seed`, through the argument `ir` will also be modified? That is, the function has an effect on what is passed, not just having a result. – francescalus Jun 27 '18 at 06:58
  • I'm just confused about how is the returned value used as the next seed value? I can see that it's modified, for a quick example, if my initial `seed = 12345`, then `ir =abs(mod(12345*da,db)+0.5)`, and `usran(seed)` returns `ir/dc`, I get your point that we now have a new ir value, but how does it contribute to a new seed value, don't you still need to evaluate `usran(seed)` in order to obtain the next value? – Gvxfjørt Jun 27 '18 at 07:06
  • in another word, how is this sequential? if it's not sequential then what makes it a PRNG? – Gvxfjørt Jun 27 '18 at 07:18
  • What do you mean by "sequential"? You call the function with a seed and get back a "random number" and a new seed. You pass this new seed to get the next value and yet another new seed. Perhaps you could show us the context of how you expect to use the generator in a main program? If that's off it gives us something to "correct". – francescalus Jun 27 '18 at 07:23
  • @francescalus, I guess I'm confused about how to pass the new seed -`ir` back to `usran()` since this functional subroutine only returns usran which is a real number in (0,1). I guess one way is to compute usran*dc after where usran(seed) is called in the program and use it as the new seed? – Gvxfjørt Jun 27 '18 at 07:54
  • That's my earlier comment: `a=usran(seed)` modifies `seed`, so you can `a=usran(seed); b=usran(seed)` and have `a` and `b` two of the sequence. `usran` is not pure. – francescalus Jun 27 '18 at 08:02
  • That is exactly why I rewrote the PRNG I am using to subroutines. The side effects in functions are simply confusing. – Vladimir F Героям слава Jun 27 '18 at 09:04
  • @Vladimir what exact side effects you see in this particular function? – Gvxfjørt Jun 27 '18 at 09:17
  • Well, I meant the changing of the input argument. Maybe *side effect* is not the right word in this case. Often the state is a saved global (module) variable and then *side effect* is the correct term. – Vladimir F Героям слава Jun 27 '18 at 09:21
  • I still don't get your "side effect", but I see how this function works now, by adding `integer, intent(inout) :: ir`, if I hold my `seed` value a constant, and run `usran(seed)` multiple times in the main program, it returns a different values with a different seed value each time. I don't know why I didn't see the case at the beginning. – Gvxfjørt Jun 27 '18 at 09:35
  • https://softwareengineering.stackexchange.com/questions/40297/what-is-a-side-effect – Vladimir F Героям слава Jun 28 '18 at 08:46
  • @francescalus, are you or \@VladmirF planning to make this comments / conversation into a proper answer? – Rodrigo Rodrigues Jul 03 '18 at 03:53

1 Answers1

1

I mean if I have an initial random value as my seed, then input usran(seed) returns a value in (0,1), then how to call the next value in the current sequence?

As @francescalus and @Vladmir F commented, this function has a side-effect. From Wikipedia:

In computer science, a function or expression is said to have a side effect if it modifies some state outside its scope or has an observable interaction with its calling functions or the outside world besides returning a value. For example, a particular function might modify a global variable or static variable, modify one of its arguments, raise an exception, write data to a display or file, read data from a keyboard or a file, or call other side-effecting functions. In the presence of side effects, a program's behaviour may depend on history; that is, the order of evaluation matters. Understanding and debugging a function with side effects requires knowledge about the context and its possible histories. A function or expression without side effects is said to be pure.

In the specific case of your function, besides returning a random number, it changes the value of its argument with ir=abs(mod(da*ir,db)+0.5d0). So each time you call it again with the same variable as argument, ir will be passed with a different value and thus a different random number will be generated.

"Purity" of procedures plays an imporant role in Fortran context because the posibility of side-effects prevents the compiler to do some code optimizations. A subroutine can still be considered pure if its only side-effect is to modify specific arguments.

But there are cases that, by the very nature of the procedure, side-effects can't be avoided and sometimes even are desired. Gathering random numbers is an example, also are doing I/O, stopping the code or configuring a module.

Rodrigo Rodrigues
  • 7,545
  • 1
  • 24
  • 36