[gfortran] Implement irand(), rand(), and srand() for G77 compatibility

Steve Kargl sgk@troutmask.apl.washington.edu
Mon May 31 14:44:00 GMT 2004


On Mon, May 31, 2004 at 12:50:41AM +0100, Paul Brook wrote:
> > irand(i) returns a value in the range [1,GFC_RAND_M-1].
> > irand(i) - 1 is in the range [0,GFC_RAND_M-2].  So, the
> > division above is in the range [0,1).
> 
> You're forgetting that real*4 has significantly less than 32 bits precision, 
> so is unable to accurately represent integers of this magnitude. After 
> rounding the result will in the range [0-1]
> 

Thanks for the wack with the clue stick.

The simple fix is

  return (GFC_REAL_4) ((double)(prefix(irand)(i) - 1) / (double)GFC_RAND_M1);

I'm not sure if this works on amd64, alpha, sparc64, etc.

A more complicate fix is 

#define PRECS	32

GFC_REAL_4 div32 (GFC_INTEGER_4 num, GFC_INTEGER_4 dem)
{
  GFC_REAL_4 val;
  mpf_t n, d;
  mpf_init2 (mpf_t n, PRECS);
  mpf_init2 (mpf_t d, PRECS);
  mpf_set_ui (n, num);
  mpf_set_ui (d, dem);
  mpf_div (n, n, d);
  val = (GFC_REAL_4) mpf_get_d(n);
  mpf_clear (n);
  mpf_clear (d);
  return val;
}

/* Return a REAL in the range [0,1).  */
GFC_REAL_4 prefix(rand) (GFC_INTEGER_4 *i)
{
  GFC_REAL_4 val;
  val = div32(prefix(irand)(i) - 1, GFC_RAND_M1); 
  return val;
}

For rand(), I think the simple fix is in order.  Also, it seems
that libgfortran does not use gmp.

-- 
Steve



More information about the Gcc-patches mailing list