/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() */ |