text:
//  (C) Copyright John Maddock 2005.
//  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)

#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
#include <boost/test/tools/floating_point_comparison.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_floating_point.hpp>
#include <boost/mpl/if.hpp>
#include <boost/math/tools/assert.hpp>
#include <boost/math/complex.hpp>

#include <iostream>
#include <iomanip>
#include <cmath>
#include <typeinfo>

#ifdef BOOST_NO_STDC_NAMESPACE
namespace std{ using ::sqrt; using ::tan; using ::tanh; }
#endif

#ifndef VERBOSE
#undef BOOST_TEST_MESSAGE
#define BOOST_TEST_MESSAGE(x)
#endif

//
// check_complex:
// Verifies that expected value "a" and found value "b" have a relative error
// less than "max_error" epsilons.  Note that relative error is calculated for
// the complex number as a whole; this means that the error in the real or
// imaginary parts alone can be much higher than max_error when the real and
// imaginary parts are of very different magnitudes.  This is important, because
// the Hull et al analysis of the acos and asin algorithms requires that very small
// real/imaginary components can be safely ignored if they are negligible compared
// to the other component.
//
template <class T>
bool check_complex(const std::complex<T>& a, const std::complex<T>& b, int max_error)
{
   //
   // a is the expected value, b is what was actually found,
   // compute | (a-b)/b | and compare with max_error which is the
   // multiple of E to permit:
   //
   bool result = true;
   static const std::complex<T> zero(0);
   static const T eps = std::pow(static_cast<T>(std::numeric_limits<T>::radix), static_cast<T>(1 - std::numeric_limits<T>::digits));
   if(a == zero)
   {
      if(b != zero)
      {
         if(boost::math::fabs(b) > eps)
         {
            result = false;
            BOOST_ERROR("Expected {0,0} but got: " << b);
         }
         else
         {
            BOOST_TEST_MESSAGE("Expected {0,0} but got: " << b);
         }
      }
      return result;
   }
   else if(b == zero)
   {
      if(boost::math::fabs(a) > eps)
      {
         BOOST_ERROR("Found {0,0} but expected: " << a);
         return false;;
      }
      else
      {
         BOOST_TEST_MESSAGE("Found {0,0} but expected: " << a);
      }
   }

   if((boost::math::isnan)(a.real()))
   {
      BOOST_ERROR("Found non-finite value for real part: " << a);
   }
   if((boost::math::isnan)(a.imag()))
   {
      BOOST_ERROR("Found non-finite value for imaginary part: " << a);
   }

   T rel = boost::math::fabs((b-a)/b) / eps;
   if( rel > max_error)
   {
      result = false;
      BOOST_ERROR("Error in result exceeded permitted limit of " << max_error << " (actual relative error was " << rel << "e).  Found " << b << " expected " << a);
   }
   return result;
}

//
// test_inverse_trig:
// This is nothing more than a sanity check, computes trig(atrig(z))
// and compare the result to z.  Note that:
//
// atrig(trig(z)) != z
//
// for certain z because the inverse trig functions are multi-valued, this
// essentially rules this out as a testing method.  On the other hand:
//
// trig(atrig(z))
//
// can vary compare to z by an arbitrarily large amount.  For one thing we
// have no control over the implementation of the trig functions, for another
// even if both functions were accurate to 1ulp (as accurate as transcendental
// number can get, thanks to the "table makers dilemma"), the errors can still
// be arbitrarily large - often the inverse trig functions will map a very large
// part of the complex domain into a small output domain, so you can never get
// back exactly where you started from.  Consequently these tests are no more than
// sanity checks (just verifies that signs are correct and so on).
//
template <class T>
void test_inverse_trig(T)
{
   using namespace std;

   static const T interval = static_cast<T>(2.0L/128.0L);

   T x, y;

   std::cout << std::setprecision(std::numeric_limits<T>::digits10+2);

   for(x = -1; x <= 1; x += interval)
   {
      for(y = -1; y <= 1; y += interval)
      {
         // acos:
         std::complex<T> val(x, y), inter, result;
         inter = boost::math::acos(val);
         result = cos(inter);
         if(!check_complex(val, result, 50))
         {
            std::cout << "Error in testing inverse complex cos for type " << typeid(T).name() << std::endl;
            std::cout << "   val=             " << val << std::endl;
            std::cout << "   acos(val) =      " << inter << std::endl;
            std::cout << "   cos(acos(val)) = " << result << std::endl;
         }
         // asin:
         inter = boost::math::asin(val);
         result = sin(inter);
         if(!check_complex(val, result, 5))
         {
            std::cout << "Error in testing inverse complex sin for type " << typeid(T).name() << std::endl;
            std::cout << "   val=             " << val << std::endl;
            std::cout << "   asin(val) =      " << inter << std::endl;
            std::cout << "   sin(asin(val)) = " << result << std::endl;
         }
      }
   }

   static const T interval2 = static_cast<T>(3.0L/256.0L);
   for(x = -3; x <= 3; x += interval2)
   {
      for(y = -3; y <= 3; y += interval2)
      {
         // asinh:
         std::complex<T> val(x, y), inter, result;
         inter = boost::math::asinh(val);
         result = sinh(inter);
         if(!check_complex(val, result, 5))
         {
            std::cout << "Error in testing inverse complex sinh for type " << typeid(T).name() << std::endl;
            std::cout << "   val=               " << val << std::endl;
            std::cout << "   asinh(val) =       " << inter << std::endl;
            std::cout << "   sinh(asinh(val)) = " << result << std::endl;
         }
         // acosh:
         if(!((y == 0) && (x <= 1))) // can't test along the branch cut
         {
            inter = boost::math::acosh(val);
            result = cosh(inter);
            if(!check_complex(val, result, 60))
            {
               std::cout << "Error in testing inverse complex cosh for type " << typeid(T).name() << std::endl;
               std::cout << "   val=               " << val << std::endl;
               std::cout << "   acosh(val) =       " << inter << std::endl;
               std::cout << "   cosh(acosh(val)) = " << result << std::endl;
            }
         }
         //
         // There is a problem in testing atan and atanh:
         // The inverse functions map a large input range to a much
         // smaller output range, so at the extremes too rather different
         // inputs may map to the same output value once rounded to N places.
         // Consequently tan(atan(z)) can suffer from arbitrarily large errors
         // even if individually they each have a small error bound.  On the other
         // hand we can't test atan(tan(z)) either because atan is multi-valued, so
         // round-tripping in this direction isn't always possible.
         // The following heuristic is designed to make the best of a bad job,
         // using atan(tan(z)) where possible and tan(atan(z)) when it's not.
         //
         static const int tanh_error = 20;
         if((0 != x) && (0 != y) && ((std::fabs(y) < 1) || (std::fabs(x) < 1)))
         {
            // atanh:
            val = boost::math::atanh(val);
            inter = tanh(val);
            result = boost::math::atanh(inter);
            if(!check_complex(val, result, tanh_error))
            {
               std::cout << "Error in testing inverse complex tanh for type " << typeid(T).name() << std::endl;
               std::cout << "   val=               " << val << std::endl;
               std::cout << "   tanh(val) =        " << inter << std::endl;
               std::cout << "   atanh(tanh(val)) = " << result << std::endl;
            }
            // atan:
            if(!((x == 0) && (std::fabs(y) == 1))) // we can't test infinities here
            {
               val = std::complex<T>(x, y);
               val = boost::math::atan(val);
               inter = tan(val);
               result = boost::math::atan(inter);
               if(!check_complex(val, result, tanh_error))
               {
                  std::cout << "Error in testing inverse complex tan for type " << typeid(T).name() << std::endl;
                  std::cout << "   val=               " << val << std::endl;
                  std::cout << "   tan(val) =         " << inter << std::endl;
                  std::cout << "   atan(tan(val)) =   " << result << std::endl;
               }
            }
         }
         else
         {
            // atanh:
            inter = boost::math::atanh(val);
            result = tanh(inter);
            if(!check_complex(val, result, tanh_error))
            {
               std::cout << "Error in testing inverse complex atanh for type " << typeid(T).name() << std::endl;
               std::cout << "   val=                 " << val << std::endl;
               std::cout << "   atanh(val) =         " << inter << std::endl;
               std::cout << "   tanh(atanh(val)) =   " << result << std::endl;
            }
            // atan:
            if(!((x == 0) && (std::fabs(y) == 1))) // we can't test infinities here
            {
               inter = boost::math::atan(val);
               result = tan(inter);
               if(!check_complex(val, result, tanh_error))
               {
                  std::cout << "Error in testing inverse complex atan for type " << typeid(T).name() << std::endl;
                  std::cout << "   val=                 " << val << std::endl;
                  std::cout << "   atan(val) =          " << inter << std::endl;
                  std::cout << "   tan(atan(val)) =     " << result << std::endl;
               }
            }
         }
      }
   }
}

//
// check_spots:
// Various spot values, mostly the C99 special cases (infinities and NAN's).
// TODO: add spot checks for the Wolfram spot values.
//
template <class T>
void check_spots(const T&)
{
   typedef std::complex<T> ct;
   ct result;
   static const T two = 2.0;
   T eps = std::pow(two, T(1-std::numeric_limits<T>::digits)); // numeric_limits<>::epsilon way too small to be useful on Darwin.
   static const T zero = 0;
   static const T mzero = -zero;
   static const T one = 1;
   static const T pi = boost::math::constants::pi<T>();
   static const T half_pi = boost::math::constants::half_pi<T>();
   static const T quarter_pi = half_pi / 2;
   static const T three_quarter_pi = boost::math::constants::three_quarters_pi<T>();
   T infinity = std::numeric_limits<T>::infinity();
   bool test_infinity = std::numeric_limits<T>::has_infinity;
   T nan = 0;
   bool test_nan = false;
#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564))
   // numeric_limits reports that a quiet NaN is present
   // but an attempt to access it will terminate the program!!!!
   if(std::numeric_limits<T>::has_quiet_NaN)
      nan = std::numeric_limits<T>::quiet_NaN();
   if((boost::math::isnan)(nan))
      test_nan = true;
#endif
#if defined(__DECCXX) && !defined(_IEEE_FP)
   // Tru64 cxx traps infinities unless the -ieee option is used:
   test_infinity = false;
#endif

   //
   // C99 spot tests for acos:
   //
   result = boost::math::acos(ct(zero));
   check_complex(ct(half_pi), result, 2);

   result = boost::math::acos(ct(mzero));
   check_complex(ct(half_pi), result, 2);

   result = boost::math::acos(ct(zero, mzero));
   check_complex(ct(half_pi), result, 2);

   result = boost::math::acos(ct(mzero, mzero));
   check_complex(ct(half_pi), result, 2);

   if(test_nan)
   {
      result = boost::math::acos(ct(zero,nan));
      BOOST_CHECK_CLOSE(result.real(), half_pi, eps*200);
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::acos(ct(mzero,nan));
      BOOST_CHECK_CLOSE(result.real(), half_pi, eps*200);
      BOOST_CHECK((boost::math::isnan)(result.imag()));
   }
   if(test_infinity)
   {
      result = boost::math::acos(ct(zero, infinity));
      BOOST_CHECK_CLOSE(result.real(), half_pi, eps*200);
      BOOST_CHECK(result.imag() == -infinity);

      result = boost::math::acos(ct(zero, -infinity));
      BOOST_CHECK_CLOSE(result.real(), half_pi, eps*200);
      BOOST_CHECK(result.imag() == infinity);
   }

   if(test_nan)
   {
      result = boost::math::acos(ct(one, nan));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));
   }
   if(test_infinity)
   {
      result = boost::math::acos(ct(-infinity, one));
      BOOST_CHECK_CLOSE(result.real(), pi, eps*200);
      BOOST_CHECK(result.imag() == -infinity);

      result = boost::math::acos(ct(infinity, one));
      BOOST_CHECK(result.real() == 0);
      BOOST_CHECK(result.imag() == -infinity);

      result = boost::math::acos(ct(-infinity, -one));
      BOOST_CHECK_CLOSE(result.real(), pi, eps*200);
      BOOST_CHECK(result.imag() == infinity);

      result = boost::math::acos(ct(infinity, -one));
      BOOST_CHECK(result.real() == 0);
      BOOST_CHECK(result.imag() == infinity);

      result = boost::math::acos(ct(-infinity, infinity));
      BOOST_CHECK_CLOSE(result.real(), three_quarter_pi, eps*200);
      BOOST_CHECK(result.imag() == -infinity);

      result = boost::math::acos(ct(infinity, infinity));
      BOOST_CHECK_CLOSE(result.real(), quarter_pi, eps*200);
      BOOST_CHECK(result.imag() == -infinity);

      result = boost::math::acos(ct(-infinity, -infinity));
      BOOST_CHECK_CLOSE(result.real(), three_quarter_pi, eps*200);
      BOOST_CHECK(result.imag() == infinity);

      result = boost::math::acos(ct(infinity, -infinity));
      BOOST_CHECK_CLOSE(result.real(), quarter_pi, eps*200);
      BOOST_CHECK(result.imag() == infinity);
   }
   if(test_nan)
   {
      result = boost::math::acos(ct(infinity, nan));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK(std::fabs(result.imag()) == infinity);

      result = boost::math::acos(ct(-infinity, nan));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK(std::fabs(result.imag()) == infinity);

      result = boost::math::acos(ct(nan, zero));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::acos(ct(nan, -zero));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::acos(ct(nan, one));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::acos(ct(nan, -one));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::acos(ct(nan, nan));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::acos(ct(nan, infinity));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK(result.imag() == -infinity);

      result = boost::math::acos(ct(nan, -infinity));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK(result.imag() == infinity);
   }
   if(boost::math::signbit(mzero))
   {
      result = boost::math::acos(ct(-1.25f, zero));
      BOOST_CHECK(result.real() > 0);
      BOOST_CHECK(result.imag() < 0);
      result = boost::math::asin(ct(-1.75f, mzero));
      BOOST_CHECK(result.real() < 0);
      BOOST_CHECK(result.imag() < 0);
      result = boost::math::atan(ct(mzero, -1.75f));
      BOOST_CHECK(result.real() < 0);
      BOOST_CHECK(result.imag() < 0);

      result = boost::math::acos(ct(zero, zero));
      BOOST_CHECK(result.real() > 0);
      BOOST_CHECK(result.imag() == 0);
      BOOST_CHECK((boost::math::signbit)(result.imag()));
      result = boost::math::acos(ct(zero, mzero));
      BOOST_CHECK(result.real() > 0);
      BOOST_CHECK(result.imag() == 0);
      BOOST_CHECK(0 == (boost::math::signbit)(result.imag()));
      result = boost::math::acos(ct(mzero, zero));
      BOOST_CHECK(result.real() > 0);
      BOOST_CHECK(result.imag() == 0);
      BOOST_CHECK((boost::math::signbit)(result.imag()));
      result = boost::math::acos(ct(mzero, mzero));
      BOOST_CHECK(result.real() > 0);
      BOOST_CHECK(result.imag() == 0);
      BOOST_CHECK(0 == (boost::math::signbit)(result.imag()));
   }

   //
   // C99 spot tests for acosh:
   //
   result = boost::math::acosh(ct(zero, zero));
   BOOST_CHECK(result.real() == 0);
   BOOST_CHECK_CLOSE(result.imag(), half_pi, eps*200);

   result = boost::math::acosh(ct(zero, mzero));
   BOOST_CHECK(result.real() == 0);
   BOOST_CHECK_CLOSE(result.imag(), -half_pi, eps*200);

   result = boost::math::acosh(ct(mzero, zero));
   BOOST_CHECK(result.real() == 0);
   BOOST_CHECK_CLOSE(result.imag(), half_pi, eps*200);

   result = boost::math::acosh(ct(mzero, mzero));
   BOOST_CHECK(result.real() == 0);
   BOOST_CHECK_CLOSE(result.imag(), -half_pi, eps*200);

   if(test_infinity)
   {
      result = boost::math::acosh(ct(one, infinity));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK_CLOSE(result.imag(), half_pi, eps*200);

      result = boost::math::acosh(ct(one, -infinity));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK_CLOSE(result.imag(), -half_pi, eps*200);
   }

   if(test_nan)
   {
      result = boost::math::acosh(ct(one, nan));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));
   }
   if(test_infinity)
   {
      result = boost::math::acosh(ct(-infinity, one));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK_CLOSE(result.imag(), pi, eps*200);

      result = boost::math::acosh(ct(infinity, one));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK(result.imag() == 0);

      result = boost::math::acosh(ct(-infinity, -one));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK_CLOSE(result.imag(), -pi, eps*200);

      result = boost::math::acosh(ct(infinity, -one));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK(result.imag() == 0);

      result = boost::math::acosh(ct(-infinity, infinity));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK_CLOSE(result.imag(), three_quarter_pi, eps*200);

      result = boost::math::acosh(ct(infinity, infinity));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK_CLOSE(result.imag(), quarter_pi, eps*200);

      result = boost::math::acosh(ct(-infinity, -infinity));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK_CLOSE(result.imag(), -three_quarter_pi, eps*200);

      result = boost::math::acosh(ct(infinity, -infinity));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK_CLOSE(result.imag(), -quarter_pi, eps*200);
   }

   if(test_nan)
   {
      result = boost::math::acosh(ct(infinity, nan));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::acosh(ct(-infinity, nan));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::acosh(ct(nan, one));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::acosh(ct(nan, infinity));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::acosh(ct(nan, -one));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::acosh(ct(nan, -infinity));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::acosh(ct(nan, nan));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));
   }
   if(boost::math::signbit(mzero))
   {
      result = boost::math::acosh(ct(-2.5f, zero));
      BOOST_CHECK(result.real() > 0);
      BOOST_CHECK(result.imag() > 0);
   }
   //
   // C99 spot checks for asinh:
   //
   result = boost::math::asinh(ct(zero, zero));
   BOOST_CHECK(result.real() == 0);
   BOOST_CHECK(result.imag() == 0);

   result = boost::math::asinh(ct(mzero, zero));
   BOOST_CHECK(result.real() == 0);
   BOOST_CHECK(result.imag() == 0);

   result = boost::math::asinh(ct(zero, mzero));
   BOOST_CHECK(result.real() == 0);
   BOOST_CHECK(result.imag() == 0);

   result = boost::math::asinh(ct(mzero, mzero));
   BOOST_CHECK(result.real() == 0);
   BOOST_CHECK(result.imag() == 0);

   if(test_infinity)
   {
      result = boost::math::asinh(ct(one, infinity));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK_CLOSE(result.imag(), half_pi, eps*200);

      result = boost::math::asinh(ct(one, -infinity));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK_CLOSE(result.imag(), -half_pi, eps*200);

      result = boost::math::asinh(ct(-one, -infinity));
      BOOST_CHECK(result.real() == -infinity);
      BOOST_CHECK_CLOSE(result.imag(), -half_pi, eps*200);

      result = boost::math::asinh(ct(-one, infinity));
      BOOST_CHECK(result.real() == -infinity);
      BOOST_CHECK_CLOSE(result.imag(), half_pi, eps*200);
   }

   if(test_nan)
   {
      result = boost::math::asinh(ct(one, nan));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::asinh(ct(-one, nan));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::asinh(ct(zero, nan));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));
   }

   if(test_infinity)
   {
      result = boost::math::asinh(ct(infinity, one));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK(result.imag() == 0);

      result = boost::math::asinh(ct(infinity, -one));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK(result.imag() == 0);

      result = boost::math::asinh(ct(-infinity, -one));
      BOOST_CHECK(result.real() == -infinity);
      BOOST_CHECK(result.imag() == 0);

      result = boost::math::asinh(ct(-infinity, one));
      BOOST_CHECK(result.real() == -infinity);
      BOOST_CHECK(result.imag() == 0);

      result = boost::math::asinh(ct(infinity, infinity));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK_CLOSE(result.imag(), quarter_pi, eps*200);

      result = boost::math::asinh(ct(infinity, -infinity));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK_CLOSE(result.imag(), -quarter_pi, eps*200);

      result = boost::math::asinh(ct(-infinity, -infinity));
      BOOST_CHECK(result.real() == -infinity);
      BOOST_CHECK_CLOSE(result.imag(), -quarter_pi, eps*200);

      result = boost::math::asinh(ct(-infinity, infinity));
      BOOST_CHECK(result.real() == -infinity);
      BOOST_CHECK_CLOSE(result.imag(), quarter_pi, eps*200);
   }

   if(test_nan)
   {
      result = boost::math::asinh(ct(infinity, nan));
      BOOST_CHECK(result.real() == infinity);
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::asinh(ct(-infinity, nan));
      BOOST_CHECK(result.real() == -infinity);
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::asinh(ct(nan, zero));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK(result.imag() == 0);

      result = boost::math::asinh(ct(nan,  mzero));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK(result.imag() == 0);

      result = boost::math::asinh(ct(nan, one));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::asinh(ct(nan,  -one));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::asinh(ct(nan,  nan));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::asinh(ct(nan, infinity));
      BOOST_CHECK(std::fabs(result.real()) == infinity);
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::asinh(ct(nan,  -infinity));
      BOOST_CHECK(std::fabs(result.real()) == infinity);
      BOOST_CHECK((boost::math::isnan)(result.imag()));
   }
   if(boost::math::signbit(mzero))
   {
      result = boost::math::asinh(ct(zero, 1.5f));
      BOOST_CHECK(result.real() > 0);
      BOOST_CHECK(result.imag() > 0);
   }

   //
   // C99 special cases for atanh:
   //
   result = boost::math::atanh(ct(zero, zero));
   BOOST_CHECK(result.real() == zero);
   BOOST_CHECK(result.imag() == zero);

   result = boost::math::atanh(ct(mzero, zero));
   BOOST_CHECK(result.real() == zero);
   BOOST_CHECK(result.imag() == zero);

   result = boost::math::atanh(ct(zero, mzero));
   BOOST_CHECK(result.real() == zero);
   BOOST_CHECK(result.imag() == zero);

   result = boost::math::atanh(ct(mzero, mzero));
   BOOST_CHECK(result.real() == zero);
   BOOST_CHECK(result.imag() == zero);

   if(test_nan)
   {
      result = boost::math::atanh(ct(zero, nan));
      BOOST_CHECK(result.real() == zero);
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::atanh(ct(-zero, nan));
      BOOST_CHECK(result.real() == zero);
      BOOST_CHECK((boost::math::isnan)(result.imag()));
   }

   if(test_infinity)
   {
      result = boost::math::atanh(ct(one, zero));
      BOOST_CHECK_EQUAL(result.real(), infinity);
      BOOST_CHECK_EQUAL(result.imag(), zero);

      result = boost::math::atanh(ct(-one, zero));
      BOOST_CHECK_EQUAL(result.real(), -infinity);
      BOOST_CHECK_EQUAL(result.imag(), zero);

      result = boost::math::atanh(ct(-one, -zero));
      BOOST_CHECK_EQUAL(result.real(), -infinity);
      BOOST_CHECK_EQUAL(result.imag(), zero);

      result = boost::math::atanh(ct(one, -zero));
      BOOST_CHECK_EQUAL(result.real(), infinity);
      BOOST_CHECK_EQUAL(result.imag(), zero);

      result = boost::math::atanh(ct(pi, infinity));
      BOOST_CHECK_EQUAL(result.real(), zero);
      BOOST_CHECK_CLOSE(result.imag(), half_pi, eps*200);

      result = boost::math::atanh(ct(pi, -infinity));
      BOOST_CHECK_EQUAL(result.real(), zero);
      BOOST_CHECK_CLOSE(result.imag(), -half_pi, eps*200);

      result = boost::math::atanh(ct(-pi, -infinity));
      BOOST_CHECK_EQUAL(result.real(), zero);
      BOOST_CHECK_CLOSE(result.imag(), -half_pi, eps*200);

      result = boost::math::atanh(ct(-pi, infinity));
      BOOST_CHECK_EQUAL(result.real(), zero);
      BOOST_CHECK_CLOSE(result.imag(), half_pi, eps*200);
   }
   if(test_nan)
   {
      result = boost::math::atanh(ct(pi, nan));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::atanh(ct(-pi, nan));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));
   }

   if(test_infinity)
   {
      result = boost::math::atanh(ct(infinity, pi));
      BOOST_CHECK(result.real() == zero);
      BOOST_CHECK_CLOSE(result.imag(), half_pi, eps*200);

      result = boost::math::atanh(ct(infinity, -pi));
      BOOST_CHECK_EQUAL(result.real(), zero);
      BOOST_CHECK_CLOSE(result.imag(), -half_pi, eps*200);

      result = boost::math::atanh(ct(-infinity, -pi));
      BOOST_CHECK_EQUAL(result.real(), zero);
      BOOST_CHECK_CLOSE(result.imag(), -half_pi, eps*200);

      result = boost::math::atanh(ct(-infinity, pi));
      BOOST_CHECK_EQUAL(result.real(), zero);
      BOOST_CHECK_CLOSE(result.imag(), half_pi, eps*200);

      result = boost::math::atanh(ct(infinity, infinity));
      BOOST_CHECK_EQUAL(result.real(), zero);
      BOOST_CHECK_CLOSE(result.imag(), half_pi, eps*200);

      result = boost::math::atanh(ct(infinity, -infinity));
      BOOST_CHECK_EQUAL(result.real(), zero);
      BOOST_CHECK_CLOSE(result.imag(), -half_pi, eps*200);

      result = boost::math::atanh(ct(-infinity, -infinity));
      BOOST_CHECK_EQUAL(result.real(), zero);
      BOOST_CHECK_CLOSE(result.imag(), -half_pi, eps*200);

      result = boost::math::atanh(ct(-infinity, infinity));
      BOOST_CHECK_EQUAL(result.real(), zero);
      BOOST_CHECK_CLOSE(result.imag(), half_pi, eps*200);
   }

   if(test_nan)
   {
      result = boost::math::atanh(ct(infinity, nan));
      BOOST_CHECK(result.real() == 0);
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::atanh(ct(-infinity, nan));
      BOOST_CHECK(result.real() == 0);
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::atanh(ct(nan, pi));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::atanh(ct(nan, -pi));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));

      result = boost::math::atanh(ct(nan, infinity));
      BOOST_CHECK(result.real() == 0);
      BOOST_CHECK_CLOSE(result.imag(), half_pi, eps*200);

      result = boost::math::atanh(ct(nan, -infinity));
      BOOST_CHECK(result.real() == 0);
      BOOST_CHECK_CLOSE(result.imag(), -half_pi, eps*200);

      result = boost::math::atanh(ct(nan, nan));
      BOOST_CHECK((boost::math::isnan)(result.real()));
      BOOST_CHECK((boost::math::isnan)(result.imag()));

   }
   if(boost::math::signbit(mzero))
   {
      result = boost::math::atanh(ct(-2.0f, mzero));
      BOOST_CHECK(result.real() < 0);
      BOOST_CHECK(result.imag() < 0);
   }
}

//
// test_boundaries:
// This is an accuracy test, sets the real and imaginary components
// of the input argument to various "boundary conditions" that exist
// inside the implementation.  Then computes the result at double precision
// and again at float precision.  The double precision result will be
// computed using the "regular" code, where as the float precision versions
// will calculate the result using the "exceptional value" handlers, so
// we end up comparing the values calculated by two different methods.
//
const float boundaries[] = {
   0,
   1,
   2,
   (std::numeric_limits<float>::max)(),
   (std::numeric_limits<float>::min)(),
   std::numeric_limits<float>::epsilon(),
   std::sqrt((std::numeric_limits<float>::max)()) / 8,
   static_cast<float>(4) * std::sqrt((std::numeric_limits<float>::min)()),
   0.6417F,
   1.5F,
   std::sqrt((std::numeric_limits<float>::max)()) / 2,
   std::sqrt((std::numeric_limits<float>::min)()),
   1.0F / 0.3F,
};

void do_test_boundaries(float x, float y)
{
   std::complex<float> r1 = boost::math::asin(std::complex<float>(x, y));
   std::complex<double> dr = boost::math::asin(std::complex<double>(x, y));
   std::complex<float> r2(static_cast<float>(dr.real()), static_cast<float>(dr.imag()));
   check_complex(r2, r1, 5);
   r1 = boost::math::acos(std::complex<float>(x, y));
   dr = boost::math::acos(std::complex<double>(x, y));
   r2 = std::complex<float>(std::complex<double>(dr.real(), dr.imag()));
   check_complex(r2, r1, 5);
   r1 = boost::math::atanh(std::complex<float>(x, y));
   dr = boost::math::atanh(std::complex<double>(x, y));
   r2 = std::complex<float>(std::complex<double>(dr.real(), dr.imag()));
   check_complex(r2, r1, 5);
}

void test_boundaries(float x, float y)
{
   do_test_boundaries(x, y);
   do_test_boundaries(-x, y);
   do_test_boundaries(-x, -y);
   do_test_boundaries(x, -y);
}

void test_boundaries(float x)
{
   for(unsigned i = 0; i < sizeof(boundaries)/sizeof(float); ++i)
   {
      test_boundaries(x, boundaries[i]);
      test_boundaries(x, boundaries[i] + std::numeric_limits<float>::epsilon()*boundaries[i]);
      test_boundaries(x, boundaries[i] - std::numeric_limits<float>::epsilon()*boundaries[i]);
   }
}

void test_boundaries()
{
   for(unsigned i = 0; i < sizeof(boundaries)/sizeof(float); ++i)
   {
      test_boundaries(boundaries[i]);
      test_boundaries(boundaries[i] + std::numeric_limits<float>::epsilon()*boundaries[i]);
      test_boundaries(boundaries[i] - std::numeric_limits<float>::epsilon()*boundaries[i]);//here
   }
}

BOOST_AUTO_TEST_CASE( test_main )
{
   std::cout << "Running complex trig sanity checks for type float." << std::endl;
   test_inverse_trig(float(0));
   std::cout << "Running complex trig sanity checks for type double." << std::endl;
   test_inverse_trig(double(0));
   //test_inverse_trig((long double)(0));

   std::cout << "Running complex trig spot checks for type float." << std::endl;
   check_spots(float(0));
   std::cout << "Running complex trig spot checks for type double." << std::endl;
   check_spots(double(0));
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
   std::cout << "Running complex trig spot checks for type long double." << std::endl;
   check_spots((long double)(0));
#endif

   std::cout << "Running complex trig boundary and accuracy tests." << std::endl;
   test_boundaries();
}

max_stars_repo_name: oleg-alexandrov/math

max_issues_repo_name: oleg-alexandrov/math

max_forks_repo_name: oleg-alexandrov/math


text:
#include <boost/test/unit_test.hpp>
#include <boost/test/test_tools.hpp>

#include "darner/queue/queue.h"
#include "darner/queue/iqstream.h"
#include "darner/queue/oqstream.h"
#include "fixtures/basic_queue.hpp"

using namespace std;
using namespace boost;
using namespace boost::asio;
using namespace darner;

BOOST_AUTO_TEST_SUITE( queue_tests )

// test that we can push and pop
BOOST_FIXTURE_TEST_CASE( test_push_pop, fixtures::basic_queue )
{
   string value = "I hate when I'm on a flight and I wake up with a water bottle next to me like oh great now I gotta "
                  "be responsible for this water bottle";
   oqs_.open(queue_, 1);
   oqs_.write(value);

   BOOST_REQUIRE(iqs_.open(queue_));

   iqs_.read(pop_value_);
   BOOST_REQUIRE_EQUAL(value, pop_value_);
}

// test having nothing to pop
BOOST_FIXTURE_TEST_CASE( test_pop_empty, fixtures::basic_queue )
{
   BOOST_REQUIRE(!iqs_.open(queue_));
}

// test a pop wait
BOOST_FIXTURE_TEST_CASE( test_pop_wait, fixtures::basic_queue )
{
   string value = "sometimes I push the door close button on people running towards the elevator. I just need my own "
                  "elevator sometimes, my 7 floor sanctuary";
   posix_time::ptime beg = boost::posix_time::microsec_clock::local_time();
   deadline_timer timer(ios_, posix_time::milliseconds(10));
   timer.async_wait(bind(&fixtures::basic_queue::delayed_push, this, boost::ref(value), _1));
   queue_->wait(100, wait_cb_);
   ios_.run();
   boost::posix_time::ptime end = boost::posix_time::microsec_clock::local_time();

   BOOST_REQUIRE(!error_);
   BOOST_REQUIRE_LT((end - beg).total_milliseconds(), 50); // should come back sooner than the timeout
}

// test multiple waiters
BOOST_FIXTURE_TEST_CASE( test_multiple_pop_wait, fixtures::basic_queue )
{
   string value1 = "I’m just tryna keep it symmetrical";
   string value2 = "Hotel robe got me feeling like a Sheik";
   posix_time::ptime beg = boost::posix_time::microsec_clock::local_time();
   deadline_timer timer1(ios_, posix_time::milliseconds(10));
   timer1.async_wait(bind(&fixtures::basic_queue::delayed_push, this, boost::ref(value1), _1));
   deadline_timer timer2(ios_, posix_time::milliseconds(20));
   timer2.async_wait(bind(&fixtures::basic_queue::delayed_push, this, boost::ref(value2), _1));
   queue_->wait(100, wait_cb_);
   queue_->wait(100, wait_cb_);
   ios_.run();
   boost::posix_time::ptime end = boost::posix_time::microsec_clock::local_time();

   BOOST_REQUIRE(!error_);
   BOOST_REQUIRE_EQUAL(cb_count_, 2);
   BOOST_REQUIRE_LT((end - beg).total_milliseconds(), 50); // should come back sooner than the timeout
}

// test the race condition where a wait callback does work that crosses it over the wait timeout
BOOST_FIXTURE_TEST_CASE( test_pop_wait_race, fixtures::basic_queue )
{
   string value = "Fur pillows are hard to actually sleep on";
   deadline_timer timer(ios_, posix_time::milliseconds(80));
   timer.async_wait(bind(&fixtures::basic_queue::delayed_push_block, this, boost::ref(value), _1));
   queue_->wait(100, wait_cb_);
   ios_.run();

   BOOST_REQUIRE(!error_);
}

// now the opposite, test a pop wait timeout
BOOST_FIXTURE_TEST_CASE( test_pop_wait_timeout, fixtures::basic_queue )
{
   string value = "Classical music is tight yo";
   deadline_timer timer(ios_, posix_time::milliseconds(50));
   timer.async_wait(bind(&fixtures::basic_queue::delayed_push, this, boost::ref(value), _1));
   queue_->wait(10, wait_cb_);
   ios_.run();

   BOOST_REQUIRE(error_);
}

// test that we can close and reopen a queue
BOOST_FIXTURE_TEST_CASE( test_queue_close_reopen, fixtures::basic_queue )
{
   string value = "Do you know where to find marble conference tables? I’m looking to have a conference…not until I "
                  "get the table though";

   oqs_.open(queue_, 1);
   oqs_.write(value);
   queue_.reset(new darner::queue(ios_, (tmp_ / "queue").string()));
   BOOST_REQUIRE_EQUAL(queue_->count(), 1);

   iqs_.open(queue_);
   iqs_.read(pop_value_);
   BOOST_REQUIRE_EQUAL(pop_value_, value);
}

// test we report count correctly
BOOST_FIXTURE_TEST_CASE( test_queue_count, fixtures::basic_queue )
{
   string value = "NO ALCOHOL BEFORE TATTOOS";

   oqs_.open(queue_, 1);
   oqs_.write(value);
   BOOST_REQUIRE_EQUAL(queue_->count(), 1);

   // even beginning a pop lowers the count...
   iqs_.open(queue_);
   BOOST_REQUIRE_EQUAL(queue_->count(), 0);

   // but returning it raises it back up
   iqs_.close(false);
   BOOST_REQUIRE_EQUAL(queue_->count(), 1);
}

// test overruning an oqstream raises
BOOST_FIXTURE_TEST_CASE( test_oqstream_overflow, fixtures::basic_queue )
{
   string value = "I would like to thank Julius Caesar for originating my hairstyle";

   oqs_.open(queue_, 1);
   oqs_.write(value);
   BOOST_REQUIRE_THROW(oqs_.write(value), system::system_error);
}

// test that we can push/pop multi-chunked
BOOST_FIXTURE_TEST_CASE( test_multi_chunked, fixtures::basic_queue )
{
   string value1 = "I don’t ever watch dramas on a plane... I don’t be wanting to reflect";
   string value2 = "I make awesome decisions in bike stores!!!";
   oqs_.open(queue_, 2);
   oqs_.write(value1);

   BOOST_REQUIRE_EQUAL(queue_->count(), 0); // not ready yet...
   BOOST_REQUIRE_EQUAL(oqs_.tell(), value1.size());

   oqs_.write(value2);
   BOOST_REQUIRE_EQUAL(queue_->count(), 1); // okay it's done
   BOOST_REQUIRE_EQUAL(oqs_.tell(), value1.size() + value2.size());

   iqs_.open(queue_);
   iqs_.read(pop_value_);
   BOOST_REQUIRE_EQUAL(queue_->count(), 0); // even beginning a pop lowers the count...
   BOOST_REQUIRE_EQUAL(iqs_.tell(), value1.size());
   BOOST_REQUIRE_EQUAL(iqs_.size(), value1.size() + value2.size());
   BOOST_REQUIRE_EQUAL(pop_value_, value1);

   iqs_.read(pop_value_);
   BOOST_REQUIRE_EQUAL(iqs_.tell(), value1.size() + value2.size());
   BOOST_REQUIRE_EQUAL(pop_value_, value2);

   // finally, the delete
   iqs_.close(true);

   // should be nothing left to pop
   BOOST_REQUIRE(!iqs_.open(queue_));
}

// test that we can cancel a multi-chunked push
BOOST_FIXTURE_TEST_CASE( test_push_cancel, fixtures::basic_queue )
{
   string value = "I ordered the salmon medium instead of medium well I didn’t want to ruin the magic";
   oqs_.open(queue_, 2);
   oqs_.write(value);

   BOOST_REQUIRE_EQUAL(oqs_.tell(), value.size());

   oqs_.cancel();

   // shouldn't be able to finish the push now
   BOOST_REQUIRE_THROW(oqs_.write(value), system::system_error);
}

// test that we can push a value that ends in a null-zero
BOOST_FIXTURE_TEST_CASE( test_push_zero, fixtures::basic_queue )
{
   string value = string("I'm sorry Taylor.") + '\0';
   oqs_.open(queue_, 1);
   oqs_.write(value);
   iqs_.open(queue_);
   iqs_.read(pop_value_);

   BOOST_REQUIRE_EQUAL(value, pop_value_);
}

// test that we can delete a queue when we are done with it
BOOST_FIXTURE_TEST_CASE( test_delete_queue, fixtures::basic_queue )
{
   queue_->destroy();
   BOOST_REQUIRE(!filesystem::exists(tmp_ / "queue"));
   BOOST_REQUIRE(filesystem::exists(tmp_ / "queue.0")); // first delete gets .0
   darner::queue queue2(ios_, (tmp_ / "queue").string());
   queue2.destroy();
   BOOST_REQUIRE(filesystem::exists(tmp_ / "queue.1")); // second delete gets .1
   queue_.reset();
   BOOST_REQUIRE(!filesystem::exists(tmp_ / "queue.0")); // finally, destroying the queue deletes the journal
}

BOOST_AUTO_TEST_SUITE_END()

ext: cpp

max_stars_repo_name: alanw/darner

max_issues_repo_name: alanw/darner

max_forks_repo_name: alanw/darner


text:
#pragma once
#ifndef URLCMDAPP_URLCMD_HPP
#   define URLCMDAPP_URLCMD_HPP

#include <vector>
#include <string>
#include <boost/program_options.hpp>

namespace po = boost::program_options;

namespace UrlCmd::UrlCmd {
    int printHelp(po::options_description &visible, int options = 0);
    int printGeneral(int options = 0);

    struct AppArgs {
        int mStatus;

        int mVerbosity;
        int mHelp;
        int mVersion;
        int mPreview;
        int mDosForm;
        int mSkip;
        std::vector<std::string> mInput;

        AppArgs(void);
        AppArgs(int argc, char **argv);
        AppArgs &reset(void);
        AppArgs &debug(int flags = 0);
    };

    AppArgs argsWithStatus(int status = 0);
    AppArgs processArgs(int argc, char **argv);
};

#endif

ext: hpp

max_stars_repo_name: GrayChrysTea/Urlcmd

max_issues_repo_name: GrayChrysTea/Urlcmd

max_forks_repo_name: GrayChrysTea/Urlcmd


text:
/*
 * Copyright (c) 2017 vargaconsulting, Toronto,ON Canada
 * Author: Varga, Steven <steven@vargaconsulting.ca>
 */
#define GOOGLE_STRIP_LOG 1

#include <gtest/gtest.h>
#include <armadillo>
#include <h5cpp/all>

#include "event_listener.hpp"
#include "abstract.h"

using namespace h5::utils;
template <typename T> class ArmadilloTest : public AbstractTest<T>{};
//typedef ::testing::Types<H5CPP_TEST_PRIMITIVE_TYPES> PrimitiveTypes;
typedef ::testing::Types<short> PrimitiveTypes;
TYPED_TEST_CASE(ArmadilloTest, PrimitiveTypes);
/*
TYPED_TEST(ArmadilloTest, ArmadilloWrite) {

	arma::Col<TypeParam>  C(10); 	 C.ones();
	arma::Row<TypeParam>  R(10);
	arma::Mat<TypeParam>  M(3,5);    M.ones();
	arma::Cube<TypeParam> Q(3,4,5);  Q.ones();
	// PLAIN
	h5::write(this->fd,this->name+".col", C);
	h5::write(this->fd,this->name+".row", R);

	h5::write(this->fd,this->name+".col unlim", C, h5::max_dims{H5S_UNLIMITED});
	h5::write(this->fd,this->name+".col unlim, gzip | chunk", C, h5::max_dims{H5S_UNLIMITED}, h5::gzip{9} | h5::chunk{10});

	h5::write(this->fd,this->name+".mat", Q, h5::count{3,5,1}, h5::stride{2,2,1}, h5::offset{2,0,0} );
	h5::write(this->fd,this->name+".custom ", C, h5::count{1,10}, h5::current_dims{4,12}, h5::offset{2,2}, h5::max_dims{12,H5S_UNLIMITED} );
}

TYPED_TEST(ArmadilloTest, ReadArmadillo) {

	arma::Col<TypeParam>  C(3);        C.ones();
	arma::Row<TypeParam>  R(3);        R.ones();
	arma::Mat<TypeParam>  M(20,20);    for(int i=0; i < M.size(); i++ ) M[i] = i;
	arma::Cube<TypeParam> Q(3,5,7);    Q.ones();

	// PLAIN
	h5::write(this->fd,this->name+".col", C);
	h5::write(this->fd,this->name+".row", R);
	h5::write(this->fd,this->name+".mat", M);
	h5::write(this->fd,this->name+".cube", Q);
	{ // READ ENTIRE DATASET
	auto c = h5::read<arma::Col<TypeParam>>(this->fd,this->name+".col");
	auto r = h5::read<arma::Row<TypeParam>>(this->fd,this->name+".row");
	auto m = h5::read<arma::Mat<TypeParam>>(this->fd,this->name+".mat");
	auto q = h5::read<arma::Cube<TypeParam>>(this->fd,this->name+".cube");
	}
	{ //READ PARTIAL DATASET
	auto c = h5::read<arma::Col<TypeParam>>(this->fd,this->name+".col",h5::count{2}, h5::offset{1} );
	auto r = h5::read<arma::Row<TypeParam>>(this->fd,this->name+".row", h5::offset{0}, h5::count{3});
	//auto m = h5::read<arma::Mat<TypeParam>>(this->fd,this->name+".mat",
	//		h5::offset{0,0}, h5::stride{2,2}, h5::count{3,4}, h5::block{2,1});
	arma::Mat<TypeParam> m(8,6);
	h5::read(this->fd,this->name+".mat", m.memptr(), h5::stride{4,3}, h5::count{4,3}, h5::block{4,3} );
	m.print();
	}
}
*/
TYPED_TEST(ArmadilloTest, BlockReadArmadillo) {

	arma::Mat<TypeParam>  M(11,11);    for(int i=0; i < M.size(); i++ ) M[i] = i;
	arma::Mat<TypeParam> m(8,6);

	h5::write(this->fd, this->name+".mat", M, h5::chunk{3,3}, h5::high_throughput);
	auto m_ = h5::read<arma::Mat<TypeParam>>(this->fd,this->name+".mat", h5::offset{3,0}, h5::count{4,4}, h5::high_throughput );
	m_.print();
	//h5::read(this->fd,this->name+".mat", m.memptr(), h5::count{2,2}, h5::block{2,2} );
}

/*----------- BEGIN TEST RUNNER ---------------*/
H5CPP_TEST_RUNNER( int argc, char**  argv );
/*----------------- END -----------------------*/


text:
//  Copyright (c) 2007-2013 Hartmut Kaiser
//
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <hpx/hpx_fwd.hpp>
#include <hpx/exception.hpp>
#include <hpx/runtime/threads/executors/service_executor.hpp>
#include <hpx/util/bind.hpp>

#include <boost/asio/basic_deadline_timer.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

namespace hpx { namespace threads { namespace executors { namespace detail
{
    ///////////////////////////////////////////////////////////////////////////
    service_executor::service_executor(char const* pool_name)
      : pool_(get_thread_pool(pool_name)), task_count_(0), shutdown_sem_(0)
    {
        if (!pool_) {
            HPX_THROW_EXCEPTION(bad_parameter,
                "service_executor::service_executor",
                "couldn't retrieve thread pool: " + std::string(pool_name));
        }
    }

    service_executor::~service_executor()
    {
        if (task_count_ != 0)
            shutdown_sem_.wait();
    }

    void service_executor::thread_wrapper(closure_type && f) //-V669
    {
        f();                          // execute the actual thread function

        if (--task_count_ == 0)
            shutdown_sem_.signal();
    }

#if defined(BOOST_ASIO_HAS_MOVE) && BOOST_VERSION >= 105500
    // Schedule the specified function for execution in this executor.
    // Depending on the subclass implementation, this may block in some
    // situations.
    void service_executor::add(closure_type && f,
        char const* desc, threads::thread_state_enum initial_state,
        bool run_now, threads::thread_stacksize stacksize, error_code& ec)
    {
        ++task_count_;

        pool_->get_io_service().post(util::bind(
            util::one_shot(&service_executor::thread_wrapper),
            this, std::move(f)));
    }

    void service_executor::add_no_count(closure_type && f)
    {
        pool_->get_io_service().post(util::bind(
            util::one_shot(&service_executor::thread_wrapper),
            this, std::move(f)));
    }
#else
    struct thread_wrapper_helper
    {
        typedef void result_type;

        thread_wrapper_helper(
            service_executor* exec
          , service_executor::closure_type && f
        ) : exec_(exec)
          , f_(std::move(f))
        {}

        result_type invoke()
        {
            exec_->thread_wrapper(std::move(f_));
        }

        service_executor* exec_;
        service_executor::closure_type f_;
    };

    // Schedule the specified function for execution in this executor.
    // Depending on the subclass implementation, this may block in some
    // situations.
    void service_executor::add(closure_type && f,
        char const* desc, threads::thread_state_enum initial_state,
        bool run_now, threads::thread_stacksize stacksize, error_code& ec)
    {
        ++task_count_;

        boost::shared_ptr<thread_wrapper_helper> wfp(
            boost::make_shared<thread_wrapper_helper>(
                this, std::move(f)));

        pool_->get_io_service().post(util::bind(
            util::one_shot(&thread_wrapper_helper::invoke), wfp));
    }

    void service_executor::add_no_count(closure_type && f)
    {
        boost::shared_ptr<thread_wrapper_helper> wfp(
            boost::make_shared<thread_wrapper_helper>(
                this, std::move(f)));

        pool_->get_io_service().post(util::bind(
            util::one_shot(&thread_wrapper_helper::invoke), wfp));
    }
#endif

    typedef boost::asio::basic_deadline_timer<
        boost::chrono::steady_clock
        , util::chrono_traits<boost::chrono::steady_clock>
    > steady_clock_deadline_timer;

#if defined(BOOST_ASIO_HAS_MOVE) && BOOST_VERSION >= 105500
    static void delayed_add(
        boost::intrusive_ptr<service_executor> this_,
        service_executor::closure_type && f,
        boost::shared_ptr<steady_clock_deadline_timer>)
    {
        this_->add_no_count(std::move(f));
    }

    // Schedule given function for execution in this executor no sooner
    // than time abs_time. This call never blocks, and may violate
    // bounds on the executor's queue size.
    void service_executor::add_at(
        boost::chrono::steady_clock::time_point const& abs_time,
        closure_type && f, char const* desc,
        threads::thread_stacksize stacksize, error_code& ec)
    {
        ++task_count_;

        boost::shared_ptr<steady_clock_deadline_timer> t(
            boost::make_shared<steady_clock_deadline_timer>(
                pool_->get_io_service(), abs_time));

        t->async_wait(util::bind(
            util::one_shot(&delayed_add),
            this, std::move(f), t));
    }

    // Schedule given function for execution in this executor no sooner
    // than time rel_time from now. This call never blocks, and may
    // violate bounds on the executor's queue size.
    void service_executor::add_after(
        boost::chrono::steady_clock::duration const& rel_time,
        closure_type && f, char const* desc,
        threads::thread_stacksize stacksize, error_code& ec)
    {
        return add_at(boost::chrono::steady_clock::now() + rel_time,
            std::move(f), desc, stacksize, ec);
    }
#else
    struct delayed_add_helper
    {
        typedef void result_type;

        delayed_add_helper(
            service_executor* exec
          , service_executor::closure_type && f
          , boost::asio::io_service& io_service
          , boost::chrono::steady_clock::time_point const& abs_time
        ) : exec_(exec)
          , f_(std::move(f))
          , timer_(io_service, abs_time)
        {}

        result_type invoke()
        {
            exec_->add_no_count(std::move(f_));
        }

        service_executor* exec_;
        service_executor::closure_type f_;
        steady_clock_deadline_timer timer_;
    };

    // Schedule given function for execution in this executor no sooner
    // than time abs_time. This call never blocks, and may violate
    // bounds on the executor's queue size.
    void service_executor::add_at(
        boost::chrono::steady_clock::time_point const& abs_time,
        closure_type && f, char const* desc,
        threads::thread_stacksize stacksize, error_code& ec)
    {
        ++task_count_;

        boost::shared_ptr<delayed_add_helper> wfp(
            boost::make_shared<delayed_add_helper>(
                this, std::move(f), pool_->get_io_service(), abs_time));

        wfp->timer_.async_wait(util::bind(
            util::one_shot(&delayed_add_helper::invoke), wfp));
    }

    // Schedule given function for execution in this executor no sooner
    // than time rel_time from now. This call never blocks, and may
    // violate bounds on the executor's queue size.
    void service_executor::add_after(
        boost::chrono::steady_clock::duration const& rel_time,
        closure_type && f, char const* desc,
        threads::thread_stacksize stacksize, error_code& ec)
    {
        return add_at(boost::chrono::steady_clock::now() + rel_time,
            std::move(f), desc, stacksize, ec);
    }
#endif

    // Return an estimate of the number of waiting tasks.
    std::size_t service_executor::num_pending_closures(error_code& ec) const
    {
        return task_count_;
    }

    // Return the requested policy element
    std::size_t service_executor::get_policy_element(
        threads::detail::executor_parameter p, error_code& ec) const
    {
        switch(p) {
        case threads::detail::min_concurrency:
        case threads::detail::max_concurrency:
        case threads::detail::current_concurrency:
            return pool_->size();

        default:
            break;
        }

        HPX_THROWS_IF(ec, bad_parameter,
            "thread_pool_executor::get_policy_element",
            "requested value of invalid policy element");
        return std::size_t(-1);
    }
}}}}


text:
#include <ctime>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <vector>
#include <memory>
#include <algorithm>
#include <Eigen/Dense>
#include <opencv2/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <ceres/ceres.h>
#include <nanoflann.hpp>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/filters/voxel_grid.h>
#include <opencv2/dnn.hpp>
#include <opencv2/face.hpp>
#include <opencv2/ximgproc.hpp>

#define GLOG_minloglevel 3

// OpenARK Libraries
#include "Version.h"
#ifdef PMDSDK_ENABLED
#include "PMDCamera.h"
#endif
#ifdef RSSDK_ENABLED
#include "SR300Camera.h"
#endif
#ifdef RSSDK2_ENABLED
#include "RS2Camera.h"
#endif
#include "MockCamera.h"

#include "Core.h"
#include "Visualizer.h"
#include "Avatar.h"
#include "HumanDetector.h"

using namespace ark;

// open a gui for interacting with avatar
void __avatarGUI()
{
    // build file names and paths
    HumanAvatar ava(HumanDetector::HUMAN_MODEL_PATH, HumanDetector::HUMAN_MODEL_SHAPE_KEYS);
    const size_t NKEYS = HumanDetector::HUMAN_MODEL_SHAPE_KEYS.size();

    cv::namedWindow("Body Shape");
    cv::namedWindow("Body Pose");
    std::vector<int> pcw(NKEYS, 1000), p_pcw(NKEYS, 0);

    // define some axes
    const Eigen::Vector3d AXISX(1, 0, 0), AXISY(0, 1, 0), AXISZ(0, 0, 1);

    // Body pose control definitions (currently this control system only supports rotation along one axis per body part)
    const std::vector<std::string> CTRL_NAMES       = {"L HIP",      "R HIP",      "L KNEE",      "R KNEE",      "L ANKLE",      "R ANKLE",      "L ARM",        "R ARM",        "L ELBOW",      "R ELBOW",      "HEAD",      "SPINE2",     "ROOT"};
    using jnt_t = HumanAvatar::JointType;
    const std::vector<jnt_t> CTRL_JNT               = {jnt_t::L_HIP, jnt_t::R_HIP, jnt_t::L_KNEE, jnt_t::R_KNEE, jnt_t::L_ANKLE, jnt_t::R_ANKLE, jnt_t::L_ELBOW, jnt_t::R_ELBOW, jnt_t::L_WRIST, jnt_t::R_WRIST, jnt_t::HEAD, jnt_t::SPINE2, jnt_t::ROOT_PELVIS};
    const std::vector<Eigen::Vector3d> CTRL_AXIS    = {AXISX,        AXISX,        AXISX,         AXISX,         AXISX,          AXISX,          AXISY,          AXISY,          AXISY,          AXISY,          AXISX,       AXISX,         AXISY};
    const int N_CTRL = (int)CTRL_NAMES.size();

    std::vector<int> ctrlw(N_CTRL, 1000), p_ctrlw(N_CTRL, 0);

    // Body shapekeys are defined in SMPL model files.
    int pifx = 0, pify = 0, picx = 0, picy = 0, pframeID = -1;
    cv::resizeWindow("Body Shape", cv::Size(400, 700));
    cv::resizeWindow("Body Pose", cv::Size(400, 700));
    cv::resizeWindow("Body Scale", cv::Size(400, 700));
    for (int i = 0; i < N_CTRL; ++i) {
        cv::createTrackbar(CTRL_NAMES[i], "Body Pose", &ctrlw[i], 2000);
    }
    for (int i = 0; i < (int)pcw.size(); ++i) {
        cv::createTrackbar("PC" + std::to_string(i), "Body Shape", &pcw[i], 2000);
    }

    auto viewer = Visualizer::getPCLVisualizer();

    int vp1 = 0;
    viewer->setWindowName("3D View");
    viewer->setCameraClipDistances(0.0, 1000.0);

    volatile bool interrupt = false;
    viewer->registerKeyboardCallback([&interrupt](const pcl::visualization::KeyboardEvent & evt) {
        unsigned char k = evt.getKeyCode();
        if (k == 'Q' || k == 'q' || k == 27) {
            interrupt = true;
        }
    });

    while (!interrupt) {
        bool controlsChanged = false;
        for (int i = 0; i < N_CTRL; ++i) {
            if (ctrlw[i] != p_ctrlw[i]) {
                controlsChanged = true;
                break;
            }
        }
        for (int i = 0; i < (int)pcw.size(); ++i) {
            if (pcw[i] != p_pcw[i]) {
                controlsChanged = true;
                break;
            }
        }
        if (controlsChanged) {
            viewer->removeAllPointClouds(vp1);
            viewer->removeAllShapes(vp1);
            HumanAvatar::Cloud_T::Ptr depthPC, depthPCPartial;
            ava.update();

            viewer->addPointCloud<HumanAvatar::Point_T>(ava.getCloud(), "vp1_cloudHM", vp1);
            ava.visualize(viewer, "vp1_", vp1);

            for (int i = 0; i < N_CTRL; ++i) {
                double angle = (ctrlw[i] - 1000) / 1000.0 * PI;
                ava.setRotation(CTRL_JNT[i], Eigen::AngleAxisd(angle, CTRL_AXIS[i]));
            }

            for (int i = 0; i < (int)pcw.size(); ++i) {
                ava.setKeyWeight(i, (float)(pcw[i] - 1000) / 500.0);
            }

            ava.setCenterPosition(Eigen::Vector3d(0, 0, -3));
            ava.update();

            for (int k = 0; k < (int) pcw.size(); ++k) {
                p_pcw[k] = pcw[k] = (int) (ava.getKeyWeight(k) * 500.0 + 1000);
                cv::setTrackbarPos("PC" + std::to_string(k), "Body Shape", pcw[k]);
            }

            double prior = ava.posePrior.residual(ava.smplParams()).squaredNorm();
            // show pose prior value
            if (!viewer->updateText("-log likelihood: " + std::to_string(prior), 10, 20, 15, 1.0, 1.0, 1.0, "poseprior_disp")) {
                viewer->addText("-log likelihood: " + std::to_string(prior), 10, 20, 15, 1.0, 1.0, 1.0, "poseprior_disp");
            }

            viewer->removePointCloud("vp1_cloudHM");
            viewer->addPointCloud<HumanAvatar::Point_T>(ava.getCloud(), "vp1_cloudHM");
            ava.visualize(viewer, "vp1_", vp1);
            viewer->spinOnce();
        }
        for (int i = 0; i < N_CTRL; ++i) p_ctrlw[i] = ctrlw[i];
        for (int i = 0; i < (int)pcw.size(); ++i) p_pcw[i] = pcw[i];

        int k = cv::waitKey(100);
        if (k == 'q' || k == 27) break;
    }
}

int main(int argc, char ** argv) {
    google::InitGoogleLogging(argv[0]);

    printf("Welcome to OpenARK v %s Demo\n\n", VERSION);
    // seed the rng
    srand(time(NULL));

    // pass 'gui' as first argument to see the GUI for manipulating SMPL avatar pose, shape, etc.
    if (argc > 1 && strcmp(argv[1], "gui") == 0) {
        __avatarGUI(); return 0;
    }

    std::string path;
    if (argc > 1) {
        path = argv[1];
    }
    else {
        // sample dataset
        path = util::resolveRootPath("data/avatar-dataset/human-dance");
    }

    cv::namedWindow("RGB Visualization");
	const auto camera = std::make_shared<MockCamera>(path.c_str());
	std::shared_ptr<HumanDetector> human_detector = std::make_shared<HumanDetector>();

	auto viewer = Visualizer::getPCLVisualizer();
	auto vp0 = Visualizer::createPCLViewport(0, 0, 0.7, 1), vp1 = Visualizer::createPCLViewport(0.7, 0, 1, 1);
	while (camera->hasNext()) {
		camera->nextFrame(false);
		cv::Mat xyzMap = camera->getXYZMap();
		cv::Mat rgbMap = camera->getRGBMap();
        long long deltaT = camera->getDeltaT();
		std::vector<cv::Point> rgbJoints = camera->getJoints();

		// Tracking code
		human_detector->update(xyzMap, rgbMap, rgbJoints, double(deltaT)/1e9);
		std::shared_ptr<HumanAvatar> avatar_model = human_detector->getAvatarModel();

        // visualize
        cv::Mat rgbVis = rgbMap.clone();
        for (int i = 0; i < avatar_model->numJoints(); ++i) {
            Eigen::Vector2d v = avatar_model->getJointPosition2d(i);
            cv::circle(rgbVis, cv::Point(int(v.x()), int(v.y())), 3, cv::Scalar(0, 0, 255));
        }
        for (size_t i = 0; i < rgbJoints.size(); ++i) {
            cv::circle(rgbVis, rgbJoints[i], 3, cv::Scalar(255, 0, 0));
        }
		// render the human in GUI
        cv::imshow("RGB Visualization", rgbVis);
		avatar_model->visualize(viewer, "o1_ava_", vp1);
		avatar_model->visualize(viewer, "ava_", vp0);
        auto dataCloud = util::toPointCloud<pcl::PointXYZRGBA>(xyzMap, true, true, 3);
        Visualizer::visualizeCloud(dataCloud, "o1_data", vp1);

		viewer->spinOnce();

		int c = cv::waitKey(1);

		if (c == 'Q' || c == 27) {
			/*** Loop Break Condition ***/
			break;
		}
	}

    cv::destroyAllWindows();
    return 0;
}