Repository: pmodels/mpich
Pull request #7345: datatype: support MPI_LOGICAL{1,2,4,8,16} and bfloat16
Author: login: hzhou
Created: 2025-03-17T16:42:37Z | Merged: 2025-03-25T18:06:45Z

## Pull Request Description
* The Fortran fixed-size logical types has been passed and merged by MPI Forum. Assuming the next MPI standard
will be ratified before next major mpich release, we are directly using the
MPI_ prefix rather than MPIX_ prefix.

Also add MPI_TYPECLASS_LOGICAL for MPI_Type_match_size API.

reference:
https://github.com/mpi-forum/mpi-issues/issues/699
https://github.com/mpi-forum/mpi-standard/pull/963

* Add support for `bfloat16` as `MPIX_BFLOAT16`

* Add software reduction support for `MPIX_BFLOAT16` and `MPIX_C_FLOAT16`. There are not efficient but should let prototype programs work.

[skip warnings]

## Author Checklist
* [x] **Provide Description** 
      Particularly focus on _why_, not _what_. Reference background, issues, test failures, xfail entries, etc.
* [x] **Commits Follow Good Practice**
      Commits are self-contained and do not do two things at once. 
      Commit message is of the form: `module: short description` 
      Commit message explains what's in the commit.
* [x] **Passes All Tests**
      Whitespace checker. Warnings test. Additional tests via comments.
* [x] **Contribution Agreement**
      For non-Argonne authors, check [contribution agreement](http://www.mpich.org/documentation/contributor-docs/). 
      If necessary, request an explicit comment from your companies PR approval manager.



Diff:
diff --git a/CHANGES b/CHANGES
index 278757109d3..01d7e5a1f6f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -22,6 +22,11 @@ of MPI_INT. Commonly used types include MPI_BYTE, MPI_CHAR, MPI_AINT, use
 MPIR_BYTE_INTERNAL, MPIR_CHAR_INTERNAL, MPIR_AINT_INTERNAL instead. There is no
 impact to users.
 
+# Added MPI_LOGICAL1, MPI_LOGICAL2, MPI_LOGICAL4, MPI_LOGICAL8, and MPI_LOGICAL16.
+
+# Added MPIX_BFLOAT16, and added software reduction support for MPIX_BFLOAT16
+  and MPIX_C_FLOAT16.
+
 ===============================================================================
                                Changes in 4.3
 ===============================================================================
diff --git a/configure.ac b/configure.ac
index e1cd1842dcc..1170c0b2b9d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2730,19 +2730,6 @@ if test "$MPID_NO_LONG_LONG" != "yes" ; then
         AC_DEFINE(HAVE_LONG_LONG_INT,1,[Define if long long is supported])
     fi
 fi
-# Add HAVE_FLOAT16 detection
-if test "$MPID_NO_FLOAT16" != "yes" ; then
-    AC_CACHE_CHECK([whether _Float16 is supported],
-    pac_cv_have_float16,[
-    # The compiler might optimize out _Float16 usage and give a false
-    # positive for this test (observed with clang 6 on Linux with -O2).
-    # We use volatile as a way to disable optimizations.
-    AC_LINK_IFELSE([AC_LANG_PROGRAM([],[volatile _Float16 a=1; return (int)a;])],
-    pac_cv_have_float16=yes,pac_cv_have_float16=no)])
-    if test "$pac_cv_have_float16" = "yes" ; then
-        AC_DEFINE(HAVE_FLOAT16,1,[Define if _Float16 is supported])
-    fi
-fi
 
 # ----------------------------------------------------------------------------
 AC_CHECK_ALIGNOF([max_align_t],[0],[#include <stddef.h>])
@@ -2788,11 +2775,6 @@ AC_CHECK_SIZEOF(wchar_t, 0, [
 #endif
 ])
 
-AC_CHECK_SIZEOF(__float128, 0)
-if test "$ac_cv_sizeof___float128" = "16" ; then
-    AC_DEFINE(HAVE_FLOAT128, 1, [Define if __float128 is supported])
-fi
-
 AC_CHECK_SIZEOF(float_int, 0, [typedef struct { float a; int b; } float_int; ])
 AC_CHECK_SIZEOF(double_int, 0, [typedef struct { double a; int b; } double_int; ])
 AC_CHECK_SIZEOF(long_int, 0, [typedef struct { long a; int b; } long_int; ])
@@ -2800,18 +2782,6 @@ AC_CHECK_SIZEOF(short_int, 0, [typedef struct { short a; int b; } short_int; ])
 AC_CHECK_SIZEOF(two_int, 0, [typedef struct { int a; int b; } two_int; ])
 AC_CHECK_SIZEOF(long_double_int, 0, [typedef struct { long double a; int b;} long_double_int; ])
 
-# alignments for basic types
-AC_CHECK_ALIGNOF(char)
-AC_CHECK_ALIGNOF(float)
-AC_CHECK_ALIGNOF(double)
-AC_CHECK_ALIGNOF(long)
-AC_CHECK_ALIGNOF(long long)
-AC_CHECK_ALIGNOF(long double)
-AC_CHECK_ALIGNOF(short)
-AC_CHECK_ALIGNOF(int)
-AC_CHECK_ALIGNOF(bool)
-AC_CHECK_ALIGNOF(wchar_t)
-
 # sys/bitypes.h defines the int16_t etc. on some systems (e.g., OSF1).
 # Include it when testing for these types
 AC_CHECK_HEADER(sys/bitypes.h,[use_bitypes="#include <sys/bitypes.h>"
@@ -2829,37 +2799,6 @@ AC_CHECK_SIZEOF(uint16_t)
 AC_CHECK_SIZEOF(uint32_t)
 AC_CHECK_SIZEOF(uint64_t)
 
-AC_CHECK_ALIGNOF(int8_t)
-AC_CHECK_ALIGNOF(int16_t)
-AC_CHECK_ALIGNOF(int32_t)
-AC_CHECK_ALIGNOF(int64_t)
-
-if test "$ac_cv_sizeof_int8_t" -eq 1 ; then
-    AC_DEFINE(HAVE_INT8_T,1,[Define if int8_t is supported by the C compiler])
-fi
-if test "$ac_cv_sizeof_int16_t" -eq 2 ; then
-    AC_DEFINE(HAVE_INT16_T,1,[Define if int16_t is supported by the C compiler])
-fi
-if test "$ac_cv_sizeof_int32_t" -eq 4 ; then
-    AC_DEFINE(HAVE_INT32_T,1,[Define if int32_t is supported by the C compiler])
-fi
-if test "$ac_cv_sizeof_int64_t" -eq 8 ; then
-    AC_DEFINE(HAVE_INT64_T,1,[Define if int64_t is supported by the C compiler])
-fi
-
-if test "$ac_cv_sizeof_uint8_t" -eq 1 ; then
-    AC_DEFINE(HAVE_UINT8_T,1,[Define if uint8_t is supported by the C compiler])
-fi
-if test "$ac_cv_sizeof_uint16_t" -eq 2 ; then
-    AC_DEFINE(HAVE_UINT16_T,1,[Define if uint16_t is supported by the C compiler])
-fi
-if test "$ac_cv_sizeof_uint32_t" -eq 4 ; then
-    AC_DEFINE(HAVE_UINT32_T,1,[Define if uint32_t is supported by the C compiler])
-fi
-if test "$ac_cv_sizeof_uint64_t" -eq 8 ; then
-    AC_DEFINE(HAVE_UINT64_T,1,[Define if uint64_t is supported by the C compiler])
-fi
-
 # Other C99 types.
 AC_CHECK_HEADERS([stdbool.h complex.h])
 AC_CHECK_SIZEOF([_Bool],0,[
@@ -2884,7 +2823,6 @@ AS_IF([test "X$pac_cv_have_long_double" = "Xyes"],[
 #endif
   ])
 ])
-AC_CHECK_SIZEOF([_Float16])
 
 # we need really could just use the result of AC_CHECK_SIZEOF, but having a
 # HAVE_typename macro is useful for consistency
@@ -2912,57 +2850,105 @@ template and manually set the correct values.])
     fi
 done
 
-# Generate _CTYPE for internal types
+# Generate _CTYPE and _ALIGN for internal types
+
+if test "$ac_cv_sizeof_int8_t" -eq 1 ; then
+    AC_DEFINE_UNQUOTED([MPIR_INT8_CTYPE],[int8_t], [The C type for MPIR_INT8])
+    AC_DEFINE_UNQUOTED([MPIR_UINT8_CTYPE],[uint8_t], [The C type for MPIR_UINT8])
+    AC_CHECK_ALIGNOF(int8_t)
+    AC_DEFINE_UNQUOTED([MPIR_INT8_ALIGN],[$ac_cv_alignof_int8_t], [The alignment for MPIR_INT8])
+fi
+
+if test "$ac_cv_sizeof_int16_t" -eq 2 ; then
+    AC_DEFINE_UNQUOTED([MPIR_INT16_CTYPE],[int16_t], [The C type for MPIR_INT16])
+    AC_DEFINE_UNQUOTED([MPIR_UINT16_CTYPE],[uint16_t], [The C type for MPIR_UINT16])
+    AC_CHECK_ALIGNOF(int16_t)
+    AC_DEFINE_UNQUOTED([MPIR_INT16_ALIGN],[$ac_cv_alignof_int16_t], [The alignment for MPIR_INT16])
+fi
+
+if test "$ac_cv_sizeof_int32_t" -eq 4 ; then
+    AC_DEFINE_UNQUOTED([MPIR_INT32_CTYPE],[int32_t], [The C type for MPIR_INT32])
+    AC_DEFINE_UNQUOTED([MPIR_UINT32_CTYPE],[uint32_t], [The C type for MPIR_UINT32])
+    AC_CHECK_ALIGNOF(int32_t)
+    AC_DEFINE_UNQUOTED([MPIR_INT32_ALIGN],[$ac_cv_alignof_int32_t], [The alignment for MPIR_INT32])
+fi
+
+if test "$ac_cv_sizeof_int64_t" -eq 8 ; then
+    AC_DEFINE_UNQUOTED([MPIR_INT64_CTYPE],[int64_t], [The C type for MPIR_INT64])
+    AC_DEFINE_UNQUOTED([MPIR_UINT64_CTYPE],[uint64_t], [The C type for MPIR_UINT64])
+    AC_CHECK_ALIGNOF(int64_t)
+    AC_DEFINE_UNQUOTED([MPIR_INT64_ALIGN],[$ac_cv_alignof_int64_t], [The alignment for MPIR_INT64])
+fi
+
+if test "$MPID_NO_INT128" != "yes" ; then
+    AC_CHECK_SIZEOF(__int128)
+    if test "$ac_cv_sizeof___int128" -eq 16 ; then
+        AC_DEFINE_UNQUOTED([MPIR_INT128_CTYPE],[__int128], [The C type for MPIR_INT128])
+        AC_DEFINE_UNQUOTED([MPIR_UINT128_CTYPE],[unsigned __int128], [The C type for MPIR_UINT128])
+        AC_CHECK_ALIGNOF(__int128)
+        AC_DEFINE_UNQUOTED([MPIR_INT128_ALIGN],[$ac_cv_alignof___int128], [The alignment for MPIR_INT128])
+    fi
+fi
 
-for i in 1 2 4 8 16 ; do
-    AC_MSG_CHECKING([for C type matching $i-byte integer])
-    get_c_int_type $i
-    AC_MSG_RESULT($pac_retval)
-    if test $pac_retval != "unavailable" ; then
-        len=`expr $i \* 8`
-        AC_DEFINE_UNQUOTED([MPIR_INT${len}_CTYPE],[$pac_retval], [The C type for MPIR_INT${len}])
-        AC_DEFINE_UNQUOTED([MPIR_UINT${len}_CTYPE],[$pac_retval], [The C type for MPIR_UINT${len}])
+if test "$MPID_NO_FLOAT16" != "yes" ; then
+    AC_CHECK_SIZEOF(_Float16)
+    AC_CHECK_SIZEOF(__fp16)
+    if test "$ac_cv_sizeof__Float16" -eq 2 ; then
+        AC_DEFINE_UNQUOTED([MPIR_FLOAT16_CTYPE],[_Float16], [The C type for MPIR_FLOAT16])
+        AC_CHECK_ALIGNOF(_Float16)
+        AC_DEFINE_UNQUOTED([MPIR_FLOAT16_ALIGN],[$ac_cv_alignof__Float16], [The alignment for MPIR_FLOAT16])
+    elif test "$ac_cv_sizeof___fp16" -eq 2 ; then
+        # enable it on ARM with -mfp16-format
+        AC_DEFINE_UNQUOTED([MPIR_FLOAT16_CTYPE],[__fp16], [The C type for MPIR_FLOAT16])
+        AC_CHECK_ALIGNOF(__fp16)
+        AC_DEFINE_UNQUOTED([MPIR_FLOAT16_ALIGN],[$ac_cv_alignof___fp16], [The alignment for MPIR_FLOAT16])
     fi
-done
+fi
+
+if test "$ac_cv_sizeof_float" -eq 4 ; then
+    AC_DEFINE_UNQUOTED([MPIR_FLOAT32_CTYPE],[float], [The C type for MPIR_FLOAT32])
+    AC_CHECK_ALIGNOF(float)
+    AC_DEFINE_UNQUOTED([MPIR_FLOAT32_ALIGN],[$ac_cv_alignof_float], [The alignment for MPIR_FLOAT32])
+fi
 
-for i in 2 4 8 16; do
-    AC_MSG_CHECKING([for C type matching $i-byte float])
-    get_c_float_type $i
-    AC_MSG_RESULT($pac_retval)
-    if test $pac_retval != "unavailable" ; then
-        len=`expr $i \* 8`
-        AC_DEFINE_UNQUOTED([MPIR_FLOAT${len}_CTYPE],[$pac_retval], [The C type for MPIR_FLOAT${len}])
+if test "$ac_cv_sizeof_double" -eq 8 ; then
+    AC_DEFINE_UNQUOTED([MPIR_FLOAT64_CTYPE],[double], [The C type for MPIR_FLOAT64])
+    AC_CHECK_ALIGNOF(double)
+    AC_DEFINE_UNQUOTED([MPIR_FLOAT64_ALIGN],[$ac_cv_alignof_double], [The alignment for MPIR_FLOAT64])
+fi
+
+if test "$MPID_NO_FLOAT128" != "yes" ; then
+    AC_CHECK_SIZEOF(__float128)
+    if test "$ac_cv_sizeof___float128" -eq 16 ; then
+        AC_DEFINE_UNQUOTED([MPIR_FLOAT128_CTYPE],[__float128], [The C type for MPIR_FLOAT128])
+        AC_CHECK_ALIGNOF(__float128)
+        AC_DEFINE_UNQUOTED([MPIR_FLOAT128_ALIGN],[$ac_cv_alignof___float128], [The alignment for MPIR_FLOAT64])
     fi
-done
+fi
 
 if test "$ac_cv_sizeof_long_double" -gt 0 ; then
     len=`expr $ac_cv_sizeof_long_double \* 8`
     AC_DEFINE_UNQUOTED([MPIR_ALT_FLOAT${len}_CTYPE],[long double], [The C type for MPIR_ALT_FLOAT${len}])
+    AC_CHECK_ALIGNOF(long double)
+    AC_DEFINE_UNQUOTED([MPIR_ALT_FLOAT${len}_ALIGN],[$ac_cv_alignof_long_double], [The alignment for MPIR_ALT_FLOAT${len}])
+fi
+
+if test "$ac_cv_sizeof_float__Complex" -eq 8 ; then
+    AC_DEFINE_UNQUOTED([MPIR_COMPLEX32_CTYPE], [float _Complex], [The C type for MPIR_COMPLEX32])
+fi
+if test "$ac_cv_sizeof_double__Complex" -eq 16 ; then
+    AC_DEFINE_UNQUOTED([MPIR_COMPLEX64_CTYPE], [double _Complex], [The C type for MPIR_COMPLEX64])
+fi
+if test "$ac_cv_sizeof_long_double__Complex" -gt 0 ; then
+    len=`expr $ac_cv_sizeof_long_double \* 8`
+    AC_DEFINE_UNQUOTED([MPIR_ALT_COMPLEX${len}_CTYPE], [long double _Complex], [The C type for MPIR_ALT_COMPLEX${len}])
 fi
 
 # autoheader won't recognize keys with variable expansion, so -
-AH_TEMPLATE([MPIR_INT8_CTYPE], [The C type for MPIR_INT8])
-AH_TEMPLATE([MPIR_INT16_CTYPE], [The C type for MPIR_INT16])
-AH_TEMPLATE([MPIR_INT32_CTYPE], [The C type for MPIR_INT32])
-AH_TEMPLATE([MPIR_INT64_CTYPE], [The C type for MPIR_INT64])
-AH_TEMPLATE([MPIR_INT128_CTYPE], [The C type for MPIR_INT128])
-AH_TEMPLATE([MPIR_UINT8_CTYPE], [The C type for MPIR_UINT8])
-AH_TEMPLATE([MPIR_UINT16_CTYPE], [The C type for MPIR_UINT16])
-AH_TEMPLATE([MPIR_UINT32_CTYPE], [The C type for MPIR_UINT32])
-AH_TEMPLATE([MPIR_UINT64_CTYPE], [The C type for MPIR_UINT64])
-AH_TEMPLATE([MPIR_UINT128_CTYPE], [The C type for MPIR_UINT128])
-AH_TEMPLATE([MPIR_FLOAT8_CTYPE], [The C type for MPIR_FLOAT8])
-AH_TEMPLATE([MPIR_FLOAT16_CTYPE], [The C type for MPIR_FLOAT16])
-AH_TEMPLATE([MPIR_FLOAT32_CTYPE], [The C type for MPIR_FLOAT32])
-AH_TEMPLATE([MPIR_FLOAT64_CTYPE], [The C type for MPIR_FLOAT64])
-AH_TEMPLATE([MPIR_FLOAT128_CTYPE], [The C type for MPIR_FLOAT128])
 AH_TEMPLATE([MPIR_ALT_FLOAT96_CTYPE], [The C type for MPIR_ALT_FLOAT96])
 AH_TEMPLATE([MPIR_ALT_FLOAT128_CTYPE], [The C type for MPIR_ALT_FLOAT128])
-dnl optionally define the following to use C native complex types in reduction op
-AH_TEMPLATE([MPIR_COMPLEX16_CTYPE], [The C type for MPIR_COMPLEX16])
-AH_TEMPLATE([MPIR_COMPLEX32_CTYPE], [The C type for MPIR_COMPLEX32])
-AH_TEMPLATE([MPIR_COMPLEX64_CTYPE], [The C type for MPIR_COMPLEX64])
-AH_TEMPLATE([MPIR_COMPLEX128_CTYPE], [The C type for MPIR_COMPLEX128])
+AH_TEMPLATE([MPIR_ALT_FLOAT96_ALIGN], [The alignment for MPIR_ALT_FLOAT96])
+AH_TEMPLATE([MPIR_ALT_FLOAT128_ALIGN], [The alignment for MPIR_ALT_FLOAT128])
 AH_TEMPLATE([MPIR_ALT_COMPLEX96_CTYPE], [The C type for MPIR_ALT_COMPLEX96])
 AH_TEMPLATE([MPIR_ALT_COMPLEX128_CTYPE], [The C type for MPIR_ALT_COMPLEX128])
 
@@ -3495,53 +3481,87 @@ AC_DEFINE_UNQUOTED([MPIR_2INT_INTERNAL],          [MPIR_2INT$len], [Internal typ
 AC_DEFINE_UNQUOTED([MPIR_SIGNED_CHAR_INTERNAL],   [MPIR_INT8], [Internal type for MPI_SIGNED_CHAR])
 len=`expr $ac_cv_sizeof_long_long \* 8`
 AC_DEFINE_UNQUOTED([MPIR_UNSIGNED_LONG_LONG_INTERNAL],[MPIR_INT$len], [Internal type for MPI_UNSIGNED_LONG_LONG])
-len=`expr $pac_cv_f77_sizeof_character \* 8`
-AC_DEFINE_UNQUOTED([MPIR_CHARACTER_INTERNAL],     [MPIR_INT$len], [Internal type for MPI_CHARACTER])
-len=`expr $pac_cv_f77_sizeof_integer \* 8`
-AC_DEFINE_UNQUOTED([MPIR_INTEGER_INTERNAL],       [MPIR_INT$len], [Internal type for MPI_INTEGER])
-len=`expr $pac_cv_f77_sizeof_real \* 8`
-AC_DEFINE_UNQUOTED([MPIR_REAL_INTERNAL],          [MPIR_INT$len], [Internal type for MPI_REAL])
-len=`expr $pac_cv_f77_sizeof_logical \* 8`
-AC_DEFINE_UNQUOTED([MPIR_LOGICAL_INTERNAL],       [MPIR_FORTRAN_LOGICAL$len], [Internal type for MPI_LOGICAL])
-len=`expr $pac_cv_f77_sizeof_real \* 8`
-AC_DEFINE_UNQUOTED([MPIR_COMPLEX_INTERNAL],       [MPIR_COMPLEX$len], [Internal type for MPI_COMPLEX])
-len=`expr $pac_cv_f77_sizeof_double_precision \* 8`
-AC_DEFINE_UNQUOTED([MPIR_DOUBLE_PRECISION_INTERNAL],[MPIR_FLOAT$len], [Internal type for MPI_DOUBLE_PRECISION])
-len=`expr $pac_cv_f77_sizeof_integer \* 8`
-AC_DEFINE_UNQUOTED([MPIR_2INTEGER_INTERNAL],      [MPIR_2INT$len], [Internal type for MPI_2INTEGER])
-len=`expr $pac_cv_f77_sizeof_real \* 8`
-AC_DEFINE_UNQUOTED([MPIR_2REAL_INTERNAL],         [MPIR_2FLOAT$len], [Internal type for MPI_2REAL])
-len=`expr $pac_cv_f77_sizeof_double_precision \* 8`
-AC_DEFINE_UNQUOTED([MPIR_DOUBLE_COMPLEX_INTERNAL],[MPIR_COMPLEX$len], [Internal type for MPI_DOUBLE_COMPLEX])
-AC_DEFINE_UNQUOTED([MPIR_2DOUBLE_PRECISION_INTERNAL],[MPIR_2FLOAT$len], [Internal type for MPI_2DOUBLE_PRECISION])
-# skip MPI_2COMPLEX, MPI_2DOUBLE_COMPLEX
-AC_DEFINE_UNQUOTED([MPIR_REAL2_INTERNAL],         [MPIR_FLOAT16], [Internal type for MPI_REAL2])
-AC_DEFINE_UNQUOTED([MPIR_REAL4_INTERNAL],         [MPIR_FLOAT32], [Internal type for MPI_REAL4])
-AC_DEFINE_UNQUOTED([MPIR_COMPLEX8_INTERNAL],      [MPIR_COMPLEX32], [Internal type for MPI_COMPLEX8])
-AC_DEFINE_UNQUOTED([MPIR_REAL8_INTERNAL],         [MPIR_FLOAT64], [Internal type for MPI_REAL8])
-AC_DEFINE_UNQUOTED([MPIR_COMPLEX16_INTERNAL],     [MPIR_COMPLEX64], [Internal type for MPI_COMPLEX16])
-AC_DEFINE_UNQUOTED([MPIR_REAL16_INTERNAL],        [MPIR_FLOAT128], [Internal type for MPI_REAL16])
-AC_DEFINE_UNQUOTED([MPIR_COMPLEX32_INTERNAL],     [MPIR_COMPLEX128], [Internal type for MPI_COMPLEX32])
-AC_DEFINE_UNQUOTED([MPIR_INTEGER1_INTERNAL],      [MPIR_INT8], [Internal type for MPI_INTEGER1])
-AC_DEFINE_UNQUOTED([MPIR_COMPLEX4_INTERNAL],      [MPIR_COMPLEX16], [Internal type for MPI_COMPLEX4])
-AC_DEFINE_UNQUOTED([MPIR_INTEGER2_INTERNAL],      [MPIR_INT16], [Internal type for MPI_INTEGER2])
-AC_DEFINE_UNQUOTED([MPIR_INTEGER4_INTERNAL],      [MPIR_INT32], [Internal type for MPI_INTEGER4])
-AC_DEFINE_UNQUOTED([MPIR_INTEGER8_INTERNAL],      [MPIR_INT64], [Internal type for MPI_INTEGER8])
-AC_DEFINE_UNQUOTED([MPIR_INTEGER16_INTERNAL],     [MPIR_INT128], [Internal type for MPI_INTEGER16])
-len=`expr $ac_cv_sizeof_bool \* 8`
-AC_DEFINE_UNQUOTED([MPIR_CXX_BOOL_INTERNAL],      [MPIR_INT$len], [Internal type for MPI_CXX_BOOL])
-len=`expr $ac_cv_sizeof_Complex / 2 \* 8`
-AC_DEFINE_UNQUOTED([MPIR_CXX_FLOAT_COMPLEX_INTERNAL],[MPIR_COMPLEX$len], [Internal type for MPI_CXX_FLOAT_COMPLEX])
-len=`expr $ac_cv_sizeof_DoubleComplex / 2 \* 8`
-AC_DEFINE_UNQUOTED([MPIR_CXX_DOUBLE_COMPLEX_INTERNAL],[MPIR_COMPLEX$len], [Internal type for MPI_CXX_DOUBLE_COMPLEX])
-len=`expr $ac_cv_sizeof_LongDoubleComplex / 2 \* 8`
-if test "$len" = 64 ; then
-    # long double is an alias of double, e.g. arm64
-    internal_type=MPIR_COMPLEX$len
+if test "$enable_f77" = "yes" ; then
+    len=`expr $pac_cv_f77_sizeof_character \* 8`
+    AC_DEFINE_UNQUOTED([MPIR_CHARACTER_INTERNAL],     [MPIR_INT$len], [Internal type for MPI_CHARACTER])
+    len=`expr $pac_cv_f77_sizeof_integer \* 8`
+    AC_DEFINE_UNQUOTED([MPIR_INTEGER_INTERNAL],       [MPIR_INT$len], [Internal type for MPI_INTEGER])
+    len=`expr $pac_cv_f77_sizeof_real \* 8`
+    AC_DEFINE_UNQUOTED([MPIR_REAL_INTERNAL],          [MPIR_INT$len], [Internal type for MPI_REAL])
+    len=`expr $pac_cv_f77_sizeof_logical \* 8`
+    AC_DEFINE_UNQUOTED([MPIR_LOGICAL_INTERNAL],       [MPIR_FORTRAN_LOGICAL$len], [Internal type for MPI_LOGICAL])
+    len=`expr $pac_cv_f77_sizeof_real \* 8`
+    AC_DEFINE_UNQUOTED([MPIR_COMPLEX_INTERNAL],       [MPIR_COMPLEX$len], [Internal type for MPI_COMPLEX])
+    len=`expr $pac_cv_f77_sizeof_double_precision \* 8`
+    AC_DEFINE_UNQUOTED([MPIR_DOUBLE_PRECISION_INTERNAL],[MPIR_FLOAT$len], [Internal type for MPI_DOUBLE_PRECISION])
+    len=`expr $pac_cv_f77_sizeof_integer \* 8`
+    AC_DEFINE_UNQUOTED([MPIR_2INTEGER_INTERNAL],      [MPIR_2INT$len], [Internal type for MPI_2INTEGER])
+    len=`expr $pac_cv_f77_sizeof_real \* 8`
+    AC_DEFINE_UNQUOTED([MPIR_2REAL_INTERNAL],         [MPIR_2FLOAT$len], [Internal type for MPI_2REAL])
+    len=`expr $pac_cv_f77_sizeof_double_precision \* 8`
+    AC_DEFINE_UNQUOTED([MPIR_DOUBLE_COMPLEX_INTERNAL],[MPIR_COMPLEX$len], [Internal type for MPI_DOUBLE_COMPLEX])
+    AC_DEFINE_UNQUOTED([MPIR_2DOUBLE_PRECISION_INTERNAL],[MPIR_2FLOAT$len], [Internal type for MPI_2DOUBLE_PRECISION])
+    # skip MPI_2COMPLEX, MPI_2DOUBLE_COMPLEX
+    AC_DEFINE_UNQUOTED([MPIR_REAL2_INTERNAL],         [MPIR_FLOAT16], [Internal type for MPI_REAL2])
+    AC_DEFINE_UNQUOTED([MPIR_REAL4_INTERNAL],         [MPIR_FLOAT32], [Internal type for MPI_REAL4])
+    AC_DEFINE_UNQUOTED([MPIR_COMPLEX8_INTERNAL],      [MPIR_COMPLEX32], [Internal type for MPI_COMPLEX8])
+    AC_DEFINE_UNQUOTED([MPIR_REAL8_INTERNAL],         [MPIR_FLOAT64], [Internal type for MPI_REAL8])
+    AC_DEFINE_UNQUOTED([MPIR_COMPLEX16_INTERNAL],     [MPIR_COMPLEX64], [Internal type for MPI_COMPLEX16])
+    AC_DEFINE_UNQUOTED([MPIR_REAL16_INTERNAL],        [MPIR_FLOAT128], [Internal type for MPI_REAL16])
+    AC_DEFINE_UNQUOTED([MPIR_COMPLEX32_INTERNAL],     [MPIR_COMPLEX128], [Internal type for MPI_COMPLEX32])
+    AC_DEFINE_UNQUOTED([MPIR_INTEGER1_INTERNAL],      [MPIR_INT8], [Internal type for MPI_INTEGER1])
+    AC_DEFINE_UNQUOTED([MPIR_COMPLEX4_INTERNAL],      [MPIR_COMPLEX16], [Internal type for MPI_COMPLEX4])
+    AC_DEFINE_UNQUOTED([MPIR_INTEGER2_INTERNAL],      [MPIR_INT16], [Internal type for MPI_INTEGER2])
+    AC_DEFINE_UNQUOTED([MPIR_INTEGER4_INTERNAL],      [MPIR_INT32], [Internal type for MPI_INTEGER4])
+    AC_DEFINE_UNQUOTED([MPIR_INTEGER8_INTERNAL],      [MPIR_INT64], [Internal type for MPI_INTEGER8])
+    AC_DEFINE_UNQUOTED([MPIR_INTEGER16_INTERNAL],     [MPIR_INT128], [Internal type for MPI_INTEGER16])
 else
-    internal_type=MPIR_ALT_COMPLEX$len
+    AC_DEFINE_UNQUOTED([MPIR_CHARACTER_INTERNAL],     [MPI_DATATYPE_NULL], [Internal type for MPI_CHARACTER])
+    AC_DEFINE_UNQUOTED([MPIR_INTEGER_INTERNAL],       [MPI_DATATYPE_NULL], [Internal type for MPI_INTEGER])
+    AC_DEFINE_UNQUOTED([MPIR_REAL_INTERNAL],          [MPI_DATATYPE_NULL], [Internal type for MPI_REAL])
+    AC_DEFINE_UNQUOTED([MPIR_LOGICAL_INTERNAL],       [MPI_DATATYPE_NULL], [Internal type for MPI_LOGICAL])
+    AC_DEFINE_UNQUOTED([MPIR_COMPLEX_INTERNAL],       [MPI_DATATYPE_NULL], [Internal type for MPI_COMPLEX])
+    AC_DEFINE_UNQUOTED([MPIR_DOUBLE_PRECISION_INTERNAL],[MPI_DATATYPE_NULL], [Internal type for MPI_DOUBLE_PRECISION])
+    AC_DEFINE_UNQUOTED([MPIR_2INTEGER_INTERNAL],      [MPI_DATATYPE_NULL], [Internal type for MPI_2INTEGER])
+    AC_DEFINE_UNQUOTED([MPIR_2REAL_INTERNAL],         [MPI_DATATYPE_NULL], [Internal type for MPI_2REAL])
+    AC_DEFINE_UNQUOTED([MPIR_DOUBLE_COMPLEX_INTERNAL],[MPI_DATATYPE_NULL], [Internal type for MPI_DOUBLE_COMPLEX])
+    AC_DEFINE_UNQUOTED([MPIR_2DOUBLE_PRECISION_INTERNAL],[MPI_DATATYPE_NULL], [Internal type for MPI_2DOUBLE_PRECISION])
+    # skip MPI_2COMPLEX, MPI_2DOUBLE_COMPLEX
+    AC_DEFINE_UNQUOTED([MPIR_REAL2_INTERNAL],         [MPI_DATATYPE_NULL], [Internal type for MPI_REAL2])
+    AC_DEFINE_UNQUOTED([MPIR_REAL4_INTERNAL],         [MPI_DATATYPE_NULL], [Internal type for MPI_REAL4])
+    AC_DEFINE_UNQUOTED([MPIR_COMPLEX8_INTERNAL],      [MPI_DATATYPE_NULL], [Internal type for MPI_COMPLEX8])
+    AC_DEFINE_UNQUOTED([MPIR_REAL8_INTERNAL],         [MPI_DATATYPE_NULL], [Internal type for MPI_REAL8])
+    AC_DEFINE_UNQUOTED([MPIR_COMPLEX16_INTERNAL],     [MPI_DATATYPE_NULL], [Internal type for MPI_COMPLEX16])
+    AC_DEFINE_UNQUOTED([MPIR_REAL16_INTERNAL],        [MPI_DATATYPE_NULL], [Internal type for MPI_REAL16])
+    AC_DEFINE_UNQUOTED([MPIR_COMPLEX32_INTERNAL],     [MPI_DATATYPE_NULL], [Internal type for MPI_COMPLEX32])
+    AC_DEFINE_UNQUOTED([MPIR_INTEGER1_INTERNAL],      [MPI_DATATYPE_NULL], [Internal type for MPI_INTEGER1])
+    AC_DEFINE_UNQUOTED([MPIR_COMPLEX4_INTERNAL],      [MPI_DATATYPE_NULL], [Internal type for MPI_COMPLEX4])
+    AC_DEFINE_UNQUOTED([MPIR_INTEGER2_INTERNAL],      [MPI_DATATYPE_NULL], [Internal type for MPI_INTEGER2])
+    AC_DEFINE_UNQUOTED([MPIR_INTEGER4_INTERNAL],      [MPI_DATATYPE_NULL], [Internal type for MPI_INTEGER4])
+    AC_DEFINE_UNQUOTED([MPIR_INTEGER8_INTERNAL],      [MPI_DATATYPE_NULL], [Internal type for MPI_INTEGER8])
+    AC_DEFINE_UNQUOTED([MPIR_INTEGER16_INTERNAL],     [MPI_DATATYPE_NULL], [Internal type for MPI_INTEGER16])
+fi
+if test -n "$CXX" ; then
+    len=`expr $ac_cv_sizeof_bool \* 8`
+    AC_DEFINE_UNQUOTED([MPIR_CXX_BOOL_INTERNAL],      [MPIR_INT$len], [Internal type for MPI_CXX_BOOL])
+    len=`expr $ac_cv_sizeof_Complex / 2 \* 8`
+    AC_DEFINE_UNQUOTED([MPIR_CXX_FLOAT_COMPLEX_INTERNAL],[MPIR_COMPLEX$len], [Internal type for MPI_CXX_FLOAT_COMPLEX])
+    len=`expr $ac_cv_sizeof_DoubleComplex / 2 \* 8`
+    AC_DEFINE_UNQUOTED([MPIR_CXX_DOUBLE_COMPLEX_INTERNAL],[MPIR_COMPLEX$len], [Internal type for MPI_CXX_DOUBLE_COMPLEX])
+    len=`expr $ac_cv_sizeof_LongDoubleComplex / 2 \* 8`
+    if test "$len" = 64 ; then
+        # long double is an alias of double, e.g. arm64
+        internal_type=MPIR_COMPLEX$len
+    else
+        internal_type=MPIR_ALT_COMPLEX$len
+    fi
+    AC_DEFINE_UNQUOTED([MPIR_CXX_LONG_DOUBLE_COMPLEX_INTERNAL],[$internal_type], [Internal type for MPI_CXX_LONG_DOUBLE_COMPLEX])
+else
+    AC_DEFINE_UNQUOTED([MPIR_CXX_BOOL_INTERNAL],          [MPI_DATATYPE_NULL], [Internal type for MPI_CXX_BOOL])
+    AC_DEFINE_UNQUOTED([MPIR_CXX_FLOAT_COMPLEX_INTERNAL], [MPI_DATATYPE_NULL], [Internal type for MPI_CXX_FLOAT_COMPLEX])
+    AC_DEFINE_UNQUOTED([MPIR_CXX_DOUBLE_COMPLEX_INTERNAL],[MPI_DATATYPE_NULL], [Internal type for MPI_CXX_DOUBLE_COMPLEX])
+    AC_DEFINE_UNQUOTED([MPIR_CXX_LONG_DOUBLE_COMPLEX_INTERNAL],[MPI_DATATYPE_NULL], [Internal type for MPI_CXX_LONG_DOUBLE_COMPLEX])
 fi
-AC_DEFINE_UNQUOTED([MPIR_CXX_LONG_DOUBLE_COMPLEX_INTERNAL],[$internal_type], [Internal type for MPI_CXX_LONG_DOUBLE_COMPLEX])
 AC_DEFINE_UNQUOTED([MPIR_INT8_T_INTERNAL],   [MPIR_INT8], [Internal type for MPI_INT8_T])
 AC_DEFINE_UNQUOTED([MPIR_INT16_T_INTERNAL],  [MPIR_INT16], [Internal type for MPI_INT16_T])
 AC_DEFINE_UNQUOTED([MPIR_INT32_T_INTERNAL],  [MPIR_INT32], [Internal type for MPI_INT32_T])
@@ -3571,6 +3591,20 @@ AC_DEFINE_UNQUOTED([MPIR_OFFSET_INTERNAL],[MPIR_INT$len], [Internal type for MPI
 len=`expr $MPI_SIZEOF_COUNT \* 8`
 AC_DEFINE_UNQUOTED([MPIR_COUNT_INTERNAL], [MPIR_INT$len], [Internal type for MPI_COUNT_DATATYPE])
 AC_DEFINE_UNQUOTED([MPIR_C_FLOAT16_INTERNAL], [MPIR_FLOAT16], [Internal type for MPIX_C_FLOAT16])
+if test "$enable_f77" = "yes" ; then
+    AC_DEFINE_UNQUOTED([MPIR_LOGICAL1_INTERNAL],  [MPIR_FORTRAN_LOGICAL8], [Internal type for MPI_LOGICAL1])
+    AC_DEFINE_UNQUOTED([MPIR_LOGICAL2_INTERNAL],  [MPIR_FORTRAN_LOGICAL16], [Internal type for MPI_LOGICAL2])
+    AC_DEFINE_UNQUOTED([MPIR_LOGICAL4_INTERNAL],  [MPIR_FORTRAN_LOGICAL32], [Internal type for MPI_LOGICAL4])
+    AC_DEFINE_UNQUOTED([MPIR_LOGICAL8_INTERNAL],  [MPIR_FORTRAN_LOGICAL64], [Internal type for MPI_LOGICAL8])
+    AC_DEFINE_UNQUOTED([MPIR_LOGICAL16_INTERNAL], [MPIR_FORTRAN_LOGICAL128],[Internal type for MPI_LOGICAL16])
+else
+    AC_DEFINE_UNQUOTED([MPIR_LOGICAL1_INTERNAL],  [MPI_DATATYPE_NULL], [Internal type for MPI_LOGICAL1])
+    AC_DEFINE_UNQUOTED([MPIR_LOGICAL2_INTERNAL],  [MPI_DATATYPE_NULL], [Internal type for MPI_LOGICAL2])
+    AC_DEFINE_UNQUOTED([MPIR_LOGICAL4_INTERNAL],  [MPI_DATATYPE_NULL], [Internal type for MPI_LOGICAL4])
+    AC_DEFINE_UNQUOTED([MPIR_LOGICAL8_INTERNAL],  [MPI_DATATYPE_NULL], [Internal type for MPI_LOGICAL8])
+    AC_DEFINE_UNQUOTED([MPIR_LOGICAL16_INTERNAL], [MPI_DATATYPE_NULL],[Internal type for MPI_LOGICAL16])
+fi
+AC_DEFINE_UNQUOTED([MPIR_BFLOAT16_INTERNAL],  [MPIR_BFLOAT16],[Internal type for MPIX_BFLOAT16])
 AC_MSG_RESULT([done])
 
 # ------------------------------------------------------------------------
diff --git a/maint/gen_abi.py b/maint/gen_abi.py
index 30ca72182c6..50e3e35cb12 100644
--- a/maint/gen_abi.py
+++ b/maint/gen_abi.py
@@ -60,8 +60,6 @@ def gen_mpi_abi_internal_h(out):
                 elif T == "MPI_Datatype":
                     idx = int(val, 0) & G.datatype_mask
                     G.abi_datatypes[idx] = name
-                    if re.match(r'MPI_LOGICAL\d+', name):
-                        G.abi_datatypes[idx] = "MPI_DATATYPE_NULL"
                 elif T == "MPI_Op":
                     idx = int(val, 0) & G.op_mask
                     G.abi_ops[idx] = name
diff --git a/src/include/mpi.h.in b/src/include/mpi.h.in
index 5499b73c447..c70a347e926 100644
--- a/src/include/mpi.h.in
+++ b/src/include/mpi.h.in
@@ -253,6 +253,14 @@ typedef int MPI_Datatype;
 #define MPI_COUNT         ((MPI_Datatype)0x4c000845)
 /* other extension types */
 #define MPIX_C_FLOAT16    ((MPI_Datatype)0x4c000246)
+/* Fortran fixed-width logicals */
+#define MPI_LOGICAL1      ((MPI_Datatype)0x4c000147)
+#define MPI_LOGICAL2      ((MPI_Datatype)0x4c000248)
+#define MPI_LOGICAL4      ((MPI_Datatype)0x4c000449)
+#define MPI_LOGICAL8      ((MPI_Datatype)0x4c00084a)
+#define MPI_LOGICAL16     ((MPI_Datatype)0x4c00104b)
+/* other */
+#define MPIX_BFLOAT16     ((MPI_Datatype)0x4c00024c)
 
 /* Communicators */
 typedef int MPI_Comm;
diff --git a/src/include/mpir_datatype.h b/src/include/mpir_datatype.h
index b469a043f88..5c8d6cd8e56 100644
--- a/src/include/mpir_datatype.h
+++ b/src/include/mpir_datatype.h
@@ -72,6 +72,7 @@
 #define MPIR_COMPLEX32          ((MPI_Datatype)0x4c840800)
 #define MPIR_COMPLEX64          ((MPI_Datatype)0x4c841000)
 #define MPIR_COMPLEX128         ((MPI_Datatype)0x4c842000)
+#define MPIR_BFLOAT16           ((MPI_Datatype)0x4c850200)      /* bfloat16, use MPIR_TYPE_ALT_FLOAT */
 #define MPIR_ALT_FLOAT96        ((MPI_Datatype)0x4c850c00)      /* long double (80-bit extended precision) on i386 */
 #define MPIR_ALT_FLOAT128       ((MPI_Datatype)0x4c851000)      /* long double (80-bit extended precision) on x86-64 */
 #define MPIR_ALT_COMPLEX96      ((MPI_Datatype)0x4c861800)      /* long double complex on i386 */
diff --git a/src/include/mpir_objects.h b/src/include/mpir_objects.h
index 808f328f7ff..a5b4c67d110 100644
--- a/src/include/mpir_objects.h
+++ b/src/include/mpir_objects.h
@@ -217,7 +217,7 @@ const char *MPIR_Handle_get_kind_str(int kind);
 #define MPIR_GROUP_PREALLOC 8
 #endif
 
-#define MPIR_DATATYPE_N_BUILTIN 71
+#define MPIR_DATATYPE_N_BUILTIN 77      /* 0x4d - must be in sync with mpi.h.in */
 #ifdef MPID_DATATYPE_PREALLOC
 #define MPIR_DATATYPE_PREALLOC MPID_DATATYPE_PREALLOC
 #else
diff --git a/src/mpi/coll/op/op_fns.c b/src/mpi/coll/op/op_fns.c
index d573a1d47a6..50c6218721b 100644
--- a/src/mpi/coll/op/op_fns.c
+++ b/src/mpi/coll/op/op_fns.c
@@ -11,6 +11,9 @@
 
 #define MPIR_LSUM(a,b) ((a)+(b))
 
+static void bfloat16_sum(void *invec, void *inoutvec, MPI_Aint len);
+static void f16_sum(void *invec, void *inoutvec, MPI_Aint len);
+
 void MPIR_SUM(void *invec, void *inoutvec, MPI_Aint * Len, MPI_Datatype * type)
 {
     MPI_Aint i, len = *Len;
@@ -35,6 +38,14 @@ void MPIR_SUM(void *invec, void *inoutvec, MPI_Aint * Len, MPI_Datatype * type)
             break;                                         \
         }
                 MPIR_OP_TYPE_GROUP(COMPLEX)
+        case MPIR_BFLOAT16:
+            bfloat16_sum(invec, inoutvec, len);
+            break;
+#ifndef MPIR_FLOAT16_CTYPE
+        case MPIR_FLOAT16:
+            f16_sum(invec, inoutvec, len);
+            break;
+#endif
         default:
             MPIR_Assert(0);
             break;
@@ -442,3 +453,75 @@ void MPIR_REPLACE(void *invec, void *inoutvec, MPI_Aint * Len, MPI_Datatype * ty
   fn_fail:
     goto fn_exit;
 }
+
+/* -- internal static routines -- */
+
+/* BFloat16 - software arithemetics
+ * TODO: add hardware support, e.g. via AVX512 intrinsics
+ */
+static float bfloat16_load(void *p)
+{
+    uint32_t u = ((uint32_t) (*(uint16_t *) p) << 16);
+    float v;
+    memcpy(&v, &u, sizeof(float));
+    return v;
+}
+
+static void bfloat16_store(void *p, float v)
+{
+    uint32_t u;
+    memcpy(&u, &v, sizeof(float));
+    if (u & 0x8000) {
+        /* round up */
+        *(uint16_t *) p = (u >> 16) + 1;
+    } else {
+        /* truncation */
+        *(uint16_t *) p = (u >> 16);
+    }
+
+}
+
+static void bfloat16_sum(void *invec, void *inoutvec, MPI_Aint len)
+{
+    for (MPI_Aint i = 0; i < len * 2; i += 2) {
+        float a = bfloat16_load((char *) inoutvec + i);
+        float b = bfloat16_load((char *) invec + i);
+        bfloat16_store((char *) inoutvec + i, a + b);
+    }
+}
+
+/* IEEE half-precision 16-bit float - software arithemetics
+ */
+static float f16_load(void *p)
+{
+    uint16_t a = *(uint16_t *) p;
+    /* expand exponent from 5 bit to 8 bit, fraction from 10 bit to 23 bit */
+    uint32_t u = ((uint32_t) ((a & 0x8000) | ((((a & 0x3c00) >> 10) + 0x70) << 7)) << 16) |
+        ((uint32_t) (a & 0x3ff) << 13);
+    float v;
+    memcpy(&v, &u, sizeof(float));
+    return v;
+}
+
+static void f16_store(void *p, float v)
+{
+    uint32_t u;
+    memcpy(&u, &v, sizeof(float));
+    /* shrink exponent from 8 bit to 5 bit, fraction from 23 bit to 10 bit */
+    uint16_t a = ((u & 0x80000000) >> 16) | ((((u & 0x7f800000) >> 23) - 0x70) << 10) |
+        ((u & 0x7fffff) >> 16);
+    if (u & 0x1000) {
+        /* round up */
+        a += 1;
+    }
+    *(uint16_t *) p = a;
+}
+
+static void f16_sum(void *invec, void *inoutvec, MPI_Aint len)
+{
+    for (MPI_Aint i = 0; i < len * 2; i += 2) {
+        float a = f16_load((char *) inoutvec + i);
+        float b = f16_load((char *) invec + i);
+        f16_store((char *) inoutvec + i, a + b);
+    }
+}
diff --git a/src/mpi/datatype/typerep/src/typerep_yaksa_init.c b/src/mpi/datatype/typerep/src/typerep_yaksa_init.c
index 05b81c4f633..694873c3822 100644
--- a/src/mpi/datatype/typerep/src/typerep_yaksa_init.c
+++ b/src/mpi/datatype/typerep/src/typerep_yaksa_init.c
@@ -30,6 +30,7 @@ yaksa_type_t MPII_Typerep_get_yaksa_type(MPI_Datatype type)
 
     switch (MPIR_DATATYPE_GET_RAW_INTERNAL(type)) {
         case MPIR_INT8:
+        case MPIR_FORTRAN_LOGICAL8:
             yaksa_type = YAKSA_TYPE__INT8_T;
             break;
 
@@ -43,6 +44,7 @@ yaksa_type_t MPII_Typerep_get_yaksa_type(MPI_Datatype type)
             break;
 
         case MPIR_INT16:
+        case MPIR_FORTRAN_LOGICAL16:
             yaksa_type = YAKSA_TYPE__INT16_T;
             break;
 
@@ -52,11 +54,13 @@ yaksa_type_t MPII_Typerep_get_yaksa_type(MPI_Datatype type)
 
         case MPIR_FIXED16:
         case MPIR_FLOAT16:
+        case MPIR_BFLOAT16:
         case MPIR_COMPLEX8:
             yaksa_type = TYPEREP_YAKSA_TYPE__FIXED2;
             break;
 
         case MPIR_INT32:
+        case MPIR_FORTRAN_LOGICAL32:
             yaksa_type = YAKSA_TYPE__INT32_T;
             break;
 
@@ -70,6 +74,7 @@ yaksa_type_t MPII_Typerep_get_yaksa_type(MPI_Datatype type)
             break;
 
         case MPIR_INT64:
+        case MPIR_FORTRAN_LOGICAL64:
             yaksa_type = YAKSA_TYPE__INT64_T;
             break;
 
@@ -111,6 +116,7 @@ yaksa_type_t MPII_Typerep_get_yaksa_type(MPI_Datatype type)
         case MPIR_INT128:
         case MPIR_UINT128:
         case MPIR_FLOAT128:
+        case MPIR_FORTRAN_LOGICAL128:
             yaksa_type = TYPEREP_YAKSA_TYPE__FIXED16;
             break;
 
diff --git a/src/mpi/datatype/typerep/src/typerep_yaksa_pack_external.c b/src/mpi/datatype/typerep/src/typerep_yaksa_pack_external.c
index b3e11ab2a69..3fc4f803995 100644
--- a/src/mpi/datatype/typerep/src/typerep_yaksa_pack_external.c
+++ b/src/mpi/datatype/typerep/src/typerep_yaksa_pack_external.c
@@ -75,8 +75,8 @@ typedef struct {
     } while (0)
 
 /* long double */
-#ifdef HAVE_FLOAT128
-#define EXTERNAL_LONG_DOUBLE_TYPE __float128
+#ifdef MPIR_FLOAT128_CTYPE
+#define EXTERNAL_LONG_DOUBLE_TYPE MPIR_FLOAT128_CTYPE
 #else
 #define EXTERNAL_LONG_DOUBLE_TYPE long double
 #endif
diff --git a/src/mpi/datatype/typeutil.c b/src/mpi/datatype/typeutil.c
index 18e6cf79276..b2ff8542b0c 100644
--- a/src/mpi/datatype/typeutil.c
+++ b/src/mpi/datatype/typeutil.c
@@ -98,6 +98,12 @@ struct MPIR_Datatype_builtin_entry MPIR_Internal_types[] = {
     type_name_entry(OFFSET,             MULTI),           /* 0x44 */
     type_name_entry(COUNT,              MULTI),           /* 0x45 */
     type_name_x(C_FLOAT16,              FLOATING_POINT),  /* 0x46 */
+    type_name_entry(LOGICAL1,           LOGICAL),         /* 0x47 */
+    type_name_entry(LOGICAL2,           LOGICAL),         /* 0x48 */
+    type_name_entry(LOGICAL4,           LOGICAL),         /* 0x49 */
+    type_name_entry(LOGICAL8,           LOGICAL),         /* 0x4a */
+    type_name_entry(LOGICAL16,          LOGICAL),         /* 0x4b */
+    type_name_x(BFLOAT16,               FLOATING_POINT),  /* 0x4c */
     /* *INDENT-ON* */
 };
 
@@ -158,34 +164,61 @@ int MPIR_Datatype_builtintype_alignment(MPI_Datatype type)
         case MPIR_FIXED8:
         case MPIR_INT8:
         case MPIR_UINT8:
-        case MPIR_FLOAT8:
-            return ALIGNOF_INT8_T;
+        case MPIR_COMPLEX8:
+        case MPIR_FORTRAN_LOGICAL8:
+            return MPIR_INT8_ALIGN;
         case MPIR_FIXED16:
         case MPIR_INT16:
         case MPIR_UINT16:
-        case MPIR_FLOAT16:
-            return ALIGNOF_INT16_T;
+        case MPIR_FORTRAN_LOGICAL16:
+            return MPIR_INT16_ALIGN;
         case MPIR_FIXED32:
         case MPIR_INT32:
         case MPIR_UINT32:
-            return ALIGNOF_INT32_T;
+        case MPIR_FORTRAN_LOGICAL32:
+            return MPIR_INT32_ALIGN;
         case MPIR_FIXED64:
         case MPIR_INT64:
         case MPIR_UINT64:
-            return ALIGNOF_INT64_T;
+        case MPIR_FORTRAN_LOGICAL64:
+            return MPIR_INT64_ALIGN;
+#ifdef MPIR_INT128_ALIGN
+        case MPIR_FIXED128:
+        case MPIR_INT128:
+        case MPIR_UINT128:
+        case MPIR_FORTRAN_LOGICAL128:
+            return MPIR_INT128_ALIGN;
+#endif
+#ifdef MPIR_FLOAT16_ALIGN
+        case MPIR_FLOAT16:
+        case MPIR_COMPLEX16:
+        case MPIR_BFLOAT16:
+            return MPIR_FLOAT16_ALIGN;
+#endif
         case MPIR_FLOAT32:
         case MPIR_COMPLEX32:
-            return ALIGNOF_FLOAT;
+            return MPIR_FLOAT32_ALIGN;
         case MPIR_FLOAT64:
         case MPIR_COMPLEX64:
-            return ALIGNOF_DOUBLE;
+            return MPIR_FLOAT64_ALIGN;
+#ifdef MPIR_FLOAT128_ALIGN
+        case MPIR_FLOAT128:
+        case MPIR_COMPLEX128:
+            return MPIR_FLOAT128_ALIGN;
+#endif
+#ifdef MPIR_ALT_FLOAT96_ALIGN
         case MPIR_ALT_FLOAT96:
-        case MPIR_ALT_FLOAT128:
         case MPIR_ALT_COMPLEX96:
+            return MPIR_ALT_FLOAT96_ALIGN;
+#endif
+#ifdef MPIR_ALT_FLOAT128_ALIGN
         case MPIR_ALT_COMPLEX128:
-            return ALIGNOF_LONG_DOUBLE;
+        case MPIR_ALT_FLOAT128:
+            return MPIR_ALT_FLOAT128_ALIGN;
+#endif
         default:
-            /* handle error cases? */
+            /* FIXME: throw error */
+            MPIR_Assert(0);
             return 1;
     }
 }
diff --git a/src/mpid/ch3/include/mpid_rma_shm.h b/src/mpid/ch3/include/mpid_rma_shm.h
index 8cfe54e90f2..eea0b6ba18e 100644
--- a/src/mpid/ch3/include/mpid_rma_shm.h
+++ b/src/mpid/ch3/include/mpid_rma_shm.h
@@ -44,184 +44,40 @@ static inline int shm_copy(const void *src, int scount, MPI_Datatype stype,
         /* The below list of datatypes is based on those specified in the MPI-3
          * standard on page 665. */
         switch (stype) {
-        case MPI_CHAR:
-            ASSIGN_COPY(src, dest, scount, char);
-
-        case MPI_SHORT:
-            ASSIGN_COPY(src, dest, scount, signed short int);
-
-        case MPI_INT:
-            ASSIGN_COPY(src, dest, scount, signed int);
-
-        case MPI_LONG:
-            ASSIGN_COPY(src, dest, scount, signed long int);
-
-        case MPI_LONG_LONG_INT:        /* covers MPI_LONG_LONG too */
-            ASSIGN_COPY(src, dest, scount, signed long long int);
-
-        case MPI_SIGNED_CHAR:
-            ASSIGN_COPY(src, dest, scount, signed char);
-
-        case MPI_UNSIGNED_CHAR:
-            ASSIGN_COPY(src, dest, scount, unsigned char);
-
-        case MPI_UNSIGNED_SHORT:
-            ASSIGN_COPY(src, dest, scount, unsigned short int);
-
-        case MPI_UNSIGNED:
-            ASSIGN_COPY(src, dest, scount, unsigned int);
-
-        case MPI_UNSIGNED_LONG:
-            ASSIGN_COPY(src, dest, scount, unsigned long int);
-
-        case MPI_UNSIGNED_LONG_LONG:
-            ASSIGN_COPY(src, dest, scount, unsigned long long int);
-
-        case MPI_FLOAT:
-            ASSIGN_COPY(src, dest, scount, float);
-
-        case MPI_DOUBLE:
-            ASSIGN_COPY(src, dest, scount, double);
-
-        case MPI_LONG_DOUBLE:
-            ASSIGN_COPY(src, dest, scount, long double);
-
-#if 0
-            /* FIXME: we need a configure check to define HAVE_WCHAR_T before
-             * this can be enabled */
-        case MPI_WCHAR:
-            ASSIGN_COPY(src, dest, scount, wchar_t);
+        case MPIR_INT8:
+        case MPIR_UINT8:
+            ASSIGN_COPY(src, dest, scount, MPIR_INT8_CTYPE);
+        case MPIR_INT16:
+        case MPIR_UINT16:
+            ASSIGN_COPY(src, dest, scount, MPIR_INT16_CTYPE);
+        case MPIR_INT32:
+        case MPIR_UINT32:
+            ASSIGN_COPY(src, dest, scount, MPIR_INT32_CTYPE);
+        case MPIR_INT64:
+        case MPIR_UINT64:
+            ASSIGN_COPY(src, dest, scount, MPIR_INT64_CTYPE);
+#ifdef MPIR_INT128_CTYPE
+        case MPIR_INT128:
+        case MPIR_UINT128:
+            ASSIGN_COPY(src, dest, scount, MPIR_INT128_CTYPE);
 #endif
-
-#if 0
-            /* FIXME: we need a configure check to define HAVE_C_BOOL before
-             * this can be enabled */
-        case MPI_C_BOOL:
-            ASSIGN_COPY(src, dest, scount, _Bool);
+#ifdef MPIR_FLOAT16_CTYPE
+        case MPIR_FLOAT16:
+            ASSIGN_COPY(src, dest, scount, MPIR_FLOAT16_CTYPE);
 #endif
-
-#if HAVE_INT8_T
-        case MPI_INT8_T:
-            ASSIGN_COPY(src, dest, scount, int8_t);
-#endif /* HAVE_INT8_T */
-
-#if HAVE_INT16_T
-        case MPI_INT16_T:
-            ASSIGN_COPY(src, dest, scount, int16_t);
-#endif /* HAVE_INT16_T */
-
-#if HAVE_INT32_T
-        case MPI_INT32_T:
-            ASSIGN_COPY(src, dest, scount, int32_t);
-#endif /* HAVE_INT32_T */
-
-#if HAVE_INT64_T
-        case MPI_INT64_T:
-            ASSIGN_COPY(src, dest, scount, int64_t);
-#endif /* HAVE_INT64_T */
-
-#if HAVE_UINT8_T
-        case MPI_UINT8_T:
-            ASSIGN_COPY(src, dest, scount, uint8_t);
-#endif /* HAVE_UINT8_T */
-
-#if HAVE_UINT16_T
-        case MPI_UINT16_T:
-            ASSIGN_COPY(src, dest, scount, uint16_t);
-#endif /* HAVE_UINT16_T */
-
-#if HAVE_UINT32_T
-        case MPI_UINT32_T:
-            ASSIGN_COPY(src, dest, scount, uint32_t);
-#endif /* HAVE_UINT32_T */
-
-#if HAVE_UINT64_T
-        case MPI_UINT64_T:
-            ASSIGN_COPY(src, dest, scount, uint64_t);
-#endif /* HAVE_UINT64_T */
-
-        case MPI_AINT:
-            ASSIGN_COPY(src, dest, scount, MPI_Aint);
-
-        case MPI_COUNT:
-            ASSIGN_COPY(src, dest, scount, MPI_Count);
-
-        case MPI_OFFSET:
-            ASSIGN_COPY(src, dest, scount, MPI_Offset);
-
-#if 0
-            /* FIXME: we need a configure check to define HAVE_C_COMPLEX before
-             * this can be enabled */
-        case MPI_C_COMPLEX:    /* covers MPI_C_FLOAT_COMPLEX as well */
-            ASSIGN_COPY(src, dest, scount, float _Complex);
-#endif
-
-#if 0
-            /* FIXME: we need a configure check to define HAVE_C_DOUPLE_COMPLEX
-             * before this can be enabled */
-        case MPI_C_DOUBLE_COMPLEX:
-            ASSIGN_COPY(src, dest, scount, double _Complex);
-#endif
-
-#if 0
-            /* FIXME: we need a configure check to define
-             * HAVE_C_LONG_DOUPLE_COMPLEX before this can be enabled */
-        case MPI_C_LONG_DOUBLE_COMPLEX:
-            ASSIGN_COPY(src, dest, scount, long double _Complex);
-#endif
-
-#if 0
-            /* Types that don't have a direct equivalent */
-        case MPI_BYTE:
-        case MPI_PACKED:
-#endif
-
-#if 0   /* Fortran types */
-        case MPI_INTEGER:
-        case MPI_REAL:
-        case MPI_DOUBLE_PRECISION:
-        case MPI_COMPLEX:
-        case MPI_LOGICAL:
-        case MPI_CHARACTER:
-#endif
-
-#if 0   /* C++ types */
-        case MPI_CXX_BOOL:
-        case MPI_CXX_FLOAT_COMPLEX:
-        case MPI_CXX_DOUBLE_COMPLEX:
-        case MPI_CXX_LONG_DOUBLE_COMPLEX:
-#endif
-
-#if 0   /* Optional Fortran types */
-        case MPI_DOUBLE_COMPLEX:
-        case MPI_INTEGER1:
-        case MPI_INTEGER2:
-        case MPI_INTEGER4:
-        case MPI_INTEGER8:
-        case MPI_INTEGER16:
-        case MPI_REAL2:
-        case MPI_REAL4:
-        case MPI_REAL8:
-        case MPI_REAL16:
-        case MPI_COMPLEX4:
-        case MPI_COMPLEX8:
-        case MPI_COMPLEX16:
-        case MPI_COMPLEX32:
-#endif
-
-#if 0   /* C datatypes for reduction functions */
-        case MPI_FLOAT_INT:
-        case MPI_DOUBLE_INT:
-        case MPI_LONG_INT:
-        case MPI_2INT:
-        case MPI_LONG_DOUBLE_INT:
+        case MPIR_FLOAT32:
+            ASSIGN_COPY(src, dest, scount, MPIR_FLOAT32_CTYPE);
+        case MPIR_FLOAT64:
+            ASSIGN_COPY(src, dest, scount, MPIR_FLOAT64_CTYPE);
+#ifdef MPIR_FLOAT128_CTYPE
+        case MPIR_FLOAT128:
+            ASSIGN_COPY(src, dest, scount, MPIR_FLOAT128_CTYPE);
 #endif
+        case MPIR_ALT_FLOAT96:
+        case MPIR_ALT_FLOAT128:
+            ASSIGN_COPY(src, dest, scount, long double);
 
-#if 0   /* Fortran datatypes for reduction functions */
-        case MPI_2REAL:
-        case MPI_2DOUBLE_PRECISION:
-        case MPI_2INTEGER:
-#endif
+        /* FIXME: native complex types */
 
         default:
             /* Just to make sure the switch statement is not empty */
diff --git a/test/mpi/configure.ac b/test/mpi/configure.ac
index 24db03e3a1a..abc870c71d3 100644
--- a/test/mpi/configure.ac
+++ b/test/mpi/configure.ac
@@ -723,6 +723,16 @@ AC_CACHE_CHECK([whether long long is supported],pac_cv_have_long_long,[
 if test "$pac_cv_have_long_long" = yes ; then
     AC_DEFINE(HAVE_LONG_LONG,1,[Define if compiler supports long long])
 fi
+
+#
+# Check for _Float16
+AC_MSG_CHECKING([whether _Float16 is supported])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[_Float16 a;])],[pac_cv_have_float16=yes],[pac_cv_have_float16=no])
+AC_MSG_RESULT($pac_cv_have_float16)
+if test "$pac_cv_have_float16" = "yes" ; then
+    AC_DEFINE(HAVE_FLOAT16,1,[Define if _Float16 is supported])
+fi
+
 #
 # Check for const and restrict (used in some of the performance tests)
 AC_C_CONST
diff --git a/test/mpi/impls/mpich/misc/Makefile.am b/test/mpi/impls/mpich/misc/Makefile.am
index 734450b17b3..90e1d82d879 100644
--- a/test/mpi/impls/mpich/misc/Makefile.am
+++ b/test/mpi/impls/mpich/misc/Makefile.am
@@ -12,4 +12,5 @@ EXTRA_DIST = testlist
 ## correctly
 noinst_PROGRAMS = \
 	type_iov \
+	type_float16 \
 	gpu_query
diff --git a/test/mpi/impls/mpich/misc/testlist b/test/mpi/impls/mpich/misc/testlist
index 6bf2bfaa991..3fb5ffc7f20 100644
--- a/test/mpi/impls/mpich/misc/testlist
+++ b/test/mpi/impls/mpich/misc/testlist
@@ -1 +1,2 @@
 gpu_query 1
+type_float16 4
diff --git a/test/mpi/impls/mpich/misc/type_float16.c b/test/mpi/impls/mpich/misc/type_float16.c
new file mode 100644
index 00000000000..f557dc4fdf9
--- /dev/null
+++ b/test/mpi/impls/mpich/misc/type_float16.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) by Argonne National Laboratory
+ *     See COPYRIGHT in top-level directory
+ */
+
+#include "mpitest.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#define N 4
+MPI_Comm comm = MPI_COMM_WORLD;
+
+int main(int argc, char *argv[])
+{
+    int errs = 0;
+    MTest_Init(&argc, &argv);
+
+    /* Test MPIX_BFLOAT16 */
+    unsigned short buf[N];
+    for (int i = 0; i < N; i++) {
+        buf[i] = 0x3f80;        /* 1.0 in bfloat16 */
+    }
+    MPI_Allreduce(MPI_IN_PLACE, buf, N, MPIX_BFLOAT16, MPI_SUM, comm);
+
+    MTestPrintfMsg(1, "Allreduce %d MPIX_BFLOAT16 (val=0.1), result: 0x%x, 0x%x, ...\n",
+                   N, buf[0], buf[1]);
+
+    /* Test MPIX_C_FLOAT16 */
+#ifdef HAVE_FLOAT16
+    _Float16 buf_f16[N];
+    for (int i = 0; i < N; i++) {
+        buf_f16[i] = 1.0;
+    }
+    MPI_Allreduce(MPI_IN_PLACE, buf_f16, N, MPIX_C_FLOAT16, MPI_SUM, comm);
+
+    MTestPrintfMsg(1, "Allreduce %d MPIX_C_FLOAT16 (val=0.1), result: %f, %f, ...\n",
+                   N, (float) buf_f16[0], (float) buf_f16[1]);
+#endif
+
+    MTest_Finalize(errs);
+
+    return MTestReturnValue(errs);
+}


Reviews:
user: login: dalcinl
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T18:57:45Z
user: login: dalcinl
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T18:58:56Z
user: login: hzhou
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T19:09:58Z
user: login: dalcinl
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T14:07:39Z
user: login: raffenet
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T16:43:33Z

Review comments:
diff_hunk: @@ -568,6 +576,7 @@ extern int * const MPI_WEIGHTS_EMPTY MPICH_API_PUBLIC;
 #define MPI_TYPECLASS_REAL 1
 #define MPI_TYPECLASS_INTEGER 2
 #define MPI_TYPECLASS_COMPLEX 3
+#define MPI_TYPECLASS_LOGICAL 4
path: src/include/mpi.h.in
user: login: dalcinl
body: Unfortunately, I think this one didn't make it for 5.0, but it may eventually land in 5.1. Should we keep it as it is or rename as `MPI_TYPECLASS_LOGICAL` ?
created_at: 2025-03-17T18:57:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -568,6 +576,7 @@ extern int * const MPI_WEIGHTS_EMPTY MPICH_API_PUBLIC;
 #define MPI_TYPECLASS_REAL 1
 #define MPI_TYPECLASS_INTEGER 2
 #define MPI_TYPECLASS_COMPLEX 3
+#define MPI_TYPECLASS_LOGICAL 4
path: src/include/mpi.h.in
user: login: dalcinl
body: BTW, `src/binding/abi/mpi_abi.h` currently lists `MPIX_TYPECLASS_LOGICAL`.
created_at: 2025-03-17T18:58:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -568,6 +576,7 @@ extern int * const MPI_WEIGHTS_EMPTY MPICH_API_PUBLIC;
 #define MPI_TYPECLASS_REAL 1
 #define MPI_TYPECLASS_INTEGER 2
 #define MPI_TYPECLASS_COMPLEX 3
+#define MPI_TYPECLASS_LOGICAL 4
path: src/include/mpi.h.in
user: login: hzhou
body: I'll remove it for now (updated). It is trivial enough that we can add it when Forum approves it. 
created_at: 2025-03-17T19:09:58Z
author_association: CONTRIBUTOR

PR comments:
user: login: hzhou
created_at: 2025-03-17T16:42:53Z
body: tag @dalcinl 
author_association: CONTRIBUTOR
user: login: hzhou
created_at: 2025-03-17T17:14:45Z
body: test:mpich/ch3/most
test:mpich/ch4/most
All ✔️ 
author_association: CONTRIBUTOR
user: login: dalcinl
created_at: 2025-03-18T11:06:16Z
body: Please do not merge this PR. There are multiple issues. The first two I found are fixed with  the tentative patches below. But that's not enough to get mpi4py tesuite happy. On top of these issues, the handling of Fortran datatypes when MPICH is configured with no Fortran are making my life miserable, forcing me to add workarounds here and there.
author_association: CONTRIBUTOR
user: login: dalcinl
created_at: 2025-03-18T11:16:34Z
body: ```diff
diff --git a/maint/gen_abi.py b/maint/gen_abi.py
index 30ca72182c..50e3e35cb1 100644
--- a/maint/gen_abi.py
+++ b/maint/gen_abi.py
@@ -60,8 +60,6 @@ def dump_mpi_abi_internal_h(mpi_abi_internal_h):
                 elif T == "MPI_Datatype":
                     idx = int(val, 0) & G.datatype_mask
                     G.abi_datatypes[idx] = name
-                    if re.match(r'MPI_LOGICAL\d+', name):
-                        G.abi_datatypes[idx] = "MPI_DATATYPE_NULL"
                 elif T == "MPI_Op":
                     idx = int(val, 0) & G.op_mask
                     G.abi_ops[idx] = name
```
author_association: CONTRIBUTOR
user: login: dalcinl
created_at: 2025-03-18T11:17:05Z
body: 
```diff
diff --git a/src/mpi/datatype/typeutil.c b/src/mpi/datatype/typeutil.c
index d4a316b826..7fa8b0c23d 100644
--- a/src/mpi/datatype/typeutil.c
+++ b/src/mpi/datatype/typeutil.c
@@ -165,27 +165,41 @@ int MPIR_Datatype_builtintype_alignment(MPI_Datatype type)
         case MPIR_INT8:
         case MPIR_UINT8:
         case MPIR_FLOAT8:
+        case MPIR_COMPLEX8:
+        case MPIR_FORTRAN_LOGICAL8:
             return ALIGNOF_INT8_T;
         case MPIR_FIXED16:
         case MPIR_INT16:
         case MPIR_UINT16:
         case MPIR_FLOAT16:
+        case MPIR_COMPLEX16:
         case MPIR_BFLOAT16:
+        case MPIR_FORTRAN_LOGICAL16:
             return ALIGNOF_INT16_T;
         case MPIR_FIXED32:
         case MPIR_INT32:
         case MPIR_UINT32:
+        case MPIR_FORTRAN_LOGICAL32:
             return ALIGNOF_INT32_T;
         case MPIR_FIXED64:
         case MPIR_INT64:
         case MPIR_UINT64:
+        case MPIR_FORTRAN_LOGICAL64:
             return ALIGNOF_INT64_T;
+        case MPIR_FIXED128:
+        case MPIR_INT128:
+        case MPIR_UINT128:
+        case MPIR_FORTRAN_LOGICAL128:
+            return MAX_ALIGNMENT; /* ALIGNOF_INT128_T */
         case MPIR_FLOAT32:
         case MPIR_COMPLEX32:
             return ALIGNOF_FLOAT;
         case MPIR_FLOAT64:
         case MPIR_COMPLEX64:
             return ALIGNOF_DOUBLE;
+        case MPIR_FLOAT128:
+        case MPIR_COMPLEX128:
+            return MAX_ALIGNMENT; /* ALIGNOF_FLOAT128_T */
         case MPIR_ALT_FLOAT96:
         case MPIR_ALT_FLOAT128:
         case MPIR_ALT_COMPLEX96:
```
author_association: CONTRIBUTOR
user: login: dalcinl
created_at: 2025-03-18T12:01:50Z
body: @hzhou My second patch makes me wonder whether `MPIR_FORTRAN_LOGICAL<N>` is really required. Maybe then can just be mapped to `MPIR_INT<N>`, just like Fortran `INTEGER|INTEGER<N>` are?
author_association: CONTRIBUTOR
user: login: hzhou
created_at: 2025-03-18T12:14:19Z
body: The reduction op need distinguish Fortran logical from integer because it may not behave the same as c bool.
author_association: CONTRIBUTOR
user: login: dalcinl
created_at: 2025-03-18T19:33:39Z
body: @hzhou Did you have a change of looking at my patches? The use `MAX_ALIGNMENT` is a bit debatable, but a better patch would require to add support in configure for `__int128`, which in turn will provide support for both `MPI_LOGICAL16` and `MPI_INTEGER16`.
author_association: CONTRIBUTOR
user: login: hzhou
created_at: 2025-03-19T04:17:32Z
body: test:mpich/ch3/most
test:mpich/ch4/most
test:mpich/custom
config: mpi-abi
author_association: CONTRIBUTOR
user: login: dalcinl
created_at: 2025-03-19T07:17:00Z
body: @hzhou Could you please update `MPI_VERSION/SUBVERSION` in the non-ABI `mpi.h`, even in done in another PR that gets merged first?
author_association: CONTRIBUTOR
user: login: dalcinl
created_at: 2025-03-19T07:36:56Z
body: @hzou Things are off. I tried a build WITHOUT Fortran, and things like MPI_REAL and MPI_INTEGER error on `MPI_Type_size_c`, but things like `MPI_REAL4` and `MPI_INTEGER4` succeed. Is that the intended behavior?
author_association: CONTRIBUTOR
user: login: hzhou
created_at: 2025-03-19T14:11:05Z
body: > @hzou Things are off. I tried a build WITHOUT Fortran, and things like MPI_REAL and MPI_INTEGER error on `MPI_Type_size_c`, but things like `MPI_REAL4` and `MPI_INTEGER4` succeed. Is that the intended behavior?

It is because those are fixed-width types that we can directly map to internal types without configure. We can make them unavailable as well.


author_association: CONTRIBUTOR
user: login: dalcinl
created_at: 2025-03-19T14:44:12Z
body: > It is because those are fixed-width types that we can directly map to internal types without configure. We can make them unavailable as well.

Well, that would be OK. Moreover, I would rather make everything available mapping INTEGER to INT32, REAL to FLOAT32, and so on, as per the usual default mapping of Fortran compilers. This would IMHO simplify things a lot, as Fortran datatypes would always be defined by default, even if a MPI implementations is built without a Fortran compiler. Jeff rejected this idea in private communication. Even if not mandated by MPI, MPICH could make this move, and eventually Open MPI will likely follow. In other words, MPICH can set internally the (default, initial) Fortran ABI, even if no Fortran compiler is available at compile time, using the very reasonable default mapping.

Give me a little more time to test. I believe there are other things that are off.
author_association: CONTRIBUTOR
user: login: hzhou
created_at: 2025-03-19T15:08:46Z
body: > > It is because those are fixed-width types that we can directly map to internal types without configure. We can make them unavailable as well.
> 
> Well, that would be OK. Moreover, I would rather make everything available mapping INTEGER to INT32, REAL to FLOAT32, and so on, as per the usual default mapping of Fortran compilers. This would IMHO simplify things a lot, as Fortran datatypes would always be defined by default, even if a MPI implementations is built without a Fortran compiler. Jeff rejected this idea in private communication. Even if not mandated by MPI, MPICH could make this move, and eventually Open MPI will likely follow. In other words, MPICH can set internally the (default, initial) Fortran ABI, even if no Fortran compiler is available at compile time, using the very reasonable default mapping.
> 
> Give me a little more time to test. I believe there are other things that are off.

It goes back to the root question of all this: Can an Fortran integer be different from a C int and so on? If the answer is no, then we won't have this fortran inter-op APIs and discussions to start with. If it can differ, then you can't have a *correct* default. If you let code to work without *correct* value, then the code is wrong. It only simplifies things when the default are correct (in common cases, i.e. by chance). I think it is a principle that we put correctness above simplifying things.
author_association: CONTRIBUTOR
user: login: hzhou
created_at: 2025-03-19T15:52:11Z
body: > > @hzou Things are off. I tried a build WITHOUT Fortran, and things like MPI_REAL and MPI_INTEGER error on `MPI_Type_size_c`, but things like `MPI_REAL4` and `MPI_INTEGER4` succeed. Is that the intended behavior?
> 
> It is because those are fixed-width types that we can directly map to internal types without configure. We can make them unavailable as well.

I pushed commit to make all Fortran trypes unavailable if Fortran binding is disabled.
author_association: CONTRIBUTOR
user: login: dalcinl
created_at: 2025-03-20T08:13:29Z
body: @hzhou There is still one issue I cannot figure out where the problem is

```python
>>> from mpi4py import MPI
>>> MPI.LOGICAL.Dup().Get_extent()
(0, 0)
```
The expected output of the duped datatype `(lb, extent) ` is not `(0, 4)`.
The same happens for all the `LOGICAL<N>` datatypes. My guess is that there is still something off in some of the internal routines that compute alignments. This is a CH4 build, have not tried CH3.

author_association: CONTRIBUTOR
user: login: dalcinl
created_at: 2025-03-20T08:39:25Z
body: Found the issue, `MPII_Typerep_get_yaksa_type` was not handling the Fortran logical types. I guess they must be handled as FIXED, but I'm not sure. In any case the patch below is a good start, as it passes mpi4py datatype tests.

```diff
iff --git a/src/mpi/datatype/typerep/src/typerep_yaksa_init.c b/src/mpi/datatype/typerep/src/typerep_yaksa_init.c
index a6257d2cf2..3697957d5f 100644
--- a/src/mpi/datatype/typerep/src/typerep_yaksa_init.c
+++ b/src/mpi/datatype/typerep/src/typerep_yaksa_init.c
@@ -39,6 +39,7 @@ yaksa_type_t MPII_Typerep_get_yaksa_type(MPI_Datatype type)
 
         case MPIR_FIXED8:
         case MPIR_FLOAT8:
+        case MPIR_FORTRAN_LOGICAL8:
             yaksa_type = TYPEREP_YAKSA_TYPE__FIXED1;
             break;
 
@@ -54,6 +55,7 @@ yaksa_type_t MPII_Typerep_get_yaksa_type(MPI_Datatype type)
         case MPIR_FLOAT16:
         case MPIR_BFLOAT16:
         case MPIR_COMPLEX8:
+        case MPIR_FORTRAN_LOGICAL16:
             yaksa_type = TYPEREP_YAKSA_TYPE__FIXED2;
             break;
 
@@ -67,6 +69,7 @@ yaksa_type_t MPII_Typerep_get_yaksa_type(MPI_Datatype type)
 
         case MPIR_FIXED32:
         case MPIR_COMPLEX16:
+        case MPIR_FORTRAN_LOGICAL32:
             yaksa_type = TYPEREP_YAKSA_TYPE__FIXED4;
             break;
 
@@ -79,6 +82,7 @@ yaksa_type_t MPII_Typerep_get_yaksa_type(MPI_Datatype type)
             break;
 
         case MPIR_FIXED64:
+        case MPIR_FORTRAN_LOGICAL64:
             yaksa_type = TYPEREP_YAKSA_TYPE__FIXED8;
             break;
 
@@ -112,6 +116,7 @@ yaksa_type_t MPII_Typerep_get_yaksa_type(MPI_Datatype type)
         case MPIR_INT128:
         case MPIR_UINT128:
         case MPIR_FLOAT128:
+        case MPIR_FORTRAN_LOGICAL128:
             yaksa_type = TYPEREP_YAKSA_TYPE__FIXED16;
             break;
 
```
author_association: CONTRIBUTOR
user: login: hzhou
created_at: 2025-03-20T15:29:45Z
body: Thanks for finding the issue. I added a commit to add the missing cases for logicals. We can treat logicals as ints in yaksa.
author_association: CONTRIBUTOR
user: login: dalcinl
created_at: 2025-03-20T16:47:19Z
body: Any chance you guys would consider addressing #7350 and rebase this PR afterwards?
author_association: CONTRIBUTOR
user: login: dalcinl
created_at: 2025-03-21T13:02:50Z
body: All mpi4py tests pass, including datatype tests for FLOAT16/BFLOAT16 mpi4py/mpi4py#626
stdabi: https://github.com/mpi4py/mpi4py-testing/actions/runs/13987600953
mpich: https://github.com/mpi4py/mpi4py-testing/actions/runs/13987594630

author_association: CONTRIBUTOR
user: login: dalcinl
created_at: 2025-03-24T10:32:44Z
body: @raffenet Any chance you can give some priority to the review/approval of this PR?
author_association: CONTRIBUTOR