hdf5_misc.hpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  1. // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
  2. // Copyright 2008-2016 National ICT Australia (NICTA)
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // ------------------------------------------------------------------------
  15. //! \addtogroup hdf5_misc
  16. //! @{
  17. #if defined(ARMA_USE_HDF5)
  18. namespace hdf5_misc
  19. {
  20. //! Given a certain type, find the corresponding HDF5 datatype. This can't be
  21. //! done entirely at compile time, unfortunately, because the H5T_* macros
  22. //! depend on function calls.
  23. template< typename eT >
  24. inline
  25. hid_t
  26. get_hdf5_type()
  27. {
  28. return -1; // Return invalid.
  29. }
  30. //! Specializations for each valid element type
  31. //! (taken from all the possible typedefs of {u8, s8, ..., u64, s64} and the other native types.
  32. //! We can't use the actual u8/s8 typedefs because their relations to the H5T_... types are unclear.
  33. template<>
  34. inline
  35. hid_t
  36. get_hdf5_type< unsigned char >()
  37. {
  38. return arma_H5Tcopy(arma_H5T_NATIVE_UCHAR);
  39. }
  40. template<>
  41. inline
  42. hid_t
  43. get_hdf5_type< char >()
  44. {
  45. return arma_H5Tcopy(arma_H5T_NATIVE_CHAR);
  46. }
  47. template<>
  48. inline
  49. hid_t
  50. get_hdf5_type< short >()
  51. {
  52. return arma_H5Tcopy(arma_H5T_NATIVE_SHORT);
  53. }
  54. template<>
  55. inline
  56. hid_t
  57. get_hdf5_type< unsigned short >()
  58. {
  59. return arma_H5Tcopy(arma_H5T_NATIVE_USHORT);
  60. }
  61. template<>
  62. inline
  63. hid_t
  64. get_hdf5_type< int >()
  65. {
  66. return arma_H5Tcopy(arma_H5T_NATIVE_INT);
  67. }
  68. template<>
  69. inline
  70. hid_t
  71. get_hdf5_type< unsigned int >()
  72. {
  73. return arma_H5Tcopy(arma_H5T_NATIVE_UINT);
  74. }
  75. template<>
  76. inline
  77. hid_t
  78. get_hdf5_type< long >()
  79. {
  80. return arma_H5Tcopy(arma_H5T_NATIVE_LONG);
  81. }
  82. template<>
  83. inline
  84. hid_t
  85. get_hdf5_type< unsigned long >()
  86. {
  87. return arma_H5Tcopy(arma_H5T_NATIVE_ULONG);
  88. }
  89. #if defined(ARMA_USE_U64S64) && defined(ULLONG_MAX)
  90. template<>
  91. inline
  92. hid_t
  93. get_hdf5_type< long long >()
  94. {
  95. return arma_H5Tcopy(arma_H5T_NATIVE_LLONG);
  96. }
  97. template<>
  98. inline
  99. hid_t
  100. get_hdf5_type< unsigned long long >()
  101. {
  102. return arma_H5Tcopy(arma_H5T_NATIVE_ULLONG);
  103. }
  104. #endif
  105. template<>
  106. inline
  107. hid_t
  108. get_hdf5_type< float >()
  109. {
  110. return arma_H5Tcopy(arma_H5T_NATIVE_FLOAT);
  111. }
  112. template<>
  113. inline
  114. hid_t
  115. get_hdf5_type< double >()
  116. {
  117. return arma_H5Tcopy(arma_H5T_NATIVE_DOUBLE);
  118. }
  119. //! Utility hid_t since HOFFSET() won't work with std::complex.
  120. template<typename eT>
  121. struct hdf5_complex_t
  122. {
  123. eT real;
  124. eT imag;
  125. };
  126. template<>
  127. inline
  128. hid_t
  129. get_hdf5_type< std::complex<float> >()
  130. {
  131. hid_t type = arma_H5Tcreate(H5T_COMPOUND, sizeof(hdf5_complex_t<float>));
  132. arma_H5Tinsert(type, "real", HOFFSET(hdf5_complex_t<float>, real), arma_H5T_NATIVE_FLOAT);
  133. arma_H5Tinsert(type, "imag", HOFFSET(hdf5_complex_t<float>, imag), arma_H5T_NATIVE_FLOAT);
  134. return type;
  135. }
  136. template<>
  137. inline
  138. hid_t
  139. get_hdf5_type< std::complex<double> >()
  140. {
  141. hid_t type = arma_H5Tcreate(H5T_COMPOUND, sizeof(hdf5_complex_t<double>));
  142. arma_H5Tinsert(type, "real", HOFFSET(hdf5_complex_t<double>, real), arma_H5T_NATIVE_DOUBLE);
  143. arma_H5Tinsert(type, "imag", HOFFSET(hdf5_complex_t<double>, imag), arma_H5T_NATIVE_DOUBLE);
  144. return type;
  145. }
  146. // Compare datatype against all supported types.
  147. inline
  148. bool
  149. is_supported_arma_hdf5_type(hid_t datatype)
  150. {
  151. hid_t search_type;
  152. bool is_equal;
  153. // start with most likely used types: double, complex<double>, float, complex<float>
  154. search_type = get_hdf5_type<double>();
  155. is_equal = ( arma_H5Tequal(datatype, search_type) > 0 );
  156. arma_H5Tclose(search_type);
  157. if (is_equal) { return true; }
  158. search_type = get_hdf5_type< std::complex<double> >();
  159. is_equal = ( arma_H5Tequal(datatype, search_type) > 0 );
  160. arma_H5Tclose(search_type);
  161. if (is_equal) { return true; }
  162. search_type = get_hdf5_type<float>();
  163. is_equal = ( arma_H5Tequal(datatype, search_type) > 0 );
  164. arma_H5Tclose(search_type);
  165. if (is_equal) { return true; }
  166. search_type = get_hdf5_type< std::complex<float> >();
  167. is_equal = ( arma_H5Tequal(datatype, search_type) > 0 );
  168. arma_H5Tclose(search_type);
  169. if (is_equal) { return true; }
  170. // remaining supported types: u8, s8, u16, s16, u32, s32, u64, s64, ulng_t, slng_t
  171. search_type = get_hdf5_type<u8>();
  172. is_equal = ( arma_H5Tequal(datatype, search_type) > 0 );
  173. arma_H5Tclose(search_type);
  174. if (is_equal) { return true; }
  175. search_type = get_hdf5_type<s8>();
  176. is_equal = ( arma_H5Tequal(datatype, search_type) > 0 );
  177. arma_H5Tclose(search_type);
  178. if (is_equal) { return true; }
  179. search_type = get_hdf5_type<u16>();
  180. is_equal = ( arma_H5Tequal(datatype, search_type) > 0 );
  181. arma_H5Tclose(search_type);
  182. if (is_equal) { return true; }
  183. search_type = get_hdf5_type<s16>();
  184. is_equal = ( arma_H5Tequal(datatype, search_type) > 0 );
  185. arma_H5Tclose(search_type);
  186. if (is_equal) { return true; }
  187. search_type = get_hdf5_type<u32>();
  188. is_equal = ( arma_H5Tequal(datatype, search_type) > 0 );
  189. arma_H5Tclose(search_type);
  190. if (is_equal) { return true; }
  191. search_type = get_hdf5_type<s32>();
  192. is_equal = ( arma_H5Tequal(datatype, search_type) > 0 );
  193. arma_H5Tclose(search_type);
  194. if (is_equal) { return true; }
  195. #if defined(ARMA_USE_U64S64)
  196. {
  197. search_type = get_hdf5_type<u64>();
  198. is_equal = ( arma_H5Tequal(datatype, search_type) > 0 );
  199. arma_H5Tclose(search_type);
  200. if (is_equal) { return true; }
  201. search_type = get_hdf5_type<s64>();
  202. is_equal = ( arma_H5Tequal(datatype, search_type) > 0 );
  203. arma_H5Tclose(search_type);
  204. if (is_equal) { return true; }
  205. }
  206. #endif
  207. #if defined(ARMA_ALLOW_LONG)
  208. {
  209. search_type = get_hdf5_type<ulng_t>();
  210. is_equal = ( arma_H5Tequal(datatype, search_type) > 0 );
  211. arma_H5Tclose(search_type);
  212. if (is_equal) { return true; }
  213. search_type = get_hdf5_type<slng_t>();
  214. is_equal = ( arma_H5Tequal(datatype, search_type) > 0 );
  215. arma_H5Tclose(search_type);
  216. if (is_equal) { return true; }
  217. }
  218. #endif
  219. return false;
  220. }
  221. //! Auxiliary functions and structs for search_hdf5_file.
  222. struct hdf5_search_info
  223. {
  224. const std::vector<std::string>& names;
  225. int num_dims;
  226. bool exact;
  227. hid_t best_match;
  228. size_t best_match_position; // Position of best match in names vector.
  229. };
  230. inline
  231. herr_t
  232. hdf5_search_callback
  233. (
  234. hid_t loc_id,
  235. const char* name,
  236. const H5O_info_t* info,
  237. void* operator_data // hdf5_search_info
  238. )
  239. {
  240. hdf5_search_info* search_info = (hdf5_search_info*) operator_data;
  241. // We are looking for datasets.
  242. if (info->type == H5O_TYPE_DATASET)
  243. {
  244. // Check type of dataset to see if we could even load it.
  245. hid_t dataset = arma_H5Dopen(loc_id, name, H5P_DEFAULT);
  246. hid_t datatype = arma_H5Dget_type(dataset);
  247. const bool is_supported = is_supported_arma_hdf5_type(datatype);
  248. arma_H5Tclose(datatype);
  249. arma_H5Dclose(dataset);
  250. if(is_supported == false)
  251. {
  252. // Forget about it and move on.
  253. return 0;
  254. }
  255. // Now we have to check against our set of names.
  256. // Only check names which could be better.
  257. for (size_t string_pos = 0; string_pos < search_info->best_match_position; ++string_pos)
  258. {
  259. // name is the full path (/path/to/dataset); names[string_pos] may be
  260. // "dataset", "/to/dataset", or "/path/to/dataset".
  261. // So if we count the number of forward slashes in names[string_pos],
  262. // and then simply take the last substring of name containing that number of slashes,
  263. // we can do the comparison.
  264. // Count the number of forward slashes in names[string_pos].
  265. uword name_count = 0;
  266. for (uword i = 0; i < search_info->names[string_pos].length(); ++i)
  267. {
  268. if ((search_info->names[string_pos])[i] == '/') { ++name_count; }
  269. }
  270. // Count the number of forward slashes in the full name.
  271. uword count = 0;
  272. const std::string str = std::string(name);
  273. for (uword i = 0; i < str.length(); ++i)
  274. {
  275. if (str[i] == '/') { ++count; }
  276. }
  277. // Is the full string the same?
  278. if (str == search_info->names[string_pos])
  279. {
  280. // We found it exactly.
  281. hid_t match_candidate = arma_H5Dopen(loc_id, name, H5P_DEFAULT);
  282. if (match_candidate < 0)
  283. {
  284. return -1;
  285. }
  286. // Ensure that the dataset is valid and of the correct dimensionality.
  287. hid_t filespace = arma_H5Dget_space(match_candidate);
  288. int num_dims = arma_H5Sget_simple_extent_ndims(filespace);
  289. if (num_dims <= search_info->num_dims)
  290. {
  291. // Valid dataset -- we'll keep it.
  292. // If we already have an existing match we have to close it.
  293. if (search_info->best_match != -1)
  294. {
  295. arma_H5Dclose(search_info->best_match);
  296. }
  297. search_info->best_match_position = string_pos;
  298. search_info->best_match = match_candidate;
  299. }
  300. arma_H5Sclose(filespace);
  301. // There is no possibility of anything better, so terminate the search.
  302. return 1;
  303. }
  304. // If we are asking for more slashes than we have, this can't be a match.
  305. // Skip to below, where we decide whether or not to keep it anyway based
  306. // on the exactness condition of the search.
  307. if (count <= name_count)
  308. {
  309. size_t start_pos = (count == 0) ? 0 : std::string::npos;
  310. while (count > 0)
  311. {
  312. // Move pointer to previous slash.
  313. start_pos = str.rfind('/', start_pos);
  314. // Break if we've run out of slashes.
  315. if (start_pos == std::string::npos) { break; }
  316. --count;
  317. }
  318. // Now take the substring (this may end up being the full string).
  319. const std::string substring = str.substr(start_pos);
  320. // Are they the same?
  321. if (substring == search_info->names[string_pos])
  322. {
  323. // We have found the object; it must be better than our existing match.
  324. hid_t match_candidate = arma_H5Dopen(loc_id, name, H5P_DEFAULT);
  325. // arma_check(match_candidate < 0, "Mat::load(): cannot open an HDF5 dataset");
  326. if(match_candidate < 0)
  327. {
  328. return -1;
  329. }
  330. // Ensure that the dataset is valid and of the correct dimensionality.
  331. hid_t filespace = arma_H5Dget_space(match_candidate);
  332. int num_dims = arma_H5Sget_simple_extent_ndims(filespace);
  333. if (num_dims <= search_info->num_dims)
  334. {
  335. // Valid dataset -- we'll keep it.
  336. // If we already have an existing match we have to close it.
  337. if (search_info->best_match != -1)
  338. {
  339. arma_H5Dclose(search_info->best_match);
  340. }
  341. search_info->best_match_position = string_pos;
  342. search_info->best_match = match_candidate;
  343. }
  344. arma_H5Sclose(filespace);
  345. }
  346. }
  347. // If they are not the same, but we have not found anything and we don't need an exact match, take this.
  348. if ((search_info->exact == false) && (search_info->best_match == -1))
  349. {
  350. hid_t match_candidate = arma_H5Dopen(loc_id, name, H5P_DEFAULT);
  351. // arma_check(match_candidate < 0, "Mat::load(): cannot open an HDF5 dataset");
  352. if(match_candidate < 0)
  353. {
  354. return -1;
  355. }
  356. hid_t filespace = arma_H5Dget_space(match_candidate);
  357. int num_dims = arma_H5Sget_simple_extent_ndims(filespace);
  358. if (num_dims <= search_info->num_dims)
  359. {
  360. // Valid dataset -- we'll keep it.
  361. search_info->best_match = arma_H5Dopen(loc_id, name, H5P_DEFAULT);
  362. }
  363. arma_H5Sclose(filespace);
  364. }
  365. }
  366. }
  367. return 0;
  368. }
  369. //! Search an HDF5 file for the given dataset names.
  370. //! If 'exact' is true, failure to find a dataset in the list of names means that -1 is returned.
  371. //! If 'exact' is false and no datasets are found, -1 is returned.
  372. //! The number of dimensions is used to help prune down invalid datasets;
  373. //! 2 dimensions is a matrix, 1 dimension is a vector, and 3 dimensions is a cube.
  374. //! If the number of dimensions in a dataset is less than or equal to num_dims,
  375. //! it will be considered -- for instance, a one-dimensional HDF5 vector can be loaded as a single-column matrix.
  376. inline
  377. hid_t
  378. search_hdf5_file
  379. (
  380. const std::vector<std::string>& names,
  381. hid_t hdf5_file,
  382. int num_dims = 2,
  383. bool exact = false
  384. )
  385. {
  386. hdf5_search_info search_info = { names, num_dims, exact, -1, names.size() };
  387. // We'll use the H5Ovisit to track potential entries.
  388. herr_t status = arma_H5Ovisit(hdf5_file, H5_INDEX_NAME, H5_ITER_NATIVE, hdf5_search_callback, void_ptr(&search_info));
  389. // Return the best match; it will be -1 if there was a problem.
  390. return (status < 0) ? -1 : search_info.best_match;
  391. }
  392. //! Load an HDF5 matrix into an array of type specified by datatype,
  393. //! then convert that into the desired array 'dest'.
  394. //! This should only be called when eT is not the datatype.
  395. template<typename eT>
  396. inline
  397. hid_t
  398. load_and_convert_hdf5
  399. (
  400. eT *dest,
  401. hid_t dataset,
  402. hid_t datatype,
  403. uword n_elem
  404. )
  405. {
  406. // We can't use nice template specializations here
  407. // as the determination of the type of 'datatype' must be done at runtime.
  408. // So we end up with this ugliness...
  409. hid_t search_type;
  410. bool is_equal;
  411. // u8
  412. search_type = get_hdf5_type<u8>();
  413. is_equal = (arma_H5Tequal(datatype, search_type) > 0);
  414. arma_H5Tclose(search_type);
  415. if(is_equal)
  416. {
  417. Col<u8> v(n_elem);
  418. hid_t status = arma_H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, void_ptr(v.memptr()));
  419. arrayops::convert(dest, v.memptr(), n_elem);
  420. return status;
  421. }
  422. // s8
  423. search_type = get_hdf5_type<s8>();
  424. is_equal = (arma_H5Tequal(datatype, search_type) > 0);
  425. arma_H5Tclose(search_type);
  426. if(is_equal)
  427. {
  428. Col<s8> v(n_elem);
  429. hid_t status = arma_H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, void_ptr(v.memptr()));
  430. arrayops::convert(dest, v.memptr(), n_elem);
  431. return status;
  432. }
  433. // u16
  434. search_type = get_hdf5_type<u16>();
  435. is_equal = (arma_H5Tequal(datatype, search_type) > 0);
  436. arma_H5Tclose(search_type);
  437. if(is_equal)
  438. {
  439. Col<u16> v(n_elem);
  440. hid_t status = arma_H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, void_ptr(v.memptr()));
  441. arrayops::convert(dest, v.memptr(), n_elem);
  442. return status;
  443. }
  444. // s16
  445. search_type = get_hdf5_type<s16>();
  446. is_equal = (arma_H5Tequal(datatype, search_type) > 0);
  447. arma_H5Tclose(search_type);
  448. if(is_equal)
  449. {
  450. Col<s16> v(n_elem);
  451. hid_t status = arma_H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, void_ptr(v.memptr()));
  452. arrayops::convert(dest, v.memptr(), n_elem);
  453. return status;
  454. }
  455. // u32
  456. search_type = get_hdf5_type<u32>();
  457. is_equal = (arma_H5Tequal(datatype, search_type) > 0);
  458. arma_H5Tclose(search_type);
  459. if(is_equal)
  460. {
  461. Col<u32> v(n_elem);
  462. hid_t status = arma_H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, void_ptr(v.memptr()));
  463. arrayops::convert(dest, v.memptr(), n_elem);
  464. return status;
  465. }
  466. // s32
  467. search_type = get_hdf5_type<s32>();
  468. is_equal = (arma_H5Tequal(datatype, search_type) > 0);
  469. arma_H5Tclose(search_type);
  470. if(is_equal)
  471. {
  472. Col<s32> v(n_elem);
  473. hid_t status = arma_H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, void_ptr(v.memptr()));
  474. arrayops::convert(dest, v.memptr(), n_elem);
  475. return status;
  476. }
  477. #if defined(ARMA_USE_U64S64)
  478. {
  479. // u64
  480. search_type = get_hdf5_type<u64>();
  481. is_equal = (arma_H5Tequal(datatype, search_type) > 0);
  482. arma_H5Tclose(search_type);
  483. if(is_equal)
  484. {
  485. Col<u64> v(n_elem);
  486. hid_t status = arma_H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, void_ptr(v.memptr()));
  487. arrayops::convert(dest, v.memptr(), n_elem);
  488. return status;
  489. }
  490. // s64
  491. search_type = get_hdf5_type<s64>();
  492. is_equal = (arma_H5Tequal(datatype, search_type) > 0);
  493. arma_H5Tclose(search_type);
  494. if(is_equal)
  495. {
  496. Col<s64> v(n_elem);
  497. hid_t status = arma_H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, void_ptr(v.memptr()));
  498. arrayops::convert(dest, v.memptr(), n_elem);
  499. return status;
  500. }
  501. }
  502. #endif
  503. #if defined(ARMA_ALLOW_LONG)
  504. {
  505. // ulng_t
  506. search_type = get_hdf5_type<ulng_t>();
  507. is_equal = (arma_H5Tequal(datatype, search_type) > 0);
  508. arma_H5Tclose(search_type);
  509. if(is_equal)
  510. {
  511. Col<ulng_t> v(n_elem);
  512. hid_t status = arma_H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, void_ptr(v.memptr()));
  513. arrayops::convert(dest, v.memptr(), n_elem);
  514. return status;
  515. }
  516. // slng_t
  517. search_type = get_hdf5_type<slng_t>();
  518. is_equal = (arma_H5Tequal(datatype, search_type) > 0);
  519. arma_H5Tclose(search_type);
  520. if(is_equal)
  521. {
  522. Col<slng_t> v(n_elem);
  523. hid_t status = arma_H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, void_ptr(v.memptr()));
  524. arrayops::convert(dest, v.memptr(), n_elem);
  525. return status;
  526. }
  527. }
  528. #endif
  529. // float
  530. search_type = get_hdf5_type<float>();
  531. is_equal = (arma_H5Tequal(datatype, search_type) > 0);
  532. arma_H5Tclose(search_type);
  533. if(is_equal)
  534. {
  535. Col<float> v(n_elem);
  536. hid_t status = arma_H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, void_ptr(v.memptr()));
  537. arrayops::convert(dest, v.memptr(), n_elem);
  538. return status;
  539. }
  540. // double
  541. search_type = get_hdf5_type<double>();
  542. is_equal = (arma_H5Tequal(datatype, search_type) > 0);
  543. arma_H5Tclose(search_type);
  544. if(is_equal)
  545. {
  546. Col<double> v(n_elem);
  547. hid_t status = arma_H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, void_ptr(v.memptr()));
  548. arrayops::convert(dest, v.memptr(), n_elem);
  549. return status;
  550. }
  551. // complex float
  552. search_type = get_hdf5_type< std::complex<float> >();
  553. is_equal = (arma_H5Tequal(datatype, search_type) > 0);
  554. arma_H5Tclose(search_type);
  555. if(is_equal)
  556. {
  557. if(is_cx<eT>::no)
  558. {
  559. return -1; // can't read complex data into non-complex matrix/cube
  560. }
  561. Col< std::complex<float> > v(n_elem);
  562. hid_t status = arma_H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, void_ptr(v.memptr()));
  563. arrayops::convert_cx(dest, v.memptr(), n_elem);
  564. return status;
  565. }
  566. // complex double
  567. search_type = get_hdf5_type< std::complex<double> >();
  568. is_equal = (arma_H5Tequal(datatype, search_type) > 0);
  569. arma_H5Tclose(search_type);
  570. if(is_equal)
  571. {
  572. if(is_cx<eT>::no)
  573. {
  574. return -1; // can't read complex data into non-complex matrix/cube
  575. }
  576. Col< std::complex<double> > v(n_elem);
  577. hid_t status = arma_H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, void_ptr(v.memptr()));
  578. arrayops::convert_cx(dest, v.memptr(), n_elem);
  579. return status;
  580. }
  581. return -1; // Failure.
  582. }
  583. struct hdf5_suspend_printing_errors
  584. {
  585. #if defined(ARMA_PRINT_HDF5_ERRORS)
  586. inline
  587. hdf5_suspend_printing_errors() {}
  588. #else
  589. herr_t (*old_client_func)(hid_t, void*);
  590. void* old_client_data;
  591. inline
  592. hdf5_suspend_printing_errors()
  593. {
  594. // Save old error handler.
  595. arma_H5Eget_auto(H5E_DEFAULT, &old_client_func, &old_client_data);
  596. // Disable annoying HDF5 error messages.
  597. arma_H5Eset_auto(H5E_DEFAULT, NULL, NULL);
  598. }
  599. inline
  600. ~hdf5_suspend_printing_errors()
  601. {
  602. arma_H5Eset_auto(H5E_DEFAULT, old_client_func, old_client_data);
  603. }
  604. #endif
  605. };
  606. } // namespace hdf5_misc
  607. #endif // #if defined(ARMA_USE_HDF5)
  608. //! @}