diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..fa4d35aae1851fe33254f5eac5aedd9da83d54ad
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,76 @@
+cmake_minimum_required(VERSION 2.8) 
+project(falkolib)
+set(CMAKE_BUILD_TYPE Release)
+add_definitions(-std=c++0x)   # Enabling c++11
+
+SET(falkolib_RUNTIME_OUTPUT_DIRECTORY ${falkolib_SOURCE_DIR}/bin CACHE PATH "Target for the binaries")
+SET(falkolib_LIBRARY_OUTPUT_DIRECTORY ${falkolib_SOURCE_DIR}/lib CACHE PATH "Target for the libraries")
+SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${falkolib_LIBRARY_OUTPUT_DIRECTORY})
+SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${falkolib_LIBRARY_OUTPUT_DIRECTORY})
+SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${falkolib_RUNTIME_OUTPUT_DIRECTORY})
+LIST(APPEND CMAKE_MODULE_PATH ${falkolib_SOURCE_DIR}/cmake_modules)
+
+message(STATUS "CMAKE_MODULE_PATH: ${CMAKE_MODULE_PATH}")
+
+find_package(Boost)  
+if (${Boost_FOUND})
+  message(STATUS "Boost_INCLUDE_DIRS: ${Boost_INCLUDE_DIRS}")
+  message(STATUS "Boost_LIBRARY_DIRS: ${Boost_LIBRARY_DIRS}")
+  message(STATUS "Boost_LIBRARIES: ${Boost_LIBRARY_DIRS}")
+  include_directories(${Boost_INCLUDE_DIRS})
+  link_directories(${Boost_LIBRARY_DIRS})
+endif(${Boost_FOUND})
+
+find_package(Eigen3 REQUIRED)
+if (${EIGEN3_FOUND})
+  include_directories(${EIGEN3_INCLUDE_DIR})
+  message(STATUS "EIGEN3_INCLUDE_DIR: ${EIGEN3_INCLUDE_DIR}")
+else(${EIGEN3_FOUND})
+  message(WARNING "Cannot find Eigen3 Library")
+endif(${EIGEN3_FOUND})
+
+message(STATUS "include dir: ${falkolib_SOURCE_DIR}/include")
+message(STATUS "include dir: ${falkolib_SOURCE_DIR}/EXTERNAL")
+include_directories(${falkolib_SOURCE_DIR}/include ${falkolib_SOURCE_DIR}/EXTERNAL)  
+
+add_library(falkolib 
+  src/Common/HoughSpectrum.cpp
+  src/Feature/FALKOExtractor.cpp
+  src/Feature/OCExtractor.cpp
+  src/Feature/CGH.cpp
+  src/Feature/BSC.cpp
+)
+
+add_executable(testKeypointFalko test/testKeypointFalko.cpp test/testData.cpp)
+target_link_libraries(testKeypointFalko falkolib ${Boost_LIBRARIES})
+
+add_executable(testFalkoAHT test/testFalkoAHT.cpp test/testData.cpp)
+target_link_libraries(testFalkoAHT falkolib ${Boost_LIBRARIES})
+
+add_executable(testFalkoCC test/testFalkoCC.cpp test/testData.cpp)
+target_link_libraries(testFalkoCC falkolib ${Boost_LIBRARIES})
+
+add_executable(testKeypointOC test/testKeypointOC.cpp test/testData.cpp)
+target_link_libraries(testKeypointOC falkolib ${Boost_LIBRARIES}) # boost_iostreams boost_system boost_filesystem
+
+
+# Option "make install": copy binaries
+INSTALL(TARGETS falkolib 
+  RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
+  LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
+  ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
+)
+
+# Option "make install": copy headers
+FILE(GLOB headers_Common "${CMAKE_CURRENT_SOURCE_DIR}/include/falkolib/Common/*.h")
+FILE(GLOB headers_Feature "${CMAKE_CURRENT_SOURCE_DIR}/include/falkolib/Feature/*.h")
+FILE(GLOB headers_Matching "${CMAKE_CURRENT_SOURCE_DIR}/include/falkolib/Matching/*.h")
+INSTALL(FILES ${headers_Common} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/falkolib/Common)
+INSTALL(FILES ${headers_Feature} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/falkolib/Feature)
+INSTALL(FILES ${headers_Matching} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/falkolib/Matching)
+
+# Option "make install": copy cmake script
+FILE(GLOB cmake_script "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/falkolibConfig.cmake")
+message(STATUS "cmake_script " ${cmake_script})
+INSTALL(FILES ${cmake_script} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/falkolib/)
+
diff --git a/LICENSE b/COPYING
similarity index 100%
rename from LICENSE
rename to COPYING
diff --git a/EXTERNAL/gnuplot-iostream.h b/EXTERNAL/gnuplot-iostream.h
new file mode 100644
index 0000000000000000000000000000000000000000..813951d0c3b401db9aed2445956a7556dc1c47ca
--- /dev/null
+++ b/EXTERNAL/gnuplot-iostream.h
@@ -0,0 +1,2211 @@
+// vim:foldmethod=marker
+
+/*
+Copyright (c) 2013 Daniel Stahlke (dan@stahlke.org)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+/* A C++ interface to gnuplot.
+ * Web page: http://www.stahlke.org/dan/gnuplot-iostream
+ * Documentation: https://gitorious.org/gnuplot-iostream/pages/Home
+ *
+ * The whole library consists of this monolithic header file, for ease of installation (the
+ * Makefile and *.cc files are only for examples and tests).
+ *
+ * TODO:
+ * 	What version of boost is currently required?
+ * 	Callbacks via gnuplot's 'bind' function.  This would allow triggering user functions when
+ * 	keys are pressed in the gnuplot window.  However, it would require a PTY reader thread.
+ * 	Maybe temporary files read in a thread can replace PTY stuff.
+ */
+
+#ifndef GNUPLOT_IOSTREAM_H
+#define GNUPLOT_IOSTREAM_H
+
+// {{{1 Includes and defines
+
+#define GNUPLOT_IOSTREAM_VERSION 2
+
+#ifndef GNUPLOT_ENABLE_CXX11
+#	define GNUPLOT_ENABLE_CXX11 (__cplusplus >= 201103)
+#endif
+
+// C system includes
+#include <cstdio>
+#ifdef GNUPLOT_ENABLE_PTY
+#	include <termios.h>
+#	include <unistd.h>
+#	include <pty.h>
+#endif // GNUPLOT_ENABLE_PTY
+
+// C++ system includes
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+#include <utility>
+#include <iomanip>
+#include <vector>
+#include <complex>
+#include <cstdlib>
+#include <cmath>
+
+#if GNUPLOT_ENABLE_CXX11
+#	include <tuple>
+#endif
+
+#include <boost/iostreams/device/file_descriptor.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/version.hpp>
+#include <boost/utility.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/mpl/bool.hpp>
+// This is the version of boost which has v3 of the filesystem libraries by default.
+#if BOOST_VERSION >= 104600
+#	define GNUPLOT_USE_TMPFILE
+#	include <boost/filesystem.hpp>
+#endif // BOOST_VERSION
+
+// This is used because VS2008 doesn't have stdint.h.
+#include <boost/cstdint.hpp>
+
+// Note: this is here for reverse compatibility.  The new way to enable blitz support is to
+// just include the gnuplot-iostream.h header after you include the blitz header (likewise for
+// armadillo).
+#ifdef GNUPLOT_ENABLE_BLITZ
+#	include <blitz/array.h>
+#endif
+
+#ifdef BOOST_STATIC_ASSERT_MSG
+#	define GNUPLOT_STATIC_ASSERT_MSG(cond, msg) BOOST_STATIC_ASSERT_MSG((cond), msg)
+#else
+#	define GNUPLOT_STATIC_ASSERT_MSG(cond, msg) BOOST_STATIC_ASSERT((cond))
+#endif
+
+// If this is defined, warn about use of deprecated functions.
+#ifdef GNUPLOT_DEPRECATE_WARN
+#	ifdef __GNUC__
+#		define GNUPLOT_DEPRECATE(msg) __attribute__ ((deprecated(msg)))
+#	elif defined(_MSC_VER)
+#		define GNUPLOT_DEPRECATE(msg) __declspec(deprecated(msg))
+#	else
+#		define GNUPLOT_DEPRECATE(msg)
+#	endif
+#else
+#	define GNUPLOT_DEPRECATE(msg)
+#endif
+
+// Patch for Windows by Damien Loison
+#ifdef _WIN32
+#	include <windows.h>
+#	define GNUPLOT_PCLOSE _pclose
+#	define GNUPLOT_POPEN  _popen
+#	define GNUPLOT_FILENO _fileno
+#else
+#	define GNUPLOT_PCLOSE pclose
+#	define GNUPLOT_POPEN  popen
+#	define GNUPLOT_FILENO fileno
+#endif
+
+#ifdef _WIN32
+#	define GNUPLOT_ISNAN _isnan
+#else
+// cppreference.com says std::isnan is only for C++11.  However, this seems to work on Linux
+// and I am assuming that if isnan exists in math.h then std::isnan exists in cmath.
+#	define GNUPLOT_ISNAN std::isnan
+#endif
+
+// MSVC gives a warning saying that fopen and getenv are not secure.  But they are secure.
+// Unfortunately their replacement functions are not simple drop-in replacements.  The best
+// solution is to just temporarily disable this warning whenever fopen or getenv is used.
+// http://stackoverflow.com/a/4805353/1048959
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+#	define GNUPLOT_MSVC_WARNING_4996_PUSH \
+		__pragma(warning(push)) \
+		__pragma(warning(disable:4996))
+#	define GNUPLOT_MSVC_WARNING_4996_POP \
+		__pragma(warning(pop))
+#else
+#	define GNUPLOT_MSVC_WARNING_4996_PUSH
+#	define GNUPLOT_MSVC_WARNING_4996_POP
+#endif
+
+#ifndef GNUPLOT_DEFAULT_COMMAND
+#ifdef _WIN32
+// "pgnuplot" is considered deprecated according to the Internet.  It may be faster.  It
+// doesn't seem to handle binary data though.
+//#	define GNUPLOT_DEFAULT_COMMAND "pgnuplot -persist"
+// On Windows, gnuplot echos commands to stderr.  So we forward its stderr to the bit bucket.
+// Unfortunately, this means you will miss out on legitimate error messages.
+#	define GNUPLOT_DEFAULT_COMMAND "gnuplot -persist 2> NUL"
+#else
+#	define GNUPLOT_DEFAULT_COMMAND "gnuplot -persist"
+#endif
+#endif
+
+// }}}1
+
+namespace gnuplotio {
+
+// {{{1 Basic traits helpers
+//
+// The mechanisms constructed in this section enable us to detect what sort of datatype has
+// been passed to a function.
+
+// This can be specialized as needed, in order to not use the STL interfaces for specific
+// classes.
+template <typename T>
+struct dont_treat_as_stl_container {
+	typedef boost::mpl::bool_<false> type;
+};
+
+BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type)
+BOOST_MPL_HAS_XXX_TRAIT_DEF(const_iterator)
+
+template <typename T>
+struct is_like_stl_container {
+	typedef boost::mpl::and_<
+			typename has_value_type<T>::type,
+			typename has_const_iterator<T>::type,
+			boost::mpl::not_<dont_treat_as_stl_container<T> >
+		> type;
+	static const bool value = type::value;
+};
+
+template <typename T>
+struct is_boost_tuple_nulltype {
+	static const bool value = false;
+	typedef boost::mpl::bool_<value> type;
+};
+
+template <>
+struct is_boost_tuple_nulltype<boost::tuples::null_type> {
+	static const bool value = true;
+	typedef boost::mpl::bool_<value> type;
+};
+
+BOOST_MPL_HAS_XXX_TRAIT_DEF(head_type)
+BOOST_MPL_HAS_XXX_TRAIT_DEF(tail_type)
+
+template <typename T>
+struct is_boost_tuple {
+	typedef boost::mpl::and_<
+			typename has_head_type<T>::type,
+			typename has_tail_type<T>::type
+		> type;
+	static const bool value = type::value;
+};
+
+// More fine-grained, but doesn't compile!
+//template <typename T>
+//struct is_boost_tuple {
+//	typedef boost::mpl::and_<
+//		typename boost::is_class<T>::type,
+//		typename boost::mpl::and_<
+//			typename has_head_type<T>::type,
+//			typename boost::mpl::and_<
+//				typename has_tail_type<T>::type,
+//				typename boost::mpl::or_<
+//					typename is_boost_tuple_nulltype<typename T::tail_type>::type,
+//					typename is_boost_tuple<typename T::tail_type>::type
+//				>::type
+//			>::type
+//		>::type
+//	> type;
+//};
+//
+//template <>
+//struct is_boost_tuple<boost::tuples::null_type> {
+//	typedef boost::mpl::bool_<false> type;
+//};
+
+// }}}1
+
+// {{{1 Tmpfile helper class
+#ifdef GNUPLOT_USE_TMPFILE
+// RAII temporary file.  File is removed when this object goes out of scope.
+class GnuplotTmpfile {
+public:
+	GnuplotTmpfile() :
+		file(boost::filesystem::unique_path(
+			boost::filesystem::temp_directory_path() /
+			"tmp-gnuplot-%%%%-%%%%-%%%%-%%%%"))
+	{ }
+
+private:
+	// noncopyable
+	GnuplotTmpfile(const GnuplotTmpfile &);
+	const GnuplotTmpfile& operator=(const GnuplotTmpfile &);
+
+public:
+	~GnuplotTmpfile() {
+		// it is never good to throw exceptions from a destructor
+		try {
+			remove(file);
+		} catch(const std::exception &) {
+			std::cerr << "Failed to remove temporary file " << file << std::endl;
+		}
+	}
+
+public:
+	boost::filesystem::path file;
+};
+#endif // GNUPLOT_USE_TMPFILE
+// }}}1
+
+// {{{1 Feedback helper classes
+//
+// Used for reading stuff sent from gnuplot via gnuplot's "print" function.
+//
+// For example, this is used for capturing mouse clicks in the gnuplot window.  There are two
+// implementations, only the first of which is complete.  The first implementation allocates a
+// PTY (pseudo terminal) which is written to by gnuplot and read by us.  This only works in
+// Linux.  The second implementation creates a temporary file which is written to by gnuplot
+// and read by us.  However, this doesn't currently work since fscanf doesn't block.  It would
+// be possible to get this working using a more complicated mechanism (select or threads) but I
+// haven't had the need for it.
+
+class GnuplotFeedback {
+public:
+	GnuplotFeedback() { }
+	virtual ~GnuplotFeedback() { }
+	virtual std::string filename() const = 0;
+	virtual FILE *handle() const = 0;
+
+private:
+	// noncopyable
+	GnuplotFeedback(const GnuplotFeedback &);
+	const GnuplotFeedback& operator=(const GnuplotFeedback &);
+};
+
+#ifdef GNUPLOT_ENABLE_PTY
+#define GNUPLOT_ENABLE_FEEDBACK
+class GnuplotFeedbackPty : public GnuplotFeedback {
+public:
+	explicit GnuplotFeedbackPty(bool debug_messages) :
+		pty_fn(),
+		pty_fh(NULL),
+		master_fd(-1),
+		slave_fd(-1)
+	{
+	// adapted from http://www.gnuplot.info/files/gpReadMouseTest.c
+		if(0 > openpty(&master_fd, &slave_fd, NULL, NULL, NULL)) {
+			perror("openpty");
+			throw std::runtime_error("openpty failed");
+		}
+		char pty_fn_buf[1024];
+		if(ttyname_r(slave_fd, pty_fn_buf, 1024)) {
+			perror("ttyname_r");
+			throw std::runtime_error("ttyname failed");
+		}
+		pty_fn = std::string(pty_fn_buf);
+		if(debug_messages) {
+			std::cerr << "feedback_fn=" << pty_fn << std::endl;
+		}
+
+		// disable echo
+		struct termios tios;
+		if(tcgetattr(slave_fd, &tios) < 0) {
+			perror("tcgetattr");
+			throw std::runtime_error("tcgetattr failed");
+		}
+		tios.c_lflag &= ~(ECHO | ECHONL);
+		if(tcsetattr(slave_fd, TCSAFLUSH, &tios) < 0) {
+			perror("tcsetattr");
+			throw std::runtime_error("tcsetattr failed");
+		}
+
+		pty_fh = fdopen(master_fd, "r");
+		if(!pty_fh) {
+			throw std::runtime_error("fdopen failed");
+		}
+	}
+
+private:
+	// noncopyable
+	GnuplotFeedbackPty(const GnuplotFeedbackPty &);
+	const GnuplotFeedbackPty& operator=(const GnuplotFeedbackPty &);
+
+public:
+	~GnuplotFeedbackPty() {
+		if(pty_fh) fclose(pty_fh);
+		if(master_fd > 0) ::close(master_fd);
+		if(slave_fd  > 0) ::close(slave_fd);
+	}
+
+	std::string filename() const {
+		return pty_fn;
+	}
+
+	FILE *handle() const {
+		return pty_fh;
+	}
+
+private:
+	std::string pty_fn;
+	FILE *pty_fh;
+	int master_fd, slave_fd;
+};
+//#elif defined GNUPLOT_USE_TMPFILE
+//// Currently this doesn't work since fscanf doesn't block (need something like "tail -f")
+//#define GNUPLOT_ENABLE_FEEDBACK
+//class GnuplotFeedbackTmpfile : public GnuplotFeedback {
+//public:
+//	explicit GnuplotFeedbackTmpfile(bool debug_messages) :
+//		tmp_file(),
+//		fh(NULL)
+//	{
+//		if(debug_messages) {
+//			std::cerr << "feedback_fn=" << filename() << std::endl;
+//		}
+//		GNUPLOT_MSVC_WARNING_4996_PUSH
+//		fh = std::fopen(filename().c_str(), "a");
+//		GNUPLOT_MSVC_WARNING_4996_POP
+//	}
+//
+//	~GnuplotFeedbackTmpfile() {
+//		fclose(fh);
+//	}
+//
+//private:
+//	// noncopyable
+//	GnuplotFeedbackTmpfile(const GnuplotFeedbackTmpfile &);
+//	const GnuplotFeedbackTmpfile& operator=(const GnuplotFeedbackTmpfile &);
+//
+//public:
+//	std::string filename() const {
+//		return tmp_file.file.string();
+//	}
+//
+//	FILE *handle() const {
+//		return fh;
+//	}
+//
+//private:
+//	GnuplotTmpfile tmp_file;
+//	FILE *fh;
+//};
+#endif // GNUPLOT_ENABLE_PTY, GNUPLOT_USE_TMPFILE
+// }}}1
+
+// {{{1 Traits and printers for entry datatypes
+//
+// This section contains the mechanisms for sending scalar and tuple data to gnuplot.  Pairs
+// and tuples are sent by appealing to the senders defined for their component scalar types.
+// Senders for arrays are defined in a later section.
+//
+// There are three classes which need to be specialized for each supported datatype:
+// 1. TextSender to send data as text.  The default is to just send using the ostream's `<<`
+// operator.
+// 2. BinarySender to send data as binary, in a format which gnuplot can understand.  There is
+// no default implementation (unimplemented types raise a compile time error), however
+// inheriting from FlatBinarySender will send the data literally as it is stored in memory.
+// This suffices for most of the standard built-in types (e.g. uint32_t or double).
+// 3. BinfmtSender sends a description of the data format to gnuplot (e.g. `%uint32`).  Type
+// `show datafile binary datasizes` in gnuplot to see a list of supported formats.
+
+// {{{2 Basic entry datatypes
+
+// Default TextSender, sends data using `<<` operator.
+template <typename T, typename Enable=void>
+struct TextSender {
+	static void send(std::ostream &stream, const T &v) {
+		stream << v;
+	}
+};
+
+// Default BinarySender, raises a compile time error.
+template <typename T, typename Enable=void>
+struct BinarySender {
+	GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "BinarySender class not specialized for this type");
+
+	// This is here to avoid further compilation errors, beyond what the assert prints.
+	static void send(std::ostream &stream, const T &v);
+};
+
+// This is a BinarySender implementation that just sends directly from memory.  Data types
+// which can be sent this way can have their BinarySender specialization inherit from this.
+template <typename T>
+struct FlatBinarySender {
+	static void send(std::ostream &stream, const T &v) {
+		stream.write(reinterpret_cast<const char *>(&v), sizeof(T));
+	}
+};
+
+// Default BinfmtSender, raises a compile time error.
+template <typename T, typename Enable=void>
+struct BinfmtSender {
+	GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "BinfmtSender class not specialized for this type");
+
+	// This is here to avoid further compilation errors, beyond what the assert prints.
+	static void send(std::ostream &);
+};
+
+// BinfmtSender implementations for basic data types supported by gnuplot.
+// Types from boost/cstdint.hpp are used because VS2008 doesn't have stdint.h.
+template<> struct BinfmtSender< float> { static void send(std::ostream &stream) { stream << "%float";  } };
+template<> struct BinfmtSender<double> { static void send(std::ostream &stream) { stream << "%double"; } };
+template<> struct BinfmtSender<boost::  int8_t> { static void send(std::ostream &stream) { stream << "%int8";   } };
+template<> struct BinfmtSender<boost:: uint8_t> { static void send(std::ostream &stream) { stream << "%uint8";  } };
+template<> struct BinfmtSender<boost:: int16_t> { static void send(std::ostream &stream) { stream << "%int16";  } };
+template<> struct BinfmtSender<boost::uint16_t> { static void send(std::ostream &stream) { stream << "%uint16"; } };
+template<> struct BinfmtSender<boost:: int32_t> { static void send(std::ostream &stream) { stream << "%int32";  } };
+template<> struct BinfmtSender<boost::uint32_t> { static void send(std::ostream &stream) { stream << "%uint32"; } };
+template<> struct BinfmtSender<boost:: int64_t> { static void send(std::ostream &stream) { stream << "%int64";  } };
+template<> struct BinfmtSender<boost::uint64_t> { static void send(std::ostream &stream) { stream << "%uint64"; } };
+
+// BinarySender implementations for basic data types supported by gnuplot.  These types can
+// just be sent as stored in memory, so all these senders inherit from FlatBinarySender.
+template<> struct BinarySender< float> : public FlatBinarySender< float> { };
+template<> struct BinarySender<double> : public FlatBinarySender<double> { };
+template<> struct BinarySender<boost::  int8_t> : public FlatBinarySender<boost::  int8_t> { };
+template<> struct BinarySender<boost:: uint8_t> : public FlatBinarySender<boost:: uint8_t> { };
+template<> struct BinarySender<boost:: int16_t> : public FlatBinarySender<boost:: int16_t> { };
+template<> struct BinarySender<boost::uint16_t> : public FlatBinarySender<boost::uint16_t> { };
+template<> struct BinarySender<boost:: int32_t> : public FlatBinarySender<boost:: int32_t> { };
+template<> struct BinarySender<boost::uint32_t> : public FlatBinarySender<boost::uint32_t> { };
+template<> struct BinarySender<boost:: int64_t> : public FlatBinarySender<boost:: int64_t> { };
+template<> struct BinarySender<boost::uint64_t> : public FlatBinarySender<boost::uint64_t> { };
+
+// Make char types print as integers, not as characters.
+template <typename T>
+struct CastIntTextSender {
+	static void send(std::ostream &stream, const T &v) {
+		stream << int(v);
+	}
+};
+template<> struct TextSender<          char> : public CastIntTextSender<          char> { };
+template<> struct TextSender<   signed char> : public CastIntTextSender<   signed char> { };
+template<> struct TextSender< unsigned char> : public CastIntTextSender< unsigned char> { };
+
+// Make sure that the same not-a-number string is printed on all platforms.
+template <typename T>
+struct FloatTextSender {
+	static void send(std::ostream &stream, const T &v) {
+		if(GNUPLOT_ISNAN(v)) { stream << "nan"; } else { stream << v; }
+	}
+};
+template<> struct TextSender<      float> : FloatTextSender<      float> { };
+template<> struct TextSender<     double> : FloatTextSender<     double> { };
+template<> struct TextSender<long double> : FloatTextSender<long double> { };
+
+// }}}2
+
+// {{{2 std::pair support
+
+template <typename T, typename U>
+struct TextSender<std::pair<T, U> > {
+	static void send(std::ostream &stream, const std::pair<T, U> &v) {
+		TextSender<T>::send(stream, v.first);
+		stream << " ";
+		TextSender<U>::send(stream, v.second);
+	}
+};
+
+template <typename T, typename U>
+struct BinfmtSender<std::pair<T, U> > {
+	static void send(std::ostream &stream) {
+		BinfmtSender<T>::send(stream);
+		BinfmtSender<U>::send(stream);
+	}
+};
+
+template <typename T, typename U>
+struct BinarySender<std::pair<T, U> > {
+	static void send(std::ostream &stream, const std::pair<T, U> &v) {
+		BinarySender<T>::send(stream, v.first);
+		BinarySender<U>::send(stream, v.second);
+	}
+};
+
+// }}}2
+
+// {{{2 std::complex support
+
+template <typename T>
+struct TextSender<std::complex<T> > {
+	static void send(std::ostream &stream, const std::complex<T> &v) {
+		TextSender<T>::send(stream, v.real());
+		stream << " ";
+		TextSender<T>::send(stream, v.imag());
+	}
+};
+
+template <typename T>
+struct BinfmtSender<std::complex<T> > {
+	static void send(std::ostream &stream) {
+		BinfmtSender<T>::send(stream);
+		BinfmtSender<T>::send(stream);
+	}
+};
+
+template <typename T>
+struct BinarySender<std::complex<T> > {
+	static void send(std::ostream &stream, const std::complex<T> &v) {
+		BinarySender<T>::send(stream, v.real());
+		BinarySender<T>::send(stream, v.imag());
+	}
+};
+
+// }}}2
+
+// {{{2 boost::tuple support
+
+template <typename T>
+struct TextSender<T,
+	typename boost::enable_if<
+		boost::mpl::and_<
+			is_boost_tuple<T>,
+			boost::mpl::not_<is_boost_tuple_nulltype<typename T::tail_type> >
+		>
+	>::type
+> {
+	static void send(std::ostream &stream, const T &v) {
+		TextSender<typename T::head_type>::send(stream, v.get_head());
+		stream << " ";
+		TextSender<typename T::tail_type>::send(stream, v.get_tail());
+	}
+};
+
+template <typename T>
+struct TextSender<T,
+	typename boost::enable_if<
+		boost::mpl::and_<
+			is_boost_tuple<T>,
+			is_boost_tuple_nulltype<typename T::tail_type>
+		>
+	>::type
+> {
+	static void send(std::ostream &stream, const T &v) {
+		TextSender<typename T::head_type>::send(stream, v.get_head());
+	}
+};
+
+template <typename T>
+struct BinfmtSender<T,
+	typename boost::enable_if<
+		boost::mpl::and_<
+			is_boost_tuple<T>,
+			boost::mpl::not_<is_boost_tuple_nulltype<typename T::tail_type> >
+		>
+	>::type
+> {
+	static void send(std::ostream &stream) {
+		BinfmtSender<typename T::head_type>::send(stream);
+		stream << " ";
+		BinfmtSender<typename T::tail_type>::send(stream);
+	}
+};
+
+template <typename T>
+struct BinfmtSender<T,
+	typename boost::enable_if<
+		boost::mpl::and_<
+			is_boost_tuple<T>,
+			is_boost_tuple_nulltype<typename T::tail_type>
+		>
+	>::type
+> {
+	static void send(std::ostream &stream) {
+		BinfmtSender<typename T::head_type>::send(stream);
+	}
+};
+
+template <typename T>
+struct BinarySender<T,
+	typename boost::enable_if<
+		boost::mpl::and_<
+			is_boost_tuple<T>,
+			boost::mpl::not_<is_boost_tuple_nulltype<typename T::tail_type> >
+		>
+	>::type
+> {
+	static void send(std::ostream &stream, const T &v) {
+		BinarySender<typename T::head_type>::send(stream, v.get_head());
+		BinarySender<typename T::tail_type>::send(stream, v.get_tail());
+	}
+};
+
+template <typename T>
+struct BinarySender<T,
+	typename boost::enable_if<
+		boost::mpl::and_<
+			is_boost_tuple<T>,
+			is_boost_tuple_nulltype<typename T::tail_type>
+		>
+	>::type
+> {
+	static void send(std::ostream &stream, const T &v) {
+		BinarySender<typename T::head_type>::send(stream, v.get_head());
+	}
+};
+
+// }}}2
+
+// {{{2 std::tuple support
+
+#if GNUPLOT_ENABLE_CXX11
+
+// http://stackoverflow.com/questions/6245735/pretty-print-stdtuple
+
+template<std::size_t> struct int_{}; // compile-time counter
+
+template <typename Tuple, std::size_t I>
+void std_tuple_formatcode_helper(std::ostream &stream, const Tuple *, int_<I>) {
+	std_tuple_formatcode_helper(stream, (const Tuple *)(0), int_<I-1>());
+	stream << " ";
+	BinfmtSender<typename std::tuple_element<I, Tuple>::type>::send(stream);
+}
+
+template <typename Tuple>
+void std_tuple_formatcode_helper(std::ostream &stream, const Tuple *, int_<0>) {
+	BinfmtSender<typename std::tuple_element<0, Tuple>::type>::send(stream);
+}
+
+template <typename... Args>
+struct BinfmtSender<std::tuple<Args...> > {
+	typedef typename std::tuple<Args...> Tuple;
+
+	static void send(std::ostream &stream) {
+		std_tuple_formatcode_helper(stream, (const Tuple *)(0), int_<sizeof...(Args)-1>());
+	}
+};
+
+template <typename Tuple, std::size_t I>
+void std_tuple_textsend_helper(std::ostream &stream, const Tuple &v, int_<I>) {
+	std_tuple_textsend_helper(stream, v, int_<I-1>());
+	stream << " ";
+	TextSender<typename std::tuple_element<I, Tuple>::type>::send(stream, std::get<I>(v));
+}
+
+template <typename Tuple>
+void std_tuple_textsend_helper(std::ostream &stream, const Tuple &v, int_<0>) {
+	TextSender<typename std::tuple_element<0, Tuple>::type>::send(stream, std::get<0>(v));
+}
+
+template <typename... Args>
+struct TextSender<std::tuple<Args...> > {
+	typedef typename std::tuple<Args...> Tuple;
+
+	static void send(std::ostream &stream, const Tuple &v) {
+		std_tuple_textsend_helper(stream, v, int_<sizeof...(Args)-1>());
+	}
+};
+
+template <typename Tuple, std::size_t I>
+void std_tuple_binsend_helper(std::ostream &stream, const Tuple &v, int_<I>) {
+	std_tuple_binsend_helper(stream, v, int_<I-1>());
+	BinarySender<typename std::tuple_element<I, Tuple>::type>::send(stream, std::get<I>(v));
+}
+
+template <typename Tuple>
+void std_tuple_binsend_helper(std::ostream &stream, const Tuple &v, int_<0>) {
+	BinarySender<typename std::tuple_element<0, Tuple>::type>::send(stream, std::get<0>(v));
+}
+
+template <typename... Args>
+struct BinarySender<std::tuple<Args...> > {
+	typedef typename std::tuple<Args...> Tuple;
+
+	static void send(std::ostream &stream, const Tuple &v) {
+		std_tuple_binsend_helper(stream, v, int_<sizeof...(Args)-1>());
+	}
+};
+
+#endif // GNUPLOT_ENABLE_CXX11
+
+// }}}2
+
+// }}}1
+
+// {{{1 ArrayTraits and Range classes
+//
+// This section handles sending of array data to gnuplot.  It is rather complicated because of
+// the diversity of storage schemes supported.  For example, it treats a
+// `std::pair<std::vector<T>, std::vector<U>>` in the same way as a
+// `std::vector<std::pair<T, U>>`, iterating through the two arrays in lockstep, and sending
+// pairs <T,U> to gnuplot as columns.  In fact, any nested combination of pairs, tuples, STL
+// containers, Blitz arrays, and Armadillo arrays is supported (with the caveat that, for
+// instance, Blitz arrays should never be put into an STL container or you will suffer
+// unpredictable results due the way Blitz handles assignment).  Nested containers are
+// considered to be multidimensional arrays.  Although gnuplot only supports 1D and 2D arrays,
+// our module is in principle not limited.
+//
+// The ArrayTraits class is specialized for every supported array or container type (the
+// default, unspecialized, version of ArrayTraits exists only to tell you that something is
+// *not* a container, via the is_container flag).  ArrayTraits tells you the depth of a nested
+// (or multidimensional) container, as well as the value type, and provides a specialized
+// sort of iterator (a.k.a. "range").  Ranges are sort of like STL iterators, except that they
+// have built-in knowledge of the end condition so you don't have to carry around both a
+// begin() and an end() iterator like in STL.
+//
+// As an example of how this works, consider a std::pair of std::vectors.  Ultimately this gets
+// sent to gnuplot as two columns, so the two vectors need to be iterated in lockstep.
+// The `value_type` of `std::pair<std::vector<T>, std::vector<U>>` is then `std::pair<T, U>`
+// and this is what deferencing the range (iterator) gives.  Internally, this range is built
+// out of a pair of ranges (PairOfRange class), the `inc()` (advance to next element)
+// method calls `inc()` on each of the children, and `deref()` calls `deref()` on each child
+// and combines the results to return a `std::pair`.  Tuples are handled as nested pairs.
+//
+// In addition to PairOfRange, there is also a VecOfRange class that can be used to treat the
+// outermost part of a nested container as if it were a tuple.  Since tuples are printed as
+// columns, this is like treating a multidimensional array as if it were column-major.  A
+// VecOfRange is obtained by calling `get_columns_range`.  This is used by, for instance,
+// `send1d_colmajor`.  The implementation is similar to that of PairOfRange.
+//
+// The range, accessed via `ArrayTraits<T>::get_range`, will be of a different class depending
+// on T, and this is defined by the ArrayTraits specialization for T.  It will always have
+// methods `inc()` to advance to the next element and `is_end()` for checking whether one has
+// advanced past the final element.  For nested containers, `deref_subiter()` returns a range
+// iterator for the next nesting level.  When at the innermost level of nesting, `deref()`
+// returns the value of the entry the iterator points to (a scalar, pair, or tuple).
+// Only one of `deref()` or `deref_subiter()` will be available, depending on whether there are
+// deeper levels of nesting.  The typedefs `value_type` and `subiter_type` tell the return
+// types of these two methods.
+//
+// Support for standard C++ and boost containers and tuples of containers is provided in this
+// section.  Support for third party packages like Blitz and Armadillo is in a later section.
+
+// {{{2 ArrayTraits generic class and defaults
+
+// Error messages involving this stem from treating something that was not a container as if it
+// was.  This is only here to allow compiliation without errors in normal cases.
+struct Error_WasNotContainer {
+	// This is just here to make VC++ happy.
+	// https://connect.microsoft.com/VisualStudio/feedback/details/777612/class-template-specialization-that-compiles-in-g-but-not-visual-c
+	typedef void subiter_type;
+};
+
+// Error messages involving this stem from calling deref instead of deref_subiter for a nested
+// container.
+struct Error_InappropriateDeref { };
+
+// The unspecialized version of this class gives traits for things that are *not* arrays.
+template <typename T, typename Enable=void>
+class ArrayTraits {
+public:
+	// The value type of elements after all levels of nested containers have been dereferenced.
+	typedef Error_WasNotContainer value_type;
+	// The type of the range (a.k.a. iterator) that `get_range()` returns.
+	typedef Error_WasNotContainer range_type;
+	// Tells whether T is in fact a container type.
+	static const bool is_container = false;
+	// This flag supports the legacy behavior of automatically guessing whether the data should
+	// be treated as column major.  This guessing happens when `send()` is called rather than
+	// `send1d()` or `send2d()`.  This is deprecated, but is still supported for reverse
+	// compatibility.
+	static const bool allow_auto_unwrap = false;
+	// The number of levels of nesting, or the dimension of multidimensional arrays.
+	static const size_t depth = 0;
+
+	// Returns the range (iterator) for an array.
+	static range_type get_range(const T &) {
+		GNUPLOT_STATIC_ASSERT_MSG((sizeof(T)==0), "argument was not a container");
+		throw std::logic_error("static assert should have been triggered by this point");
+	}
+};
+
+// Most specializations of ArrayTraits should inherit from this (with V set to the value type).
+// It sets some default values.
+template <typename V>
+class ArrayTraitsDefaults {
+public:
+	typedef V value_type;
+
+	static const bool is_container = true;
+	static const bool allow_auto_unwrap = true;
+	static const size_t depth = ArrayTraits<V>::depth + 1;
+};
+
+// This handles reference types, such as are given with boost::tie.
+// It also allows for instance "ArrayTraits<T[N]>" to match "ArrayTraits<T (&) [N]>".
+// I think this is okay to do... The alternative is to use remove_reference all over the place.
+template <typename T>
+class ArrayTraits<T&> : public ArrayTraits<T> { };
+
+// FIXME - is this okay?
+// It supports gp.send1d(std::forward_as_tuple(x, std::move(y)));
+#if GNUPLOT_ENABLE_CXX11
+template <typename T>
+class ArrayTraits<T&&> : public ArrayTraits<T> { };
+#endif
+
+// }}}2
+
+// {{{2 STL container support
+
+template <typename TI, typename TV>
+class IteratorRange {
+public:
+	IteratorRange() { }
+	IteratorRange(const TI &_it, const TI &_end) : it(_it), end(_end) { }
+
+	static const bool is_container = ArrayTraits<TV>::is_container;
+	typedef typename boost::mpl::if_c<is_container,
+			Error_InappropriateDeref, TV>::type value_type;
+	typedef typename ArrayTraits<TV>::range_type subiter_type;
+
+	bool is_end() const { return it == end; }
+
+	void inc() { ++it; }
+
+	value_type deref() const {
+		GNUPLOT_STATIC_ASSERT_MSG(sizeof(TV) && !is_container,
+			"deref called on nested container");
+		return *it;
+	}
+
+	subiter_type deref_subiter() const {
+		GNUPLOT_STATIC_ASSERT_MSG(sizeof(TV) && is_container,
+			"deref_iter called on non-nested container");
+		return ArrayTraits<TV>::get_range(*it);
+	}
+
+private:
+	TI it, end;
+};
+
+template <typename T>
+class ArrayTraits<T,
+	typename boost::enable_if<is_like_stl_container<T> >::type
+> : public ArrayTraitsDefaults<typename T::value_type> {
+public:
+	typedef IteratorRange<typename T::const_iterator, typename T::value_type> range_type;
+
+	static range_type get_range(const T &arg) {
+		return range_type(arg.begin(), arg.end());
+	}
+};
+
+// }}}2
+
+// {{{2 C style array support
+
+template <typename T, size_t N>
+class ArrayTraits<T[N]> : public ArrayTraitsDefaults<T> {
+public:
+	typedef IteratorRange<const T*, T> range_type;
+
+	static range_type get_range(const T (&arg)[N]) {
+		return range_type(arg, arg+N);
+	}
+};
+
+// }}}2
+
+// {{{2 std::pair support
+
+template <typename RT, typename RU>
+class PairOfRange {
+	template <typename T, typename U, typename PrintMode>
+	friend void deref_and_print(std::ostream &, const PairOfRange<T, U> &, PrintMode);
+
+public:
+	PairOfRange() { }
+	PairOfRange(const RT &_l, const RU &_r) : l(_l), r(_r) { }
+
+	static const bool is_container = RT::is_container && RU::is_container;
+
+	typedef std::pair<typename RT::value_type, typename RU::value_type> value_type;
+	typedef PairOfRange<typename RT::subiter_type, typename RU::subiter_type> subiter_type;
+
+	bool is_end() const {
+		bool el = l.is_end();
+		bool er = r.is_end();
+		if(el != er) {
+			throw std::length_error("columns were different lengths");
+		}
+		return el;
+	}
+
+	void inc() {
+		l.inc();
+		r.inc();
+	}
+
+	value_type deref() const {
+		return std::make_pair(l.deref(), r.deref());
+	}
+
+	subiter_type deref_subiter() const {
+		return subiter_type(l.deref_subiter(), r.deref_subiter());
+	}
+
+private:
+	RT l;
+	RU r;
+};
+
+template <typename T, typename U>
+class ArrayTraits<std::pair<T, U> > {
+public:
+	typedef PairOfRange<typename ArrayTraits<T>::range_type, typename ArrayTraits<U>::range_type> range_type;
+	typedef std::pair<typename ArrayTraits<T>::value_type, typename ArrayTraits<U>::value_type> value_type;
+	static const bool is_container = ArrayTraits<T>::is_container && ArrayTraits<U>::is_container;
+	// Don't allow colwrap since it's already wrapped.
+	static const bool allow_auto_unwrap = false;
+	// It is allowed for l_depth != r_depth, for example one column could be 'double' and the
+	// other column could be 'vector<double>'.
+	static const size_t l_depth = ArrayTraits<T>::depth;
+	static const size_t r_depth = ArrayTraits<U>::depth;
+	static const size_t depth = (l_depth < r_depth) ? l_depth : r_depth;
+
+	static range_type get_range(const std::pair<T, U> &arg) {
+		return range_type(
+			ArrayTraits<T>::get_range(arg.first),
+			ArrayTraits<U>::get_range(arg.second)
+		);
+	}
+};
+
+// }}}2
+
+// {{{2 boost::tuple support
+
+template <typename T>
+class ArrayTraits<T,
+	typename boost::enable_if<
+		boost::mpl::and_<
+			is_boost_tuple<T>,
+			boost::mpl::not_<is_boost_tuple_nulltype<typename T::tail_type> >
+		>
+	>::type
+> : public ArrayTraits<
+	typename std::pair<
+		typename T::head_type,
+		typename T::tail_type
+	>
+> {
+public:
+	typedef typename T::head_type HT;
+	typedef typename T::tail_type TT;
+
+	typedef ArrayTraits<typename std::pair<HT, TT> > parent;
+
+	static typename parent::range_type get_range(const T &arg) {
+		return typename parent::range_type(
+			ArrayTraits<HT>::get_range(arg.get_head()),
+			ArrayTraits<TT>::get_range(arg.get_tail())
+		);
+	}
+};
+
+template <typename T>
+class ArrayTraits<T,
+	typename boost::enable_if<
+		boost::mpl::and_<
+			is_boost_tuple<T>,
+			is_boost_tuple_nulltype<typename T::tail_type>
+		>
+	>::type
+> : public ArrayTraits<
+	typename T::head_type
+> {
+	typedef typename T::head_type HT;
+
+	typedef ArrayTraits<HT> parent;
+
+public:
+	static typename parent::range_type get_range(const T &arg) {
+		return parent::get_range(arg.get_head());
+	}
+};
+
+// }}}2
+
+// {{{2 std::tuple support
+
+#if GNUPLOT_ENABLE_CXX11
+
+template <typename Tuple, size_t idx>
+struct StdTupUnwinder {
+	typedef std::pair<
+		typename StdTupUnwinder<Tuple, idx-1>::type,
+		typename std::tuple_element<idx, Tuple>::type
+	> type;
+
+	static typename ArrayTraits<type>::range_type get_range(const Tuple &arg) {
+		return typename ArrayTraits<type>::range_type(
+			StdTupUnwinder<Tuple, idx-1>::get_range(arg),
+			ArrayTraits<typename std::tuple_element<idx, Tuple>::type>::get_range(std::get<idx>(arg))
+		);
+	}
+};
+
+template <typename Tuple>
+struct StdTupUnwinder<Tuple, 0> {
+	typedef typename std::tuple_element<0, Tuple>::type type;
+
+	static typename ArrayTraits<type>::range_type get_range(const Tuple &arg) {
+		return ArrayTraits<type>::get_range(std::get<0>(arg));
+	}
+};
+
+template <typename... Args>
+class ArrayTraits<std::tuple<Args...> > :
+	public ArrayTraits<typename StdTupUnwinder<std::tuple<Args...>, sizeof...(Args)-1>::type>
+{
+	typedef std::tuple<Args...> Tuple;
+	typedef ArrayTraits<typename StdTupUnwinder<Tuple, sizeof...(Args)-1>::type> parent;
+
+public:
+	static typename parent::range_type get_range(const Tuple &arg) {
+		return StdTupUnwinder<std::tuple<Args...>, sizeof...(Args)-1>::get_range(arg);
+	}
+};
+
+#endif // GNUPLOT_ENABLE_CXX11
+
+// }}}2
+
+// {{{2 Support column unwrap of container (VecOfRange)
+//
+// VecOfRange (created via `get_columns_range()`) treats the outermost level of a nested
+// container as if it were a tuple.  Since tuples are sent to gnuplot as columns, this has the
+// effect of addressing a multidimensional array in column major order.
+
+template <typename RT>
+class VecOfRange {
+	template <typename T, typename PrintMode>
+	friend void deref_and_print(std::ostream &, const VecOfRange<T> &, PrintMode);
+
+public:
+	VecOfRange() { }
+	explicit VecOfRange(const std::vector<RT> &_rvec) : rvec(_rvec) { }
+
+	static const bool is_container = RT::is_container;
+	// Don't allow colwrap since it's already wrapped.
+	static const bool allow_auto_unwrap = false;
+
+	typedef std::vector<typename RT::value_type> value_type;
+	typedef VecOfRange<typename RT::subiter_type> subiter_type;
+
+	bool is_end() const {
+		if(rvec.empty()) return true;
+		bool ret = rvec[0].is_end();
+		for(size_t i=1; i<rvec.size(); i++) {
+			if(ret != rvec[i].is_end()) {
+				throw std::length_error("columns were different lengths");
+			}
+		}
+		return ret;
+	}
+
+	void inc() {
+		for(size_t i=0; i<rvec.size(); i++) {
+			rvec[i].inc();
+		}
+	}
+
+	value_type deref() const {
+		value_type ret(rvec.size());
+		for(size_t i=0; i<rvec.size(); i++) {
+			ret[i] = rvec[i].deref();
+		}
+		return ret;
+	}
+
+	subiter_type deref_subiter() const {
+		std::vector<typename RT::subiter_type> subvec(rvec.size());
+		for(size_t i=0; i<rvec.size(); i++) {
+			subvec[i] = rvec[i].deref_subiter();
+		}
+		return subiter_type(subvec);
+	}
+
+private:
+	std::vector<RT> rvec;
+};
+
+template <typename T>
+VecOfRange<typename ArrayTraits<T>::range_type::subiter_type>
+get_columns_range(const T &arg) {
+	typedef typename ArrayTraits<T>::range_type::subiter_type U;
+	std::vector<U> rvec;
+	typename ArrayTraits<T>::range_type outer = ArrayTraits<T>::get_range(arg);
+	while(!outer.is_end()) {
+		rvec.push_back(outer.deref_subiter());
+		outer.inc();
+	}
+	VecOfRange<U> ret(rvec);
+	return ret;
+}
+
+// }}}2
+
+// }}}1
+
+// {{{1 Array printing functions
+//
+// This section coordinates the sending of data to gnuplot.  The ArrayTraits mechanism tells us
+// about nested containers and provides iterators over them.  Here we make use of this,
+// deciding what dimensions should be treated as rows, columns, or blocks, telling gnuplot the
+// size of the array if needed, and so on.
+
+// If this is set, then text-mode data will be sent in a format that is not compatible with
+// gnuplot, but which helps the programmer tell what the library is thinking.  Basically it
+// puts brackets around groups of items and puts a message delineating blocks of data.
+static bool debug_array_print = 0;
+void set_debug_array_print(bool v) { debug_array_print = v; }
+
+// {{{2 Tags (like enums for metaprogramming)
+
+// These tags define what our goal is, what sort of thing should ultimately be sent to the
+// ostream.  These tags are passed to the PrintMode template argument of the functions in this
+// section.
+//
+// ModeText   - Sends the data in an array in text format
+// ModeBinary - Sends the data in an array in binary format
+// ModeBinfmt - Sends the gnuplot format code for binary data (e.g. "%double%double")
+// ModeSize   - Sends the size of an array.  Needed when sending binary data.
+struct ModeText   { static const bool is_text = 1; static const bool is_binfmt = 0; static const bool is_size = 0; };
+struct ModeBinary { static const bool is_text = 0; static const bool is_binfmt = 0; static const bool is_size = 0; };
+struct ModeBinfmt { static const bool is_text = 0; static const bool is_binfmt = 1; static const bool is_size = 0; };
+struct ModeSize   { static const bool is_text = 0; static const bool is_binfmt = 0; static const bool is_size = 1; };
+
+// Whether to treat the outermost level of a nested container as columns (column major mode).
+struct ColUnwrapNo  { };
+struct ColUnwrapYes { };
+
+// The user must give a hint to describe how nested containers are to be interpreted.  This is
+// done by calling e.g. `send1d_colmajor()` or `send2d()`.  This hint is then described by the
+// following tags.  This is passed to the OrganizationMode template argument.
+struct Mode1D       { static std::string class_name() { return "Mode1D"      ; } };
+struct Mode2D       { static std::string class_name() { return "Mode2D"      ; } };
+struct Mode1DUnwrap { static std::string class_name() { return "Mode1DUnwrap"; } };
+struct Mode2DUnwrap { static std::string class_name() { return "Mode2DUnwrap"; } };
+// Support for the legacy behavior that guesses which of the above four modes should be used.
+struct ModeAuto     { static std::string class_name() { return "ModeAuto"    ; } };
+
+// }}}2
+
+// {{{2 ModeAutoDecoder
+//
+// ModeAuto guesses which of Mode1D, Mode2D, Mode1DUnwrap, or Mode2DUnwrap should be used.
+// This is provided for reverse compatibility; it is better to specify explicitly which mode to
+// use.  Since this is only for reverse compatibility, and shouldn't be used, I'm not going to
+// spell out what the rules are.  See below for details.
+
+template <typename T, typename Enable=void>
+struct ModeAutoDecoder { };
+
+template <typename T>
+struct ModeAutoDecoder<T,
+	typename boost::enable_if_c<
+		(ArrayTraits<T>::depth == 1)
+	>::type>
+{
+	typedef Mode1D mode;
+};
+
+template <typename T>
+struct ModeAutoDecoder<T,
+	typename boost::enable_if_c<
+		(ArrayTraits<T>::depth == 2) &&
+		!ArrayTraits<T>::allow_auto_unwrap
+	>::type>
+{
+	typedef Mode2D mode;
+};
+
+template <typename T>
+struct ModeAutoDecoder<T,
+	typename boost::enable_if_c<
+		(ArrayTraits<T>::depth == 2) &&
+		ArrayTraits<T>::allow_auto_unwrap
+	>::type>
+{
+	typedef Mode1DUnwrap mode;
+};
+
+template <typename T>
+struct ModeAutoDecoder<T,
+	typename boost::enable_if_c<
+		(ArrayTraits<T>::depth > 2) &&
+		ArrayTraits<T>::allow_auto_unwrap
+	>::type>
+{
+	typedef Mode2DUnwrap mode;
+};
+
+template <typename T>
+struct ModeAutoDecoder<T,
+	typename boost::enable_if_c<
+		(ArrayTraits<T>::depth > 2) &&
+		!ArrayTraits<T>::allow_auto_unwrap
+	>::type>
+{
+	typedef Mode2D mode;
+};
+
+// }}}2
+
+// The data is processed using several levels of functions that call each other in sequence,
+// each defined in a subsection of code below.  Because C++ wants you to declare a function
+// before using it, we begin with the innermost function.  So in order to see the sequence in
+// which these are called, you should read the following subsections in reverse order.  Nested
+// arrays are formated into blocks (for 2D data) and lines (for 1D or 2D data), then further
+// nesting levels are formatted into columns.  Also tag dispatching is used in order to define
+// various sorts of behavior.  Each of these tasks is handled by one of the following
+// subsections.
+
+// {{{2 send_scalar()
+//
+// Send a scalar in one of three possible ways: via TextSender, BinarySender, or BinfmtSender,
+// depending on which PrintMode tag is passed to the function.
+
+template <typename T>
+void send_scalar(std::ostream &stream, const T &arg, ModeText) {
+	TextSender<T>::send(stream, arg);
+}
+
+template <typename T>
+void send_scalar(std::ostream &stream, const T &arg, ModeBinary) {
+	BinarySender<T>::send(stream, arg);
+}
+
+template <typename T>
+void send_scalar(std::ostream &stream, const T &, ModeBinfmt) {
+	BinfmtSender<T>::send(stream);
+}
+
+// }}}2
+
+// {{{2 deref_and_print()
+//
+// Dereferences and prints the given range (iterator).  At this point we are done with treating
+// containers as blocks (for 2D data) and lines (for 1D or 2D data).  Any further levels of
+// nested containers will at this point be treated as columns.
+
+// If arg is not a container, then print it via send_scalar().
+template <typename T, typename PrintMode>
+typename boost::disable_if_c<T::is_container>::type
+deref_and_print(std::ostream &stream, const T &arg, PrintMode) {
+	const typename T::value_type &v = arg.deref();
+	send_scalar(stream, v, PrintMode());
+}
+
+// If arg is a container (but not a PairOfRange or VecOfRange, which are handled below) then
+// treat the contents as columns, iterating over the contents recursively.  If outputting in
+// text mode, put a space between columns.
+template <typename T, typename PrintMode>
+typename boost::enable_if_c<T::is_container>::type
+deref_and_print(std::ostream &stream, const T &arg, PrintMode) {
+	if(debug_array_print && PrintMode::is_text) stream << "{";
+	typename T::subiter_type subrange = arg.deref_subiter();
+	bool first = true;
+	while(!subrange.is_end()) {
+		if(!first && PrintMode::is_text) stream << " ";
+		first = false;
+		deref_and_print(stream, subrange, PrintMode());
+		subrange.inc();
+	}
+	if(debug_array_print && PrintMode::is_text) stream << "}";
+}
+
+// PairOfRange is treated as columns.  In text mode, put a space between columns.
+template <typename T, typename U, typename PrintMode>
+void deref_and_print(std::ostream &stream, const PairOfRange<T, U> &arg, PrintMode) {
+	deref_and_print(stream, arg.l, PrintMode());
+	if(PrintMode::is_text) stream << " ";
+	deref_and_print(stream, arg.r, PrintMode());
+}
+
+// VecOfRange is treated as columns.  In text mode, put a space between columns.
+template <typename T, typename PrintMode>
+void deref_and_print(std::ostream &stream, const VecOfRange<T> &arg, PrintMode) {
+	for(size_t i=0; i<arg.rvec.size(); i++) {
+		if(i && PrintMode::is_text) stream << " ";
+		deref_and_print(stream, arg.rvec[i], PrintMode());
+	}
+}
+
+// }}}2
+
+// {{{2 print_block()
+//
+// Here we format nested containers into blocks (for 2D data) and lines.  Actually, block and
+// line formatting is only truely needed for text mode output, but for uniformity this function
+// is also invoked in binary mode (the PrintMode tag determines the output mode).  If the goal
+// is to just print the array size or the binary format string, then the loops exit after the
+// first iteration.
+//
+// The Depth argument tells how deep to recurse.  It will be either `2` for 2D data, formatted
+// into blocks and lines, with empty lines between blocks, or `1` for 1D data formatted into
+// lines but not blocks.  Gnuplot only supports 1D and 2D data, but if it were to support 3D in
+// the future (e.g. volume rendering), all that would be needed would be some trivial changes
+// in this section.  After Depth number of nested containers have been recursed into, control
+// is passed to deref_and_print(), which treats any further nested containers as columns.
+
+// Depth==1 and we are not asked to print the size of the array.  Send each element of the
+// range to deref_and_print() for further processing into columns.
+template <size_t Depth, typename T, typename PrintMode>
+typename boost::enable_if_c<(Depth==1) && !PrintMode::is_size>::type
+print_block(std::ostream &stream, T &arg, PrintMode) {
+	for(; !arg.is_end(); arg.inc()) {
+		//print_entry(arg.deref());
+		deref_and_print(stream, arg, PrintMode());
+		// If asked to print the binary format string, only the first element needs to be
+		// looked at.
+		if(PrintMode::is_binfmt) break;
+		if(PrintMode::is_text) stream << std::endl;
+	}
+}
+
+// Depth>1 and we are not asked to print the size of the array.  Loop over the range and
+// recurse into print_block() with Depth -> Depth-1.
+template <size_t Depth, typename T, typename PrintMode>
+typename boost::enable_if_c<(Depth>1) && !PrintMode::is_size>::type
+print_block(std::ostream &stream, T &arg, PrintMode) {
+	bool first = true;
+	for(; !arg.is_end(); arg.inc()) {
+		if(first) {
+			first = false;
+		} else {
+			if(PrintMode::is_text) stream << std::endl;
+		}
+		if(debug_array_print && PrintMode::is_text) stream << "<block>" << std::endl;
+		typename T::subiter_type sub = arg.deref_subiter();
+		print_block<Depth-1>(stream, sub, PrintMode());
+		// If asked to print the binary format string, only the first element needs to be
+		// looked at.
+		if(PrintMode::is_binfmt) break;
+	}
+}
+
+// Determine how many elements are in the given range.  Used in the functions below.
+template <typename T>
+size_t get_range_size(const T &arg) {
+	// FIXME - not the fastest way.  Implement a size() method for range.
+	size_t ret = 0;
+	for(T i=arg; !i.is_end(); i.inc()) ++ret;
+	return ret;
+}
+
+// Depth==1 and we are asked to print the size of the array.
+template <size_t Depth, typename T, typename PrintMode>
+typename boost::enable_if_c<(Depth==1) && PrintMode::is_size>::type
+print_block(std::ostream &stream, T &arg, PrintMode) {
+	stream << get_range_size(arg);
+}
+
+// Depth>1 and we are asked to print the size of the array.
+template <size_t Depth, typename T, typename PrintMode>
+typename boost::enable_if_c<(Depth>1) && PrintMode::is_size>::type
+print_block(std::ostream &stream, T &arg, PrintMode) {
+	// It seems that size for two dimensional arrays needs the fastest varying index first,
+	// contrary to intuition.  The gnuplot documentation is not too clear on this point.
+	typename T::subiter_type sub = arg.deref_subiter();
+	print_block<Depth-1>(stream, sub, PrintMode());
+	stream << "," << get_range_size(arg);
+}
+
+// }}}2
+
+// {{{2 handle_colunwrap_tag()
+//
+// If passed the ColUnwrapYes then treat the outermost nested container as columns by calling
+// get_columns_range().  Otherwise just call get_range().  The range iterator is then passed to
+// print_block() for further processing.
+
+template <size_t Depth, typename T, typename PrintMode>
+void handle_colunwrap_tag(std::ostream &stream, const T &arg, ColUnwrapNo, PrintMode) {
+	GNUPLOT_STATIC_ASSERT_MSG(ArrayTraits<T>::depth >= Depth, "container not deep enough");
+	typename ArrayTraits<T>::range_type range = ArrayTraits<T>::get_range(arg);
+	print_block<Depth>(stream, range, PrintMode());
+}
+
+template <size_t Depth, typename T, typename PrintMode>
+void handle_colunwrap_tag(std::ostream &stream, const T &arg, ColUnwrapYes, PrintMode) {
+	GNUPLOT_STATIC_ASSERT_MSG(ArrayTraits<T>::depth >= Depth+1, "container not deep enough");
+	VecOfRange<typename ArrayTraits<T>::range_type::subiter_type> cols = get_columns_range(arg);
+	print_block<Depth>(stream, cols, PrintMode());
+}
+
+// }}}2
+
+// {{{2 handle_organization_tag()
+//
+// Parse the OrganizationMode tag then forward to handle_colunwrap_tag() for further
+// processing.  If passed the Mode1D or Mode2D tags, then set Depth=1 or Depth=2.  If passed
+// Mode{1,2}DUnwrap then use the ColUnwrapYes tag.  If passed ModeAuto (which is for legacy
+// support) then use ModeAutoDecoder to guess which of Mode1D, Mode2D, etc. should be used.
+
+template <typename T, typename PrintMode>
+void handle_organization_tag(std::ostream &stream, const T &arg, Mode1D, PrintMode) {
+	handle_colunwrap_tag<1>(stream, arg, ColUnwrapNo(), PrintMode());
+}
+
+template <typename T, typename PrintMode>
+void handle_organization_tag(std::ostream &stream, const T &arg, Mode2D, PrintMode) {
+	handle_colunwrap_tag<2>(stream, arg, ColUnwrapNo(), PrintMode());
+}
+
+template <typename T, typename PrintMode>
+void handle_organization_tag(std::ostream &stream, const T &arg, Mode1DUnwrap, PrintMode) {
+	handle_colunwrap_tag<1>(stream, arg, ColUnwrapYes(), PrintMode());
+}
+
+template <typename T, typename PrintMode>
+void handle_organization_tag(std::ostream &stream, const T &arg, Mode2DUnwrap, PrintMode) {
+	handle_colunwrap_tag<2>(stream, arg, ColUnwrapYes(), PrintMode());
+}
+
+template <typename T, typename PrintMode>
+void handle_organization_tag(std::ostream &stream, const T &arg, ModeAuto, PrintMode) {
+	handle_organization_tag(stream, arg, typename ModeAutoDecoder<T>::mode(), PrintMode());
+}
+
+// }}}2
+
+// The entry point for the processing defined in this section.  It just forwards immediately to
+// handle_organization_tag().  This function is only here to give a sane name to the entry
+// point.
+//
+// The allowed values for the OrganizationMode and PrintMode tags are defined in the beginning
+// of this section.
+template <typename T, typename OrganizationMode, typename PrintMode>
+void top_level_array_sender(std::ostream &stream, const T &arg, OrganizationMode, PrintMode) {
+	handle_organization_tag(stream, arg, OrganizationMode(), PrintMode());
+}
+
+// }}}1
+
+// {{{1 FileHandleWrapper
+
+// This holds the file handle that gnuplot commands will be sent to.  The purpose of this
+// wrapper is twofold:
+// 1. It allows storing the FILE* before it gets passed to the boost::iostreams::stream
+//    constructor (which is a base class of the main Gnuplot class).  This is accomplished
+//    via multiple inheritance as described at http://stackoverflow.com/a/3821756/1048959
+// 2. It remembers whether the handle needs to be closed via fclose or pclose.
+struct FileHandleWrapper {
+	FileHandleWrapper(std::FILE *_fh, bool _should_use_pclose) :
+		wrapped_fh(_fh), should_use_pclose(_should_use_pclose) { }
+
+	void fh_close() {
+		if(should_use_pclose) {
+			if(GNUPLOT_PCLOSE(wrapped_fh)) {
+				std::cerr << "pclose returned error" << std::endl;
+			}
+		} else {
+			if(fclose(wrapped_fh)) {
+				std::cerr << "fclose returned error" << std::endl;
+			}
+		}
+	}
+
+	int fh_fileno() {
+		return GNUPLOT_FILENO(wrapped_fh);
+	}
+
+	std::FILE *wrapped_fh;
+	bool should_use_pclose;
+};
+
+// }}}1
+
+// {{{1 Main class
+
+class Gnuplot :
+	// Some setup needs to be done before obtaining the file descriptor that gets passed to
+	// boost::iostreams::stream.  This is accomplished by using a multiple inheritance trick,
+	// as described at http://stackoverflow.com/a/3821756/1048959
+	private FileHandleWrapper,
+	public boost::iostreams::stream<boost::iostreams::file_descriptor_sink>
+{
+private:
+	static std::string get_default_cmd() {
+		GNUPLOT_MSVC_WARNING_4996_PUSH
+		char *from_env = std::getenv("GNUPLOT_IOSTREAM_CMD");
+		GNUPLOT_MSVC_WARNING_4996_POP
+		if(from_env && from_env[0]) {
+			return from_env;
+		} else {
+			return GNUPLOT_DEFAULT_COMMAND;
+		}
+	}
+
+	static FileHandleWrapper open_cmdline(const std::string &in) {
+		std::string cmd = in.empty() ? get_default_cmd() : in;
+		assert(!cmd.empty());
+		if(cmd[0] == '>') {
+			std::string fn = cmd.substr(1);
+			GNUPLOT_MSVC_WARNING_4996_PUSH
+			FILE *fh = std::fopen(fn.c_str(), "w");
+			GNUPLOT_MSVC_WARNING_4996_POP
+			if(!fh) throw(std::ios_base::failure("cannot open file "+fn));
+			return FileHandleWrapper(fh, false);
+		} else {
+			FILE *fh = GNUPLOT_POPEN(cmd.c_str(), "w");
+			if(!fh) throw(std::ios_base::failure("cannot open pipe "+cmd));
+			return FileHandleWrapper(fh, true);
+		}
+	}
+
+public:
+	explicit Gnuplot(const std::string &_cmd="") :
+		FileHandleWrapper(open_cmdline(_cmd)),
+		boost::iostreams::stream<boost::iostreams::file_descriptor_sink>(
+			fh_fileno(),
+#if BOOST_VERSION >= 104400
+			boost::iostreams::never_close_handle
+#else
+			false
+#endif
+		),
+		feedback(NULL),
+		tmp_files(),
+		debug_messages(false)
+	{
+		*this << std::scientific << std::setprecision(18);  // refer <iomanip>
+	}
+
+	explicit Gnuplot(FILE *_fh) :
+		FileHandleWrapper(_fh, 0),
+		boost::iostreams::stream<boost::iostreams::file_descriptor_sink>(
+			fh_fileno(),
+#if BOOST_VERSION >= 104400
+			boost::iostreams::never_close_handle
+#else
+			false
+#endif
+		),
+		feedback(NULL),
+		tmp_files(),
+		debug_messages(false)
+	{
+		*this << std::scientific << std::setprecision(18);  // refer <iomanip>
+	}
+
+private:
+	// noncopyable
+	Gnuplot(const Gnuplot &);
+	const Gnuplot& operator=(const Gnuplot &);
+
+public:
+	~Gnuplot() {
+		if(debug_messages) {
+			std::cerr << "ending gnuplot session" << std::endl;
+		}
+
+		// FIXME - boost's close method calls close() on the file descriptor, but we need to
+		// use sometimes use pclose instead.  For now, just skip calling boost's close and use
+		// flush just in case.
+		do_flush();
+		// Wish boost had a pclose method...
+		//close();
+
+		fh_close();
+
+		delete feedback;
+	}
+
+	void clearTmpfiles() {
+		// destructors will cause deletion
+		tmp_files.clear();
+	}
+
+private:
+	void do_flush() {
+		*this << std::flush;
+		fflush(wrapped_fh);
+	}
+
+	std::string make_tmpfile() {
+#ifdef GNUPLOT_USE_TMPFILE
+		boost::shared_ptr<GnuplotTmpfile> tmp_file(new GnuplotTmpfile());
+		// The file will be removed once the pointer is removed from the
+		// tmp_files container.
+		tmp_files.push_back(tmp_file);
+		return tmp_file->file.string();
+#else
+		throw(std::logic_error("no filename given and temporary files not enabled"));
+#endif // GNUPLOT_USE_TMPFILE
+	}
+
+public:
+// {{{2 Generic sender routines.
+//
+// These are declared public, but are undocumented.  It is recommended to use the functions in
+// the next section, which serve as adapters that pass specific values for the OrganizationMode
+// tag.
+
+	template <typename T, typename OrganizationMode>
+	Gnuplot &send(const T &arg, OrganizationMode) {
+		top_level_array_sender(*this, arg, OrganizationMode(), ModeText());
+		*this << "e" << std::endl; // gnuplot's "end of array" token
+		do_flush(); // probably not really needed, but doesn't hurt
+		return *this;
+	}
+
+	template <typename T, typename OrganizationMode>
+	Gnuplot &sendBinary(const T &arg, OrganizationMode) {
+		top_level_array_sender(*this, arg, OrganizationMode(), ModeBinary());
+		do_flush(); // probably not really needed, but doesn't hurt
+		return *this;
+	}
+
+	template <typename T, typename OrganizationMode>
+	std::string binfmt(const T &arg, const std::string &arr_or_rec, OrganizationMode) {
+		std::ostringstream tmp;
+		tmp << " format='";
+		top_level_array_sender(tmp, arg, OrganizationMode(), ModeBinfmt());
+		assert((arr_or_rec == "array") || (arr_or_rec == "record"));
+		tmp << "' " << arr_or_rec << "=(";
+		top_level_array_sender(tmp, arg, OrganizationMode(), ModeSize());
+		tmp << ")";
+		tmp << " ";
+		return tmp.str();
+	}
+
+	// NOTE: empty filename makes temporary file
+	template <typename T, typename OrganizationMode>
+	std::string file(const T &arg, std::string filename, OrganizationMode) {
+		if(filename.empty()) filename = make_tmpfile();
+		std::fstream tmp_stream(filename.c_str(), std::fstream::out);
+		top_level_array_sender(tmp_stream, arg, OrganizationMode(), ModeText());
+		tmp_stream.close();
+
+		std::ostringstream cmdline;
+		// FIXME - hopefully filename doesn't contain quotes or such...
+		cmdline << " '" << filename << "' ";
+		return cmdline.str();
+	}
+
+	// NOTE: empty filename makes temporary file
+	template <typename T, typename OrganizationMode>
+	std::string binaryFile(const T &arg, std::string filename, const std::string &arr_or_rec, OrganizationMode) {
+		if(filename.empty()) filename = make_tmpfile();
+		std::fstream tmp_stream(filename.c_str(), std::fstream::out | std::fstream::binary);
+		top_level_array_sender(tmp_stream, arg, OrganizationMode(), ModeBinary());
+		tmp_stream.close();
+
+		std::ostringstream cmdline;
+		// FIXME - hopefully filename doesn't contain quotes or such...
+		cmdline << " '" << filename << "' binary" << binfmt(arg, arr_or_rec, OrganizationMode());
+		return cmdline.str();
+	}
+
+// }}}2
+
+// {{{2 Deprecated data sending interface that guesses an appropriate OrganizationMode.  This is here
+// for reverse compatibility.  Don't use it.  A warning will be printed if
+// GNUPLOT_DEPRECATE_WARN is defined.
+
+	template <typename T> Gnuplot GNUPLOT_DEPRECATE("use send1d or send2d")
+		&send(const T &arg) { return send(arg, ModeAuto()); }
+
+	template <typename T> std::string GNUPLOT_DEPRECATE("use binfmt1d or binfmt2d")
+		binfmt(const T &arg, const std::string &arr_or_rec="array")
+		{ return binfmt(arg, arr_or_rec,  ModeAuto()); }
+
+	template <typename T> Gnuplot GNUPLOT_DEPRECATE("use sendBinary1d or sendBinary2d")
+		&sendBinary(const T &arg) { return sendBinary(arg, ModeAuto()); }
+
+	template <typename T> std::string GNUPLOT_DEPRECATE("use file1d or file2d")
+		file(const T &arg, const std::string &filename="")
+		{ return file(arg, filename, ModeAuto()); }
+
+	template <typename T> std::string GNUPLOT_DEPRECATE("use binArr1d or binArr2d")
+		binaryFile(const T &arg, const std::string &filename="", const std::string &arr_or_rec="array")
+		{ return binaryFile(arg, filename, arr_or_rec,  ModeAuto()); }
+
+// }}}2
+
+// {{{2 Public (documented) data sending interface.
+//
+// It seems odd to define 16 different functions, but I think this ends up being the most
+// convenient in terms of usage by the end user.
+
+	template <typename T> Gnuplot &send1d         (const T &arg) { return send(arg, Mode1D      ()); }
+	template <typename T> Gnuplot &send2d         (const T &arg) { return send(arg, Mode2D      ()); }
+	template <typename T> Gnuplot &send1d_colmajor(const T &arg) { return send(arg, Mode1DUnwrap()); }
+	template <typename T> Gnuplot &send2d_colmajor(const T &arg) { return send(arg, Mode2DUnwrap()); }
+
+	template <typename T> Gnuplot &sendBinary1d         (const T &arg) { return sendBinary(arg, Mode1D      ()); }
+	template <typename T> Gnuplot &sendBinary2d         (const T &arg) { return sendBinary(arg, Mode2D      ()); }
+	template <typename T> Gnuplot &sendBinary1d_colmajor(const T &arg) { return sendBinary(arg, Mode1DUnwrap()); }
+	template <typename T> Gnuplot &sendBinary2d_colmajor(const T &arg) { return sendBinary(arg, Mode2DUnwrap()); }
+
+	template <typename T> std::string file1d         (const T &arg, const std::string &filename="") { return file(arg, filename, Mode1D      ()); }
+	template <typename T> std::string file2d         (const T &arg, const std::string &filename="") { return file(arg, filename, Mode2D      ()); }
+	template <typename T> std::string file1d_colmajor(const T &arg, const std::string &filename="") { return file(arg, filename, Mode1DUnwrap()); }
+	template <typename T> std::string file2d_colmajor(const T &arg, const std::string &filename="") { return file(arg, filename, Mode2DUnwrap()); }
+
+	template <typename T> std::string binFmt1d         (const T &arg, const std::string &arr_or_rec) { return binfmt(arg, arr_or_rec,  Mode1D      ()); }
+	template <typename T> std::string binFmt2d         (const T &arg, const std::string &arr_or_rec) { return binfmt(arg, arr_or_rec,  Mode2D      ()); }
+	template <typename T> std::string binFmt1d_colmajor(const T &arg, const std::string &arr_or_rec) { return binfmt(arg, arr_or_rec,  Mode1DUnwrap()); }
+	template <typename T> std::string binFmt2d_colmajor(const T &arg, const std::string &arr_or_rec) { return binfmt(arg, arr_or_rec,  Mode2DUnwrap()); }
+
+	template <typename T> std::string binFile1d         (const T &arg, const std::string &arr_or_rec, const std::string &filename="") { return binaryFile(arg, filename, arr_or_rec,  Mode1D      ()); }
+	template <typename T> std::string binFile2d         (const T &arg, const std::string &arr_or_rec, const std::string &filename="") { return binaryFile(arg, filename, arr_or_rec,  Mode2D      ()); }
+	template <typename T> std::string binFile1d_colmajor(const T &arg, const std::string &arr_or_rec, const std::string &filename="") { return binaryFile(arg, filename, arr_or_rec,  Mode1DUnwrap()); }
+	template <typename T> std::string binFile2d_colmajor(const T &arg, const std::string &arr_or_rec, const std::string &filename="") { return binaryFile(arg, filename, arr_or_rec,  Mode2DUnwrap()); }
+
+// }}}2
+
+#ifdef GNUPLOT_ENABLE_FEEDBACK
+public:
+	// Input variables are set to the mouse position and button.  If the gnuplot
+	// window is closed, button -1 is returned.  The msg parameter is the prompt
+	// that is printed to the console.
+	void getMouse(
+		double &mx, double &my, int &mb,
+		std::string msg="Click Mouse!"
+	) {
+		allocFeedback();
+
+		*this << "set mouse" << std::endl;
+		*this << "pause mouse \"" << msg << "\\n\"" << std::endl;
+		*this << "if (exists(\"MOUSE_X\")) print MOUSE_X, MOUSE_Y, MOUSE_BUTTON; else print 0, 0, -1;" << std::endl;
+		if(debug_messages) {
+			std::cerr << "begin scanf" << std::endl;
+		}
+		if(3 != fscanf(feedback->handle(), "%50lf %50lf %50d", &mx, &my, &mb)) {
+			throw std::runtime_error("could not parse reply");
+		}
+		if(debug_messages) {
+			std::cerr << "end scanf" << std::endl;
+		}
+	}
+
+private:
+	void allocFeedback() {
+		if(!feedback) {
+#ifdef GNUPLOT_ENABLE_PTY
+			feedback = new GnuplotFeedbackPty(debug_messages);
+//#elif defined GNUPLOT_USE_TMPFILE
+//// Currently this doesn't work since fscanf doesn't block (need something like "tail -f")
+//			feedback = new GnuplotFeedbackTmpfile(debug_messages);
+#else
+			// This shouldn't happen because we are in an `#ifdef GNUPLOT_ENABLE_FEEDBACK`
+			// block which should only be activated if GNUPLOT_ENABLE_PTY is defined.
+			GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "No feedback mechanism defined.");
+#endif
+			*this << "set print \"" << feedback->filename() << "\"" << std::endl;
+		}
+	}
+#endif // GNUPLOT_ENABLE_FEEDBACK
+
+private:
+	GnuplotFeedback *feedback;
+#ifdef GNUPLOT_USE_TMPFILE
+	std::vector<boost::shared_ptr<GnuplotTmpfile> > tmp_files;
+#else
+	// just a placeholder
+	std::vector<int> tmp_files;
+#endif // GNUPLOT_USE_TMPFILE
+
+public:
+	bool debug_messages;
+};
+
+// }}}1
+
+} // namespace gnuplotio
+
+// The first version of this library didn't use namespaces, and now this must be here forever
+// for reverse compatibility.
+using gnuplotio::Gnuplot;
+
+#endif // GNUPLOT_IOSTREAM_H
+
+// {{{1 Support for 3rd party array libraries
+
+// {{{2 Blitz support
+
+// This is outside of the main header guard so that it will be compiled when people do
+// something like this:
+//    #include "gnuplot-iostream.h"
+//    #include <blitz/array.h>
+//    #include "gnuplot-iostream.h"
+// Note that it has its own header guard to avoid double inclusion.
+
+#ifdef BZ_BLITZ_H
+#ifndef GNUPLOT_BLITZ_SUPPORT_LOADED
+#define GNUPLOT_BLITZ_SUPPORT_LOADED
+namespace gnuplotio {
+
+template <typename T, int N>
+struct BinfmtSender<blitz::TinyVector<T, N> > {
+	static void send(std::ostream &stream) {
+		for(int i=0; i<N; i++) {
+			BinfmtSender<T>::send(stream);
+		}
+	}
+};
+
+template <typename T, int N>
+struct TextSender<blitz::TinyVector<T, N> > {
+	static void send(std::ostream &stream, const blitz::TinyVector<T, N> &v) {
+		for(int i=0; i<N; i++) {
+			if(i) stream << " ";
+			TextSender<T>::send(stream, v[i]);
+		}
+	}
+};
+
+template <typename T, int N>
+struct BinarySender<blitz::TinyVector<T, N> > {
+	static void send(std::ostream &stream, const blitz::TinyVector<T, N> &v) {
+		for(int i=0; i<N; i++) {
+			BinarySender<T>::send(stream, v[i]);
+		}
+	}
+};
+
+class Error_WasBlitzPartialSlice { };
+
+template <typename T, int ArrayDim, int SliceDim>
+class BlitzIterator {
+public:
+	BlitzIterator() : p(NULL) { }
+	BlitzIterator(
+		const blitz::Array<T, ArrayDim> *_p,
+		const blitz::TinyVector<int, ArrayDim> _idx
+	) : p(_p), idx(_idx) { }
+
+	typedef Error_WasBlitzPartialSlice value_type;
+	typedef BlitzIterator<T, ArrayDim, SliceDim-1> subiter_type;
+	static const bool is_container = true;
+
+	// FIXME - it would be nice to also handle one-based arrays
+	bool is_end() const {
+		return idx[ArrayDim-SliceDim] == p->shape()[ArrayDim-SliceDim];
+	}
+
+	void inc() {
+		++idx[ArrayDim-SliceDim];
+	}
+
+	value_type deref() const {
+		GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "cannot deref a blitz slice");
+		throw std::logic_error("static assert should have been triggered by this point");
+	}
+
+	subiter_type deref_subiter() const {
+		return BlitzIterator<T, ArrayDim, SliceDim-1>(p, idx);
+	}
+
+private:
+	const blitz::Array<T, ArrayDim> *p;
+	blitz::TinyVector<int, ArrayDim> idx;
+};
+
+template <typename T, int ArrayDim>
+class BlitzIterator<T, ArrayDim, 1> {
+public:
+	BlitzIterator() : p(NULL) { }
+	BlitzIterator(
+		const blitz::Array<T, ArrayDim> *_p,
+		const blitz::TinyVector<int, ArrayDim> _idx
+	) : p(_p), idx(_idx) { }
+
+	typedef T value_type;
+	typedef Error_WasNotContainer subiter_type;
+	static const bool is_container = false;
+
+	// FIXME - it would be nice to also handle one-based arrays
+	bool is_end() const {
+		return idx[ArrayDim-1] == p->shape()[ArrayDim-1];
+	}
+
+	void inc() {
+		++idx[ArrayDim-1];
+	}
+
+	value_type deref() const {
+		return (*p)(idx);
+	}
+
+	subiter_type deref_subiter() const {
+		GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "argument was not a container");
+		throw std::logic_error("static assert should have been triggered by this point");
+	}
+
+private:
+	const blitz::Array<T, ArrayDim> *p;
+	blitz::TinyVector<int, ArrayDim> idx;
+};
+
+template <typename T, int ArrayDim>
+class ArrayTraits<blitz::Array<T, ArrayDim> > : public ArrayTraitsDefaults<T> {
+public:
+	static const bool allow_auto_unwrap = false;
+	static const size_t depth = ArrayTraits<T>::depth + ArrayDim;
+
+	typedef BlitzIterator<T, ArrayDim, ArrayDim> range_type;
+
+	static range_type get_range(const blitz::Array<T, ArrayDim> &arg) {
+		blitz::TinyVector<int, ArrayDim> start_idx;
+		start_idx = 0;
+		return range_type(&arg, start_idx);
+	}
+};
+
+} // namespace gnuplotio
+#endif // GNUPLOT_BLITZ_SUPPORT_LOADED
+#endif // BZ_BLITZ_H
+
+// }}}2
+
+// {{{2 Armadillo support
+
+// This is outside of the main header guard so that it will be compiled when people do
+// something like this:
+//    #include "gnuplot-iostream.h"
+//    #include <armadillo>
+//    #include "gnuplot-iostream.h"
+// Note that it has its own header guard to avoid double inclusion.
+
+#ifdef ARMA_INCLUDES
+#ifndef GNUPLOT_ARMADILLO_SUPPORT_LOADED
+#define GNUPLOT_ARMADILLO_SUPPORT_LOADED
+namespace gnuplotio {
+
+template <typename T> struct dont_treat_as_stl_container<arma::Row  <T> > { typedef boost::mpl::bool_<true> type; };
+template <typename T> struct dont_treat_as_stl_container<arma::Col  <T> > { typedef boost::mpl::bool_<true> type; };
+template <typename T> struct dont_treat_as_stl_container<arma::Mat  <T> > { typedef boost::mpl::bool_<true> type; };
+template <typename T> struct dont_treat_as_stl_container<arma::Cube <T> > { typedef boost::mpl::bool_<true> type; };
+template <typename T> struct dont_treat_as_stl_container<arma::field<T> > { typedef boost::mpl::bool_<true> type; };
+
+// {{{3 Cube
+
+template <typename T>
+class ArrayTraits<arma::Cube<T> > : public ArrayTraitsDefaults<T> {
+	class SliceRange {
+	public:
+		SliceRange() : p(NULL), col(0), slice(0) { }
+		explicit SliceRange(const arma::Cube<T> *_p, size_t _row, size_t _col) :
+			p(_p), row(_row), col(_col), slice(0) { }
+
+		typedef T value_type;
+		typedef Error_WasNotContainer subiter_type;
+		static const bool is_container = false;
+
+		bool is_end() const { return slice == p->n_slices; }
+
+		void inc() { ++slice; }
+
+		value_type deref() const {
+			return (*p)(row, col, slice);
+		}
+
+		subiter_type deref_subiter() const {
+			GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "argument was not a container");
+			throw std::logic_error("static assert should have been triggered by this point");
+		}
+
+	private:
+		const arma::Cube<T> *p;
+		size_t row, col, slice;
+	};
+
+	class ColRange {
+	public:
+		ColRange() : p(NULL), row(0), col(0) { }
+		explicit ColRange(const arma::Cube<T> *_p, size_t _row) :
+			p(_p), row(_row), col(0) { }
+
+		typedef T value_type;
+		typedef SliceRange subiter_type;
+		static const bool is_container = true;
+
+		bool is_end() const { return col == p->n_cols; }
+
+		void inc() { ++col; }
+
+		value_type deref() const {
+			GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "can't call deref on an armadillo cube col");
+			throw std::logic_error("static assert should have been triggered by this point");
+		}
+
+		subiter_type deref_subiter() const {
+			return subiter_type(p, row, col);
+		}
+
+	private:
+		const arma::Cube<T> *p;
+		size_t row, col;
+	};
+
+	class RowRange {
+	public:
+		RowRange() : p(NULL), row(0) { }
+		explicit RowRange(const arma::Cube<T> *_p) : p(_p), row(0) { }
+
+		typedef T value_type;
+		typedef ColRange subiter_type;
+		static const bool is_container = true;
+
+		bool is_end() const { return row == p->n_rows; }
+
+		void inc() { ++row; }
+
+		value_type deref() const {
+			GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "can't call deref on an armadillo cube row");
+			throw std::logic_error("static assert should have been triggered by this point");
+		}
+
+		subiter_type deref_subiter() const {
+			return subiter_type(p, row);
+		}
+
+	private:
+		const arma::Cube<T> *p;
+		size_t row;
+	};
+
+public:
+	static const bool allow_auto_unwrap = false;
+	static const size_t depth = ArrayTraits<T>::depth + 3;
+
+	typedef RowRange range_type;
+
+	static range_type get_range(const arma::Cube<T> &arg) {
+		//std::cout << arg.n_elem << "," << arg.n_rows << "," << arg.n_cols << std::endl;
+		return range_type(&arg);
+	}
+};
+
+// }}}3
+
+// {{{3 Mat and Field
+
+template <typename RF, typename T>
+class ArrayTraits_ArmaMatOrField : public ArrayTraitsDefaults<T> {
+	class ColRange {
+	public:
+		ColRange() : p(NULL), row(0), col(0) { }
+		explicit ColRange(const RF *_p, size_t _row) :
+			p(_p), row(_row), col(0) { }
+
+		typedef T value_type;
+		typedef Error_WasNotContainer subiter_type;
+		static const bool is_container = false;
+
+		bool is_end() const { return col == p->n_cols; }
+
+		void inc() { ++col; }
+
+		value_type deref() const {
+			return (*p)(row, col);
+		}
+
+		subiter_type deref_subiter() const {
+			GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "argument was not a container");
+			throw std::logic_error("static assert should have been triggered by this point");
+		}
+
+	private:
+		const RF *p;
+		size_t row, col;
+	};
+
+	class RowRange {
+	public:
+		RowRange() : p(NULL), row(0) { }
+		explicit RowRange(const RF *_p) : p(_p), row(0) { }
+
+		typedef T value_type;
+		typedef ColRange subiter_type;
+		static const bool is_container = true;
+
+		bool is_end() const { return row == p->n_rows; }
+
+		void inc() { ++row; }
+
+		value_type deref() const {
+			GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "can't call deref on an armadillo matrix row");
+			throw std::logic_error("static assert should have been triggered by this point");
+		}
+
+		subiter_type deref_subiter() const {
+			return subiter_type(p, row);
+		}
+
+	private:
+		const RF *p;
+		size_t row;
+	};
+
+public:
+	static const bool allow_auto_unwrap = false;
+	static const size_t depth = ArrayTraits<T>::depth + 2;
+
+	typedef RowRange range_type;
+
+	static range_type get_range(const RF &arg) {
+		//std::cout << arg.n_elem << "," << arg.n_rows << "," << arg.n_cols << std::endl;
+		return range_type(&arg);
+	}
+};
+
+template <typename T>
+class ArrayTraits<arma::field<T> > : public ArrayTraits_ArmaMatOrField<arma::field<T>, T> { };
+
+template <typename T>
+class ArrayTraits<arma::Mat<T> > : public ArrayTraits_ArmaMatOrField<arma::Mat<T>, T> { };
+
+// }}}3
+
+// {{{3 Row
+
+template <typename T>
+class ArrayTraits<arma::Row<T> > : public ArrayTraitsDefaults<T> {
+public:
+	static const bool allow_auto_unwrap = false;
+
+	typedef IteratorRange<typename arma::Row<T>::const_iterator, T> range_type;
+
+	static range_type get_range(const arma::Row<T> &arg) {
+		//std::cout << arg.n_elem << "," << arg.n_rows << "," << arg.n_cols << std::endl;
+		return range_type(arg.begin(), arg.end());
+	}
+};
+
+// }}}3
+
+// {{{3 Col
+
+template <typename T>
+class ArrayTraits<arma::Col<T> > : public ArrayTraitsDefaults<T> {
+public:
+	static const bool allow_auto_unwrap = false;
+
+	typedef IteratorRange<typename arma::Col<T>::const_iterator, T> range_type;
+
+	static range_type get_range(const arma::Col<T> &arg) {
+		//std::cout << arg.n_elem << "," << arg.n_rows << "," << arg.n_cols << std::endl;
+		return range_type(arg.begin(), arg.end());
+	}
+};
+
+// }}}3
+
+} // namespace gnuplotio
+#endif // GNUPLOT_ARMADILLO_SUPPORT_LOADED
+#endif // ARMA_INCLUDES
+
+// }}}2
+
+// }}}1
diff --git a/EXTERNAL/mcqd/COPYING b/EXTERNAL/mcqd/COPYING
new file mode 100644
index 0000000000000000000000000000000000000000..3d90694ade2af6f840b175a00477c8a15cfc6eeb
--- /dev/null
+++ b/EXTERNAL/mcqd/COPYING
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
\ No newline at end of file
diff --git a/EXTERNAL/mcqd/README b/EXTERNAL/mcqd/README
new file mode 100644
index 0000000000000000000000000000000000000000..981ffc09b633eb3726832c8307037855cb27b4d2
--- /dev/null
+++ b/EXTERNAL/mcqd/README
@@ -0,0 +1,5 @@
+Compile with: g++ -O3 mcqd.cpp -o mcqd
+Run with: mcqd test.clq
+mcqd.cpp ... example program that shows how to use class implemented in mcqd.h
+mcqd.h ... a class that contains two variants of the MCQD maximum clique algorithm
+test.clq ... an example clique in DIMACS format
diff --git a/EXTERNAL/mcqd/mcqd.cpp b/EXTERNAL/mcqd/mcqd.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..86bd9d99f9d189a8fdde263bd8c57505055fb1c7
--- /dev/null
+++ b/EXTERNAL/mcqd/mcqd.cpp
@@ -0,0 +1,107 @@
+/*
+    Copyright 2007-2012 Janez Konc 
+
+    If you use this program, please cite: 
+    Janez Konc and Dusanka Janezic. An improved branch and bound algorithm for the 
+    maximum clique problem. MATCH Commun. Math. Comput. Chem., 2007, 58, 569-590.
+
+    More information at: http://www.sicmm.org/~konc
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <fstream>
+#include <iostream>
+#include <set>
+#include <string.h>
+#include <map>
+#include <assert.h>
+#include <emotion/3rdparty/mcqd.h>
+
+using namespace std;
+        
+void read_dimacs(string name, bool** &conn, int &size) {
+  ifstream f (name.c_str());
+  string buffer;
+  assert(f.is_open());
+  set<int> v;
+  multimap<int,int> e;
+  while (!getline(f, buffer).eof()) {
+    if (buffer[0] == 'e') {
+      int vi, vj;
+      sscanf(buffer.c_str(), "%*c %d %d", &vi, &vj);
+      v.insert(vi);
+      v.insert(vj);
+      e.insert(make_pair(vi, vj));
+    }
+  }
+//  size = v.size() + 1;
+  size = *v.rbegin() + 1;
+  conn = new bool*[size];
+  for (int i=0; i < size; i++) {
+    conn[i] = new bool[size];
+    memset(conn[i], 0, size * sizeof(bool));
+  }
+  for (multimap<int,int>::iterator it = e.begin(); it != e.end(); it++) {
+    conn[it->first][it->second] = true;
+    conn[it->second][it->first] = true;
+  }
+  cout << "|E| = " << e.size() << "  |V| = " << v.size() << " p = " << (double) e.size() / (v.size() * (v.size() - 1) / 2) << endl;
+  f.close();
+}
+  
+
+int main(int argc, char *argv[]) {
+  assert(argc == 2);
+  cout << "args = " << argv[1] << endl;
+  bool **conn;
+  int size;
+  read_dimacs(argv[1], conn, size);
+  cout << "---------- Example 1: run max clique with improved coloring ----------------"<<endl;
+  clock_t start1 = time(NULL);
+  clock_t start2 = clock();
+  Maxclique m(conn, size);
+  int *qmax;
+  int qsize;
+  m.mcq(qmax, qsize);  // run max clique with improved coloring
+  cout << "Maximum clique: ";
+  for (int i = 0; i < qsize; i++) 
+    cout << qmax[i] << " ";
+  cout << endl;
+  cout << "Size = " << qsize << endl;
+  cout << "Number of steps = " << m.steps() << endl;
+  cout << "Time = " << difftime(time(NULL), start1) << endl;
+  cout << "Time (precise) = " << ((double) (clock() - start2)) / CLOCKS_PER_SEC << endl << endl;
+  delete [] qmax;
+  cout << "---------- Example 2: run max clique with improved coloring and dynamic sorting of vertices ----------------"<<endl;
+  start1 = time(NULL);
+  start2 = clock();
+  Maxclique md(conn, size, 0.025);  //(3rd parameter is optional - default is 0.025 - this heuristics parameter enables you to use dynamic resorting of vertices (time expensive)
+  // on the part of the search tree that is close to the root - in this case, approximately 2.5% of the search tree -
+  // you can probably find a more optimal value for your graphs
+  md.mcqdyn(qmax, qsize);  // run max clique with improved coloring and dynamic sorting of vertices 
+  cout << "Maximum clique: ";
+  for (int i = 0; i < qsize; i++) 
+    cout << qmax[i] << " ";
+  cout << endl;
+  cout << "Size = " << qsize << endl;
+  cout << "Number of steps = " << md.steps() << endl;
+  cout << "Time = " << difftime(time(NULL), start1) << endl;
+  cout << "Time (precise) = " << ((double) (clock() - start2)) / CLOCKS_PER_SEC << endl << endl;
+  delete [] qmax;
+  for (int i=0;i<size;i++)
+    delete [] conn[i];
+  delete [] conn;
+  return 0;
+}
diff --git a/EXTERNAL/mcqd/mcqd.h b/EXTERNAL/mcqd/mcqd.h
new file mode 100644
index 0000000000000000000000000000000000000000..ca1ebd8c58a609e9501a72926674bf5354250055
--- /dev/null
+++ b/EXTERNAL/mcqd/mcqd.h
@@ -0,0 +1,295 @@
+/*
+    Copyright 2007-2012 Janez Konc 
+
+    If you use this program, please cite: 
+    Janez Konc and Dusanka Janezic. An improved branch and bound algorithm for the 
+    maximum clique problem. MATCH Commun. Math. Comput. Chem., 2007, 58, 569-590.
+
+    More information at: http://www.sicmm.org/~konc
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MCQD
+#define MCQD
+
+#include <iostream>
+#include <algorithm>
+#include <assert.h>
+#ifdef DBG
+using namespace std;
+#endif
+
+class Maxclique {
+  const bool* const* e;
+  int pk, level;
+  const float Tlimit;
+  class Vertices {
+    class Vertex {
+      int i, d;
+    public:
+      void set_i(const int ii)  { i = ii; }
+      int get_i() const { return i; }
+      void set_degree(int dd) { d = dd; }
+      int get_degree() const { return d; }
+    };
+    Vertex *v;
+    int sz;
+    static bool desc_degree(const Vertex vi, const Vertex vj) { return (vi.get_degree() > vj.get_degree()); }
+  public:
+#ifdef DBG
+    void dbg_v(const string msg="") const {
+      std::cout << msg << " Vertices: [";
+      for (int i=0; i < sz; i++) 
+	std::cout << "(" << v[i].get_i() << "," << v[i].get_degree() << ") ";
+      std::cout << "]" << std::endl;
+    }
+#endif
+    Vertices(int size) : sz(0) { v = new Vertex[size]; }
+    ~Vertices () {}
+    void dispose() { if (v) delete [] v; }
+    void sort() { std::sort(v, v+sz, desc_degree); }
+    void init_colors();
+    void set_degrees(Maxclique&);
+    int size() const { return sz; }
+    void push(const int ii) { v[sz++].set_i(ii); };
+    void pop() { sz--; };
+    Vertex& at(const int ii) const { return v[ii]; };
+    Vertex& end() const { return v[sz - 1]; };
+  };
+  class ColorClass {
+    int *i;
+    int sz;
+  public:
+#ifdef DBG
+    void dbg_i(const string msg="") const {
+      std::cout << msg << " Class: [";
+      for (int ii=0; ii < sz; ii++) 
+	std::cout << i[ii] << " ";
+      std::cout << "]" << std::endl;
+    }
+#endif
+    ColorClass() : sz(0), i(0) {}
+    ColorClass(const int sz) : sz(sz), i(0) { init(sz); }
+    ~ColorClass() { if (i) delete [] i;
+    }
+    void init(const int sz) { i = new int[sz]; rewind(); }
+    void push(const int ii) { i[sz++] = ii; };
+    void pop() { sz--; };
+    void rewind() { sz = 0; };
+    int size() const { return sz; }
+    int& at(const int ii) const { return i[ii]; }
+    ColorClass& operator=(const ColorClass& dh) {
+      for (int j = 0; j < dh.sz; j++) i[j] = dh.i[j];
+      sz = dh.sz;
+      return *this;
+    }
+  };
+  Vertices V;
+  ColorClass *C, QMAX, Q;
+  class StepCount {
+    int i1, i2;
+  public:
+    StepCount() : i1(0), i2(0) {}
+    void set_i1(const int ii)  { i1 = ii; }
+    int get_i1() const { return i1; }
+    void set_i2(const int ii)  { i2 = ii; }
+    int get_i2() const { return i2; }
+    void inc_i1()  { i1++; }
+  };
+  StepCount *S;
+  bool connection(const int i, const int j) const { return e[i][j]; }
+  bool cut1(const int, const ColorClass&);
+  void cut2(const Vertices&, Vertices&);
+  void color_sort(Vertices&);
+  void expand(Vertices);
+  void expand_dyn(Vertices);
+  void _mcq(int*&, int&, bool);
+  void degree_sort(Vertices &R) { R.set_degrees(*this); R.sort(); }
+public:
+#ifdef DBG
+  void dbg_C() const {
+    for (int i=0; i < V.size(); i++) {
+      std::cout << "C["<< i << "] : ";
+      C[i].dbg_i();
+    }
+  }
+  void dbg_conn() const {
+    for (int i=0; i < V.size(); i++) {
+      for (int j=0; j < V.size(); j++) {
+	std::cout <<e[i][j];
+      }
+      std::cout<< std::endl;
+    }
+  }
+#endif
+  Maxclique(const bool* const*, const int, const float=0.025);
+  int steps() const { return pk; }
+  void mcq(int* &maxclique, int &sz) { _mcq(maxclique, sz, false); }
+  void mcqdyn(int* &maxclique, int &sz) { _mcq(maxclique, sz, true); }
+  ~Maxclique() {
+    if (C) delete [] C;
+    if (S) delete [] S;
+    V.dispose();
+  };
+};
+
+Maxclique::Maxclique (const bool* const* conn, const int sz, const float tt) : pk(0), level(1), Tlimit(tt), V(sz), Q(sz), QMAX(sz) {
+  assert(conn!=0 && sz>0);
+  for (int i=0; i < sz; i++) V.push(i);
+  e = conn;
+  C = new ColorClass[sz + 1];
+  for (int i=0; i < sz + 1; i++) C[i].init(sz + 1);
+  S = new StepCount[sz + 1];
+}
+
+void Maxclique::_mcq(int* &maxclique, int &sz, bool dyn) { 
+  V.set_degrees(*this);
+  V.sort();
+  V.init_colors();
+  if (dyn) {
+    for (int i=0; i < V.size() + 1; i++) {
+      S[i].set_i1(0);
+      S[i].set_i2(0);
+    }
+    expand_dyn(V);
+  }
+  else
+    expand(V);
+  maxclique = new int[QMAX.size()]; 
+  for (int i=0; i<QMAX.size(); i++) { 
+    maxclique[i] = QMAX.at(i);
+  }
+  sz = QMAX.size();
+}
+
+void Maxclique::Vertices::init_colors() { 
+  const int max_degree = v[0].get_degree();
+  for (int i = 0; i < max_degree; i++)
+    v[i].set_degree(i + 1);
+  for (int i = max_degree; i < sz; i++)
+    v[i].set_degree(max_degree + 1);
+}
+
+void Maxclique::Vertices::set_degrees(Maxclique &m) { 
+  for (int i=0; i < sz; i++) {
+    int d = 0;
+    for (int j=0; j < sz; j++)
+      if (m.connection(v[i].get_i(), v[j].get_i())) d++;
+    v[i].set_degree(d);
+  }
+}
+
+bool Maxclique::cut1(const int pi, const ColorClass &A) {
+  for (int i = 0; i < A.size(); i++)
+    if (connection(pi, A.at(i)))
+      return true;
+  return false;
+}
+
+void Maxclique::cut2(const Vertices &A, Vertices &B) {
+  for (int i = 0; i < A.size() - 1; i++) {
+    if (connection(A.end().get_i(), A.at(i).get_i()))
+      B.push(A.at(i).get_i());
+  }
+}
+
+void Maxclique::color_sort(Vertices &R) {
+  int j = 0;
+  int maxno = 1;
+  int min_k = QMAX.size() - Q.size() + 1;
+  C[1].rewind();
+  C[2].rewind();
+  int k = 1;
+  for (int i=0; i < R.size(); i++) {
+    int pi = R.at(i).get_i();
+    k = 1;
+    while (cut1(pi, C[k]))
+      k++;
+    if (k > maxno) {
+      maxno = k;
+      C[maxno + 1].rewind();
+    }
+    C[k].push(pi);
+    if (k < min_k) {
+      R.at(j++).set_i(pi);
+    }
+  }
+  if (j > 0) R.at(j-1).set_degree(0);
+  if (min_k <= 0) min_k = 1;
+  for (k = min_k; k <= maxno; k++)
+    for (int i = 0; i < C[k].size(); i++) {
+      R.at(j).set_i(C[k].at(i));
+      R.at(j++).set_degree(k);
+    }
+}
+
+void Maxclique::expand(Vertices R) {
+  while (R.size()) {
+    if (Q.size() + R.end().get_degree() > QMAX.size()) {
+      Q.push(R.end().get_i());
+      Vertices Rp(R.size());
+      cut2(R, Rp);
+      if (Rp.size()) {
+        color_sort(Rp);
+	pk++;
+        expand(Rp);
+      }
+      else if (Q.size() > QMAX.size()) { 
+        //std::cout << "step = " << pk << " current max. clique size = " << Q.size() << std::endl; 
+	QMAX = Q;
+      }    
+      Rp.dispose();
+      Q.pop();
+    }
+    else {
+      return;
+    }
+    R.pop();
+  }
+}
+
+void Maxclique::expand_dyn(Vertices R) {
+  S[level].set_i1(S[level].get_i1() + S[level - 1].get_i1() - S[level].get_i2());
+  S[level].set_i2(S[level - 1].get_i1());
+  while (R.size()) {
+    if (Q.size() + R.end().get_degree() > QMAX.size()) {
+      Q.push(R.end().get_i());
+      Vertices Rp(R.size());
+      cut2(R, Rp);
+      if (Rp.size()) {
+        if ((float)S[level].get_i1()/++pk < Tlimit) {
+          degree_sort(Rp);
+        }
+        color_sort(Rp);
+	S[level].inc_i1();
+	level++;
+	expand_dyn(Rp);
+	level--;
+      }
+      else if (Q.size() > QMAX.size()) { 
+        //std::cout << "step = " << pk << " current max. clique size = " << Q.size() << std::endl; 
+	QMAX = Q;
+      }    
+      Rp.dispose();
+      Q.pop();
+    }
+    else {
+      return;
+    }
+    R.pop();
+  }
+}
+
+#endif
diff --git a/cmake_modules/FindEigen3.cmake b/cmake_modules/FindEigen3.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..8c2a734c3d3fe5f73fd3d87557037522de13e964
--- /dev/null
+++ b/cmake_modules/FindEigen3.cmake
@@ -0,0 +1,87 @@
+# - Try to find Eigen3 lib
+#
+# This module supports requiring a minimum version, e.g. you can do
+#   find_package(Eigen3 3.1.2)
+# to require version 3.1.2 or newer of Eigen3.
+#
+# Once done this will define
+#
+#  EIGEN3_FOUND - system has eigen lib with correct version
+#  EIGEN3_INCLUDE_DIR - the eigen include directory
+#  EIGEN3_VERSION - eigen version
+
+# Copyright (c) 2006, 2007 Montel Laurent, <montel@kde.org>
+# Copyright (c) 2008, 2009 Gael Guennebaud, <g.gael@free.fr>
+# Copyright (c) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
+# Redistribution and use is allowed according to the terms of the 2-clause BSD license.
+
+if(NOT Eigen3_FIND_VERSION)
+  if(NOT Eigen3_FIND_VERSION_MAJOR)
+    set(Eigen3_FIND_VERSION_MAJOR 2)
+  endif(NOT Eigen3_FIND_VERSION_MAJOR)
+  if(NOT Eigen3_FIND_VERSION_MINOR)
+    set(Eigen3_FIND_VERSION_MINOR 91)
+  endif(NOT Eigen3_FIND_VERSION_MINOR)
+  if(NOT Eigen3_FIND_VERSION_PATCH)
+    set(Eigen3_FIND_VERSION_PATCH 0)
+  endif(NOT Eigen3_FIND_VERSION_PATCH)
+
+  set(Eigen3_FIND_VERSION "${Eigen3_FIND_VERSION_MAJOR}.${Eigen3_FIND_VERSION_MINOR}.${Eigen3_FIND_VERSION_PATCH}")
+endif(NOT Eigen3_FIND_VERSION)
+
+macro(_eigen3_check_version)
+  file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header)
+
+  string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match "${_eigen3_version_header}")
+  set(EIGEN3_WORLD_VERSION "${CMAKE_MATCH_1}")
+  string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen3_major_version_match "${_eigen3_version_header}")
+  set(EIGEN3_MAJOR_VERSION "${CMAKE_MATCH_1}")
+  string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen3_minor_version_match "${_eigen3_version_header}")
+  set(EIGEN3_MINOR_VERSION "${CMAKE_MATCH_1}")
+
+  set(EIGEN3_VERSION ${EIGEN3_WORLD_VERSION}.${EIGEN3_MAJOR_VERSION}.${EIGEN3_MINOR_VERSION})
+  if(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
+    set(EIGEN3_VERSION_OK FALSE)
+  else(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
+    set(EIGEN3_VERSION_OK TRUE)
+  endif(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
+
+  if(NOT EIGEN3_VERSION_OK)
+
+    message(STATUS "Eigen3 version ${EIGEN3_VERSION} found in ${EIGEN3_INCLUDE_DIR}, "
+                   "but at least version ${Eigen3_FIND_VERSION} is required")
+  endif(NOT EIGEN3_VERSION_OK)
+endmacro(_eigen3_check_version)
+
+if (EIGEN3_INCLUDE_DIR)
+
+  # in cache already
+  _eigen3_check_version()
+  set(EIGEN3_FOUND ${EIGEN3_VERSION_OK})
+
+else (EIGEN3_INCLUDE_DIR)
+
+  # specific additional paths for some OS
+  if (WIN32)
+    set(EIGEN_ADDITIONAL_SEARCH_PATHS ${EIGEN_ADDITIONAL_SEARCH_PATHS} "C:/Program Files/Eigen/include" "C:/Program Files (x86)/Eigen/include")
+  endif(WIN32)
+
+  find_path(EIGEN3_INCLUDE_DIR NAMES signature_of_eigen3_matrix_library
+      PATHS
+      ${CMAKE_INSTALL_PREFIX}/include
+      ${EIGEN_ADDITIONAL_SEARCH_PATHS}
+      ${KDE4_INCLUDE_DIR}
+      PATH_SUFFIXES eigen3 eigen
+    )
+
+  if(EIGEN3_INCLUDE_DIR)
+    _eigen3_check_version()
+  endif(EIGEN3_INCLUDE_DIR)
+
+  include(FindPackageHandleStandardArgs)
+  find_package_handle_standard_args(Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK)
+
+  mark_as_advanced(EIGEN3_INCLUDE_DIR)
+
+endif(EIGEN3_INCLUDE_DIR)
+
diff --git a/cmake_modules/falkolibConfig.cmake b/cmake_modules/falkolibConfig.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..750b29ee9667404cd0bca0ec4e1c91bfb6d4d95b
--- /dev/null
+++ b/cmake_modules/falkolibConfig.cmake
@@ -0,0 +1,41 @@
+# - Try to find Library falkolib
+# Once done, this will define
+#
+#  falkolib_FOUND - system has falkolib module
+#  falkolib_INCLUDE_DIRS - the falkolib include directories
+#  falkolib_LIBRARY_DIRS - the falkolib library directories
+#  falkolib_LIBRARIES - link these to use falkolib
+
+
+# Uses  directory to search mrf_segmentation directory!
+set(falkolib_PREFIX_DIR /usr/local)
+message(STATUS "Searching falkolib in directory ${falkolib_PREFIX_DIR}." )
+
+# Searches include directory /usr/local/include/falkolib
+find_path(falkolib_INCLUDE_DIR falkolib ${falkolib_PREFIX_DIR}/include)
+message(STATUS "    falkolib_INCLUDE_DIR ${falkolib_INCLUDE_DIR}." )
+set(falkolib_INCLUDE_DIRS ${falkolib_INCLUDE_DIR})
+  
+# Searches library librimagraph.a in /usr/local/lib
+find_path(falkolib_LIBRARY_DIR librimagraph.a ${falkolib_PREFIX_DIR}/lib)
+message(STATUS "    falkolib_LIBRARY_DIR ${falkolib_LIBRARY_DIR}." )
+set(falkolib_LIBRARY_DIRS ${falkolib_PREFIX_DIR}/lib)
+
+# Sets the names of library components (actually A name and A component)
+find_library(falkolib_LIBRARY falkolib ${falkolib_LIBRARY_DIRS})
+message(STATUS "    falkolib_LIBRARY ${falkolib_LIBRARY}." )
+set(falkolib_LIBRARIES ${falkolib_LIBRARY})
+
+if(("${falkolib_INCLUDE_DIR}" STREQUAL "falkolib_INCLUDE_DIR-NOTFOUND") OR
+   ("${falkolib_LIBRARY_DIRS}" STREQUAL "falkolib_LIBRARY_DIRS-NOTFOUND") OR
+   ("${falkolib_LIBRARY}" STREQUAL "falkolib_LIBRARY-NOTFOUND")
+  )
+  message(STATUS "Library falkolib NOT found")
+  unset(falkolib_FOUND)
+  unset(falkolib_INCLUDE_DIR)
+  unset(falkolib_LIBRARY_DIR)
+  unset(falkolib_LIBRARY)
+  unset(falkolib_LIBRARIES)
+endif()
+
+mark_as_advanced(falkolib_INCLUDE_DIRS falkolib_LIBRARY_DIRS falkolib_LIBRARIES)
diff --git a/include/falkolib/Common/GeomUtils.h b/include/falkolib/Common/GeomUtils.h
new file mode 100644
index 0000000000000000000000000000000000000000..ddb445e5471e9ac1cd72b766199b359bcad2b088
--- /dev/null
+++ b/include/falkolib/Common/GeomUtils.h
@@ -0,0 +1,114 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+/**
+ * @brief Useful geometric functions
+ */
+
+#include <falkolib/Common/Point.h>
+
+#include <Eigen/Dense>
+
+namespace falkolib {
+
+    /**
+     * @brief point-to-point distance
+     * @param p1 point 1
+     * @param p2 point 2
+     * @return distance between p1 and p2F
+     */
+    template <typename T>
+    double pointsDistance(const T& p1, const T& p2) {
+        return (p2 - p1).norm();
+    }
+
+    /**
+     * @brief angle between two given points
+     * @param p1 point 1
+     * @param p2 point 2
+     * @return angle between p1 and p2 [rad]
+     */
+    template <typename T>
+    double angleBetweenPoints(const T& p1, const T& p2) {
+        double angle = atan2(p2[1] - p1[1], p2[0] - p1[0]);
+        //numeric problems..........
+        if (angle >= M_PI) return M_PI - 0.000001;
+        if (angle <= -M_PI) return -M_PI + 0.000001;
+        return angle;
+    }
+
+    /**
+     * @brief This function computes the inner area of a triangle defined by 3 vertices
+     * @param p0 triangle first vertex
+     * @param p1 triangle second vertex
+     * @param p2 triangle third vertex
+     * @return signed area of the inner triangle, p0-p1 as base of the triangle
+     */
+    template <typename T>
+    double signedTriangleArea(const T& p0, const T& p1, const T& p2) {
+        return ((p2[1] - p1[1]) * p0[0] - (p2[0] - p1[0]) * p0[1] + p2[0] * p1[1] - p2[1] * p1[0]);
+    }
+
+    /**
+     * @brief Compute Affine transform between two points sets using least square regression
+     * @param v1 first points set
+     * @param v2 second points set
+     * @param indices matching vectors, pair.first corresponds to v1 and pair.second corresponds to v2
+     * @param transform resulting affine transform which move v2 in v1 frame.
+     * @return if false, the resulting transform is invalid
+     */
+    template <typename T>
+    bool computeTransform(const std::vector<T>& v1, const std::vector<T>& v2, const std::vector<std::pair<int, int> >& indices, Eigen::Affine2d& transform) {
+
+        Eigen::Vector2d t1 = Eigen::Vector2d::Zero();
+        Eigen::Vector2d t2 = Eigen::Vector2d::Zero();
+        Eigen::Matrix2d S = Eigen::Matrix2d::Zero();
+        int n = 0;
+        for (int i = 0; i < (int) indices.size(); ++i) {
+            if (0 <= indices[i].first && indices[i].first < (int) v1.size() &&
+                    0 <= indices[i].second && indices[i].second < (int) v2.size()) {
+                t1 += v1[indices[i].first].point;
+                t2 += v2[indices[i].second].point;
+                n++;
+            }
+        }
+        if (n == 0) {
+            return false;
+        }
+        t1 = (1.0 / n) * t1;
+        t2 = (1.0 / n) * t2;
+        for (int i = 0; i < (int) indices.size(); ++i) {
+            if (0 <= indices[i].first && indices[i].first < (int) v1.size() &&
+                    0 <= indices[i].second && indices[i].second < (int) v2.size()) {
+                S += (v2[indices[i].second].point - t2) * ((v1[indices[i].first].point - t1).transpose());
+            }
+        }
+        double theta = std::atan2(S(0, 1) - S(1, 0), S(0, 0) + S(1, 1));
+        Eigen::Rotation2Dd rot(theta);
+        Eigen::Vector2d transl = t1 - (rot * t2);
+        transform = Eigen::Affine2d::Identity();
+        transform.prerotate(rot);
+        transform.pretranslate(transl);
+
+        return true;
+    }
+
+}
\ No newline at end of file
diff --git a/include/falkolib/Common/HoughSpectrum.h b/include/falkolib/Common/HoughSpectrum.h
new file mode 100644
index 0000000000000000000000000000000000000000..c95bff5c35107ad0f940b2c094f9d3b401241e25
--- /dev/null
+++ b/include/falkolib/Common/HoughSpectrum.h
@@ -0,0 +1,147 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <iostream>
+#include <Eigen/Dense>
+
+namespace falkolib {
+
+    /** Hough transform and spectrum. 
+     */
+    class HoughSpectrum {
+    public:
+        /** Constructor with deafult parameters. 
+         */
+        HoughSpectrum();
+
+        /** Constructor with the number of theta. 
+         */
+        HoughSpectrum(double thetaStep, double rhoStep, double rhoMax);
+
+        /** Inits params.
+         */
+        void init(double thetaStep, double rhoStep, double rhoMax);
+
+        /** Inserts the points and computes Hough Transform and Spectrum. 
+         */
+        template <typename It>
+        void insertPoint(It pbeg, It pend);
+
+        /** Returns the Hough Transform. 
+         */
+        const Eigen::MatrixXd& hough() const {
+            return hough_;
+        }
+
+        /** Returns the value of Hough Transform for a specific value of theta and rho.
+         * If the theta and rho are not in the domain, then it return 0.0.
+         */
+        double hough(double theta, double rho) const {
+            int ith = thetaToIdx(theta);
+            int irh = rhoToIdx(theta);
+            if (0 <= ith && ith < hough_.rows() && 0 <= irh && irh < hough_.cols()) {
+                return hough_(ith, irh);
+            }
+            return 0.0;
+        }
+
+        /** Returns the spectrum.
+         */
+        const Eigen::VectorXd& spectrum() const {
+            return spectrum_;
+        }
+
+        /** Returns the spectrum.
+         */
+        const double spectrum(double theta) const {
+            int ith = thetaToIdx(theta);
+            if (0 <= ith && ith < hough_.rows()) {
+                return spectrum_(ith);
+            }
+            return 0.0;
+        }
+
+        /** Returns the spectrum.
+         */
+        const Eigen::VectorXd& orthoSpectrum() const {
+            return orthoSpectrum_;
+        }
+
+    private:
+        int thetaNum_;
+        int rhoNum_;
+        double thetaStep_;
+        double rhoStep_;
+        // Hough transform and spectra should be integer types. 
+        // However, since their value may be very large, double type is used instead. 
+        Eigen::MatrixXd hough_;
+        Eigen::VectorXd spectrum_;
+        Eigen::VectorXd orthoSpectrum_;
+        Eigen::VectorXd cosLut_;
+        Eigen::VectorXd sinLut_;
+
+        double idxToRho(int idx) const {
+            return (rhoStep_ * (idx - rhoNum_));
+        }
+
+        int rhoToIdx(double rho) const {
+            return ((int) round(rho / rhoStep_) + rhoNum_ / 2);
+        }
+
+        int thetaToIdx(double theta) const {
+            int idx = (int) round(theta / thetaStep_);
+            int thetaNum2 = 2 * thetaNum_;
+            idx = ((idx % thetaNum2) + thetaNum2) % thetaNum2;
+            return idx;
+        }
+    };
+
+    // -------------------------------------------------------------
+    // TEMPLATE METHOD
+    // -------------------------------------------------------------
+
+    template <typename It>
+    void HoughSpectrum::insertPoint(It pbeg, It pend) {
+        double rho;
+        int irho;
+
+        hough_.fill(0.0);
+        spectrum_.fill(0.0);
+        // Computes Hough
+        for (It pit = pbeg; pit != pend; ++pit) {
+            for (int i = 0; i < thetaNum_; ++i) {
+                rho = pit->x() * cosLut_(i) + pit->y() * sinLut_(i);
+                irho = rhoToIdx(rho);
+                if (0 <= irho && irho < rhoNum_) {
+                    hough_(i, irho) = hough_(i, irho) + 1;
+                }
+                //			else {
+                //				std::cerr << "Out-of-bound: rho " << rho << ", theta " << (180.0 / M_PI * thetaStep_ * i) << ", "
+                //					<< "point [" << pit->x() << " " << pit->y() << "]\n";
+                //			}
+            }
+        }
+        spectrum_ = (hough_.array() * hough_.array()).rowwise().sum();
+        orthoSpectrum_ = spectrum_.segment(0, thetaNum_ / 2) + spectrum_.segment(thetaNum_ / 2, thetaNum_ / 2);
+    }
+
+} // end of namespace
+
diff --git a/include/falkolib/Common/LaserScan.h b/include/falkolib/Common/LaserScan.h
new file mode 100644
index 0000000000000000000000000000000000000000..eae9e962d651be31c35405f3b8611c9e054c83c8
--- /dev/null
+++ b/include/falkolib/Common/LaserScan.h
@@ -0,0 +1,155 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <vector>
+#include <falkolib/Common/Point.h>
+#include <falkolib/Common/GeomUtils.h>
+
+namespace falkolib {
+
+	/**
+	 * @brief Laser scan container
+	 * 
+	 * This class provides an essential interface for laser scan data 
+	 */
+	class LaserScan {
+	public:
+
+		/**
+		 * @brief Constructor
+		 */
+		LaserScan() {
+			angleMin = 0;
+			fov = 0;
+			angleInc = 0;
+			numBeams = 0;
+			timestamp = 0;
+		}
+
+		/**
+		 * @brief Constructor
+		 * @param _angleMin laser scanner start angle [rad]
+		 * @param _fov laser scanner field of view [rad]
+		 * @param _numBeams laser scanner number of beams
+		 */
+		LaserScan(double _angleMin, double _fov, int _numBeams) {
+			angleMin = _angleMin;
+			fov = _fov;
+			angleInc = _fov / _numBeams;
+			numBeams = _numBeams;
+			timestamp = 0;
+		}
+
+		/** @brief Set laser scanner start angle [rad] */
+		inline void setAngleMin(double _angleMin) {
+			angleMin = _angleMin;
+		};
+
+		/** @brief Set laser scanner field of view [rad] */
+		inline void setLaserFoV(double _fov) {
+			fov = _fov;
+		};
+
+		/** @brief Set laser scanner angle increment [rad] */
+		inline void setAngleInc(double _angleInc) {
+			angleInc = _angleInc;
+		};
+
+		/** @brief Set laser scanner number of beams */
+		inline void setNumBeams(int _numBeams) {
+			numBeams = _numBeams;
+		};
+
+		/** @brief Set scan beginning timestamp [s] */
+		inline void setTimestamp(double _timestamp) {
+			timestamp = _timestamp;
+		};
+
+		/** @brief Get laser scanner number of beams */
+		inline int getNumBeams() const {
+			return numBeams;
+		};
+
+		/** @brief Get laser scanner angle increment [rad] */
+		inline double getAngleInc() const {
+			return angleInc;
+		};
+
+		/**
+		 * @brief Compute scan points from ranges
+		 * 
+		 * @param _ranges plain array of double representing the scan ranges
+		 */
+		inline void fromRanges(const double* _ranges) {
+			fromRanges(std::vector<double>(_ranges, _ranges + numBeams));
+		}
+
+		/**
+		 * @brief Compute scan points from ranges
+		 * 
+		 * @param _ranges std::vector of double representing the scan ranges
+		 */
+		inline void fromRanges(const std::vector<double>& _ranges) {
+			double theta;
+			ranges = _ranges;
+			points.resize(numBeams);
+			for (int i = 0; i < numBeams; ++i) {
+				theta = i * angleInc + angleMin;
+				points[i][0] = ranges[i] * std::cos(theta);
+				points[i][1] = ranges[i] * std::sin(theta);
+			}
+		}
+
+		/**
+		 * @brief compute neighborhood points list given a single point index and a search radius
+		 * @param candIndex index of the central point
+		 * @param radius search euclidean radius [m]
+		 * @param neigh vector of the neighborhood points
+		 * @param midIndex index representing the central point in the neigh vector
+		 */
+		void getNeighPoints(int candIndex, double radius, std::vector<Point2d>& neigh, int& midIndex) const {
+			const Point2d& candPoint = points[candIndex];
+			int alpha = std::floor(std::asin(radius / ranges[candIndex]) / angleInc);
+			int begIndex = std::max(0, candIndex - alpha);
+			int endIndex = std::min(candIndex + alpha + 1, numBeams);
+			for (int i = begIndex; i <= endIndex; ++i) {
+				if (pointsDistance(points[i], candPoint) <= radius) {
+					if (i == candIndex) {
+						midIndex = neigh.size();
+					}
+					neigh.push_back(points[i]);
+				}
+			}
+		}
+
+
+		std::vector<double> ranges;
+		std::vector<Point2d> points;
+
+	private:
+
+		double angleMin;
+		double fov;
+		double angleInc;
+		int numBeams;
+		double timestamp;
+	};
+}
\ No newline at end of file
diff --git a/include/falkolib/Common/Point.h b/include/falkolib/Common/Point.h
new file mode 100644
index 0000000000000000000000000000000000000000..4fb0bd6485e28a311ab137e746f250613567b95c
--- /dev/null
+++ b/include/falkolib/Common/Point.h
@@ -0,0 +1,28 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <Eigen/Core>
+
+namespace falkolib {
+	typedef Eigen::Vector2d Point2d;
+	typedef Eigen::Vector2f Point2f;
+	typedef Eigen::Vector2i Point2i;
+}
\ No newline at end of file
diff --git a/include/falkolib/Feature/BSC.h b/include/falkolib/Feature/BSC.h
new file mode 100644
index 0000000000000000000000000000000000000000..f3403f1070384707fae0be06c65bfcf9c97b9c19
--- /dev/null
+++ b/include/falkolib/Feature/BSC.h
@@ -0,0 +1,81 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <falkolib/Feature/Descriptor.h>
+#include <falkolib/Common/Point.h>
+#include <vector>
+
+namespace falkolib {
+
+	/**
+	 * @brief Binary Shape Context descriptor
+	 * 
+	 * This class represents a BSC Descriptor.
+	 */
+	class BSC : public Descriptor {
+	public:
+		
+		/**
+		 * @brief Constructor
+		 * @param _radius descriptor max radius
+		 * @param _circularSectorNumber number of circular sectors
+		 * @param _radialRingNumber number of radial rings
+		 * 
+		 * Set the grid dimension and cells resolutions
+		 */
+		BSC(double _radius, int _circularSectorNumber, int _radialRingNumber);
+		
+		/**
+		 * @brief Compute distance between two descriptors
+		 * @param desc descriptor to measure distance
+		 * @return the distance between *this and desc
+		 * 
+		 * Compute the distance between two descriptors of the same type (BSC)
+		 */
+		double distance(const Descriptor& desc) const;
+		
+		/**
+		 * @brief Rotate the descriptor grid
+		 * @param theta angle of rotation [rad]
+		 * 
+		 * Rotate the descriptor grid of a number of circular sector based on theta
+		 */
+		void rotate(double theta);
+		
+		/**
+		 * @brief Compute the grid descriptor
+		 * @param neigh vector of neighborhood points
+		 * @param centralPointIndex index of the central point in the neigh vector
+		 */
+		void compute(std::vector<Point2d>& neigh, int centralPointIndex);
+		
+	private:
+		std::vector<std::vector<uint8_t> > grid;
+		int circularSectorNumber;
+		int radialRingNumber;
+		double sectorResolution;
+		double ringResolution;
+		double radius;
+		
+		/** @brief compute the Hamming distance between two binary grid*/
+		double HammingDistance(const std::vector<std::vector<uint8_t> >& g1, const std::vector<std::vector<uint8_t> >& g2) const;
+	};
+}
\ No newline at end of file
diff --git a/include/falkolib/Feature/BSCExtractor.h b/include/falkolib/Feature/BSCExtractor.h
new file mode 100644
index 0000000000000000000000000000000000000000..aee7ce5189dd0e0177496e6a30598bb6375fd3a9
--- /dev/null
+++ b/include/falkolib/Feature/BSCExtractor.h
@@ -0,0 +1,81 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <falkolib/Common/LaserScan.h>
+#include <falkolib/Feature/Keypoint.h>
+#include <falkolib/Feature/DescriptorExtractor.h>
+#include <falkolib/Feature/BSC.h>
+
+namespace falkolib {
+
+	/**
+	 * @brief class representing a BSC descriptor extractor engine 
+	 */
+	template <typename T>
+	class BSCExtractor : public DescriptorExtractor<T, BSC> {
+	public:
+
+		/**
+		 * @brief Constructor
+		 * @param _circularSectorNumber number of grid circular sector
+		 * @param _radialRingNumber number of grid radial number
+		 * @param _useKeypointRadius if true, the selected neighborhood points search radius is keypoint one
+		 * @param _radius neighborhood points search radius
+		 */
+		BSCExtractor(int _circularSectorNumber, int _radialRingNumber, bool _useKeypointRadius = true, double _radius = 0.1) {
+			circularSectorNumber = _circularSectorNumber;
+			radialRingNumber = _radialRingNumber;
+			useKeypointRadius = _useKeypointRadius;
+			radius = _radius;
+		};
+
+		/**
+		 * @brief Extract BSC descriptor from a given scan and a list of keypoints
+		 * @param scan input laser scan
+		 * @param keypoints keypoints list
+		 * @param descriptor extracted from scan and keypoints
+		 */
+		void compute(const LaserScan& scan, const std::vector<T>& keypoints, std::vector<BSC>& descriptors) {
+			descriptors.reserve(keypoints.size());
+			for (int i = 0; i < keypoints.size(); ++i) {
+				std::vector<Point2d> neigh;
+				int midIndex;
+				if (useKeypointRadius) {
+					scan.getNeighPoints(keypoints[i].index, keypoints[i].radius, neigh, midIndex);
+					BSC desc(keypoints[i].radius, circularSectorNumber, radialRingNumber);
+					desc.compute(neigh, midIndex);
+					descriptors.push_back(std::move(desc));
+				} else {
+					scan.getNeighPoints(keypoints[i].index, radius, neigh, midIndex);
+					BSC desc(radius, circularSectorNumber, radialRingNumber);
+					desc.compute(neigh, midIndex);
+					descriptors.push_back(std::move(desc));
+				}
+			}
+		};
+
+	private:
+		int circularSectorNumber;
+		int radialRingNumber;
+		bool useKeypointRadius;
+		double radius;
+	};
+}
\ No newline at end of file
diff --git a/include/falkolib/Feature/CGH.h b/include/falkolib/Feature/CGH.h
new file mode 100644
index 0000000000000000000000000000000000000000..60e3cecd4f866ccf7cb5f0ce7b5f04d6b7448790
--- /dev/null
+++ b/include/falkolib/Feature/CGH.h
@@ -0,0 +1,78 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <falkolib/Feature/Descriptor.h>
+#include <falkolib/Common/Point.h>
+#include <vector>
+
+namespace falkolib {
+
+	/**
+	 * @brief Cumulative Gaussian Histogram descriptor
+	 * 
+	 * This class represents a CGH Descriptor.
+	 */
+	class CGH : public Descriptor {
+	public:
+		
+		/**
+		 * @brief Constructor
+		 * @param _radius descriptor max radius
+		 * @param _circularSectorNumber number of histogram bins
+		 * 
+		 * Set the histogram dimension and the circular sectors resolutions
+		 */
+		CGH(double _radius, int _circularSectorNumber);
+		
+		/**
+		 * @brief Compute distance between two descriptors
+		 * @param desc descriptor to measure distance
+		 * @return the distance between *this and desc
+		 * 
+		 * Compute the distance between two descriptors of the same type (CGH)
+		 */
+		double distance(const Descriptor& desc) const;
+		
+		/**
+		 * @brief Rotate the descriptor grid
+		 * @param theta angle of rotation [rad]
+		 * 
+		 * Rotate the descriptor grid of a number of circular sector based on theta
+		 */
+		void rotate(double theta);
+		
+		/**
+		 * @brief Compute the histogram descriptor
+		 * @param neigh vector of neighborhood points
+		 * @param centralPointIndex index of the central point in the neigh vector
+		 */
+		void compute(std::vector<Point2d>& neigh, int centralPointIndex);
+		
+	private:
+		std::vector<double> histogram;
+		int circularSectorNumber;
+		double sectorResolution;
+		double radius;
+		
+		/** @brief compute the Chi-squared distance between two histograms*/
+		double SymmetricChiSquaredDistance(const std::vector<double>& h1, const std::vector<double>& h2) const;
+	};
+}
\ No newline at end of file
diff --git a/include/falkolib/Feature/CGHExtractor.h b/include/falkolib/Feature/CGHExtractor.h
new file mode 100644
index 0000000000000000000000000000000000000000..d8bd7ad9ea0c308574a08115ff23f695163c8170
--- /dev/null
+++ b/include/falkolib/Feature/CGHExtractor.h
@@ -0,0 +1,78 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <falkolib/Common/LaserScan.h>
+#include <falkolib/Feature/Keypoint.h>
+#include <falkolib/Feature/DescriptorExtractor.h>
+#include <falkolib/Feature/CGH.h>
+
+namespace falkolib {
+
+	/**
+	 * @brief class representing a CGH descriptor extractor engine 
+	 */
+	template <typename T>
+	class CGHExtractor : public DescriptorExtractor<T, CGH> {
+	public:
+
+		/**
+		 * @brief Constructor
+		 * @param _circularSectorNumber number of grid circular sector
+		 * @param _useKeypointRadius if true, the selected neighborhood points search radius is keypoint one
+		 * @param _radius neighborhood points search radius
+		 */
+		CGHExtractor(int _circularSectorNumber, bool _useKeypointRadius = true, double _radius = 0.1) {
+			circularSectorNumber = _circularSectorNumber;
+			useKeypointRadius = _useKeypointRadius;
+			radius = _radius;
+		};
+
+		/**
+		 * @brief Extract CGH descriptor from a given scan and a list of keypoints
+		 * @param scan input laser scan
+		 * @param keypoints keypoints list
+		 * @param descriptor extracted from scan and keypoints
+		 */
+		void compute(const LaserScan& scan, const std::vector<T>& keypoints, std::vector<CGH>& descriptors) {
+			descriptors.reserve(keypoints.size());
+			for (int i = 0; i < keypoints.size(); ++i) {
+				std::vector<Point2d> neigh;
+				int midIndex;
+				if (useKeypointRadius) {
+					scan.getNeighPoints(keypoints[i].index, keypoints[i].radius, neigh, midIndex);
+					CGH desc(keypoints[i].radius, circularSectorNumber);
+					desc.compute(neigh, midIndex);
+					descriptors.push_back(std::move(desc));
+				} else {
+					scan.getNeighPoints(keypoints[i].index, radius, neigh, midIndex);
+					CGH desc(radius, circularSectorNumber);
+					desc.compute(neigh, midIndex);
+					descriptors.push_back(std::move(desc));
+				}
+			}
+		};
+
+	private:
+		int circularSectorNumber;
+		bool useKeypointRadius;
+		double radius;
+	};
+}
\ No newline at end of file
diff --git a/include/falkolib/Feature/Descriptor.h b/include/falkolib/Feature/Descriptor.h
new file mode 100644
index 0000000000000000000000000000000000000000..530fd14a665eb3a66efc6135e752331253ca524b
--- /dev/null
+++ b/include/falkolib/Feature/Descriptor.h
@@ -0,0 +1,40 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+namespace falkolib {
+
+	/**
+	 * @brief class representing a generic descriptor
+	 * 
+	 * No properties are defined for a generic descriptor
+	 */
+
+	class Descriptor {
+	protected:
+
+		/**
+		 * @brief Compute distance between two descriptors
+		 * @param desc descriptor to measure distance
+		 * @return the distance between *this and desc
+		 */
+		virtual double distance(const Descriptor& desc) const = 0;
+	};
+}
\ No newline at end of file
diff --git a/include/falkolib/Feature/DescriptorExtractor.h b/include/falkolib/Feature/DescriptorExtractor.h
new file mode 100644
index 0000000000000000000000000000000000000000..c1002e44bcd2b990e037c101f7f9751578e7de07
--- /dev/null
+++ b/include/falkolib/Feature/DescriptorExtractor.h
@@ -0,0 +1,41 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <falkolib/Common/LaserScan.h>
+#include <falkolib/Feature/Keypoint.h>
+
+namespace falkolib {
+	
+	/**
+	 * @brief class representing a descriptor extractor engine 
+	 */
+	template <typename T, typename D>
+	class DescriptorExtractor {
+	protected:
+		/**
+		 * @brief Extract descriptor from a given scan and a list of keypoints
+		 * @param scan input laser scan
+		 * @param keypoints keypoints list
+		 * @param descriptor extracted from scan and keypoints
+		 */
+		virtual void compute(const LaserScan& scan, const std::vector<T>& keypoints, std::vector<D>& descriptors) = 0;
+	};
+}
\ No newline at end of file
diff --git a/include/falkolib/Feature/FALKO.h b/include/falkolib/Feature/FALKO.h
new file mode 100644
index 0000000000000000000000000000000000000000..7204b7fcb3f75fc50f7a24f9e144951dd02d4e69
--- /dev/null
+++ b/include/falkolib/Feature/FALKO.h
@@ -0,0 +1,38 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <falkolib/Feature/Keypoint.h>
+
+namespace falkolib{
+	
+	/**
+	 * @brief class representing a FALKO keypoint
+	 * 
+	 * FALKO keypoint extends simple keypoint interface.
+	 * The index in the original scan, corner orientation and neighborhood search radius are also preserved.
+	 */
+	class FALKO : public Keypoint{
+	public:
+		int index;
+		double radius;
+		double orientation;
+	};
+}
\ No newline at end of file
diff --git a/include/falkolib/Feature/FALKOExtractor.h b/include/falkolib/Feature/FALKOExtractor.h
new file mode 100644
index 0000000000000000000000000000000000000000..2c50ad3192cafca62f649726251cbb0c8a2dfbaa
--- /dev/null
+++ b/include/falkolib/Feature/FALKOExtractor.h
@@ -0,0 +1,132 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <falkolib/Feature/KeypointExtractor.h>
+#include <falkolib/Feature/FALKO.h>
+#include <falkolib/Common/GeomUtils.h>
+
+namespace falkolib {
+
+	/**
+	 * @brief class representing a FALKO keypoint extractor engine 
+	 */
+	class FALKOExtractor : public KeypointExtractor<FALKO> {
+	public:
+
+		/**
+		 * @brief Constructor
+		 */
+		FALKOExtractor();
+
+		/**
+		 * @brief Extract FALKO keypoints from a given scan 	 
+		 * @param scan input laser scan
+		 * @param features FALKO keypoint extracted from given scan
+		 */
+		void extract(const LaserScan& scan, std::vector<FALKO>& keypoints);
+
+		/** @brief Set minimum score threshold for a candidate keypoint [%]*/
+		inline void setMinScoreTh(double _minScoreTh) {
+			minScoreTh = _minScoreTh;
+		};
+
+		/** @brief Set minimum extraction range [m]*/
+		inline void setMinExtractionRange(double _minExtractionRange) {
+			minExtractionRange = _minExtractionRange;
+		};
+
+		/** @brief Set maximum extraction range [m]*/
+		inline void setMaxExtractionRange(double _maxExtractionRange) {
+			maxExtractionRange = _maxExtractionRange;
+		};
+
+		/** @brief Enable subbeam accuracy in keypoint extraction */
+		inline void enableSubbeam(bool _subbeam) {
+			subbeam = _subbeam;
+		};
+
+		/** @brief Set Non-Maxima-Suppression radius [m]*/
+		inline void setNMSRadius(double _NMSRadius) {
+			NMSRadius = _NMSRadius;
+		};
+
+		/** @brief Set neighA parameter for neighborhood radius computation*/
+		inline void setNeighA(double _neighA) {
+			neighA = _neighA;
+		};
+
+		/** @brief Set neighB parameter for neighborhood radius computation*/
+		inline void setNeighB(double _neighB) {
+			neighB = _neighB;
+		};
+
+		/** @brief Set minimum neighborhood size for each corner side*/
+		inline void setNeighMinPoint(double _neighMinPoint) {
+			neighMinPoint = _neighMinPoint;
+		};
+
+		/** @brief Set b-ratio for geometric corner validation*/
+		inline void setBRatio(double _bRatio) {
+			bRatio = _bRatio;
+		};
+
+		/** @brief Set number of circular grid sector for score computation*/
+		inline void setGridSectors(double _gridSectors) {
+			gridSectors = _gridSectors;
+		};
+
+	private:
+		double minScoreTh;
+		double minExtractionRange;
+		double maxExtractionRange;
+		bool subbeam;
+		double NMSRadius;
+		double neighA;
+		double neighB;
+		int neighMinPoint;
+		double bRatio;
+		int gridSectors;
+
+		/** @brief distance between grid circular sectors*/
+		int circularSectorDistance(int a1, int a2, int res);
+
+		/** @brief return index of corresponding circular sector in the score grid*/
+		int getCircularSectorIndex(const Point2d& p, const Point2d& pmid, double theta);
+
+		/** @brief return neighborhood search radius, different heuristics are used based on rho*/
+		double getNeighRadius(double rho);
+
+		/** @brief compute corner orientation given neighborhood points*/
+		double getCornerOrientation(const std::vector<Point2d>& neigh, int midIndex);
+
+		/** @brief Non-Maxima-Suppression function for keypoint extraction*/
+		void NMSKeypoint(const std::vector<int>& scores, const LaserScan& scan, unsigned int ibeg, unsigned int iend, double radius, int minval, std::vector<int>& peaks);
+
+		/** @brief compute corner position with subbeam accuracy*/
+		void subBeamCorner(const LaserScan& scan, int index, double radius, Point2d& p);
+
+		/** @brief generate a line model using least-square*/
+		void generateLine(const std::vector<Point2d>& points, Eigen::Vector3d& model);
+
+		/** @brief built-in 2x2 system solver function*/
+		bool solveSystem2x2(double* A, double* b, double* x);
+	};
+}
\ No newline at end of file
diff --git a/include/falkolib/Feature/Keypoint.h b/include/falkolib/Feature/Keypoint.h
new file mode 100644
index 0000000000000000000000000000000000000000..00f441f4451cac02a19fd23eca7b3de5834b0294
--- /dev/null
+++ b/include/falkolib/Feature/Keypoint.h
@@ -0,0 +1,44 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <falkolib/Common/Point.h>
+
+namespace falkolib {
+
+	/**
+	 * @brief class representing a keypoint
+	 * 
+	 * Keypoints are defined as a 2d point
+	 */
+	class Keypoint {
+	public:
+		Point2d point;
+		
+		/**
+		 * @brief measure distance between keypoints
+		 * @param desc external keypoints
+		 * @return measured distance
+		 */
+		inline double distance(const Keypoint& desc) const {
+			return (point - desc.point).norm();
+		}
+	};
+}
\ No newline at end of file
diff --git a/include/falkolib/Feature/KeypointExtractor.h b/include/falkolib/Feature/KeypointExtractor.h
new file mode 100644
index 0000000000000000000000000000000000000000..d31b7f6539a4e175acb710fbebd90ffb4078b06e
--- /dev/null
+++ b/include/falkolib/Feature/KeypointExtractor.h
@@ -0,0 +1,40 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <falkolib/Common/LaserScan.h>
+#include <falkolib/Feature/Keypoint.h>
+
+namespace falkolib {
+	
+	/**
+	 * @brief class representing a keypoints extractor engine 
+	 */
+	template <typename T>
+	class KeypointExtractor {
+	protected:
+		/**
+		 * @brief Extract keypoints from a given scan 	 
+		 * @param scan input laser scan
+		 * @param features keypoints extracted from given scan
+		 */
+		virtual void extract(const LaserScan& scan, std::vector<T>& keypoints) = 0;
+	};
+}
\ No newline at end of file
diff --git a/include/falkolib/Feature/OC.h b/include/falkolib/Feature/OC.h
new file mode 100644
index 0000000000000000000000000000000000000000..2bd5768006470e110f8fa55a112489dc7b9509c5
--- /dev/null
+++ b/include/falkolib/Feature/OC.h
@@ -0,0 +1,38 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <falkolib/Feature/Keypoint.h>
+
+namespace falkolib{
+	
+	/**
+	 * @brief class representing a OC keypoint
+	 * 
+	 * OC keypoint extends simple keypoint interface.
+	 * The index in the original scan, corner orientation and neighborhood search radius are also preserved.
+	 */
+	class OC : public Keypoint{
+	public:
+		int index;
+		double radius;
+		double orientation;
+	};
+}
diff --git a/include/falkolib/Feature/OCExtractor.h b/include/falkolib/Feature/OCExtractor.h
new file mode 100644
index 0000000000000000000000000000000000000000..27bb351c88c3cb1cfd6a126c5b3749189ce793c1
--- /dev/null
+++ b/include/falkolib/Feature/OCExtractor.h
@@ -0,0 +1,131 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <falkolib/Feature/KeypointExtractor.h>
+#include <falkolib/Feature/OC.h>
+#include <falkolib/Common/Point.h>
+#include <falkolib/Common/GeomUtils.h>
+#include <falkolib/Common/HoughSpectrum.h>
+
+namespace falkolib {
+
+    /**
+     * @brief class representing a OC keypoint extractor engine 
+     */
+    class OCExtractor : public KeypointExtractor<OC> {
+    public:
+
+        enum CornerOrientation {
+            NE = 0, NW, SW, SE
+        };
+
+        /**
+         * @brief Constructor
+         */
+        OCExtractor();
+
+        /**
+         * @brief Extract OC keypoints from a given scan 	 
+         * @param scan input laser scan
+         * @param features OC keypoint extracted from given scan
+         */
+        void extract(const LaserScan& scan, std::vector<OC>& keypoints);
+
+        /** @brief Set the tolerance distance to consider point aligned to corner edge. */
+        inline void setTol(double _tol) {
+            tol = _tol;
+        };
+
+        /** @brief Set the angular resolution. */
+        inline void setAngleRes(double _angleRes) {
+            angleRes = _angleRes;
+            houghSpectrum.init(angleRes, rangeRes, rangeMax);
+        };
+
+        /** @brief Set the range/distance resolution used for Hough rho size. */
+        inline void setRangeRes(double _rangeRes) {
+            rangeRes = _rangeRes;
+            houghSpectrum.init(angleRes, rangeRes, rangeMax);
+        };
+
+        /** @brief Set the maximum range for Hough rho cell grid. */
+        inline void setRangeMax(double _rangeMax) {
+            rangeMax = _rangeMax;
+            houghSpectrum.init(angleRes, rangeRes, rangeMax);
+        };
+
+        /** @brief Set the non maxima suppression radius. */
+        inline void setNMSRadius(double _nmsRadius) {
+            nmsRadius = _nmsRadius;
+        };
+
+        /** @brief Set neighA parameter for neighborhood radius computation*/
+        inline void setNeighA(double _neighA) {
+            neighA = _neighA;
+        };
+
+        /** @brief Set neighB parameter for neighborhood radius computation*/
+        inline void setNeighB(double _neighB) {
+            neighB = _neighB;
+        };
+
+        /** @brief Set minimum neighborhood size for each corner side*/
+        inline void setNeighMinPoint(int _neighMinPoint) {
+            neighMinPoint = _neighMinPoint;
+        };
+
+
+    private:
+        HoughSpectrum houghSpectrum;
+        double tol;
+        double angleRes;
+        double rangeRes;
+        double rangeMax;
+        double nmsRadius;
+        double neighA;
+        double neighB;
+        int neighMinPoint;
+
+        /** @brief Computes the dominant direction of a scan using Hough Spectrum.
+         */
+        double computeDominantAngle(const std::vector<Point2d>& points);
+
+        /** @brief Rotates points. 
+         */
+        void rotatePoints(const std::vector<Point2d>& pointsIn, double angle, std::vector<Point2d>& pointsOut);
+
+        /** @brief Computes the corner score, position and orientation of point with given index. */
+        double computeCornerScore(const std::vector<Point2d>& scan, int index, OC& keypoint);
+
+        /** @brief Finds the neighborhood of point with the given index in vector. 
+         * @param pointsIn vector of all the points 
+         * @param index index of the center point in the 
+         * @param neigh found neighborhood
+         * @param midIndex index of the center point in neigh vector
+         */
+        void getNeighPoints(const std::vector<Point2d>& pointsIn, int index, std::vector<Point2d>& neigh, int& midIndex, double& dist) const;
+
+        /** @brief Finds the peaks of score function using Non-Maxima Suppression (NMS) over a circular neighborhood with given radius.
+         * It is almost a duplicate of FALKOExtractor similar function.
+         */
+        void NMSKeypoint(const std::vector<double>& scores, const LaserScan& scan, unsigned int ibeg, unsigned int iend, double radius, int minval, std::vector<int>& peaks);
+    };
+}
diff --git a/include/falkolib/Matching/AHTMatcher.h b/include/falkolib/Matching/AHTMatcher.h
new file mode 100644
index 0000000000000000000000000000000000000000..8dcd985fba4fdfd2e77ef088ab69b00be2f01435
--- /dev/null
+++ b/include/falkolib/Matching/AHTMatcher.h
@@ -0,0 +1,182 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <falkolib/Matching/Matcher.h>
+
+#include <vector>
+#include <falkolib/Feature/Descriptor.h>
+#include <falkolib/Feature/Keypoint.h>
+
+namespace falkolib {
+
+	/**
+	 * @brief class representing a Affine Hough Transform feature matching engine 
+	 */
+	template <typename T = Keypoint, typename D = Descriptor>
+	class AHTMatcher : public Matcher<T> {
+	public:
+
+		/**
+		 * @brief Constructor
+		 */
+		AHTMatcher() : AHTMatcher(0.1, 0.1, 0.04, 5, 5, 1.57) {
+		};
+
+		/**
+		 * @brief Constructor
+		 */
+		AHTMatcher(double _xRes, double _yRes, double _thetaRes, double _xAbsMax, double _yAbsMax, double _thetaAbsMax) {
+			xRes = _xRes;
+			yRes = _yRes;
+			thetaRes = _thetaRes;
+			xAbsMax = _xAbsMax;
+			yAbsMax = _yAbsMax;
+			thetaAbsMax = _thetaAbsMax;
+			xSize = static_cast<int> (2.0 * xAbsMax / xRes);
+			ySize = static_cast<int> (2.0 * yAbsMax / yRes);
+			thetaSize = static_cast<int> (2.0 * thetaAbsMax / thetaRes);
+			matchesGrid.resize(xSize * ySize * thetaSize);
+			txMax = 0;
+			tyMax = 0;
+			thetaMax = 0;
+		};
+
+		/**
+		 * @brief match keypoints between two sets using AHT matcher
+		 * @param v1 first set of keypoints
+		 * @param v2 second set of keypoints
+		 * @param match matching vector representing associations, pair.first corresponds to v1 and pair.second corresponds to v2
+		 * @return number of valid association in match
+		 */
+		int match(const std::vector<T>& v1, const std::vector<T>& v2, std::vector<std::pair<int, int> >& match) {
+			std::vector<std::pair<int, int> > assoInit;
+			for (int i1 = 0; i1 < v1.size(); ++i1) {
+				for (int i2 = 0; i2 < v2.size(); ++i2) {
+					if (v1[i1].distance(v2[i2]) < distTh) {
+						assoInit.push_back(std::make_pair(i1, i2));
+					}
+				}
+			}
+
+			return getBestMatching(v1, v2, assoInit, match);
+		}
+
+		/**
+		 * @brief match keypoints between two sets using descriptors
+		 * @param keypoints1 first set of keypoints
+		 * @param descriptors1 first set of descriptors
+		 * @param keypoints2 second set of keypoints
+		 * @param descriptors2 second set of descriptors
+		 * @param match matching vector representing associations, pair.first corresponds to v1 and pair.second corresponds to v2
+		 * @return number of valid association in match
+		 */
+		int match(const std::vector<T>& keypoints1, const std::vector<D>& descriptors1, const std::vector<T>& keypoints2, const std::vector<D>& descriptors2, std::vector<std::pair<int, int> >& match) {
+			std::vector<std::pair<int, int> > assoInit;
+			for (int i1 = 0; i1 < keypoints1.size(); ++i1) {
+				for (int i2 = 0; i2 < keypoints2.size(); ++i2) {
+					if (keypoints1[i1].distance(keypoints2[i2]) < distTh && descriptors1[i1].distance(descriptors2[i2]) < descTh) {
+						assoInit.push_back(std::make_pair(i1, i2));
+					}
+				}
+			}
+
+			return getBestMatching(keypoints1, keypoints2, assoInit, match);
+		}
+
+		/** @brief set euclidean distance threshold for keypoints distance measurement*/
+		void setDistanceThreshold(double _th) {
+			distTh = _th;
+		}
+
+		/** @brief set descriptor threshold for distance measurement*/
+		void setDescriptorThreshold(double _th) {
+			descTh = _th;
+		}
+
+
+
+	private:
+		double distTh;
+		double descTh;
+		double xRes;
+		double yRes;
+		double thetaRes;
+		double xAbsMax;
+		double yAbsMax;
+		double thetaAbsMax;
+		int xSize;
+		int ySize;
+		int thetaSize;
+		std::vector<std::vector<std::pair<int, int> > > matchesGrid;
+		//		std::vector<int> countGrid;
+		int txMax;
+		int tyMax;
+		int thetaMax;
+
+		/** @brief get grid index from separated transform indexes*/
+		int getGridIndex(int ix, int iy, int it) {
+			return ix + iy * xSize + it * xSize * ySize;
+		}
+
+		/** @brief get best matching given point and an initial guest associations list*/
+		int getBestMatching(const std::vector<T>& v1, const std::vector<T>& v2, const std::vector<std::pair<int, int> >& init, std::vector<std::pair<int, int> >& match) {
+			for (auto& asso : init) {
+				for (int it = 0; it < thetaSize; ++it) {
+					double theta = thetaRes * (it - thetaSize / 2);
+					const Point2d& p1 = v1[asso.first].point;
+					const Point2d& p2 = v2[asso.second].point;
+					double tx = p1[0] - p2[0] * std::cos(theta) + p2[1] * std::sin(theta);
+					double ty = p1[1] - p2[0] * std::sin(theta) - p2[1] * std::cos(theta);
+
+					int ix = static_cast<int> (tx / xRes + xSize / 2);
+					int iy = static_cast<int> (ty / yRes + ySize / 2);
+
+					if (ix >= 0 && ix < xSize && iy >= 0 && iy < ySize && it >= 0 && it < thetaSize) {
+//						std::cout << "ind: " << getGridIndex(ix, iy, it) << "\t" << ix << "\t" << iy << "\t" << it << "\tpoints: " << p1.transpose() << "\t" << p2.transpose() << std::endl;
+						matchesGrid[getGridIndex(ix, iy, it)].push_back(asso);
+
+						if (matchesGrid[getGridIndex(ix, iy, it)].size() >= matchesGrid[getGridIndex(txMax, tyMax, thetaMax)].size()) {
+							txMax = ix;
+							tyMax = iy;
+							thetaMax = it;
+						}
+					}
+				}
+			}
+
+			match = matchesGrid[getGridIndex(txMax, tyMax, thetaMax)];
+			int numAsso = match.size();
+			for (int i = 0; i < v1.size(); ++i) {
+				bool found = false;
+				for (int j = 0; j < match.size(); ++j) {
+					if (i == match[j].first) {
+						found = true;
+						break;
+					}
+				}
+				if (not found) {
+					match.push_back(std::make_pair(i, -1));
+				}
+			}
+			return numAsso;
+		}
+	};
+}
\ No newline at end of file
diff --git a/include/falkolib/Matching/CCDAMatcher.h b/include/falkolib/Matching/CCDAMatcher.h
new file mode 100644
index 0000000000000000000000000000000000000000..f94abc51b90bb39b4cde4120763e6e235e122286
--- /dev/null
+++ b/include/falkolib/Matching/CCDAMatcher.h
@@ -0,0 +1,235 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <Eigen/Dense>
+#include <iostream>
+#include <falkolib/Matching/Matcher.h>
+#include <mcqd/mcqd.h>
+
+namespace falkolib {
+
+    /** @brief This class implements the Combined Constraint Data Association (CCDA)
+     * proposed by Tim Bailey. The best reference is:
+     *
+     * T. Bailey, "Mobile Robot Localisation and Mapping in Extensive Outdoor Environments", 
+     *  PhD Thesis, University of Sydney, 2002.
+     *
+     * Of course, there are the related papers. 
+     * The method is based on the so called CorrespondenceGraph built on two point sets.
+     * Data Association is computed as the maximum clique CorrespondenceGraph. 
+     *
+     * Maximum clique has been computed according to T. Bailey suggestions.
+     * However, for different approaches see:
+     *  http://www.dharwadker.org/clique/
+     *  http://www.sanfoundry.com/cpp-program-find-maximum-size-clique-graph/
+     *  http://www.sicmm.org/~konc/maxclique/mcqd/mcqd.h
+     */
+    template <typename T = Keypoint, typename D = Descriptor>
+    class CCDAMatcher : public Matcher<T> {
+    public:
+
+        /** Node of correspondence graph represents an association 
+         * between an input point and a target point. 
+         */
+        struct Node {
+            int index; // global index (that should correspond to position in nodes vector)
+            int inputId; // input point ID
+            int targetId; // target point ID
+            std::vector<int> adjacents;
+
+            bool operator<(const Node& n) const {
+                return (index < n.index);
+            }
+
+            int degree() const {
+                return adjacents.size();
+            }
+        };
+
+        /** Distance constraint between the point belonging to the same set.
+         */
+        struct Constraint {
+            int i;
+            int j;
+            double dist;
+
+            bool operator<(const Constraint& c) const {
+                return (dist < c.dist);
+            }
+        };
+
+        /** @brief Default constructor. */
+        CCDAMatcher() : distTol(0.10), distMin(0.0) {
+        }
+
+        /** @brief Sets the tolerance on distances differences to be compatible. See CCDA details. */
+        void setDistTol(double _distTol) {
+            distTol = _distTol;
+        }
+
+        /** @brief Sets the minimum distance between two keypoints to be a constraint. */
+        void setDistMin(double _distMin) {
+            distMin = _distMin;
+        }
+
+        /** Computes the value 
+         */
+        int match(const std::vector<T>& v1, const std::vector<T>& v2, std::vector<std::pair<int, int> >& match) {
+            std::vector<Node> nodes;
+            std::vector<std::pair<int, int> > edges;
+            std::vector<Constraint> constraints1;
+            std::vector<Constraint> constraints2;
+            Constraint constrTmp;
+            std::vector<int> cliqueMax;
+            int num1 = v1.size();
+            int num2 = v2.size();
+            int isrc, idst;
+
+            match.clear();
+            // Creates constraints inside each group of keypoints.
+            // A constraint is the geometric distance (must be > distMin!) between two internal keypoints of a given set.
+            makeRelativeConstraints(v1, constraints1);
+            makeRelativeConstraints(v2, constraints2);
+
+            // Creates correspondence graph based on constraints:
+            // * node: association hypothesis n=(k1,k2) where k1 in set1, k2 in set2;
+            // * edge: connects 2 compatible association hypotheses (compatibility (na,nb) if ||na.k1-na.k2| - |nb.k1-nb.k2|| < distToll);
+
+            // Nodes
+            makeNodeSet(v1, v2, nodes);
+
+            // Edges
+            for (auto& constrCurr : constraints1) {
+                // Finds the candidate target constraints, i.e. pair of target points with similar 
+                // distance, and visits them 
+                constrTmp.dist = constrCurr.dist - distTol;
+                typename std::vector<Constraint>::iterator it = std::upper_bound(constraints2.begin(), constraints2.end(), constrTmp);
+                for (; it != constraints2.end() && it->dist < constrCurr.dist + distTol; ++it) {
+                    //std::cout << "  target constr (" << it->i << "," << it->j << "): " << it->dist << std::endl;
+                    if (std::abs(it->dist - constrCurr.dist) < distTol && (it->dist + constrCurr.dist) > distMin) {
+                        assert(constrCurr.i < num1 && constrCurr.j < num1);
+                        assert(it->i < num2 && it->j < num2);
+                        // Match 1
+                        isrc = it->i + constrCurr.i * num2;
+                        idst = it->j + constrCurr.j * num2;
+                        assert(isrc < nodes.size() && idst < nodes.size());
+                        assert(nodes[isrc].inputId == constrCurr.i && nodes[isrc].targetId == it->i);
+                        assert(nodes[idst].inputId == constrCurr.j && nodes[idst].targetId == it->j);
+                        nodes[isrc].adjacents.push_back(idst);
+                        nodes[idst].adjacents.push_back(isrc);
+                        // Match 2
+                        isrc = it->i + constrCurr.j * num2;
+                        idst = it->j + constrCurr.i * num2;
+                        assert(isrc < nodes.size() && idst < nodes.size());
+                        assert(nodes[isrc].inputId == constrCurr.j && nodes[isrc].targetId == it->i);
+                        assert(nodes[idst].inputId == constrCurr.i && nodes[idst].targetId == it->j);
+                        nodes[isrc].adjacents.push_back(idst);
+                        nodes[idst].adjacents.push_back(isrc);
+                    }
+                }
+            }
+
+            // Finds maximum clique
+            findCliqueDyn(nodes, cliqueMax);
+            match.reserve(cliqueMax.size());
+            for (auto& id : cliqueMax) {
+                match.push_back(std::make_pair(nodes[id].inputId, nodes[id].targetId));
+            }
+        }
+
+    private:
+        double distTol;
+        double distMin;
+
+        void makeNodeSet(const std::vector<T>& points1, const std::vector<T>& points2, std::vector<Node>& nodes) {
+            Node corresp;
+            int index;
+            nodes.clear();
+            nodes.resize(points1.size() * points2.size());
+            for (int i = 0; i < points1.size(); ++i) {
+                for (int j = 0; j < points2.size(); ++j) {
+                    index = i * points2.size() + j;
+                    nodes[index].inputId = i;
+                    nodes[index].targetId = j;
+                    nodes[index].index = index;
+                    nodes[index].adjacents.clear();
+                }
+            }
+            //      for (int i = 0; i < nodes.size(); ++i) {
+            //        if (nodes[i].index != i) {
+            //          std::cerr << __PRETTY_FUNCTION__ << ": difference bewteen node index " << nodes[i].index << " and its position " << i << " in node vector" << std::endl;
+            //        }
+            //      }
+        }
+
+        void makeRelativeConstraints(const std::vector<T>& points, std::vector<Constraint>& constraints) {
+            Constraint constraint;
+            int n = points.size();
+            for (int i = 0; i < n; ++i) {
+                for (int j = i + 1; j < n; ++j) {
+                    constraint.i = i;
+                    constraint.j = j;
+                    constraint.dist = points[i].distance(points[j]);
+                    constraints.push_back(constraint);
+                }
+            }
+            std::sort(constraints.begin(), constraints.end());
+        }
+
+        void findCliqueDyn(const std::vector<Node>& nodes, std::vector<int>& cliqueMax) {
+            bool **conn;
+            int nsize = nodes.size();
+            int *qmax;
+            int qsize;
+
+            if (nsize == 0) {
+                return;
+            }
+
+            // Allocates space for adjacence matrix 
+            conn = new bool*[nsize];
+            for (int i = 0; i < nsize; ++i) {
+                conn[i] = new bool[nsize];
+                memset(conn[i], 0, nsize * sizeof (bool));
+            }
+            // Fills adjacence matrix
+            for (int i = 0; i < nodes.size(); ++i) {
+                assert(nodes[i].index == i);
+                for (auto& j : nodes[i].adjacents) {
+                    conn[i][j] = true;
+                }
+            }
+            // Computes maximum clique
+            Maxclique maxcl(conn, nsize);
+            maxcl.mcq(qmax, qsize);
+            cliqueMax.resize(qsize);
+            for (int i = 0; i < qsize; ++i) {
+                cliqueMax[i] = qmax[i];
+            }
+
+            delete [] qmax;
+            for (int i = 0; i < nsize; ++i)
+                delete [] conn[i];
+            delete [] conn;
+        }
+
+    };
+}
diff --git a/include/falkolib/Matching/Matcher.h b/include/falkolib/Matching/Matcher.h
new file mode 100644
index 0000000000000000000000000000000000000000..cace20b196fc4201b66d42da2c6a3064a4327cea
--- /dev/null
+++ b/include/falkolib/Matching/Matcher.h
@@ -0,0 +1,42 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <vector>
+
+namespace falkolib {
+	
+	/**
+	 * @brief class representing a simple feature matching engine 
+	 */
+	template <typename T>
+	class Matcher {
+	protected:
+		
+		/**
+		 * @brief match features between two sets
+		 * @param v1 first set of features
+		 * @param v2 second set of features
+		 * @param match matching vector representing associations, pair.first corresponds to v1 and pair.second corresponds to v2
+		 * @return number of valid association in match
+		 */
+		virtual int match(const std::vector<T>& v1, const std::vector<T>& v2, std::vector<std::pair<int, int> >& match) = 0;
+	};
+}
\ No newline at end of file
diff --git a/include/falkolib/Matching/NNMatcher.h b/include/falkolib/Matching/NNMatcher.h
new file mode 100644
index 0000000000000000000000000000000000000000..acda421e2cb95c6b536a43afdbf16a504aa08752
--- /dev/null
+++ b/include/falkolib/Matching/NNMatcher.h
@@ -0,0 +1,136 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <falkolib/Matching/Matcher.h>
+
+#include <vector>
+#include <falkolib/Feature/Descriptor.h>
+#include <falkolib/Feature/Keypoint.h>
+
+namespace falkolib {
+
+	/**
+	 * @brief class representing a simple Nearest-Neighborhood feature matching engine 
+	 */
+	template <typename T = Keypoint, typename D = Descriptor>
+	class NNMatcher : public Matcher<T> {
+	public:
+
+		/**
+		 * @brief Constructor
+		 */
+		NNMatcher() {
+
+		};
+
+		/**
+		 * @brief match keypoints or descriptors between two sets
+		 * @param v1 first set of keypoints or descriptors
+		 * @param v2 second set of keypoints or descriptors
+		 * @param match matching vector representing associations, pair.first corresponds to v1 and pair.second corresponds to v2
+		 * @return number of valid association in match
+		 */
+		int match(const std::vector<T>& v1, const std::vector<T>& v2, std::vector<std::pair<int, int> >& match) {
+			match.clear();
+			int imin;
+			double dmin, d;
+			int counter = 0;
+			std::vector<bool> matched(v2.size(), false);
+			for (int i1 = 0; i1 < (int) v1.size(); ++i1) {
+				imin = -1;
+				dmin = 1.05 * distTh;
+				for (int i2 = 0; i2 < (int) v2.size(); ++i2) {
+					if (not matched[i2]) {
+						d = v1[i1].distance(v2[i2]);
+						if (d < dmin) {
+							imin = i2;
+							dmin = d;
+						}
+					}
+				}
+				if (dmin < distTh) {
+					match.push_back(std::make_pair(i1, imin));
+					matched[imin] = true;
+					counter++;
+				} else {
+					match.push_back(std::make_pair(i1, -1));
+				}
+			}
+
+			return counter;
+		}
+
+		/**
+		 * @brief match keypoints between two sets using descriptors
+		 * @param keypoints1 first set of keypoints
+		 * @param descriptors1 first set of descriptors
+		 * @param keypoints2 second set of keypoints
+		 * @param descriptors2 second set of descriptors
+		 * @param match matching vector representing associations, pair.first corresponds to v1 and pair.second corresponds to v2
+		 * @return number of valid association in match
+		 */
+		int match(const std::vector<T>& keypoints1, const std::vector<D>& descriptors1, const std::vector<T>& keypoints2, const std::vector<D>& descriptors2, std::vector<std::pair<int, int> >& match) {
+			match.clear();
+			int imin;
+			double dmin, d, ddesc;
+			int counter = 0;
+			std::vector<bool> matched(keypoints2.size(), false);
+			for (int i1 = 0; i1 < (int) keypoints1.size(); ++i1) {
+				imin = -1;
+				dmin = 1.05 * distTh;
+				for (int i2 = 0; i2 < (int) keypoints2.size(); ++i2) {
+					if (not matched[i2]) {
+						d = keypoints1[i1].distance(keypoints2[i2]);
+						ddesc = descriptors1[i1].distance(descriptors2[i2]);
+						if (d < dmin && ddesc < descTh) {
+							imin = i2;
+							dmin = d;
+						}
+					}
+				}
+				if (dmin < distTh && descriptors1[i1].distance(descriptors2[imin]) < descTh) {
+					match.push_back(std::make_pair(i1, imin));
+					matched[imin] = true;
+					counter++;
+				} else {
+					match.push_back(std::make_pair(i1, -1));
+				}
+			}
+
+			return counter;
+		}
+
+		/** @brief set euclidean distance threshold for keypoints distance measurements*/
+		void setDistanceThreshold(double _th) {
+			distTh = _th;
+		}
+
+		/** #brief set descriptor threshold for distance measurements*/
+		void setDescriptorThreshold(double _th) {
+			descTh = _th;
+		}
+
+	private:
+		double distTh;
+		double descTh;
+
+	};
+}
\ No newline at end of file
diff --git a/src/Common/HoughSpectrum.cpp b/src/Common/HoughSpectrum.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cb2a1479144ccde986bfc63180d3d8e78299187a
--- /dev/null
+++ b/src/Common/HoughSpectrum.cpp
@@ -0,0 +1,74 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <falkolib/Common/HoughSpectrum.h>
+#include <cassert>
+
+using namespace std;
+
+namespace falkolib {
+
+    HoughSpectrum::HoughSpectrum()
+    : thetaNum_(360),
+    rhoNum_(1000),
+    thetaStep_(0.0087266), rhoStep_(0.02),
+    hough_(thetaNum_, rhoNum_),
+    spectrum_(thetaNum_),
+    orthoSpectrum_((thetaNum_ / 2) + (thetaNum_ % 2)),
+    cosLut_(thetaNum_), sinLut_(thetaNum_) {
+        for (unsigned int i = 0; i < thetaNum_; ++i) {
+            cosLut_(i) = cos(thetaStep_ * i);
+            sinLut_(i) = sin(thetaStep_ * i);
+        }
+    }
+
+    HoughSpectrum::HoughSpectrum(double thetaStep, double rhoStep, double rhoMax)
+    : thetaNum_(static_cast<unsigned int> (ceil(M_PI / thetaStep))),
+    rhoNum_(2 * static_cast<unsigned int> (ceil(rhoMax / rhoStep))),
+    thetaStep_(thetaStep), rhoStep_(rhoStep),
+    hough_(thetaNum_, rhoNum_),
+    spectrum_(thetaNum_),
+    orthoSpectrum_((thetaNum_ / 2) + (thetaNum_ % 2)),
+    cosLut_(thetaNum_), sinLut_(thetaNum_) {
+        for (unsigned int i = 0; i < thetaNum_; ++i) {
+            cosLut_(i) = cos(thetaStep_ * i);
+            sinLut_(i) = sin(thetaStep_ * i);
+        }
+    }
+
+    void HoughSpectrum::init(double thetaStep, double rhoStep, double rhoMax) {
+        thetaStep_ = thetaStep;
+        rhoStep_ = rhoStep;
+        thetaNum_ = (unsigned int) ceil(M_PI / thetaStep);
+        rhoNum_ = (unsigned int) ceil(rhoMax / rhoStep);
+
+        hough_.resize(thetaNum_, rhoNum_);
+        spectrum_.resize(thetaNum_);
+        orthoSpectrum_.resize(thetaNum_ / 2);
+        cosLut_.resize(thetaNum_);
+        sinLut_.resize(thetaNum_);
+
+        for (unsigned int i = 0; i < thetaNum_; ++i) {
+            cosLut_(i) = cos(thetaStep_ * i);
+            sinLut_(i) = sin(thetaStep_ * i);
+        }
+    }
+
+} // end of namespace
+
diff --git a/src/Feature/BSC.cpp b/src/Feature/BSC.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..98f73d8546f759b8073d32f66951da03b0074ba1
--- /dev/null
+++ b/src/Feature/BSC.cpp
@@ -0,0 +1,85 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <falkolib/Feature/BSC.h>
+#include <falkolib/Common/GeomUtils.h>
+#include <limits>
+#include <math.h>
+#include <assert.h>
+#include <algorithm>
+
+using namespace std;
+
+namespace falkolib {
+
+	BSC::BSC(double _radius, int _circularSectorNumber, int _radialRingNumber) {
+		radius = _radius;
+		circularSectorNumber = _circularSectorNumber;
+		sectorResolution = 2.0 * M_PI / circularSectorNumber;
+		radialRingNumber = _radialRingNumber;
+		ringResolution = radius / radialRingNumber;
+	}
+
+	void BSC::compute(std::vector<Point2d>& neigh, int centralPointIndex) {
+		const int size = neigh.size();
+		grid.resize(radialRingNumber, std::vector<uint8_t>(circularSectorNumber, 0));
+		for (int i = 0; i < size; ++i) {
+			if (i != centralPointIndex) {
+				int col = static_cast<int> (floor((angleBetweenPoints(neigh[i], neigh[centralPointIndex]) + M_PI) / sectorResolution));
+				assert(col < circularSectorNumber);
+				int row = static_cast<int> (floor(((neigh[i] - neigh[centralPointIndex]).norm()) / ringResolution));
+				assert(row < radialRingNumber);
+				grid[row][col] = 1;
+			}
+		}
+	}
+
+	double BSC::distance(const Descriptor& desc) const{
+		try {
+			const BSC& d2 = dynamic_cast<const BSC&> (desc);
+			assert(circularSectorNumber == d2.circularSectorNumber);
+			assert(radialRingNumber == d2.radialRingNumber);
+			if (circularSectorNumber == d2.circularSectorNumber && radialRingNumber == d2.radialRingNumber) {
+				return HammingDistance(grid, d2.grid);
+			}
+		} catch (const std::bad_cast& e){
+			;
+		}
+		return numeric_limits<double>::max();
+	}
+
+	double BSC::HammingDistance(const std::vector<std::vector<uint8_t> >& g1, const std::vector<std::vector<uint8_t> >& g2) const {
+		double diff = 0.0;
+		for (int i = 0; i < g1.size(); ++i) {
+			for (int j = 0; j < g1[i].size(); ++j) {
+				if (g1[i][j] != g2[i][j]) {
+					diff++;
+				}
+			}
+		}
+		return diff;
+	}
+
+	void BSC::rotate(double theta) {
+		int rot = static_cast<int> (floor((theta + M_PI) / sectorResolution)) % circularSectorNumber;
+		for (auto& i : grid) {
+			std::rotate(i.begin(), i.begin() + rot, i.end());
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/Feature/CGH.cpp b/src/Feature/CGH.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e551bb1f09df522a9fa9d137c7bc75e24a682c8d
--- /dev/null
+++ b/src/Feature/CGH.cpp
@@ -0,0 +1,93 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <falkolib/Feature/CGH.h>
+#include <falkolib/Common/GeomUtils.h>
+#include <limits>
+#include <math.h>
+#include <assert.h>
+#include <algorithm>
+
+#include <iostream>
+
+using namespace std;
+
+namespace falkolib {
+
+	CGH::CGH(double _radius, int _circularSectorNumber) {
+		radius = _radius;
+		circularSectorNumber = _circularSectorNumber;
+		sectorResolution = 2.0 * M_PI / circularSectorNumber;
+	}
+
+	void CGH::compute(std::vector<Point2d>& neigh, int centralPointIndex) {
+		const int size = neigh.size();
+		histogram.resize(circularSectorNumber, 0);
+		for (int i = 0; i < size; ++i) {
+			if (i != centralPointIndex) {
+				int ind = static_cast<int> (floor((angleBetweenPoints(neigh[i], neigh[centralPointIndex]) + M_PI) / sectorResolution));
+				assert(ind < circularSectorNumber);
+				if (ind == 0) {
+					histogram[circularSectorNumber - 1]++;
+				} else {
+					histogram[ind - 1]++;
+				}
+				histogram[ind] += 5;
+				if (ind == (circularSectorNumber - 1)) {
+					histogram[0]++;
+				} else {
+					histogram[ind + 1]++;
+				}
+			}
+		}
+		double sum = 0;
+		for (auto& l : histogram) {
+			sum += l;
+		}
+		for (auto& l : histogram) {
+			l /= sum;
+		}
+	}
+
+	double CGH::distance(const Descriptor& desc) const {
+		try {
+			const CGH& d2 = dynamic_cast<const CGH&> (desc);
+			assert(circularSectorNumber == d2.circularSectorNumber);
+			if (circularSectorNumber == d2.circularSectorNumber) {
+				return SymmetricChiSquaredDistance(histogram, d2.histogram);
+			}
+		} catch (const std::bad_cast& e){
+			;
+		}
+		return numeric_limits<double>::max();
+	}
+
+	double CGH::SymmetricChiSquaredDistance(const std::vector<double>& h1, const std::vector<double>& h2) const {
+		double sum1 = 0.0;
+		for (int i = 0; i < h1.size(); ++i) {
+			sum1 += ((h1[i] - h2[i])*(h1[i] - h2[i]) / (h1[i] + h2[i] + 0.00000001));
+		}
+		return sum1/2.0;
+	}
+
+	void CGH::rotate(double theta) {
+		int rot = (static_cast<int> (floor((theta + M_PI) / sectorResolution)) % circularSectorNumber);
+		std::rotate(histogram.begin(), histogram.begin()+rot, histogram.end());
+	}
+}
\ No newline at end of file
diff --git a/src/Feature/FALKOExtractor.cpp b/src/Feature/FALKOExtractor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9abe9417ba857325cdb05e9eff266fbda0222320
--- /dev/null
+++ b/src/Feature/FALKOExtractor.cpp
@@ -0,0 +1,331 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <falkolib/Feature/FALKOExtractor.h>
+
+using namespace std;
+
+namespace falkolib {
+
+    FALKOExtractor::FALKOExtractor() {
+        minScoreTh = 50;
+        minExtractionRange = 0;
+        maxExtractionRange = 30;
+        subbeam = true;
+        NMSRadius = 0.1;
+        neighA = 0.1;
+        neighB = 0.07;
+        neighMinPoint = 2;
+        bRatio = 2.5;
+        gridSectors = 16;
+    }
+
+    void FALKOExtractor::extract(const LaserScan& scan, std::vector<FALKO>& keypoints) {
+        const int numBeams = scan.getNumBeams();
+        vector<int> scores(numBeams, -10);
+        vector<Point2d> neigh;
+        vector<double> radius(numBeams);
+        int neighSize;
+        int neighSizeL;
+        int neighSizeR;
+        int midIndex;
+        double triangleBLength;
+        double triangleHLength;
+        vector<double> thetaCorner(numBeams);
+        int scoreL;
+        int scoreR;
+        int scoreMax = 0;
+        vector<int> peaks;
+        vector<int> neighCircularIndexesL;
+        vector<int> neighCircularIndexesR;
+
+        for (int ind = 0; ind < numBeams; ++ind) {
+            if (scan.ranges[ind] < minExtractionRange || scan.ranges[ind] > maxExtractionRange) {
+                scores[ind] = -10;
+                continue;
+            }
+            neigh.clear();
+            radius[ind] = getNeighRadius(scan.ranges[ind]);
+            scan.getNeighPoints(ind, radius[ind], neigh, midIndex);
+            neighSize = neigh.size();
+
+            neighSizeL = midIndex;
+            neighSizeR = neighSize - midIndex - 1;
+
+            if (neighSizeL < neighMinPoint || neighSizeR < neighMinPoint) {
+                scores[ind] = -10;
+                continue;
+            }
+
+            triangleBLength = pointsDistance(neigh.front(), neigh.back());
+            triangleHLength = std::abs(signedTriangleArea(neigh[midIndex], neigh.front(), neigh.back())) / triangleBLength;
+
+            if (triangleBLength < (radius[ind] / bRatio) || triangleHLength < (radius[ind] / bRatio)) {
+                scores[ind] = -10;
+                continue;
+            }
+
+            thetaCorner[ind] = getCornerOrientation(neigh, midIndex);
+
+            neighCircularIndexesL.resize(neighSizeL, 0);
+            neighCircularIndexesR.resize(neighSizeR, 0);
+
+            for (int i = 0; i < neighSizeL; ++i) {
+                neighCircularIndexesL[i] = getCircularSectorIndex(neigh[i], neigh[midIndex], thetaCorner[ind]);
+            }
+            for (int i = 0; i < neighSizeR; ++i) {
+                neighCircularIndexesR[i] = getCircularSectorIndex(neigh[midIndex + i + 1], neigh[midIndex], thetaCorner[ind]);
+            }
+
+            scoreL = 0;
+            scoreR = 0;
+
+            for (int i = midIndex - 1; i >= 0; --i) {
+                for (int j = i; j >= 0; --j) {
+                    scoreL += circularSectorDistance(neighCircularIndexesL[i], neighCircularIndexesL[j], gridSectors);
+                }
+            }
+
+            for (int i = midIndex + 1; i < neighSize; ++i) {
+                for (int j = i; j < neighSize; ++j) {
+                    scoreR += circularSectorDistance(neighCircularIndexesR[i - midIndex - 1], neighCircularIndexesR[j - midIndex - 1], gridSectors);
+                }
+            }
+
+            scores[ind] = scoreL + scoreR;
+
+            if (scores[ind] > scoreMax) {
+                scoreMax = scores[ind];
+            }
+        }
+
+        for (int ind = 0; ind < numBeams; ++ind) {
+            if (scores[ind] < 0) {
+                scores[ind] = scoreMax;
+            }
+            scores[ind] = scoreMax - scores[ind];
+        }
+
+        NMSKeypoint(scores, scan, 0, numBeams, NMSRadius, (scoreMax * minScoreTh / 100.0), peaks);
+
+        for (int i = 0; i < peaks.size(); ++i) {
+            FALKO kp;
+            kp.index = peaks[i];
+            kp.orientation = thetaCorner[peaks[i]];
+            kp.radius = radius[peaks[i]];
+
+            if (subbeam) {
+                subBeamCorner(scan, peaks[i], radius[peaks[i]], kp.point);
+            } else {
+                kp.point = scan.points[peaks[i]];
+            }
+
+            keypoints.push_back(std::move(kp));
+        }
+
+    }
+
+    int FALKOExtractor::circularSectorDistance(int a1, int a2, int res) {
+        const int r2 = res / 2;
+        return std::abs(((a1 - a2) + r2) % res - r2);
+    }
+
+    int FALKOExtractor::getCircularSectorIndex(const Point2d& p, const Point2d& pmid, double theta) {
+        return (int) floor((angleBetweenPoints(p, pmid) + M_PI - theta) / (2.0 * M_PI / gridSectors));
+    }
+
+    double FALKOExtractor::getNeighRadius(double rho) {
+        double radius = neighA * std::exp(neighB * rho);
+        if (radius >= rho) {
+            return rho * 0.8;
+        }
+        return radius;
+    }
+
+    double FALKOExtractor::getCornerOrientation(const std::vector<Point2d>& neigh, int midIndex) {
+        Point2d oriL(0, 0);
+        Point2d oriR(0, 0);
+        int size = neigh.size();
+        for (int i = 0; i < size; ++i) {
+            if (i < midIndex) {
+                oriL += (neigh[i] - neigh[midIndex]); // / (s[i] - s[mid]).norm();
+            } else if (i > midIndex) {
+                oriR += (neigh[i] - neigh[midIndex]); // / (s[i] - s[mid]).norm();
+            }
+        }
+        oriL /= midIndex;
+        oriR /= (size - (midIndex + 1));
+        Point2d ori = oriL + oriR;
+        double theta = atan2(ori(1), ori(0));
+    }
+
+    void FALKOExtractor::NMSKeypoint(const std::vector<int>& scores, const LaserScan& scan, unsigned int ibeg, unsigned int iend, double radius, int minval, std::vector<int>& peaks) {
+        unsigned i, imax;
+        unsigned j, jbeg, jend, jmax;
+        std::vector<int> candidates;
+        peaks.clear();
+
+        i = ibeg;
+        imax = ibeg;
+        while (i < iend) {
+            int win;
+            if (radius >= scan.ranges[i]) {
+                win = std::floor(std::asin(0.8) / scan.getAngleInc());
+            } else {
+                win = std::floor(std::asin(radius / scan.ranges[i]) / scan.getAngleInc());
+            }
+
+            jmax = i;
+
+            if (imax + win < i) {
+                jbeg = (i >= win ? i - win : 0);
+                imax = i;
+            } else {
+                jbeg = i;
+            }
+
+            jend = (i + win + 1 < iend ? i + win + 1 : iend);
+            for (j = jbeg; j < jend; ++j) {
+                if (scores[j] > scores[jmax]) {
+                    jmax = j;
+                }
+            }
+            imax = (scores[jmax] >= scores[imax] ? jmax : imax);
+
+            if (i == imax && scores[i] > minval) {
+                candidates.push_back(i);
+            }
+            if (jmax > i) i = jmax;
+            else ++i;
+        }
+
+        int i1 = 0;
+        int i2 = 0;
+        int counter = 0;
+
+        for (i1 = 0, i2 = 0; i1 < candidates.size(); ++i1) {
+            if (scores[candidates[i2]] == scores[candidates[i1]]) {
+                counter++;
+                if (2 * abs(i2 - i1) > counter) {
+                    ++i2;
+                }
+            } else {
+                peaks.push_back(candidates[i2]);
+                i2 = i1;
+                counter = 0;
+            }
+        }
+        if (i2 != candidates.size()) {
+            peaks.push_back(candidates[i2]);
+        }
+    }
+
+    void FALKOExtractor::subBeamCorner(const LaserScan& scan, int index, double radius, Point2d& p) {
+        vector<Point2d> neigh;
+        int midIndex;
+        scan.getNeighPoints(index, radius, neigh, midIndex);
+        int neighSize = neigh.size();
+
+        Eigen::Vector3d leftLine;
+        Eigen::Vector3d rightLine;
+
+        std::vector<Point2d> leftSide;
+        for (int i = 0; i <= midIndex; ++i) {
+            leftSide.push_back(neigh[i]);
+        }
+
+        std::vector<Point2d> rightSide;
+        for (int i = midIndex; i < neighSize; ++i) {
+            rightSide.push_back(neigh[i]);
+        }
+
+        generateLine(leftSide, leftLine);
+        generateLine(rightSide, rightLine);
+
+        double A[4];
+        double b[2];
+        double x[2];
+        A[0] = leftLine[0];
+        A[1] = leftLine[1];
+        A[2] = rightLine[0];
+        A[3] = rightLine[1];
+
+        b[0] = -leftLine[2];
+        b[1] = -rightLine[2];
+
+        bool valid = solveSystem2x2(A, b, x);
+
+        if (not valid) {
+            p = neigh[midIndex];
+            return;
+        }
+
+        Point2d temp(x[0], x[1]);
+
+        if (pointsDistance(neigh[midIndex], temp) < 0.20) {
+            p = temp;
+        } else {
+            p = neigh[midIndex];
+        }
+    }
+
+    void FALKOExtractor::generateLine(const std::vector<Point2d>& points, Eigen::Vector3d& model) {
+        double sxx = 0.0;
+        double syy = 0.0;
+        double sxy = 0.0;
+        double sx = 0.0;
+        double sy = 0.0;
+        int num = 0;
+        for (unsigned int i = 0; i < points.size(); ++i) {
+            sxx += points[i](0) * points[i](0);
+            syy += points[i](1) * points[i](1);
+            sxy += points[i](0) * points[i](1);
+            sx += points[i](0);
+            sy += points[i](1);
+            ++num;
+        }
+
+        double msxx = (sxx - sx * sx / num) / num;
+        double msyy = (syy - sy * sy / num) / num;
+        double msxy = (sxy - sx * sy / num) / num;
+        double b = 2.0 * msxy;
+        double a = msxx;
+        double c = msyy;
+        double theta = 0.5 * (atan2(b, a - c) + M_PI);
+        theta = atan2(sin(theta), cos(theta));
+        double rho = (sx * cos(theta) + sy * sin(theta)) / num;
+
+        if (rho < 0) {
+            theta = atan2(sin(theta + M_PI), cos(theta + M_PI));
+            rho = -rho;
+        }
+        model(0) = cos(theta);
+        model(1) = sin(theta);
+        model(2) = -rho;
+    }
+
+    bool FALKOExtractor::solveSystem2x2(double* A, double* b, double* x) {
+        double det = A[0] * A[3] - A[1] * A[2];
+        if (std::abs(det) < 0.0000001)
+            return false;
+        x[0] = (b[0] * A[3] - A[1] * b[1]) / det;
+        x[1] = (A[0] * b[1] - b[0] * A[2]) / det;
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/src/Feature/OCExtractor.cpp b/src/Feature/OCExtractor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4fce6c24a93f67c48be146759fea6f10774cf3cb
--- /dev/null
+++ b/src/Feature/OCExtractor.cpp
@@ -0,0 +1,293 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <falkolib/Feature/OCExtractor.h>
+#include <cassert>
+
+using namespace std;
+
+namespace falkolib {
+
+    OCExtractor::OCExtractor()
+    //: houghSpectrum((M_PI / 180.0) * 0.5, 0.02, 10.0) {
+    {
+        tol = 0.1;
+        angleRes = (M_PI / 180.0) * 0.5;
+        rangeRes = 0.02;
+        rangeMax = 10.0;
+        nmsRadius = 0.1;
+        neighA = 0.1;
+        neighB = 0.07;
+        neighMinPoint = 2;
+        houghSpectrum.init(angleRes, rangeRes, rangeMax);
+    }
+
+    void OCExtractor::extract(const LaserScan& scan, std::vector<OC>& keypoints) {
+        std::vector<Point2d> pointRot;
+        std::vector<OC> keypointCandidates;
+        std::vector<double> scores;
+        std::vector<int> maxima;
+        OC keypoint;
+        double angle, score;
+        int win;
+        Eigen::Affine2d rot2orth, rot2inve;
+        OC kp;
+
+        // Computes dominant orientation angle and rotates the points
+        angle = computeDominantAngle(scan.points);
+        rotatePoints(scan.points, -angle, pointRot);
+//        std::cout << "Rotated " << scan.points.size() << " by angle " << (180.0 / M_PI * angle) << " deg" << std::endl;
+        rot2orth = Eigen::Affine2d::Identity();
+        rot2orth.prerotate(angle);
+        rot2inve = rot2orth.inverse();
+
+        // For each point, computes the corresponding corner and score
+        keypointCandidates.reserve(pointRot.size());
+        scores.reserve(pointRot.size());
+        for (int idx = 0; idx < pointRot.size(); ++idx) {
+            score = computeCornerScore(pointRot, idx, keypoint);
+            keypointCandidates.push_back(keypoint);
+            scores.push_back(score);
+        }
+
+        // Extracts the maxima using non-maxima suppression (NMS)
+        //        assert(scores.size() == scan.getNumBeams();
+        NMSKeypoint(scores, scan, 0, scan.getNumBeams(), nmsRadius, 1.0, maxima);
+
+        keypoints.clear();
+        keypoints.reserve(maxima.size());
+        for (auto& idx : maxima) {
+            kp = keypointCandidates[idx];
+            kp.point = rot2orth * keypointCandidates[idx].point;
+            double a = keypointCandidates[idx].orientation + angle;
+            kp.orientation = atan2(sin(a), cos(a));
+            keypoints.push_back(kp);
+        }
+    }
+
+    void OCExtractor::rotatePoints(const std::vector<Point2d>& pointsIn, double angle, std::vector<Point2d>& pointsOut) {
+        Point2d p;
+        double ct = cos(angle);
+        double st = sin(angle);
+
+        pointsOut.clear();
+        pointsOut.reserve(pointsIn.size());
+        for (int i = 0; i < pointsIn.size(); ++i) {
+            p.x() = pointsIn[i].x() * ct - pointsIn[i].y() * st;
+            p.y() = pointsIn[i].x() * st + pointsIn[i].y() * ct;
+            pointsOut.push_back(p);
+        }
+    }
+
+    double OCExtractor::computeDominantAngle(const std::vector<Point2d>& points) {
+        int maxIdx;
+        double angle;
+
+        houghSpectrum.insertPoint(points.begin(), points.end());
+        houghSpectrum.orthoSpectrum().maxCoeff(&maxIdx);
+        angle = angleRes * maxIdx;
+        return angle;
+    }
+
+    double OCExtractor::computeCornerScore(const std::vector<Point2d>& pointsIn, int index, OC& keypoint) {
+        vector<Point2d> neigh;
+        double range, distNeigh;
+        double score, dx, dy;
+        int midIndex, orientationMax;
+        int neighSize, neighSizeL, neighSizeR;
+        int xnum, ynum;
+        int orientationBin[4] = {0, 0, 0, 0};
+
+        // Computes the neighborhood
+        neigh.clear();
+        getNeighPoints(pointsIn, index, neigh, midIndex, distNeigh);
+
+        // Check if it current point is in the center of the neighbor interval
+        neighSize = neigh.size();
+        neighSizeL = midIndex;
+        neighSizeR = neighSize - midIndex - 1;
+        //        std::cout << __FILE__ << "," << __LINE__ << ": distNeigh " << distNeigh << ", neighSize " << neighSize << ", neighSizeL " << neighSizeL << ", neighSizeR " << neighSizeR << std::endl;
+        if (neighSizeL < neighMinPoint || neighSizeR < neighMinPoint) {
+            //            std::cout << "  unbalanced neighborhood: distNeigh " << distNeigh << ", neighSize " << neighSize << ", neighSizeL " << neighSizeL << ", neighSizeR " << neighSizeR << ", neighMinPoint " << neighMinPoint << std::endl;
+            return 0.0;
+        }
+
+        // Check that the neighborhood has a triangular shape rather than a flat one
+        //        double triangleBLength = pointsDistance(neigh.front(), neigh.back());
+        //        double triangleHLength = std::abs(signedTriangleArea(neigh[midIndex], neigh.front(), neigh.back())) / triangleBLength;
+        //        std::cout << __FILE__ << "," << __LINE__ << ": triangleBLength " << triangleBLength << " > " << (distNeigh / bRatio) << ", triangleHLength " << triangleHLength << ", (distNeigh / bRatio) " << (distNeigh / bRatio) << std::endl;
+        //        if (triangleBLength < (distNeigh / bRatio) || triangleHLength < (distNeigh / bRatio)) {
+        //            return 0.0;
+        //        }
+
+        // Computes the keypoint/corner 
+        keypoint.index = index;
+        keypoint.point.x() = 0.0;
+        keypoint.point.y() = 0.0;
+        keypoint.index = index;
+        keypoint.radius = distNeigh;
+        xnum = 0;
+        ynum = 0;
+        for (auto& np : neigh) {
+            dx = np.x() - pointsIn[index].x();
+            dy = np.y() - pointsIn[index].y();
+            // a. Neighboor pointIn[i] has similar x coordinate and different y coordinate.
+            //    Condition std::abs(dy) < distNeigh means that is inside circle with radius distNeigh.
+            // b. Neighboor pointIn[i] has similar y coordinate and different x coordinate.
+            //    Condition std::abs(dx) < distNeigh means that is inside circle with radius distNeigh.
+            if (std::abs(dx) < tol && tol < std::abs(dy) && std::abs(dy) < distNeigh) {
+                xnum++;
+                keypoint.point.x() += (np.x() - keypoint.point.x()) / xnum;
+                if (dy > 0) {
+                    orientationBin[NE]++; // NE
+                    orientationBin[NW]++; // NW
+                } else {
+                    orientationBin[SW]++; // SW
+                    orientationBin[SE]++; // SE
+                }
+            }
+            if (std::abs(dy) < tol && tol < std::abs(dx) && std::abs(dx) < distNeigh) {
+                ynum++;
+                keypoint.point.y() += (np.y() - keypoint.point.y()) / ynum;
+                if (dx > 0) {
+                    orientationBin[NE]++; // NE
+                    orientationBin[SE]++; // SE
+                } else {
+                    orientationBin[NW]++; // NW
+                    orientationBin[SW]++; // SW
+                }
+            }
+            //            std::cout << "  index " << index << " dx " << dx << ", dy " << dy << ", xnum " << xnum << ", ynum " << ynum << "\n";
+        }
+        if (xnum == 0) {
+            keypoint.point.x() = pointsIn[index].x();
+        }
+        if (ynum == 0) {
+            keypoint.point.y() = pointsIn[index].y();
+        }
+
+        score = 1.0 * (xnum + ynum) / (0.1 + std::abs(xnum - ynum));
+//        if (score > 1.0 || index == 1197 || (1304 <= index && index <= 1305) || (117 <= index && index <= 119)) {
+//            std::cout << __FILE__ << "," << __LINE__ << "\n  index " << index << ", score " << score << ", xnum " << xnum << ", ynum " << ynum
+//                    << "\n  neighSize " << neighSize << ", neighSizeL " << neighSizeL << ", neighSizeR " << neighSizeR << ", neighMinPoint " << neighMinPoint << std::endl;
+//        }
+
+        // Computes keypoint orientation according to maximum of orientationBin[] histogram:
+        // * orientationBin[0]: I   quadrant, 45 deg
+        // * orientationBin[1]: II  quadrant, 135 deg
+        // * orientationBin[2]: III quadrant, 225 deg (or -135 deg)
+        // * orientationBin[3]: IV  quadrant, 315 deg (or -45 deg)
+        orientationMax = 0;
+        for (int i = 1; i < 4; ++i) {
+            if (orientationBin[i] > orientationBin[orientationMax]) {
+                orientationMax = i;
+            }
+        }
+        keypoint.orientation = M_PI * (0.25 + 0.5 * orientationMax);
+        keypoint.orientation = atan2(sin(keypoint.orientation), cos(keypoint.orientation));
+        return score;
+    }
+
+    void OCExtractor::getNeighPoints(const std::vector<Point2d>& pointsIn, int index, std::vector<Point2d>& neigh, int& midIndex, double& dist) const {
+        double range;
+        int imin, imax, win;
+
+        neigh.clear();
+        range = pointsIn[index].norm();
+        dist = neighA * exp(neighB * range);
+        if (range > dist) {
+            win = (int) ceil(asin(dist / range) / angleRes);
+        } else {
+            win = pointsIn.size();
+        }
+        imin = std::max(index - win, 0);
+        imax = std::min(index + win + 1, (int) pointsIn.size());
+        for (int i = imin; i < imax; ++i) {
+            if ((pointsIn[i] - pointsIn[index]).norm() < dist) {
+                neigh.push_back(pointsIn[i]);
+                if (i == index) {
+                    midIndex = neigh.size();
+                }
+            }
+        }
+    }
+
+    void OCExtractor::NMSKeypoint(const std::vector<double>& scores, const LaserScan& scan, unsigned int ibeg, unsigned int iend, double radius, int minval, std::vector<int>& peaks) {
+        unsigned i, imax;
+        unsigned j, jbeg, jend, jmax;
+        std::vector<int> candidates;
+        peaks.clear();
+
+        i = ibeg;
+        imax = ibeg;
+        while (i < iend) {
+            int win;
+            if (radius >= scan.ranges[i]) {
+                win = std::floor(std::asin(0.8) / scan.getAngleInc());
+            } else {
+                win = std::floor(std::asin(radius / scan.ranges[i]) / scan.getAngleInc());
+            }
+
+            jmax = i;
+
+            if (imax + win < i) {
+                jbeg = (i >= win ? i - win : 0);
+                imax = i;
+            } else {
+                jbeg = i;
+            }
+
+            jend = (i + win + 1 < iend ? i + win + 1 : iend);
+            for (j = jbeg; j < jend; ++j) {
+                if (scores[j] > scores[jmax]) {
+                    jmax = j;
+                }
+            }
+            imax = (scores[jmax] >= scores[imax] ? jmax : imax);
+
+            if (i == imax && scores[i] > minval) {
+                candidates.push_back(i);
+            }
+            if (jmax > i) i = jmax;
+            else ++i;
+        }
+
+        int i1 = 0;
+        int i2 = 0;
+        int counter = 0;
+
+        for (i1 = 0, i2 = 0; i1 < candidates.size(); ++i1) {
+            if (scores[candidates[i2]] == scores[candidates[i1]]) {
+                counter++;
+                if (2 * abs(i2 - i1) > counter) {
+                    ++i2;
+                }
+            } else {
+                peaks.push_back(candidates[i2]);
+                i2 = i1;
+                counter = 0;
+            }
+        }
+        if (i2 != candidates.size()) {
+            peaks.push_back(candidates[i2]);
+        }
+    }
+
+}
+
diff --git a/test/testData.cpp b/test/testData.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bce6b18dd853ffa28db4521538110b8e662602bc
--- /dev/null
+++ b/test/testData.cpp
@@ -0,0 +1,24 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+double testRanges[]  = {250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 5.62, 5.591, 5.574, 5.595, 5.59, 5.613, 5.605, 5.619, 5.645, 5.678, 5.645, 5.644, 5.677, 5.684, 5.675, 5.675, 5.681, 5.712, 5.751, 5.742, 5.766, 5.807, 5.801, 5.833, 21.32, 21.829, 23.012, 23.046, 23.089, 23.111, 23.164, 23.182, 22.961, 22.104, 21.701, 18.683, 18.667, 250, 18.106, 250, 2.94, 2.874, 2.834, 2.772, 2.745, 2.732, 2.691, 2.66, 2.632, 2.615, 2.614, 2.565, 2.538, 2.527, 2.523, 2.471, 2.447, 2.441, 2.431, 2.421, 2.421, 2.415, 2.381, 2.354, 2.36, 2.344, 2.342, 2.318, 2.335, 2.27, 2.266, 2.253, 2.251, 2.252, 2.212, 2.209, 2.179, 2.188, 2.189, 2.179, 2.178, 2.151, 2.18, 2.169, 2.162, 2.152, 2.125, 2.122, 2.127, 2.121, 2.114, 2.1, 2.118, 2.115, 2.097, 2.13, 2.155, 2.161, 2.167, 2.163, 2.18, 2.174, 2.174, 2.18, 2.222, 2.236, 2.221, 2.206, 2.237, 2.228, 2.229, 2.23, 2.029, 1.905, 1.875, 1.857, 1.846, 1.845, 1.842, 1.827, 1.825, 1.808, 1.797, 1.799, 1.797, 1.813, 1.816, 1.809, 1.831, 1.833, 1.846, 1.891, 1.976, 2.01, 1.999, 2.006, 1.988, 2.01, 2.021, 1.998, 2.011, 2.008, 2.009, 2.002, 1.998, 1.999, 2.006, 1.98, 1.991, 1.998, 1.998, 1.984, 1.984, 1.992, 1.975, 1.973, 1.99, 1.965, 1.991, 1.935, 1.947, 1.967, 1.99, 2, 1.941, 1.775, 1.649, 1.563, 1.524, 1.527, 1.502, 1.521, 1.501, 1.51, 1.515, 1.521, 1.498, 1.493, 1.486, 1.487, 1.479, 1.475, 1.474, 1.479, 1.498, 1.47, 1.471, 1.508, 1.505, 1.521, 1.582, 1.588, 1.611, 1.604, 1.616, 1.632, 1.643, 1.634, 1.631, 1.668, 1.66, 1.654, 1.683, 1.694, 1.668, 1.691, 1.683, 1.68, 1.686, 1.697, 1.691, 1.706, 1.691, 1.694, 1.71, 1.688, 1.708, 1.7, 1.702, 1.695, 1.674, 1.651, 1.659, 1.649, 1.642, 1.63, 1.574, 1.548, 1.489, 1.481, 1.478, 1.42, 1.408, 1.38, 1.356, 1.359, 1.375, 1.336, 1.35, 1.364, 1.36, 1.363, 1.327, 1.341, 1.309, 1.302, 1.315, 1.31, 1.311, 1.319, 1.329, 1.306, 1.305, 1.319, 1.297, 1.316, 1.313, 1.301, 1.298, 1.308, 1.307, 1.281, 1.287, 1.275, 1.314, 1.296, 1.325, 1.304, 1.298, 1.307, 1.291, 1.282, 1.285, 1.281, 1.279, 1.296, 1.284, 1.265, 1.276, 1.283, 1.279, 1.278, 1.284, 1.287, 1.297, 1.27, 1.265, 1.282, 1.285, 1.277, 1.274, 1.264, 1.267, 1.292, 1.323, 1.403, 1.552, 1.622, 1.568, 1.55, 1.508, 1.561, 1.452, 1.644, 1.625, 1.665, 1.634, 1.547, 1.405, 1.293, 1.275, 1.313, 1.359, 1.326, 1.311, 1.339, 1.397, 1.347, 1.402, 1.306, 1.259, 1.256, 1.287, 1.5, 1.512, 1.483, 1.415, 1.446, 1.353, 1.427, 1.397, 1.535, 1.573, 1.614, 1.592, 1.579, 1.645, 1.581, 1.528, 1.607, 1.635, 1.646, 1.728, 1.731, 1.771, 1.765, 1.781, 1.716, 1.672, 1.604, 1.583, 1.6, 1.592, 1.6, 1.577, 1.593, 1.597, 1.586, 1.539, 1.47, 1.389, 1.314, 1.298, 1.317, 1.306, 1.314, 1.311, 1.317, 1.294, 1.313, 1.337, 1.337, 1.317, 1.324, 1.327, 1.331, 1.328, 1.339, 1.33, 1.342, 1.333, 1.353, 1.319, 1.343, 1.351, 1.377, 1.438, 1.592, 1.662, 1.661, 1.66, 1.677, 1.661, 1.731, 1.774, 1.769, 1.844, 1.828, 1.884, 1.873, 1.894, 1.908, 1.892, 1.884, 1.907, 1.943, 1.915, 1.946, 1.946, 1.953, 1.9, 1.854, 1.85, 1.834, 1.844, 1.805, 1.817, 1.796, 1.795, 1.776, 1.786, 1.792, 1.786, 1.766, 1.786, 1.779, 1.783, 1.768, 1.774, 1.757, 1.741, 1.733, 1.702, 1.659, 1.62, 1.57, 1.578, 1.563, 1.542, 1.547, 1.537, 1.521, 1.544, 1.54, 1.535, 1.523, 1.579, 1.595, 1.598, 1.615, 1.63, 1.635, 1.623, 1.597, 1.621, 1.61, 1.615, 1.709, 2.039, 2.079, 2.065, 2.055, 2.04, 2.048, 2.048, 2.031, 2.053, 2.015, 2.001, 1.996, 1.963, 1.955, 1.911, 1.866, 1.835, 1.788, 1.719, 1.689, 1.653, 1.511, 1.47, 1.475, 1.474, 1.458, 1.48, 1.468, 1.459, 1.468, 1.468, 1.461, 1.468, 1.479, 1.465, 1.453, 1.479, 1.479, 1.48, 1.521, 1.529, 1.541, 1.56, 1.604, 1.627, 1.729, 1.735, 1.771, 1.805, 1.81, 1.828, 1.854, 1.815, 1.848, 1.86, 1.878, 1.885, 1.902, 1.928, 1.923, 1.931, 1.946, 1.958, 1.943, 1.961, 1.981, 1.977, 1.985, 2.005, 2.016, 2.044, 2.031, 2.052, 2.065, 2.071, 2.08, 2.105, 2.105, 2.128, 2.135, 2.149, 2.183, 2.159, 2.186, 2.188, 2.197, 2.207, 2.223, 2.24, 2.256, 2.282, 2.297, 2.311, 2.341, 2.351, 2.383, 2.41, 2.42, 2.45, 2.461, 2.477, 2.511, 2.529, 2.547, 2.571, 2.561, 2.534, 2.552, 2.617, 2.724, 2.812, 2.801, 2.801, 2.789, 2.8, 2.811, 2.81, 2.815, 2.82, 2.84, 2.867, 2.889, 2.901, 2.914, 2.924, 2.946, 3.005, 3.056, 3.051, 3.093, 3.092, 3.14, 3.216, 3.213, 3.2, 3.211, 3.23, 3.242, 3.27, 3.323, 3.357, 3.424, 12.108, 12.065, 12.075, 12.058, 12.023, 12.015, 11.996, 11.981, 11.986, 11.953, 11.959, 11.937, 11.909, 11.903, 11.899, 11.873, 11.882, 11.846, 11.842, 11.808, 11.789, 11.816, 11.815, 11.771, 11.764, 11.766, 11.749, 11.741, 11.732, 11.723, 11.726, 11.707, 11.715, 11.692, 11.7, 11.667, 11.672, 11.673, 11.659, 11.655, 11.654, 11.643, 11.633, 11.64, 11.639, 11.606, 11.619, 11.612, 11.604, 11.608, 11.602, 11.605, 11.593, 11.587, 11.583, 11.581, 11.588, 11.577, 11.567, 11.567, 11.579, 11.577, 11.563, 11.556, 11.41, 11.433, 11.453, 11.558, 11.493, 11.565, 11.568, 11.552, 11.553, 11.56, 11.574, 11.584, 11.561, 11.572, 11.577, 11.568, 11.583, 11.586, 11.586, 11.579, 11.595, 11.591, 11.605, 11.59, 11.616, 11.612, 11.616, 11.631, 11.639, 11.652, 11.654, 11.668, 11.657, 11.651, 11.667, 11.69, 11.688, 11.71, 11.692, 11.712, 11.726, 11.728, 11.736, 11.735, 11.755, 11.77, 11.768, 11.788, 11.791, 11.798, 11.794, 11.814, 11.841, 11.825, 11.856, 11.857, 11.863, 11.906, 11.91, 11.914, 11.931, 11.955, 11.965, 11.97, 11.98, 12.006, 12.016, 12.027, 12.044, 12.067, 12.082, 12.115, 12.129, 12.136, 12.151, 250, 3.819, 3.839, 3.819, 3.848, 3.832, 3.837, 3.839, 3.813, 3.817, 3.811, 3.815, 3.82, 3.873, 3.875, 3.885, 3.884, 3.834, 3.848, 3.824, 3.689, 3.714, 3.636, 3.564, 3.493, 3.423, 3.41, 3.355, 3.323, 3.293, 3.275, 3.226, 3.196, 3.188, 3.145, 3.123, 3.112, 3.093, 3.057, 3.005, 3.002, 3, 2.942, 2.908, 2.888, 2.89, 2.864, 2.848, 2.815, 2.789, 2.79, 2.776, 2.772, 2.772, 2.725, 2.713, 2.704, 2.704, 2.695, 2.695, 2.704, 2.704, 2.712, 2.706, 2.604, 2.562, 2.543, 2.526, 2.48, 2.469, 2.453, 2.441, 2.443, 2.428, 2.401, 2.368, 2.36, 2.349, 2.346, 2.339, 2.314, 2.309, 2.283, 2.277, 2.267, 2.255, 2.264, 2.225, 2.215, 2.194, 2.191, 2.175, 2.172, 2.149, 2.168, 2.142, 2.142, 2.128, 2.08, 2.073, 2.064, 2.068, 2.068, 2.06, 2.062, 2.042, 2.021, 2.002, 2.002, 1.991, 1.986, 1.98, 1.957, 1.981, 1.992, 1.954, 1.937, 1.918, 1.913, 1.895, 1.881, 1.891, 1.879, 1.884, 1.905, 1.886, 1.872, 1.85, 1.852, 1.828, 1.842, 1.835, 1.825, 1.8, 1.821, 1.828, 1.828, 1.831, 1.81, 1.804, 1.779, 1.767, 1.781, 1.768, 1.771, 1.771, 1.759, 1.751, 1.771, 1.761, 1.777, 1.776, 1.776, 1.803, 1.82, 1.838, 1.866, 1.79, 1.728, 1.699, 1.685, 1.671, 1.66, 1.67, 1.656, 1.661, 1.666, 1.652, 1.63, 1.638, 1.641, 1.627, 1.623, 1.635, 1.626, 1.617, 1.613, 1.603, 1.61, 1.61, 1.599, 1.587, 1.584, 1.583, 1.584, 1.579, 1.567, 1.569, 1.56, 1.538, 1.565, 1.542, 1.536, 1.567, 1.544, 1.551, 1.547, 1.516, 1.524, 1.511, 1.523, 1.522, 1.514, 1.516, 1.492, 1.504, 1.509, 1.482, 1.493, 1.485, 1.499, 1.496, 1.482, 1.48, 1.475, 1.473, 1.49, 1.473, 1.482, 1.463, 1.467, 1.459, 1.469, 1.453, 1.455, 1.469, 1.458, 1.468, 1.452, 1.463, 1.449, 1.457, 1.447, 1.439, 1.439, 1.46, 1.439, 1.44, 1.438, 1.435, 1.44, 1.445, 1.426, 1.425, 1.432, 1.427, 1.415, 1.432, 1.424, 1.412, 1.425, 1.428, 1.438, 1.418, 1.423, 1.436, 1.431, 1.426, 1.426, 1.447, 1.419, 1.427, 1.42, 1.43, 1.41, 1.439, 1.409, 1.422, 1.435, 1.435, 1.415, 1.39, 1.4, 1.426, 1.412, 1.419, 1.397, 1.418, 1.403, 1.411, 1.434, 1.414, 1.419, 1.409, 1.427, 1.414, 1.417, 1.417, 1.411, 1.435, 1.409, 1.422, 1.416, 1.432, 1.425, 1.431, 1.423, 1.431, 1.418, 1.439, 1.412, 1.422, 1.428, 1.433, 1.418, 1.434, 1.437, 1.44, 1.432, 1.437, 10.855, 10.857, 10.856, 10.86, 10.881, 10.889, 10.885, 10.873, 10.904, 10.911, 10.921, 10.92, 10.933, 250, 2.356, 2.316, 2.248, 2.195, 2.139, 2.097, 2.063, 2.012, 1.985, 1.924, 1.899, 1.869, 1.824, 1.813, 1.803, 1.763, 1.747, 1.719, 1.709, 1.704, 1.688, 1.639, 1.646, 1.609, 1.588, 1.578, 1.567, 1.549, 1.52, 1.492, 1.506, 1.528, 1.501, 1.532, 1.532, 1.532, 1.531, 1.526, 1.542, 1.542, 1.542, 1.54, 1.538, 1.557, 1.552, 1.55, 1.546, 1.562, 1.553, 1.567, 1.566, 1.566, 1.572, 1.551, 1.591, 1.596, 1.599, 1.593, 1.604, 1.598, 1.595, 1.585, 1.596, 1.62, 1.594, 1.633, 1.631, 1.613, 1.624, 1.63, 1.642, 1.635, 1.654, 1.646, 1.662, 1.648, 1.649, 1.659, 1.658, 1.688, 1.681, 1.688, 1.694, 1.678, 1.695, 1.689, 1.686, 1.704, 1.699, 1.719, 1.724, 1.731, 1.729, 1.734, 1.744, 1.753, 1.75, 1.777, 1.78, 1.773, 1.779, 1.778, 1.776, 1.799, 1.794, 1.813, 1.808, 1.822, 1.808, 1.836, 1.822, 1.835, 1.845, 1.855, 1.856, 1.872, 1.866, 1.888, 1.882, 1.891, 1.913, 1.912, 1.927, 1.916, 1.92, 1.938, 1.934, 1.977, 1.972, 1.974, 1.97, 1.998, 2.001, 2.01, 2.031, 2.022, 2.039, 2.054, 2.044, 2.076, 2.077, 2.105, 2.134, 2.193, 2.2, 2.187, 2.16, 2.184, 2.176, 2.174, 2.161, 2.169, 2.143, 2.148, 2.143, 2.136, 2.118, 2.127, 2.109, 2.141, 2.136, 2.146, 2.131, 2.159, 2.139, 2.167, 2.195, 2.228, 2.215, 2.214, 2.232, 2.25, 2.276, 2.306, 2.305, 2.324, 2.33, 2.342, 2.379, 2.406, 2.426, 2.425, 2.426, 2.446, 2.464, 2.488, 2.519, 2.522, 2.554, 2.559, 2.581, 2.613, 2.634, 2.651, 2.652, 2.684, 2.731, 2.751, 2.761, 2.775, 2.814, 2.842, 2.867, 2.887, 2.922, 2.966, 3.01, 3.118, 3.139, 3.139, 3.147, 3.143, 3.118, 3.123, 3.122, 3.134, 3.154, 3.157, 3.195, 3.221, 3.232, 3.263, 3.306, 3.349, 3.443, 3.489, 3.479, 3.492, 3.505, 3.519, 3.534, 3.607, 3.725, 3.822, 3.886, 3.922, 3.991, 4.063, 4.126, 4.194, 4.253, 4.291, 4.289, 4.293, 4.271, 4.265, 4.251, 4.223, 4.246, 4.243, 4.246, 4.267, 4.242, 4.271, 250, 15.705, 15.89, 16.172, 16.401, 16.571, 16.903, 17.157, 17.337, 17.702, 17.94, 18.313, 18.526, 18.878, 19.159, 19.659, 19.896, 20.309, 20.669, 21.071, 21.554, 22.006, 21.988, 22.021, 22.134, 22.148, 22.127, 22.098, 22.077, 22.042, 22.033, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250};
+double testRanges2[] = {250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 5.617, 5.593, 5.58, 5.579, 5.605, 5.628, 5.613, 5.633, 5.662, 5.642, 5.646, 5.655, 5.663, 5.682, 5.677, 5.672, 5.691, 5.729, 5.747, 5.733, 5.783, 5.798, 5.8, 5.835, 21.331, 21.854, 23.03, 23.055, 23.082, 23.133, 23.178, 23.174, 22.968, 22.127, 21.706, 18.682, 18.669, 250, 18.153, 2.957, 2.961, 2.878, 2.842, 2.776, 2.735, 2.718, 2.69, 2.659, 2.625, 2.627, 2.612, 2.562, 2.549, 2.534, 2.52, 2.474, 2.441, 2.44, 2.428, 2.424, 2.422, 2.407, 2.379, 2.364, 2.354, 2.343, 2.33, 2.312, 2.293, 2.271, 2.248, 2.251, 2.257, 2.252, 2.241, 2.194, 2.188, 2.197, 2.187, 2.174, 2.164, 2.163, 2.167, 2.177, 2.176, 2.144, 2.125, 2.126, 2.125, 2.113, 2.103, 2.109, 2.107, 2.121, 2.119, 2.11, 2.153, 2.168, 2.17, 2.156, 2.184, 2.18, 2.182, 2.193, 2.238, 2.228, 2.239, 2.22, 2.226, 2.242, 2.229, 2.222, 1.994, 1.884, 1.86, 1.85, 1.846, 1.849, 1.856, 1.838, 1.829, 1.813, 1.812, 1.794, 1.808, 1.81, 1.824, 1.825, 1.827, 1.836, 1.868, 1.906, 1.987, 2.003, 1.998, 2.012, 2.016, 2.022, 2.003, 2, 2.008, 2.012, 2.018, 2.011, 1.999, 1.999, 2.018, 1.997, 1.989, 2.001, 2.002, 1.995, 1.981, 1.988, 1.971, 1.988, 2.001, 1.984, 1.961, 1.936, 1.951, 1.992, 1.979, 1.998, 1.866, 1.714, 1.618, 1.533, 1.528, 1.521, 1.54, 1.533, 1.514, 1.503, 1.514, 1.497, 1.495, 1.497, 1.508, 1.485, 1.478, 1.474, 1.479, 1.475, 1.463, 1.487, 1.479, 1.523, 1.495, 1.542, 1.559, 1.595, 1.602, 1.614, 1.618, 1.614, 1.64, 1.625, 1.638, 1.656, 1.675, 1.686, 1.678, 1.678, 1.682, 1.674, 1.716, 1.703, 1.663, 1.672, 1.693, 1.73, 1.697, 1.669, 1.69, 1.702, 1.646, 1.698, 1.676, 1.681, 1.669, 1.665, 1.683, 1.659, 1.655, 1.623, 1.54, 1.522, 1.513, 1.474, 1.439, 1.412, 1.387, 1.397, 1.394, 1.361, 1.348, 1.343, 1.354, 1.361, 1.374, 1.362, 1.321, 1.313, 1.312, 1.328, 1.315, 1.328, 1.314, 1.316, 1.298, 1.309, 1.305, 1.321, 1.319, 1.303, 1.313, 1.284, 1.295, 1.309, 1.303, 1.305, 1.3, 1.309, 1.284, 1.294, 1.32, 1.297, 1.316, 1.287, 1.285, 1.279, 1.311, 1.286, 1.285, 1.288, 1.293, 1.299, 1.291, 1.28, 1.283, 1.287, 1.282, 1.269, 1.279, 1.264, 1.282, 1.286, 1.264, 1.285, 1.286, 1.273, 1.286, 1.275, 1.345, 1.438, 1.614, 1.599, 1.557, 1.582, 1.545, 1.556, 1.508, 1.688, 1.635, 1.659, 1.593, 1.534, 1.414, 1.299, 1.29, 1.315, 1.353, 1.322, 1.306, 1.32, 1.414, 1.421, 1.395, 1.271, 1.25, 1.271, 1.386, 1.51, 1.532, 1.437, 1.424, 1.41, 1.349, 1.422, 1.474, 1.549, 1.565, 1.549, 1.562, 1.59, 1.591, 1.569, 1.523, 1.621, 1.651, 1.696, 1.728, 1.74, 1.744, 1.713, 1.744, 1.709, 1.683, 1.593, 1.601, 1.588, 1.586, 1.579, 1.587, 1.584, 1.599, 1.591, 1.517, 1.454, 1.352, 1.326, 1.321, 1.302, 1.31, 1.325, 1.321, 1.297, 1.323, 1.305, 1.323, 1.306, 1.315, 1.306, 1.323, 1.335, 1.342, 1.332, 1.345, 1.339, 1.327, 1.34, 1.336, 1.357, 1.36, 1.369, 1.507, 1.637, 1.653, 1.649, 1.646, 1.668, 1.693, 1.738, 1.779, 1.829, 1.852, 1.857, 1.851, 1.896, 1.906, 1.906, 1.878, 1.914, 1.911, 1.952, 1.919, 1.934, 1.945, 1.932, 1.903, 1.863, 1.837, 1.835, 1.817, 1.812, 1.81, 1.801, 1.783, 1.799, 1.801, 1.778, 1.794, 1.782, 1.776, 1.767, 1.768, 1.783, 1.756, 1.732, 1.737, 1.724, 1.685, 1.641, 1.586, 1.586, 1.572, 1.557, 1.557, 1.521, 1.534, 1.51, 1.541, 1.545, 1.541, 1.566, 1.583, 1.581, 1.602, 1.627, 1.618, 1.63, 1.614, 1.613, 1.593, 1.603, 1.629, 1.745, 2.084, 2.077, 2.066, 2.07, 2.029, 2.044, 2.043, 2.042, 2.043, 2.001, 1.987, 1.982, 1.958, 1.94, 1.893, 1.855, 1.799, 1.731, 1.693, 1.701, 1.627, 1.502, 1.467, 1.476, 1.484, 1.462, 1.475, 1.475, 1.466, 1.471, 1.448, 1.453, 1.457, 1.455, 1.451, 1.453, 1.483, 1.491, 1.511, 1.53, 1.545, 1.553, 1.556, 1.607, 1.646, 1.738, 1.756, 1.782, 1.804, 1.811, 1.829, 1.844, 1.861, 1.871, 1.859, 1.867, 1.859, 1.896, 1.895, 1.917, 1.923, 1.936, 1.931, 1.952, 1.962, 1.964, 1.995, 2.01, 2.01, 2.023, 2.025, 2.05, 2.054, 2.051, 2.08, 2.096, 2.105, 2.094, 2.114, 2.143, 2.149, 2.155, 2.163, 2.173, 2.17, 2.201, 2.193, 2.23, 2.232, 2.262, 2.282, 2.299, 2.318, 2.33, 2.349, 2.401, 2.417, 2.431, 2.45, 2.478, 2.492, 2.512, 2.523, 2.544, 2.561, 2.547, 2.541, 2.554, 2.636, 2.774, 2.804, 2.803, 2.809, 2.797, 2.795, 2.799, 2.801, 2.809, 2.814, 2.859, 2.854, 2.892, 2.912, 2.921, 2.922, 2.957, 3.024, 3.059, 3.061, 3.082, 3.111, 3.14, 3.196, 3.204, 3.2, 3.225, 3.225, 3.23, 3.267, 3.332, 3.366, 3.449, 12.079, 12.094, 12.04, 12.029, 12.045, 12.008, 12.012, 11.979, 11.982, 11.948, 11.944, 11.937, 11.936, 11.908, 11.894, 11.89, 11.866, 11.859, 11.846, 11.831, 11.785, 11.814, 11.803, 11.799, 11.784, 11.771, 11.761, 11.765, 11.732, 11.734, 11.708, 11.716, 11.701, 11.706, 11.678, 11.683, 11.666, 11.654, 11.654, 11.646, 11.651, 11.636, 11.641, 11.633, 11.626, 11.638, 11.613, 11.626, 11.627, 11.585, 11.612, 11.605, 11.595, 11.576, 11.576, 11.595, 11.577, 11.563, 11.562, 11.577, 11.574, 11.573, 11.569, 11.543, 11.429, 11.425, 11.447, 11.563, 11.495, 11.558, 11.548, 11.541, 11.566, 11.556, 11.554, 11.576, 11.587, 11.567, 11.564, 11.591, 11.572, 11.579, 11.581, 11.574, 11.583, 11.578, 11.587, 11.601, 11.631, 11.625, 11.631, 11.606, 11.64, 11.646, 11.623, 11.637, 11.658, 11.673, 11.666, 11.657, 11.698, 11.701, 11.69, 11.703, 11.691, 11.726, 11.73, 11.736, 11.752, 11.753, 11.779, 11.771, 11.775, 11.799, 11.805, 11.801, 11.832, 11.825, 11.865, 11.872, 11.878, 11.898, 11.9, 11.928, 11.925, 11.945, 11.957, 11.968, 11.988, 11.986, 12.018, 12.037, 12.048, 12.07, 12.091, 12.095, 12.11, 12.132, 12.135, 3.819, 3.835, 3.827, 3.785, 3.822, 3.853, 3.851, 3.823, 3.818, 3.81, 3.805, 3.812, 3.834, 3.867, 3.888, 3.896, 3.878, 3.848, 3.877, 3.785, 3.689, 3.709, 3.624, 3.545, 3.493, 3.421, 3.39, 3.375, 3.308, 3.283, 3.267, 3.225, 3.218, 3.192, 3.171, 3.116, 3.089, 3.082, 3.048, 3.017, 2.985, 2.975, 2.949, 2.906, 2.896, 2.888, 2.864, 2.854, 2.811, 2.787, 2.779, 2.78, 2.768, 2.757, 2.739, 2.723, 2.701, 2.704, 2.698, 2.688, 2.693, 2.707, 2.704, 2.704, 2.612, 2.562, 2.548, 2.548, 2.489, 2.454, 2.447, 2.436, 2.445, 2.44, 2.396, 2.384, 2.35, 2.366, 2.348, 2.334, 2.317, 2.302, 2.27, 2.28, 2.274, 2.267, 2.25, 2.23, 2.215, 2.189, 2.19, 2.183, 2.181, 2.167, 2.17, 2.148, 2.146, 2.14, 2.073, 2.089, 2.073, 2.073, 2.078, 2.071, 2.054, 2.042, 2.002, 1.997, 1.993, 1.975, 1.988, 1.978, 1.981, 1.953, 1.966, 1.955, 1.936, 1.919, 1.91, 1.923, 1.906, 1.885, 1.907, 1.892, 1.885, 1.881, 1.875, 1.853, 1.836, 1.848, 1.823, 1.819, 1.805, 1.821, 1.822, 1.821, 1.841, 1.815, 1.814, 1.782, 1.804, 1.778, 1.771, 1.761, 1.766, 1.778, 1.766, 1.761, 1.77, 1.771, 1.772, 1.775, 1.799, 1.813, 1.801, 1.83, 1.842, 1.832, 1.742, 1.686, 1.677, 1.675, 1.685, 1.673, 1.653, 1.679, 1.654, 1.661, 1.652, 1.636, 1.637, 1.649, 1.63, 1.62, 1.6, 1.604, 1.624, 1.602, 1.576, 1.604, 1.59, 1.581, 1.586, 1.575, 1.57, 1.563, 1.566, 1.559, 1.567, 1.556, 1.547, 1.537, 1.528, 1.54, 1.527, 1.53, 1.544, 1.521, 1.528, 1.501, 1.517, 1.516, 1.525, 1.511, 1.522, 1.514, 1.485, 1.496, 1.512, 1.511, 1.505, 1.474, 1.495, 1.49, 1.484, 1.497, 1.485, 1.486, 1.478, 1.459, 1.473, 1.445, 1.467, 1.482, 1.479, 1.452, 1.447, 1.467, 1.476, 1.434, 1.46, 1.459, 1.432, 1.445, 1.44, 1.441, 1.45, 1.447, 1.432, 1.442, 1.449, 1.424, 1.439, 1.439, 1.431, 1.433, 1.438, 1.44, 1.427, 1.414, 1.418, 1.44, 1.423, 1.417, 1.416, 1.437, 1.43, 1.419, 1.435, 1.424, 1.424, 1.404, 1.425, 1.413, 1.417, 1.415, 1.439, 1.438, 1.437, 1.443, 1.416, 1.426, 1.416, 1.419, 1.404, 1.41, 1.408, 1.399, 1.414, 1.424, 1.419, 1.413, 1.425, 1.413, 1.407, 1.417, 1.419, 1.436, 1.414, 1.436, 1.421, 1.424, 1.435, 1.433, 1.439, 1.412, 1.42, 1.433, 1.431, 1.435, 1.44, 1.429, 1.406, 1.414, 1.436, 1.433, 1.438, 1.431, 1.436, 1.446, 1.422, 10.867, 10.876, 10.859, 10.867, 10.874, 10.889, 10.882, 10.903, 10.902, 10.921, 10.924, 10.919, 10.93, 2.371, 2.324, 2.277, 2.216, 2.166, 2.121, 2.081, 2.007, 1.988, 1.943, 1.894, 1.884, 1.859, 1.806, 1.787, 1.771, 1.744, 1.747, 1.733, 1.689, 1.705, 1.657, 1.648, 1.642, 1.59, 1.598, 1.563, 1.557, 1.521, 1.525, 1.533, 1.5, 1.512, 1.519, 1.503, 1.525, 1.544, 1.536, 1.522, 1.543, 1.557, 1.536, 1.536, 1.551, 1.565, 1.555, 1.562, 1.56, 1.546, 1.565, 1.567, 1.565, 1.583, 1.583, 1.563, 1.606, 1.583, 1.604, 1.579, 1.621, 1.615, 1.604, 1.613, 1.614, 1.605, 1.628, 1.626, 1.604, 1.629, 1.618, 1.635, 1.626, 1.645, 1.638, 1.667, 1.667, 1.661, 1.663, 1.658, 1.664, 1.676, 1.661, 1.681, 1.69, 1.692, 1.706, 1.696, 1.724, 1.702, 1.701, 1.738, 1.709, 1.744, 1.732, 1.738, 1.754, 1.772, 1.744, 1.771, 1.771, 1.786, 1.76, 1.769, 1.807, 1.792, 1.804, 1.81, 1.841, 1.824, 1.837, 1.853, 1.833, 1.842, 1.87, 1.866, 1.849, 1.883, 1.884, 1.862, 1.896, 1.902, 1.927, 1.926, 1.94, 1.948, 1.935, 1.952, 1.946, 1.973, 1.979, 1.99, 2.008, 1.998, 2.021, 2.03, 2.038, 2.059, 2.047, 2.047, 2.069, 2.094, 2.101, 2.135, 2.197, 2.189, 2.184, 2.182, 2.185, 2.188, 2.186, 2.184, 2.165, 2.153, 2.136, 2.128, 2.145, 2.131, 2.129, 2.116, 2.132, 2.143, 2.134, 2.146, 2.157, 2.146, 2.17, 2.22, 2.215, 2.223, 2.228, 2.239, 2.269, 2.261, 2.288, 2.307, 2.312, 2.327, 2.336, 2.379, 2.405, 2.428, 2.428, 2.443, 2.44, 2.463, 2.484, 2.508, 2.533, 2.538, 2.564, 2.588, 2.599, 2.644, 2.65, 2.663, 2.683, 2.748, 2.753, 2.762, 2.77, 2.814, 2.847, 2.863, 2.875, 2.9, 2.968, 2.999, 3.117, 3.142, 3.132, 3.126, 3.139, 3.124, 3.123, 3.126, 3.116, 3.163, 3.188, 3.207, 3.214, 3.246, 3.284, 3.308, 3.353, 3.438, 3.483, 3.466, 3.467, 3.497, 3.521, 3.554, 3.595, 3.718, 3.816, 3.88, 3.904, 4.006, 4.061, 4.116, 4.159, 4.244, 4.305, 4.303, 4.293, 4.267, 4.258, 4.232, 4.237, 4.246, 4.243, 4.28, 4.23, 4.266, 4.301, 250, 15.708, 15.894, 16.17, 16.392, 16.558, 16.899, 17.175, 17.345, 17.708, 17.955, 18.299, 18.532, 18.88, 19.168, 19.657, 19.872, 20.318, 20.668, 21.067, 21.543, 21.989, 22.006, 22.029, 22.138, 22.123, 22.104, 22.103, 22.064, 22.064, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250};
+double testRangesOrtho1[] = {7.88663, 7.89185, 7.89723, 7.90276, 7.90846, 7.91431, 7.92033, 7.9265, 7.93284, 7.93933, 7.94599, 7.95281, 7.9598, 7.96694, 7.97426, 7.98174, 7.98938, 7.99719, 8.00517, 8.01332, 8.02164, 8.03013, 8.03879, 8.04762, 8.05662, 8.0658, 8.07515, 8.08468, 8.09439, 8.10427, 8.11434, 8.12458, 8.135, 8.14561, 8.1564, 8.16737, 8.17853, 8.18987, 8.20141, 8.21313, 8.22504, 8.23714, 8.24944, 8.26193, 8.27462, 8.2875, 8.30059, 8.31387, 8.32735, 8.34104, 8.35493, 8.36903, 8.38333, 8.39785, 8.41257, 8.42751, 8.44266, 8.45803, 8.47361, 8.48942, 8.50544, 8.52169, 8.53816, 8.55486, 8.57179, 8.58895, 8.60635, 8.62398, 8.64184, 8.65995, 8.6783, 8.69689, 8.71572, 8.73481, 8.75414, 8.77373, 8.79358, 8.81368, 8.83405, 8.85467, 8.87557, 8.89673, 8.91816, 8.93987, 8.96185, 8.98412, 9.00666, 9.0295, 9.05262, 9.07603, 9.09974, 9.12375, 9.14806, 9.17267, 9.19759, 9.22283, 9.24837, 9.27424, 9.30043, 9.32695, 9.3538, 9.38098, 9.4085, 9.43636, 9.46457, 9.49313, 9.52204, 9.55131, 9.58095, 9.61095, 9.64133, 9.67208, 9.70322, 9.73474, 9.76666, 9.79897, 9.83168, 9.86481, 9.89834, 9.9323, 9.96667, 10.0015, 10.0108, 9.95724, 9.90444, 9.85239, 9.80106, 9.75045, 9.70054, 9.65133, 9.60279, 9.55493, 9.50771, 9.46114, 9.4152, 9.36989, 9.32518, 9.28107, 9.23756, 9.19462, 9.15226, 9.11046, 9.06921, 9.0285, 8.98832, 8.94868, 8.90955, 7.46284, 7.43077, 7.39911, 7.36787, 7.33702, 7.30657, 7.27651, 7.24684, 7.21754, 7.18861, 7.16005, 7.13185, 7.10401, 7.07652, 7.04937, 7.02257, 6.9961, 6.96996, 6.94415, 6.91866, 6.89349, 6.86863, 6.84407, 6.81983, 6.79588, 6.77223, 6.74887, 6.7258, 6.70301, 6.6805, 6.65827, 6.63632, 6.61463, 6.59321, 6.57206, 6.55116, 6.53052, 6.51013, 6.49, 6.47011, 6.45046, 6.43105, 6.41189, 6.39296, 6.37426, 6.35579, 6.33754, 6.31953, 6.30173, 6.28415, 6.26679, 6.24965, 6.23271, 6.21599, 6.19947, 6.18316, 6.16705, 6.15114, 6.13543, 6.11991, 6.10459, 6.08946, 6.07453, 6.05978, 6.04521, 6.03083, 6.01664, 6.00262, 5.98878, 5.97512, 5.96164, 5.94833, 5.93519, 5.92222, 5.90942, 5.89679, 5.88432, 5.87202, 5.85988, 5.8479, 5.83608, 5.82442, 5.81292, 5.80157, 5.79038, 5.77934, 5.76845, 5.75771, 5.74712, 5.73668, 5.72638, 5.71623, 5.70623, 5.69637, 5.68665, 5.67707, 5.66763, 5.65833, 5.64917, 5.64014, 5.63125, 5.6225, 5.61388, 5.60539, 5.59703, 5.58881, 5.58071, 5.57275, 5.56491, 5.5572, 5.54962, 5.54217, 5.53484, 5.52763, 5.52055, 5.51359, 5.50675, 5.50003, 5.49344, 5.48696, 5.48061, 5.47437, 5.46825, 5.46225, 5.45637, 5.4506, 5.44495, 5.43941, 5.43399, 5.42868, 5.42349, 5.41841, 5.41344, 5.40858, 5.40383, 5.3992, 5.39467, 5.39026, 5.38596, 5.38176, 5.37767, 5.3737, 5.36983, 5.36607, 5.36241, 5.35886, 5.35542, 5.35209, 5.34886, 5.34573, 5.34272, 5.3398, 5.33699, 5.33429, 5.33169, 5.32919, 5.3268, 5.32451, 5.32233, 5.32025, 5.31827, 5.31639, 5.31461, 5.31294, 5.31137, 5.3099, 5.30854, 5.30727, 5.30611, 5.30505, 5.30409, 5.30323, 5.30247, 5.30182, 5.30126, 5.30081, 5.30045, 5.3002, 5.30005, 5.3, 5.30005, 5.3002, 5.30045, 5.30081, 5.30126, 5.30182, 5.30247, 5.30323, 5.30409, 5.30505, 5.30611, 5.30727, 5.30854, 5.3099, 5.31137, 5.31294, 5.31461, 5.31639, 5.31827, 5.32025, 5.32233, 5.32451, 5.3268, 5.32919, 5.33169, 5.33429, 5.33699, 5.3398, 5.34272, 5.34573, 5.34886, 5.35209, 5.35542, 5.35886, 5.36241, 5.36607, 5.36983, 5.3737, 5.37767, 5.38176, 5.38596, 5.39026, 5.39467, 5.3992, 5.40383, 5.40858, 5.41344, 5.41841, 5.42349, 5.42868, 5.43399, 5.43941, 5.44495, 5.4506, 5.45637, 5.46225, 5.46825, 5.47437, 5.48061, 5.48696, 5.49344, 5.50003, 5.50675, 5.51359, 5.52055, 5.52763, 5.53484, 5.54217, 5.54962, 5.5572, 5.56491, 5.57275, 5.58071, 5.58881, 5.59703, 5.60539, 5.61388, 5.6225, 5.63125, 5.64014, 5.64917, 5.65833, 5.66763, 5.67707, 5.68665, 5.69637, 5.70623, 5.71623, 5.72638, 5.73668, 5.74712, 5.75771, 5.76845, 5.77934, 5.79038, 5.80157, 5.81292, 5.82442, 5.83608, 5.8479, 5.85988, 5.87202, 5.88432, 5.89679, 5.90942, 5.92222, 5.93519, 5.94833, 5.96164, 5.97512, 5.98878, 6.00262, 6.01664, 6.03083, 6.04521, 6.05978, 6.07453, 6.08946, 6.10459, 6.11991, 6.13543, 6.15114, 6.16705, 6.18316, 6.19947, 6.21599, 6.23271, 6.24965, 6.26679, 6.28415, 6.30173, 6.31953, 6.33754, 6.35579, 6.37426, 6.39296, 6.41189, 6.43105, 6.45046, 6.47011, 6.49, 6.51013, 6.53052, 6.55116, 6.57206, 6.59321, 6.61463, 6.63632, 6.65827, 6.6805, 6.70301, 6.7258, 6.74887, 6.77223, 6.79588, 6.81983, 6.84407, 6.86863, 6.89349, 6.91866, 6.94415, 6.96996, 6.9961, 7.02257, 7.04937, 7.07652, 7.10401, 7.13185, 7.16005, 7.18861, 7.21754, 7.24684, 7.27651, 7.30657, 7.33702, 7.36787, 7.39911, 7.43077, 7.46284, 7.49533, 7.52825, 7.56161, 7.5954, 7.62965, 7.66435, 7.69952, 7.73516, 7.77128, 7.76226, 7.73115, 7.70043, 7.67011, 7.64016, 7.6106, 7.5814, 7.55257, 7.52411, 7.496, 7.46824, 7.44082, 7.41375, 7.38701, 7.36061, 7.33453, 7.30877, 7.28334, 7.25822, 7.2334, 7.2089, 7.18469, 7.16079, 7.13717, 7.11385, 7.09081, 7.06806, 7.04559, 7.02339, 7.00146, 6.97981, 6.95842, 6.93729, 6.91642, 6.8958, 6.87544, 6.85533, 6.83547, 6.81585, 6.79647, 6.77733, 6.75843, 6.73976, 6.72132, 6.7031, 6.68512, 6.66735, 6.64981, 6.63248, 6.61537, 6.59848, 6.58179, 6.56532, 6.54905, 6.53298, 6.51712, 6.50146, 6.48599, 6.47072, 6.45565, 6.44077, 6.42608, 6.41157, 6.39726, 6.38313, 6.36918, 6.35542, 6.34183, 6.32842, 6.31519, 6.30214, 6.28925, 6.27654, 6.264, 6.25163, 6.23943, 6.22739, 6.21551, 6.2038, 6.19225, 6.18087, 6.16964, 6.15856, 6.14765, 6.13689, 6.12628, 6.11583, 6.10553, 6.09538, 6.08537, 6.07552, 6.06581, 6.05625, 6.04684, 6.03757, 6.02844, 6.01945, 6.01061, 6.0019, 5.99333, 5.98491, 5.97662, 5.96846, 5.96044, 5.95256, 5.94481, 5.93719, 5.92971, 5.92235, 5.91513, 5.90804, 5.90107, 5.89424, 5.88753, 5.88095, 5.8745, 5.86817, 5.86197, 5.85589, 5.84993, 5.8441, 5.83839, 5.83281, 5.82734, 5.822, 5.81677, 5.81167, 5.80669, 5.80182, 5.79707, 5.79244, 5.78793, 5.78354, 5.77926, 5.7751, 5.77105, 5.76712, 5.7633, 5.7596, 5.75602, 5.93248, 6.12904, 6.24997, 6.24656, 6.24328, 6.24011, 6.23707, 6.23415, 6.23135, 6.22868, 6.22612, 6.22368, 6.22137, 6.21917, 6.2171, 6.21514, 6.2133, 6.21159, 6.20999, 6.20851, 6.20715, 6.20591, 6.20478, 6.20378, 6.20289, 6.20213, 6.20148, 6.20094, 6.20053, 6.20024, 6.20006, 6.2, 6.20006, 6.20024, 6.20053, 6.20094, 6.20148, 6.20213, 6.20289, 6.20378, 6.20478, 6.20591, 6.20715, 6.20851, 6.20999, 6.21159, 6.2133, 6.21514, 6.2171, 6.21917, 6.22137, 6.22368, 6.22612, 6.22868, 6.23135, 6.23415, 6.23707, 6.24011, 6.24328, 6.24656, 6.24997, 6.2535, 6.25715, 6.26093, 6.26483, 6.26886, 6.27301, 6.27728, 6.28168, 6.28621, 6.29086, 6.29564, 6.30055, 6.30559, 6.31075, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 10.1306, 10.1511, 10.1719, 10.1929, 10.2143, 10.2359, 10.2579, 10.2801, 10.3026, 10.3254, 10.3485, 10.3719, 10.3956, 10.4196, 10.444, 10.4686, 10.4936, 10.5189, 10.5445, 10.56, 10.4793, 10.4, 10.3221, 10.2455, 10.1703, 10.0963, 10.0236, 9.95218, 9.88191, 9.81282, 9.74486, 9.67803, 9.61228, 9.54761, 9.48398, 9.42137, 9.35975, 9.29912, 9.23944, 9.18069, 9.12286, 9.06592, 9.00986, 8.95466, 8.9003, 8.84677, 8.79404, 8.7421, 8.69093, 8.64053, 8.59087, 8.54193, 8.49372, 8.4462, 8.39937, 8.35322, 8.30772, 8.26288, 8.21868, 8.1751, 8.13213, 8.09353, 8.12334, 8.15354, 8.18412, 8.21508, 8.24644, 8.27819, 8.31035, 8.34292, 8.37591, 8.40932, 8.44316, 8.47743, 8.51215, 8.54731, 8.58293, 8.61901, 8.65557, 8.6926, 8.73011, 8.76812, 8.80663, 8.84565, 8.88519, 8.92525, 8.96585, 9.00699, 9.04868, 9.09093, 9.13376, 9.17716, 9.22116, 9.26575, 9.31096, 9.3568, 9.40326, 9.45037, 9.49813, 9.54657, 9.59568, 9.64549, 9.696, 9.74723, 9.79919, 9.8519, 9.90536, 9.95961, 10.0146, 10.0705, 10.1271, 10.1846, 10.243, 10.3022, 10.3623, 10.4233, 10.4852, 10.5481, 10.6119, 10.6767, 10.7425, 10.8094, 10.8773, 10.9462, 11.0163, 11.0874, 11.1597, 11.2332, 11.3078, 11.3837, 11.4608, 11.5392, 11.6189, 11.6999, 11.7823, 11.8661, 11.9513, 12.0379, 12.1261, 12.2158, 12.3071, 12.4, 5.41351, 5.40009, 5.38684, 5.37376, 5.36085, 5.3481, 5.33551, 5.32308, 5.31081, 5.2987, 5.28674, 5.27493, 5.26328, 5.25178, 5.24043, 5.22923, 5.21817, 5.20726, 5.1965, 5.18588, 5.1754, 5.16505, 5.15485, 5.14479, 5.13486, 5.12507, 5.11542, 5.10589, 5.0965, 5.08724, 5.07811, 5.06911, 5.06024, 5.0515, 5.04288, 5.03438, 5.02601, 5.01776, 5.00964, 5.00164, 4.99375, 4.98599, 4.97834, 4.97082, 4.96341, 4.95611, 4.94894, 4.94187, 4.93492, 4.92809, 4.92136, 4.91475, 4.90825, 4.90186, 4.89558, 4.88941, 4.88334, 4.87739, 4.87154, 4.8658, 4.86016, 4.85463, 4.84921, 4.84388, 4.83867, 4.83355, 4.82854, 4.82363, 4.81882, 4.81411, 4.80951, 4.805, 4.80059, 4.79629, 4.79208, 4.78797, 4.78396, 4.78004, 4.77623, 4.77251, 4.76888, 4.76535, 4.76192, 4.75859, 4.75535, 4.7522, 4.8783, 5.02971, 5.19092, 5.36291, 5.5468, 5.74386, 5.95555, 6.18357, 6.23707, 6.23415, 6.23135, 6.22868, 6.22612, 6.22368, 6.22137, 6.21917, 6.2171, 6.21514, 6.2133, 6.21159, 6.20999, 6.20851, 6.20715, 6.20591, 6.20478, 6.20378, 6.20289, 6.20213, 6.20148, 6.20094, 6.20053, 6.20024, 6.20006, 6.2, 6.20006, 6.20024, 6.20053, 6.20094, 6.20148, 6.20213, 6.20289, 6.20378, 6.20478, 6.20591, 6.20715, 6.20851, 6.20999, 6.21159, 6.2133, 6.21514, 6.2171, 6.21917, 6.22137, 6.22368, 6.22612, 6.22868, 6.23135, 6.23415, 6.23707, 6.24011, 6.24328, 6.24656, 6.24997, 6.2535, 6.25715, 6.26093, 6.26483, 6.26886, 6.27301, 6.27728, 6.28168, 6.28621, 6.29086, 6.29564, 6.30055, 6.30559, 6.31075, 6.31604, 6.32147, 6.32702, 6.3327, 6.33851, 6.34446, 6.35053, 6.35674, 6.36309, 6.36956, 6.37617, 6.38292, 6.3898, 6.39682, 6.40398, 6.41128, 6.41871, 6.42629, 6.434, 6.44186, 6.44986, 6.458, 6.46628, 6.47471, 6.48329, 6.49201, 6.50088, 6.5099, 6.51907, 6.52838, 6.53785, 6.54747, 6.55725, 6.56718, 6.57726, 6.5875, 6.5979, 6.60846, 6.61918, 6.63006, 6.6411, 6.6523, 6.66367, 6.67521, 6.68692, 6.69879, 6.71083, 6.72305, 6.73543, 6.748, 6.76073, 6.77365, 6.78674, 6.80002, 6.81348, 6.82712, 6.84094, 6.85496, 6.86916, 6.88355, 6.89813, 6.91291, 6.92788, 6.94305, 6.95842, 6.97399, 6.98977, 7.00575, 7.02193, 7.03833, 7.05494, 7.07176, 7.0888, 7.10605, 7.12352, 7.14122, 7.15914, 7.17729, 7.19567, 7.21428, 7.23313, 7.25221, 7.27153, 7.2911, 7.31091, 7.33096, 7.35127, 7.37183, 7.39265, 7.41373, 7.43507, 7.45668, 7.47855, 7.5007, 7.52312, 7.54582, 7.5688, 7.59207, 7.61563, 7.63948, 7.66362, 7.68807, 7.71282, 7.73787, 7.76324, 7.78893, 7.81493, 7.84035, 7.79649, 7.75327, 7.71066, 7.66867, 7.62728, 7.58647, 7.54624, 7.50658, 7.46747, 7.42891, 7.39089, 7.35339, 7.31641, 7.27994, 7.24397, 7.20849, 7.17349, 7.13896, 7.1049, 7.07129, 7.03814, 7.00543, 6.97315, 6.9413, 6.90987, 6.87886, 6.84825, 6.81804, 6.78823, 6.7588, 6.72975, 6.70108, 6.67279, 6.64485, 6.61727, 6.59005, 6.56317, 6.53664, 6.51044, 6.48458, 6.45904, 6.43382, 6.40892, 6.38434, 6.36006, 6.33609, 6.31242, 6.28904, 6.26595, 6.24316, 6.22064, 6.19841, 6.17645, 6.15476, 6.13334, 6.11218, 6.09129, 6.07065, 6.07791, 6.11273, 6.14807, 6.18393, 6.22034, 6.2573, 6.29482, 6.33291, 6.37159, 6.41087, 6.45075, 6.49126, 6.53241, 6.57421, 6.61668, 6.65982, 6.70366, 6.74821, 6.79349, 6.83951, 6.88629, 6.93384, 6.9822, 7.03136, 7.08136, 7.13221, 7.18393, 7.23655, 7.29009, 7.34456, 7.4, 7.45642, 7.51386, 7.57233, 7.63186, 7.69249, 7.75423, 7.81713, 7.8812, 7.94649, 8.01302, 8.08083, 8.14995, 8.22042, 8.29229, 8.36558, 8.44034, 8.51661, 8.59444, 8.62398, 8.60635, 8.58895, 8.57179, 8.55486, 8.53816, 8.52169, 8.50544, 8.48942, 8.47361, 8.45803, 8.44266, 8.42751, 8.41257, 8.39785, 8.38333, 8.36903, 8.35493, 8.34104, 8.32735, 8.31387, 8.30059, 8.2875, 8.27462, 8.26193, 8.24944, 8.23714, 8.22504, 8.21313, 8.20141, 8.18987, 8.17853, 8.16737, 8.1564, 8.14561, 8.135, 8.12458, 8.11434, 8.10427, 8.09439, 8.08468, 8.07515, 8.0658, 8.05662, 8.04762, 8.03879, 8.03013, 8.02164, 8.01332, 8.00517, 7.99719, 7.98938, 7.98174, 7.97426, 7.96694, 7.9598, 7.95281, 7.94599, 7.93933, 7.93284, 7.9265, 7.92033, 7.91431, 7.90846, 7.90276, 7.89723, 7.89185, 7.88663, 7.88156, 7.87666, 7.8719, 7.86731, 7.86286, 7.85858, 7.85444, 7.85046, 7.84664, 7.84296, 7.83944, 7.83608, 7.83286, 7.82979, 7.82688, 7.82412, 7.82151, 7.81905, 7.81674, 7.81458, 7.81257, 7.8107, 7.80899, 7.80743, 7.80602, 7.80475, 7.80364, 7.80267, 7.80186, 7.80119, 7.80067, 7.8003, 7.80007, 7.8, 7.80007, 7.8003, 7.80067, 7.80119, 7.80186, 7.80267, 7.80364, 7.80475, 7.80602, 7.80743, 7.80899, 7.8107, 7.81257, 7.81458, 7.81674, 7.81905, 7.82151, 7.82412, 7.82688, 7.82979, 7.83286, 7.83608, 7.83944, 7.84296, 7.84664, 7.85046, 7.85444, 7.85858, 7.86286, 7.86731, 7.8719, 7.87666, 7.88156, 7.88663 };
+double testRangesOrtho2[] = {8.82969, 8.82661, 8.8237, 8.82095, 8.81838, 8.81598, 8.81374, 8.81168, 8.80978, 8.80805, 8.80649, 8.8051, 8.80387, 8.80282, 8.80193, 8.80121, 8.80066, 8.80027, 8.80005, 8.8, 8.80012, 8.80041, 8.80086, 8.80148, 8.80227, 8.80322, 8.80434, 8.80564, 8.8071, 8.80872, 8.81052, 8.81248, 8.81462, 8.81692, 8.81939, 8.82203, 8.82484, 8.82782, 8.83097, 8.83429, 8.83778, 8.84145, 8.84528, 8.84929, 8.85347, 8.85782, 8.86234, 8.86704, 8.87191, 8.87696, 8.88218, 8.88758, 8.89315, 8.8989, 8.90482, 8.91093, 8.91721, 8.92367, 8.93031, 8.93713, 8.94413, 8.95132, 8.95868, 8.96623, 8.97396, 8.98188, 8.98998, 8.99827, 9.00674, 9.01541, 9.02426, 9.0333, 9.04253, 9.05195, 9.06157, 9.07138, 9.08138, 9.09158, 9.10197, 9.11256, 9.12336, 9.13435, 9.14554, 9.15693, 9.16853, 9.18033, 9.19233, 9.20455, 9.21697, 9.2296, 9.24244, 9.2555, 9.26876, 9.28225, 9.29595, 9.30986, 9.324, 9.33836, 9.35294, 9.36774, 9.38277, 9.39803, 9.41352, 9.42924, 9.44519, 9.46137, 9.4778, 9.49446, 9.51136, 9.5285, 9.54589, 9.56352, 9.5814, 9.59953, 9.61791, 9.63655, 9.65544, 9.67459, 9.69401, 9.71368, 9.73362, 9.75383, 9.77432, 9.79507, 9.8161, 9.83741, 9.859, 9.88087, 9.90303, 9.92547, 9.94821, 9.97125, 9.99458, 10.0182, 10.0421, 10.0664, 10.0909, 10.1158, 10.141, 10.1665, 10.1923, 10.2185, 10.2449, 10.2718, 10.2989, 10.3264, 10.3542, 10.3824, 10.411, 10.4399, 10.4691, 10.4988, 10.5287, 10.5591, 10.5898, 10.621, 10.6525, 10.6844, 10.7167, 10.7494, 10.7825, 10.816, 10.8499, 10.8843, 10.9191, 10.9543, 10.99, 11.026, 11.0626, 11.0996, 11.1371, 11.175, 11.2134, 11.2523, 11.2916, 11.3315, 11.3676, 11.3074, 11.2481, 11.1896, 11.1319, 11.075, 11.0189, 10.9636, 10.9091, 10.8553, 10.8022, 10.7498, 10.6982, 10.6472, 10.5969, 10.5473, 10.4984, 10.4501, 10.4025, 10.3555, 10.3091, 8.83781, 8.79889, 8.76048, 8.72257, 8.68515, 8.64822, 8.61176, 8.57577, 8.54024, 8.50517, 8.47054, 8.43635, 8.4026, 8.36928, 8.33638, 8.30389, 8.27181, 8.24013, 8.20886, 8.17797, 8.14747, 8.11735, 8.08761, 8.05823, 8.02922, 8.00057, 7.97228, 7.94433, 7.91674, 7.88948, 7.86256, 7.83597, 7.8097, 7.78376, 7.75814, 7.73284, 7.70784, 7.68315, 7.65877, 7.63468, 7.61089, 7.58739, 7.56418, 7.54126, 7.51861, 7.49625, 7.47415, 7.45233, 7.43078, 7.40949, 7.38847, 7.3677, 7.34719, 7.32693, 7.30692, 7.28716, 7.26765, 7.24837, 7.22934, 7.21054, 7.19198, 7.17364, 7.15554, 7.13766, 7.12001, 7.10258, 7.08537, 7.06838, 7.0516, 7.03503, 7.01868, 7.00254, 6.9866, 6.97086, 6.95533, 6.94, 6.92487, 6.90994, 6.8952, 6.88065, 6.8663, 6.85214, 6.83816, 6.82437, 6.81077, 6.79735, 6.78411, 6.77105, 6.75817, 6.74547, 6.73294, 6.72059, 6.70841, 6.6964, 6.68456, 6.67289, 6.66139, 6.65005, 6.63888, 6.62787, 6.61702, 6.60634, 6.59581, 6.58544, 6.57523, 6.56518, 6.55528, 6.54554, 6.53595, 6.52651, 6.51722, 6.50808, 6.49909, 6.49025, 6.48156, 6.47302, 6.46461, 6.45636, 6.44825, 6.44028, 6.43245, 6.42476, 6.41721, 6.40981, 6.40254, 6.39541, 6.38842, 6.38156, 6.37484, 6.36826, 6.36181, 6.35549, 6.34931, 6.34326, 6.33734, 6.33155, 6.3259, 6.32037, 6.31497, 6.30971, 6.30457, 6.29956, 6.29468, 6.28992, 6.2853, 6.28079, 6.27642, 6.27217, 6.26804, 6.26404, 6.26017, 6.25641, 6.25278, 6.24928, 6.24589, 6.24263, 6.23949, 6.23648, 6.23358, 6.23081, 6.22815, 6.22562, 6.22321, 6.22092, 6.21875, 6.2167, 6.21476, 6.21295, 6.21126, 6.20968, 6.20823, 6.20689, 6.20567, 6.20457, 6.20359, 6.20273, 6.20199, 6.20136, 6.20085, 6.20046, 6.20019, 6.20004, 6.2, 6.20008, 6.20029, 6.2006, 6.20104, 6.2016, 6.20227, 6.20306, 6.20397, 6.205, 6.20615, 6.20741, 6.20879, 6.2103, 6.21192, 6.21366, 6.21552, 6.2175, 6.2196, 6.22182, 6.22416, 6.22662, 6.2292, 6.2319, 6.23473, 6.23767, 6.24074, 6.24392, 6.24723, 6.25067, 6.25422, 6.2579, 6.2617, 6.26563, 6.26968, 6.27385, 6.27815, 6.28258, 6.28713, 6.29181, 6.29662, 6.30155, 6.30661, 6.3118, 6.31712, 6.32257, 6.32814, 6.33385, 6.33969, 6.34566, 6.35176, 6.358, 6.36437, 6.37087, 6.37751, 6.38429, 6.3912, 6.39824, 6.40543, 6.41275, 6.42022, 6.42782, 6.43556, 6.44345, 6.45147, 6.45964, 6.46796, 6.47642, 6.48502, 6.49377, 6.50267, 6.51172, 6.52092, 6.53027, 6.53976, 6.54942, 6.55922, 6.56918, 6.5793, 6.58957, 6.6, 6.61059, 6.62134, 6.63225, 6.64333, 6.65457, 6.66597, 6.67754, 6.68928, 6.70118, 6.71326, 6.72551, 6.73793, 6.75053, 6.7633, 6.77625, 6.78939, 6.8027, 6.81619, 6.82987, 6.84373, 6.85778, 6.87202, 6.88645, 6.90107, 6.91589, 6.9309, 6.94611, 6.96152, 6.97713, 6.99295, 7.00897, 7.0252, 7.04163, 7.05828, 7.07515, 7.09223, 7.10953, 7.12705, 7.14479, 7.16275, 7.18095, 7.19937, 7.21803, 7.23692, 7.25605, 7.27543, 7.29504, 7.3149, 7.33501, 7.35536, 7.37598, 7.39685, 7.41798, 7.43937, 7.46103, 7.48296, 7.50516, 7.52764, 7.55039, 7.57343, 7.59676, 7.62037, 7.64428, 7.66849, 7.69299, 7.7178, 7.74292, 7.76835, 7.75592, 7.71183, 7.66837, 7.62555, 7.58335, 7.54175, 7.50075, 7.46034, 7.4205, 7.38122, 7.34249, 7.30431, 7.26666, 7.22953, 7.19292, 7.15681, 7.12119, 7.08607, 7.05142, 7.01724, 6.98353, 6.95026, 6.91745, 6.88507, 6.85313, 6.82161, 6.7905, 6.75981, 6.72952, 6.69963, 6.67013, 6.64101, 6.61227, 6.58391, 6.55591, 6.52827, 6.50099, 6.47405, 6.44747, 6.42122, 6.3953, 6.36971, 6.34445, 6.31951, 6.29488, 6.27057, 6.24655, 6.22284, 6.19943, 6.17631, 6.15348, 6.13093, 6.10866, 6.08667, 6.06495, 6.0435, 6.02232, 6.0014, 5.98073, 5.96032, 5.94017, 5.92026, 5.90059, 5.88117, 5.86199, 5.84304, 5.82433, 5.80584, 5.78758, 5.76955, 5.75173, 5.73414, 5.71676, 5.69959, 5.68264, 5.66589, 5.64935, 5.63301, 5.61687, 5.60094, 5.58519, 5.56964, 5.55429, 5.53912, 5.52414, 5.50935, 5.49474, 5.48031, 5.46606, 5.45198, 5.43809, 5.42436, 5.41081, 5.39743, 5.38421, 5.37117, 5.35829, 5.34557, 5.33301, 5.32061, 5.30837, 5.29629, 5.28436, 5.27259, 5.26097, 5.2495, 5.23818, 5.22701, 5.21598, 5.2051, 5.19436, 5.18377, 5.17332, 5.163, 5.15283, 5.14279, 5.1329, 5.12313, 5.1135, 5.10401, 5.09464, 5.08541, 5.0763, 5.06733, 5.05848, 5.04976, 5.04117, 5.0327, 5.02435, 5.01613, 5.00803, 5.00005, 5.04308, 5.10535, 5.16927, 5.23491, 5.30234, 5.37164, 5.44288, 5.46606, 5.45839, 5.45085, 5.44344, 5.43615, 5.42898, 5.42193, 5.41501, 5.40821, 5.40152, 5.39496, 5.38851, 5.38218, 5.37597, 5.36987, 5.36389, 5.35803, 5.35228, 5.34664, 5.34112, 5.33571, 5.33041, 5.32523, 5.32015, 5.31519, 5.31033, 5.30559, 5.30096, 5.29643, 5.29201, 5.2877, 5.2835, 5.27941, 5.27542, 5.27154, 5.26776, 5.26409, 5.26053, 5.25707, 5.25371, 5.25046, 5.24731, 5.24427, 5.24133, 5.23849, 5.23576, 5.23312, 5.23059, 5.22817, 5.22584, 5.22361, 5.22149, 5.21947, 5.21754, 5.21572, 5.214, 5.21238, 5.21086, 5.20944, 5.20812, 5.2069, 5.20578, 5.20476, 5.20384, 5.20301, 5.20229, 5.20167, 5.20114, 5.20071, 5.20039, 5.20016, 5.20003, 5.2, 5.20007, 5.20024, 5.20051, 5.20087, 5.20134, 5.2019, 5.20257, 5.20333, 5.20419, 5.20515, 5.20622, 5.20738, 5.20864, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 8.84711, 8.86286, 8.87883, 8.89503, 8.91146, 8.92812, 8.94501, 8.96214, 8.97951, 8.99711, 9.01496, 9.03305, 9.05139, 9.06997, 9.0888, 9.10789, 9.12722, 9.14682, 9.16668, 9.18679, 9.20717, 9.22782, 9.24874, 9.21982, 9.14423, 9.07004, 8.99722, 8.92572, 8.85552, 8.78658, 8.71887, 8.65236, 8.58702, 8.52282, 8.45974, 8.39773, 8.33679, 8.27689, 8.21799, 8.16008, 8.10313, 8.04712, 7.99204, 7.93785, 7.88455, 7.8321, 7.78049, 7.7297, 7.67972, 7.63053, 7.5821, 7.53443, 7.48749, 7.44128, 7.39577, 7.35096, 7.30682, 7.26335, 7.22053, 7.17835, 7.13679, 7.09585, 7.0555, 7.01575, 6.97657, 6.93796, 6.8999, 6.86239, 6.82541, 6.78896, 6.75303, 6.76833, 6.79309, 6.81817, 6.84356, 6.86927, 6.8953, 6.92167, 6.94837, 6.97541, 7.0028, 7.03053, 7.05862, 7.08708, 7.1159, 7.14509, 7.17466, 7.20461, 7.23495, 7.26569, 7.29683, 7.32837, 7.36034, 7.39272, 7.42553, 7.45878, 7.49247, 7.52661, 7.5612, 7.59626, 7.6318, 7.66781, 7.70431, 7.74131, 7.77882, 7.81684, 7.85539, 7.89446, 7.93408, 7.97426, 8.01499, 8.0563, 8.09819, 8.14067, 8.18376, 8.22747, 8.2718, 8.31677, 8.36239, 8.40868, 8.45565, 8.5033, 8.55166, 8.60074, 8.65055, 8.70111, 8.75242, 8.80452, 8.85741, 8.91111, 8.96564, 9.02101, 9.07724, 9.13435, 9.19237, 9.2513, 9.31117, 9.372, 9.43381, 9.49662, 9.56046, 9.62535, 9.69131, 9.75836, 9.82654, 9.89587, 9.96638, 10.0381, 10.111, 10.1852, 10.2607, 10.3376, 10.4157, 10.4953, 10.5763, 10.6588, 10.7428, 10.8283, 10.9154, 11.0041, 11.0945, 11.1866, 11.2805, 11.3761, 11.4736, 11.5731, 11.6745, 11.7779, 11.8834, 11.991, 12.1008, 12.2129, 12.3273, 12.4441, 12.5635, 12.6853, 4.158, 4.15, 4.14211, 4.13432, 4.12664, 4.11907, 4.11161, 4.10425, 4.09699, 4.08984, 4.08279, 4.07584, 4.06899, 4.06224, 4.05559, 4.04904, 4.04259, 4.03624, 4.02998, 4.02382, 4.01775, 4.01178, 4.0059, 4.00012, 3.99443, 3.98883, 3.98332, 3.9779, 3.97257, 3.96733, 3.96218, 3.95712, 3.95215, 3.94727, 3.94247, 3.93776, 3.93313, 3.92859, 3.92414, 3.91977, 3.91548, 3.91128, 3.90716, 3.90312, 3.89917, 3.8953, 3.89151, 3.8878, 3.88418, 3.88063, 3.87716, 3.87378, 3.87047, 3.86724, 3.86409, 3.86102, 3.85803, 3.85511, 3.85228, 3.84952, 3.84684, 3.84423, 3.8417, 3.83925, 3.83688, 3.83458, 3.83235, 3.8302, 3.82813, 3.82613, 3.82421, 3.82236, 3.82058, 3.81888, 3.81726, 3.8157, 3.81423, 3.81282, 3.81149, 3.81023, 3.80905, 3.80794, 3.8069, 3.80593, 3.80504, 3.80422, 3.80348, 3.8028, 3.8022, 3.80167, 3.80122, 3.80083, 3.80052, 3.80028, 3.80012, 3.80002, 3.8, 3.80005, 3.80018, 3.80037, 3.80064, 3.80098, 3.80139, 3.80188, 3.80243, 3.80306, 3.80377, 3.80454, 3.80539, 3.80631, 3.80731, 3.80837, 3.80951, 3.81073, 5.31676, 5.31865, 5.32065, 5.32276, 5.32496, 5.32727, 5.32968, 5.3322, 5.33482, 5.33755, 5.34038, 5.34331, 5.34635, 5.34949, 5.35274, 5.3561, 5.35956, 5.36313, 5.36681, 5.37059, 5.37448, 5.37848, 5.38259, 5.38681, 5.39113, 5.39557, 5.40012, 5.40477, 5.40954, 5.41442, 5.41941, 5.42452, 5.42973, 5.43506, 5.44051, 5.44607, 5.45174, 5.45754, 5.46344, 5.46947, 5.47561, 5.48187, 5.48825, 5.49475, 5.50137, 5.50811, 5.51497, 5.52195, 5.52906, 5.53629, 5.54365, 5.55113, 5.55874, 5.56647, 5.57433, 5.58232, 5.59044, 5.59869, 5.60708, 5.61559, 5.62424, 5.63302, 5.64194, 5.65099, 5.66018, 5.66951, 5.67897, 5.68858, 5.69833, 5.70822, 5.71825, 5.72843, 5.73876, 5.74923, 5.75985, 5.77061, 5.78153, 5.79261, 5.80383, 5.81521, 5.82674, 5.83844, 5.85029, 5.8623, 5.87447, 5.8868, 5.8993, 5.91197, 5.9248, 5.9378, 5.95098, 5.96432, 5.97784, 5.99154, 6.00541, 6.01946, 6.0337, 6.04811, 6.06271, 6.0775, 6.09247, 6.10764, 6.123, 6.13855, 6.1543, 6.17025, 6.1864, 6.20276, 6.21932, 6.23608, 6.25306, 6.27025, 6.28765, 6.30527, 6.32311, 6.34117, 6.35946, 6.37798, 6.39672, 6.4157, 6.43492, 6.45437, 6.47406, 6.494, 6.51419, 6.53463, 6.55532, 6.57627, 6.59748, 6.61895, 6.64069, 6.6627, 6.68498, 6.70754, 6.73039, 6.75352, 6.77693, 6.80064, 6.82465, 6.84896, 6.87357, 6.89849, 6.92373, 6.94929, 6.97516, 7.00137, 7.0279, 7.05478, 7.08199, 7.10955, 7.13746, 7.16573, 7.19437, 7.22337, 7.25274, 7.28249, 7.31263, 7.34316, 7.37408, 7.40541, 7.43715, 7.4693, 7.50188, 7.53489, 7.56833, 7.60222, 7.63655, 7.67135, 7.70661, 7.74235, 7.77856, 7.81527, 7.85247, 7.82933, 7.79855, 7.76815, 7.73814, 7.70851, 7.67925, 7.65036, 7.62183, 7.59365, 7.56583, 7.53835, 7.51121, 7.48441, 7.45794, 7.4318, 7.40598, 7.38048, 7.35529, 7.33042, 7.30585, 7.28158, 7.25762, 7.23394, 7.21056, 7.18747, 7.16465, 7.14212, 7.11987, 7.09788, 7.07617, 7.05472, 7.03354, 7.01262, 6.99195, 6.97154, 6.95138, 6.93146, 6.91179, 6.89237, 6.87318, 6.85423, 6.83551, 6.81702, 6.79877, 6.78074, 6.76293, 6.74534, 6.72798, 6.71083, 6.69389, 6.67717, 6.66066, 6.64435, 6.62825, 6.61235, 6.59666, 6.58116, 6.56586, 6.55076, 6.53585, 6.52113, 6.5066, 6.49226, 6.47811, 6.46414, 6.45035, 6.45668, 6.51582, 6.57618, 6.63779, 6.7007, 6.76494, 6.83055, 6.89758, 6.96608, 7.03608, 7.10765, 7.18082, 7.25565, 7.3322, 7.41053, 7.49069, 7.57275, 7.65678, 7.74284, 7.831, 7.92136, 8.01397, 8.10893, 8.20633, 8.30626, 8.40881, 8.51409, 8.62221, 8.73327, 8.84741, 8.96474, 9.0854, 9.20952, 9.22452, 9.21197, 9.19964, 9.18751, 9.17558, 9.16386, 9.15235, 9.14104, 9.12993, 9.11902, 9.1083, 9.09779, 9.08748, 9.07736, 9.06743, 9.0577, 9.04816, 9.03882, 9.02966, 9.0207, 9.01192, 9.00333, 8.99493, 8.98672, 8.97869, 8.97085, 8.96319, 8.95571, 8.94842, 8.94131, 8.93438, 8.92763, 8.92107, 8.91468, 8.90847, 8.90243, 8.89658, 8.8909, 8.8854, 8.88007, 8.87492, 8.86994, 8.86514, 8.86051, 8.85606, 8.85177, 8.84766, 8.84373, 8.83996, 8.83637, 8.83294, 8.82969 };
+
diff --git a/test/testData.h b/test/testData.h
new file mode 100644
index 0000000000000000000000000000000000000000..3dcae10a8f87afbc5d18702509096731d75f28aa
--- /dev/null
+++ b/test/testData.h
@@ -0,0 +1,28 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+extern double testRanges[];
+
+extern double testRanges2[];
+
+extern double testRangesOrtho1[];
+
+extern double testRangesOrtho2[];
diff --git a/test/testFalkoAHT.cpp b/test/testFalkoAHT.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a392817300ae36a128d331e59c92c34afe772083
--- /dev/null
+++ b/test/testFalkoAHT.cpp
@@ -0,0 +1,110 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <iostream>
+
+
+#include <falkolib/Feature/FALKO.h>
+#include <falkolib/Feature/BSC.h>
+#include <falkolib/Feature/FALKOExtractor.h>
+
+#include <falkolib/Feature/BSCExtractor.h>
+
+#include <falkolib/Matching/NNMatcher.h>
+#include <falkolib/Matching/AHTMatcher.h>
+
+#include "testData.h"
+
+using namespace std;
+using namespace falkolib;
+
+int main(int argc, char** argv) {
+	LaserScan scan1(-0.003316126, 2.0 * M_PI, 1440);
+	scan1.fromRanges(testRanges);
+	LaserScan scan2(-0.003316126, 2.0 * M_PI, 1440);
+	scan2.fromRanges(testRanges2);
+
+	FALKOExtractor fe;
+	fe.setMinExtractionRange(0);
+	fe.setMaxExtractionRange(30);
+	fe.enableSubbeam(true);
+	fe.setNMSRadius(0.1);
+	fe.setNeighB(0.07);
+	fe.setBRatio(2.5);
+	fe.setGridSectors(16);
+
+	std::vector<FALKO> keypoints1;
+	std::vector<FALKO> keypoints2;
+
+
+	fe.extract(scan1, keypoints1);
+	fe.extract(scan2, keypoints2);
+
+	cout << "num keypoints1 extracted: " << keypoints1.size() << endl;
+	cout << "num keypoints2 extracted: " << keypoints2.size() << endl;
+
+	BSCExtractor<FALKO> bsc(16, 8);
+	vector<BSC> bscDesc1;
+	vector<BSC> bscDesc2;
+
+
+	bsc.compute(scan1, keypoints1, bscDesc1);
+	bsc.compute(scan2, keypoints2, bscDesc2);
+
+
+
+
+	NNMatcher<FALKO> matcher;
+	matcher.setDistanceThreshold(0.1);
+	std::vector<std::pair<int, int> > assoNN;
+	std::cout << "num matching NN: " << matcher.match(keypoints1, keypoints2, assoNN) << endl;
+	for (auto& match : assoNN) {
+		if (match.second >= 0) {
+			int i1 = match.first;
+			int i2 = match.second;
+			std::cout << "i1: " << i1 << "\ti2: " << i2 << "\t keypoints distance: " << (keypoints1[i1].distance(keypoints2[i2])) << endl;
+		}
+	}
+
+	cout << endl;
+	AHTMatcher<FALKO> aht(0.01, 0.01, 0.001, 0.2, 0.2, 0.05);
+	aht.setDistanceThreshold(0.1);
+	std::vector<std::pair<int, int> > assoAHT;
+	std::cout << "num matching AHT: " << aht.match(keypoints1, keypoints2, assoAHT) << endl;
+	for (auto& match : assoAHT) {
+		if (match.second >= 0) {
+			int i1 = match.first;
+			int i2 = match.second;
+			std::cout << "i1: " << i1 << "\ti2: " << i2 << "\t keypoints distance: " << (keypoints1[i1].distance(keypoints2[i2])) << endl;
+		}
+	}
+	
+	Eigen::Affine2d transformNN;
+	Eigen::Affine2d transformAHT;
+	computeTransform(keypoints1, keypoints2, assoNN, transformNN);
+	computeTransform(keypoints1, keypoints2, assoAHT, transformAHT);
+	
+	std::cout << "NN transform: " << std::endl;
+	std::cout << transformNN.inverse().matrix() << std::endl;
+	std::cout << "AHT transform: " << std::endl;
+	std::cout << transformAHT.inverse().matrix() << std::endl;
+
+	return 0;
+}
+
diff --git a/test/testFalkoCC.cpp b/test/testFalkoCC.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..63441839bfde80db5cd3ab14714e561d3496e280
--- /dev/null
+++ b/test/testFalkoCC.cpp
@@ -0,0 +1,111 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <iostream>
+
+
+#include <falkolib/Feature/FALKO.h>
+#include <falkolib/Feature/BSC.h>
+#include <falkolib/Feature/FALKOExtractor.h>
+
+#include <falkolib/Feature/BSCExtractor.h>
+
+#include <falkolib/Matching/NNMatcher.h>
+#include <falkolib/Matching/CCDAMatcher.h>
+
+#include "testData.h"
+
+using namespace std;
+using namespace falkolib;
+
+int main(int argc, char** argv) {
+	LaserScan scan1(-0.003316126, 2.0 * M_PI, 1440);
+	scan1.fromRanges(testRanges);
+	LaserScan scan2(-0.003316126, 2.0 * M_PI, 1440);
+	scan2.fromRanges(testRanges2);
+
+	FALKOExtractor fe;
+	fe.setMinExtractionRange(0);
+	fe.setMaxExtractionRange(30);
+	fe.enableSubbeam(true);
+	fe.setNMSRadius(0.1);
+	fe.setNeighB(0.07);
+	fe.setBRatio(2.5);
+	fe.setGridSectors(16);
+
+	std::vector<FALKO> keypoints1;
+	std::vector<FALKO> keypoints2;
+
+
+	fe.extract(scan1, keypoints1);
+	fe.extract(scan2, keypoints2);
+
+	cout << "num keypoints1 extracted: " << keypoints1.size() << endl;
+	cout << "num keypoints2 extracted: " << keypoints2.size() << endl;
+
+	BSCExtractor<FALKO> bsc(16, 8);
+	vector<BSC> bscDesc1;
+	vector<BSC> bscDesc2;
+
+
+	bsc.compute(scan1, keypoints1, bscDesc1);
+	bsc.compute(scan2, keypoints2, bscDesc2);
+
+
+
+
+	NNMatcher<FALKO> matcher;
+	matcher.setDistanceThreshold(0.1);
+	std::vector<std::pair<int, int> > assoNN;
+	std::cout << "num matching NN: " << matcher.match(keypoints1, keypoints2, assoNN) << endl;
+	for (auto& match : assoNN) {
+		if (match.second >= 0) {
+			int i1 = match.first;
+			int i2 = match.second;
+			std::cout << "i1: " << i1 << "\ti2: " << i2 << "\t keypoints distance: " << (keypoints1[i1].distance(keypoints2[i2])) << endl;
+		}
+	}
+
+	cout << endl;
+	CCDAMatcher<FALKO> cc;
+	cc.setDistMin(0.05);
+	cc.setDistTol(0.1);
+	std::vector<std::pair<int, int> > assoCC;
+	std::cout << "num matching CC: " << cc.match(keypoints1, keypoints2, assoCC) << endl;
+	for (auto& match : assoCC) {
+		if (match.second >= 0) {
+			int i1 = match.first;
+			int i2 = match.second;
+			std::cout << "i1: " << i1 << "\ti2: " << i2 << "\t keypoints distance: " << (keypoints1[i1].distance(keypoints2[i2])) << endl;
+		}
+	}
+	
+//	Eigen::Affine2d transformNN;
+//	Eigen::Affine2d transformCC;
+//	computeTransform(keypoints1, keypoints2, assoNN, transformNN);
+//	computeTransform(keypoints1, keypoints2, assoCC, transformCC);
+//	
+//	std::cout << "NN transform: " << std::endl;
+//	std::cout << transformNN.inverse().matrix() << std::endl;
+//	std::cout << "AHT transform: " << std::endl;
+//	std::cout << transformCC.inverse().matrix() << std::endl;
+
+	return 0;
+}
+
diff --git a/test/testKeypointFalko.cpp b/test/testKeypointFalko.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..71f7a961ec6470b8b47f7bfc539e57ba938c45b5
--- /dev/null
+++ b/test/testKeypointFalko.cpp
@@ -0,0 +1,147 @@
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <iostream>
+
+
+#include <falkolib/Feature/FALKO.h>
+#include <falkolib/Feature/CGH.h>
+#include <falkolib/Feature/BSC.h>
+#include <falkolib/Feature/FALKOExtractor.h>
+
+#include <falkolib/Feature/BSCExtractor.h>
+#include <falkolib/Feature/CGHExtractor.h>
+
+#include <falkolib/Matching/NNMatcher.h>
+#include <falkolib/Matching/AHTMatcher.h>
+
+#include "testData.h"
+
+using namespace std;
+using namespace falkolib;
+
+int main(int argc, char** argv) {
+	FALKOExtractor fe;
+	fe.setMinExtractionRange(1);
+	fe.setMaxExtractionRange(30);
+	fe.enableSubbeam(true);
+	fe.setNMSRadius(0.1);
+	fe.setNeighB(0.07);
+	fe.setBRatio(2.5);
+	fe.setGridSectors(16);
+
+	LaserScan scan1(-0.003316126, 2.0 * M_PI, 1440);
+	scan1.fromRanges(testRanges);
+	LaserScan scan2(-0.003316126, 2.0 * M_PI, 1440);
+	scan2.fromRanges(testRanges2);
+
+	std::vector<FALKO> keypoints1;
+	std::vector<FALKO> keypoints2;
+
+
+	fe.extract(scan1, keypoints1);
+	fe.extract(scan2, keypoints2);
+
+	cout << "num keypoints1 extracted: " << keypoints1.size() << endl;
+	cout << "num keypoints2 extracted: " << keypoints2.size() << endl;
+
+	CGHExtractor<FALKO> cgh(16);
+	BSCExtractor<FALKO> bsc(16, 8);
+
+	vector<CGH> cghDesc1;
+	vector<CGH> cghDesc2;
+	vector<BSC> bscDesc1;
+	vector<BSC> bscDesc2;
+
+
+	cgh.compute(scan1, keypoints1, cghDesc1);
+	bsc.compute(scan1, keypoints1, bscDesc1);
+	cgh.compute(scan2, keypoints2, cghDesc2);
+	bsc.compute(scan2, keypoints2, bscDesc2);
+	
+	
+	
+	cout << endl;
+	NNMatcher<FALKO> matcher;
+	matcher.setDistanceThreshold(0.1);
+	std::vector<std::pair<int, int> > asso;
+	std::cout << "num matching NN: " << matcher.match(keypoints1, keypoints2, asso) << endl;
+	for (auto& match : asso) {
+		if (match.second >= 0) {
+			int i1 = match.first;
+			int i2 = match.second;
+			std::cout << "i1: " << i1 << "\ti2: " << i2 << "\t keypoints distance: " << (keypoints1[i1].distance(keypoints2[i2])) << "\t CHG Distance: " << (cghDesc1[i1].distance(cghDesc2[i2])) << "\t BSC Distance: " << (bscDesc1[i1].distance(bscDesc2[i2])) << endl;
+		}
+	}
+	
+	cout << endl;
+	NNMatcher<FALKO, BSC> matcherFALKOBSC;
+	matcherFALKOBSC.setDistanceThreshold(0.1);
+	matcherFALKOBSC.setDescriptorThreshold(15);
+	std::cout << "num matching NN FALKO BSC: " << matcherFALKOBSC.match(keypoints1, bscDesc1, keypoints2, bscDesc2, asso) << endl;
+	for (auto& match : asso) {
+		if (match.second >= 0) {
+			int i1 = match.first;
+			int i2 = match.second;
+			std::cout << "i1: " << i1 << "\ti2: " << i2 << "\t keypoints distance: " << (keypoints1[i1].distance(keypoints2[i2])) << "\t CHG Distance: " << (cghDesc1[i1].distance(cghDesc2[i2])) << "\t BSC Distance: " << (bscDesc1[i1].distance(bscDesc2[i2])) << endl;
+		}
+	}
+	
+	cout << endl;
+	NNMatcher<FALKO, CGH> matcherFALKOCGH;
+	matcherFALKOCGH.setDistanceThreshold(0.1);
+	matcherFALKOCGH.setDescriptorThreshold(0.2);
+	std::cout << "num matching NN FALKO CGH: " << matcherFALKOCGH.match(keypoints1, cghDesc1, keypoints2, cghDesc2, asso) << endl;
+	for (auto& match : asso) {
+		if (match.second >= 0) {
+			int i1 = match.first;
+			int i2 = match.second;
+			std::cout << "i1: " << i1 << "\ti2: " << i2 << "\t keypoints distance: " << (keypoints1[i1].distance(keypoints2[i2])) << "\t CHG Distance: " << (cghDesc1[i1].distance(cghDesc2[i2])) << "\t BSC Distance: " << (bscDesc1[i1].distance(bscDesc2[i2])) << endl;
+		}
+	}
+	
+	cout << endl;
+	NNMatcher<BSC> matcherBSC;
+	matcherBSC.setDistanceThreshold(15);
+	std::cout << "num matching NN BSC: " << matcherBSC.match(bscDesc1, bscDesc2, asso) << endl;
+	for (auto& match : asso) {
+		if (match.second >= 0) {
+			int i1 = match.first;
+			int i2 = match.second;
+			std::cout << "i1: " << i1 << "\ti2: " << i2 << "\t keypoints distance: " << (keypoints1[i1].distance(keypoints2[i2])) << "\t CHG Distance: " << (cghDesc1[i1].distance(cghDesc2[i2])) << "\t BSC Distance: " << (bscDesc1[i1].distance(bscDesc2[i2])) << endl;
+		}
+	}
+	cout << endl;
+	NNMatcher<CGH> matcherCGH;
+	matcherCGH.setDistanceThreshold(0.2);
+	std::cout << "num matching NN CGH: " << matcherCGH.match(cghDesc1, cghDesc2, asso) << endl;
+	for (auto& match : asso) {
+		if (match.second >= 0) {
+			int i1 = match.first;
+			int i2 = match.second;
+			std::cout << "i1: " << i1 << "\ti2: " << i2 << "\t keypoints distance: " << (keypoints1[i1].distance(keypoints2[i2])) << "\t CHG Distance: " << (cghDesc1[i1].distance(cghDesc2[i2])) << "\t BSC Distance: " << (bscDesc1[i1].distance(bscDesc2[i2])) << endl;
+		}
+	}
+	
+	AHTMatcher<FALKO> aht;
+	
+
+	return 0;
+}
+
diff --git a/test/testKeypointOC.cpp b/test/testKeypointOC.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6ca64080653ab34ca2770bc8de0a30017b8bf782
--- /dev/null
+++ b/test/testKeypointOC.cpp
@@ -0,0 +1,105 @@
+#include <iostream>
+/**
+ * FALKOLib - Fast Adaptive Laser Keypoint Orientation-invariant
+ * Copyright (C) 2016 Fabjan Kallasi and Dario Lodi Rizzini.
+ *
+ * This file is part of FALKOLib.
+ *
+ * FALKOLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * FALKOLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FALKOLib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <falkolib/Feature/OC.h>
+#include <falkolib/Feature/CGH.h>
+#include <falkolib/Feature/BSC.h>
+
+#include <falkolib/Feature/OCExtractor.h>
+#include <falkolib/Feature/BSCExtractor.h>
+#include <falkolib/Feature/CGHExtractor.h>
+
+#include <falkolib/Matching/NNMatcher.h>
+#include <falkolib/Matching/CCDAMatcher.h>
+
+#include "testData.h"
+
+//#ifdef FEATURELIB_DEBUG
+//#include <gnuplot-iostream.h>
+//#endif
+
+using namespace std;
+using namespace falkolib;
+
+int main(int argc, char** argv) {
+    OCExtractor oe;
+    oe.setAngleRes(M_PI / 180.0 * 0.25);
+    oe.setTol(0.1);
+    oe.setRangeRes(0.05);
+    oe.setRangeMax(10.0);
+    oe.setNMSRadius(0.3);
+    oe.setNeighMinPoint(2);
+
+    LaserScan scan1(-0.003316126, 2.0 * M_PI, 1440);
+    scan1.fromRanges(testRangesOrtho1);
+    LaserScan scan2(-0.003316126, 2.0 * M_PI, 1440);
+    scan2.fromRanges(testRangesOrtho2);
+
+    std::vector<OC> keypoints1;
+    std::vector<OC> keypoints2;
+
+    std::cout << "extract OC keypoints: " << std::endl;
+    oe.extract(scan1, keypoints1);
+    oe.extract(scan2, keypoints2);
+
+    cout << "num keypoints1 extracted: " << keypoints1.size() << endl;
+    for (auto& kp : keypoints1) {
+        std::cout << kp.point.transpose() << ", index " << kp.index << ", radius " << kp.radius << ", orientation [deg] " << (180.0 / M_PI * kp.orientation) << std::endl;
+    }
+
+    cout << "num keypoints2 extracted: " << keypoints2.size() << endl;
+    for (auto& kp : keypoints2) {
+        std::cout << kp.point.transpose() << ", index " << kp.index << ", radius " << kp.radius << ", orientation [deg] " << (180.0 / M_PI * kp.orientation) << std::endl;
+    }
+
+//#ifdef FEATURELIB_DEBUG
+//    Gnuplot gp("gnuplot -persist");
+//    gp << "set size ratio -1\n";
+//    for (int i = 0; i < scan1.points.size(); i += 10) {
+//        gp << "set label \"" << i << "\" at " << scan1.points[i].x() << "," << scan1.points[i].y() << "\n";
+//    }
+//    gp << "plot '-' u 1:2 notitle pt 7 w p, '-' u 1:2 notitle pt 7 w p\n";
+//    for (auto& p : scan1.points) {
+//        gp << p.x() << " " << p.y() << "\n";
+//    }
+//    gp << "e" << std::endl;
+//    for (auto& kp : keypoints1) {
+//        gp << kp.point.x() << " " << kp.point.y() << "\n";
+//    }
+//    gp << "e" << std::endl;
+//#endif
+
+    CGHExtractor<OC> cgh(16);
+    BSCExtractor<OC> bsc(16, 8);
+
+    vector<CGH> cghDesc1;
+    vector<CGH> cghDesc2;
+    vector<BSC> bscDesc1;
+    vector<BSC> bscDesc2;
+
+
+    cgh.compute(scan1, keypoints1, cghDesc1);
+    bsc.compute(scan1, keypoints1, bscDesc1);
+    cgh.compute(scan2, keypoints2, cghDesc2);
+    bsc.compute(scan2, keypoints2, bscDesc2);
+
+    return 0;
+}
+