#ifndef __HAL_HPP__
#define __HAL_HPP__
#include <vector>
#include <string>
#include <algorithm>
#include <armadillo>

namespace wove
{
class hal
{
protected:
    std::string corpus_name;
public:
    hal(std::string corpus_name);
    ~hal();
    void word_vectors(std::vector<std::string> tokens, std::vector<std::string> vocab, bool save=true);
    void find_distance(std::string word);
    arma::sp_mat build_hal(std::vector<std::string>tokens, std::vector<std::string> vocab, bool reverse);
};
}
#endif // !__HAL_HPP__


///////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2014 MaidSafe.net Limited
//
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)
//
///////////////////////////////////////////////////////////////////////////////

#include <boost/test/unit_test.hpp>
#include <cstdint>
#include <maidsafe/crux/detail/sequence_number.hpp>

using maidsafe::crux::detail::sequence_number;

template<class SN> void test_limits()
{
    constexpr auto max = SN::max_value;

    BOOST_REQUIRE(SN(0)       < SN(1));
    BOOST_REQUIRE(SN(0)       < SN(max/2));
    BOOST_REQUIRE(SN(max)     < SN(max/2));
    BOOST_REQUIRE(SN(max/2+1) < SN(0));
    BOOST_REQUIRE(SN(max/2+1) < SN(max));
    BOOST_REQUIRE(SN(max)     < SN(0));
}

BOOST_AUTO_TEST_SUITE(sequence_suite)

BOOST_AUTO_TEST_CASE(sequence_number_uint8)
{
    test_limits<sequence_number<std::uint8_t>>();
}

BOOST_AUTO_TEST_CASE(sequence_number_uint16)
{
    test_limits<sequence_number<std::uint16_t>>();
}

BOOST_AUTO_TEST_CASE(sequence_number_uint32)
{
    test_limits<sequence_number<std::uint32_t>>();
}

BOOST_AUTO_TEST_CASE(sequence_number_uint32_custom_max)
{
    using T = std::uint32_t;
    constexpr T max = std::numeric_limits<T>::max();

    test_limits<sequence_number<T, max/2>>();
    test_limits<sequence_number<T, max/4>>();
    test_limits<sequence_number<T, max/8>>();
    test_limits<sequence_number<T, max/16>>();
}

BOOST_AUTO_TEST_CASE(sequence_number_pre_increment)
{
    using T = std::uint8_t;
    constexpr T max = std::numeric_limits<T>::max()/2;
    sequence_number<T, max> s;
    std::uint32_t counter = 0;
    while ((++s).value()) { ++counter; }
    BOOST_REQUIRE_EQUAL(counter, max);
}

BOOST_AUTO_TEST_CASE(sequence_number_post_increment)
{
    using T = std::uint8_t;
    constexpr T max = std::numeric_limits<T>::max()/2;
    sequence_number<T, max> s;
    s++;
    std::uint32_t counter = 0;
    while ((s++).value()) { ++counter; }
    BOOST_REQUIRE_EQUAL(counter, max);
}

BOOST_AUTO_TEST_CASE(distances)
{
    using T = std::uint32_t;
    constexpr T max = sequence_number<T>::max_value;
    sequence_number<T> zero(0);
    sequence_number<T> one(1);
    sequence_number<T> half(max/2);
    sequence_number<T> almost_largest(max-1);
    sequence_number<T> largest(max);

    BOOST_CHECK_EQUAL(zero.distance(one), 1);
    BOOST_CHECK_EQUAL(one.distance(zero), -1);
    BOOST_CHECK_EQUAL(almost_largest.distance(largest), 1);
    BOOST_CHECK_EQUAL(largest.distance(almost_largest), -1);
    BOOST_CHECK_EQUAL(largest.distance(zero), 1);
    BOOST_CHECK_EQUAL(zero.distance(largest), -1);
    BOOST_CHECK_EQUAL(zero.distance(half), half.value());
    BOOST_CHECK_EQUAL(half.distance(zero), -half.value());
    BOOST_CHECK_EQUAL(one.distance(half), half.value() - 1);
    BOOST_CHECK_EQUAL(half.distance(one), -(half.value() - 1));
    BOOST_CHECK_EQUAL(largest.distance(half), -(half.value() + 1));
    BOOST_CHECK_EQUAL(half.distance(largest), half.value() + 1);
    BOOST_CHECK_EQUAL(largest.distance(one), 2);
    BOOST_CHECK_EQUAL(one.distance(largest), -2);
    BOOST_CHECK_EQUAL(almost_largest.distance(one), 3);
    BOOST_CHECK_EQUAL(one.distance(almost_largest), -3);
}

BOOST_AUTO_TEST_SUITE_END()


#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/karma.hpp>

#include <iostream>
#include <string>
#include <vector>
#include <vector>
#include <cstdlib>
#include <ctime>

namespace karma = boost::spirit::karma;

namespace client{
  template <typename OutputIterator>
    struct matrix_grammar : karma::grammar<OutputIterator, std::vector<std::vector<int> >()>{
      matrix_grammar() : matrix_grammar::base_type(matrix){
        using karma::int_;
        using karma::right_align;
        using karma::eol;

        element = right_align(10)[int_];
        row = '|' << *element << '|';
        matrix = row % eol;
      }

      karma::rule<OutputIterator, std::vector<std::vector<int> >()> matrix;
      karma::rule<OutputIterator, std::vector<int>()> row;
      karma::rule<OutputIterator, int()> element;
    };

  template <typename OutputIterator>
    bool generate_matrix(OutputIterator& sink, std::vector<std::vector<int> > const& v){
      matrix_grammar<OutputIterator>matrix;
      return karma::generate(
          sink,
          matrix,
          v
      );
    }
}

int main(){
  std::vector<std::vector<int> > v;

  std::srand((unsigned int)std::time(NULL));
  std::size_t rows = std::rand() / (RAND_MAX / 10);
  std::size_t columns = std::rand() / (RAND_MAX / 10);

  v.resize(rows);
  for(std::size_t row = 0; row < rows; ++row){
    v[row].resize(columns);
    std::generate(v[row].begin(), v[row].end(), std::rand);
  }

  std::string generated;
  std::back_insert_iterator<std::string> sink(generated);
  if(!client::generate_matrix(sink, v)){
    std::cout << "Generating failed\n";
  }
  else{
    std::cout << "Generated:\n" << generated << std::endl;
  }

  return 0;
}


#pragma once

#include <roerei/generic/common.hpp>
#include <roerei/generic/encapsulated_vector.hpp>

#include <boost/optional.hpp>

#include <vector>
#include <map>

namespace roerei
{

template<typename M, typename N, typename T>
class full_matrix_t
{
public:
    typedef M row_key_t;
    typedef N column_key_t;

    typedef std::vector<T> buffer_t;

    template<typename MATRIX, typename ITERATOR>
    class row_proxy_base_t
    {
    public:
        typedef ITERATOR iterator;
        typedef MATRIX parent_t;

    private:
        friend MATRIX;

        MATRIX& parent;

    public:
        M const row_i;

    private:
        row_proxy_base_t(MATRIX& _parent, M const _row_i)
            : parent(_parent)
            , row_i(_row_i)
        {}

    public:
        T& operator[](N j)
        {
            assert(j < parent.n);
			return parent.data[row_i.unseal() * parent.n + j.unseal()];
        }

        T const operator[](N j) const
        {
            assert(j < parent.n);
			return parent.data[row_i.unseal() * parent.n + j.unseal()];
        }

        iterator begin() const
        {
			return parent.data.begin() + (row_i.unseal() * parent.n);
        }

        iterator end() const
        {
			return parent.data.begin() + ((row_i.unseal() + 1) * parent.n);
        }

        size_t size() const
        {
            return parent.n;
        }

        size_t nonempty_size() const
        {
            return parent.n;
        }
    };

    typedef row_proxy_base_t<full_matrix_t<M, N, T>, typename buffer_t::iterator> row_proxy_t;
    typedef row_proxy_base_t<full_matrix_t<M, N, T> const, typename buffer_t::const_iterator> const_row_proxy_t;

private:
    size_t m, n;
    buffer_t data;

public:
    full_matrix_t(full_matrix_t&&) = default;
    full_matrix_t(full_matrix_t&) = delete;

    full_matrix_t(size_t _m, size_t _n)
        : m(_m)
        , n(_n)
        , data(m*n)
    {}

    row_proxy_t operator[](M i)
    {
        assert(i < m);
        return row_proxy_t(*this, i);
    }

    const_row_proxy_t const operator[](M i) const
    {
        assert(i < m);
        return const_row_proxy_t(*this, i);
    }

    size_t size_m() const
    {
        return m;
    }

    size_t size_n() const
    {
        return n;
    }

    template<typename F>
    void iterate(F const& f)
    {
        for(size_t i = 0; i < m; ++i)
            f(row_proxy_t(*this, M(i)));
    }

    template<typename F>
    void citerate(F const& f) const
    {
        for(size_t i = 0; i < m; ++i)
            f(const_row_proxy_t(*this, M(i)));
    }

    template<typename F>
    void iterate(F const& f) const
    {
        citerate(f);
    }
};

}


/*

Copyright (c) 2005-2015, University of Oxford.
All rights reserved.

University of Oxford means the Chancellor, Masters and Scholars of the
University of Oxford, having an administrative office at Wellington
Square, Oxford OX1 2JD, UK.

This file is part of Chaste.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
 * Neither the name of the University of Oxford nor the names of its
   contributors may be used to endorse or promote products derived from this
   software without specific prior written permission.

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

*/

#ifndef WNTCELLCYCLEODESYSTEM_HPP_
#define WNTCELLCYCLEODESYSTEM_HPP_

#include "ChasteSerialization.hpp"
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/shared_ptr.hpp>

#include <cmath>
#include <iostream>

#include "AbstractOdeSystem.hpp"
#include "AbstractCellMutationState.hpp"

/**
 * Represents the Mirams et al. system of ODEs, based on Swat et al. (2004)
 * [doi:10.1093/bioinformatics/bth110]
 * and a simple Wnt model (unpublished)
 *
 * The variables are
 *
 * 0. r = pRb
 * 1. e = E2F1
 * 2. i = CycD (inactive)
 * 3. j = CycD (active)
 * 4. p = pRb-p
 * 5. c = destruction complex (Active)
 * 6. b1 = Beta-Catenin (from 1st allele)
 * 7. b2 = Beta-Catenin (from 1st allele)
 * 8. WntLevel
 */
class WntCellCycleOdeSystem : public AbstractOdeSystem
{
private:

    /**
     * Parameters for the Swat et al. (2004) model
     */

    /** Dimensional parameter k_2. */
    double mk2d;
    /** Dimensional parameter k_3. */
    double mk3d;
    /** Dimensional parameter k_34. */
    double mk34d;
    /** Dimensional parameter k_2. */
    double mk43d;
    /** Dimensional parameter k_23. */
    double mk23d;
    /** Dimensional parameter a. */
    double mad;
    /** Dimensional parameter J_11. */
    double mJ11d;
    /** Dimensional parameter J_12. */
    double mJ12d;
    /** Dimensional parameter J_13. */
    double mJ13d;
    /** Dimensional parameter J_13. */
    double mJ61d;
    /** Dimensional parameter J_62. */
    double mJ62d;
    /** Dimensional parameter J_63. */
    double mJ63d;
    /** Dimensional parameter K_m1. */
    double mKm1d;
    /** Dimensional parameter k_p. */
    double mkpd;
    /** Dimensionless parameter phi_r. */
    double mphi_r;
    /** Dimensionless parameter phi_i. */
    double mphi_i;
    /** Dimensionless parameter phi_j. */
    double mphi_j;
    /** Dimensionless parameter phi_p. */
    double mphi_p;
    /** Dimensional parameter a_2. */
    double ma2d;
    /** Dimensional parameter a_3. */
    double ma3d;
    /** Dimensional parameter a_4. */
    double ma4d;
    /** Dimensional parameter a_5. */
    double ma5d;
    /** Dimensional parameter k_16. */
    double mk16d;
    /** Dimensional parameter k_61. */
    double mk61d;
    /** Dimensionless parameter phi_E2F1. */
    double mPhiE2F1;

    /** The mutation state of the cell - Wnt pathway behaviour (and hence cell cycle time) changes depending on this */
    boost::shared_ptr<AbstractCellMutationState> mpMutationState;

    /** The Wnt level (this affects the ODE system). */
    double mWntLevel;

    friend class boost::serialization::access;
    /**
     * Serialize the object and its member variables.
     *
     * @param archive the archive
     * @param version the current version of this class
     */
    template<class Archive>
    void serialize(Archive & archive, const unsigned int version)
    {
        archive & boost::serialization::base_object<AbstractOdeSystem>(*this);
    }

public:

    /**
     * Constructor.
     *
     * @param wntLevel is a non-dimensional Wnt value between 0 and 1. This sets up the Wnt pathway in its steady state.
     * @param pMutationState optional mutation state (affects the ODE system)
     * @param stateVariables optional initial conditions for state variables (only used in archiving)
     */
    WntCellCycleOdeSystem(double wntLevel=0.0,
                          boost::shared_ptr<AbstractCellMutationState> pMutationState=boost::shared_ptr<AbstractCellMutationState>(),
                          std::vector<double> stateVariables=std::vector<double>());

    /**
     * Destructor.
     */
    ~WntCellCycleOdeSystem();

    /**
     * Initialise parameter values.
     */
    void Init();

    /**
     * Set the mutation state of the cell.
     *
     * This should be called by the relevant cell-cycle model before any solving
     * of the ODE system (as it is used to evaluate the Y derivatives).
     *
     * @param pMutationState the mutation state.
     */
    void SetMutationState(boost::shared_ptr<AbstractCellMutationState> pMutationState);

    /**
     * Called by the archive function on the Wnt cell-cycle model.
     *
     * @return #mpMutationState the mutation state of the cell.
     */
    const boost::shared_ptr<AbstractCellMutationState> GetMutationState() const;

    /**
     * Compute the RHS of the WntCellCycle system of ODEs.
     *
     * Returns a vector representing the RHS of the ODEs at each time step, y' = [y1' ... yn'].
     * An ODE solver will call this function repeatedly to solve for y = [y1 ... yn].
     *
     * @param time used to evaluate the RHS.
     * @param rY value of the solution vector used to evaluate the RHS.
     * @param rDY filled in with the resulting derivatives (using Alarcons et al. (2004) system of equations).
     */
    void EvaluateYDerivatives(double time, const std::vector<double>& rY, std::vector<double>& rDY);

    /**
     * This also contains a calculation of dY[1], copied from EvaluateYDerivatives.
     * Ensure they do not get out of sync!
     *
     * @param time at which to calculate whether the stopping event has occurred
     * @param rY value of the solution vector used to evaluate the RHS
     *
     * @return whether we have reached the stopping event
     */
    bool CalculateStoppingEvent(double time, const std::vector<double>& rY);

    /**
     * When using CVODE this function is called instead of CalculateStoppingEvent.
     * It allows the point at which rY[1] reaches 1 to be found to greater precision.
     *
     * @param time at which to calculate whether the stopping event has occurred
     * @param rY value of the solution vector used to evaluate the RHS
     *
     * @return function value - giving CVODE an estimate of how close we are to the root.
     */
    double CalculateRootFunction(double time, const std::vector<double>& rY);

    /**
     * @return #mWntLevel.
     */
    double GetWntLevel() const;
};

// Declare identifier for the serializer
#include "SerializationExportWrapper.hpp"
CHASTE_CLASS_EXPORT(WntCellCycleOdeSystem)

namespace boost
{
namespace serialization
{
/**
 * Serialize information required to construct a WntCellCycleOdeSystem.
 */
template<class Archive>
inline void save_construct_data(
    Archive & ar, const WntCellCycleOdeSystem * t, const unsigned int file_version)
{
    // Save data required to construct instance
    const double wnt_level = t->GetWntLevel();
    ar & wnt_level;

    const boost::shared_ptr<AbstractCellMutationState> p_mutation_state = t->GetMutationState();
    ar & p_mutation_state;

    const std::vector<double> state_variables = t->rGetConstStateVariables();
    ar & state_variables;
}

/**
 * De-serialize constructor parameters and initialise a WntCellCycleOdeSystem.
 */
template<class Archive>
inline void load_construct_data(
    Archive & ar, WntCellCycleOdeSystem * t, const unsigned int file_version)
{
    // Retrieve data from archive required to construct new instance
    double wnt_level;
    ar & wnt_level;

    boost::shared_ptr<AbstractCellMutationState> p_mutation_state;
    ar & p_mutation_state;

    std::vector<double> state_variables;
    ar & state_variables;

    // Invoke inplace constructor to initialise instance
    ::new(t)WntCellCycleOdeSystem(wnt_level, p_mutation_state, state_variables);
}
}
} // namespace ...

#endif /*WNTCELLCYCLEODESYSTEM_HPP_*/


#include <ros/ros.h>
#include <ros/time.h>
#include <std_msgs/Float32.h>
#include <std_msgs/Float64.h>
#include <nav_msgs/Odometry.h>
#include <geometry_msgs/Point.h>
#include <mongodb_store/SetParam.h>
#include <boost/thread.hpp>

#include <math.h>

int save;

ros::Publisher mileage_pub;
double total_distance;
geometry_msgs::Point last_point;
ros::ServiceClient client;
mongodb_store::SetParam srv;
int save_interval;
bool updated;
boost::mutex mutex;

bool isUpdated() {
    boost::lock_guard<boost::mutex> lock(mutex);
    return updated;
}

void setUpdated(bool up) {
    boost::lock_guard<boost::mutex> lock(mutex);
    updated = up;
}

void updateMileageCallback(const std_msgs::Float32::ConstPtr &mileage)
{
    ROS_INFO("Update mileage");
    if(mileage->data > total_distance){
        total_distance = mileage->data;
    }
    setUpdated(true);
}

void callback(const nav_msgs::Odometry::ConstPtr &odom)
{
    if(isnan(last_point.x) && isnan(last_point.y) && isnan(last_point.z)) {
        last_point = odom->pose.pose.position;
        return;
    }

    double distance = sqrt(pow(odom->pose.pose.position.x-last_point.x,2)+pow(odom->pose.pose.position.y-last_point.y,2));
    total_distance += distance;

    std_msgs::Float32 pub_dist;
    pub_dist.data = (float) total_distance;
    mileage_pub.publish(pub_dist);

    last_point = odom->pose.pose.position;

    if(save % save_interval == 0) {
        ros::param::set("/saved_mileage",total_distance);
        srv.request.param = "saved_mileage";
        if (client.call(srv))
            ROS_DEBUG("Save mileage: success");
        else
            ROS_WARN("Save mileage: failed");
        save = 0;
    }
    save++;
}

void updateMileage(ros::NodeHandle &n, double timeout, std::string mileage_topic) {
    ROS_INFO("Waiting for mileage update from: %s", mileage_topic.c_str());
    ros::Subscriber sub = n.subscribe(mileage_topic, 1, &updateMileageCallback);
    ros::Time end;
    end.fromSec(ros::Time::now().toSec() + timeout);
    while(!isUpdated() && ros::Time::now() < end) {
        ros::spinOnce();
    }
    sub.shutdown();
    ROS_INFO("%s", isUpdated() ? "Updated from topic" : "Timed out");
}

int main(int argc, char **argv)
{
    // Set up ROS.
    ros::init(argc, argv, "odom_mileage");
    ros::NodeHandle n;

    last_point.x = NAN;
    last_point.y = NAN;
    last_point.z = NAN;

    save = 1;
    updated = false;

    // Declare variables that can be modified by launch file or command line.
    std::string mileage_topic;
    std::string update_mileage_topic;
    std::string odom_topic;
    double timeout;

    // Initialize node parameters from launch file or command line.
    // Use a private node handle so that multiple instances of the node can be run simultaneously
    // while using different parameters.
    ros::NodeHandle private_node_handle_("~");
    private_node_handle_.param("mileage_topic", mileage_topic, std::string("/odom_mileage"));
    private_node_handle_.param("initial_mileage_topic", update_mileage_topic, std::string("/mileage"));
    private_node_handle_.param("odom_topic", odom_topic, std::string("/odom"));
    private_node_handle_.param("save_interval", save_interval, 500);
    private_node_handle_.param("init_update_timeout", timeout, 10.0);
    n.param("/saved_mileage", total_distance, 0.0);
    updateMileage(n, timeout, update_mileage_topic);

    client = n.serviceClient<mongodb_store::SetParam>("/config_manager/save_param");

    //Create a subscriber
    ros::Subscriber odom_sub = n.subscribe(odom_topic.c_str(), 50, &callback);
//    ros::Subscriber sub = n.subscribe("/mileage", 1, &updateMileageCallback);

    // Create a publisher
    mileage_pub = n.advertise<std_msgs::Float32>(mileage_topic.c_str(), 10);

    ros::spin();
    return 0;
}


/*
 * Copyright (c) 2017-2018 Nicholas Corgan (n.corgan@gmail.com)
 *
 * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
 * or copy at http://opensource.org/licenses/MIT)
 */

#include <pkmn/calculations/nature.hpp>

#include <boost/config.hpp>

namespace pkmn { namespace calculations {

    pkmn::e_nature nature(
        uint32_t personality
    )
    {
        static const size_t NUM_NATURES = 25;

        return static_cast<pkmn::e_nature>((personality % NUM_NATURES) + 1);
    }

}}


#include <iostream>
//
#include <polyvec/api.hpp>
#include <polyvec/core/log.hpp>
#include <polyvec/io/vtk_curve_writer.hpp>
#include <polyvec/misc.hpp>
//
#include <polyvec/mc/get_bounding_box.hpp>
#include <polyvec/mc/get_pixel_regions.hpp>
#include <polyvec/mc/raster_image_connectivity.hpp>
//
#include <Eigen/Geometry>

NAMESPACE_BEGIN()
NAMESPACE_END()

NAMESPACE_BEGIN ( polyvectest )
NAMESPACE_BEGIN ( mc )

int raster_image_connectivity ( int, char** ) {
    std::vector<std::string> image_addrs;
    image_addrs.emplace_back ( POLYVEC_TEST_PATH "/mc/abc.png" );
    image_addrs.emplace_back ( POLYVEC_TEST_PATH "/mc/holes001.png" );
    // image_addrs.emplace_back ( POLYVEC_TEST_PATH "/mc/chess.png" );

    printf ( "==== Testing raster image connectivity \n" );

    polyfit::Log::open ( "test_dump/log-export-multicolor-traces.txt" );

    for ( int i = 0 ; i < (int)image_addrs.size() ; ++i ) {
        std::vector<Eigen::Matrix2Xi> boundaries;
        std::vector<Eigen::Vector4d> colors;
        polyfit::mc::get_pixel_regions_from_bmp ( image_addrs[i], boundaries, colors );

        // Get the bounding box of the whole picture
        Eigen::AlignedBox<int, 2> bbox = polyfit::mc::get_bounding_box ( boundaries );

        // Can you build a connectivity
        polyfit::mc::RasterImageConnectivity raster_conn = polyfit::mc::RasterImageConnectivity::build ( boundaries );
        const bool is_mesh_okay = raster_conn.connectivity().check_sanity_slowly ( true );
        printf ( "Mesh okay status: %d \n", ( int ) is_mesh_okay );
        raster_conn.dump_as_vtk ( ::polyvec::misc::sfmt ( "test_dump/raster_image_conn_%d_ALL.vtk", i, 0 ) ) ;

        // WRITE REGIONS
        for ( int j = 0; j < ( int ) raster_conn.n_regions(); ++j ) {
            ::polyvec::VtkCurveWriter writer;
            std::vector<int> holes;
            int outer_boundary;
            raster_conn.region_to_polygon ( j, outer_boundary, holes );
            assert_break ( outer_boundary == j );

            writer.add_polyline ( raster_conn.get_polygon_points ( outer_boundary ).cast<double>() , true);
            writer.dump ( ::polyvec::misc::sfmt ( "test_dump/raster_image_conn_%d_REGION%04d.vtk", i, j ) ) ;
        } // end of regions

        // WRITE HOLES
        for ( int j = raster_conn.n_regions(); j < ( int ) raster_conn.n_polygons(); ++j ) {
            ::polyvec::VtkCurveWriter writer;
            writer.add_polyline ( raster_conn.get_polygon_points ( j ).cast<double>() , true);
            writer.dump ( ::polyvec::misc::sfmt ( "test_dump/raster_image_conn_%d_HOLE%04d.vtk", i, j ) ) ;
        } // end of holes

        // WRITE HOLES AND REGIONS
        for ( int j = 0; j < raster_conn.n_regions(); ++j ) {
            ::polyvec::VtkCurveWriter writer;
            std::vector<int> holes;
            int outer_boundary;
            raster_conn.region_to_polygon ( j, outer_boundary, holes );
            assert_break ( outer_boundary == j );

            writer.add_polyline ( raster_conn.get_polygon_points ( outer_boundary ).cast<double>() , true);

            for ( int h : holes ) {
                Eigen::Matrix2Xi bdry = raster_conn.get_polygon_points ( h );
                bdry.rowwise().reverseInPlace();
                writer.add_polyline ( bdry.cast<double>() , true);
            }

            writer.dump ( ::polyvec::misc::sfmt ( "test_dump/raster_image_conn_%d_BOTH%04d.vtk", i, j ) ) ;
        } // end of holes  + regions

    } // end of images

    return EXIT_FAILURE;
}

NAMESPACE_END ( mc )
NAMESPACE_END ( polyvectest )


/*
 *  BiasMonitor.cpp
 *  MWorksCore
 *
 *  Created by David Cox on 7/21/08.
 *  Copyright 2008 The Rowland Institute at Harvard. All rights reserved.
 *
 */

#include "BiasMonitor.h"

#include "ComponentRegistry.h"
#include <boost/lexical_cast.hpp>

BEGIN_NAMESPACE_MW

BiasMonitor::BiasMonitor(shared_ptr<Variable> _success,
							  shared_ptr<Variable> _response_index,
							  shared_ptr<Variable> _task_correlation,
							  shared_ptr<Variable> _response_bias_correlation,
                              shared_ptr<Variable> _alternation_correlation,
							  unsigned int _grace_period,
							  unsigned int _history){

	success = _success;
    response_index = _response_index;
    task_correlation = _task_correlation;
    response_bias_correlation = _response_bias_correlation;
    alternation_correlation = _alternation_correlation;

    history = _history;
    grace_period = _grace_period;

	if(_grace_period > history) {
		grace_period = _grace_period;
	} else {
		grace_period = _history;
	}

    count = 0;

	registerInput(success);
	task_corr_index = registerOutput(task_correlation);
    response_corr_index = registerOutput(response_bias_correlation);
    alternation_corr_index = registerOutput(alternation_correlation);

}

void BiasMonitor::newDataReceived(int inputIndex, const Datum& data,
                                                MWTime timeUS){

	if(inputIndex != 0){
		// error
		return;
	}

	count++;

    success_buffer.push_back(data);
    response_index_buffer.push_back(response_index->getValue());

    if(success_buffer.size() > history){
        success_buffer.pop_front();
        response_index_buffer.pop_front();
    }

    if(count < grace_period){
		return;
	}

    // compute task correlation (e.g. normalized cross correlation of responses
    // with correct answers

    std::deque<Datum>::iterator success_iterator;
    std::deque<Datum>::iterator response_iterator;

    double task_corr = 0.;
    double resp_corr = 0.;
    double alt_corr = 0.;

    success_iterator = success_buffer.begin();
    response_iterator = response_index_buffer.begin();

    int alternation = -1;
    while(success_iterator != success_buffer.end()){

        int success = (int)(*success_iterator);
        int response = (int)(*response_iterator);

        alternation *= -1;
        if(success == 0) success = -1;
        if(response == 0) response = -1;

        task_corr += success;
        resp_corr += response;
        alt_corr += alternation * response;

        success_iterator++;
        response_iterator++;
    }

    double divisor = history;

    postResults(task_corr_index, Datum(task_corr / divisor));
    postResults(response_corr_index, Datum(resp_corr / divisor));
    postResults(alternation_corr_index, Datum(alt_corr / divisor));
}

void BiasMonitor::reset(){
	success_buffer.clear();
    response_index_buffer.clear();

	count = 0;
}

shared_ptr<mw::Component> BiasMonitorFactory::createObject(std::map<std::string, std::string> parameters,
															ComponentRegistry *reg) {
	REQUIRE_ATTRIBUTES(parameters,
					   "success",
						"response_index",
						"task_correlation",
						"response_bias_correlation",
                        "alternation_correlation",
						"grace_period",
						"history");

	shared_ptr <Variable> success = reg->getVariable(parameters.find("success")->second);
	shared_ptr <Variable> response_index = reg->getVariable(parameters.find("response_index")->second);
    shared_ptr <Variable> task_correlation = reg->getVariable(parameters.find("task_correlation")->second);
    shared_ptr <Variable> response_bias_correlation = reg->getVariable(parameters.find("response_bias_correlation")->second);
	shared_ptr <Variable> alternation_correlation = reg->getVariable(parameters.find("alternation_correlation")->second);

	unsigned int grace_period = 0;
	try {
		grace_period = boost::lexical_cast< unsigned int >(parameters.find("grace_period")->second);
	} catch(boost::bad_lexical_cast &) {
		throw InvalidReferenceException(parameters["reference_id"], "grace_period", parameters.find("grace_period")->second);
	}

	unsigned int history = 0;
	try {
		history = boost::lexical_cast< unsigned int >(parameters.find("history")->second);
	} catch(boost::bad_lexical_cast &) {
		throw InvalidReferenceException(parameters["reference_id"], "history", parameters.find("history")->second);
	}

	checkAttribute(success, parameters["reference_id"], "success", parameters.find("success")->second);
    checkAttribute(response_index, parameters["reference_id"], "response_index", parameters.find("response_index")->second);
    checkAttribute(task_correlation, parameters["reference_id"], "task_correlation", parameters.find("task_correlation")->second);
    checkAttribute(response_bias_correlation, parameters["reference_id"], "response_bias_correlation", parameters.find("response_bias_correlation")->second);
    checkAttribute(alternation_correlation, parameters["reference_id"], "alternation_correlation", parameters.find("alternation_correlation")->second);

	shared_ptr <mw::Component> newBiasMonitor =
                shared_ptr<mw::Component>(new BiasMonitor(success,
                                                        response_index,
                                                        task_correlation,
                                                        response_bias_correlation,
                                                        alternation_correlation,
                                                        grace_period,
                                                        history));

	return newBiasMonitor;
}

END_NAMESPACE_MW


//---------------------------------------------------------------------------//
// Copyright (c) 2014 Roshan <thisisroshansmail@gmail.com>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// See http://boostorg.github.com/compute for more information.
//---------------------------------------------------------------------------//

#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>

#include <boost/compute/system.hpp>
#include <boost/compute/algorithm/set_difference.hpp>
#include <boost/compute/container/vector.hpp>

#include "perf.hpp"

int rand_int()
{
    return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
}

int main(int argc, char *argv[])
{
    perf_parse_args(argc, argv);
    std::cout << "size: " << PERF_N << std::endl;

    // setup context and queue for the default device
    boost::compute::device device = boost::compute::system::default_device();
    boost::compute::context context(device);
    boost::compute::command_queue queue(context, device);
    std::cout << "device: " << device.name() << std::endl;

    // create vectors of random numbers on the host
    std::vector<int> v1(std::floor(PERF_N / 2.0));
    std::vector<int> v2(std::ceil(PERF_N / 2.0));
    std::generate(v1.begin(), v1.end(), rand_int);
    std::generate(v2.begin(), v2.end(), rand_int);
    std::sort(v1.begin(), v1.end());
    std::sort(v2.begin(), v2.end());

    // create vectors on the device and copy the data
    boost::compute::vector<int> gpu_v1(std::floor(PERF_N / 2.0), context);
    boost::compute::vector<int> gpu_v2(std::ceil(PERF_N / 2.0), context);

    boost::compute::copy(
        v1.begin(), v1.end(), gpu_v1.begin(), queue
    );
    boost::compute::copy(
        v2.begin(), v2.end(), gpu_v2.begin(), queue
    );

    boost::compute::vector<int> gpu_v3(PERF_N, context);
    boost::compute::vector<int>::iterator gpu_v3_end;

    perf_timer t;
    for(size_t trial = 0; trial < PERF_TRIALS; trial++){
        t.start();
        gpu_v3_end = boost::compute::set_difference(
            gpu_v1.begin(), gpu_v1.end(),
            gpu_v2.begin(), gpu_v2.end(),
            gpu_v3.begin(), queue
        );
        queue.finish();
        t.stop();
    }
    std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
    std::cout << "size: " << std::distance(gpu_v3.begin(), gpu_v3_end) << std::endl;

    return 0;
}


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

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

#include <adobe/config.hpp>
#include <boost/test/unit_test.hpp>
#include <adobe/utility/ignore_unused.hpp>

namespace adobe {

/*!
\addtogroup testing
@{
*/

template <typename T, typename Op>
void check_transitive(const T& x, const T& y, const T& z, Op op)
{
    ignore_unused(y);
    assert(op(x,y) && op(y,z));
    BOOST_CHECK_MESSAGE(op(x,z), "tranisitive");
}

template <typename T, typename Op>
void check_irreflexive(const T& x, Op op)
{
    BOOST_CHECK_MESSAGE(!op(x,x), "irreflexive");
}

template <typename T, typename Op>
void check_antisymmetric(const T& x, const T& y, Op op)
{
    BOOST_CHECK_MESSAGE(!(op(x,y) && op(y,x)), "anti-symmetric");
}

template <typename T, typename Op>
void check_less_than_comparable(const T& x, const T& y, const T& z, Op op)
{
    check_irreflexive(x, op);
    check_antisymmetric(x, y, op);
    check_transitive(x, y, z, op);
}

//!@}
}


/*

Copyright (c) 2005-2015, University of Oxford.
All rights reserved.

University of Oxford means the Chancellor, Masters and Scholars of the
University of Oxford, having an administrative office at Wellington
Square, Oxford OX1 2JD, UK.

This file is part of Chaste.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
 * Neither the name of the University of Oxford nor the names of its
   contributors may be used to endorse or promote products derived from this
   software without specific prior written permission.

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

*/

#ifndef _TESTLINEARSYSTEM_HPP_
#define _TESTLINEARSYSTEM_HPP_

#include <cxxtest/TestSuite.h>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <cmath>
#include <iostream>
#include <cstring>

#include "LinearSystem.hpp"
#include "DistributedVector.hpp"
#include "PetscTools.hpp"
#include "PetscVecTools.hpp"
#include "PetscMatTools.hpp"
#include "OutputFileHandler.hpp"
#include "DistributedVectorFactory.hpp"
#include "ReplicatableVector.hpp"
#include "PetscSetupAndFinalize.hpp"
#include "Timer.hpp"

/**
 * Tests the LinearSystem class, and some methods in the PETSc helper classes PetscVecTools and PetscMatTools.
 */
class TestLinearSystem : public CxxTest::TestSuite
{
public:

   void TestLinearSystem1()
    {
        TS_ASSERT_THROWS_THIS(LinearSystem too_big_to_be_dense(20), "You must provide a rowPreallocation argument for a large sparse system");

        const unsigned size_u = 3u;
        const int size = (int) size_u;
        LinearSystem ls(size_u);
        TS_ASSERT_EQUALS(ls.GetSize(), size_u);
        TS_ASSERT_EQUALS(PetscVecTools::GetSize(ls.GetRhsVector()), size_u);
        TS_ASSERT_EQUALS(PetscMatTools::GetSize(ls.GetLhsMatrix()), size_u);

        ls.SetMatrixIsConstant(true);

        for (int row=0; row<3; row++)
        {
            for (int col=0; col<3; col++)
            {
                ls.SetMatrixElement(row, col, (double) row*3+col+1);
            }
        }

        ls.SetRhsVectorElement(0, 1400000.0);
        ls.SetRhsVectorElement(1, 3200000.0);
        ls.SetRhsVectorElement(2, 5000000.0);

        ls.AssembleFinalLinearSystem();

        // For coverage
        ls.DisplayMatrix();
        ls.DisplayRhs();

        Vec solution_vector;
        solution_vector = ls.Solve();

        int lo, hi;
        VecGetOwnershipRange(solution_vector, &lo, &hi);
        PetscScalar* p_solution_elements_array;
        VecGetArray(solution_vector, &p_solution_elements_array);
        for (int global_index=0; global_index<size; global_index++)
        {
            int local_index = global_index-lo;
            if (lo<=global_index && global_index<hi)
            {
                TS_ASSERT_DELTA(p_solution_elements_array[local_index], 100000.0*(global_index+1), 1e-8);
            }
        }
        VecRestoreArray(solution_vector, &p_solution_elements_array);
        PetscTools::Destroy(solution_vector);

        // SetRelativeTolerance
        ls.SetRelativeTolerance(1e-2);
        TS_ASSERT_THROWS_NOTHING(solution_vector = ls.Solve());

        KSPConvergedReason reason;
        KSPGetConvergedReason(ls.mKspSolver, &reason);
        TS_ASSERT_EQUALS(reason, KSP_CONVERGED_RTOL);

        VecGetOwnershipRange(solution_vector,&lo,&hi);
        VecGetArray(solution_vector, &p_solution_elements_array);

        for (int global_index=0; global_index<size; global_index++)
        {
            int local_index = global_index-lo;
            if (lo<=global_index && global_index<hi)
            {
                TS_ASSERT_DELTA(p_solution_elements_array[local_index], 100000.0*(global_index+1), 2e4);
            }
        }
        VecRestoreArray(solution_vector, &p_solution_elements_array);
        PetscTools::Destroy(solution_vector);

        /*
         * Reset KSP stuff. This doesn't need to be done, but we're making sure
         * we cover this method (and check that it works).
         */
        ls.ResetKspSolver();

        // SetAbsoluteTolerance
        ls.SetAbsoluteTolerance(1e-8);
        solution_vector = ls.Solve();
        KSPGetConvergedReason(ls.mKspSolver, &reason);
        TS_ASSERT_EQUALS(reason, KSP_CONVERGED_ATOL);

        // Check that it converged for the right reason
        VecGetOwnershipRange(solution_vector,&lo,&hi);
        VecGetArray(solution_vector, &p_solution_elements_array);

        for (int global_index=0; global_index<size; global_index++)
        {
            int local_index = global_index-lo;
            if (lo<=global_index && global_index<hi)
            {
                TS_ASSERT_DELTA(p_solution_elements_array[local_index], 100000.0*(global_index+1), 1e-8);
            }
        }
        VecRestoreArray(solution_vector, &p_solution_elements_array);
        PetscTools::Destroy(solution_vector);
    }

    void TestZeroingLinearSystem()
    {
        LinearSystem ls(5);
        for (int i=0; i<5; i++)
        {
            ls.SetMatrixRow(i, (double)i);
            ls.SetRhsVectorElement(i, (double)i);
        }
        ls.AssembleFinalLinearSystem();

        int lo, hi;
        ls.GetOwnershipRange(lo, hi);
        for (int row=lo; row<hi; row++)
        {
            TS_ASSERT_EQUALS(ls.GetRhsVectorElement(row), row);
            for (int col=0; col<5; col++)
            {
                TS_ASSERT_EQUALS(ls.GetMatrixElement(row, col), row);
            }
        }

        ls.ZeroLinearSystem();

        for (int row=lo; row<hi; row++)
        {
            TS_ASSERT_EQUALS(ls.GetRhsVectorElement(row), 0.0);
            for (int col=0; col<5; col++)
            {
                TS_ASSERT_EQUALS(ls.GetMatrixElement(row, col), 0.0);
            }
        }

        ls.SetMatrixRow(2, 125.0);

        // Note: this method is collective. All processes MUST do it together.
        ls.AssembleFinalLinearSystem();

        if (lo <=2 && 2<hi)
        {
            TS_ASSERT_EQUALS(ls.GetMatrixElement(2, 1), 125.0);
        }
    }

    void TestZeroMatrixRowsWithValueOnDiagonal()
    {
        LinearSystem ls(5);
        for (int i=0; i<5; i++)
        {
            ls.SetMatrixRow(i, (double)i);
            ls.SetRhsVectorElement(i, (double)i);
        }
        ls.AssembleFinalLinearSystem();

        std::vector<unsigned> rows;
        rows.push_back(2);
        rows.push_back(3);
        rows.push_back(4);

        ls.ZeroMatrixRowsWithValueOnDiagonal(rows, 3.14);

        int lo, hi;
        ls.GetOwnershipRange(lo, hi);
        for (int row=2; row<5; row++)
        {
            if (lo<=row && row<hi)
            {
                for (int i=0; i<5; (i+1==row? i+=2 : i++)) // for i=0,1..,row-1,row+1,..,5
                {
                    TS_ASSERT_EQUALS(ls.GetMatrixElement(row,i), 0.0);
                }
                TS_ASSERT_EQUALS(ls.GetMatrixElement(row,row), 3.14);
            }
        }
    }

    void TestAddingNonzeroesLater()
    {
        // Make a linear system from which the vector becomes a template to use in a later constructor
        LinearSystem ls_template(5);
        for (int i=0; i<5; i++)
        {
            ls_template.SetMatrixElement(i, i, 3.0);
        }
        ls_template.SetMatrixElement(1, 3, 3.0);
        ls_template.AssembleFinalLinearSystem();

        // The "false" says that we are allowed to do new mallocs without PETSc 3.3 causing an error
        LinearSystem ls(ls_template.rGetRhsVector(), 1, false);
        for (int i=0; i<5; i++)
        {
            ls.SetMatrixElement(i, i, 3.0);
        }
        ls.AssembleFinalLinearSystem();
        //Adding a new non-zero element gives an error in PETSc 3.3
        ls.SetMatrixElement(1, 3, 3.0);
        ls.AssembleFinalLinearSystem();

        TS_ASSERT(PetscMatTools::CheckEquality(ls_template.rGetLhsMatrix(), ls.rGetLhsMatrix()));
    }

    void TestZeroingLinearSystemByColumn()
    {
        LinearSystem ls(5);
        for (int i=0; i<5; i++)
        {
            ls.SetMatrixElement(i, i, 3.0);
        }
        ls.SetMatrixElement(0, 1, 4.0);

        ls.AssembleFinalLinearSystem();

        for (unsigned col=0; col<5; col++)
        {
            ls.ZeroMatrixColumn(col);
        }
        ls.AssembleFinalLinearSystem();

        int lo, hi;
        ls.GetOwnershipRange(lo, hi);
        for (int row=lo; row<hi; row++)
        {
            TS_ASSERT_EQUALS(ls.GetRhsVectorElement(row), 0);
            for (int col=0; col<5; col++)
            {
                TS_ASSERT_EQUALS(ls.GetMatrixElement(row, col), 0);
            }
        }

        MatInfo info;
        double num_nonzeros;

        MatGetInfo(ls.rGetLhsMatrix(),MAT_GLOBAL_SUM,&info);

        num_nonzeros = info.nz_used;

        TS_ASSERT_EQUALS(int(num_nonzeros),6);
    }

    void TestZeroMatrixRowsAndColumnsWithValueOnDiagonal() throw(Exception)
    {
        LinearSystem ls(5);
        for (int i=0; i<5; i++)
        {
            ls.SetMatrixRow(i, (double)i);
        }
        ls.AssembleFinalLinearSystem();

        std::vector<unsigned> rows(3);
        rows[0] = 2;
        rows[1] = 3;
        rows[2] = 4;

        ls.ZeroMatrixRowsAndColumnsWithValueOnDiagonal(rows, 3.1);

        int lo, hi;
        ls.GetOwnershipRange(lo, hi);
        for (int row=lo; row<hi; row++)
        {
            for (int col=0; col<5; col++)
            {
                if ( (col>=2) || (row>=2) )
                {
                    // The altered values
                    if (row != col)
                    {
                        TS_ASSERT_EQUALS(ls.GetMatrixElement(row, col), 0);
                    }
                    else
                    {
                        TS_ASSERT_EQUALS(ls.GetMatrixElement(row, col), 3.1);
                    }
                }
                else
                {
                    // Unaltered values
                    TS_ASSERT_EQUALS(ls.GetMatrixElement(row, col), row);
                }
            }
        }
    }

    void TestGetMatrixRowDistributed()
    {
        LinearSystem ls(5);
        for (int i=0; i<5; i++)
        {
            ls.SetMatrixRow(i, (double)i);
        }
        ls.AssembleFinalLinearSystem();

        Vec third_row = ls.GetMatrixRowDistributed(3);

        DistributedVectorFactory factory(third_row);

        DistributedVector distributed_third_row = factory.CreateDistributedVector(third_row);
        for (DistributedVector::Iterator index = distributed_third_row.Begin();
             index!= distributed_third_row.End();
             ++index)
        {
            TS_ASSERT_EQUALS(distributed_third_row[index], 3);
        }

        PetscTools::Destroy(third_row);
    }

    void TestCreateFromVector()
    {
        const int SIZE = 5;
        Vec test_vec=PetscTools::CreateVec(SIZE);

        LinearSystem ls(test_vec, 5);

        // Check ownership ranges match
        int lo1, hi1, lo2, hi2;
        VecGetOwnershipRange(test_vec, &lo1, &hi1);
        ls.GetOwnershipRange(lo2, hi2);
        TS_ASSERT_EQUALS(lo1, lo2);
        TS_ASSERT_EQUALS(hi1, hi2);

        PetscTools::Destroy(test_vec);
    }

    void TestLinearSystem2()
    {
        LinearSystem ls(2);
        ls.SetMatrixRow(0, 1.0);
        ls.SetMatrixRow(1, 3.0);
        ls.AssembleIntermediateLinearSystem();

        ls.AddToMatrixElement(0, 1, 1.0);
        ls.AddToMatrixElement(1, 1, 1.0);

        ls.AddToRhsVectorElement(0, 3.0);
        ls.AddToRhsVectorElement(1, 7.0);
        ls.AssembleFinalLinearSystem();

        Vec solution_vector;
        solution_vector = ls.Solve();

        int lo,hi;
        VecGetOwnershipRange(solution_vector,&lo,&hi);
        PetscScalar* p_solution_elements_array;
        VecGetArray(solution_vector, &p_solution_elements_array);

        for (int global_index=0; global_index<2; global_index++)
        {
            int local_index = global_index-lo;
            if (lo<=global_index && global_index<hi)
            {
                TS_ASSERT_DELTA(p_solution_elements_array[local_index], 1.0, 0.000001);
            }
        }
        VecRestoreArray(solution_vector, &p_solution_elements_array);

        PetscTools::Destroy(solution_vector);
    }

    /**
     * This is a stub test for coverage purposes.
     */
    void TestNullBasis()
    {
 #ifndef NDEBUG //Only do this test in debug mode, since functionality is skipped in optimized code
        unsigned size = 10;

        // Test it throws if one of the vectors in the base is not normal
        {
            std::vector<double> data(size,1.0);
            Vec non_orthonormal = PetscTools::CreateVec(data);

            LinearSystem ls((PetscInt) size);
            TS_ASSERT_THROWS_THIS(ls.SetNullBasis(&non_orthonormal, 1),
                    "One of the vectors in the null space is not normalised");
            PetscTools::Destroy(non_orthonormal);
        }

        // Test it throws if the vectors in the base are not orthogonal
        {
            std::vector<double> data(size,0.0);
            data[0] = 1.0;
            Vec one_zeros = PetscTools::CreateVec(data);

            std::vector<double> data2(size,0.0);
            data2[1] = 1.0;
            Vec zero_one_zeros = PetscTools::CreateVec(data2);

            Vec null_basis[] = {one_zeros, zero_one_zeros, one_zeros};

            LinearSystem ls((PetscInt) size);
            TS_ASSERT_THROWS_THIS(ls.SetNullBasis(null_basis, 3),"The null space is not orthogonal.");

            PetscTools::Destroy(one_zeros);
            PetscTools::Destroy(zero_one_zeros);
        }

        // Test it doesn't throws if a non-orthonormal basis is passed
        {
            std::vector<double> data(size,0.0);
            data[0] = 1.0;
            Vec one_zeros = PetscTools::CreateVec(data);

            std::vector<double> data2(size,0.0);
            data2[1] = 1.0;
            Vec zero_one_zeros = PetscTools::CreateVec(data2);

            Vec null_basis[] = {one_zeros, zero_one_zeros};

            LinearSystem ls((PetscInt) size);
            TS_ASSERT_THROWS_NOTHING(ls.SetNullBasis(null_basis, 2));

            PetscTools::Destroy(one_zeros);
            PetscTools::Destroy(zero_one_zeros);
        }
#endif
    }

   void TestRemoveNullSpace()
    {
        LinearSystem ls(3);
        ls.SetMatrixIsConstant(true);

        TS_ASSERT_EQUALS(ls.GetSize(), 3U);

        for (int row=0; row<3; row++)
        {
            ls.SetMatrixElement(row, row, (double) row+1);
        }

        ls.SetRhsVectorElement(0, 1.0);
        ls.SetRhsVectorElement(1, 2.0);
        ls.SetRhsVectorElement(2, 3.0);
        ls.AssembleFinalLinearSystem();

        std::vector<double> data(3,0.0);
        data[0] = 1.0;
        Vec one_zeros = PetscTools::CreateVec(data);

        Vec null_basis[] = {one_zeros};

        ls.SetNullBasis(null_basis, 1);

        Vec wrong_solution = ls.Solve();
        ReplicatableVector replicated_wrong_solution(wrong_solution);

        // Wrong solution since wrong null space was provided.
        TS_ASSERT_DELTA(replicated_wrong_solution[0], 0.0, 1e-8);
        TS_ASSERT_DELTA(replicated_wrong_solution[1], 1.0, 1e-8);
        TS_ASSERT_DELTA(replicated_wrong_solution[2], 1.0, 1e-8);

        // Now remove the null space and we will hopefully get the right solution
        ls.RemoveNullSpace();
        Vec solution = ls.Solve();
        ReplicatableVector replicated_solution(solution);

        TS_ASSERT_DELTA(replicated_solution[0], 1.0, 1e-8);
        TS_ASSERT_DELTA(replicated_solution[1], 1.0, 1e-8);
        TS_ASSERT_DELTA(replicated_solution[2], 1.0, 1e-8);

        PetscTools::Destroy(one_zeros);
        PetscTools::Destroy(wrong_solution);
        PetscTools::Destroy(solution);

    }

    // Test the 3rd constructor
    void TestCreateWithPetscObjects()
    {
        // First try giving it just a vector
        unsigned size = 5u;
        DistributedVectorFactory factory(size);
        Vec test_vec = factory.CreateVec();

        DistributedVector dist_vec = factory.CreateDistributedVector(test_vec);
        double test_val = -1.0;
        if (dist_vec.Begin() != dist_vec.End())
        {
            dist_vec[dist_vec.Begin()] = test_val;
        }
        dist_vec.Restore();

        LinearSystem lsv(test_vec, (Mat) NULL);
        TS_ASSERT_EQUALS(lsv.GetSize(), size);

        if (dist_vec.Begin() != dist_vec.End())
        {
            TS_ASSERT_EQUALS(lsv.GetRhsVectorElement(dist_vec.Begin().Global),
                             test_val);
        }

        // Change the Vec and see if the linear system reflects the change
        double test_val2 = 2.0;
        if (dist_vec.Begin() != dist_vec.End())
        {
            dist_vec[dist_vec.Begin()] = test_val2;
        }
        dist_vec.Restore();
        if (dist_vec.Begin() != dist_vec.End())
        {
            TS_ASSERT_EQUALS(lsv.GetRhsVectorElement(dist_vec.Begin().Global),
                             test_val2);
        }

        // Now try with just a matrix
        Mat m;
        PetscTools::SetupMat(m, size, size, size);

        if (dist_vec.Begin() != dist_vec.End())
        {
            PetscMatTools::SetElement(m, dist_vec.Begin().Global, 0, test_val);
        }

        LinearSystem lsm(NULL, m);
        TS_ASSERT_EQUALS(lsm.GetSize(), size);
        lsm.FinaliseLhsMatrix();

        if (dist_vec.Begin() != dist_vec.End())
        {
            TS_ASSERT_EQUALS(lsm.GetMatrixElement(dist_vec.Begin().Global, 0),
                             test_val);
        }

        // Change the Mat and see if the linear system reflects the change
        if (dist_vec.Begin() != dist_vec.End())
        {
            PetscMatTools::SetElement(m, dist_vec.Begin().Global, 0, test_val2);
        }
        MatAssemblyBegin(m, MAT_FINAL_ASSEMBLY);
        MatAssemblyEnd(m, MAT_FINAL_ASSEMBLY);
        if (dist_vec.Begin() != dist_vec.End())
        {
            TS_ASSERT_EQUALS(lsm.GetMatrixElement(dist_vec.Begin().Global, 0),
                             test_val2);
        }

        PetscTools::Destroy(test_vec);
        PetscTools::Destroy(m);
    }

    void TestLinearSystem1WithIntialGuess()
    {
        LinearSystem ls(3);

        for (int row=0; row<3; row++)
        {
            for (int col=0; col<3; col++)
            {
                ls.SetMatrixElement(row, col, (double) row*3+col+1);
            }
        }

        ls.SetRhsVectorElement(0, 14.0);
        ls.SetRhsVectorElement(1, 32.0);
        ls.SetRhsVectorElement(2, 50.0);
        ls.AssembleFinalLinearSystem();
//      /* This will mess up the following because the *first call* to Solve has to contain an initial guess. */
//        Vec sol1 = ls.Solve();
//        PetscTools::Destroy(sol1);
//        unsigned num_iters_from_default = ls.GetNumIterations();

        Vec zero_guess=PetscTools::CreateVec(3);
        PetscVecTools::SetElement(zero_guess, 0, 0.0);
        PetscVecTools::SetElement(zero_guess, 1, 0.0);
        PetscVecTools::SetElement(zero_guess, 2, 0.0);
        PetscVecTools::Finalise(zero_guess);
        Vec sol2 = ls.Solve(zero_guess);
        PetscTools::Destroy(zero_guess);
        PetscTools::Destroy(sol2);

        unsigned num_iters_from_zero = ls.GetNumIterations();

        // Set the correct answer for the intial guess
        Vec good_guess=PetscTools::CreateVec(3);
        PetscVecTools::SetElement(good_guess, 0, 1.0);
        PetscVecTools::SetElement(good_guess, 1, 2.0);
        PetscVecTools::SetElement(good_guess, 2, 3.0);
        PetscVecTools::Finalise(good_guess);

        Vec solution_vector;
        solution_vector = ls.Solve(good_guess);
        unsigned num_iters_from_perfect = ls.GetNumIterations();
        TS_ASSERT_EQUALS(num_iters_from_perfect, 0u);
        TS_ASSERT_LESS_THAN(num_iters_from_perfect, num_iters_from_zero);

        int lo, hi;
        VecGetOwnershipRange(solution_vector,&lo,&hi);
        PetscScalar* p_solution_elements_array;
        VecGetArray(solution_vector, &p_solution_elements_array);

        for (int global_index=0; global_index<3; global_index++)
        {
            int local_index = global_index-lo;
            if (lo<=global_index && global_index<hi)
            {
                TS_ASSERT_EQUALS(p_solution_elements_array[local_index], global_index+1.0);
                // Zero tolerance
            }
        }
        VecRestoreArray(solution_vector, &p_solution_elements_array);

        // Set the a bad intial guess
        Vec bad_guess;
        VecDuplicate(good_guess, &bad_guess);
        PetscScalar too_big = 1e5;
#if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
        VecSet(&too_big, bad_guess);
#else
        VecSet(bad_guess, too_big);
#endif
        TS_ASSERT_THROWS_CONTAINS(solution_vector = ls.Solve(bad_guess),
                "DIVERGED_DTOL in function");
        PetscTools::Destroy(solution_vector);
        PetscTools::Destroy(good_guess);
        PetscTools::Destroy(bad_guess);
    }

    void TestAddMultipleValues()
    {
        LinearSystem syst = LinearSystem(3);

        c_matrix<double, 2, 2> small_matrix;
        c_vector<double, 2> small_vector;

        small_matrix(0,0) = 1;
        small_matrix(0,1) = 2;
        small_matrix(1,0) = 3;
        small_matrix(1,1) = 4;

        small_vector(0) = -1;
        small_vector(1) = -2;

        unsigned large_matrix_indices[2]={0,2};

        syst.AddLhsMultipleValues(large_matrix_indices, small_matrix);
        syst.AddRhsMultipleValues(large_matrix_indices, small_vector);

        syst.AssembleFinalLinearSystem();

        PetscInt lo, hi;
        syst.GetOwnershipRange(lo, hi);

        if (lo <=0 && 0<hi)
        {
            TS_ASSERT_EQUALS(syst.GetMatrixElement(0,0), 1);
            TS_ASSERT_EQUALS(syst.GetMatrixElement(0,1), 0);
            TS_ASSERT_EQUALS(syst.GetMatrixElement(0,2), 2);

            TS_ASSERT_EQUALS(syst.GetRhsVectorElement(0), -1);
        }
        if (lo <=1 && 1<hi)
        {
            TS_ASSERT_EQUALS(syst.GetMatrixElement(1,0), 0);
            TS_ASSERT_EQUALS(syst.GetMatrixElement(1,1), 0);
            TS_ASSERT_EQUALS(syst.GetMatrixElement(1,2), 0);

            TS_ASSERT_EQUALS(syst.GetRhsVectorElement(1), 0);
        }
        if (lo <=2 && 2<hi)
        {
            TS_ASSERT_EQUALS(syst.GetMatrixElement(2,0), 3);
            TS_ASSERT_EQUALS(syst.GetMatrixElement(2,1), 0);
            TS_ASSERT_EQUALS(syst.GetMatrixElement(2,2), 4);

            TS_ASSERT_EQUALS(syst.GetRhsVectorElement(2), -2);
        }
    }

    void TestSymmetricMatrix()
    {
        LinearSystem ls = LinearSystem(3);

        TS_ASSERT(!ls.IsMatrixSymmetric());
        ls.SetMatrixIsSymmetric();
        TS_ASSERT(ls.IsMatrixSymmetric());

        // Enter symmetric data
        for (int row=0; row<3; row++)
        {
            for (int col=0; col<3; col++)
            {
                ls.SetMatrixElement(row, col, (double)(abs(row-col)));
            }
        }

        // arbitrary
        ls.SetRhsVectorElement(0, 14.0);
        ls.SetRhsVectorElement(1, 32.0);
        ls.SetRhsVectorElement(2, 50.0);
        ls.AssembleFinalLinearSystem();

        Vec solution_vector;
        solution_vector = ls.Solve();

        double expected_solution[3]={25.0,0.0,7.0};
        PetscInt lo, hi;
        ls.GetOwnershipRange(lo, hi);
        double* p_solution_elements_array;
        VecGetArray(solution_vector, &p_solution_elements_array);
        for (int global_index=0; global_index<3; global_index++)
        {
            int local_index = global_index-lo;
            if (lo<=global_index && global_index<hi)
            {
                TS_ASSERT_DELTA(p_solution_elements_array[local_index], expected_solution[global_index], 1e-5);
            }
        }

        VecRestoreArray(solution_vector, &p_solution_elements_array);

        PetscTools::Destroy(solution_vector);

        // coverage
        ls.SetMatrixIsSymmetric(false);
        TS_ASSERT(!ls.IsMatrixSymmetric());
    }

    void TestNonSymmetricMatrix()
    {
        LinearSystem ls = LinearSystem(3);

        // Enter non-symmetric data
        for (int row=0; row<3; row++)
        {
            for (int col=0; col<3; col++)
            {
                ls.SetMatrixElement(row, col, (double)(10+row-col));
            }
        }

        // Arbitrary
        ls.SetRhsVectorElement(0, 14.0);
        ls.SetRhsVectorElement(1, 32.0);
        ls.SetRhsVectorElement(2, 50.0);
        ls.AssembleFinalLinearSystem();

        // Solving should be fine
        Vec solution_vector;
        solution_vector = ls.Solve();

        LinearSystem ls2 = LinearSystem(3);
        ls2.SetMatrixIsSymmetric();

        for (int row=0; row<3; row++)
        {
            for (int col=0; col<3; col++)
            {
                ls2.SetMatrixElement(row, col, (double)(10+row-col));
            }
        }
        ls2.AssembleFinalLinearSystem();

        // What happens when we solve?
        Vec solution_vector2;
        solution_vector2 = ls2.Solve();

        // Check answers
        double expected_solution[3]={-68.0,6.0,80.0};
        PetscInt lo, hi;
        ls.GetOwnershipRange(lo, hi);
        double* p_solution_elements_array,* p_solution_elements_array2;
        VecGetArray(solution_vector, &p_solution_elements_array);
        VecGetArray(solution_vector2, &p_solution_elements_array2);
        for (int global_index=0; global_index<3; global_index++)
        {
            int local_index = global_index-lo;
            if (lo<=global_index && global_index<hi)
            {
                TS_ASSERT_DELTA(p_solution_elements_array[local_index], expected_solution[global_index], 1e-5);
                TS_ASSERT_LESS_THAN(2, fabs(p_solution_elements_array2[local_index] - expected_solution[global_index]));
                //Diverges from expected by more than 2
            }
        }

        VecRestoreArray(solution_vector, &p_solution_elements_array);
        VecRestoreArray(solution_vector2, &p_solution_elements_array2);
        PetscTools::Destroy(solution_vector2);
        PetscTools::Destroy(solution_vector);
    }

    void TestGetSetKSP() throw (Exception)
    {
        {
            // Test that small systems don't have preconditioning
#if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR <= 3) //PETSc 3.0 to PETSc 3.3
        //The PETSc developers changed this one, but later changed it back again!
            const PCType pc_small;
#else
            PCType pc_small;
#endif
            LinearSystem ls_small = LinearSystem(6);
            ls_small.SetPcType("jacobi"); //Will be over-ridden because the system is small
            ls_small.AssembleFinalLinearSystem();
            Vec solution_vector_small;
            solution_vector_small = ls_small.Solve();
            PetscTools::Destroy(solution_vector_small);
            PC prec_small;
            KSPGetPC(ls_small.mKspSolver, &prec_small);
            PCGetType(prec_small, &pc_small);
            TS_ASSERT( strcmp(pc_small,"none")==0 );
        }
        // Set relative tolerance before first solve
        LinearSystem ls = LinearSystem(7);
        ls.SetRelativeTolerance(1e-3);
        ls.SetKspType("cg");
        ls.SetPcType("jacobi"); //Will not be over-ridden because the system is larger...
        ls.AssembleFinalLinearSystem();
        Vec solution_vector;
        solution_vector = ls.Solve();
        PetscTools::Destroy(solution_vector);
        PetscReal rtol, atol, dtol;
        int maxits;
        KSPGetTolerances(ls.mKspSolver, &rtol, &atol, &dtol, &maxits);
        TS_ASSERT_EQUALS(rtol, 1e-3);

        // Others should be their PETSc defaults (unless we've done different)
        TS_ASSERT_EQUALS(atol, 1e-50);
        TS_ASSERT_EQUALS(dtol, 10000.0);
        TS_ASSERT_EQUALS(maxits, 1000); /// \todo #1695 Test against member variable in LinearSystem. At the moment this value depends on whether any previous test called ResetKspSolver() (maxits=1000) or not (maxits=10000).

#if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR <= 3) //PETSc 3.0 to PETSc 3.3
        //The PETSc developers changed this one, but later changed it back again!
        const KSPType solver;
        const PCType pc;
#else
        KSPType solver;
        PCType pc;
#endif

        PC prec;
        KSPGetType(ls.mKspSolver, &solver);
        KSPGetPC(ls.mKspSolver, &prec);
        PCGetType(prec, &pc);
        TS_ASSERT( strcmp(solver,"cg")==0 );
        TS_ASSERT( strcmp(pc,"jacobi")==0 );
        ls.SetKspType("gmres");
        ls.SetPcType("ilu");

        // Test that we can change the solver type after its first use
        KSPGetType(ls.mKspSolver, &solver);
        PCGetType(prec, &pc);
        TS_ASSERT( strcmp(solver,"gmres")==0 );
        TS_ASSERT( strcmp(pc,"ilu")==0 );

        /////////////////////////////////
        // Set relative tolerance after first solve
        /////////////////////////////////
        ls.SetRelativeTolerance(1e-4);
        KSPGetTolerances(ls.mKspSolver, &rtol, &atol, &dtol, &maxits);
        TS_ASSERT_EQUALS(rtol, 1e-4);
        TS_ASSERT_EQUALS(atol, 1e-50);
        TS_ASSERT_EQUALS(dtol, 10000.0);
        TS_ASSERT_EQUALS(maxits, 1000); /// \todo #1695 Test against member variable in LinearSystem. At the moment this value depends on whether any previous test called ResetKspSolver() (maxits=1000) or not (maxits=10000).

        /////////////////////////////////
        // Set abs tolerance before first solve
        //////////////////////////////////
        LinearSystem ls2 = LinearSystem(5);
        ls2.SetAbsoluteTolerance(1e-3);
        ls2.AssembleFinalLinearSystem();
        Vec solution_vector2;
        solution_vector2 = ls2.Solve();
        PetscTools::Destroy(solution_vector2);
        KSPGetTolerances(ls2.mKspSolver, &rtol, &atol, &dtol, &maxits);
        TS_ASSERT_EQUALS(rtol, DBL_EPSILON);
        TS_ASSERT_EQUALS(atol, 1e-3);
        TS_ASSERT_EQUALS(dtol, 10000.0);
        TS_ASSERT_EQUALS(maxits, 1000); /// \todo #1695 Test against member variable in LinearSystem. At the moment this value depends on whether any previous test called ResetKspSolver() (maxits=1000) or not (maxits=10000).

        ///////////////////////////////////
        // Set abs tolerance after first solve
        ////////////////////////////////////
        ls2.SetAbsoluteTolerance(1e-2);
        Vec solution_vector3;
        solution_vector3 = ls2.Solve();
        PetscTools::Destroy(solution_vector3);
        KSPGetTolerances(ls2.mKspSolver, &rtol, &atol, &dtol, &maxits);
        TS_ASSERT_EQUALS(rtol, DBL_EPSILON);
        TS_ASSERT_EQUALS(atol, 1e-2);
        TS_ASSERT_EQUALS(dtol, 10000.0);
        TS_ASSERT_EQUALS(maxits, 1000); /// \todo #1695 Test against member variable in LinearSystem

    }

    void TestPetscSaveAndLoad()
    {
        // Archive
        OutputFileHandler handler("archive", false);
        std::string archive_filename_lhs, archive_filename_rhs;
        archive_filename_lhs = handler.GetOutputDirectoryFullPath() + "direct_lhs.mat";
        archive_filename_rhs = handler.GetOutputDirectoryFullPath() + "direct_rhs.vec";

        // Make a linear system
        LinearSystem ls = LinearSystem(3);
        ls.SetMatrixIsSymmetric();

        // Enter symmetric data
        for (int row=0; row<3; row++)
        {
            for (int col=0; col<3; col++)
            {
                ls.SetMatrixElement(row, col, (double)(abs(row-col)));
            }
        }

        // Arbitrary
        ls.SetRhsVectorElement(0, 14.0);
        ls.SetRhsVectorElement(1, 32.0);
        ls.SetRhsVectorElement(2, 50.0);

        ls.AssembleFinalLinearSystem();

        // SAVE
        {
            PetscViewer vec_viewer;
#if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
            PetscViewerFileType type = PETSC_FILE_CREATE;
#else
            PetscFileMode type = FILE_MODE_WRITE;
#endif
            PetscViewerBinaryOpen(PETSC_COMM_WORLD, archive_filename_rhs.c_str(), type, &vec_viewer);

            VecView(ls.GetRhsVector(), vec_viewer);
            PetscViewerDestroy(PETSC_DESTROY_PARAM(vec_viewer));

            PetscViewer mat_viewer;
            PetscViewerBinaryOpen(PETSC_COMM_WORLD, archive_filename_lhs.c_str(), type, &mat_viewer);

            MatView(ls.GetLhsMatrix(), mat_viewer);
            PetscViewerDestroy(PETSC_DESTROY_PARAM(mat_viewer));
        }
        // LOAD
        {

            PetscViewer vec_viewer;
#if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
            PetscViewerFileType type = PETSC_FILE_RDONLY;
#else
            PetscFileMode type = FILE_MODE_READ;
#endif
            PetscViewerBinaryOpen(PETSC_COMM_WORLD, archive_filename_rhs.c_str(), type, &vec_viewer);
            Vec new_vec;

#if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 2) //PETSc 3.2 or later
            VecCreate(PETSC_COMM_WORLD, &new_vec);
            VecSetType(new_vec, PETSC_NULL);
            VecLoad(new_vec, vec_viewer);
#else
            VecLoad(vec_viewer, PETSC_NULL, &new_vec);
#endif
            PetscViewerDestroy(PETSC_DESTROY_PARAM(vec_viewer));

            int lo, hi;
            VecGetOwnershipRange(new_vec, &lo, &hi);
            std::vector<double> answer;
            answer.push_back(14.0);
            answer.push_back(32.0);
            answer.push_back(50.0);

            double* p_vec_values;
            VecGetArray(new_vec, &p_vec_values);

            for ( int i = lo; i < hi; i++ )
            {
                TS_ASSERT_DELTA(p_vec_values[i-lo], answer[i], 1e-9);
            }

            PetscTools::Destroy(new_vec);

            PetscViewer mat_viewer;
            PetscViewerBinaryOpen(PETSC_COMM_WORLD, archive_filename_lhs.c_str(), type, &mat_viewer);
            Mat new_mat;

#if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 2) //PETSc 3.2 or later
            MatCreate(PETSC_COMM_WORLD, &new_mat);
            MatSetType(new_mat, PETSC_NULL);
            MatLoad(new_mat, mat_viewer);
#else
            MatLoad(mat_viewer, PETSC_NULL, &new_mat);
#endif

            PetscViewerDestroy(PETSC_DESTROY_PARAM(mat_viewer));

            for (int row=lo; row<hi; row++)
            {
                // Get a whole row out of the matrix and check it
                PetscInt row_as_array[1];
                row_as_array[0] = row;
                PetscInt col_as_array[3];
                for (int col=0; col<3; col++)
                {
                   col_as_array[col] = col;
                }
                double ret_array[3];
                MatGetValues(new_mat, 1, row_as_array, 3, col_as_array, ret_array);

                for (int col=0; col<3; col++)
                {
                    TS_ASSERT_DELTA(ret_array[col], (double)(abs(row-col)), 1e-9);
                }
            }

            PetscTools::Destroy(new_mat);
        }
    }

    void TestSaveAndLoadLinearSystem()
    {
        // Archive
        OutputFileHandler handler("archive", false);
        handler.SetArchiveDirectory();
        std::string archive_filename;
        archive_filename = handler.GetOutputDirectoryFullPath() + "linear_system.arch";

        int lo, hi;
        unsigned size = 5;
        std::vector<double> rhs_values;
        rhs_values.push_back(14.0);
        rhs_values.push_back(32.0);
        rhs_values.push_back(50.0);
        rhs_values.push_back(50.0);
        rhs_values.push_back(50.0);
        TS_ASSERT_EQUALS(rhs_values.size(), size);
        // SAVE
        {
            LinearSystem ls = LinearSystem(size);
            Mat temp_mat=ls.GetLhsMatrix();
            PetscBool symm_set, is_symmetric;
            is_symmetric = PETSC_FALSE;
            MatIsSymmetricKnown(temp_mat, &symm_set, &is_symmetric);
            TS_ASSERT_EQUALS(symm_set, PETSC_FALSE);
            TS_ASSERT_EQUALS(is_symmetric, PETSC_FALSE);

            ls.SetMatrixIsSymmetric();

            MatIsSymmetricKnown(temp_mat, &symm_set, &is_symmetric);
            TS_ASSERT_EQUALS(symm_set, PETSC_TRUE);
            TS_ASSERT_EQUALS(is_symmetric, PETSC_TRUE);

            // Enter symmetric data
            for (unsigned row=0; row<size; row++)
            {
                for (unsigned col=0; col<size; col++)
                {
                    ls.SetMatrixElement(row, col, (row == col)?(row+1.0):0.0);
                }
            }
            ls.AssembleFinalLinearSystem();

            for (unsigned i=0; i<size; i++)
            {
                ls.SetRhsVectorElement(i, rhs_values[i]);
            }
            ls.SetKspType("cg");
            ls.SetPcType("none");

            std::ofstream ofs(archive_filename.c_str());
            boost::archive::text_oarchive output_arch(ofs);
            LinearSystem* const p_linear_system = &ls;
            output_arch << p_linear_system;

            TS_ASSERT_EQUALS(p_linear_system->GetSize(), size);
            VecGetOwnershipRange(p_linear_system->GetRhsVector(), &lo, &hi);

            for ( int i = lo; i < hi; i++ )
            {
                TS_ASSERT_DELTA(p_linear_system->GetRhsVectorElement(i), rhs_values[i], 1e-9);
            }

            for (unsigned row=(unsigned)lo; row<(unsigned)hi; row++)
            {
                for (unsigned col=0; col<size; col++)
                {
                    TS_ASSERT_DELTA(p_linear_system->GetMatrixElement(row, col), (row == col)?(row+1.0):0.0, 1e-9);
                }
            }

        }
        // LOAD
        {
            std::ifstream ifs(archive_filename.c_str(), std::ios::binary);
            boost::archive::text_iarchive input_arch(ifs);

            // LinearSystem linear_system(3);
            LinearSystem* p_linear_system;//=&linear_system;
            input_arch >> p_linear_system;

            // Check that structural symmetry is preserved
            PetscBool symm_set, is_symmetric;
            is_symmetric=PETSC_FALSE;
            MatIsSymmetricKnown(p_linear_system->GetLhsMatrix(), &symm_set, &is_symmetric);
            TS_ASSERT_EQUALS(symm_set, PETSC_TRUE);
            TS_ASSERT_EQUALS(is_symmetric, PETSC_TRUE);

            TS_ASSERT_EQUALS(p_linear_system->GetSize(), size);

            int saved_lo, saved_hi;
            VecGetOwnershipRange(p_linear_system->GetRhsVector(), &saved_lo, &saved_hi);

            TS_ASSERT_EQUALS(hi, saved_hi);
            TS_ASSERT_EQUALS(lo, saved_lo);

            for ( int i = lo; i < hi; i++ )
            {
                TS_ASSERT_DELTA(p_linear_system->GetRhsVectorElement(i), rhs_values[i], 1e-9);
            }

            for (unsigned row=(unsigned)lo; row<(unsigned)hi; row++)
            {
                for (unsigned col=0; col<size; col++)
                {
                    TS_ASSERT_DELTA(p_linear_system->GetMatrixElement(row, col), (row == col)?(row+1.0):0.0, 1e-9);
                }
            }

            // Check archiving of KSP/PC types
            Vec solution_vector3;
            solution_vector3 = p_linear_system->Solve();
            PetscTools::Destroy(solution_vector3);
#if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR <= 3) //PETSc 3.0 to PETSc 3.3
            //The PETSc developers changed this one, but later changed it back again!
            const KSPType solver;
            const PCType pc;
#else
            KSPType solver;
            PCType pc;
#endif
            PC prec;
            KSPGetType(p_linear_system->mKspSolver, &solver);
            KSPGetPC(p_linear_system->mKspSolver, &prec);
            PCGetType(prec, &pc);

            TS_ASSERT(strcmp(solver, "cg") == 0);
            TS_ASSERT(strcmp(pc, "none") == 0);
            delete p_linear_system;
        }
    }
    // This test causes test-suite to exit abnormally with PETSc 3.2
    // and with MPICH-1.
    // Note: it's on the LDU solve.  Investigate Hypre.
    void TestConsecutiveSolvesDifferentPreconditioner()
    {
        unsigned num_nodes = 1331;
        DistributedVectorFactory factory(num_nodes);
        Vec parallel_layout = factory.CreateVec(2);

        Mat system_matrix;
        // Note that this test deadlocks if the file's not on the disk
        PetscTools::ReadPetscObject(system_matrix, "linalg/test/data/matrices/cube_6000elems_half_activated.mat", parallel_layout);

        Vec system_rhs;
        // Note that this test deadlocks if the file's not on the disk
        PetscTools::ReadPetscObject(system_rhs, "linalg/test/data/matrices/cube_6000elems_half_activated.vec", parallel_layout);

        PetscTools::Destroy(parallel_layout);

        LinearSystem ls = LinearSystem(system_rhs, system_matrix);

        ls.SetAbsoluteTolerance(1e-9);
        ls.SetKspType("cg");

        ls.SetPcType("bjacobi");
        Vec solution = ls.Solve(/*no guess provided*/);
        unsigned block_jacobi_its = ls.GetNumIterations();
        PetscTools::Destroy(solution);

        ls.SetPcType("ldufactorisation");
        solution = ls.Solve(/*no guess provided*/);
        unsigned ldu_its = ls.GetNumIterations();
        PetscTools::Destroy(solution);

        ls.SetPcType("bjacobi");
        solution = ls.Solve(/*no guess provided*/);
        unsigned second_block_jacobi_its = ls.GetNumIterations();
        PetscTools::Destroy(solution);

        TS_ASSERT_DIFFERS(block_jacobi_its, ldu_its)
        TS_ASSERT_DIFFERS(ldu_its, second_block_jacobi_its)

        PetscTools::Destroy(system_matrix);
        PetscTools::Destroy(system_rhs);
    }

//    void TestSingularSolves() throw(Exception)
//    {
//        LinearSystem ls(2);
//
//        ls.SetMatrixElement(0, 0, 2);
//        ls.SetMatrixElement(0, 1, 2);
//        ls.SetMatrixElement(1, 0, 2);
//        ls.SetMatrixElement(1, 1, 2);
//
//        ls.SetRhsVectorElement(0, 100.0);
//        ls.SetRhsVectorElement(1, 100.0);
//
//        ls.AssembleFinalLinearSystem();
//
//        Vec x = ls.Solve();
//        ReplicatableVector xx(x);
//
//        std::cout << xx[0] << " " << xx[1] << "\n"; //solves fine without null space?
//    }

    void TestDifferentMatrixForPreconditioning()
    {

        unsigned num_nodes = 1331;
        DistributedVectorFactory factory(num_nodes);
        Vec parallel_layout = factory.CreateVec(2);

        Mat system_matrix;
        // Note that this test deadlocks if the file's not on the disk
        PetscTools::ReadPetscObject(system_matrix, "linalg/test/data/matrices/cube_6000elems_half_activated.mat", parallel_layout);

        Vec system_rhs;
        // Note that this test deadlocks if the file's not on the disk
        PetscTools::ReadPetscObject(system_rhs, "linalg/test/data/matrices/cube_6000elems_half_activated.vec", parallel_layout);

        PetscTools::Destroy(parallel_layout);

        unsigned num_it_same_mat=0, num_it_diff_mat=1;

        {
            LinearSystem ls(system_rhs, system_matrix);
            ls.SetKspType("cg");

            Vec solution = ls.Solve();
            num_it_same_mat = ls.GetNumIterations();

            PetscTools::Destroy(solution);
        }

        /*
         * Basic test, we pretend matrix for preconditioning assembly is different
         * from LHS but then we set LHS as preconditioning matrix. Number of iterations
         * should agree.
         */
        {
            LinearSystem ls_diff_precond(system_rhs, system_matrix);
            ls_diff_precond.SetKspType("cg");

            // For coverage
            TS_ASSERT_THROWS_THIS(ls_diff_precond.rGetPrecondMatrix(), "LHS matrix used for preconditioner construction");

            ls_diff_precond.SetPrecondMatrixIsDifferentFromLhs();
            MatCopy(ls_diff_precond.GetLhsMatrix(), ls_diff_precond.rGetPrecondMatrix(), DIFFERENT_NONZERO_PATTERN);

            Vec solution = ls_diff_precond.Solve();
            num_it_diff_mat = ls_diff_precond.GetNumIterations();

            PetscTools::Destroy(solution);
        }

        TS_ASSERT_EQUALS(num_it_diff_mat, num_it_same_mat);

        /*
         * Setting the identity matrix as a preconditioner is equivalent to no preconditioning
         */
        {
            LinearSystem ls_diff_precond(system_rhs, system_matrix);
            ls_diff_precond.SetKspType("cg");

            ls_diff_precond.SetPrecondMatrixIsDifferentFromLhs();
            Mat& r_identity_matrix=ls_diff_precond.rGetPrecondMatrix();

            for (unsigned row_col=0; row_col<num_nodes; row_col++)
            {
                PetscMatTools::SetElement(r_identity_matrix, row_col, row_col, 1.0);
            }
            ls_diff_precond.FinalisePrecondMatrix();

            Vec solution = ls_diff_precond.Solve();
            num_it_diff_mat = ls_diff_precond.GetNumIterations();

            PetscTools::Destroy(solution);
        }

        TS_ASSERT_EQUALS(num_it_diff_mat, 80u); // It takes 80 iterations if you run with ls.SetPcType("none");
        TS_ASSERT_LESS_THAN(num_it_same_mat, num_it_diff_mat);

        PetscTools::Destroy(system_rhs);
        PetscTools::Destroy(system_matrix);
    }

    void TestFixedNumberOfIterations() throw (Exception)
    {
        unsigned num_nodes = 1331;
        DistributedVectorFactory factory(num_nodes);
        Vec parallel_layout = factory.CreateVec(2);

        Mat system_matrix;
        // Note that this test deadlocks if the file's not on the disk
        PetscTools::ReadPetscObject(system_matrix, "linalg/test/data/matrices/cube_6000elems_half_activated.mat", parallel_layout);

        Vec system_rhs;
        // Note that this test deadlocks if the file's not on the disk
        PetscTools::ReadPetscObject(system_rhs, "linalg/test/data/matrices/cube_6000elems_half_activated.vec", parallel_layout);

        LinearSystem ls = LinearSystem(system_rhs, system_matrix);

        ls.SetMatrixIsSymmetric();
        ls.SetKspType("cg");
        ls.SetPcType("jacobi");
        ls.SetAbsoluteTolerance(1e-4);

        Vec guess;
        VecDuplicate(parallel_layout, &guess);
#if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2)
        PetscScalar zero = 0.0;
        VecSet(&zero, guess);
#else
        VecSet(guess, 0.0);
#endif

        /*
         * Use fixed number of iterations, updating the number of iterations to perform every other solve.
         */
        TS_ASSERT_THROWS_NOTHING(ls.SetUseFixedNumberIterations(true, 2));

        Vec solution = ls.Solve(guess);

        unsigned chebyshev_its = ls.GetNumIterations();
        TS_ASSERT_EQUALS(chebyshev_its, 52u);

        Vec new_solution;
        Vec difference;
        VecDuplicate(parallel_layout, &difference);
        PetscReal l_inf_norm;

        /*
         * Solve using previous solution as new guess. If we were checking convergence
         * normally it would take 0 iterations to solve. Since we set fixed number of
         * iterations based on first solve, it will take the same number as above.
         */
        new_solution = ls.Solve(solution);
        chebyshev_its = ls.GetNumIterations();

        TS_ASSERT_EQUALS(chebyshev_its, 52u);

        PetscVecTools::WAXPY(difference, -1.0, new_solution, solution);
        VecNorm(difference, NORM_INFINITY, &l_inf_norm);
        TS_ASSERT_DELTA(l_inf_norm, 0.0, 4e-4);
        PetscTools::Destroy(new_solution);

        /*
         * Solve using previous solution as new guess takes 0 iterations as
         * it is performed with tolerance-based stop criteria.
         */
        new_solution = ls.Solve(solution);
        chebyshev_its = ls.GetNumIterations();

        TS_ASSERT_EQUALS(chebyshev_its, 0u);

        PetscVecTools::WAXPY(difference, -1.0, new_solution, solution);
        VecNorm(difference, NORM_INFINITY, &l_inf_norm);
        TS_ASSERT_DELTA(l_inf_norm, 0.0, 4e-4);
        PetscTools::Destroy(new_solution);

        /*
         * Solve with initial guess should take 52 iterations but the solver
         * uses the same number of iterations as the previous call.
         */
        new_solution = ls.Solve(guess);
        chebyshev_its = ls.GetNumIterations();

#if ((PETSC_VERSION_MAJOR==3) || (PETSC_VERSION_MAJOR==2 && PETSC_VERSION_MINOR==3 && PETSC_VERSION_SUBMINOR==3))
        TS_ASSERT_EQUALS(chebyshev_its, 0u);
#else
        TS_ASSERT_EQUALS(chebyshev_its, 1u);
#endif

        PetscVecTools::WAXPY(difference, -1.0, new_solution, solution);
        VecNorm(difference, NORM_INFINITY, &l_inf_norm);

#if ((PETSC_VERSION_MAJOR==3) || (PETSC_VERSION_MAJOR==2 && PETSC_VERSION_MINOR==3 && PETSC_VERSION_SUBMINOR==3))
        TS_ASSERT_DELTA(l_inf_norm, 60.47, 2.0);
#else
        TS_ASSERT_DELTA(l_inf_norm, 22.43, 2.0);
#endif

        PetscTools::Destroy(new_solution);

        /*
         * Solve with initial guess and tolerance-based stop criteria takes 52 iterations
         */
        new_solution = ls.Solve(guess);
        chebyshev_its = ls.GetNumIterations();

        TS_ASSERT_EQUALS(chebyshev_its, 52u);

        PetscVecTools::WAXPY(difference, -1.0, new_solution, solution);
        VecNorm(difference, NORM_INFINITY, &l_inf_norm);
        TS_ASSERT_DELTA(l_inf_norm, 0.0, 4e-4);

        PetscTools::Destroy(solution);
        PetscTools::Destroy(new_solution);
        PetscTools::Destroy(difference);

        PetscTools::Destroy(system_matrix);
        PetscTools::Destroy(system_rhs);
        PetscTools::Destroy(parallel_layout);
        PetscTools::Destroy(guess);
    }

    void TestFixedNumberOfIterationsRelativeToleranceCoverage() throw (Exception)
    {
        unsigned num_nodes = 1331;
        DistributedVectorFactory factory(num_nodes);
        Vec parallel_layout = factory.CreateVec(2);

        Mat system_matrix;
        // Note that this test deadlocks if the file's not on the disk
        PetscTools::ReadPetscObject(system_matrix, "linalg/test/data/matrices/cube_6000elems_half_activated.mat", parallel_layout);

        Vec system_rhs;
        // Note that this test deadlocks if the file's not on the disk
        PetscTools::ReadPetscObject(system_rhs, "linalg/test/data/matrices/cube_6000elems_half_activated.vec", parallel_layout);

        LinearSystem ls = LinearSystem(system_rhs, system_matrix);

        ls.SetMatrixIsSymmetric();
        ls.SetKspType("cg");
        ls.SetPcType("jacobi");
        ls.SetRelativeTolerance(1e-6); // Covering the use of relative tolerance for solution

        Vec guess;
        VecDuplicate(parallel_layout, &guess);
#if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2)
        PetscScalar zero = 0.0;
        VecSet(&zero, guess);
#else
        VecSet(guess, 0.0);
#endif

        /*
         *  Use fixed number of iterations, updating the number of iterations to perform every other solve.
         */
        TS_ASSERT_THROWS_NOTHING(ls.SetUseFixedNumberIterations(true, 2));

        Vec solution = ls.Solve(guess);

        unsigned chebyshev_its = ls.GetNumIterations();
        TS_ASSERT_EQUALS(chebyshev_its, 40u);

        Vec new_solution;
        Vec difference;
        VecDuplicate(parallel_layout, &difference);
        PetscReal l_inf_norm;

        /*
         * Solve using previous solution as new guess. If we were checking convergence
         * normally it would take 0 iterations to solve. Since we set fixed number of
         * iterations based on first solve, it will take the same number as above.
         */
        new_solution = ls.Solve(solution);
        chebyshev_its = ls.GetNumIterations();

        TS_ASSERT_EQUALS(chebyshev_its, 40u);

        PetscVecTools::WAXPY(difference, -1.0, new_solution, solution);
        VecNorm(difference, NORM_INFINITY, &l_inf_norm);
        TS_ASSERT_DELTA(l_inf_norm, 0.0, 1e-3);
        PetscTools::Destroy(new_solution);

        PetscTools::Destroy(solution);
        PetscTools::Destroy(difference);

        PetscTools::Destroy(system_matrix);
        PetscTools::Destroy(system_rhs);
        PetscTools::Destroy(parallel_layout);
        PetscTools::Destroy(guess);
    }

    void TestSolveZerosInitialGuessForSmallRhs() throw(Exception)
    {
        LinearSystem ls(2);

        ls.SetMatrixElement(0, 0, 1.0);
        ls.SetMatrixElement(0, 1, 0.0);
        ls.SetMatrixElement(1, 0, 0.0);
        ls.SetMatrixElement(1, 1, 1.0);

        ls.SetRhsVectorElement(0, 1e-17);
        ls.SetRhsVectorElement(1, 0.0);

        Vec init_cond = PetscTools::CreateAndSetVec(2, 0.0);
        PetscVecTools::SetElement(init_cond, 0, 0.01);

        ls.AssembleFinalLinearSystem();

        Vec solution_vector;
        solution_vector = ls.Solve(init_cond);

        ReplicatableVector solution_vector_repl(solution_vector);
        TS_ASSERT_DELTA(solution_vector_repl[0], 0.0, 1e-6);
        TS_ASSERT_DELTA(solution_vector_repl[1], 0.0, 1e-6);

        PetscTools::Destroy(init_cond);
        PetscTools::Destroy(solution_vector);
    }

    /** See #1834 */
    void xxxxTestSolveShowingPetscRubbishInEvenMoreWays() throw(Exception)
    {
        LinearSystem ls(2);

        ls.SetMatrixElement(0, 0, 1.0);
        ls.SetMatrixElement(0, 1, 0.0);
        ls.SetMatrixElement(1, 0, 0.0);
        ls.SetMatrixElement(1, 1, 1.0);

        ls.SetRhsVectorElement(0, log(0.0)); // -inf
        ls.SetRhsVectorElement(1, 0.0);

        ls.AssembleFinalLinearSystem();

        ls.DisplayRhs();

        Vec solution_vector;
        solution_vector = ls.Solve(); // SHOULD fail with an error, but doesn't
        PetscTools::Destroy(solution_vector);
    }

    // This test should be the last in the suite
    void TestSetFromOptions()
    {
        LinearSystem ls = LinearSystem(5);
        PetscOptionsSetValue("-ksp_type", "gmres");
        PetscOptionsSetValue("-pc_type", "jacobi");
        ls.AssembleFinalLinearSystem();

        ls.SetKspType("cg"); //Not really -- see above
        ls.SetPcType("ilu"); //Not really -- see above
        Vec solution_vector3;
        solution_vector3 = ls.Solve();
        PetscTools::Destroy(solution_vector3);

#if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR <= 3) //PETSc 3.0 to PETSc 3.3
        //The PETSc developers changed this one, but later changed it back again!
        const KSPType solver;
        const PCType pc;
#else
        KSPType solver;
        PCType pc;
#endif
        PC prec;
        KSPGetType(ls.mKspSolver, &solver);
        KSPGetPC(ls.mKspSolver, &prec);
        PCGetType(prec, &pc);

        TS_ASSERT( strcmp(solver,"gmres")==0 );
        TS_ASSERT( strcmp(pc,"jacobi")==0 );
    }
    // The above test should be last in the suite

};
#endif //_TESTLINEARSYSTEM_HPP_


// Copyright (c) 2000, 2001, 2002, 2003 by David Scherer and others.
// Copyright (c) 2003, 2004 by Jonathan Brandmeyer and others.
// See the file license.txt for complete license terms.
// See the file authors.txt for a complete list of contributors.

#include "python/convex.hpp"
#include "python/slice.hpp"
#include "util/gl_enable.hpp"
#include "util/errors.hpp"

#include <boost/python/extract.hpp>
#include <boost/crc.hpp>

namespace cvisual { namespace python {

convex::jitter_table convex::jitter;

long
convex::checksum() const
{
	boost::crc_32_type engine;
	engine.process_block( pos.data(), pos.end() );
	return engine.checksum();
}

bool
convex::degenerate() const
{
	return count < 3;
}

void
convex::recalc()
{
	hull.clear();

	const double* pos_i = pos.data();
	// A face from the first, second, and third vectors.
	hull.push_back( face( vector(pos_i), vector(pos_i+3), vector(pos_i+3*2)));
	// The reverse face from the first, third, and second vectors.
	hull.push_back( face( vector(pos_i), vector(pos_i+3*2), vector(pos_i+3)));
	// The remainder of the possible faces.
	for (size_t i = 3; i < count; ++i) {
		add_point( i, vector(pos_i + i*3));
	}

	// Calculate extents
	min_extent = max_extent = vector( pos_i );
	for(size_t i=1; i<count; i++)
		for(size_t j=0; j<3; j++) {
			if (*pos_i < min_extent[j]) min_extent[j] = *pos_i;
			else if (*pos_i > max_extent[j]) max_extent[j] = *pos_i;
			pos_i++;
		}

	last_checksum = checksum();
}

void
convex::add_point( size_t n, vector pv)
{
	double m = pv.mag();
	pv.x += m * jitter.v[(n  ) & jitter.mask];
	pv.y += m * jitter.v[(n+1) & jitter.mask];
	pv.z += m * jitter.v[(n+2) & jitter.mask];

	std::vector<edge> hole;
	for (size_t f=0; f<hull.size(); ) {
		if ( hull[f].visible_from(pv) ) {
			// hull[f] is visible from pv.  We will never get here if pv is
			//   inside the hull.

			// add the edges to the hole.  If an edge is already in the hole,
			//   it is not on the boundary of the hole and is removed.
			for(int e=0; e<3; ++e) {
				edge E( hull[f].corner[e], hull[f].corner[(e+1)%3] );

				bool boundary = true;
				for(std::vector<edge>::iterator h = hole.begin(); h != hole.end(); ++h) {
					if (*h == E) {
						*h = hole.back();
						hole.pop_back();
						boundary = false;
						break;
					}
				}

				if (boundary) {
					hole.push_back(E);
				}
			}

			// remove hull[f]
			hull[f] = hull.back();
			hull.pop_back();
		}
		else
			f++;
	}

	// Now add the boundary of the hole to the hull.  If pv was inside
	//   the hull, the hole will be empty and nothing happens here.
	for (std::vector<edge>::const_iterator h = hole.begin(); h != hole.end(); ++h) {
		hull.push_back(face(h->v[0], h->v[1], pv));
	}
}

convex::convex()
	: last_checksum(0)
{
}

void convex::set_color( const rgb& n_color)
{
	color = n_color;
}

rgb convex::get_color()
{
	return color;
}

void
convex::gl_render(view& scene)
{
	if (degenerate())
		return;
	long check = checksum();
	if (check != last_checksum) {
		recalc();
		last_checksum = check;
	}

	glShadeModel(GL_FLAT);
	gl_enable cull_face( GL_CULL_FACE);
	color.gl_set(1.0);

	glBegin(GL_TRIANGLES);
	for (std::vector<face>::const_iterator f = hull.begin(); f != hull.end(); ++f) {
		f->normal.gl_normal();
		(f->corner[0] * scene.gcf).gl_render();
		(f->corner[1] * scene.gcf).gl_render();
		(f->corner[2] * scene.gcf).gl_render();
	}
	glEnd();
	glShadeModel( GL_SMOOTH);
}

vector
convex::get_center() const
{
	if (degenerate())
		return vector();

	vector ret;
	for (std::vector<face>::const_iterator f = hull.begin(); f != hull.end(); ++f) {
		ret += f->center;
	}
	ret /= hull.empty() ? 1 : hull.size();

	return ret;
}

void
convex::gl_pick_render(view& scene)
{
	gl_render( scene);
}

void
convex::grow_extent( extent& world)
{
	if (degenerate())
		return;

	long check = checksum();
	if (check != last_checksum) {
		recalc();
	}
	assert( hull.size() != 0);

	for (std::vector<face>::const_iterator f = hull.begin(); f != hull.end(); ++f) {
		world.add_point( f->corner[0]);
		world.add_point( f->corner[1]);
		world.add_point( f->corner[2]);
	}
	world.add_body();
}

void
convex::get_material_matrix( const view& v, tmatrix& out ) {
	out.translate( vector(.5,.5,.5) );

	out.scale( vector(1,1,1) * (.999 / (v.gcf * std::max(max_extent.x-min_extent.x, std::max(max_extent.y-min_extent.y, max_extent.z-min_extent.z)))) );

	out.translate( -.5 * v.gcf * (min_extent + max_extent) );
}

} } // !namespace cvisual::python


// Copyright (C) 2009-2012 Lorenzo Caminiti
// Distributed under the Boost Software License, Version 1.0
// (see accompanying file LICENSE_1_0.txt or a copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Home at http://www.boost.org/libs/local_function

#include <boost/config.hpp>
#ifdef BOOST_NO_VARIADIC_MACROS
#   error "variadic macros required"
#else

#include <boost/local_function.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <algorithm>
#include <vector>

int main(void) {
    //[transform
    int offset = 5;
    std::vector<int> v;
    std::vector<int> w;

    for(int i = 1; i <= 2; ++i) v.push_back(i * 10);
    BOOST_TEST(v[0] == 10); BOOST_TEST(v[1] == 20);
    w.resize(v.size());

    int BOOST_LOCAL_FUNCTION(const bind& offset, int i) {
        return ++i + offset;
    } BOOST_LOCAL_FUNCTION_NAME(inc)

    std::transform(v.begin(), v.end(), w.begin(), inc);
    BOOST_TEST(w[0] == 16); BOOST_TEST(w[1] == 26);

    int BOOST_LOCAL_FUNCTION(bind& inc, int i, int j) {
        return inc(i + j); // Call the other bound local function.
    } BOOST_LOCAL_FUNCTION_NAME(inc_sum)

    offset = 0;
    std::transform(v.begin(), v.end(), w.begin(), v.begin(), inc_sum);
    BOOST_TEST(v[0] == 27); BOOST_TEST(v[1] == 47);
    //]
    return boost::report_errors();
}

#endif // VARIADIC_MACROS