/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
 * terms governing use, modification, and redistribution, is contained in    *
 * the LICENSE file, which can be found at the root of the source code       *
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
 * If you do not have access to either file, you may request a copy from     *
 * help@hdfgroup.org.                                                        *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#ifndef H5Tconv_macros_H
#define H5Tconv_macros_H

#include "H5private.h"  
#include "H5Eprivate.h" 
#include "H5Tprivate.h" 

#ifdef H5T_DEBUG

typedef struct H5T_conv_hw_t {
    size_t s_aligned; 
    size_t d_aligned; 
} H5T_conv_hw_t;

#endif

#define H5T_CONV_xX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
        *(D) = (DT)(*(S));                                                                                   \
    }
#define H5T_CONV_xX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    {                                                                                                        \
        *(D) = (DT)(*(S));                                                                                   \
    }

#define H5T_CONV_Xx_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
        H5T_conv_ret_t except_ret;                                                                           \
        if (*(S) > (ST)(D_MAX)) {                                                                            \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id,                              \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = (DT)(D_MAX);                                                                          \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else if (*(S) < (ST)(D_MIN)) {                                                                       \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id,                             \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = (DT)(D_MIN);                                                                          \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else                                                                                                 \
            *(D) = (DT)(*(S));                                                                               \
    }
#define H5T_CONV_Xx_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    {                                                                                                        \
        if (*(S) > (ST)(D_MAX)) {                                                                            \
            *(D) = (DT)(D_MAX);                                                                              \
        }                                                                                                    \
        else if (*(S) < (ST)(D_MIN)) {                                                                       \
            *(D) = (DT)(D_MIN);                                                                              \
        }                                                                                                    \
        else                                                                                                 \
            *(D) = (DT)(*(S));                                                                               \
    }

#define H5T_CONV_Ux_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
        if (*(S) > (ST)(D_MAX)) {                                                                            \
            H5T_conv_ret_t except_ret;                                                                       \
                                                                                                             \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id,                              \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = (DT)(D_MAX);                                                                          \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else                                                                                                 \
            *(D) = (DT)(*(S));                                                                               \
    }
#define H5T_CONV_Ux_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    {                                                                                                        \
        if (*(S) > (ST)(D_MAX)) {                                                                            \
            *(D) = (DT)(D_MAX);                                                                              \
        }                                                                                                    \
        else                                                                                                 \
            *(D) = (DT)(*(S));                                                                               \
    }

#define H5T_CONV_sS(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) <= sizeof(DT));                                                          \
        H5T_CONV(H5T_CONV_xX, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#define H5T_CONV_sU_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
        if (*(S) < 0) {                                                                                      \
            H5T_conv_ret_t except_ret;                                                                       \
                                                                                                             \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id,                             \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = 0;                                                                                    \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else                                                                                                 \
            *(D) = (DT)(*(S));                                                                               \
    }
#define H5T_CONV_sU_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    {                                                                                                        \
        if (*(S) < 0)                                                                                        \
            *(D) = 0;                                                                                        \
        else                                                                                                 \
            *(D) = (DT)(*(S));                                                                               \
    }

#define H5T_CONV_sU(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) <= sizeof(DT));                                                          \
        H5T_CONV(H5T_CONV_sU, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#define H5T_CONV_uS_UCHAR_SHORT 0
#define H5T_CONV_uS_UCHAR_INT   0
#define H5T_CONV_uS_UCHAR_LONG  0
#define H5T_CONV_uS_UCHAR_LLONG 0
#if H5_SIZEOF_SHORT == H5_SIZEOF_INT
#define H5T_CONV_uS_USHORT_INT 1
#else
#define H5T_CONV_uS_USHORT_INT 0
#endif
#define H5T_CONV_uS_USHORT_LONG  0
#define H5T_CONV_uS_USHORT_LLONG 0
#if H5_SIZEOF_INT == H5_SIZEOF_LONG
#define H5T_CONV_uS_UINT_LONG 1
#else
#define H5T_CONV_uS_UINT_LONG 0
#endif
#define H5T_CONV_uS_UINT_LLONG 0
#if H5_SIZEOF_LONG == H5_SIZEOF_LONG_LONG
#define H5T_CONV_uS_ULONG_LLONG 1
#else
#define H5T_CONV_uS_ULONG_LLONG 0
#endif

#define H5T_CONV_uS_EVAL_TYPES(STYPE, DTYPE) H5_GLUE4(H5T_CONV_uS_, STYPE, _, DTYPE)

#define H5T_CONV_uS_CORE_1(S, D, ST, DT, D_MIN, D_MAX)                                                       \
    if (*(S) > (DT)(D_MAX)) {                                                                                \
        H5T_conv_ret_t except_ret;                                                                           \
                                                                                                             \
                                                            \
        H5_BEFORE_USER_CB(FAIL)                                                                              \
            {                                                                                                \
                except_ret = (conv_ctx->u.conv.cb_struct.func)(                                              \
                    H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, S, \
                    D, conv_ctx->u.conv.cb_struct.user_data);                                                \
            }                                                                                                \
        H5_AFTER_USER_CB(FAIL)                                                                               \
        if (except_ret == H5T_CONV_UNHANDLED)                                                                \
                                                \
            *(D) = (DT)(D_MAX);                                                                              \
        else if (except_ret == H5T_CONV_ABORT)                                                               \
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");           \
                                       \
    }                                                                                                        \
    else                                                                                                     \
        *(D) = (DT)(*(S));

#define H5T_CONV_uS_CORE_0(S, D, ST, DT, D_MIN, D_MAX) *(D) = (DT)(*(S));

#define H5T_CONV_uS_CORE_I(over, S, D, ST, DT, D_MIN, D_MAX)                                                 \
    H5_GLUE(H5T_CONV_uS_CORE_, over)(S, D, ST, DT, D_MIN, D_MAX)

#define H5T_CONV_uS_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
        H5T_CONV_uS_CORE_I(H5T_CONV_uS_EVAL_TYPES(STYPE, DTYPE), S, D, ST, DT, D_MIN, D_MAX)                 \
    }

#define H5T_CONV_uS_NOEX_CORE_1(S, D, ST, DT, D_MIN, D_MAX)                                                  \
    if (*(S) > (DT)(D_MAX))                                                                                  \
        *(D) = (D_MAX);                                                                                      \
    else                                                                                                     \
        *(D) = (DT)(*(S));

#define H5T_CONV_uS_NOEX_CORE_0(S, D, ST, DT, D_MIN, D_MAX) *(D) = (DT)(*(S));

#define H5T_CONV_uS_NOEX_CORE_I(over, S, D, ST, DT, D_MIN, D_MAX)                                            \
    H5_GLUE(H5T_CONV_uS_NOEX_CORE_, over)(S, D, ST, DT, D_MIN, D_MAX)

#define H5T_CONV_uS_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    {                                                                                                        \
        H5T_CONV_uS_NOEX_CORE_I(H5T_CONV_uS_EVAL_TYPES(STYPE, DTYPE), S, D, ST, DT, D_MIN, D_MAX)            \
    }

#define H5T_CONV_uS(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) <= sizeof(DT));                                                          \
        H5T_CONV(H5T_CONV_uS, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#define H5T_CONV_uU(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) <= sizeof(DT));                                                          \
        H5T_CONV(H5T_CONV_xX, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#define H5T_CONV_Ss(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) >= sizeof(DT));                                                          \
        H5T_CONV(H5T_CONV_Xx, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#define H5T_CONV_Su_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
        H5T_conv_ret_t except_ret;                                                                           \
        if (*(S) < 0) {                                                                                      \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id,                             \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = 0;                                                                                    \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else if (sizeof(ST) > sizeof(DT) && *(S) > (ST)(D_MAX)) {                                            \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id,                              \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = (DT)(D_MAX);                                                                          \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else                                                                                                 \
            *(D) = (DT)(*(S));                                                                               \
    }
#define H5T_CONV_Su_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    {                                                                                                        \
        if (*(S) < 0)                                                                                        \
            *(D) = 0;                                                                                        \
        else if (sizeof(ST) > sizeof(DT) && *(S) > (ST)(D_MAX))                                              \
            *(D) = (DT)(D_MAX);                                                                              \
        else                                                                                                 \
            *(D) = (DT)(*(S));                                                                               \
    }

#define H5T_CONV_Su(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) >= sizeof(DT));                                                          \
        H5T_CONV(H5T_CONV_Su, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#define H5T_CONV_Us(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) >= sizeof(DT));                                                          \
        H5T_CONV(H5T_CONV_Ux, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#define H5T_CONV_Uu(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) >= sizeof(DT));                                                          \
        H5T_CONV(H5T_CONV_Ux, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#define H5T_CONV_su_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
                                            \
        if (*(S) < 0) {                                                                                      \
            H5T_conv_ret_t except_ret;                                                                       \
                                                                                                             \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id,                             \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = 0;                                                                                    \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else                                                                                                 \
            *(D) = (DT)(*(S));                                                                               \
    }
#define H5T_CONV_su_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    {                                                                                                        \
                                            \
        if (*(S) < 0)                                                                                        \
            *(D) = 0;                                                                                        \
        else                                                                                                 \
            *(D) = (DT)(*(S));                                                                               \
    }

#define H5T_CONV_su(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) == sizeof(DT));                                                          \
        H5T_CONV(H5T_CONV_su, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#define H5T_CONV_us_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
                                            \
        if (*(S) > (ST)(D_MAX)) {                                                                            \
            H5T_conv_ret_t except_ret;                                                                       \
                                                                                                             \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id,                              \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = (DT)(D_MAX);                                                                          \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else                                                                                                 \
            *(D) = (DT)(*(S));                                                                               \
    }
#define H5T_CONV_us_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    {                                                                                                        \
                                            \
        if (*(S) > (ST)(D_MAX))                                                                              \
            *(D) = (DT)(D_MAX);                                                                              \
        else                                                                                                 \
            *(D) = (DT)(*(S));                                                                               \
    }

#define H5T_CONV_us(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) == sizeof(DT));                                                          \
        H5T_CONV(H5T_CONV_us, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#define H5T_CONV_fF(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) <= sizeof(DT));                                                          \
        H5T_CONV(H5T_CONV_xX, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#define H5T_CONV_Ff_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
        H5T_conv_ret_t except_ret;                                                                           \
        if (*(S) > (ST)(D_MAX)) {                                                                            \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id,                              \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _POS_INF_g);                                             \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else if (*(S) < (ST)(D_MIN)) {                                                                       \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id,                             \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _NEG_INF_g);                                             \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else                                                                                                 \
            *(D) = (DT)(*(S));                                                                               \
    }
#define H5T_CONV_Ff_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    {                                                                                                        \
        if (*(S) > (ST)(D_MAX))                                                                              \
            *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _POS_INF_g);                                                 \
        else if (*(S) < (ST)(D_MIN))                                                                         \
            *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _NEG_INF_g);                                                 \
        else                                                                                                 \
            *(D) = (DT)(*(S));                                                                               \
    }

#define H5T_CONV_Ff(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) >= sizeof(DT));                                                          \
        H5T_CONV(H5T_CONV_Ff, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#define H5T_HI_LO_BIT_SET(TYP, V, LO, HI)                                                                    \
    {                                                                                                        \
        unsigned      count;                                                                                 \
        unsigned char p;                                                                                     \
        unsigned      u;                                                                                     \
                                                                                                             \
        count = 0;                                                                                           \
        for (u = 0; u < sizeof(TYP); u++) {                                                                  \
            count = (((unsigned)sizeof(TYP) - 1) - u) * 8;                                                   \
            p     = (unsigned char)((V) >> count);                                                           \
            if (p > 0) {                                                                                     \
                if (p & 0x80)                                                                                \
                    count += 7;                                                                              \
                else if (p & 0x40)                                                                           \
                    count += 6;                                                                              \
                else if (p & 0x20)                                                                           \
                    count += 5;                                                                              \
                else if (p & 0x10)                                                                           \
                    count += 4;                                                                              \
                else if (p & 0x08)                                                                           \
                    count += 3;                                                                              \
                else if (p & 0x04)                                                                           \
                    count += 2;                                                                              \
                else if (p & 0x02)                                                                           \
                    count += 1;                                                                              \
                break;                                                                                       \
            }                                                                                    \
        }                                                                                       \
                                                                                                             \
        HI = count;                                                                                          \
                                                                                                             \
        count = 0;                                                                                           \
        for (u = 0; u < sizeof(TYP); u++) {                                                                  \
            p = (unsigned char)((V) >> (u * 8));                                                             \
            if (p > 0) {                                                                                     \
                count = u * 8;                                                                               \
                                                                                                             \
                if (p & 0x01)                                                                                \
                    ;                                                                                        \
                else if (p & 0x02)                                                                           \
                    count += 1;                                                                              \
                else if (p & 0x04)                                                                           \
                    count += 2;                                                                              \
                else if (p & 0x08)                                                                           \
                    count += 3;                                                                              \
                else if (p & 0x10)                                                                           \
                    count += 4;                                                                              \
                else if (p & 0x20)                                                                           \
                    count += 5;                                                                              \
                else if (p & 0x40)                                                                           \
                    count += 6;                                                                              \
                else if (p & 0x80)                                                                           \
                    count += 7;                                                                              \
                break;                                                                                       \
            }                                                                                    \
        }                                                                                       \
                                                                                                             \
        LO = count;                                                                                          \
    }

#define H5T_CONV_xF_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
        if (sprec > dprec) {                                                                                 \
            unsigned low_bit_pos, high_bit_pos;                                                              \
                                                                                                             \
                                                                   \
            H5T_HI_LO_BIT_SET(ST, *(S), low_bit_pos, high_bit_pos)                                           \
                                                                                                             \
                                          \
            if ((high_bit_pos - low_bit_pos) >= dprec) {                                                     \
                H5T_conv_ret_t except_ret;                                                                   \
                                                                                                             \
                                                            \
                H5_BEFORE_USER_CB(FAIL)                                                                      \
                    {                                                                                        \
                        except_ret = (conv_ctx->u.conv.cb_struct.func)(                                      \
                            H5T_CONV_EXCEPT_PRECISION, conv_ctx->u.conv.src_type_id,                         \
                            conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);       \
                    }                                                                                        \
                H5_AFTER_USER_CB(FAIL)                                                                       \
                if (except_ret == H5T_CONV_UNHANDLED)                                                        \
                                                 \
                    *(D) = (DT)(*(S));                                                                       \
                else if (except_ret == H5T_CONV_ABORT)                                                       \
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");   \
                                        \
            }                                                                                                \
            else                                                                                             \
                *(D) = (DT)(*(S));                                                                           \
        }                                                                                                    \
        else                                                                                                 \
            *(D) = (DT)(*(S));                                                                               \
    }
#define H5T_CONV_xF_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    {                                                                                                        \
        *(D) = (DT)(*(S));                                                                                   \
    }

#define H5T_CONV_xF(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        H5T_CONV(H5T_CONV_xF, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, Y)                                         \
    } while (0)

#define H5T_CONV_Fx_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
        H5T_conv_ret_t except_ret;                                                                           \
        if (*(S) > (ST)(D_MAX) || (sprec < dprec && *(S) == (ST)(D_MAX))) {                                  \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id,                              \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = (DT)(D_MAX);                                                                          \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else if (*(S) < (ST)(D_MIN)) {                                                                       \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id,                             \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = (DT)(D_MIN);                                                                          \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else if (*(S) != (ST)((DT)(*(S)))) {                                                                 \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_TRUNCATE, conv_ctx->u.conv.src_type_id,                              \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = (DT)(*(S));                                                                           \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else                                                                                                 \
            *(D) = (DT)(*(S));                                                                               \
    }
#define H5T_CONV_Fx_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    {                                                                                                        \
        if (*(S) > (ST)(D_MAX))                                                                              \
            *(D) = (DT)(D_MAX);                                                                              \
        else if (*(S) < (ST)(D_MIN))                                                                         \
            *(D) = (DT)(D_MIN);                                                                              \
        else                                                                                                 \
            *(D) = (DT)(*(S));                                                                               \
    }

#define H5T_CONV_Fx(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        H5T_CONV(H5T_CONV_Fx, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, Y)                                         \
    } while (0)

#define H5T_CONV_fX(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) <= sizeof(DT));                                                          \
        H5T_CONV(H5T_CONV_xX, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#define H5T_CONV_Xf_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
        H5T_conv_ret_t except_ret;                                                                           \
        if (*(S) > (ST)(D_MAX) || (sprec < dprec && *(S) == (ST)(D_MAX))) {                                  \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id,                              \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _POS_INF_g);                                             \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else if (*(S) < (ST)(D_MIN)) {                                                                       \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id,                             \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _NEG_INF_g);                                             \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else if (sprec > dprec) {                                                                            \
            unsigned low_bit_pos, high_bit_pos;                                                              \
                                                                                                             \
                                                                   \
            H5T_HI_LO_BIT_SET(ST, *(S), low_bit_pos, high_bit_pos)                                           \
                                                                                                             \
                                          \
            if ((high_bit_pos - low_bit_pos) >= dprec) {                                                     \
                                                            \
                H5_BEFORE_USER_CB(FAIL)                                                                      \
                    {                                                                                        \
                        except_ret = (conv_ctx->u.conv.cb_struct.func)(                                      \
                            H5T_CONV_EXCEPT_PRECISION, conv_ctx->u.conv.src_type_id,                         \
                            conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);       \
                    }                                                                                        \
                H5_AFTER_USER_CB(FAIL)                                                                       \
                if (except_ret == H5T_CONV_UNHANDLED)                                                        \
                                                 \
                    *(D) = (DT)(*(S));                                                                       \
                else if (except_ret == H5T_CONV_ABORT)                                                       \
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");   \
                                        \
            }                                                                                                \
            else                                                                                             \
                *(D) = (DT)(*(S));                                                                           \
        }                                                                                                    \
        else                                                                                                 \
            *(D) = (DT)(*(S));                                                                               \
    }
#define H5T_CONV_Xf_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    {                                                                                                        \
        if (*(S) > (ST)(D_MAX))                                                                              \
            *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _POS_INF_g);                                                 \
        else {                                                                                               \
            intmax_t s_cast = (intmax_t)(*(S));                                                              \
            intmax_t d_cast = (intmax_t)(D_MAX);                                                             \
                                                                                                             \
                                                                                                          \
            if (s_cast != INTMAX_MIN)                                                                        \
                s_cast = imaxabs(s_cast);                                                                    \
            else {                                                                                           \
                                                                                                          \
                s_cast = INTMAX_MAX;                                                                         \
                d_cast -= 1;                                                                                 \
            }                                                                                                \
                                                                                                             \
            if (s_cast > d_cast)                                                                             \
                *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _NEG_INF_g);                                             \
            else                                                                                             \
                *(D) = (DT)(*(S));                                                                           \
        }                                                                                                    \
    }

#define H5T_CONV_Xf(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) >= sizeof(DT));                                                          \
        H5T_CONV(H5T_CONV_Xf, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, Y)                                         \
    } while (0)

#ifdef H5_HAVE_COMPLEX_NUMBERS

#define H5T_CONV_FLOAT_COMPLEX_REALVAL(S)   float sr_val = crealf(*(S));
#define H5T_CONV_DOUBLE_COMPLEX_REALVAL(S)  double sr_val = creal(*(S));
#define H5T_CONV_LDOUBLE_COMPLEX_REALVAL(S) long double sr_val = creall(*(S));
#define H5T_CONV_FLOAT_COMPLEX_IMAGVAL(S)   float si_val = cimagf(*(S));
#define H5T_CONV_DOUBLE_COMPLEX_IMAGVAL(S)  double si_val = cimag(*(S));
#define H5T_CONV_LDOUBLE_COMPLEX_IMAGVAL(S) long double si_val = cimagl(*(S));

#ifndef H5_HAVE_C99_COMPLEX_NUMBERS
#define H5T_CONV_CAST_TO_FLOAT_COMPLEX(S_REAL, S_IMAG, D, DT)                                                \
    {                                                                                                        \
        *(D) = H5_CMPLXF(S_REAL, S_IMAG);                                                                    \
    }
#define H5T_CONV_CAST_TO_DOUBLE_COMPLEX(S_REAL, S_IMAG, D, DT)                                               \
    {                                                                                                        \
        *(D) = H5_CMPLX(S_REAL, S_IMAG);                                                                     \
    }
#define H5T_CONV_CAST_TO_LDOUBLE_COMPLEX(S_REAL, S_IMAG, D, DT)                                              \
    {                                                                                                        \
        *(D) = H5_CMPLXL(S_REAL, S_IMAG);                                                                    \
    }

#define H5T_CONV_CAST_zZ(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT)                                         \
    {                                                                                                        \
        H5T_CONV_##STYPE##_REALVAL(S);                            \
        H5T_CONV_##STYPE##_IMAGVAL(S);                       \
        H5T_CONV_CAST_TO_##DTYPE(sr_val, si_val, D, DT)                                                      \
    }
#define H5T_CONV_CAST_Zz(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT)                                         \
    {                                                                                                        \
        H5T_CONV_CAST_TO_##DTYPE(S_REAL, S_IMAG, D, DT)                                                      \
    }
#define H5T_CONV_CAST_zF(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT)                                         \
    {                                                                                                        \
        H5T_CONV_##STYPE##_REALVAL(S);                            \
        *(D) = (DT)(sr_val);                                                                                 \
    }
#define H5T_CONV_CAST_zf(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT)                                         \
    {                                                                                                        \
        H5T_CONV_##STYPE##_REALVAL(S);                            \
        *(D) = (DT)(sr_val);                                                                                 \
    }
#define H5T_CONV_CAST_zX(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT)                                         \
    {                                                                                                        \
        H5T_CONV_##STYPE##_REALVAL(S);                            \
        *(D) = (DT)(sr_val);                                                                                 \
    }
#define H5T_CONV_CAST_fZ(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT)                                         \
    {                                                                                                        \
        H5T_CONV_CAST_TO_##DTYPE(*(S), (ST)0.0, D, DT)                                                       \
    }
#define H5T_CONV_CAST_Fz(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT)                                         \
    {                                                                                                        \
        H5T_CONV_CAST_TO_##DTYPE(*(S), (ST)0.0, D, DT)                                                       \
    }
#define H5T_CONV_CAST_fz(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT)                                         \
    {                                                                                                        \
        H5T_CONV_CAST_TO_##DTYPE(*(S), (ST)0.0, D, DT)                                                       \
    }
#define H5T_CONV_CAST_xZ(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT)                                         \
    {                                                                                                        \
        H5T_CONV_CAST_TO_##DTYPE(*(S), (ST)0.0, D, DT)                                                       \
    }

#define H5T_CONV_CAST_Z(SYMBOLS, STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT)                                 \
    do {                                                                                                     \
        H5T_CONV_CAST_##SYMBOLS(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT)                                  \
    } while (0)

#else

#define H5T_CONV_CAST_Z(SYMBOLS, STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT)                                 \
    do {                                                                                                     \
        *(D) = (DT)(*(S));                                                                                   \
    } while (0)

#endif

#define H5T_CONV_zZ_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
        H5T_CONV_CAST_Z(zZ, STYPE, DTYPE, S, -, -, D, ST, DT);                                               \
    }
#define H5T_CONV_zZ_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    H5T_CONV_zZ_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)

#define H5T_CONV_zZ(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) <= sizeof(DT));                                                          \
        H5T_CONV(H5T_CONV_zZ, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#define H5T_CONV_Zz_CORE_IMP(STYPE, DTYPE, DBTYPE, S, D, ST, DT, SBT, DBT, D_MIN, D_MAX)                     \
    {                                                                                                        \
        H5T_CONV_##STYPE##_REALVAL(S);                            \
        H5T_CONV_##STYPE##_IMAGVAL(S);                       \
        bool sr_over  = (sr_val) > (SBT)(D_MAX);                                                             \
        bool sr_under = (sr_val) < (SBT)(D_MIN);                                                             \
        bool si_over  = (si_val) > (SBT)(D_MAX);                                                             \
        bool si_under = (si_val) < (SBT)(D_MIN);                                                             \
        if (!sr_over && !sr_under && !si_over && !si_under)                                                  \
            H5T_CONV_CAST_Z(Zz, STYPE, DTYPE, S, sr_val, si_val, D, ST, DT);                                 \
        else {                                                                                               \
            H5T_conv_ret_t except_ret = H5T_CONV_UNHANDLED;                                                  \
                                                                                                             \
                                                                                                          \
            if (sr_over || si_over) {                                                                        \
                                                            \
                H5_BEFORE_USER_CB(FAIL)                                                                      \
                    {                                                                                        \
                        except_ret = (conv_ctx->u.conv.cb_struct.func)(                                      \
                            H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id,                          \
                            conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);       \
                    }                                                                                        \
                H5_AFTER_USER_CB(FAIL)                                                                       \
            }                                                                                                \
            else if (sr_under || si_under) {                                                                 \
                                                            \
                H5_BEFORE_USER_CB(FAIL)                                                                      \
                    {                                                                                        \
                        except_ret = (conv_ctx->u.conv.cb_struct.func)(                                      \
                            H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id,                         \
                            conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);       \
                    }                                                                                        \
                H5_AFTER_USER_CB(FAIL)                                                                       \
            }                                                                                                \
                                                                                                             \
                                                                                                          \
            if (except_ret == H5T_CONV_UNHANDLED) {                                                          \
                DBT tmp_val[2];                                                     \
                                                                                                             \
                if (sr_over)                                                                                 \
                    tmp_val[0] = H5_GLUE3(H5T_NATIVE_, DBTYPE, _POS_INF_g);                                  \
                else if (sr_under)                                                                           \
                    tmp_val[0] = H5_GLUE3(H5T_NATIVE_, DBTYPE, _NEG_INF_g);                                  \
                else                                                                                         \
                    tmp_val[0] = (DBT)(sr_val);                                                              \
                if (si_over)                                                                                 \
                    tmp_val[1] = H5_GLUE3(H5T_NATIVE_, DBTYPE, _POS_INF_g);                                  \
                else if (si_under)                                                                           \
                    tmp_val[1] = H5_GLUE3(H5T_NATIVE_, DBTYPE, _NEG_INF_g);                                  \
                else                                                                                         \
                    tmp_val[1] = (DBT)(si_val);                                                              \
                                                                                                             \
                H5T_CONV_CAST_Z(Zz, STYPE, DTYPE, (DT *)tmp_val, tmp_val[0], tmp_val[1], D, ST, DT);         \
            }                                                                                                \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
        }                                                                                                    \
    }
#define H5T_CONV_Zz_DOUBLE_COMPLEX_FLOAT_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)              \
    H5T_CONV_Zz_CORE_IMP(STYPE, DTYPE, FLOAT, S, D, ST, DT, double, float, D_MIN, D_MAX)
#define H5T_CONV_Zz_DOUBLE_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                            \
    H5T_CONV_Zz_DOUBLE_COMPLEX_##DTYPE##_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)
#define H5T_CONV_Zz_LDOUBLE_COMPLEX_FLOAT_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)             \
    H5T_CONV_Zz_CORE_IMP(STYPE, DTYPE, FLOAT, S, D, ST, DT, long double, float, D_MIN, D_MAX)
#define H5T_CONV_Zz_LDOUBLE_COMPLEX_DOUBLE_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)            \
    H5T_CONV_Zz_CORE_IMP(STYPE, DTYPE, DOUBLE, S, D, ST, DT, long double, double, D_MIN, D_MAX)
#define H5T_CONV_Zz_LDOUBLE_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                           \
    H5T_CONV_Zz_LDOUBLE_COMPLEX_##DTYPE##_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)
#define H5T_CONV_Zz_NOEX_CORE_IMP(STYPE, DTYPE, DBTYPE, S, D, ST, DT, SBT, DBT, D_MIN, D_MAX)                \
    {                                                                                                        \
        H5T_CONV_##STYPE##_REALVAL(S);                            \
        H5T_CONV_##STYPE##_IMAGVAL(S);                       \
        bool sr_over  = (sr_val) > (SBT)(D_MAX);                                                             \
        bool sr_under = (sr_val) < (SBT)(D_MIN);                                                             \
        bool si_over  = (si_val) > (SBT)(D_MAX);                                                             \
        bool si_under = (si_val) < (SBT)(D_MIN);                                                             \
        if (!sr_over && !sr_under && !si_over && !si_under)                                                  \
            H5T_CONV_CAST_Z(Zz, STYPE, DTYPE, S, sr_val, si_val, D, ST, DT);                                 \
        else {                                                                                               \
            DBT tmp_val[2];                                                         \
                                                                                                             \
            if (sr_over)                                                                                     \
                tmp_val[0] = H5_GLUE3(H5T_NATIVE_, DBTYPE, _POS_INF_g);                                      \
            else if (sr_under)                                                                               \
                tmp_val[0] = H5_GLUE3(H5T_NATIVE_, DBTYPE, _NEG_INF_g);                                      \
            else                                                                                             \
                tmp_val[0] = (DBT)(sr_val);                                                                  \
            if (si_over)                                                                                     \
                tmp_val[1] = H5_GLUE3(H5T_NATIVE_, DBTYPE, _POS_INF_g);                                      \
            else if (si_under)                                                                               \
                tmp_val[1] = H5_GLUE3(H5T_NATIVE_, DBTYPE, _NEG_INF_g);                                      \
            else                                                                                             \
                tmp_val[1] = (DBT)(si_val);                                                                  \
                                                                                                             \
            H5T_CONV_CAST_Z(Zz, STYPE, DTYPE, (DT *)tmp_val, tmp_val[0], tmp_val[1], D, ST, DT);             \
        }                                                                                                    \
    }
#define H5T_CONV_Zz_DOUBLE_COMPLEX_FLOAT_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)         \
    H5T_CONV_Zz_NOEX_CORE_IMP(STYPE, DTYPE, FLOAT, S, D, ST, DT, double, float, D_MIN, D_MAX)
#define H5T_CONV_Zz_DOUBLE_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                       \
    H5T_CONV_Zz_DOUBLE_COMPLEX_##DTYPE##_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)
#define H5T_CONV_Zz_LDOUBLE_COMPLEX_FLOAT_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)        \
    H5T_CONV_Zz_NOEX_CORE_IMP(STYPE, DTYPE, FLOAT, S, D, ST, DT, long double, float, D_MIN, D_MAX)
#define H5T_CONV_Zz_LDOUBLE_COMPLEX_DOUBLE_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)       \
    H5T_CONV_Zz_NOEX_CORE_IMP(STYPE, DTYPE, DOUBLE, S, D, ST, DT, long double, double, D_MIN, D_MAX)
#define H5T_CONV_Zz_LDOUBLE_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                      \
    H5T_CONV_Zz_LDOUBLE_COMPLEX_##DTYPE##_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)

#define H5T_CONV_Zz(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) >= sizeof(DT));                                                          \
        H5T_CONV(H5T_CONV_Zz_##STYPE, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                 \
    } while (0)

#define H5T_CONV_zF_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
        H5T_CONV_CAST_Z(zF, STYPE, DTYPE, S, -, -, D, ST, DT);                                               \
    }
#define H5T_CONV_zF_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    H5T_CONV_zF_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)

#define H5T_CONV_zF(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        H5T_CONV(H5T_CONV_zF, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#define H5T_CONV_Zf_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, SBT, D_MIN, D_MAX)                                  \
    {                                                                                                        \
        H5T_CONV_##STYPE##_REALVAL(S);                                                                       \
        if ((sr_val) > (SBT)(D_MAX)) {                                                                       \
            H5T_conv_ret_t except_ret;                                                                       \
                                                                                                             \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id,                              \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _POS_INF_g);                                             \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else if ((sr_val) < (SBT)(D_MIN)) {                                                                  \
            H5T_conv_ret_t except_ret;                                                                       \
                                                                                                             \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id,                             \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _NEG_INF_g);                                             \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else                                                                                                 \
            *(D) = (DT)((sr_val));                                                                           \
    }
#define H5T_CONV_Zf_FLOAT_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                             \
    H5T_CONV_Zf_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, float, D_MIN, D_MAX)
#define H5T_CONV_Zf_DOUBLE_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                            \
    H5T_CONV_Zf_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, double, D_MIN, D_MAX)
#define H5T_CONV_Zf_LDOUBLE_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                           \
    H5T_CONV_Zf_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, long double, D_MIN, D_MAX)
#define H5T_CONV_Zf_NOEX_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, SBT, D_MIN, D_MAX)                             \
    {                                                                                                        \
        H5T_CONV_##STYPE##_REALVAL(S);                            \
        if ((sr_val) > (SBT)(D_MAX))                                                                         \
            *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _POS_INF_g);                                                 \
        else if ((sr_val) < (SBT)(D_MIN))                                                                    \
            *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _NEG_INF_g);                                                 \
        else                                                                                                 \
            *(D) = (DT)((sr_val));                                                                           \
    }
#define H5T_CONV_Zf_FLOAT_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                        \
    H5T_CONV_Zf_NOEX_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, float, D_MIN, D_MAX)
#define H5T_CONV_Zf_DOUBLE_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                       \
    H5T_CONV_Zf_NOEX_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, double, D_MIN, D_MAX)
#define H5T_CONV_Zf_LDOUBLE_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                      \
    H5T_CONV_Zf_NOEX_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, long double, D_MIN, D_MAX)

#define H5T_CONV_Zf(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) >= sizeof(DT));                                                          \
        H5T_CONV(H5T_CONV_Zf_##STYPE, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                 \
    } while (0)

#define H5T_CONV_fZ_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
        H5T_CONV_CAST_Z(fZ, STYPE, DTYPE, S, -, -, D, ST, DT);                                               \
    }
#define H5T_CONV_fZ_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    H5T_CONV_fZ_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)

#define H5T_CONV_fZ(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) <= sizeof(DT));                                                          \
        H5T_CONV(H5T_CONV_fZ, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#define H5T_CONV_Fz_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
        if (*(S) > (ST)(D_MAX)) {                                                                            \
            H5T_conv_ret_t except_ret;                                                                       \
                                                                                                             \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id,                              \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _POS_INF_g);                                             \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else if (*(S) < (ST)(D_MIN)) {                                                                       \
            H5T_conv_ret_t except_ret;                                                                       \
                                                                                                             \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id,                             \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _NEG_INF_g);                                             \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else                                                                                                 \
            H5T_CONV_CAST_Z(Fz, STYPE, DTYPE, S, -, -, D, ST, DT);                                           \
    }
#define H5T_CONV_Fz_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    {                                                                                                        \
        if (*(S) > (ST)(D_MAX))                                                                              \
            *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _POS_INF_g);                                                 \
        else if (*(S) < (ST)(D_MIN))                                                                         \
            *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _NEG_INF_g);                                                 \
        else                                                                                                 \
            H5T_CONV_CAST_Z(Fz, STYPE, DTYPE, S, -, -, D, ST, DT);                                           \
    }

#define H5T_CONV_Fz(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        H5T_CONV(H5T_CONV_Fz, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#define H5T_CONV_zf_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
        H5T_CONV_CAST_Z(zf, STYPE, DTYPE, S, -, -, D, ST, DT);                                               \
    }
#define H5T_CONV_zf_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    H5T_CONV_zf_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)

#define H5T_CONV_zf(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) == (2 * sizeof(DT)));                                                    \
        H5T_CONV(H5T_CONV_zf, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#define H5T_CONV_fz_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
        H5T_CONV_CAST_Z(fz, STYPE, DTYPE, S, -, -, D, ST, DT);                                               \
    }
#define H5T_CONV_fz_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    H5T_CONV_fz_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)

#define H5T_CONV_fz(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert((2 * sizeof(ST)) == sizeof(DT));                                                    \
        H5T_CONV(H5T_CONV_fz, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#define H5T_CONV_xZ_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
        if (sprec > dprec) {                                                                                 \
            unsigned low_bit_pos, high_bit_pos;                                                              \
                                                                                                             \
                                                                   \
            H5T_HI_LO_BIT_SET(ST, *(S), low_bit_pos, high_bit_pos)                                           \
                                                                                                             \
                                          \
            if ((high_bit_pos - low_bit_pos) >= dprec) {                                                     \
                H5T_conv_ret_t except_ret;                                                                   \
                                                                                                             \
                                                            \
                H5_BEFORE_USER_CB(FAIL)                                                                      \
                    {                                                                                        \
                        except_ret = (conv_ctx->u.conv.cb_struct.func)(                                      \
                            H5T_CONV_EXCEPT_PRECISION, conv_ctx->u.conv.src_type_id,                         \
                            conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);       \
                    }                                                                                        \
                H5_AFTER_USER_CB(FAIL)                                                                       \
                if (except_ret == H5T_CONV_UNHANDLED)                                                        \
                                                 \
                    H5T_CONV_CAST_Z(xZ, STYPE, DTYPE, S, -, -, D, ST, DT);                                   \
                else if (except_ret == H5T_CONV_ABORT)                                                       \
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");   \
                                        \
            }                                                                                                \
            else                                                                                             \
                H5T_CONV_CAST_Z(xZ, STYPE, DTYPE, S, -, -, D, ST, DT);                                       \
        }                                                                                                    \
        else                                                                                                 \
            H5T_CONV_CAST_Z(xZ, STYPE, DTYPE, S, -, -, D, ST, DT);                                           \
    }
#define H5T_CONV_xZ_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    {                                                                                                        \
        H5T_CONV_CAST_Z(xZ, STYPE, DTYPE, S, -, -, D, ST, DT);                                               \
    }

#define H5T_CONV_xZ(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        H5T_CONV(H5T_CONV_xZ, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, Y)                                         \
    } while (0)

#define H5T_CONV_Zx_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, SBT, D_MIN, D_MAX)                                  \
    {                                                                                                        \
        H5T_CONV_##STYPE##_REALVAL(S);                            \
        if ((sr_val) > (SBT)(D_MAX) || (sprec < dprec && (sr_val) == (SBT)(D_MAX))) {                        \
            H5T_conv_ret_t except_ret;                                                                       \
                                                                                                             \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id,                              \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = (DT)(D_MAX);                                                                          \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else if ((sr_val) < (SBT)(D_MIN)) {                                                                  \
            H5T_conv_ret_t except_ret;                                                                       \
                                                                                                             \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id,                             \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = (DT)(D_MIN);                                                                          \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else if ((sr_val) != (SBT)((DT)((sr_val)))) {                                                        \
            H5T_conv_ret_t except_ret;                                                                       \
                                                                                                             \
                                                            \
            H5_BEFORE_USER_CB(FAIL)                                                                          \
                {                                                                                            \
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(                                          \
                        H5T_CONV_EXCEPT_TRUNCATE, conv_ctx->u.conv.src_type_id,                              \
                        conv_ctx->u.conv.dst_type_id, S, D, conv_ctx->u.conv.cb_struct.user_data);           \
                }                                                                                            \
            H5_AFTER_USER_CB(FAIL)                                                                           \
            if (except_ret == H5T_CONV_UNHANDLED)                                                            \
                                                 \
                *(D) = (DT)((sr_val));                                                                       \
            else if (except_ret == H5T_CONV_ABORT)                                                           \
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");       \
                                        \
        }                                                                                                    \
        else                                                                                                 \
            *(D) = (DT)((sr_val));                                                                           \
    }
#define H5T_CONV_Zx_FLOAT_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                             \
    H5T_CONV_Zx_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, float, D_MIN, D_MAX)
#define H5T_CONV_Zx_DOUBLE_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                            \
    H5T_CONV_Zx_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, double, D_MIN, D_MAX)
#define H5T_CONV_Zx_LDOUBLE_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                           \
    H5T_CONV_Zx_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, long double, D_MIN, D_MAX)
#define H5T_CONV_Zx_NOEX_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, SBT, D_MIN, D_MAX)                             \
    {                                                                                                        \
        H5T_CONV_##STYPE##_REALVAL(S);                            \
        if ((sr_val) > (SBT)(D_MAX))                                                                         \
            *(D) = (DT)(D_MAX);                                                                              \
        else if ((sr_val) < (SBT)(D_MIN))                                                                    \
            *(D) = (DT)(D_MIN);                                                                              \
        else                                                                                                 \
            *(D) = (DT)((sr_val));                                                                           \
    }
#define H5T_CONV_Zx_FLOAT_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                        \
    H5T_CONV_Zx_NOEX_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, float, D_MIN, D_MAX)
#define H5T_CONV_Zx_DOUBLE_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                       \
    H5T_CONV_Zx_NOEX_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, double, D_MIN, D_MAX)
#define H5T_CONV_Zx_LDOUBLE_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                      \
    H5T_CONV_Zx_NOEX_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, long double, D_MIN, D_MAX)

#define H5T_CONV_Zx(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        H5T_CONV(H5T_CONV_Zx_##STYPE, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, Y)                                 \
    } while (0)

#define H5T_CONV_zX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                           \
    {                                                                                                        \
        H5T_CONV_CAST_Z(zX, STYPE, DTYPE, S, -, -, D, ST, DT);                                               \
    }
#define H5T_CONV_zX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                      \
    H5T_CONV_zX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)

#define H5T_CONV_zX(STYPE, DTYPE, ST, DT, D_MIN, D_MAX)                                                      \
    do {                                                                                                     \
        HDcompile_assert(sizeof(ST) <= sizeof(DT));                                                          \
        H5T_CONV(H5T_CONV_zX, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N)                                         \
    } while (0)

#endif

#ifndef H5_WANT_DCONV_EXCEPTION
#define H5T_CONV_NO_EXCEPT_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                    \
    {                                                                                                        \
        *(D) = (DT)(*(S));                                                                                   \
    }
#endif 

#define H5T_CONV_DECL_PREC(PREC) H5_GLUE(H5T_CONV_DECL_PREC_, PREC)

#define H5T_CONV_DECL_PREC_Y                                                                                 \
    size_t      sprec;                                                           \
    size_t      dprec;                                                      \
    H5T_class_t tclass; 

#define H5T_CONV_DECL_PREC_N 

#define H5T_CONV_SET_PREC(PREC) H5_GLUE(H5T_CONV_SET_PREC_, PREC)

#define H5T_CONV_SET_PREC_Y                                                                                  \
                                                    \
    tclass = st->shared->type;                                                                               \
    assert(tclass == H5T_INTEGER || tclass == H5T_FLOAT || tclass == H5T_COMPLEX);                           \
    if (tclass == H5T_INTEGER)                                                                               \
        sprec = st->shared->u.atomic.prec;                                                                   \
    else if (tclass == H5T_FLOAT)                                                                            \
        sprec = 1 + st->shared->u.atomic.u.f.msize;                                                          \
    else                                                                                                     \
        sprec = 1 + st->shared->parent->shared->u.atomic.u.f.msize;                                          \
    tclass = dt->shared->type;                                                                               \
    assert(tclass == H5T_INTEGER || tclass == H5T_FLOAT || tclass == H5T_COMPLEX);                           \
    if (tclass == H5T_INTEGER)                                                                               \
        dprec = dt->shared->u.atomic.prec;                                                                   \
    else if (tclass == H5T_FLOAT)                                                                            \
        dprec = 1 + dt->shared->u.atomic.u.f.msize;                                                          \
    else                                                                                                     \
        dprec = 1 + dt->shared->parent->shared->u.atomic.u.f.msize;

#define H5T_CONV_SET_PREC_N 

#define H5T_CONV_LOOP_PRE_SALIGN(ST)                                                                         \
    {                                                                                                        \
                                                                                                          \
        H5MM_memcpy(&src_aligned, (const uint8_t *)src, sizeof(ST));                                         \
    }

#define H5T_CONV_LOOP_PRE_SNOALIGN(ST)                                                                       \
    {                                                                                                        \
    }

#define H5T_CONV_LOOP_PRE_DALIGN(DT)                                                                         \
    {                                                                                                        \
        d = &dst_aligned;                                                                                    \
    }

#define H5T_CONV_LOOP_PRE_DNOALIGN(DT)                                                                       \
    {                                                                                                        \
    }

#define H5T_CONV_LOOP_POST_SALIGN(ST)                                                                        \
    {                                                                                                        \
    }

#define H5T_CONV_LOOP_POST_SNOALIGN(ST)                                                                      \
    {                                                                                                        \
    }

#define H5T_CONV_LOOP_POST_DALIGN(DT)                                                                        \
    {                                                                                                        \
                                                                                                          \
        H5MM_memcpy((uint8_t *)dst, &dst_aligned, sizeof(DT));                                               \
    }

#define H5T_CONV_LOOP_POST_DNOALIGN(DT)                                                                      \
    {                                                                                                        \
    }

#define H5T_CONV_LOOP_OUTER(PRE_SALIGN_GUTS, PRE_DALIGN_GUTS, POST_SALIGN_GUTS, POST_DALIGN_GUTS, GUTS,      \
                            STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                        \
    if (conv_ctx->u.conv.cb_struct.func) {                                                                   \
        H5T_CONV_LOOP(PRE_SALIGN_GUTS, PRE_DALIGN_GUTS, POST_SALIGN_GUTS, POST_DALIGN_GUTS, GUTS, STYPE,     \
                      DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                                     \
    }                                                                                                        \
    else {                                                                                                   \
        H5T_CONV_LOOP(PRE_SALIGN_GUTS, PRE_DALIGN_GUTS, POST_SALIGN_GUTS, POST_DALIGN_GUTS,                  \
                      H5_GLUE(GUTS, _NOEX), STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                        \
    }

#ifdef H5_WANT_DCONV_EXCEPTION
#define H5T_CONV_LOOP_GUTS(GUTS, STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                   \
                                                      \
    H5_GLUE(GUTS, _CORE)(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)
#else 
#define H5T_CONV_LOOP_GUTS(GUTS, STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                   \
    H5_GLUE(H5T_CONV_NO_EXCEPT, _CORE)(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)
#endif 

#define H5T_CONV_LOOP(PRE_SALIGN_GUTS, PRE_DALIGN_GUTS, POST_SALIGN_GUTS, POST_DALIGN_GUTS, GUTS, STYPE,     \
                      DTYPE, S, D, ST, DT, D_MIN, D_MAX)                                                     \
    for (elmtno = 0; elmtno < safe; elmtno++) {                                                              \
                                                                            \
        H5_GLUE(H5T_CONV_LOOP_, PRE_SALIGN_GUTS)                                                             \
        (ST)                                                                                                 \
                                                                                                             \
                                                                       \
            H5_GLUE(H5T_CONV_LOOP_, PRE_DALIGN_GUTS)(DT)                                                     \
                                                                                                             \
                                                      \
            H5T_CONV_LOOP_GUTS(GUTS, STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX)                               \
                                                                                                             \
                                                                           \
            H5_GLUE(H5T_CONV_LOOP_, POST_SALIGN_GUTS)(ST)                                                    \
                                                                                                             \
                                                                      \
            H5_GLUE(H5T_CONV_LOOP_, POST_DALIGN_GUTS)(DT)                                                    \
                                                                                                             \
                                                                                       \
            src_buf = (void *)((uint8_t *)src_buf + s_stride);                                               \
        src         = (ST *)src_buf;                                                                         \
        dst_buf     = (void *)((uint8_t *)dst_buf + d_stride);                                               \
        dst         = (DT *)dst_buf;                                                                         \
    }

#define H5T_CONV(GUTS, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, PREC)                                             \
    {                                                                                                        \
        herr_t ret_value = SUCCEED;                                                \
                                                                                                             \
        FUNC_ENTER_PACKAGE                                                                                   \
                                                                                                             \
        {                                                                                                    \
            size_t elmtno;                                                         \
            H5T_CONV_DECL_PREC(PREC)                                 \
            void   *src_buf;                                                  \
            void   *dst_buf;                                                 \
            ST     *src, *s;                                                    \
            DT     *dst, *d;                                                   \
            ST      src_aligned;                                              \
            DT      dst_aligned;                                             \
            bool    s_mv, d_mv;                                                \
            ssize_t s_stride, d_stride;                                       \
            size_t  safe;                             \
                                                                                                             \
            switch (cdata->command) {                                                                        \
                case H5T_CONV_INIT:                                                                          \
                                                                 \
                    cdata->need_bkg = H5T_BKG_NO;                                                            \
                    if (NULL == st || NULL == dt)                                                            \
                        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype");                   \
                    if (st->shared->size != sizeof(ST) || dt->shared->size != sizeof(DT))                    \
                        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "disagreement about datatype size");   \
                    CI_ALLOC_PRIV                                                                            \
                    break;                                                                                   \
                                                                                                             \
                case H5T_CONV_FREE:                                                                          \
                                                                              \
                    CI_PRINT_STATS(STYPE, DTYPE);                                                            \
                    CI_FREE_PRIV                                                                             \
                    break;                                                                                   \
                                                                                                             \
                case H5T_CONV_CONV:                                                                          \
                    if (NULL == st || NULL == dt)                                                            \
                        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype");                   \
                    if (NULL == conv_ctx)                                                                    \
                        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL,                                        \
                                    "invalid datatype conversion context pointer");                          \
                                                                                                             \
                                                                \
                    if (buf_stride) {                                                                        \
                        assert(buf_stride >= sizeof(ST));                                                    \
                        assert(buf_stride >= sizeof(DT));                                                    \
                        s_stride = d_stride = (ssize_t)buf_stride;                                           \
                    }                                                                                        \
                    else {                                                                                   \
                        s_stride = sizeof(ST);                                                               \
                        d_stride = sizeof(DT);                                                               \
                    }                                                                                        \
                                                                                                             \
                                                              \
                    s_mv = H5T_NATIVE_##STYPE##_ALIGN_g > 1 &&                                               \
                           ((size_t)buf % H5T_NATIVE_##STYPE##_ALIGN_g ||                                    \
                             ((size_t)((ST *)buf) != (size_t)buf) ||                               \
                            (size_t)s_stride % H5T_NATIVE_##STYPE##_ALIGN_g);                                \
                    d_mv = H5T_NATIVE_##DTYPE##_ALIGN_g > 1 &&                                               \
                           ((size_t)buf % H5T_NATIVE_##DTYPE##_ALIGN_g ||                                    \
                             ((size_t)((DT *)buf) != (size_t)buf) ||                               \
                            (size_t)d_stride % H5T_NATIVE_##DTYPE##_ALIGN_g);                                \
                    CI_INC_SRC(s_mv)                                                                         \
                    CI_INC_DST(d_mv)                                                                         \
                                                                                                             \
                    H5T_CONV_SET_PREC(PREC)                             \
                                                                                                             \
                                         \
                                                                         \
                    while (nelmts > 0) {                                                                     \
                                                    \
                        if (d_stride > s_stride) {                                                           \
                                                   \
                                                  \
                                                    \
                            safe = nelmts - (((nelmts * (size_t)s_stride) + (size_t)(d_stride - 1)) /        \
                                             (size_t)d_stride);                                              \
                                                                                                             \
                                                   \
                                                                             \
                            if (safe < 2) {                                                                  \
                                src      = (ST *)(src_buf = (void *)((uint8_t *)buf +                        \
                                                                (nelmts - 1) * (size_t)s_stride));      \
                                dst      = (DT *)(dst_buf = (void *)((uint8_t *)buf +                        \
                                                                (nelmts - 1) * (size_t)d_stride));      \
                                s_stride = -s_stride;                                                        \
                                d_stride = -d_stride;                                                        \
                                                                                                             \
                                safe = nelmts;                                                               \
                            }                                                                    \
                            else {                                                                           \
                                src = (ST *)(src_buf = (void *)((uint8_t *)buf +                             \
                                                                (nelmts - safe) * (size_t)s_stride));        \
                                dst = (DT *)(dst_buf = (void *)((uint8_t *)buf +                             \
                                                                (nelmts - safe) * (size_t)d_stride));        \
                            }                                                                  \
                        }                                                                        \
                        else {                                                                               \
                                                                      \
                            src  = (ST *)(src_buf = buf);                                                    \
                            dst  = (DT *)(dst_buf = buf);                                                    \
                            safe = nelmts;                                                                   \
                        }                                                                      \
                                                                                                             \
                                                                  \
                        if (s_mv && d_mv) {                                                                  \
                                                         \
                            s = &src_aligned;                                                                \
                            H5T_CONV_LOOP_OUTER(PRE_SALIGN, PRE_DALIGN, POST_SALIGN, POST_DALIGN, GUTS,      \
                                                STYPE, DTYPE, s, d, ST, DT, D_MIN, D_MAX)                    \
                        }                                                                                    \
                        else if (s_mv) {                                                                     \
                                                                  \
                            s = &src_aligned;                                                                \
                            H5T_CONV_LOOP_OUTER(PRE_SALIGN, PRE_DNOALIGN, POST_SALIGN, POST_DNOALIGN, GUTS,  \
                                                STYPE, DTYPE, s, dst, ST, DT, D_MIN, D_MAX)                  \
                        }                                                                                    \
                        else if (d_mv) {                                                                     \
                                                             \
                            H5T_CONV_LOOP_OUTER(PRE_SNOALIGN, PRE_DALIGN, POST_SNOALIGN, POST_DALIGN, GUTS,  \
                                                STYPE, DTYPE, src, d, ST, DT, D_MIN, D_MAX)                  \
                        }                                                                                    \
                        else {                                                                               \
                                              \
                            H5T_CONV_LOOP_OUTER(PRE_SNOALIGN, PRE_DNOALIGN, POST_SNOALIGN, POST_DNOALIGN,    \
                                                GUTS, STYPE, DTYPE, src, dst, ST, DT, D_MIN, D_MAX)          \
                        }                                                                                    \
                                                                                                             \
                                                           \
                        nelmts -= safe;                                                                      \
                    }                                                                         \
                    break;                                                                                   \
                                                                                                             \
                default:                                                                                     \
                    HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command");          \
            }                                                                                                \
        }                                                                                                    \
                                                                                                             \
done:                                                                                                        \
        FUNC_LEAVE_NOAPI(ret_value)                                                                          \
    }

#ifdef H5T_DEBUG

#define CI_PRINT_STATS(STYPE, DTYPE)                                                                         \
    do {                                                                                                     \
        if (H5DEBUG(T) && ((H5T_conv_hw_t *)cdata->priv)->s_aligned) {                                       \
            fprintf(H5DEBUG(T), "      %llu src elements aligned on %llu-byte boundaries\n",                 \
                    (unsigned long long)(((H5T_conv_hw_t *)cdata->priv)->s_aligned),                         \
                    (unsigned long long)(H5T_NATIVE_##STYPE##_ALIGN_g));                                     \
        }                                                                                                    \
        if (H5DEBUG(T) && ((H5T_conv_hw_t *)cdata->priv)->d_aligned) {                                       \
            fprintf(H5DEBUG(T), "      %llu dst elements aligned on %llu-byte boundaries\n",                 \
                    (unsigned long long)(((H5T_conv_hw_t *)cdata->priv)->d_aligned),                         \
                    (unsigned long long)(H5T_NATIVE_##DTYPE##_ALIGN_g));                                     \
        }                                                                                                    \
    } while (0)

#define CI_ALLOC_PRIV                                                                                        \
    if (NULL == (cdata->priv = H5MM_calloc(sizeof(H5T_conv_hw_t)))) {                                        \
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");                            \
    }

#define CI_FREE_PRIV                                                                                         \
    if (cdata->priv != NULL)                                                                                 \
        cdata->priv = H5MM_xfree(cdata->priv);

#define CI_INC_SRC(s)                                                                                        \
    if (s)                                                                                                   \
        ((H5T_conv_hw_t *)cdata->priv)->s_aligned += nelmts;

#define CI_INC_DST(d)                                                                                        \
    if (d)                                                                                                   \
        ((H5T_conv_hw_t *)cdata->priv)->d_aligned += nelmts;
#else                                
#define CI_PRINT_STATS(STYPE, DTYPE) 
#define CI_ALLOC_PRIV                cdata->priv = NULL;
#define CI_FREE_PRIV                 
#define CI_INC_SRC(s)                
#define CI_INC_DST(d)                
#endif                               

#endif 
