Grid 0.7.0
BaseIO.h
Go to the documentation of this file.
1 /*************************************************************************************
2
3 Grid physics library, www.github.com/paboyle/Grid
4
5 Source file: ./lib/serialisation/BaseIO.h
6
7 Copyright (C) 2015
8
9Author: Antonin Portelli <antonin.portelli@me.com>
10Author: Peter Boyle <paboyle@ph.ed.ac.uk>
11Author: Guido Cossu <guido.cossu@ed.ac.uk>
12Author: Michael Marshall <michael.marshall@ed.ac.uk>
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License along
25 with this program; if not, write to the Free Software Foundation, Inc.,
26 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27
28 See the full license in the file "LICENSE" in the top level distribution directory
29 *************************************************************************************/
30 /* END LEGAL */
31#ifndef GRID_SERIALISATION_ABSTRACT_READER_H
32#define GRID_SERIALISATION_ABSTRACT_READER_H
33
34#include <atomic>
35#include <type_traits>
39
40namespace Grid {
41 namespace EigenIO {
42 // EigenIO works for scalars that are not just Grid supported scalars
43 template<typename T, typename V = void> struct is_complex : public std::false_type {};
44 // Support all complex types (not just Grid complex types) - even if the definitions overlap (!)
45 template<typename T> struct is_complex< T , typename
46 std::enable_if< ::Grid::is_complex< T >::value>::type> : public std::true_type {};
47 template<typename T> struct is_complex<std::complex<T>, typename
48 std::enable_if<!::Grid::is_complex<std::complex<T>>::value>::type> : public std::true_type {};
49
50 // Helpers to support I/O for Eigen tensors of arithmetic scalars, complex types, or Grid tensors
51 template<typename T, typename V = void> struct is_scalar : public std::false_type {};
52 template<typename T> struct is_scalar<T, typename std::enable_if<std::is_arithmetic<T>::value || is_complex<T>::value>::type> : public std::true_type {};
53
54 // Is this an Eigen tensor
55 template<typename T> struct is_tensor : std::integral_constant<bool,
56 std::is_base_of<Eigen::TensorBase<T, Eigen::ReadOnlyAccessors>, T>::value> {};
57
58 // Is this an Eigen tensor of a supported scalar
59 template<typename T, typename V = void> struct is_tensor_of_scalar : public std::false_type {};
60 template<typename T> struct is_tensor_of_scalar<T, typename std::enable_if<is_tensor<T>::value && is_scalar<typename T::Scalar>::value>::type> : public std::true_type {};
61
62 // Is this an Eigen tensor of a supported container
63 template<typename T, typename V = void> struct is_tensor_of_container : public std::false_type {};
64 template<typename T> struct is_tensor_of_container<T, typename std::enable_if<is_tensor<T>::value && isGridTensor<typename T::Scalar>::value>::type> : public std::true_type {};
65
66 // These traits describe the scalars inside Eigen tensors
67 // I wish I could define these in reference to the scalar type (so there would be fewer traits defined)
68 // but I'm unable to find a syntax to make this work
69 template<typename T, typename V = void> struct Traits {};
70 // Traits are the default for scalars, or come from GridTypeMapper for GridTensors
71 template<typename T> struct Traits<T, typename std::enable_if<is_tensor_of_scalar<T>::value>::type>
72 : public GridTypeMapper_Base {
73 using scalar_type = typename T::Scalar; // ultimate base scalar
75 };
76 // Traits are the default for scalars, or come from GridTypeMapper for GridTensors
77 template<typename T> struct Traits<T, typename std::enable_if<is_tensor_of_container<T>::value>::type> {
79 using scalar_type = typename BaseTraits::scalar_type; // ultimate base scalar
81 static constexpr int TensorLevel = BaseTraits::TensorLevel;
82 static constexpr int Rank = BaseTraits::Rank;
83 static constexpr std::size_t count = BaseTraits::count;
84 static constexpr int Dimension(int dim) { return BaseTraits::Dimension(dim); }
85 };
86
87 // Is this a fixed-size Eigen tensor
88 template<typename T> struct is_tensor_fixed : public std::false_type {};
89 template<typename Scalar_, typename Dimensions_, int Options_, typename IndexType>
90 struct is_tensor_fixed<Eigen::TensorFixedSize<Scalar_, Dimensions_, Options_, IndexType>>
91 : public std::true_type {};
92 template<typename T> struct is_tensor_fixed<Eigen::TensorMap<T>> : public std::true_type {};
93
94 // Is this a variable-size Eigen tensor
95 template<typename T, typename V = void> struct is_tensor_variable : public std::false_type {};
96 template<typename T> struct is_tensor_variable<T, typename std::enable_if<is_tensor<T>::value
97 && !is_tensor_fixed<T>::value>::type> : public std::true_type {};
98
99 // Helper functions to get the ultimate scalar inside a tensor, and corresponding size
100 template <typename ET>
101 inline typename std::enable_if<is_tensor<ET>::value, const typename ET::Index>::type
102 getScalarCount(const ET &eigenTensor) { return eigenTensor.size() * Traits<ET>::count; }
103 template <typename ET>
104 inline typename std::enable_if<is_tensor_of_scalar<ET>::value, const typename ET::Scalar *>::type
105 getFirstScalar(const ET &eigenTensor) { return eigenTensor.data(); }
106 template <typename ET>
107 inline typename std::enable_if<is_tensor_of_scalar<ET>::value, typename ET::Scalar *>::type
108 getFirstScalar(ET &eigenTensor) { return eigenTensor.data(); }
109 template <typename ET>
110 inline typename std::enable_if<is_tensor_of_container<ET>::value, const typename Traits<ET>::scalar_type *>::type
111 getFirstScalar(const ET &eigenTensor) { return eigenTensor.data()->begin(); }
112 template <typename ET>
113 inline typename std::enable_if<is_tensor_of_container<ET>::value, typename Traits<ET>::scalar_type *>::type
114 getFirstScalar(ET &eigenTensor) { return eigenTensor.data()->begin(); }
115
116 // Counter for resized EigenTensors (poor man's substitute for allocator)
117 // Defined in BinaryIO.cc
118 extern std::uint64_t EigenResizeCounter;
119 }
120
121 // Abstract writer/reader classes ////////////////////////////////////////////
122 // static polymorphism implemented using CRTP idiom
123 class Serializable;
124
125 // Static abstract writer
126 template <typename T>
127 class Writer
128 {
129 public:
130 Writer(void);
131 virtual ~Writer(void) = default;
132 void push(const std::string &s);
133 void pop(void);
134 template <typename U>
135 typename std::enable_if<std::is_base_of<Serializable, U>::value>::type
136 write(const std::string& s, const U &output);
137 template <typename U>
138 typename std::enable_if<!std::is_base_of<Serializable, U>::value && !EigenIO::is_tensor<U>::value>::type
139 write(const std::string& s, const U &output);
140 template <typename U>
141 void write(const std::string &s, const iScalar<U> &output);
142 template <typename U, int N>
143 void write(const std::string &s, const iVector<U, N> &output);
144 template <typename U, int N>
145 void write(const std::string &s, const iMatrix<U, N> &output);
146 template <typename ETensor>
147 typename std::enable_if<EigenIO::is_tensor<ETensor>::value>::type
148 write(const std::string &s, const ETensor &output);
149
150 template <typename S>
151 inline typename std::enable_if<EigenIO::is_scalar<S>::value, void>::type
152 copyScalars(S * &pCopy, const S &Source)
153 {
154 * pCopy ++ = Source;
155 }
156
157 template <typename S>
158 inline typename std::enable_if<isGridTensor<S>::value, void>::type
159 copyScalars(typename GridTypeMapper<S>::scalar_type * &pCopy, const S &Source)
160 {
161 for( const typename GridTypeMapper<S>::scalar_type &item : Source )
162 * pCopy ++ = item;
163 }
164
165 void scientificFormat(const bool set);
166 bool isScientific(void);
167 void setPrecision(const unsigned int prec);
168 unsigned int getPrecision(void);
169 private:
171 bool scientific_{false};
172 unsigned int prec_{0};
173 };
174
175 // Static abstract reader
176 template <typename T>
177 class Reader
178 {
179 public:
180 Reader(void);
181 virtual ~Reader(void) = default;
182 bool push(const std::string &s);
183 void pop(void);
184 template <typename U>
185 typename std::enable_if<std::is_base_of<Serializable, U>::value, void>::type
186 read(const std::string& s, U &output);
187 template <typename U>
188 typename std::enable_if<!std::is_base_of<Serializable, U>::value
190 read(const std::string& s, U &output);
191 template <typename U>
192 void read(const std::string &s, iScalar<U> &output);
193 template <typename U, int N>
194 void read(const std::string &s, iVector<U, N> &output);
195 template <typename U, int N>
196 void read(const std::string &s, iMatrix<U, N> &output);
197 template <typename ETensor>
198 typename std::enable_if<EigenIO::is_tensor<ETensor>::value, void>::type
199 read(const std::string &s, ETensor &output);
200 template <typename ETensor>
201 typename std::enable_if<EigenIO::is_tensor_fixed<ETensor>::value, void>::type
202 Reshape(ETensor &t, const std::array<typename ETensor::Index, ETensor::NumDimensions> &dims );
203 template <typename ETensor>
204 typename std::enable_if<EigenIO::is_tensor_variable<ETensor>::value, void>::type
205 Reshape(ETensor &t, const std::array<typename ETensor::Index, ETensor::NumDimensions> &dims );
206
207 // Helper functions for Scalar vs Container specialisations
208 template <typename S>
209 inline typename std::enable_if<EigenIO::is_scalar<S>::value, void>::type
210 copyScalars(S &Dest, const S * &pSource)
211 {
212 Dest = * pSource ++;
213 }
214
215 template <typename S>
216 inline typename std::enable_if<isGridTensor<S>::value, void>::type
217 copyScalars(S &Dest, const typename GridTypeMapper<S>::scalar_type * &pSource)
218 {
219 for( typename GridTypeMapper<S>::scalar_type &item : Dest )
220 item = * pSource ++;
221 }
222
223 protected:
224 template <typename U>
225 void fromString(U &output, const std::string &s);
226 private:
228 };
229
230 // What is the vtype
231 template<typename T> struct isReader {
232 static const bool value = false;
233 };
234 template<typename T> struct isWriter {
235 static const bool value = false;
236 };
237
238 // Writer template implementation
239 template <typename T>
241 {
242 upcast = static_cast<T *>(this);
243 }
244
245 template <typename T>
246 void Writer<T>::push(const std::string &s)
247 {
248 upcast->push(s);
249 }
250
251 template <typename T>
252 void Writer<T>::pop(void)
253 {
254 upcast->pop();
255 }
256
257 template <typename T>
258 template <typename U>
259 typename std::enable_if<std::is_base_of<Serializable, U>::value, void>::type
260 Writer<T>::write(const std::string &s, const U &output)
261 {
262 U::write(*this, s, output);
263 }
264
265 template <typename T>
266 template <typename U>
267 typename std::enable_if<!std::is_base_of<Serializable, U>::value
269 Writer<T>::write(const std::string &s, const U &output)
270 {
271 upcast->writeDefault(s, output);
272 }
273
274
275 template <typename T>
276 template <typename U>
277 void Writer<T>::write(const std::string &s, const iScalar<U> &output)
278 {
279 upcast->writeDefault(s, tensorToVec(output));
280 }
281
282 template <typename T>
283 template <typename U, int N>
284 void Writer<T>::write(const std::string &s, const iVector<U, N> &output)
285 {
286 upcast->writeDefault(s, tensorToVec(output));
287 }
288
289 template <typename T>
290 template <typename U, int N>
291 void Writer<T>::write(const std::string &s, const iMatrix<U, N> &output)
292 {
293 upcast->writeDefault(s, tensorToVec(output));
294 }
295
296 // Eigen::Tensors of Grid tensors (iScalar, iVector, iMatrix)
297 template <typename T>
298 template <typename ETensor>
299 typename std::enable_if<EigenIO::is_tensor<ETensor>::value, void>::type
300 Writer<T>::write(const std::string &s, const ETensor &output)
301 {
302 using Index = typename ETensor::Index;
303 using Container = typename ETensor::Scalar; // NB: could be same as scalar
304 using Traits = EigenIO::Traits<ETensor>;
305 using Scalar = typename Traits::scalar_type; // type of the underlying scalar
306 constexpr unsigned int TensorRank{ETensor::NumIndices};
307 constexpr unsigned int ContainerRank{Traits::Rank}; // Only non-zero for containers
308 constexpr unsigned int TotalRank{TensorRank + ContainerRank};
309 const Index NumElements{output.size()};
310 assert( NumElements > 0 );
311
312 // Get the dimensionality of the tensor
313 std::vector<std::size_t> TotalDims(TotalRank);
314 for(auto i = 0; i < TensorRank; i++ ) {
315 auto dim = output.dimension(i);
316 TotalDims[i] = static_cast<size_t>(dim);
317 assert( TotalDims[i] == dim ); // check we didn't lose anything in the conversion
318 }
319 for(auto i = 0; i < ContainerRank; i++ )
320 TotalDims[TensorRank + i] = Traits::Dimension(i);
321
322 // If the Tensor isn't in Row-Major order, then we'll need to copy it's data
323 const bool CopyData{NumElements > 1 && static_cast<int>( ETensor::Layout ) != static_cast<int>( Eigen::StorageOptions::RowMajor )};
324 const Scalar * pWriteBuffer;
325 std::vector<Scalar> CopyBuffer;
326 const Index TotalNumElements = NumElements * Traits::count;
327 if( !CopyData ) {
328 pWriteBuffer = EigenIO::getFirstScalar( output );
329 } else {
330 // Regardless of the Eigen::Tensor storage order, the copy will be Row Major
331 CopyBuffer.resize( TotalNumElements );
332 Scalar * pCopy = &CopyBuffer[0];
333 pWriteBuffer = pCopy;
334 std::array<Index, TensorRank> MyIndex;
335 for( auto &idx : MyIndex ) idx = 0;
336 for( auto n = 0; n < NumElements; n++ ) {
337 const Container & c = output( MyIndex );
338 copyScalars( pCopy, c );
339 // Now increment the index
340 for( int i = output.NumDimensions - 1; i >= 0 && ++MyIndex[i] == output.dimension(i); i-- )
341 MyIndex[i] = 0;
342 }
343 }
344 upcast->template writeMultiDim<Scalar>(s, TotalDims, pWriteBuffer, TotalNumElements);
345 }
346
347 template <typename T>
348 void Writer<T>::scientificFormat(const bool set)
349 {
350 scientific_ = set;
351 }
352
353 template <typename T>
355 {
356 return scientific_;
357 }
358
359 template <typename T>
360 void Writer<T>::setPrecision(const unsigned int prec)
361 {
362 prec_ = prec;
363 }
364
365 template <typename T>
366 unsigned int Writer<T>::getPrecision(void)
367 {
368 return prec_;
369 }
370
371 // Reader template implementation
372 template <typename T>
374 {
375 upcast = static_cast<T *>(this);
376 }
377
378 template <typename T>
379 bool Reader<T>::push(const std::string &s)
380 {
381 return upcast->push(s);
382 }
383
384 template <typename T>
385 void Reader<T>::pop(void)
386 {
387 upcast->pop();
388 }
389
390 template <typename T>
391 template <typename U>
392 typename std::enable_if<std::is_base_of<Serializable, U>::value, void>::type
393 Reader<T>::read(const std::string &s, U &output)
394 {
395 U::read(*this, s, output);
396 }
397
398 template <typename T>
399 template <typename U>
400 typename std::enable_if<!std::is_base_of<Serializable, U>::value
402 Reader<T>::read(const std::string &s, U &output)
403 {
404 upcast->readDefault(s, output);
405 }
406
407 template <typename T>
408 template <typename U>
409 void Reader<T>::read(const std::string &s, iScalar<U> &output)
410 {
412
413 upcast->readDefault(s, v);
414 vecToTensor(output, v);
415 }
416
417 template <typename T>
418 template <typename U, int N>
419 void Reader<T>::read(const std::string &s, iVector<U, N> &output)
420 {
422
423 upcast->readDefault(s, v);
424 vecToTensor(output, v);
425 }
426
427 template <typename T>
428 template <typename U, int N>
429 void Reader<T>::read(const std::string &s, iMatrix<U, N> &output)
430 {
432
433 upcast->readDefault(s, v);
434 vecToTensor(output, v);
435 }
436
437 template <typename T>
438 template <typename ETensor>
439 typename std::enable_if<EigenIO::is_tensor<ETensor>::value, void>::type
440 Reader<T>::read(const std::string &s, ETensor &output)
441 {
442 using Index = typename ETensor::Index;
443 using Container = typename ETensor::Scalar; // NB: could be same as scalar
444 using Traits = EigenIO::Traits<ETensor>;
445 using Scalar = typename Traits::scalar_type; // type of the underlying scalar
446 constexpr unsigned int TensorRank{ETensor::NumIndices};
447 constexpr unsigned int ContainerRank{Traits::Rank}; // Only non-zero for containers
448 constexpr unsigned int TotalRank{TensorRank + ContainerRank};
449 using ETDims = std::array<Index, TensorRank>; // Dimensions of the tensor
450
451 // read the (flat) data and dimensionality
452 std::vector<std::size_t> dimData;
453 std::vector<Scalar> buf;
454 upcast->readMultiDim( s, buf, dimData );
455 assert(dimData.size() == TotalRank && "EigenIO: Tensor rank mismatch" );
456 // Make sure that the number of elements read matches dimensions read
457 std::size_t NumContainers = 1;
458 for( auto i = 0 ; i < TensorRank ; i++ )
459 NumContainers *= dimData[i];
460 // If our scalar object is a Container, make sure it's dimensions match what we read back
461 std::size_t ElementsPerContainer = 1;
462 for( auto i = 0 ; i < ContainerRank ; i++ ) {
463 assert( dimData[TensorRank+i] == Traits::Dimension(i) && "Tensor Container dimensions don't match data" );
464 ElementsPerContainer *= dimData[TensorRank+i];
465 }
466 assert( NumContainers * ElementsPerContainer == buf.size() && "EigenIO: Number of elements != product of dimensions" );
467 // Now see whether the tensor is the right shape, or can be made to be
468 const auto & dims = output.dimensions();
469 bool bShapeOK = (output.data() != nullptr);
470 for( auto i = 0; bShapeOK && i < TensorRank ; i++ )
471 if( dims[i] != dimData[i] )
472 bShapeOK = false;
473 // Make the tensor the same size as the data read
474 ETDims MyIndex;
475 if( !bShapeOK ) {
476 for( auto i = 0 ; i < TensorRank ; i++ )
477 MyIndex[i] = dimData[i];
478 Reshape(output, MyIndex);
479 }
480 // Copy the data into the tensor
481 for( auto &d : MyIndex ) d = 0;
482 const Scalar * pSource = &buf[0];
483 for( std::size_t n = 0 ; n < NumContainers ; n++ ) {
484 Container & c = output( MyIndex );
485 copyScalars( c, pSource );
486 // Now increment the index
487 for( int i = TensorRank - 1; i != -1 && ++MyIndex[i] == dims[i]; i-- )
488 MyIndex[i] = 0;
489 }
490 assert( pSource == &buf[NumContainers * ElementsPerContainer] );
491 }
492
493 template <typename T>
494 template <typename ETensor>
495 typename std::enable_if<EigenIO::is_tensor_fixed<ETensor>::value, void>::type
496 Reader<T>::Reshape(ETensor &t, const std::array<typename ETensor::Index, ETensor::NumDimensions> &dims )
497 {
498 assert( 0 && "EigenIO: Fixed tensor dimensions can't be changed" );
499 }
500
501 template <typename T>
502 template <typename ETensor>
503 typename std::enable_if<EigenIO::is_tensor_variable<ETensor>::value, void>::type
504 Reader<T>::Reshape(ETensor &t, const std::array<typename ETensor::Index, ETensor::NumDimensions> &dims )
505 {
506#ifdef GRID_OMP
507 // The memory counter is the reason this must be done from the primary thread
508 assert(omp_in_parallel()==0 && "Deserialisation which resizes Eigen tensor must happen from primary thread");
509#endif
510 EigenIO::EigenResizeCounter -= static_cast<uint64_t>(t.size()) * sizeof(typename ETensor::Scalar);
511 //t.reshape( dims );
512 t.resize( dims );
513 EigenIO::EigenResizeCounter += static_cast<uint64_t>(t.size()) * sizeof(typename ETensor::Scalar);
514 }
515
516 template <typename T>
517 template <typename U>
518 void Reader<T>::fromString(U &output, const std::string &s)
519 {
520 std::istringstream is(s);
521
522 is.exceptions(std::ios::failbit);
523 try
524 {
525 is >> std::boolalpha >> output;
526 }
527 catch(std::ios_base::failure &e)
528 {
529 std::cerr << "numerical conversion failure on '" << s << "' ";
530 std::cerr << "(typeid: " << typeid(U).name() << ")" << std::endl;
531 abort();
532 }
533 }
534
535 // serializable base class ///////////////////////////////////////////////////
537 {
538 public:
539 template <typename T>
540 static inline void write(Writer<T> &WR,const std::string &s,
541 const Serializable &obj)
542 {}
543
544 template <typename T>
545 static inline void read(Reader<T> &RD,const std::string &s,
546 Serializable &obj)
547 {}
548
549 friend inline std::ostream & operator<<(std::ostream &os,
550 const Serializable &obj)
551 {
552 return os;
553 }
554
555 template <typename T1, typename T2>
556 static inline typename std::enable_if<!EigenIO::is_tensor<T1>::value || !EigenIO::is_tensor<T2>::value, bool>::type
557 CompareMember(const T1 &lhs, const T2 &rhs) {
558 return lhs == rhs;
559 }
560
561 template <typename T1, typename T2>
562 static inline typename std::enable_if<EigenIO::is_tensor<T1>::value && EigenIO::is_tensor<T2>::value, bool>::type
563 CompareMember(const T1 &lhs, const T2 &rhs) {
564 // First check whether dimensions match (Eigen tensor library will assert if they don't match)
565 bool bReturnValue = (T1::NumIndices == T2::NumIndices);
566 for( auto i = 0 ; bReturnValue && i < T1::NumIndices ; i++ )
567 bReturnValue = ( lhs.dimension(i) == rhs.dimension(i) );
568 if( bReturnValue ) {
569 Eigen::Tensor<bool, 0, T1::Options> bResult = (lhs == rhs).all();
570 bReturnValue = bResult(0);
571 }
572 return bReturnValue;
573 }
574
575 template <typename T>
576 static inline typename std::enable_if<EigenIO::is_tensor<T>::value, bool>::type
577 CompareMember(const std::vector<T> &lhs, const std::vector<T> &rhs) {
578 const auto NumElements = lhs.size();
579 bool bResult = ( NumElements == rhs.size() );
580 for( auto i = 0 ; i < NumElements && bResult ; i++ )
581 bResult = CompareMember(lhs[i], rhs[i]);
582 return bResult;
583 }
584
585 template <typename T>
586 static inline typename std::enable_if<!EigenIO::is_tensor<T>::value, void>::type
587 WriteMember(std::ostream &os, const T &object) {
588 os << object;
589 }
590
591 template <typename T>
592 static inline typename std::enable_if<EigenIO::is_tensor<T>::value, void>::type
593 WriteMember(std::ostream &os, const T &object) {
594 using Index = typename T::Index;
595 const Index NumElements{object.size()};
596 assert( NumElements > 0 );
597 Index count = 1;
598 os << "T<";
599 for( int i = 0; i < T::NumIndices; i++ ) {
600 Index dim = object.dimension(i);
601 count *= dim;
602 if( i )
603 os << ",";
604 os << dim;
605 }
606 assert( count == NumElements && "Number of elements doesn't match tensor dimensions" );
607 os << ">{";
608 const typename T::Scalar * p = object.data();
609 for( Index i = 0; i < count; i++ ) {
610 if( i )
611 os << ",";
612 os << *p++;
613 }
614 os << "}";
615 }
616 };
617
618 // Generic writer interface //////////////////////////////////////////////////
619 template <typename T>
620 inline void push(Writer<T> &w, const std::string &s) {
621 w.push(s);
622 }
623
624 template <typename T>
625 inline void push(Writer<T> &w, const char *s)
626 {
627 w.push(std::string(s));
628 }
629
630 template <typename T>
631 inline void pop(Writer<T> &w)
632 {
633 w.pop();
634 }
635
636 template <typename T, typename U>
637 inline void write(Writer<T> &w, const std::string& s, const U &output)
638 {
639 w.write(s, output);
640 }
641
642 // Generic reader interface //////////////////////////////////////////////////
643 template <typename T>
644 inline bool push(Reader<T> &r, const std::string &s)
645 {
646 return r.push(s);
647 }
648
649 template <typename T>
650 inline bool push(Reader<T> &r, const char *s)
651 {
652 return r.push(std::string(s));
653 }
654
655 template <typename T>
656 inline void pop(Reader<T> &r)
657 {
658 r.pop();
659 }
660
661 template <typename T, typename U>
662 inline void read(Reader<T> &r, const std::string &s, U &output)
663 {
664 r.read(s, output);
665 }
666}
667
668#endif
std::complex< T > complex
Definition Simd.h:82
#define T2
#define T1
static INTERNAL_PRECISION U
Definition Zolotarev.cc:230
std::enable_if< isGridTensor< S >::value, void >::type copyScalars(S &Dest, const typename GridTypeMapper< S >::scalar_type *&pSource)
Definition BaseIO.h:217
void fromString(U &output, const std::string &s)
Definition BaseIO.h:518
std::enable_if< EigenIO::is_scalar< S >::value, void >::type copyScalars(S &Dest, const S *&pSource)
Definition BaseIO.h:210
std::enable_if< EigenIO::is_tensor_variable< ETensor >::value, void >::type Reshape(ETensor &t, const std::array< typename ETensor::Index, ETensor::NumDimensions > &dims)
void pop(void)
Definition BaseIO.h:385
std::enable_if<!std::is_base_of< Serializable, U >::value &&!EigenIO::is_tensor< U >::value, void >::type read(const std::string &s, U &output)
std::enable_if< EigenIO::is_tensor_fixed< ETensor >::value, void >::type Reshape(ETensor &t, const std::array< typename ETensor::Index, ETensor::NumDimensions > &dims)
Definition BaseIO.h:496
Reader(void)
Definition BaseIO.h:373
virtual ~Reader(void)=default
std::enable_if< std::is_base_of< Serializable, U >::value, void >::type read(const std::string &s, U &output)
Definition BaseIO.h:393
bool push(const std::string &s)
Definition BaseIO.h:379
static std::enable_if< EigenIO::is_tensor< T >::value, void >::type WriteMember(std::ostream &os, const T &object)
Definition BaseIO.h:593
static void read(Reader< T > &RD, const std::string &s, Serializable &obj)
Definition BaseIO.h:545
static std::enable_if<!EigenIO::is_tensor< T1 >::value||!EigenIO::is_tensor< T2 >::value, bool >::type CompareMember(const T1 &lhs, const T2 &rhs)
Definition BaseIO.h:557
static void write(Writer< T > &WR, const std::string &s, const Serializable &obj)
Definition BaseIO.h:540
friend std::ostream & operator<<(std::ostream &os, const Serializable &obj)
Definition BaseIO.h:549
static std::enable_if<!EigenIO::is_tensor< T >::value, void >::type WriteMember(std::ostream &os, const T &object)
Definition BaseIO.h:587
static std::enable_if< EigenIO::is_tensor< T1 >::value &&EigenIO::is_tensor< T2 >::value, bool >::type CompareMember(const T1 &lhs, const T2 &rhs)
Definition BaseIO.h:563
static std::enable_if< EigenIO::is_tensor< T >::value, bool >::type CompareMember(const std::vector< T > &lhs, const std::vector< T > &rhs)
Definition BaseIO.h:577
std::enable_if< EigenIO::is_scalar< S >::value, void >::type copyScalars(S *&pCopy, const S &Source)
Definition BaseIO.h:152
std::enable_if< std::is_base_of< Serializable, U >::value >::type write(const std::string &s, const U &output)
Definition BaseIO.h:260
std::enable_if< isGridTensor< S >::value, void >::type copyScalars(typename GridTypeMapper< S >::scalar_type *&pCopy, const S &Source)
Definition BaseIO.h:159
void push(const std::string &s)
Definition BaseIO.h:246
unsigned int getPrecision(void)
Definition BaseIO.h:366
bool scientific_
Definition BaseIO.h:171
void pop(void)
Definition BaseIO.h:252
void setPrecision(const unsigned int prec)
Definition BaseIO.h:360
Writer(void)
Definition BaseIO.h:240
void scientificFormat(const bool set)
Definition BaseIO.h:348
bool isScientific(void)
Definition BaseIO.h:354
std::enable_if<!std::is_base_of< Serializable, U >::value &&!EigenIO::is_tensor< U >::value >::type write(const std::string &s, const U &output)
virtual ~Writer(void)=default
unsigned int prec_
Definition BaseIO.h:172
std::enable_if< is_tensor< ET >::value, consttypenameET::Index >::type getScalarCount(const ET &eigenTensor)
Definition BaseIO.h:102
std::enable_if< is_tensor_of_scalar< ET >::value, consttypenameET::Scalar * >::type getFirstScalar(const ET &eigenTensor)
Definition BaseIO.h:105
std::uint64_t EigenResizeCounter
void pop(Writer< T > &w)
Definition BaseIO.h:631
void read(Reader< T > &r, const std::string &s, U &output)
Definition BaseIO.h:662
TensorToVec< T >::type tensorToVec(const T &t)
void push(Writer< T > &w, const std::string &s)
Definition BaseIO.h:620
void write(Writer< T > &w, const std::string &s, const U &output)
Definition BaseIO.h:637
void vecToTensor(T &t, const typename TensorToVec< T >::type &v)
static const bool value
Definition BaseIO.h:232
static const bool value
Definition BaseIO.h:235