/** example for serialization -*- c++ -*- ***************************
 * - begin                : 2007-01-02
 * - copyright            : (C) 2007 by Gunter Winkler
 * - email                : guwi17@gmx.de
 *
 * Distributed under the Boost Software License, Version 1.0. (See
 * accompanying file LICENSE_1_0.txt or copy at
 * http://www.boost.org/LICENSE_1_0.txt)
 ********************************************************************/

#include <fstream>
#include <complex>


#if defined(XMLARCH)
# include <boost/archive/xml_oarchive.hpp>
# include <boost/archive/xml_iarchive.hpp>
#elif defined (BINARCH)
# include <boost/archive/binary_oarchive.hpp>
# include <boost/archive/binary_iarchive.hpp>
#else
# include <boost/archive/text_oarchive.hpp>
# include <boost/archive/text_iarchive.hpp>
#endif

#include <boost/serialization/nvp.hpp>

#include <boost/numeric/ublas/storage.hpp>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>

#include <boost/numeric/ublas/vector_of_vector.hpp>

#include <boost/numeric/ublas/io.hpp>

template<class E, class T, class V>
std::basic_ostream<E, T> &operator << (std::basic_ostream<E, T> &os,
                                       const V &v) {
  os << '[' << v .size () << "](";
  if (v .size () > 0)
    os << v [0];
  for (size_t i = 1; i < v .size (); ++ i)
    os << ',' << v [i];
  os << ')';
  return os;
}

namespace boost {
  namespace serialization {
    template<class Archive, class T>
    void serialize(Archive & ar, std::complex<T> & x, const unsigned int /* version */)
    {
      ar & make_nvp("real", x.real())
         & make_nvp("imag", x.imag());
    }
  } // namespace serialization
} // namespace boost


#if defined(XMLARCH)
typedef boost::archive::xml_oarchive OARCH;
typedef boost::archive::xml_iarchive IARCH;
#elif defined(BINARCH)
typedef boost::archive::binary_oarchive OARCH;
typedef boost::archive::binary_iarchive IARCH;
#else
typedef boost::archive::text_oarchive OARCH;
typedef boost::archive::text_iarchive IARCH;
#endif

template <class CONTAINER> 
bool test_archive(const size_t size, const char* fname = "ua.txt")
{
  CONTAINER x((size));
  for (size_t i=0; i<size; ++i) x[i] = i;
  
  {
    CONTAINER const & const_x(x);
    std::ofstream ofs(fname, std::ios::trunc);
    OARCH oa(ofs);
    
    oa & boost::serialization::make_nvp("x", const_x);
  }

  CONTAINER y;

  {
    std::ifstream ifs(fname, std::ios::in);
    IARCH ia(ifs);
    
    ia & boost::serialization::make_nvp("x", y);
  }

  //  std::cerr << y << std::endl;
  return (std::equal(y.begin(), y.end(), x.begin()));
}


template <class CONTAINER> 
bool test_archive(const size_t size1, const size_t size2, const char* fname = "ua.txt")
{
  CONTAINER x(size1,size2);
  x.clear();
  for (size_t i=0; i<size1; ++i)
    for (size_t j=0; j<size2; ++j) 
      if ( abs(i-j)<5 )
        x(i,j) = 100*i+j;
  
  {
    CONTAINER const & const_x(x);
    std::ofstream ofs(fname, std::ios::trunc);
    OARCH oa(ofs);
    
    oa & boost::serialization::make_nvp("x", const_x);
  }

  CONTAINER y;

  {
    std::ifstream ifs(fname, std::ios::in);
    IARCH ia(ifs);
    
    ia & boost::serialization::make_nvp("x", y);
  }

  //  std::cerr << y << std::endl;
  return (norm_inf(x-y) == 0);
}

template <class CONTAINER> 
bool test_archive2(const CONTAINER & x, const char* fname = "za.txt")
{
  
  {
    CONTAINER const & const_x(x);
    std::ofstream ofs(fname, std::ios::trunc);
    OARCH oa(ofs);
    
    oa & boost::serialization::make_nvp("x", const_x);
  }

  CONTAINER y;

  {
    std::ifstream ifs(fname, std::ios::in);
    IARCH ia(ifs);
    
    ia & boost::serialization::make_nvp("x", y);
  }

  //  std::cerr << y << std::endl;
  return (norm_inf(x-y) == 0);
}

int main(int argc, char * argv[])
{

  size_t size = 10;

  if (argc > 1)
	size = ::atoi (argv [1]);

  std::cout << "size " << size << std::endl;

  using namespace boost::numeric::ublas;

  std::cout 
    << ( test_archive< unbounded_array<double> >(size, "u1.txt") )
    << std::endl;

  std::cout 
    << ( test_archive< bounded_array<double, 50> >(40, "u2.txt") )
    << std::endl;

  std::cout 
    << ( test_archive< vector<double> >(size, "ua.txt") )
    << std::endl;

  std::cout 
    << ( test_archive< vector<std::complex<double> > >(size, "ub.txt") )
    << std::endl;

  std::cout 
    << ( test_archive< vector<unsigned long> >(size, "uc.txt") )
    << std::endl;

  std::cout 
    << ( test_archive< bounded_vector<unsigned long, 5> >(5, "ud.txt") )
    << std::endl;

  std::cout 
    << ( test_archive< c_vector<unsigned long, 5> >(5, "ue.txt") )
    << std::endl;

  std::cout 
    << ( test_archive< matrix<float> >(size, size, "m1.txt") )
    << std::endl;

  std::cout 
    << ( test_archive< bounded_matrix<float, 5, 3> >(5, 3, "m2.txt") )
    << std::endl;

  std::cout 
    << ( test_archive< vector_of_vector<float> >(size, size, "m3.txt") )
    << std::endl;

  std::cout 
    << ( test_archive< c_matrix<float, 5, 3> >(5, 3, "m4.txt") )
    << std::endl;

  std::cout 
    << ( test_archive< generalized_vector_of_vector<double, row_major, vector< vector<double> > > >(size, size, "m5.txt") )
    << std::endl;

  std::cout 
    << ( test_archive< generalized_vector_of_vector<double, row_major, vector< mapped_vector<double, map_array<unsigned int, double> > > > >(size, size, "m6.txt") )
    << std::endl;

  std::cout 
    << ( test_archive< generalized_vector_of_vector<double, row_major, vector< mapped_vector<double> > > >(size, size, "m7.txt") )
    << std::endl;

  /* test special matrices */

  std::cout 
    << ( test_archive2( zero_matrix<float>(size, 2*size), "z1.txt") )
    << std::endl;

  std::cout 
    << ( test_archive2( scalar_matrix<float>(size, 2*size, 2.1), "z2.txt") )
    << std::endl;

  std::cout 
    << ( test_archive2( identity_matrix<float>(size, 2*size), "z3.txt") )
    << std::endl;

  /* test special vectors */

  std::cout 
    << ( test_archive2( zero_vector<float>(size), "z4.txt") )
    << std::endl;

  std::cout 
    << ( test_archive2( scalar_vector<float>(size, 2.1), "z5.txt") )
    << std::endl;

  std::cout 
    << ( test_archive2( unit_vector<float>(size, size/2), "z6.txt") )
    << std::endl;

  /* test sparse vectors */

  mapped_vector<double> x(size);
  x.reserve(size/3);
  for (size_t i=2; i<size; i += 5) x.insert_element(i, 0.5+i);

  std::cout 
    << ( test_archive2( mapped_vector<double>(x), "sp1.txt") )
    << std::endl;

  std::cout 
    << ( test_archive2( compressed_vector<double>(x), "sp2.txt") )
    << std::endl;

  std::cout 
    << ( test_archive2( coordinate_vector<double>(x), "sp3.txt") )
    << std::endl;

  /* test sparse matrices */

  std::cout 
    << ( test_archive< mapped_matrix<float> >(size, size, "sp4.txt") )
    << std::endl;

  std::cout 
    << ( test_archive< mapped_vector_of_mapped_vector<float> >(size, size, "sp5.txt") )
    << std::endl;

  std::cout 
    << ( test_archive< compressed_matrix<float> >(size, size, "sp6.txt") )
    << std::endl;

  std::cout 
    << ( test_archive< coordinate_matrix<float> >(size, size, "sp7.txt") )
    << std::endl;

  return EXIT_SUCCESS;
}


/*
compile: (use one of)

$ LANG=C g++ -g -Wall -I $HOME/include -o ex_serial ex_serial.cpp -L $HOME/lib -l boost_serialization
$ LANG=C g++ -DXMLARCH -g -Wall -I $HOME/include -o ex_serial ex_serial.cpp -L $HOME/lib -l boost_serialization
$ LANG=C g++ -DBINARCH -g -Wall -I $HOME/include -o ex_serial ex_serial.cpp -L $HOME/lib -l boost_serialization

generated output:

$ ./ex_serial
size 10
1
.
.
.
1
$ cat u?.txt m?.txt z?.txt sp?.txt
22 serialization::archive 4 0 0 0 0 10 0 1 2 3 4 5 6 7 8 9
22 serialization::archive 4 0 0 0 0 5 0 1 2 3 4
22 serialization::archive 4 0 0 0 0 10 0 0 0 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 0
22 serialization::archive 4 0 0 5 5 0 1 2 3 4
22 serialization::archive 4 0 0 10 10 0 0 100 0 1 2 3 4 5 6 7 8 9 100 101 102 103 104 105 106 107 108 109 200 201 202 203 204 205 206 207 208 209 300 301 302 303 304 305 306 307 308 309 400 401 402 403 404 405 406 407 408 409 500 501 502 503 504 505 506 507 508 509 600 601 602 603 604 605 606 607 608 609 700 701 702 703 704 705 706 707 708 709 800 801 802 803 804 805 806 807 808 809 900 901 902 903 904 905 906 907 908 909
22 serialization::archive 4 0 0 5 3 0 0 15 0 1 2 100 101 102 200 201 202 300 301 302 400 401 402
22 serialization::archive 4 0 0 10 10 0 0 11 0 0 10 0 1 2 3 4 5 6 7 8 9 10 100 101 102 103 104 105 106 107 108 109 10 200 201 202 203 204 205 206 207 208 209 10 300 301 302 303 304 305 306 307 308 309 10 400 401 402 403 404 405 406 407 408 409 10 500 501 502 503 504 505 506 507 508 509 10 600 601 602 603 604 605 606 607 608 609 10 700 701 702 703 704 705 706 707 708 709 10 800 801 802 803 804 805 806 807 808 809 10 900 901 902 903 904 905 906 907 908 909 0
22 serialization::archive 4 0 0 5 3 3 0 1 2 3 100 101 102 3 200 201 202 3 300 301 302 3 400 401 402
22 serialization::archive 4 0 0 10 10 0 0 0 0 11 0 0 0 0 10 0 1 2 3 4 5 6 7 8 9 10 100 101 102 103 104 105 106 107 108 109 10 200 201 202 203 204 205 206 207 208 209 10 300 301 302 303 304 305 306 307 308 309 10 400 401 402 403 404 405 406 407 408 409 10 500 501 502 503 504 505 506 507 508 509 10 600 601 602 603 604 605 606 607 608 609 10 700 701 702 703 704 705 706 707 708 709 10 800 801 802 803 804 805 806 807 808 809 10 900 901 902 903 904 905 906 907 908 909 0
22 serialization::archive 4 0 0 10 20
22 serialization::archive 4 0 0 10 20 2.0999999
22 serialization::archive 4 0 0 10 20
22 serialization::archive 4 0 0 10
22 serialization::archive 4 0 0 10 2.0999999
22 serialization::archive 4 0 0 10 5
22 serialization::archive 4 0 0 10 0 0 0 0 2 0 0 0 2 2.5 7 7.5
22 serialization::archive 4 0 0 10 2 2 0 0 2 2 7 0 0 2 2.5 7.5
22 serialization::archive 4 0 0 10 2 2 2 1 0 0 2 2 7 0 0 2 2.5 7.5
22 serialization::archive 4 0 0 10 10 0 0 0 0 70 0 0 0 0 0 1 1 2 2 3 3 4 4 10 100 11 101 12 102 13 103 14 104 15 105 20 200 21 201 22 202 23 203 24 204 25 205 26 206 30 300 31 301 32 302 33 303 34 304 35 305 36 306 37 307 40 400 41 401 42 402 43 403 44 404 45 405 46 406 47 407 48 408 51 501 52 502 53 503 54 504 55 505 56 506 57 507 58 508 59 509 62 602 63 603 64 604 65 605 66 606 67 607 68 608 69 609 73 703 74 704 75 705 76 706 77 707 78 708 79 709 84 804 85 805 86 806 87 807 88 808 89 809 95 905 96 906 97 907 98 908 99 909
22 serialization::archive 4 0 0 10 10 0 0 0 0 11 0 0 0 0 0 0 0 0 5 0 0 0 0 0 1 1 2 2 3 3 4 4 1 6 0 0 100 1 101 2 102 3 103 4 104 5 105 2 7 0 0 200 1 201 2 202 3 203 4 204 5 205 6 206 3 8 0 0 300 1 301 2 302 3 303 4 304 5 305 6 306 7 307 4 9 0 0 400 1 401 2 402 3 403 4 404 5 405 6 406 7 407 8 408 5 9 0 1 501 2 502 3 503 4 504 5 505 6 506 7 507 8 508 9 509 6 8 0 2 602 3 603 4 604 5 605 6 606 7 607 8 608 9 609 7 7 0 3 703 4 704 5 705 6 706 7 707 8 708 9 709 8 6 0 4 804 5 805 6 806 7 807 8 808 9 809 9 5 0 5 905 6 906 7 907 8 908 9 909 10 0 0
22 serialization::archive 4 0 0 10 10 80 11 70 0 0 11 0 5 11 18 26 35 44 52 59 65 70 80 0 1 2 3 4 0 1 2 3 4 5 0 1 2 3 4 5 6 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 9 2 3 4 5 6 7 8 9 3 4 5 6 7 8 9 4 5 6 7 8 9 5 6 7 8 9 0 0 0 0 0 0 0 0 0 0 0 0 80 0 1 2 3 4 100 101 102 103 104 105 200 201 202 203 204 205 206 300 301 302 303 304 305 306 307 400 401 402 403 404 405 406 407 408 501 502 503 504 505 506 507 508 509 602 603 604 605 606 607 608 609 703 704 705 706 707 708 709 804 805 806 807 808 809 905 906 907 908 909 0 0 0 0 0 0 0 0 0 0
22 serialization::archive 4 0 0 10 10 80 70 69 0 0 0 80 0 0 0 0 0 1 1 1 1 1 1 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6 6 7 7 7 7 7 7 7 8 8 8 8 8 8 9 9 9 9 9 0 0 0 0 0 0 0 0 0 0 80 0 1 2 3 4 0 1 2 3 4 5 0 1 2 3 4 5 6 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 9 2 3 4 5 6 7 8 9 3 4 5 6 7 8 9 4 5 6 7 8 9 5 6 7 8 9 0 0 0 0 0 0 0 0 0 0 0 0 80 0 1 2 3 4 100 101 102 103 104 105 200 201 202 203 204 205 206 300 301 302 303 304 305 306 307 400 401 402 403 404 405 406 407 408 501 502 503 504 505 506 507 508 509 602 603 604 605 606 607 608 609 703 704 705 706 707 708 709 804 805 806 807 808 809 905 906 907 908 909 0 0 0 0 0 0 0 0 0 0

*/

