// --------------------------------------------------------------------------
//                   OpenMS -- Open-Source Mass Spectrometry
// --------------------------------------------------------------------------
// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen,
// ETH Zurich, and Freie Universitaet Berlin 2002-2015.
//
// This software is released under a three-clause BSD license:
//  * Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//  * Neither the name of any author or any participating institution
//    may be used to endorse or promote products derived from this software
//    without specific prior written permission.
// For a full list of authors, refer to the file AUTHORS.
// --------------------------------------------------------------------------
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// --------------------------------------------------------------------------
// $Maintainer: Stephan Aiche $
// $Authors: Stephan Aiche $
// --------------------------------------------------------------------------

#include <OpenMS/SIMULATION/EGHFitter1D.h>
#include <OpenMS/TRANSFORMATIONS/FEATUREFINDER/InterpolationModel.h>
#include <OpenMS/MATH/STATISTICS/StatisticFunctions.h>
#include <OpenMS/CONCEPT/Constants.h>
#include <OpenMS/CONCEPT/LogStream.h>
#include <OpenMS/CONCEPT/Factory.h>

#include <boost/math/special_functions/fpclassify.hpp>

#define DEBUG_EGHFITTER

namespace OpenMS
{
  int EGHFitter1D::EGHFitterFunctor::operator()(const Eigen::VectorXd& x, Eigen::VectorXd& fvec)
  {
    Size n = m_data->n;
    RawDataArrayType set = m_data->set;

    CoordinateType H  = x(0);
    CoordinateType tR = x(1);
    CoordinateType sigma_square = x(2);
    CoordinateType tau = x(3);

    CoordinateType t_diff, t_diff2, denominator = 0.0;

    CoordinateType fegh = 0.0;

    // iterate over all points of the signal
    for (Size i = 0; i < n; i++)
    {
      double t = set[i].getPos();

      t_diff = t - tR;
      t_diff2 = t_diff * t_diff; // -> (t - t_R)^2

      denominator = 2 * sigma_square + tau * t_diff; // -> 2\sigma_{g}^{2} + \tau \left(t - t_R\right)

      if (denominator > 0.0)
      {
        fegh = H * exp(-t_diff2 / denominator);
      }
      else
      {
        fegh = 0.0;
      }

      fvec(i) = (fegh - set[i].getIntensity());
    }
    return 0;
  }

  // compute Jacobian matrix for the different parameters
  int EGHFitter1D::EGHFitterFunctor::df(const Eigen::VectorXd& x, Eigen::MatrixXd& J)
  {
    Size n =  m_data->n;
    RawDataArrayType set = m_data->set;

    CoordinateType H  = x(0);
    CoordinateType tR = x(1);
    CoordinateType sigma_square = x(2);
    CoordinateType tau = x(3);

    CoordinateType derivative_H, derivative_tR, derivative_sigma_square, derivative_tau = 0.0;
    CoordinateType t_diff, t_diff2, exp1, denominator = 0.0;

    // iterate over all points of the signal
    for (Size i = 0; i < n; i++)
    {
      CoordinateType t = set[i].getPos();

      t_diff = t - tR;
      t_diff2 = t_diff * t_diff; // -> (t - t_R)^2

      denominator = 2 * sigma_square + tau * t_diff; // -> 2\sigma_{g}^{2} + \tau \left(t - t_R\right)

      if (denominator > 0)
      {
        exp1 = exp(-t_diff2 / denominator);

        // \partial H f_{egh}(t) = \exp\left( \frac{-\left(t-t_R \right)}{2\sigma_{g}^{2} + \tau \left(t - t_R\right)} \right)
        derivative_H = exp1;

        // \partial t_R f_{egh}(t) &=& H \exp \left( \frac{-\left(t-t_R \right)}{2\sigma_{g}^{2} + \tau \left(t - t_R\right)} \right) \left( \frac{\left( 4 \sigma_{g}^{2} + \tau \left(t-t_R \right) \right) \left(t-t_R \right)}{\left( 2\sigma_{g}^{2} + \tau \left(t - t_R\right) \right)^2} \right)
        derivative_tR = H * exp1 * (((4 * sigma_square + tau * t_diff) * t_diff) / (denominator * denominator));

        // \partial \sigma_{g}^{2} f_{egh}(t) &=& H \exp \left( \frac{-\left(t-t_R \right)^2}{2\sigma_{g}^{2} + \tau \left(t - t_R\right)} \right) \left( \frac{ 2 \left(t - t_R\right)^2}{\left( 2\sigma_{g}^{2} + \tau \left(t - t_R\right) \right)^2} \right)
        derivative_sigma_square = H * exp1 * ((2 * t_diff2) / (denominator * denominator));

        // \partial \tau f_{egh}(t) &=& H \exp \left( \frac{-\left(t-t_R \right)^2}{2\sigma_{g}^{2} + \tau \left(t - t_R\right)} \right) \left( \frac{ \left(t - t_R\right)^3}{\left( 2\sigma_{g}^{2} + \tau \left(t - t_R\right) \right)^2} \right)
        derivative_tau = H * exp1 * ((t_diff * t_diff2) / (denominator * denominator));
      }
      else
      {
        derivative_H = 0.0;
        derivative_tR = 0.0;
        derivative_sigma_square = 0.0;
        derivative_tau = 0.0;
      }

      // set the jacobian matrix
      J(i, 0) = derivative_H;
      J(i, 1) = derivative_tR;
      J(i, 2) = derivative_sigma_square;
      J(i, 3) = derivative_tau;
    }
    return 0;
  }

  EGHFitter1D::EGHFitter1D() :
    LevMarqFitter1D()
  {
    setName(getProductName());
    defaults_.setValue("statistics:variance", 1.0, "Variance of the model.", ListUtils::create<String>("advanced"));
    defaultsToParam_();
  }

  EGHFitter1D::EGHFitter1D(const EGHFitter1D& source) :
    LevMarqFitter1D(source)
  {
    setParameters(source.getParameters());
    updateMembers_();
  }

  EGHFitter1D::~EGHFitter1D()
  {
  }

  EGHFitter1D& EGHFitter1D::operator=(const EGHFitter1D& source)
  {
    if (&source == this)
      return *this;

    LevMarqFitter1D::operator=(source);
    setParameters(source.getParameters());
    updateMembers_();

    return *this;
  }

  EGHFitter1D::QualityType EGHFitter1D::fit1d(const RawDataArrayType& set, InterpolationModel*& model)
  {
    // Calculate bounding box
    CoordinateType min_bb = set[0].getPos(), max_bb = set[0].getPos();
    for (Size pos = 1; pos < set.size(); ++pos)
    {
      CoordinateType tmp = set[pos].getPos();
      if (min_bb > tmp)
        min_bb = tmp;
      if (max_bb < tmp)
        max_bb = tmp;
    }

    // Enlarge the bounding box by a few multiples of the standard deviation

    const CoordinateType stdev = sqrt(statistics_.variance()) * tolerance_stdev_box_;
    min_bb -= stdev;
    max_bb += stdev;

    // Set advanced parameters for residual_  und jacobian_ method
    EGHFitter1D::Data d;
    d.n = set.size();
    d.set = set;

    // Compute start parameters
    setInitialParameters_(set);

    Eigen::VectorXd x_init(4);
    x_init(0) = height_;
    x_init(1) = retention_;
    x_init(2) = sigma_square_;
    x_init(3) = tau_;

    EGHFitterFunctor functor(4, &d);
    optimize_(x_init, functor);

    // Set optimized parameters
    height_ = x_init[0];
    retention_ = x_init[1];
    sigma_square_ = x_init[2];
    tau_ = x_init[3];

#ifdef DEBUG_EGHFITTER
    LOG_DEBUG << "Fitter returned \n";
    LOG_DEBUG << "height:       " << height_ << "\n";
    LOG_DEBUG << "retention:    " << retention_ << "\n";
    LOG_DEBUG << "sigma_square: " << sigma_square_ << "\n";
    LOG_DEBUG << "tau:          " << tau_ << std::endl;
#endif

    // build model
    model = static_cast<InterpolationModel*>(Factory<BaseModel<1> >::create("EGHModel"));
    model->setInterpolationStep(interpolation_step_);

    Param tmp;
    tmp.setValue("statistics:variance", statistics_.variance());
    tmp.setValue("statistics:mean", statistics_.mean());

    tmp.setValue("bounding_box:compute", "false"); // disable auto computation of bounding box
    tmp.setValue("bounding_box:min", min_bb);
    tmp.setValue("bounding_box:max", max_bb);

    tmp.setValue("egh:height", height_);
    tmp.setValue("egh:retention", retention_);

    tmp.setValue("egh:guess_parameter", "false"); // disable guessing of parameters from A/B
    tmp.setValue("egh:tau", tau_);
    tmp.setValue("egh:sigma_square", sigma_square_);

    model->setParameters(tmp);

    // calculate pearson correlation
    std::vector<float> real_data;
    real_data.reserve(set.size());
    std::vector<float> model_data;
    model_data.reserve(set.size());

    for (Size i = 0; i < set.size(); ++i)
    {
      real_data.push_back(set[i].getIntensity());
      model_data.push_back(model->getIntensity(DPosition<1>(set[i].getPosition())));
    }

    QualityType correlation = Math::pearsonCorrelationCoefficient(real_data.begin(), real_data.end(), model_data.begin(), model_data.end());
    if (boost::math::isnan(correlation))
      correlation = -1.0;

    return correlation;
  }

  void EGHFitter1D::setInitialParameters_(const RawDataArrayType& set)
  {
    // sum over all intensities
    CoordinateType sum = 0.0;
    for (Size i = 0; i < set.size(); ++i)
      sum += set[i].getIntensity();

    // calculate the median
    //Size median = 0;
    //float count = 0.0;
    Size apex_rt = 0;
    CoordinateType apex = 0.0;
    for (Size i = 0; i < set.size(); ++i)
    {
      //count += set[i].getIntensity();
      //if ( count <= sum / 2 ) median = i;

      if (set[i].getIntensity() > apex)
      {
        apex = set[i].getIntensity();
        apex_rt = i;
      }

    }

    // calculate the height of the peak
    height_ = set[apex_rt].getIntensity();

    // calculate retention time
    retention_ = set[apex_rt].getPos();

    // guess A / B for alpha = 0.5 -> left/right half max distance

    Size i = apex_rt;
    while (i > 0)
    {
      if (set[i].getIntensity() / height_ < 0.5)
        break;
      else
        --i;
    }
    CoordinateType A = retention_ - set[i + 1].getPos();

    i = apex_rt;
    while (i < set.size())
    {
      if (set[i].getIntensity() / height_ < 0.5)
        break;
      else
        ++i;
    }
    CoordinateType B = set[i - 1].getPos() - retention_;

    // compute estimates for tau / sigma_square based on A/B
    CoordinateType log_alpha = log(0.5);

    tau_ = (-1 / log_alpha) * (B - A);
    sigma_square_ = (-1 / (2 * log_alpha)) * (B * A);

#ifdef DEBUG_EGHFITTER
    LOG_DEBUG << "Initial parameters\n";
    LOG_DEBUG << "height:       " << height_ << "\n";
    LOG_DEBUG << "retention:    " << retention_ << "\n";
    LOG_DEBUG << "A:            " << A << "\n";
    LOG_DEBUG << "B:            " << B << "\n";
    LOG_DEBUG << "sigma_square: " << sigma_square_ << "\n";
    LOG_DEBUG << "tau:          " << tau_ << std::endl;
#endif
  }

  void EGHFitter1D::updateMembers_()
  {
    LevMarqFitter1D::updateMembers_();
    statistics_.setVariance(param_.getValue("statistics:variance"));
  }

}


//
//  handlers.hpp
//  Jdlib
//
//  Created by Taha Emara on 12/18/20.
//

#ifndef handlers_hpp
#define handlers_hpp

#include <stdio.h>
#include <dlib/image_processing/frontal_face_detector.h>
#include <dlib/image_processing.h>
#include <dlib/dnn.h>
using namespace dlib;

template <template <int,template<typename>class,int,typename> class block, int N, template<typename>class BN, typename SUBNET>
using residual = add_prev1<block<N,BN,1,tag1<SUBNET>>>;

template <template <int,template<typename>class,int,typename> class block, int N, template<typename>class BN, typename SUBNET>
using residual_down = add_prev2<avg_pool<2,2,2,2,skip1<tag2<block<N,BN,2,tag1<SUBNET>>>>>>;

template <int N, template <typename> class BN, int stride, typename SUBNET>
using block  = BN<con<N,3,3,1,1,relu<BN<con<N,3,3,stride,stride,SUBNET>>>>>;

template <int N, typename SUBNET> using ares      = relu<residual<block,N,affine,SUBNET>>;
template <int N, typename SUBNET> using ares_down = relu<residual_down<block,N,affine,SUBNET>>;

template <typename SUBNET> using alevel0 = ares_down<256,SUBNET>;
template <typename SUBNET> using alevel1 = ares<256,ares<256,ares_down<256,SUBNET>>>;
template <typename SUBNET> using alevel2 = ares<128,ares<128,ares_down<128,SUBNET>>>;
template <typename SUBNET> using alevel3 = ares<64,ares<64,ares<64,ares_down<64,SUBNET>>>>;
template <typename SUBNET> using alevel4 = ares<32,ares<32,ares<32,SUBNET>>>;

typedef  loss_metric<fc_no_bias<128,avg_pool_everything<
   alevel0<
   alevel1<
   alevel2<
   alevel3<
   alevel4<
   max_pool<3,3,2,2,relu<affine<con<32,7,7,2,2,
   input_rgb_image_sized<150>
   >>>>>>>>>>>>  anet_type;

class FaceDetectorHandler{
public:
    static FaceDetectorHandler *getFaceDetectorHandler();
    dlib::frontal_face_detector getFaceDetector();

    FaceDetectorHandler(FaceDetectorHandler const&) = delete;
    void operator=(FaceDetectorHandler const&)  = delete;

private:
    FaceDetectorHandler();
    dlib::frontal_face_detector face_detector;
};

class ShapePredictorHandler{
public:
    static ShapePredictorHandler *getShapePredictorHandler(const std::string & model_path);
    dlib::shape_predictor getShapePredictorModel();

    ShapePredictorHandler(ShapePredictorHandler const&) = delete;
    void operator=(ShapePredictorHandler const&)  = delete;

private:
    ShapePredictorHandler(const std::string & model_path);
    dlib::shape_predictor shape_predictor_model;
    std::string model_path;
};

class FaceEmbeddingHandler{
public:
    static FaceEmbeddingHandler *getFaceEmbeddingHandler(const std::string & model_path);

    anet_type getFaceEmbeddingModel();

    FaceEmbeddingHandler(FaceEmbeddingHandler const&) = delete;
    void operator=(FaceEmbeddingHandler const&)  = delete;

private:
    FaceEmbeddingHandler(const std::string & model_path);
    anet_type face_embedding_model;
    std::string model_path;

};

#endif /* handlers_hpp */


//
// Copyright © 2019 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include "SpaceToDepthEndToEndTestImpl.hpp"
#include "ResolveType.hpp"
#include "EndToEndTestImpl.hpp"

#include <armnn/INetwork.hpp>

#include <armnnUtils/Permute.hpp>
#include <armnnUtils/DataLayoutIndexed.hpp>

#include <backendsCommon/test/DataLayoutUtils.hpp>

#include <test/TestUtils.hpp>

#include <boost/test/unit_test.hpp>

namespace
{

template<typename armnn::DataType DataType>
armnn::INetworkPtr CreateSpaceToDepthNetwork(const armnn::TensorShape& inputShape,
                                             const armnn::TensorShape& outputShape,
                                             const armnn::DataLayout dataLayout,
                                             unsigned int blockSize,
                                             const float qScale = 1.0f,
                                             const int32_t qOffset = 0)
{
    using namespace armnn;

    // Builds up the structure of the network.
    INetworkPtr net(INetwork::Create());

    TensorInfo inputTensorInfo(inputShape, DataType, qScale, qOffset);

    armnnUtils::DataLayoutIndexed dimensionIndices(dataLayout);
    if (inputShape[dimensionIndices.GetHeightIndex()] % blockSize!=0
        || inputShape[dimensionIndices.GetWidthIndex()] % blockSize!=0)
    {
        throw InvalidArgumentException("Input shape must be divisible by block size in all spatial dimensions");
    }

    SpaceToDepthDescriptor spaceToDepthDesc;
    spaceToDepthDesc.m_BlockSize = blockSize;
    spaceToDepthDesc.m_DataLayout = dataLayout;

    IConnectableLayer* SpaceToDepth = net->AddSpaceToDepthLayer(spaceToDepthDesc, "SpaceToDepth");
    IConnectableLayer* input        = net->AddInputLayer(0, "input");
    Connect(input, SpaceToDepth, inputTensorInfo, 0, 0);

    TensorInfo outputTensorInfo(outputShape, DataType, qScale, qOffset);
    IConnectableLayer* output = net->AddOutputLayer(0, "output");
    Connect(SpaceToDepth, output, outputTensorInfo, 0, 0);

    return net;
}

void SpaceToDepthEndToEnd(const std::vector<armnn::BackendId>& backends,
                          const armnn::DataLayout& dataLayout,
                          armnn::TensorInfo& inputTensorInfo,
                          armnn::TensorInfo& outputTensorInfo,
                          std::vector<float>& inputData,
                          std::vector<float>& expectedOutputData,
                          const unsigned int blockSize)
{
    using namespace armnn;

    if (dataLayout == DataLayout::NCHW)
    {
        PermuteTensorNhwcToNchw<float>(inputTensorInfo, inputData);
        PermuteTensorNhwcToNchw<float>(outputTensorInfo, expectedOutputData);
    }

    // Builds up the structure of the network
    INetworkPtr net = CreateSpaceToDepthNetwork<DataType::Float32>(
            inputTensorInfo.GetShape(),
            outputTensorInfo.GetShape(),
            dataLayout,
            blockSize);

    BOOST_TEST_CHECKPOINT("Create a network");

    std::map<int, std::vector<float>> inputTensorData = { { 0, inputData } };
    std::map<int, std::vector<float>> expectedOutputTensorData = { { 0, expectedOutputData } };

    EndToEndLayerTestImpl<DataType::Float32, DataType::Float32>(
            move(net),
            inputTensorData,
            expectedOutputTensorData,
            backends);
}

} // anonymous namespace

void SpaceToDepthNhwcEndToEndTest1(const std::vector<armnn::BackendId>& defaultBackends)
{
    using namespace armnn;

    const unsigned int blockSize = 2;

    TensorShape inputShape{1, 2, 2, 1};
    TensorInfo inputTensorInfo(inputShape, DataType::Float32);

    TensorShape outputShape{1, 1, 1, 4};
    TensorInfo outputTensorInfo(outputShape, DataType::Float32);

    std::vector<float> inputData = std::vector<float>(
    {
        1.0f, 2.0f, 3.0f, 4.0f
    });

    std::vector<float> expectedOutputData = std::vector<float>(
    {
        1.0f, 2.0f, 3.0f, 4.0f
    });

    SpaceToDepthEndToEnd(defaultBackends,
                         DataLayout::NHWC,
                         inputTensorInfo,
                         outputTensorInfo,
                         inputData,
                         expectedOutputData,
                         blockSize);
}

void SpaceToDepthNchwEndToEndTest1(const std::vector<armnn::BackendId>& defaultBackends)
{
    using namespace armnn;

    const unsigned int blockSize = 2;

    TensorShape inputShape{1, 2, 2, 1};
    TensorInfo inputTensorInfo(inputShape, DataType::Float32);

    TensorShape outputShape{1, 1, 1, 4};
    TensorInfo outputTensorInfo(outputShape, DataType::Float32);

    std::vector<float> inputData = std::vector<float>(
    {
        1.0f, 2.0f, 3.0f, 4.0f
    });

    std::vector<float> expectedOutputData = std::vector<float>(
    {
        1.0f, 2.0f, 3.0f, 4.0f
    });

    SpaceToDepthEndToEnd(defaultBackends,
                         DataLayout::NCHW,
                         inputTensorInfo,
                         outputTensorInfo,
                         inputData,
                         expectedOutputData,
                         blockSize);
}

void SpaceToDepthNhwcEndToEndTest2(const std::vector<armnn::BackendId>& defaultBackends)
{
    using namespace armnn;

    const unsigned int blockSize = 2;

    TensorShape inputShape{1, 2, 2, 2};
    TensorShape outputShape{1, 1, 1, 8};

    TensorInfo outputTensorInfo(outputShape, DataType::Float32);
    TensorInfo inputTensorInfo(inputShape, DataType::Float32);

    std::vector<float> inputData = std::vector<float>(
    {
        1.4f, 2.3f, 3.2f, 4.1f, 5.4f, 6.3f, 7.2f, 8.1f
    });

    std::vector<float> expectedOutputData = std::vector<float>(
    {
        1.4f, 2.3f, 3.2f, 4.1f, 5.4f, 6.3f, 7.2f, 8.1f
    });

    SpaceToDepthEndToEnd(defaultBackends,
                         DataLayout::NHWC,
                         inputTensorInfo,
                         outputTensorInfo,
                         inputData,
                         expectedOutputData,
                         blockSize);
}

void SpaceToDepthNchwEndToEndTest2(const std::vector<armnn::BackendId>& defaultBackends)
{
    using namespace armnn;

    const unsigned int blockSize = 2;

    TensorShape inputShape{1, 2, 2, 2};
    TensorShape outputShape{1, 1, 1, 8};

    TensorInfo inputTensorInfo(inputShape, DataType::Float32);
    TensorInfo outputTensorInfo(outputShape, DataType::Float32);

    std::vector<float> inputData = std::vector<float>(
    {
        1.4f, 2.3f, 3.2f, 4.1f, 5.4f, 6.3f, 7.2f, 8.1f
    });

    std::vector<float> expectedOutputData = std::vector<float>(
    {
        1.4f, 2.3f, 3.2f, 4.1f, 5.4f, 6.3f, 7.2f, 8.1f
    });

    SpaceToDepthEndToEnd(defaultBackends,
                         DataLayout::NCHW,
                         inputTensorInfo,
                         outputTensorInfo,
                         inputData,
                         expectedOutputData,
                         blockSize);
}


#include <string>
#include <vector>

#include <boost/graph/adjacency_list.hpp>
#include <boost/range/iterator_range_core.hpp>

extern "C" {
  #include "nauty.h"
}

#include "arch_graph.hpp"
#include "nauty_graph.hpp"
#include "perm_group.hpp"

namespace mpsym
{

using namespace internal;

NautyGraph ArchGraph::graph_nauty() const
{
  int cts = num_channel_types();
  int cts_log2 = 0; while (cts >>= 1) ++cts_log2;

  int n_orig = num_processors();
  int n = n_orig * (cts_log2 + 1u);

  NautyGraph g(n, n_orig, directed());

  /* node numbering:
   *  ...     ...           ...
   *   |       |             |
   * (n+1)---(n+2)-- ... --(n+n)
   *   |       |             |
   *  (1)-----(2)--- ... ---(n)
   */

  // add edges
  for (int level = 0; level <= cts_log2; ++level) {
    for (int level_ = 0; level_ <= cts_log2; ++level_) {
      if (level_ == level)
        continue;

      for (int v = 0; v < n_orig; ++v)
        g.add_edge(v + level * n_orig, v + level_ * n_orig);
    }

    for (auto ch : channels()) {
      if (channel_type(ch) + 1 & (1 << level))
        g.add_edge(source(ch) + level * n_orig, target(ch) + level * n_orig);
    }
  }

  // set partition
  std::vector<std::vector<int>> ptn(num_processor_types() * (cts_log2 + 1));

  for (int level = 0; level <= cts_log2; ++level) {
    for (int v = 0; v < n_orig; ++v) {
      auto p = processor_type(v) + level * num_processor_types();

      ptn[p].push_back(v + level * n_orig);
    }
  }

  g.set_partition(ptn);

  return g;
}

std::string ArchGraph::to_gap_nauty() const
{
  auto g(graph_nauty());

  return g.to_gap();
}

PermSet ArchGraph::automorphism_generators_nauty()
{
  auto g(graph_nauty());

  return g.automorphism_generators();
}

PermGroup ArchGraph::automorphisms_nauty(AutomorphismOptions const *options,
                                         timeout::flag aborted)
{
  auto generators(automorphism_generators_nauty());

  return PermGroup(BSGS(num_processors(), generators, options, aborted));
}

} // namespace mpsym


// -----------------------------------------------------------------------------
// Copyright (c) 2016-2018 Benjamin Buch
//
// https://github.com/bebuch/mitrax
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
// -----------------------------------------------------------------------------
#define BOOST_TEST_MODULE mitrax reinit
#include <boost/test/unit_test.hpp>
#include <boost/mpl/list.hpp>

#include <mitrax/make_matrix.hpp>
#include <mitrax/reinit.hpp>

#include <complex>
#include <iostream>

using namespace mitrax;
using namespace mitrax::literals;

template < typename T >
auto rt_id(T&& v){
	return boost::typeindex::type_id_runtime(static_cast< T&& >(v));
}

template < typename T >
auto const id = boost::typeindex::type_id< T >();

template < typename Matrix, size_t RefC, size_t RefR >
constexpr bool check_fn(
	Matrix& m,
	value_type_t< Matrix > const(&ref)[RefR][RefC]
){
	using value_type = value_type_t< Matrix >;

	bool res = true;
	res &= m.cols() == cols< col_t(RefC) >();
	res &= m.rows() == rows< row_t(RefR) >();

	for(size_t y = 0; y < RefR; ++y){
		for(size_t x = 0; x < RefC; ++x){
			res &= m(c_t(x), r_t(y)) == ref[y][x];
		}
	}

	if constexpr(Matrix::ct_cols == 1_C || Matrix::ct_rows == 1_R){
		auto vec_ref =
			reinterpret_cast< value_type const(&)[RefC * RefR] >(ref);

		for(size_t i = 0; i < RefC * RefR; ++i){
			res &= m[d_t(i)] == vec_ref[i];
		}
	}

	if constexpr(Matrix::ct_cols == 1_C && Matrix::ct_rows == 1_R){
		res &= static_cast< value_type >(m) == ref[0][0];
	}

	return res;
}

template < typename M, col_t C, row_t R, size_t RefC, size_t RefR >
constexpr bool check(
	matrix< M, C, R > const& m,
	value_type_t< M > const(&ref)[RefR][RefC]
){
	return check_fn(m, ref);
}

template < typename M, col_t C, row_t R, size_t RefC, size_t RefR >
constexpr bool check(
	matrix< M, C, R >& m,
	value_type_t< M > const(&ref)[RefR][RefC]
){
	auto const& m_const = m;
	return check_fn(m, ref) && check(m_const, ref);
}

template < typename T >
struct fn_xy_t{
	template < typename T1, typename T2 >
	constexpr T operator()(T1 x, T2 y)const noexcept{
		return size_t(x) + size_t(y) * 10;
	}
};

template < typename T >
struct fn_x_t{
	template < typename T1 >
	constexpr T operator()(T1 i)const noexcept{
		return size_t(i) * 10;
	}
};

template < typename T >
struct fn_y_t{
	template < typename T1 >
	constexpr T operator()(T1 i)const noexcept{
		return size_t(i);
	}
};

template < typename T >
struct fn_i_t{
	template < typename T1 >
	constexpr T operator()(T1 i)const noexcept{
		return size_t(i) + size_t(i) * 10;
	}
};

BOOST_AUTO_TEST_SUITE(suite_reinit)

using types = boost::mpl::list< int, double, std::complex< float > >;

BOOST_AUTO_TEST_CASE_TEMPLATE(test_std, T, types){
	constexpr T ref_0[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
	constexpr T ref_v[3][3] = {{7, 7, 7}, {7, 7, 7}, {7, 7, 7}};
	constexpr T ref_i[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
	constexpr T ref_f[3][3] = {{0, 1, 2}, {10, 11, 12}, {20, 21, 22}};
	static constexpr T init_i[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
	constexpr auto init_p = mitrax::begin(init_i);
	constexpr auto fn = fn_xy_t< T >();

	auto m1 = make_matrix_v< T >(3_CS, 3_RS);
	auto m2 = make_matrix_v< T >(3_CD, 3_RS);
	auto m3 = make_matrix_v< T >(3_CS, 3_RD);
	auto m4 = make_matrix_v< T >(3_CD, 3_RD);
	auto m5 = make_matrix_v(3_CS, 3_RS, T(), maker::heap);

	BOOST_TEST((check(m1, ref_0)));
	BOOST_TEST((check(m2, ref_0)));
	BOOST_TEST((check(m3, ref_0)));
	BOOST_TEST((check(m4, ref_0)));
	BOOST_TEST((check(m5, ref_0)));

	reinit_v(m1, T(7));
	reinit_v(m2, T(7));
	reinit_v(m3, T(7));
	reinit_v(m4, T(7));
	reinit_v(m5, T(7));

	BOOST_TEST((check(m1, ref_v)));
	BOOST_TEST((check(m2, ref_v)));
	BOOST_TEST((check(m3, ref_v)));
	BOOST_TEST((check(m4, ref_v)));
	BOOST_TEST((check(m5, ref_v)));

	reinit_fn(m1, fn);
	reinit_fn(m2, fn);
	reinit_fn(m3, fn);
	reinit_fn(m4, fn);
	reinit_fn(m5, fn);

	BOOST_TEST((check(m1, ref_f)));
	BOOST_TEST((check(m2, ref_f)));
	BOOST_TEST((check(m3, ref_f)));
	BOOST_TEST((check(m4, ref_f)));
	BOOST_TEST((check(m5, ref_f)));

	reinit_iter(m1, init_p);
	reinit_iter(m2, init_p);
	reinit_iter(m3, init_p);
	reinit_iter(m4, init_p);
	reinit_iter(m5, init_p);

	BOOST_TEST((check(m1, ref_i)));
	BOOST_TEST((check(m2, ref_i)));
	BOOST_TEST((check(m3, ref_i)));
	BOOST_TEST((check(m4, ref_i)));
	BOOST_TEST((check(m5, ref_i)));
}

BOOST_AUTO_TEST_CASE_TEMPLATE(test_ct, T, types){
	constexpr T ref_i[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
	constexpr T ref_v[3][3] = {{7, 7, 7}, {7, 7, 7}, {7, 7, 7}};

	auto m1 = make_matrix_v< T >(3_CS, 3_RS);
	auto m2 = make_matrix_v(3_CS, 3_RS, T(), maker::heap);

	reinit(m1, {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}});
	reinit(m2, {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}});

	BOOST_TEST((check(m1, ref_i)));
	BOOST_TEST((check(m2, ref_i)));

	reinit_v(m1, T(7));
	reinit_v(m2, T(7));

	BOOST_TEST((check(m1, ref_v)));
	BOOST_TEST((check(m2, ref_v)));

	reinit(m1, ref_i);
	reinit(m2, ref_i);

	BOOST_TEST((check(m1, ref_i)));
	BOOST_TEST((check(m2, ref_i)));
}

BOOST_AUTO_TEST_CASE_TEMPLATE(test_vector, T, types){
	constexpr T ref_i[3] = {0, 1, 2};
	constexpr T ref_f_c[3][1] = {{0}, {11}, {22}};
	constexpr T ref_f_r[1][3] = {{0, 11, 22}};
	constexpr T ref_i_c[3][1] = {{0}, {1}, {2}};
	constexpr T ref_i_r[1][3] = {{0, 1, 2}};
	constexpr T ref_v_c[3][1] = {{7}, {7}, {7}};
	constexpr T ref_v_r[1][3] = {{7, 7, 7}};
	constexpr auto fn = fn_i_t< T >();

	auto mc1 = make_vector_v< T >(3_RS);
	auto mc2 = make_vector_v(3_RS, T(), maker::heap);
	auto mr1 = make_vector_v< T >(3_CS);
	auto mr2 = make_vector_v(3_CS, T(), maker::heap);

	reinit_vector_fn(mc1, fn);
	reinit_vector_fn(mc2, fn);
	reinit_vector_fn(mr1, fn);
	reinit_vector_fn(mr2, fn);

	BOOST_TEST((check(mc1, ref_f_c)));
	BOOST_TEST((check(mc2, ref_f_c)));
	BOOST_TEST((check(mr1, ref_f_r)));
	BOOST_TEST((check(mr2, ref_f_r)));

	reinit_v(mc1, T(7));
	reinit_v(mc2, T(7));
	reinit_v(mr1, T(7));
	reinit_v(mr2, T(7));

	BOOST_TEST((check(mc1, ref_v_c)));
	BOOST_TEST((check(mc2, ref_v_c)));
	BOOST_TEST((check(mr1, ref_v_r)));
	BOOST_TEST((check(mr2, ref_v_r)));

	reinit_vector(mc1, {0, 1, 2});
	reinit_vector(mc2, {0, 1, 2});
	reinit_vector(mr1, {0, 1, 2});
	reinit_vector(mr2, {0, 1, 2});

	BOOST_TEST((check(mc1, ref_i_c)));
	BOOST_TEST((check(mc2, ref_i_c)));
	BOOST_TEST((check(mr1, ref_i_r)));
	BOOST_TEST((check(mr2, ref_i_r)));

	reinit_v(mc1, T(7));
	reinit_v(mc2, T(7));
	reinit_v(mr1, T(7));
	reinit_v(mr2, T(7));

	BOOST_TEST((check(mc1, ref_v_c)));
	BOOST_TEST((check(mc2, ref_v_c)));
	BOOST_TEST((check(mr1, ref_v_r)));
	BOOST_TEST((check(mr2, ref_v_r)));

	reinit_vector(mc1, ref_i);
	reinit_vector(mc2, ref_i);
	reinit_vector(mr1, ref_i);
	reinit_vector(mr2, ref_i);

	BOOST_TEST((check(mc1, ref_i_c)));
	BOOST_TEST((check(mc2, ref_i_c)));
	BOOST_TEST((check(mr1, ref_i_r)));
	BOOST_TEST((check(mr2, ref_i_r)));
}

BOOST_AUTO_TEST_SUITE_END()


//==============================================================================
//         Copyright 2003 - 2012   LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2012   LRI    UMR 8623 CNRS/Univ Paris Sud XI
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#define NT2_UNIT_MODULE "nt2 reduction toolbox - maximum/simd Mode"

//////////////////////////////////////////////////////////////////////////////
// unit test behavior of reduction components in simd mode
//////////////////////////////////////////////////////////////////////////////
/// created  by jt the 24/02/2011
///
#include <nt2/reduction/include/functions/maximum.hpp>
#include <boost/simd/sdk/simd/native.hpp>
#include <nt2/include/functions/arith.hpp>
#include <nt2/include/functions/extract.hpp>
#include <boost/type_traits/is_same.hpp>
#include <nt2/sdk/functor/meta/call.hpp>
#include <nt2/sdk/complex/complex.hpp>

#include <nt2/sdk/unit/tests/relation.hpp>
#include <nt2/sdk/unit/module.hpp>

NT2_TEST_CASE_TPL ( maximum,  NT2_SIMD_REAL_TYPES)
{
  using nt2::maximum;
  using nt2::tag::maximum_;
  using boost::simd::native;
  using nt2::meta::cardinal_of;
  typedef NT2_SIMD_DEFAULT_EXTENSION  ext_t;
  typedef native<T,ext_t>                        vT;
  typedef std::complex<T>                         cT;
  typedef native<cT ,ext_t>                      vcT;

  // specific values tests
  vT r =  nt2::arith<vT>(0, 1);
  vT i =  nt2::arith<vT>(0, 1);
  vcT z = vcT(r, i);
  NT2_TEST_EQUAL(maximum(z), z[cardinal_of<vT>::value-1]);
  i =  nt2::arith<vT>(T(cardinal_of<vT>::value-1), T(-1));
  z = vcT(r, i);
  NT2_TEST_EQUAL(maximum(z), z[0]);

} // end of test for floating_


#include <ros/ros.h>
#include <ros/package.h>
#include <Eigen/Eigen>
#include <cv_bridge/cv_bridge.h>
#include <rovi_gazebo/rovi_gazebo.h>
#include <rovi_utils/rovi_utils.h>
#include <eigen_conversions/eigen_msg.h>

#include <rovi_pose_estimator/rovi_pose_estimator.h>

const static std::vector<std::array<double, 3>> OBJECT_POS{
                                                                {0.55, 0.95, 0.75},
                                                                {0.55, 1.00, 0.75},
                                                                {0.55, 1.05, 0.75},
                                                                {0.60, 0.95, 0.75},
                                                                {0.60, 1.00, 0.75},
                                                                {0.60, 1.05, 0.75},
                                                            };

const static std::vector<std::array<double, 3>> OBJECT_ORI{
                                                                {0.0, 0.0, 0.0},
                                                                {0.0, 0.0, 0.0},
                                                                {0.0, 0.0, 0.0},
                                                                {0.0, 0.0, 0.0},
                                                                {0.0, 0.0, 0.0},
                                                                {0.0, 0.0, 0.0}
                                                            };

const static std::vector<double> OBJECT_NOISE               {
                                                                0,
                                                                10,
                                                                20,
                                                                30,
                                                                40,
                                                                50
                                                            };

int main(int argc, char** argv)
{
    using namespace rovi_pose_estimator;

    if ( argc != 2 )
    {
        ROS_INFO_STREAM("How to use, insert number of it : <it>");
        return -1;
    }

    std::fstream file_handle("rovi_pose_M1.csv", std::ios_base::out);

    if( not file_handle.is_open() )
    {
        ROS_INFO_STREAM("File is not open, closing.");
        return -1;
    }

    // set
    int iterations = std::stoi(argv[1]);

    // init the node
	ros::init(argc, argv, "pose_M1");
	ros::NodeHandle nh;
	ros::AsyncSpinner spin(4);
	spin.start();

    // init
    rovi_gazebo::set_projector(true);
    rovi_gazebo::set_simulation(true);
    rovi_gazebo::spawn_model("bottle", "bottle1", OBJECT_POS[0], OBJECT_ORI[0]);

    geometry_msgs::Pose guess;

    for (auto i = 0; i < OBJECT_ORI.size(); ++i )
    {

        rovi_gazebo::move_model("bottle1", OBJECT_POS[i], OBJECT_ORI[i]);

        ros::Duration(1).sleep();

        for (auto k = 0; k < OBJECT_NOISE.size(); k++)
        {

            for (auto j = 0; j < 20; j++)
            {
                auto tic = ros::Time::now();

                guess = M1::estimate_pose(iterations, false, OBJECT_NOISE[k]);

                geometry_msgs::Pose actual = rovi_utils::make_pose(OBJECT_POS[i], OBJECT_ORI[i]);

                auto toc = ros::Time::now();

                file_handle << (toc-tic).toSec() << ", "
                            << actual.position.x << ", "
                            << actual.position.y << ", "
                            << actual.position.z << ", "
                            << guess.position.x << ", "
                            << guess.position.y << ", "
                            << guess.position.z << ", "
                            << OBJECT_NOISE[k] << std::endl;
            }

        }

    }

    file_handle.close();

    return 0;
}


/*
 * Copyright (c) 2019, Eberty Alves
 */

// C++ standard library
#include <bits/stdc++.h>

// Point cloud library
#include <pcl/common/centroid.h>
#include <pcl/filters/crop_box.h>
#include <pcl/io/ply_io.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>

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

// Typedefs
typedef pcl::PointXYZRGBNormal PointT;
typedef pcl::PointCloud<PointT> PointC;

int main(int argc, char* argv[]) {
  pcl::console::setVerbosityLevel(pcl::console::L_ERROR);

  try {
    // Declaration of variables
    std::string input_file_name;
    std::string output_file_name;
    double radius;
    bool negative;

    // Parse command-line options
    namespace po = boost::program_options;

    // Define command-line options
    po::options_description desc("Options");
    desc.add_options()
    ("help,h", "Print help message")
    ("input,i", po::value<std::string>(&input_file_name)->required(), "Input file (.ply)")
    ("output,o", po::value<std::string>(&output_file_name)->required(), "Output file (.ply)")
    ("radius,r", po::value<double>(&radius)->required(), "Standard radius to remove")
    ("negative,n", "Saves the removed points in a .ply file");

    // Use a parser to evaluate the command line
    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);

    // Store the command-line options evaluated by the parser
    if (vm.count("help")) {
      std::cout << "Filter all data inside of a box." << std::endl << std::endl;
      std::cout << desc << std::endl;
      return 0;
    }

    if (vm.count("input") && vm.count("output") && vm.count("radius")) {
      input_file_name = vm["input"].as<std::string>();
      output_file_name = vm["output"].as<std::string>();
      radius = vm["radius"].as<double>();
    } else {
      throw std::string("Correct mode of use: " + std::string(argv[0]) + " -i input.ply -o output.ply -r [radius]");
    }
    negative = vm.count("negative");

    PointC::Ptr point_cloud(new PointC);
    PointC::Ptr cloud_filtered(new PointC);

    // Load the point cloud data from disk
    if (pcl::io::loadPLYFile<PointT>(input_file_name, *point_cloud) == -1) {
      throw std::string("Couldn't load input file");
    }

    std::cout << "Cloud before filtering: " << std::endl;
    std::cout << *point_cloud << std::endl;

    // Compute point cloud centroid
    Eigen::Vector4f centroid;
    pcl::compute3DCentroid(*point_cloud, centroid);

    // Create the filtering object
    pcl::CropBox<PointT> crop_box;
    crop_box.setMin(Eigen::Vector4f(centroid[0] - radius, centroid[1] - radius, centroid[2] - radius, 1.0));
    crop_box.setMax(Eigen::Vector4f(centroid[0] + radius, centroid[1] + radius, centroid[2] + radius, 1.0));
    crop_box.setInputCloud(point_cloud);
    crop_box.filter(*cloud_filtered);

    // Save ply with points croped
    std::cout << "Cloud after filtering: " << std::endl;
    std::cout << *cloud_filtered << std::endl;
    pcl::io::savePLYFileBinary(output_file_name, *cloud_filtered);

    // Save points outside the crop box
    if (negative) {
      crop_box.setNegative(true);
      crop_box.filter(*cloud_filtered);
      size_t pos = output_file_name.rfind(".ply");
      if (pos != std::string::npos) output_file_name.erase(pos, 4);
      pcl::io::savePLYFileBinary(output_file_name + "_negative.ply", *cloud_filtered);
    }

    return 0;
  } catch (boost::program_options::error& msg) {
    std::cout << "ERROR: " << msg.what() << std::endl;
  } catch (std::string msg) {
    std::cout << msg << std::endl;
  }

  return -1;
}


#ifndef __KDTREE2_HPP
#define __KDTREE2_HPP

//
// (c) Matthew B. Kennel, Institute for Nonlinear Science, UCSD (2004)
//
// Licensed under the Academic Free License version 1.1 found in file LICENSE
// with additional provisions in that same file.

//
// Implement a kd tree for fast searching of points in a fixed data base
// in k-dimensional Euclidean space.
//
//

#include <vector>
#include <algorithm>

#include <boost/multi_array.hpp>
#include <boost/array.hpp>

namespace kdtree2 {
typedef double KDFloat;
typedef boost::multi_array<KDFloat,2>             KDTreeArray;
typedef boost::const_multi_array_ref<KDFloat,2>   KDTreeROArray;  // read only ref

typedef struct {
  KDFloat lower, upper;
} interval;

// let the compiler know that this is a names of classes.
class KDTreeNode;
class SearchRecord;

//
// struct KDTreeResult
// class  KDTreeResult
//

struct KDTreeResult {
  //
  // the search routines return a (wrapped) vector
  // of these.
  //
public:
  KDFloat dis;  // its square Euclidean distance
  int idx;    // which neighbor was found
};

class KDTreeResultVector : public std::vector<KDTreeResult> {
  // inherit a std::vector<KDTreeResult>
  // but, optionally maintain it in heap form as a priority
  // queue.
public:

  //
  // add one new element to the list of results, and
  // keep it in heap order.  To keep it in ordinary, as inserted,
  // order, then simply use push_back() as inherited
  // via std::vector<>

  void push_element_and_heapify(KDTreeResult&);
  KDFloat replace_maxpri_elt_return_new_maxpri(KDTreeResult&);

  KDFloat max_value();
  // return the distance which has the maximum value of all on list,
  // assuming that ALL insertions were made by
  // push_element_and_heapify()
};

//
// class KDTree
//
// The main data structure, one for each k-d tree, pointing
// to a tree of an indeterminate number of "KDTreeNode"s.
//

class KDTree {
public:
  const KDTreeArray& the_data;
  // "the_data" is a reference to the underlying multi_array of the
  // data to be included in the tree.
  //
  // NOTE: this structure does *NOT* own the storage underlying this.
  // Hence, it would be a very bad idea to change the underlying data
  // during use of the search facilities of this tree.
  // Also, the user must deallocate the memory underlying it.

  const int N;   // number of data points
  int dim; //
  bool sort_results;  // USERS set to 'true'.
  const bool rearrange; // are we rearranging?

public:
  //
  // constructor, passing in a multi_array<KDFloat,2> , aka
  // KDTreeArray.
  //
  // constructor, has optional 'dim_in' feature, to use only
  // first 'dim_in' components for definition of nearest neighbors.
  //

  KDTree(KDTreeArray& data_in,bool rearrange_in = true,int dim_in=-1);

  // destructor
  ~KDTree();

public:
  // search routines

  void n_nearest_brute_force(std::vector<KDFloat>& qv, int nn, KDTreeResultVector& result);
  // search for n nearest to a given query vector 'qv' usin
  // exhaustive slow search.  For debugging, usually.

  void n_nearest(std::vector<KDFloat>& qv, int nn, KDTreeResultVector& result);
  // search for n nearest to a given query vector 'qv'.

  void n_nearest_around_point(int idxin, int correltime, int nn,
			      KDTreeResultVector& result);
  // search for 'nn' nearest to point [idxin] of the input data, excluding
  // neighbors within correltime

  void r_nearest(std::vector<KDFloat>& qv, KDFloat r2,KDTreeResultVector& result);
  // search for all neighbors in ball of size (square Euclidean distance)
  // r2.   Return number of neighbors in 'result.size()',

  void r_nearest_around_point(int idxin, int correltime, KDFloat r2,
			      KDTreeResultVector& result);
  // like 'r_nearest', but around existing point, with decorrelation
  // interval.

  int r_count(std::vector<KDFloat>& qv, KDFloat r2);
  // count number of neighbors within square distance r2.
  int r_count_around_point(int idxin, int correltime, KDFloat r2);
  // like r_count, c

  friend class KDTreeNode;
  friend class SearchRecord;
private:
  // private data members

  KDTreeNode* root; // the root pointer

  const KDTreeArray* data;
  // pointing either to the_data or an internal
  // rearranged data as necessary

  std::vector<int> ind;
  // the index for the tree leaves.  Data in a leaf with bounds [l,u] are
  // in  'the_data[ind[l],*] to the_data[ind[u],*]

  KDTreeArray rearranged_data;
  // if rearrange is true then this is the rearranged data storage.

  static const int bucketsize = 12;  // global constant.

private:
  void set_data(KDTreeArray& din);
  void build_tree(); // builds the tree.  Used upon construction.
  KDTreeNode* build_tree_for_range(int l, int u, KDTreeNode* parent);
  void select_on_coordinate(int c, int k, int l, int u);
  int select_on_coordinate_value(int c, KDFloat alpha, int l, int u);
  void spread_in_coordinate(int c, int l, int u, interval& interv);
};

//
// class KDTREENODE
//
// a node in the tree.  Many are created per tree dynamically..
//

class KDTreeNode {
public:
  // constructor
  KDTreeNode(int dim);
  //, int cut_dim_in,
  // 	       KDFloat cut_val_in, KDFloat cut_val_left_in,
  //	       KDFloat cut_val_right_in);
  // destructor
  ~KDTreeNode();

private:
  // visible to self and KDTree.
  friend class KDTree;  // allow kdtree2 to access private

  int cut_dim;                                 // dimension to cut;
  KDFloat cut_val, cut_val_left, cut_val_right;  //cut value
  int l,u;  // extents in index array for searching

  std::vector<interval> box; // [min,max] of the box enclosing all points

  KDTreeNode *left, *right;  // pointers to left and right nodes.

  void search(SearchRecord& sr);
  // recursive innermost core routine for searching..

  bool box_in_search_range(SearchRecord& sr);
  // return true if the bounding box for this node is within the
  // search range given by the searchvector and maximum ballsize in 'sr'.

  void check_query_in_bound(SearchRecord& sr); // debugging only

  // for processing final buckets.
  void process_terminal_node(SearchRecord& sr);
  void process_terminal_node_fixedball(SearchRecord& sr);

};

} // namespace kdtree2

#endif


/*
@copyright Louis Dionne 2015
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
 */

#include <boost/hana/map.hpp>

#include <boost/hana/assert.hpp>
#include <boost/hana/tuple.hpp>

#include <laws/base.hpp>
#include <laws/comparable.hpp>
#include <test/minimal_product.hpp>
using namespace boost::hana;

template <int i>
auto key = test::ct_eq<i>{};

template <int i>
auto val = test::ct_eq<-i>{};

template <int i, int j>
auto p = test::minimal_product(key<i>, val<j>);

int main() {
    auto eq_maps = make<Tuple>(
        make<Map>(),
        make<Map>(p<1, 1>),
        make<Map>(p<1, 2>),
        make<Map>(p<1, 1>, p<2, 2>),
        make<Map>(p<1, 1>, p<2, 2>, p<3, 3>)
    );

    //////////////////////////////////////////////////////////////////////////
    // Comparable
    //////////////////////////////////////////////////////////////////////////
    {
        // equal
        {
            BOOST_HANA_CONSTANT_CHECK(equal(
                make<Map>(),
                make<Map>()
            ));
            BOOST_HANA_CONSTANT_CHECK(not_(equal(
                make<Map>(p<1, 1>),
                make<Map>())
            ));
            BOOST_HANA_CONSTANT_CHECK(not_(equal(
                make<Map>(),
                make<Map>(p<1, 1>)
            )));

            BOOST_HANA_CONSTANT_CHECK(equal(
                make<Map>(p<1, 1>),
                make<Map>(p<1, 1>)
            ));
            BOOST_HANA_CONSTANT_CHECK(not_(equal(
                make<Map>(p<1, 1>),
                make<Map>(p<1, 2>))
            ));
            BOOST_HANA_CONSTANT_CHECK(not_(equal(
                make<Map>(p<1, 1>),
                make<Map>(p<2, 1>))
            ));
            BOOST_HANA_CONSTANT_CHECK(not_(equal(
                make<Map>(p<1, 1>),
                make<Map>(p<1, 1>, p<2, 2>))
            ));

            BOOST_HANA_CONSTANT_CHECK(equal(
                make<Map>(p<1, 1>, p<2, 2>),
                make<Map>(p<1, 1>, p<2, 2>)
            ));
            BOOST_HANA_CONSTANT_CHECK(equal(
                make<Map>(p<1, 1>, p<2, 2>),
                make<Map>(p<2, 2>, p<1, 1>)
            ));
            BOOST_HANA_CONSTANT_CHECK(not_(equal(
                make<Map>(p<1, 1>, p<2, 2>),
                make<Map>(p<9, 1>, p<2, 2>))
            ));
            BOOST_HANA_CONSTANT_CHECK(not_(equal(
                make<Map>(p<1, 1>, p<2, 2>),
                make<Map>(p<1, 9>, p<2, 2>))
            ));
            BOOST_HANA_CONSTANT_CHECK(not_(equal(
                make<Map>(p<1, 1>, p<2, 2>),
                make<Map>(p<1, 1>, p<9, 2>))
            ));
            BOOST_HANA_CONSTANT_CHECK(not_(equal(
                make<Map>(p<1, 1>, p<2, 2>),
                make<Map>(p<1, 1>, p<2, 9>))
            ));
            BOOST_HANA_CONSTANT_CHECK(not_(equal(
                make<Map>(p<1, 1>, p<2, 2>),
                make<Map>(p<1, 1>, p<2, 2>, p<3, 3>))
            ));
        }

        // laws
        test::TestComparable<Map>{eq_maps};
    }
}


// Copyright 2008 The Trustees of Indiana University.

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

//  Boost.MultiArray Library
//  Authors: Ronald Garcia
//           Jeremy Siek
//           Andrew Lumsdaine
//  See http://www.boost.org/libs/multi_array for documentation.

//
// resize_from_other.cpp - an experiment in writing a resize function for
// multi_arrays that will use the extents from another to build itself.
//

#include <boost/multi_array.hpp>
#include <boost/static_assert.hpp>
#include <boost/array.hpp>
#include <algorithm>

template <typename T, typename U, std::size_t N>
void
resize_from_MultiArray(boost::multi_array<T,N>& marray, U& other) {

  // U must be a model of MultiArray
  boost::function_requires<
  boost::detail::multi_array::ConstMultiArrayConcept<U,U::dimensionality> >();
  // U better have U::dimensionality == N
  BOOST_STATIC_ASSERT(U::dimensionality == N);

  boost::array<typename boost::multi_array<T,N>::size_type, N> shape;

  std::copy(other.shape(), other.shape()+N, shape.begin());

  marray.resize(shape);

}

#include <iostream>

int main () {

  boost::multi_array<int,2> A(boost::extents[5][4]), B;
  boost::multi_array<int,3> C;

  resize_from_MultiArray(B,A);

#if 0
  resize_from_MultiArray(C,A); // Compile-time error
#endif

  std::cout << B.shape()[0] << ", " << B.shape()[1] << '\n';

}


/*
    Copyright 2005-2007 Adobe Systems Incorporated
    Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
    or a copy at http://stlab.adobe.com/licenses.html)
*/

/*************************************************************************************************/

#ifndef ADOBE_SHA_HPP
#define ADOBE_SHA_HPP

/*************************************************************************************************/

#include <adobe/config.hpp>

#include <boost/array.hpp>
#include <boost/cstdint.hpp>
#include <boost/static_assert.hpp>

#include <stdexcept>
#include <limits>
#include <cstring>

/*************************************************************************************************/

namespace adobe {

/*!
\class adobe::sha1_t
\ingroup secure_algorithm

\brief A bit-oriented implementation of the SHA-1 Secure Hash Algorithm
*/

/*!
\class adobe::sha224_t
\ingroup secure_algorithm

\brief A bit-oriented implementation of the SHA-224 Secure Hash Algorithm
*/

/*!
\class adobe::sha256_t
\ingroup secure_algorithm

\brief A bit-oriented implementation of the SHA-256 Secure Hash Algorithm
*/

/*!
\class adobe::sha384_t
\ingroup secure_algorithm

\brief A bit-oriented implementation of the SHA-384 Secure Hash Algorithm
*/

/*!
\class adobe::sha512_t
\ingroup secure_algorithm

\brief A bit-oriented implementation of the SHA-512 Secure Hash Algorithm
*/

/*!
\typedef adobe::sha1_t::digest_type

A boost::array<boost::uint32_t, 5> for the 160-bit digest
*/

/*!
\fn adobe::sha1_t::digest_type adobe::sha1_t::digest(I first, I last)

\pre
    sizeof(std::iterator_traits::value_type) must be 1

\param first    first iterator over the range to hash
\param last     last iterator over the range to hash

\return The SHA-1 digest of the message
*/

/*!
\fn adobe::sha1_t::digest_type adobe::sha1_t::digest(I first, boost::uint64_t num_bits)

\pre
    sizeof(std::iterator_traits::value_type) must be 1

\param first    first iterator over the range to hash
\param num_bits number of bits to hash

\return The SHA-1 digest of the message
*/

/*!
\typedef adobe::sha224_t::digest_type

A boost::array<boost::uint32_t, 7> for the 224-bit digest
*/

/*!
\fn adobe::sha224_t::digest_type adobe::sha224_t::digest(I first, I last)

\pre
    sizeof(std::iterator_traits::value_type) must be 1

\param first    first iterator over the range to hash
\param last     last iterator over the range to hash

\return The SHA-224 digest of the message
*/

/*!
\fn adobe::sha224_t::digest_type adobe::sha224_t::digest(I first, boost::uint64_t num_bits)

\pre
    sizeof(std::iterator_traits::value_type) must be 1

\param first    first iterator over the range to hash
\param num_bits number of bits to hash

\return The SHA-224 digest of the message
*/

/*!
\typedef adobe::sha256_t::digest_type

A boost::array<boost::uint32_t, 8> for the 256-bit digest
*/

/*!
\fn adobe::sha256_t::digest_type adobe::sha256_t::digest(I first, I last)

\pre
    sizeof(std::iterator_traits::value_type) must be 1

\param first    first iterator over the range to hash
\param last     last iterator over the range to hash

\return The SHA-256 digest of the message
*/

/*!
\fn adobe::sha256_t::digest_type adobe::sha256_t::digest(I first, boost::uint64_t num_bits)

\pre
    sizeof(std::iterator_traits::value_type) must be 1

\param first    first iterator over the range to hash
\param num_bits number of bits to hash

\return The SHA-256 digest of the message
*/

/*!
\typedef adobe::sha384_t::digest_type

A boost::array<boost::uint64_t, 6> for the 384-bit digest
*/

/*!
\fn adobe::sha384_t::digest_type adobe::sha384_t::digest(I first, I last)

\pre
    sizeof(std::iterator_traits::value_type) must be 1

\param first    first iterator over the range to hash
\param last     last iterator over the range to hash

\return The SHA-384 digest of the message

\note While the SHA standard specifies the ability to process messages of 2^128 in length, currently this SHA-384 implementation only handles messages up to 2^64 in length.
*/

/*!
\fn adobe::sha384_t::digest_type adobe::sha384_t::digest(I first, boost::uint64_t num_bits)

\pre
    sizeof(std::iterator_traits::value_type) must be 1

\param first    first iterator over the range to hash
\param num_bits number of bits to hash

\return The SHA-384 digest of the message

\note While the SHA standard specifies the ability to process messages of 2^128 in length, currently this SHA-384 implementation only handles messages up to 2^64 in length.
*/

/*!
\typedef adobe::sha512_t::digest_type

A boost::array<boost::uint64_t, 8> for the 512-bit digest
*/

/*!
\fn adobe::sha512_t::digest_type adobe::sha512_t::digest(I first, I last)

\pre
    sizeof(std::iterator_traits::value_type) must be 1

\param first    first iterator over the range to hash
\param last     last iterator over the range to hash

\return The SHA-512 digest of the message

\note While the SHA standard specifies the ability to process messages of 2^128 in length, currently this SHA-512 implementation only handles messages up to 2^64 in length.
*/

/*!
\fn adobe::sha512_t::digest_type adobe::sha512_t::digest(I first, boost::uint64_t num_bits)

\pre
    sizeof(std::iterator_traits::value_type) must be 1

\param first    first iterator over the range to hash
\param num_bits number of bits to hash

\return The SHA-512 digest of the message

\note While the SHA standard specifies the ability to process messages of 2^128 in length, currently this SHA-512 implementation only handles messages up to 2^64 in length.
*/

/*************************************************************************************************/

class sha1_t;
class sha224_t;
class sha256_t;
class sha384_t;
class sha512_t;

/*************************************************************************************************/

namespace implementation {

/*************************************************************************************************/

#if !defined(ADOBE_NO_DOCUMENTATION)

/*************************************************************************************************/

template <typename HashT>
struct sha_traits;

/*************************************************************************************************/

template <typename I> // I models InputIterator
inline boost::uint64_t long_distance(I first, I last)
{
    boost::uint64_t result(0);

    while (first != last)
    {
        ++result;

        ++first;
    }

    return result;
}

/*************************************************************************************************/

template <typename I> // I models InputIterator
struct bit_packer
{
    typedef typename std::iterator_traits::value_type value_type;

    BOOST_STATIC_ASSERT((sizeof(value_type) == 1));

    bit_packer(I first, I last) :
        first_m(first), bitsize_m(long_distance(first, last))
    { }

    bit_packer(I first, boost::uint64_t bitsize) :
        first_m(first), bitsize_m(bitsize)
    { }

    template <typename T>
    inline std::size_t operator () (T& result)
    { return byte_pack(result); }

private:
    template <typename T>
    std::size_t byte_pack(T& result)
    {
        std::size_t to_pack(sizeof(T));

        result = 0;

        while (to_pack != 0 && bitsize_m != 0)
        {
            std::size_t shift_count(8 * (to_pack - 1));
            T           mask(T(255) << shift_count);

            result |= (T(*first_m) << shift_count) & mask;

            if (bitsize_m >= 8)
            {
                bitsize_m -= 8;
            }
            else
            {
                std::size_t remaining(static_cast<std::size_t>(to_pack * 8 - bitsize_m));

                bitsize_m = 0;

                return remaining;
            }

            ++first_m;
            --to_pack;
        }

        return to_pack * 8;
    }

    I               first_m;
    boost::uint64_t bitsize_m;
};

/*************************************************************************************************/

template <typename T>
struct bitsizeof
{ enum { value = sizeof(T) * 8 }; };

/*************************************************************************************************/

template <std::size_t N, typename T>
inline T shr(const T& x)
{
    BOOST_STATIC_ASSERT((N < bitsizeof<T>::value));

    return x >> N;
}

template <std::size_t N, typename T>
inline T rotr(const T& x)
{
    BOOST_STATIC_ASSERT((N < bitsizeof<T>::value));

    enum { l_shift = bitsizeof<T>::value - N };

    return (x >> N) | (x << l_shift);
}

template <std::size_t N, typename T>
inline T rotl(const T& x)
{
    BOOST_STATIC_ASSERT((N < bitsizeof<T>::value));

    enum { r_shift = bitsizeof<T>::value - N };

    return (x << N) | (x >> r_shift);
}

/*************************************************************************************************/

template <typename T>
inline T ch(T x, T y, T z)
    { return (x & y) ^ (~x & z); }

template <typename T>
inline T parity(T x, T y, T z)
    { return x ^ y ^ z; }

template <typename T>
inline T maj(T x, T y, T z)
    { return (x & y) ^ (x & z) ^ (y & z); }

/*************************************************************************************************/

template <bool UseMB14, typename HashTraits>
struct message_block_part_14_set_t
{
    typedef HashTraits                                  traits_type;
    typedef typename traits_type::hash_type             hash_type;
    typedef typename traits_type::message_block_type    message_block_type;
    typedef typename message_block_type::value_type     message_block_value_type;

    enum { half_max_message_bitsize_k = traits_type::max_message_bitsize_k / 2 };

    void operator () (message_block_value_type& mbp14, boost::uint64_t num_bits)
    {
        message_block_value_type message_block_value_type_max(std::numeric_limits<message_block_value_type>::max());

        mbp14 = static_cast<message_block_value_type>((num_bits >> (half_max_message_bitsize_k)) & message_block_value_type_max);
    }
};

/*************************************************************************************************/

template <typename HashTraits>
struct message_block_part_14_set_t<false, HashTraits>
{
    typedef HashTraits                                  traits_type;
    typedef typename traits_type::message_block_type    message_block_type;
    typedef typename message_block_type::value_type     message_block_value_type;

    void operator () (message_block_value_type& mbp14, boost::uint64_t)
    { mbp14 = 0; }
};

/*************************************************************************************************/

template <typename HashTraits, typename I>
void block_and_digest(typename HashTraits::digest_type& digest, I first, boost::uint64_t num_bits)
{
    typedef HashTraits                                  traits_type;
    typedef typename traits_type::hash_type             hash_type;
    typedef typename traits_type::message_block_type    message_block_type;
    typedef typename message_block_type::value_type     message_block_value_type;

    enum
    {
        max_message_bitsize_k = traits_type::max_message_bitsize_k,
        half_max_message_bitsize_k = max_message_bitsize_k / 2,
        message_blocksize_k = traits_type::message_blocksize_k,
        use_mb_14 = half_max_message_bitsize_k < bitsizeof<boost::uint64_t>::value
    };

    message_block_value_type    message_block_value_type_max(std::numeric_limits<message_block_value_type>::max());
    message_block_type          message_block;
    boost::uint64_t             message_size(num_bits + max_message_bitsize_k);
    boost::uint64_t             num_blocks(message_size / message_blocksize_k + 1);
    bool                        in_padding(false);
    bit_packer               bits(first, num_bits);

    while (num_blocks != 0)
    {
        for (std::size_t i(0); i < 16; ++i)
        {
            if (!in_padding)
            {
                std::size_t unset_bits(bits(message_block[i]));

                if (unset_bits != 0)
                {
                    message_block[i] |= message_block_value_type(1) << (unset_bits - 1);

                    in_padding = true;
                }
            }
            else
            {
                if (num_blocks == 1)
                {
                    // REVISIT (fbrereto) : According to the SHA standard the message length in the
                    //                      1024-block-size case can be up to 2^128 bits long,
                    //                      but we only support messages up to 2^64 in length. In
                    //                      all instances when padding in the generic case, block
                    //                      part 14 would be:
                    //                          mbp14 = (num_bits >> (half_max_message_bitsize_k)) &
                    //                              message_block_value_type_max
                    //                      But in the 1024-block-size case
                    //                      half_max_message_bitsize_k == num_bits, and we will get
                    //                      a compiler error basically saying "hey, you're
                    //                      overshifting this value to 0", which would be fine in
                    //                      this case because the number should be set to 0, but
                    //                      the compiler is still (rightfully) noisy about it. This
                    //                      workaround forces the right thing to do in that it sets
                    //                      message block part 14 to zero in this special
                    //                      1024-block-size case, thus sliencing the compiler.

                    if (i == 14)
                        message_block_part_14_set_t<use_mb_14, traits_type>()(message_block[i], num_bits);
                    else if (i == 15)
                        message_block[i] = static_cast<message_block_value_type>(num_bits & message_block_value_type_max);
                    else
                        message_block[i] = 0;
                }
                else
                    message_block[i] = 0;
            }
        }

        sha_traits<hash_type>().digest_message_block(digest, message_block);

        --num_blocks;
    }

    // clears potentioally sensitive information
    std::memset(&message_block, 0, sizeof(message_block));
}

/*************************************************************************************************/

template <typename HashTraits>
void sha_2_digest_message_block(typename HashTraits::digest_type&               digest,
                                const typename HashTraits::message_block_type&  message_block)
{
    //  The "sha_2" in the name of this function is in
    //  reference to the second generation of SHA algorithms
    //  (224, 256, 384, and 512), all of which have the same
    //  message block process implementation.

    typedef HashTraits                                  traits_type;
    typedef typename traits_type::hash_type             hash_type;
    typedef typename traits_type::message_block_type    message_block_type;
    typedef typename traits_type::schedule_type         schedule_type;
    typedef typename hash_type::digest_type::value_type digest_value_type;

    schedule_type schedule;

    adobe::copy(message_block, &schedule[0]);

    for (std::size_t t(message_block_type::static_size); t < schedule_type::static_size; ++t)
        schedule[t] =   traits_type::small_sigma_1(schedule[t - 2]) + schedule[t - 7] +
                        traits_type::small_sigma_0(schedule[t - 15]) + schedule[t - 16];

    digest_value_type a(digest[0]);
    digest_value_type b(digest[1]);
    digest_value_type c(digest[2]);
    digest_value_type d(digest[3]);
    digest_value_type e(digest[4]);
    digest_value_type f(digest[5]);
    digest_value_type g(digest[6]);
    digest_value_type h(digest[7]);

    for (std::size_t t(0); t < schedule.size(); ++t)
    {
        digest_value_type T1 =  h                           +
                                traits_type::big_sigma_1(e) +
                                implementation::ch(e, f, g) +
                                traits_type::k(t)           +
                                schedule[t];
        digest_value_type T2 =  traits_type::big_sigma_0(a) +
                                implementation::maj(a, b, c);
        h = g;
        g = f;
        f = e;
        e = d + T1;
        d = c;
        c = b;
        b = a;
        a = T1 + T2;
    }

    digest[0] += a;
    digest[1] += b;
    digest[2] += c;
    digest[3] += d;
    digest[4] += e;
    digest[5] += f;
    digest[6] += g;
    digest[7] += h;

    // clears potentioally sensitive information
    std::memset(&schedule, 0, sizeof(schedule));
}

/*************************************************************************************************/

template <>
struct sha_traits<sha1_t>
{
    typedef class sha1_t                 hash_type;
    typedef boost::array<boost::uint32_t, 5>    digest_type;
    typedef boost::array<boost::uint32_t, 16>   message_block_type;
    typedef boost::array<boost::uint32_t, 80>   schedule_type;

    enum
    {
        max_message_bitsize_k = 64,
        message_blocksize_k = 512
    };

    static void reset_digest(digest_type& digest)
    {
        digest[0] = 0x67452301;
        digest[1] = 0xefcdab89;
        digest[2] = 0x98badcfe;
        digest[3] = 0x10325476;
        digest[4] = 0xc3d2e1f0;
    }

    static void digest_message_block(digest_type& digest, const message_block_type& message_block)
    {
        schedule_type schedule;

        adobe::copy(message_block, &schedule[0]);

        for (std::size_t t(message_block_type::static_size); t < schedule_type::static_size; ++t)
            schedule[t] = implementation::rotl<1>(  schedule[t - 3] ^ schedule[t - 8] ^
                                                    schedule[t - 14] ^ schedule[t - 16]);

        boost::uint32_t a(digest[0]);
        boost::uint32_t b(digest[1]);
        boost::uint32_t c(digest[2]);
        boost::uint32_t d(digest[3]);
        boost::uint32_t e(digest[4]);

        for (std::size_t t(0); t < schedule.size(); ++t)
        {
            boost::uint32_t T = implementation::rotl<5>(a)  +
                                f(t, b, c, d)               +
                                e                           +
                                k(t)                        +
                                schedule[t];
            e = d;
            d = c;
            c = implementation::rotl<30>(b);
            b = a;
            a = T;
        }

        digest[0] += a;
        digest[1] += b;
        digest[2] += c;
        digest[3] += d;
        digest[4] += e;

        // clears potentioally sensitive information
        std::memset(&schedule, 0, sizeof(schedule));
    }

private:
    static boost::uint32_t f(   std::size_t     t,
                                boost::uint32_t x,
                                boost::uint32_t y,
                                boost::uint32_t z)
    {
        assert (t < 80);

        if (t <= 19)        return implementation::ch(x, y, z);
        else if (t <= 39)   return implementation::parity(x, y, z);
        else if (t <= 59)   return implementation::maj(x, y, z);

        return implementation::parity(x, y, z);
    }

    static boost::uint32_t k(std::size_t t)
    {
        assert(t < 80);

        if (t <= 19)        return 0x5a827999;
        else if (t <= 39)   return 0x6ed9eba1;
        else if (t <= 59)   return 0x8f1bbcdc;

        return 0xca62c1d6;
    }
};

/*************************************************************************************************/

template <>
struct sha_traits<sha256_t>
{
    typedef class sha256_t               hash_type;
    typedef boost::array<boost::uint32_t, 8>    digest_type;
    typedef boost::array<boost::uint32_t, 16>   message_block_type;
    typedef boost::array<boost::uint32_t, 64>   schedule_type;

    enum
    {
        max_message_bitsize_k = 64,
        message_blocksize_k = 512
    };

    static void reset_digest(digest_type& digest)
    {
        digest[0] = 0x6a09e667;
        digest[1] = 0xbb67ae85;
        digest[2] = 0x3c6ef372;
        digest[3] = 0xa54ff53a;
        digest[4] = 0x510e527f;
        digest[5] = 0x9b05688c;
        digest[6] = 0x1f83d9ab;
        digest[7] = 0x5be0cd19;
    }

    static void digest_message_block(digest_type& digest, const message_block_type& message_block)
        { sha_2_digest_message_block<sha_traits<hash_type> >(digest, message_block); }

    static boost::uint32_t big_sigma_0(boost::uint32_t x)
        { return implementation::rotr<2>(x) ^ implementation::rotr<13>(x) ^ implementation::rotr<22>(x); }

    static boost::uint32_t big_sigma_1(boost::uint32_t x)
        { return implementation::rotr<6>(x) ^ implementation::rotr<11>(x) ^ implementation::rotr<25>(x); }

    static boost::uint32_t small_sigma_0(boost::uint32_t x)
        { return implementation::rotr<7>(x) ^ implementation::rotr<18>(x) ^ implementation::shr<3>(x); }

    static boost::uint32_t small_sigma_1(boost::uint32_t x)
        { return implementation::rotr<17>(x) ^ implementation::rotr<19>(x) ^ implementation::shr<10>(x); }

    static boost::uint32_t k(std::size_t t)
    {
        static const boost::uint32_t k_set[] =
        {
            0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
            0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
            0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
            0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
            0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
            0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
            0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
            0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
        };

        assert (t < 64);

        return k_set[t];
    }
};

/*************************************************************************************************/

template <>
struct sha_traits<sha224_t>
{
    typedef class sha224_t                           hash_type;
    typedef sha_traits<sha256_t>::digest_type        digest_type;
    typedef sha_traits<sha256_t>::message_block_type message_block_type;
    typedef sha_traits<sha256_t>::schedule_type      schedule_type;

    enum
    {
        max_message_bitsize_k = sha_traits<sha256_t>::max_message_bitsize_k,
        message_blocksize_k = sha_traits<sha256_t>::message_blocksize_k
    };

    static void reset_digest(digest_type& digest)
    {
        digest[0] = 0xc1059ed8;
        digest[1] = 0x367cd507;
        digest[2] = 0x3070dd17;
        digest[3] = 0xf70e5939;
        digest[4] = 0xffc00b31;
        digest[5] = 0x68581511;
        digest[6] = 0x64f98fa7;
        digest[7] = 0xbefa4fa4;
    }

    static void digest_message_block(digest_type& digest, const message_block_type& message_block)
        { sha_2_digest_message_block<sha_traits<hash_type> >(digest, message_block); }

    static boost::uint32_t big_sigma_0(boost::uint32_t x)
        { return sha_traits<sha256_t>::big_sigma_0(x); }

    static boost::uint32_t big_sigma_1(boost::uint32_t x)
        { return sha_traits<sha256_t>::big_sigma_1(x); }

    static boost::uint32_t small_sigma_0(boost::uint32_t x)
        { return sha_traits<sha256_t>::small_sigma_0(x); }

    static boost::uint32_t small_sigma_1(boost::uint32_t x)
        { return sha_traits<sha256_t>::small_sigma_1(x); }

    static boost::uint32_t k(std::size_t x)
        { return sha_traits<sha256_t>::k(x); }
};

/*************************************************************************************************/

template <>
struct sha_traits<sha512_t>
{
    typedef class sha512_t               hash_type;
    typedef boost::array<boost::uint64_t, 8>    digest_type;
    typedef boost::array<boost::uint64_t, 16>   message_block_type;
    typedef boost::array<boost::uint64_t, 80>   schedule_type;

    enum
    {
        max_message_bitsize_k = 128,
        message_blocksize_k = 1024
    };

    static void reset_digest(digest_type& digest)
    {
        digest[0] = 0x6a09e667f3bcc908ULL;
        digest[1] = 0xbb67ae8584caa73bULL;
        digest[2] = 0x3c6ef372fe94f82bULL;
        digest[3] = 0xa54ff53a5f1d36f1ULL;
        digest[4] = 0x510e527fade682d1ULL;
        digest[5] = 0x9b05688c2b3e6c1fULL;
        digest[6] = 0x1f83d9abfb41bd6bULL;
        digest[7] = 0x5be0cd19137e2179ULL;
    }

    static void digest_message_block(digest_type& digest, const message_block_type& message_block)
        { sha_2_digest_message_block<sha_traits<hash_type> >(digest, message_block); }

    static boost::uint64_t big_sigma_0(boost::uint64_t x)
        { return implementation::rotr<28>(x) ^ implementation::rotr<34>(x) ^ implementation::rotr<39>(x); }

    static boost::uint64_t big_sigma_1(boost::uint64_t x)
        { return implementation::rotr<14>(x) ^ implementation::rotr<18>(x) ^ implementation::rotr<41>(x); }

    static boost::uint64_t small_sigma_0(boost::uint64_t x)
        { return implementation::rotr<1>(x) ^ implementation::rotr<8>(x) ^ implementation::shr<7>(x); }

    static boost::uint64_t small_sigma_1(boost::uint64_t x)
        { return implementation::rotr<19>(x) ^ implementation::rotr<61>(x) ^ implementation::shr<6>(x); }

    static boost::uint64_t k(std::size_t t)
    {
        static const boost::uint64_t k_set[] =
        {
            0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
            0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
            0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
            0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
            0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
            0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
            0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
            0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
            0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
            0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
            0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
            0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
            0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
            0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
            0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
            0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
            0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
            0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
            0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
            0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
        };

        assert (t < 80);

        return k_set[t];
    }
};

/*************************************************************************************************/

template <>
struct sha_traits<sha384_t>
{
    typedef class sha384_t                           hash_type;
    typedef sha_traits<sha512_t>::digest_type        digest_type;
    typedef sha_traits<sha512_t>::message_block_type message_block_type;
    typedef sha_traits<sha512_t>::schedule_type      schedule_type;

    enum
    {
        max_message_bitsize_k = sha_traits<sha512_t>::max_message_bitsize_k,
        message_blocksize_k = sha_traits<sha512_t>::message_blocksize_k
    };

    static void reset_digest(digest_type& digest)
    {
        digest[0] = 0xcbbb9d5dc1059ed8ULL;
        digest[1] = 0x629a292a367cd507ULL;
        digest[2] = 0x9159015a3070dd17ULL;
        digest[3] = 0x152fecd8f70e5939ULL;
        digest[4] = 0x67332667ffc00b31ULL;
        digest[5] = 0x8eb44a8768581511ULL;
        digest[6] = 0xdb0c2e0d64f98fa7ULL;
        digest[7] = 0x47b5481dbefa4fa4ULL;
    }

    static void digest_message_block(digest_type& digest, const message_block_type& message_block)
        { sha_2_digest_message_block<sha_traits<hash_type> >(digest, message_block); }

    static boost::uint64_t big_sigma_0(boost::uint64_t x)
        { return sha_traits<sha512_t>::big_sigma_0(x); }

    static boost::uint64_t big_sigma_1(boost::uint64_t x)
        { return sha_traits<sha512_t>::big_sigma_1(x); }

    static boost::uint64_t small_sigma_0(boost::uint64_t x)
        { return sha_traits<sha512_t>::small_sigma_0(x); }

    static boost::uint64_t small_sigma_1(boost::uint64_t x)
        { return sha_traits<sha512_t>::small_sigma_1(x); }

    static boost::uint64_t k(std::size_t x)
        { return sha_traits<sha512_t>::k(x); }
};

/*************************************************************************************************/

#endif

/*************************************************************************************************/

} // namespace implementation

/*************************************************************************************************/

class sha1_t
{
public:
#if !defined(ADOBE_NO_DOCUMENTATION)
    typedef implementation::sha_traits<sha1_t>   traits_type;
#endif
    typedef traits_type::digest_type                    digest_type;

    template <typename I>
    inline digest_type digest(I first, I last)
    {
        enum { ibits_k = implementation::bitsizeof<typename std::iterator_traits::value_type>::value };

        return digest(first, implementation::long_distance(first, last) * ibits_k);
    }

    template <typename I>
    inline digest_type digest(I first, boost::uint64_t num_bits)
    {
        traits_type().reset_digest(digest_m);

        implementation::block_and_digest<traits_type>(digest_m, first, num_bits);

        return digest_m;
    }

private:
    digest_type digest_m;
};

/*************************************************************************************************/

class sha224_t
{
public:
#if !defined(ADOBE_NO_DOCUMENTATION)
    typedef implementation::sha_traits<sha224_t> traits_type;
#endif
    typedef boost::array<boost::uint32_t, 7>            digest_type;

    template <typename I>
    inline digest_type digest(I first, I last)
    {
        enum { ibits_k = implementation::bitsizeof<typename std::iterator_traits::value_type>::value };

        return digest(first, implementation::long_distance(first, last) * ibits_k);
    }

    template <typename I>
    inline digest_type digest(I first, boost::uint64_t num_bits)
    {
        traits_type().reset_digest(digest_m);

        implementation::block_and_digest<traits_type>(digest_m, first, num_bits);

        return crop_digest(digest_m);
    }

private:
    inline digest_type crop_digest(traits_type::digest_type& digest)
    {
        digest_type result;

        std::copy(digest.begin(), digest.begin() + digest_type::static_size, &result[0]);

        return result;
    }

    traits_type::digest_type digest_m;
};

/*************************************************************************************************/

class sha256_t
{
public:
#if !defined(ADOBE_NO_DOCUMENTATION)
    typedef implementation::sha_traits<sha256_t> traits_type;
#endif
    typedef traits_type::digest_type                    digest_type;

    template <typename I>
    inline digest_type digest(I first, I last)
    {
        enum { ibits_k = implementation::bitsizeof<typename std::iterator_traits::value_type>::value };

        return digest(first, implementation::long_distance(first, last) * ibits_k);
    }

    template <typename I>
    inline digest_type digest(I first, boost::uint64_t num_bits)
    {
        traits_type().reset_digest(digest_m);

        implementation::block_and_digest<traits_type>(digest_m, first, num_bits);

        return digest_m;
    }

private:
    digest_type digest_m;
};

/*************************************************************************************************/

class sha512_t
{
public:
#if !defined(ADOBE_NO_DOCUMENTATION)
    typedef implementation::sha_traits<sha512_t> traits_type;
#endif
    typedef traits_type::digest_type                    digest_type;

    template <typename I>
    inline digest_type digest(I first, I last)
    {
        enum { ibits_k = implementation::bitsizeof<typename std::iterator_traits::value_type>::value };

        return digest(first, implementation::long_distance(first, last) * ibits_k);
    }

    template <typename I>
    inline digest_type digest(I first, boost::uint64_t num_bits)
    {
        traits_type().reset_digest(digest_m);

        implementation::block_and_digest<traits_type>(digest_m, first, num_bits);

        return digest_m;
    }

private:
    digest_type digest_m;
};

/*************************************************************************************************/

class sha384_t
{
public:
#if !defined(ADOBE_NO_DOCUMENTATION)
    typedef implementation::sha_traits<sha384_t> traits_type;
#endif
    typedef boost::array<boost::uint64_t, 6>            digest_type;

    template <typename I>
    inline digest_type digest(I first, I last)
    {
        enum { ibits_k = implementation::bitsizeof<typename std::iterator_traits::value_type>::value };

        return digest(first, implementation::long_distance(first, last) * ibits_k);
    }

    template <typename I>
    inline digest_type digest(I first, boost::uint64_t num_bits)
    {
        traits_type().reset_digest(digest_m);

        implementation::block_and_digest<traits_type>(digest_m, first, num_bits);

        return crop_digest(digest_m);
    }

private:
    inline digest_type crop_digest(traits_type::digest_type& digest)
    {
        digest_type result;

        std::copy(digest.begin(), digest.begin() + digest_type::static_size, &result[0]);

        return result;
    }

    traits_type::digest_type digest_m;
};

/*************************************************************************************************/

} // namespace adobe

/*************************************************************************************************/

#endif

/*************************************************************************************************/


//            Copyright Fernando Vilas 2012.
//     Based on stoer_wagner_test.cpp by Daniel Trebbien.
// Distributed under the Boost Software License, Version 1.0.
//   (See accompanying file LICENSE_1_0.txt or the copy at
//         http://www.boost.org/LICENSE_1_0.txt)

#include <fstream>
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/connected_components.hpp>
#include <boost/graph/exception.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/read_dimacs.hpp>
#include <boost/graph/maximum_adjacency_search.hpp>
#include <boost/graph/visitors.hpp>
#include <boost/graph/property_maps/constant_property_map.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/tuple/tuple_io.hpp>

#include <boost/graph/iteration_macros.hpp>

typedef boost::adjacency_list< boost::vecS, boost::vecS, boost::undirectedS,
    boost::no_property, boost::property< boost::edge_weight_t, int > >
    undirected_graph;
typedef boost::property_map< undirected_graph, boost::edge_weight_t >::type
    weight_map_type;
typedef boost::property_traits< weight_map_type >::value_type weight_type;

typedef boost::adjacency_list< boost::vecS, boost::vecS, boost::undirectedS >
    undirected_unweighted_graph;

std::string test_dir;

boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[])
{
    if (argc != 2)
    {
        std::cerr << "Usage: " << argv[0] << " path-to-libs-graph-test"
                  << std::endl;
        throw boost::unit_test::framework::setup_error(
            "Invalid command line arguments");
    }
    test_dir = argv[1];
    return 0;
}

struct edge_t
{
    unsigned long first;
    unsigned long second;
};

template < typename Graph, typename KeyedUpdatablePriorityQueue >
class mas_edge_connectivity_visitor : public boost::default_mas_visitor
{
public:
    typedef typename boost::graph_traits< Graph >::vertex_descriptor
        vertex_descriptor;
    typedef typename KeyedUpdatablePriorityQueue::key_type weight_type;
#if 0
    mas_edge_connectivity_visitor(const mas_edge_connectivity_visitor<Graph, KeyedUpdatablePriorityQueue>& r)
      : m_pq(r.m_pq), m_curr(r.m_curr), m_prev(r.m_prev),
        m_reach_weight(r.m_reach_weight) {
          BOOST_TEST_MESSAGE( "COPY CTOR" );
        }
#endif
    explicit mas_edge_connectivity_visitor(KeyedUpdatablePriorityQueue& pq)
    : m_pq(pq)
    , m_curr(new vertex_descriptor(0))
    , m_prev(new vertex_descriptor(0))
    , m_reach_weight(new weight_type(0))
    {
        //    BOOST_TEST_MESSAGE( "CTOR" );
    }

    void clear()
    {
        *m_curr = 0;
        *m_prev = 0;
        *m_reach_weight = 0;
    }

    // template <typename Vertex> //, typename Graph>
    // void start_vertex(Vertex u, const Graph& g) {
    void start_vertex(vertex_descriptor u, const Graph& g)
    {
        *m_prev = *m_curr;
        *m_curr = u;
        // BOOST_TEST_MESSAGE( "Initializing Vertex(weight): " << u << "(" <<
        // *m_reach_weight << ")" );
        *m_reach_weight = get(m_pq.keys(), u);
    }

    vertex_descriptor curr() const { return *m_curr; }
    vertex_descriptor prev() const { return *m_prev; }
    weight_type reach_weight() const { return *m_reach_weight; }

private:
    const KeyedUpdatablePriorityQueue& m_pq;
    boost::shared_ptr< vertex_descriptor > m_curr, m_prev;
    boost::shared_ptr< weight_type > m_reach_weight;
};

// the example from Stoer & Wagner (1997)
// Check various implementations of the ArgPack where
// the weights are provided in it, and one case where
// they are not.
BOOST_AUTO_TEST_CASE(test0)
{
    typedef boost::graph_traits< undirected_graph >::vertex_descriptor
        vertex_descriptor;
    typedef boost::graph_traits< undirected_graph >::edge_descriptor
        edge_descriptor;

    edge_t edges[] = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 0, 4 }, { 1, 4 },
        { 1, 5 }, { 2, 6 }, { 3, 6 }, { 3, 7 }, { 4, 5 }, { 5, 6 }, { 6, 7 } };
    weight_type ws[] = { 2, 3, 4, 3, 2, 2, 2, 2, 2, 3, 1, 3 };
    undirected_graph g(edges, edges + 12, ws, 8, 12);

    weight_map_type weights = get(boost::edge_weight, g);

    std::map< vertex_descriptor, vertex_descriptor > assignment;
    boost::associative_property_map<
        std::map< vertex_descriptor, vertex_descriptor > >
        assignments(assignment);

    typedef boost::shared_array_property_map< weight_type,
        boost::property_map< undirected_graph,
            boost::vertex_index_t >::const_type >
        distances_type;
    distances_type distances = boost::make_shared_array_property_map(
        num_vertices(g), weight_type(0), get(boost::vertex_index, g));
    typedef std::vector< vertex_descriptor >::size_type index_in_heap_type;
    typedef boost::shared_array_property_map< index_in_heap_type,
        boost::property_map< undirected_graph,
            boost::vertex_index_t >::const_type >
        indicesInHeap_type;
    indicesInHeap_type indicesInHeap = boost::make_shared_array_property_map(
        num_vertices(g), index_in_heap_type(-1), get(boost::vertex_index, g));
    boost::d_ary_heap_indirect< vertex_descriptor, 22, indicesInHeap_type,
        distances_type, std::greater< weight_type > >
        pq(distances, indicesInHeap);

    mas_edge_connectivity_visitor< undirected_graph,
        boost::d_ary_heap_indirect< vertex_descriptor, 22, indicesInHeap_type,
            distances_type, std::greater< weight_type > > >
        test_vis(pq);

    boost::maximum_adjacency_search(g,
        boost::weight_map(weights)
            .visitor(test_vis)
            .root_vertex(*vertices(g).first)
            .vertex_assignment_map(assignments)
            .max_priority_queue(pq));

    BOOST_CHECK_EQUAL(test_vis.curr(), vertex_descriptor(7));
    BOOST_CHECK_EQUAL(test_vis.prev(), vertex_descriptor(6));
    BOOST_CHECK_EQUAL(test_vis.reach_weight(), 5);

    test_vis.clear();
    boost::maximum_adjacency_search(g,
        boost::weight_map(weights)
            .visitor(test_vis)
            .root_vertex(*vertices(g).first)
            .max_priority_queue(pq));

    BOOST_CHECK_EQUAL(test_vis.curr(), vertex_descriptor(7));
    BOOST_CHECK_EQUAL(test_vis.prev(), vertex_descriptor(6));
    BOOST_CHECK_EQUAL(test_vis.reach_weight(), 5);

    test_vis.clear();
    boost::maximum_adjacency_search(
        g, boost::weight_map(weights).visitor(test_vis).max_priority_queue(pq));

    BOOST_CHECK_EQUAL(test_vis.curr(), vertex_descriptor(7));
    BOOST_CHECK_EQUAL(test_vis.prev(), vertex_descriptor(6));
    BOOST_CHECK_EQUAL(test_vis.reach_weight(), 5);

    boost::maximum_adjacency_search(g,
        boost::weight_map(weights).visitor(
            boost::make_mas_visitor(boost::null_visitor())));

    boost::maximum_adjacency_search(g, boost::weight_map(weights));

    boost::maximum_adjacency_search(g, boost::root_vertex(*vertices(g).first));

    test_vis.clear();
    boost::maximum_adjacency_search(g,
        boost::weight_map(
            boost::make_constant_property< edge_descriptor >(weight_type(1)))
            .visitor(test_vis)
            .max_priority_queue(pq));
    BOOST_CHECK_EQUAL(test_vis.curr(), vertex_descriptor(7));
    BOOST_CHECK_EQUAL(test_vis.prev(), vertex_descriptor(3));
    BOOST_CHECK_EQUAL(test_vis.reach_weight(), 2);
}

// Check the unweighted case
// with and without providing a weight_map
BOOST_AUTO_TEST_CASE(test1)
{
    typedef boost::graph_traits<
        undirected_unweighted_graph >::vertex_descriptor vertex_descriptor;
    typedef boost::graph_traits< undirected_unweighted_graph >::edge_descriptor
        edge_descriptor;

    edge_t edge_list[] = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 0, 4 }, { 1, 4 },
        { 1, 5 }, { 2, 6 }, { 3, 6 }, { 3, 7 }, { 4, 5 }, { 5, 6 }, { 6, 7 } };
    undirected_unweighted_graph g(edge_list, edge_list + 12, 8);

    std::map< vertex_descriptor, vertex_descriptor > assignment;
    boost::associative_property_map<
        std::map< vertex_descriptor, vertex_descriptor > >
        assignments(assignment);

    typedef unsigned weight_type;
    typedef boost::shared_array_property_map< weight_type,
        boost::property_map< undirected_graph,
            boost::vertex_index_t >::const_type >
        distances_type;
    distances_type distances = boost::make_shared_array_property_map(
        num_vertices(g), weight_type(0), get(boost::vertex_index, g));
    typedef std::vector< vertex_descriptor >::size_type index_in_heap_type;
    typedef boost::shared_array_property_map< index_in_heap_type,
        boost::property_map< undirected_graph,
            boost::vertex_index_t >::const_type >
        indicesInHeap_type;
    indicesInHeap_type indicesInHeap = boost::make_shared_array_property_map(
        num_vertices(g), index_in_heap_type(-1), get(boost::vertex_index, g));
    boost::d_ary_heap_indirect< vertex_descriptor, 22, indicesInHeap_type,
        distances_type, std::greater< weight_type > >
        pq(distances, indicesInHeap);

    mas_edge_connectivity_visitor< undirected_unweighted_graph,
        boost::d_ary_heap_indirect< vertex_descriptor, 22, indicesInHeap_type,
            distances_type, std::greater< weight_type > > >
        test_vis(pq);

    boost::maximum_adjacency_search(g,
        boost::weight_map(
            boost::make_constant_property< edge_descriptor >(weight_type(1)))
            .visitor(test_vis)
            .max_priority_queue(pq));

    BOOST_CHECK_EQUAL(test_vis.curr(), vertex_descriptor(7));
    BOOST_CHECK_EQUAL(test_vis.prev(), vertex_descriptor(3));
    BOOST_CHECK_EQUAL(test_vis.reach_weight(), weight_type(2));

    weight_type ws[] = { 2, 3, 4, 3, 2, 2, 2, 2, 2, 3, 1, 3 };
    std::map< edge_descriptor, weight_type > wm;

    weight_type i = 0;
    BGL_FORALL_EDGES(e, g, undirected_unweighted_graph)
    {
        wm[e] = ws[i];
        ++i;
    }
    boost::associative_property_map< std::map< edge_descriptor, weight_type > >
        ws_map(wm);

    boost::maximum_adjacency_search(
        g, boost::weight_map(ws_map).visitor(test_vis).max_priority_queue(pq));
    BOOST_CHECK_EQUAL(test_vis.curr(), vertex_descriptor(7));
    BOOST_CHECK_EQUAL(test_vis.prev(), vertex_descriptor(6));
    BOOST_CHECK_EQUAL(test_vis.reach_weight(), weight_type(5));
}

#include <boost/graph/iteration_macros_undef.hpp>