/src/hdf5/src/H5Tprecis.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 | | * Module Info: This module contains the functionality for setting & querying |
15 | | * the datatype precision for the H5T interface. |
16 | | */ |
17 | | |
18 | | #include "H5Tmodule.h" /* This source code file is part of the H5T module */ |
19 | | |
20 | | #include "H5private.h" /* Generic Functions */ |
21 | | #include "H5Eprivate.h" /* Error handling */ |
22 | | #include "H5Iprivate.h" /* IDs */ |
23 | | #include "H5Tpkg.h" /* Datatypes */ |
24 | | |
25 | | /* Static local functions */ |
26 | | static herr_t H5T__set_precision(const H5T_t *dt, size_t prec); |
27 | | |
28 | | /*------------------------------------------------------------------------- |
29 | | * Function: H5Tget_precision |
30 | | * |
31 | | * Purpose: Gets the precision of a datatype. The precision is |
32 | | * the number of significant bits which, unless padding is |
33 | | * present, is 8 times larger than the value returned by |
34 | | * H5Tget_size(). |
35 | | * |
36 | | * Return: Success: Number of significant bits |
37 | | * |
38 | | * Failure: 0 (all atomic types have at least one |
39 | | * significant bit) |
40 | | * |
41 | | *------------------------------------------------------------------------- |
42 | | */ |
43 | | size_t |
44 | | H5Tget_precision(hid_t type_id) |
45 | 0 | { |
46 | 0 | H5T_t *dt; |
47 | 0 | size_t ret_value; |
48 | |
|
49 | 0 | FUNC_ENTER_API(0) |
50 | | |
51 | | /* Check args */ |
52 | 0 | if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) |
53 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a datatype"); |
54 | | |
55 | | /* Get precision */ |
56 | 0 | if ((ret_value = H5T_get_precision(dt)) == 0) |
57 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, 0, "can't get precision for specified datatype"); |
58 | | |
59 | 0 | done: |
60 | 0 | FUNC_LEAVE_API(ret_value) |
61 | 0 | } /* end H5Tget_precision() */ |
62 | | |
63 | | /*------------------------------------------------------------------------- |
64 | | * Function: H5T_get_precision |
65 | | * |
66 | | * Purpose: Gets the precision of a datatype. The precision is |
67 | | * the number of significant bits which, unless padding is |
68 | | * present, is 8 times larger than the value returned by |
69 | | * H5Tget_size(). |
70 | | * |
71 | | * Return: Success: Number of significant bits |
72 | | * Failure: 0 (all atomic types have at least one |
73 | | * significant bit) |
74 | | * |
75 | | *------------------------------------------------------------------------- |
76 | | */ |
77 | | size_t |
78 | | H5T_get_precision(const H5T_t *dt) |
79 | 0 | { |
80 | 0 | size_t ret_value = 0; /* Return value */ |
81 | |
|
82 | 0 | FUNC_ENTER_NOAPI(0) |
83 | | |
84 | | /* Defer to parent*/ |
85 | 0 | while (dt->shared->parent) |
86 | 0 | dt = dt->shared->parent; |
87 | 0 | if (!H5T_IS_ATOMIC(dt->shared)) |
88 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, 0, "operation not defined for specified datatype"); |
89 | | |
90 | | /* Precision */ |
91 | 0 | ret_value = dt->shared->u.atomic.prec; |
92 | |
|
93 | 0 | done: |
94 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
95 | 0 | } /* end H5T_get_precision() */ |
96 | | |
97 | | /*------------------------------------------------------------------------- |
98 | | * Function: H5Tset_precision |
99 | | * |
100 | | * Purpose: Sets the precision of a datatype. The precision is |
101 | | * the number of significant bits which, unless padding is |
102 | | * present, is 8 times larger than the value returned by |
103 | | * H5Tget_size(). |
104 | | * |
105 | | * If the precision is increased then the offset is decreased |
106 | | * and then the size is increased to insure that significant |
107 | | * bits do not "hang over" the edge of the datatype. |
108 | | * |
109 | | * The precision property of strings is read-only. |
110 | | * |
111 | | * When decreasing the precision of a floating point type, set |
112 | | * the locations and sizes of the sign, mantissa, and exponent |
113 | | * fields first. |
114 | | * |
115 | | * Return: Non-negative on success/Negative on failure |
116 | | * |
117 | | *------------------------------------------------------------------------- |
118 | | */ |
119 | | herr_t |
120 | | H5Tset_precision(hid_t type_id, size_t prec) |
121 | 0 | { |
122 | 0 | H5T_t *dt = NULL; |
123 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
124 | |
|
125 | 0 | FUNC_ENTER_API(FAIL) |
126 | | |
127 | | /* Check args */ |
128 | 0 | if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) |
129 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); |
130 | 0 | if (H5T_STATE_TRANSIENT != dt->shared->state) |
131 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_CANTSET, FAIL, "datatype is read-only"); |
132 | 0 | if (NULL != dt->vol_obj) |
133 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_CANTSET, FAIL, "datatype is committed"); |
134 | 0 | if (prec == 0) |
135 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "precision must be positive"); |
136 | 0 | if (H5T_ENUM == dt->shared->type && dt->shared->u.enumer.nmembs > 0) |
137 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "operation not allowed after members are defined"); |
138 | 0 | if (H5T_STRING == dt->shared->type) |
139 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "precision for this type is read-only"); |
140 | 0 | if (H5T_COMPOUND == dt->shared->type || H5T_OPAQUE == dt->shared->type) |
141 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "operation not defined for specified datatype"); |
142 | | |
143 | | /* Do the work */ |
144 | 0 | if (H5T__set_precision(dt, prec) < 0) |
145 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "unable to set precision"); |
146 | | |
147 | 0 | done: |
148 | 0 | FUNC_LEAVE_API(ret_value) |
149 | 0 | } |
150 | | |
151 | | /*------------------------------------------------------------------------- |
152 | | * Function: H5T__set_precision |
153 | | * |
154 | | * Purpose: Sets the precision of a datatype. The precision is |
155 | | * the number of significant bits which, unless padding is |
156 | | * present, is 8 times larger than the value returned by |
157 | | * H5Tget_size(). |
158 | | * |
159 | | * If the precision is increased then the offset is decreased |
160 | | * and then the size is increased to insure that significant |
161 | | * bits do not "hang over" the edge of the datatype. |
162 | | * |
163 | | * The precision property of strings is read-only. |
164 | | * |
165 | | * When decreasing the precision of a floating point type, set |
166 | | * the locations and sizes of the sign, mantissa, and exponent |
167 | | * fields first. |
168 | | * |
169 | | * Return: Non-negative on success/Negative on failure |
170 | | * |
171 | | *------------------------------------------------------------------------- |
172 | | */ |
173 | | static herr_t |
174 | | H5T__set_precision(const H5T_t *dt, size_t prec) |
175 | 0 | { |
176 | 0 | size_t offset, size; |
177 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
178 | |
|
179 | 0 | FUNC_ENTER_PACKAGE |
180 | | |
181 | | /* Check args */ |
182 | 0 | assert(dt); |
183 | 0 | assert(prec > 0); |
184 | 0 | assert(H5T_OPAQUE != dt->shared->type); |
185 | 0 | assert(H5T_COMPOUND != dt->shared->type); |
186 | 0 | assert(H5T_STRING != dt->shared->type); |
187 | 0 | assert(!(H5T_ENUM == dt->shared->type && 0 == dt->shared->u.enumer.nmembs)); |
188 | |
|
189 | 0 | if (dt->shared->parent) { |
190 | 0 | if (H5T__set_precision(dt->shared->parent, prec) < 0) |
191 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "unable to set precision for base type"); |
192 | | |
193 | | /* Adjust size of datatype appropriately */ |
194 | 0 | if (dt->shared->type == H5T_ARRAY) |
195 | 0 | dt->shared->size = dt->shared->parent->shared->size * dt->shared->u.array.nelem; |
196 | 0 | else if (dt->shared->type == H5T_COMPLEX) |
197 | 0 | dt->shared->size = 2 * dt->shared->parent->shared->size; |
198 | 0 | else if (dt->shared->type != H5T_VLEN) |
199 | 0 | dt->shared->size = dt->shared->parent->shared->size; |
200 | 0 | } |
201 | 0 | else { |
202 | 0 | if (H5T_IS_ATOMIC(dt->shared)) { |
203 | | /* Adjust the offset and size */ |
204 | 0 | offset = dt->shared->u.atomic.offset; |
205 | 0 | size = dt->shared->size; |
206 | 0 | if (prec > 8 * size) |
207 | 0 | offset = 0; |
208 | 0 | else if (offset + prec > 8 * size) |
209 | 0 | offset = 8 * size - prec; |
210 | 0 | if (prec > 8 * size) |
211 | 0 | size = (prec + 7) / 8; |
212 | | |
213 | | /* Check that things are still kosher */ |
214 | 0 | switch (dt->shared->type) { |
215 | 0 | case H5T_INTEGER: |
216 | 0 | case H5T_TIME: |
217 | 0 | case H5T_BITFIELD: |
218 | | /* nothing to check */ |
219 | 0 | break; |
220 | | |
221 | 0 | case H5T_FLOAT: |
222 | | /* |
223 | | * The sign, mantissa, and exponent fields should be adjusted |
224 | | * first when decreasing the precision of a floating point |
225 | | * type. |
226 | | */ |
227 | 0 | if (dt->shared->u.atomic.u.f.sign >= prec + offset || |
228 | 0 | dt->shared->u.atomic.u.f.epos + dt->shared->u.atomic.u.f.esize > prec + offset || |
229 | 0 | dt->shared->u.atomic.u.f.mpos + dt->shared->u.atomic.u.f.msize > prec + offset) |
230 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, |
231 | 0 | "adjust sign, mantissa, and exponent fields first"); |
232 | 0 | break; |
233 | | |
234 | 0 | case H5T_NO_CLASS: |
235 | 0 | case H5T_STRING: |
236 | 0 | case H5T_OPAQUE: |
237 | 0 | case H5T_COMPOUND: |
238 | 0 | case H5T_REFERENCE: |
239 | 0 | case H5T_ENUM: |
240 | 0 | case H5T_VLEN: |
241 | 0 | case H5T_ARRAY: |
242 | 0 | case H5T_COMPLEX: |
243 | 0 | case H5T_NCLASSES: |
244 | 0 | default: |
245 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "operation not defined for datatype class"); |
246 | 0 | } /* end switch */ |
247 | | |
248 | | /* Commit */ |
249 | 0 | dt->shared->size = size; |
250 | 0 | dt->shared->u.atomic.offset = offset; |
251 | 0 | dt->shared->u.atomic.prec = prec; |
252 | 0 | } /* end if */ |
253 | 0 | else |
254 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for specified datatype"); |
255 | 0 | } /* end else */ |
256 | | |
257 | 0 | done: |
258 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
259 | 0 | } |