annotate armadillo-3.900.4/include/armadillo_bits/diskio_meat.hpp @ 84:55a047986812 tip

Update library URI so as not to be document-local
author Chris Cannam
date Wed, 22 Apr 2020 14:21:57 +0100
parents 1ec0e2823891
children
rev   line source
Chris@49 1 // Copyright (C) 2008-2012 NICTA (www.nicta.com.au)
Chris@49 2 // Copyright (C) 2008-2012 Conrad Sanderson
Chris@49 3 // Copyright (C) 2009-2010 Ian Cullinan
Chris@49 4 // Copyright (C) 2012 Ryan Curtin
Chris@49 5 // Copyright (C) 2013 Szabolcs Horvat
Chris@49 6 //
Chris@49 7 // This Source Code Form is subject to the terms of the Mozilla Public
Chris@49 8 // License, v. 2.0. If a copy of the MPL was not distributed with this
Chris@49 9 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
Chris@49 10
Chris@49 11
Chris@49 12 //! \addtogroup diskio
Chris@49 13 //! @{
Chris@49 14
Chris@49 15
Chris@49 16 //! Generate the first line of the header used for saving matrices in text format.
Chris@49 17 //! Format: "ARMA_MAT_TXT_ABXYZ".
Chris@49 18 //! A is one of: I (for integral types) or F (for floating point types).
Chris@49 19 //! B is one of: U (for unsigned types), S (for signed types), N (for not appliable) or C (for complex types).
Chris@49 20 //! XYZ specifies the width of each element in terms of bytes, e.g. "008" indicates eight bytes.
Chris@49 21 template<typename eT>
Chris@49 22 inline
Chris@49 23 std::string
Chris@49 24 diskio::gen_txt_header(const Mat<eT>& x)
Chris@49 25 {
Chris@49 26 arma_type_check(( is_supported_elem_type<eT>::value == false ));
Chris@49 27
Chris@49 28 arma_ignore(x);
Chris@49 29
Chris@49 30 if(is_u8<eT>::value == true)
Chris@49 31 {
Chris@49 32 return std::string("ARMA_MAT_TXT_IU001");
Chris@49 33 }
Chris@49 34 else
Chris@49 35 if(is_s8<eT>::value == true)
Chris@49 36 {
Chris@49 37 return std::string("ARMA_MAT_TXT_IS001");
Chris@49 38 }
Chris@49 39 else
Chris@49 40 if(is_u16<eT>::value == true)
Chris@49 41 {
Chris@49 42 return std::string("ARMA_MAT_TXT_IU002");
Chris@49 43 }
Chris@49 44 else
Chris@49 45 if(is_s16<eT>::value == true)
Chris@49 46 {
Chris@49 47 return std::string("ARMA_MAT_TXT_IS002");
Chris@49 48 }
Chris@49 49 else
Chris@49 50 if(is_u32<eT>::value == true)
Chris@49 51 {
Chris@49 52 return std::string("ARMA_MAT_TXT_IU004");
Chris@49 53 }
Chris@49 54 else
Chris@49 55 if(is_s32<eT>::value == true)
Chris@49 56 {
Chris@49 57 return std::string("ARMA_MAT_TXT_IS004");
Chris@49 58 }
Chris@49 59 #if defined(ARMA_USE_U64S64)
Chris@49 60 else
Chris@49 61 if(is_u64<eT>::value == true)
Chris@49 62 {
Chris@49 63 return std::string("ARMA_MAT_TXT_IU008");
Chris@49 64 }
Chris@49 65 else
Chris@49 66 if(is_s64<eT>::value == true)
Chris@49 67 {
Chris@49 68 return std::string("ARMA_MAT_TXT_IS008");
Chris@49 69 }
Chris@49 70 #endif
Chris@49 71 #if defined(ARMA_ALLOW_LONG)
Chris@49 72 else
Chris@49 73 if(is_ulng_t_32<eT>::value == true)
Chris@49 74 {
Chris@49 75 return std::string("ARMA_MAT_TXT_IU004");
Chris@49 76 }
Chris@49 77 else
Chris@49 78 if(is_slng_t_32<eT>::value == true)
Chris@49 79 {
Chris@49 80 return std::string("ARMA_MAT_TXT_IS004");
Chris@49 81 }
Chris@49 82 else
Chris@49 83 if(is_ulng_t_64<eT>::value == true)
Chris@49 84 {
Chris@49 85 return std::string("ARMA_MAT_TXT_IU008");
Chris@49 86 }
Chris@49 87 else
Chris@49 88 if(is_slng_t_64<eT>::value == true)
Chris@49 89 {
Chris@49 90 return std::string("ARMA_MAT_TXT_IS008");
Chris@49 91 }
Chris@49 92 #endif
Chris@49 93 else
Chris@49 94 if(is_float<eT>::value == true)
Chris@49 95 {
Chris@49 96 return std::string("ARMA_MAT_TXT_FN004");
Chris@49 97 }
Chris@49 98 else
Chris@49 99 if(is_double<eT>::value == true)
Chris@49 100 {
Chris@49 101 return std::string("ARMA_MAT_TXT_FN008");
Chris@49 102 }
Chris@49 103 else
Chris@49 104 if(is_complex_float<eT>::value == true)
Chris@49 105 {
Chris@49 106 return std::string("ARMA_MAT_TXT_FC008");
Chris@49 107 }
Chris@49 108 else
Chris@49 109 if(is_complex_double<eT>::value == true)
Chris@49 110 {
Chris@49 111 return std::string("ARMA_MAT_TXT_FC016");
Chris@49 112 }
Chris@49 113 else
Chris@49 114 {
Chris@49 115 return std::string();
Chris@49 116 }
Chris@49 117
Chris@49 118 }
Chris@49 119
Chris@49 120
Chris@49 121
Chris@49 122 //! Generate the first line of the header used for saving matrices in binary format.
Chris@49 123 //! Format: "ARMA_MAT_BIN_ABXYZ".
Chris@49 124 //! A is one of: I (for integral types) or F (for floating point types).
Chris@49 125 //! B is one of: U (for unsigned types), S (for signed types), N (for not appliable) or C (for complex types).
Chris@49 126 //! XYZ specifies the width of each element in terms of bytes, e.g. "008" indicates eight bytes.
Chris@49 127 template<typename eT>
Chris@49 128 inline
Chris@49 129 std::string
Chris@49 130 diskio::gen_bin_header(const Mat<eT>& x)
Chris@49 131 {
Chris@49 132 arma_type_check(( is_supported_elem_type<eT>::value == false ));
Chris@49 133
Chris@49 134 arma_ignore(x);
Chris@49 135
Chris@49 136 if(is_u8<eT>::value == true)
Chris@49 137 {
Chris@49 138 return std::string("ARMA_MAT_BIN_IU001");
Chris@49 139 }
Chris@49 140 else
Chris@49 141 if(is_s8<eT>::value == true)
Chris@49 142 {
Chris@49 143 return std::string("ARMA_MAT_BIN_IS001");
Chris@49 144 }
Chris@49 145 else
Chris@49 146 if(is_u16<eT>::value == true)
Chris@49 147 {
Chris@49 148 return std::string("ARMA_MAT_BIN_IU002");
Chris@49 149 }
Chris@49 150 else
Chris@49 151 if(is_s16<eT>::value == true)
Chris@49 152 {
Chris@49 153 return std::string("ARMA_MAT_BIN_IS002");
Chris@49 154 }
Chris@49 155 else
Chris@49 156 if(is_u32<eT>::value == true)
Chris@49 157 {
Chris@49 158 return std::string("ARMA_MAT_BIN_IU004");
Chris@49 159 }
Chris@49 160 else
Chris@49 161 if(is_s32<eT>::value == true)
Chris@49 162 {
Chris@49 163 return std::string("ARMA_MAT_BIN_IS004");
Chris@49 164 }
Chris@49 165 #if defined(ARMA_USE_U64S64)
Chris@49 166 else
Chris@49 167 if(is_u64<eT>::value == true)
Chris@49 168 {
Chris@49 169 return std::string("ARMA_MAT_BIN_IU008");
Chris@49 170 }
Chris@49 171 else
Chris@49 172 if(is_s64<eT>::value == true)
Chris@49 173 {
Chris@49 174 return std::string("ARMA_MAT_BIN_IS008");
Chris@49 175 }
Chris@49 176 #endif
Chris@49 177 #if defined(ARMA_ALLOW_LONG)
Chris@49 178 else
Chris@49 179 if(is_ulng_t_32<eT>::value == true)
Chris@49 180 {
Chris@49 181 return std::string("ARMA_MAT_BIN_IU004");
Chris@49 182 }
Chris@49 183 else
Chris@49 184 if(is_slng_t_32<eT>::value == true)
Chris@49 185 {
Chris@49 186 return std::string("ARMA_MAT_BIN_IS004");
Chris@49 187 }
Chris@49 188 else
Chris@49 189 if(is_ulng_t_64<eT>::value == true)
Chris@49 190 {
Chris@49 191 return std::string("ARMA_MAT_BIN_IU008");
Chris@49 192 }
Chris@49 193 else
Chris@49 194 if(is_slng_t_64<eT>::value == true)
Chris@49 195 {
Chris@49 196 return std::string("ARMA_MAT_BIN_IS008");
Chris@49 197 }
Chris@49 198 #endif
Chris@49 199 else
Chris@49 200 if(is_float<eT>::value == true)
Chris@49 201 {
Chris@49 202 return std::string("ARMA_MAT_BIN_FN004");
Chris@49 203 }
Chris@49 204 else
Chris@49 205 if(is_double<eT>::value == true)
Chris@49 206 {
Chris@49 207 return std::string("ARMA_MAT_BIN_FN008");
Chris@49 208 }
Chris@49 209 else
Chris@49 210 if(is_complex_float<eT>::value == true)
Chris@49 211 {
Chris@49 212 return std::string("ARMA_MAT_BIN_FC008");
Chris@49 213 }
Chris@49 214 else
Chris@49 215 if(is_complex_double<eT>::value == true)
Chris@49 216 {
Chris@49 217 return std::string("ARMA_MAT_BIN_FC016");
Chris@49 218 }
Chris@49 219 else
Chris@49 220 {
Chris@49 221 return std::string();
Chris@49 222 }
Chris@49 223
Chris@49 224 }
Chris@49 225
Chris@49 226
Chris@49 227
Chris@49 228 //! Generate the first line of the header used for saving matrices in binary format.
Chris@49 229 //! Format: "ARMA_SPM_BIN_ABXYZ".
Chris@49 230 //! A is one of: I (for integral types) or F (for floating point types).
Chris@49 231 //! B is one of: U (for unsigned types), S (for signed types), N (for not appliable) or C (for complex types).
Chris@49 232 //! XYZ specifies the width of each element in terms of bytes, e.g. "008" indicates eight bytes.
Chris@49 233 template<typename eT>
Chris@49 234 inline
Chris@49 235 std::string
Chris@49 236 diskio::gen_bin_header(const SpMat<eT>& x)
Chris@49 237 {
Chris@49 238 arma_type_check(( is_supported_elem_type<eT>::value == false ));
Chris@49 239
Chris@49 240 arma_ignore(x);
Chris@49 241
Chris@49 242 if(is_u8<eT>::value == true)
Chris@49 243 {
Chris@49 244 return std::string("ARMA_SPM_BIN_IU001");
Chris@49 245 }
Chris@49 246 else
Chris@49 247 if(is_s8<eT>::value == true)
Chris@49 248 {
Chris@49 249 return std::string("ARMA_SPM_BIN_IS001");
Chris@49 250 }
Chris@49 251 else
Chris@49 252 if(is_u16<eT>::value == true)
Chris@49 253 {
Chris@49 254 return std::string("ARMA_SPM_BIN_IU002");
Chris@49 255 }
Chris@49 256 else
Chris@49 257 if(is_s16<eT>::value == true)
Chris@49 258 {
Chris@49 259 return std::string("ARMA_SPM_BIN_IS002");
Chris@49 260 }
Chris@49 261 else
Chris@49 262 if(is_u32<eT>::value == true)
Chris@49 263 {
Chris@49 264 return std::string("ARMA_SPM_BIN_IU004");
Chris@49 265 }
Chris@49 266 else
Chris@49 267 if(is_s32<eT>::value == true)
Chris@49 268 {
Chris@49 269 return std::string("ARMA_SPM_BIN_IS004");
Chris@49 270 }
Chris@49 271 #if defined(ARMA_USE_U64S64)
Chris@49 272 else
Chris@49 273 if(is_u64<eT>::value == true)
Chris@49 274 {
Chris@49 275 return std::string("ARMA_SPM_BIN_IU008");
Chris@49 276 }
Chris@49 277 else
Chris@49 278 if(is_s64<eT>::value == true)
Chris@49 279 {
Chris@49 280 return std::string("ARMA_SPM_BIN_IS008");
Chris@49 281 }
Chris@49 282 #endif
Chris@49 283 #if defined(ARMA_ALLOW_LONG)
Chris@49 284 else
Chris@49 285 if(is_ulng_t_32<eT>::value == true)
Chris@49 286 {
Chris@49 287 return std::string("ARMA_SPM_BIN_IU004");
Chris@49 288 }
Chris@49 289 else
Chris@49 290 if(is_slng_t_32<eT>::value == true)
Chris@49 291 {
Chris@49 292 return std::string("ARMA_SPM_BIN_IS004");
Chris@49 293 }
Chris@49 294 else
Chris@49 295 if(is_ulng_t_64<eT>::value == true)
Chris@49 296 {
Chris@49 297 return std::string("ARMA_SPM_BIN_IU008");
Chris@49 298 }
Chris@49 299 else
Chris@49 300 if(is_slng_t_64<eT>::value == true)
Chris@49 301 {
Chris@49 302 return std::string("ARMA_SPM_BIN_IS008");
Chris@49 303 }
Chris@49 304 #endif
Chris@49 305 else
Chris@49 306 if(is_float<eT>::value == true)
Chris@49 307 {
Chris@49 308 return std::string("ARMA_SPM_BIN_FN004");
Chris@49 309 }
Chris@49 310 else
Chris@49 311 if(is_double<eT>::value == true)
Chris@49 312 {
Chris@49 313 return std::string("ARMA_SPM_BIN_FN008");
Chris@49 314 }
Chris@49 315 else
Chris@49 316 if(is_complex_float<eT>::value == true)
Chris@49 317 {
Chris@49 318 return std::string("ARMA_SPM_BIN_FC008");
Chris@49 319 }
Chris@49 320 else
Chris@49 321 if(is_complex_double<eT>::value == true)
Chris@49 322 {
Chris@49 323 return std::string("ARMA_SPM_BIN_FC016");
Chris@49 324 }
Chris@49 325 else
Chris@49 326 {
Chris@49 327 return std::string();
Chris@49 328 }
Chris@49 329
Chris@49 330 }
Chris@49 331
Chris@49 332
Chris@49 333 //! Generate the first line of the header used for saving cubes in text format.
Chris@49 334 //! Format: "ARMA_CUB_TXT_ABXYZ".
Chris@49 335 //! A is one of: I (for integral types) or F (for floating point types).
Chris@49 336 //! B is one of: U (for unsigned types), S (for signed types), N (for not appliable) or C (for complex types).
Chris@49 337 //! XYZ specifies the width of each element in terms of bytes, e.g. "008" indicates eight bytes.
Chris@49 338 template<typename eT>
Chris@49 339 inline
Chris@49 340 std::string
Chris@49 341 diskio::gen_txt_header(const Cube<eT>& x)
Chris@49 342 {
Chris@49 343 arma_type_check(( is_supported_elem_type<eT>::value == false ));
Chris@49 344
Chris@49 345 arma_ignore(x);
Chris@49 346
Chris@49 347 if(is_u8<eT>::value == true)
Chris@49 348 {
Chris@49 349 return std::string("ARMA_CUB_TXT_IU001");
Chris@49 350 }
Chris@49 351 else
Chris@49 352 if(is_s8<eT>::value == true)
Chris@49 353 {
Chris@49 354 return std::string("ARMA_CUB_TXT_IS001");
Chris@49 355 }
Chris@49 356 else
Chris@49 357 if(is_u16<eT>::value == true)
Chris@49 358 {
Chris@49 359 return std::string("ARMA_CUB_TXT_IU002");
Chris@49 360 }
Chris@49 361 else
Chris@49 362 if(is_s16<eT>::value == true)
Chris@49 363 {
Chris@49 364 return std::string("ARMA_CUB_TXT_IS002");
Chris@49 365 }
Chris@49 366 else
Chris@49 367 if(is_u32<eT>::value == true)
Chris@49 368 {
Chris@49 369 return std::string("ARMA_CUB_TXT_IU004");
Chris@49 370 }
Chris@49 371 else
Chris@49 372 if(is_s32<eT>::value == true)
Chris@49 373 {
Chris@49 374 return std::string("ARMA_CUB_TXT_IS004");
Chris@49 375 }
Chris@49 376 #if defined(ARMA_USE_U64S64)
Chris@49 377 else
Chris@49 378 if(is_u64<eT>::value == true)
Chris@49 379 {
Chris@49 380 return std::string("ARMA_CUB_TXT_IU008");
Chris@49 381 }
Chris@49 382 else
Chris@49 383 if(is_s64<eT>::value == true)
Chris@49 384 {
Chris@49 385 return std::string("ARMA_CUB_TXT_IS008");
Chris@49 386 }
Chris@49 387 #endif
Chris@49 388 #if defined(ARMA_ALLOW_LONG)
Chris@49 389 else
Chris@49 390 if(is_ulng_t_32<eT>::value == true)
Chris@49 391 {
Chris@49 392 return std::string("ARMA_CUB_TXT_IU004");
Chris@49 393 }
Chris@49 394 else
Chris@49 395 if(is_slng_t_32<eT>::value == true)
Chris@49 396 {
Chris@49 397 return std::string("ARMA_CUB_TXT_IS004");
Chris@49 398 }
Chris@49 399 else
Chris@49 400 if(is_ulng_t_64<eT>::value == true)
Chris@49 401 {
Chris@49 402 return std::string("ARMA_CUB_TXT_IU008");
Chris@49 403 }
Chris@49 404 else
Chris@49 405 if(is_slng_t_64<eT>::value == true)
Chris@49 406 {
Chris@49 407 return std::string("ARMA_CUB_TXT_IS008");
Chris@49 408 }
Chris@49 409 #endif
Chris@49 410 else
Chris@49 411 if(is_float<eT>::value == true)
Chris@49 412 {
Chris@49 413 return std::string("ARMA_CUB_TXT_FN004");
Chris@49 414 }
Chris@49 415 else
Chris@49 416 if(is_double<eT>::value == true)
Chris@49 417 {
Chris@49 418 return std::string("ARMA_CUB_TXT_FN008");
Chris@49 419 }
Chris@49 420 else
Chris@49 421 if(is_complex_float<eT>::value == true)
Chris@49 422 {
Chris@49 423 return std::string("ARMA_CUB_TXT_FC008");
Chris@49 424 }
Chris@49 425 else
Chris@49 426 if(is_complex_double<eT>::value == true)
Chris@49 427 {
Chris@49 428 return std::string("ARMA_CUB_TXT_FC016");
Chris@49 429 }
Chris@49 430 else
Chris@49 431 {
Chris@49 432 return std::string();
Chris@49 433 }
Chris@49 434
Chris@49 435 }
Chris@49 436
Chris@49 437
Chris@49 438
Chris@49 439 //! Generate the first line of the header used for saving cubes in binary format.
Chris@49 440 //! Format: "ARMA_CUB_BIN_ABXYZ".
Chris@49 441 //! A is one of: I (for integral types) or F (for floating point types).
Chris@49 442 //! B is one of: U (for unsigned types), S (for signed types), N (for not appliable) or C (for complex types).
Chris@49 443 //! XYZ specifies the width of each element in terms of bytes, e.g. "008" indicates eight bytes.
Chris@49 444 template<typename eT>
Chris@49 445 inline
Chris@49 446 std::string
Chris@49 447 diskio::gen_bin_header(const Cube<eT>& x)
Chris@49 448 {
Chris@49 449 arma_type_check(( is_supported_elem_type<eT>::value == false ));
Chris@49 450
Chris@49 451 arma_ignore(x);
Chris@49 452
Chris@49 453 if(is_u8<eT>::value == true)
Chris@49 454 {
Chris@49 455 return std::string("ARMA_CUB_BIN_IU001");
Chris@49 456 }
Chris@49 457 else
Chris@49 458 if(is_s8<eT>::value == true)
Chris@49 459 {
Chris@49 460 return std::string("ARMA_CUB_BIN_IS001");
Chris@49 461 }
Chris@49 462 else
Chris@49 463 if(is_u16<eT>::value == true)
Chris@49 464 {
Chris@49 465 return std::string("ARMA_CUB_BIN_IU002");
Chris@49 466 }
Chris@49 467 else
Chris@49 468 if(is_s16<eT>::value == true)
Chris@49 469 {
Chris@49 470 return std::string("ARMA_CUB_BIN_IS002");
Chris@49 471 }
Chris@49 472 else
Chris@49 473 if(is_u32<eT>::value == true)
Chris@49 474 {
Chris@49 475 return std::string("ARMA_CUB_BIN_IU004");
Chris@49 476 }
Chris@49 477 else
Chris@49 478 if(is_s32<eT>::value == true)
Chris@49 479 {
Chris@49 480 return std::string("ARMA_CUB_BIN_IS004");
Chris@49 481 }
Chris@49 482 #if defined(ARMA_USE_U64S64)
Chris@49 483 else
Chris@49 484 if(is_u64<eT>::value == true)
Chris@49 485 {
Chris@49 486 return std::string("ARMA_CUB_BIN_IU008");
Chris@49 487 }
Chris@49 488 else
Chris@49 489 if(is_s64<eT>::value == true)
Chris@49 490 {
Chris@49 491 return std::string("ARMA_CUB_BIN_IS008");
Chris@49 492 }
Chris@49 493 #endif
Chris@49 494 #if defined(ARMA_ALLOW_LONG)
Chris@49 495 else
Chris@49 496 if(is_ulng_t_32<eT>::value == true)
Chris@49 497 {
Chris@49 498 return std::string("ARMA_CUB_BIN_IU004");
Chris@49 499 }
Chris@49 500 else
Chris@49 501 if(is_slng_t_32<eT>::value == true)
Chris@49 502 {
Chris@49 503 return std::string("ARMA_CUB_BIN_IS004");
Chris@49 504 }
Chris@49 505 else
Chris@49 506 if(is_ulng_t_64<eT>::value == true)
Chris@49 507 {
Chris@49 508 return std::string("ARMA_CUB_BIN_IU008");
Chris@49 509 }
Chris@49 510 else
Chris@49 511 if(is_slng_t_64<eT>::value == true)
Chris@49 512 {
Chris@49 513 return std::string("ARMA_CUB_BIN_IS008");
Chris@49 514 }
Chris@49 515 #endif
Chris@49 516 else
Chris@49 517 if(is_float<eT>::value == true)
Chris@49 518 {
Chris@49 519 return std::string("ARMA_CUB_BIN_FN004");
Chris@49 520 }
Chris@49 521 else
Chris@49 522 if(is_double<eT>::value == true)
Chris@49 523 {
Chris@49 524 return std::string("ARMA_CUB_BIN_FN008");
Chris@49 525 }
Chris@49 526 else
Chris@49 527 if(is_complex_float<eT>::value == true)
Chris@49 528 {
Chris@49 529 return std::string("ARMA_CUB_BIN_FC008");
Chris@49 530 }
Chris@49 531 else
Chris@49 532 if(is_complex_double<eT>::value == true)
Chris@49 533 {
Chris@49 534 return std::string("ARMA_CUB_BIN_FC016");
Chris@49 535 }
Chris@49 536 else
Chris@49 537 {
Chris@49 538 return std::string();
Chris@49 539 }
Chris@49 540
Chris@49 541 }
Chris@49 542
Chris@49 543
Chris@49 544
Chris@49 545 inline
Chris@49 546 file_type
Chris@49 547 diskio::guess_file_type(std::istream& f)
Chris@49 548 {
Chris@49 549 arma_extra_debug_sigprint();
Chris@49 550
Chris@49 551 f.clear();
Chris@49 552 const std::fstream::pos_type pos1 = f.tellg();
Chris@49 553
Chris@49 554 f.clear();
Chris@49 555 f.seekg(0, ios::end);
Chris@49 556
Chris@49 557 f.clear();
Chris@49 558 const std::fstream::pos_type pos2 = f.tellg();
Chris@49 559
Chris@49 560 const uword N = ( (pos1 >= 0) && (pos2 >= 0) ) ? uword(pos2 - pos1) : 0;
Chris@49 561
Chris@49 562 f.clear();
Chris@49 563 f.seekg(pos1);
Chris@49 564
Chris@49 565 podarray<unsigned char> data(N);
Chris@49 566
Chris@49 567 unsigned char* ptr = data.memptr();
Chris@49 568
Chris@49 569 f.clear();
Chris@49 570 f.read( reinterpret_cast<char*>(ptr), std::streamsize(N) );
Chris@49 571
Chris@49 572 const bool load_okay = f.good();
Chris@49 573
Chris@49 574 f.clear();
Chris@49 575 f.seekg(pos1);
Chris@49 576
Chris@49 577 bool has_binary = false;
Chris@49 578 bool has_comma = false;
Chris@49 579 bool has_bracket = false;
Chris@49 580
Chris@49 581 if(load_okay == true)
Chris@49 582 {
Chris@49 583 uword i = 0;
Chris@49 584 uword j = (N >= 2) ? 1 : 0;
Chris@49 585
Chris@49 586 for(; j<N; i+=2, j+=2)
Chris@49 587 {
Chris@49 588 const unsigned char val_i = ptr[i];
Chris@49 589 const unsigned char val_j = ptr[j];
Chris@49 590
Chris@49 591 // the range checking can be made more elaborate
Chris@49 592 if( ((val_i <= 8) || (val_i >= 123)) || ((val_j <= 8) || (val_j >= 123)) )
Chris@49 593 {
Chris@49 594 has_binary = true;
Chris@49 595 break;
Chris@49 596 }
Chris@49 597
Chris@49 598 if( (val_i == ',') || (val_j == ',') )
Chris@49 599 {
Chris@49 600 has_comma = true;
Chris@49 601 }
Chris@49 602
Chris@49 603 if( (val_i == '(') || (val_j == '(') || (val_i == ')') || (val_j == ')') )
Chris@49 604 {
Chris@49 605 has_bracket = true;
Chris@49 606 }
Chris@49 607 }
Chris@49 608 }
Chris@49 609 else
Chris@49 610 {
Chris@49 611 return file_type_unknown;
Chris@49 612 }
Chris@49 613
Chris@49 614 if(has_binary)
Chris@49 615 {
Chris@49 616 return raw_binary;
Chris@49 617 }
Chris@49 618
Chris@49 619 if(has_comma && (has_bracket == false))
Chris@49 620 {
Chris@49 621 return csv_ascii;
Chris@49 622 }
Chris@49 623
Chris@49 624 return raw_ascii;
Chris@49 625 }
Chris@49 626
Chris@49 627
Chris@49 628
Chris@49 629 inline
Chris@49 630 char
Chris@49 631 diskio::conv_to_hex_char(const u8 x)
Chris@49 632 {
Chris@49 633 char out;
Chris@49 634
Chris@49 635 switch(x)
Chris@49 636 {
Chris@49 637 case 0: out = '0'; break;
Chris@49 638 case 1: out = '1'; break;
Chris@49 639 case 2: out = '2'; break;
Chris@49 640 case 3: out = '3'; break;
Chris@49 641 case 4: out = '4'; break;
Chris@49 642 case 5: out = '5'; break;
Chris@49 643 case 6: out = '6'; break;
Chris@49 644 case 7: out = '7'; break;
Chris@49 645 case 8: out = '8'; break;
Chris@49 646 case 9: out = '9'; break;
Chris@49 647 case 10: out = 'a'; break;
Chris@49 648 case 11: out = 'b'; break;
Chris@49 649 case 12: out = 'c'; break;
Chris@49 650 case 13: out = 'd'; break;
Chris@49 651 case 14: out = 'e'; break;
Chris@49 652 case 15: out = 'f'; break;
Chris@49 653 default: out = '-'; break;
Chris@49 654 }
Chris@49 655
Chris@49 656 return out;
Chris@49 657 }
Chris@49 658
Chris@49 659
Chris@49 660
Chris@49 661 inline
Chris@49 662 void
Chris@49 663 diskio::conv_to_hex(char* out, const u8 x)
Chris@49 664 {
Chris@49 665 const u8 a = x / 16;
Chris@49 666 const u8 b = x - 16*a;
Chris@49 667
Chris@49 668 out[0] = conv_to_hex_char(a);
Chris@49 669 out[1] = conv_to_hex_char(b);
Chris@49 670 }
Chris@49 671
Chris@49 672
Chris@49 673
Chris@49 674 //! Append a quasi-random string to the given filename.
Chris@49 675 //! The rand() function is deliberately not used,
Chris@49 676 //! as rand() has an internal state that changes
Chris@49 677 //! from call to call. Such states should not be
Chris@49 678 //! modified in scientific applications, where the
Chris@49 679 //! results should be reproducable and not affected
Chris@49 680 //! by saving data.
Chris@49 681 inline
Chris@49 682 std::string
Chris@49 683 diskio::gen_tmp_name(const std::string& x)
Chris@49 684 {
Chris@49 685 const std::string* ptr_x = &x;
Chris@49 686 const u8* ptr_ptr_x = reinterpret_cast<const u8*>(&ptr_x);
Chris@49 687
Chris@49 688 const char* extra = ".tmp_";
Chris@49 689 const uword extra_size = 5;
Chris@49 690
Chris@49 691 const uword tmp_size = 2*sizeof(u8*) + 2*2;
Chris@49 692 char tmp[tmp_size];
Chris@49 693
Chris@49 694 uword char_count = 0;
Chris@49 695
Chris@49 696 for(uword i=0; i<sizeof(u8*); ++i)
Chris@49 697 {
Chris@49 698 conv_to_hex(&tmp[char_count], ptr_ptr_x[i]);
Chris@49 699 char_count += 2;
Chris@49 700 }
Chris@49 701
Chris@49 702 const uword x_size = static_cast<uword>(x.size());
Chris@49 703 u8 sum = 0;
Chris@49 704
Chris@49 705 for(uword i=0; i<x_size; ++i)
Chris@49 706 {
Chris@49 707 sum += u8(x[i]);
Chris@49 708 }
Chris@49 709
Chris@49 710 conv_to_hex(&tmp[char_count], sum);
Chris@49 711 char_count += 2;
Chris@49 712
Chris@49 713 conv_to_hex(&tmp[char_count], u8(x_size));
Chris@49 714
Chris@49 715
Chris@49 716 std::string out;
Chris@49 717 out.resize(x_size + extra_size + tmp_size);
Chris@49 718
Chris@49 719
Chris@49 720 for(uword i=0; i<x_size; ++i)
Chris@49 721 {
Chris@49 722 out[i] = x[i];
Chris@49 723 }
Chris@49 724
Chris@49 725 for(uword i=0; i<extra_size; ++i)
Chris@49 726 {
Chris@49 727 out[x_size + i] = extra[i];
Chris@49 728 }
Chris@49 729
Chris@49 730 for(uword i=0; i<tmp_size; ++i)
Chris@49 731 {
Chris@49 732 out[x_size + extra_size + i] = tmp[i];
Chris@49 733 }
Chris@49 734
Chris@49 735 return out;
Chris@49 736 }
Chris@49 737
Chris@49 738
Chris@49 739
Chris@49 740 //! Safely rename a file.
Chris@49 741 //! Before renaming, test if we can write to the final file.
Chris@49 742 //! This should prevent:
Chris@49 743 //! (i) overwriting files that are write protected,
Chris@49 744 //! (ii) overwriting directories.
Chris@49 745 inline
Chris@49 746 bool
Chris@49 747 diskio::safe_rename(const std::string& old_name, const std::string& new_name)
Chris@49 748 {
Chris@49 749 std::fstream f(new_name.c_str(), std::fstream::out | std::fstream::app);
Chris@49 750 f.put(' ');
Chris@49 751
Chris@49 752 bool save_okay = f.good();
Chris@49 753 f.close();
Chris@49 754
Chris@49 755 if(save_okay == true)
Chris@49 756 {
Chris@49 757 std::remove(new_name.c_str());
Chris@49 758
Chris@49 759 const int mv_result = std::rename(old_name.c_str(), new_name.c_str());
Chris@49 760
Chris@49 761 save_okay = (mv_result == 0);
Chris@49 762 }
Chris@49 763
Chris@49 764 return save_okay;
Chris@49 765 }
Chris@49 766
Chris@49 767
Chris@49 768
Chris@49 769 template<typename eT>
Chris@49 770 inline
Chris@49 771 bool
Chris@49 772 diskio::convert_naninf(eT& val, const std::string& token)
Chris@49 773 {
Chris@49 774 // see if the token represents a NaN or Inf
Chris@49 775
Chris@49 776 if( (token.length() == 3) || (token.length() == 4) )
Chris@49 777 {
Chris@49 778 const bool neg = (token[0] == '-');
Chris@49 779 const bool pos = (token[0] == '+');
Chris@49 780
Chris@49 781 const size_t offset = ( (neg || pos) && (token.length() == 4) ) ? 1 : 0;
Chris@49 782
Chris@49 783 const std::string token2 = token.substr(offset, 3);
Chris@49 784
Chris@49 785 if( (token2 == "inf") || (token2 == "Inf") || (token2 == "INF") )
Chris@49 786 {
Chris@49 787 val = neg ? -(Datum<eT>::inf) : Datum<eT>::inf;
Chris@49 788
Chris@49 789 return true;
Chris@49 790 }
Chris@49 791 else
Chris@49 792 if( (token2 == "nan") || (token2 == "Nan") || (token2 == "NaN") || (token2 == "NAN") )
Chris@49 793 {
Chris@49 794 val = neg ? -(Datum<eT>::nan) : Datum<eT>::nan;
Chris@49 795
Chris@49 796 return true;
Chris@49 797 }
Chris@49 798 }
Chris@49 799
Chris@49 800 return false;
Chris@49 801 }
Chris@49 802
Chris@49 803
Chris@49 804
Chris@49 805 template<typename T>
Chris@49 806 inline
Chris@49 807 bool
Chris@49 808 diskio::convert_naninf(std::complex<T>& val, const std::string& token)
Chris@49 809 {
Chris@49 810 if( token.length() >= 5 )
Chris@49 811 {
Chris@49 812 std::stringstream ss( token.substr(1, token.length()-2) ); // strip '(' at the start and ')' at the end
Chris@49 813
Chris@49 814 std::string token_real;
Chris@49 815 std::string token_imag;
Chris@49 816
Chris@49 817 std::getline(ss, token_real, ',');
Chris@49 818 std::getline(ss, token_imag);
Chris@49 819
Chris@49 820 std::stringstream ss_real(token_real);
Chris@49 821 std::stringstream ss_imag(token_imag);
Chris@49 822
Chris@49 823 T val_real = T(0);
Chris@49 824 T val_imag = T(0);
Chris@49 825
Chris@49 826 ss_real >> val_real;
Chris@49 827 ss_imag >> val_imag;
Chris@49 828
Chris@49 829 bool success_real = true;
Chris@49 830 bool success_imag = true;
Chris@49 831
Chris@49 832 if(ss_real.fail() == true)
Chris@49 833 {
Chris@49 834 success_real = diskio::convert_naninf( val_real, token_real );
Chris@49 835 }
Chris@49 836
Chris@49 837 if(ss_imag.fail() == true)
Chris@49 838 {
Chris@49 839 success_imag = diskio::convert_naninf( val_imag, token_imag );
Chris@49 840 }
Chris@49 841
Chris@49 842 val = std::complex<T>(val_real, val_imag);
Chris@49 843
Chris@49 844 return (success_real && success_imag);
Chris@49 845 }
Chris@49 846
Chris@49 847 return false;
Chris@49 848 }
Chris@49 849
Chris@49 850
Chris@49 851
Chris@49 852 //! Save a matrix as raw text (no header, human readable).
Chris@49 853 //! Matrices can be loaded in Matlab and Octave, as long as they don't have complex elements.
Chris@49 854 template<typename eT>
Chris@49 855 inline
Chris@49 856 bool
Chris@49 857 diskio::save_raw_ascii(const Mat<eT>& x, const std::string& final_name)
Chris@49 858 {
Chris@49 859 arma_extra_debug_sigprint();
Chris@49 860
Chris@49 861 const std::string tmp_name = diskio::gen_tmp_name(final_name);
Chris@49 862
Chris@49 863 std::fstream f(tmp_name.c_str(), std::fstream::out);
Chris@49 864
Chris@49 865 bool save_okay = f.is_open();
Chris@49 866
Chris@49 867 if(save_okay == true)
Chris@49 868 {
Chris@49 869 save_okay = diskio::save_raw_ascii(x, f);
Chris@49 870
Chris@49 871 f.flush();
Chris@49 872 f.close();
Chris@49 873
Chris@49 874 if(save_okay == true)
Chris@49 875 {
Chris@49 876 save_okay = diskio::safe_rename(tmp_name, final_name);
Chris@49 877 }
Chris@49 878 }
Chris@49 879
Chris@49 880 return save_okay;
Chris@49 881 }
Chris@49 882
Chris@49 883
Chris@49 884
Chris@49 885 //! Save a matrix as raw text (no header, human readable).
Chris@49 886 //! Matrices can be loaded in Matlab and Octave, as long as they don't have complex elements.
Chris@49 887 template<typename eT>
Chris@49 888 inline
Chris@49 889 bool
Chris@49 890 diskio::save_raw_ascii(const Mat<eT>& x, std::ostream& f)
Chris@49 891 {
Chris@49 892 arma_extra_debug_sigprint();
Chris@49 893
Chris@49 894 uword cell_width;
Chris@49 895
Chris@49 896 // TODO: need sane values for complex numbers
Chris@49 897
Chris@49 898 if( (is_float<eT>::value == true) || (is_double<eT>::value == true) )
Chris@49 899 {
Chris@49 900 f.setf(ios::scientific);
Chris@49 901 f.precision(12);
Chris@49 902 cell_width = 20;
Chris@49 903 }
Chris@49 904
Chris@49 905 for(uword row=0; row < x.n_rows; ++row)
Chris@49 906 {
Chris@49 907 for(uword col=0; col < x.n_cols; ++col)
Chris@49 908 {
Chris@49 909 f.put(' ');
Chris@49 910
Chris@49 911 if( (is_float<eT>::value == true) || (is_double<eT>::value == true) )
Chris@49 912 {
Chris@49 913 f.width(cell_width);
Chris@49 914 }
Chris@49 915
Chris@49 916 f << x.at(row,col);
Chris@49 917 }
Chris@49 918
Chris@49 919 f.put('\n');
Chris@49 920 }
Chris@49 921
Chris@49 922 return f.good();
Chris@49 923 }
Chris@49 924
Chris@49 925
Chris@49 926
Chris@49 927 //! Save a matrix as raw binary (no header)
Chris@49 928 template<typename eT>
Chris@49 929 inline
Chris@49 930 bool
Chris@49 931 diskio::save_raw_binary(const Mat<eT>& x, const std::string& final_name)
Chris@49 932 {
Chris@49 933 arma_extra_debug_sigprint();
Chris@49 934
Chris@49 935 const std::string tmp_name = diskio::gen_tmp_name(final_name);
Chris@49 936
Chris@49 937 std::ofstream f(tmp_name.c_str(), std::fstream::binary);
Chris@49 938
Chris@49 939 bool save_okay = f.is_open();
Chris@49 940
Chris@49 941 if(save_okay == true)
Chris@49 942 {
Chris@49 943 save_okay = diskio::save_raw_binary(x, f);
Chris@49 944
Chris@49 945 f.flush();
Chris@49 946 f.close();
Chris@49 947
Chris@49 948 if(save_okay == true)
Chris@49 949 {
Chris@49 950 save_okay = diskio::safe_rename(tmp_name, final_name);
Chris@49 951 }
Chris@49 952 }
Chris@49 953
Chris@49 954 return save_okay;
Chris@49 955 }
Chris@49 956
Chris@49 957
Chris@49 958
Chris@49 959 template<typename eT>
Chris@49 960 inline
Chris@49 961 bool
Chris@49 962 diskio::save_raw_binary(const Mat<eT>& x, std::ostream& f)
Chris@49 963 {
Chris@49 964 arma_extra_debug_sigprint();
Chris@49 965
Chris@49 966 f.write( reinterpret_cast<const char*>(x.mem), std::streamsize(x.n_elem*sizeof(eT)) );
Chris@49 967
Chris@49 968 return f.good();
Chris@49 969 }
Chris@49 970
Chris@49 971
Chris@49 972
Chris@49 973 //! Save a matrix in text format (human readable),
Chris@49 974 //! with a header that indicates the matrix type as well as its dimensions
Chris@49 975 template<typename eT>
Chris@49 976 inline
Chris@49 977 bool
Chris@49 978 diskio::save_arma_ascii(const Mat<eT>& x, const std::string& final_name)
Chris@49 979 {
Chris@49 980 arma_extra_debug_sigprint();
Chris@49 981
Chris@49 982 const std::string tmp_name = diskio::gen_tmp_name(final_name);
Chris@49 983
Chris@49 984 std::ofstream f(tmp_name.c_str());
Chris@49 985
Chris@49 986 bool save_okay = f.is_open();
Chris@49 987
Chris@49 988 if(save_okay == true)
Chris@49 989 {
Chris@49 990 save_okay = diskio::save_arma_ascii(x, f);
Chris@49 991
Chris@49 992 f.flush();
Chris@49 993 f.close();
Chris@49 994
Chris@49 995 if(save_okay == true)
Chris@49 996 {
Chris@49 997 save_okay = diskio::safe_rename(tmp_name, final_name);
Chris@49 998 }
Chris@49 999 }
Chris@49 1000
Chris@49 1001 return save_okay;
Chris@49 1002 }
Chris@49 1003
Chris@49 1004
Chris@49 1005
Chris@49 1006 //! Save a matrix in text format (human readable),
Chris@49 1007 //! with a header that indicates the matrix type as well as its dimensions
Chris@49 1008 template<typename eT>
Chris@49 1009 inline
Chris@49 1010 bool
Chris@49 1011 diskio::save_arma_ascii(const Mat<eT>& x, std::ostream& f)
Chris@49 1012 {
Chris@49 1013 arma_extra_debug_sigprint();
Chris@49 1014
Chris@49 1015 const ios::fmtflags orig_flags = f.flags();
Chris@49 1016
Chris@49 1017 f << diskio::gen_txt_header(x) << '\n';
Chris@49 1018 f << x.n_rows << ' ' << x.n_cols << '\n';
Chris@49 1019
Chris@49 1020 uword cell_width;
Chris@49 1021
Chris@49 1022 // TODO: need sane values for complex numbers
Chris@49 1023
Chris@49 1024 if( (is_float<eT>::value == true) || (is_double<eT>::value == true) )
Chris@49 1025 {
Chris@49 1026 f.setf(ios::scientific);
Chris@49 1027 f.precision(12);
Chris@49 1028 cell_width = 20;
Chris@49 1029 }
Chris@49 1030
Chris@49 1031 for(uword row=0; row < x.n_rows; ++row)
Chris@49 1032 {
Chris@49 1033 for(uword col=0; col < x.n_cols; ++col)
Chris@49 1034 {
Chris@49 1035 f.put(' ');
Chris@49 1036
Chris@49 1037 if( (is_float<eT>::value == true) || (is_double<eT>::value == true) )
Chris@49 1038 {
Chris@49 1039 f.width(cell_width);
Chris@49 1040 }
Chris@49 1041
Chris@49 1042 f << x.at(row,col);
Chris@49 1043 }
Chris@49 1044
Chris@49 1045 f.put('\n');
Chris@49 1046 }
Chris@49 1047
Chris@49 1048 const bool save_okay = f.good();
Chris@49 1049
Chris@49 1050 f.flags(orig_flags);
Chris@49 1051
Chris@49 1052 return save_okay;
Chris@49 1053 }
Chris@49 1054
Chris@49 1055
Chris@49 1056
Chris@49 1057 //! Save a matrix in CSV text format (human readable)
Chris@49 1058 template<typename eT>
Chris@49 1059 inline
Chris@49 1060 bool
Chris@49 1061 diskio::save_csv_ascii(const Mat<eT>& x, const std::string& final_name)
Chris@49 1062 {
Chris@49 1063 arma_extra_debug_sigprint();
Chris@49 1064
Chris@49 1065 const std::string tmp_name = diskio::gen_tmp_name(final_name);
Chris@49 1066
Chris@49 1067 std::ofstream f(tmp_name.c_str());
Chris@49 1068
Chris@49 1069 bool save_okay = f.is_open();
Chris@49 1070
Chris@49 1071 if(save_okay == true)
Chris@49 1072 {
Chris@49 1073 save_okay = diskio::save_csv_ascii(x, f);
Chris@49 1074
Chris@49 1075 f.flush();
Chris@49 1076 f.close();
Chris@49 1077
Chris@49 1078 if(save_okay == true)
Chris@49 1079 {
Chris@49 1080 save_okay = diskio::safe_rename(tmp_name, final_name);
Chris@49 1081 }
Chris@49 1082 }
Chris@49 1083
Chris@49 1084 return save_okay;
Chris@49 1085 }
Chris@49 1086
Chris@49 1087
Chris@49 1088
Chris@49 1089 //! Save a matrix in CSV text format (human readable)
Chris@49 1090 template<typename eT>
Chris@49 1091 inline
Chris@49 1092 bool
Chris@49 1093 diskio::save_csv_ascii(const Mat<eT>& x, std::ostream& f)
Chris@49 1094 {
Chris@49 1095 arma_extra_debug_sigprint();
Chris@49 1096
Chris@49 1097 const ios::fmtflags orig_flags = f.flags();
Chris@49 1098
Chris@49 1099 // TODO: need sane values for complex numbers
Chris@49 1100
Chris@49 1101 if( (is_float<eT>::value == true) || (is_double<eT>::value == true) )
Chris@49 1102 {
Chris@49 1103 f.setf(ios::scientific);
Chris@49 1104 f.precision(12);
Chris@49 1105 }
Chris@49 1106
Chris@49 1107 uword x_n_rows = x.n_rows;
Chris@49 1108 uword x_n_cols = x.n_cols;
Chris@49 1109
Chris@49 1110 for(uword row=0; row < x_n_rows; ++row)
Chris@49 1111 {
Chris@49 1112 for(uword col=0; col < x_n_cols; ++col)
Chris@49 1113 {
Chris@49 1114 f << x.at(row,col);
Chris@49 1115
Chris@49 1116 if( col < (x_n_cols-1) )
Chris@49 1117 {
Chris@49 1118 f.put(',');
Chris@49 1119 }
Chris@49 1120 }
Chris@49 1121
Chris@49 1122 f.put('\n');
Chris@49 1123 }
Chris@49 1124
Chris@49 1125 const bool save_okay = f.good();
Chris@49 1126
Chris@49 1127 f.flags(orig_flags);
Chris@49 1128
Chris@49 1129 return save_okay;
Chris@49 1130 }
Chris@49 1131
Chris@49 1132
Chris@49 1133
Chris@49 1134 //! Save a matrix in binary format,
Chris@49 1135 //! with a header that stores the matrix type as well as its dimensions
Chris@49 1136 template<typename eT>
Chris@49 1137 inline
Chris@49 1138 bool
Chris@49 1139 diskio::save_arma_binary(const Mat<eT>& x, const std::string& final_name)
Chris@49 1140 {
Chris@49 1141 arma_extra_debug_sigprint();
Chris@49 1142
Chris@49 1143 const std::string tmp_name = diskio::gen_tmp_name(final_name);
Chris@49 1144
Chris@49 1145 std::ofstream f(tmp_name.c_str(), std::fstream::binary);
Chris@49 1146
Chris@49 1147 bool save_okay = f.is_open();
Chris@49 1148
Chris@49 1149 if(save_okay == true)
Chris@49 1150 {
Chris@49 1151 save_okay = diskio::save_arma_binary(x, f);
Chris@49 1152
Chris@49 1153 f.flush();
Chris@49 1154 f.close();
Chris@49 1155
Chris@49 1156 if(save_okay == true)
Chris@49 1157 {
Chris@49 1158 save_okay = diskio::safe_rename(tmp_name, final_name);
Chris@49 1159 }
Chris@49 1160 }
Chris@49 1161
Chris@49 1162 return save_okay;
Chris@49 1163 }
Chris@49 1164
Chris@49 1165
Chris@49 1166
Chris@49 1167 //! Save a matrix in binary format,
Chris@49 1168 //! with a header that stores the matrix type as well as its dimensions
Chris@49 1169 template<typename eT>
Chris@49 1170 inline
Chris@49 1171 bool
Chris@49 1172 diskio::save_arma_binary(const Mat<eT>& x, std::ostream& f)
Chris@49 1173 {
Chris@49 1174 arma_extra_debug_sigprint();
Chris@49 1175
Chris@49 1176 f << diskio::gen_bin_header(x) << '\n';
Chris@49 1177 f << x.n_rows << ' ' << x.n_cols << '\n';
Chris@49 1178
Chris@49 1179 f.write( reinterpret_cast<const char*>(x.mem), std::streamsize(x.n_elem*sizeof(eT)) );
Chris@49 1180
Chris@49 1181 return f.good();
Chris@49 1182 }
Chris@49 1183
Chris@49 1184
Chris@49 1185
Chris@49 1186 //! Save a matrix as a PGM greyscale image
Chris@49 1187 template<typename eT>
Chris@49 1188 inline
Chris@49 1189 bool
Chris@49 1190 diskio::save_pgm_binary(const Mat<eT>& x, const std::string& final_name)
Chris@49 1191 {
Chris@49 1192 arma_extra_debug_sigprint();
Chris@49 1193
Chris@49 1194 const std::string tmp_name = diskio::gen_tmp_name(final_name);
Chris@49 1195
Chris@49 1196 std::fstream f(tmp_name.c_str(), std::fstream::out | std::fstream::binary);
Chris@49 1197
Chris@49 1198 bool save_okay = f.is_open();
Chris@49 1199
Chris@49 1200 if(save_okay == true)
Chris@49 1201 {
Chris@49 1202 save_okay = diskio::save_pgm_binary(x, f);
Chris@49 1203
Chris@49 1204 f.flush();
Chris@49 1205 f.close();
Chris@49 1206
Chris@49 1207 if(save_okay == true)
Chris@49 1208 {
Chris@49 1209 save_okay = diskio::safe_rename(tmp_name, final_name);
Chris@49 1210 }
Chris@49 1211 }
Chris@49 1212
Chris@49 1213 return save_okay;
Chris@49 1214 }
Chris@49 1215
Chris@49 1216
Chris@49 1217
Chris@49 1218 //
Chris@49 1219 // TODO:
Chris@49 1220 // add functionality to save the image in a normalised format,
Chris@49 1221 // i.e. scaled so that every value falls in the [0,255] range.
Chris@49 1222
Chris@49 1223 //! Save a matrix as a PGM greyscale image
Chris@49 1224 template<typename eT>
Chris@49 1225 inline
Chris@49 1226 bool
Chris@49 1227 diskio::save_pgm_binary(const Mat<eT>& x, std::ostream& f)
Chris@49 1228 {
Chris@49 1229 arma_extra_debug_sigprint();
Chris@49 1230
Chris@49 1231 f << "P5" << '\n';
Chris@49 1232 f << x.n_cols << ' ' << x.n_rows << '\n';
Chris@49 1233 f << 255 << '\n';
Chris@49 1234
Chris@49 1235 const uword n_elem = x.n_rows * x.n_cols;
Chris@49 1236 podarray<u8> tmp(n_elem);
Chris@49 1237
Chris@49 1238 uword i = 0;
Chris@49 1239
Chris@49 1240 for(uword row=0; row < x.n_rows; ++row)
Chris@49 1241 {
Chris@49 1242 for(uword col=0; col < x.n_cols; ++col)
Chris@49 1243 {
Chris@49 1244 tmp[i] = u8( x.at(row,col) ); // TODO: add round() ?
Chris@49 1245 ++i;
Chris@49 1246 }
Chris@49 1247 }
Chris@49 1248
Chris@49 1249 f.write(reinterpret_cast<const char*>(tmp.mem), std::streamsize(n_elem) );
Chris@49 1250
Chris@49 1251 return f.good();
Chris@49 1252 }
Chris@49 1253
Chris@49 1254
Chris@49 1255
Chris@49 1256 //! Save a matrix as a PGM greyscale image
Chris@49 1257 template<typename T>
Chris@49 1258 inline
Chris@49 1259 bool
Chris@49 1260 diskio::save_pgm_binary(const Mat< std::complex<T> >& x, const std::string& final_name)
Chris@49 1261 {
Chris@49 1262 arma_extra_debug_sigprint();
Chris@49 1263
Chris@49 1264 const uchar_mat tmp = conv_to<uchar_mat>::from(x);
Chris@49 1265
Chris@49 1266 return diskio::save_pgm_binary(tmp, final_name);
Chris@49 1267 }
Chris@49 1268
Chris@49 1269
Chris@49 1270
Chris@49 1271 //! Save a matrix as a PGM greyscale image
Chris@49 1272 template<typename T>
Chris@49 1273 inline
Chris@49 1274 bool
Chris@49 1275 diskio::save_pgm_binary(const Mat< std::complex<T> >& x, std::ostream& f)
Chris@49 1276 {
Chris@49 1277 arma_extra_debug_sigprint();
Chris@49 1278
Chris@49 1279 const uchar_mat tmp = conv_to<uchar_mat>::from(x);
Chris@49 1280
Chris@49 1281 return diskio::save_pgm_binary(tmp, f);
Chris@49 1282 }
Chris@49 1283
Chris@49 1284
Chris@49 1285
Chris@49 1286 //! Save a matrix as part of a HDF5 file
Chris@49 1287 template<typename eT>
Chris@49 1288 inline
Chris@49 1289 bool
Chris@49 1290 diskio::save_hdf5_binary(const Mat<eT>& x, const std::string& final_name)
Chris@49 1291 {
Chris@49 1292 arma_extra_debug_sigprint();
Chris@49 1293
Chris@49 1294 #if defined(ARMA_USE_HDF5)
Chris@49 1295 {
Chris@49 1296 #if !defined(ARMA_PRINT_HDF5_ERRORS)
Chris@49 1297 {
Chris@49 1298 // Disable annoying HDF5 error messages.
Chris@49 1299 H5Eset_auto(H5E_DEFAULT, NULL, NULL);
Chris@49 1300 }
Chris@49 1301 #endif
Chris@49 1302
Chris@49 1303 bool save_okay = false;
Chris@49 1304
Chris@49 1305 const std::string tmp_name = diskio::gen_tmp_name(final_name);
Chris@49 1306
Chris@49 1307 // Set up the file according to HDF5's preferences
Chris@49 1308 hid_t file = H5Fcreate(tmp_name.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
Chris@49 1309
Chris@49 1310 // We need to create a dataset, datatype, and dataspace
Chris@49 1311 hsize_t dims[2];
Chris@49 1312 dims[1] = x.n_rows;
Chris@49 1313 dims[0] = x.n_cols;
Chris@49 1314
Chris@49 1315 hid_t dataspace = H5Screate_simple(2, dims, NULL); // treat the matrix as a 2d array dataspace
Chris@49 1316 hid_t datatype = hdf5_misc::get_hdf5_type<eT>();
Chris@49 1317
Chris@49 1318 // If this returned something invalid, well, it's time to crash.
Chris@49 1319 arma_check(datatype == -1, "Mat::save(): unknown datatype for HDF5");
Chris@49 1320
Chris@49 1321 // MATLAB forces the users to specify a name at save time for HDF5; Octave
Chris@49 1322 // will use the default of 'dataset' unless otherwise specified, so we will
Chris@49 1323 // use that.
Chris@49 1324 hid_t dataset = H5Dcreate(file, "dataset", datatype, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
Chris@49 1325
Chris@49 1326 // H5Dwrite does not make a distinction between row-major and column-major;
Chris@49 1327 // it just writes the memory. MATLAB and Octave store HDF5 matrices as
Chris@49 1328 // column-major, though, so we can save ours like that too and not need to
Chris@49 1329 // transpose.
Chris@49 1330 herr_t status = H5Dwrite(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, x.mem);
Chris@49 1331 save_okay = (status >= 0);
Chris@49 1332
Chris@49 1333 H5Dclose(dataset);
Chris@49 1334 H5Tclose(datatype);
Chris@49 1335 H5Sclose(dataspace);
Chris@49 1336 H5Fclose(file);
Chris@49 1337
Chris@49 1338 if(save_okay == true) { save_okay = diskio::safe_rename(tmp_name, final_name); }
Chris@49 1339
Chris@49 1340 return save_okay;
Chris@49 1341 }
Chris@49 1342 #else
Chris@49 1343 {
Chris@49 1344 arma_ignore(x);
Chris@49 1345 arma_ignore(final_name);
Chris@49 1346
Chris@49 1347 arma_stop("Mat::save(): use of HDF5 needs to be enabled");
Chris@49 1348
Chris@49 1349 return false;
Chris@49 1350 }
Chris@49 1351 #endif
Chris@49 1352 }
Chris@49 1353
Chris@49 1354
Chris@49 1355
Chris@49 1356 //! Load a matrix as raw text (no header, human readable).
Chris@49 1357 //! Can read matrices saved as text in Matlab and Octave.
Chris@49 1358 //! NOTE: this is much slower than reading a file with a header.
Chris@49 1359 template<typename eT>
Chris@49 1360 inline
Chris@49 1361 bool
Chris@49 1362 diskio::load_raw_ascii(Mat<eT>& x, const std::string& name, std::string& err_msg)
Chris@49 1363 {
Chris@49 1364 arma_extra_debug_sigprint();
Chris@49 1365
Chris@49 1366 std::fstream f;
Chris@49 1367 f.open(name.c_str(), std::fstream::in);
Chris@49 1368
Chris@49 1369 bool load_okay = f.is_open();
Chris@49 1370
Chris@49 1371 if(load_okay == true)
Chris@49 1372 {
Chris@49 1373 load_okay = diskio::load_raw_ascii(x, f, err_msg);
Chris@49 1374 f.close();
Chris@49 1375 }
Chris@49 1376
Chris@49 1377 return load_okay;
Chris@49 1378 }
Chris@49 1379
Chris@49 1380
Chris@49 1381
Chris@49 1382 //! Load a matrix as raw text (no header, human readable).
Chris@49 1383 //! Can read matrices saved as text in Matlab and Octave.
Chris@49 1384 //! NOTE: this is much slower than reading a file with a header.
Chris@49 1385 template<typename eT>
Chris@49 1386 inline
Chris@49 1387 bool
Chris@49 1388 diskio::load_raw_ascii(Mat<eT>& x, std::istream& f, std::string& err_msg)
Chris@49 1389 {
Chris@49 1390 arma_extra_debug_sigprint();
Chris@49 1391
Chris@49 1392 bool load_okay = f.good();
Chris@49 1393
Chris@49 1394 f.clear();
Chris@49 1395 const std::fstream::pos_type pos1 = f.tellg();
Chris@49 1396
Chris@49 1397 //
Chris@49 1398 // work out the size
Chris@49 1399
Chris@49 1400 uword f_n_rows = 0;
Chris@49 1401 uword f_n_cols = 0;
Chris@49 1402
Chris@49 1403 bool f_n_cols_found = false;
Chris@49 1404
Chris@49 1405 std::string line_string;
Chris@49 1406 std::string token;
Chris@49 1407
Chris@49 1408 std::stringstream line_stream;
Chris@49 1409
Chris@49 1410 while( (f.good() == true) && (load_okay == true) )
Chris@49 1411 {
Chris@49 1412 std::getline(f, line_string);
Chris@49 1413
Chris@49 1414 if(line_string.size() == 0)
Chris@49 1415 {
Chris@49 1416 break;
Chris@49 1417 }
Chris@49 1418
Chris@49 1419 line_stream.clear();
Chris@49 1420 line_stream.str(line_string);
Chris@49 1421
Chris@49 1422 uword line_n_cols = 0;
Chris@49 1423
Chris@49 1424 while (line_stream >> token)
Chris@49 1425 {
Chris@49 1426 ++line_n_cols;
Chris@49 1427 }
Chris@49 1428
Chris@49 1429 if(f_n_cols_found == false)
Chris@49 1430 {
Chris@49 1431 f_n_cols = line_n_cols;
Chris@49 1432 f_n_cols_found = true;
Chris@49 1433 }
Chris@49 1434 else
Chris@49 1435 {
Chris@49 1436 if(line_n_cols != f_n_cols)
Chris@49 1437 {
Chris@49 1438 err_msg = "inconsistent number of columns in ";
Chris@49 1439 load_okay = false;
Chris@49 1440 }
Chris@49 1441 }
Chris@49 1442
Chris@49 1443 ++f_n_rows;
Chris@49 1444 }
Chris@49 1445
Chris@49 1446 if(load_okay == true)
Chris@49 1447 {
Chris@49 1448 f.clear();
Chris@49 1449 f.seekg(pos1);
Chris@49 1450
Chris@49 1451 x.set_size(f_n_rows, f_n_cols);
Chris@49 1452
Chris@49 1453 std::stringstream ss;
Chris@49 1454
Chris@49 1455 for(uword row=0; (row < x.n_rows) && (load_okay == true); ++row)
Chris@49 1456 {
Chris@49 1457 for(uword col=0; (col < x.n_cols) && (load_okay == true); ++col)
Chris@49 1458 {
Chris@49 1459 f >> token;
Chris@49 1460
Chris@49 1461 ss.clear();
Chris@49 1462 ss.str(token);
Chris@49 1463
Chris@49 1464 eT val = eT(0);
Chris@49 1465 ss >> val;
Chris@49 1466
Chris@49 1467 if(ss.fail() == false)
Chris@49 1468 {
Chris@49 1469 x.at(row,col) = val;
Chris@49 1470 }
Chris@49 1471 else
Chris@49 1472 {
Chris@49 1473 const bool success = diskio::convert_naninf( x.at(row,col), token );
Chris@49 1474
Chris@49 1475 if(success == false)
Chris@49 1476 {
Chris@49 1477 load_okay = false;
Chris@49 1478 err_msg = "couldn't interpret data in ";
Chris@49 1479 }
Chris@49 1480 }
Chris@49 1481 }
Chris@49 1482 }
Chris@49 1483 }
Chris@49 1484
Chris@49 1485
Chris@49 1486 // an empty file indicates an empty matrix
Chris@49 1487 if( (f_n_cols_found == false) && (load_okay == true) )
Chris@49 1488 {
Chris@49 1489 x.reset();
Chris@49 1490 }
Chris@49 1491
Chris@49 1492
Chris@49 1493 return load_okay;
Chris@49 1494 }
Chris@49 1495
Chris@49 1496
Chris@49 1497
Chris@49 1498 //! Load a matrix in binary format (no header);
Chris@49 1499 //! the matrix is assumed to have one column
Chris@49 1500 template<typename eT>
Chris@49 1501 inline
Chris@49 1502 bool
Chris@49 1503 diskio::load_raw_binary(Mat<eT>& x, const std::string& name, std::string& err_msg)
Chris@49 1504 {
Chris@49 1505 arma_extra_debug_sigprint();
Chris@49 1506
Chris@49 1507 std::ifstream f;
Chris@49 1508 f.open(name.c_str(), std::fstream::binary);
Chris@49 1509
Chris@49 1510 bool load_okay = f.is_open();
Chris@49 1511
Chris@49 1512 if(load_okay == true)
Chris@49 1513 {
Chris@49 1514 load_okay = diskio::load_raw_binary(x, f, err_msg);
Chris@49 1515 f.close();
Chris@49 1516 }
Chris@49 1517
Chris@49 1518 return load_okay;
Chris@49 1519 }
Chris@49 1520
Chris@49 1521
Chris@49 1522
Chris@49 1523 template<typename eT>
Chris@49 1524 inline
Chris@49 1525 bool
Chris@49 1526 diskio::load_raw_binary(Mat<eT>& x, std::istream& f, std::string& err_msg)
Chris@49 1527 {
Chris@49 1528 arma_extra_debug_sigprint();
Chris@49 1529 arma_ignore(err_msg);
Chris@49 1530
Chris@49 1531 f.clear();
Chris@49 1532 const std::streampos pos1 = f.tellg();
Chris@49 1533
Chris@49 1534 f.clear();
Chris@49 1535 f.seekg(0, ios::end);
Chris@49 1536
Chris@49 1537 f.clear();
Chris@49 1538 const std::streampos pos2 = f.tellg();
Chris@49 1539
Chris@49 1540 const uword N = ( (pos1 >= 0) && (pos2 >= 0) ) ? uword(pos2 - pos1) : 0;
Chris@49 1541
Chris@49 1542 f.clear();
Chris@49 1543 //f.seekg(0, ios::beg);
Chris@49 1544 f.seekg(pos1);
Chris@49 1545
Chris@49 1546 x.set_size(N / sizeof(eT), 1);
Chris@49 1547
Chris@49 1548 f.clear();
Chris@49 1549 f.read( reinterpret_cast<char *>(x.memptr()), std::streamsize(N) );
Chris@49 1550
Chris@49 1551 return f.good();
Chris@49 1552 }
Chris@49 1553
Chris@49 1554
Chris@49 1555
Chris@49 1556 //! Load a matrix in text format (human readable),
Chris@49 1557 //! with a header that indicates the matrix type as well as its dimensions
Chris@49 1558 template<typename eT>
Chris@49 1559 inline
Chris@49 1560 bool
Chris@49 1561 diskio::load_arma_ascii(Mat<eT>& x, const std::string& name, std::string& err_msg)
Chris@49 1562 {
Chris@49 1563 arma_extra_debug_sigprint();
Chris@49 1564
Chris@49 1565 std::ifstream f(name.c_str());
Chris@49 1566
Chris@49 1567 bool load_okay = f.is_open();
Chris@49 1568
Chris@49 1569 if(load_okay == true)
Chris@49 1570 {
Chris@49 1571 load_okay = diskio::load_arma_ascii(x, f, err_msg);
Chris@49 1572 f.close();
Chris@49 1573 }
Chris@49 1574
Chris@49 1575 return load_okay;
Chris@49 1576 }
Chris@49 1577
Chris@49 1578
Chris@49 1579
Chris@49 1580 //! Load a matrix in text format (human readable),
Chris@49 1581 //! with a header that indicates the matrix type as well as its dimensions
Chris@49 1582 template<typename eT>
Chris@49 1583 inline
Chris@49 1584 bool
Chris@49 1585 diskio::load_arma_ascii(Mat<eT>& x, std::istream& f, std::string& err_msg)
Chris@49 1586 {
Chris@49 1587 arma_extra_debug_sigprint();
Chris@49 1588
Chris@49 1589 bool load_okay = true;
Chris@49 1590
Chris@49 1591 std::string f_header;
Chris@49 1592 uword f_n_rows;
Chris@49 1593 uword f_n_cols;
Chris@49 1594
Chris@49 1595 f >> f_header;
Chris@49 1596 f >> f_n_rows;
Chris@49 1597 f >> f_n_cols;
Chris@49 1598
Chris@49 1599 if(f_header == diskio::gen_txt_header(x))
Chris@49 1600 {
Chris@49 1601 x.zeros(f_n_rows, f_n_cols);
Chris@49 1602
Chris@49 1603 std::string token;
Chris@49 1604 std::stringstream ss;
Chris@49 1605
Chris@49 1606 for(uword row=0; row < x.n_rows; ++row)
Chris@49 1607 {
Chris@49 1608 for(uword col=0; col < x.n_cols; ++col)
Chris@49 1609 {
Chris@49 1610 f >> token;
Chris@49 1611
Chris@49 1612 ss.clear();
Chris@49 1613 ss.str(token);
Chris@49 1614
Chris@49 1615 eT val = eT(0);
Chris@49 1616 ss >> val;
Chris@49 1617
Chris@49 1618 if(ss.fail() == false)
Chris@49 1619 {
Chris@49 1620 x.at(row,col) = val;
Chris@49 1621 }
Chris@49 1622 else
Chris@49 1623 {
Chris@49 1624 diskio::convert_naninf( x.at(row,col), token );
Chris@49 1625 }
Chris@49 1626 }
Chris@49 1627 }
Chris@49 1628
Chris@49 1629 load_okay = f.good();
Chris@49 1630 }
Chris@49 1631 else
Chris@49 1632 {
Chris@49 1633 load_okay = false;
Chris@49 1634 err_msg = "incorrect header in ";
Chris@49 1635 }
Chris@49 1636
Chris@49 1637 return load_okay;
Chris@49 1638 }
Chris@49 1639
Chris@49 1640
Chris@49 1641
Chris@49 1642 //! Load a matrix in CSV text format (human readable)
Chris@49 1643 template<typename eT>
Chris@49 1644 inline
Chris@49 1645 bool
Chris@49 1646 diskio::load_csv_ascii(Mat<eT>& x, const std::string& name, std::string& err_msg)
Chris@49 1647 {
Chris@49 1648 arma_extra_debug_sigprint();
Chris@49 1649
Chris@49 1650 std::fstream f;
Chris@49 1651 f.open(name.c_str(), std::fstream::in);
Chris@49 1652
Chris@49 1653 bool load_okay = f.is_open();
Chris@49 1654
Chris@49 1655 if(load_okay == true)
Chris@49 1656 {
Chris@49 1657 load_okay = diskio::load_csv_ascii(x, f, err_msg);
Chris@49 1658 f.close();
Chris@49 1659 }
Chris@49 1660
Chris@49 1661 return load_okay;
Chris@49 1662 }
Chris@49 1663
Chris@49 1664
Chris@49 1665
Chris@49 1666 //! Load a matrix in CSV text format (human readable)
Chris@49 1667 template<typename eT>
Chris@49 1668 inline
Chris@49 1669 bool
Chris@49 1670 diskio::load_csv_ascii(Mat<eT>& x, std::istream& f, std::string&)
Chris@49 1671 {
Chris@49 1672 arma_extra_debug_sigprint();
Chris@49 1673
Chris@49 1674 bool load_okay = f.good();
Chris@49 1675
Chris@49 1676 f.clear();
Chris@49 1677 const std::fstream::pos_type pos1 = f.tellg();
Chris@49 1678
Chris@49 1679 //
Chris@49 1680 // work out the size
Chris@49 1681
Chris@49 1682 uword f_n_rows = 0;
Chris@49 1683 uword f_n_cols = 0;
Chris@49 1684
Chris@49 1685 std::string line_string;
Chris@49 1686 std::string token;
Chris@49 1687
Chris@49 1688 std::stringstream line_stream;
Chris@49 1689
Chris@49 1690 while( (f.good() == true) && (load_okay == true) )
Chris@49 1691 {
Chris@49 1692 std::getline(f, line_string);
Chris@49 1693
Chris@49 1694 if(line_string.size() == 0)
Chris@49 1695 {
Chris@49 1696 break;
Chris@49 1697 }
Chris@49 1698
Chris@49 1699 line_stream.clear();
Chris@49 1700 line_stream.str(line_string);
Chris@49 1701
Chris@49 1702 uword line_n_cols = 0;
Chris@49 1703
Chris@49 1704 while(line_stream.good() == true)
Chris@49 1705 {
Chris@49 1706 std::getline(line_stream, token, ',');
Chris@49 1707 ++line_n_cols;
Chris@49 1708 }
Chris@49 1709
Chris@49 1710 if(f_n_cols < line_n_cols)
Chris@49 1711 {
Chris@49 1712 f_n_cols = line_n_cols;
Chris@49 1713 }
Chris@49 1714
Chris@49 1715 ++f_n_rows;
Chris@49 1716 }
Chris@49 1717
Chris@49 1718 f.clear();
Chris@49 1719 f.seekg(pos1);
Chris@49 1720
Chris@49 1721 x.zeros(f_n_rows, f_n_cols);
Chris@49 1722
Chris@49 1723 uword row = 0;
Chris@49 1724
Chris@49 1725 std::stringstream ss;
Chris@49 1726
Chris@49 1727 while(f.good() == true)
Chris@49 1728 {
Chris@49 1729 std::getline(f, line_string);
Chris@49 1730
Chris@49 1731 if(line_string.size() == 0)
Chris@49 1732 {
Chris@49 1733 break;
Chris@49 1734 }
Chris@49 1735
Chris@49 1736 line_stream.clear();
Chris@49 1737 line_stream.str(line_string);
Chris@49 1738
Chris@49 1739 uword col = 0;
Chris@49 1740
Chris@49 1741 while(line_stream.good() == true)
Chris@49 1742 {
Chris@49 1743 std::getline(line_stream, token, ',');
Chris@49 1744
Chris@49 1745 ss.clear();
Chris@49 1746 ss.str(token);
Chris@49 1747
Chris@49 1748 eT val = eT(0);
Chris@49 1749 ss >> val;
Chris@49 1750
Chris@49 1751 if(ss.fail() == false)
Chris@49 1752 {
Chris@49 1753 x.at(row,col) = val;
Chris@49 1754 }
Chris@49 1755 else
Chris@49 1756 {
Chris@49 1757 diskio::convert_naninf( x.at(row,col), token );
Chris@49 1758 }
Chris@49 1759
Chris@49 1760 ++col;
Chris@49 1761 }
Chris@49 1762
Chris@49 1763 ++row;
Chris@49 1764 }
Chris@49 1765
Chris@49 1766 return load_okay;
Chris@49 1767 }
Chris@49 1768
Chris@49 1769
Chris@49 1770
Chris@49 1771 //! Load a matrix in binary format,
Chris@49 1772 //! with a header that indicates the matrix type as well as its dimensions
Chris@49 1773 template<typename eT>
Chris@49 1774 inline
Chris@49 1775 bool
Chris@49 1776 diskio::load_arma_binary(Mat<eT>& x, const std::string& name, std::string& err_msg)
Chris@49 1777 {
Chris@49 1778 arma_extra_debug_sigprint();
Chris@49 1779
Chris@49 1780 std::ifstream f;
Chris@49 1781 f.open(name.c_str(), std::fstream::binary);
Chris@49 1782
Chris@49 1783 bool load_okay = f.is_open();
Chris@49 1784
Chris@49 1785 if(load_okay == true)
Chris@49 1786 {
Chris@49 1787 load_okay = diskio::load_arma_binary(x, f, err_msg);
Chris@49 1788 f.close();
Chris@49 1789 }
Chris@49 1790
Chris@49 1791 return load_okay;
Chris@49 1792 }
Chris@49 1793
Chris@49 1794
Chris@49 1795
Chris@49 1796 template<typename eT>
Chris@49 1797 inline
Chris@49 1798 bool
Chris@49 1799 diskio::load_arma_binary(Mat<eT>& x, std::istream& f, std::string& err_msg)
Chris@49 1800 {
Chris@49 1801 arma_extra_debug_sigprint();
Chris@49 1802
Chris@49 1803 bool load_okay = true;
Chris@49 1804
Chris@49 1805 std::string f_header;
Chris@49 1806 uword f_n_rows;
Chris@49 1807 uword f_n_cols;
Chris@49 1808
Chris@49 1809 f >> f_header;
Chris@49 1810 f >> f_n_rows;
Chris@49 1811 f >> f_n_cols;
Chris@49 1812
Chris@49 1813 if(f_header == diskio::gen_bin_header(x))
Chris@49 1814 {
Chris@49 1815 //f.seekg(1, ios::cur); // NOTE: this may not be portable, as on a Windows machine a newline could be two characters
Chris@49 1816 f.get();
Chris@49 1817
Chris@49 1818 x.set_size(f_n_rows,f_n_cols);
Chris@49 1819 f.read( reinterpret_cast<char *>(x.memptr()), std::streamsize(x.n_elem*sizeof(eT)) );
Chris@49 1820
Chris@49 1821 load_okay = f.good();
Chris@49 1822 }
Chris@49 1823 else
Chris@49 1824 {
Chris@49 1825 load_okay = false;
Chris@49 1826 err_msg = "incorrect header in ";
Chris@49 1827 }
Chris@49 1828
Chris@49 1829 return load_okay;
Chris@49 1830 }
Chris@49 1831
Chris@49 1832
Chris@49 1833
Chris@49 1834 inline
Chris@49 1835 void
Chris@49 1836 diskio::pnm_skip_comments(std::istream& f)
Chris@49 1837 {
Chris@49 1838 while( isspace(f.peek()) )
Chris@49 1839 {
Chris@49 1840 while( isspace(f.peek()) )
Chris@49 1841 {
Chris@49 1842 f.get();
Chris@49 1843 }
Chris@49 1844
Chris@49 1845 if(f.peek() == '#')
Chris@49 1846 {
Chris@49 1847 while( (f.peek() != '\r') && (f.peek()!='\n') )
Chris@49 1848 {
Chris@49 1849 f.get();
Chris@49 1850 }
Chris@49 1851 }
Chris@49 1852 }
Chris@49 1853 }
Chris@49 1854
Chris@49 1855
Chris@49 1856
Chris@49 1857 //! Load a PGM greyscale image as a matrix
Chris@49 1858 template<typename eT>
Chris@49 1859 inline
Chris@49 1860 bool
Chris@49 1861 diskio::load_pgm_binary(Mat<eT>& x, const std::string& name, std::string& err_msg)
Chris@49 1862 {
Chris@49 1863 arma_extra_debug_sigprint();
Chris@49 1864
Chris@49 1865 std::fstream f;
Chris@49 1866 f.open(name.c_str(), std::fstream::in | std::fstream::binary);
Chris@49 1867
Chris@49 1868 bool load_okay = f.is_open();
Chris@49 1869
Chris@49 1870 if(load_okay == true)
Chris@49 1871 {
Chris@49 1872 load_okay = diskio::load_pgm_binary(x, f, err_msg);
Chris@49 1873 f.close();
Chris@49 1874 }
Chris@49 1875
Chris@49 1876 return load_okay;
Chris@49 1877 }
Chris@49 1878
Chris@49 1879
Chris@49 1880
Chris@49 1881 //! Load a PGM greyscale image as a matrix
Chris@49 1882 template<typename eT>
Chris@49 1883 inline
Chris@49 1884 bool
Chris@49 1885 diskio::load_pgm_binary(Mat<eT>& x, std::istream& f, std::string& err_msg)
Chris@49 1886 {
Chris@49 1887 bool load_okay = true;
Chris@49 1888
Chris@49 1889 std::string f_header;
Chris@49 1890 f >> f_header;
Chris@49 1891
Chris@49 1892 if(f_header == "P5")
Chris@49 1893 {
Chris@49 1894 uword f_n_rows = 0;
Chris@49 1895 uword f_n_cols = 0;
Chris@49 1896 int f_maxval = 0;
Chris@49 1897
Chris@49 1898 diskio::pnm_skip_comments(f);
Chris@49 1899
Chris@49 1900 f >> f_n_cols;
Chris@49 1901 diskio::pnm_skip_comments(f);
Chris@49 1902
Chris@49 1903 f >> f_n_rows;
Chris@49 1904 diskio::pnm_skip_comments(f);
Chris@49 1905
Chris@49 1906 f >> f_maxval;
Chris@49 1907 f.get();
Chris@49 1908
Chris@49 1909 if( (f_maxval > 0) || (f_maxval <= 65535) )
Chris@49 1910 {
Chris@49 1911 x.set_size(f_n_rows,f_n_cols);
Chris@49 1912
Chris@49 1913 if(f_maxval <= 255)
Chris@49 1914 {
Chris@49 1915 const uword n_elem = f_n_cols*f_n_rows;
Chris@49 1916 podarray<u8> tmp(n_elem);
Chris@49 1917
Chris@49 1918 f.read( reinterpret_cast<char*>(tmp.memptr()), std::streamsize(n_elem) );
Chris@49 1919
Chris@49 1920 uword i = 0;
Chris@49 1921
Chris@49 1922 //cout << "f_n_cols = " << f_n_cols << endl;
Chris@49 1923 //cout << "f_n_rows = " << f_n_rows << endl;
Chris@49 1924
Chris@49 1925
Chris@49 1926 for(uword row=0; row < f_n_rows; ++row)
Chris@49 1927 {
Chris@49 1928 for(uword col=0; col < f_n_cols; ++col)
Chris@49 1929 {
Chris@49 1930 x.at(row,col) = eT(tmp[i]);
Chris@49 1931 ++i;
Chris@49 1932 }
Chris@49 1933 }
Chris@49 1934
Chris@49 1935 }
Chris@49 1936 else
Chris@49 1937 {
Chris@49 1938 const uword n_elem = f_n_cols*f_n_rows;
Chris@49 1939 podarray<u16> tmp(n_elem);
Chris@49 1940
Chris@49 1941 f.read( reinterpret_cast<char *>(tmp.memptr()), std::streamsize(n_elem*2) );
Chris@49 1942
Chris@49 1943 uword i = 0;
Chris@49 1944
Chris@49 1945 for(uword row=0; row < f_n_rows; ++row)
Chris@49 1946 {
Chris@49 1947 for(uword col=0; col < f_n_cols; ++col)
Chris@49 1948 {
Chris@49 1949 x.at(row,col) = eT(tmp[i]);
Chris@49 1950 ++i;
Chris@49 1951 }
Chris@49 1952 }
Chris@49 1953
Chris@49 1954 }
Chris@49 1955
Chris@49 1956 }
Chris@49 1957 else
Chris@49 1958 {
Chris@49 1959 load_okay = false;
Chris@49 1960 err_msg = "currently no code available to handle loading ";
Chris@49 1961 }
Chris@49 1962
Chris@49 1963 if(f.good() == false)
Chris@49 1964 {
Chris@49 1965 load_okay = false;
Chris@49 1966 }
Chris@49 1967 }
Chris@49 1968 else
Chris@49 1969 {
Chris@49 1970 load_okay = false;
Chris@49 1971 err_msg = "unsupported header in ";
Chris@49 1972 }
Chris@49 1973
Chris@49 1974 return load_okay;
Chris@49 1975 }
Chris@49 1976
Chris@49 1977
Chris@49 1978
Chris@49 1979 //! Load a PGM greyscale image as a matrix
Chris@49 1980 template<typename T>
Chris@49 1981 inline
Chris@49 1982 bool
Chris@49 1983 diskio::load_pgm_binary(Mat< std::complex<T> >& x, const std::string& name, std::string& err_msg)
Chris@49 1984 {
Chris@49 1985 arma_extra_debug_sigprint();
Chris@49 1986
Chris@49 1987 uchar_mat tmp;
Chris@49 1988 const bool load_okay = diskio::load_pgm_binary(tmp, name, err_msg);
Chris@49 1989
Chris@49 1990 x = conv_to< Mat< std::complex<T> > >::from(tmp);
Chris@49 1991
Chris@49 1992 return load_okay;
Chris@49 1993 }
Chris@49 1994
Chris@49 1995
Chris@49 1996
Chris@49 1997 //! Load a PGM greyscale image as a matrix
Chris@49 1998 template<typename T>
Chris@49 1999 inline
Chris@49 2000 bool
Chris@49 2001 diskio::load_pgm_binary(Mat< std::complex<T> >& x, std::istream& is, std::string& err_msg)
Chris@49 2002 {
Chris@49 2003 arma_extra_debug_sigprint();
Chris@49 2004
Chris@49 2005 uchar_mat tmp;
Chris@49 2006 const bool load_okay = diskio::load_pgm_binary(tmp, is, err_msg);
Chris@49 2007
Chris@49 2008 x = conv_to< Mat< std::complex<T> > >::from(tmp);
Chris@49 2009
Chris@49 2010 return load_okay;
Chris@49 2011 }
Chris@49 2012
Chris@49 2013
Chris@49 2014
Chris@49 2015 //! Load a HDF5 file as a matrix
Chris@49 2016 template<typename eT>
Chris@49 2017 inline
Chris@49 2018 bool
Chris@49 2019 diskio::load_hdf5_binary(Mat<eT>& x, const std::string& name, std::string& err_msg)
Chris@49 2020 {
Chris@49 2021 arma_extra_debug_sigprint();
Chris@49 2022
Chris@49 2023 #if defined(ARMA_USE_HDF5)
Chris@49 2024 {
Chris@49 2025
Chris@49 2026 // These may be necessary to store the error handler (if we need to).
Chris@49 2027 herr_t (*old_func)(hid_t, void*);
Chris@49 2028 void *old_client_data;
Chris@49 2029
Chris@49 2030 #if !defined(ARMA_PRINT_HDF5_ERRORS)
Chris@49 2031 {
Chris@49 2032 // Save old error handler.
Chris@49 2033 H5Eget_auto(H5E_DEFAULT, &old_func, &old_client_data);
Chris@49 2034
Chris@49 2035 // Disable annoying HDF5 error messages.
Chris@49 2036 H5Eset_auto(H5E_DEFAULT, NULL, NULL);
Chris@49 2037 }
Chris@49 2038 #endif
Chris@49 2039
Chris@49 2040 bool load_okay = false;
Chris@49 2041
Chris@49 2042 hid_t fid = H5Fopen(name.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
Chris@49 2043
Chris@49 2044 if(fid >= 0)
Chris@49 2045 {
Chris@49 2046 // MATLAB HDF5 dataset names are user-specified;
Chris@49 2047 // Octave tends to store the datasets in a group, with the actual dataset being referred to as "value".
Chris@49 2048 // So we will search for "dataset" and "value", and if those are not found we will take the first dataset we do find.
Chris@49 2049 std::vector<std::string> searchNames;
Chris@49 2050 searchNames.push_back("dataset");
Chris@49 2051 searchNames.push_back("value");
Chris@49 2052
Chris@49 2053 hid_t dataset = hdf5_misc::search_hdf5_file(searchNames, fid, 2, false);
Chris@49 2054
Chris@49 2055 if(dataset >= 0)
Chris@49 2056 {
Chris@49 2057 hid_t filespace = H5Dget_space(dataset);
Chris@49 2058
Chris@49 2059 // This must be <= 2 due to our search rules.
Chris@49 2060 const int ndims = H5Sget_simple_extent_ndims(filespace);
Chris@49 2061
Chris@49 2062 hsize_t dims[2];
Chris@49 2063 const herr_t query_status = H5Sget_simple_extent_dims(filespace, dims, NULL);
Chris@49 2064
Chris@49 2065 // arma_check(query_status < 0, "Mat::load(): cannot get size of HDF5 dataset");
Chris@49 2066 if(query_status < 0)
Chris@49 2067 {
Chris@49 2068 err_msg = "cannot get size of HDF5 dataset in ";
Chris@49 2069
Chris@49 2070 H5Sclose(filespace);
Chris@49 2071 H5Dclose(dataset);
Chris@49 2072 H5Fclose(fid);
Chris@49 2073
Chris@49 2074 #if !defined(ARMA_PRINT_HDF5_ERRORS)
Chris@49 2075 {
Chris@49 2076 // Restore HDF5 error handler.
Chris@49 2077 H5Eset_auto(H5E_DEFAULT, old_func, old_client_data);
Chris@49 2078 }
Chris@49 2079 #endif
Chris@49 2080
Chris@49 2081 return false;
Chris@49 2082 }
Chris@49 2083
Chris@49 2084 if(ndims == 1) { dims[1] = 1; } // Vector case; fake second dimension (one column).
Chris@49 2085
Chris@49 2086 x.set_size(dims[1], dims[0]);
Chris@49 2087
Chris@49 2088 // Now we have to see what type is stored to figure out how to load it.
Chris@49 2089 hid_t datatype = H5Dget_type(dataset);
Chris@49 2090 hid_t mat_type = hdf5_misc::get_hdf5_type<eT>();
Chris@49 2091
Chris@49 2092 // If these are the same type, it is simple.
Chris@49 2093 if(H5Tequal(datatype, mat_type) > 0)
Chris@49 2094 {
Chris@49 2095 // Load directly; H5S_ALL used so that we load the entire dataset.
Chris@49 2096 hid_t read_status = H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, void_ptr(x.memptr()));
Chris@49 2097
Chris@49 2098 if(read_status >= 0) { load_okay = true; }
Chris@49 2099 }
Chris@49 2100 else
Chris@49 2101 {
Chris@49 2102 // Load into another array and convert its type accordingly.
Chris@49 2103 hid_t read_status = hdf5_misc::load_and_convert_hdf5(x.memptr(), dataset, datatype, x.n_elem);
Chris@49 2104
Chris@49 2105 if(read_status >= 0) { load_okay = true; }
Chris@49 2106 }
Chris@49 2107
Chris@49 2108 // Now clean up.
Chris@49 2109 H5Tclose(datatype);
Chris@49 2110 H5Tclose(mat_type);
Chris@49 2111 H5Sclose(filespace);
Chris@49 2112 }
Chris@49 2113
Chris@49 2114 H5Dclose(dataset);
Chris@49 2115
Chris@49 2116 H5Fclose(fid);
Chris@49 2117
Chris@49 2118 if(load_okay == false)
Chris@49 2119 {
Chris@49 2120 err_msg = "unsupported or incorrect HDF5 data in ";
Chris@49 2121 }
Chris@49 2122 }
Chris@49 2123 else
Chris@49 2124 {
Chris@49 2125 err_msg = "cannot open file ";
Chris@49 2126 }
Chris@49 2127
Chris@49 2128 #if !defined(ARMA_PRINT_HDF5_ERRORS)
Chris@49 2129 {
Chris@49 2130 // Restore HDF5 error handler.
Chris@49 2131 H5Eset_auto(H5E_DEFAULT, old_func, old_client_data);
Chris@49 2132 }
Chris@49 2133 #endif
Chris@49 2134
Chris@49 2135 return load_okay;
Chris@49 2136 }
Chris@49 2137 #else
Chris@49 2138 {
Chris@49 2139 arma_ignore(x);
Chris@49 2140 arma_ignore(name);
Chris@49 2141 arma_ignore(err_msg);
Chris@49 2142
Chris@49 2143 arma_stop("Mat::load(): use of HDF5 needs to be enabled");
Chris@49 2144
Chris@49 2145 return false;
Chris@49 2146 }
Chris@49 2147 #endif
Chris@49 2148 }
Chris@49 2149
Chris@49 2150
Chris@49 2151
Chris@49 2152 //! Try to load a matrix by automatically determining its type
Chris@49 2153 template<typename eT>
Chris@49 2154 inline
Chris@49 2155 bool
Chris@49 2156 diskio::load_auto_detect(Mat<eT>& x, const std::string& name, std::string& err_msg)
Chris@49 2157 {
Chris@49 2158 arma_extra_debug_sigprint();
Chris@49 2159
Chris@49 2160 #if defined(ARMA_USE_HDF5)
Chris@49 2161 // We're currently using the C bindings for the HDF5 library, which don't support C++ streams
Chris@49 2162 if( H5Fis_hdf5(name.c_str()) ) { return load_hdf5_binary(x, name, err_msg); }
Chris@49 2163 #endif
Chris@49 2164
Chris@49 2165 std::fstream f;
Chris@49 2166 f.open(name.c_str(), std::fstream::in | std::fstream::binary);
Chris@49 2167
Chris@49 2168 bool load_okay = f.is_open();
Chris@49 2169
Chris@49 2170 if(load_okay == true)
Chris@49 2171 {
Chris@49 2172 load_okay = diskio::load_auto_detect(x, f, err_msg);
Chris@49 2173 f.close();
Chris@49 2174 }
Chris@49 2175
Chris@49 2176 return load_okay;
Chris@49 2177 }
Chris@49 2178
Chris@49 2179
Chris@49 2180
Chris@49 2181 //! Try to load a matrix by automatically determining its type
Chris@49 2182 template<typename eT>
Chris@49 2183 inline
Chris@49 2184 bool
Chris@49 2185 diskio::load_auto_detect(Mat<eT>& x, std::istream& f, std::string& err_msg)
Chris@49 2186 {
Chris@49 2187 arma_extra_debug_sigprint();
Chris@49 2188
Chris@49 2189 static const std::string ARMA_MAT_TXT = "ARMA_MAT_TXT";
Chris@49 2190 static const std::string ARMA_MAT_BIN = "ARMA_MAT_BIN";
Chris@49 2191 static const std::string P5 = "P5";
Chris@49 2192
Chris@49 2193 podarray<char> raw_header(ARMA_MAT_TXT.length() + 1);
Chris@49 2194
Chris@49 2195 std::streampos pos = f.tellg();
Chris@49 2196
Chris@49 2197 f.read( raw_header.memptr(), std::streamsize(ARMA_MAT_TXT.length()) );
Chris@49 2198 raw_header[ARMA_MAT_TXT.length()] = '\0';
Chris@49 2199
Chris@49 2200 f.clear();
Chris@49 2201 f.seekg(pos);
Chris@49 2202
Chris@49 2203 const std::string header = raw_header.mem;
Chris@49 2204
Chris@49 2205 if(ARMA_MAT_TXT == header.substr(0,ARMA_MAT_TXT.length()))
Chris@49 2206 {
Chris@49 2207 return load_arma_ascii(x, f, err_msg);
Chris@49 2208 }
Chris@49 2209 else
Chris@49 2210 if(ARMA_MAT_BIN == header.substr(0,ARMA_MAT_BIN.length()))
Chris@49 2211 {
Chris@49 2212 return load_arma_binary(x, f, err_msg);
Chris@49 2213 }
Chris@49 2214 else
Chris@49 2215 if(P5 == header.substr(0,P5.length()))
Chris@49 2216 {
Chris@49 2217 return load_pgm_binary(x, f, err_msg);
Chris@49 2218 }
Chris@49 2219 else
Chris@49 2220 {
Chris@49 2221 const file_type ft = guess_file_type(f);
Chris@49 2222
Chris@49 2223 switch(ft)
Chris@49 2224 {
Chris@49 2225 case csv_ascii:
Chris@49 2226 return load_csv_ascii(x, f, err_msg);
Chris@49 2227 break;
Chris@49 2228
Chris@49 2229 case raw_binary:
Chris@49 2230 return load_raw_binary(x, f, err_msg);
Chris@49 2231 break;
Chris@49 2232
Chris@49 2233 case raw_ascii:
Chris@49 2234 return load_raw_ascii(x, f, err_msg);
Chris@49 2235 break;
Chris@49 2236
Chris@49 2237 default:
Chris@49 2238 err_msg = "unknown data in ";
Chris@49 2239 return false;
Chris@49 2240 }
Chris@49 2241 }
Chris@49 2242
Chris@49 2243 return false;
Chris@49 2244 }
Chris@49 2245
Chris@49 2246
Chris@49 2247
Chris@49 2248 //
Chris@49 2249 // sparse matrices
Chris@49 2250 //
Chris@49 2251
Chris@49 2252
Chris@49 2253
Chris@49 2254 //! Save a matrix in ASCII coord format
Chris@49 2255 template<typename eT>
Chris@49 2256 inline
Chris@49 2257 bool
Chris@49 2258 diskio::save_coord_ascii(const SpMat<eT>& x, const std::string& final_name)
Chris@49 2259 {
Chris@49 2260 arma_extra_debug_sigprint();
Chris@49 2261
Chris@49 2262 const std::string tmp_name = diskio::gen_tmp_name(final_name);
Chris@49 2263
Chris@49 2264 std::ofstream f(tmp_name.c_str());
Chris@49 2265
Chris@49 2266 bool save_okay = f.is_open();
Chris@49 2267
Chris@49 2268 if(save_okay == true)
Chris@49 2269 {
Chris@49 2270 save_okay = diskio::save_coord_ascii(x, f);
Chris@49 2271
Chris@49 2272 f.flush();
Chris@49 2273 f.close();
Chris@49 2274
Chris@49 2275 if(save_okay == true)
Chris@49 2276 {
Chris@49 2277 save_okay = diskio::safe_rename(tmp_name, final_name);
Chris@49 2278 }
Chris@49 2279 }
Chris@49 2280
Chris@49 2281 return save_okay;
Chris@49 2282 }
Chris@49 2283
Chris@49 2284
Chris@49 2285
Chris@49 2286 //! Save a matrix in ASCII coord format
Chris@49 2287 template<typename eT>
Chris@49 2288 inline
Chris@49 2289 bool
Chris@49 2290 diskio::save_coord_ascii(const SpMat<eT>& x, std::ostream& f)
Chris@49 2291 {
Chris@49 2292 arma_extra_debug_sigprint();
Chris@49 2293
Chris@49 2294 const ios::fmtflags orig_flags = f.flags();
Chris@49 2295
Chris@49 2296 typename SpMat<eT>::const_iterator iter = x.begin();
Chris@49 2297 typename SpMat<eT>::const_iterator iter_end = x.end();
Chris@49 2298
Chris@49 2299 for(; iter != iter_end; ++iter)
Chris@49 2300 {
Chris@49 2301 f.setf(ios::fixed);
Chris@49 2302
Chris@49 2303 f << iter.row() << ' ' << iter.col() << ' ';
Chris@49 2304
Chris@49 2305 if( (is_float<eT>::value == true) || (is_double<eT>::value == true) )
Chris@49 2306 {
Chris@49 2307 f.setf(ios::scientific);
Chris@49 2308 f.precision(12);
Chris@49 2309 }
Chris@49 2310
Chris@49 2311 f << (*iter) << '\n';
Chris@49 2312 }
Chris@49 2313
Chris@49 2314
Chris@49 2315 // make sure it's possible to figure out the matrix size later
Chris@49 2316 if( (x.n_rows > 0) && (x.n_cols > 0) )
Chris@49 2317 {
Chris@49 2318 const uword max_row = (x.n_rows > 0) ? x.n_rows-1 : 0;
Chris@49 2319 const uword max_col = (x.n_cols > 0) ? x.n_cols-1 : 0;
Chris@49 2320
Chris@49 2321 if( x.at(max_row, max_col) == eT(0) )
Chris@49 2322 {
Chris@49 2323 f.setf(ios::fixed);
Chris@49 2324
Chris@49 2325 f << max_row << ' ' << max_col << " 0\n";
Chris@49 2326 }
Chris@49 2327 }
Chris@49 2328
Chris@49 2329 const bool save_okay = f.good();
Chris@49 2330
Chris@49 2331 f.flags(orig_flags);
Chris@49 2332
Chris@49 2333 return save_okay;
Chris@49 2334 }
Chris@49 2335
Chris@49 2336
Chris@49 2337
Chris@49 2338 //! Save a matrix in ASCII coord format (complex numbers)
Chris@49 2339 template<typename T>
Chris@49 2340 inline
Chris@49 2341 bool
Chris@49 2342 diskio::save_coord_ascii(const SpMat< std::complex<T> >& x, std::ostream& f)
Chris@49 2343 {
Chris@49 2344 arma_extra_debug_sigprint();
Chris@49 2345
Chris@49 2346 const ios::fmtflags orig_flags = f.flags();
Chris@49 2347
Chris@49 2348 typedef typename std::complex<T> eT;
Chris@49 2349
Chris@49 2350 typename SpMat<eT>::const_iterator iter = x.begin();
Chris@49 2351 typename SpMat<eT>::const_iterator iter_end = x.end();
Chris@49 2352
Chris@49 2353 for(; iter != iter_end; ++iter)
Chris@49 2354 {
Chris@49 2355 f.setf(ios::fixed);
Chris@49 2356
Chris@49 2357 f << iter.row() << ' ' << iter.col() << ' ';
Chris@49 2358
Chris@49 2359 if( (is_float<T>::value == true) || (is_double<T>::value == true) )
Chris@49 2360 {
Chris@49 2361 f.setf(ios::scientific);
Chris@49 2362 f.precision(12);
Chris@49 2363 }
Chris@49 2364
Chris@49 2365 const eT val = (*iter);
Chris@49 2366
Chris@49 2367 f << val.real() << ' ' << val.imag() << '\n';
Chris@49 2368 }
Chris@49 2369
Chris@49 2370 // make sure it's possible to figure out the matrix size later
Chris@49 2371 if( (x.n_rows > 0) && (x.n_cols > 0) )
Chris@49 2372 {
Chris@49 2373 const uword max_row = (x.n_rows > 0) ? x.n_rows-1 : 0;
Chris@49 2374 const uword max_col = (x.n_cols > 0) ? x.n_cols-1 : 0;
Chris@49 2375
Chris@49 2376 if( x.at(max_row, max_col) == eT(0) )
Chris@49 2377 {
Chris@49 2378 f.setf(ios::fixed);
Chris@49 2379
Chris@49 2380 f << max_row << ' ' << max_col << " 0 0\n";
Chris@49 2381 }
Chris@49 2382 }
Chris@49 2383
Chris@49 2384 const bool save_okay = f.good();
Chris@49 2385
Chris@49 2386 f.flags(orig_flags);
Chris@49 2387
Chris@49 2388 return save_okay;
Chris@49 2389 }
Chris@49 2390
Chris@49 2391
Chris@49 2392
Chris@49 2393 //! Save a matrix in binary format,
Chris@49 2394 //! with a header that stores the matrix type as well as its dimensions
Chris@49 2395 template<typename eT>
Chris@49 2396 inline
Chris@49 2397 bool
Chris@49 2398 diskio::save_arma_binary(const SpMat<eT>& x, const std::string& final_name)
Chris@49 2399 {
Chris@49 2400 arma_extra_debug_sigprint();
Chris@49 2401
Chris@49 2402 const std::string tmp_name = diskio::gen_tmp_name(final_name);
Chris@49 2403
Chris@49 2404 std::ofstream f(tmp_name.c_str(), std::fstream::binary);
Chris@49 2405
Chris@49 2406 bool save_okay = f.is_open();
Chris@49 2407
Chris@49 2408 if(save_okay == true)
Chris@49 2409 {
Chris@49 2410 save_okay = diskio::save_arma_binary(x, f);
Chris@49 2411
Chris@49 2412 f.flush();
Chris@49 2413 f.close();
Chris@49 2414
Chris@49 2415 if(save_okay == true)
Chris@49 2416 {
Chris@49 2417 save_okay = diskio::safe_rename(tmp_name, final_name);
Chris@49 2418 }
Chris@49 2419 }
Chris@49 2420
Chris@49 2421 return save_okay;
Chris@49 2422 }
Chris@49 2423
Chris@49 2424
Chris@49 2425
Chris@49 2426 //! Save a matrix in binary format,
Chris@49 2427 //! with a header that stores the matrix type as well as its dimensions
Chris@49 2428 template<typename eT>
Chris@49 2429 inline
Chris@49 2430 bool
Chris@49 2431 diskio::save_arma_binary(const SpMat<eT>& x, std::ostream& f)
Chris@49 2432 {
Chris@49 2433 arma_extra_debug_sigprint();
Chris@49 2434
Chris@49 2435 f << diskio::gen_bin_header(x) << '\n';
Chris@49 2436 f << x.n_rows << ' ' << x.n_cols << ' ' << x.n_nonzero << '\n';
Chris@49 2437
Chris@49 2438 f.write( reinterpret_cast<const char*>(x.values), std::streamsize(x.n_nonzero*sizeof(eT)) );
Chris@49 2439 f.write( reinterpret_cast<const char*>(x.row_indices), std::streamsize(x.n_nonzero*sizeof(uword)) );
Chris@49 2440 f.write( reinterpret_cast<const char*>(x.col_ptrs), std::streamsize((x.n_cols+1)*sizeof(uword)) );
Chris@49 2441
Chris@49 2442 return f.good();
Chris@49 2443 }
Chris@49 2444
Chris@49 2445
Chris@49 2446
Chris@49 2447 template<typename eT>
Chris@49 2448 inline
Chris@49 2449 bool
Chris@49 2450 diskio::load_coord_ascii(SpMat<eT>& x, const std::string& name, std::string& err_msg)
Chris@49 2451 {
Chris@49 2452 arma_extra_debug_sigprint();
Chris@49 2453
Chris@49 2454 std::fstream f;
Chris@49 2455 f.open(name.c_str(), std::fstream::in | std::fstream::binary);
Chris@49 2456
Chris@49 2457 bool load_okay = f.is_open();
Chris@49 2458
Chris@49 2459 if(load_okay == true)
Chris@49 2460 {
Chris@49 2461 load_okay = diskio::load_coord_ascii(x, f, err_msg);
Chris@49 2462 f.close();
Chris@49 2463 }
Chris@49 2464
Chris@49 2465 return load_okay;
Chris@49 2466 }
Chris@49 2467
Chris@49 2468
Chris@49 2469
Chris@49 2470 template<typename eT>
Chris@49 2471 inline
Chris@49 2472 bool
Chris@49 2473 diskio::load_coord_ascii(SpMat<eT>& x, std::istream& f, std::string& err_msg)
Chris@49 2474 {
Chris@49 2475 bool load_okay = f.good();
Chris@49 2476
Chris@49 2477 f.clear();
Chris@49 2478 const std::fstream::pos_type pos1 = f.tellg();
Chris@49 2479
Chris@49 2480 //
Chris@49 2481 // work out the size
Chris@49 2482
Chris@49 2483 uword f_n_rows = 0;
Chris@49 2484 uword f_n_cols = 0;
Chris@49 2485 uword f_n_nz = 0;
Chris@49 2486
Chris@49 2487 bool size_found = false;
Chris@49 2488
Chris@49 2489 std::string line_string;
Chris@49 2490 std::string token;
Chris@49 2491
Chris@49 2492 std::stringstream line_stream;
Chris@49 2493 std::stringstream ss;
Chris@49 2494
Chris@49 2495 uword last_line_row = 0;
Chris@49 2496 uword last_line_col = 0;
Chris@49 2497
Chris@49 2498 bool first_line = true;
Chris@49 2499 bool weird_format = false;
Chris@49 2500
Chris@49 2501
Chris@49 2502 while( (f.good() == true) && (load_okay == true) )
Chris@49 2503 {
Chris@49 2504 std::getline(f, line_string);
Chris@49 2505
Chris@49 2506 if(line_string.size() == 0)
Chris@49 2507 {
Chris@49 2508 break;
Chris@49 2509 }
Chris@49 2510
Chris@49 2511 line_stream.clear();
Chris@49 2512 line_stream.str(line_string);
Chris@49 2513
Chris@49 2514 uword line_row = 0;
Chris@49 2515 uword line_col = 0;
Chris@49 2516
Chris@49 2517 // a valid line in co-ord format has at least 2 entries
Chris@49 2518
Chris@49 2519 line_stream >> line_row;
Chris@49 2520
Chris@49 2521 if(line_stream.good() == false)
Chris@49 2522 {
Chris@49 2523 load_okay = false;
Chris@49 2524 break;
Chris@49 2525 }
Chris@49 2526
Chris@49 2527 line_stream >> line_col;
Chris@49 2528
Chris@49 2529 size_found = true;
Chris@49 2530
Chris@49 2531 if(f_n_rows < line_row) f_n_rows = line_row;
Chris@49 2532 if(f_n_cols < line_col) f_n_cols = line_col;
Chris@49 2533
Chris@49 2534 if(first_line == true)
Chris@49 2535 {
Chris@49 2536 first_line = false;
Chris@49 2537 }
Chris@49 2538 else
Chris@49 2539 {
Chris@49 2540 if( (line_col < last_line_col) || ((line_row <= last_line_row) && (line_col <= last_line_col)) )
Chris@49 2541 {
Chris@49 2542 weird_format = true;
Chris@49 2543 }
Chris@49 2544 }
Chris@49 2545
Chris@49 2546 last_line_row = line_row;
Chris@49 2547 last_line_col = line_col;
Chris@49 2548
Chris@49 2549
Chris@49 2550 if(line_stream.good() == true)
Chris@49 2551 {
Chris@49 2552 eT final_val = eT(0);
Chris@49 2553
Chris@49 2554 line_stream >> token;
Chris@49 2555
Chris@49 2556 if(line_stream.fail() == false)
Chris@49 2557 {
Chris@49 2558 eT val = eT(0);
Chris@49 2559
Chris@49 2560 ss.clear();
Chris@49 2561 ss.str(token);
Chris@49 2562
Chris@49 2563 ss >> val;
Chris@49 2564
Chris@49 2565 if(ss.fail() == false)
Chris@49 2566 {
Chris@49 2567 final_val = val;
Chris@49 2568 }
Chris@49 2569 else
Chris@49 2570 {
Chris@49 2571 val = eT(0);
Chris@49 2572
Chris@49 2573 const bool success = diskio::convert_naninf( val, token );
Chris@49 2574
Chris@49 2575 if(success == true)
Chris@49 2576 {
Chris@49 2577 final_val = val;
Chris@49 2578 }
Chris@49 2579 }
Chris@49 2580 }
Chris@49 2581
Chris@49 2582 if(final_val != eT(0))
Chris@49 2583 {
Chris@49 2584 ++f_n_nz;
Chris@49 2585 }
Chris@49 2586 }
Chris@49 2587 }
Chris@49 2588
Chris@49 2589
Chris@49 2590 if(size_found == true)
Chris@49 2591 {
Chris@49 2592 // take into account that indices start at 0
Chris@49 2593 f_n_rows++;
Chris@49 2594 f_n_cols++;
Chris@49 2595 }
Chris@49 2596
Chris@49 2597
Chris@49 2598 if(load_okay == true)
Chris@49 2599 {
Chris@49 2600 f.clear();
Chris@49 2601 f.seekg(pos1);
Chris@49 2602
Chris@49 2603 x.set_size(f_n_rows, f_n_cols);
Chris@49 2604
Chris@49 2605 if(weird_format == false)
Chris@49 2606 {
Chris@49 2607 x.mem_resize(f_n_nz);
Chris@49 2608 }
Chris@49 2609
Chris@49 2610 uword pos = 0;
Chris@49 2611
Chris@49 2612 while(f.good() == true)
Chris@49 2613 {
Chris@49 2614 std::getline(f, line_string);
Chris@49 2615
Chris@49 2616 if(line_string.size() == 0)
Chris@49 2617 {
Chris@49 2618 break;
Chris@49 2619 }
Chris@49 2620
Chris@49 2621 line_stream.clear();
Chris@49 2622 line_stream.str(line_string);
Chris@49 2623
Chris@49 2624 uword line_row = 0;
Chris@49 2625 uword line_col = 0;
Chris@49 2626
Chris@49 2627 line_stream >> line_row;
Chris@49 2628 line_stream >> line_col;
Chris@49 2629
Chris@49 2630 eT final_val = eT(0);
Chris@49 2631
Chris@49 2632 line_stream >> token;
Chris@49 2633
Chris@49 2634 if(line_stream.fail() == false)
Chris@49 2635 {
Chris@49 2636 eT val = eT(0);
Chris@49 2637
Chris@49 2638 ss.clear();
Chris@49 2639 ss.str(token);
Chris@49 2640
Chris@49 2641 ss >> val;
Chris@49 2642
Chris@49 2643 if(ss.fail() == false)
Chris@49 2644 {
Chris@49 2645 final_val = val;
Chris@49 2646 }
Chris@49 2647 else
Chris@49 2648 {
Chris@49 2649 val = eT(0);
Chris@49 2650
Chris@49 2651 const bool success = diskio::convert_naninf( val, token );
Chris@49 2652
Chris@49 2653 if(success == true)
Chris@49 2654 {
Chris@49 2655 final_val = val;
Chris@49 2656 }
Chris@49 2657 }
Chris@49 2658 }
Chris@49 2659
Chris@49 2660
Chris@49 2661 if(final_val != eT(0))
Chris@49 2662 {
Chris@49 2663 if(weird_format == false)
Chris@49 2664 {
Chris@49 2665 access::rw(x.row_indices[pos]) = line_row;
Chris@49 2666 access::rw(x.values[pos]) = final_val;
Chris@49 2667 ++access::rw(x.col_ptrs[line_col + 1]);
Chris@49 2668
Chris@49 2669 ++pos;
Chris@49 2670 }
Chris@49 2671 else
Chris@49 2672 {
Chris@49 2673 x.at(line_row,line_col) = final_val;
Chris@49 2674 }
Chris@49 2675 }
Chris@49 2676 }
Chris@49 2677
Chris@49 2678 if(weird_format == false)
Chris@49 2679 {
Chris@49 2680 for(uword c = 1; c <= f_n_cols; ++c)
Chris@49 2681 {
Chris@49 2682 access::rw(x.col_ptrs[c]) += x.col_ptrs[c - 1];
Chris@49 2683 }
Chris@49 2684 }
Chris@49 2685 }
Chris@49 2686
Chris@49 2687 return load_okay;
Chris@49 2688 }
Chris@49 2689
Chris@49 2690
Chris@49 2691
Chris@49 2692 template<typename T>
Chris@49 2693 inline
Chris@49 2694 bool
Chris@49 2695 diskio::load_coord_ascii(SpMat< std::complex<T> >& x, std::istream& f, std::string& err_msg)
Chris@49 2696 {
Chris@49 2697 bool load_okay = f.good();
Chris@49 2698
Chris@49 2699 f.clear();
Chris@49 2700 const std::fstream::pos_type pos1 = f.tellg();
Chris@49 2701
Chris@49 2702 //
Chris@49 2703 // work out the size
Chris@49 2704
Chris@49 2705 uword f_n_rows = 0;
Chris@49 2706 uword f_n_cols = 0;
Chris@49 2707 uword f_n_nz = 0;
Chris@49 2708
Chris@49 2709 bool size_found = false;
Chris@49 2710
Chris@49 2711 std::string line_string;
Chris@49 2712 std::string token_real;
Chris@49 2713 std::string token_imag;
Chris@49 2714
Chris@49 2715 std::stringstream line_stream;
Chris@49 2716 std::stringstream ss;
Chris@49 2717
Chris@49 2718 uword last_line_row = 0;
Chris@49 2719 uword last_line_col = 0;
Chris@49 2720
Chris@49 2721 bool first_line = true;
Chris@49 2722 bool weird_format = false;
Chris@49 2723
Chris@49 2724 while( (f.good() == true) && (load_okay == true) )
Chris@49 2725 {
Chris@49 2726 std::getline(f, line_string);
Chris@49 2727
Chris@49 2728 if(line_string.size() == 0)
Chris@49 2729 {
Chris@49 2730 break;
Chris@49 2731 }
Chris@49 2732
Chris@49 2733 line_stream.clear();
Chris@49 2734 line_stream.str(line_string);
Chris@49 2735
Chris@49 2736 uword line_row = 0;
Chris@49 2737 uword line_col = 0;
Chris@49 2738
Chris@49 2739 // a valid line in co-ord format has at least 2 entries
Chris@49 2740
Chris@49 2741 line_stream >> line_row;
Chris@49 2742
Chris@49 2743 if(line_stream.good() == false)
Chris@49 2744 {
Chris@49 2745 load_okay = false;
Chris@49 2746 break;
Chris@49 2747 }
Chris@49 2748
Chris@49 2749 line_stream >> line_col;
Chris@49 2750
Chris@49 2751 size_found = true;
Chris@49 2752
Chris@49 2753 if(f_n_rows < line_row) f_n_rows = line_row;
Chris@49 2754 if(f_n_cols < line_col) f_n_cols = line_col;
Chris@49 2755
Chris@49 2756
Chris@49 2757 if(first_line == true)
Chris@49 2758 {
Chris@49 2759 first_line = false;
Chris@49 2760 }
Chris@49 2761 else
Chris@49 2762 {
Chris@49 2763 if( (line_col < last_line_col) || ((line_row <= last_line_row) && (line_col <= last_line_col)) )
Chris@49 2764 {
Chris@49 2765 weird_format = true;
Chris@49 2766 }
Chris@49 2767 }
Chris@49 2768
Chris@49 2769 last_line_row = line_row;
Chris@49 2770 last_line_col = line_col;
Chris@49 2771
Chris@49 2772
Chris@49 2773 if(line_stream.good() == true)
Chris@49 2774 {
Chris@49 2775 T final_val_real = T(0);
Chris@49 2776 T final_val_imag = T(0);
Chris@49 2777
Chris@49 2778
Chris@49 2779 line_stream >> token_real;
Chris@49 2780
Chris@49 2781 if(line_stream.fail() == false)
Chris@49 2782 {
Chris@49 2783 T val_real = T(0);
Chris@49 2784
Chris@49 2785 ss.clear();
Chris@49 2786 ss.str(token_real);
Chris@49 2787
Chris@49 2788 ss >> val_real;
Chris@49 2789
Chris@49 2790 if(ss.fail() == false)
Chris@49 2791 {
Chris@49 2792 final_val_real = val_real;
Chris@49 2793 }
Chris@49 2794 else
Chris@49 2795 {
Chris@49 2796 val_real = T(0);
Chris@49 2797
Chris@49 2798 const bool success = diskio::convert_naninf( val_real, token_real );
Chris@49 2799
Chris@49 2800 if(success == true)
Chris@49 2801 {
Chris@49 2802 final_val_real = val_real;
Chris@49 2803 }
Chris@49 2804 }
Chris@49 2805 }
Chris@49 2806
Chris@49 2807
Chris@49 2808 line_stream >> token_imag;
Chris@49 2809
Chris@49 2810 if(line_stream.fail() == false)
Chris@49 2811 {
Chris@49 2812 T val_imag = T(0);
Chris@49 2813
Chris@49 2814 ss.clear();
Chris@49 2815 ss.str(token_imag);
Chris@49 2816
Chris@49 2817 ss >> val_imag;
Chris@49 2818
Chris@49 2819 if(ss.fail() == false)
Chris@49 2820 {
Chris@49 2821 final_val_imag = val_imag;
Chris@49 2822 }
Chris@49 2823 else
Chris@49 2824 {
Chris@49 2825 val_imag = T(0);
Chris@49 2826
Chris@49 2827 const bool success = diskio::convert_naninf( val_imag, token_imag );
Chris@49 2828
Chris@49 2829 if(success == true)
Chris@49 2830 {
Chris@49 2831 final_val_imag = val_imag;
Chris@49 2832 }
Chris@49 2833 }
Chris@49 2834 }
Chris@49 2835
Chris@49 2836
Chris@49 2837 if( (final_val_real != T(0)) || (final_val_imag != T(0)) )
Chris@49 2838 {
Chris@49 2839 ++f_n_nz;
Chris@49 2840 }
Chris@49 2841 }
Chris@49 2842 }
Chris@49 2843
Chris@49 2844
Chris@49 2845 if(size_found == true)
Chris@49 2846 {
Chris@49 2847 // take into account that indices start at 0
Chris@49 2848 f_n_rows++;
Chris@49 2849 f_n_cols++;
Chris@49 2850 }
Chris@49 2851
Chris@49 2852
Chris@49 2853 if(load_okay == true)
Chris@49 2854 {
Chris@49 2855 f.clear();
Chris@49 2856 f.seekg(pos1);
Chris@49 2857
Chris@49 2858 x.set_size(f_n_rows, f_n_cols);
Chris@49 2859
Chris@49 2860 if(weird_format == false)
Chris@49 2861 {
Chris@49 2862 x.mem_resize(f_n_nz);
Chris@49 2863 }
Chris@49 2864
Chris@49 2865 uword pos = 0;
Chris@49 2866
Chris@49 2867 while(f.good() == true)
Chris@49 2868 {
Chris@49 2869 std::getline(f, line_string);
Chris@49 2870
Chris@49 2871 if(line_string.size() == 0)
Chris@49 2872 {
Chris@49 2873 break;
Chris@49 2874 }
Chris@49 2875
Chris@49 2876 line_stream.clear();
Chris@49 2877 line_stream.str(line_string);
Chris@49 2878
Chris@49 2879 uword line_row = 0;
Chris@49 2880 uword line_col = 0;
Chris@49 2881
Chris@49 2882 line_stream >> line_row;
Chris@49 2883 line_stream >> line_col;
Chris@49 2884
Chris@49 2885 T final_val_real = T(0);
Chris@49 2886 T final_val_imag = T(0);
Chris@49 2887
Chris@49 2888
Chris@49 2889 line_stream >> token_real;
Chris@49 2890
Chris@49 2891 if(line_stream.fail() == false)
Chris@49 2892 {
Chris@49 2893 T val_real = T(0);
Chris@49 2894
Chris@49 2895 ss.clear();
Chris@49 2896 ss.str(token_real);
Chris@49 2897
Chris@49 2898 ss >> val_real;
Chris@49 2899
Chris@49 2900 if(ss.fail() == false)
Chris@49 2901 {
Chris@49 2902 final_val_real = val_real;
Chris@49 2903 }
Chris@49 2904 else
Chris@49 2905 {
Chris@49 2906 val_real = T(0);
Chris@49 2907
Chris@49 2908 const bool success = diskio::convert_naninf( val_real, token_real );
Chris@49 2909
Chris@49 2910 if(success == true)
Chris@49 2911 {
Chris@49 2912 final_val_real = val_real;
Chris@49 2913 }
Chris@49 2914 }
Chris@49 2915 }
Chris@49 2916
Chris@49 2917
Chris@49 2918 line_stream >> token_imag;
Chris@49 2919
Chris@49 2920 if(line_stream.fail() == false)
Chris@49 2921 {
Chris@49 2922 T val_imag = T(0);
Chris@49 2923
Chris@49 2924 ss.clear();
Chris@49 2925 ss.str(token_imag);
Chris@49 2926
Chris@49 2927 ss >> val_imag;
Chris@49 2928
Chris@49 2929 if(ss.fail() == false)
Chris@49 2930 {
Chris@49 2931 final_val_imag = val_imag;
Chris@49 2932 }
Chris@49 2933 else
Chris@49 2934 {
Chris@49 2935 val_imag = T(0);
Chris@49 2936
Chris@49 2937 const bool success = diskio::convert_naninf( val_imag, token_imag );
Chris@49 2938
Chris@49 2939 if(success == true)
Chris@49 2940 {
Chris@49 2941 final_val_imag = val_imag;
Chris@49 2942 }
Chris@49 2943 }
Chris@49 2944 }
Chris@49 2945
Chris@49 2946
Chris@49 2947 if( (final_val_real != T(0)) || (final_val_imag != T(0)) )
Chris@49 2948 {
Chris@49 2949 if(weird_format == false)
Chris@49 2950 {
Chris@49 2951 access::rw(x.row_indices[pos]) = line_row;
Chris@49 2952 access::rw(x.values[pos]) = std::complex<T>(final_val_real, final_val_imag);
Chris@49 2953 ++access::rw(x.col_ptrs[line_col + 1]);
Chris@49 2954
Chris@49 2955 ++pos;
Chris@49 2956 }
Chris@49 2957 else
Chris@49 2958 {
Chris@49 2959 x.at(line_row,line_col) = std::complex<T>(final_val_real, final_val_imag);
Chris@49 2960 }
Chris@49 2961 }
Chris@49 2962 }
Chris@49 2963
Chris@49 2964
Chris@49 2965 if(weird_format == false)
Chris@49 2966 {
Chris@49 2967 for(uword c = 1; c <= f_n_cols; ++c)
Chris@49 2968 {
Chris@49 2969 access::rw(x.col_ptrs[c]) += x.col_ptrs[c - 1];
Chris@49 2970 }
Chris@49 2971 }
Chris@49 2972 }
Chris@49 2973
Chris@49 2974 return load_okay;
Chris@49 2975 }
Chris@49 2976
Chris@49 2977
Chris@49 2978
Chris@49 2979 //! Load a matrix in binary format,
Chris@49 2980 //! with a header that indicates the matrix type as well as its dimensions
Chris@49 2981 template<typename eT>
Chris@49 2982 inline
Chris@49 2983 bool
Chris@49 2984 diskio::load_arma_binary(SpMat<eT>& x, const std::string& name, std::string& err_msg)
Chris@49 2985 {
Chris@49 2986 arma_extra_debug_sigprint();
Chris@49 2987
Chris@49 2988 std::ifstream f;
Chris@49 2989 f.open(name.c_str(), std::fstream::binary);
Chris@49 2990
Chris@49 2991 bool load_okay = f.is_open();
Chris@49 2992
Chris@49 2993 if(load_okay == true)
Chris@49 2994 {
Chris@49 2995 load_okay = diskio::load_arma_binary(x, f, err_msg);
Chris@49 2996 f.close();
Chris@49 2997 }
Chris@49 2998
Chris@49 2999 return load_okay;
Chris@49 3000 }
Chris@49 3001
Chris@49 3002
Chris@49 3003
Chris@49 3004 template<typename eT>
Chris@49 3005 inline
Chris@49 3006 bool
Chris@49 3007 diskio::load_arma_binary(SpMat<eT>& x, std::istream& f, std::string& err_msg)
Chris@49 3008 {
Chris@49 3009 arma_extra_debug_sigprint();
Chris@49 3010
Chris@49 3011 bool load_okay = true;
Chris@49 3012
Chris@49 3013 std::string f_header;
Chris@49 3014
Chris@49 3015 f >> f_header;
Chris@49 3016
Chris@49 3017 if(f_header == diskio::gen_bin_header(x))
Chris@49 3018 {
Chris@49 3019 uword f_n_rows;
Chris@49 3020 uword f_n_cols;
Chris@49 3021 uword f_n_nz;
Chris@49 3022
Chris@49 3023 f >> f_n_rows;
Chris@49 3024 f >> f_n_cols;
Chris@49 3025 f >> f_n_nz;
Chris@49 3026
Chris@49 3027 //f.seekg(1, ios::cur); // NOTE: this may not be portable, as on a Windows machine a newline could be two characters
Chris@49 3028 f.get();
Chris@49 3029
Chris@49 3030 x.set_size(f_n_rows, f_n_cols);
Chris@49 3031
Chris@49 3032 x.mem_resize(f_n_nz);
Chris@49 3033
Chris@49 3034 f.read( reinterpret_cast<char*>(access::rwp(x.values)), std::streamsize(x.n_nonzero*sizeof(eT)) );
Chris@49 3035 f.read( reinterpret_cast<char*>(access::rwp(x.row_indices)), std::streamsize(x.n_nonzero*sizeof(uword)) );
Chris@49 3036 f.read( reinterpret_cast<char*>(access::rwp(x.col_ptrs)), std::streamsize((x.n_cols+1)*sizeof(uword)) );
Chris@49 3037
Chris@49 3038 load_okay = f.good();
Chris@49 3039 }
Chris@49 3040 else
Chris@49 3041 {
Chris@49 3042 load_okay = false;
Chris@49 3043 err_msg = "incorrect header in ";
Chris@49 3044 }
Chris@49 3045
Chris@49 3046 return load_okay;
Chris@49 3047 }
Chris@49 3048
Chris@49 3049
Chris@49 3050
Chris@49 3051 // cubes
Chris@49 3052
Chris@49 3053
Chris@49 3054
Chris@49 3055 //! Save a cube as raw text (no header, human readable).
Chris@49 3056 template<typename eT>
Chris@49 3057 inline
Chris@49 3058 bool
Chris@49 3059 diskio::save_raw_ascii(const Cube<eT>& x, const std::string& final_name)
Chris@49 3060 {
Chris@49 3061 arma_extra_debug_sigprint();
Chris@49 3062
Chris@49 3063 const std::string tmp_name = diskio::gen_tmp_name(final_name);
Chris@49 3064
Chris@49 3065 std::fstream f(tmp_name.c_str(), std::fstream::out);
Chris@49 3066
Chris@49 3067 bool save_okay = f.is_open();
Chris@49 3068
Chris@49 3069 if(save_okay == true)
Chris@49 3070 {
Chris@49 3071 save_okay = save_raw_ascii(x, f);
Chris@49 3072
Chris@49 3073 f.flush();
Chris@49 3074 f.close();
Chris@49 3075
Chris@49 3076 if(save_okay == true)
Chris@49 3077 {
Chris@49 3078 save_okay = diskio::safe_rename(tmp_name, final_name);
Chris@49 3079 }
Chris@49 3080 }
Chris@49 3081
Chris@49 3082 return save_okay;
Chris@49 3083 }
Chris@49 3084
Chris@49 3085
Chris@49 3086
Chris@49 3087 //! Save a cube as raw text (no header, human readable).
Chris@49 3088 template<typename eT>
Chris@49 3089 inline
Chris@49 3090 bool
Chris@49 3091 diskio::save_raw_ascii(const Cube<eT>& x, std::ostream& f)
Chris@49 3092 {
Chris@49 3093 arma_extra_debug_sigprint();
Chris@49 3094
Chris@49 3095 uword cell_width;
Chris@49 3096
Chris@49 3097 // TODO: need sane values for complex numbers
Chris@49 3098
Chris@49 3099 if( (is_float<eT>::value == true) || (is_double<eT>::value == true) )
Chris@49 3100 {
Chris@49 3101 f.setf(ios::scientific);
Chris@49 3102 f.precision(12);
Chris@49 3103 cell_width = 20;
Chris@49 3104 }
Chris@49 3105
Chris@49 3106 for(uword slice=0; slice < x.n_slices; ++slice)
Chris@49 3107 {
Chris@49 3108 for(uword row=0; row < x.n_rows; ++row)
Chris@49 3109 {
Chris@49 3110 for(uword col=0; col < x.n_cols; ++col)
Chris@49 3111 {
Chris@49 3112 f.put(' ');
Chris@49 3113
Chris@49 3114 if( (is_float<eT>::value == true) || (is_double<eT>::value == true) )
Chris@49 3115 {
Chris@49 3116 f.width(cell_width);
Chris@49 3117 }
Chris@49 3118
Chris@49 3119 f << x.at(row,col,slice);
Chris@49 3120 }
Chris@49 3121
Chris@49 3122 f.put('\n');
Chris@49 3123 }
Chris@49 3124 }
Chris@49 3125
Chris@49 3126 return f.good();
Chris@49 3127 }
Chris@49 3128
Chris@49 3129
Chris@49 3130
Chris@49 3131 //! Save a cube as raw binary (no header)
Chris@49 3132 template<typename eT>
Chris@49 3133 inline
Chris@49 3134 bool
Chris@49 3135 diskio::save_raw_binary(const Cube<eT>& x, const std::string& final_name)
Chris@49 3136 {
Chris@49 3137 arma_extra_debug_sigprint();
Chris@49 3138
Chris@49 3139 const std::string tmp_name = diskio::gen_tmp_name(final_name);
Chris@49 3140
Chris@49 3141 std::ofstream f(tmp_name.c_str(), std::fstream::binary);
Chris@49 3142
Chris@49 3143 bool save_okay = f.is_open();
Chris@49 3144
Chris@49 3145 if(save_okay == true)
Chris@49 3146 {
Chris@49 3147 save_okay = diskio::save_raw_binary(x, f);
Chris@49 3148
Chris@49 3149 f.flush();
Chris@49 3150 f.close();
Chris@49 3151
Chris@49 3152 if(save_okay == true)
Chris@49 3153 {
Chris@49 3154 save_okay = diskio::safe_rename(tmp_name, final_name);
Chris@49 3155 }
Chris@49 3156 }
Chris@49 3157
Chris@49 3158 return save_okay;
Chris@49 3159 }
Chris@49 3160
Chris@49 3161
Chris@49 3162
Chris@49 3163 template<typename eT>
Chris@49 3164 inline
Chris@49 3165 bool
Chris@49 3166 diskio::save_raw_binary(const Cube<eT>& x, std::ostream& f)
Chris@49 3167 {
Chris@49 3168 arma_extra_debug_sigprint();
Chris@49 3169
Chris@49 3170 f.write( reinterpret_cast<const char*>(x.mem), std::streamsize(x.n_elem*sizeof(eT)) );
Chris@49 3171
Chris@49 3172 return f.good();
Chris@49 3173 }
Chris@49 3174
Chris@49 3175
Chris@49 3176
Chris@49 3177 //! Save a cube in text format (human readable),
Chris@49 3178 //! with a header that indicates the cube type as well as its dimensions
Chris@49 3179 template<typename eT>
Chris@49 3180 inline
Chris@49 3181 bool
Chris@49 3182 diskio::save_arma_ascii(const Cube<eT>& x, const std::string& final_name)
Chris@49 3183 {
Chris@49 3184 arma_extra_debug_sigprint();
Chris@49 3185
Chris@49 3186 const std::string tmp_name = diskio::gen_tmp_name(final_name);
Chris@49 3187
Chris@49 3188 std::ofstream f(tmp_name.c_str());
Chris@49 3189
Chris@49 3190 bool save_okay = f.is_open();
Chris@49 3191
Chris@49 3192 if(save_okay == true)
Chris@49 3193 {
Chris@49 3194 save_okay = diskio::save_arma_ascii(x, f);
Chris@49 3195
Chris@49 3196 f.flush();
Chris@49 3197 f.close();
Chris@49 3198
Chris@49 3199 if(save_okay == true)
Chris@49 3200 {
Chris@49 3201 save_okay = diskio::safe_rename(tmp_name, final_name);
Chris@49 3202 }
Chris@49 3203 }
Chris@49 3204
Chris@49 3205 return save_okay;
Chris@49 3206 }
Chris@49 3207
Chris@49 3208
Chris@49 3209
Chris@49 3210 //! Save a cube in text format (human readable),
Chris@49 3211 //! with a header that indicates the cube type as well as its dimensions
Chris@49 3212 template<typename eT>
Chris@49 3213 inline
Chris@49 3214 bool
Chris@49 3215 diskio::save_arma_ascii(const Cube<eT>& x, std::ostream& f)
Chris@49 3216 {
Chris@49 3217 arma_extra_debug_sigprint();
Chris@49 3218
Chris@49 3219 const ios::fmtflags orig_flags = f.flags();
Chris@49 3220
Chris@49 3221 f << diskio::gen_txt_header(x) << '\n';
Chris@49 3222 f << x.n_rows << ' ' << x.n_cols << ' ' << x.n_slices << '\n';
Chris@49 3223
Chris@49 3224 uword cell_width;
Chris@49 3225
Chris@49 3226 // TODO: need sane values for complex numbers
Chris@49 3227
Chris@49 3228 if( (is_float<eT>::value == true) || (is_double<eT>::value == true) )
Chris@49 3229 {
Chris@49 3230 f.setf(ios::scientific);
Chris@49 3231 f.precision(12);
Chris@49 3232 cell_width = 20;
Chris@49 3233 }
Chris@49 3234
Chris@49 3235 for(uword slice=0; slice < x.n_slices; ++slice)
Chris@49 3236 {
Chris@49 3237 for(uword row=0; row < x.n_rows; ++row)
Chris@49 3238 {
Chris@49 3239 for(uword col=0; col < x.n_cols; ++col)
Chris@49 3240 {
Chris@49 3241 f.put(' ');
Chris@49 3242
Chris@49 3243 if( (is_float<eT>::value == true) || (is_double<eT>::value == true) )
Chris@49 3244 {
Chris@49 3245 f.width(cell_width);
Chris@49 3246 }
Chris@49 3247
Chris@49 3248 f << x.at(row,col,slice);
Chris@49 3249 }
Chris@49 3250
Chris@49 3251 f.put('\n');
Chris@49 3252 }
Chris@49 3253 }
Chris@49 3254
Chris@49 3255 const bool save_okay = f.good();
Chris@49 3256
Chris@49 3257 f.flags(orig_flags);
Chris@49 3258
Chris@49 3259 return save_okay;
Chris@49 3260 }
Chris@49 3261
Chris@49 3262
Chris@49 3263
Chris@49 3264 //! Save a cube in binary format,
Chris@49 3265 //! with a header that stores the cube type as well as its dimensions
Chris@49 3266 template<typename eT>
Chris@49 3267 inline
Chris@49 3268 bool
Chris@49 3269 diskio::save_arma_binary(const Cube<eT>& x, const std::string& final_name)
Chris@49 3270 {
Chris@49 3271 arma_extra_debug_sigprint();
Chris@49 3272
Chris@49 3273 const std::string tmp_name = diskio::gen_tmp_name(final_name);
Chris@49 3274
Chris@49 3275 std::ofstream f(tmp_name.c_str(), std::fstream::binary);
Chris@49 3276
Chris@49 3277 bool save_okay = f.is_open();
Chris@49 3278
Chris@49 3279 if(save_okay == true)
Chris@49 3280 {
Chris@49 3281 save_okay = diskio::save_arma_binary(x, f);
Chris@49 3282
Chris@49 3283 f.flush();
Chris@49 3284 f.close();
Chris@49 3285
Chris@49 3286 if(save_okay == true)
Chris@49 3287 {
Chris@49 3288 save_okay = diskio::safe_rename(tmp_name, final_name);
Chris@49 3289 }
Chris@49 3290 }
Chris@49 3291
Chris@49 3292 return save_okay;
Chris@49 3293 }
Chris@49 3294
Chris@49 3295
Chris@49 3296
Chris@49 3297 //! Save a cube in binary format,
Chris@49 3298 //! with a header that stores the cube type as well as its dimensions
Chris@49 3299 template<typename eT>
Chris@49 3300 inline
Chris@49 3301 bool
Chris@49 3302 diskio::save_arma_binary(const Cube<eT>& x, std::ostream& f)
Chris@49 3303 {
Chris@49 3304 arma_extra_debug_sigprint();
Chris@49 3305
Chris@49 3306 f << diskio::gen_bin_header(x) << '\n';
Chris@49 3307 f << x.n_rows << ' ' << x.n_cols << ' ' << x.n_slices << '\n';
Chris@49 3308
Chris@49 3309 f.write( reinterpret_cast<const char*>(x.mem), std::streamsize(x.n_elem*sizeof(eT)) );
Chris@49 3310
Chris@49 3311 return f.good();
Chris@49 3312 }
Chris@49 3313
Chris@49 3314
Chris@49 3315
Chris@49 3316 //! Save a cube as part of a HDF5 file
Chris@49 3317 template<typename eT>
Chris@49 3318 inline
Chris@49 3319 bool
Chris@49 3320 diskio::save_hdf5_binary(const Cube<eT>& x, const std::string& final_name)
Chris@49 3321 {
Chris@49 3322 arma_extra_debug_sigprint();
Chris@49 3323
Chris@49 3324 #if defined(ARMA_USE_HDF5)
Chris@49 3325 {
Chris@49 3326 #if !defined(ARMA_PRINT_HDF5_ERRORS)
Chris@49 3327 {
Chris@49 3328 // Disable annoying HDF5 error messages.
Chris@49 3329 H5Eset_auto(H5E_DEFAULT, NULL, NULL);
Chris@49 3330 }
Chris@49 3331 #endif
Chris@49 3332
Chris@49 3333 bool save_okay = false;
Chris@49 3334
Chris@49 3335 const std::string tmp_name = diskio::gen_tmp_name(final_name);
Chris@49 3336
Chris@49 3337 // Set up the file according to HDF5's preferences
Chris@49 3338 hid_t file = H5Fcreate(tmp_name.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
Chris@49 3339
Chris@49 3340 // We need to create a dataset, datatype, and dataspace
Chris@49 3341 hsize_t dims[3];
Chris@49 3342 dims[2] = x.n_rows;
Chris@49 3343 dims[1] = x.n_cols;
Chris@49 3344 dims[0] = x.n_slices;
Chris@49 3345
Chris@49 3346 hid_t dataspace = H5Screate_simple(3, dims, NULL); // treat the cube as a 3d array dataspace
Chris@49 3347 hid_t datatype = hdf5_misc::get_hdf5_type<eT>();
Chris@49 3348
Chris@49 3349 // If this returned something invalid, well, it's time to crash.
Chris@49 3350 arma_check(datatype == -1, "Cube::save(): unknown datatype for HDF5");
Chris@49 3351
Chris@49 3352 // MATLAB forces the users to specify a name at save time for HDF5; Octave
Chris@49 3353 // will use the default of 'dataset' unless otherwise specified, so we will
Chris@49 3354 // use that.
Chris@49 3355 hid_t dataset = H5Dcreate(file, "dataset", datatype, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
Chris@49 3356
Chris@49 3357 herr_t status = H5Dwrite(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, x.mem);
Chris@49 3358 save_okay = (status >= 0);
Chris@49 3359
Chris@49 3360 H5Dclose(dataset);
Chris@49 3361 H5Tclose(datatype);
Chris@49 3362 H5Sclose(dataspace);
Chris@49 3363 H5Fclose(file);
Chris@49 3364
Chris@49 3365 if(save_okay == true) { save_okay = diskio::safe_rename(tmp_name, final_name); }
Chris@49 3366
Chris@49 3367 return save_okay;
Chris@49 3368 }
Chris@49 3369 #else
Chris@49 3370 {
Chris@49 3371 arma_ignore(x);
Chris@49 3372 arma_ignore(final_name);
Chris@49 3373
Chris@49 3374 arma_stop("Cube::save(): use of HDF5 needs to be enabled");
Chris@49 3375
Chris@49 3376 return false;
Chris@49 3377 }
Chris@49 3378 #endif
Chris@49 3379 }
Chris@49 3380
Chris@49 3381
Chris@49 3382
Chris@49 3383 //! Load a cube as raw text (no header, human readable).
Chris@49 3384 //! NOTE: this is much slower than reading a file with a header.
Chris@49 3385 template<typename eT>
Chris@49 3386 inline
Chris@49 3387 bool
Chris@49 3388 diskio::load_raw_ascii(Cube<eT>& x, const std::string& name, std::string& err_msg)
Chris@49 3389 {
Chris@49 3390 arma_extra_debug_sigprint();
Chris@49 3391
Chris@49 3392 Mat<eT> tmp;
Chris@49 3393 const bool load_okay = diskio::load_raw_ascii(tmp, name, err_msg);
Chris@49 3394
Chris@49 3395 if(load_okay == true)
Chris@49 3396 {
Chris@49 3397 if(tmp.is_empty() == false)
Chris@49 3398 {
Chris@49 3399 x.set_size(tmp.n_rows, tmp.n_cols, 1);
Chris@49 3400
Chris@49 3401 x.slice(0) = tmp;
Chris@49 3402 }
Chris@49 3403 else
Chris@49 3404 {
Chris@49 3405 x.reset();
Chris@49 3406 }
Chris@49 3407 }
Chris@49 3408
Chris@49 3409 return load_okay;
Chris@49 3410 }
Chris@49 3411
Chris@49 3412
Chris@49 3413
Chris@49 3414 //! Load a cube as raw text (no header, human readable).
Chris@49 3415 //! NOTE: this is much slower than reading a file with a header.
Chris@49 3416 template<typename eT>
Chris@49 3417 inline
Chris@49 3418 bool
Chris@49 3419 diskio::load_raw_ascii(Cube<eT>& x, std::istream& f, std::string& err_msg)
Chris@49 3420 {
Chris@49 3421 arma_extra_debug_sigprint();
Chris@49 3422
Chris@49 3423 Mat<eT> tmp;
Chris@49 3424 const bool load_okay = diskio::load_raw_ascii(tmp, f, err_msg);
Chris@49 3425
Chris@49 3426 if(load_okay == true)
Chris@49 3427 {
Chris@49 3428 if(tmp.is_empty() == false)
Chris@49 3429 {
Chris@49 3430 x.set_size(tmp.n_rows, tmp.n_cols, 1);
Chris@49 3431
Chris@49 3432 x.slice(0) = tmp;
Chris@49 3433 }
Chris@49 3434 else
Chris@49 3435 {
Chris@49 3436 x.reset();
Chris@49 3437 }
Chris@49 3438 }
Chris@49 3439
Chris@49 3440 return load_okay;
Chris@49 3441 }
Chris@49 3442
Chris@49 3443
Chris@49 3444
Chris@49 3445 //! Load a cube in binary format (no header);
Chris@49 3446 //! the cube is assumed to have one slice with one column
Chris@49 3447 template<typename eT>
Chris@49 3448 inline
Chris@49 3449 bool
Chris@49 3450 diskio::load_raw_binary(Cube<eT>& x, const std::string& name, std::string& err_msg)
Chris@49 3451 {
Chris@49 3452 arma_extra_debug_sigprint();
Chris@49 3453
Chris@49 3454 std::ifstream f;
Chris@49 3455 f.open(name.c_str(), std::fstream::binary);
Chris@49 3456
Chris@49 3457 bool load_okay = f.is_open();
Chris@49 3458
Chris@49 3459 if(load_okay == true)
Chris@49 3460 {
Chris@49 3461 load_okay = diskio::load_raw_binary(x, f, err_msg);
Chris@49 3462 f.close();
Chris@49 3463 }
Chris@49 3464
Chris@49 3465 return load_okay;
Chris@49 3466 }
Chris@49 3467
Chris@49 3468
Chris@49 3469
Chris@49 3470 template<typename eT>
Chris@49 3471 inline
Chris@49 3472 bool
Chris@49 3473 diskio::load_raw_binary(Cube<eT>& x, std::istream& f, std::string& err_msg)
Chris@49 3474 {
Chris@49 3475 arma_extra_debug_sigprint();
Chris@49 3476 arma_ignore(err_msg);
Chris@49 3477
Chris@49 3478 f.clear();
Chris@49 3479 const std::streampos pos1 = f.tellg();
Chris@49 3480
Chris@49 3481 f.clear();
Chris@49 3482 f.seekg(0, ios::end);
Chris@49 3483
Chris@49 3484 f.clear();
Chris@49 3485 const std::streampos pos2 = f.tellg();
Chris@49 3486
Chris@49 3487 const uword N = ( (pos1 >= 0) && (pos2 >= 0) ) ? uword(pos2 - pos1) : 0;
Chris@49 3488
Chris@49 3489 f.clear();
Chris@49 3490 //f.seekg(0, ios::beg);
Chris@49 3491 f.seekg(pos1);
Chris@49 3492
Chris@49 3493 x.set_size(N / sizeof(eT), 1, 1);
Chris@49 3494
Chris@49 3495 f.clear();
Chris@49 3496 f.read( reinterpret_cast<char *>(x.memptr()), std::streamsize(N) );
Chris@49 3497
Chris@49 3498 return f.good();
Chris@49 3499 }
Chris@49 3500
Chris@49 3501
Chris@49 3502
Chris@49 3503 //! Load a cube in text format (human readable),
Chris@49 3504 //! with a header that indicates the cube type as well as its dimensions
Chris@49 3505 template<typename eT>
Chris@49 3506 inline
Chris@49 3507 bool
Chris@49 3508 diskio::load_arma_ascii(Cube<eT>& x, const std::string& name, std::string& err_msg)
Chris@49 3509 {
Chris@49 3510 arma_extra_debug_sigprint();
Chris@49 3511
Chris@49 3512 std::ifstream f(name.c_str());
Chris@49 3513
Chris@49 3514 bool load_okay = f.is_open();
Chris@49 3515
Chris@49 3516 if(load_okay == true)
Chris@49 3517 {
Chris@49 3518 load_okay = diskio::load_arma_ascii(x, f, err_msg);
Chris@49 3519 f.close();
Chris@49 3520 }
Chris@49 3521
Chris@49 3522 return load_okay;
Chris@49 3523 }
Chris@49 3524
Chris@49 3525
Chris@49 3526
Chris@49 3527 //! Load a cube in text format (human readable),
Chris@49 3528 //! with a header that indicates the cube type as well as its dimensions
Chris@49 3529 template<typename eT>
Chris@49 3530 inline
Chris@49 3531 bool
Chris@49 3532 diskio::load_arma_ascii(Cube<eT>& x, std::istream& f, std::string& err_msg)
Chris@49 3533 {
Chris@49 3534 arma_extra_debug_sigprint();
Chris@49 3535
Chris@49 3536 bool load_okay = true;
Chris@49 3537
Chris@49 3538 std::string f_header;
Chris@49 3539 uword f_n_rows;
Chris@49 3540 uword f_n_cols;
Chris@49 3541 uword f_n_slices;
Chris@49 3542
Chris@49 3543 f >> f_header;
Chris@49 3544 f >> f_n_rows;
Chris@49 3545 f >> f_n_cols;
Chris@49 3546 f >> f_n_slices;
Chris@49 3547
Chris@49 3548 if(f_header == diskio::gen_txt_header(x))
Chris@49 3549 {
Chris@49 3550 x.set_size(f_n_rows, f_n_cols, f_n_slices);
Chris@49 3551
Chris@49 3552 for(uword slice=0; slice < x.n_slices; ++slice)
Chris@49 3553 {
Chris@49 3554 for(uword row=0; row < x.n_rows; ++row)
Chris@49 3555 {
Chris@49 3556 for(uword col=0; col < x.n_cols; ++col)
Chris@49 3557 {
Chris@49 3558 f >> x.at(row,col,slice);
Chris@49 3559 }
Chris@49 3560 }
Chris@49 3561 }
Chris@49 3562
Chris@49 3563 load_okay = f.good();
Chris@49 3564 }
Chris@49 3565 else
Chris@49 3566 {
Chris@49 3567 load_okay = false;
Chris@49 3568 err_msg = "incorrect header in ";
Chris@49 3569 }
Chris@49 3570
Chris@49 3571 return load_okay;
Chris@49 3572 }
Chris@49 3573
Chris@49 3574
Chris@49 3575
Chris@49 3576 //! Load a cube in binary format,
Chris@49 3577 //! with a header that indicates the cube type as well as its dimensions
Chris@49 3578 template<typename eT>
Chris@49 3579 inline
Chris@49 3580 bool
Chris@49 3581 diskio::load_arma_binary(Cube<eT>& x, const std::string& name, std::string& err_msg)
Chris@49 3582 {
Chris@49 3583 arma_extra_debug_sigprint();
Chris@49 3584
Chris@49 3585 std::ifstream f;
Chris@49 3586 f.open(name.c_str(), std::fstream::binary);
Chris@49 3587
Chris@49 3588 bool load_okay = f.is_open();
Chris@49 3589
Chris@49 3590 if(load_okay == true)
Chris@49 3591 {
Chris@49 3592 load_okay = diskio::load_arma_binary(x, f, err_msg);
Chris@49 3593 f.close();
Chris@49 3594 }
Chris@49 3595
Chris@49 3596 return load_okay;
Chris@49 3597 }
Chris@49 3598
Chris@49 3599
Chris@49 3600
Chris@49 3601 template<typename eT>
Chris@49 3602 inline
Chris@49 3603 bool
Chris@49 3604 diskio::load_arma_binary(Cube<eT>& x, std::istream& f, std::string& err_msg)
Chris@49 3605 {
Chris@49 3606 arma_extra_debug_sigprint();
Chris@49 3607
Chris@49 3608 bool load_okay = true;
Chris@49 3609
Chris@49 3610 std::string f_header;
Chris@49 3611 uword f_n_rows;
Chris@49 3612 uword f_n_cols;
Chris@49 3613 uword f_n_slices;
Chris@49 3614
Chris@49 3615 f >> f_header;
Chris@49 3616 f >> f_n_rows;
Chris@49 3617 f >> f_n_cols;
Chris@49 3618 f >> f_n_slices;
Chris@49 3619
Chris@49 3620 if(f_header == diskio::gen_bin_header(x))
Chris@49 3621 {
Chris@49 3622 //f.seekg(1, ios::cur); // NOTE: this may not be portable, as on a Windows machine a newline could be two characters
Chris@49 3623 f.get();
Chris@49 3624
Chris@49 3625 x.set_size(f_n_rows, f_n_cols, f_n_slices);
Chris@49 3626 f.read( reinterpret_cast<char *>(x.memptr()), std::streamsize(x.n_elem*sizeof(eT)) );
Chris@49 3627
Chris@49 3628 load_okay = f.good();
Chris@49 3629 }
Chris@49 3630 else
Chris@49 3631 {
Chris@49 3632 load_okay = false;
Chris@49 3633 err_msg = "incorrect header in ";
Chris@49 3634 }
Chris@49 3635
Chris@49 3636 return load_okay;
Chris@49 3637 }
Chris@49 3638
Chris@49 3639
Chris@49 3640
Chris@49 3641 //! Load a HDF5 file as a cube
Chris@49 3642 template<typename eT>
Chris@49 3643 inline
Chris@49 3644 bool
Chris@49 3645 diskio::load_hdf5_binary(Cube<eT>& x, const std::string& name, std::string& err_msg)
Chris@49 3646 {
Chris@49 3647 arma_extra_debug_sigprint();
Chris@49 3648
Chris@49 3649 #if defined(ARMA_USE_HDF5)
Chris@49 3650 {
Chris@49 3651
Chris@49 3652 // These may be necessary to store the error handler (if we need to).
Chris@49 3653 herr_t (*old_func)(hid_t, void*);
Chris@49 3654 void *old_client_data;
Chris@49 3655
Chris@49 3656 #if !defined(ARMA_PRINT_HDF5_ERRORS)
Chris@49 3657 {
Chris@49 3658 // Save old error handler.
Chris@49 3659 H5Eget_auto(H5E_DEFAULT, &old_func, &old_client_data);
Chris@49 3660
Chris@49 3661 // Disable annoying HDF5 error messages.
Chris@49 3662 H5Eset_auto(H5E_DEFAULT, NULL, NULL);
Chris@49 3663 }
Chris@49 3664 #endif
Chris@49 3665
Chris@49 3666 bool load_okay = false;
Chris@49 3667
Chris@49 3668 hid_t fid = H5Fopen(name.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
Chris@49 3669
Chris@49 3670 if(fid >= 0)
Chris@49 3671 {
Chris@49 3672 // MATLAB HDF5 dataset names are user-specified;
Chris@49 3673 // Octave tends to store the datasets in a group, with the actual dataset being referred to as "value".
Chris@49 3674 // So we will search for "dataset" and "value", and if those are not found we will take the first dataset we do find.
Chris@49 3675 std::vector<std::string> searchNames;
Chris@49 3676 searchNames.push_back("dataset");
Chris@49 3677 searchNames.push_back("value");
Chris@49 3678
Chris@49 3679 hid_t dataset = hdf5_misc::search_hdf5_file(searchNames, fid, 3, false);
Chris@49 3680
Chris@49 3681 if(dataset >= 0)
Chris@49 3682 {
Chris@49 3683 hid_t filespace = H5Dget_space(dataset);
Chris@49 3684
Chris@49 3685 // This must be <= 3 due to our search rules.
Chris@49 3686 const int ndims = H5Sget_simple_extent_ndims(filespace);
Chris@49 3687
Chris@49 3688 hsize_t dims[3];
Chris@49 3689 const herr_t query_status = H5Sget_simple_extent_dims(filespace, dims, NULL);
Chris@49 3690
Chris@49 3691 // arma_check(query_status < 0, "Cube::load(): cannot get size of HDF5 dataset");
Chris@49 3692 if(query_status < 0)
Chris@49 3693 {
Chris@49 3694 err_msg = "cannot get size of HDF5 dataset in ";
Chris@49 3695
Chris@49 3696 H5Sclose(filespace);
Chris@49 3697 H5Dclose(dataset);
Chris@49 3698 H5Fclose(fid);
Chris@49 3699
Chris@49 3700 #if !defined(ARMA_PRINT_HDF5_ERRORS)
Chris@49 3701 {
Chris@49 3702 // Restore HDF5 error handler.
Chris@49 3703 H5Eset_auto(H5E_DEFAULT, old_func, old_client_data);
Chris@49 3704 }
Chris@49 3705 #endif
Chris@49 3706
Chris@49 3707 return false;
Chris@49 3708 }
Chris@49 3709
Chris@49 3710 if (ndims == 1) { dims[1] = 1; dims[2] = 1; } // Vector case; one row/colum, several slices
Chris@49 3711 if (ndims == 2) { dims[2] = 1; } // Matrix case; one column, several rows/slices
Chris@49 3712
Chris@49 3713 x.set_size(dims[2], dims[1], dims[0]);
Chris@49 3714
Chris@49 3715 // Now we have to see what type is stored to figure out how to load it.
Chris@49 3716 hid_t datatype = H5Dget_type(dataset);
Chris@49 3717 hid_t mat_type = hdf5_misc::get_hdf5_type<eT>();
Chris@49 3718
Chris@49 3719 // If these are the same type, it is simple.
Chris@49 3720 if(H5Tequal(datatype, mat_type) > 0)
Chris@49 3721 {
Chris@49 3722 // Load directly; H5S_ALL used so that we load the entire dataset.
Chris@49 3723 hid_t read_status = H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, void_ptr(x.memptr()));
Chris@49 3724
Chris@49 3725 if(read_status >= 0) { load_okay = true; }
Chris@49 3726 }
Chris@49 3727 else
Chris@49 3728 {
Chris@49 3729 // Load into another array and convert its type accordingly.
Chris@49 3730 hid_t read_status = hdf5_misc::load_and_convert_hdf5(x.memptr(), dataset, datatype, x.n_elem);
Chris@49 3731
Chris@49 3732 if(read_status >= 0) { load_okay = true; }
Chris@49 3733 }
Chris@49 3734
Chris@49 3735 // Now clean up.
Chris@49 3736 H5Tclose(datatype);
Chris@49 3737 H5Tclose(mat_type);
Chris@49 3738 H5Sclose(filespace);
Chris@49 3739 }
Chris@49 3740
Chris@49 3741 H5Dclose(dataset);
Chris@49 3742
Chris@49 3743 H5Fclose(fid);
Chris@49 3744
Chris@49 3745 if(load_okay == false)
Chris@49 3746 {
Chris@49 3747 err_msg = "unsupported or incorrect HDF5 data in ";
Chris@49 3748 }
Chris@49 3749 }
Chris@49 3750 else
Chris@49 3751 {
Chris@49 3752 err_msg = "cannot open file ";
Chris@49 3753 }
Chris@49 3754
Chris@49 3755 #if !defined(ARMA_PRINT_HDF5_ERRORS)
Chris@49 3756 {
Chris@49 3757 // Restore HDF5 error handler.
Chris@49 3758 H5Eset_auto(H5E_DEFAULT, old_func, old_client_data);
Chris@49 3759 }
Chris@49 3760 #endif
Chris@49 3761
Chris@49 3762 return load_okay;
Chris@49 3763 }
Chris@49 3764 #else
Chris@49 3765 {
Chris@49 3766 arma_ignore(x);
Chris@49 3767 arma_ignore(name);
Chris@49 3768 arma_ignore(err_msg);
Chris@49 3769
Chris@49 3770 arma_stop("Cube::load(): use of HDF5 needs to be enabled");
Chris@49 3771
Chris@49 3772 return false;
Chris@49 3773 }
Chris@49 3774 #endif
Chris@49 3775 }
Chris@49 3776
Chris@49 3777
Chris@49 3778
Chris@49 3779 //! Try to load a cube by automatically determining its type
Chris@49 3780 template<typename eT>
Chris@49 3781 inline
Chris@49 3782 bool
Chris@49 3783 diskio::load_auto_detect(Cube<eT>& x, const std::string& name, std::string& err_msg)
Chris@49 3784 {
Chris@49 3785 arma_extra_debug_sigprint();
Chris@49 3786
Chris@49 3787 #if defined(ARMA_USE_HDF5)
Chris@49 3788 // We're currently using the C bindings for the HDF5 library, which don't support C++ streams
Chris@49 3789 if( H5Fis_hdf5(name.c_str()) ) { return load_hdf5_binary(x, name, err_msg); }
Chris@49 3790 #endif
Chris@49 3791
Chris@49 3792 std::fstream f;
Chris@49 3793 f.open(name.c_str(), std::fstream::in | std::fstream::binary);
Chris@49 3794
Chris@49 3795 bool load_okay = f.is_open();
Chris@49 3796
Chris@49 3797 if(load_okay == true)
Chris@49 3798 {
Chris@49 3799 load_okay = diskio::load_auto_detect(x, f, err_msg);
Chris@49 3800 f.close();
Chris@49 3801 }
Chris@49 3802
Chris@49 3803 return load_okay;
Chris@49 3804 }
Chris@49 3805
Chris@49 3806
Chris@49 3807
Chris@49 3808 //! Try to load a cube by automatically determining its type
Chris@49 3809 template<typename eT>
Chris@49 3810 inline
Chris@49 3811 bool
Chris@49 3812 diskio::load_auto_detect(Cube<eT>& x, std::istream& f, std::string& err_msg)
Chris@49 3813 {
Chris@49 3814 arma_extra_debug_sigprint();
Chris@49 3815
Chris@49 3816 static const std::string ARMA_CUB_TXT = "ARMA_CUB_TXT";
Chris@49 3817 static const std::string ARMA_CUB_BIN = "ARMA_CUB_BIN";
Chris@49 3818 static const std::string P6 = "P6";
Chris@49 3819
Chris@49 3820 podarray<char> raw_header(ARMA_CUB_TXT.length() + 1);
Chris@49 3821
Chris@49 3822 std::streampos pos = f.tellg();
Chris@49 3823
Chris@49 3824 f.read( raw_header.memptr(), std::streamsize(ARMA_CUB_TXT.length()) );
Chris@49 3825 raw_header[ARMA_CUB_TXT.length()] = '\0';
Chris@49 3826
Chris@49 3827 f.clear();
Chris@49 3828 f.seekg(pos);
Chris@49 3829
Chris@49 3830 const std::string header = raw_header.mem;
Chris@49 3831
Chris@49 3832 if(ARMA_CUB_TXT == header.substr(0, ARMA_CUB_TXT.length()))
Chris@49 3833 {
Chris@49 3834 return load_arma_ascii(x, f, err_msg);
Chris@49 3835 }
Chris@49 3836 else
Chris@49 3837 if(ARMA_CUB_BIN == header.substr(0, ARMA_CUB_BIN.length()))
Chris@49 3838 {
Chris@49 3839 return load_arma_binary(x, f, err_msg);
Chris@49 3840 }
Chris@49 3841 else
Chris@49 3842 if(P6 == header.substr(0, P6.length()))
Chris@49 3843 {
Chris@49 3844 return load_ppm_binary(x, f, err_msg);
Chris@49 3845 }
Chris@49 3846 else
Chris@49 3847 {
Chris@49 3848 const file_type ft = guess_file_type(f);
Chris@49 3849
Chris@49 3850 switch(ft)
Chris@49 3851 {
Chris@49 3852 // case csv_ascii:
Chris@49 3853 // return load_csv_ascii(x, f, err_msg);
Chris@49 3854 // break;
Chris@49 3855
Chris@49 3856 case raw_binary:
Chris@49 3857 return load_raw_binary(x, f, err_msg);
Chris@49 3858 break;
Chris@49 3859
Chris@49 3860 case raw_ascii:
Chris@49 3861 return load_raw_ascii(x, f, err_msg);
Chris@49 3862 break;
Chris@49 3863
Chris@49 3864 default:
Chris@49 3865 err_msg = "unknown data in ";
Chris@49 3866 return false;
Chris@49 3867 }
Chris@49 3868 }
Chris@49 3869
Chris@49 3870 return false;
Chris@49 3871 }
Chris@49 3872
Chris@49 3873
Chris@49 3874
Chris@49 3875
Chris@49 3876
Chris@49 3877 // fields
Chris@49 3878
Chris@49 3879
Chris@49 3880
Chris@49 3881 template<typename T1>
Chris@49 3882 inline
Chris@49 3883 bool
Chris@49 3884 diskio::save_arma_binary(const field<T1>& x, const std::string& final_name)
Chris@49 3885 {
Chris@49 3886 arma_extra_debug_sigprint();
Chris@49 3887
Chris@49 3888 const std::string tmp_name = diskio::gen_tmp_name(final_name);
Chris@49 3889
Chris@49 3890 std::ofstream f( tmp_name.c_str(), std::fstream::binary );
Chris@49 3891
Chris@49 3892 bool save_okay = f.is_open();
Chris@49 3893
Chris@49 3894 if(save_okay == true)
Chris@49 3895 {
Chris@49 3896 save_okay = diskio::save_arma_binary(x, f);
Chris@49 3897
Chris@49 3898 f.flush();
Chris@49 3899 f.close();
Chris@49 3900
Chris@49 3901 if(save_okay == true)
Chris@49 3902 {
Chris@49 3903 save_okay = diskio::safe_rename(tmp_name, final_name);
Chris@49 3904 }
Chris@49 3905 }
Chris@49 3906
Chris@49 3907 return save_okay;
Chris@49 3908 }
Chris@49 3909
Chris@49 3910
Chris@49 3911
Chris@49 3912 template<typename T1>
Chris@49 3913 inline
Chris@49 3914 bool
Chris@49 3915 diskio::save_arma_binary(const field<T1>& x, std::ostream& f)
Chris@49 3916 {
Chris@49 3917 arma_extra_debug_sigprint();
Chris@49 3918
Chris@49 3919 arma_type_check(( (is_Mat<T1>::value == false) && (is_Cube<T1>::value == false) ));
Chris@49 3920
Chris@49 3921 f << "ARMA_FLD_BIN" << '\n';
Chris@49 3922 f << x.n_rows << '\n';
Chris@49 3923 f << x.n_cols << '\n';
Chris@49 3924
Chris@49 3925 bool save_okay = true;
Chris@49 3926
Chris@49 3927 for(uword i=0; i<x.n_elem; ++i)
Chris@49 3928 {
Chris@49 3929 save_okay = diskio::save_arma_binary(x[i], f);
Chris@49 3930
Chris@49 3931 if(save_okay == false)
Chris@49 3932 {
Chris@49 3933 break;
Chris@49 3934 }
Chris@49 3935 }
Chris@49 3936
Chris@49 3937 return save_okay;
Chris@49 3938 }
Chris@49 3939
Chris@49 3940
Chris@49 3941
Chris@49 3942 template<typename T1>
Chris@49 3943 inline
Chris@49 3944 bool
Chris@49 3945 diskio::load_arma_binary(field<T1>& x, const std::string& name, std::string& err_msg)
Chris@49 3946 {
Chris@49 3947 arma_extra_debug_sigprint();
Chris@49 3948
Chris@49 3949 std::ifstream f( name.c_str(), std::fstream::binary );
Chris@49 3950
Chris@49 3951 bool load_okay = f.is_open();
Chris@49 3952
Chris@49 3953 if(load_okay == true)
Chris@49 3954 {
Chris@49 3955 load_okay = diskio::load_arma_binary(x, f, err_msg);
Chris@49 3956 f.close();
Chris@49 3957 }
Chris@49 3958
Chris@49 3959 return load_okay;
Chris@49 3960 }
Chris@49 3961
Chris@49 3962
Chris@49 3963
Chris@49 3964 template<typename T1>
Chris@49 3965 inline
Chris@49 3966 bool
Chris@49 3967 diskio::load_arma_binary(field<T1>& x, std::istream& f, std::string& err_msg)
Chris@49 3968 {
Chris@49 3969 arma_extra_debug_sigprint();
Chris@49 3970
Chris@49 3971 arma_type_check(( (is_Mat<T1>::value == false) && (is_Cube<T1>::value == false) ));
Chris@49 3972
Chris@49 3973 bool load_okay = true;
Chris@49 3974
Chris@49 3975 std::string f_type;
Chris@49 3976 f >> f_type;
Chris@49 3977
Chris@49 3978 if(f_type != "ARMA_FLD_BIN")
Chris@49 3979 {
Chris@49 3980 load_okay = false;
Chris@49 3981 err_msg = "unsupported field type in ";
Chris@49 3982 }
Chris@49 3983 else
Chris@49 3984 {
Chris@49 3985 uword f_n_rows;
Chris@49 3986 uword f_n_cols;
Chris@49 3987
Chris@49 3988 f >> f_n_rows;
Chris@49 3989 f >> f_n_cols;
Chris@49 3990
Chris@49 3991 x.set_size(f_n_rows, f_n_cols);
Chris@49 3992
Chris@49 3993 f.get();
Chris@49 3994
Chris@49 3995 for(uword i=0; i<x.n_elem; ++i)
Chris@49 3996 {
Chris@49 3997 load_okay = diskio::load_arma_binary(x[i], f, err_msg);
Chris@49 3998
Chris@49 3999 if(load_okay == false)
Chris@49 4000 {
Chris@49 4001 break;
Chris@49 4002 }
Chris@49 4003 }
Chris@49 4004 }
Chris@49 4005
Chris@49 4006 return load_okay;
Chris@49 4007 }
Chris@49 4008
Chris@49 4009
Chris@49 4010
Chris@49 4011 inline
Chris@49 4012 bool
Chris@49 4013 diskio::save_std_string(const field<std::string>& x, const std::string& final_name)
Chris@49 4014 {
Chris@49 4015 arma_extra_debug_sigprint();
Chris@49 4016
Chris@49 4017 const std::string tmp_name = diskio::gen_tmp_name(final_name);
Chris@49 4018
Chris@49 4019 std::ofstream f( tmp_name.c_str(), std::fstream::binary );
Chris@49 4020
Chris@49 4021 bool save_okay = f.is_open();
Chris@49 4022
Chris@49 4023 if(save_okay == true)
Chris@49 4024 {
Chris@49 4025 save_okay = diskio::save_std_string(x, f);
Chris@49 4026
Chris@49 4027 f.flush();
Chris@49 4028 f.close();
Chris@49 4029
Chris@49 4030 if(save_okay == true)
Chris@49 4031 {
Chris@49 4032 save_okay = diskio::safe_rename(tmp_name, final_name);
Chris@49 4033 }
Chris@49 4034 }
Chris@49 4035
Chris@49 4036 return save_okay;
Chris@49 4037 }
Chris@49 4038
Chris@49 4039
Chris@49 4040
Chris@49 4041 inline
Chris@49 4042 bool
Chris@49 4043 diskio::save_std_string(const field<std::string>& x, std::ostream& f)
Chris@49 4044 {
Chris@49 4045 arma_extra_debug_sigprint();
Chris@49 4046
Chris@49 4047 for(uword row=0; row<x.n_rows; ++row)
Chris@49 4048 for(uword col=0; col<x.n_cols; ++col)
Chris@49 4049 {
Chris@49 4050 f << x.at(row,col);
Chris@49 4051
Chris@49 4052 if(col < x.n_cols-1)
Chris@49 4053 {
Chris@49 4054 f << ' ';
Chris@49 4055 }
Chris@49 4056 else
Chris@49 4057 {
Chris@49 4058 f << '\n';
Chris@49 4059 }
Chris@49 4060 }
Chris@49 4061
Chris@49 4062 return f.good();
Chris@49 4063 }
Chris@49 4064
Chris@49 4065
Chris@49 4066
Chris@49 4067 inline
Chris@49 4068 bool
Chris@49 4069 diskio::load_std_string(field<std::string>& x, const std::string& name, std::string& err_msg)
Chris@49 4070 {
Chris@49 4071 arma_extra_debug_sigprint();
Chris@49 4072
Chris@49 4073 std::ifstream f( name.c_str() );
Chris@49 4074
Chris@49 4075 bool load_okay = f.is_open();
Chris@49 4076
Chris@49 4077 if(load_okay == true)
Chris@49 4078 {
Chris@49 4079 load_okay = diskio::load_std_string(x, f, err_msg);
Chris@49 4080 f.close();
Chris@49 4081 }
Chris@49 4082
Chris@49 4083 return load_okay;
Chris@49 4084 }
Chris@49 4085
Chris@49 4086
Chris@49 4087
Chris@49 4088 inline
Chris@49 4089 bool
Chris@49 4090 diskio::load_std_string(field<std::string>& x, std::istream& f, std::string& err_msg)
Chris@49 4091 {
Chris@49 4092 arma_extra_debug_sigprint();
Chris@49 4093
Chris@49 4094 bool load_okay = true;
Chris@49 4095
Chris@49 4096 //
Chris@49 4097 // work out the size
Chris@49 4098
Chris@49 4099 uword f_n_rows = 0;
Chris@49 4100 uword f_n_cols = 0;
Chris@49 4101
Chris@49 4102 bool f_n_cols_found = false;
Chris@49 4103
Chris@49 4104 std::string line_string;
Chris@49 4105 std::string token;
Chris@49 4106
Chris@49 4107 while( (f.good() == true) && (load_okay == true) )
Chris@49 4108 {
Chris@49 4109 std::getline(f, line_string);
Chris@49 4110 if(line_string.size() == 0)
Chris@49 4111 break;
Chris@49 4112
Chris@49 4113 std::stringstream line_stream(line_string);
Chris@49 4114
Chris@49 4115 uword line_n_cols = 0;
Chris@49 4116 while (line_stream >> token)
Chris@49 4117 line_n_cols++;
Chris@49 4118
Chris@49 4119 if(f_n_cols_found == false)
Chris@49 4120 {
Chris@49 4121 f_n_cols = line_n_cols;
Chris@49 4122 f_n_cols_found = true;
Chris@49 4123 }
Chris@49 4124 else
Chris@49 4125 {
Chris@49 4126 if(line_n_cols != f_n_cols)
Chris@49 4127 {
Chris@49 4128 load_okay = false;
Chris@49 4129 err_msg = "inconsistent number of columns in ";
Chris@49 4130 }
Chris@49 4131 }
Chris@49 4132
Chris@49 4133 ++f_n_rows;
Chris@49 4134 }
Chris@49 4135
Chris@49 4136 if(load_okay == true)
Chris@49 4137 {
Chris@49 4138 f.clear();
Chris@49 4139 f.seekg(0, ios::beg);
Chris@49 4140 //f.seekg(start);
Chris@49 4141
Chris@49 4142 x.set_size(f_n_rows, f_n_cols);
Chris@49 4143
Chris@49 4144 for(uword row=0; row < x.n_rows; ++row)
Chris@49 4145 {
Chris@49 4146 for(uword col=0; col < x.n_cols; ++col)
Chris@49 4147 {
Chris@49 4148 f >> x.at(row,col);
Chris@49 4149 }
Chris@49 4150 }
Chris@49 4151 }
Chris@49 4152
Chris@49 4153 if(f.good() == false)
Chris@49 4154 {
Chris@49 4155 load_okay = false;
Chris@49 4156 }
Chris@49 4157
Chris@49 4158 return load_okay;
Chris@49 4159 }
Chris@49 4160
Chris@49 4161
Chris@49 4162
Chris@49 4163 //! Try to load a field by automatically determining its type
Chris@49 4164 template<typename T1>
Chris@49 4165 inline
Chris@49 4166 bool
Chris@49 4167 diskio::load_auto_detect(field<T1>& x, const std::string& name, std::string& err_msg)
Chris@49 4168 {
Chris@49 4169 arma_extra_debug_sigprint();
Chris@49 4170
Chris@49 4171 std::fstream f;
Chris@49 4172 f.open(name.c_str(), std::fstream::in | std::fstream::binary);
Chris@49 4173
Chris@49 4174 bool load_okay = f.is_open();
Chris@49 4175
Chris@49 4176 if(load_okay == true)
Chris@49 4177 {
Chris@49 4178 load_okay = diskio::load_auto_detect(x, f, err_msg);
Chris@49 4179 f.close();
Chris@49 4180 }
Chris@49 4181
Chris@49 4182 return load_okay;
Chris@49 4183 }
Chris@49 4184
Chris@49 4185
Chris@49 4186
Chris@49 4187 //! Try to load a field by automatically determining its type
Chris@49 4188 template<typename T1>
Chris@49 4189 inline
Chris@49 4190 bool
Chris@49 4191 diskio::load_auto_detect(field<T1>& x, std::istream& f, std::string& err_msg)
Chris@49 4192 {
Chris@49 4193 arma_extra_debug_sigprint();
Chris@49 4194
Chris@49 4195 arma_type_check(( is_Mat<T1>::value == false ));
Chris@49 4196
Chris@49 4197 static const std::string ARMA_FLD_BIN = "ARMA_FLD_BIN";
Chris@49 4198 static const std::string P6 = "P6";
Chris@49 4199
Chris@49 4200 podarray<char> raw_header(ARMA_FLD_BIN.length() + 1);
Chris@49 4201
Chris@49 4202 std::streampos pos = f.tellg();
Chris@49 4203
Chris@49 4204 f.read( raw_header.memptr(), std::streamsize(ARMA_FLD_BIN.length()) );
Chris@49 4205
Chris@49 4206 f.clear();
Chris@49 4207 f.seekg(pos);
Chris@49 4208
Chris@49 4209 raw_header[ARMA_FLD_BIN.length()] = '\0';
Chris@49 4210
Chris@49 4211 const std::string header = raw_header.mem;
Chris@49 4212
Chris@49 4213 if(ARMA_FLD_BIN == header.substr(0, ARMA_FLD_BIN.length()))
Chris@49 4214 {
Chris@49 4215 return load_arma_binary(x, f, err_msg);
Chris@49 4216 }
Chris@49 4217 else
Chris@49 4218 if(P6 == header.substr(0, P6.length()))
Chris@49 4219 {
Chris@49 4220 return load_ppm_binary(x, f, err_msg);
Chris@49 4221 }
Chris@49 4222 else
Chris@49 4223 {
Chris@49 4224 err_msg = "unsupported header in ";
Chris@49 4225 return false;
Chris@49 4226 }
Chris@49 4227 }
Chris@49 4228
Chris@49 4229
Chris@49 4230
Chris@49 4231 //
Chris@49 4232 // handling of PPM images by cubes
Chris@49 4233
Chris@49 4234
Chris@49 4235 template<typename eT>
Chris@49 4236 inline
Chris@49 4237 bool
Chris@49 4238 diskio::load_ppm_binary(Cube<eT>& x, const std::string& name, std::string& err_msg)
Chris@49 4239 {
Chris@49 4240 arma_extra_debug_sigprint();
Chris@49 4241
Chris@49 4242 std::fstream f;
Chris@49 4243 f.open(name.c_str(), std::fstream::in | std::fstream::binary);
Chris@49 4244
Chris@49 4245 bool load_okay = f.is_open();
Chris@49 4246
Chris@49 4247 if(load_okay == true)
Chris@49 4248 {
Chris@49 4249 load_okay = diskio::load_ppm_binary(x, f, err_msg);
Chris@49 4250 f.close();
Chris@49 4251 }
Chris@49 4252
Chris@49 4253 return load_okay;
Chris@49 4254 }
Chris@49 4255
Chris@49 4256
Chris@49 4257
Chris@49 4258 template<typename eT>
Chris@49 4259 inline
Chris@49 4260 bool
Chris@49 4261 diskio::load_ppm_binary(Cube<eT>& x, std::istream& f, std::string& err_msg)
Chris@49 4262 {
Chris@49 4263 arma_extra_debug_sigprint();
Chris@49 4264
Chris@49 4265 bool load_okay = true;
Chris@49 4266
Chris@49 4267 std::string f_header;
Chris@49 4268 f >> f_header;
Chris@49 4269
Chris@49 4270 if(f_header == "P6")
Chris@49 4271 {
Chris@49 4272 uword f_n_rows = 0;
Chris@49 4273 uword f_n_cols = 0;
Chris@49 4274 int f_maxval = 0;
Chris@49 4275
Chris@49 4276 diskio::pnm_skip_comments(f);
Chris@49 4277
Chris@49 4278 f >> f_n_cols;
Chris@49 4279 diskio::pnm_skip_comments(f);
Chris@49 4280
Chris@49 4281 f >> f_n_rows;
Chris@49 4282 diskio::pnm_skip_comments(f);
Chris@49 4283
Chris@49 4284 f >> f_maxval;
Chris@49 4285 f.get();
Chris@49 4286
Chris@49 4287 if( (f_maxval > 0) || (f_maxval <= 65535) )
Chris@49 4288 {
Chris@49 4289 x.set_size(f_n_rows, f_n_cols, 3);
Chris@49 4290
Chris@49 4291 if(f_maxval <= 255)
Chris@49 4292 {
Chris@49 4293 const uword n_elem = 3*f_n_cols*f_n_rows;
Chris@49 4294 podarray<u8> tmp(n_elem);
Chris@49 4295
Chris@49 4296 f.read( reinterpret_cast<char*>(tmp.memptr()), std::streamsize(n_elem) );
Chris@49 4297
Chris@49 4298 uword i = 0;
Chris@49 4299
Chris@49 4300 //cout << "f_n_cols = " << f_n_cols << endl;
Chris@49 4301 //cout << "f_n_rows = " << f_n_rows << endl;
Chris@49 4302
Chris@49 4303
Chris@49 4304 for(uword row=0; row < f_n_rows; ++row)
Chris@49 4305 {
Chris@49 4306 for(uword col=0; col < f_n_cols; ++col)
Chris@49 4307 {
Chris@49 4308 x.at(row,col,0) = eT(tmp[i+0]);
Chris@49 4309 x.at(row,col,1) = eT(tmp[i+1]);
Chris@49 4310 x.at(row,col,2) = eT(tmp[i+2]);
Chris@49 4311 i+=3;
Chris@49 4312 }
Chris@49 4313
Chris@49 4314 }
Chris@49 4315 }
Chris@49 4316 else
Chris@49 4317 {
Chris@49 4318 const uword n_elem = 3*f_n_cols*f_n_rows;
Chris@49 4319 podarray<u16> tmp(n_elem);
Chris@49 4320
Chris@49 4321 f.read( reinterpret_cast<char *>(tmp.memptr()), std::streamsize(2*n_elem) );
Chris@49 4322
Chris@49 4323 uword i = 0;
Chris@49 4324
Chris@49 4325 for(uword row=0; row < f_n_rows; ++row)
Chris@49 4326 {
Chris@49 4327 for(uword col=0; col < f_n_cols; ++col)
Chris@49 4328 {
Chris@49 4329 x.at(row,col,0) = eT(tmp[i+0]);
Chris@49 4330 x.at(row,col,1) = eT(tmp[i+1]);
Chris@49 4331 x.at(row,col,2) = eT(tmp[i+2]);
Chris@49 4332 i+=3;
Chris@49 4333 }
Chris@49 4334
Chris@49 4335 }
Chris@49 4336
Chris@49 4337 }
Chris@49 4338
Chris@49 4339 }
Chris@49 4340 else
Chris@49 4341 {
Chris@49 4342 load_okay = false;
Chris@49 4343 err_msg = "currently no code available to handle loading ";
Chris@49 4344 }
Chris@49 4345
Chris@49 4346 if(f.good() == false)
Chris@49 4347 {
Chris@49 4348 load_okay = false;
Chris@49 4349 }
Chris@49 4350
Chris@49 4351 }
Chris@49 4352 else
Chris@49 4353 {
Chris@49 4354 load_okay = false;
Chris@49 4355 err_msg = "unsupported header in ";
Chris@49 4356 }
Chris@49 4357
Chris@49 4358 return load_okay;
Chris@49 4359 }
Chris@49 4360
Chris@49 4361
Chris@49 4362
Chris@49 4363 template<typename eT>
Chris@49 4364 inline
Chris@49 4365 bool
Chris@49 4366 diskio::save_ppm_binary(const Cube<eT>& x, const std::string& final_name)
Chris@49 4367 {
Chris@49 4368 arma_extra_debug_sigprint();
Chris@49 4369
Chris@49 4370 const std::string tmp_name = diskio::gen_tmp_name(final_name);
Chris@49 4371
Chris@49 4372 std::ofstream f( tmp_name.c_str(), std::fstream::binary );
Chris@49 4373
Chris@49 4374 bool save_okay = f.is_open();
Chris@49 4375
Chris@49 4376 if(save_okay == true)
Chris@49 4377 {
Chris@49 4378 save_okay = diskio::save_ppm_binary(x, f);
Chris@49 4379
Chris@49 4380 f.flush();
Chris@49 4381 f.close();
Chris@49 4382
Chris@49 4383 if(save_okay == true)
Chris@49 4384 {
Chris@49 4385 save_okay = diskio::safe_rename(tmp_name, final_name);
Chris@49 4386 }
Chris@49 4387 }
Chris@49 4388
Chris@49 4389 return save_okay;
Chris@49 4390 }
Chris@49 4391
Chris@49 4392
Chris@49 4393
Chris@49 4394 template<typename eT>
Chris@49 4395 inline
Chris@49 4396 bool
Chris@49 4397 diskio::save_ppm_binary(const Cube<eT>& x, std::ostream& f)
Chris@49 4398 {
Chris@49 4399 arma_extra_debug_sigprint();
Chris@49 4400
Chris@49 4401 arma_debug_check( (x.n_slices != 3), "diskio::save_ppm_binary(): given cube must have exactly 3 slices" );
Chris@49 4402
Chris@49 4403 const uword n_elem = 3 * x.n_rows * x.n_cols;
Chris@49 4404 podarray<u8> tmp(n_elem);
Chris@49 4405
Chris@49 4406 uword i = 0;
Chris@49 4407 for(uword row=0; row < x.n_rows; ++row)
Chris@49 4408 {
Chris@49 4409 for(uword col=0; col < x.n_cols; ++col)
Chris@49 4410 {
Chris@49 4411 tmp[i+0] = u8( access::tmp_real( x.at(row,col,0) ) );
Chris@49 4412 tmp[i+1] = u8( access::tmp_real( x.at(row,col,1) ) );
Chris@49 4413 tmp[i+2] = u8( access::tmp_real( x.at(row,col,2) ) );
Chris@49 4414
Chris@49 4415 i+=3;
Chris@49 4416 }
Chris@49 4417 }
Chris@49 4418
Chris@49 4419 f << "P6" << '\n';
Chris@49 4420 f << x.n_cols << '\n';
Chris@49 4421 f << x.n_rows << '\n';
Chris@49 4422 f << 255 << '\n';
Chris@49 4423
Chris@49 4424 f.write( reinterpret_cast<const char*>(tmp.mem), std::streamsize(n_elem) );
Chris@49 4425
Chris@49 4426 return f.good();
Chris@49 4427 }
Chris@49 4428
Chris@49 4429
Chris@49 4430
Chris@49 4431 //
Chris@49 4432 // handling of PPM images by fields
Chris@49 4433
Chris@49 4434
Chris@49 4435
Chris@49 4436 template<typename T1>
Chris@49 4437 inline
Chris@49 4438 bool
Chris@49 4439 diskio::load_ppm_binary(field<T1>& x, const std::string& name, std::string& err_msg)
Chris@49 4440 {
Chris@49 4441 arma_extra_debug_sigprint();
Chris@49 4442
Chris@49 4443 std::fstream f;
Chris@49 4444 f.open(name.c_str(), std::fstream::in | std::fstream::binary);
Chris@49 4445
Chris@49 4446 bool load_okay = f.is_open();
Chris@49 4447
Chris@49 4448 if(load_okay == true)
Chris@49 4449 {
Chris@49 4450 load_okay = diskio::load_ppm_binary(x, f, err_msg);
Chris@49 4451 f.close();
Chris@49 4452 }
Chris@49 4453
Chris@49 4454 return load_okay;
Chris@49 4455 }
Chris@49 4456
Chris@49 4457
Chris@49 4458
Chris@49 4459 template<typename T1>
Chris@49 4460 inline
Chris@49 4461 bool
Chris@49 4462 diskio::load_ppm_binary(field<T1>& x, std::istream& f, std::string& err_msg)
Chris@49 4463 {
Chris@49 4464 arma_extra_debug_sigprint();
Chris@49 4465
Chris@49 4466 arma_type_check(( is_Mat<T1>::value == false ));
Chris@49 4467 typedef typename T1::elem_type eT;
Chris@49 4468
Chris@49 4469 bool load_okay = true;
Chris@49 4470
Chris@49 4471 std::string f_header;
Chris@49 4472 f >> f_header;
Chris@49 4473
Chris@49 4474 if(f_header == "P6")
Chris@49 4475 {
Chris@49 4476 uword f_n_rows = 0;
Chris@49 4477 uword f_n_cols = 0;
Chris@49 4478 int f_maxval = 0;
Chris@49 4479
Chris@49 4480 diskio::pnm_skip_comments(f);
Chris@49 4481
Chris@49 4482 f >> f_n_cols;
Chris@49 4483 diskio::pnm_skip_comments(f);
Chris@49 4484
Chris@49 4485 f >> f_n_rows;
Chris@49 4486 diskio::pnm_skip_comments(f);
Chris@49 4487
Chris@49 4488 f >> f_maxval;
Chris@49 4489 f.get();
Chris@49 4490
Chris@49 4491 if( (f_maxval > 0) || (f_maxval <= 65535) )
Chris@49 4492 {
Chris@49 4493 x.set_size(3);
Chris@49 4494 Mat<eT>& R = x(0);
Chris@49 4495 Mat<eT>& G = x(1);
Chris@49 4496 Mat<eT>& B = x(2);
Chris@49 4497
Chris@49 4498 R.set_size(f_n_rows,f_n_cols);
Chris@49 4499 G.set_size(f_n_rows,f_n_cols);
Chris@49 4500 B.set_size(f_n_rows,f_n_cols);
Chris@49 4501
Chris@49 4502 if(f_maxval <= 255)
Chris@49 4503 {
Chris@49 4504 const uword n_elem = 3*f_n_cols*f_n_rows;
Chris@49 4505 podarray<u8> tmp(n_elem);
Chris@49 4506
Chris@49 4507 f.read( reinterpret_cast<char*>(tmp.memptr()), std::streamsize(n_elem) );
Chris@49 4508
Chris@49 4509 uword i = 0;
Chris@49 4510
Chris@49 4511 //cout << "f_n_cols = " << f_n_cols << endl;
Chris@49 4512 //cout << "f_n_rows = " << f_n_rows << endl;
Chris@49 4513
Chris@49 4514
Chris@49 4515 for(uword row=0; row < f_n_rows; ++row)
Chris@49 4516 {
Chris@49 4517 for(uword col=0; col < f_n_cols; ++col)
Chris@49 4518 {
Chris@49 4519 R.at(row,col) = eT(tmp[i+0]);
Chris@49 4520 G.at(row,col) = eT(tmp[i+1]);
Chris@49 4521 B.at(row,col) = eT(tmp[i+2]);
Chris@49 4522 i+=3;
Chris@49 4523 }
Chris@49 4524
Chris@49 4525 }
Chris@49 4526 }
Chris@49 4527 else
Chris@49 4528 {
Chris@49 4529 const uword n_elem = 3*f_n_cols*f_n_rows;
Chris@49 4530 podarray<u16> tmp(n_elem);
Chris@49 4531
Chris@49 4532 f.read( reinterpret_cast<char *>(tmp.memptr()), std::streamsize(2*n_elem) );
Chris@49 4533
Chris@49 4534 uword i = 0;
Chris@49 4535
Chris@49 4536 for(uword row=0; row < f_n_rows; ++row)
Chris@49 4537 {
Chris@49 4538 for(uword col=0; col < f_n_cols; ++col)
Chris@49 4539 {
Chris@49 4540 R.at(row,col) = eT(tmp[i+0]);
Chris@49 4541 G.at(row,col) = eT(tmp[i+1]);
Chris@49 4542 B.at(row,col) = eT(tmp[i+2]);
Chris@49 4543 i+=3;
Chris@49 4544 }
Chris@49 4545
Chris@49 4546 }
Chris@49 4547
Chris@49 4548 }
Chris@49 4549
Chris@49 4550 }
Chris@49 4551 else
Chris@49 4552 {
Chris@49 4553 load_okay = false;
Chris@49 4554 err_msg = "currently no code available to handle loading ";
Chris@49 4555 }
Chris@49 4556
Chris@49 4557 if(f.good() == false)
Chris@49 4558 {
Chris@49 4559 load_okay = false;
Chris@49 4560 }
Chris@49 4561
Chris@49 4562 }
Chris@49 4563 else
Chris@49 4564 {
Chris@49 4565 load_okay = false;
Chris@49 4566 err_msg = "unsupported header in ";
Chris@49 4567 }
Chris@49 4568
Chris@49 4569 return load_okay;
Chris@49 4570 }
Chris@49 4571
Chris@49 4572
Chris@49 4573
Chris@49 4574 template<typename T1>
Chris@49 4575 inline
Chris@49 4576 bool
Chris@49 4577 diskio::save_ppm_binary(const field<T1>& x, const std::string& final_name)
Chris@49 4578 {
Chris@49 4579 arma_extra_debug_sigprint();
Chris@49 4580
Chris@49 4581 const std::string tmp_name = diskio::gen_tmp_name(final_name);
Chris@49 4582 std::ofstream f( tmp_name.c_str(), std::fstream::binary );
Chris@49 4583
Chris@49 4584 bool save_okay = f.is_open();
Chris@49 4585
Chris@49 4586 if(save_okay == true)
Chris@49 4587 {
Chris@49 4588 save_okay = diskio::save_ppm_binary(x, f);
Chris@49 4589
Chris@49 4590 f.flush();
Chris@49 4591 f.close();
Chris@49 4592
Chris@49 4593 if(save_okay == true)
Chris@49 4594 {
Chris@49 4595 save_okay = diskio::safe_rename(tmp_name, final_name);
Chris@49 4596 }
Chris@49 4597 }
Chris@49 4598
Chris@49 4599 return save_okay;
Chris@49 4600 }
Chris@49 4601
Chris@49 4602
Chris@49 4603
Chris@49 4604 template<typename T1>
Chris@49 4605 inline
Chris@49 4606 bool
Chris@49 4607 diskio::save_ppm_binary(const field<T1>& x, std::ostream& f)
Chris@49 4608 {
Chris@49 4609 arma_extra_debug_sigprint();
Chris@49 4610
Chris@49 4611 arma_type_check(( is_Mat<T1>::value == false ));
Chris@49 4612
Chris@49 4613 typedef typename T1::elem_type eT;
Chris@49 4614
Chris@49 4615 arma_debug_check( (x.n_elem != 3), "diskio::save_ppm_binary(): given field must have exactly 3 matrices of equal size" );
Chris@49 4616
Chris@49 4617 bool same_size = true;
Chris@49 4618 for(uword i=1; i<3; ++i)
Chris@49 4619 {
Chris@49 4620 if( (x(0).n_rows != x(i).n_rows) || (x(0).n_cols != x(i).n_cols) )
Chris@49 4621 {
Chris@49 4622 same_size = false;
Chris@49 4623 break;
Chris@49 4624 }
Chris@49 4625 }
Chris@49 4626
Chris@49 4627 arma_debug_check( (same_size != true), "diskio::save_ppm_binary(): given field must have exactly 3 matrices of equal size" );
Chris@49 4628
Chris@49 4629 const Mat<eT>& R = x(0);
Chris@49 4630 const Mat<eT>& G = x(1);
Chris@49 4631 const Mat<eT>& B = x(2);
Chris@49 4632
Chris@49 4633 f << "P6" << '\n';
Chris@49 4634 f << R.n_cols << '\n';
Chris@49 4635 f << R.n_rows << '\n';
Chris@49 4636 f << 255 << '\n';
Chris@49 4637
Chris@49 4638 const uword n_elem = 3 * R.n_rows * R.n_cols;
Chris@49 4639 podarray<u8> tmp(n_elem);
Chris@49 4640
Chris@49 4641 uword i = 0;
Chris@49 4642 for(uword row=0; row < R.n_rows; ++row)
Chris@49 4643 {
Chris@49 4644 for(uword col=0; col < R.n_cols; ++col)
Chris@49 4645 {
Chris@49 4646 tmp[i+0] = u8( access::tmp_real( R.at(row,col) ) );
Chris@49 4647 tmp[i+1] = u8( access::tmp_real( G.at(row,col) ) );
Chris@49 4648 tmp[i+2] = u8( access::tmp_real( B.at(row,col) ) );
Chris@49 4649
Chris@49 4650 i+=3;
Chris@49 4651 }
Chris@49 4652 }
Chris@49 4653
Chris@49 4654 f.write( reinterpret_cast<const char*>(tmp.mem), std::streamsize(n_elem) );
Chris@49 4655
Chris@49 4656 return f.good();
Chris@49 4657 }
Chris@49 4658
Chris@49 4659
Chris@49 4660
Chris@49 4661 //! @}
Chris@49 4662