[petsc-dev] fortran literals

Munson, Todd tmunson at mcs.anl.gov
Thu Sep 1 14:36:52 CDT 2016

Dear petsc developers,

Please do not get too mad at me...

I have a C and Fortran test example that should be exactly the same 
problem.  The numerical methods, however, produce different results.
I traced this back to the literals used to define constants in the 
test Fortran problem.  C defaults to double, while Fortran defaults 
to single for literals.

What is the correct PETSc way to define literals in Fortran that works 
across single and double installations (as well as complex and real) 
so that I get the same behavior?  PETSc does not appear to define a 
macro for this.

I'd like to be able to do something like the following in Fortran:

       PetscReal c

       c = PetscRealCast(5.78D0)

where PetscRealCast is real() for single precision and dble()
for double precision.  Without the cast, you would get all 
kinds of warnings of the form "change of value in 
conversion" for a single precision installation.

This macro should work for real numbers (not sure about complex as
real() is overloaded as the real part of a complex number), avoids 
generating warnings for single and double installs, and produces
the same output for the C and Fortran code.


The followup question is then, how do I make this work correctly for 
__float128?  In C, I would need to declare the literals using the Q 
(e.g. 5.78Q) and then cast to the actual PetscReal type.  Without 
the Q, the __float128 constant would be initialized to the double 
version of 5.78 and only correct to 16 digits.

But is the Q suffix portable?  If not, is there portable macro magic
to get full precision constants for single, double, and 
quad installs?

Or is the support for __float128 just going to be flakey?

Other than the examples, the biggest place I can see where __float128 may not be 
supported correctly is the ts methods where, ts/impls/rosw/rosw.c for example, 
defines a ton of constants, many with a very large number of digits, but all 
of them are truncated to double precision and the extra digits are thrown 
away because of the lack of a Q at the end of the constant, even when 
assigned to __float128 variables.

Most others are okay because they are exactly representable, but you can
find constants like 0.7 in few other places.


Note: I already get warnings about using 5.78Q0 in gfortran when declaring 
real(16), as its an "extension".

Things get more complicated if you allow people to muck with compiler options 
like the gfortran -fdefault-real-8, but maybe we should just call that a 
user problem.

Thanks, Todd.

More information about the petsc-dev mailing list