[testsuite gfortran] partial fix for secnds*.f

Dominique Dhumieres dominiq@lps.ens.fr
Fri May 11 14:51:00 GMT 2007


> [...]
> > I am submitting this patch for analysis, but I have found a remaining 
> > problem on Linux at midnight:
> > 
> >                 nearest(t1, -1.)       dat1             nearest(t1a, 1.)
> > secnds.f        86398.625          -1.3740234           86398.641
> > secnds-1.f      86399.992           0.0000000           86400.008
> > 
> > apparently date_and_time is zero at midnight while secnds() is 86400.
> > I don't know if this a bug in one of the intrinsic or if this the
> > intended behavior.  ...  This problem can only be tested once a day!
> 
> This is the standard-required behavior for DATE_AND_TIME.  SECNDS is 
> nonstandard, and the G77 manual doesn't document its behavior at midnight.

>From libgfortran/intrinsics/date_and_time.c, I get

...
extern GFC_REAL_4 secnds (GFC_REAL_4 *);
export_proto(secnds);

GFC_REAL_4
secnds (GFC_REAL_4 *x)
{
  GFC_INTEGER_4 values[VALUES_SIZE];
  GFC_REAL_4 temp1, temp2;

  /* Make the INTEGER*4 array for passing to date_and_time.  */
  gfc_array_i4 *avalues = internal_malloc_size (sizeof (gfc_array_i4));
  avalues->data = &values[0];
  GFC_DESCRIPTOR_DTYPE (avalues) = ((GFC_DTYPE_REAL << GFC_DTYPE_TYPE_SHIFT)
					& GFC_DTYPE_TYPE_MASK) +
				    (4 << GFC_DTYPE_SIZE_SHIFT);

  avalues->dim[0].ubound = 7;
  avalues->dim[0].lbound = 0;
  avalues->dim[0].stride = 1;

  date_and_time (NULL, NULL, NULL, avalues, 0, 0, 0);

  free_mem (avalues);

  temp1 = 3600.0 * (GFC_REAL_4)values[4] +
	    60.0 * (GFC_REAL_4)values[5] +
		   (GFC_REAL_4)values[6] +
	   0.001 * (GFC_REAL_4)values[7];
  temp2 = fmod (*x, 86400.0);
  temp2 = (temp1 - temp2 >= 0.0) ? temp2 : (temp2 - 86400.0);
  return temp1 - temp2;
}
...

So, unless the C function 'fmod' is YAMIIOM (yet another math illiterate
implementation of modulo), I don't understand how the tests can return
86400.0!

> Probably we want to emulate whatever g77 did, 

This is not the case: the following codelet

print *, secnds(86400.0), secnds(86401.0)
end

gives

-27613. -27614.

with g77 ( -27581.053 -27582.053 with g95, slightly later!-) and

58799.91       58798.91

with gfortran, i.e., gfortran fold the result in [0.0,86400.0[ (or]?).

> but we also probably don't really care.  Thus, IMHO the test should be
> set up to pass regardless of what SECNDS returns at midnight.

It's what I was planning to do after I really understand what's going on.
In particular I don't understand why I see the problem under Linux and not 
under OSX.

> I assume that dat1 was negative because of your midnight-shift 
> correction?  Otherwise, that would be somewhat concerning, as it should 
> always be nonnegative.  (I'm having a little trouble figuring out how 
> the midnight shift would cause that, though; any ideas?)

I don't understand the -1.3740234. As far as I understand what I have 
done, it should not have happened. I am planning to change the "polling" 
code in order to see what's happening around midnight, but I can only do 
that once a day.  If someone is willing to give me an access to some 
machines on my east (asia or australia) or volonteer to do the tests on my 
west (America), it will speedup the testing.  Any suggestion is also 
welcomed.

> This should probably just be "real" rather than "real*4".

Yes, indeed!

[...]
> I don't really like using magic numbers like this.  How about defining
> 
>    tol = 2.0 * (24.0 * 3600.0 - nearest (24.0 * 3600.0, -1.0))
> 
> at the beginning, and using that?  Though, actually, there's a better 
> phrasing of the same idea:
> 
>    tol = 2.0 * spacing (24.0 * 3600.0)
> 
> Does that seem to work as well?

Just a coding style question: is F90 syntax allowed in *.f codes? or
are they supposed to be compiled with a f77 compiler?

Note that I don't use the 2.0 factor and I have prejudice against SPACING 
because I never remember if it returns the difference with the above or 
below nearest values for powers of 2.0 (it is the former).  In the present 
case, it does not make any difference and I'll use it or add a comment 
with it depending on the answer to the previous questions.

Dominique



More information about the Fortran mailing list