Coverage Report

Created: 2025-08-26 06:30

/src/hdf5/src/H5Tinit_float.c
Line
Count
Source (jump to first uncovered line)
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: Initialize native floating-point datatypes
15
 */
16
17
/****************/
18
/* Module Setup */
19
/****************/
20
21
#include "H5Tmodule.h" /* This source code file is part of the H5T module */
22
23
/***********/
24
/* Headers */
25
/***********/
26
#include "H5private.h"   /* Generic Functions                */
27
#include "H5Eprivate.h"  /* Error handling                   */
28
#include "H5FLprivate.h" /* Free Lists                       */
29
#include "H5Iprivate.h"  /* IDs                              */
30
#include "H5MMprivate.h" /* Memory management                        */
31
#include "H5Tpkg.h"      /* Datatypes                        */
32
33
/****************/
34
/* Local Macros */
35
/****************/
36
37
/* This could also go in H5private.h, but this is the only place we
38
 * need to turn off the sanitizers and we don't want to encourage
39
 * this.
40
 */
41
#if defined(__has_attribute)
42
#if __has_attribute(no_sanitize)
43
#define H5_NO_UBSAN __attribute__((no_sanitize("undefined")))
44
#else
45
#define H5_NO_UBSAN
46
#endif
47
#else
48
#define H5_NO_UBSAN
49
#endif
50
51
/*-------------------------------------------------------------------------
52
 * Function:    DETECT_F
53
 *
54
 * Purpose:     This macro takes a floating point type like `double' and
55
 *              and detects byte order, mantissa location, exponent location,
56
 *              sign bit location, presence or absence of implicit mantissa
57
 *              bit, and exponent bias and initializes a H5T_fpoint_det_t
58
 *              structure with those properties.
59
 *
60
 *              Note that these operations can raise floating-point
61
 *              exceptions and building with some compiler options
62
 *              (especially Fortran) can cause problems.
63
 *-------------------------------------------------------------------------
64
 */
65
#define DETECT_F(TYPE, INFO)                                                                                 \
66
3
    do {                                                                                                     \
67
3
        TYPE    _v1, _v2, _v3;                                                                               \
68
3
        uint8_t _buf1[sizeof(TYPE)], _buf3[sizeof(TYPE)];                                                    \
69
3
        uint8_t _pad_mask[sizeof(TYPE)];                                                                     \
70
3
        uint8_t _byte_mask;                                                                                  \
71
3
        int     _i, _j, _last = -1;                                                                          \
72
3
                                                                                                             \
73
3
        memset(&INFO, 0, sizeof(INFO));                                                                      \
74
3
        INFO.size = sizeof(TYPE);                                                                            \
75
3
                                                                                                             \
76
3
        /* Initialize padding mask */                                                                        \
77
3
        memset(_pad_mask, 0, sizeof(_pad_mask));                                                             \
78
3
                                                                                                             \
79
3
        /* Padding bits.  Set a variable to 4.0, then flip each bit and see if                               \
80
3
         * the modified variable is equal ("==") to the original.  Build a                                   \
81
3
         * padding bitmask to indicate which bits in the type are padding (i.e.                              \
82
3
         * have no effect on the value and should be ignored by subsequent                                   \
83
3
         * steps).  This is necessary because padding bits can change arbitrarily                            \
84
3
         * and interfere with detection of the various properties below unless we                            \
85
3
         * know to ignore them. */                                                                           \
86
3
        _v1 = (TYPE)4.0L;                                                                                    \
87
3
        H5MM_memcpy(_buf1, (const void *)&_v1, sizeof(TYPE));                                                \
88
31
        for (_i = 0; _i < (int)sizeof(TYPE); _i++)                                                           \
89
252
            for (_byte_mask = (uint8_t)1; _byte_mask; _byte_mask = (uint8_t)(_byte_mask << 1)) {             \
90
224
                _buf1[_i] ^= _byte_mask;                                                                     \
91
224
                H5MM_memcpy((void *)&_v2, (const void *)_buf1, sizeof(TYPE));                                \
92
224
                H5_WARN_FLOAT_EQUAL_OFF                                                                      \
93
224
                if (_v1 != _v2)                                                                              \
94
224
                    _pad_mask[_i] |= _byte_mask;                                                             \
95
224
                H5_WARN_FLOAT_EQUAL_ON                                                                       \
96
224
                _buf1[_i] ^= _byte_mask;                                                                     \
97
224
            }                                                                                                \
98
3
                                                                                                             \
99
3
        /* Byte Order */                                                                                     \
100
31
        for (_i = 0, _v1 = (TYPE)0.0L, _v2 = (TYPE)1.0L; _i < (int)sizeof(TYPE); _i++) {                     \
101
28
            _v3 = _v1;                                                                                       \
102
28
            _v1 += _v2;                                                                                      \
103
28
            _v2 /= (TYPE)256.0L;                                                                             \
104
28
            H5MM_memcpy(_buf1, (const void *)&_v1, sizeof(TYPE));                                            \
105
28
            H5MM_memcpy(_buf3, (const void *)&_v3, sizeof(TYPE));                                            \
106
28
            _j = H5T__byte_cmp(sizeof(TYPE), _buf3, _buf1, _pad_mask);                                       \
107
28
            if (_j >= 0) {                                                                                   \
108
18
                INFO.perm[_i] = _j;                                                                          \
109
18
                _last         = _i;                                                                          \
110
18
            }                                                                                                \
111
28
        }                                                                                                    \
112
3
        if (H5T__fix_order(sizeof(TYPE), _last, INFO.perm, &INFO.order) < 0)                                 \
113
3
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "failed to detect byte order");                    \
114
3
                                                                                                             \
115
3
        /* Implicit mantissa bit */                                                                          \
116
3
        _v1 = (TYPE)0.5L;                                                                                    \
117
3
        _v2 = (TYPE)1.0L;                                                                                    \
118
3
        if (H5T__imp_bit(sizeof(TYPE), INFO.perm, &_v1, &_v2, _pad_mask, &(INFO.imp)) < 0)                   \
119
3
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "failed to determine implicit bit");               \
120
3
        INFO.norm = INFO.imp ? H5T_NORM_IMPLIED : H5T_NORM_NONE;                                             \
121
3
                                                                                                             \
122
3
        /* Sign bit */                                                                                       \
123
3
        _v1 = (TYPE)1.0L;                                                                                    \
124
3
        _v2 = (TYPE)-1.0L;                                                                                   \
125
3
        if (H5T__bit_cmp(sizeof(TYPE), INFO.perm, &_v1, &_v2, _pad_mask, &(INFO.sign)) < 0)                  \
126
3
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "failed to determine sign bit");                   \
127
3
                                                                                                             \
128
3
        /* Mantissa */                                                                                       \
129
3
        INFO.mpos = 0;                                                                                       \
130
3
                                                                                                             \
131
3
        _v1 = (TYPE)1.0L;                                                                                    \
132
3
        _v2 = (TYPE)1.5L;                                                                                    \
133
3
        if (H5T__bit_cmp(sizeof(TYPE), INFO.perm, &_v1, &_v2, _pad_mask, &(INFO.msize)) < 0)                 \
134
3
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "failed to determine mantissa");                   \
135
3
        INFO.msize += 1 + (unsigned)(INFO.imp ? 0 : 1) - INFO.mpos;                                          \
136
3
                                                                                                             \
137
3
        /* Exponent */                                                                                       \
138
3
        INFO.epos  = INFO.mpos + INFO.msize;                                                                 \
139
3
        INFO.esize = INFO.sign - INFO.epos;                                                                  \
140
3
                                                                                                             \
141
3
        _v1        = (TYPE)1.0L;                                                                             \
142
3
        INFO.ebias = H5T__find_bias(INFO.epos, INFO.esize, INFO.perm, &_v1);                                 \
143
3
        H5T__set_precision(&(INFO));                                                                         \
144
3
        COMP_ALIGNMENT(TYPE, INFO.comp_align);                                                               \
145
3
    } while (0)
146
147
/* Detect alignment for C structure */
148
#define COMP_ALIGNMENT(TYPE, COMP_ALIGN)                                                                     \
149
3
    {                                                                                                        \
150
3
        struct {                                                                                             \
151
3
            char c;                                                                                          \
152
3
            TYPE x;                                                                                          \
153
3
        } s;                                                                                                 \
154
3
                                                                                                             \
155
3
        COMP_ALIGN = (unsigned)((char *)(&(s.x)) - (char *)(&s));                                            \
156
3
    }
157
158
/******************/
159
/* Local Typedefs */
160
/******************/
161
162
/* Holds detected information about a native floating-point type */
163
typedef struct H5T_fpoint_det_t {
164
    unsigned      size;             /* Total byte size                  */
165
    unsigned      prec;             /* Meaningful bits                  */
166
    unsigned      offset;           /* Bit offset to meaningful bits    */
167
    int           perm[32];         /* For detection of byte order      */
168
    H5T_order_t   order;            /* byte order                       */
169
    unsigned      sign;             /* Location of sign bit             */
170
    unsigned      mpos, msize, imp; /* Information about mantissa       */
171
    H5T_norm_t    norm;             /* Information about mantissa       */
172
    unsigned      epos, esize;      /* Information about exponent       */
173
    unsigned long ebias;            /* Exponent bias for floating point */
174
    unsigned      comp_align;       /* Alignment for structure          */
175
} H5T_fpoint_det_t;
176
177
/********************/
178
/* Package Typedefs */
179
/********************/
180
181
/********************/
182
/* Local Prototypes */
183
/********************/
184
185
/********************/
186
/* Public Variables */
187
/********************/
188
189
/*****************************/
190
/* Library Private Variables */
191
/*****************************/
192
193
/*********************/
194
/* Package Variables */
195
/*********************/
196
197
/*******************/
198
/* Local Variables */
199
/*******************/
200
201
/* Functions used in the DETECT_F() macro */
202
static int      H5T__byte_cmp(int, const void *, const void *, const unsigned char *);
203
static herr_t   H5T__bit_cmp(unsigned, int *, void *, void *, const unsigned char *, unsigned *);
204
static herr_t   H5T__fix_order(int, int, int *, H5T_order_t *);
205
static herr_t   H5T__imp_bit(unsigned, int *, void *, void *, const unsigned char *, unsigned *);
206
static unsigned H5T__find_bias(unsigned, unsigned, int *, void *);
207
static void     H5T__set_precision(H5T_fpoint_det_t *);
208
209
/*-------------------------------------------------------------------------
210
 * Function:    H5T__byte_cmp
211
 *
212
 * Purpose:     Compares two chunks of memory A and B and returns the
213
 *              byte index into those arrays of the first byte that
214
 *              differs between A and B.  Ignores differences where the
215
 *              corresponding bit in pad_mask is set to 0.
216
 *
217
 * Return:      Success:    Index of differing byte.
218
 *              Failure:    -1 if all bytes are the same.
219
 *-------------------------------------------------------------------------
220
 */
221
static int
222
H5T__byte_cmp(int n, const void *_a, const void *_b, const unsigned char *pad_mask)
223
28
{
224
28
    const unsigned char *a         = (const unsigned char *)_a;
225
28
    const unsigned char *b         = (const unsigned char *)_b;
226
28
    int                  ret_value = -1;
227
228
28
    FUNC_ENTER_PACKAGE_NOERR
229
230
220
    for (int i = 0; i < n; i++)
231
210
        if ((a[i] & pad_mask[i]) != (b[i] & pad_mask[i]))
232
18
            HGOTO_DONE(i);
233
234
28
done:
235
28
    FUNC_LEAVE_NOAPI(ret_value)
236
28
}
237
238
/*-------------------------------------------------------------------------
239
 * Function:    H5T__bit_cmp
240
 *
241
 * Purpose:     Compares two bit vectors and returns the index for the
242
 *              first bit that differs between the two vectors.     The
243
 *              size of the vector is NBYTES.  PERM is a mapping from
244
 *              actual order to little endian.  Ignores differences where
245
 *              the corresponding bit in pad_mask is set to 0.
246
 *
247
 *              Sets `first` to the index of the first differing bit
248
 *
249
 * Return:      SUCCEED/FAIL
250
 *-------------------------------------------------------------------------
251
 */
252
static herr_t
253
H5T__bit_cmp(unsigned nbytes, int *perm, void *_a, void *_b, const unsigned char *pad_mask, unsigned *first)
254
9
{
255
9
    unsigned char *a = (unsigned char *)_a;
256
9
    unsigned char *b = (unsigned char *)_b;
257
9
    unsigned char  aa, bb;
258
9
    herr_t         ret_value = SUCCEED;
259
260
9
    FUNC_ENTER_PACKAGE
261
262
9
    *first = 0;
263
264
59
    for (unsigned i = 0; i < nbytes; i++) {
265
59
        if (perm[i] >= (int)nbytes)
266
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "failure in bit comparison");
267
59
        if ((aa = (unsigned char)(a[perm[i]] & pad_mask[perm[i]])) !=
268
59
            (bb = (unsigned char)(b[perm[i]] & pad_mask[perm[i]]))) {
269
270
56
            for (unsigned j = 0; j < 8; j++, aa >>= 1, bb >>= 1) {
271
56
                if ((aa & 1) != (bb & 1)) {
272
9
                    *first = i * 8 + j;
273
9
                    HGOTO_DONE(SUCCEED);
274
9
                }
275
56
            }
276
9
        }
277
59
    }
278
279
    /* If we got here and didn't set a value, error out */
280
0
    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "didn't find a value for `first`");
281
282
9
done:
283
9
    FUNC_LEAVE_NOAPI(ret_value)
284
9
}
285
286
/*-------------------------------------------------------------------------
287
 * Function:    H5T__fix_order
288
 *
289
 * Purpose:     Given an array PERM with elements FIRST through LAST
290
 *              initialized with zero origin byte numbers, this function
291
 *              creates a permutation vector that maps the actual order
292
 *              of a floating point number to little-endian.
293
 *
294
 *              This function assumes that the mantissa byte ordering
295
 *              implies the total ordering.
296
 *
297
 * Return:      SUCCEED/FAIL
298
 *-------------------------------------------------------------------------
299
 */
300
static herr_t
301
H5T__fix_order(int n, int last, int *perm, H5T_order_t *order)
302
3
{
303
3
    herr_t ret_value = SUCCEED;
304
305
3
    FUNC_ENTER_PACKAGE
306
307
3
    if (last <= 0)
308
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "failed to detect byte order");
309
310
3
    if (perm[last] < perm[last - 1] &&
311
        /* Only check perm[last - 2] if we have more than 2 points to consider */
312
3
        ((last < 2) || (perm[last - 1] < perm[last - 2]))) {
313
        /* Little endian */
314
3
        *order = H5T_ORDER_LE;
315
31
        for (int i = 0; i < n; i++)
316
28
            perm[i] = i;
317
3
    }
318
0
    else if (perm[last] > perm[last - 1] &&
319
             /* Only check perm[last - 2] if we have more than 2 points to consider */
320
0
             ((last < 2) || (perm[last - 1] > perm[last - 2]))) {
321
        /* Big endian */
322
0
        *order = H5T_ORDER_BE;
323
0
        for (int i = 0; i < n; i++)
324
0
            perm[i] = (n - 1) - i;
325
0
    }
326
0
    else {
327
        /* Undetermined endianness - defaults to 'VAX' for historical
328
         * reasons, but there are other mixed-endian systems (like ARM
329
         * in rare cases)
330
         */
331
0
        if (0 != n % 2)
332
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "n is not a power of 2");
333
334
0
        *order = H5T_ORDER_VAX;
335
0
        for (int i = 0; i < n; i += 2) {
336
0
            perm[i]     = (n - 2) - i;
337
0
            perm[i + 1] = (n - 1) - i;
338
0
        }
339
0
    }
340
341
3
done:
342
3
    FUNC_LEAVE_NOAPI(ret_value)
343
3
}
344
345
/*-------------------------------------------------------------------------
346
 * Function:    H5T__imp_bit
347
 *
348
 * Purpose:     Looks for an implicit bit in the mantissa.  The value
349
 *              of _A should be 1.0 and the value of _B should be 0.5.
350
 *              Some floating-point formats discard the most significant
351
 *              bit of the mantissa after normalizing since it will always
352
 *              be a one (except for 0.0).  If this is true for the native
353
 *              floating point values stored in _A and _B then the function
354
 *              returns non-zero.
355
 *
356
 *              This function assumes that the exponent occupies higher
357
 *              order bits than the mantissa and that the most significant
358
 *              bit of the mantissa is next to the least significant bit
359
 *              of the exponent.
360
 *
361
 *
362
 * Return:      imp_bit will be set to 1 if the most significant bit
363
 *              of the mantissa is discarded (ie, the mantissa has an
364
 *              implicit `one' as the most significant bit). Otherwise,
365
 *              imp_bit will be set to zero.
366
 *
367
 *              SUCCEED/FAIL
368
 *-------------------------------------------------------------------------
369
 */
370
static herr_t
371
H5T__imp_bit(unsigned n, int *perm, void *_a, void *_b, const unsigned char *pad_mask, unsigned *imp_bit)
372
3
{
373
3
    unsigned char *a = (unsigned char *)_a;
374
3
    unsigned char *b = (unsigned char *)_b;
375
3
    unsigned       changed;
376
3
    unsigned       major;
377
3
    unsigned       minor;
378
3
    unsigned       msmb; /* Most significant mantissa bit */
379
3
    herr_t         ret_value = SUCCEED;
380
381
3
    FUNC_ENTER_PACKAGE
382
383
    /* Look for the least significant bit that has changed between
384
     * A and B.  This is the least significant bit of the exponent.
385
     */
386
3
    if (H5T__bit_cmp(n, perm, a, b, pad_mask, &changed) < 0)
387
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "couldn't find LSB");
388
389
    /* The bit to the right (less significant) of the changed bit should
390
     * be the most significant bit of the mantissa.  If it is non-zero
391
     * then the format does not remove the leading `1' of the mantissa.
392
     */
393
3
    msmb  = changed - 1;
394
3
    major = msmb / 8;
395
3
    minor = msmb % 8;
396
397
3
    *imp_bit = (a[perm[major]] >> minor) & 0x01 ? 0 : 1;
398
399
3
done:
400
3
    FUNC_LEAVE_NOAPI(ret_value)
401
3
}
402
403
/*-------------------------------------------------------------------------
404
 * Function:  find_bias
405
 *
406
 * Purpose:   Determines the bias of the exponent.  This function should
407
 *            be called with _A having a value of `1'.
408
 *
409
 * Return:    The exponent bias
410
 *-------------------------------------------------------------------------
411
 */
412
H5_ATTR_PURE static unsigned
413
H5T__find_bias(unsigned epos, unsigned esize, int *perm, void *_a)
414
3
{
415
3
    unsigned char *a = (unsigned char *)_a;
416
3
    unsigned char  mask;
417
3
    unsigned       b, shift = 0, nbits, bias = 0;
418
419
3
    FUNC_ENTER_PACKAGE_NOERR
420
421
9
    while (esize > 0) {
422
6
        nbits = MIN(esize, (8 - epos % 8));
423
6
        mask  = (unsigned char)((1 << nbits) - 1);
424
6
        b     = (unsigned)(a[perm[epos / 8]] >> (epos % 8)) & mask;
425
6
        bias |= b << shift;
426
427
6
        shift += nbits;
428
6
        esize -= nbits;
429
6
        epos += nbits;
430
6
    }
431
432
3
    FUNC_LEAVE_NOAPI(bias)
433
3
}
434
435
/*-------------------------------------------------------------------------
436
 * Function:    H5T__set_precision
437
 *
438
 * Purpose:     Determine the precision and offset
439
 *
440
 * Return:      void
441
 *-------------------------------------------------------------------------
442
 */
443
static void
444
H5T__set_precision(H5T_fpoint_det_t *d)
445
3
{
446
3
    FUNC_ENTER_PACKAGE_NOERR
447
448
3
    d->offset = MIN3(d->mpos, d->epos, d->sign);
449
3
    d->prec   = d->msize + d->esize + 1;
450
451
3
    FUNC_LEAVE_NOAPI_VOID
452
3
}
453
454
/*-------------------------------------------------------------------------
455
 * Function:    H5T__init_native_float_types
456
 *
457
 * Purpose:     Initialize native floating-point datatypes
458
 *
459
 * Return:      Success:    non-negative
460
 *              Failure:    negative
461
 *-------------------------------------------------------------------------
462
 */
463
herr_t H5_NO_UBSAN
464
H5T__init_native_float_types(void)
465
1
{
466
1
    fenv_t           saved_fenv;
467
1
    H5T_fpoint_det_t det;
468
1
    H5T_t           *dt        = NULL;
469
1
    herr_t           ret_value = SUCCEED;
470
471
1
    FUNC_ENTER_PACKAGE
472
473
    /* Turn off floating-point exceptions while initializing to avoid
474
     * tripping over signaling NaNs while looking at "don't care" bits.
475
     */
476
1
    if (feholdexcept(&saved_fenv) != 0)
477
1
        HSYS_GOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't save floating-point environment");
478
479
    /* H5T_NATIVE_FLOAT */
480
481
    /* Get the type's characteristics */
482
1
    memset(&det, 0, sizeof(H5T_fpoint_det_t));
483
1
    DETECT_F(float, det);
484
485
    /* Allocate and fill type structure */
486
1
    if (NULL == (dt = H5T__alloc()))
487
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, "datatype allocation failed");
488
1
    dt->shared->state              = H5T_STATE_IMMUTABLE;
489
1
    dt->shared->type               = H5T_FLOAT;
490
1
    dt->shared->size               = det.size;
491
1
    dt->shared->u.atomic.order     = det.order;
492
1
    dt->shared->u.atomic.offset    = det.offset;
493
1
    dt->shared->u.atomic.prec      = det.prec;
494
1
    dt->shared->u.atomic.lsb_pad   = H5T_PAD_ZERO;
495
1
    dt->shared->u.atomic.msb_pad   = H5T_PAD_ZERO;
496
1
    dt->shared->u.atomic.u.f.sign  = det.sign;
497
1
    dt->shared->u.atomic.u.f.epos  = det.epos;
498
1
    dt->shared->u.atomic.u.f.esize = det.esize;
499
1
    dt->shared->u.atomic.u.f.ebias = det.ebias;
500
1
    dt->shared->u.atomic.u.f.mpos  = det.mpos;
501
1
    dt->shared->u.atomic.u.f.msize = det.msize;
502
1
    dt->shared->u.atomic.u.f.norm  = det.norm;
503
1
    dt->shared->u.atomic.u.f.pad   = H5T_PAD_ZERO;
504
505
    /* Register the type and set global variables */
506
1
    if ((H5T_NATIVE_FLOAT_g = H5I_register(H5I_DATATYPE, dt, false)) < 0)
507
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "can't register ID for built-in datatype");
508
1
    H5T_NATIVE_FLOAT_ALIGN_g = det.comp_align;
509
510
    /* H5T_NATIVE_DOUBLE */
511
512
    /* Get the type's characteristics */
513
1
    memset(&det, 0, sizeof(H5T_fpoint_det_t));
514
1
    DETECT_F(double, det);
515
516
    /* Allocate and fill type structure */
517
1
    if (NULL == (dt = H5T__alloc()))
518
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, "datatype allocation failed");
519
1
    dt->shared->state              = H5T_STATE_IMMUTABLE;
520
1
    dt->shared->type               = H5T_FLOAT;
521
1
    dt->shared->size               = det.size;
522
1
    dt->shared->u.atomic.order     = det.order;
523
1
    dt->shared->u.atomic.offset    = det.offset;
524
1
    dt->shared->u.atomic.prec      = det.prec;
525
1
    dt->shared->u.atomic.lsb_pad   = H5T_PAD_ZERO;
526
1
    dt->shared->u.atomic.msb_pad   = H5T_PAD_ZERO;
527
1
    dt->shared->u.atomic.u.f.sign  = det.sign;
528
1
    dt->shared->u.atomic.u.f.epos  = det.epos;
529
1
    dt->shared->u.atomic.u.f.esize = det.esize;
530
1
    dt->shared->u.atomic.u.f.ebias = det.ebias;
531
1
    dt->shared->u.atomic.u.f.mpos  = det.mpos;
532
1
    dt->shared->u.atomic.u.f.msize = det.msize;
533
1
    dt->shared->u.atomic.u.f.norm  = det.norm;
534
1
    dt->shared->u.atomic.u.f.pad   = H5T_PAD_ZERO;
535
536
    /* Register the type and set global variables */
537
1
    if ((H5T_NATIVE_DOUBLE_g = H5I_register(H5I_DATATYPE, dt, false)) < 0)
538
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "can't register ID for built-in datatype");
539
1
    H5T_NATIVE_DOUBLE_ALIGN_g = det.comp_align;
540
541
    /* H5T_NATIVE_LDOUBLE */
542
543
    /* Get the type's characteristics */
544
1
    memset(&det, 0, sizeof(H5T_fpoint_det_t));
545
1
    DETECT_F(long double, det);
546
547
    /* Allocate and fill type structure */
548
1
    if (NULL == (dt = H5T__alloc()))
549
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, "datatype allocation failed");
550
1
    dt->shared->state              = H5T_STATE_IMMUTABLE;
551
1
    dt->shared->type               = H5T_FLOAT;
552
1
    dt->shared->size               = det.size;
553
1
    dt->shared->u.atomic.order     = det.order;
554
1
    dt->shared->u.atomic.offset    = det.offset;
555
1
    dt->shared->u.atomic.prec      = det.prec;
556
1
    dt->shared->u.atomic.lsb_pad   = H5T_PAD_ZERO;
557
1
    dt->shared->u.atomic.msb_pad   = H5T_PAD_ZERO;
558
1
    dt->shared->u.atomic.u.f.sign  = det.sign;
559
1
    dt->shared->u.atomic.u.f.epos  = det.epos;
560
1
    dt->shared->u.atomic.u.f.esize = det.esize;
561
1
    dt->shared->u.atomic.u.f.ebias = det.ebias;
562
1
    dt->shared->u.atomic.u.f.mpos  = det.mpos;
563
1
    dt->shared->u.atomic.u.f.msize = det.msize;
564
1
    dt->shared->u.atomic.u.f.norm  = det.norm;
565
1
    dt->shared->u.atomic.u.f.pad   = H5T_PAD_ZERO;
566
567
    /* Register the type and set global variables */
568
1
    if ((H5T_NATIVE_LDOUBLE_g = H5I_register(H5I_DATATYPE, dt, false)) < 0)
569
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "can't register ID for built-in datatype");
570
1
    H5T_NATIVE_LDOUBLE_ALIGN_g = det.comp_align;
571
572
    /* Set the platform's alignment (assumes long double's order
573
     * is true for all types)
574
     */
575
1
    H5T_native_order_g = det.order;
576
577
#ifdef H5_HAVE__FLOAT16
578
    /* H5T_NATIVE_FLOAT16 */
579
580
    /* Get the type's characteristics */
581
    memset(&det, 0, sizeof(H5T_fpoint_det_t));
582
    DETECT_F(H5__Float16, det);
583
584
    /* Allocate and fill type structure */
585
    if (NULL == (dt = H5T__alloc()))
586
        HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, "datatype allocation failed");
587
    dt->shared->state              = H5T_STATE_IMMUTABLE;
588
    dt->shared->type               = H5T_FLOAT;
589
    dt->shared->size               = det.size;
590
    dt->shared->u.atomic.order     = det.order;
591
    dt->shared->u.atomic.offset    = det.offset;
592
    dt->shared->u.atomic.prec      = det.prec;
593
    dt->shared->u.atomic.lsb_pad   = H5T_PAD_ZERO;
594
    dt->shared->u.atomic.msb_pad   = H5T_PAD_ZERO;
595
    dt->shared->u.atomic.u.f.sign  = det.sign;
596
    dt->shared->u.atomic.u.f.epos  = det.epos;
597
    dt->shared->u.atomic.u.f.esize = det.esize;
598
    dt->shared->u.atomic.u.f.ebias = det.ebias;
599
    dt->shared->u.atomic.u.f.mpos  = det.mpos;
600
    dt->shared->u.atomic.u.f.msize = det.msize;
601
    dt->shared->u.atomic.u.f.norm  = det.norm;
602
    dt->shared->u.atomic.u.f.pad   = H5T_PAD_ZERO;
603
604
    /* Register the type and set global variables */
605
    if ((H5T_NATIVE_FLOAT16_g = H5I_register(H5I_DATATYPE, dt, false)) < 0)
606
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "can't register ID for built-in datatype");
607
    H5T_NATIVE_FLOAT16_ALIGN_g = det.comp_align;
608
#endif
609
610
1
done:
611
    /* Clear any FE_INVALID exceptions from NaN handling. FE_INVALID is C99/C11,
612
     * but may not be present on all systems.
613
     */
614
1
#ifdef FE_INVALID
615
1
    if (feclearexcept(FE_INVALID) != 0)
616
1
        HSYS_GOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't clear floating-point exceptions");
617
1
#endif
618
619
    /* Restore the original environment */
620
1
    if (feupdateenv(&saved_fenv) != 0)
621
1
        HSYS_GOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't restore floating-point environment");
622
623
1
    if (ret_value < 0) {
624
0
        if (dt != NULL) {
625
0
            dt->shared = H5FL_FREE(H5T_shared_t, dt->shared);
626
0
            dt         = H5FL_FREE(H5T_t, dt);
627
0
        }
628
0
    }
629
630
1
    FUNC_LEAVE_NOAPI(ret_value)
631
1
} /* end H5T__init_native_float_types() */