Commit 1e7d533c authored by William Gropp's avatar William Gropp
Browse files

[svn-r3396] Added support for C types in Fortran, along with tests

parent 8f8749fe
......@@ -1565,6 +1565,14 @@ PAC_CC_STRICT
if test -n "$pac_cc_strict_flags" ; then
MPICH2_EXTRA_CFLAGS="$MPICH2_EXTRA_CFLAGS $pac_cc_strict_flags"
fi
# Check for whether the compiler defines a symbol that contains the
# function name. The MPICH2 code, for greater portability, defines
# its own symbols, FCNAME (a string) and FUNCNAME (a token that is not a
# string). Code should use these symbols where possible. However,
# some debugging macros may want to use a compiler-provided symbol
# for the function name, and this check makes it possible to
# define such macros in a way that is always correct.
PAC_CC_FUNCTION_NAME_SYMBOL
# Check if $MPI_DEFAULT_COPTS is valid with $CC
if test "$enable_default_optimize" = "yes" \
......@@ -4333,6 +4341,81 @@ int main( int argc, char **argv ){
fi
AC_SUBST(MPI_STATUS_SIZE)
#
# We must convert all hex values to decimal (!).
# This is for the C types so they are also available in Fortran
for var in CHAR SIGNED_CHAR UNSIGNED_CHAR WCHAR SHORT \
UNSIGNED_SHORT INT UNSIGNED_INT LONG UNSIGNED_LONG \
FLOAT DOUBLE LONG_DOUBLE LONG_LONG_INT \
UNSIGNED_LONG_LONG LONG_LONG FLOAT_INT DOUBLE_INT \
LONG_INT SHORT_INT "2INT" LONG_DOUBLE_INT ; do
fullvar="MPI_$var"
fullf77var="MPI_F77_$var"
eval fullvarvalue=\$$fullvar
#echo "$fullvar = $fullvarvalue"
if test "x$fullvarvalue" = "x" ; then
eval $fullf77var="MPI_DATATYPE_NULL"
continue
fi
value=0
fullvarvalue=`echo $fullvarvalue | sed -e 's/..\(.*\)/\1/'`
offset=0
for pos in 3 4 5 6 7 8 9 10 ; do
# This works, even for Tru64, because only a single character
# is extracted
char=`expr $fullvarvalue : '\(.\)'`
# FIXME: Tru64 Unix eliminates leading zeros (!)
# How do we fix something that broken?
fullvarvalue=`echo $fullvarvalue | sed -e 's/.\(.*\)/\1/'`
case $char in
a) char=10 ;;
b) char=11 ;;
c) char=12 ;;
d) char=13 ;;
e) char=14 ;;
f) char=15 ;;
esac
# For Fortran, if the value is too big for an unsigned int,
# we need to make it a signed (negative) int. Currently, the
# types in this class are the minloc/maxloc types.
if test $pos = 3 -a $char -ge 8 ; then
#echo "for $var in position $pos found a value >= 8"
char=`expr $char - 8`
offset=-2147483648
fi
value=`expr $value \* 16 + $char`
done
if test "$offset" != 0 ; then
#echo "$fullf77var: $value, $offset"
value=`expr $value + $offset`
fi
#echo "$fullf77var = $value"
eval $fullf77var=$value
done
AC_SUBST(MPI_F77_CHAR)
AC_SUBST(MPI_F77_SIGNED_CHAR)
AC_SUBST(MPI_F77_UNSIGNED_CHAR)
AC_SUBST(MPI_F77_WCHAR)
AC_SUBST(MPI_F77_SHORT)
AC_SUBST(MPI_F77_UNSIGNED_SHORT)
MPI_F77_UNSIGNED=$MPI_F77_UNSIGNED_INT
AC_SUBST(MPI_F77_UNSIGNED)
AC_SUBST(MPI_F77_INT)
AC_SUBST(MPI_F77_LONG)
AC_SUBST(MPI_F77_UNSIGNED_LONG)
AC_SUBST(MPI_F77_FLOAT)
AC_SUBST(MPI_F77_DOUBLE)
AC_SUBST(MPI_F77_LONG_DOUBLE)
AC_SUBST(MPI_F77_UNSIGNED_LONG_LONG)
MPI_F77_LONG_LONG_INT=$MPI_F77_LONG_LONG
AC_SUBST(MPI_F77_LONG_LONG_INT)
AC_SUBST(MPI_F77_LONG_LONG)
AC_SUBST(MPI_F77_FLOAT_INT)
AC_SUBST(MPI_F77_DOUBLE_INT)
AC_SUBST(MPI_F77_LONG_INT)
AC_SUBST(MPI_F77_SHORT_INT)
AC_SUBST(MPI_F77_2INT)
AC_SUBST(MPI_F77_LONG_DOUBLE_INT)
# Try and compute the values of .true. and .false. in Fortran
# This code has been removed because the Fortran binding code does
# not yet support it.
......
......@@ -2303,6 +2303,18 @@ if ($write_mpif) {
print MPIFFD " PARAMETER (MPI_ADDRESS_KIND=\@ADDRESS_KIND\@)\n";
print MPIFFD " PARAMETER (MPI_OFFSET_KIND=\@OFFSET_KIND\@)\n";
#
# C Types. Note that we need to convert the C hex constant
# into a decimal constant for Fortran (there is no standard
# for for hex constants in Fortran, and different compilers make
# use of different extensions)
foreach $key (CHAR, SIGNED_CHAR, UNSIGNED_CHAR, WCHAR, SHORT,
UNSIGNED_SHORT, INT, UNSIGNED, LONG, UNSIGNED_LONG,
FLOAT, DOUBLE, LONG_DOUBLE, LONG_LONG_INT,
UNSIGNED_LONG_LONG, LONG_LONG, FLOAT_INT, DOUBLE_INT,
LONG_INT, SHORT_INT, "2INT", LONG_DOUBLE_INT) {
print MPIFFD " INTEGER MPI_$key\n";
print MPIFFD " PARAMETER (MPI_$key=\@MPI_F77_$key\@)\n";
}
# Datatype combiners
foreach $key (NAMED, DUP, CONTIGUOUS, VECTOR, HVECTOR_INTEGER, HVECTOR,
INDEXED, HINDEXED_INTEGER, HINDEXED, INDEXED_BLOCK,
......
......@@ -11,7 +11,8 @@ allocmemf_LDADD = ../util/mtestf.o
c2f2cf_SOURCES = c2f2c.c c2f2cf.f
c2f2cf_LDADD = ../util/mtestf.o
c2f2c_CFLAGSADD = -I../../include
ctypesinf_SOURCES = ctypesinf.f ctypesfromc.c
ctypesinf_LDADD = ../util/mtestf.o
c2fmult_SOURCES = c2fmult.c
../util/mtestf.o:
......
/* -*- Mode: C; c-basic-offset:4 ; -*- */
/*
*
* (C) 2008 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
*/
/*
* This file contains the C routines used in testing that all C datatypes
* are available in Fortran and have the correct values.
*
* The tests follow this pattern:
*
* Fortran main program
* calls the c routine f2ctype with each of the C types and the name of
* the type. That c routine using MPI_Type_f2c to convert the
* Fortran handle to a C handle, and then compares it to the corresponding
* C type, which is found by looking up the C handle by name
*
* C routine uses xxx_f2c routine to get C handle, checks some
* properties (i.e., size and rank of communicator, contents of datatype)
*
* Then the Fortran main program calls a C routine that provides
* a handle, and the Fortran program performs similar checks.
*
* We also assume that a C int is a Fortran integer. If this is not the
* case, these tests must be modified.
*/
/* style: allow:fprintf:10 sig:0 */
#include <stdio.h>
#include "mpi.h"
#include "../../include/mpitestconf.h"
#include <string.h>
/* Create an array with all of the MPI names in it */
/* This is extracted from the test in test/mpi/types/typename.c ; only the
C types are included. */
typedef struct mpi_names_t { MPI_Datatype dtype; const char *name; } mpi_names_t;
/* The MPI standard specifies that the names must be the MPI names,
not the related language names (e.g., MPI_CHAR, not char) */
static mpi_names_t mpi_names[] = {
{ MPI_CHAR, "MPI_CHAR" },
{ MPI_SIGNED_CHAR, "MPI_SIGNED_CHAR" },
{ MPI_UNSIGNED_CHAR, "MPI_UNSIGNED_CHAR" },
{ MPI_WCHAR, "MPI_WCHAR" },
{ MPI_SHORT, "MPI_SHORT" },
{ MPI_UNSIGNED_SHORT, "MPI_UNSIGNED_SHORT" },
{ MPI_INT, "MPI_INT" },
{ MPI_UNSIGNED, "MPI_UNSIGNED" },
{ MPI_LONG, "MPI_LONG" },
{ MPI_UNSIGNED_LONG, "MPI_UNSIGNED_LONG" },
{ MPI_FLOAT, "MPI_FLOAT" },
{ MPI_DOUBLE, "MPI_DOUBLE" },
{ MPI_FLOAT_INT, "MPI_FLOAT_INT" },
{ MPI_DOUBLE_INT, "MPI_DOUBLE_INT" },
{ MPI_LONG_INT, "MPI_LONG_INT" },
{ MPI_SHORT_INT, "MPI_SHORT_INT" },
{ MPI_2INT, "MPI_2INT" },
{ MPI_LONG_DOUBLE, "MPI_LONG_DOUBLE" },
{ MPI_LONG_LONG_INT, "MPI_LONG_LONG_INT" },
{ MPI_LONG_LONG, "MPI_LONG_LONG" },
{ MPI_UNSIGNED_LONG_LONG, "MPI_UNSIGNED_LONG_LONG" },
{ MPI_LONG_DOUBLE_INT, "MPI_LONG_DOUBLE_INT" },
{ 0, (char *)0 }, /* Sentinal used to indicate the last element */
};
/*
Name mapping. All routines are created with names that are lower case
with a single trailing underscore. This matches many compilers.
We use #define to change the name for Fortran compilers that do
not use the lowercase/underscore pattern
*/
#ifdef F77_NAME_UPPER
#define f2ctype_ F2CTYPE
#elif defined(F77_NAME_LOWER) || defined(F77_NAME_MIXED)
/* Mixed is ok because we use lowercase in all uses */
#define f2ctype_ f2ctype
#elif defined(F77_NAME_LOWER_2USCORE) || defined(F77_NAME_LOWER_USCORE) || \
defined(F77_NAME_MIXED_USCORE)
/* Else leave name alone (routines have no underscore, so both
of these map to a lowercase, single underscore) */
#else
#error 'Unrecognized Fortran name mapping'
#endif
/* Prototypes to keep compilers happy */
int f2ctype_( MPI_Fint *, MPI_Fint * );
/* */
int f2ctype_( MPI_Fint *fhandle, MPI_Fint *typeidx )
{
int i, errs = 0;
MPI_Datatype ctype;
/* printf( "Testing %s\n", mpi_names[*typeidx].name ); */
ctype = MPI_Type_f2c( *fhandle );
if (ctype != mpi_names[*typeidx].dtype) {
errs++;
printf( "C and Fortran types for %s do not match f=%d, c=%d.\n",
mpi_names[*typeidx].name, *fhandle, MPI_Type_c2f( ctype ) );
}
return errs;
}
program main
include 'mpif.h'
integer ierr
integer errs, toterrs, wrank
integer f2ctype
C
call mpi_init( ierr )
call mpi_comm_rank( MPI_COMM_WORLD, wrank, ierr )
C
errs = 0
C
errs = errs + f2ctype( MPI_CHAR, 0 )
errs = errs + f2ctype( MPI_SIGNED_CHAR, 1 )
errs = errs + f2ctype( MPI_UNSIGNED_CHAR, 2 )
errs = errs + f2ctype( MPI_WCHAR, 3 )
errs = errs + f2ctype( MPI_SHORT, 4 )
errs = errs + f2ctype( MPI_UNSIGNED_SHORT, 5 )
errs = errs + f2ctype( MPI_INT, 6 )
errs = errs + f2ctype( MPI_UNSIGNED, 7 )
errs = errs + f2ctype( MPI_LONG, 8 )
errs = errs + f2ctype( MPI_UNSIGNED_LONG, 9 )
errs = errs + f2ctype( MPI_FLOAT, 10 )
errs = errs + f2ctype( MPI_DOUBLE, 11 )
errs = errs + f2ctype( MPI_FLOAT_INT, 12 )
errs = errs + f2ctype( MPI_DOUBLE_INT, 13 )
errs = errs + f2ctype( MPI_LONG_INT, 14 )
errs = errs + f2ctype( MPI_SHORT_INT, 15 )
errs = errs + f2ctype( MPI_2INT, 16 )
if (MPI_LONG_DOUBLE .ne. MPI_TYPE_NULL) then
errs = errs + f2ctype( MPI_LONG_DOUBLE, 17 )
errs = errs + f2ctype( MPI_LONG_DOUBLE_INT, 21 )
endif
if (MPI_LONG_LONG .ne. MPI_TYPE_NULL) then
errs = errs + f2ctype( MPI_LONG_LONG_INT, 18 )
errs = errs + f2ctype( MPI_LONG_LONG, 19 )
errs = errs + f2ctype( MPI_UNSIGNED_LONG_LONG, 20 )
endif
C
C Summarize the errors
C
call mpi_allreduce( errs, toterrs, 1, MPI_INTEGER, MPI_SUM,
$ MPI_COMM_WORLD, ierr )
if (wrank .eq. 0) then
if (toterrs .eq. 0) then
print *, ' No Errors'
else
print *, ' Found ', toterrs, ' errors'
endif
endif
call mpi_finalize( ierr )
end
c2f2cf 1
c2fmult 1
ctypesinf 1
@ALLOCMEMF@
\ No newline at end of file
c2f902c.c: $(srcdir)/../../f90/ext/c2f902c.c
cp $(srcdir)/../../f90/ext/c2f902c.c c2f902c.c
ctypesfromc.c: $(srcdir)/../../f77/ext/ctypesfromc.c
cp $(srcdir)/../../f77/ext/ctypesfromc.c ctypesfromc.c
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment