Coverage Report

Created: 2025-11-09 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Tconv_complex.c
Line
Count
Source
1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
 * Copyright by The HDF Group.                                               *
3
 * All rights reserved.                                                      *
4
 *                                                                           *
5
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
6
 * terms governing use, modification, and redistribution, is contained in    *
7
 * the LICENSE file, which can be found at the root of the source code       *
8
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
9
 * If you do not have access to either file, you may request a copy from     *
10
 * help@hdfgroup.org.                                                        *
11
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13
/*
14
 * Purpose: Datatype conversion functions for complex number datatypes
15
 */
16
17
/****************/
18
/* Module Setup */
19
/****************/
20
#include "H5Tmodule.h" /* This source code file is part of the H5T module */
21
22
/***********/
23
/* Headers */
24
/***********/
25
#include "H5private.h"  /*  Generic Functions                    */
26
#include "H5Eprivate.h" /* Error handling                       */
27
#include "H5Tconv.h"    /* Datatype conversions                 */
28
#include "H5Tconv_macros.h"
29
#include "H5Tconv_complex.h"
30
#include "H5Tconv_integer.h"
31
#include "H5Tconv_float.h"
32
33
/******************/
34
/* Local Typedefs */
35
/******************/
36
37
/********************/
38
/* Local Prototypes */
39
/********************/
40
41
static herr_t H5T__conv_complex_loop(const H5T_t *src_p, const H5T_t *dst_p, const H5T_conv_ctx_t *conv_ctx,
42
                                     size_t nelmts, size_t buf_stride, void *buf);
43
static herr_t H5T__conv_complex_part(const H5T_t *src_p, const H5T_t *dst_p, uint8_t *s, uint8_t *d,
44
                                     const H5T_conv_ctx_t *conv_ctx, uint8_t *src_rev,
45
                                     bool *exception_handled);
46
47
/*-------------------------------------------------------------------------
48
 * Function:    H5T__conv_complex
49
 *
50
 * Purpose:     Convert one complex number type to another. This is the
51
 *              catch-all function for complex number conversions and is
52
 *              probably not particularly fast.
53
 *
54
 * Return:      Non-negative on success/Negative on failure
55
 *
56
 *-------------------------------------------------------------------------
57
 */
58
herr_t
59
H5T__conv_complex(const H5T_t *src_p, const H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
60
                  size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
61
                  void H5_ATTR_UNUSED *bkg)
62
0
{
63
0
    herr_t ret_value = SUCCEED;
64
65
0
    FUNC_ENTER_PACKAGE
66
67
0
    switch (cdata->command) {
68
0
        case H5T_CONV_INIT: {
69
0
            H5T_atomic_t src_atomic; /* source datatype atomic info      */
70
0
            H5T_atomic_t dst_atomic; /* destination datatype atomic info */
71
72
0
            if (!src_p || !dst_p)
73
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
74
0
            if (!H5T_IS_ATOMIC(src_p->shared->parent->shared))
75
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid source complex number datatype");
76
0
            if (!H5T_IS_ATOMIC(dst_p->shared->parent->shared))
77
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid destination complex number datatype");
78
0
            src_atomic = src_p->shared->parent->shared->u.atomic;
79
0
            dst_atomic = dst_p->shared->parent->shared->u.atomic;
80
0
            if (H5T_ORDER_LE != src_atomic.order && H5T_ORDER_BE != src_atomic.order &&
81
0
                H5T_ORDER_VAX != src_atomic.order)
82
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
83
0
                            "unsupported byte order for source datatype");
84
0
            if (H5T_ORDER_LE != dst_atomic.order && H5T_ORDER_BE != dst_atomic.order &&
85
0
                H5T_ORDER_VAX != src_atomic.order)
86
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
87
0
                            "unsupported byte order for destination datatype");
88
0
            if (dst_p->shared->size > 2 * TEMP_FLOAT_CONV_BUFFER_SIZE)
89
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "destination datatype size is too large");
90
0
            if (8 * sizeof(int64_t) - 1 < src_atomic.u.f.esize ||
91
0
                8 * sizeof(int64_t) - 1 < dst_atomic.u.f.esize)
92
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "exponent field is too large");
93
0
            cdata->need_bkg = H5T_BKG_NO;
94
95
0
            break;
96
0
        }
97
98
0
        case H5T_CONV_FREE:
99
0
            break;
100
101
0
        case H5T_CONV_CONV:
102
0
            if (!src_p || !dst_p)
103
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
104
0
            if (NULL == conv_ctx)
105
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid datatype conversion context pointer");
106
107
0
            if (H5T__conv_complex_loop(src_p, dst_p, conv_ctx, nelmts, buf_stride, buf) < 0)
108
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "unable to convert data values");
109
110
0
            break;
111
112
0
        default:
113
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command");
114
0
    }
115
116
0
done:
117
0
    FUNC_LEAVE_NOAPI(ret_value)
118
0
} /* end H5T__conv_complex() */
119
120
/*-------------------------------------------------------------------------
121
 * Function:    H5T__conv_complex_loop
122
 *
123
 * Purpose:     Implements the body of the conversion loop when converting
124
 *              complex number values to another complex number type.
125
 *
126
 * Return:      Non-negative on success/Negative on failure
127
 *
128
 *-------------------------------------------------------------------------
129
 */
130
static herr_t
131
H5T__conv_complex_loop(const H5T_t *src_p, const H5T_t *dst_p, const H5T_conv_ctx_t *conv_ctx, size_t nelmts,
132
                       size_t buf_stride, void *buf)
133
0
{
134
0
    H5T_conv_float_specval_t realval_type; /* floating-point value type (regular, +/-Inf, +/-0, NaN) */
135
0
    H5T_conv_float_specval_t imagval_type; /* floating-point value type (regular, +/-Inf, +/-0, NaN) */
136
0
    H5T_conv_ret_t           except_ret;   /* return of conversion exception callback function       */
137
0
    H5T_atomic_t             src_atomic;   /* source datatype atomic info                            */
138
0
    H5T_atomic_t             dst_atomic;   /* destination datatype atomic info                       */
139
0
    ssize_t  src_delta, dst_delta;         /* source & destination stride                            */
140
0
    uint8_t *s, *sp, *d, *dp;              /* source and dest traversal ptrs                         */
141
0
    uint8_t *src_rev = NULL;               /* order-reversed source buffer                           */
142
0
    uint8_t  dbuf[2 * TEMP_FLOAT_CONV_BUFFER_SIZE]; /* temp destination buffer */
143
0
    size_t   src_part_size; /* size of each complex number part                       */
144
0
    size_t   dst_part_size; /* size of each complex number part                       */
145
0
    size_t   olap;          /* num overlapping elements                               */
146
0
    int      direction;     /* forward or backward traversal                          */
147
0
    herr_t   ret_value = SUCCEED;
148
149
0
    assert(src_p);
150
0
    assert(src_p->shared->type == H5T_COMPLEX);
151
0
    assert(dst_p);
152
0
    assert(dst_p->shared->type == H5T_COMPLEX);
153
0
    assert(conv_ctx);
154
0
    assert(buf);
155
156
0
    FUNC_ENTER_PACKAGE
157
158
0
    src_atomic    = src_p->shared->parent->shared->u.atomic;
159
0
    dst_atomic    = dst_p->shared->parent->shared->u.atomic;
160
0
    src_part_size = src_p->shared->size / 2;
161
0
    dst_part_size = dst_p->shared->size / 2;
162
163
    /*
164
     * Do we process the values from beginning to end or vice versa? Also,
165
     * how many of the elements have the source and destination areas
166
     * overlapping?
167
     */
168
0
    if (src_p->shared->size == dst_p->shared->size || buf_stride) {
169
0
        sp = dp   = (uint8_t *)buf;
170
0
        direction = 1;
171
0
        olap      = nelmts;
172
0
    }
173
0
    else if (src_p->shared->size >= dst_p->shared->size) {
174
0
        double olap_d =
175
0
            ceil((double)(dst_p->shared->size) / (double)(src_p->shared->size - dst_p->shared->size));
176
0
        olap = (size_t)olap_d;
177
0
        sp = dp   = (uint8_t *)buf;
178
0
        direction = 1;
179
0
    }
180
0
    else {
181
0
        double olap_d =
182
0
            ceil((double)(src_p->shared->size) / (double)(dst_p->shared->size - src_p->shared->size));
183
0
        olap      = (size_t)olap_d;
184
0
        sp        = (uint8_t *)buf + (nelmts - 1) * src_p->shared->size;
185
0
        dp        = (uint8_t *)buf + (nelmts - 1) * dst_p->shared->size;
186
0
        direction = -1;
187
0
    }
188
189
    /* Direction & size of buffer traversal */
190
0
    H5_CHECK_OVERFLOW(buf_stride, size_t, ssize_t);
191
0
    H5_CHECK_OVERFLOW(src_p->shared->size, size_t, ssize_t);
192
0
    H5_CHECK_OVERFLOW(dst_p->shared->size, size_t, ssize_t);
193
0
    src_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : src_p->shared->size);
194
0
    dst_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : dst_p->shared->size);
195
196
    /* Allocate space for order-reversed source buffer */
197
0
    if (conv_ctx->u.conv.cb_struct.func)
198
0
        if (NULL == (src_rev = H5MM_calloc(src_p->shared->size)))
199
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "couldn't allocate temporary buffer");
200
201
    /* The conversion loop */
202
0
    for (size_t elmtno = 0; elmtno < nelmts; elmtno++) {
203
0
        bool reverse     = true;  /* if reversed the order of destination            */
204
0
        bool real_zero   = false; /* if real part is +/-0                            */
205
0
        bool imag_zero   = false; /* if imaginary part is +/-0                       */
206
0
        bool real_except = false; /* if an exception happened for the real part      */
207
0
        bool imag_except = false; /* if an exception happened for the imaginary part */
208
209
        /*
210
         * If the source and destination buffers overlap then use a
211
         * temporary buffer for the destination.
212
         */
213
0
        s = sp;
214
0
        if (direction > 0)
215
0
            d = elmtno < olap ? dbuf : dp;
216
0
        else
217
0
            d = elmtno + olap >= nelmts ? dbuf : dp;
218
0
        if (d == dbuf)
219
0
            memset(dbuf, 0, sizeof(dbuf));
220
221
#ifndef NDEBUG
222
        if (d == dbuf) {
223
            assert((dp >= sp && dp < sp + src_p->shared->size) ||
224
                   (sp >= dp && sp < dp + dst_p->shared->size));
225
        }
226
        else {
227
            assert((dp < sp && dp + dst_p->shared->size <= sp) ||
228
                   (sp < dp && sp + src_p->shared->size <= dp));
229
        }
230
#endif
231
232
        /*
233
         * Put the data in little endian order so our loops aren't so
234
         * complicated. We'll do all the conversion stuff assuming
235
         * little endian and then we'll fix the order at the end.
236
         */
237
0
        if (H5T_ORDER_BE == src_atomic.order) {
238
0
            uint8_t *cur_part = s;
239
            /* Swap real part of complex number element */
240
0
            for (size_t j = 0; j < src_part_size / 2; j++)
241
0
                H5_SWAP_BYTES(cur_part, j, src_part_size - (j + 1));
242
            /* Swap imaginary part of complex number element */
243
0
            cur_part += src_part_size;
244
0
            for (size_t j = 0; j < src_part_size / 2; j++)
245
0
                H5_SWAP_BYTES(cur_part, j, src_part_size - (j + 1));
246
0
        }
247
0
        else if (H5T_ORDER_VAX == src_atomic.order)
248
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
249
0
                        "VAX byte ordering is unsupported for complex number type conversions");
250
251
        /* Check for special cases: +0, -0, +Inf, -Inf, NaN */
252
0
        realval_type = H5T__conv_float_find_special(s, &src_atomic, NULL);
253
0
        imagval_type = H5T__conv_float_find_special(s + (src_p->shared->size / 2), &src_atomic, NULL);
254
255
0
        real_zero = (realval_type == H5T_CONV_FLOAT_SPECVAL_POSZERO ||
256
0
                     realval_type == H5T_CONV_FLOAT_SPECVAL_NEGZERO);
257
0
        imag_zero = (imagval_type == H5T_CONV_FLOAT_SPECVAL_POSZERO ||
258
0
                     imagval_type == H5T_CONV_FLOAT_SPECVAL_NEGZERO);
259
0
        real_except =
260
0
            (realval_type == H5T_CONV_FLOAT_SPECVAL_POSINF || realval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF ||
261
0
             realval_type == H5T_CONV_FLOAT_SPECVAL_NAN);
262
0
        imag_except =
263
0
            (imagval_type == H5T_CONV_FLOAT_SPECVAL_POSINF || imagval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF ||
264
0
             imagval_type == H5T_CONV_FLOAT_SPECVAL_NAN);
265
266
        /* A complex number is zero if both parts are +/-0 */
267
0
        if (real_zero && imag_zero) {
268
0
            H5T__bit_copy(d, dst_atomic.u.f.sign, s, src_atomic.u.f.sign, (size_t)1);
269
0
            H5T__bit_copy(d + dst_part_size, dst_atomic.u.f.sign, s + src_part_size, src_atomic.u.f.sign,
270
0
                          (size_t)1);
271
0
            H5T__bit_set(d, dst_atomic.u.f.epos, dst_atomic.u.f.esize, false);
272
0
            H5T__bit_set(d + dst_part_size, dst_atomic.u.f.epos, dst_atomic.u.f.esize, false);
273
0
            H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false);
274
0
            H5T__bit_set(d + dst_part_size, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false);
275
0
            goto padding;
276
0
        }
277
0
        else if (real_except || imag_except) {
278
0
            except_ret = H5T_CONV_UNHANDLED;
279
280
            /* If user's exception handler is present, use it */
281
0
            if (conv_ctx->u.conv.cb_struct.func) {
282
0
                H5T_conv_except_t except_type; /* type of conversion exception that occurred */
283
284
                /* Reverse source buffer order first */
285
0
                H5T__reverse_order(src_rev, s, src_p);
286
287
                /*
288
                 * A complex number is infinity if either part is infinity,
289
                 * even if the other part is NaN. If a part is infinity,
290
                 * since we can only throw one type of conversion exception,
291
                 * arbitrarily choose the exception type to throw based
292
                 * on the infinity type for the real part (if it's infinity),
293
                 * followed by the infinity type for the imaginary part. For
294
                 * now, it will be assumed that the conversion exception
295
                 * callback will inspect and handle both parts of the complex
296
                 * number value.
297
                 */
298
0
                if (realval_type == H5T_CONV_FLOAT_SPECVAL_POSINF)
299
0
                    except_type = H5T_CONV_EXCEPT_PINF;
300
0
                else if (realval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF)
301
0
                    except_type = H5T_CONV_EXCEPT_NINF;
302
0
                else if (imagval_type == H5T_CONV_FLOAT_SPECVAL_POSINF)
303
0
                    except_type = H5T_CONV_EXCEPT_PINF;
304
0
                else if (imagval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF)
305
0
                    except_type = H5T_CONV_EXCEPT_NINF;
306
0
                else {
307
0
                    assert(realval_type == H5T_CONV_FLOAT_SPECVAL_NAN ||
308
0
                           imagval_type == H5T_CONV_FLOAT_SPECVAL_NAN);
309
0
                    except_type = H5T_CONV_EXCEPT_NAN;
310
0
                }
311
312
                /* Prepare & restore library for user callback */
313
0
                H5_BEFORE_USER_CB(FAIL)
314
0
                    {
315
0
                        except_ret = (conv_ctx->u.conv.cb_struct.func)(
316
0
                            except_type, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, src_rev,
317
0
                            d, conv_ctx->u.conv.cb_struct.user_data);
318
0
                    }
319
0
                H5_AFTER_USER_CB(FAIL)
320
0
            }
321
322
0
            if (except_ret == H5T_CONV_UNHANDLED) {
323
0
                if (realval_type == H5T_CONV_FLOAT_SPECVAL_POSINF ||
324
0
                    realval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF ||
325
0
                    imagval_type == H5T_CONV_FLOAT_SPECVAL_POSINF ||
326
0
                    imagval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF) {
327
0
                    H5T__bit_copy(d, dst_atomic.u.f.sign, s, src_atomic.u.f.sign, (size_t)1);
328
0
                    H5T__bit_copy(d + dst_part_size, dst_atomic.u.f.sign, s + src_part_size,
329
0
                                  src_atomic.u.f.sign, (size_t)1);
330
331
0
                    if (realval_type == H5T_CONV_FLOAT_SPECVAL_POSINF ||
332
0
                        realval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF) {
333
0
                        H5T__bit_set(d, dst_atomic.u.f.epos, dst_atomic.u.f.esize, true);
334
0
                        H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false);
335
                        /* If the destination has no implied mantissa bit, we'll need to set
336
                         * the 1st bit of mantissa to 1. The Intel-Linux "long double" is
337
                         * this case. */
338
0
                        if (H5T_NORM_NONE == dst_atomic.u.f.norm)
339
0
                            H5T__bit_set(d, dst_atomic.u.f.mpos + dst_atomic.u.f.msize - 1, (size_t)1, true);
340
0
                    }
341
0
                    if (imagval_type == H5T_CONV_FLOAT_SPECVAL_POSINF ||
342
0
                        imagval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF) {
343
0
                        H5T__bit_set(d + dst_part_size, dst_atomic.u.f.epos, dst_atomic.u.f.esize, true);
344
0
                        H5T__bit_set(d + dst_part_size, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false);
345
                        /* If the destination has no implied mantissa bit, we'll need to set
346
                         * the 1st bit of mantissa to 1. The Intel-Linux "long double" is
347
                         * this case. */
348
0
                        if (H5T_NORM_NONE == dst_atomic.u.f.norm)
349
0
                            H5T__bit_set(d + dst_part_size, dst_atomic.u.f.mpos + dst_atomic.u.f.msize - 1,
350
0
                                         (size_t)1, true);
351
0
                    }
352
0
                }
353
0
                else {
354
                    /* There are many NaN values, so we just set all bits of the significand. */
355
0
                    if (realval_type == H5T_CONV_FLOAT_SPECVAL_NAN) {
356
0
                        H5T__bit_copy(d, dst_atomic.u.f.sign, s, src_atomic.u.f.sign, (size_t)1);
357
0
                        H5T__bit_set(d, dst_atomic.u.f.epos, dst_atomic.u.f.esize, true);
358
0
                        H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, true);
359
0
                    }
360
0
                    if (imagval_type == H5T_CONV_FLOAT_SPECVAL_NAN) {
361
0
                        H5T__bit_copy(d + dst_part_size, dst_atomic.u.f.sign, s + src_part_size,
362
0
                                      src_atomic.u.f.sign, (size_t)1);
363
0
                        H5T__bit_set(d + dst_part_size, dst_atomic.u.f.epos, dst_atomic.u.f.esize, true);
364
0
                        H5T__bit_set(d + dst_part_size, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, true);
365
0
                    }
366
0
                }
367
0
            }
368
0
            else if (except_ret == H5T_CONV_HANDLED) {
369
                /* No need to reverse the order of destination because user handles it */
370
0
                reverse = false;
371
0
                goto next;
372
0
            }
373
0
            else if (except_ret == H5T_CONV_ABORT)
374
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");
375
376
0
            goto padding;
377
0
        }
378
379
0
        if (real_zero) {
380
0
            H5T__bit_copy(d, dst_atomic.u.f.sign, s, src_atomic.u.f.sign, (size_t)1);
381
0
            H5T__bit_set(d, dst_atomic.u.f.epos, dst_atomic.u.f.esize, false);
382
0
            H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false);
383
0
        }
384
0
        else {
385
0
            bool exception_handled = false;
386
387
0
            if (H5T__conv_complex_part(src_p, dst_p, s, d, conv_ctx, src_rev, &exception_handled) < 0)
388
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't convert real part of complex number");
389
390
            /* If an exception was handled, go to the next element */
391
0
            if (exception_handled) {
392
0
                reverse = false;
393
0
                goto next;
394
0
            }
395
0
        }
396
397
0
        if (imag_zero) {
398
0
            H5T__bit_copy(d + dst_part_size, dst_atomic.u.f.sign, s + src_part_size, src_atomic.u.f.sign,
399
0
                          (size_t)1);
400
0
            H5T__bit_set(d + dst_part_size, dst_atomic.u.f.epos, dst_atomic.u.f.esize, false);
401
0
            H5T__bit_set(d + dst_part_size, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false);
402
0
        }
403
0
        else {
404
0
            bool exception_handled = false;
405
406
0
            if (H5T__conv_complex_part(src_p, dst_p, s + src_part_size, d + dst_part_size, conv_ctx, src_rev,
407
0
                                       &exception_handled) < 0)
408
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL,
409
0
                            "can't convert imaginary part of complex number");
410
411
            /* If an exception was handled, go to the next element */
412
0
            if (exception_handled) {
413
0
                reverse = false;
414
0
                goto next;
415
0
            }
416
0
        }
417
418
0
padding:
419
        /*
420
         * Set external padding areas
421
         */
422
0
        if (dst_atomic.offset > 0) {
423
0
            assert(H5T_PAD_ZERO == dst_atomic.lsb_pad || H5T_PAD_ONE == dst_atomic.lsb_pad);
424
0
            H5T__bit_set(d, (size_t)0, dst_atomic.offset, (bool)(H5T_PAD_ONE == dst_atomic.lsb_pad));
425
0
            H5T__bit_set(d + dst_part_size, (size_t)0, dst_atomic.offset,
426
0
                         (bool)(H5T_PAD_ONE == dst_atomic.lsb_pad));
427
0
        }
428
0
        {
429
0
            size_t type_size = dst_p->shared->parent->shared->size;
430
431
0
            if (dst_atomic.offset + dst_atomic.prec != 8 * type_size) {
432
0
                assert(H5T_PAD_ZERO == dst_atomic.msb_pad || H5T_PAD_ONE == dst_atomic.msb_pad);
433
0
                H5T__bit_set(d, dst_atomic.offset + dst_atomic.prec,
434
0
                             8 * type_size - (dst_atomic.offset + dst_atomic.prec),
435
0
                             (bool)(H5T_PAD_ONE == dst_atomic.msb_pad));
436
0
                H5T__bit_set(d + dst_part_size, dst_atomic.offset + dst_atomic.prec,
437
0
                             8 * type_size - (dst_atomic.offset + dst_atomic.prec),
438
0
                             (bool)(H5T_PAD_ONE == dst_atomic.msb_pad));
439
0
            }
440
0
        }
441
442
        /* Put the destination in the correct byte order. See note at beginning of loop. */
443
0
        if (H5T_ORDER_BE == dst_atomic.order && reverse) {
444
0
            uint8_t *cur_part = d;
445
            /* Swap real part of complex number element */
446
0
            for (size_t j = 0; j < dst_part_size / 2; j++)
447
0
                H5_SWAP_BYTES(cur_part, j, dst_part_size - (j + 1));
448
            /* Swap imaginary part of complex number element */
449
0
            cur_part += dst_part_size;
450
0
            for (size_t j = 0; j < dst_part_size / 2; j++)
451
0
                H5_SWAP_BYTES(cur_part, j, dst_part_size - (j + 1));
452
0
        }
453
0
        else if (H5T_ORDER_VAX == dst_atomic.order)
454
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
455
0
                        "VAX byte ordering is unsupported for complex number type conversions");
456
457
0
next:
458
        /*
459
         * If we had used a temporary buffer for the destination then we
460
         * should copy the value to the true destination buffer.
461
         */
462
0
        if (d == dbuf)
463
0
            H5MM_memcpy(dp, d, dst_p->shared->size);
464
465
        /* Advance source & destination pointers by delta amounts */
466
0
        sp += src_delta;
467
0
        dp += dst_delta;
468
0
    } /* end conversion loop */
469
470
0
done:
471
0
    H5MM_free(src_rev);
472
473
0
    FUNC_LEAVE_NOAPI(ret_value)
474
0
} /* end H5T__conv_complex_loop() */
475
476
/*-------------------------------------------------------------------------
477
 * Function:    H5T__conv_complex_part
478
 *
479
 * Purpose:     Helper function to convert a single part (real or
480
 *              imaginary) of a complex number.
481
 *
482
 * NOTE:        The conversion logic in this function is essentially
483
 *              identical to the logic in the H5T__conv_f_f_loop function.
484
 *              However, conversion has to be performed on both the real
485
 *              and imaginary parts of each complex number element. Since
486
 *              complex numbers have the same representation as an array
487
 *              of two elements of the base floating-point type, this could
488
 *              be simulated in some cases with the H5T__conv_f_f_loop
489
 *              function by doubling the number of elements to be converted
490
 *              and halving the sizes involved. However, overlapping
491
 *              elements or a non-zero `buf_stride` value would complicate
492
 *              the buffer pointer advancements since each part of the
493
 *              complex number value has to be processed before advancing
494
 *              the buffer pointer. Conversion exceptions also pose a
495
 *              problem since both parts of the complex number have to be
496
 *              taken into account when determining if an exception
497
 *              occurred. Application conversion exception callbacks would
498
 *              also expect to receive an entire complex number rather than
499
 *              part of one. Therefore, the H5T__conv_f_f_loop logic is
500
 *              mostly duplicated here and fixes to one function should be
501
 *              made to the other, if appropriate.
502
 *
503
 * Return:      Non-negative on success/Negative on failure
504
 *
505
 *-------------------------------------------------------------------------
506
 */
507
static herr_t
508
H5T__conv_complex_part(const H5T_t *src_p, const H5T_t *dst_p, uint8_t *s, uint8_t *d,
509
                       const H5T_conv_ctx_t *conv_ctx, uint8_t *src_rev, bool *exception_handled)
510
0
{
511
0
    H5T_conv_ret_t except_ret = H5T_CONV_UNHANDLED; /* return of conversion exception callback function */
512
0
    H5T_atomic_t   src_atomic;                      /* source datatype atomic info                      */
513
0
    H5T_atomic_t   dst_atomic;                      /* destination datatype atomic info                 */
514
0
    hssize_t       expo_max;                        /* maximum possible dst exponent                    */
515
0
    ssize_t        mant_msb = 0;                    /* most significant bit set in mantissa             */
516
0
    int64_t        expo;                            /* exponent                                         */
517
0
    size_t         msize = 0;                       /* useful size of mantissa in src                   */
518
0
    size_t         mpos;                            /* offset to useful mant in src                     */
519
0
    size_t         mrsh;                            /* amount to right shift mantissa                   */
520
0
    size_t         implied;                         /* destination implied bits                         */
521
0
    bool           denormalized = false;            /* is either source or destination denormalized?    */
522
0
    bool           carry        = false;            /* carry after rounding mantissa                    */
523
0
    herr_t         ret_value    = SUCCEED;
524
525
0
    FUNC_ENTER_PACKAGE
526
527
0
    assert(src_p);
528
0
    assert(dst_p);
529
0
    assert(s);
530
0
    assert(d);
531
0
    assert(conv_ctx);
532
0
    assert(exception_handled);
533
534
0
    if (conv_ctx->u.conv.cb_struct.func)
535
0
        assert(src_rev);
536
537
0
    *exception_handled = false;
538
539
0
    src_atomic = src_p->shared->parent->shared->u.atomic;
540
0
    dst_atomic = dst_p->shared->parent->shared->u.atomic;
541
0
    expo_max   = ((hssize_t)1 << dst_atomic.u.f.esize) - 1;
542
543
    /*
544
     * Get the exponent as an unsigned quantity from the section of
545
     * the source bit field where it's located. Don't worry about
546
     * the exponent bias yet.
547
     */
548
0
    expo = (int64_t)H5T__bit_get_d(s, src_atomic.u.f.epos, src_atomic.u.f.esize);
549
550
0
    if (expo == 0)
551
0
        denormalized = true;
552
553
    /* Determine size of mantissa */
554
0
    if (0 == expo || H5T_NORM_NONE == src_atomic.u.f.norm) {
555
0
        if ((mant_msb = H5T__bit_find(s, src_atomic.u.f.mpos, src_atomic.u.f.msize, H5T_BIT_MSB, true)) > 0)
556
0
            msize = (size_t)mant_msb;
557
0
        else if (0 == mant_msb) {
558
0
            msize = 1;
559
0
            H5T__bit_set(s, src_atomic.u.f.mpos, (size_t)1, false);
560
0
        }
561
0
    }
562
0
    else if (H5T_NORM_IMPLIED == src_atomic.u.f.norm)
563
0
        msize = src_atomic.u.f.msize;
564
0
    else
565
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "normalization method not implemented yet");
566
567
    /*
568
     * The sign for the destination is the same as the sign for the
569
     * source in all cases.
570
     */
571
0
    H5T__bit_copy(d, dst_atomic.u.f.sign, s, src_atomic.u.f.sign, (size_t)1);
572
573
    /*
574
     * Calculate the true source exponent by adjusting according to
575
     * the source exponent bias.
576
     */
577
0
    if (0 == expo || H5T_NORM_NONE == src_atomic.u.f.norm) {
578
0
        assert(mant_msb >= 0);
579
0
        expo -= (int64_t)((src_atomic.u.f.ebias - 1) + (src_atomic.u.f.msize - (size_t)mant_msb));
580
0
    }
581
0
    else if (H5T_NORM_IMPLIED == src_atomic.u.f.norm)
582
0
        expo -= (int64_t)src_atomic.u.f.ebias;
583
0
    else
584
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "normalization method not implemented yet");
585
586
    /*
587
     * If the destination is not normalized then right shift the
588
     * mantissa by one.
589
     */
590
0
    mrsh = 0;
591
0
    if (H5T_NORM_NONE == dst_atomic.u.f.norm)
592
0
        mrsh++;
593
594
    /*
595
     * Calculate the destination exponent by adding the destination
596
     * bias and clipping by the minimum and maximum possible
597
     * destination exponent values.
598
     */
599
0
    expo += (int64_t)dst_atomic.u.f.ebias;
600
601
0
    if (expo < -(hssize_t)(dst_atomic.u.f.msize)) {
602
        /* The exponent is way too small. Result is zero. */
603
0
        expo = 0;
604
0
        H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false);
605
0
        msize = 0;
606
0
    }
607
0
    else if (expo <= 0) {
608
        /*
609
         * The exponent is too small to fit in the exponent field,
610
         * but by shifting the mantissa to the right we can
611
         * accommodate that value. The mantissa of course is no
612
         * longer normalized.
613
         */
614
0
        mrsh += (size_t)(1 - expo);
615
0
        expo         = 0;
616
0
        denormalized = true;
617
0
    }
618
0
    else if (expo >= expo_max) {
619
        /*
620
         * The exponent is too large to fit in the available region
621
         * or it results in the maximum possible value. Use positive
622
         * or negative infinity instead unless the application
623
         * specifies something else. Before calling the overflow
624
         * handler make sure the source buffer we hand it is in the
625
         * original byte order.
626
         */
627
0
        if (conv_ctx->u.conv.cb_struct.func) { /* If user's exception handler is present, use it */
628
            /* Reverse source buffer order first */
629
0
            H5T__reverse_order(src_rev, s, src_p);
630
631
            /* Prepare & restore library for user callback */
632
0
            H5_BEFORE_USER_CB(FAIL)
633
0
                {
634
0
                    except_ret = (conv_ctx->u.conv.cb_struct.func)(
635
0
                        H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id,
636
0
                        src_rev, d, conv_ctx->u.conv.cb_struct.user_data);
637
0
                }
638
0
            H5_AFTER_USER_CB(FAIL)
639
0
        }
640
641
0
        if (except_ret == H5T_CONV_UNHANDLED) {
642
0
            expo = expo_max;
643
0
            H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false);
644
0
            msize = 0;
645
0
        }
646
0
        else if (except_ret == H5T_CONV_HANDLED) {
647
0
            *exception_handled = true;
648
0
            goto done;
649
0
        }
650
0
        else if (except_ret == H5T_CONV_ABORT)
651
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");
652
0
    }
653
654
    /*
655
     * If the destination mantissa is smaller than the source
656
     * mantissa then round the source mantissa. Rounding may cause a
657
     * carry in which case the exponent has to be re-evaluated for
658
     * overflow. That is, if `carry' is clear then the implied
659
     * mantissa bit is `1', else it is `10' binary.
660
     */
661
0
    implied = 1;
662
0
    mpos    = src_atomic.u.f.mpos;
663
0
    if (msize > 0 && mrsh <= dst_atomic.u.f.msize && mrsh + msize > dst_atomic.u.f.msize) {
664
0
        mant_msb = (ssize_t)(mrsh + msize - dst_atomic.u.f.msize);
665
0
        assert(mant_msb >= 0 && (size_t)mant_msb <= msize);
666
        /* If the 1st bit being cut off is set and source isn't denormalized. */
667
0
        if (H5T__bit_get_d(s, (mpos + (size_t)mant_msb) - 1, (size_t)1) && !denormalized) {
668
            /* Don't do rounding if exponent is 111...110 and mantissa is 111...11.
669
             * To do rounding and increment exponent in this case will create an infinity value. */
670
0
            if ((H5T__bit_find(s, mpos + (size_t)mant_msb, msize - (size_t)mant_msb, H5T_BIT_LSB, false) >=
671
0
                     0 ||
672
0
                 expo < expo_max - 1)) {
673
0
                carry = H5T__bit_inc(s, mpos + (size_t)mant_msb - 1, 1 + msize - (size_t)mant_msb);
674
0
                if (carry)
675
0
                    implied = 2;
676
0
            }
677
0
        }
678
0
        else if (H5T__bit_get_d(s, (mpos + (size_t)mant_msb) - 1, (size_t)1) && denormalized)
679
            /* For either source or destination, denormalized value doesn't increment carry. */
680
0
            H5T__bit_inc(s, mpos + (size_t)mant_msb - 1, 1 + msize - (size_t)mant_msb);
681
0
    }
682
0
    else
683
0
        carry = false;
684
685
    /* Write the mantissa to the destination */
686
0
    if (mrsh > dst_atomic.u.f.msize + 1) {
687
0
        H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false);
688
0
    }
689
0
    else if (mrsh == dst_atomic.u.f.msize + 1) {
690
0
        H5T__bit_set(d, dst_atomic.u.f.mpos + 1, dst_atomic.u.f.msize - 1, false);
691
0
        H5T__bit_set(d, dst_atomic.u.f.mpos, (size_t)1, true);
692
0
    }
693
0
    else if (mrsh == dst_atomic.u.f.msize) {
694
0
        H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false);
695
0
        H5T__bit_set_d(d, dst_atomic.u.f.mpos, MIN(2, dst_atomic.u.f.msize), (hsize_t)implied);
696
0
    }
697
0
    else {
698
0
        if (mrsh > 0) {
699
0
            H5T__bit_set(d, dst_atomic.u.f.mpos + dst_atomic.u.f.msize - mrsh, mrsh, false);
700
0
            H5T__bit_set_d(d, dst_atomic.u.f.mpos + dst_atomic.u.f.msize - mrsh, (size_t)2, (hsize_t)implied);
701
0
        }
702
0
        if (mrsh + msize >= dst_atomic.u.f.msize) {
703
0
            H5T__bit_copy(d, dst_atomic.u.f.mpos, s, (mpos + msize + mrsh - dst_atomic.u.f.msize),
704
0
                          dst_atomic.u.f.msize - mrsh);
705
0
        }
706
0
        else {
707
0
            H5T__bit_copy(d, dst_atomic.u.f.mpos + dst_atomic.u.f.msize - (mrsh + msize), s, mpos, msize);
708
0
            H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize - (mrsh + msize), false);
709
0
        }
710
0
    }
711
712
    /* Write the exponent */
713
0
    if (carry) {
714
0
        expo++;
715
0
        if (expo >= expo_max) {
716
            /*
717
             * The exponent is too large to fit in the available
718
             * region or it results in the maximum possible value.
719
             * Use positive or negative infinity instead unless the
720
             * application specifies something else. Before calling
721
             * the overflow handler make sure the source buffer we
722
             * hand it is in the original byte order.
723
             */
724
0
            if (conv_ctx->u.conv.cb_struct.func) { /* If user's exception handler is present, use it */
725
                /* Reverse source buffer order first */
726
0
                H5T__reverse_order(src_rev, s, src_p);
727
728
                /* Prepare & restore library for user callback */
729
0
                H5_BEFORE_USER_CB(FAIL)
730
0
                    {
731
0
                        except_ret = (conv_ctx->u.conv.cb_struct.func)(
732
0
                            H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id,
733
0
                            conv_ctx->u.conv.dst_type_id, src_rev, d, conv_ctx->u.conv.cb_struct.user_data);
734
0
                    }
735
0
                H5_AFTER_USER_CB(FAIL)
736
0
            }
737
738
0
            if (except_ret == H5T_CONV_UNHANDLED) {
739
0
                expo = expo_max;
740
0
                H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false);
741
0
            }
742
0
            else if (except_ret == H5T_CONV_HANDLED) {
743
0
                *exception_handled = true;
744
0
                goto done;
745
0
            }
746
0
            else if (except_ret == H5T_CONV_ABORT)
747
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");
748
0
        }
749
0
    }
750
751
0
    H5_CHECK_OVERFLOW(expo, hssize_t, hsize_t);
752
0
    H5T__bit_set_d(d, dst_atomic.u.f.epos, dst_atomic.u.f.esize, (hsize_t)expo);
753
754
0
done:
755
0
    FUNC_LEAVE_NOAPI(ret_value)
756
0
}
757
758
/*-------------------------------------------------------------------------
759
 * Function:    H5T__conv_complex_i
760
 *
761
 * Purpose:     Convert complex number values to integer values. This is
762
 *              the catch-all function for complex number -> integer
763
 *              conversions and is probably not particularly fast.
764
 *
765
 * Return:      Non-negative on success/Negative on failure
766
 *
767
 *-------------------------------------------------------------------------
768
 */
769
herr_t
770
H5T__conv_complex_i(const H5T_t *src_p, const H5T_t *dst_p, H5T_cdata_t *cdata,
771
                    const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
772
                    size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
773
0
{
774
0
    herr_t ret_value = SUCCEED;
775
776
0
    FUNC_ENTER_PACKAGE
777
778
0
    switch (cdata->command) {
779
0
        case H5T_CONV_INIT: {
780
0
            H5T_atomic_t src_atomic; /* source datatype atomic info      */
781
0
            H5T_atomic_t dst_atomic; /* destination datatype atomic info */
782
783
0
            if (!src_p || !dst_p)
784
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
785
0
            if (!H5T_IS_ATOMIC(src_p->shared->parent->shared))
786
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid complex number datatype");
787
0
            src_atomic = src_p->shared->parent->shared->u.atomic;
788
0
            dst_atomic = dst_p->shared->u.atomic;
789
0
            if (H5T_ORDER_LE != src_atomic.order && H5T_ORDER_BE != src_atomic.order &&
790
0
                H5T_ORDER_VAX != src_atomic.order)
791
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
792
0
                            "unsupported byte order for source datatype");
793
0
            if (H5T_ORDER_LE != dst_atomic.order && H5T_ORDER_BE != dst_atomic.order &&
794
0
                H5T_ORDER_VAX != dst_atomic.order)
795
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
796
0
                            "unsupported byte order for destination datatype");
797
0
            if (dst_p->shared->size > TEMP_INT_CONV_BUFFER_SIZE)
798
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "destination datatype size is too large");
799
0
            if (8 * sizeof(hssize_t) - 1 < src_atomic.u.f.esize)
800
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "exponent field is too large");
801
0
            cdata->need_bkg = H5T_BKG_NO;
802
803
0
            break;
804
0
        }
805
806
0
        case H5T_CONV_FREE:
807
0
            break;
808
809
0
        case H5T_CONV_CONV:
810
0
            if (!src_p || !dst_p)
811
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
812
0
            if (NULL == conv_ctx)
813
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid datatype conversion context pointer");
814
815
0
            if (H5T__conv_f_i_loop(src_p, dst_p, conv_ctx, nelmts, buf_stride, buf) < 0)
816
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "unable to convert data values");
817
818
0
            break;
819
820
0
        default:
821
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command");
822
0
    }
823
824
0
done:
825
0
    FUNC_LEAVE_NOAPI(ret_value)
826
0
} /* end H5T__conv_complex_i() */
827
828
/*-------------------------------------------------------------------------
829
 * Function:    H5T__conv_complex_f
830
 *
831
 * Purpose:     Convert complex number values to floating-point values.
832
 *              This is the catch-all function for complex number -> float
833
 *              conversions and is probably not particularly fast.
834
 *
835
 * Return:      Non-negative on success/Negative on failure
836
 *
837
 *-------------------------------------------------------------------------
838
 */
839
herr_t
840
H5T__conv_complex_f(const H5T_t *src_p, const H5T_t *dst_p, H5T_cdata_t *cdata,
841
                    const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
842
                    size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
843
0
{
844
0
    bool   equal_cplx_conv = false; /* if converting between complex and matching float */
845
0
    herr_t ret_value       = SUCCEED;
846
847
0
    FUNC_ENTER_PACKAGE
848
849
0
    switch (cdata->command) {
850
0
        case H5T_CONV_INIT: {
851
0
            H5T_atomic_t src_atomic; /* source datatype atomic info                      */
852
0
            H5T_atomic_t dst_atomic; /* destination datatype atomic info                 */
853
854
0
            if (!src_p || !dst_p)
855
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
856
0
            if (!H5T_IS_ATOMIC(src_p->shared->parent->shared))
857
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid complex number datatype");
858
0
            src_atomic = src_p->shared->parent->shared->u.atomic;
859
0
            dst_atomic = dst_p->shared->u.atomic;
860
0
            if (H5T_ORDER_LE != src_atomic.order && H5T_ORDER_BE != src_atomic.order &&
861
0
                H5T_ORDER_VAX != src_atomic.order)
862
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
863
0
                            "unsupported byte order for source datatype");
864
0
            if (H5T_ORDER_LE != dst_atomic.order && H5T_ORDER_BE != dst_atomic.order &&
865
0
                H5T_ORDER_VAX != dst_atomic.order)
866
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
867
0
                            "unsupported byte order for destination datatype");
868
0
            if (dst_p->shared->size > TEMP_FLOAT_CONV_BUFFER_SIZE)
869
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "destination datatype size is too large");
870
0
            if (8 * sizeof(int64_t) - 1 < src_atomic.u.f.esize ||
871
0
                8 * sizeof(int64_t) - 1 < dst_atomic.u.f.esize)
872
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "exponent field is too large");
873
0
            cdata->need_bkg = H5T_BKG_NO;
874
875
0
            break;
876
0
        }
877
878
0
        case H5T_CONV_FREE:
879
0
            break;
880
881
0
        case H5T_CONV_CONV:
882
0
            if (!src_p || !dst_p)
883
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
884
0
            if (NULL == conv_ctx)
885
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid datatype conversion context pointer");
886
887
            /* Are we converting between a floating-point type and a complex number
888
             * type consisting of the same floating-point type?
889
             */
890
0
            equal_cplx_conv = (0 == H5T_cmp(src_p->shared->parent, dst_p, false));
891
0
            if (!equal_cplx_conv) {
892
                /* If floating-point types differ, use generic f_f loop */
893
0
                if (H5T__conv_f_f_loop(src_p, dst_p, conv_ctx, nelmts, buf_stride, buf) < 0)
894
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "unable to convert data values");
895
0
            }
896
0
            else {
897
                /* If floating-point types are the same, use specialized loop */
898
0
                if (H5T__conv_complex_f_matched(src_p, dst_p, conv_ctx, nelmts, buf_stride, buf) < 0)
899
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "unable to convert data values");
900
0
            }
901
902
0
            break;
903
904
0
        default:
905
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command");
906
0
    }
907
908
0
done:
909
0
    FUNC_LEAVE_NOAPI(ret_value)
910
0
} /* end H5T__conv_complex_f() */
911
912
/*-------------------------------------------------------------------------
913
 * Function:    H5T__conv_complex_f_matched
914
 *
915
 * Purpose:     Implements the body of the conversion loop when converting
916
 *              between a floating-point type and a complex number type
917
 *              consisting of the same floating-point type. Encapsulates
918
 *              common code that is shared between the H5T__conv_complex_f
919
 *              and H5T__conv_f_complex functions. Values can be directly
920
 *              converted between the types after checking for conversion
921
 *              exceptions.
922
 *
923
 * Return:      Non-negative on success/Negative on failure
924
 *
925
 *-------------------------------------------------------------------------
926
 */
927
herr_t
928
H5T__conv_complex_f_matched(const H5T_t *src_p, const H5T_t *dst_p, const H5T_conv_ctx_t *conv_ctx,
929
                            size_t nelmts, size_t buf_stride, void *buf)
930
0
{
931
0
    H5T_conv_float_specval_t specval_type;      /* floating-point value type (regular, +/-Inf, +/-0, NaN) */
932
0
    H5T_atomic_t             src_atomic;        /* source datatype atomic info                            */
933
0
    H5T_atomic_t             dst_atomic;        /* destination datatype atomic info                       */
934
0
    ssize_t  src_delta, dst_delta;              /* source & destination stride                            */
935
0
    uint8_t *s, *sp, *d, *dp;                   /* source and dest traversal ptrs                         */
936
0
    uint8_t *src_rev = NULL;                    /* order-reversed source buffer                           */
937
0
    uint8_t  dbuf[TEMP_FLOAT_CONV_BUFFER_SIZE]; /* temp destination buffer                                */
938
0
    size_t   olap;                              /* num overlapping elements                               */
939
0
    int      direction;                         /* forward or backward traversal                          */
940
0
    herr_t   ret_value = SUCCEED;
941
942
0
    assert(src_p);
943
0
    assert(src_p->shared->type == H5T_FLOAT || src_p->shared->type == H5T_COMPLEX);
944
0
    assert(dst_p);
945
0
    assert(dst_p->shared->type == H5T_FLOAT || dst_p->shared->type == H5T_COMPLEX);
946
0
    assert(conv_ctx);
947
0
    assert(buf);
948
949
0
    FUNC_ENTER_PACKAGE
950
951
0
    if (src_p->shared->type == H5T_COMPLEX)
952
0
        src_atomic = src_p->shared->parent->shared->u.atomic;
953
0
    else
954
0
        src_atomic = src_p->shared->u.atomic;
955
0
    if (dst_p->shared->type == H5T_COMPLEX)
956
0
        dst_atomic = dst_p->shared->parent->shared->u.atomic;
957
0
    else
958
0
        dst_atomic = dst_p->shared->u.atomic;
959
960
#ifndef NDEBUG
961
    {
962
        /* Make sure the floating-point types match */
963
        const H5T_t *src_base = (src_p->shared->type == H5T_FLOAT) ? src_p : src_p->shared->parent;
964
        const H5T_t *dst_base = (dst_p->shared->type == H5T_FLOAT) ? dst_p : dst_p->shared->parent;
965
        assert(0 == (H5T_cmp(src_base, dst_base, false)));
966
    }
967
#endif
968
969
    /*
970
     * Do we process the values from beginning to end or vice versa? Also,
971
     * how many of the elements have the source and destination areas
972
     * overlapping?
973
     */
974
0
    if (src_p->shared->size == dst_p->shared->size || buf_stride) {
975
0
        sp = dp   = (uint8_t *)buf;
976
0
        direction = 1;
977
0
        olap      = nelmts;
978
0
    }
979
0
    else if (src_p->shared->size >= dst_p->shared->size) {
980
0
        double olap_d =
981
0
            ceil((double)(dst_p->shared->size) / (double)(src_p->shared->size - dst_p->shared->size));
982
0
        olap = (size_t)olap_d;
983
0
        sp = dp   = (uint8_t *)buf;
984
0
        direction = 1;
985
0
    }
986
0
    else {
987
0
        double olap_d =
988
0
            ceil((double)(src_p->shared->size) / (double)(dst_p->shared->size - src_p->shared->size));
989
0
        olap      = (size_t)olap_d;
990
0
        sp        = (uint8_t *)buf + (nelmts - 1) * src_p->shared->size;
991
0
        dp        = (uint8_t *)buf + (nelmts - 1) * dst_p->shared->size;
992
0
        direction = -1;
993
0
    }
994
995
    /* Direction & size of buffer traversal */
996
0
    H5_CHECK_OVERFLOW(buf_stride, size_t, ssize_t);
997
0
    H5_CHECK_OVERFLOW(src_p->shared->size, size_t, ssize_t);
998
0
    H5_CHECK_OVERFLOW(dst_p->shared->size, size_t, ssize_t);
999
0
    src_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : src_p->shared->size);
1000
0
    dst_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : dst_p->shared->size);
1001
1002
    /* Allocate space for order-reversed source buffer */
1003
0
    if (conv_ctx->u.conv.cb_struct.func)
1004
0
        if (NULL == (src_rev = H5MM_calloc(src_p->shared->size)))
1005
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "couldn't allocate temporary buffer");
1006
1007
    /* The conversion loop */
1008
0
    for (size_t elmtno = 0; elmtno < nelmts; elmtno++) {
1009
0
        H5T_conv_ret_t except_ret = H5T_CONV_UNHANDLED; /* return of conversion exception callback function */
1010
0
        bool           reverse    = true;               /* if reversed the order of destination             */
1011
1012
        /*
1013
         * If the source and destination buffers overlap then use a
1014
         * temporary buffer for the destination.
1015
         */
1016
0
        s = sp;
1017
0
        if (direction > 0)
1018
0
            d = elmtno < olap ? dbuf : dp;
1019
0
        else
1020
0
            d = elmtno + olap >= nelmts ? dbuf : dp;
1021
0
        if (d == dbuf)
1022
0
            memset(dbuf, 0, sizeof(dbuf));
1023
1024
#ifndef NDEBUG
1025
        if (d == dbuf) {
1026
            assert((dp >= sp && dp < sp + src_p->shared->size) ||
1027
                   (sp >= dp && sp < dp + dst_p->shared->size));
1028
        }
1029
        else {
1030
            assert((dp < sp && dp + dst_p->shared->size <= sp) ||
1031
                   (sp < dp && sp + src_p->shared->size <= dp));
1032
        }
1033
#endif
1034
1035
        /*
1036
         * Put the data in little endian order so our loops aren't so
1037
         * complicated. We'll do all the conversion stuff assuming
1038
         * little endian and then we'll fix the order at the end.
1039
         */
1040
0
        if (H5T_ORDER_BE == src_atomic.order) {
1041
0
            size_t half_size = src_p->shared->size / 2;
1042
1043
0
            if (H5T_FLOAT == src_p->shared->type) {
1044
0
                for (size_t j = 0; j < half_size; j++)
1045
0
                    H5_SWAP_BYTES(s, j, src_p->shared->size - (j + 1));
1046
0
            }
1047
0
            else {
1048
0
                uint8_t *cur_part = s;
1049
                /* Swap real part of complex number element */
1050
0
                for (size_t j = 0; j < half_size / 2; j++)
1051
0
                    H5_SWAP_BYTES(cur_part, j, half_size - (j + 1));
1052
                /* Swap imaginary part of complex number element */
1053
0
                cur_part += half_size;
1054
0
                for (size_t j = 0; j < half_size / 2; j++)
1055
0
                    H5_SWAP_BYTES(cur_part, j, half_size - (j + 1));
1056
0
            }
1057
0
        }
1058
0
        else if (H5T_ORDER_VAX == src_atomic.order) {
1059
0
            if (H5T_FLOAT == src_p->shared->type) {
1060
0
                uint8_t tmp1, tmp2;
1061
0
                size_t  tsize = src_p->shared->size;
1062
0
                assert(0 == tsize % 2);
1063
1064
0
                for (size_t i = 0; i < tsize; i += 4) {
1065
0
                    tmp1 = s[i];
1066
0
                    tmp2 = s[i + 1];
1067
1068
0
                    s[i]     = s[(tsize - 2) - i];
1069
0
                    s[i + 1] = s[(tsize - 1) - i];
1070
1071
0
                    s[(tsize - 2) - i] = tmp1;
1072
0
                    s[(tsize - 1) - i] = tmp2;
1073
0
                }
1074
0
            }
1075
0
            else
1076
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
1077
0
                            "VAX byte ordering is unsupported for complex number type conversions");
1078
0
        }
1079
1080
        /* Check for special cases: +0, -0, +Inf, -Inf, NaN */
1081
0
        specval_type = H5T__conv_float_find_special(s, &src_atomic, NULL);
1082
0
        if (specval_type == H5T_CONV_FLOAT_SPECVAL_POSZERO ||
1083
0
            specval_type == H5T_CONV_FLOAT_SPECVAL_NEGZERO) {
1084
0
            H5T__bit_copy(d, dst_atomic.u.f.sign, s, src_atomic.u.f.sign, (size_t)1);
1085
0
            H5T__bit_set(d, dst_atomic.u.f.epos, dst_atomic.u.f.esize, false);
1086
0
            H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false);
1087
0
            goto padding;
1088
0
        }
1089
0
        else if (specval_type != H5T_CONV_FLOAT_SPECVAL_REGULAR) {
1090
            /* If user's exception handler is present, use it */
1091
0
            if (conv_ctx->u.conv.cb_struct.func) {
1092
0
                H5T_conv_except_t except_type; /* type of conversion exception that occurred */
1093
1094
                /* Reverse source buffer order first */
1095
0
                H5T__reverse_order(src_rev, s, src_p);
1096
1097
0
                if (specval_type == H5T_CONV_FLOAT_SPECVAL_POSINF)
1098
0
                    except_type = H5T_CONV_EXCEPT_PINF;
1099
0
                else if (specval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF)
1100
0
                    except_type = H5T_CONV_EXCEPT_NINF;
1101
0
                else
1102
0
                    except_type = H5T_CONV_EXCEPT_NAN;
1103
1104
                /* Prepare & restore library for user callback */
1105
0
                H5_BEFORE_USER_CB(FAIL)
1106
0
                    {
1107
0
                        except_ret = (conv_ctx->u.conv.cb_struct.func)(
1108
0
                            except_type, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, src_rev,
1109
0
                            d, conv_ctx->u.conv.cb_struct.user_data);
1110
0
                    }
1111
0
                H5_AFTER_USER_CB(FAIL)
1112
0
            }
1113
1114
0
            if (except_ret == H5T_CONV_UNHANDLED) {
1115
0
                H5T__bit_copy(d, dst_atomic.u.f.sign, s, src_atomic.u.f.sign, (size_t)1);
1116
0
                H5T__bit_set(d, dst_atomic.u.f.epos, dst_atomic.u.f.esize, true);
1117
0
                if (specval_type == H5T_CONV_FLOAT_SPECVAL_NAN)
1118
                    /* There are many NaN values, so we just set all bits of the significand. */
1119
0
                    H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, true);
1120
0
                else {
1121
                    /* +/-Inf */
1122
0
                    H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false);
1123
                    /* If the destination has no implied mantissa bit, we'll need to set
1124
                     * the 1st bit of mantissa to 1. The Intel-Linux "long double" is
1125
                     * this case. */
1126
0
                    if (H5T_NORM_NONE == dst_atomic.u.f.norm)
1127
0
                        H5T__bit_set(d, dst_atomic.u.f.mpos + dst_atomic.u.f.msize - 1, (size_t)1, true);
1128
0
                }
1129
0
            }
1130
0
            else if (except_ret == H5T_CONV_HANDLED) {
1131
                /* No need to reverse the order of destination because user handles it */
1132
0
                reverse = false;
1133
0
                goto next;
1134
0
            }
1135
0
            else if (except_ret == H5T_CONV_ABORT)
1136
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception");
1137
1138
0
            goto padding;
1139
0
        }
1140
1141
        /* Direct copy between complex number and floating-point type */
1142
0
        if (H5T_FLOAT == src_p->shared->type)
1143
0
            memcpy(d, s, src_p->shared->size);
1144
0
        else
1145
0
            memcpy(d, s, src_p->shared->size / 2);
1146
1147
0
padding:
1148
        /*
1149
         * Set external padding areas
1150
         */
1151
0
        if (dst_atomic.offset > 0) {
1152
0
            assert(H5T_PAD_ZERO == dst_atomic.lsb_pad || H5T_PAD_ONE == dst_atomic.lsb_pad);
1153
0
            H5T__bit_set(d, (size_t)0, dst_atomic.offset, (bool)(H5T_PAD_ONE == dst_atomic.lsb_pad));
1154
0
        }
1155
0
        {
1156
0
            size_t type_size;
1157
1158
0
            if (dst_p->shared->type == H5T_FLOAT)
1159
0
                type_size = dst_p->shared->size;
1160
0
            else
1161
0
                type_size = dst_p->shared->parent->shared->size;
1162
1163
0
            if (dst_atomic.offset + dst_atomic.prec != 8 * type_size) {
1164
0
                assert(H5T_PAD_ZERO == dst_atomic.msb_pad || H5T_PAD_ONE == dst_atomic.msb_pad);
1165
0
                H5T__bit_set(d, dst_atomic.offset + dst_atomic.prec,
1166
0
                             8 * type_size - (dst_atomic.offset + dst_atomic.prec),
1167
0
                             (bool)(H5T_PAD_ONE == dst_atomic.msb_pad));
1168
0
            }
1169
0
        }
1170
1171
        /*
1172
         * Put the destination in the correct byte order. See note at
1173
         * beginning of loop. Only the "real" part of a complex number
1174
         * element is swapped. By the C standard, the "imaginary" part
1175
         * should just be zeroed when converting a real value to a
1176
         * complex value.
1177
         */
1178
0
        if (H5T_ORDER_BE == dst_atomic.order && reverse) {
1179
0
            size_t half_size = dst_p->shared->size / 2;
1180
1181
0
            if (H5T_FLOAT == dst_p->shared->type) {
1182
0
                for (size_t j = 0; j < half_size; j++)
1183
0
                    H5_SWAP_BYTES(d, j, dst_p->shared->size - (j + 1));
1184
0
            }
1185
0
            else {
1186
0
                for (size_t j = 0; j < half_size / 2; j++)
1187
0
                    H5_SWAP_BYTES(d, j, half_size - (j + 1));
1188
0
            }
1189
0
        }
1190
0
        else if (H5T_ORDER_VAX == dst_atomic.order && reverse) {
1191
0
            if (H5T_FLOAT == dst_p->shared->type) {
1192
0
                uint8_t tmp1, tmp2;
1193
0
                size_t  tsize = dst_p->shared->size / 2;
1194
0
                assert(0 == tsize % 2);
1195
1196
0
                for (size_t i = 0; i < tsize; i += 4) {
1197
0
                    tmp1 = d[i];
1198
0
                    tmp2 = d[i + 1];
1199
1200
0
                    d[i]     = d[(tsize - 2) - i];
1201
0
                    d[i + 1] = d[(tsize - 1) - i];
1202
1203
0
                    d[(tsize - 2) - i] = tmp1;
1204
0
                    d[(tsize - 1) - i] = tmp2;
1205
0
                }
1206
0
            }
1207
0
            else
1208
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
1209
0
                            "VAX byte ordering is unsupported for complex number type conversions");
1210
0
        }
1211
1212
0
next:
1213
        /*
1214
         * If we had used a temporary buffer for the destination then we
1215
         * should copy the value to the true destination buffer.
1216
         */
1217
0
        if (d == dbuf) {
1218
0
            if (H5T_FLOAT == dst_p->shared->type)
1219
0
                H5MM_memcpy(dp, d, dst_p->shared->size);
1220
0
            else
1221
0
                H5MM_memcpy(dp, d, dst_p->shared->size / 2);
1222
0
        }
1223
1224
        /* Ensure imaginary part of complex number is zeroed */
1225
0
        if (H5T_COMPLEX == dst_p->shared->type)
1226
0
            memset(dp + (dst_p->shared->size / 2), 0, dst_p->shared->size / 2);
1227
1228
        /* Advance source & destination pointers by delta amounts */
1229
0
        sp += src_delta;
1230
0
        dp += dst_delta;
1231
0
    } /* end conversion loop */
1232
1233
0
done:
1234
0
    H5MM_free(src_rev);
1235
1236
0
    FUNC_LEAVE_NOAPI(ret_value)
1237
0
} /* end H5T__conv_complex_f_matched() */
1238
1239
/*-------------------------------------------------------------------------
1240
 * Function:    H5T__conv_complex_compat
1241
 *
1242
 * Purpose:     Performs a no-op conversion between a complex number type
1243
 *              and an equivalent datatype. Complex number types are
1244
 *              considered equivalent to the following:
1245
 *
1246
 *              - An array datatype consisting of two elements where each
1247
 *                element is of the same floating-point datatype as the
1248
 *                complex number type's base floating-point datatype
1249
 *
1250
 *              - A compound datatype consisting of two fields where each
1251
 *                field is of the same floating-point datatype as the
1252
 *                complex number type's base floating-point datatype. The
1253
 *                compound datatype must not have any leading or trailing
1254
 *                structure padding or any padding between its two fields.
1255
 *                The fields must also have compatible names, must have
1256
 *                compatible offsets within the datatype and must be in
1257
 *                the order of "real" part -> "imaginary" part, such that
1258
 *                the compound datatype matches the following representation:
1259
 *
1260
 *                H5T_COMPOUND {
1261
 *                    <float_type> "r(e)(a)(l)";                OFFSET 0
1262
 *                    <float_type> "i(m)(a)(g)(i)(n)(a)(r)(y)"; OFFSET SIZEOF("r(e)(a)(l)")
1263
 *                }
1264
 *
1265
 *                where "r(e)(a)(l)" means the field may be named any
1266
 *                substring of "real", such as "r", or "re" and
1267
 *                "i(m)(a)(g)(i)(n)(a)(r)(y)" means the field may be named
1268
 *                any substring of "imaginary", such as "im" or "imag".
1269
 *
1270
 * Return:      Non-negative on success/Negative on failure
1271
 *
1272
 *-------------------------------------------------------------------------
1273
 */
1274
herr_t
1275
H5T__conv_complex_compat(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata,
1276
                         const H5T_conv_ctx_t H5_ATTR_UNUSED *conv_ctx, size_t H5_ATTR_UNUSED nelmts,
1277
                         size_t H5_ATTR_UNUSED buf_stride, size_t H5_ATTR_UNUSED bkg_stride,
1278
                         void H5_ATTR_UNUSED *_buf, void H5_ATTR_UNUSED *bkg)
1279
0
{
1280
0
    H5T_t *compound_copy = NULL;
1281
0
    herr_t ret_value     = SUCCEED;
1282
1283
0
    FUNC_ENTER_PACKAGE
1284
1285
0
    switch (cdata->command) {
1286
0
        case H5T_CONV_INIT: {
1287
0
            const H5T_t *complex_type;
1288
0
            const H5T_t *other_type;
1289
1290
0
            if (src->shared->type == H5T_COMPLEX) {
1291
0
                if (dst->shared->type != H5T_ARRAY && dst->shared->type != H5T_COMPOUND)
1292
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
1293
0
                                "unsupported destination datatype for conversion");
1294
0
                complex_type = src;
1295
0
                other_type   = dst;
1296
0
            }
1297
0
            else {
1298
0
                if (dst->shared->type != H5T_COMPLEX)
1299
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
1300
0
                                "unsupported destination datatype for conversion");
1301
0
                complex_type = dst;
1302
0
                other_type   = src;
1303
0
            }
1304
1305
0
            if (complex_type->shared->u.cplx.form != H5T_COMPLEX_RECTANGULAR)
1306
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
1307
0
                            "unsupported form of complex number datatype for conversion");
1308
1309
0
            if (other_type->shared->type == H5T_ARRAY) {
1310
0
                if (other_type->shared->u.array.nelem != 2)
1311
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
1312
0
                                "array datatype doesn't have the correct number of elements for conversion");
1313
0
                if (H5T_cmp(other_type->shared->parent, complex_type->shared->parent, false))
1314
0
                    HGOTO_ERROR(
1315
0
                        H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
1316
0
                        "array datatype's base datatype doesn't match complex number type's base datatype");
1317
0
            }
1318
0
            else {
1319
0
                H5T_cmemb_t *fields;
1320
0
                size_t       name_len;
1321
1322
0
                assert(other_type->shared->type == H5T_COMPOUND);
1323
1324
0
                if (other_type->shared->u.compnd.nmembs != 2)
1325
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
1326
0
                                "compound datatype doesn't have the correct number of fields for conversion");
1327
0
                if (!other_type->shared->u.compnd.packed)
1328
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
1329
0
                                "compound datatype fields aren't packed together");
1330
0
                if (other_type->shared->u.compnd.memb_size != complex_type->shared->size)
1331
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
1332
0
                                "compound datatype size doesn't match size of complex number datatype");
1333
1334
                /* Make sure members are unsorted or sorted according to
1335
                 * their offsets before checking their names
1336
                 */
1337
0
                if (other_type->shared->u.compnd.sorted == H5T_SORT_NONE ||
1338
0
                    other_type->shared->u.compnd.sorted == H5T_SORT_VALUE)
1339
0
                    fields = other_type->shared->u.compnd.memb;
1340
0
                else {
1341
                    /* Make a copy so the sort order of the original type isn't disturbed */
1342
0
                    if (NULL == (compound_copy = H5T_copy(other_type, H5T_COPY_TRANSIENT)))
1343
0
                        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy datatype");
1344
1345
0
                    H5T__sort_value(compound_copy, NULL);
1346
0
                    fields = compound_copy->shared->u.compnd.memb;
1347
0
                }
1348
1349
                /* Check "real" part of compound datatype */
1350
0
                if (fields[0].offset != 0)
1351
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
1352
0
                                "compound datatype's 'real' field is not at offset 0");
1353
0
                if (fields[0].size != complex_type->shared->parent->shared->size)
1354
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
1355
0
                                "compound datatype's 'real' field is not the same size as the complex number "
1356
0
                                "datatype's base datatype");
1357
1358
                /* Match up to 5 characters (including the NUL terminator) from the
1359
                 * field name to a substring of "real".
1360
                 */
1361
0
                name_len = strlen(fields[0].name);
1362
0
                if (strncmp(fields[0].name, "real", (name_len < 5) ? name_len : 5))
1363
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
1364
0
                                "compound datatype's 'real' field name ('%s') didn't match an expected name "
1365
0
                                "for conversion",
1366
0
                                fields[0].name);
1367
1368
0
                if (H5T_cmp(fields[0].type, complex_type->shared->parent, false))
1369
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
1370
0
                                "compound datatype's 'real' field is not the same datatype as the complex "
1371
0
                                "number datatype's base datatype");
1372
1373
                /* Check "imaginary" part of compound datatype */
1374
0
                if (fields[1].offset != fields[0].size)
1375
0
                    HGOTO_ERROR(
1376
0
                        H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
1377
0
                        "compound datatype's 'imaginary' field is not at offset 'sizeof(real_field)'");
1378
0
                if (fields[1].size != complex_type->shared->parent->shared->size)
1379
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
1380
0
                                "compound datatype's 'imaginary' field is not the same size as the complex "
1381
0
                                "number datatype's base datatype");
1382
1383
                /* Match up to 10 characters (including the NUL terminator) from the
1384
                 * field name to a substring of "imaginary".
1385
                 */
1386
0
                name_len = strlen(fields[1].name);
1387
0
                if (strncmp(fields[1].name, "imaginary", (name_len < 10) ? name_len : 10))
1388
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
1389
0
                                "compound datatype's 'imaginary' field name ('%s') didn't match an expected "
1390
0
                                "name for conversion",
1391
0
                                fields[1].name);
1392
1393
0
                if (H5T_cmp(fields[1].type, complex_type->shared->parent, false))
1394
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
1395
0
                                "compound datatype's 'imaginary' field is not the same datatype as the "
1396
0
                                "complex number datatype's base datatype");
1397
0
            }
1398
1399
0
            cdata->need_bkg = H5T_BKG_NO;
1400
1401
0
            break;
1402
0
        }
1403
1404
0
        case H5T_CONV_FREE:
1405
0
            break;
1406
1407
0
        case H5T_CONV_CONV:
1408
            /* no-op as the types should be equivalent */
1409
0
            break;
1410
1411
0
        default:
1412
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command");
1413
0
    }
1414
1415
0
done:
1416
0
    if (compound_copy && H5T_close(compound_copy) < 0)
1417
0
        HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "can't close datatype");
1418
1419
0
    FUNC_LEAVE_NOAPI(ret_value)
1420
0
} /* end H5T__conv_complex_compat() */
1421
1422
#ifdef H5_HAVE_COMPLEX_NUMBERS
1423
/*-------------------------------------------------------------------------
1424
 * Function:    H5T__conv_fcomplex_schar
1425
 *
1426
 * Purpose:     Converts `float _Complex' / `_Fcomplex' to `signed char'
1427
 *
1428
 * Return:      Non-negative on success/Negative on failure
1429
 *
1430
 *-------------------------------------------------------------------------
1431
 */
1432
herr_t
1433
H5T__conv_fcomplex_schar(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
1434
                         size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
1435
                         void H5_ATTR_UNUSED *bkg)
1436
2
{
1437
2
    H5_WARN_FLOAT_EQUAL_OFF
1438
2
    H5T_CONV_Zx(FLOAT_COMPLEX, SCHAR, H5_float_complex, signed char, SCHAR_MIN, SCHAR_MAX);
1439
2
    H5_WARN_FLOAT_EQUAL_ON
1440
2
}
1441
1442
/*-------------------------------------------------------------------------
1443
 * Function:    H5T__conv_fcomplex_uchar
1444
 *
1445
 * Purpose:     Converts `float _Complex' / `_Fcomplex' to `unsigned char'
1446
 *
1447
 * Return:      Non-negative on success/Negative on failure
1448
 *
1449
 *-------------------------------------------------------------------------
1450
 */
1451
herr_t
1452
H5T__conv_fcomplex_uchar(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
1453
                         size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
1454
                         void H5_ATTR_UNUSED *bkg)
1455
2
{
1456
2
    H5_WARN_FLOAT_EQUAL_OFF
1457
2
    H5T_CONV_Zx(FLOAT_COMPLEX, UCHAR, H5_float_complex, unsigned char, 0, UCHAR_MAX);
1458
2
    H5_WARN_FLOAT_EQUAL_ON
1459
2
}
1460
1461
/*-------------------------------------------------------------------------
1462
 * Function:    H5T__conv_fcomplex_short
1463
 *
1464
 * Purpose:     Converts `float _Complex' / `_Fcomplex' to `short'
1465
 *
1466
 * Return:      Non-negative on success/Negative on failure
1467
 *
1468
 *-------------------------------------------------------------------------
1469
 */
1470
herr_t
1471
H5T__conv_fcomplex_short(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
1472
                         size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
1473
                         void H5_ATTR_UNUSED *bkg)
1474
2
{
1475
2
    H5_WARN_FLOAT_EQUAL_OFF
1476
2
    H5T_CONV_Zx(FLOAT_COMPLEX, SHORT, H5_float_complex, short, SHRT_MIN, SHRT_MAX);
1477
2
    H5_WARN_FLOAT_EQUAL_ON
1478
2
}
1479
1480
/*-------------------------------------------------------------------------
1481
 * Function:    H5T__conv_fcomplex_ushort
1482
 *
1483
 * Purpose:     Converts `float _Complex' / `_Fcomplex' to `unsigned short'
1484
 *
1485
 * Return:      Non-negative on success/Negative on failure
1486
 *
1487
 *-------------------------------------------------------------------------
1488
 */
1489
herr_t
1490
H5T__conv_fcomplex_ushort(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
1491
                          const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
1492
                          size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
1493
2
{
1494
2
    H5_WARN_FLOAT_EQUAL_OFF
1495
2
    H5T_CONV_Zx(FLOAT_COMPLEX, USHORT, H5_float_complex, unsigned short, 0, USHRT_MAX);
1496
2
    H5_WARN_FLOAT_EQUAL_ON
1497
2
}
1498
1499
/*-------------------------------------------------------------------------
1500
 * Function:    H5T__conv_fcomplex_int
1501
 *
1502
 * Purpose:     Converts `float _Complex' / `_Fcomplex' to `int'
1503
 *
1504
 * Return:      Non-negative on success/Negative on failure
1505
 *
1506
 *-------------------------------------------------------------------------
1507
 */
1508
herr_t
1509
H5T__conv_fcomplex_int(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
1510
                       size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
1511
                       void H5_ATTR_UNUSED *bkg)
1512
2
{
1513
2
    H5_WARN_FLOAT_EQUAL_OFF
1514
2
    H5T_CONV_Zx(FLOAT_COMPLEX, INT, H5_float_complex, int, INT_MIN, INT_MAX);
1515
2
    H5_WARN_FLOAT_EQUAL_ON
1516
2
}
1517
1518
/*-------------------------------------------------------------------------
1519
 * Function:    H5T__conv_fcomplex_uint
1520
 *
1521
 * Purpose:     Converts `float _Complex' / `_Fcomplex' to `unsigned int'
1522
 *
1523
 * Return:      Non-negative on success/Negative on failure
1524
 *
1525
 *-------------------------------------------------------------------------
1526
 */
1527
herr_t
1528
H5T__conv_fcomplex_uint(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
1529
                        size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
1530
                        void H5_ATTR_UNUSED *bkg)
1531
2
{
1532
2
    H5_WARN_FLOAT_EQUAL_OFF
1533
2
    H5T_CONV_Zx(FLOAT_COMPLEX, UINT, H5_float_complex, unsigned int, 0, UINT_MAX);
1534
2
    H5_WARN_FLOAT_EQUAL_ON
1535
2
}
1536
1537
/*-------------------------------------------------------------------------
1538
 * Function:    H5T__conv_fcomplex_long
1539
 *
1540
 * Purpose:     Converts `float _Complex' / `_Fcomplex' to `long'
1541
 *
1542
 * Return:      Non-negative on success/Negative on failure
1543
 *
1544
 *-------------------------------------------------------------------------
1545
 */
1546
herr_t
1547
H5T__conv_fcomplex_long(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
1548
                        size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
1549
                        void H5_ATTR_UNUSED *bkg)
1550
2
{
1551
2
    H5_WARN_FLOAT_EQUAL_OFF
1552
2
    H5T_CONV_Zx(FLOAT_COMPLEX, LONG, H5_float_complex, long, LONG_MIN, LONG_MAX);
1553
2
    H5_WARN_FLOAT_EQUAL_ON
1554
2
}
1555
1556
/*-------------------------------------------------------------------------
1557
 * Function:    H5T__conv_fcomplex_ulong
1558
 *
1559
 * Purpose:     Converts `float _Complex' / `_Fcomplex' to `unsigned long'
1560
 *
1561
 * Return:      Non-negative on success/Negative on failure
1562
 *
1563
 *-------------------------------------------------------------------------
1564
 */
1565
herr_t
1566
H5T__conv_fcomplex_ulong(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
1567
                         size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
1568
                         void H5_ATTR_UNUSED *bkg)
1569
2
{
1570
2
    H5_WARN_FLOAT_EQUAL_OFF
1571
2
    H5T_CONV_Zx(FLOAT_COMPLEX, ULONG, H5_float_complex, unsigned long, 0, ULONG_MAX);
1572
2
    H5_WARN_FLOAT_EQUAL_ON
1573
2
}
1574
1575
/*-------------------------------------------------------------------------
1576
 * Function:    H5T__conv_fcomplex_llong
1577
 *
1578
 * Purpose:     Converts `float _Complex' / `_Fcomplex' to `long long'
1579
 *
1580
 * Return:      Non-negative on success/Negative on failure
1581
 *
1582
 *-------------------------------------------------------------------------
1583
 */
1584
herr_t
1585
H5T__conv_fcomplex_llong(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
1586
                         size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
1587
                         void H5_ATTR_UNUSED *bkg)
1588
0
{
1589
0
    H5_WARN_FLOAT_EQUAL_OFF
1590
0
    H5T_CONV_Zx(FLOAT_COMPLEX, LLONG, H5_float_complex, long long, LLONG_MIN, LLONG_MAX);
1591
0
    H5_WARN_FLOAT_EQUAL_ON
1592
0
}
1593
1594
/*-------------------------------------------------------------------------
1595
 * Function:    H5T__conv_fcomplex_ullong
1596
 *
1597
 * Purpose:     Converts `float _Complex' / `_Fcomplex' to
1598
 *              `unsigned long long'
1599
 *
1600
 * Return:      Non-negative on success/Negative on failure
1601
 *
1602
 *-------------------------------------------------------------------------
1603
 */
1604
herr_t
1605
H5T__conv_fcomplex_ullong(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
1606
                          const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
1607
                          size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
1608
0
{
1609
0
    H5_WARN_FLOAT_EQUAL_OFF
1610
0
    H5T_CONV_Zx(FLOAT_COMPLEX, ULLONG, H5_float_complex, unsigned long long, 0, ULLONG_MAX);
1611
0
    H5_WARN_FLOAT_EQUAL_ON
1612
0
}
1613
1614
#ifdef H5_HAVE__FLOAT16
1615
/*-------------------------------------------------------------------------
1616
 * Function:    H5T__conv_fcomplex__Float16
1617
 *
1618
 * Purpose:     Converts `float _Complex' / `_Fcomplex' to `_Float16'
1619
 *
1620
 * Return:      Non-negative on success/Negative on failure
1621
 *
1622
 *-------------------------------------------------------------------------
1623
 */
1624
herr_t
1625
H5T__conv_fcomplex__Float16(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
1626
                            const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
1627
                            size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
1628
{
1629
    /* Suppress warning about non-standard floating-point literal suffix (F16) */
1630
    H5_WARN_NONSTD_SUFFIX_OFF
1631
    H5T_CONV_Zf(FLOAT_COMPLEX, FLOAT16, H5_float_complex, H5__Float16, -FLT16_MAX, FLT16_MAX);
1632
    H5_WARN_NONSTD_SUFFIX_ON
1633
}
1634
#endif
1635
1636
/*-------------------------------------------------------------------------
1637
 * Function:    H5T__conv_fcomplex_float
1638
 *
1639
 * Purpose:     Converts `float _Complex' / `_Fcomplex' to `float'
1640
 *
1641
 * Return:      Non-negative on success/Negative on failure
1642
 *
1643
 *-------------------------------------------------------------------------
1644
 */
1645
herr_t
1646
H5T__conv_fcomplex_float(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
1647
                         size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
1648
                         void H5_ATTR_UNUSED *bkg)
1649
2
{
1650
2
    H5T_CONV_zf(FLOAT_COMPLEX, FLOAT, H5_float_complex, float, -, -);
1651
2
}
1652
1653
/*-------------------------------------------------------------------------
1654
 * Function:    H5T__conv_fcomplex_double
1655
 *
1656
 * Purpose:     Converts `float _Complex' / `_Fcomplex' to `double'
1657
 *
1658
 * Return:      Non-negative on success/Negative on failure
1659
 *
1660
 *-------------------------------------------------------------------------
1661
 */
1662
herr_t
1663
H5T__conv_fcomplex_double(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
1664
                          const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
1665
                          size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
1666
2
{
1667
2
    H5T_CONV_zF(FLOAT_COMPLEX, DOUBLE, H5_float_complex, double, -, -);
1668
2
}
1669
1670
/*-------------------------------------------------------------------------
1671
 * Function:    H5T__conv_fcomplex_ldouble
1672
 *
1673
 * Purpose:     Converts `float _Complex' / `_Fcomplex' to `long double'
1674
 *
1675
 * Return:      Non-negative on success/Negative on failure
1676
 *
1677
 *-------------------------------------------------------------------------
1678
 */
1679
herr_t
1680
H5T__conv_fcomplex_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
1681
                           const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
1682
                           size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
1683
2
{
1684
2
    H5T_CONV_zF(FLOAT_COMPLEX, LDOUBLE, H5_float_complex, long double, -, -);
1685
2
}
1686
1687
/*-------------------------------------------------------------------------
1688
 * Function:    H5T__conv_fcomplex_dcomplex
1689
 *
1690
 * Purpose:     Converts `float _Complex' / `_Fcomplex' to
1691
 *              `double _Complex' / `_Dcomplex'
1692
 *
1693
 * Return:      Non-negative on success/Negative on failure
1694
 *
1695
 *-------------------------------------------------------------------------
1696
 */
1697
herr_t
1698
H5T__conv_fcomplex_dcomplex(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
1699
                            const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
1700
                            size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
1701
2
{
1702
2
    H5T_CONV_zZ(FLOAT_COMPLEX, DOUBLE_COMPLEX, H5_float_complex, H5_double_complex, -, -);
1703
2
}
1704
1705
/*-------------------------------------------------------------------------
1706
 * Function:    H5T__conv_fcomplex_lcomplex
1707
 *
1708
 * Purpose:     Converts `float _Complex' / `_Fcomplex' to
1709
 *              `long double _Complex' / `_Lcomplex'
1710
 *
1711
 * Return:      Non-negative on success/Negative on failure
1712
 *
1713
 *-------------------------------------------------------------------------
1714
 */
1715
herr_t
1716
H5T__conv_fcomplex_lcomplex(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
1717
                            const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
1718
                            size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
1719
2
{
1720
2
    H5T_CONV_zZ(FLOAT_COMPLEX, LDOUBLE_COMPLEX, H5_float_complex, H5_ldouble_complex, -, -);
1721
2
}
1722
1723
/*-------------------------------------------------------------------------
1724
 * Function:    H5T__conv_dcomplex_schar
1725
 *
1726
 * Purpose:     Converts `double _Complex' / `_Dcomplex' to `signed char'
1727
 *
1728
 * Return:      Non-negative on success/Negative on failure
1729
 *
1730
 *-------------------------------------------------------------------------
1731
 */
1732
herr_t
1733
H5T__conv_dcomplex_schar(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
1734
                         size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
1735
                         void H5_ATTR_UNUSED *bkg)
1736
2
{
1737
2
    H5_WARN_FLOAT_EQUAL_OFF
1738
2
    H5T_CONV_Zx(DOUBLE_COMPLEX, SCHAR, H5_double_complex, signed char, SCHAR_MIN, SCHAR_MAX);
1739
2
    H5_WARN_FLOAT_EQUAL_ON
1740
2
}
1741
1742
/*-------------------------------------------------------------------------
1743
 * Function:    H5T__conv_dcomplex_uchar
1744
 *
1745
 * Purpose:     Converts `double _Complex' / `_Dcomplex' to `unsigned char'
1746
 *
1747
 * Return:      Non-negative on success/Negative on failure
1748
 *
1749
 *-------------------------------------------------------------------------
1750
 */
1751
herr_t
1752
H5T__conv_dcomplex_uchar(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
1753
                         size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
1754
                         void H5_ATTR_UNUSED *bkg)
1755
2
{
1756
2
    H5_WARN_FLOAT_EQUAL_OFF
1757
2
    H5T_CONV_Zx(DOUBLE_COMPLEX, UCHAR, H5_double_complex, unsigned char, 0, UCHAR_MAX);
1758
2
    H5_WARN_FLOAT_EQUAL_ON
1759
2
}
1760
1761
/*-------------------------------------------------------------------------
1762
 * Function:    H5T__conv_dcomplex_short
1763
 *
1764
 * Purpose:     Converts `double _Complex' / `_Dcomplex' to `short'
1765
 *
1766
 * Return:      Non-negative on success/Negative on failure
1767
 *
1768
 *-------------------------------------------------------------------------
1769
 */
1770
herr_t
1771
H5T__conv_dcomplex_short(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
1772
                         size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
1773
                         void H5_ATTR_UNUSED *bkg)
1774
2
{
1775
2
    H5_WARN_FLOAT_EQUAL_OFF
1776
2
    H5T_CONV_Zx(DOUBLE_COMPLEX, SHORT, H5_double_complex, short, SHRT_MIN, SHRT_MAX);
1777
2
    H5_WARN_FLOAT_EQUAL_ON
1778
2
}
1779
1780
/*-------------------------------------------------------------------------
1781
 * Function:    H5T__conv_dcomplex_ushort
1782
 *
1783
 * Purpose:     Converts `double _Complex' / `_Dcomplex' to
1784
 *              `unsigned short'
1785
 *
1786
 * Return:      Non-negative on success/Negative on failure
1787
 *
1788
 *-------------------------------------------------------------------------
1789
 */
1790
herr_t
1791
H5T__conv_dcomplex_ushort(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
1792
                          const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
1793
                          size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
1794
2
{
1795
2
    H5_WARN_FLOAT_EQUAL_OFF
1796
2
    H5T_CONV_Zx(DOUBLE_COMPLEX, USHORT, H5_double_complex, unsigned short, 0, USHRT_MAX);
1797
2
    H5_WARN_FLOAT_EQUAL_ON
1798
2
}
1799
1800
/*-------------------------------------------------------------------------
1801
 * Function:    H5T__conv_dcomplex_int
1802
 *
1803
 * Purpose:     Converts `double _Complex' / `_Dcomplex' to `int'
1804
 *
1805
 * Return:      Non-negative on success/Negative on failure
1806
 *
1807
 *-------------------------------------------------------------------------
1808
 */
1809
herr_t
1810
H5T__conv_dcomplex_int(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
1811
                       size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
1812
                       void H5_ATTR_UNUSED *bkg)
1813
2
{
1814
2
    H5_WARN_FLOAT_EQUAL_OFF
1815
2
    H5T_CONV_Zx(DOUBLE_COMPLEX, INT, H5_double_complex, int, INT_MIN, INT_MAX);
1816
2
    H5_WARN_FLOAT_EQUAL_ON
1817
2
}
1818
1819
/*-------------------------------------------------------------------------
1820
 * Function:    H5T__conv_dcomplex_uint
1821
 *
1822
 * Purpose:     Converts `double _Complex' / `_Dcomplex' to `unsigned int'
1823
 *
1824
 * Return:      Non-negative on success/Negative on failure
1825
 *
1826
 *-------------------------------------------------------------------------
1827
 */
1828
herr_t
1829
H5T__conv_dcomplex_uint(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
1830
                        size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
1831
                        void H5_ATTR_UNUSED *bkg)
1832
2
{
1833
2
    H5_WARN_FLOAT_EQUAL_OFF
1834
2
    H5T_CONV_Zx(DOUBLE_COMPLEX, UINT, H5_double_complex, unsigned int, 0, UINT_MAX);
1835
2
    H5_WARN_FLOAT_EQUAL_ON
1836
2
}
1837
1838
/*-------------------------------------------------------------------------
1839
 * Function:    H5T__conv_dcomplex_long
1840
 *
1841
 * Purpose:     Converts `double _Complex' / `_Dcomplex' to `long'
1842
 *
1843
 * Return:      Non-negative on success/Negative on failure
1844
 *
1845
 *-------------------------------------------------------------------------
1846
 */
1847
herr_t
1848
H5T__conv_dcomplex_long(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
1849
                        size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
1850
                        void H5_ATTR_UNUSED *bkg)
1851
2
{
1852
2
    H5_WARN_FLOAT_EQUAL_OFF
1853
2
    H5T_CONV_Zx(DOUBLE_COMPLEX, LONG, H5_double_complex, long, LONG_MIN, LONG_MAX);
1854
2
    H5_WARN_FLOAT_EQUAL_ON
1855
2
}
1856
1857
/*-------------------------------------------------------------------------
1858
 * Function:    H5T__conv_dcomplex_ulong
1859
 *
1860
 * Purpose:     Converts `double _Complex' / `_Dcomplex' to `unsigned long'
1861
 *
1862
 * Return:      Non-negative on success/Negative on failure
1863
 *
1864
 *-------------------------------------------------------------------------
1865
 */
1866
herr_t
1867
H5T__conv_dcomplex_ulong(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
1868
                         size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
1869
                         void H5_ATTR_UNUSED *bkg)
1870
2
{
1871
2
    H5_WARN_FLOAT_EQUAL_OFF
1872
2
    H5T_CONV_Zx(DOUBLE_COMPLEX, ULONG, H5_double_complex, unsigned long, 0, ULONG_MAX);
1873
2
    H5_WARN_FLOAT_EQUAL_ON
1874
2
}
1875
1876
/*-------------------------------------------------------------------------
1877
 * Function:    H5T__conv_dcomplex_llong
1878
 *
1879
 * Purpose:     Converts `double _Complex' / `_Dcomplex' to `long long'
1880
 *
1881
 * Return:      Non-negative on success/Negative on failure
1882
 *
1883
 *-------------------------------------------------------------------------
1884
 */
1885
herr_t
1886
H5T__conv_dcomplex_llong(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
1887
                         size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
1888
                         void H5_ATTR_UNUSED *bkg)
1889
0
{
1890
0
    H5_WARN_FLOAT_EQUAL_OFF
1891
0
    H5T_CONV_Zx(DOUBLE_COMPLEX, LLONG, H5_double_complex, long long, LLONG_MIN, LLONG_MAX);
1892
0
    H5_WARN_FLOAT_EQUAL_ON
1893
0
}
1894
1895
/*-------------------------------------------------------------------------
1896
 * Function:    H5T__conv_dcomplex_ullong
1897
 *
1898
 * Purpose:     Converts `double _Complex' / `_Dcomplex' to
1899
 *              `unsigned long long'
1900
 *
1901
 * Return:      Non-negative on success/Negative on failure
1902
 *
1903
 *-------------------------------------------------------------------------
1904
 */
1905
herr_t
1906
H5T__conv_dcomplex_ullong(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
1907
                          const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
1908
                          size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
1909
0
{
1910
0
    H5_WARN_FLOAT_EQUAL_OFF
1911
0
    H5T_CONV_Zx(DOUBLE_COMPLEX, ULLONG, H5_double_complex, unsigned long long, 0, ULLONG_MAX);
1912
0
    H5_WARN_FLOAT_EQUAL_ON
1913
0
}
1914
1915
#ifdef H5_HAVE__FLOAT16
1916
/*-------------------------------------------------------------------------
1917
 * Function:    H5T__conv_dcomplex__Float16
1918
 *
1919
 * Purpose:     Converts `double _Complex' / `_Dcomplex' to `_Float16'
1920
 *
1921
 * Return:      Non-negative on success/Negative on failure
1922
 *
1923
 *-------------------------------------------------------------------------
1924
 */
1925
herr_t
1926
H5T__conv_dcomplex__Float16(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
1927
                            const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
1928
                            size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
1929
{
1930
    /* Suppress warning about non-standard floating-point literal suffix */
1931
    H5_WARN_NONSTD_SUFFIX_OFF
1932
    H5T_CONV_Zf(DOUBLE_COMPLEX, FLOAT16, H5_double_complex, H5__Float16, -FLT16_MAX, FLT16_MAX);
1933
    H5_WARN_NONSTD_SUFFIX_ON
1934
}
1935
#endif
1936
1937
/*-------------------------------------------------------------------------
1938
 * Function:    H5T__conv_dcomplex_float
1939
 *
1940
 * Purpose:     Converts `double _Complex' / `_Dcomplex' to `float'
1941
 *
1942
 * Return:      Non-negative on success/Negative on failure
1943
 *
1944
 *-------------------------------------------------------------------------
1945
 */
1946
herr_t
1947
H5T__conv_dcomplex_float(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
1948
                         size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
1949
                         void H5_ATTR_UNUSED *bkg)
1950
2
{
1951
2
    H5T_CONV_Zf(DOUBLE_COMPLEX, FLOAT, H5_double_complex, float, -FLT_MAX, FLT_MAX);
1952
2
}
1953
1954
/*-------------------------------------------------------------------------
1955
 * Function:    H5T__conv_dcomplex_double
1956
 *
1957
 * Purpose:     Converts `double _Complex' / `_Dcomplex' to `double'
1958
 *
1959
 * Return:      Non-negative on success/Negative on failure
1960
 *
1961
 *-------------------------------------------------------------------------
1962
 */
1963
herr_t
1964
H5T__conv_dcomplex_double(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
1965
                          const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
1966
                          size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
1967
2
{
1968
2
    H5T_CONV_zf(DOUBLE_COMPLEX, DOUBLE, H5_double_complex, double, -, -);
1969
2
}
1970
1971
/*-------------------------------------------------------------------------
1972
 * Function:    H5T__conv_dcomplex_ldouble
1973
 *
1974
 * Purpose:     Converts `double _Complex' / `_Dcomplex' to `long double'
1975
 *
1976
 * Return:      Non-negative on success/Negative on failure
1977
 *
1978
 *-------------------------------------------------------------------------
1979
 */
1980
herr_t
1981
H5T__conv_dcomplex_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
1982
                           const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
1983
                           size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
1984
2
{
1985
2
    H5T_CONV_zF(DOUBLE_COMPLEX, LDOUBLE, H5_double_complex, long double, -, -);
1986
2
}
1987
1988
/*-------------------------------------------------------------------------
1989
 * Function:    H5T__conv_dcomplex_fcomplex
1990
 *
1991
 * Purpose:     Converts `double _Complex' / `_Dcomplex' to
1992
 *              `float _Complex' / `_Fcomplex'
1993
 *
1994
 * Return:      Non-negative on success/Negative on failure
1995
 *
1996
 *-------------------------------------------------------------------------
1997
 */
1998
herr_t
1999
H5T__conv_dcomplex_fcomplex(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
2000
                            const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
2001
                            size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
2002
2
{
2003
2
    H5T_CONV_Zz(DOUBLE_COMPLEX, FLOAT_COMPLEX, H5_double_complex, H5_float_complex, -FLT_MAX, FLT_MAX);
2004
2
}
2005
2006
/*-------------------------------------------------------------------------
2007
 * Function:    H5T__conv_dcomplex_lcomplex
2008
 *
2009
 * Purpose:     Converts `double _Complex' / `_Dcomplex' to
2010
 *              `long double _Complex' / `_Lcomplex'
2011
 *
2012
 * Return:      Non-negative on success/Negative on failure
2013
 *
2014
 *-------------------------------------------------------------------------
2015
 */
2016
herr_t
2017
H5T__conv_dcomplex_lcomplex(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
2018
                            const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
2019
                            size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
2020
2
{
2021
2
    H5T_CONV_zZ(DOUBLE_COMPLEX, LDOUBLE_COMPLEX, H5_double_complex, H5_ldouble_complex, -, -);
2022
2
}
2023
2024
/*-------------------------------------------------------------------------
2025
 * Function:    H5T__conv_lcomplex_schar
2026
 *
2027
 * Purpose:     Converts `long double _Complex' / `_Lcomplex' to
2028
 *              `signed char'
2029
 *
2030
 * Return:      Non-negative on success/Negative on failure
2031
 *
2032
 *-------------------------------------------------------------------------
2033
 */
2034
herr_t
2035
H5T__conv_lcomplex_schar(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
2036
                         size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
2037
                         void H5_ATTR_UNUSED *bkg)
2038
2
{
2039
2
    H5_WARN_FLOAT_EQUAL_OFF
2040
2
    H5T_CONV_Zx(LDOUBLE_COMPLEX, SCHAR, H5_ldouble_complex, signed char, SCHAR_MIN, SCHAR_MAX);
2041
2
    H5_WARN_FLOAT_EQUAL_ON
2042
2
}
2043
2044
/*-------------------------------------------------------------------------
2045
 * Function:    H5T__conv_lcomplex_uchar
2046
 *
2047
 * Purpose:     Converts `long double _Complex' / `_Lcomplex' to
2048
 *              `unsigned char'
2049
 *
2050
 * Return:      Non-negative on success/Negative on failure
2051
 *
2052
 *-------------------------------------------------------------------------
2053
 */
2054
herr_t
2055
H5T__conv_lcomplex_uchar(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
2056
                         size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
2057
                         void H5_ATTR_UNUSED *bkg)
2058
2
{
2059
2
    H5_WARN_FLOAT_EQUAL_OFF
2060
2
    H5T_CONV_Zx(LDOUBLE_COMPLEX, UCHAR, H5_ldouble_complex, unsigned char, 0, UCHAR_MAX);
2061
2
    H5_WARN_FLOAT_EQUAL_ON
2062
2
}
2063
2064
/*-------------------------------------------------------------------------
2065
 * Function:    H5T__conv_lcomplex_short
2066
 *
2067
 * Purpose:     Converts `long double _Complex' / `_Lcomplex' to `short'
2068
 *
2069
 * Return:      Non-negative on success/Negative on failure
2070
 *
2071
 *-------------------------------------------------------------------------
2072
 */
2073
herr_t
2074
H5T__conv_lcomplex_short(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
2075
                         size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
2076
                         void H5_ATTR_UNUSED *bkg)
2077
2
{
2078
2
    H5_WARN_FLOAT_EQUAL_OFF
2079
2
    H5T_CONV_Zx(LDOUBLE_COMPLEX, SHORT, H5_ldouble_complex, short, SHRT_MIN, SHRT_MAX);
2080
2
    H5_WARN_FLOAT_EQUAL_ON
2081
2
}
2082
2083
/*-------------------------------------------------------------------------
2084
 * Function:    H5T__conv_lcomplex_ushort
2085
 *
2086
 * Purpose:     Converts `long double _Complex' / `_Lcomplex' to
2087
 *              `unsigned short'
2088
 *
2089
 * Return:      Non-negative on success/Negative on failure
2090
 *
2091
 *-------------------------------------------------------------------------
2092
 */
2093
herr_t
2094
H5T__conv_lcomplex_ushort(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
2095
                          const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
2096
                          size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
2097
2
{
2098
2
    H5_WARN_FLOAT_EQUAL_OFF
2099
2
    H5T_CONV_Zx(LDOUBLE_COMPLEX, USHORT, H5_ldouble_complex, unsigned short, 0, USHRT_MAX);
2100
2
    H5_WARN_FLOAT_EQUAL_ON
2101
2
}
2102
2103
/*-------------------------------------------------------------------------
2104
 * Function:    H5T__conv_lcomplex_int
2105
 *
2106
 * Purpose:     Converts `long double _Complex' / `_Lcomplex' to `int'
2107
 *
2108
 * Return:      Non-negative on success/Negative on failure
2109
 *
2110
 *-------------------------------------------------------------------------
2111
 */
2112
herr_t
2113
H5T__conv_lcomplex_int(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
2114
                       size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
2115
                       void H5_ATTR_UNUSED *bkg)
2116
2
{
2117
2
    H5_WARN_FLOAT_EQUAL_OFF
2118
2
    H5T_CONV_Zx(LDOUBLE_COMPLEX, INT, H5_ldouble_complex, int, INT_MIN, INT_MAX);
2119
2
    H5_WARN_FLOAT_EQUAL_ON
2120
2
}
2121
2122
/*-------------------------------------------------------------------------
2123
 * Function:    H5T__conv_lcomplex_uint
2124
 *
2125
 * Purpose:     Converts `long double _Complex' / `_Lcomplex' to
2126
 *              `unsigned int'
2127
 *
2128
 * Return:      Non-negative on success/Negative on failure
2129
 *
2130
 *-------------------------------------------------------------------------
2131
 */
2132
herr_t
2133
H5T__conv_lcomplex_uint(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
2134
                        size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
2135
                        void H5_ATTR_UNUSED *bkg)
2136
2
{
2137
2
    H5_WARN_FLOAT_EQUAL_OFF
2138
2
    H5T_CONV_Zx(LDOUBLE_COMPLEX, UINT, H5_ldouble_complex, unsigned int, 0, UINT_MAX);
2139
2
    H5_WARN_FLOAT_EQUAL_ON
2140
2
}
2141
2142
/*-------------------------------------------------------------------------
2143
 * Function:    H5T__conv_lcomplex_long
2144
 *
2145
 * Purpose:     Converts `long double _Complex' / `_Lcomplex' to `long'
2146
 *
2147
 * Return:      Non-negative on success/Negative on failure
2148
 *
2149
 *-------------------------------------------------------------------------
2150
 */
2151
herr_t
2152
H5T__conv_lcomplex_long(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
2153
                        size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
2154
                        void H5_ATTR_UNUSED *bkg)
2155
2
{
2156
2
    H5_WARN_FLOAT_EQUAL_OFF
2157
2
    H5T_CONV_Zx(LDOUBLE_COMPLEX, LONG, H5_ldouble_complex, long, LONG_MIN, LONG_MAX);
2158
2
    H5_WARN_FLOAT_EQUAL_ON
2159
2
}
2160
2161
/*-------------------------------------------------------------------------
2162
 * Function:    H5T__conv_lcomplex_ulong
2163
 *
2164
 * Purpose:     Converts `long double _Complex' / `_Lcomplex' to
2165
 *              `unsigned long'
2166
 *
2167
 * Return:      Non-negative on success/Negative on failure
2168
 *
2169
 *-------------------------------------------------------------------------
2170
 */
2171
herr_t
2172
H5T__conv_lcomplex_ulong(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
2173
                         size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
2174
                         void H5_ATTR_UNUSED *bkg)
2175
2
{
2176
2
    H5_WARN_FLOAT_EQUAL_OFF
2177
2
    H5T_CONV_Zx(LDOUBLE_COMPLEX, ULONG, H5_ldouble_complex, unsigned long, 0, ULONG_MAX);
2178
2
    H5_WARN_FLOAT_EQUAL_ON
2179
2
}
2180
2181
/*-------------------------------------------------------------------------
2182
 * Function:    H5T__conv_lcomplex_llong
2183
 *
2184
 * Purpose:     Converts `long double _Complex' / `_Lcomplex' to
2185
 *              `long long'
2186
 *
2187
 * Return:      Non-negative on success/Negative on failure
2188
 *
2189
 *-------------------------------------------------------------------------
2190
 */
2191
#ifdef H5T_CONV_INTERNAL_LDOUBLE_LLONG
2192
herr_t
2193
H5T__conv_lcomplex_llong(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
2194
                         size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
2195
                         void H5_ATTR_UNUSED *bkg)
2196
0
{
2197
0
    H5_WARN_FLOAT_EQUAL_OFF
2198
0
    H5T_CONV_Zx(LDOUBLE_COMPLEX, LLONG, H5_ldouble_complex, long long, LLONG_MIN, LLONG_MAX);
2199
0
    H5_WARN_FLOAT_EQUAL_ON
2200
0
}
2201
#endif /* H5T_CONV_INTERNAL_LDOUBLE_LLONG */
2202
2203
/*-------------------------------------------------------------------------
2204
 * Function:    H5T__conv_lcomplex_ullong
2205
 *
2206
 * Purpose:     Converts `long double _Complex' / `_Lcomplex' to
2207
 *              `unsigned long long'
2208
 *
2209
 * Return:      Non-negative on success/Negative on failure
2210
 *
2211
 *-------------------------------------------------------------------------
2212
 */
2213
#ifdef H5T_CONV_INTERNAL_LDOUBLE_ULLONG
2214
herr_t
2215
H5T__conv_lcomplex_ullong(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
2216
                          const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
2217
                          size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
2218
0
{
2219
0
    H5_WARN_FLOAT_EQUAL_OFF
2220
0
    H5T_CONV_Zx(LDOUBLE_COMPLEX, ULLONG, H5_ldouble_complex, unsigned long long, 0, ULLONG_MAX);
2221
0
    H5_WARN_FLOAT_EQUAL_ON
2222
0
}
2223
#endif /* H5T_CONV_INTERNAL_LDOUBLE_ULLONG */
2224
2225
#ifdef H5_HAVE__FLOAT16
2226
#ifdef H5T_CONV_INTERNAL_LDOUBLE_FLOAT16
2227
/*-------------------------------------------------------------------------
2228
 * Function:    H5T__conv_lcomplex__Float16
2229
 *
2230
 * Purpose:     Converts `long double _Complex' / `_Lcomplex' to `_Float16'
2231
 *
2232
 * Return:      Non-negative on success/Negative on failure
2233
 *
2234
 *-------------------------------------------------------------------------
2235
 */
2236
herr_t
2237
H5T__conv_lcomplex__Float16(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
2238
                            const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
2239
                            size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
2240
{
2241
    /* Suppress warning about non-standard floating-point literal suffix */
2242
    H5_WARN_NONSTD_SUFFIX_OFF
2243
    H5T_CONV_Zf(LDOUBLE_COMPLEX, FLOAT16, H5_ldouble_complex, H5__Float16, -FLT16_MAX, FLT16_MAX);
2244
    H5_WARN_NONSTD_SUFFIX_ON
2245
}
2246
#endif
2247
#endif
2248
2249
/*-------------------------------------------------------------------------
2250
 * Function:    H5T__conv_lcomplex_float
2251
 *
2252
 * Purpose:     Converts `long double _Complex' / `_Lcomplex' to `float'
2253
 *
2254
 * Return:      Non-negative on success/Negative on failure
2255
 *
2256
 *-------------------------------------------------------------------------
2257
 */
2258
herr_t
2259
H5T__conv_lcomplex_float(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
2260
                         size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf,
2261
                         void H5_ATTR_UNUSED *bkg)
2262
2
{
2263
2
    H5T_CONV_Zf(LDOUBLE_COMPLEX, FLOAT, H5_ldouble_complex, float, -FLT_MAX, FLT_MAX);
2264
2
}
2265
2266
/*-------------------------------------------------------------------------
2267
 * Function:    H5T__conv_lcomplex_double
2268
 *
2269
 * Purpose:     Converts `long double _Complex' / `_Lcomplex' to `double'
2270
 *
2271
 * Return:      Non-negative on success/Negative on failure
2272
 *
2273
 *-------------------------------------------------------------------------
2274
 */
2275
herr_t
2276
H5T__conv_lcomplex_double(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
2277
                          const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
2278
                          size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
2279
2
{
2280
2
    H5T_CONV_Zf(LDOUBLE_COMPLEX, DOUBLE, H5_ldouble_complex, double, -DBL_MAX, DBL_MAX);
2281
2
}
2282
2283
/*-------------------------------------------------------------------------
2284
 * Function:    H5T__conv_lcomplex_ldouble
2285
 *
2286
 * Purpose:     Converts `long double _Complex' / `_Lcomplex' to
2287
 *              `long double'
2288
 *
2289
 * Return:      Non-negative on success/Negative on failure
2290
 *
2291
 *-------------------------------------------------------------------------
2292
 */
2293
herr_t
2294
H5T__conv_lcomplex_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
2295
                           const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
2296
                           size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
2297
2
{
2298
2
    H5T_CONV_zf(LDOUBLE_COMPLEX, LDOUBLE, H5_ldouble_complex, long double, -, -);
2299
2
}
2300
2301
/*-------------------------------------------------------------------------
2302
 * Function:    H5T__conv_lcomplex_fcomplex
2303
 *
2304
 * Purpose:     Converts `long double _Complex' / `_Lcomplex' to
2305
 *              `float _Complex' / `_Fcomplex'
2306
 *
2307
 * Return:      Non-negative on success/Negative on failure
2308
 *
2309
 *-------------------------------------------------------------------------
2310
 */
2311
herr_t
2312
H5T__conv_lcomplex_fcomplex(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
2313
                            const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
2314
                            size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
2315
2
{
2316
2
    H5T_CONV_Zz(LDOUBLE_COMPLEX, FLOAT_COMPLEX, H5_ldouble_complex, H5_float_complex, -FLT_MAX, FLT_MAX);
2317
2
}
2318
2319
/*-------------------------------------------------------------------------
2320
 * Function:    H5T__conv_lcomplex_dcomplex
2321
 *
2322
 * Purpose:     Converts `long double _Complex' / `_Lcomplex' to
2323
 *              `double _Complex' / `_Dcomplex'
2324
 *
2325
 * Return:      Non-negative on success/Negative on failure
2326
 *
2327
 *-------------------------------------------------------------------------
2328
 */
2329
herr_t
2330
H5T__conv_lcomplex_dcomplex(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata,
2331
                            const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
2332
                            size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
2333
2
{
2334
    H5T_CONV_Zz(LDOUBLE_COMPLEX, DOUBLE_COMPLEX, H5_ldouble_complex, H5_double_complex, -DBL_MAX, DBL_MAX);
2335
2
}
2336
#endif /* H5_HAVE_COMPLEX_NUMBERS */