1 //=================================================================================================
2 /*!
3 //  \file blaze/math/serialization/MatrixSerializer.h
4 //  \brief Serialization of dense and sparse matrices
5 //
6 //  Copyright (C) 2012-2020 Klaus Iglberger - All Rights Reserved
7 //
8 //  This file is part of the Blaze library. You can redistribute it and/or modify it under
9 //  the terms of the New (Revised) BSD License. Redistribution and use in source and binary
10 //  forms, with or without modification, are permitted provided that the following conditions
11 //  are met:
12 //
13 //  1. Redistributions of source code must retain the above copyright notice, this list of
14 //     conditions and the following disclaimer.
15 //  2. Redistributions in binary form must reproduce the above copyright notice, this list
16 //     of conditions and the following disclaimer in the documentation and/or other materials
17 //     provided with the distribution.
18 //  3. Neither the names of the Blaze development group nor the names of its contributors
19 //     may be used to endorse or promote products derived from this software without specific
20 //     prior written permission.
21 //
22 //  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
23 //  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 //  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25 //  SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 //  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27 //  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 //  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 //  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 //  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 //  DAMAGE.
32 */
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_SERIALIZATION_MATRIXSERIALIZER_H_
36 #define _BLAZE_MATH_SERIALIZATION_MATRIXSERIALIZER_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <blaze/math/Aliases.h>
44 #include <blaze/math/constraints/Matrix.h>
45 #include <blaze/math/dense/DynamicMatrix.h>
46 #include <blaze/math/Exception.h>
47 #include <blaze/math/expressions/DenseMatrix.h>
48 #include <blaze/math/expressions/SparseMatrix.h>
49 #include <blaze/math/expressions/Matrix.h>
50 #include <blaze/math/serialization/TypeValueMapping.h>
51 #include <blaze/math/sparse/CompressedMatrix.h>
52 #include <blaze/math/typetraits/IsDenseMatrix.h>
53 #include <blaze/math/typetraits/IsResizable.h>
54 #include <blaze/math/typetraits/IsRowMajorMatrix.h>
55 #include <blaze/util/Assert.h>
56 #include <blaze/util/EnableIf.h>
57 #include <blaze/util/Types.h>
58 #include <blaze/util/typetraits/IsNumeric.h>
59 
60 
61 namespace blaze {
62 
63 //=================================================================================================
64 //
65 //  CLASS DEFINITION
66 //
67 //=================================================================================================
68 
69 //*************************************************************************************************
70 /*!\brief Serializer for dense and sparse matrices.
71 // \ingroup math_serialization
72 //
73 // The MatrixSerializer implements the necessary logic to serialize dense and sparse matrices,
74 // i.e. to convert them into a portable, binary representation. The following example demonstrates
75 // the (de-)serialization process of matrices:
76 
77    \code
78    using blaze::rowMajor;
79    using blaze::columnMajor;
80 
81    // Serialization of both matrices
82    {
83       blaze::StaticMatrix<double,3UL,5UL,rowMajor> D;
84       blaze::CompressedMatrix<int,columnMajor> S;
85 
86       // ... Resizing and initialization
87 
88       // Creating an archive that writes into a the file "matrices.blaze"
89       blaze::Archive<std::ofstream> archive( "matrices.blaze" );
90 
91       // Serialization of both matrices into the same archive. Note that D lies before S!
92       archive << D << S;
93    }
94 
95    // Reconstitution of both matrices
96    {
97       blaze::DynamicMatrix<double,rowMajor> D1;
98       blaze::DynamicMatrix<int,rowMajor> D2;
99 
100       // Creating an archive that reads from the file "matrices.blaze"
101       blaze::Archive<std::ofstream> archive( "matrices.blaze" );
102 
103       // Reconstituting the former D matrix into D1. Note that it is possible to reconstitute
104       // the matrix into a differrent kind of matrix (StaticMatrix -> DynamicMatrix), but that
105       // the type of elements has to be the same.
106       archive >> D1;
107 
108       // Reconstituting the former S matrix into D2. Note that is is even possible to reconstitute
109       // a sparse matrix as a dense matrix (also the reverse is possible) and that a column-major
110       // matrix can be reconstituted as row-major matrix (and vice versa). Note however that also
111       // in this case the type of elements is the same!
112       archive >> D2
113    }
114    \endcode
115 
116 // Note that it is even possible to (de-)serialize matrices with vector or matrix elements:
117 
118    \code
119    // Serialization
120    {
121       blaze::CompressedMatrix< blaze::DynamicMatrix< blaze::complex<double> > > mat;
122 
123       // ... Resizing and initialization
124 
125       // Creating an archive that writes into a the file "matrix.blaze"
126       blaze::Archive<std::ofstream> archive( "matrix.blaze" );
127 
128       // Serialization of the matrix into the archive
129       archive << mat;
130    }
131 
132    // Deserialization
133    {
134       blaze::CompressedMatrix< blaze::DynamicMatrix< blaze::complex<double> > > mat;
135 
136       // Creating an archive that reads from the file "matrix.blaze"
137       blaze::Archive<std::ofstream> archive( "matrix.blaze" );
138 
139       // Reconstitution of the matrix from the archive
140       archive >> mat;
141    }
142    \endcode
143 
144 // As the examples demonstrates, the matrix serialization offers an enormous flexibility. However,
145 // several actions result in errors:
146 //
147 //  - matrices cannot be reconstituted as vectors (and vice versa)
148 //  - the element type of the serialized and reconstituted matrix must match, which means
149 //    that on the source and destination platform the general type (signed/unsigned integral
150 //    or floating point) and the size of the type must be exactly the same
151 //  - when reconstituting a StaticMatrix, the number of rows and columns must match those of
152 //    the serialized matrix
153 //
154 // In case an error is encountered during (de-)serialization, a \a std::runtime_exception is
155 // thrown.
156 */
157 class MatrixSerializer
158 {
159  private:
160    //**Private class MatrixValueMappingHelper******************************************************
161    /*! \cond BLAZE_INTERNAL */
162    /*!\brief Auxiliary helper class for the MatrixValueMapping class template.
163    //
164    // The MatrixValueMapping class template is an auxiliary class for the MatrixSerializer. It
165    // maps a matrix type into an integral representation. For the mapping, the following bit
166    // mapping is used:
167 
168       \code
169       0x01 - Vector/Matrix flag
170       0x02 - Dense/Sparse flag
171       0x04 - Row-/Column-major flag
172       \endcode
173    */
174    template< bool IsDenseMatrix, bool IsRowMajorMatrix >
175    struct MatrixValueMappingHelper;
176    /*! \endcond */
177    //**********************************************************************************************
178 
179    //**Private class MatrixValueMapping************************************************************
180    /*! \cond BLAZE_INTERNAL */
181    /*!\brief Serialization of the type of a matrix.
182    //
183    // This class template converts the given matrix type into an integral representation suited
184    // for serialization. Depending on the given matrix type, the \a value member enumeration is
185    // set to the according integral representation.
186    */
187    template< typename T >
188    struct MatrixValueMapping
189    {
190       enum { value = MatrixValueMappingHelper< IsDenseMatrix_v<T>, IsRowMajorMatrix_v<T> >::value };
191       BLAZE_CONSTRAINT_MUST_BE_MATRIX_TYPE( T );
192    };
193    /*! \endcond */
194    //**********************************************************************************************
195 
196  public:
197    //**Constructors********************************************************************************
198    /*!\name Constructors */
199    //@{
200    inline MatrixSerializer();
201    //@}
202    //**********************************************************************************************
203 
204    //**Serialization functions*********************************************************************
205    /*!\name Serialization functions */
206    //@{
207    template< typename Archive, typename MT, bool SO >
208    void serialize( Archive& archive, const Matrix<MT,SO>& mat );
209    //@}
210    //**********************************************************************************************
211 
212    //**Deserialization functions*******************************************************************
213    /*!\name Deserialization functions */
214    //@{
215    template< typename Archive, typename MT, bool SO >
216    void deserialize( Archive& archive, Matrix<MT,SO>& mat );
217    //@}
218    //**********************************************************************************************
219 
220  private:
221    //**Serialization functions*********************************************************************
222    /*!\name Serialization functions */
223    //@{
224    template< typename Archive, typename MT >
225    void serializeHeader( Archive& archive, const MT& mat );
226 
227    template< typename Archive, typename MT, bool SO >
228    void serializeMatrix( Archive& archive, const DenseMatrix<MT,SO>& mat );
229 
230    template< typename Archive, typename MT, bool SO >
231    void serializeMatrix( Archive& archive, const SparseMatrix<MT,SO>& mat );
232    //@}
233    //**********************************************************************************************
234 
235    //**Deserialization functions*******************************************************************
236    /*!\name Deserialization functions */
237    //@{
238    template< typename Archive, typename MT >
239    void deserializeHeader( Archive& archive, const MT& mat );
240 
241    template< typename MT, bool SO >
242    DisableIf_t< IsResizable_v<MT> > prepareMatrix( DenseMatrix<MT,SO>& mat );
243 
244    template< typename MT, bool SO >
245    DisableIf_t< IsResizable_v<MT> > prepareMatrix( SparseMatrix<MT,SO>& mat );
246 
247    template< typename MT >
248    EnableIf_t< IsResizable_v<MT> > prepareMatrix( MT& mat );
249 
250    template< typename Archive, typename MT >
251    void deserializeMatrix( Archive& archive, MT& mat );
252 
253    template< typename Archive, typename MT >
254    EnableIf_t< MT::simdEnabled >
255       deserializeDenseRowMatrix( Archive& archive, DenseMatrix<MT,rowMajor>& mat );
256 
257    template< typename Archive, typename MT, bool SO >
258    void deserializeDenseRowMatrix( Archive& archive, DenseMatrix<MT,SO>& mat );
259 
260    template< typename Archive, typename MT, bool SO >
261    DisableIf_t< IsNumeric_v< ElementType_t<MT> > >
262       deserializeDenseRowMatrix( Archive& archive, SparseMatrix<MT,SO>& mat );
263 
264    template< typename Archive, typename MT, bool SO >
265    EnableIf_t< IsNumeric_v< ElementType_t<MT> > >
266       deserializeDenseRowMatrix( Archive& archive, SparseMatrix<MT,SO>& mat );
267 
268    template< typename Archive, typename MT >
269    EnableIf_t< MT::simdEnabled>
270       deserializeDenseColumnMatrix( Archive& archive, DenseMatrix<MT,columnMajor>& mat );
271 
272    template< typename Archive, typename MT, bool SO >
273    void deserializeDenseColumnMatrix( Archive& archive, DenseMatrix<MT,SO>& mat );
274 
275    template< typename Archive, typename MT, bool SO >
276    DisableIf_t< IsNumeric_v< ElementType_t<MT> > >
277       deserializeDenseColumnMatrix( Archive& archive, SparseMatrix<MT,SO>& mat );
278 
279    template< typename Archive, typename MT, bool SO >
280    EnableIf_t< IsNumeric_v< ElementType_t<MT> > >
281       deserializeDenseColumnMatrix( Archive& archive, SparseMatrix<MT,SO>& mat );
282 
283    template< typename Archive, typename MT, bool SO >
284    void deserializeSparseRowMatrix( Archive& archive, DenseMatrix<MT,SO>& mat );
285 
286    template< typename Archive, typename MT >
287    void deserializeSparseRowMatrix( Archive& archive, SparseMatrix<MT,rowMajor>& mat );
288 
289    template< typename Archive, typename MT >
290    void deserializeSparseRowMatrix( Archive& archive, SparseMatrix<MT,columnMajor>& mat );
291 
292    template< typename Archive, typename MT, bool SO >
293    void deserializeSparseColumnMatrix( Archive& archive, DenseMatrix<MT,SO>& mat );
294 
295    template< typename Archive, typename MT >
296    void deserializeSparseColumnMatrix( Archive& archive, SparseMatrix<MT,rowMajor>& mat );
297 
298    template< typename Archive, typename MT >
299    void deserializeSparseColumnMatrix( Archive& archive, SparseMatrix<MT,columnMajor>& mat );
300    //@}
301    //**********************************************************************************************
302 
303    //**Member variables****************************************************************************
304    /*!\name Member variables */
305    //@{
306    uint8_t  version_;      //!< The version of the archive.
307    uint8_t  type_;         //!< The type of the matrix.
308    uint8_t  elementType_;  //!< The type of an element.
309    uint8_t  elementSize_;  //!< The size in bytes of a single element of the matrix.
310    uint64_t rows_;         //!< The number of rows of the matrix.
311    uint64_t columns_;      //!< The number of columns of the matrix.
312    uint64_t number_;       //!< The total number of elements contained in the matrix.
313    //@}
314    //**********************************************************************************************
315 };
316 //*************************************************************************************************
317 
318 
319 
320 
321 //=================================================================================================
322 //
323 //  CONSTRUCTORS
324 //
325 //=================================================================================================
326 
327 //*************************************************************************************************
328 /*!\brief The default constructor of the MatrixSerializer class.
329 */
MatrixSerializer()330 MatrixSerializer::MatrixSerializer()
331    : version_    ( 0U  )  // The version of the archive
332    , type_       ( 0U  )  // The type of the matrix
333    , elementType_( 0U  )  // The type of an element
334    , elementSize_( 0U  )  // The size in bytes of a single element of the matrix
335    , rows_       ( 0UL )  // The number of rows of the matrix
336    , columns_    ( 0UL )  // The number of columns of the matrix
337    , number_     ( 0UL )  // The total number of elements contained in the matrix
338 {}
339 //*************************************************************************************************
340 
341 
342 
343 
344 //=================================================================================================
345 //
346 //  SERIALIZATION FUNCTIONS
347 //
348 //=================================================================================================
349 
350 //*************************************************************************************************
351 /*!\brief Serializes the given matrix and writes it to the archive.
352 //
353 // \param archive The archive to be written.
354 // \param mat The matrix to be serialized.
355 // \return void
356 // \exception std::runtime_error Error during serialization.
357 */
358 template< typename Archive  // Type of the archive
359         , typename MT       // Type of the matrix
360         , bool SO >         // Storage order
serialize(Archive & archive,const Matrix<MT,SO> & mat)361 void MatrixSerializer::serialize( Archive& archive, const Matrix<MT,SO>& mat )
362 {
363    if( !archive ) {
364       BLAZE_THROW_RUNTIME_ERROR( "Faulty archive detected" );
365    }
366 
367    serializeHeader( archive, *mat );
368    serializeMatrix( archive, *mat );
369 }
370 //*************************************************************************************************
371 
372 
373 //*************************************************************************************************
374 /*!\brief Serializes all meta information about the given matrix.
375 //
376 // \param archive The archive to be written.
377 // \param mat The matrix to be serialized.
378 // \return void
379 // \exception std::runtime_error File header could not be serialized.
380 */
381 template< typename Archive  // Type of the archive
382         , typename MT >     // Type of the matrix
serializeHeader(Archive & archive,const MT & mat)383 void MatrixSerializer::serializeHeader( Archive& archive, const MT& mat )
384 {
385    using ET = ElementType_t<MT>;
386 
387    archive << uint8_t ( 1U );
388    archive << uint8_t ( MatrixValueMapping<MT>::value );
389    archive << uint8_t ( TypeValueMapping<ET>::value );
390    archive << uint8_t ( sizeof( ET ) );
391    archive << uint64_t( mat.rows() );
392    archive << uint64_t( mat.columns() );
393    archive << uint64_t( ( IsDenseMatrix_v<MT> ) ? ( mat.rows()*mat.columns() ) : ( mat.nonZeros() ) );
394 
395    if( !archive ) {
396       BLAZE_THROW_RUNTIME_ERROR( "File header could not be serialized" );
397    }
398 }
399 //*************************************************************************************************
400 
401 
402 //*************************************************************************************************
403 /*!\brief Serializes the elements of a dense matrix.
404 //
405 // \param archive The archive to be written.
406 // \param mat The matrix to be serialized.
407 // \return void
408 // \exception std::runtime_error Dense matrix could not be serialized.
409 */
410 template< typename Archive  // Type of the archive
411         , typename MT       // Type of the matrix
412         , bool SO >         // Storage order
serializeMatrix(Archive & archive,const DenseMatrix<MT,SO> & mat)413 void MatrixSerializer::serializeMatrix( Archive& archive, const DenseMatrix<MT,SO>& mat )
414 {
415    if( IsRowMajorMatrix_v<MT> ) {
416       for( size_t i=0UL; i<(*mat).rows(); ++i ) {
417          for( size_t j=0UL; j<(*mat).columns(); ++j ) {
418             archive << (*mat)(i,j);
419          }
420       }
421    }
422    else {
423       for( size_t j=0UL; j<(*mat).columns(); ++j ) {
424          for( size_t i=0UL; i<(*mat).rows(); ++i ) {
425             archive << (*mat)(i,j);
426          }
427       }
428    }
429 
430    if( !archive ) {
431       BLAZE_THROW_RUNTIME_ERROR( "Dense matrix could not be serialized" );
432    }
433 }
434 //*************************************************************************************************
435 
436 
437 //*************************************************************************************************
438 /*!\brief Serializes the elements of a sparse matrix.
439 //
440 // \param archive The archive to be written.
441 // \param mat The matrix to be serialized.
442 // \return void
443 // \exception std::runtime_error Sparse matrix could not be serialized.
444 */
445 template< typename Archive  // Type of the archive
446         , typename MT       // Type of the matrix
447         , bool SO >         // Storage order
serializeMatrix(Archive & archive,const SparseMatrix<MT,SO> & mat)448 void MatrixSerializer::serializeMatrix( Archive& archive, const SparseMatrix<MT,SO>& mat )
449 {
450    if( IsRowMajorMatrix_v<MT> ) {
451       for( size_t i=0UL; i<(*mat).rows(); ++i ) {
452          archive << uint64_t( (*mat).nonZeros( i ) );
453          for( auto element=(*mat).begin(i); element!=(*mat).end(i); ++element ) {
454             archive << element->index() << element->value();
455          }
456       }
457    }
458    else {
459       for( size_t j=0UL; j<(*mat).columns(); ++j ) {
460          archive << uint64_t( (*mat).nonZeros( j ) );
461          for( auto element=(*mat).begin(j); element!=(*mat).end(j); ++element ) {
462             archive << element->index() << element->value();
463          }
464       }
465    }
466 
467    if( !archive ) {
468       BLAZE_THROW_RUNTIME_ERROR( "Sparse matrix could not be serialized" );
469    }
470 }
471 //*************************************************************************************************
472 
473 
474 
475 
476 //=================================================================================================
477 //
478 //  DESERIALIZATION FUNCTIONS
479 //
480 //=================================================================================================
481 
482 //*************************************************************************************************
483 /*!\brief Deserializes a matrix from the given archive.
484 //
485 // \param archive The archive to be read from.
486 // \param mat The matrix to be deserialized.
487 // \return void
488 // \exception std::runtime_error Error during deserialization.
489 */
490 template< typename Archive  // Type of the archive
491         , typename MT       // Type of the matrix
492         , bool SO >         // Storage order
deserialize(Archive & archive,Matrix<MT,SO> & mat)493 void MatrixSerializer::deserialize( Archive& archive, Matrix<MT,SO>& mat )
494 {
495    if( !archive ) {
496       BLAZE_THROW_INVALID_ARGUMENT( "Faulty archive detected" );
497    }
498 
499    deserializeHeader( archive, *mat );
500    prepareMatrix( *mat );
501    deserializeMatrix( archive, *mat );
502 }
503 //*************************************************************************************************
504 
505 
506 //*************************************************************************************************
507 /*!\brief Deserializes all meta information about the given matrix.
508 //
509 // \param archive The archive to be read from.
510 // \param mat The matrix to be deserialized.
511 // \return void
512 // \exception std::runtime_error Error during deserialization.
513 */
514 template< typename Archive  // Type of the archive
515         , typename MT >     // Type of the matrix
deserializeHeader(Archive & archive,const MT & mat)516 void MatrixSerializer::deserializeHeader( Archive& archive, const MT& mat )
517 {
518    using ET = ElementType_t<MT>;
519 
520    if( !( archive >> version_ >> type_ >> elementType_ >> elementSize_ >> rows_ >> columns_ >> number_ ) ) {
521       BLAZE_THROW_RUNTIME_ERROR( "Corrupt archive detected" );
522    }
523    else if( version_ != 1UL ) {
524       BLAZE_THROW_RUNTIME_ERROR( "Invalid version detected" );
525    }
526    else if( ( type_ & 1U ) != 1U || ( type_ & (~7U) ) != 0U ) {
527       BLAZE_THROW_RUNTIME_ERROR( "Invalid matrix type detected" );
528    }
529    else if( elementType_ != TypeValueMapping<ET>::value ) {
530       BLAZE_THROW_RUNTIME_ERROR( "Invalid element type detected" );
531    }
532    else if( elementSize_ != sizeof( ET ) ) {
533       BLAZE_THROW_RUNTIME_ERROR( "Invalid element size detected" );
534    }
535    else if( !IsResizable_v<MT> && ( rows_ != mat.rows() || columns_ != mat.columns() ) ) {
536       BLAZE_THROW_RUNTIME_ERROR( "Invalid matrix size detected" );
537    }
538    else if( number_ > rows_*columns_ ) {
539       BLAZE_THROW_RUNTIME_ERROR( "Invalid number of elements detected" );
540    }
541 }
542 //*************************************************************************************************
543 
544 
545 //*************************************************************************************************
546 /*!\brief Prepares the given non-resizable dense matrix for the deserialization process.
547 //
548 // \param mat The dense matrix to be prepared.
549 // \return void
550 */
551 template< typename MT  // Type of the dense matrix
552         , bool SO >    // Storage order
prepareMatrix(DenseMatrix<MT,SO> & mat)553 DisableIf_t< IsResizable_v<MT> > MatrixSerializer::prepareMatrix( DenseMatrix<MT,SO>& mat )
554 {
555    reset( *mat );
556 }
557 //*************************************************************************************************
558 
559 
560 //*************************************************************************************************
561 /*!\brief Prepares the given non-resizable sparse matrix for the deserialization process.
562 //
563 // \param mat The sparse matrix to be prepared.
564 // \return void
565 */
566 template< typename MT  // Type of the sparse matrix
567         , bool SO >    // Storage order
prepareMatrix(SparseMatrix<MT,SO> & mat)568 DisableIf_t< IsResizable_v<MT> > MatrixSerializer::prepareMatrix( SparseMatrix<MT,SO>& mat )
569 {
570    (*mat).reserve( number_ );
571    reset( *mat );
572 }
573 //*************************************************************************************************
574 
575 
576 //*************************************************************************************************
577 /*!\brief Prepares the given resizable matrix for the deserialization process.
578 //
579 // \param mat The matrix to be prepared.
580 // \return void
581 */
582 template< typename MT >  // Type of the matrix
prepareMatrix(MT & mat)583 EnableIf_t< IsResizable_v<MT> > MatrixSerializer::prepareMatrix( MT& mat )
584 {
585    mat.resize ( rows_, columns_, false );
586    mat.reserve( number_ );
587    reset( mat );
588 }
589 //*************************************************************************************************
590 
591 
592 //*************************************************************************************************
593 /*!\brief Deserializes a matrix from the archive.
594 //
595 // \param archive The archive to be read from.
596 // \param mat The matrix to be reconstituted.
597 // \return void
598 // \exception std::runtime_error Error during deserialization.
599 //
600 // This function deserializes the contents of the matrix from the archive and reconstitutes the
601 // given matrix.
602 */
603 template< typename Archive  // Type of the archive
604         , typename MT >     // Type of the matrix
deserializeMatrix(Archive & archive,MT & mat)605 void MatrixSerializer::deserializeMatrix( Archive& archive, MT& mat )
606 {
607    if( type_ == 1U ) {
608       deserializeDenseRowMatrix( archive, *mat );
609    }
610    else if( type_ == 5UL ) {
611       deserializeDenseColumnMatrix( archive, *mat );
612    }
613    else if( type_ == 3UL ) {
614       deserializeSparseRowMatrix( archive, *mat );
615    }
616    else if( type_ == 7UL ) {
617       deserializeSparseColumnMatrix( archive, *mat );
618    }
619    else {
620       BLAZE_INTERNAL_ASSERT( false, "Undefined type flag" );
621    }
622 }
623 //*************************************************************************************************
624 
625 
626 //*************************************************************************************************
627 /*!\brief Deserializes a row-major dense matrix from the archive.
628 //
629 // \param archive The archive to be read from.
630 // \param mat The dense matrix to be reconstituted.
631 // \return void
632 // \exception std::runtime_error Dense matrix could not be deserialized.
633 //
634 // This function deserializes a row-major dense matrix from the archive and reconstitutes
635 // the given row-major dense matrix. In case any error is detected during the deserialization
636 // process, a \a std::runtime_error is thrown.
637 */
638 template< typename Archive  // Type of the archive
639         , typename MT >     // Type of the matrix
640 EnableIf_t< MT::simdEnabled >
deserializeDenseRowMatrix(Archive & archive,DenseMatrix<MT,rowMajor> & mat)641    MatrixSerializer::deserializeDenseRowMatrix( Archive& archive, DenseMatrix<MT,rowMajor>& mat )
642 {
643    if( columns_ == 0UL ) return;
644 
645    for( size_t i=0UL; i<rows_; ++i ) {
646       archive.read( &(*mat)(i,0), columns_ );
647    }
648 
649    if( !archive ) {
650       BLAZE_THROW_RUNTIME_ERROR( "Dense matrix could not be deserialized" );
651    }
652 }
653 //*************************************************************************************************
654 
655 
656 //*************************************************************************************************
657 /*!\brief Deserializes a row-major dense matrix from the archive.
658 //
659 // \param archive The archive to be read from.
660 // \param mat The dense matrix to be reconstituted.
661 // \return void
662 // \exception std::runtime_error Dense matrix could not be deserialized.
663 //
664 // This function deserializes a row-major dense matrix from the archive and reconstitutes
665 // the given dense matrix. In case any error is detected during the deserialization process,
666 // a \a std::runtime_error is thrown.
667 */
668 template< typename Archive  // Type of the archive
669         , typename MT       // Type of the matrix
670         , bool SO >         // Storage order
deserializeDenseRowMatrix(Archive & archive,DenseMatrix<MT,SO> & mat)671 void MatrixSerializer::deserializeDenseRowMatrix( Archive& archive, DenseMatrix<MT,SO>& mat )
672 {
673    using ET = ElementType_t<MT>;
674 
675    ET value{};
676 
677    for( size_t i=0UL; i<rows_; ++i ) {
678       size_t j( 0UL );
679       while( ( j != columns_ ) && ( archive >> value ) ) {
680          (*mat)(i,j) = value;
681          ++j;
682       }
683    }
684 
685    if( !archive ) {
686       BLAZE_THROW_RUNTIME_ERROR( "Dense matrix could not be deserialized" );
687    }
688 }
689 //*************************************************************************************************
690 
691 
692 //*************************************************************************************************
693 /*!\brief Deserializes a row-major dense matrix from the archive.
694 //
695 // \param archive The archive to be read from.
696 // \param mat The dense matrix to be reconstituted.
697 // \return void
698 // \exception std::runtime_error Sparse matrix could not be deserialized.
699 //
700 // This function deserializes a row-major dense matrix from the archive and reconstitutes
701 // the given sparse matrix. In case any error is detected during the deserialization
702 // process, a \a std::runtime_error is thrown.
703 */
704 template< typename Archive  // Type of the archive
705         , typename MT       // Type of the matrix
706         , bool SO >         // Storage order
707 EnableIf_t< IsNumeric_v< ElementType_t<MT> > >
deserializeDenseRowMatrix(Archive & archive,SparseMatrix<MT,SO> & mat)708    MatrixSerializer::deserializeDenseRowMatrix( Archive& archive, SparseMatrix<MT,SO>& mat )
709 {
710    DynamicMatrix< ElementType_t<MT>, rowMajor > tmp( rows_, columns_ );
711    deserializeDenseRowMatrix( archive, tmp );
712    (*mat) = tmp;
713 
714    if( !archive ) {
715       BLAZE_THROW_RUNTIME_ERROR( "Sparse matrix could not be deserialized" );
716    }
717 }
718 //*************************************************************************************************
719 
720 
721 //*************************************************************************************************
722 /*!\brief Deserializes a row-major dense matrix from the archive.
723 //
724 // \param archive The archive to be read from.
725 // \param mat The dense matrix to be reconstituted.
726 // \return void
727 // \exception std::runtime_error Sparse matrix could not be deserialized.
728 //
729 // This function deserializes a row-major dense matrix from the archive and reconstitutes
730 // the given sparse matrix. In case any error is detected during the deserialization
731 // process, a \a std::runtime_error is thrown.
732 */
733 template< typename Archive  // Type of the archive
734         , typename MT       // Type of the matrix
735         , bool SO >         // Storage order
736 DisableIf_t< IsNumeric_v< ElementType_t<MT> > >
deserializeDenseRowMatrix(Archive & archive,SparseMatrix<MT,SO> & mat)737    MatrixSerializer::deserializeDenseRowMatrix( Archive& archive, SparseMatrix<MT,SO>& mat )
738 {
739    using ET = ElementType_t<MT>;
740 
741    ET value{};
742 
743    const size_t dim1( ( SO == rowMajor )?( rows_ ):( columns_ ) );
744    const size_t dim2( ( SO != rowMajor )?( rows_ ):( columns_ ) );
745 
746    for( size_t i=0UL; i<dim1; ++i ) {
747       (*mat).reserve( i, dim2 );
748    }
749 
750    for( size_t i=0UL; i<rows_; ++i ) {
751       size_t j( 0UL );
752       while( ( j != columns_ ) && ( archive >> value ) ) {
753          (*mat).append( i, j, value, false );
754          ++j;
755       }
756    }
757 
758    if( !archive ) {
759       BLAZE_THROW_RUNTIME_ERROR( "Sparse matrix could not be deserialized" );
760    }
761 }
762 //*************************************************************************************************
763 
764 
765 //*************************************************************************************************
766 /*!\brief Deserializes a column-major dense matrix from the archive.
767 //
768 // \param archive The archive to be read from.
769 // \param mat The dense matrix to be reconstituted.
770 // \return void
771 // \exception std::runtime_error Dense matrix could not be deserialized.
772 //
773 // This function deserializes a column-major dense matrix from the archive and reconstitutes
774 // the given column-major dense matrix. In case any error is detected during the deserialization
775 // process, a \a std::runtime_error is thrown.
776 */
777 template< typename Archive  // Type of the archive
778         , typename MT >     // Type of the matrix
779 EnableIf_t< MT::simdEnabled >
deserializeDenseColumnMatrix(Archive & archive,DenseMatrix<MT,columnMajor> & mat)780    MatrixSerializer::deserializeDenseColumnMatrix( Archive& archive, DenseMatrix<MT,columnMajor>& mat )
781 {
782    if( rows_ == 0UL ) return;
783 
784    for( size_t j=0UL; j<columns_; ++j ) {
785       archive.read( &(*mat)(0,j), rows_ );
786    }
787 
788    if( !archive ) {
789       BLAZE_THROW_RUNTIME_ERROR( "Dense matrix could not be deserialized" );
790    }
791 }
792 //*************************************************************************************************
793 
794 
795 //*************************************************************************************************
796 /*!\brief Deserializes a column-major dense matrix from the archive.
797 //
798 // \param archive The archive to be read from.
799 // \param mat The dense matrix to be reconstituted.
800 // \return void
801 // \exception std::runtime_error Dense matrix could not be deserialized.
802 //
803 // This function deserializes a column-major dense matrix from the archive and reconstitutes
804 // the given dense matrix. In case any error is detected during the deserialization process,
805 // a \a std::runtime_error is thrown.
806 */
807 template< typename Archive  // Type of the archive
808         , typename MT       // Type of the matrix
809         , bool SO >         // Storage order
deserializeDenseColumnMatrix(Archive & archive,DenseMatrix<MT,SO> & mat)810 void MatrixSerializer::deserializeDenseColumnMatrix( Archive& archive, DenseMatrix<MT,SO>& mat )
811 {
812    using ET = ElementType_t<MT>;
813 
814    ET value{};
815 
816    for( size_t j=0UL; j<columns_; ++j ) {
817       size_t i( 0UL );
818       while( ( i != rows_ ) && ( archive >> value ) ) {
819          (*mat)(i,j) = value;
820          ++i;
821       }
822    }
823 
824    if( !archive ) {
825       BLAZE_THROW_RUNTIME_ERROR( "Dense matrix could not be deserialized" );
826    }
827 }
828 //*************************************************************************************************
829 
830 
831 //*************************************************************************************************
832 /*!\brief Deserializes a column-major dense matrix from the archive.
833 //
834 // \param archive The archive to be read from.
835 // \param mat The sparse matrix to be reconstituted.
836 // \return void
837 // \exception std::runtime_error Sparse matrix could not be deserialized.
838 //
839 // This function deserializes a column-major dense matrix from the archive and reconstitutes
840 // the given sparse matrix. In case any error is detected during the deserialization process,
841 // a \a std::runtime_error is thrown.
842 */
843 template< typename Archive  // Type of the archive
844         , typename MT       // Type of the matrix
845         , bool SO >         // Storage order
846 EnableIf_t< IsNumeric_v< ElementType_t<MT> > >
deserializeDenseColumnMatrix(Archive & archive,SparseMatrix<MT,SO> & mat)847    MatrixSerializer::deserializeDenseColumnMatrix( Archive& archive, SparseMatrix<MT,SO>& mat )
848 {
849    DynamicMatrix< ElementType_t<MT>, columnMajor > tmp( rows_, columns_ );
850    deserializeDenseColumnMatrix( archive, tmp );
851    (*mat) = tmp;
852 
853    if( !archive ) {
854       BLAZE_THROW_RUNTIME_ERROR( "Sparse matrix could not be deserialized" );
855    }
856 }
857 //*************************************************************************************************
858 
859 
860 //*************************************************************************************************
861 /*!\brief Deserializes a column-major dense matrix from the archive.
862 //
863 // \param archive The archive to be read from.
864 // \param mat The sparse matrix to be reconstituted.
865 // \return void
866 // \exception std::runtime_error Sparse matrix could not be deserialized.
867 //
868 // This function deserializes a column-major dense matrix from the archive and reconstitutes
869 // the given sparse matrix. In case any error is detected during the deserialization process,
870 // a \a std::runtime_error is thrown.
871 */
872 template< typename Archive  // Type of the archive
873         , typename MT       // Type of the matrix
874         , bool SO >         // Storage order
875 DisableIf_t< IsNumeric_v< ElementType_t<MT> > >
deserializeDenseColumnMatrix(Archive & archive,SparseMatrix<MT,SO> & mat)876    MatrixSerializer::deserializeDenseColumnMatrix( Archive& archive, SparseMatrix<MT,SO>& mat )
877 {
878    using ET = ElementType_t<MT>;
879 
880    ET value{};
881 
882    const size_t dim1( ( SO == rowMajor )?( rows_ ):( columns_ ) );
883    const size_t dim2( ( SO != rowMajor )?( rows_ ):( columns_ ) );
884 
885    for( size_t i=0UL; i<dim1; ++i ) {
886       (*mat).reserve( i, dim2 );
887    }
888 
889    for( size_t j=0UL; j<columns_; ++j ) {
890       size_t i( 0UL );
891       while( ( i != rows_ ) && ( archive >> value ) ) {
892          (*mat).append( i, j, value, false );
893          ++i;
894       }
895    }
896 
897    if( !archive ) {
898       BLAZE_THROW_RUNTIME_ERROR( "Sparse matrix could not be deserialized" );
899    }
900 }
901 //*************************************************************************************************
902 
903 
904 //*************************************************************************************************
905 /*!\brief Deserializes a row-major sparse matrix from the archive.
906 //
907 // \param archive The archive to be read from.
908 // \param mat The matrix to be reconstituted.
909 // \return void
910 // \exception std::runtime_error Dense matrix could not be deserialized.
911 //
912 // This function deserializes a row-major sparse matrix from the archive and reconstitutes
913 // the given dense matrix. In case any error is detected during the deserialization process,
914 // a \a std::runtime_error is thrown.
915 */
916 template< typename Archive  // Type of the archive
917         , typename MT       // Type of the matrix
918         , bool SO >         // Storage order
deserializeSparseRowMatrix(Archive & archive,DenseMatrix<MT,SO> & mat)919 void MatrixSerializer::deserializeSparseRowMatrix( Archive& archive, DenseMatrix<MT,SO>& mat )
920 {
921    using ET = ElementType_t<MT>;
922 
923    uint64_t number( 0UL );
924    size_t   index ( 0UL );
925    ET       value {};
926 
927    for( size_t i=0UL; i<rows_; ++i ) {
928       archive >> number;
929       size_t j( 0UL );
930       while( ( j != number ) && ( archive >> index >> value ) ) {
931          (*mat)(i,index) = value;
932          ++j;
933       }
934    }
935 
936    if( !archive ) {
937       BLAZE_THROW_RUNTIME_ERROR( "Dense matrix could not be deserialized" );
938    }
939 }
940 //*************************************************************************************************
941 
942 
943 //*************************************************************************************************
944 /*!\brief Deserializes a row-major sparse matrix from the archive.
945 //
946 // \param archive The archive to be read from.
947 // \param mat The matrix to be reconstituted.
948 // \return void
949 // \exception std::runtime_error Sparse matrix could not be deserialized.
950 //
951 // This function deserializes a row-major sparse matrix from the archive and reconstitutes
952 // the given row-major sparse matrix. In case any error is detected during the deserialization
953 // process, a \a std::runtime_error is thrown.
954 */
955 template< typename Archive  // Type of the archive
956         , typename MT >     // Type of the matrix
deserializeSparseRowMatrix(Archive & archive,SparseMatrix<MT,rowMajor> & mat)957 void MatrixSerializer::deserializeSparseRowMatrix( Archive& archive, SparseMatrix<MT,rowMajor>& mat )
958 {
959    using ET = ElementType_t<MT>;
960 
961    uint64_t number( 0UL );
962    size_t   index ( 0UL );
963    ET       value {};
964 
965    for( size_t i=0UL; i<rows_; ++i )
966    {
967       archive >> number;
968 
969       size_t j( 0UL );
970       while( ( j != number ) && ( archive >> index >> value ) ) {
971          (*mat).append( i, index, value, false );
972          ++j;
973       }
974 
975       (*mat).finalize( i );
976    }
977 
978    if( !archive ) {
979       BLAZE_THROW_RUNTIME_ERROR( "Sparse matrix could not be deserialized" );
980    }
981 }
982 //*************************************************************************************************
983 
984 
985 //*************************************************************************************************
986 /*!\brief Deserializes a row-major sparse matrix from the archive.
987 //
988 // \param archive The archive to be read from.
989 // \param mat The matrix to be reconstituted.
990 // \return void
991 // \exception std::runtime_error Sparse matrix could not be deserialized.
992 //
993 // This function deserializes a row-major sparse matrix from the archive and reconstitutes
994 // the given column-major sparse matrix. In case any error is detected during the deserialization
995 // process, a \a std::runtime_error is thrown.
996 */
997 template< typename Archive  // Type of the archive
998         , typename MT >     // Type of the matrix
deserializeSparseRowMatrix(Archive & archive,SparseMatrix<MT,columnMajor> & mat)999 void MatrixSerializer::deserializeSparseRowMatrix( Archive& archive, SparseMatrix<MT,columnMajor>& mat )
1000 {
1001    CompressedMatrix< ElementType_t<MT>, rowMajor > tmp( rows_, columns_, number_ );
1002    deserializeSparseRowMatrix( archive, tmp );
1003    (*mat) = tmp;
1004 
1005    if( !archive ) {
1006       BLAZE_THROW_RUNTIME_ERROR( "Sparse matrix could not be deserialized" );
1007    }
1008 }
1009 //*************************************************************************************************
1010 
1011 
1012 //*************************************************************************************************
1013 /*!\brief Deserializes a column-major sparse matrix from the archive.
1014 //
1015 // \param archive The archive to be read from.
1016 // \param mat The matrix to be reconstituted.
1017 // \return void
1018 // \exception std::runtime_error Dense matrix could not be deserialized.
1019 //
1020 // This function deserializes a column-major sparse matrix from the archive and reconstitutes
1021 // the given dense matrix. In case any error is detected during the deserialization process,
1022 // a \a std::runtime_error is thrown.
1023 */
1024 template< typename Archive  // Type of the archive
1025         , typename MT       // Type of the matrix
1026         , bool SO >         // Storage order
deserializeSparseColumnMatrix(Archive & archive,DenseMatrix<MT,SO> & mat)1027 void MatrixSerializer::deserializeSparseColumnMatrix( Archive& archive, DenseMatrix<MT,SO>& mat )
1028 {
1029    using ET = ElementType_t<MT>;
1030 
1031    uint64_t number( 0UL );
1032    size_t   index ( 0UL );
1033    ET       value {};
1034 
1035    for( size_t j=0UL; j<columns_; ++j ) {
1036       archive >> number;
1037       size_t i( 0UL );
1038       while( ( i != number ) && ( archive >> index >> value ) ) {
1039          (*mat)(index,j) = value;
1040          ++i;
1041       }
1042    }
1043 
1044    if( !archive ) {
1045       BLAZE_THROW_RUNTIME_ERROR( "Dense matrix could not be deserialized" );
1046    }
1047 }
1048 //*************************************************************************************************
1049 
1050 
1051 //*************************************************************************************************
1052 /*!\brief Deserializes a column-major sparse matrix from the archive.
1053 //
1054 // \param archive The archive to be read from.
1055 // \param mat The matrix to be reconstituted.
1056 // \return void
1057 // \exception std::runtime_error Sparse matrix could not be deserialized.
1058 //
1059 // This function deserializes a column-major sparse matrix from the archive and reconstitutes
1060 // the given row-major sparse matrix. In case any error is detected during the deserialization
1061 // process, a \a std::runtime_error is thrown.
1062 */
1063 template< typename Archive  // Type of the archive
1064         , typename MT >     // Type of the matrix
deserializeSparseColumnMatrix(Archive & archive,SparseMatrix<MT,rowMajor> & mat)1065 void MatrixSerializer::deserializeSparseColumnMatrix( Archive& archive, SparseMatrix<MT,rowMajor>& mat )
1066 {
1067    CompressedMatrix< ElementType_t<MT>, columnMajor > tmp( rows_, columns_, number_ );
1068    deserializeSparseColumnMatrix( archive, tmp );
1069    (*mat) = tmp;
1070 
1071    if( !archive ) {
1072       BLAZE_THROW_RUNTIME_ERROR( "Sparse matrix could not be deserialized" );
1073    }
1074 }
1075 //*************************************************************************************************
1076 
1077 
1078 //*************************************************************************************************
1079 /*!\brief Deserializes a column-major sparse matrix from the archive.
1080 //
1081 // \param archive The archive to be read from.
1082 // \param mat The matrix to be reconstituted.
1083 // \return void
1084 // \exception std::runtime_error Sparse matrix could not be deserialized.
1085 //
1086 // This function deserializes a column-major sparse matrix from the archive and reconstitutes
1087 // the given column-major sparse matrix. In case any error is detected during the deserialization
1088 // process, a \a std::runtime_error is thrown.
1089 */
1090 template< typename Archive  // Type of the archive
1091         , typename MT >     // Type of the matrix
deserializeSparseColumnMatrix(Archive & archive,SparseMatrix<MT,columnMajor> & mat)1092 void MatrixSerializer::deserializeSparseColumnMatrix( Archive& archive, SparseMatrix<MT,columnMajor>& mat )
1093 {
1094    using ET = ElementType_t<MT>;
1095 
1096    uint64_t number( 0UL );
1097    size_t   index ( 0UL );
1098    ET       value {};
1099 
1100    for( size_t j=0UL; j<columns_; ++j )
1101    {
1102       archive >> number;
1103 
1104       size_t i( 0UL );
1105       while( ( i != number ) && ( archive >> index >> value ) ) {
1106          (*mat).append( index, j, value, false );
1107          ++i;
1108       }
1109 
1110       (*mat).finalize( j );
1111    }
1112 
1113    if( !archive ) {
1114       BLAZE_THROW_RUNTIME_ERROR( "Sparse matrix could not be deserialized" );
1115    }
1116 }
1117 //*************************************************************************************************
1118 
1119 
1120 
1121 
1122 //=================================================================================================
1123 //
1124 //  MATRIXVALUEMAPPINGHELPER SPECIALIZATIONS
1125 //
1126 //=================================================================================================
1127 
1128 //*************************************************************************************************
1129 /*! \cond BLAZE_INTERNAL */
1130 /*!\brief Specialization of the MatrixValueMappingHelper class template for row-major dense matrices.
1131 */
1132 template<>
1133 struct MatrixSerializer::MatrixValueMappingHelper<true,true>
1134 {
1135    enum { value = 1 };
1136 };
1137 /*! \endcond */
1138 //*************************************************************************************************
1139 
1140 
1141 //*************************************************************************************************
1142 /*! \cond BLAZE_INTERNAL */
1143 /*!\brief Specialization of the MatrixValueMappingHelper class template for column-major dense matrices.
1144 */
1145 template<>
1146 struct MatrixSerializer::MatrixValueMappingHelper<true,false>
1147 {
1148    enum { value = 5 };
1149 };
1150 /*! \endcond */
1151 //*************************************************************************************************
1152 
1153 
1154 //*************************************************************************************************
1155 /*! \cond BLAZE_INTERNAL */
1156 /*!\brief Specialization of the MatrixValueMappingHelper class template for row-major sparse matrices.
1157 */
1158 template<>
1159 struct MatrixSerializer::MatrixValueMappingHelper<false,true>
1160 {
1161    enum { value = 3 };
1162 };
1163 /*! \endcond */
1164 //*************************************************************************************************
1165 
1166 
1167 //*************************************************************************************************
1168 /*! \cond BLAZE_INTERNAL */
1169 /*!\brief Specialization of the MatrixValueMappingHelper class template for column-major sparse matrices.
1170 */
1171 template<>
1172 struct MatrixSerializer::MatrixValueMappingHelper<false,false>
1173 {
1174    enum { value = 7 };
1175 };
1176 /*! \endcond */
1177 //*************************************************************************************************
1178 
1179 
1180 
1181 
1182 //=================================================================================================
1183 //
1184 //  GLOBAL FUNCTIONS
1185 //
1186 //=================================================================================================
1187 
1188 //*************************************************************************************************
1189 /*!\brief Serializes the given matrix and writes it to the archive.
1190 //
1191 // \param archive The archive to be written.
1192 // \param mat The matrix to be serialized.
1193 // \return void
1194 // \exception std::runtime_error Matrix could not be serialized.
1195 //
1196 // The serialize() function converts the given matrix into a portable, binary representation.
1197 // The following example demonstrates the (de-)serialization process of matrices:
1198 
1199    \code
1200    using blaze::rowMajor;
1201    using blaze::columnMajor;
1202 
1203    // Serialization of both matrices
1204    {
1205       blaze::StaticMatrix<double,3UL,5UL,rowMajor> D;
1206       blaze::CompressedMatrix<int,columnMajor> S;
1207 
1208       // ... Resizing and initialization
1209 
1210       // Creating an archive that writes into a the file "matrices.blaze"
1211       blaze::Archive<std::ofstream> archive( "matrices.blaze" );
1212 
1213       // Serialization of both matrices into the same archive. Note that D lies before S!
1214       archive << D << S;
1215    }
1216 
1217    // Reconstitution of both matrices
1218    {
1219       blaze::DynamicMatrix<double,rowMajor> D1;
1220       blaze::DynamicMatrix<int,rowMajor> D2;
1221 
1222       // ... Resizing and initialization
1223 
1224       // Creating an archive that reads from the file "matrices.blaze"
1225       blaze::Archive<std::ofstream> archive( "matrices.blaze" );
1226 
1227       // Reconstituting the former D matrix into D1. Note that it is possible to reconstitute
1228       // the matrix into a differrent kind of matrix (StaticMatrix -> DynamicMatrix), but that
1229       // the type of elements has to be the same.
1230       archive >> D1;
1231 
1232       // Reconstituting the former S matrix into D2. Note that is is even possible to reconstitute
1233       // a sparse matrix as a dense matrix (also the reverse is possible) and that a column-major
1234       // matrix can be reconstituted as row-major matrix (and vice versa). Note however that also
1235       // in this case the type of elements is the same!
1236       archive >> D2
1237    }
1238    \endcode
1239 
1240 // As the example demonstrates, the matrix serialization offers an enormous flexibility. However,
1241 // several actions result in errors:
1242 //
1243 //  - matrices cannot be reconstituted as vectors (and vice versa)
1244 //  - the element type of the serialized and reconstituted matrix must match, which means
1245 //    that on the source and destination platform the general type (signed/unsigned integral
1246 //    or floating point) and the size of the type must be exactly the same
1247 //  - when reconstituting a StaticMatrix, the number of rows and columns must match those of
1248 //    the serialized matrix
1249 //
1250 // In case an error is encountered during (de-)serialization, a \a std::runtime_exception is
1251 // thrown.
1252 */
1253 template< typename Archive  // Type of the archive
1254         , typename MT       // Type of the matrix
1255         , bool SO >         // Storage order
1256 void serialize( Archive& archive, const Matrix<MT,SO>& mat )
1257 {
1258    MatrixSerializer().serialize( archive, *mat );
1259 }
1260 //*************************************************************************************************
1261 
1262 
1263 //*************************************************************************************************
1264 /*!\brief Deserializes a matrix from the given archive.
1265 //
1266 // \param archive The archive to be read from.
1267 // \param mat The matrix to be deserialized.
1268 // \return void
1269 // \exception std::runtime_error Matrix could not be deserialized.
1270 //
1271 // The deserialize() function converts the portable, binary representation contained in the
1272 // given archive into the given matrix type. For a detailed example that demonstrates the
1273 // (de-)serialization process of matrices, see the serialize() function.
1274 */
1275 template< typename Archive  // Type of the archive
1276         , typename MT       // Type of the matrix
1277         , bool SO >         // Storage order
1278 void deserialize( Archive& archive, Matrix<MT,SO>& mat )
1279 {
1280    MatrixSerializer().deserialize( archive, *mat );
1281 }
1282 //*************************************************************************************************
1283 
1284 } // namespace blaze
1285 
1286 #endif
1287