/** nonfinite_num_facet_serialization.cpp
 *
 * Copyright (c) 2011 Francois Mauger
 * Copyright (c) 2011 Paul A. Bristow
 *
 * 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)
 *
 * This sample program by Francois Mauger illustrates how to use the
 * `boost/math/nonfinite_num_facets.hpp'  material  from the  original
 * Floating Point  Utilities contribution by  Johan Rade.  Here  it is
 * shown  how  non  finite  floating  number  can  be  serialized  and
 * deserialized from  I/O streams and/or Boost  text/XML archives.  It
 * produces two archives stored in `test.txt' and `test.xml' files.
 *
 * Tested with Boost 1.44, gcc 4.4.1, Linux/i686 (32bits).
 * Tested with Boost.1.46.1  MSVC 10.0 32 bit.
 */

#ifdef _MSC_VER
#   pragma warning(push)
//#   pragma warning(disable : 4100) // unreferenced formal parameter.
#endif

#include <iostream>
#include <sstream>
#include <fstream>
#include <limits>

#include <boost/cstdint.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/codecvt_null.hpp>

// from the Floating Point Utilities :
#include <boost/math/special_functions/nonfinite_num_facets.hpp>

static const char sep = ','; // Separator of bracketed float and double values.

// Use max_digits10 (or equivalent) to obtain
// all potentially significant decimal digits for the floating-point types.

#ifdef BOOST_NO_CXX11_NUMERIC_LIMITS
  std::streamsize  max_digits10_float = 2 + std::numeric_limits<float>::digits * 30103UL / 100000UL;
  std::streamsize  max_digits10_double = 2 + std::numeric_limits<double>::digits * 30103UL / 100000UL;
#else
  // Can use new C++0X max_digits10 (the maximum potentially significant digits).
  std::streamsize  max_digits10_float = std::numeric_limits<float>::max_digits10;
  std::streamsize  max_digits10_double = std::numeric_limits<double>::max_digits10;
#endif

/* A class with a float and a double */
struct foo
{
  foo () : fvalue (3.1415927F), dvalue (3.1415926535897931)
  { // Construct using 32 and 64-bit max_digits10 decimal digits value of pi.
  }
  // Set the values at -infinity :
  void minus_infinity ()
  {
    fvalue = -std::numeric_limits<float>::infinity ();
    dvalue = -std::numeric_limits<double>::infinity ();
    return;
  }
  // Set the values at +infinity :
  void plus_infinity ()
  {
    fvalue = +std::numeric_limits<float>::infinity ();
    dvalue = +std::numeric_limits<double>::infinity ();
    return;
  }
  // Set the values at NaN :
  void nan ()
  {
    fvalue = +std::numeric_limits<float>::quiet_NaN ();
    dvalue = +std::numeric_limits<double>::quiet_NaN ();
    return;
  }
  // Print :
  void print (std::ostream & a_out, const std::string & a_title)
  {
    if (a_title.empty ()) a_out << "foo";
    else a_out << a_title;
    a_out << " : " << std::endl;
    a_out << "|-- " << "fvalue = ";
    a_out.precision (7);
    a_out << fvalue << std::endl;
    a_out << "`-- " << "dvalue = ";
    a_out.precision (15);
    a_out << dvalue << std::endl;
    return;
  }

  // I/O operators :
  friend std::ostream & operator<< (std::ostream & a_out, const foo & a_foo);
  friend std::istream & operator>> (std::istream & a_in, foo & a_foo);

  // Boost serialization :
  template <class Archive>
  void serialize (Archive & ar, int /*version*/)
  {
    ar & BOOST_SERIALIZATION_NVP (fvalue);
    ar & BOOST_SERIALIZATION_NVP (dvalue);
    return;
  }

  // Attributes :
  float  fvalue; // Single precision floating-point number.
  double dvalue; // Double precision floating-point number.
};

std::ostream & operator<< (std::ostream & a_out, const foo & a_foo)
{ // Output bracketed FPs, for example "(3.1415927,3.1415926535897931)"
  a_out.precision (max_digits10_float);
  a_out << "(" << a_foo.fvalue << sep ;
  a_out.precision (max_digits10_double);
  a_out << a_foo.dvalue << ")";
  return a_out;
}

std::istream & operator>> (std::istream & a_in, foo & a_foo)
{ // Input bracketed floating-point values into a foo structure,
  // for example from "(3.1415927,3.1415926535897931)"
  char c = 0;
  a_in.get (c);
  if (c != '(')
  {
    std::cerr << "ERROR: operator>> No ( " << std::endl;
    a_in.setstate(std::ios::failbit);
    return a_in;
  }
  float f;
  a_in >> std::ws >> f;
  if (! a_in)
  {
    return a_in;
  }
  a_in >> std::ws;
  a_in.get (c);
  if (c != sep)
  {
    std::cerr << "ERROR: operator>> c='" << c << "'" << std::endl;
    std::cerr << "ERROR: operator>> No '" << sep << "'" << std::endl;
    a_in.setstate(std::ios::failbit);
    return a_in;
  }
  double d;
  a_in >> std::ws >> d;
  if (! a_in)
  {
    return a_in;
  }
  a_in >> std::ws;
  a_in.get (c);
  if (c != ')')
  {
    std::cerr << "ERROR: operator>> No ) " << std::endl;
    a_in.setstate(std::ios::failbit);
    return a_in;
  }
  a_foo.fvalue = f;
  a_foo.dvalue = d;
  return a_in;
}

int main (void)
{
  std::clog << std::endl
      << "Nonfinite_serialization.cpp' example program." << std::endl;

#ifdef BOOST_NO_CXX11_NUMERIC_LIMITS
  std::cout << "BOOST_NO_CXX11_NUMERIC_LIMITS is defined, so no max_digits10 available either,"
     "using our own version instead." << std::endl;
#endif
  std::cout << "std::numeric_limits<float>::max_digits10 is " << max_digits10_float << std::endl;
  std::cout << "std::numeric_limits<double>::max_digits10 is " << max_digits10_double << std::endl;

  std::locale the_default_locale (std::locale::classic (),
          new boost::archive::codecvt_null<char>);

  // Demonstrate use of nonfinite facets with stringstreams.
  {
    std::clog << "Construct some foo structures with a finite and nonfinites." << std::endl;
    foo f0;
    foo f1; f1.minus_infinity ();
    foo f2; f2.plus_infinity ();
    foo f3; f3.nan ();
    // Display them.
    f0.print (std::clog, "f0");
    f1.print (std::clog, "f1");
    f2.print (std::clog, "f2");
    f3.print (std::clog, "f3");
    std::clog << " Write to a string buffer." << std::endl;

    std::ostringstream oss;
    std::locale the_out_locale (the_default_locale, new boost::math::nonfinite_num_put<char>);
    oss.imbue (the_out_locale);
    oss.precision (max_digits10_double);
    oss << f0 << f1 << f2 << f3;
    std::clog << "Output is: `" << oss.str () << "'" << std::endl;
    std::clog << "Done output to ostringstream." << std::endl;
  }

  {
    std::clog << "Read foo structures from a string buffer." << std::endl;

    std::string the_string = "(3.1415927,3.1415926535897931)(-inf,-inf)(inf,inf)(nan,nan)";
    std::clog << "Input is: `" << the_string << "'" << std::endl;

    std::locale the_in_locale (the_default_locale, new boost::math::nonfinite_num_get<char>);
    std::istringstream iss (the_string);
    iss.imbue (the_in_locale);

    foo f0, f1, f2, f3;
    iss >> f0 >> f1 >> f2 >> f3;
    if (! iss)
    {
      std::cerr << "Format error !" << std::endl;
    }
    else
    {
      std::cerr << "Read OK." << std::endl;
      f0.print (std::clog, "f0");
      f1.print (std::clog, "f1");
      f2.print (std::clog, "f2");
      f3.print (std::clog, "f3");
    }
    std::clog << "Done input from istringstream." << std::endl;
  }

  {  // Demonstrate use of nonfinite facets for Serialization with Boost text archives.
    std::clog << "Serialize (using Boost text archive)." << std::endl;
    // Construct some foo structures with a finite and nonfinites.
    foo f0;
    foo f1; f1.minus_infinity ();
    foo f2; f2.plus_infinity ();
    foo f3; f3.nan ();
    // Display them.
    f0.print (std::clog, "f0");
    f1.print (std::clog, "f1");
    f2.print (std::clog, "f2");
    f3.print (std::clog, "f3");

    std::locale the_out_locale (the_default_locale, new boost::math::nonfinite_num_put<char>);
    std::ofstream fout ("nonfinite_archive_test.txt");
    fout.imbue (the_out_locale);
    boost::archive::text_oarchive toar (fout, boost::archive::no_codecvt);
    // Write to archive.
    toar & f0;
    toar & f1;
    toar & f2;
    toar & f3;
    std::clog << "Done." << std::endl;
  }

  {
    std::clog << "Deserialize (Boost text archive)..." << std::endl;
    std::locale the_in_locale (the_default_locale, new boost::math::nonfinite_num_get<char>);
    std::ifstream fin ("nonfinite_archive_test.txt");
    fin.imbue (the_in_locale);
    boost::archive::text_iarchive tiar (fin, boost::archive::no_codecvt);
    foo f0, f1, f2, f3;
    // Read from archive.
    tiar & f0;
    tiar & f1;
    tiar & f2;
    tiar & f3;
    // Display foos.
    f0.print (std::clog, "f0");
    f1.print (std::clog, "f1");
    f2.print (std::clog, "f2");
    f3.print (std::clog, "f3");

    std::clog << "Done." << std::endl;
  }

  {   // Demonstrate use of nonfinite facets for Serialization with Boost XML Archive.
    std::clog << "Serialize (Boost XML archive)..." << std::endl;
    // Construct some foo structures with a finite and nonfinites.
    foo f0;
    foo f1; f1.minus_infinity ();
    foo f2; f2.plus_infinity ();
    foo f3; f3.nan ();
     // Display foos.
    f0.print (std::clog, "f0");
    f1.print (std::clog, "f1");
    f2.print (std::clog, "f2");
    f3.print (std::clog, "f3");

    std::locale the_out_locale (the_default_locale, new boost::math::nonfinite_num_put<char>);
    std::ofstream fout ("nonfinite_XML_archive_test.txt");
    fout.imbue (the_out_locale);
    boost::archive::xml_oarchive xoar (fout, boost::archive::no_codecvt);

    xoar & BOOST_SERIALIZATION_NVP (f0);
    xoar & BOOST_SERIALIZATION_NVP (f1);
    xoar & BOOST_SERIALIZATION_NVP (f2);
    xoar & BOOST_SERIALIZATION_NVP (f3);
    std::clog << "Done." << std::endl;
  }

  {
    std::clog << "Deserialize (Boost XML archive)..." << std::endl;
    std::locale the_in_locale (the_default_locale, new boost::math::nonfinite_num_get<char>);
    std::ifstream fin ("nonfinite_XML_archive_test.txt");
    fin.imbue (the_in_locale);
    boost::archive::xml_iarchive xiar (fin, boost::archive::no_codecvt);
    foo f0, f1, f2, f3;

    xiar & BOOST_SERIALIZATION_NVP (f0);
    xiar & BOOST_SERIALIZATION_NVP (f1);
    xiar & BOOST_SERIALIZATION_NVP (f2);
    xiar & BOOST_SERIALIZATION_NVP (f3);

    f0.print (std::clog, "f0");
    f1.print (std::clog, "f1");
    f2.print (std::clog, "f2");
    f3.print (std::clog, "f3");

    std::clog << "Done." << std::endl;
  }

  std::clog << "End nonfinite_serialization.cpp' example program." << std::endl;
  return 0;
}

/*

Output:

  Nonfinite_serialization.cpp' example program.
  std::numeric_limits<float>::max_digits10 is 8
  std::numeric_limits<double>::max_digits10 is 17
  Construct some foo structures with a finite and nonfinites.
  f0 :
  |-- fvalue = 3.141593
  `-- dvalue = 3.14159265358979
  f1 :
  |-- fvalue = -1.#INF
  `-- dvalue = -1.#INF
  f2 :
  |-- fvalue = 1.#INF
  `-- dvalue = 1.#INF
  f3 :
  |-- fvalue = 1.#QNAN
  `-- dvalue = 1.#QNAN
   Write to a string buffer.
  Output is: `(3.1415927,3.1415926535897931)(-inf,-inf)(inf,inf)(nan,nan)'
  Done output to ostringstream.
  Read foo structures from a string buffer.
  Input is: `(3.1415927,3.1415926535897931)(-inf,-inf)(inf,inf)(nan,nan)'
  Read OK.
  f0 :
  |-- fvalue = 3.141593
  `-- dvalue = 3.14159265358979
  f1 :
  |-- fvalue = -1.#INF
  `-- dvalue = -1.#INF
  f2 :
  |-- fvalue = 1.#INF
  `-- dvalue = 1.#INF
  f3 :
  |-- fvalue = 1.#QNAN
  `-- dvalue = 1.#QNAN
  Done input from istringstream.
  Serialize (using Boost text archive).
  f0 :
  |-- fvalue = 3.141593
  `-- dvalue = 3.14159265358979
  f1 :
  |-- fvalue = -1.#INF
  `-- dvalue = -1.#INF
  f2 :
  |-- fvalue = 1.#INF
  `-- dvalue = 1.#INF
  f3 :
  |-- fvalue = 1.#QNAN
  `-- dvalue = 1.#QNAN
  Done.
  Deserialize (Boost text archive)...
  f0 :
  |-- fvalue = 3.141593
  `-- dvalue = 3.14159265358979
  f1 :
  |-- fvalue = -1.#INF
  `-- dvalue = -1.#INF
  f2 :
  |-- fvalue = 1.#INF
  `-- dvalue = 1.#INF
  f3 :
  |-- fvalue = 1.#QNAN
  `-- dvalue = 1.#QNAN
  Done.
  Serialize (Boost XML archive)...
  f0 :
  |-- fvalue = 3.141593
  `-- dvalue = 3.14159265358979
  f1 :
  |-- fvalue = -1.#INF
  `-- dvalue = -1.#INF
  f2 :
  |-- fvalue = 1.#INF
  `-- dvalue = 1.#INF
  f3 :
  |-- fvalue = 1.#QNAN
  `-- dvalue = 1.#QNAN
  Done.
  Deserialize (Boost XML archive)...
  f0 :
  |-- fvalue = 3.141593
  `-- dvalue = 3.14159265358979
  f1 :
  |-- fvalue = -1.#INF
  `-- dvalue = -1.#INF
  f2 :
  |-- fvalue = 1.#INF
  `-- dvalue = 1.#INF
  f3 :
  |-- fvalue = 1.#QNAN
  `-- dvalue = 1.#QNAN
  Done.
  End nonfinite_serialization.cpp' example program.

  */


// Date Last Altered: $Date: 2008-08-04 22:55:41 -0600 (Mon, 04 Aug 2008) $
// Revision Number: $Revision: 344 $
//----------------------------------*-C++-*------------------------------------//
/*! \file Dimension.hh
 *  \author Greg Davidson
 *  \date August 4, 2007
 *
 *  \brief Provides the \c Dimension class template and \c DimensionConcept
 *         concept.
 *
 *  This file provides the \c Dimension class template and the
 *  \c DimensionConcept concept.  The \c Dimension class stores what spatial
 *  dimension we are working in.  The \c DimensionConcept sets the functionality
 *  that a \c Dimension type must satisfy. */

#ifndef DIMENSION_HH
#define DIMENSION_HH

#include <boost/static_assert.hpp>
#include <boost/concept_check.hpp>

#include "Types.hh"

using boost::function_requires;
using boost::UnsignedIntegerConcept;

/*! \addtogroup MeshMod Mesh Module
 *  @{  */

/// Defines the type that stores the dimension number.
typedef UnsignedInt2  DimensionValue;

/*! \brief Stores what spatial dimension we are working in.
 *
 *  This class depicts what spatial dimension we are working
 *  in.
 *  \par Template Parameters:
 *     <dl> <dt> \e val </dt>
 *          <dd> This is the numerical value of the spatial dimension.  Valid
 *               values are 1, 2, and 3. </dd> </dl> */
template<DimensionValue val>
class Dimension
{
public:
   /*! \brief This static assert is used to ensure that only spatial
    *         values of 1, 2, or 3 are used. */
   BOOST_STATIC_ASSERT(val <= 3 && val != 0);

   /// Define \c type as the type of this class.
   typedef Dimension<val>     type;
   /// Define the type of the spatial dimension value.
   typedef DimensionValue     value_type;
   /// Stores the numerical value of the spatial dimension.
   static const value_type    value = val;
};

/// Defines the \c OneD type as a \c Dimension<1>.
typedef Dimension<1>   OneD;
/// Defines the \c TwoD type as a \c Dimension<2>.
typedef Dimension<2>   TwoD;
/// Defines the \c ThreeD type as a \c Dimension<3>.
typedef Dimension<3>   ThreeD;

/*! \brief The \c DimensionConcept concept class ensures that a type
 *         provides the \c Dimension functionality.
 *
 *  The \c DimensionConcept concept class ensures that a type
 *  provides the functionality necessary to function as a \c Dimension
 *  instantiation.
 *  \par Template Parameters:
 *     <dl> <dt> \e dimension_type </dt>
 *          <dd> This is the type we wish to check for concept
 *               compatibility. </dd> </dl>
 *  \par Concept Requirements:
 *       The following types must be provided by the \c dimension_type type:
 *       <TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0" WIDTH="100%">
 *          <TR>  <TD> \arg \c type </TD>
 *                <TD> The type of the \c Dimension template. </TD> </TR>
 *          <TR>  <TD> \arg \c value_type </TD>
 *                <TD> The value of the spatial dimension. </TD> </TR>
 *       </TABLE>
 *       The following functionality must be provided by the \c dimension_type type:
 *       \arg The \c value_type type must satisfy the \c boost::UnsignedIntegerConcept concept.
 *       \arg The \a value must be between 1 and 3 inclusively.
 *  \remarks  It should be noted that this class is compiled but never executed, so concept
 *            checking does not imply any runtime overhead. */
template<typename dimension_type>
class DimensionConcept
{
public:
   /// Alias the \c dimension_type as a \c DimensionType.
   typedef dimension_type                       DimensionType;
   /// Require the \c DimensionType to provide a \c type.
   typedef typename DimensionType::type         type;
   /// Require the \c DimensionType to provide a \c value_type.
   typedef typename DimensionType::value_type   value_type;

   /*! \brief The constraints method tests that the \c dimension_type
    *         provides certain functionality. */
   void constraints()
   {
      function_requires< UnsignedIntegerConcept<value_type> >();

      BOOST_STATIC_ASSERT(DimensionType::value <= 3
                              && DimensionType::value != 0);
   }
};

///  @}

#endif


/*! \file demo_annotation.cpp
    \brief Demonstration of 2D 'note' annotation.
    \details Adding a text annotation to a plot, changing its color, font and/or orientation.
*/

// Copyright Paul A. Bristow 2009, 2020

// Use, modification and distribution are subject to 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)

// This file is written to be included from a Quickbook .qbk document.
// It can be compiled by the C++ compiler, and run. Any output can
// also be added here as comment or included or pasted in elsewhere.
// Caution: this file contains Quickbook markup as well as code
// and comments: don't change any of the special comment markups!

//[demo_2d_annotation_1

/*`First we need some includes to use Boost.Plot and C++ Standard Library:
*/#include <boost/svg_plot/svg_2d_plot.hpp>
using namespace boost::svg;

//#include <boost/svg_plot/show_2d_settings.hpp>
// using boost::svg::show_2d_plot_settings - Only needed for showing which settings in use.

#include <map>
  //using std::map;

#include <iostream>
  // using std::cout;
 //  using std::endl;
   //using std::scientific;
   //using std::hex;
   //using std::ios;
   //using std::boolalpha;

int main()
{
  try
  {
//[demo_2d_annotation_2

/*`
This shows how to add notes to a plot, for example to identify a particular area or point.
*/

  std::map<double, double> my_data;

  my_data[1.1] = 3.2;
  my_data[4.3] = 3.1;
  my_data[0.25] = 1.4;

  /*`
  First construct, size and draw a simple plot ready to add some sample annotation.
  */
  svg_2d_plot my_plot;
  my_plot.size(400, 300);
  my_plot.plot(my_data, "my_data").fill_color(red);
  /*`Now add a string note at the SVG coordinates X = 100 and Y =200.
  */
  my_plot.draw_note(150, 200, "My 1st (default) Note");

  text_style mini_note_style(7, "verdana", "italic", "bold");
  // Used for note showing origin at top left and bottom right below.
  /*`
  Note that for SVG coordinates, Y increases *down* the page, so Y = 0 is the top and Y = 300 is the bottom.
  Defaults are provided for size, text style = no_text_style, center alignment and rotation horizontal.
  */
  my_plot.draw_note(7, 7, "top left (0, 0)", rotate_style::downward , align_style::left_align, red, mini_note_style);
  my_plot.draw_note(my_plot.image_x_size()-3, my_plot.image_y_size()-3, "bottom right(400, 300)", rotate_style::horizontal, align_style::right_align, red, mini_note_style);

/*`Using enum center_align is strongly recommended because it will ensure that note will center correctly
(even if note-string is made much longer because it contains Unicode,
for example Greek, taking about 6 characters per symbol)
because the render engine does the centering.

You can use either plain char space or Unicode spaces like \
*/
  my_plot.draw_note(150, 100, "Greek Unicode ΩΦ√ ∞ζ ±");
/*`You can change the font, but defining a new text_style, for example: */

  text_style my_note_style(16, "verdana", "italic", "bold"); // Used for note below.

/*`and you can change the alignment and rotation using enums align_style and rotate_style.
*/
  my_plot.draw_note(350, 70, "My 2nd Note", slopeup, align_style::right_align, black, my_note_style);

/*`To change the color to red (and text style, alignment and rotation too, just for fun:)
*/
  text_style my_red_note_style(16, "arial", "italic", "bold");

  std::cout << "my_red_note_style " << my_red_note_style << std::endl;
  // my_red_note_style text_style(16, "arial", "bold", "italic", "", "")
  my_plot.draw_note(350, 170, "Red upsidedown Note",  rotate_style::upsidedown, align_style::left_align, red, my_red_note_style);
  my_plot.draw_note(300, 210, "Blue steepup Note", rotate_style::steepup, align_style::center_align, blue);

  my_plot.write("./demo_annotation");

  // show_2d_plot_settings(my_plot); // Optional diagnostics.

  //] [/demo_2d_annotation_2]

  }
  catch (const std::exception& e)
  {
    std::cout <<
      "\n""Message from thrown exception was:\n   " << e.what() << std::endl;
  }
  return 0;
} // int main()

/*

Output :

*/
/*

*/


//==============================================================================
//         Copyright 2003 - 2012   LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2012   LRI    UMR 8623 CNRS/Univ Paris Sud XI
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#include <boost/simd/boolean/include/functions/logical_ornot.hpp>
#include <boost/simd/sdk/simd/io.hpp>
#include <boost/dispatch/meta/as_integer.hpp>
#include <nt2/sdk/unit/tests/relation.hpp>
#include <nt2/sdk/unit/module.hpp>
#include <nt2/sdk/unit/tests/type_expr.hpp>
#include <nt2/sdk/meta/as_logical.hpp>
#include <nt2/sdk/meta/as_integer.hpp>

#include <boost/simd/include/constants/one.hpp>
#include <boost/simd/include/constants/inf.hpp>
#include <boost/simd/include/constants/zero.hpp>
#include <boost/simd/include/constants/minf.hpp>
#include <boost/simd/include/constants/mone.hpp>
#include <boost/simd/include/constants/nan.hpp>
#include <boost/simd/include/constants/true.hpp>
#include <boost/simd/include/constants/false.hpp>
#include <boost/simd/sdk/simd/io.hpp>

NT2_TEST_CASE_TPL ( logical_ornot_real__2_0,  BOOST_SIMD_REAL_TYPES)
{

  using boost::simd::logical_ornot;
  using boost::simd::tag::logical_ornot_;
  using boost::simd::logical;
  using boost::simd::True;
  using boost::simd::False;
  typedef typename boost::dispatch::meta::call<logical_ornot_(T, T)>::type r_t;
  typedef typename nt2::meta::as_logical<T>::type lT;
  typedef lT wished_r_t;

  // return type conformity test
  NT2_TEST_TYPE_IS( r_t, wished_r_t );

  // specific values tests
  NT2_TEST_EQUAL(logical_ornot(T(0), T(1)), False<lT>());
  NT2_TEST_EQUAL(logical_ornot(T(1), T(0)), True<lT>());
  NT2_TEST_EQUAL(logical_ornot(boost::simd::Inf<T>(),  T(0)), True<lT>());
  NT2_TEST_EQUAL(logical_ornot(boost::simd::Minf<T>(), T(0)), True<lT>());
  NT2_TEST_EQUAL(logical_ornot(boost::simd::Nan<T>(),  T(0)), True<lT>());
  NT2_TEST_EQUAL(logical_ornot(boost::simd::Zero<T>(), T(1)), False<lT>());
  NT2_TEST_EQUAL(logical_ornot(False<lT>(), T(1)), False<lT>());
  NT2_TEST_EQUAL(logical_ornot(True<lT>(), T(1)), True<lT>());

} // end of test for floating_

NT2_TEST_CASE_TPL ( logical_ornot_signed_int__2_0,  BOOST_SIMD_INTEGRAL_SIGNED_TYPES)
{

  using boost::simd::logical_ornot;
  using boost::simd::tag::logical_ornot_;
  using boost::simd::logical;
  using boost::simd::False;
  using boost::simd::True;
  typedef typename boost::dispatch::meta::call<logical_ornot_(T, T)>::type r_t;
  typedef typename nt2::meta::as_logical<T>::type lT;
  typedef lT wished_r_t;

  // return type conformity test
  NT2_TEST_TYPE_IS( r_t, wished_r_t );

  // specific values tests
  NT2_TEST_EQUAL(logical_ornot(T(0), T(1)), False<lT>());
  NT2_TEST_EQUAL(logical_ornot(T(1), T(0)), True<lT>());
  NT2_TEST_EQUAL(logical_ornot(False<lT>(), T(1)), False<lT>());
  NT2_TEST_EQUAL(logical_ornot(True<lT>(), T(1)), True<lT>());
} // end of test for signed_int_

NT2_TEST_CASE_TPL ( logical_ornot_mix,  BOOST_SIMD_REAL_TYPES)
{

  using boost::simd::logical_ornot;
  using boost::simd::tag::logical_ornot_;
  using boost::simd::logical;
  using boost::simd::True;
  using boost::simd::False;
  typedef typename boost::dispatch::meta::call<logical_ornot_(T, T)>::type r_t;
  typedef typename nt2::meta::as_integer<T>::type iT;
  typedef typename nt2::meta::as_logical<T>::type lT;
  typedef lT wished_r_t;

  // return type conformity test
  NT2_TEST_TYPE_IS( r_t, wished_r_t );

  // specific values tests
  NT2_TEST_EQUAL(logical_ornot(T(0), iT(1)), False<lT>());
  NT2_TEST_EQUAL(logical_ornot(T(1), iT(0)), True<lT>());
  NT2_TEST_EQUAL(logical_ornot(boost::simd::Inf<T>(),  iT(0)), True<lT>());
  NT2_TEST_EQUAL(logical_ornot(boost::simd::Minf<T>(), iT(0)), True<lT>());
  NT2_TEST_EQUAL(logical_ornot(boost::simd::Nan<T>(),  iT(0)), True<lT>());
  NT2_TEST_EQUAL(logical_ornot(boost::simd::Zero<T>(), iT(1)), False<lT>());
  NT2_TEST_EQUAL(logical_ornot(False<lT>(), iT(1)), False<lT>());
  NT2_TEST_EQUAL(logical_ornot(True<lT>(), iT(1)), True<lT>());

} // end of test for floating_


/*! \file
    \brief Demonstration of showing the 1D values.
    \details  Showing the 1D values of items from the data set.

    Some of the many possible formatting options are demonstrated,
    including controlling the precision and iosflags,
    and prefix and suffix also useful for giving units.

    Quickbook markup to include in documentation.
*/

// demo_1d_values.cpp
//
// Copyright Jacob Voytko 2007
// Copyright Paul A Bristow 2008, 2009, 2021

// Use, modification and distribution are subject to 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)

// An example to demonstrate labelling data-points with their values and other information.

// This file is written to be included from a Quickbook .qbk document.
// It can be compiled by the C++ compiler, and run. Any output can
// also be added here as comment or included or pasted in elsewhere.

// Caution: this file contains Quickbook markup as well as code
// and comments: don't change any of the special comment markups!

//[demo_1d_values_1

/*` Showing the 1-D values of items from the data set.
    Some of the many possible formatting options are demonstrated.

    As ever, we need a few includes to use Boost.Plot
*/

#include <boost/svg_plot/svg_1d_plot.hpp>
  using namespace boost::svg;
  using boost::svg::svg_1d_plot;

  #include <boost/svg_plot/show_1d_settings.hpp>
// using boost::svg::show_1d_plot_settings - Only needed for showing which settings in use.

#include <iostream>
  using std::cout;
  using std::endl;
  using std::hex;

#include <vector>
  using std::vector;
//] [demo_1d_values_1]

int main()
{
//[demo_1d_values_2
/*`Some fictional data is pushed into an STL container, here `vector<double>`:*/
  vector<double> my_data;
  my_data.push_back(-1.6);
  my_data.push_back(2.0);
  my_data.push_back(4.2563);
  my_data.push_back(0.00333974);
  my_data.push_back(5.4);
  my_data.push_back(6.556);

  try
  { // try'n'catch blocks are needed to ensure error messages from any exceptions are shown.
    svg_1d_plot my_1d_plot; // Construct a plot with all the default constructor values.

    my_1d_plot.title("Default 1D Values Demo") // Add a string title of the plot.
      .x_range(-5, 10) // Add a range for the X-axis.
      .x_label("length (m)"); // Add a label for the X-axis.

/*`Add the one data series, `my_data` and a description, and how the data points are to marked,
here a circle with a diameter of 5 pixels.
*/
    my_1d_plot.plot(my_data, "1D Values").shape(circlet).size(5);

/*`To put a value-label against each data point, switch on the option:
*/
    my_1d_plot.x_values_on(true); // Add a label for the X-axis.

/*`If the default size and color are not to your taste, set more options, like:
*/
    my_1d_plot.size(500, 350) // Change from default size
      .x_values_font_size(14) // Change font size for the X-axis value-labels.
      .x_values_font_family("Times New Roman") // Change font for the X-axis value-labels.
      .x_values_color(red); // Change color from default black to red.

/*`The format of the values may also not be ideal,
so we can use the normal `iostream precision` and `ioflags` to change,
here to reduce the number of digits used from default precision 6 down to a more readable 2,
reducing the risk of collisions between adjacent values.
(Obviously the most suitable precision depends on the range of the data points.
If values are very close to each other, a higher precision wil be needed to differentiate them).
*/
    my_1d_plot.x_values_precision(2); // precision label for the X-axis value-label.

/*`We can also prescribe the use of scientific format and force a positive sign:
*/
   my_1d_plot.x_values_ioflags(std::ios::scientific | std::ios::showpos);

/*`By default, any unnecessary spacing-wasting zeros in the exponent field are removed.
(If, perversely, the full 1.123456e+012 format is required, the stripping can be switched off with:
  `my_1d_plot.x_labels_strip_e0s(false);` )

In general, sticking to the defaults usually produces the neatest presentation of the values.
*/

/*`The default value-label is horizontal, centered above the data point marker,
but, depending on the type and density of data points, and the length of the values
(controlled in turn by the `precision` and `ioflags` in use),
it is often clearer to use a different orientation.
This can be controlled in steps of 45 degrees, using an 'enum rotate_style`.

* `uphill` - writing up at 45 degree slope is often a good choice,
* `upward` - writing vertically up and
* `backup` are also useful.

(For 1-D plots other directions are less attractive,
placing the values below the horizontal Y-axis line,
but for 2-D plots all writing orientations can be useful).
*/
   my_1d_plot.x_values_rotation(steepup); // Orientation for the X-axis value-labels, nearly vertical.

   my_1d_plot.x_decor(" [ x = ", "", " sec]"); // Note the need for a Unicode space A0 as   .

/*`To use all these settings, finally write the plot to file.
*/
    my_1d_plot.write("demo_1d_values.svg");

/*`If chosen settings do not have the effect that you expect, it may be helpful to display some of them!
(All the myriad settings can be displayed with `show_1d_plot_settings(my_1d_plot)`.)
*/
    //show_1d_plot_settings(my_1d_plot);
    using boost::svg::detail::operator<<;
    cout << "my_1d_plot.image_size() " << my_1d_plot.size() << endl;
    cout << "my_1d_plot.image x_size() " << my_1d_plot.x_size() << endl;
    cout << "my_1d_plot.image y_size() " << my_1d_plot.y_size() << endl;
    cout << "my_1d_plot.x_values_font_size() " << my_1d_plot.x_values_font_size() << endl;
    cout << "my_1d_plot.x_values_font_family() " << my_1d_plot.x_values_font_family() << endl;
    cout << "my_1d_plot.x_values_color() " << my_1d_plot.x_values_color() << endl;
    cout << "my_1d_plot.x_values_precision() " << my_1d_plot.x_values_precision() << endl;
    cout << "my_1d_plot.x_values_ioflags() " << hex << my_1d_plot.x_values_ioflags() << endl;
//] [demo_1d_values_2]
  }
  catch(const std::exception& e)
  {
    std::cout <<
      "\n""Message from thrown exception was:\n   " << e.what() << std::endl;
  }
  return 0;
} // int main()

/*

//[demo_1d_values_output

Output:

demo_1d_values.cpp
Plot written to file demo_1d_values.svg.
my_1d_plot.image_size() 500, 350
my_1d_plot.image x_size() 500
my_1d_plot.image y_size() 350
my_1d_plot.x_values_font_size() 14
my_1d_plot.x_values_font_family() Times New Roman
my_1d_plot.x_values_color() RGB(255,0,0)
my_1d_plot.x_values_precision() 2
my_1d_plot.x_values_ioflags() 1020

//] [demo_1d_values_output]
*/


// Boost.Geometry (aka GGL, Generic Geometry Library)

// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.

// This file was modified by Oracle on 2013, 2014, 2015, 2017.
// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle

// Use, modification and distribution is subject to 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)

#ifndef BOOST_GEOMETRY_TEST_RELATE_HPP
#define BOOST_GEOMETRY_TEST_RELATE_HPP

#include <geometry_test_common.hpp>

#include <boost/variant.hpp>

#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/algorithms/relate.hpp>
#include <boost/geometry/algorithms/relation.hpp>
#include <boost/geometry/strategies/strategies.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/geometries/point_xy.hpp>

#include <boost/geometry/io/wkt/read.hpp>

#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
#include <boost/geometry/strategies/agnostic/point_in_box_by_side.hpp>

namespace bgdr = bg::detail::relate;

std::string transposed(std::string matrix)
{
    if ( !matrix.empty() )
    {
        std::swap(matrix[1], matrix[3]);
        std::swap(matrix[2], matrix[6]);
        std::swap(matrix[5], matrix[7]);
    }
    return matrix;
}

bool matrix_compare(std::string const& m1, std::string const& m2)
{
    BOOST_ASSERT(m1.size() == 9 && m2.size() == 9);
    for ( size_t i = 0 ; i < 9 ; ++i )
    {
        if ( m1[i] == '*' || m2[i] == '*' )
            continue;

        if ( m1[i] != m2[i] )
            return false;
    }
    return true;
}

bool matrix_compare(std::string const& m, std::string const& res1, std::string const& res2)
{
    return matrix_compare(m, res1)
        || ( !res2.empty() ? matrix_compare(m, res2) : false );
}

std::string matrix_format(std::string const& matrix1, std::string const& matrix2)
{
    return matrix1
         + ( !matrix2.empty() ? " || " : "" ) + matrix2;
}

template <typename M>
char get_ii(M const& m)
{
    using bg::detail::relate::interior;
    return m.template get<interior, interior>();
}

template <typename M>
char get_ee(M const& m)
{
    using bg::detail::relate::exterior;
    return m.template get<exterior, exterior>();
}

void check_mask()
{
    bg::de9im::mask m1("");
    bg::de9im::mask m2("TTT");
    bg::de9im::mask m3("000111222");
    bg::de9im::mask m4("000111222FFFF");
    bg::de9im::mask m5(std::string(""));
    bg::de9im::mask m6(std::string("TTT"));
    bg::de9im::mask m7(std::string("000111222"));
    bg::de9im::mask m8(std::string("000111222FFFF"));

    using bg::detail::relate::interior;
    using bg::detail::relate::exterior;

    BOOST_CHECK(get_ii(m1) == '*' && get_ee(m1) == '*');
    BOOST_CHECK(get_ii(m2) == 'T' && get_ee(m2) == '*');
    BOOST_CHECK(get_ii(m3) == '0' && get_ee(m3) == '2');
    BOOST_CHECK(get_ii(m4) == '0' && get_ee(m4) == '2');
    BOOST_CHECK(get_ii(m5) == '*' && get_ee(m5) == '*');
    BOOST_CHECK(get_ii(m6) == 'T' && get_ee(m6) == '*');
    BOOST_CHECK(get_ii(m7) == '0' && get_ee(m7) == '2');
    BOOST_CHECK(get_ii(m8) == '0' && get_ee(m8) == '2');
}

template <typename Geometry1, typename Geometry2>
void check_geometry(Geometry1 const& geometry1,
                    Geometry2 const& geometry2,
                    std::string const& wkt1,
                    std::string const& wkt2,
                    std::string const& expected1,
                    std::string const& expected2 = std::string())
{
    boost::variant<Geometry1> variant1 = geometry1;
    boost::variant<Geometry2> variant2 = geometry2;

    {
        std::string res_str = bg::relation(geometry1, geometry2).str();
        bool ok = matrix_compare(res_str, expected1, expected2);
        BOOST_CHECK_MESSAGE(ok,
            "relate: " << wkt1
            << " and " << wkt2
            << " -> Expected: " << matrix_format(expected1, expected2)
            << " detected: " << res_str);

        typedef typename bg::strategy::relate::services::default_strategy
            <
                Geometry1, Geometry2
            >::type strategy_type;
        std::string res_str0 = bg::relation(geometry1, geometry2, strategy_type()).str();
        BOOST_CHECK(res_str == res_str0);

        // test variants
        boost::variant<Geometry1> v1 = geometry1;
        boost::variant<Geometry2> v2 = geometry2;
        std::string res_str1 = bg::relation(geometry1, variant2).str();
        std::string res_str2 = bg::relation(variant1, geometry2).str();
        std::string res_str3 = bg::relation(variant1, variant2).str();
        BOOST_CHECK(res_str == res_str1);
        BOOST_CHECK(res_str == res_str2);
        BOOST_CHECK(res_str == res_str3);
    }

    // changed sequence of geometries - transposed result
    {
        std::string res_str = bg::relation(geometry2, geometry1).str();
        std::string expected1_tr = transposed(expected1);
        std::string expected2_tr = transposed(expected2);
        bool ok = matrix_compare(res_str, expected1_tr, expected2_tr);
        BOOST_CHECK_MESSAGE(ok,
            "relate: " << wkt2
            << " and " << wkt1
            << " -> Expected: " << matrix_format(expected1_tr, expected2_tr)
            << " detected: " << res_str);
    }

    if ( expected2.empty() )
    {
        {
            bool result = bg::relate(geometry1, geometry2, bg::de9im::mask(expected1));
            // TODO: SHOULD BE !interrupted - CHECK THIS!
            BOOST_CHECK_MESSAGE(result,
                "relate: " << wkt1
                << " and " << wkt2
                << " -> Expected: " << expected1);

            typedef typename bg::strategy::relate::services::default_strategy
                <
                    Geometry1, Geometry2
                >::type strategy_type;
            bool result0 = bg::relate(geometry1, geometry2, bg::de9im::mask(expected1), strategy_type());
            BOOST_CHECK(result == result0);

            // test variants
            bool result1 = bg::relate(geometry1, variant2, bg::de9im::mask(expected1));
            bool result2 = bg::relate(variant1, geometry2, bg::de9im::mask(expected1));
            bool result3 = bg::relate(variant1, variant2, bg::de9im::mask(expected1));
            BOOST_CHECK(result == result1);
            BOOST_CHECK(result == result2);
            BOOST_CHECK(result == result3);
        }

        if ( BOOST_GEOMETRY_CONDITION((
                bg::detail::relate::interruption_enabled<Geometry1, Geometry2>::value )) )
        {
            // brake the expected output
            std::string expected_interrupt = expected1;
            bool changed = false;
            BOOST_FOREACH(char & c, expected_interrupt)
            {
                if ( c >= '0' && c <= '9' )
                {
                    if ( c == '0' )
                        c = 'F';
                    else
                        --c;

                    changed = true;
                }
            }

            if ( changed )
            {
                bool result = bg::relate(geometry1, geometry2, bg::de9im::mask(expected_interrupt));
                // TODO: SHOULD BE interrupted - CHECK THIS!
                BOOST_CHECK_MESSAGE(!result,
                    "relate: " << wkt1
                    << " and " << wkt2
                    << " -> Expected interrupt for:" << expected_interrupt);
            }
        }
    }
}

template <typename Geometry1, typename Geometry2>
void test_geometry(std::string const& wkt1,
                   std::string const& wkt2,
                   std::string const& expected1,
                   std::string const& expected2 = std::string())
{
    Geometry1 geometry1;
    Geometry2 geometry2;
    bg::read_wkt(wkt1, geometry1);
    bg::read_wkt(wkt2, geometry2);
    check_geometry(geometry1, geometry2, wkt1, wkt2, expected1, expected2);
}

#endif // BOOST_GEOMETRY_TEST_RELATE_HPP


/*
This file is a part of NNTL project (https://github.com/Arech/nntl)

Copyright (c) 2015-2021, Arech (aradvert@gmail.com; https://github.com/Arech)
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

* Neither the name of NNTL nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// tests.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

//to get rid of '... decorated name length exceeded, name was truncated'
#pragma warning( disable : 4503 )

#include "../nntl/nntl.h"
#include "../nntl/_supp/io/binfile.h"
#include "../nntl/_supp/io/matfile.h"

#include "../nntl/weights_init/LsuvExt.h"

#include "asserts.h"
#include "common_routines.h"

#include "nn_base_arch.h"

using namespace nntl;

template<typename ArchPrmsT>
struct GC_ALPHADROPOUT : public nntl_tests::NN_base_arch_td<ArchPrmsT> {
	typedef nntl::LFC_DO<activation::selu<real_t>, myGradWorks> testedLFC;

	testedLFC lFinal;

	~GC_ALPHADROPOUT()noexcept {}
	GC_ALPHADROPOUT(const ArchPrms_t& Prms)noexcept
		: lFinal(100, Prms.learningRate, "lFinal")
	{
		lFinal.dropoutPercentActive(Prms.specialDropoutAlivePerc);
	}
};
TEST(TestSelu, GradCheck_alphaDropout) {
#pragma warning(disable:4459)
	typedef double real_t;
	typedef nntl_tests::NN_base_params<real_t, nntl::inspector::GradCheck<real_t>> ArchPrms_t;
#pragma warning(default:4459)

	nntl::inmem_train_data<real_t> td;
	readTd(td);

	ArchPrms_t Prms(td);
	Prms.specialDropoutAlivePerc = real_t(.75);

	nntl_tests::NN_arch<GC_ALPHADROPOUT<ArchPrms_t>> nnArch(Prms);

	auto ec = nnArch.warmup(td, 5, 200);
	ASSERT_EQ(decltype(nnArch)::ErrorCode_t::Success, ec) << "Reason: " << nnArch.NN.get_error_str(ec);

	gradcheck_settings<real_t> ngcSetts(true, true, 1e-4);
	//ngcSetts.evalSetts.bIgnoreZerodLdWInUndelyingLayer = true;
	ngcSetts.evalSetts.dLdW_setts.relErrFailThrsh = real_t(1e-1);//big error is possible due to selu derivative kink :(
	//need some handling for it :(
	STDCOUTL("*** WARNING: there's no handling of SELU discontinious derivative, therefore occational failures are possible :(");
	ngcSetts.evalSetts.dLdA_setts.percOfZeros = 70;
	ngcSetts.evalSetts.dLdW_setts.percOfZeros = 70;
	ASSERT_TRUE(nnArch.NN.gradcheck(td.train_x(), td.train_y(), 5, ngcSetts));
}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
#pragma warning(push,3)
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <boost/accumulators/statistics/variance.hpp>
#pragma warning(pop)

template<typename RealT, bool bAdjustForSampleVar>
struct inspector_act_var_checker : public inspector::_impl::_base<RealT> {
protected:
	typedef utils::layer_idx_keeper<layer_index_t, _NoLayerIdxSpecified, 32> keeper_t;
	keeper_t m_curLayer;

	layer_index_t m_lastLayerIdxToCheck;

	//note that we don't compare variances, calculated with different algos now. We just need precise variance value, and no more
	typedef ::boost::accumulators::accumulator_set<ext_real_t
		, ::boost::accumulators::stats<
		::boost::accumulators::tag::mean
		, ::boost::accumulators::tag::lazy_variance
		>
	> stats_t;

	struct layers_stats_t {
		stats_t sMean;
		stats_t sVar;
	};

	typedef ::std::vector<layers_stats_t> a_layers_stat_t;
	a_layers_stat_t m_layersStats;

	void _calc_neuronwise_stats(const realmtx_t& act, const layer_index_t lidx)noexcept {
		auto& lStats = m_layersStats[lidx];

		const ptrdiff_t tr = act.rows();
		auto pA = act.data();
		const auto pAE = act.colDataAsVec(act.cols_no_bias());
		NNTL_ASSERT(tr > 1);
		const ext_real_t adjVar = bAdjustForSampleVar ? (static_cast<ext_real_t>(tr) / (tr - 1)) : ext_real_t(1);

		while (pA != pAE) {
			stats_t st;
			const auto pAEr = pA + tr;
			while (pA != pAEr) {
				st(*pA++);
			}

			lStats.sMean(::boost::accumulators::extract_result<::boost::accumulators::tag::mean>(st));
			lStats.sVar(adjVar*::boost::accumulators::extract_result<::boost::accumulators::tag::lazy_variance>(st));
		}
	}

public:
	void init_nnet(const size_t totalLayers, const numel_cnt_t totalEpochs)noexcept {
		NNTL_UNREF(totalEpochs);
		m_lastLayerIdxToCheck = static_cast<layer_index_t>(totalLayers - 2);
		m_layersStats.resize(totalLayers - 1);
	}
	void fprop_begin(const layer_index_t lIdx, const realmtx_t& prevAct, const bool bTrainingMode) noexcept {
		NNTL_UNREF(prevAct); NNTL_UNREF(bTrainingMode);
		m_curLayer.push(lIdx);
	}
	void fprop_end(const realmtx_t& act) noexcept {
		if (m_curLayer <= m_lastLayerIdxToCheck) {
			_calc_neuronwise_stats(act, m_curLayer);
		}

		m_curLayer.pop();
	}

	template<typename base_t> struct stats_EPS {};
	template<> struct stats_EPS<double> {
		static constexpr double mean_eps = .07;
		static constexpr double var_eps = .17;
	};
	template<> struct stats_EPS<float> {
		static constexpr float mean_eps = .07f;
		static constexpr float var_eps = .17f;
	};

	void report_stats(bool bDoAsserts = true)const noexcept {
		for (unsigned i = 0; i <= m_lastLayerIdxToCheck; ++i) {
			STDCOUTL("Reporting data distribution for layer#" << i << (i ? " -- SELU" : " -- input data"));

			const auto& lStats = m_layersStats[i];

			const ext_real_t _cnt = static_cast<ext_real_t>(::boost::accumulators::count(lStats.sMean));
			NNTL_ASSERT(_cnt > 1);
			const ext_real_t adjVar = bAdjustForSampleVar ? (_cnt / (_cnt - 1)) : ext_real_t(1);

			const auto mean_of_mean = ::boost::accumulators::extract_result<::boost::accumulators::tag::mean>(lStats.sMean);
			const auto var_of_mean = adjVar*::boost::accumulators::extract_result<::boost::accumulators::tag::lazy_variance>(lStats.sMean);
			const auto mean_of_var = ::boost::accumulators::extract_result<::boost::accumulators::tag::mean>(lStats.sVar);
			const auto var_of_var = adjVar*::boost::accumulators::extract_result<::boost::accumulators::tag::lazy_variance>(lStats.sVar);

			printf_s("mean = %05.3f +/- %06.4f, variance = %05.3f +/- %06.4f\n", mean_of_mean, ::std::sqrt(var_of_mean)
				, mean_of_var, ::std::sqrt(var_of_var));

			if (bDoAsserts) {
				//real_t is a type of underlying data, but we compare calculated statistics value with pre-set value, so with ext_real_t
				ASSERT_NEAR(mean_of_mean, ext_real_t(0), stats_EPS<real_t>::mean_eps);
				ASSERT_NEAR(mean_of_var, ext_real_t(1), stats_EPS<real_t>::var_eps);
			}
		}
	}

};

template<typename iRngT>
void _test_selu_make_td(inmem_train_data< typename iRngT::real_t >& td, const vec_len_t tr_cnt, const neurons_count_t xwidth, iRngT& iR)noexcept
{
	typedef typename iRngT::real_t real_t;
	typedef typename iRngT::realmtxdef_t realmtxdef_t;

	realmtxdef_t trX(tr_cnt, xwidth, true), trY(tr_cnt, 1), tX(2, xwidth, true), tY(2, 1);

	rng::distr_normal_naive<iRngT> rg(iR, real_t(0), real_t(1));
	rg.gen_matrix_no_bias(trX); rg.gen_matrix_no_bias(tX);

	iR.binary_matrix(trY), iR.binary_matrix(tY);

	ASSERT_TRUE(td.absorb(::std::move(trX), ::std::move(trY), ::std::move(tX), ::std::move(tY)));
}

//template<ADCorr corrType, typename RealT>
template<typename RealT>
void test_selu_distr(const size_t seedVal, const RealT dpa, const neurons_count_t xwidth = 10, const neurons_count_t nc = 30
	, const bool bApplyWeightNorm = false, const bool bVerbose = true
	, const vec_len_t batchSize = 1000, const vec_len_t batchesCnt = 100)noexcept
{
	typedef RealT real_t;

	constexpr unsigned _scopeMsgLen = 128;
	char _scopeMsg[_scopeMsgLen];
	sprintf_s(_scopeMsg, "SELU_Distribution for X=%d/nc=%d with dropout dpa=%04.3f", xwidth, nc, dpa);
	SCOPED_TRACE(_scopeMsg);
	STDCOUTL(_scopeMsg);

	const real_t learningRate(::std::numeric_limits<real_t>::min());

	struct myIntf : public d_int_nI<real_t> {
		typedef inspector_act_var_checker<real_t, true> iInspect_t;
	};
	typedef grad_works_f<myIntf
		, GW::ILR_dummy
		, GW::Loss_Addendums_dummy
	> GrW;

	//typedef activation::selu<real_t, 0, 0, 0, 1000000, corrType> mySelu_t;
	typedef activation::selu<real_t, 0, 0, 0, 1000000> mySelu_t;

	layer_input<myIntf> inp(xwidth);
	LFC_DO<mySelu_t, GrW> fcl(nc, learningRate);
	fcl.dropoutPercentActive(dpa);
#ifndef TESTS_SKIP_LONGRUNNING
	LFC_DO<mySelu_t, GrW> fcl2(nc, learningRate);
	fcl2.dropoutPercentActive(dpa);
	LFC_DO<mySelu_t, GrW> fcl3(nc, learningRate);
	fcl3.dropoutPercentActive(dpa);
	LFC_DO<mySelu_t, GrW> fcl4(nc, learningRate);
	fcl4.dropoutPercentActive(dpa);
#endif

	layer_output<activation::softsigm_quad_loss<real_t>, GrW> outp(1, learningRate);

#ifdef TESTS_SKIP_LONGRUNNING
	auto lp = make_layers(inp, fcl, outp);
#else
	auto lp = make_layers(inp, fcl, fcl2, fcl3, fcl4, outp);
#endif

	nnet_train_opts<real_t, training_observer_stdcout<real_t, eval_classification_binary_cached<real_t>>> opts(1);
	opts.batchSize(batchSize);

	auto nn = make_nnet(lp);

	nn.get_iRng().seed64(seedVal);

	inmem_train_data<real_t> td;
	_test_selu_make_td(td, batchesCnt*batchSize, xwidth, nn.get_iRng());

	if (bApplyWeightNorm) {
		typedef weights_init::procedural::LSUVExt<decltype(nn), ::std::decay_t<decltype(td)>> winit_t;
		winit_t::LayerSetts_t def, outpS;

		def.bOverPreActivations = false;
		def.bCentralNormalize = true;
		def.bScaleNormalize = true;
		def.bOnInvidualNeurons = true;
		def.maxTries = 10;
		def.targetScale = real_t(1.);
		def.bVerbose = bVerbose;

		outpS.bCentralNormalize = false;
		outpS.bScaleNormalize = false;
		outpS.bVerbose = bVerbose;

		winit_t obj(nn, td, def);

		obj.setts().add(outp.get_layer_idx(), outpS);

		//individual neuron stats requires a lot of data to be correctly evaluated
		if (!obj.run()) {
			STDCOUTL("*** Layer with ID=" << obj.m_firstFailedLayerIdx << " was the first to fail convergence. There might be more of them.");
		}
	}

	nn.get_iRng().seed64(seedVal + 1);

	auto ec = nn.train(td, opts);
	ASSERT_EQ(decltype(nn)::ErrorCode::Success, ec) << "Error code description: " << nn.get_last_error_string();

	ASSERT_NO_FATAL_FAILURE(nn.get_iInspect().report_stats(bVerbose));

}

TEST(TestSelu, SELU_Distribution) {
	typedef float real_t;

	//#TODO
	STDCOUTL("#The test may generate some false failures b/c of data variance. Need to redesign it.");

	const size_t t = ::std::time(0);
	const real_t dpa = real_t(.8);

	STDCOUTL("================ No weight renormalizing ================");
	ASSERT_NO_FATAL_FAILURE(test_selu_distr(t, real_t(1.), 10, 50, false));
	STDCOUTL("================ With weight renormalizing ================");
	ASSERT_NO_FATAL_FAILURE(test_selu_distr(t, real_t(1.), 10, 50, true));

	STDCOUTL("================ No weight renormalizing + AlphaDropout ================");
	ASSERT_NO_FATAL_FAILURE(test_selu_distr(t, dpa, 10, 50, false));
	STDCOUTL("================ With weight renormalizing + AlphaDropout ================");
	ASSERT_NO_FATAL_FAILURE(test_selu_distr(t, dpa, 10, 50, true));

#ifndef TESTS_SKIP_LONGRUNNING
	STDCOUTL("================ No weight renormalizing ================");
	ASSERT_NO_FATAL_FAILURE(test_selu_distr(t, real_t(1.), 100, 400, false));
	STDCOUTL("================ With weight renormalizing ================");
	ASSERT_NO_FATAL_FAILURE(test_selu_distr(t, real_t(1.), 100, 400, true));

	STDCOUTL("================ No weight renormalizing + AlphaDropout ================");
	ASSERT_NO_FATAL_FAILURE(test_selu_distr(t, dpa, 100, 400, false));
	STDCOUTL("================ With weight renormalizing + AlphaDropout ================");
	ASSERT_NO_FATAL_FAILURE(test_selu_distr(t, dpa, 100, 400, true));
#endif

	/*STDCOUTL("================ No weight renormalizing ================");
	ASSERT_NO_FATAL_FAILURE(test_selu_distr<ADCorr::no>(t, real_t(1.), 10, 50, false));
	STDCOUTL("================ With weight renormalizing ================");
	ASSERT_NO_FATAL_FAILURE(test_selu_distr<ADCorr::no>(t, real_t(1.), 10, 50, true));

	STDCOUTL("================ No weight renormalizing + AlphaDropout ================");
	ASSERT_NO_FATAL_FAILURE(test_selu_distr<ADCorr::no>(t, dpa, 10, 50, false));
	STDCOUTL("================ With weight renormalizing + AlphaDropout ================");
	ASSERT_NO_FATAL_FAILURE(test_selu_distr<ADCorr::no>(t, dpa, 10, 50, true));

#ifndef TESTS_SKIP_LONGRUNNING
	STDCOUTL("================ No weight renormalizing ================");
	ASSERT_NO_FATAL_FAILURE(test_selu_distr<ADCorr::no>(t, real_t(1.), 100, 400, false));
	STDCOUTL("================ With weight renormalizing ================");
	ASSERT_NO_FATAL_FAILURE(test_selu_distr<ADCorr::no>(t, real_t(1.), 100, 400, true));

	STDCOUTL("================ No weight renormalizing + AlphaDropout ================");
	ASSERT_NO_FATAL_FAILURE(test_selu_distr<ADCorr::no>(t, dpa, 100, 400, false));
	STDCOUTL("================ With weight renormalizing + AlphaDropout ================");
	ASSERT_NO_FATAL_FAILURE(test_selu_distr<ADCorr::no>(t, dpa, 100, 400, true));

	STDCOUTL("Assessing corrections (without weight renormalizing)");
	STDCOUTL("ADCorr::correctVar");
	ASSERT_NO_FATAL_FAILURE(test_selu_distr<ADCorr::correctVar>(t, dpa, 100, 400, false));
	STDCOUTL("ADCorr::correctDoVal");
	ASSERT_NO_FATAL_FAILURE(test_selu_distr<ADCorr::correctDoVal>(t, dpa, 100, 400, false));
	STDCOUTL("ADCorr::correctDoAndVar");
	ASSERT_NO_FATAL_FAILURE(test_selu_distr<ADCorr::correctDoAndVar>(t, dpa, 100, 400, false));
#endif*/
}

/*
TEST(TestSelu, AlphaDropoutDistributionWithCorrection) {
	typedef float real_t;

	const size_t t = ::std::time(0);

	vec_len_t xW = 20;

	for (neurons_count_t nc = 5; nc <= 30; nc+=5) {
		real_t dpa = real_t(0.97);
		STDCOUTL(::std::endl<<"================ No correction ================");
		ASSERT_NO_FATAL_FAILURE((test_selu_distr<real_t, false>(t, dpa, xW, nc, true, false)));
		STDCOUTL("================ With correction ================");
		ASSERT_NO_FATAL_FAILURE((test_selu_distr<real_t, true>(t, dpa, xW, nc, true, false)));

		dpa = real_t(0.7);
		STDCOUTL("================ No correction ================");
		ASSERT_NO_FATAL_FAILURE((test_selu_distr<real_t, false>(t, dpa, xW, nc, true, false)));
		STDCOUTL("================ With correction ================");
		ASSERT_NO_FATAL_FAILURE((test_selu_distr<real_t, true>(t, dpa, xW, nc, true, false)));
	}

}*/


//
// Copyright (c) 2002--2010
// Toon Knapen, Karl Meerbergen, Kresimir Fresl,
// Thomas Klimpel and Rutger ter Borg
//
// 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)
//
// THIS FILE IS AUTOMATICALLY GENERATED
// PLEASE DO NOT EDIT!
//

#ifndef BOOST_NUMERIC_BINDINGS_LAPACK_AUXILIARY_LARFG_HPP
#define BOOST_NUMERIC_BINDINGS_LAPACK_AUXILIARY_LARFG_HPP

#include <boost/assert.hpp>
#include <boost/numeric/bindings/begin.hpp>
#include <boost/numeric/bindings/is_complex.hpp>
#include <boost/numeric/bindings/is_mutable.hpp>
#include <boost/numeric/bindings/is_real.hpp>
#include <boost/numeric/bindings/remove_imaginary.hpp>
#include <boost/numeric/bindings/size.hpp>
#include <boost/numeric/bindings/stride.hpp>
#include <boost/numeric/bindings/value_type.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/utility/enable_if.hpp>

//
// The LAPACK-backend for larfg is the netlib-compatible backend.
//
#include <boost/numeric/bindings/lapack/detail/lapack.h>
#include <boost/numeric/bindings/lapack/detail/lapack_option.hpp>

namespace boost {
namespace numeric {
namespace bindings {
namespace lapack {

//
// The detail namespace contains value-type-overloaded functions that
// dispatch to the appropriate back-end LAPACK-routine.
//
namespace detail {

//
// Overloaded function for dispatching to
// * netlib-compatible LAPACK backend (the default), and
// * float value-type.
//
inline std::ptrdiff_t larfg( const fortran_int_t n, float& alpha, float* x,
        const fortran_int_t incx, float& tau ) {
    fortran_int_t info(0);
    LAPACK_SLARFG( &n, &alpha, x, &incx, &tau );
    return info;
}

//
// Overloaded function for dispatching to
// * netlib-compatible LAPACK backend (the default), and
// * double value-type.
//
inline std::ptrdiff_t larfg( const fortran_int_t n, double& alpha, double* x,
        const fortran_int_t incx, double& tau ) {
    fortran_int_t info(0);
    LAPACK_DLARFG( &n, &alpha, x, &incx, &tau );
    return info;
}

//
// Overloaded function for dispatching to
// * netlib-compatible LAPACK backend (the default), and
// * complex<float> value-type.
//
inline std::ptrdiff_t larfg( const fortran_int_t n, std::complex<float>& alpha,
        std::complex<float>* x, const fortran_int_t incx,
        std::complex<float>& tau ) {
    fortran_int_t info(0);
    LAPACK_CLARFG( &n, &alpha, x, &incx, &tau );
    return info;
}

//
// Overloaded function for dispatching to
// * netlib-compatible LAPACK backend (the default), and
// * complex<double> value-type.
//
inline std::ptrdiff_t larfg( const fortran_int_t n,
        std::complex<double>& alpha, std::complex<double>* x,
        const fortran_int_t incx, std::complex<double>& tau ) {
    fortran_int_t info(0);
    LAPACK_ZLARFG( &n, &alpha, x, &incx, &tau );
    return info;
}

} // namespace detail

//
// Value-type based template class. Use this class if you need a type
// for dispatching to larfg.
//
template< typename Value, typename Enable = void >
struct larfg_impl {};

//
// This implementation is enabled if Value is a real type.
//
template< typename Value >
struct larfg_impl< Value, typename boost::enable_if< is_real< Value > >::type > {

    typedef Value value_type;
    typedef typename remove_imaginary< Value >::type real_type;

    //
    // Static member function, that
    // * Deduces the required arguments for dispatching to LAPACK, and
    // * Asserts that most arguments make sense.
    //
    template< typename VectorX >
    static std::ptrdiff_t invoke( const fortran_int_t n, real_type& alpha,
            VectorX& x, real_type& tau ) {
        namespace bindings = ::boost::numeric::bindings;
        BOOST_STATIC_ASSERT( (bindings::is_mutable< VectorX >::value) );
        return detail::larfg( n, alpha, bindings::begin_value(x),
                bindings::stride(x), tau );
    }

};

//
// This implementation is enabled if Value is a complex type.
//
template< typename Value >
struct larfg_impl< Value, typename boost::enable_if< is_complex< Value > >::type > {

    typedef Value value_type;
    typedef typename remove_imaginary< Value >::type real_type;

    //
    // Static member function, that
    // * Deduces the required arguments for dispatching to LAPACK, and
    // * Asserts that most arguments make sense.
    //
    template< typename VectorX >
    static std::ptrdiff_t invoke( const fortran_int_t n, value_type& alpha,
            VectorX& x, value_type& tau ) {
        namespace bindings = ::boost::numeric::bindings;
        BOOST_STATIC_ASSERT( (bindings::is_mutable< VectorX >::value) );
        return detail::larfg( n, alpha, bindings::begin_value(x),
                bindings::stride(x), tau );
    }

};

//
// Functions for direct use. These functions are overloaded for temporaries,
// so that wrapped types can still be passed and used for write-access. In
// addition, if applicable, they are overloaded for user-defined workspaces.
// Calls to these functions are passed to the larfg_impl classes. In the
// documentation, most overloads are collapsed to avoid a large number of
// prototypes which are very similar.
//

//
// Overloaded function for larfg. Its overload differs for
//
template< typename VectorX >
inline std::ptrdiff_t larfg( const fortran_int_t n,
        typename remove_imaginary< typename bindings::value_type<
        VectorX >::type >::type& alpha, VectorX& x, typename remove_imaginary<
        typename bindings::value_type< VectorX >::type >::type& tau ) {
    return larfg_impl< typename bindings::value_type<
            VectorX >::type >::invoke( n, alpha, x, tau );
}

//
// Overloaded function for larfg. Its overload differs for
//
template< typename VectorX >
inline std::ptrdiff_t larfg( const fortran_int_t n,
        typename bindings::value_type< VectorX >::type& alpha, VectorX& x,
        typename bindings::value_type< VectorX >::type& tau ) {
    return larfg_impl< typename bindings::value_type<
            VectorX >::type >::invoke( n, alpha, x, tau );
}

} // namespace lapack
} // namespace bindings
} // namespace numeric
} // namespace boost

#endif


/*! \file demo_1d_plot.cpp
    \brief Demonstration of many features for 1D plots.
    \details Contains Quickbook markup.

    \author Paul A. Bristow
*/

// Copyright Jacob Voytko 2007
// Copyright Paul A Bristow 2008, 2020

// Use, modification and distribution are subject to 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)

// This file is written to be included from a Quickbook .qbk document.
// It can be compiled by the C++ compiler, and run. Any output can
// also be added here as comment or included or pasted in elsewhere.

// Caution: this file contains Quickbook markup as well as code
// and comments: don't change any of the special comment markups!

//[demo_1d_plot_1
// An entirely contrived example designed to demonstration
// as many features as possible in a single example.
// The results is not intended to be useful,
// nor is it intended to be pretty, but solely to highlight features used!
// See other examples for more practical (and tasteful) examples using typical features.

#include <boost/svg_plot/svg_1d_plot.hpp>
  using namespace boost::svg;
  using boost::svg::svg_1d_plot;

#include <boost/svg_plot/show_1d_settings.hpp>
// void boost::svg::show_1d_plot_settings(svg_1d_plot&);

#include <boost/svg_plot/svg_fwd.hpp> // forward declarations.
// for testing its correctness.

#include <iostream> // for debugging.
 // using std::cout;
 // using std::endl;

#include <vector>
 // using std::vector;

#include <limits>
//  using std::numeric_limits;

int main()
{
  std::vector<double> my_data1;
  // Initialize my_data here with some entirely fictional data.
  my_data1.push_back(0.1);
  my_data1.push_back(1.1);
  my_data1.push_back(4.2);
  my_data1.push_back(3.3);
  my_data1.push_back(5.4);
  my_data1.push_back(6.5);

  std::vector<double> my_data2;
  // Initialize my_data here with some more entirely fictional data.
  my_data2.push_back(0.5);
  my_data2.push_back(1.5);
  my_data2.push_back(4.7);

  std::vector<double> my_data3;
  // Initialize my_data here with some more entirely fictional data.
  my_data3.push_back(0.7);
  my_data3.push_back(2.5);
  my_data3.push_back(5.8);

  std::vector<double> my_data4;
  // Initialize my_data with some integral values so can check points are marked exactly right.
  my_data4.push_back(1.);
  my_data4.push_back(2.);
  my_data4.push_back(3.);
  my_data4.push_back(6.);
  my_data4.push_back(7.);
  my_data4.push_back(8.);

  std::vector<double> my_data5;
  my_data5.push_back(0.);
  my_data5.push_back(-1.);
  my_data5.push_back(+1.);
  // Include an out-of-axis range value:
  my_data5.push_back(999.9);
  // Max and min values.
  my_data5.push_back((std::numeric_limits<double>::max)());
  my_data5.push_back((std::numeric_limits<double>::min)());
  // and non-finite values.
  my_data5.push_back((std::numeric_limits<double>::quiet_NaN)());
  my_data5.push_back((std::numeric_limits<double>::infinity)());

  svg_1d_plot my_1d_plot; // Construct with all the default constructor values.
  std::cout << "Image x & y " << my_1d_plot.x_size() << " by " << my_1d_plot.y_size() << std::endl;
  //my_1d_plot.size(100,100); // Alter both together.
  //cout << "Image x & y " << my_1d_plot.x_size() << " by " << my_1d_plot.y_size() << endl;
  //// And alter both separately.
  //my_1d_plot.x_size(200);
  //my_1d_plot.y_size(600);
  //cout << "Image x & y " << my_1d_plot.x_size() << " by " << my_1d_plot.y_size() << endl;

  my_1d_plot.document_title("Document title demo_1d_plot"); // This text shows on the browser tab.
  my_1d_plot.description("My demo_1d_plot description");
  my_1d_plot.copyright_date("2008-03-29");
  my_1d_plot.copyright_holder("Paul A. Bristow");
  my_1d_plot.license("permits", "permits", "requires", "permits", "permits"); // Require notice only.
  //see  http://creativecommons.org/licenses/ for details.
  my_1d_plot.coord_precision(4);

 std::cout << "font-family was " << my_1d_plot.title_font_family() << std::endl;

  my_1d_plot
  .y_size(250)
  .background_color(ghostwhite) // whole image.
  .background_border_color(aqua) //
  .background_border_width(10.) //
  .plot_window_on(true) //
  .plot_background_color(aliceblue) // just the plot area.
  .plot_border_color(pink)
  .plot_border_width(5.)
  .title("Demo 1D plot -α  Ω Φ √ ∞ ζ ±")
    // domain of the random variable is [0, ∞]") //  Capital Omega <superscript> Ω </superscript>") doesn't work yet.
  .title_font_size(20)
  .title_font_family("Times New Roman")
  .title_color(magenta)
  .legend_on(true)
  .legend_background_color(beige)
  .legend_border_color(chocolate)
  .legend_title("My Legend μ") // generates μ  greek mu
  .legend_title_font_size(12)
  .legend_font_family("arial") // "arial", "impact", "courier", "lucida console",  "Lucida sans unicode", "verdana"
  .legend_font_weight("bold")
  .legend_color(darkgreen)
  .legend_lines(false) // Horizontal sample color line not useful if already showing values with colored shapes.
  .x_label_on(true) // show x-axis text label.
  .x_label("volume") // Care: this doesn't show unless .x_label_on() == true!
  .x_axis_color(blue)
  .x_label_color(blue)
  //.x_label_font_family("Verdana")
  .x_label_font_family("Lucida sans unicode")
//  .x_label_font_family("Times New Roman")
  .x_label_units_on(true)
  .x_label_font_size(12)
  .x_label_units(" (meter³ or m³)") // super 2 = ² super 3 = ³
  // Note you must provide any space and any brackets if required.
  // Care: this doesn't show unless .x_label_units_on() == true!
  // Ticks
  .x_ticks_up_on(true) //
  .x_ticks_down_on(true) // So have Up and downward ticks.
  // Add grid - not very useful for 1D.
  .x_major_tick_width(3)
  .x_major_tick_length(10)
  .x_minor_tick_length(7)
  .x_major_grid_on(true)
  .x_major_grid_width(2)
  .x_major_grid_color(lightblue)
  .x_minor_grid_on(true)
  .x_minor_grid_width(1)
  .x_minor_grid_color(pink)
  .nan_limit_color(red)
  .nan_limit_fill_color(green)
  .x_ticks_on_window_or_axis(0) // -1 bottom, 0 on axis, +1 top

  .x_range(-1., 7.); // Display range.

  //my_1d_plot.plot(my_data1, "my values 1");

  //my_1d_plot.plot(my_data2, "my values round").shape(round).size(10).fill_color(pink);

  //my_1d_plot.plot(my_data1, "my values 1").shape(vertical_tick);

  //my_1d_plot.plot(my_data2, "my red values ").stroke_color(red).fill_color(blue);

  my_1d_plot.plot(my_data3, "data3").shape(diamond).size(10).stroke_color(red).fill_color(blue);
  my_1d_plot.plot(my_data4, "data4").shape(symbol).size(20);
  my_1d_plot.plot(my_data5, "data5").shape(cone).symbols("Ω").stroke_color(magenta).fill_color(aqua);
  //my_1d_plot.plot(my_data4, "data4").shape(symbol).symbols("✡").stroke_color(magenta).fill_color(aqua);
 // // U+2721 is Star of David or hexagram http://en.wikipedia.org/wiki/Hexagram

  my_1d_plot.write("demo_1d_plot.svg");

  show_1d_plot_settings(my_1d_plot);

//] [/demo_1d_plot_1]

  return 0;
} // int main()

/*

Compiling...
demo_1d_plot.cpp
Linking...
Embedding manifest...
Autorun "j:\Cpp\SVG\debug\demo_1d_plot.exe"
Build Time 0:11

*/


/**
 * \file libs/numeric/ublasx/test/for_each.cpp
 *
 * \brief Test suite for the \c for_each operation.
 *
 * Copyright (c) 2010, Marco Guazzone
 *
 * 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)
 *
 * \author Marco Guazzone, marco.guazzone@gmail.com
 */

#include <boost/bind.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublasx/operation/for_each.hpp>
#include <boost/numeric/ublasx/tags.hpp>
#include <cstddef>
#include <functional>
#include <iostream>
#include "libs/numeric/ublasx/test/utils.hpp"

namespace ublas = ::boost::numeric::ublas;
namespace ublasx = ::boost::numeric::ublasx;

static const double tol = 1.0e-5;

template <typename T>
static void my_function(T const& x)
{
	BOOST_UBLASX_DEBUG_TRACE("x = " << x);
}

template <typename T>
struct my_functor: public std::unary_function<T,void>
{
	void operator()(T const& x) const
	{
		BOOST_UBLASX_DEBUG_TRACE("x = " << x);
	}
};

template <typename T>
void my_add(T const& x, T& s)
{
	s += x;
}

template <typename T>
struct my_adder
{
	void operator()(T const& x, T& s) const
	{
		s += x;
	}
};

BOOST_UBLASX_TEST_DEF( test_vector_function )
{
	BOOST_UBLASX_DEBUG_TRACE("Test Case: Vector - Function");

	typedef double value_type;
	typedef ublas::vector<value_type> vector_type;

	const std::size_t n(4);

	vector_type v(n);
	v(0) =  1;
	v(1) = -2;
	v(2) = -3;
	v(3) =  4;

	ublasx::for_each(v, my_function<value_type>);

	BOOST_UBLASX_TEST_CHECK(true);
}

BOOST_UBLASX_TEST_DEF( test_vector_functor )
{
	BOOST_UBLASX_DEBUG_TRACE("Test Case: Vector - Functor");

	typedef double value_type;
	typedef ublas::vector<value_type> vector_type;

	const std::size_t n(4);

	vector_type v(n);
	v(0) =  1;
	v(1) = -2;
	v(2) = -3;
	v(3) =  4;

	ublasx::for_each(v, my_functor<value_type>());

	BOOST_UBLASX_TEST_CHECK(true);
}

BOOST_UBLASX_TEST_DEF( test_vector_bound_function )
{
	BOOST_UBLASX_DEBUG_TRACE("Test Case: Vector - Bound Function");

	typedef double value_type;
	typedef std::size_t size_type;
	typedef ublas::vector<value_type> vector_type;

	const size_type n(4);

	vector_type v(n);
	v(0) =  1;
	v(1) = -2;
	v(2) = -3;
	v(3) =  4;

	value_type res(0);
	value_type expect_res(0);

	ublasx::for_each(v, boost::bind<void>(my_add<value_type>, _1, boost::ref(res)));

	BOOST_UBLASX_DEBUG_TRACE( "res = " << res );

	for (size_type i = 0; i < n; ++i)
	{
		expect_res += v(i);
	}

	BOOST_UBLASX_TEST_CHECK_CLOSE( res, expect_res, tol );
}

BOOST_UBLASX_TEST_DEF( test_vector_bound_functor )
{
	BOOST_UBLASX_DEBUG_TRACE("Test Case: Vector - Bound Functor");

	typedef double value_type;
	typedef std::size_t size_type;
	typedef ublas::vector<value_type> vector_type;

	const size_type n(4);

	vector_type v(n);
	v(0) =  1;
	v(1) = -2;
	v(2) = -3;
	v(3) =  4;

	value_type res(0);
	value_type expect_res(0);

	ublasx::for_each(v, boost::bind<void>(my_adder<value_type>(), _1, boost::ref(res)));

	BOOST_UBLASX_DEBUG_TRACE( "res = " << res );

	for (size_type i = 0; i < n; ++i)
	{
		expect_res += v(i);
	}

	BOOST_UBLASX_TEST_CHECK_CLOSE( res, expect_res, tol );
}

BOOST_UBLASX_TEST_DEF( test_matrix_function )
{
	BOOST_UBLASX_DEBUG_TRACE("Test Case: Matrix - Function");

	typedef double value_type;
	typedef ublas::matrix<value_type> matrix_type;

	const std::size_t nr(2);
	const std::size_t nc(3);

	matrix_type A(nr,nc);
	A(0,0) =  1; A(0,1) = -2; A(0,2) = -3;
	A(1,0) =  4; A(1,1) =  5; A(1,2) =  6;

	ublasx::for_each(A, my_function<value_type>);

	BOOST_UBLASX_TEST_CHECK(true);
}

BOOST_UBLASX_TEST_DEF( test_matrix_functor )
{
	BOOST_UBLASX_DEBUG_TRACE("Test Case: Matrix - Functor");

	typedef double value_type;
	typedef ublas::matrix<value_type> matrix_type;

	const std::size_t nr(2);
	const std::size_t nc(3);

	matrix_type A(nr,nc);
	A(0,0) =  1; A(0,1) = -2; A(0,2) = -3;
	A(1,0) =  4; A(1,1) =  5; A(1,2) =  6;

	ublasx::for_each(A, my_functor<value_type>());

	BOOST_UBLASX_TEST_CHECK(true);
}

BOOST_UBLASX_TEST_DEF( test_matrix_bound_function )
{
	BOOST_UBLASX_DEBUG_TRACE("Test Case: Matrix - Bound Function");

	typedef double value_type;
	typedef std::size_t size_type;
	typedef ublas::matrix<value_type> matrix_type;

	const size_type nr(2);
	const size_type nc(3);

	matrix_type A(nr,nc);
	A(0,0) =  1; A(0,1) = -2; A(0,2) = -3;
	A(1,0) =  4; A(1,1) =  5; A(1,2) =  6;

	value_type res(0);
	value_type expect_res(0);

	ublasx::for_each(A, boost::bind<void>(my_add<value_type>, _1, boost::ref(res)));

	BOOST_UBLASX_DEBUG_TRACE( "res = " << res );

	for (size_type r = 0; r < nr; ++r)
	{
		for (size_type c = 0; c < nc; ++c)
		{
			expect_res += A(r,c);
		}
	}

	BOOST_UBLASX_TEST_CHECK_CLOSE( res, expect_res, tol );
}

BOOST_UBLASX_TEST_DEF( test_matrix_bound_functor )
{
	BOOST_UBLASX_DEBUG_TRACE("Test Case: Matrix - Bound Function");

	typedef double value_type;
	typedef std::size_t size_type;
	typedef ublas::matrix<value_type> matrix_type;

	const size_type nr(2);
	const size_type nc(3);

	matrix_type A(nr,nc);
	A(0,0) =  1; A(0,1) = -2; A(0,2) = -3;
	A(1,0) =  4; A(1,1) =  5; A(1,2) =  6;

	value_type res(0);
	value_type expect_res(0);

	ublasx::for_each(A, boost::bind<void>(my_adder<value_type>(), _1, boost::ref(res)));

	BOOST_UBLASX_DEBUG_TRACE( "res = " << res );

	for (size_type r = 0; r < nr; ++r)
	{
		for (size_type c = 0; c < nc; ++c)
		{
			expect_res += A(r,c);
		}
	}

	BOOST_UBLASX_TEST_CHECK_CLOSE( res, expect_res, tol );
}

BOOST_UBLASX_TEST_DEF( test_matrix_function_dim1 )
{
	BOOST_UBLASX_DEBUG_TRACE("Test Case: Matrix - Function - By Dimension: 1");

	typedef double value_type;
	typedef ublas::matrix<value_type> matrix_type;

	const std::size_t nr(2);
	const std::size_t nc(3);

	matrix_type A(nr,nc);
	A(0,0) =  1; A(0,1) = -2; A(0,2) = -3;
	A(1,0) =  4; A(1,1) =  5; A(1,2) =  6;

	ublasx::for_each<1>(A, my_function<value_type>);

	BOOST_UBLASX_TEST_CHECK(true);
}

BOOST_UBLASX_TEST_DEF( test_matrix_functor_dim1 )
{
	BOOST_UBLASX_DEBUG_TRACE("Test Case: Matrix - Functor - By Dimension: 1");

	typedef double value_type;
	typedef ublas::matrix<value_type> matrix_type;

	const std::size_t nr(2);
	const std::size_t nc(3);

	matrix_type A(nr,nc);
	A(0,0) =  1; A(0,1) = -2; A(0,2) = -3;
	A(1,0) =  4; A(1,1) =  5; A(1,2) =  6;

	ublasx::for_each<1>(A, my_functor<value_type>());

	BOOST_UBLASX_TEST_CHECK(true);
}

BOOST_UBLASX_TEST_DEF( test_matrix_function_dim2 )
{
	BOOST_UBLASX_DEBUG_TRACE("Test Case: Matrix - Function - By Dimension: 2");

	typedef double value_type;
	typedef ublas::matrix<value_type> matrix_type;

	const std::size_t nr(2);
	const std::size_t nc(3);

	matrix_type A(nr,nc);
	A(0,0) =  1; A(0,1) = -2; A(0,2) = -3;
	A(1,0) =  4; A(1,1) =  5; A(1,2) =  6;

	ublasx::for_each<2>(A, my_function<value_type>);

	BOOST_UBLASX_TEST_CHECK(true);
}

BOOST_UBLASX_TEST_DEF( test_matrix_functor_dim2 )
{
	BOOST_UBLASX_DEBUG_TRACE("Test Case: Matrix - Functor - By Dimension: 2");

	typedef double value_type;
	typedef ublas::matrix<value_type> matrix_type;

	const std::size_t nr(2);
	const std::size_t nc(3);

	matrix_type A(nr,nc);
	A(0,0) =  1; A(0,1) = -2; A(0,2) = -3;
	A(1,0) =  4; A(1,1) =  5; A(1,2) =  6;

	ublasx::for_each<2>(A, my_functor<value_type>());

	BOOST_UBLASX_TEST_CHECK(true);
}

BOOST_UBLASX_TEST_DEF( test_matrix_function_dim_major )
{
	BOOST_UBLASX_DEBUG_TRACE("Test Case: Matrix - Function - By Dimension: Major");

	typedef double value_type;
	typedef ublas::matrix<value_type> matrix_type;

	const std::size_t nr(2);
	const std::size_t nc(3);

	matrix_type A(nr,nc);
	A(0,0) =  1; A(0,1) = -2; A(0,2) = -3;
	A(1,0) =  4; A(1,1) =  5; A(1,2) =  6;

	ublasx::for_each_by_tag<ublasx::tag::major>(A, my_function<value_type>);

	BOOST_UBLASX_TEST_CHECK(true);
}

BOOST_UBLASX_TEST_DEF( test_matrix_functor_dim_major )
{
	BOOST_UBLASX_DEBUG_TRACE("Test Case: Matrix - Functor - By Dimension: Major");

	typedef double value_type;
	typedef ublas::matrix<value_type> matrix_type;

	const std::size_t nr(2);
	const std::size_t nc(3);

	matrix_type A(nr,nc);
	A(0,0) =  1; A(0,1) = -2; A(0,2) = -3;
	A(1,0) =  4; A(1,1) =  5; A(1,2) =  6;

	ublasx::for_each_by_tag<ublasx::tag::major>(A, my_functor<value_type>());

	BOOST_UBLASX_TEST_CHECK(true);
}

BOOST_UBLASX_TEST_DEF( test_matrix_function_dim_minor )
{
	BOOST_UBLASX_DEBUG_TRACE("Test Case: Matrix - Function - By Dimension: Minor");

	typedef double value_type;
	typedef ublas::matrix<value_type> matrix_type;

	const std::size_t nr(2);
	const std::size_t nc(3);

	matrix_type A(nr,nc);
	A(0,0) =  1; A(0,1) = -2; A(0,2) = -3;
	A(1,0) =  4; A(1,1) =  5; A(1,2) =  6;

	ublasx::for_each_by_tag<ublasx::tag::minor>(A, my_function<value_type>);

	BOOST_UBLASX_TEST_CHECK(true);
}

BOOST_UBLASX_TEST_DEF( test_matrix_functor_dim_minor )
{
	BOOST_UBLASX_DEBUG_TRACE("Test Case: Matrix - Functor - By Dimension: Minor");

	typedef double value_type;
	typedef ublas::matrix<value_type> matrix_type;

	const std::size_t nr(2);
	const std::size_t nc(3);

	matrix_type A(nr,nc);
	A(0,0) =  1; A(0,1) = -2; A(0,2) = -3;
	A(1,0) =  4; A(1,1) =  5; A(1,2) =  6;

	ublasx::for_each_by_tag<ublasx::tag::minor>(A, my_functor<value_type>());

	BOOST_UBLASX_TEST_CHECK(true);
}

int main()
{
    BOOST_UBLASX_DEBUG_TRACE("Test Suite: 'for_each' operation");

	BOOST_UBLASX_TEST_BEGIN();

	BOOST_UBLASX_TEST_DO( test_vector_function );
	BOOST_UBLASX_TEST_DO( test_vector_functor );
	BOOST_UBLASX_TEST_DO( test_matrix_function );
	BOOST_UBLASX_TEST_DO( test_matrix_functor );
	BOOST_UBLASX_TEST_DO( test_matrix_function_dim1 );
	BOOST_UBLASX_TEST_DO( test_matrix_functor_dim1 );
	BOOST_UBLASX_TEST_DO( test_matrix_function_dim2 );
	BOOST_UBLASX_TEST_DO( test_matrix_functor_dim2 );
	BOOST_UBLASX_TEST_DO( test_matrix_function_dim_major );
	BOOST_UBLASX_TEST_DO( test_matrix_functor_dim_major );
	BOOST_UBLASX_TEST_DO( test_matrix_function_dim_minor );
	BOOST_UBLASX_TEST_DO( test_matrix_functor_dim_minor );
	BOOST_UBLASX_TEST_DO( test_vector_bound_function );
	BOOST_UBLASX_TEST_DO( test_vector_bound_functor );
	BOOST_UBLASX_TEST_DO( test_matrix_bound_function );
	BOOST_UBLASX_TEST_DO( test_matrix_bound_functor );

	BOOST_UBLASX_TEST_END();
}


/**
 * @ file
 * @ brief NPDE homework TEMPLATE MAIN FILE
 * @ author Tobias Rohner
 * @ date 25-03-2022
 * @ copyright Developed at SAM, ETH Zurich
 */

#include <Eigen/Core>
#include <iostream>

#include "mehrstellenverfahren.h"

int main(int /*argc*/, char** /*argv*/) {
  mehrstellenverfahren::tabulateMehrstellenError();
  return 0;
}


//
// Copyright (c) 2002--2010
// Toon Knapen, Karl Meerbergen, Kresimir Fresl,
// Thomas Klimpel and Rutger ter Borg
//
// 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)
//
// THIS FILE IS AUTOMATICALLY GENERATED
// PLEASE DO NOT EDIT!
//

#ifndef BOOST_NUMERIC_BINDINGS_LAPACK_DRIVER_GTSV_HPP
#define BOOST_NUMERIC_BINDINGS_LAPACK_DRIVER_GTSV_HPP

#include <boost/assert.hpp>
#include <boost/numeric/bindings/begin.hpp>
#include <boost/numeric/bindings/is_column_major.hpp>
#include <boost/numeric/bindings/is_mutable.hpp>
#include <boost/numeric/bindings/remove_imaginary.hpp>
#include <boost/numeric/bindings/size.hpp>
#include <boost/numeric/bindings/stride.hpp>
#include <boost/numeric/bindings/value_type.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_const.hpp>

//
// The LAPACK-backend for gtsv is the netlib-compatible backend.
//
#include <boost/numeric/bindings/lapack/detail/lapack.h>
#include <boost/numeric/bindings/lapack/detail/lapack_option.hpp>

namespace boost {
namespace numeric {
namespace bindings {
namespace lapack {

//
// The detail namespace contains value-type-overloaded functions that
// dispatch to the appropriate back-end LAPACK-routine.
//
namespace detail {

//
// Overloaded function for dispatching to
// * netlib-compatible LAPACK backend (the default), and
// * float value-type.
//
inline std::ptrdiff_t gtsv( const fortran_int_t n, const fortran_int_t nrhs,
        float* dl, float* d, float* du, float* b, const fortran_int_t ldb ) {
    fortran_int_t info(0);
    LAPACK_SGTSV( &n, &nrhs, dl, d, du, b, &ldb, &info );
    return info;
}

//
// Overloaded function for dispatching to
// * netlib-compatible LAPACK backend (the default), and
// * double value-type.
//
inline std::ptrdiff_t gtsv( const fortran_int_t n, const fortran_int_t nrhs,
        double* dl, double* d, double* du, double* b,
        const fortran_int_t ldb ) {
    fortran_int_t info(0);
    LAPACK_DGTSV( &n, &nrhs, dl, d, du, b, &ldb, &info );
    return info;
}

//
// Overloaded function for dispatching to
// * netlib-compatible LAPACK backend (the default), and
// * complex<float> value-type.
//
inline std::ptrdiff_t gtsv( const fortran_int_t n, const fortran_int_t nrhs,
        std::complex<float>* dl, std::complex<float>* d,
        std::complex<float>* du, std::complex<float>* b,
        const fortran_int_t ldb ) {
    fortran_int_t info(0);
    LAPACK_CGTSV( &n, &nrhs, dl, d, du, b, &ldb, &info );
    return info;
}

//
// Overloaded function for dispatching to
// * netlib-compatible LAPACK backend (the default), and
// * complex<double> value-type.
//
inline std::ptrdiff_t gtsv( const fortran_int_t n, const fortran_int_t nrhs,
        std::complex<double>* dl, std::complex<double>* d,
        std::complex<double>* du, std::complex<double>* b,
        const fortran_int_t ldb ) {
    fortran_int_t info(0);
    LAPACK_ZGTSV( &n, &nrhs, dl, d, du, b, &ldb, &info );
    return info;
}

} // namespace detail

//
// Value-type based template class. Use this class if you need a type
// for dispatching to gtsv.
//
template< typename Value >
struct gtsv_impl {

    typedef Value value_type;
    typedef typename remove_imaginary< Value >::type real_type;

    //
    // Static member function, that
    // * Deduces the required arguments for dispatching to LAPACK, and
    // * Asserts that most arguments make sense.
    //
    template< typename VectorDL, typename VectorD, typename VectorDU,
            typename MatrixB >
    static std::ptrdiff_t invoke( const fortran_int_t n, VectorDL& dl,
            VectorD& d, VectorDU& du, MatrixB& b ) {
        namespace bindings = ::boost::numeric::bindings;
        BOOST_STATIC_ASSERT( (bindings::is_column_major< MatrixB >::value) );
        BOOST_STATIC_ASSERT( (boost::is_same< typename remove_const<
                typename bindings::value_type< VectorDL >::type >::type,
                typename remove_const< typename bindings::value_type<
                VectorD >::type >::type >::value) );
        BOOST_STATIC_ASSERT( (boost::is_same< typename remove_const<
                typename bindings::value_type< VectorDL >::type >::type,
                typename remove_const< typename bindings::value_type<
                VectorDU >::type >::type >::value) );
        BOOST_STATIC_ASSERT( (boost::is_same< typename remove_const<
                typename bindings::value_type< VectorDL >::type >::type,
                typename remove_const< typename bindings::value_type<
                MatrixB >::type >::type >::value) );
        BOOST_STATIC_ASSERT( (bindings::is_mutable< VectorDL >::value) );
        BOOST_STATIC_ASSERT( (bindings::is_mutable< VectorD >::value) );
        BOOST_STATIC_ASSERT( (bindings::is_mutable< VectorDU >::value) );
        BOOST_STATIC_ASSERT( (bindings::is_mutable< MatrixB >::value) );
        BOOST_ASSERT( bindings::size(d) >= n );
        BOOST_ASSERT( bindings::size(dl) >= n-1 );
        BOOST_ASSERT( bindings::size(du) >= n-1 );
        BOOST_ASSERT( bindings::size_column(b) >= 0 );
        BOOST_ASSERT( bindings::size_minor(b) == 1 ||
                bindings::stride_minor(b) == 1 );
        BOOST_ASSERT( bindings::stride_major(b) >= std::max< std::ptrdiff_t >(1,
                n) );
        BOOST_ASSERT( n >= 0 );
        return detail::gtsv( n, bindings::size_column(b),
                bindings::begin_value(dl), bindings::begin_value(d),
                bindings::begin_value(du), bindings::begin_value(b),
                bindings::stride_major(b) );
    }

};

//
// Functions for direct use. These functions are overloaded for temporaries,
// so that wrapped types can still be passed and used for write-access. In
// addition, if applicable, they are overloaded for user-defined workspaces.
// Calls to these functions are passed to the gtsv_impl classes. In the
// documentation, most overloads are collapsed to avoid a large number of
// prototypes which are very similar.
//

//
// Overloaded function for gtsv. Its overload differs for
//
template< typename VectorDL, typename VectorD, typename VectorDU,
        typename MatrixB >
inline std::ptrdiff_t gtsv( const fortran_int_t n, VectorDL& dl,
        VectorD& d, VectorDU& du, MatrixB& b ) {
    return gtsv_impl< typename bindings::value_type<
            VectorDL >::type >::invoke( n, dl, d, du, b );
}

} // namespace lapack
} // namespace bindings
} // namespace numeric
} // namespace boost

#endif


/**
 * @file advectionfv2d_test.cc
 * @brief NPDE homework AdvectionFV2D code
 * @author Philipp Egg
 * @date 01.01.2020
 * @copyright Developed at ETH Zurich
 */

#include <Eigen/Core>

#include <gtest/gtest.h>

#include "../advectionfv2d.h"

namespace AdvectionFV2D::test {

TEST(AdvectionFV2D, dummyFunction) {
  double x = 0.0;
  int n = 0;

  // Eigen::Vector2d v = AdvectionFV2D::dummyFunction(x, n);
  Eigen::Vector2d v = {1.0, 1.0};

  Eigen::Vector2d v_ref = {1.0, 1.0};

  double tol = 1.0e-8;
  ASSERT_NEAR(0.0, (v - v_ref).lpNorm<Eigen::Infinity>(), tol);
}

}  // namespace AdvectionFV2D::test


//------------------------------------------------------------------------------
/// \file Pointers_tests.cpp
/// \ref
//------------------------------------------------------------------------------
#include <boost/test/unit_test.hpp>
#include <iostream>
#include <memory>
#include <optional>
#include <string>
#include <utility>

BOOST_AUTO_TEST_SUITE(Cpp) // The C++ Language
BOOST_AUTO_TEST_SUITE(Pointers_test)

std::optional<bool> is_Foo_constructed {std::nullopt};

struct Foo
{
  Foo()
  {
    std::cout << "Foo...\n";

    is_Foo_constructed = true;
  }

  ~Foo()
  {
    std::cout << "~Foo...\n";
    is_Foo_constructed = false;
  }
};

struct D
{
  void operator()(Foo* p)
  {
    std::cout << "Calling delete for Foo object...\n";
    delete p;
  }
};

std::optional<bool> is_Quantity_constructed {std::nullopt};

class Quantity
{
  public:
    Quantity() = delete;

    Quantity(const double x):
      x_{x}
    {
      is_Quantity_constructed = true;
    }

    ~Quantity()
    {
      is_Quantity_constructed = false;
    }

    double x() const
    {
      return x_;
    }

  private:
    double x_;
};

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOST_AUTO_TEST_CASE(DemonstratePointers)
{
  {
    // For type T, T* is type "pointer to T", i.e.
    // variable of type T* can hold address of an object of type T
    char c = 'a';
    char* p = &c;

    BOOST_TEST(c == 'a');
    std::cout << " c : " << c << " p : " << p << " c as unsigned int : " <<
      static_cast<unsigned int>(c) << " *p : " << *p << " &p : " << &p <<
        " &c : " << &c <<  '\n';
    BOOST_TEST(*p == 'a');
  }
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOST_AUTO_TEST_CASE(PointerSizes)
{
  {
    int x {10};
    int* xPtr = &x;
    char y {'a'};
    char* yPtr {&y};
    float z {3.f};
    float* zptr {&z};

    BOOST_TEST(sizeof(x) == 4); // 4 bytes, 32 bit
    BOOST_TEST(sizeof(xPtr) == 8); // 8 byte, 64 bit
    BOOST_TEST(sizeof(y) == 1); // 1 byte, 8 bit
    BOOST_TEST(sizeof(yPtr) == 8); // 8 byte, 64 bit
    BOOST_TEST(sizeof(z) == 4); // 4 byte, 32 bit
    BOOST_TEST(sizeof(zptr) == 8); // 8 byte, 64 bit
  }
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOST_AUTO_TEST_CASE(DemonstrateNullPtr)
{
  {
    void* x {nullptr};

    &x;

    BOOST_TEST(true);

    x;

    BOOST_TEST(true);

    // error: 'void*' is not a pointer-to-object type
    //*x;
  }
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOST_AUTO_TEST_CASE(DemonstrateUniquePointers)
{
  {
    // https://en.cppreference.com/w/cpp/memory/unique_ptr/reset

    // Creating new Foo...\n, D is a custom deleter
    std::cout << "Creating new Foo...\n";
    BOOST_TEST(!static_cast<bool>(is_Foo_constructed));

    std::unique_ptr<Foo, D> up {new Foo(), D()}; // up owns the Foo pointer
    // (deleter D)
    BOOST_TEST(static_cast<bool>(is_Foo_constructed));
    BOOST_TEST(is_Foo_constructed.value());

    // Replace owned Foo with a new Foo...\n
    std::cout << "Replace owned Foo with a new Foo...\n";
    up.reset(new Foo()); // calls deleter for the old one

    BOOST_TEST(static_cast<bool>(is_Foo_constructed));
    BOOST_TEST(!is_Foo_constructed.value());

    std::cout << "Release and delete the owned Foo...\n";

    up.reset(nullptr);

    BOOST_TEST(static_cast<bool>(is_Foo_constructed));
    BOOST_TEST(!is_Foo_constructed.value());
  }
  {
    std::unique_ptr<Quantity> u_ptr {std::make_unique<Quantity>(3)};

    BOOST_TEST(u_ptr->x() == 3.);

    Quantity q1 {5};

    // Releases the ownership of the managed object if any.
    u_ptr.release();

    // SIGABRT applicat abort requested
    //u_ptr.reset(&q1);

    // THIS WORKS
    u_ptr = std::make_unique<Quantity>(q1);

    BOOST_TEST(u_ptr->x() == 5.);

    Quantity q2 {8};

    is_Quantity_constructed = true;

    u_ptr = std::make_unique<Quantity>(q2);

    BOOST_TEST(u_ptr->x() == 8.);
    BOOST_TEST(q2.x() == 8.);

    // This refers to q1 going out of scope and being deleted.
    BOOST_TEST(is_Quantity_constructed.value() == false);
  }
  {
    Quantity q1 {42};
    std::unique_ptr<Quantity> u_ptr {nullptr};
    u_ptr = std::make_unique<Quantity>(q1);
    BOOST_TEST(u_ptr->x() == 42);
  }
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOST_AUTO_TEST_CASE(DemonstrateUniquePointersInClasses)
{
  // TODO
}

class IntString
{
  public:

    IntString(const int x, const std::string& s):
      x_{x},
      s_{s}
    {}

    int x() const
    {
      return x_;
    }

    const std::string& s() const
    {
      return s_;
    }

    void x(const int x)
    {
      x_ = x;
    }

    void s(const std::string& s)
    {
      s_ = s;
    }

  private:

    int x_;
    std::string s_;
};

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOST_AUTO_TEST_CASE(DemonstrateReleasingUniquePointers)
{
  {
    IntString int_string {42, "Peek"};
    const IntString const_int_string {43, "Linked List"};

    std::unique_ptr<IntString> u_ptr {std::make_unique<IntString>(int_string)};

    BOOST_TEST(u_ptr->x() == 42);
    BOOST_TEST(u_ptr->s() == "Peek");

    u_ptr.release();

    BOOST_TEST(int_string.x() == 42);
    BOOST_TEST(int_string.s() == "Peek");

    u_ptr = std::make_unique<IntString>(const_int_string);

    BOOST_TEST(u_ptr->x() == 43);
    BOOST_TEST(u_ptr->s() == "Linked List");

    BOOST_TEST(const_int_string.x() == 43);
    BOOST_TEST(const_int_string.s() == "Linked List");

    std::cout << " &u_ptr : " << &u_ptr << '\n';

    auto released_ptr = u_ptr.release();

    std::cout << " u_ptr release: " << &released_ptr << ' ' << released_ptr << '\n';

    u_ptr = std::make_unique<IntString>(int_string);

    BOOST_TEST(int_string.x() == 42);
    BOOST_TEST(int_string.s() == "Peek");

    int_string.x(69);
    int_string.s("Last-in First-Out");

    BOOST_TEST(int_string.x() == 69);
    BOOST_TEST(int_string.s() == "Last-in First-Out");

    BOOST_TEST(u_ptr->x() == 42);
    BOOST_TEST(u_ptr->s() == "Peek");

    std::cout << " &u_ptr : " << &u_ptr << '\n';

    auto released_ptr1 = u_ptr.release();

    std::cout << " u_ptr release1: " << &released_ptr1 << ' ' << released_ptr1 << '\n';

    u_ptr = std::make_unique<IntString>(std::move(int_string));

    BOOST_TEST(u_ptr->x() == 69);
    BOOST_TEST(u_ptr->s() == "Last-in First-Out");

    int_string.x(70);
    int_string.s("Queues");

    BOOST_TEST(int_string.x() == 70);
    BOOST_TEST(int_string.s() == "Queues");

    BOOST_TEST(u_ptr->x() == 69);
    BOOST_TEST(u_ptr->s() == "Last-in First-Out");

    u_ptr->x(70);
    u_ptr->s("Queues");

    BOOST_TEST(u_ptr->x() == 70);
    BOOST_TEST(u_ptr->s() == "Queues");

    std::cout << " &u_ptr : " << &u_ptr << '\n';

    auto released_ptr2 = u_ptr.release();

    std::cout << " u_ptr release2: " << &released_ptr2 << ' ' << released_ptr2 << '\n';

  }
}

BOOST_AUTO_TEST_SUITE_END() // Pointers_test
BOOST_AUTO_TEST_SUITE_END() // Cpp