/*
 *                   GridGain Community Edition Licensing
 *                   Copyright 2019 GridGain Systems, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License") modified with Commons Clause
 * Restriction; you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * Commons Clause Restriction
 *
 * The Software is provided to you by the Licensor under the License, as defined below, subject to
 * the following condition.
 *
 * Without limiting other conditions in the License, the grant of rights under the License will not
 * include, and the License does not grant to you, the right to Sell the Software.
 * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you
 * under the License to provide to third parties, for a fee or other consideration (including without
 * limitation fees for hosting or consulting/ support services related to the Software), a product or
 * service whose value derives, entirely or substantially, from the functionality of the Software.
 * Any license notice or attribution required by the License must also include this Commons Clause
 * License Condition notice.
 *
 * For purposes of the clause above, the “Licensor” is Copyright 2019 GridGain Systems, Inc.,
 * the “License” is the Apache License, Version 2.0, and the Software is the GridGain Community
 * Edition software provided with this notice.
 */

#define _USE_MATH_DEFINES

#ifdef _WIN32
#   include <windows.h>
#endif

#include <sql.h>
#include <sqlext.h>

#include <cmath>

#include <vector>
#include <string>

#ifndef _MSC_VER
#   define BOOST_TEST_DYN_LINK
#endif

#include <boost/test/unit_test.hpp>

#include "ignite/ignite.h"
#include "ignite/ignition.h"
#include "ignite/impl/binary/binary_utils.h"

#include "test_type.h"
#include "test_utils.h"
#include "sql_test_suite_fixture.h"

using namespace ignite;
using namespace ignite::cache;
using namespace ignite::cache::query;
using namespace ignite::common;
using namespace ignite_test;

using namespace boost::unit_test;

using ignite::impl::binary::BinaryUtils;

BOOST_FIXTURE_TEST_SUITE(SqlNumericFunctionTestSuite, ignite::SqlTestSuiteFixture)

BOOST_AUTO_TEST_CASE(TestNumericFunctionAbs)
{
    TestType in;

    in.i32Field = -42;

    testCache.Put(1, in);

    CheckSingleResult<SQLINTEGER>("SELECT {fn ABS(i32Field)} FROM TestType", std::abs(in.i32Field));
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionAcos)
{
    TestType in;

    in.doubleField = 0.32;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn ACOS(doubleField)} FROM TestType", std::acos(in.doubleField));
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionAsin)
{
    TestType in;

    in.doubleField = 0.12;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn ASIN(doubleField)} FROM TestType", std::asin(in.doubleField));
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionAtan)
{
    TestType in;

    in.doubleField = 0.14;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn ATAN(doubleField)} FROM TestType", std::atan(in.doubleField));
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionAtan2)
{
    TestType in;

    in.doubleField = 0.24;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn ATAN2(doubleField, 0.2)} FROM TestType", std::atan2(in.doubleField, 0.2));
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionCeiling)
{
    TestType in;

    in.doubleField = 7.31;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn CEILING(doubleField)} FROM TestType", std::ceil(in.doubleField));
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionCos)
{
    TestType in;

    in.doubleField = 2.31;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn COS(doubleField)} FROM TestType", std::cos(in.doubleField));
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionCot)
{
    TestType in;

    in.doubleField = 2.31;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn COT(doubleField)} FROM TestType", 1 / std::tan(in.doubleField));
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionDegrees)
{
    TestType in;

    in.doubleField = 2.31;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn DEGREES(doubleField)} FROM TestType", in.doubleField * M_1_PI * 180);
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionExp)
{
    TestType in;

    in.doubleField = 1.23;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn EXP(doubleField)} FROM TestType", std::exp(in.doubleField));
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionFloor)
{
    TestType in;

    in.doubleField = 5.29;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn FLOOR(doubleField)} FROM TestType", std::floor(in.doubleField));
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionLog)
{
    TestType in;

    in.doubleField = 15.3;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn LOG(doubleField)} FROM TestType", std::log(in.doubleField));
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionLog10)
{
    TestType in;

    in.doubleField = 15.3;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn LOG10(doubleField)} FROM TestType", std::log10(in.doubleField));
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionMod)
{
    TestType in;

    in.i64Field = 26;

    testCache.Put(1, in);

    CheckSingleResult<SQLBIGINT>("SELECT {fn MOD(i64Field, 3)} FROM TestType", in.i64Field % 3);
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionPi)
{
    CheckSingleResult<double>("SELECT {fn PI()}", M_PI);
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionPower)
{
    TestType in;

    in.doubleField = 1.81;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn POWER(doubleField, 2.5)} FROM TestType", std::pow(in.doubleField, 2.5));
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionRadians)
{
    TestType in;

    in.doubleField = 161;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn RADIANS(doubleField)} FROM TestType", in.doubleField * M_PI / 180.0);
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionRand)
{
    CheckSingleResult<double>("SELECT {fn RAND()} * 0", 0);
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionRound)
{
    TestType in;

    in.doubleField = 5.29;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn ROUND(doubleField)} FROM TestType", std::floor(in.doubleField));
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionSign)
{
    TestType in;

    in.doubleField = -1.39;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn SIGN(doubleField)} FROM TestType", in.doubleField < 0 ? -1 : in.doubleField == 0 ? 0 : 1);
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionSin)
{
    TestType in;

    in.doubleField = 1.01;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn SIN(doubleField)} FROM TestType", std::sin(in.doubleField));
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionSqrt)
{
    TestType in;

    in.doubleField = 2.56;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn SQRT(doubleField)} FROM TestType", std::sqrt(in.doubleField));
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionTan)
{
    TestType in;

    in.doubleField = 0.56;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn TAN(doubleField)} FROM TestType", std::tan(in.doubleField));
}

BOOST_AUTO_TEST_CASE(TestNumericFunctionTruncate)
{
    TestType in;

    in.doubleField = 4.17133;

    testCache.Put(1, in);

    CheckSingleResult<double>("SELECT {fn TRUNCATE(doubleField, 3)} FROM TestType", 4.171);
}

BOOST_AUTO_TEST_SUITE_END()


#include <Eigen/Core>
#include <Eigen/Geometry>
#include <glog/logging.h>
#include <gtest/gtest.h>
#include <kindr/minimal/quat-transformation.h>
#include <kindr/minimal/transform-2d.h>

#include "minkindr_conversions/kindr_msg.h"
#include "testing_predicates.h"

namespace tf {

const double kTestTolerance = std::numeric_limits<double>::epsilon() * 3;

TEST(KindrMsgTest, poseKindrToMsgToKindr) {
  Eigen::Quaterniond rotation(Eigen::Vector4d::Random());
  rotation.normalize();
  Eigen::Vector3d position(Eigen::Vector3d::Random());
  kindr::minimal::QuatTransformation kindr_transform(rotation, position);

  geometry_msgs::Pose msg;
  poseKindrToMsg(kindr_transform, &msg);
  kindr::minimal::QuatTransformation output_transform;
  poseMsgToKindr(msg, &output_transform);

  EXPECT_NEAR_EIGEN(
      output_transform.getRotation().toImplementation().coeffs(),
      rotation.coeffs(), kTestTolerance);
  EXPECT_NEAR_EIGEN(output_transform.getPosition(), position, kTestTolerance);
}

TEST(KindrMsgTest, poseKindr2DToMsgToKindr2D) {
  static constexpr double kTestRotationAngleRad = 0.5;
  Eigen::Rotation2D<double> rotation(kTestRotationAngleRad);
  const Eigen::Vector2d position = Eigen::Vector2d::Random();
  kindr::minimal::Transformation2D kindr_transform(rotation, position);

  geometry_msgs::Pose msg;
  poseKindr2DToMsg(kindr_transform, &msg);
  kindr::minimal::Transformation2D output_transform;
  poseMsgToKindr2D(msg, &output_transform);

  EXPECT_NEAR(
      output_transform.getRotation().angle(), rotation.angle(), kTestTolerance);
  EXPECT_NEAR_EIGEN(output_transform.getPosition(), position, kTestTolerance);
}

TEST(KindrMsgTest, poseMsgToKindr2DFailsForInvalidInputPose) {
  geometry_msgs::Pose invalid_position_msg;
  invalid_position_msg.position.z = 1.0;
  kindr::minimal::Transformation2D invalid_position_output_transform;
  EXPECT_DEATH(
      poseMsgToKindr2D(
          invalid_position_msg, &invalid_position_output_transform),
      "No proper 2D position.");

  geometry_msgs::Pose invalid_rotation_msg;
  kindr::minimal::Transformation2D invalid_rotation_output_transform;
  const kindr::minimal::RotationQuaternion invalid_2d_rotation(
      kindr::minimal::AngleAxis(0.5, 0.0, 1.0, 0.0));
  quaternionKindrToMsg(invalid_2d_rotation, &invalid_rotation_msg.orientation);
  EXPECT_DEATH(
      poseMsgToKindr2D(invalid_rotation_msg, &invalid_rotation_output_transform),
      "No proper 2D rotation.");
}

TEST(KindrMsgTest, transformKindrToMsgToKindr) {
  Eigen::Quaterniond rotation(Eigen::Vector4d::Random());
  rotation.normalize();
  Eigen::Vector3d position(Eigen::Vector3d::Random());
  kindr::minimal::QuatTransformation kindr_transform(rotation, position);

  geometry_msgs::Transform msg;
  transformKindrToMsg(kindr_transform, &msg);
  kindr::minimal::QuatTransformation output_transform;
  transformMsgToKindr(msg, &output_transform);

  EXPECT_NEAR_EIGEN(
      output_transform.getRotation().toImplementation().coeffs(),
      rotation.coeffs(), kTestTolerance);
  EXPECT_NEAR_EIGEN(output_transform.getPosition(), position, kTestTolerance);
}

TEST(KindrMsgTest, quaternionKindrToMsgToKindr) {
  Eigen::Quaterniond rotation(Eigen::Vector4d::Random());
  rotation.normalize();

  geometry_msgs::Quaternion msg;
  quaternionKindrToMsg(rotation, &msg);
  Eigen::Quaterniond output_rotation;
  quaternionMsgToKindr(msg, &output_rotation);

  EXPECT_NEAR_EIGEN(
      output_rotation.coeffs(), rotation.coeffs(), kTestTolerance);
}

TEST(KindrMsgTest, vectorKindrToMsgToKindr) {
  Eigen::Vector3d position(Eigen::Vector3d::Random());

  geometry_msgs::Vector3 msg;
  vectorKindrToMsg(position, &msg);
  Eigen::Vector3d output_position;
  vectorMsgToKindr(msg, &output_position);

  EXPECT_NEAR_EIGEN(output_position, position, kTestTolerance);
}

}  // namespace tf

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}


// Copyright 2020 Matthias Heinz
#include "negele/matrix.h"

#include <lapack.h>

#include <cmath>
#include <iostream>
#include <vector>

#include <boost/numeric/odeint.hpp>

#include "negele/constants.h"

namespace boost {
namespace numeric {
namespace odeint {

template <>
struct is_resizeable<negele::matrix::MomentumSpaceMatrix> {  // declare
                                                             // resizeability
  typedef boost::true_type type;
  const static bool value = type::value;
};

template <>
struct same_size_impl<negele::matrix::MomentumSpaceMatrix,
                      negele::matrix::MomentumSpaceMatrix> {  // define how to
                                                              // check size
  static bool same_size(const negele::matrix::MomentumSpaceMatrix& v1,
                        const negele::matrix::MomentumSpaceMatrix& v2) {
    return v1.same_size(v2);
  }
};

template <>
struct resize_impl<negele::matrix::MomentumSpaceMatrix,
                   negele::matrix::MomentumSpaceMatrix> {  // define how to
                                                           // resize
  static void resize(negele::matrix::MomentumSpaceMatrix& v1,
                     const negele::matrix::MomentumSpaceMatrix& v2) {
    v1.resize(v2);
  }
};

}  // namespace odeint
}  // namespace numeric
}  // namespace boost

negele::matrix::SquareMatrix::SquareMatrix(int dim, double value)
    : m_dim(dim), m_matrix(dim * dim, value) {}

negele::matrix::SquareMatrix::SquareMatrix(int dim,
                                           const std::vector<double>& mels)
    : m_dim(dim), m_matrix(mels) {
  if (m_matrix.size() != m_dim * m_dim) {
    std::cout << "Matrix initialized with incompatible dimensions: \n"
              << "\tsingle-axis dimension given: " << m_dim << "\n"
              << "\tactual size of matrix: " << m_matrix.size() << "\n";
    exit(EXIT_FAILURE);
  }
}

negele::matrix::SquareMatrix negele::matrix::SquareMatrix::from_diag(
    const std::vector<double>& diag_mels) {
  int dim = diag_mels.size();
  std::vector<double> mels(dim * dim, 0.0);
  for (int i = 0; i < dim; i++) {
    mels[i * dim + i] = diag_mels[i];
  }

  return negele::matrix::SquareMatrix(dim, mels);
}

negele::matrix::SquareMatrix& negele::matrix::SquareMatrix::operator+=(
    const negele::matrix::SquareMatrix& other) {
  if (m_dim != other.m_dim) {
    std::cout << "Matrices have incompatible dimensions: " << m_dim << ", and "
              << other.m_dim << "\n";
    exit(EXIT_FAILURE);
  }
  for (int i = 0; i < m_dim * m_dim; i++) {
    m_matrix[i] += other.m_matrix[i];
  }
  return *this;
}

negele::matrix::SquareMatrix& negele::matrix::SquareMatrix::operator-=(
    const negele::matrix::SquareMatrix& other) {
  if (m_dim != other.m_dim) {
    std::cout << "Matrices have incompatible dimensions: " << m_dim << ", and "
              << other.m_dim << "\n";
    exit(EXIT_FAILURE);
  }
  for (int i = 0; i < m_dim * m_dim; i++) {
    m_matrix[i] -= other.m_matrix[i];
  }
  return *this;
}
negele::matrix::SquareMatrix& negele::matrix::SquareMatrix::operator*=(
    double factor) {
  for (int i = 0; i < m_dim * m_dim; i++) {
    m_matrix[i] *= factor;
  }
  return *this;
}
negele::matrix::SquareMatrix& negele::matrix::SquareMatrix::operator/=(
    double factor) {
  if (factor == 0.0) {
    std::cout << "Attempted division by 0.\n";
    exit(EXIT_FAILURE);
  }
  for (int i = 0; i < m_dim * m_dim; i++) {
    m_matrix[i] /= factor;
  }
  return *this;
}

negele::matrix::SquareMatrix& negele::matrix::SquareMatrix::operator/=(
    const negele::matrix::SquareMatrix& other) {
  if (m_dim != other.m_dim) {
    std::cout << "Matrices have incompatible dimensions: " << m_dim << ", and "
              << other.m_dim << "\n";
    exit(EXIT_FAILURE);
  }
  for (int i = 0; i < m_dim * m_dim; i++) {
    if (other.m_matrix[i] != 0.0) {
      m_matrix[i] /= other.m_matrix[i];
    }
  }
  return *this;
}

negele::matrix::SquareMatrix& negele::matrix::SquareMatrix::abs() {
  for (int i = 0; i < m_dim * m_dim; i++) {
    m_matrix[i] = fabs(m_matrix[i]);
  }
  return *this;
}

double negele::matrix::SquareMatrix::max() const {
  double val = 0.0;
  if (m_dim > 0) {
    val = m_matrix[0];
  }
  for (int i = 0; i < m_dim * m_dim; i++) {
    if (m_matrix[i] > val) {
      val = m_matrix[i];
    }
  }
  return val;
}

negele::matrix::SquareMatrix negele::matrix::operator+(
    const SquareMatrix& a, const negele::matrix::SquareMatrix& b) {
  negele::matrix::SquareMatrix c(a);
  c += b;
  return c;
}
negele::matrix::SquareMatrix negele::matrix::operator-(
    const negele::matrix::SquareMatrix& a,
    const negele::matrix::SquareMatrix& b) {
  negele::matrix::SquareMatrix c(a);
  c -= b;
  return c;
}
negele::matrix::SquareMatrix negele::matrix::operator*(
    double factor, const negele::matrix::SquareMatrix& mat) {
  negele::matrix::SquareMatrix c(mat);
  c *= factor;
  return c;
}
negele::matrix::SquareMatrix negele::matrix::operator*(
    const negele::matrix::SquareMatrix& mat, double factor) {
  negele::matrix::SquareMatrix c(mat);
  c *= factor;
  return c;
}
negele::matrix::SquareMatrix negele::matrix::operator/(
    const negele::matrix::SquareMatrix& mat, double factor) {
  negele::matrix::SquareMatrix c(mat);
  c /= factor;
  return c;
}
negele::matrix::SquareMatrix negele::matrix::operator/(
    const negele::matrix::SquareMatrix& a,
    const negele::matrix::SquareMatrix& b) {
  negele::matrix::SquareMatrix c(a);
  c /= b;
  return c;
}
negele::matrix::SquareMatrix negele::matrix::abs(
    const negele::matrix::SquareMatrix& a) {
  negele::matrix::SquareMatrix c(a);
  c.abs();
  return c;
}

negele::matrix::SquareMatrix negele::matrix::operator*(
    const negele::matrix::SquareMatrix& a,
    const negele::matrix::SquareMatrix& b) {
  if (a.m_dim != b.m_dim) {
    std::cout << "Matrices have incompatible dimensions: " << a.m_dim
              << ", and " << b.m_dim << "\n";
    exit(EXIT_FAILURE);
  }
  auto new_mels = negele::matrix::mat_mul(a.m_matrix, b.m_matrix, a.m_dim);
  return negele::matrix::SquareMatrix(a.m_dim, new_mels);
}

std::vector<double> negele::matrix::SquareMatrix::eigenvalues() const {
  std::vector<double> evs(m_dim, 0.0);
  std::vector<double> matrix_copy(m_matrix);
  std::vector<double> work(20 * m_dim, 0.0);
  int info = 0;
  char uplo = 'U';
  char jobz = 'N';
  int lwork = work.size();
  LAPACK_dsyev(&jobz, &uplo, &m_dim, matrix_copy.data(), &m_dim, evs.data(),
               work.data(), &lwork, &info);

  return evs;
}

negele::matrix::MomentumSpaceMatrix::MomentumSpaceMatrix(
    const std::vector<double>& pts, const std::vector<double>& weights,
    const std::vector<double>& mels)
    : m_dim(pts.size()),
      m_pts(pts),
      m_weights(weights),
      m_mels_with_weights(pts.size(), 0.0),
      m_kin_e(pts.size(), 0.0) {
  std::vector<double> weights_sqrt;
  for (const auto& w : m_weights) {
    weights_sqrt.push_back(sqrt(w));
  }

  auto weights_mat = negele::matrix::SquareMatrix::from_diag(weights_sqrt);
  negele::matrix::SquareMatrix mels_wo_weights(m_dim, mels);

  m_mels_with_weights = weights_mat * mels_wo_weights * weights_mat;

  std::vector<double> kin_diag;
  for (const auto& p : pts) {
    kin_diag.push_back(p * p * HBARC * HBARC / (2 * MASS));
  }
  m_kin_e = negele::matrix::SquareMatrix::from_diag(kin_diag);
}

void negele::matrix::MomentumSpaceMatrix::clear_mels() {
  m_mels_with_weights *= 0.0;
}
double negele::matrix::MomentumSpaceMatrix::max() const {
  return negele::matrix::abs(m_mels_with_weights).max();
}

void negele::matrix::MomentumSpaceMatrix::resize(
    const negele::matrix::MomentumSpaceMatrix& other) {
  m_dim = other.m_dim;
  m_pts = std::vector<double>(other.m_pts);
  m_weights = std::vector<double>(other.m_weights);

  m_mels_with_weights = negele::matrix::SquareMatrix(m_dim, 0.0);
  m_kin_e = negele::matrix::SquareMatrix(m_dim, 0.0);
}

bool negele::matrix::MomentumSpaceMatrix::same_size(
    const negele::matrix::MomentumSpaceMatrix& other) const {
  if (m_dim != other.m_dim) {
    return false;
  }
  for (int i = 0; i < m_dim; i++) {
    if (m_pts[i] != other.m_pts[i]) {
      return false;
    }
    if (m_weights[i] != other.m_weights[i]) {
      return false;
    }
  }
  if (m_mels_with_weights.size() != other.m_mels_with_weights.size()) {
    return false;
  }
  if (m_kin_e.size() != other.m_kin_e.size()) {
    return false;
  }
  return true;
}

negele::matrix::SquareMatrix
negele::matrix::MomentumSpaceMatrix::matrix_elements() const {
  std::vector<double> weights_inv_sqrt;
  for (const auto& w : m_weights) {
    weights_inv_sqrt.push_back(1.0 / sqrt(w));
  }
  auto weights_inv_mat =
      negele::matrix::SquareMatrix::from_diag(weights_inv_sqrt);
  return weights_inv_mat * m_mels_with_weights * weights_inv_mat;
}

std::vector<double> negele::matrix::mat_mul(const std::vector<double>& a,
                                            const std::vector<double>& b,
                                            int dim) {
  std::vector<double> new_matrix(dim * dim, 0.0);

  for (int i = 0; i < dim; i++) {
    for (int j = 0; j < dim; j++) {
      for (int k = 0; k < dim; k++) {
        new_matrix[i * dim + j] += a[i * dim + k] * b[k * dim + j];
      }
    }
  }

  return new_matrix;
}

negele::matrix::MomentumSpaceMatrix& negele::matrix::MomentumSpaceMatrix::
operator+=(const negele::matrix::MomentumSpaceMatrix& other) {
  m_mels_with_weights += other.m_mels_with_weights;
  return *this;
}

negele::matrix::MomentumSpaceMatrix& negele::matrix::MomentumSpaceMatrix::
operator+=(const double other) {
  for (int i = 0; i < m_dim * m_dim; i++) {
    m_mels_with_weights[i] += copysign(other, m_mels_with_weights[i]);
  }
  return *this;
}

negele::matrix::MomentumSpaceMatrix& negele::matrix::MomentumSpaceMatrix::
operator*=(const double factor) {
  m_mels_with_weights *= factor;
  return *this;
}

negele::matrix::MomentumSpaceMatrix negele::matrix::operator/(
    const negele::matrix::MomentumSpaceMatrix& a,
    const negele::matrix::MomentumSpaceMatrix& b) {
  negele::matrix::MomentumSpaceMatrix c(a);
  c.m_mels_with_weights /= b.m_mels_with_weights;
  return c;
}

negele::matrix::MomentumSpaceMatrix negele::matrix::abs(
    const negele::matrix::MomentumSpaceMatrix& a) {
  negele::matrix::MomentumSpaceMatrix c(a);
  c.m_mels_with_weights.abs();
  return c;
}


#include <iostream>
#include <vector>

#include <Eigen/Geometry>
#include <gtest/gtest.h>
#include <voxelized_geometry_tools/mesh_rasterizer.hpp>

namespace voxelized_geometry_tools
{
namespace
{
GTEST_TEST(MeshRasterizationTest, Test)
{
  const std::vector<Eigen::Vector3d> vertices = {
      Eigen::Vector3d(0.0, 0.0, 0.0), Eigen::Vector3d(1.0, 0.0, 0.0),
      Eigen::Vector3d(0.0, 1.0, 0.0) };
  const std::vector<Eigen::Vector3i> triangles = { Eigen::Vector3i(0, 1, 2) };

  const double resolution = 0.125;
  const auto collision_map =
      RasterizeMeshIntoCollisionMap(vertices, triangles, resolution);

  const auto get_cell_occupancy =
      [&] (const int64_t x, const int64_t y, const int64_t z)
  {
    return collision_map.GetImmutable(x, y, z).Value().Occupancy();
  };

  // Due to how the triangle discretizes, we expect the lower layer to be empty.
  for (int64_t xidx = 0; xidx < collision_map.GetNumXCells(); xidx++)
  {
    for (int64_t yidx = 0; yidx < collision_map.GetNumYCells(); yidx++)
    {
      EXPECT_EQ(get_cell_occupancy(xidx, yidx, 0), 0.0f);
    }
  }

  // Check the upper layer of voxels.
  for (int64_t xidx = 0; xidx < collision_map.GetNumXCells(); xidx++)
  {
    for (int64_t yidx = 0; yidx < collision_map.GetNumYCells(); yidx++)
    {
      if (xidx == 0 || yidx == 0)
      {
        EXPECT_EQ(get_cell_occupancy(xidx, yidx, 1), 0.0f);
      }
      else if (yidx >= (collision_map.GetNumYCells() - xidx))
      {
        EXPECT_EQ(get_cell_occupancy(xidx, yidx, 1), 0.0f);
      }
      else
      {
        EXPECT_EQ(get_cell_occupancy(xidx, yidx, 1), 1.0f);
      }
    }
  }
}
}  // namespace
}  // namespace voxelized_geometry_tools

int main(int argc, char** argv)
{
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}


/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file difficulty.cpp
 * @author Christoph Jentzsch <cj@ethdev.com>
 * @date 2015
 * difficulty calculation tests.
 */

#include <test/tools/libtesteth/TestHelper.h>
#include <test/tools/fuzzTesting/fuzzHelper.h>
#include <libethashseal/Ethash.h>
#include <libethashseal/GenesisInfo.h>
#include <libethereum/ChainParams.h>
#include <boost/filesystem/path.hpp>
using namespace std;
using namespace dev;
using namespace dev::eth;

namespace fs = boost::filesystem;
namespace js = json_spirit;
std::string const c_testDifficulty = R"(
 "DifficultyTest[N]" : {
		"parentTimestamp" : "[PSTAMP]",
		"parentDifficulty" : "[PDIFF]",
		"parentUncles" : "[PUNCLS]",
		"currentTimestamp" : "[СSTAMP]",
		"currentBlockNumber" : "[CNUM]",
		"currentDifficulty" : "[CDIFF]"
	},
)";
h256 const nonzeroHash = sha3("whatever nonempty string");

void fillDifficulty(boost::filesystem::path const& _testFileFullName, Ethash& _sealEngine)
{
	int testN = 0;
	ostringstream finalTest;
	finalTest << "{\n";
	test::TestOutputHelper::get().initTest(900);

	for (int stampDelta = 0; stampDelta < 45; stampDelta += 2)
	{
		for (int pUncles = 0; pUncles < 2; pUncles++)
		{
			for (int blockNumber = 100000; blockNumber < 5000000; blockNumber += 100000)
			{
				testN++;
				string testName = "DifficultyTest"+toString(testN);
				if (!test::TestOutputHelper::get().checkTest(testName))
					continue;

				// A random timestamp up to year 3048.
				auto pStamp =
					static_cast<int64_t>(test::RandomCode::get().randomUniInt(1, 34020247236));
				u256 pDiff = test::RandomCode::get().randomUniInt();
				int64_t cStamp = pStamp + stampDelta;
				int cNum = blockNumber;

				BlockHeader parent;
				parent.setTimestamp(pStamp);
				parent.setDifficulty(pDiff);
				parent.setNumber(cNum - 1);
				parent.setSha3Uncles((pUncles == 0) ? EmptyListSHA3 : nonzeroHash);

				BlockHeader current;
				current.setTimestamp(cStamp);
				current.setNumber(cNum);

				string tmptest = c_testDifficulty;
				std::map<string, string> replaceMap;
				replaceMap["[N]"] = toString(testN);
				replaceMap["[PDIFF]"] = toCompactHexPrefixed(pDiff);
				replaceMap["[PSTAMP]"] = toCompactHexPrefixed(pStamp);
				replaceMap["[PUNCLS]"] = toCompactHexPrefixed(parent.sha3Uncles());
				replaceMap["[СSTAMP]"] = toCompactHexPrefixed(cStamp);
				replaceMap["[CNUM]"] = toCompactHexPrefixed(cNum);
                replaceMap["[CDIFF]"] = toCompactHexPrefixed(
                    calculateEthashDifficulty(_sealEngine.chainParams(), current, parent));

                test::RandomCodeOptions defaultOptions;
                test::RandomCode::get().parseTestWithTypes(tmptest, replaceMap, defaultOptions);
				finalTest << tmptest;
			}
		}
	}

	finalTest << "\n}";
	string testFile = finalTest.str();
	testFile = testFile.replace(testFile.find_last_of(","), 1, "");
	writeFile(_testFileFullName, asBytes(testFile));
}

void testDifficulty(fs::path const& _testFileFullName, Ethash& _sealEngine)
{
	//Test File
	js::mValue v;
	string s = contentsString(_testFileFullName);
	BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of '" << _testFileFullName << "' is empty. Have you cloned the 'tests' repo branch develop?");
	js::read_string(s, v);
	test::TestOutputHelper::get().initTest(v.get_obj().size());

	for (auto& i: v.get_obj())
	{
		js::mObject o = i.second.get_obj();
		string testname = i.first;
		if (!test::TestOutputHelper::get().checkTest(testname))
			continue;

		BOOST_REQUIRE_MESSAGE(o.count("parentTimestamp") > 0, testname + " missing parentTimestamp field");
		BOOST_REQUIRE_MESSAGE(o.count("parentDifficulty") > 0, testname + " missing parentDifficulty field");
		BOOST_REQUIRE_MESSAGE(o.count("currentBlockNumber") > 0, testname + " missing currentBlockNumber field");
		BOOST_REQUIRE_MESSAGE(o.count("parentUncles") > 0, testname + " missing parentUncles field");
		BOOST_REQUIRE_MESSAGE(o.count("currentTimestamp") > 0, testname + " missing currentTimestamp field");
		BOOST_REQUIRE_MESSAGE(o.count("currentBlockNumber") > 0, testname + " missing currentBlockNumber field");
		BOOST_REQUIRE_MESSAGE(o.count("currentDifficulty") > 0, testname + " missing currentDifficulty field");

		BlockHeader parent;
        parent.setTimestamp(test::toUint64(o["parentTimestamp"]));
        parent.setDifficulty(test::toU256(o["parentDifficulty"]));
        parent.setNumber(test::toUint64(o["currentBlockNumber"]) - 1);
        parent.setSha3Uncles(h256(o["parentUncles"].get_str()));

        BlockHeader current;
        current.setTimestamp(test::toUint64(o["currentTimestamp"]));
        current.setNumber(test::toUint64(o["currentBlockNumber"]));

        u256 difficulty = calculateEthashDifficulty(_sealEngine.chainParams(), current, parent);
        BOOST_CHECK_EQUAL(difficulty, test::toU256(o["currentDifficulty"]));
    }
}

BOOST_AUTO_TEST_SUITE(DifficultyTests)

BOOST_AUTO_TEST_CASE(difficultyTestsFrontier)
{
	fs::path const testFileFullName = test::getTestPath() / fs::path("BasicTests/difficultyFrontier.json");

	Ethash sealEngine;
	sealEngine.setChainParams(ChainParams(genesisInfo(eth::Network::FrontierTest)));

	if (dev::test::Options::get().filltests)
		fillDifficulty(testFileFullName, sealEngine);

	testDifficulty(testFileFullName, sealEngine);
}

BOOST_AUTO_TEST_CASE(difficultyTestsRopsten)
{
	fs::path const testFileFullName = test::getTestPath() / fs::path("BasicTests/difficultyRopsten.json");

	Ethash sealEngine;
	sealEngine.setChainParams(ChainParams(genesisInfo(eth::Network::Ropsten)));

	if (dev::test::Options::get().filltests)
		fillDifficulty(testFileFullName, sealEngine);

	testDifficulty(testFileFullName, sealEngine);
}

BOOST_AUTO_TEST_CASE(difficultyTestsHomestead)
{
	fs::path const testFileFullName = test::getTestPath() / fs::path("BasicTests/difficultyHomestead.json");

	Ethash sealEngine;
	sealEngine.setChainParams(ChainParams(genesisInfo(eth::Network::HomesteadTest)));

	if (dev::test::Options::get().filltests)
		fillDifficulty(testFileFullName, sealEngine);

	testDifficulty(testFileFullName, sealEngine);
}

BOOST_AUTO_TEST_CASE(difficultyByzantium)
{
	fs::path const testFileFullName = test::getTestPath() / fs::path("BasicTests/difficultyByzantium.json");

	Ethash sealEngine;
	sealEngine.setChainParams(ChainParams(genesisInfo(eth::Network::ByzantiumTest)));

	if (dev::test::Options::get().filltests)
		fillDifficulty(testFileFullName, sealEngine);

	testDifficulty(testFileFullName, sealEngine);
}

BOOST_AUTO_TEST_CASE(difficultyConstantinople)
{
    fs::path const testFileFullName = test::getTestPath() / fs::path("BasicTests/difficultyConstantinople.json");

    Ethash sealEngine;
    sealEngine.setChainParams(ChainParams(genesisInfo(eth::Network::ConstantinopleTest)));

    if (dev::test::Options::get().filltests)
        fillDifficulty(testFileFullName, sealEngine);

    testDifficulty(testFileFullName, sealEngine);
}

BOOST_AUTO_TEST_CASE(difficultyTestsMainNetwork)
{
	fs::path const testFileFullName = test::getTestPath() / fs::path("BasicTests/difficultyMainNetwork.json");

	Ethash sealEngine;
	sealEngine.setChainParams(ChainParams(genesisInfo(eth::Network::MainNetworkTest)));

	if (dev::test::Options::get().filltests)
		fillDifficulty(testFileFullName, sealEngine);

	testDifficulty(testFileFullName, sealEngine);
}

BOOST_AUTO_TEST_CASE(difficultyTestsCustomMainNetwork)
{
	fs::path const testFileFullName = test::getTestPath() / fs::path("BasicTests/difficultyCustomMainNetwork.json");

	Ethash sealEngine;
	sealEngine.setChainParams(ChainParams(genesisInfo(eth::Network::MainNetworkTest)));

	if (dev::test::Options::get().filltests)
	{
		int64_t byzantiumBlockNumber = 4370000;
		std::vector<int64_t> blockNumberVector = {byzantiumBlockNumber - 100000, byzantiumBlockNumber, byzantiumBlockNumber + 100000};
		std::vector<u256> parentDifficultyVector = {1000, 2048, 4000, 1000000};
		std::vector<int> timestampDeltaVector = {0, 1, 8, 10, 13, 20, 100, 800, 1000, 1500};

		int testN = 0;
		ostringstream finalTest;
		finalTest << "{\n";

		for (size_t bN = 0; bN < blockNumberVector.size(); bN++)
			for (size_t pdN = 0; pdN < parentDifficultyVector.size(); pdN++)
				for (int pUncles = 0; pUncles < 3; pUncles++)
					for (size_t tsN = 0; tsN < timestampDeltaVector.size(); tsN++)
					{
						testN++;
						int stampDelta = timestampDeltaVector.at(tsN);
						int64_t blockNumber = blockNumberVector.at(bN);
						u256 pDiff = parentDifficultyVector.at(pdN);

						auto cStamp = static_cast<int64_t>(test::RandomCode::get().randomUniInt(timestampDeltaVector.back()));
						int64_t pStamp = cStamp - stampDelta;
                        int64_t cNum = blockNumber;

						BlockHeader parent;
						parent.setTimestamp(pStamp);
						parent.setDifficulty(pDiff);
						parent.setNumber(cNum - 1);

						parent.setSha3Uncles((pUncles == 0) ? EmptyListSHA3 : nonzeroHash);

						BlockHeader current;
						current.setTimestamp(cStamp);
						current.setNumber(cNum);

						string tmptest = c_testDifficulty;
						std::map<string, string> replaceMap;
						replaceMap["[N]"] = toString(testN);
						replaceMap["[PDIFF]"] = toCompactHexPrefixed(pDiff);
						replaceMap["[PSTAMP]"] = toCompactHexPrefixed(pStamp);
						replaceMap["[PUNCLS]"] = toCompactHexPrefixed(parent.sha3Uncles());
						replaceMap["[СSTAMP]"] = toCompactHexPrefixed(cStamp);
						replaceMap["[CNUM]"] = toCompactHexPrefixed(cNum);
                        replaceMap["[CDIFF]"] = toCompactHexPrefixed(
                            calculateEthashDifficulty(sealEngine.chainParams(), current, parent));

                        test::RandomCodeOptions defaultOptions;
                        test::RandomCode::get().parseTestWithTypes(tmptest, replaceMap, defaultOptions);
						finalTest << tmptest;
					}

		finalTest << "\n}";
		string testFile = finalTest.str();
		testFile = testFile.replace(testFile.find_last_of(","), 1, "");
		writeFile(testFileFullName, asBytes(testFile));
	}

	testDifficulty(testFileFullName, sealEngine);
}

BOOST_AUTO_TEST_CASE(basicDifficultyTest)
{
	fs::path const testPath = test::getTestPath() / fs::path("BasicTests/difficulty.json");

	Ethash sealEngine;
	sealEngine.setChainParams(ChainParams(genesisInfo(eth::Network::MainNetwork)));

	testDifficulty(testPath, sealEngine);
}

BOOST_AUTO_TEST_SUITE_END()


#include "gtest/gtest.h"

#include <boost/shared_ptr.hpp>

#include "wali/Key.hpp"
#include "wali/Common.hpp"
#include "wali/wpds/Config.hpp"
#include "wali/wpds/Rule.hpp"
#include "wali/witness/WitnessMerge.hpp"
#include "wali/witness/WitnessCombine.hpp"
#include "wali/witness/WitnessExtend.hpp"
#include "wali/witness/WitnessRule.hpp"
#include "wali/witness/WitnessTrans.hpp"
#include "wali/witness/CalculatingVisitor.hpp"

using wali::wpds::Config;
using wali::wpds::Rule;
using wali::wfa::Trans;

namespace wali {
    namespace witness {

        struct NumberComputer : public CalculatingVisitor<int>
        {
            //! Overload to calculate the value of an extend
            //! node. Modifications to the AnswerType& parameters will not
            //! persist.
            virtual int calculateExtend( WitnessExtend * w,
                                         int & leftValue,
                                         int & rightValue )
            {
                (void) w;
                return leftValue * rightValue;
            }

            //! Overload to calculate the value of an combine
            //! node. Modifications to the list parameter will not persist.
            virtual int calculateCombine( WitnessCombine * w,
                                          std::list<int> & childrenValues )
            {
                (void) w;
                int i = 0;
                for(std::list<int>::const_iterator iter = childrenValues.begin();
                    iter != childrenValues.end() ; ++iter)
                {
                    i += *iter;
                }
                return i;
            }

            //! Overload to calculate the value of an merge
            //! node. Modifications to the int& parameters will not
            //! persist.
            virtual int calculateMerge( WitnessMerge * w,
                                        int & callerValue,
                                        int & ruleValue,
                                        int & calleeValue )
            {
                (void) w;
                return callerValue + ruleValue + calleeValue;
            }

            //! Overload to calculate the value of a rule node.
            virtual int calculateRule( WitnessRule * w)
            {
                (void) w;
                std::string s = key2str(w->getRuleStub().from_state());
                std::stringstream ss(s);
                int ret = -1;
                ss >> ret;
                return ret;
            }

            //! Overload to calculate the value of a trans node.
            virtual int calculateTrans( WitnessTrans * w)
            {
                (void) w;
                std::string s = key2str(w->getTrans().from_state());
                std::stringstream ss(s);
                int ret = -1;
                ss >> ret;
                return ret;
            }
        };

        struct StringComputer : public CalculatingVisitor<std::string>
        {
            //! Overload to calculate the value of an extend
            //! node. Modifications to the AnswerType& parameters will not
            //! persist.
            virtual std::string calculateExtend( WitnessExtend * w,
                                                 std::string & leftValue,
                                                 std::string & rightValue )
            {
                (void) w;
                return "(" + leftValue + " * " + rightValue + ")";
            }

            //! Overload to calculate the value of an combine
            //! node. Modifications to the list parameter will not persist.
            virtual std::string calculateCombine( WitnessCombine * w,
                                                  std::list<std::string> & childrenValues )
            {
                (void) w;
                std::string s = "(";
                for(std::list<std::string>::const_iterator iter = childrenValues.begin();
                    iter != childrenValues.end() ; ++iter)
                {
                    if (iter != childrenValues.begin()) {
                        s += " + ";
                    }
                    s += *iter;
                }
                return s + ")";
            }

            //! Overload to calculate the value of an merge
            //! node. Modifications to the std::string& parameters will not
            //! persist.
            virtual std::string calculateMerge( WitnessMerge * w,
                                                std::string & callerValue,
                                                std::string & ruleValue,
                                                std::string & calleeValue )
            {
                (void) w;
                return "merge(" + callerValue + ", " + ruleValue + ", " + calleeValue + ")";
            }

            //! Overload to calculate the value of a rule node.
            virtual std::string calculateRule( WitnessRule * w)
            {
                (void) w;
                return key2str(w->getRuleStub().from_state());
            }

            //! Overload to calculate the value of a trans node.
            virtual std::string calculateTrans( WitnessTrans * w)
            {
                (void) w;
                return key2str(w->getTrans().from_state());
            }
        };

        witness_t make_example_trans(std::string val)
        {
            Key k = getKey("dummy");
            witness_t w = new WitnessTrans(Trans(getKey(val), k, k, NULL));
            return w;
        }

        typedef boost::shared_ptr<Config> config_ptr;
        typedef std::pair<config_ptr, config_ptr> config_ptr_pair;

        witness_t make_example_rule(std::string val, config_ptr_pair * configs)
        {
            Key k = getKey("dummy");
            configs->first = config_ptr(new Config(getKey(val), k));
            configs->second = config_ptr(new Config(k, k));
            Rule rule(configs->first.get(), configs->second.get(), 0, NULL);
            witness_t w = new WitnessRule(rule);
            return w;
        }

        witness_t make_combine(witness_t left, witness_t right)
        {
            WitnessCombine * w = new WitnessCombine(NULL);
            w->addChild(left);
            w->addChild(right);
            return w;
        }

        TEST(wali$witness$CalculatingVisitor, WitnessTrans) {
            witness_t w = make_example_trans("1");

            NumberComputer nc;
            w->accept(nc);
            EXPECT_EQ(1, nc.answer());

            StringComputer sc;
            w->accept(sc);
            EXPECT_EQ("1", sc.answer());
        }

        TEST(wali$witness$CalculatingVisitor, WitnessRule) {
            config_ptr_pair ptrs;
            witness_t w = make_example_rule("1", &ptrs);

            NumberComputer nc;
            w->accept(nc);
            EXPECT_EQ(1, nc.answer());

            StringComputer sc;
            w->accept(sc);
            EXPECT_EQ("1", sc.answer());
        }

        TEST(wali$witness$CalculatingVisitor, WitnessCombine) {
            config_ptr_pair ptrs1, ptrs2;
            witness_t w1 = make_example_rule("2", &ptrs1);
            witness_t w2 = make_example_rule("3", &ptrs2);

            witness_t w = make_combine(w1, w2);

            NumberComputer nc;
            w->accept(nc);
            EXPECT_EQ(5, nc.answer());

            StringComputer sc;
            w->accept(sc);
            EXPECT_EQ("(2 + 3)", sc.answer());
        }

        TEST(wali$witness$CalculatingVisitor, WitnessExtend$2arg) {
            config_ptr_pair ptrs1, ptrs2;
            witness_t w1 = make_example_rule("2", &ptrs1);
            witness_t w2 = make_example_rule("3", &ptrs2);

            witness_t w = new WitnessExtend(NULL, w1, w2);

            NumberComputer nc;
            w->accept(nc);
            EXPECT_EQ(6, nc.answer());

            StringComputer sc;
            w->accept(sc);
            EXPECT_EQ("(2 * 3)", sc.answer());
        }

        TEST(wali$witness$CalculatingVisitor, WitnessExtend$1arg$impossible) {
            config_ptr_pair ptrs;
            witness_t w1 = make_example_rule("1", &ptrs);

#if defined(_MSC_VER)
	    char const * death_message_left = "Assertion failed: the_left != NULL";
	    char const * death_message_right = "Assertion failed: the_right != NULL";
#else
	    char const * death_message_left = "Assertion `the_left != .?__null.?\' failed";
	    char const * death_message_right = "Assertion `the_right != .?__null.?\' failed";
#endif

            EXPECT_DEATH({
                    WitnessExtend e(NULL, NULL, w1);
                },
		death_message_left);
            EXPECT_DEATH({
                    WitnessExtend e(NULL, w1, NULL);
                },
                death_message_right);
            EXPECT_DEATH({
                    WitnessExtend e(NULL, NULL, NULL);
                },
                death_message_left);
        }

        TEST(wali$witness$CalculatingVisitor, largeExamples$Richs) {
            config_ptr_pair ptrs1, ptrs2, ptrs3, ptrs4, ptrs5, ptrs6, ptrs7, ptrs8, ptrs9, ptrs10;

            witness_t stem =
                new WitnessExtend(NULL,
                                  new WitnessExtend(NULL,
                                                    make_example_trans("1 root"),
                                                    make_example_rule("2->3", &ptrs1)),
                                  make_example_rule("3->6", &ptrs8));

            witness_t loop_body =
                new WitnessExtend(NULL,
                                  new WitnessExtend(NULL,
                                                    new WitnessExtend(NULL,
                                                                      new WitnessExtend(NULL,
                                                                                stem,
                                                                                make_example_rule("6->7", &ptrs9)),
                                                                      make_example_rule("7->11", &ptrs2)),
                                                    make_example_rule("11->13", &ptrs3)),
                                  make_example_rule("13->6", &ptrs4));

            witness_t loop_head = make_combine(loop_body, stem);

            witness_t tree =
                new WitnessExtend(NULL,
                                  new WitnessExtend(NULL,
                                                    new WitnessExtend(NULL,
                                                                      new WitnessExtend(NULL,
                                                                                loop_head,
                                                                                make_example_rule("6->7", &ptrs10)),
                                                                      make_example_rule("7->11", &ptrs5)),
                                                    make_example_rule("11->13", &ptrs6)),
                                  make_example_rule("13->15", &ptrs7));

            NumberComputer nc;
            tree->accept(nc);
            EXPECT_EQ(216468252, nc.answer());

            std::string str_stem = "((1 root * 2->3) * 3->6)";
            std::string str_body = "((((" + str_stem + " * 6->7) * 7->11) * 11->13) * 13->6)";
            std::string str_loop = "(" + str_body + " + " + str_stem + ")";
            std::string str_tree = "((((" + str_loop + " * 6->7) * 7->11) * 11->13) * 13->15)";

            StringComputer sc;
            tree->accept(sc);
            EXPECT_EQ(str_tree, sc.answer());
        }

    }
}


/*
    Copyright 2005-2007 Adobe Systems Incorporated

    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).

    See http://opensource.adobe.com/gil for most recent version including documentation.
*/
// channel.cpp : Tests channel
//

#include <cstdint>
#include <exception>
#include <iostream>
#include <boost/gil/gil_config.hpp>
#include <boost/gil/gil_concept.hpp>
#include <boost/gil/channel.hpp>
#include <boost/gil/channel_algorithm.hpp>
#include <boost/gil/typedefs.hpp>

#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(push)
#pragma warning(disable:4512) //assignment operator could not be generated
#endif

using namespace boost::gil;
using namespace std;

void error_if(bool);

auto c8_min   = channel_traits<uint8_t>::min_value();
auto c8_max   = channel_traits<uint8_t>::max_value();
auto c8s_min  = channel_traits<int8_t>::min_value();
auto c8s_max  = channel_traits<int8_t>::max_value();
auto c16_min  = channel_traits<uint16_t>::min_value();
auto c16_max  = channel_traits<uint16_t>::max_value();
auto c16s_min = channel_traits<int16_t>::min_value();
auto c16s_max = channel_traits<int16_t>::max_value();
auto c32_min  = channel_traits<uint32_t>::min_value();
auto c32_max  = channel_traits<uint32_t>::max_value();
auto c32s_min = channel_traits<int32_t>::min_value();
auto c32s_max = channel_traits<int32_t>::max_value();
auto c32f_min = channel_traits<float32_t>::min_value();
auto c32f_max = channel_traits<float32_t>::max_value();

template <typename ChannelTestCore>
struct do_test : public ChannelTestCore {
    typedef typename ChannelTestCore::channel_t channel_t;
    typedef typename channel_traits<channel_t>::value_type channel_value_t;

    do_test() : ChannelTestCore() {
        error_if(this->_min_v != channel_traits<channel_t>::min_value());
        error_if(this->_max_v != channel_traits<channel_t>::max_value());
    }

    void test_all() {
        test_channel_invert();
        test_channel_convert();
        test_channel_multiply();
        test_channel_math();
    }

    void test_mutable(boost::mpl::false_) {}
    void test_mutable(boost::mpl::true_) {
        channel_value_t mv=this->_min_v;
        ++this->_min_v; this->_min_v++;
        --this->_min_v; this->_min_v--;
        error_if(mv!=this->_min_v);

        this->_min_v+=1;
        this->_min_v-=1;
        error_if(mv!=this->_min_v);

        this->_min_v*=1;
        this->_min_v/=1;
        error_if(mv!=this->_min_v);

         this->_min_v = 1;    // assignable to scalar
         this->_min_v = mv;   // and to value type

         // test swap
         channel_value_t v1=this->_min_v;
         channel_value_t v2=this->_max_v;
         swap(this->_min_v, this->_max_v);

         channel_value_t v3=this->_min_v;
         channel_value_t v4=this->_max_v;
         error_if(v1!=v4 || v2!=v3);
    }

    void test_channel_math() {
        error_if(this->_min_v >= this->_max_v);
        error_if(this->_max_v <= this->_min_v);
        error_if(this->_min_v > this->_max_v);
        error_if(this->_max_v < this->_min_v);
        error_if(this->_max_v == this->_min_v);
        error_if(!(this->_max_v != this->_min_v));

        error_if(this->_min_v * 1 != this->_min_v);
        error_if(this->_min_v / 1 != this->_min_v);

        error_if((this->_min_v + 1) + 1 != (this->_min_v + 2));
        error_if((this->_max_v - 1) - 1 != (this->_max_v - 2));

        error_if(this->_min_v != 1 && this->_min_v==1);  // comparable to integral

        test_mutable(boost::mpl::bool_<channel_traits<channel_t>::is_mutable>());
    }

    void test_channel_invert() {
        error_if(channel_invert(this->_min_v) != this->_max_v);
        error_if(channel_invert(this->_max_v) != this->_min_v);
    }

    void test_channel_multiply() {
        error_if(channel_multiply(this->_min_v, this->_min_v) != this->_min_v);
        error_if(channel_multiply(this->_max_v, this->_max_v) != this->_max_v);
        error_if(channel_multiply(this->_max_v, this->_min_v) != this->_min_v);
    }

    void test_channel_convert() {
        channel_value_t  v_min, v_max;

        v_min=channel_convert<channel_t>(c8_min);
        v_max=channel_convert<channel_t>(c8_max);
        error_if(v_min!=this->_min_v || v_max!=this->_max_v);

        v_min=channel_convert<channel_t>(c8s_min);
        v_max=channel_convert<channel_t>(c8s_max);
        error_if(v_min!=this->_min_v || v_max!=this->_max_v);

        v_min=channel_convert<channel_t>(c16_min);
        v_max=channel_convert<channel_t>(c16_max);
        error_if(v_min!=this->_min_v || v_max!=this->_max_v);

        v_min=channel_convert<channel_t>(c16s_min);
        v_max=channel_convert<channel_t>(c16s_max);
        error_if(v_min!=this->_min_v || v_max!=this->_max_v);

        v_min=channel_convert<channel_t>(c32_min);
        v_max=channel_convert<channel_t>(c32_max);
        error_if(v_min!=this->_min_v || v_max!=this->_max_v);

        v_min=channel_convert<channel_t>(c32s_min);
        v_max=channel_convert<channel_t>(c32s_max);
        error_if(v_min!=this->_min_v || v_max!=this->_max_v);

        v_min=channel_convert<channel_t>(c32f_min);
        v_max=channel_convert<channel_t>(c32f_max);
        error_if(v_min!=this->_min_v || v_max!=this->_max_v);
    }
};

// Different core classes depending on the different types of channels - channel values, references and subbyte references
// The cores ensure there are two members, _min_v and _max_v initialized with the minimum and maximum channel value.
// The different channel types have different ways to initialize them, thus require different cores

// For channel values simply initialize the value directly
template <typename ChannelValue>
class value_core {
protected:
    typedef ChannelValue channel_t;
    channel_t _min_v, _max_v;

    value_core() : _min_v(channel_traits<ChannelValue>::min_value()), _max_v(channel_traits<ChannelValue>::max_value()) {
        boost::function_requires<ChannelValueConcept<ChannelValue> >();
    }
};

// For channel references we need to have separate channel values
template <typename ChannelRef>
class reference_core : public value_core<typename channel_traits<ChannelRef>::value_type> {
    typedef value_core<typename channel_traits<ChannelRef>::value_type> parent_t;
protected:
    typedef ChannelRef channel_t;
    channel_t _min_v, _max_v;

    reference_core() : parent_t(), _min_v(parent_t::_min_v), _max_v(parent_t::_max_v) {
        boost::function_requires<ChannelConcept<ChannelRef> >();
    }
};

// For subbyte channel references we need to store the bit buffers somewhere
template <typename ChannelSubbyteRef, typename ChannelMutableRef = ChannelSubbyteRef>
class packed_reference_core {
protected:
    typedef ChannelSubbyteRef channel_t;
    typedef typename channel_t::integer_t integer_t;
    channel_t _min_v, _max_v;

    integer_t _min_buf, _max_buf;

    packed_reference_core() : _min_v(&_min_buf), _max_v(&_max_buf) {
        ChannelMutableRef b1(&_min_buf), b2(&_max_buf);
        b1 = channel_traits<channel_t>::min_value();
        b2 = channel_traits<channel_t>::max_value();

        boost::function_requires<ChannelConcept<ChannelSubbyteRef> >();
    }
};

template <typename ChannelSubbyteRef, typename ChannelMutableRef = ChannelSubbyteRef>
class packed_dynamic_reference_core {
protected:
    typedef ChannelSubbyteRef channel_t;
    channel_t _min_v, _max_v;

    typename channel_t::integer_t _min_buf, _max_buf;

    packed_dynamic_reference_core(int first_bit1=1, int first_bit2=2) : _min_v(&_min_buf,first_bit1), _max_v(&_max_buf,first_bit2) {
        ChannelMutableRef b1(&_min_buf,1), b2(&_max_buf,2);
        b1 = channel_traits<channel_t>::min_value();
        b2 = channel_traits<channel_t>::max_value();

        boost::function_requires<ChannelConcept<ChannelSubbyteRef> >();
    }
};

template <typename ChannelValue>
void test_channel_value() {
    do_test<value_core<ChannelValue> >().test_all();
}

template <typename ChannelRef>
void test_channel_reference() {
    do_test<reference_core<ChannelRef> >().test_all();
}

template <typename ChannelSubbyteRef>
void test_packed_channel_reference() {
    do_test<packed_reference_core<ChannelSubbyteRef,ChannelSubbyteRef> >().test_all();
}

template <typename ChannelSubbyteRef, typename MutableRef>
void test_const_packed_channel_reference() {
    do_test<packed_reference_core<ChannelSubbyteRef,MutableRef> >().test_all();
}

template <typename ChannelSubbyteRef>
void test_packed_dynamic_channel_reference() {
    do_test<packed_dynamic_reference_core<ChannelSubbyteRef,ChannelSubbyteRef> >().test_all();
}

template <typename ChannelSubbyteRef, typename MutableRef>
void test_const_packed_dynamic_channel_reference() {
    do_test<packed_dynamic_reference_core<ChannelSubbyteRef,MutableRef> >().test_all();
}

template <typename ChannelValue>
void test_channel_value_impl() {
    test_channel_value<ChannelValue>();
    test_channel_reference<ChannelValue&>();
    test_channel_reference<const ChannelValue&>();
}

/////////////////////////////////////////////////////////
///
/// A channel archetype - to test the minimum requirements of the concept
///
/////////////////////////////////////////////////////////

struct channel_value_archetype;
struct channel_archetype {
    // equality comparable
    friend bool operator==(const channel_archetype&,const channel_archetype&) { return true; }
    friend bool operator!=(const channel_archetype&,const channel_archetype&) { return false; }
    // less-than comparable
    friend bool operator<(const channel_archetype&,const channel_archetype&) { return false; }
    // convertible to a scalar
    operator std::uint8_t() const { return 0; }

    channel_archetype& operator++() { return *this; }
    channel_archetype& operator--() { return *this; }
    channel_archetype  operator++(int) { return *this; }
    channel_archetype  operator--(int) { return *this; }

    template <typename Scalar> channel_archetype operator+=(Scalar) { return *this; }
    template <typename Scalar> channel_archetype operator-=(Scalar) { return *this; }
    template <typename Scalar> channel_archetype operator*=(Scalar) { return *this; }
    template <typename Scalar> channel_archetype operator/=(Scalar) { return *this; }

    typedef channel_value_archetype         value_type;
    typedef channel_archetype               reference;
    typedef const channel_archetype         const_reference;
    typedef channel_value_archetype*        pointer;
    typedef const channel_value_archetype*  const_pointer;
    BOOST_STATIC_CONSTANT(bool, is_mutable=true);

    static value_type min_value();
    static value_type max_value();
};

struct channel_value_archetype : public channel_archetype {
    channel_value_archetype() {}                                        // default constructible
    channel_value_archetype(const channel_value_archetype&) {}          // copy constructible
    channel_value_archetype& operator=(const channel_value_archetype&){return *this;} // assignable
    channel_value_archetype(std::uint8_t) {}
};

channel_value_archetype channel_archetype::min_value() { return channel_value_archetype(); }
channel_value_archetype channel_archetype::max_value() { return channel_value_archetype(); }

void test_packed_channel_reference() {
    typedef packed_channel_reference<std::uint16_t, 0,5,true> channel16_0_5_reference_t;
    typedef packed_channel_reference<std::uint16_t, 5,6,true> channel16_5_6_reference_t;
    typedef packed_channel_reference<std::uint16_t, 11,5,true> channel16_11_5_reference_t;

    std::uint16_t data=0;
    channel16_0_5_reference_t   channel1(&data);
    channel16_5_6_reference_t   channel2(&data);
    channel16_11_5_reference_t  channel3(&data);

    channel1=channel_traits<channel16_0_5_reference_t>::max_value();
    channel2=channel_traits<channel16_5_6_reference_t>::max_value();
    channel3=channel_traits<channel16_11_5_reference_t>::max_value();
    error_if(data!=65535);

    test_packed_channel_reference<channel16_0_5_reference_t>();
    test_packed_channel_reference<channel16_5_6_reference_t>();
    test_packed_channel_reference<channel16_11_5_reference_t>();
}

void test_packed_dynamic_channel_reference() {
    typedef packed_dynamic_channel_reference<std::uint16_t,5,true> channel16_5_reference_t;
    typedef packed_dynamic_channel_reference<std::uint16_t,6,true> channel16_6_reference_t;

    std::uint16_t data=0;
    channel16_5_reference_t  channel1(&data,0);
    channel16_6_reference_t  channel2(&data,5);
    channel16_5_reference_t  channel3(&data,11);

    channel1=channel_traits<channel16_5_reference_t>::max_value();
    channel2=channel_traits<channel16_6_reference_t>::max_value();
    channel3=channel_traits<channel16_5_reference_t>::max_value();
    error_if(data!=65535);

    test_packed_dynamic_channel_reference<channel16_5_reference_t>();
}

void test_channel() {
    test_channel_value_impl<uint8_t>();
    test_channel_value_impl<int8_t>();
    test_channel_value_impl<uint16_t>();
    test_channel_value_impl<int16_t>();
    test_channel_value_impl<uint32_t>();
    test_channel_value_impl<int16_t>();

    test_channel_value_impl<float32_t>();

    test_packed_channel_reference();
    test_packed_dynamic_channel_reference();

    // Do only compile-time tests for the archetype (because asserts like val1<val2 fail)
    boost::function_requires<MutableChannelConcept<channel_archetype> >();

    do_test<value_core<channel_value_archetype> >();
    do_test<reference_core<channel_archetype> >();
    do_test<reference_core<const channel_archetype&> >();
}

int main()
{
    try
    {
        test_channel();

        return EXIT_SUCCESS;
    }
    catch (std::exception const& e)
    {
        std::cerr << e.what() << std::endl;
        return EXIT_FAILURE;
    }
    catch (...)
    {
        return EXIT_FAILURE;
    }
}

// TODO:
// - provide algorithm performance overloads for scoped channel and packed channels
// - Update concepts and documentation
// - What to do about pointer types?!
// - Performance!!
//      - is channel_convert the same as native?
//      - is operator++ on float32_t the same as native? How about if operator++ is defined in scoped_channel to do _value++?


/**************************************************************************
 * Copyright (c) 2017-2019 by the mfmg authors                            *
 * All rights reserved.                                                   *
 *                                                                        *
 * This file is part of the mfmg library. mfmg is distributed under a BSD *
 * 3-clause license. For the licensing terms see the LICENSE file in the  *
 * top-level directory                                                    *
 *                                                                        *
 * SPDX-License-Identifier: BSD-3-Clause                                  *
 **************************************************************************/

#define BOOST_TEST_MODULE lanczos

#include <mfmg/common/lanczos.templates.hpp>

#include <boost/test/data/test_case.hpp>

#include <cmath>
#include <cstdio>

#include "lanczos_simpleop.templates.hpp"
#include "main.cc"

namespace bdata = boost::unit_test::data;
namespace tt = boost::test_tools;

BOOST_DATA_TEST_CASE(lanczos,
                     bdata::make({1, 2}) * bdata::make({false, true}) *
                         bdata::make({1, 2, 3, 5, 10, 20, 40}),
                     multiplicity, is_deflated, n_distinct_eigenvalues)
{
  using namespace mfmg;

  using VectorType = dealii::Vector<double>;
  using OperatorType = SimpleOperator<VectorType>;

  int const n = 1000;
  int const n_eigenvectors = n_distinct_eigenvalues * multiplicity;

  OperatorType op(n, multiplicity);

  boost::property_tree::ptree lanczos_params;
  lanczos_params.put("is_deflated", is_deflated);
  lanczos_params.put("num_eigenpairs", n_eigenvectors);
  if (is_deflated)
  {
    lanczos_params.put("num_cycles", multiplicity);
    lanczos_params.put("num_eigenpairs_per_cycle", n_distinct_eigenvalues);
  }
  else
  {
    if (multiplicity > 1)
    {
      // Skip test when using regular Lanczos for multiplicities larger than 1
      return;
    }
  }

  lanczos_params.put("max_iterations", 2000);
  lanczos_params.put("tolerance", 1e-2);
  lanczos_params.put("percent_overshoot", 5);

  Lanczos<OperatorType, VectorType> solver(op);

  VectorType initial_guess(n);
  initial_guess = 1.;

  // Add random noise to the guess
  std::mt19937 gen(0);
  std::uniform_real_distribution<double> dist(0, 1);
  std::transform(initial_guess.begin(), initial_guess.end(),
                 initial_guess.begin(), [&](auto &v) { return v + dist(gen); });

  std::vector<double> computed_evals;
  std::vector<VectorType> computed_evecs;
  std::tie(computed_evals, computed_evecs) =
      solver.solve(lanczos_params, initial_guess);

  auto ref_evals = op.get_evals();

  BOOST_TEST(computed_evals.size() == n_eigenvectors);

  // Loop to ensure each Ritz value is near an eigenvalue.
  double const tolerance =
      lanczos_params.get<double>("tolerance"); // this may need adjustment

  std::sort(ref_evals.begin(), ref_evals.end());
  std::sort(computed_evals.begin(), computed_evals.end());

  for (int i = 0; i < n_eigenvectors; i++)
    BOOST_TEST(computed_evals[i] == ref_evals[i], tt::tolerance(tolerance));

  // Testing eigenvectors is tricky. Specifically, when multiplicity > 1, one
  // gets a subspace of possible solutions. One way to test that is to
  //   a) test that each eigenvector is indeed an eigenvector corresponding to
  //   the eigenvalue
  //   b) test that the eigenvectors corresponding to the same eigenvalue are
  //   orthogonal
  // In addition, from the numerical perspective, one should also care about
  // scaling/normalization things. It is also unclear what tolerance should be
  // used here.  For now, we are just happy to have something here.
  for (int i = 0; i < n_eigenvectors; i++)
  {
    VectorType result(n);
    op.vmult(result, computed_evecs[i]);
    result.add(-computed_evals[i], computed_evecs[i]);
    BOOST_TEST(result.l2_norm() < tolerance);
  }
}


#include <vector>
#include <iostream>
#include <type_traits>
#include <boost/range/counting_range.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/utility/result_of.hpp>
#include "cartesian.h"
#include "adaptors.h"

int main() {

	std::vector<int> xx = { 1, 2, 3 };
	std::vector<char> yy = { 'a', 'b', 'c' };
	std::vector<double> zz = { 0.1, 0.2, 0.3 };
/*
	auto r = cartesian(xx, yy, zz)
	       | filtered([](std::tuple<int&, char&, double&> x) { return std::get<0>(x) > 1 && std::get<1>(x) < 'c'; })
	       | transformed([](std::tuple<int&, char&, double&> x) { return std::get<0>(x) + int(std::get<1>(x)) + std::get<2>(x); });

*/
	auto r = cartesian(xx, yy, zz)
	       | xfiltered([](int x, char y, double z) { return x > 1 && y < 'c'; })
	       | xtransformed([](int x, char y, double z) { return x + int(y) + z; });

	for( auto x : r )
		std::cout << x << std::endl;

	return 0;
}


//  Copyright (c) 2011-2013 Thomas Heller
//
//  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/hpx_init.hpp>

#include <boost/program_options.hpp>
#include <boost/assign.hpp>

#include <iostream>

using boost::program_options::variables_map;
using boost::program_options::options_description;
using boost::program_options::value;
using boost::program_options::store;
using boost::program_options::parse_command_line;

#include "jacobi.hpp"

namespace jacobi_smp {

    void jacobi_kernel(
        double * dst
      , const double * src
      , std::size_t n
    )
    {
#ifdef HPX_INTEL_VERSION
#pragma vector always
#pragma unroll(4)
#endif
        for(std::size_t x = 1; x < n-1; ++x) {
            dst[x] = (src[x-n] + src[x+n] + src[x] + src[x-1] + src[x+1]) * 0.2;
        }
    }
}

int hpx_main(variables_map &vm)
{
    {
        std::size_t n           = vm["n"].as<std::size_t>();
        std::size_t iterations  = vm["iterations"].as<std::size_t>();
        std::size_t block_size  = vm["block-size"].as<std::size_t>();

        std::string output_filename;
        if(vm.count("output-filename"))
        {
            output_filename = vm["output-filename"].as<std::string>();
        }

        if(n > block_size) {
            jacobi_smp::jacobi(n, iterations, block_size, output_filename);
        } else {
            jacobi_smp::jacobi_serial(n, iterations, output_filename);
        }
    }

    return hpx::finalize();
}

int main(int argc, char **argv)
{
    options_description
        desc_cmd("usage: " HPX_APPLICATION_STRING " [options]");

    desc_cmd.add_options()
    (
        "n", value<std::size_t>()->default_value(16)
      , "Will run on grid with dimensions (n x n)"
    )
    (
        "iterations", value<std::size_t>()->default_value(1000)
      , "Number of iterations"
    )
    (
        "block-size", value<std::size_t>()->default_value(256)
      , "Block size of the different chunks to calculate in parallel"
    )
    (
        "output-filename", value<std::string>()
      , "Filename of the result (if empty no result is written)"
    );
    using namespace boost::assign;
    std::vector<std::string> cfg;
    cfg += "hpx.os_threads=" +
        boost::lexical_cast<std::string>(hpx::threads::hardware_concurrency());

    return hpx::init(desc_cmd, argc, argv, cfg);
}


// Boost.Geometry

// Copyright (c) 2016-2017 Oracle and/or its affiliates.

// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// 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)

#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/geometries/adapted/c_array.hpp>
#include <boost/geometry/geometries/adapted/boost_tuple.hpp>
#include <test_common/test_point.hpp>

#include <boost/geometry/formulas/andoyer_inverse.hpp>
#include <boost/geometry/formulas/thomas_inverse.hpp>
#include <boost/geometry/formulas/vincenty_inverse.hpp>

#include <boost/geometry/strategies/strategies.hpp>

#include <boost/geometry/algorithms/disjoint.hpp>

#include <geometry_test_common.hpp>

#include "test_disjoint_seg_box.hpp"

namespace bg = boost::geometry;

//Tests for disjoint(point, box), disjoint(box, box) and disjoint(segment, box)

template <typename P>
void disjoint_tests_1()
{
    test_disjoint<bg::model::box<P>, P>("BOX(1 1,3 3)", "POINT(4 4)", true);
    test_disjoint<bg::model::box<P>, P>("BOX(1 1,3 3)", "POINT(2 2)", false);
    test_disjoint<bg::model::box<P>, P>("BOX(1 1,3 3)", "POINT(3 3)", false);
    test_disjoint<bg::model::box<P>, P>("BOX(1 1,3 3)", "POINT(2 3)", false);

    test_disjoint<bg::model::box<P>, bg::model::box<P> >("BOX(1 1,3 3)",
                                                         "BOX(1 4,5 5)",
                                                         true);
    test_disjoint<bg::model::box<P>, bg::model::box<P> >("BOX(1 1,3 3)",
                                                         "BOX(2 2,4 4)",
                                                         false);
    test_disjoint<bg::model::box<P>, bg::model::box<P> >("BOX(1 1,3 3)",
                                                         "BOX(3 3,4 4)",
                                                         false);
    test_disjoint<bg::model::box<P>, bg::model::box<P> >("BOX(1 1,3 3)",
                                                         "BOX(2 3,4 4)",
                                                         false);

    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(1 1,3 3)",
                                                             "SEGMENT(1 4, 5 5)",
                                                             true);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(1 1,3 3)",
                                                             "SEGMENT(3 3, 5 5)",
                                                             false);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(1 1,3 3)",
                                                             "SEGMENT(1 1, 4 1)",
                                                             false);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(1 1,3 3)",
                                                             "SEGMENT(1 2, 5 5)",
                                                             false);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(1 1,3 3)",
                                                             "SEGMENT(1 2, 3 2)",
                                                             false);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(1 1,3 3)",
                                                             "SEGMENT(0 0, 4 0)",
                                                             true);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(1 1,3 3)",
                                                             "SEGMENT(2 2, 4 4)",
                                                             false);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(1 1,3 3)",
                                                             "SEGMENT(4 4, 2 2)",
                                                             false);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(1 1,3 3)",
                                                             "SEGMENT(1.5 1.5, 2 2)",
                                                             false);
}

template <typename P>
void disjoint_tests_2(bool expected_result)
{
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(1 1,3 3)",
                                                             "SEGMENT(1 0.999, 10 0.999)",
                                                             expected_result);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(1 1,3 3)",
                                                             "SEGMENT(10 0.999, 1 0.999)",
                                                             expected_result);
}

template <typename P>
void disjoint_tests_3(bool expected_result)
{
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(3 4.42, 100 5)",
                                                             "SEGMENT(2 2.9, 100 2.9)",
                                                             expected_result);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(3 4.42, 100 5)",
                                                             "SEGMENT(100 2.9, 2 2.9)",
                                                             expected_result);
}

template <typename P>
void disjoint_tests_4(bool expected_result)
{
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(1 1,3 3)",
                                                             "SEGMENT(0 0.99999999, 2 0.99999999)",
                                                             expected_result);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(1 1,3 3)",
                                                             "SEGMENT(2 0.99999999, 0 0.99999999)",
                                                             expected_result);
}

template <typename P, typename CT>
void disjoint_tests_with_strategy(bool expected_result)
{
    bg::strategy::disjoint::segment_box_geographic
    <
        bg::strategy::andoyer,
        bg::srs::spheroid<CT>,
        CT
    > geographic_andoyer;

    bg::strategy::disjoint::segment_box_geographic
    <
        bg::strategy::thomas,
        bg::srs::spheroid<CT>,
        CT
    > geographic_thomas;

    bg::strategy::disjoint::segment_box_geographic
    <
        bg::strategy::vincenty,
        bg::srs::spheroid<CT>,
        CT
    > geographic_vincenty;

    test_disjoint_strategy<bg::model::box<P>, bg::model::segment<P> >
            ("BOX(1 1,3 3)", "SEGMENT(1 0.999, 10 0.999)",
             expected_result, geographic_andoyer);
    test_disjoint_strategy<bg::model::box<P>, bg::model::segment<P> >
            ("BOX(1 1,3 3)", "SEGMENT(1 0.999, 10 0.999)",
             expected_result, geographic_thomas);
    test_disjoint_strategy<bg::model::box<P>, bg::model::segment<P> >
            ("BOX(1 1,3 3)", "SEGMENT(1 0.999, 10 0.999)",
             expected_result, geographic_vincenty);
}

template <typename P>
void disjoint_tests_sph_geo()
{
    //Case A: box intersects without containing the vertex
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(0 6, 120 7)",
                                                             "SEGMENT(0 5, 120 5)",
                                                             false);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(0 -6, 120 -7)",
                                                             "SEGMENT(0 -5, 120 -5)",
                                                             false);

    //Case B: box intersects and contains the vertex
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(0 9, 120 10)",
                                                             "SEGMENT(0 5, 120 5)",
                                                             false);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(0 -10, 120 -9)",
                                                             "SEGMENT(0 -5, 120 -5)",
                                                             false);

    //Case C: bounding boxes disjoint
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(0 10, 10 20)",
                                                             "SEGMENT(0 5, 120 5)",
                                                             true);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(0 -20, 10 -10)",
                                                             "SEGMENT(0 -5, 120 -5)",
                                                             true);

    //Case D: bounding boxes intersect but box segment are disjoint
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(0 9, 0.1 20)",
                                                             "SEGMENT(0 5, 120 5)",
                                                             true);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(0 -20, 0.1 -9)",
                                                             "SEGMENT(0 -5, 120 -5)",
                                                             true);

    //Case E: geodesic intersects box but box segment are disjoint
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(121 0, 122 10)",
                                                             "SEGMENT(0 5, 120 5)",
                                                             true);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(121 -10, 122 0)",
                                                             "SEGMENT(0 -5, 120 -5)",
                                                             true);

    //Case F: segment crosses box
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(100 0, 110 20)",
                                                             "SEGMENT(0 5, 120 5)",
                                                             false);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(100 -20, 110 0)",
                                                             "SEGMENT(0 -5, 120 -5)",
                                                             false);

    //Case G: box contains one segment endpoint
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(110 0, 130 10)",
                                                             "SEGMENT(0 5, 120 5)",
                                                             false);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(110 -10, 130 0)",
                                                             "SEGMENT(0 -5, 120 -5)",
                                                             false);

    //Case H: box below segment
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(50 0, 70 6)",
                                                             "SEGMENT(0 5, 120 5)",
                                                             true);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(50 -6, 70 0)",
                                                             "SEGMENT(0 -5, 120 -5)",
                                                             true);

    //Case I: box contains segment
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(-10 0, 130 10)",
                                                             "SEGMENT(0 5, 120 5)",
                                                             false);
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(-10 -10, 130 0)",
                                                             "SEGMENT(0 -5, 120 -5)",
                                                             false);

    //ascending segment
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(0 10, 120 10.1)",
                                                             "SEGMENT(0 5, 120 5.1)",
                                                             false);

    //descending segment
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(0 9.8, 120 10)",
                                                             "SEGMENT(0 5, 120 4.9)",
                                                             false);

    //ascending segment both hemispheres
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(100 5, 120 6)",
                                                             "SEGMENT(0 -1, 120 4.9)",
                                                             false);

    //descending segment both hemispheres
    test_disjoint<bg::model::box<P>, bg::model::segment<P> >("BOX(0 5, 20 6)",
                                                             "SEGMENT(0 4.9, 120 -1)",
                                                             false);
}

template <typename CT>
void test_all()
{
    typedef bg::model::d2::point_xy<CT> point;
    typedef bg::model::point<CT, 2,
            bg::cs::spherical_equatorial<bg::degree> > sph_point;
    typedef bg::model::point<CT, 2,
            bg::cs::geographic<bg::degree> > geo_point;

    disjoint_tests_1<point>();
    disjoint_tests_1<sph_point>();
    disjoint_tests_1<geo_point>();

    disjoint_tests_2<point>(true);
    disjoint_tests_2<sph_point>(false);
    disjoint_tests_2<geo_point>(false);

    //illustrate difference between spherical and geographic computation on same data
    disjoint_tests_3<point>(true);
    disjoint_tests_3<sph_point>(true);
    disjoint_tests_3<geo_point>(false);

    disjoint_tests_4<sph_point>(false);
    disjoint_tests_4<geo_point>(false);

    disjoint_tests_with_strategy<geo_point, CT>(false);

    disjoint_tests_sph_geo<sph_point>();
    disjoint_tests_sph_geo<geo_point>();
}

int test_main( int , char* [] )
{
    test_all<float>();
    test_all<double>();

#ifdef HAVE_TTMATH
    common_tests<bg::model::d2::point_xy<ttmath_big> >();
    common_tests<bg::model::point<ttmath_big, 3, bg::cs::cartesian> >();
#endif

    return 0;
}


//==================================================================================================
/*
  Copyright 2017 NumScale SAS

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
//==================================================================================================
//! [aligned_range_t]
#include <boost/simd/range/aligned_range.hpp>
#include <boost/simd/memory/allocator.hpp>
#include <boost/simd/literal.hpp>
#include <iostream>
#include <vector>

int main()
{
  using namespace boost::simd::literal;

  std::vector<float, boost::simd::allocator<float>> data{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};

  boost::simd::aligned_range_t<float*,8> r = boost::simd::aligned_range(&data[0], &data[0]+16, 8_c);

  std::cout << *r.begin() << "\n";
  std::cout << *(r.begin()+1) << "\n";

  return 0;
}
//! [aligned_range_t]