[mathic] 02/62: Initial commit of Mathic code.

Doug Torrance dtorrance-guest at moszumanska.debian.org
Wed Apr 1 11:36:17 UTC 2015


This is an automated email from the git hooks/post-receive script.

dtorrance-guest pushed a commit to branch master
in repository mathic.

commit f7bd26d658416b540ff5fd69fa04597a43131bcf
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date:   Sun Jul 8 01:14:15 2012 -0400

    Initial commit of Mathic code.
---
 Makefile.am                              | 104 ++++
 autogen.sh                               |   3 +
 build/autotools/mathic.pc.in             |  12 +
 build/vc10/divsim/divsim.vcxproj         | 133 +++++
 build/vc10/divsim/divsim.vcxproj.filters | 153 ++++++
 build/vc10/divsim/divsim.vcxproj.user    |   3 +
 build/vc10/mathic.sln                    |  26 +
 build/vc10/pqsim/pqsim.vcxproj           | 114 +++++
 configure.ac                             |  79 +++
 fixspace                                 |  51 ++
 include/mathic/mathic.cpp                |  17 +
 include/mathic/mathic.h                  |  27 ++
 replace                                  |  11 +
 src/divsim/DivListModel.h                | 195 ++++++++
 src/divsim/KDTreeModel.h                 | 193 ++++++++
 src/divsim/Monomial.h                    |  52 ++
 src/divsim/Simulation.cpp                |  62 +++
 src/divsim/Simulation.h                  | 310 ++++++++++++
 src/divsim/divMain.cpp                   | 148 ++++++
 src/divsim/divMain.h                     |   6 +
 src/divsim/stdinc.h                      |  57 +++
 src/mathic.h                             |  27 ++
 src/mathic/Action.cpp                    |  17 +
 src/mathic/Action.h                      |  46 ++
 src/mathic/BinaryKDTree.h                | 780 ++++++++++++++++++++++++++++++
 src/mathic/BoolParameter.cpp             |  31 ++
 src/mathic/BoolParameter.h               |  31 ++
 src/mathic/CliParameter.cpp              |  19 +
 src/mathic/CliParameter.h                |  29 ++
 src/mathic/CliParser.cpp                 | 101 ++++
 src/mathic/CliParser.h                   |  50 ++
 src/mathic/ColumnPrinter.cpp             | 185 +++++++
 src/mathic/ColumnPrinter.h               |  64 +++
 src/mathic/ComTree.h                     | 273 +++++++++++
 src/mathic/Comparer.h                    |  18 +
 src/mathic/DivFinder.h                   |  74 +++
 src/mathic/DivList.h                     | 616 +++++++++++++++++++++++
 src/mathic/DivMask.cpp                   |  14 +
 src/mathic/DivMask.h                     | 463 ++++++++++++++++++
 src/mathic/ElementDeleter.cpp            |   1 +
 src/mathic/ElementDeleter.h              | 138 ++++++
 src/mathic/GeoFront.h                    | 375 ++++++++++++++
 src/mathic/Geobucket.h                   | 805 +++++++++++++++++++++++++++++++
 src/mathic/Heap.h                        | 200 ++++++++
 src/mathic/HelpAction.cpp                | 113 +++++
 src/mathic/HelpAction.h                  |  34 ++
 src/mathic/IntegerParameter.cpp          |  36 ++
 src/mathic/IntegerParameter.h            |  31 ++
 src/mathic/KDEntryArray.h                | 493 +++++++++++++++++++
 src/mathic/KDTree.h                      | 366 ++++++++++++++
 src/mathic/NameFactory.cpp               |   1 +
 src/mathic/NameFactory.h                 | 201 ++++++++
 src/mathic/PackedKDTree.h                | 760 +++++++++++++++++++++++++++++
 src/mathic/StlSet.h                      |  68 +++
 src/mathic/StringParameter.cpp           |  22 +
 src/mathic/StringParameter.h             |  32 ++
 src/mathic/Timer.cpp                     |  51 ++
 src/mathic/Timer.h                       |  44 ++
 src/mathic/TourTree.h                    | 261 ++++++++++
 src/mathic/display.cpp                   | 145 ++++++
 src/mathic/display.h                     |  41 ++
 src/mathic/error.cpp                     |  22 +
 src/mathic/error.h                       |  56 +++
 src/mathic/main.cpp                      |  17 +
 src/mathic/stdinc.h                      |  26 +
 src/pqsim/GeobucketModel.h               |  68 +++
 src/pqsim/HeapModel.h                    |  16 +
 src/pqsim/Item.cpp                       |   9 +
 src/pqsim/Item.h                         | 110 +++++
 src/pqsim/Model.cpp                      |   2 +
 src/pqsim/Model.h                        | 202 ++++++++
 src/pqsim/Simulator.cpp                  | 326 +++++++++++++
 src/pqsim/Simulator.h                    | 103 ++++
 src/pqsim/StlSetModel.h                  |  10 +
 src/pqsim/TourTreeModel.h                |  16 +
 src/pqsim/pqMain.cpp                     |  65 +++
 src/pqsim/pqMain.h                       |   6 +
 src/pqsim/stdinc.h                       |  48 ++
 src/test/DivFinder.cpp                   |  10 +
 src/test/gtestInclude.cpp                |  10 +
 src/test/testMain.cpp                    |   6 +
 81 files changed, 9940 insertions(+)

diff --git a/Makefile.am b/Makefile.am
new file mode 100755
index 0000000..2b31892
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,104 @@
+# options passed to aclocal, which is a tool for making macroes visible to
+# autoconf. We use -I to tell aclocal where we put the local macros.
+ACLOCAL_AMFLAGS = -I build/autotools/m4
+
+# Options passed to the C PreProcessor (CPP), NOT the C Plus Plus compiler.
+AM_CPPFLAGS = -I${top_srcdir}/
+libmathic_ at MATHIC_API_VERSION@_la_CPPFLAGS = $(DEPS_CFLAGS)
+
+# tell Libtool what the name of the library is.
+lib_LTLIBRARIES = libmathic- at MATHIC_API_VERSION@.la
+
+# set the C++ compiler to include src/
+AM_CXXFLAGS=-I$(top_srcdir)/src/
+
+# set the linker flags to build libmathic
+#libmathic_ at MATHIC_API_VERSION@_la_LDFLAGS =
+
+# libraries that are needed by this library
+libmathic_ at MATHIC_API_VERSION@_la_LIBADD= $(DEPS_LIBS)
+
+# the sources that are built to make libmathic
+libmathic_ at MATHIC_API_VERSION@_la_SOURCES = src/mathic/Timer.cpp	\
+  src/mathic/ColumnPrinter.cpp src/mathic/DivMask.cpp				\
+  src/mathic/Action.cpp src/mathic/BoolParameter.cpp				\
+  src/mathic/CliParameter.cpp src/mathic/CliParser.cpp				\
+  src/mathic/ElementDeleter.cpp src/mathic/NameFactory.cpp			\
+  src/mathic/error.cpp src/mathic/HelpAction.cpp					\
+  src/mathic/IntegerParameter.cpp src/mathic/StringParameter.cpp	\
+  src/mathic/display.cpp
+
+# The headers that libmathic installs.
+# Normally, automake strips the path from the files when installing them,
+# so src/mathic/x.h gets installed as just x.h.
+mathicA_include_HEADERS = src/mathic.h
+mathicA_includedir = $(includedir)/mathic-$(MATHIC_API_VERSION)
+# install remaining headers into subdirectory of the include dir
+mathicB_includedir = \
+  $(includedir)/mathic-$(MATHIC_API_VERSION)/mathic
+mathicB_include_HEADERS = src/mathic/stdinc.h src/mathic/Timer.h	\
+  src/mathic/ColumnPrinter.h src/mathic/ElementDeleter.h			\
+  src/mathic/error.h src/mathic/DivList.h src/mathic/KDTree.h		\
+  src/mathic/TourTree.h src/mathic/StlSet.h src/mathic/Heap.h		\
+  src/mathic/Geobucket.h src/mathic/Action.h src/mathic/DivMask.h	\
+  src/mathic/BoolParameter.h src/mathic/CliParameter.h				\
+  src/mathic/CliParser.h src/mathic/HelpAction.h					\
+  src/mathic/IntegerParameter.h src/mathic/StringParameter.h		\
+  src/mathic/display.h src/mathic/NameFactory.h
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = build/autotools/mathic-$(MATHIC_API_VERSION).pc
+
+# When making a distribution file, Automake knows to include all files
+# that are necessary to build the project. EXTRA_DIST specifies files
+# to include beyond those used in the build process.
+EXTRA_DIST = autogen.sh
+
+# tell automake what programs are there that are not built automatically
+EXTRA_PROGRAMS = pqsim divsim
+
+# set up the divisor query simulation
+divsim_CPPFLAGS = $(DEPS_CFLAGS)
+divsim_SOURCES = src/divsim/divMain.cpp src/divsim/Simulation.cpp
+divsim_LDADD = $(top_builddir)/libmathic-$(MATHIC_API_VERSION).la
+
+# set up the priority queue simulation
+pqsim_CPPFLAGS = $(DEPS_CFLAGS)
+pqsim_SOURCES = src/pqsim/Item.cpp src/pqsim/Model.cpp	\
+  src/pqsim/pqMain.cpp src/pqsim/Simulator.cpp
+pqsim_LDADD = $(top_builddir)/libmathic-$(MATHIC_API_VERSION).la
+
+
+# set up tests to run on "make check"
+TESTS=unittest
+check_PROGRAMS=$(TESTS)
+
+unittest_CPPFLAGS = $(DEPS_CFLAGS)
+unittest_CXXFLAGS=\
+  -I$(top_srcdir)/libs/gtest/include\
+  -I$(top_srcdir)/libs/gtest/\
+  -I$(top_srcdir)/src/
+unittest_LDADD = $(DEPS_LIBS)
+unittest_LDFLAGS= $(top_builddir)/libmathic-$(MATHIC_API_VERSION).la
+
+test_LIBS=
+unittest_SOURCES=src/test/DivFinder.cpp src/test/gtestInclude.cpp	\
+src/test/testMain.cpp
+
+# allow to download gtest in case of needing to run unit tests
+GTEST_DIR = $(top_srcdir)/libs/
+GTEST_TMP_DIR = $(top_srcdir)/libs/
+GTEST_VERSION = 1.6.0
+GTEST_DOWNLOAD_FILE = gtest-$(GTEST_VERSION).zip
+gtest: $(GTEST_DIR)/gtest
+$(GTEST_DIR)/gtest:
+	mkdir -p $(GTEST_TMP_DIR);
+	rm -rf $(GTEST_TMP_DIR)/$(GTEST_DOWNLOAD_FILE);
+	rm -rf $(GTEST_TMP_DIR)/gtest-$(GTEST_VERSION);
+	rm -rf $(GTEST_TMP_DIR)/gtest;
+	(cd $(GTEST_TMP_DIR); \
+	  wget http://googletest.googlecode.com/files/$(GTEST_DOWNLOAD_FILE); \
+	  unzip $(GTEST_DOWNLOAD_FILE);)
+	rm -rf $(GTEST_DIR)/gtest;
+	mv $(GTEST_TMP_DIR)/gtest-$(GTEST_VERSION) $(GTEST_DIR)/gtest;
+.PHONY: gtest
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..a8f9bcb
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+autoreconf --verbose --install --force `dirname "$0"`
diff --git a/build/autotools/mathic.pc.in b/build/autotools/mathic.pc.in
new file mode 100755
index 0000000..07b91c4
--- /dev/null
+++ b/build/autotools/mathic.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: mathic
+Description: C++ library of symbolic algebra data structures for use in Groebner basis computation.
+URL: https://github.com/broune/mathic
+Requires: memtailor-1.0
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -lmathic- at MATHIC_API_VERSION@
+Cflags: -I${includedir}/mathic- at MATHIC_API_VERSION@/
diff --git a/build/vc10/divsim/divsim.vcxproj b/build/vc10/divsim/divsim.vcxproj
new file mode 100755
index 0000000..e2e0ee2
--- /dev/null
+++ b/build/vc10/divsim/divsim.vcxproj
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{CEF324F2-5D58-48DE-A67F-C7EB21E0737E}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>mathic</RootNamespace>
+    <ProjectName>divsim</ProjectName>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>D:\key\projs\mathic\libs\memtailor\include;D:\key\projs\mathic\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <MinimalRebuild>false</MinimalRebuild>
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>D:\key\projs\mathic\libs\memtailor\include;D:\key\projs\mathic\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\src\Action.cpp" />
+    <ClCompile Include="..\..\src\BoolParameter.cpp" />
+    <ClCompile Include="..\..\src\CliParameter.cpp" />
+    <ClCompile Include="..\..\src\CliParser.cpp" />
+    <ClCompile Include="..\..\src\ColumnPrinter.cpp" />
+    <ClCompile Include="..\..\src\display.cpp" />
+    <ClCompile Include="..\..\src\DivMask.cpp" />
+    <ClCompile Include="..\..\src\divsim\divMain.cpp" />
+    <ClCompile Include="..\..\src\divsim\Simulation.cpp" />
+    <ClCompile Include="..\..\src\ElementDeleter.cpp" />
+    <ClCompile Include="..\..\src\error.cpp" />
+    <ClCompile Include="..\..\src\HelpAction.cpp" />
+    <ClCompile Include="..\..\src\IntegerParameter.cpp" />
+    <ClCompile Include="..\..\src\libs\memtailor.cpp" />
+    <ClCompile Include="..\..\src\NameFactory.cpp" />
+    <ClCompile Include="..\..\src\StringParameter.cpp" />
+    <ClCompile Include="..\..\src\Timer.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\src\Action.h" />
+    <ClInclude Include="..\..\src\BinaryKDTree.h" />
+    <ClInclude Include="..\..\src\BoolParameter.h" />
+    <ClInclude Include="..\..\src\CliParameter.h" />
+    <ClInclude Include="..\..\src\CliParser.h" />
+    <ClInclude Include="..\..\src\ColumnPrinter.h" />
+    <ClInclude Include="..\..\src\Comparer.h" />
+    <ClInclude Include="..\..\src\display.h" />
+    <ClInclude Include="..\..\src\DivFinder.h" />
+    <ClInclude Include="..\..\src\DivList.h" />
+    <ClInclude Include="..\..\src\DivMask.h" />
+    <ClInclude Include="..\..\src\divsim\DivListModel.h" />
+    <ClInclude Include="..\..\src\divsim\KDTreeModel.h" />
+    <ClInclude Include="..\..\src\divsim\Monomial.h" />
+    <ClInclude Include="..\..\src\divsim\Simulation.h" />
+    <ClInclude Include="..\..\src\divsim\stdinc.h" />
+    <ClInclude Include="..\..\src\ElementDeleter.h" />
+    <ClInclude Include="..\..\src\error.h" />
+    <ClInclude Include="..\..\src\HelpAction.h" />
+    <ClInclude Include="..\..\src\IntegerParameter.h" />
+    <ClInclude Include="..\..\src\KDEntryArray.h" />
+    <ClInclude Include="..\..\src\KDTree.h" />
+    <ClInclude Include="..\..\src\NameFactory.h" />
+    <ClInclude Include="..\..\src\PackedKDTree.h" />
+    <ClInclude Include="..\..\src\stdinc.h" />
+    <ClInclude Include="..\..\src\StringParameter.h" />
+    <ClInclude Include="..\..\src\Timer.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/build/vc10/divsim/divsim.vcxproj.filters b/build/vc10/divsim/divsim.vcxproj.filters
new file mode 100755
index 0000000..7361366
--- /dev/null
+++ b/build/vc10/divsim/divsim.vcxproj.filters
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\src\ColumnPrinter.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Timer.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\divsim\divMain.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\divsim\Simulation.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\libs\memtailor.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\DivMask.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Action.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\CliParser.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\BoolParameter.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\CliParameter.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\ElementDeleter.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\error.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\NameFactory.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\HelpAction.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\display.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\IntegerParameter.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\StringParameter.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\src\ColumnPrinter.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\Comparer.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\DivFinder.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\DivList.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\DivMask.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\KDTree.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\stdinc.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\Timer.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\divsim\DivListModel.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\divsim\KDTreeModel.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\divsim\Monomial.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\divsim\Simulation.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\divsim\stdinc.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\BinaryKDTree.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\KDEntryArray.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\PackedKDTree.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\Action.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\CliParser.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\BoolParameter.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\CliParameter.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\ElementDeleter.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\error.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\NameFactory.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\HelpAction.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\display.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\IntegerParameter.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\StringParameter.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/build/vc10/divsim/divsim.vcxproj.user b/build/vc10/divsim/divsim.vcxproj.user
new file mode 100755
index 0000000..695b5c7
--- /dev/null
+++ b/build/vc10/divsim/divsim.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project>
\ No newline at end of file
diff --git a/build/vc10/mathic.sln b/build/vc10/mathic.sln
new file mode 100755
index 0000000..ad8a08f
--- /dev/null
+++ b/build/vc10/mathic.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual C++ Express 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "divsim", "divsim\divsim.vcxproj", "{CEF324F2-5D58-48DE-A67F-C7EB21E0737E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pqsim", "pqsim\pqsim.vcxproj", "{1B6A84DF-114E-46A3-B868-04F203156CF4}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CEF324F2-5D58-48DE-A67F-C7EB21E0737E}.Debug|Win32.ActiveCfg = Debug|Win32
+		{CEF324F2-5D58-48DE-A67F-C7EB21E0737E}.Debug|Win32.Build.0 = Debug|Win32
+		{CEF324F2-5D58-48DE-A67F-C7EB21E0737E}.Release|Win32.ActiveCfg = Release|Win32
+		{CEF324F2-5D58-48DE-A67F-C7EB21E0737E}.Release|Win32.Build.0 = Release|Win32
+		{1B6A84DF-114E-46A3-B868-04F203156CF4}.Debug|Win32.ActiveCfg = Debug|Win32
+		{1B6A84DF-114E-46A3-B868-04F203156CF4}.Debug|Win32.Build.0 = Debug|Win32
+		{1B6A84DF-114E-46A3-B868-04F203156CF4}.Release|Win32.ActiveCfg = Release|Win32
+		{1B6A84DF-114E-46A3-B868-04F203156CF4}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/build/vc10/pqsim/pqsim.vcxproj b/build/vc10/pqsim/pqsim.vcxproj
new file mode 100755
index 0000000..c61a38b
--- /dev/null
+++ b/build/vc10/pqsim/pqsim.vcxproj
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{1B6A84DF-114E-46A3-B868-04F203156CF4}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>pqsim</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>D:\key\projs\mathic\src;D:\key\projs\mathic\libs\memtailor\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>D:\key\projs\mathic\src;D:\key\projs\mathic\libs\memtailor\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\src\ColumnPrinter.cpp" />
+    <ClCompile Include="..\..\src\libs\memtailor.cpp" />
+    <ClCompile Include="..\..\src\pqsim\Item.cpp" />
+    <ClCompile Include="..\..\src\pqsim\Model.cpp" />
+    <ClCompile Include="..\..\src\pqsim\pqMain.cpp" />
+    <ClCompile Include="..\..\src\pqsim\Simulator.cpp" />
+    <ClCompile Include="..\..\src\Timer.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\src\ColumnPrinter.h" />
+    <ClInclude Include="..\..\src\Comparer.h" />
+    <ClInclude Include="..\..\src\ComTree.h" />
+    <ClInclude Include="..\..\src\DivFinder.h" />
+    <ClInclude Include="..\..\src\Geobucket.h" />
+    <ClInclude Include="..\..\src\GeoFront.h" />
+    <ClInclude Include="..\..\src\Heap.h" />
+    <ClInclude Include="..\..\src\pqsim\GeobucketModel.h" />
+    <ClInclude Include="..\..\src\pqsim\HeapModel.h" />
+    <ClInclude Include="..\..\src\pqsim\Item.h" />
+    <ClInclude Include="..\..\src\pqsim\Model.h" />
+    <ClInclude Include="..\..\src\pqsim\pqMain.h" />
+    <ClInclude Include="..\..\src\pqsim\Simulator.h" />
+    <ClInclude Include="..\..\src\pqsim\stdinc.h" />
+    <ClInclude Include="..\..\src\pqsim\StlSetModel.h" />
+    <ClInclude Include="..\..\src\pqsim\TourTreeModel.h" />
+    <ClInclude Include="..\..\src\stdinc.h" />
+    <ClInclude Include="..\..\src\StlSet.h" />
+    <ClInclude Include="..\..\src\Timer.h" />
+    <ClInclude Include="..\..\src\TourTree.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/configure.ac b/configure.ac
new file mode 100755
index 0000000..a1524f1
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,79 @@
+dnl AC_INIT sets up autoconf and must be first macro.
+AC_INIT([mathic], [1.0]) # package, version, bug-report-email
+
+# Check that memtailor is installed and locate it
+PKG_CHECK_MODULES([DEPS], [memtailor-1.0])
+
+# set up information about directories
+AC_CONFIG_MACRO_DIR([build/autotools/m4]) # directory of extra autoconf macroes
+AC_CONFIG_AUX_DIR([build/autotools]) # directory for auxiliary build tools (install-sh etc)
+
+# check that source directory is correct
+dnl  if autoconf is told the source code is in a directory that does not
+dnl  contain this file then it knows that the directory is wrong.
+AC_CONFIG_SRCDIR([src/mathic.h])
+
+# Enable optional maintainer mode (off by default)
+dnl AM_MAINTAINER_MODE turns off automatic reconstruction of the build
+dnl files if the source build files have changed. A developer will want
+dnl those automatic reconstructions to happen so that changes to the
+dnl build system are actually carried out. However, a user might not
+dnl have the tools required to reconfigure and the need for
+dnl reconstruction might be spurious if the last-modified date is set
+dnl incorrectly on the build files.
+dnl
+dnl Passing the option [enable] to AM_MAINTAINER_MODE makes the
+dnl non-reconstruction feature available, but only when turned on by
+dnl passing the option –disable-maintainer-mode. This option is
+dnl apparently useful to some package distributors.
+AM_MAINTAINER_MODE([enable])
+
+# Set up Automake
+dnl foreign: do not create the GNU-specific file COPYING and do not complain
+dnl   that GNU-specific files like NEWS, README, AUTHORS and ChangeLog are
+dnl   missing.
+dnl -Wall: set Automake to emit all warnings it can. Is NOT RELATED to setting
+dnl   warnings for other tools. For example, it wil not make the compiler
+dnl   get a -Wall option.
+dnl subdir-objects: Put object files in a directory structure based on
+dnl   the directory structure of the source files. This way, two source
+dnl   files with the same name in different directories do not conflict.
+AM_INIT_AUTOMAKE([foreign subdir-objects -Wall])
+
+# Set up the $(LN_S) macro, which creates symbolic links
+AC_PROG_LN_S
+
+# set output variable INSTALL to the name of a BSD-compatible install program.
+# Requires install-sh to be present as a fallback, even on systems where
+# the fallback is not used.
+AC_PROG_INSTALL
+
+# Locate the C++ compiler.
+AC_PROG_CXX
+
+# Locate the archiver. This is only necessary in case of using an
+# unusual archiver such as Microsoft lib.
+AM_PROG_AR
+
+# Set up LibTool
+LT_INIT
+
+dnl Set the version for the library -- this concerns compatibility of the
+dnl source and binary interface of the library and is not the same as the
+dnl version of the project.
+AC_SUBST([MATHIC_SO_VERSION], [0:0:0])
+
+dnl Set the version displayed in the pkg-config file. This is currently
+dnl the same as the version of the project but it is possible that
+dnl for example the project will gain a version like x.y.z but that
+dnl the pkg-config file is only named as foo-x.y.pc (no z).
+AC_SUBST([MATHIC_API_VERSION], [1.0])
+
+dnl Set up AC_OUTPUT to create each file by copying an input file
+dnl while substituting the output variable values.
+AC_CONFIG_FILES([Makefile
+  build/autotools/mathic-${MATHIC_API_VERSION}.pc:build/autotools/mathic.pc.in])
+
+dnl Macro that is required to be at the end of any Autoconf script.
+dnl Creates config.status and launches it.
+AC_OUTPUT
diff --git a/fixspace b/fixspace
new file mode 100755
index 0000000..0228dcd
--- /dev/null
+++ b/fixspace
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+# Does the following operations on the files passed as arguments:
+#  - Remove trailing space from lines
+#  - Remove trailing blank lines
+#  - Remove/convert DOS-style line breaks
+#  - Expand tabs to spaces with a tabspace of 8
+
+# I once had an error where the conversion had an error (the computer
+# didn't have dos2unix), resulting in the converted files being empty.
+# The result was that every file got replaced by an empty file! That
+# was not so nice, so this script stops operation as soon as any error
+# occurs, and it also checks that only space has been changed before
+# it overwrites the original file with a space-fixed version.
+
+for f in $*; do echo $f;
+
+  tr -d '\r' < $f > __spaceTmp0;
+  if [ $? != 0 ]; then echo "There was an error removing DOS-style line breaks."; exit 1; fi;
+
+  expand -4 < __spaceTmp0 > __spaceTmp1;
+  if [ $? != 0 ]; then echo "There was an error expanding tabs."; exit 1; fi;
+
+  sed 's/[[:blank:]]*$//g' < __spaceTmp1 > __spaceTmp2;
+  if [ $? != 0 ]; then echo "There was an error eliminating trailing space from lines."; exit 1; fi;
+
+  # Make completely sure that we only changed the spaces
+  diff -EbwB -q $f __spaceTmp2;
+  if [ $? != 0 ]; then echo "There was an error. Conversion not confirmed correct."; exit 1; fi;
+
+  sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' < __spaceTmp2 > __spaceTmp3;
+  if [ $? != 0 ]; then echo "There was an error eliminating trailing blank lines."; exit 1; fi;
+
+  # We have to do diff twice, because diff will not ignore trailing
+  # lines that consist only of spaces. It will ignore changes to space and removal of
+  # completely empty lines, so if we do it twice we get the right thing.
+
+  # Make completely sure that we only changed the spaces
+  diff -EbwB -q __spaceTmp2  __spaceTmp3;
+  if [ $? != 0 ]; then echo "There was an error. Conversion not confirmed correct."; exit 1; fi;
+
+  diff -q $f __spaceTmp3 1>/dev/null;
+  if [ $? != 0 ]; then
+    mv -f __spaceTmp3 $f;
+    if [ $? != 0 ]; then echo "There was an error moving fixed file into place."; exit 1; fi;
+    echo "Fixed space issue for $f."
+  fi
+
+  rm -f __spaceTmp0 __spaceTmp1 __spaceTmp2 __spaceTmp3;
+  if [ $? != 0 ]; then echo "There was an error removing temporary files."; exit 1; fi;
+done;
diff --git a/include/mathic/mathic.cpp b/include/mathic/mathic.cpp
new file mode 100755
index 0000000..97f7d37
--- /dev/null
+++ b/include/mathic/mathic.cpp
@@ -0,0 +1,17 @@
+// This implementation file includes all the implementation files needed
+// to get MemTailor working.
+#include "mathic.h"
+#include "../../src/Timer.cpp"
+#include "../../src/ColumnPrinter.cpp"
+#include "../../src/DivMask.cpp"
+#include "../../src/Action.cpp"
+#include "../../src/BoolParameter.cpp"
+#include "../../src/CliParameter.cpp"
+#include "../../src/CliParser.cpp"
+#include "../../src/ElementDeleter.cpp"
+#include "../../src/NameFactory.cpp"
+#include "../../src/error.cpp"
+#include "../../src/HelpAction.cpp"
+#include "../../src/IntegerParameter.cpp"
+#include "../../src/StringParameter.cpp"
+#include "../../src/display.cpp"
diff --git a/include/mathic/mathic.h b/include/mathic/mathic.h
new file mode 100755
index 0000000..4d46862
--- /dev/null
+++ b/include/mathic/mathic.h
@@ -0,0 +1,27 @@
+// Include this file to pull in all external MemTailor files
+
+// utilities
+#include "../../src/Timer.h"
+#include "../../src/ColumnPrinter.h"
+#include "../../src/ElementDeleter.h"
+#include "../../src/error.h"
+
+// divisor query data structures
+#include "../../src/DivList.h"
+#include "../../src/KDTree.h"
+
+// priority queue data structures
+#include "../../src/TourTree.h"
+#include "../../src/StlSet.h"
+#include "../../src/Heap.h"
+#include "../../src/Geobucket.h"
+
+// CLI package
+#include "../../src/Action.h"
+#include "../../src/BoolParameter.h"
+#include "../../src/CliParameter.h"
+#include "../../src/CliParser.h"
+#include "../../src/HelpAction.h"
+#include "../../src/IntegerParameter.h"
+#include "../../src/StringParameter.h"
+#include "../../src/display.h"
diff --git a/replace b/replace
new file mode 100755
index 0000000..fb8bd7e
--- /dev/null
+++ b/replace
@@ -0,0 +1,11 @@
+#!/bin/bash
+echo "Running script \"sed s/$1/$2/\""
+for i in 1 2 3; do
+  /usr/bin/sleep 1; echo -n .;
+done
+
+for f in `ls src/*.cpp src/*.h`; do
+  echo "Processing $f";
+  sed "s/$1/$2/" < $f > $f.tmp
+  mv $f.tmp $f
+done
diff --git a/src/divsim/DivListModel.h b/src/divsim/DivListModel.h
new file mode 100755
index 0000000..eda34db
--- /dev/null
+++ b/src/divsim/DivListModel.h
@@ -0,0 +1,195 @@
+#ifndef DIV_ARRAY_MODEL_GUARD
+#define DIV_ARRAY_MODEL_GUARD
+
+#include "Monomial.h"
+#include "mathic/DivList.h"
+#include <string>
+#include <vector>
+
+/** Helper class for DivListModel. */
+template<bool UseLinkedList, bool UseDivMask>
+class DivListModelConfiguration;
+
+template<bool ULL, bool UDM>
+class DivListModelConfiguration {
+public:
+  typedef int Exponent;
+  typedef ::Monomial Monomial;
+  typedef Monomial Entry;
+
+  DivListModelConfiguration
+    (size_t varCount,
+    bool sortOnInsert,
+     double rebuildRatio,
+     size_t minRebuild):
+  _varCount(varCount),
+  _sortOnInsert(sortOnInsert),
+  _useAutomaticRebuild((rebuildRatio > 0.0 || minRebuild > 0) && UDM),
+  _rebuildRatio(rebuildRatio),
+  _minRebuild(minRebuild),
+  _expQueryCount(0) {}
+
+  static const bool UseLinkedList = ULL;
+  static const bool UseDivMask = UDM;
+
+  bool getDoAutomaticRebuilds() const {return _useAutomaticRebuild;}
+  double getRebuildRatio() const {return _rebuildRatio;}
+  size_t getRebuildMin() const {return _minRebuild;}
+  bool getSortOnInsert() const {return _sortOnInsert;}
+
+
+  size_t getVarCount() const {return _varCount;}
+
+  Exponent getExponent(const Monomial& monomial, size_t var) const {
+    ++_expQueryCount;
+    ASSERT(var < monomial.size());
+    return monomial[var];
+  }
+
+  bool divides(const Monomial& a, const Monomial& b) const {
+    for (size_t var = 0; var < getVarCount(); ++var)
+      if (getExponent(b, var) < getExponent(a, var))
+        return false;
+    return true;
+  }
+
+  bool isLessThan(const Monomial& a, const Monomial& b) const {
+    for (size_t var = 0; var < getVarCount(); ++var) {
+      if (getExponent(a, var) < getExponent(b, var))
+        return true;
+      if (getExponent(b, var) < getExponent(a, var))
+        return false;
+    }
+    return false;
+  }
+
+  unsigned long long getExpQueryCount() const {return _expQueryCount;}
+
+ private:
+  const size_t _varCount;
+  const bool _sortOnInsert;
+  const bool _useAutomaticRebuild;
+  const double _rebuildRatio;
+  const size_t _minRebuild;
+  mutable unsigned long long _expQueryCount;
+};
+
+template<bool UseLinkedList, bool UseDivMask>
+class DivListModel;
+
+/** An instantiation of the capabilities of DivList. */
+template<bool ULL, bool UDM>
+class DivListModel {
+ private:
+  typedef DivListModelConfiguration<ULL, UDM> C;
+  typedef mathic::DivList<C> Finder;
+ public:
+  typedef typename Finder::iterator iterator;
+  typedef typename Finder::const_iterator const_iterator;
+  typedef typename Finder::Monomial Monomial;
+  typedef typename Finder::Entry Entry;
+
+  DivListModel(size_t varCount,
+              bool minimizeOnInsert,
+              bool moveDivisorToFront,
+              bool sortOnInsert,
+              double rebuildRatio,
+              size_t minRebuild):
+  _finder(C(varCount, sortOnInsert, rebuildRatio, minRebuild)),
+  _minimizeOnInsert(minimizeOnInsert),
+  _moveDivisorToFront(moveDivisorToFront) {
+    ASSERT(!sortOnInsert || !moveDivisorToFront);
+  }
+
+  void insert(const Entry& entry);
+  template<class MultipleOutput>
+  void insert(const Entry& entry, MultipleOutput& removed);
+
+  Entry* findDivisor(const Monomial& monomial) {
+    iterator it = _finder.findDivisorIterator(monomial);
+    if (_moveDivisorToFront && it != _finder.end()) {
+      _finder.moveToFront(it);
+      it = _finder.begin();
+    }
+    return it == end() ? 0 : &*it;
+  }
+  const Entry* findDivisor(const Monomial& monomial) const {
+    return const_cast<DivListModel<ULL, UDM>&>(*this).findDivisor(monomial);
+  }
+
+  template<class DO>
+  void findAllDivisors(const Monomial& monomial, DO& out) {
+    _finder.findAllDivisors(monomial, out);
+  }
+  template<class DO>
+  void findAllDivisors(const Monomial& monomial, DO& out) const {
+    _finder.findAllDivisors(monomial, out);
+  }
+  template<class EO>
+  void forAll(EO& out) {
+    _finder.forAll(out);
+  }
+  template<class EO>
+  void forAll(EO& out) const {
+    _finder.forAll(out);
+  }
+
+  std::string getName() const;
+
+  iterator begin() {return _finder.begin();}
+  const_iterator begin() const {return _finder.begin();}
+  iterator end() {return _finder.end();}
+  const_iterator end() const {return _finder.end();}
+  size_t size() const {return _finder.size();}
+
+  unsigned long long getExpQueryCount() const {
+    return _finder.getConfiguration().getExpQueryCount();
+  }
+
+ private:
+  Finder _finder;
+  const bool _minimizeOnInsert;
+  const bool _moveDivisorToFront;
+};
+
+template<bool ULL, bool UDM>
+inline void DivListModel<ULL, UDM>::insert(const Entry& entry) {
+  if (!_minimizeOnInsert) {
+    _finder.insert(entry);
+    return;
+  }
+  if (findDivisor(entry) != 0)
+    return;
+  bool hasMultiples = _finder.removeMultiples(entry);
+  _finder.insert(entry);
+  if (_moveDivisorToFront && hasMultiples) {
+    iterator it = _finder.end();
+    _finder.moveToFront(--it);
+  }
+}
+
+template<bool ULL, bool UDM>
+template<class MO>
+inline void DivListModel<ULL, UDM>::insert(const Entry& entry, MO& out) {
+  if (!_minimizeOnInsert) {
+    _finder.insert(entry);
+    return;
+  }
+  if (findDivisor(entry) != 0)
+    return;
+  bool hasMultiples = _finder.removeMultiples(entry, out);
+  _finder.insert(entry);
+  if (_moveDivisorToFront && hasMultiples) {
+    iterator it = _finder.end();
+    _finder.moveToFront(--it);
+  }
+}
+
+template<bool ULL, bool UDM>
+inline std::string DivListModel<ULL, UDM>::getName() const {
+  return _finder.getName() +
+    (_minimizeOnInsert ? " remin" : " nomin") +
+    (_moveDivisorToFront ? " toFront" : "");
+}
+
+#endif
diff --git a/src/divsim/KDTreeModel.h b/src/divsim/KDTreeModel.h
new file mode 100755
index 0000000..7b5a44f
--- /dev/null
+++ b/src/divsim/KDTreeModel.h
@@ -0,0 +1,193 @@
+#ifndef K_D_TREE_MODEL_GUARD
+#define K_D_TREE_MODEL_GUARD
+
+#include "Monomial.h"
+#include "mathic/KDTree.h"
+#include <string>
+#include <vector>
+
+template<
+  bool UseDivMask,
+  bool UseTreeDivMask,
+  bool PackedTree,
+  size_t LeafSize,
+  bool AllowRemovals>
+class KDTreeModelConfiguration;
+
+/** Helper class for KDTreeModel. */
+template<bool UDM, bool UTDM, bool PT, size_t LS, bool AR>
+class KDTreeModelConfiguration {
+ public:
+  typedef int Exponent;
+  typedef ::Monomial Monomial;
+  typedef Monomial Entry;
+
+  KDTreeModelConfiguration
+    (size_t varCount,
+     bool sortOnInsert,
+     bool useDivisorCache,
+     double rebuildRatio,
+     size_t minRebuild):
+   _varCount(varCount),
+   _sortOnInsert(sortOnInsert),
+   _useDivisorCache(useDivisorCache),
+   _useAutomaticRebuild((rebuildRatio > 0.0 || minRebuild > 0) && UDM),
+   _rebuildRatio(rebuildRatio),
+   _minRebuild(minRebuild),
+   _expQueryCount(0) {
+     ASSERT(rebuildRatio >= 0);
+   }
+
+  size_t getVarCount() const {return _varCount;}
+  bool getSortOnInsert() const {return _sortOnInsert;}
+
+  Exponent getExponent(const Monomial& monomial, size_t var) const {
+    ++_expQueryCount;
+    ASSERT(var < monomial.size());
+    return monomial[var];
+  }
+
+  NO_PINLINE bool divides(const Monomial& a, const Monomial& b) const {
+    for (size_t var = 0; var < getVarCount(); ++var)
+      if (getExponent(b, var) < getExponent(a, var))
+        return false;
+    return true;
+  }
+
+  bool isLessThan(const Monomial& a, const Monomial& b) const {
+    for (size_t var = 0; var < getVarCount(); ++var) {
+      if (getExponent(a, var) < getExponent(b, var))
+        return true;
+      if (getExponent(b, var) < getExponent(a, var))
+        return false;
+    }
+    return false;
+  }
+
+  size_t getLeafSize() const {return LeafSize;}
+  bool getUseDivisorCache() const {return _useDivisorCache;}
+  bool getDoAutomaticRebuilds() const {return _useAutomaticRebuild;}
+  double getRebuildRatio() const {return _rebuildRatio;}
+  size_t getRebuildMin() const {return _minRebuild;}
+
+  static const bool UseDivMask = UDM;
+  static const bool UseTreeDivMask = UTDM;
+  static const bool PackedTree = PT;
+  static const size_t LeafSize = LS;
+  static const bool AllowRemovals = AR;
+
+  unsigned long long getExpQueryCount() const {return _expQueryCount;}
+
+ private:
+  const size_t _varCount;
+  const bool _sortOnInsert;
+  const bool _useDivisorCache;
+  const bool _useAutomaticRebuild;
+  const double _rebuildRatio;
+  const size_t _minRebuild;
+  mutable unsigned long long _expQueryCount;
+};
+
+/** An instantiation of the capabilities of KDTree. */
+template<
+  bool UseDivMask,
+  bool UseTreeDivMask,
+  bool PackedTree,
+  size_t LeafSize,
+  bool AllowRemovals
+>
+class KDTreeModel {
+ private:
+  typedef KDTreeModelConfiguration
+    <UseDivMask, UseTreeDivMask, PackedTree, LeafSize, AllowRemovals> C;
+  typedef mathic::KDTree<C> Finder;
+ public:
+  typedef typename Finder::Monomial Monomial;
+  typedef typename Finder::Entry Entry;
+
+ KDTreeModel(size_t varCount,
+             bool minimizeOnInsert,
+             bool sortOnInsert,
+             bool useDivisorCache,
+             double rebuildRatio,
+             size_t minRebuild):
+  _finder(C(varCount, sortOnInsert, useDivisorCache, rebuildRatio, minRebuild)),
+  _minimizeOnInsert(minimizeOnInsert) {
+    ASSERT(!UseTreeDivMask || UseDivMask);
+  }
+
+
+  void insert(const Entry& entry);
+  template<class MultipleOutput>
+  void insert(const Entry& entry, MultipleOutput& removed);
+
+  Entry* findDivisor(const Monomial& monomial) {
+    return _finder.findDivisor(monomial);
+  }
+  const Entry* findDivisor(const Monomial& monomial) const {
+    return _finder.findDivisor(monomial);
+  }
+  std::string getName() const;
+
+  template<class DO>
+  void findAllDivisors(const Monomial& monomial, DO& out) {
+    _finder.findAllDivisors(monomial, out);
+  }
+  template<class DO>
+  void findAllDivisors(const Monomial& monomial, DO& out) const {
+    _finder.findAllDivisors(monomial, out);
+  }
+  template<class EO>
+  void forAll(EO& out) {
+    _finder.forAll(out);
+  }
+  template<class EO>
+  void forAll(EO& out) const {
+    _finder.forAll(out);
+  }
+  size_t size() const {return _finder.size();}
+
+  unsigned long long getExpQueryCount() const {
+    return _finder.getConfiguration().getExpQueryCount();
+  }
+
+  class Comparer;
+
+ private:
+  Finder _finder;
+  bool _minimizeOnInsert;
+};
+
+template<bool UDM, bool UTDM, bool PT, size_t LS, bool AR>
+inline void KDTreeModel<UDM, UTDM, PT, LS, AR>::insert(const Entry& entry) {
+  if (!_minimizeOnInsert) {
+    _finder.insert(entry);
+    return;
+  }
+  if (findDivisor(entry) != 0)
+    return;
+  _finder.removeMultiples(entry);
+  _finder.insert(entry);
+}
+
+template<bool UDM, bool UTDM, bool PT, size_t LS, bool AR>
+template<class MultipleOutput>
+inline void KDTreeModel<UDM, UTDM, PT, LS, AR>::
+insert(const Entry& entry, MultipleOutput& removed) {
+  if (!_minimizeOnInsert) {
+    _finder.insert(entry);
+    return;
+  }
+  if (findDivisor(entry) != 0)
+    return;
+  _finder.removeMultiples(entry, removed);
+  _finder.insert(entry);
+}
+
+template<bool UDM, bool UTDM, bool PT, size_t LS, bool AR>
+inline std::string KDTreeModel<UDM, UTDM, PT, LS, AR>::getName() const {
+  return _finder.getName() +
+    (_minimizeOnInsert ? " remin" : " nomin");
+}
+
+#endif
diff --git a/src/divsim/Monomial.h b/src/divsim/Monomial.h
new file mode 100644
index 0000000..45c1c13
--- /dev/null
+++ b/src/divsim/Monomial.h
@@ -0,0 +1,52 @@
+#ifndef MONOMIAL_GUARD
+#define MONOMIAL_GUARD
+
+#include <vector>
+#include <ostream>
+
+class Monomial {
+public:
+  typedef int Exponent;
+
+  Monomial(): _exponents(0) {IF_DEBUG(_size = 0);}
+  Monomial(std::vector<Exponent>& v): _exponents(&v[0]) {
+    IF_DEBUG(_size = v.size());
+  }
+
+  inline Exponent& operator[](size_t index) {
+    ASSERT(index < _size);
+    return _exponents[index];
+  }
+  inline const Exponent& operator[](size_t index) const {
+    ASSERT(index < _size);
+    return _exponents[index];
+  }
+
+  const Exponent* getPointer() const {return _exponents;}
+
+#ifdef DEBUG
+  size_t size() const {return _size;}
+  bool operator==(const Monomial& m) const {return _exponents == m._exponents;}
+  bool operator<(const Monomial& m) const {return _exponents < m._exponents;}
+#endif
+
+private:
+#ifdef DEBUG
+  size_t _size;
+#endif
+  Exponent* _exponents;
+};
+
+inline std::ostream& operator<<(std::ostream& out, const Monomial& monomial) {
+#ifdef DEBUG
+  out << "(Monomial:";
+  for (size_t i = 0; i < monomial.size(); ++i)
+    out << ' ' << monomial[i];
+  out << ')';
+#else
+  out << "(Monomial)";
+#endif
+  return out;
+}
+
+#endif
diff --git a/src/divsim/Simulation.cpp b/src/divsim/Simulation.cpp
new file mode 100755
index 0000000..49ca2f9
--- /dev/null
+++ b/src/divsim/Simulation.cpp
@@ -0,0 +1,62 @@
+#include "stdinc.h"
+#include "Simulation.h"
+
+#include "mathic/ColumnPrinter.h"
+#include <cstdlib>
+#include <algorithm>
+
+namespace {
+  void makeRandom(std::vector<int>& monomial) {
+    for (size_t var = 0; var < monomial.size(); ++var)
+      monomial[var] = rand() % 1000;
+  }
+}
+
+void Simulation::makeStandard
+  (size_t varCount, size_t inserts, size_t queries, bool findAll) {
+  srand(0);
+
+  _findAll = findAll;
+  _varCount = varCount;
+  _events.clear();
+  for (size_t i = 0; i < inserts + queries; ++i) {
+    /*Event event2;
+    event2._type = StateUnknown;
+    _events.push_back(event2);*/
+
+    Event event;
+    event._monomial.resize(varCount);
+    makeRandom(event._monomial);
+    event._type = (i <= inserts ? InsertUnknown : QueryUnknown);
+    _events.push_back(event);
+  }
+}
+
+void Simulation::printData(std::ostream& out) const {
+  std::vector<SimData> sorted(_data);
+  std::sort(sorted.begin(), sorted.end());
+  out << "*** Simulation outcome for "
+      << _repeats << " repeats ***" << std::endl;
+  mic::ColumnPrinter pr;
+  pr.addColumn(true);
+  pr.addColumn(false, " ", "ms");
+  pr.addColumn(false, " ", "eqs");
+  for (std::vector<SimData>::const_iterator it = sorted.begin();
+    it != sorted.end(); ++it) {
+    pr[0] << it->_name << '\n';
+    pr[1] << mic::ColumnPrinter::commafy(it->_mseconds) << '\n';
+    pr[2] << mic::ColumnPrinter::commafy(it->_expQueryCount) << '\n';
+  }
+  pr.print(out);
+}
+
+void Simulation::SimData::print(std::ostream& out) {
+  out << _name
+    << " " << mic::ColumnPrinter::commafy(_mseconds) << " ms"
+    << " " << mic::ColumnPrinter::commafy(_expQueryCount) << " eqs"
+    << '\n';
+}
+
+bool Simulation::SimData::operator<(const SimData& sd) const {
+  return _mseconds < sd._mseconds;
+}
diff --git a/src/divsim/Simulation.h b/src/divsim/Simulation.h
new file mode 100755
index 0000000..75222cb
--- /dev/null
+++ b/src/divsim/Simulation.h
@@ -0,0 +1,310 @@
+#ifndef SIMULATION_GUARD
+#define SIMULATION_GUARD
+
+#include "Monomial.h"
+#include "mathic/Timer.h"
+#include <vector>
+#include <iostream>
+#include <cstdlib>
+#include <algorithm>
+
+class Simulation {
+ public:
+  Simulation(size_t repeats, bool printPartialData):
+   _repeats(repeats), _printPartialData(printPartialData), _simType("none") {}
+
+  void makeStandard(size_t varCount, size_t inserts, size_t queries, bool findAll);
+
+  template<class DivFinder>
+  void run();
+  template<class DivFinder, class Param1>
+  void run(const Param1& param1);
+  template<class DivFinder, class Param1, class Param2>
+  void run(const Param1& param1, const Param2& param2);
+  template<class DivFinder, class Param1, class Param2, class Param3>
+  void run(const Param1& param1, const Param2& param2, const Param3& param3);
+  template<class DivFinder, class P1, class P2, class P3, class P4>
+  void run(const P1& p1, const P2& p2, const P3& param3, const P4& param4);
+  template<class DivFinder, class P1, class P2, class P3, class P4, class P5>
+  void run(const P1& p1, const P2& p2, const P3& param3, const P4& param4,
+    const P5& p5);
+  template<class DivFinder, class P1, class P2, class P3, class P4, class P5,
+  class P6>
+  void run(const P1& p1, const P2& p2, const P3& param3, const P4& param4,
+    const P5& p5, const P6& p6);
+
+  void printData(std::ostream& out) const;
+
+ private:
+  struct SimData {
+    bool operator<(const SimData& sd) const;
+    void print(std::ostream& out);
+
+    std::string _name;
+    unsigned long _mseconds;
+    unsigned long long _expQueryCount;
+  };
+
+  template<class DivFinder>
+  void run(DivFinder& finder);
+
+  enum EventType {
+    InsertUnknown,
+    InsertKnown,
+    QueryNoDivisor,
+    QueryHasDivisor,
+    QueryUnknown,
+    StateUnknown,
+    StateKnown
+  };
+  struct Event {
+    EventType _type;
+    std::vector<int> _monomial;
+    std::vector<const Monomial::Exponent*> _state;
+#ifdef DEBUG
+    std::vector<Monomial> _allMonomials;
+#else
+    size_t _monomialCount;
+#endif
+  };
+  class MonomialStore;
+
+  bool _findAll;
+  std::vector<Event> _events;
+  std::vector<SimData> _data;
+  size_t _varCount;
+  size_t _repeats;
+  bool _printPartialData;
+  std::string _simType;
+};
+
+template<class DivFinder>
+void Simulation::run() {
+  DivFinder finder(_varCount);
+  run(finder);
+}
+
+template<class DivFinder, class Param1>
+void Simulation::run(const Param1& param1) {
+  DivFinder finder(_varCount, param1);
+  run(finder);
+}
+
+template<class DivFinder, class Param1, class Param2>
+void Simulation::run(const Param1& param1, const Param2& param2) {
+  DivFinder finder(_varCount, param1, param2);
+  run(finder);
+}
+
+template<class DivFinder, class Param1, class Param2, class Param3>
+void Simulation::run
+(const Param1& param1, const Param2& param2, const Param3& param3) {
+  DivFinder finder(_varCount, param1, param2, param3);
+  run(finder);
+}
+
+template<class DivFinder, class P1, class P2, class P3, class P4>
+void Simulation::run
+(const P1& param1, const P2& param2, const P3& param3, const P4& param4) {
+  DivFinder finder(_varCount, param1, param2, param3, param4);
+  run(finder);
+}
+
+template<class DivFinder, class P1, class P2, class P3, class P4, class P5>
+void Simulation::run
+(const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5) {
+  DivFinder finder(_varCount, p1, p2, p3, p4, p5);
+  run(finder);
+}
+
+template<class DivFinder, class P1, class P2, class P3, class P4,
+class P5, class P6>
+void Simulation::run
+(const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5,
+const P6& p6) {
+  DivFinder finder(_varCount, p1, p2, p3, p4, p5, p6);
+  run(finder);
+}
+
+class Simulation::MonomialStore {
+public:
+  MonomialStore() {clear();}
+  void clear() {
+#ifdef DEBUG
+    _monomials.clear();
+#else
+    _monomialCount = 0;
+#endif
+  }
+
+  void push_back(const Monomial& monomial) {
+    proceed(monomial);
+  }
+  bool proceed(const Monomial& monomial) {
+#ifdef DEBUG
+    _monomials.push_back(monomial);
+#else
+    ++_monomialCount;
+#endif
+    return true;
+  }
+
+  template<class Finder>
+  void checkInsert(Event& e, const Finder& finder) {
+#ifdef DEBUG
+    std::sort(_monomials.begin(), _monomials.end());
+#endif
+
+    if (e._type == InsertUnknown) {
+#ifdef DEBUG
+      e._allMonomials.clear();
+      for (size_t i = 0; i < _monomials.size(); ++i)
+        e._allMonomials.push_back(_monomials[i]);
+#else
+      e._monomialCount = _monomialCount;
+#endif
+      e._type = InsertKnown;
+    } else {
+#ifdef DEBUG
+      ASSERT(_monomials == e._allMonomials);
+#else
+      if (_monomialCount != e._monomialCount) {
+        std::cerr << "Finder \"" << finder.getName() <<
+          "\" found incorrect number of monomials." << std::endl;
+        std::exit(1);
+      }
+#endif
+    }
+  }
+
+  template<class Finder>
+  void checkQuery(Event& e, const Finder& finder) {
+#ifdef DEBUG
+    for (size_t d = 0; d < _monomials.size(); ++d) {
+      for (size_t var = 0; var < e._monomial.size(); ++var) {
+        ASSERT(_monomials[d][var] <= e._monomial[var]);
+      }
+    }
+    std::sort(_monomials.begin(), _monomials.end());
+#endif
+
+    if (e._type == QueryUnknown) {
+      bool noMonomials;
+#ifdef DEBUG
+      e._allMonomials.clear();
+      for (size_t i = 0; i < _monomials.size(); ++i)
+        e._allMonomials.push_back(_monomials[i]);
+      noMonomials = _monomials.empty();
+#else
+      e._monomialCount = _monomialCount;
+      noMonomials = _monomialCount == 0;
+#endif
+      e._type = noMonomials ? QueryNoDivisor : QueryHasDivisor;
+    } else {
+#ifdef DEBUG
+      for (size_t i = 0; i < _monomials.size(); ++i)
+        ASSERT(_monomials[i] == e._allMonomials[i]);
+#else
+      if (_monomialCount != e._monomialCount) {
+        std::cerr << "Finder \"" << finder.getName() <<
+          "\" found incorrect number of monomials." << std::endl;
+        std::exit(1);
+      }
+#endif
+    }
+  }
+
+private:
+#ifdef DEBUG
+  std::vector<Monomial> _monomials;
+#else
+  size_t _monomialCount;
+#endif
+};
+
+struct ForAll {
+public:
+  ForAll(std::vector<const Monomial::Exponent*>& entries): _entries(entries) {}
+  bool proceed(const Monomial& m) {
+    _entries.push_back(m.getPointer());
+    return true;
+  }
+
+private:
+  std::vector<const Monomial::Exponent*>& _entries;
+};
+
+template<class DivFinder>
+void Simulation::run(DivFinder& finder) {
+  mic::Timer timer;
+  std::vector<Monomial> divisors;
+  std::vector<const Monomial::Exponent*> tmp;
+  for (size_t step = 0; step < _repeats; ++step) {
+    for (size_t i = 0; i < _events.size(); ++i) {
+      Event& e = _events[i];
+      if (e._type == InsertKnown || e._type == InsertUnknown) {
+        divisors.clear();
+        MonomialStore store;
+        if (0) {
+          // here to make sure it compiles, also easy to switch to checking this instead.
+          finder.insert(e._monomial);
+        } else
+          finder.insert(e._monomial, store);
+        store.checkInsert(e, finder);
+      } else if (e._type == StateUnknown || e._type == StateKnown) {
+        tmp.clear();
+        ForAll forAll(tmp);
+        finder.forAll(forAll);
+        if (e._type == StateUnknown) {
+          e._type = StateKnown;
+          e._state.swap(tmp);
+        } else {
+          if (e._state != tmp) {
+            std::cerr << "states differ." << std::endl;
+            std::exit(1);
+          }
+        }
+      } else if (!_findAll) {
+        typename DivFinder::Entry* entry = finder.findDivisor(e._monomial);
+        if (entry == 0) {
+          if (e._type == QueryHasDivisor) {
+            std::cerr << "Divisor finder \"" << finder.getName()
+                      << "\" failed to find divisor." << std::endl;
+            std::exit(1);
+          }
+          e._type = QueryNoDivisor;
+        } else {
+#ifdef DEBUG
+          for (size_t var = 0; var < _varCount; ++var) {
+            ASSERT((*entry)[var] <= e._monomial[var]);
+          }
+#endif
+          if (e._type == QueryNoDivisor) {
+            std::cerr << "Divisor finder \"" << finder.getName() <<
+              "\" found incorrect divisor." << std::endl;
+            std::exit(1);
+          }
+          e._type = QueryHasDivisor;
+        }
+      } else {
+        ASSERT(_findAll);
+        divisors.clear();
+        MonomialStore store;
+        const_cast<const DivFinder&>(finder) // to test const interface
+          .findAllDivisors(e._monomial, store);
+        store.checkQuery(e, finder);
+      }
+    }
+  }
+
+  SimData data;
+  data._mseconds = (unsigned long)timer.getMilliseconds();
+  data._name = finder.getName();
+  data._expQueryCount = finder.getExpQueryCount();
+  _data.push_back(data);
+  if (_printPartialData)
+    data.print(std::cerr);
+  std::cout << finder.size() << std::endl;
+}
+
+#endif
diff --git a/src/divsim/divMain.cpp b/src/divsim/divMain.cpp
new file mode 100755
index 0000000..8db1e30
--- /dev/null
+++ b/src/divsim/divMain.cpp
@@ -0,0 +1,148 @@
+#include "stdinc.h"
+
+#include "DivListModel.h"
+#include "KDTreeModel.h"
+#include "Simulation.h"
+#include "mathic/Timer.h"
+#include <iostream>
+
+int main() {
+  const size_t repeats = IF_DEBUG(true ? 1 :) 1;
+  Simulation sim(repeats, true);
+  mic::Timer timer;
+  std::cout << "Generating simulation. ";
+
+    
+#ifdef DEBUG
+  sim.makeStandard(10, 400, 1000, true);
+#else
+  sim.makeStandard(10, 5000, 2000000, true);
+#endif
+  timer.print(std::cout);
+  std::cout << std::endl;
+
+#ifndef DEBUG
+  sim.run<KDTreeModel<1,1,1,1,1> >(0, 0, 0, 1.0, 1000);
+  sim.run<KDTreeModel<1,1,1,1,0> >(0, 0, 0, 1.0, 1000);
+return 0;
+
+  sim.run<KDTreeModel<0,0,1,2,1> >(1, 0, 0, 0.0, 0); // best tree, no mask
+  sim.run<KDTreeModel<0,0,0,2,1> >(1, 0, 0, 0.0, 0); // best tree, no mask
+
+  sim.run<KDTreeModel<0,0,1,2,1> >(1, 0, 0, 1.0, 1000); // best tree, mask
+  sim.run<KDTreeModel<0,0,0,2,1> >(1, 0, 0, 1.0, 1000); // best tree, mask
+
+  sim.run<DivListModel<0, 0> >(1, 1, 0, 0.5, 500);
+  return 0;
+#endif
+
+
+  /*
+  for (int minimizeOnInsert = 1; minimizeOnInsert <= 1; ++minimizeOnInsert) {
+    for (int order = 0; order <= 2; ++order) {
+      bool moveDivisorToFront = (order == 1);
+      bool sortOnInsert = (order == 2);
+      sim.run<DivListModel<1> >
+        (minimizeOnInsert, moveDivisorToFront, sortOnInsert);
+      sim.run<DivListModel<0> >
+        (minimizeOnInsert, moveDivisorToFront, sortOnInsert);
+    }
+  }
+  //*/
+
+  //sim.run<DivListModel<0, 0> >(1, 0, 1, 0.0, 0); // best array, no mask
+  /*
+  sim.run<DivListModel<0> >(1, 0, 0)
+  sim.run<DivListModel<0> >(1, 1, 0);
+  sim.run<DivListModel<0> >(1, 0, 1);
+  sim.run<DivListModel<1> >(1, 0, 0);
+  sim.run<DivListModel<1> >(1, 1, 0);
+  sim.run<DivListModel<1> >(1, 0, 1);
+  //*/
+
+  sim.run<KDTreeModel<0,0,1,1,0> >(0, 0, 0, 0.0, 0);
+  sim.run<DivListModel<0,0> >(0, 1, 0, 0.5, 500);
+  for (int mini = 0; mini <= 0; ++mini) {
+    for (int sortOnInsert = 0; sortOnInsert <= 1; ++sortOnInsert) {
+      for (int useDivCache = 0; useDivCache <= 1; ++useDivCache) {
+        sim.run<KDTreeModel<1,1,1,1,0> >(mini,sortOnInsert,useDivCache, 0.5, 10);
+        sim.run<KDTreeModel<1,0,1,1,0> >(mini,sortOnInsert,useDivCache, 0.5, 10);
+        sim.run<KDTreeModel<0,0,1,1,0> >(mini,sortOnInsert,useDivCache, 0.5, 10);
+
+        sim.run<KDTreeModel<1,1,1,2,0> >(mini,sortOnInsert,useDivCache, 0.5, 10);
+        sim.run<KDTreeModel<1,0,1,2,0> >(mini,sortOnInsert,useDivCache, 0.5, 10);
+        sim.run<KDTreeModel<0,0,1,2,0> >(mini,sortOnInsert,useDivCache, 0.5, 10);
+
+        sim.run<KDTreeModel<1,1,1,3,0> >(mini,sortOnInsert,useDivCache, 0.5, 10);
+        sim.run<KDTreeModel<1,0,1,3,0> >(mini,sortOnInsert,useDivCache, 0.5, 10);
+        sim.run<KDTreeModel<0,0,1,3,0> >(mini,sortOnInsert,useDivCache, 0.5, 10);
+
+        sim.run<KDTreeModel<1,1,1,20,0> >(mini,sortOnInsert,useDivCache, 0.5, 10);
+
+        sim.run<KDTreeModel<1,1,0,1,0> >(mini,sortOnInsert,useDivCache, 0.5, 10);
+        sim.run<KDTreeModel<1,1,0,2,0> >(mini,sortOnInsert,useDivCache, 0.5, 10);
+        sim.run<KDTreeModel<1,1,0,40,0> >(mini,sortOnInsert,useDivCache, 0.5, 10);
+
+		/*
+        for (size_t leafSize = 5; leafSize <= 15; leafSize += 5)
+          for (size_t start = 0; start <= 0; start += 200)
+            for (double ratio = 0; ratio < 0.1; ratio += 0.2)
+              sim.run<KDTreeModel<0,0> >(leafSize, mini,sortOnInsert,useDivisorCache, ratio, start);
+
+              //*/
+        /*sim.run<KDTreeModel<0> >(8, mini,sortOnInsert,useDivisorCache, 0, 0);
+        sim.run<KDTreeModel<1> >(8, mini,sortOnInsert,useDivisorCache, 0, 0);
+        sim.run<KDTreeModel<0> >(20, mini,sortOnInsert,useDivisorCache, 0, 0);
+        sim.run<KDTreeModel<1> >(20, mini,sortOnInsert,useDivisorCache, 0, 0);
+        sim.run<KDTreeModel<0> >(40, mini,sortOnInsert,useDivisorCache, 0, 0);
+        sim.run<KDTreeModel<1> >(40, mini,sortOnInsert,useDivisorCache, 0, 0);
+        sim.run<KDTreeModel<0> >(60, mini,sortOnInsert,useDivisorCache, 0, 0);
+        sim.run<KDTreeModel<1> >(60, mini,sortOnInsert,useDivisorCache, 0, 0);*/
+
+        /*
+        sim.run<KDTreeModel<1> >(10, mini,sortOnInsert,useDivisorCache, 0.001, 2000);
+        sim.run<KDTreeModel<1> >(10, mini,sortOnInsert,useDivisorCache, 0.001, 4000);
+
+        sim.run<KDTreeModel<0> >(10, mini,sortOnInsert,useDivisorCache, 0.001, 6000);
+        sim.run<KDTreeModel<1> >(10, mini,sortOnInsert,useDivisorCache, 0.001, 6000);
+
+        sim.run<KDTreeModel<1> >(10, mini,sortOnInsert,useDivisorCache, 0.001, 8000);
+        sim.run<KDTreeModel<1> >(10, mini,sortOnInsert,useDivisorCache, 0.001, 10000);*/
+        //sim.run<KDTreeModel>(10, mini,sortOnInsert,useDivisorCache, 4, 2000);
+        //sim.run<KDTreeModel>(20, mini,sortOnInsert,useDivisorCache, 0.75, 2000);
+        //sim.run<KDTreeModel>(8, mini,sortOnInsert,useDivisorCache, 0.75, 2000);
+      }
+    }
+  }
+  //*/
+  /*
+  for (int mini = 1; mini <= 1; ++mini) {
+    for (int noneFrontSort = 0; noneFrontSort <= 2; ++noneFrontSort) {
+      bool tof = (noneFrontSort == 1);
+      bool sort = (noneFrontSort == 2);
+      
+      for (double ratio = 0.5; ratio < 0.51; ratio += 0.1)
+        for (size_t start = 500; start <= 500; start += 100)
+          sim.run<DivListModel<1, 1> >(mini, tof, sort, ratio, start);
+    }
+  }
+  //*/
+
+  /* best for single query from best to worst
+  sim.run<KDTreeModel<1,1> >(40, 1, 0, 0, 1.0, 1000); // best tree, mask
+  sim.run<KDTreeModel<0,0> >(15, 1, 0, 0, 0.0, 0); // best tree, no mask
+  sim.run<DivListModel<0, 1> >(1, 1, 0, 0.5, 500); // best array, mask
+  sim.run<DivListModel<1, 1> >(1, 1, 0, 0.5, 500); // should be best linked, mask
+  sim.run<DivListModel<0, 0> >(1, 0, 1, 0.0, 0); // best array, no mask
+  sim.run<DivListModel<1, 0> >(1, 0, 1, 0.0, 0); // best linked, no mask
+  //*/
+
+  /* base div lists
+  sim.run<DivListModel<0, 0> >(1, 0, 0, 0.0, 0); // base array
+  sim.run<DivListModel<1, 0> >(1, 0, 0, 0.0, 0); // base linked
+  //*/
+
+  std::cout << "\n\n";
+  sim.printData(std::cout);
+  return 0;
+}
diff --git a/src/divsim/divMain.h b/src/divsim/divMain.h
new file mode 100755
index 0000000..c466ef7
--- /dev/null
+++ b/src/divsim/divMain.h
@@ -0,0 +1,6 @@
+#ifndef MATHIC_DIV_MAIN_GUARD
+#define MATHIC_DIV_MAIN_GUARD
+
+int main();
+
+#endif
diff --git a/src/divsim/stdinc.h b/src/divsim/stdinc.h
new file mode 100755
index 0000000..d03df67
--- /dev/null
+++ b/src/divsim/stdinc.h
@@ -0,0 +1,57 @@
+#ifdef STDINC_GUARD
+#error stdinc.h included twice
+#endif
+#define STDINC_GUARD
+
+#ifdef _MSC_VER // For Microsoft Compiler in Visual Studio C++.
+#pragma warning (push, 1) // Reduce warning level for GMP headers.
+#endif
+
+#ifdef PROFILE
+#define NO_PINLINE NO_INLINE
+#else
+#define NO_PINLINE
+#endif
+
+#ifndef _MSC_VER
+#define NO_INLINE __attribute__ ((noinline))
+#endif
+
+#ifdef _MSC_VER // For Microsoft Compiler in Visual Studio C++.
+#define NO_INLINE __declspec(noinline)
+#pragma warning (pop) // Go back to previous warning level.
+#pragma warning (disable: 4996) // std::copy is flagged as dangerous.
+#pragma warning (disable: 4290) // VC++ ignores throw () specification.
+#pragma warning (disable: 4127) // Warns about using "while (true)".
+#pragma warning (disable: 4100) // Warns about unused parameters.
+#pragma warning (disable: 4800) // Warns on int to bool conversion.
+#pragma warning (disable: 4146) // Warns on unary minus on unsigned (bit trick)
+
+// This warning warns about using the this pointer in base member
+// initializer lists. This is a pretty good warning as that can
+// obviously easily go wrong, but it is pretty useful to do as well,
+// so the warning is turned off.
+#pragma warning (disable: 4355)
+
+#ifdef _DEBUG
+#define DEBUG
+#endif
+
+#endif
+
+#include <cstddef>
+#include <memory>
+
+#ifdef DEBUG
+#include <iostream> // Useful for debugging.
+#define PRINT
+#include <cassert>
+#define ASSERT(X) assert(X);
+#define IF_DEBUG(X) X
+#else
+#define ASSERT(X)
+#define IF_DEBUG(X)
+#endif
+
+static const size_t BitsPerByte = 8;
+static const size_t MemoryAlignment = sizeof(void*);
diff --git a/src/mathic.h b/src/mathic.h
new file mode 100755
index 0000000..4d46862
--- /dev/null
+++ b/src/mathic.h
@@ -0,0 +1,27 @@
+// Include this file to pull in all external MemTailor files
+
+// utilities
+#include "../../src/Timer.h"
+#include "../../src/ColumnPrinter.h"
+#include "../../src/ElementDeleter.h"
+#include "../../src/error.h"
+
+// divisor query data structures
+#include "../../src/DivList.h"
+#include "../../src/KDTree.h"
+
+// priority queue data structures
+#include "../../src/TourTree.h"
+#include "../../src/StlSet.h"
+#include "../../src/Heap.h"
+#include "../../src/Geobucket.h"
+
+// CLI package
+#include "../../src/Action.h"
+#include "../../src/BoolParameter.h"
+#include "../../src/CliParameter.h"
+#include "../../src/CliParser.h"
+#include "../../src/HelpAction.h"
+#include "../../src/IntegerParameter.h"
+#include "../../src/StringParameter.h"
+#include "../../src/display.h"
diff --git a/src/mathic/Action.cpp b/src/mathic/Action.cpp
new file mode 100755
index 0000000..a0e2488
--- /dev/null
+++ b/src/mathic/Action.cpp
@@ -0,0 +1,17 @@
+#include "Action.h"
+#include "error.h"
+
+namespace mathic {
+  Action::~Action() {
+  }
+
+  void Action::directOptions(
+    std::vector<std::string> tokens,
+    CliParser& parser
+  ) {
+    if (!tokens.empty()) {
+      reportError("Expected a dash (-) to indicate an option when reading \"" +
+        tokens.front() + "\".");
+    }
+  }
+}
diff --git a/src/mathic/Action.h b/src/mathic/Action.h
new file mode 100755
index 0000000..2266bc1
--- /dev/null
+++ b/src/mathic/Action.h
@@ -0,0 +1,46 @@
+#ifndef MATHIC_ACTION_GUARD
+#define MATHIC_ACTION_GUARD
+
+#include "stdinc.h"
+#include <string>
+#include <vector>
+
+namespace mathic {
+  class CliParameter;
+  class CliParser;
+
+  class Action {
+  public:
+    virtual ~Action();
+
+    // Called with tokens that precede any option of the
+    // form -option. The default is to give an error saying
+    // that a dash was expected if tokens is not empty.
+    virtual void directOptions
+      (std::vector<std::string> tokens, CliParser& parser);
+
+    // Do what it is this action does.
+    virtual void performAction() = 0;
+
+    // ***************************************
+    // **** Information provided by each Action
+
+    // The name of the action.
+    virtual const char* name() const = 0;
+
+    // More detailed explanation of what the action does.
+    virtual const char* description() const = 0;
+
+    // One-line summary of the description.
+    virtual const char* shortDescription() const = 0;
+
+    // Append the parameters for this action to the passed-in container.
+    // Do not clear the passed-in container.
+    virtual void pushBackParameters(std::vector<CliParameter*>& parameters) = 0;
+
+    // Return true if this class is HelpAction.
+    virtual bool isHelpAction() const {return false;}
+  };
+}
+
+#endif
diff --git a/src/mathic/BinaryKDTree.h b/src/mathic/BinaryKDTree.h
new file mode 100755
index 0000000..9d88307
--- /dev/null
+++ b/src/mathic/BinaryKDTree.h
@@ -0,0 +1,780 @@
+#ifndef MATHIC_BINARY_K_D_TRExtEntry_GUARD
+#define MATHIC_BINARY_K_D_TRExtEntry_GUARD
+
+#include "stdinc.h"
+#include "DivMask.h"
+#include "KDEntryArray.h"
+#include <memtailor.h>
+#include <ostream>
+
+namespace mathic {
+  template<class C>
+  class BinaryKDTree {
+  public:
+    typedef typename C::Monomial Monomial;
+    typedef typename C::Entry Entry;
+    typedef typename C::Exponent Exponent;
+    typedef typename DivMask::Extender<Entry, C::UseDivMask> ExtEntry;
+    typedef typename DivMask::Extender<const Monomial&,C::UseDivMask> ExtMonoRef;
+    typedef typename DivMask::Calculator<C> DivMaskCalculator;
+
+    struct ExpOrder {
+    ExpOrder(size_t var, const C& conf): _var(var), _conf(conf) {}
+      bool operator()(const ExtEntry& a, const ExtEntry& b) const {
+        return _conf.getExponent(a.get(), _var) < _conf.getExponent(b.get(), _var);
+      }
+    private:
+      const size_t _var;
+      const C& _conf;
+    };
+
+    private:
+    /** A helper class for KDTree. A node in the tree. The ExtEntry
+        comes from the KdTree. */
+    class KDTreeNode;
+
+    /** A helper class for KDTree. An interior node in the tree. The ExtEntry
+        comes from the KdTree. @todo: rename to KDTreeInternal. */
+    class KDTreeInterior;
+
+    /** A helper class for KDTree. Represents a leaf in the tree. Leaves
+        hold the monomials. The Configuration is as for KdTree. The ExtEntry
+        comes from the KdTree. */
+    class KDTreeLeaf;
+
+    typedef KDTreeNode Node;
+    typedef KDTreeInterior Interior;
+    typedef KDTreeLeaf Leaf;
+    typedef C Configuration;
+    static const bool UseDivMask = C::UseDivMask;
+
+    class KDTreeNode {
+    public:
+      bool isLeaf() const {return _isLeaf;}
+      const Leaf& asLeaf() const {
+        MATHIC_ASSERT(isLeaf());
+        return static_cast<const Leaf&>(*this);
+      }
+      Leaf& asLeaf() {
+        MATHIC_ASSERT(isLeaf());
+        return static_cast<Leaf&>(*this);
+      }
+
+      bool isInterior() const {return !isLeaf();}
+      const Interior& asInterior() const {
+        MATHIC_ASSERT(isInterior());
+        return static_cast<Interior&>(*this);
+      }
+      Interior& asInterior() {
+        MATHIC_ASSERT(isInterior());
+        return static_cast<Interior&>(*this);
+      }
+
+    protected:
+      KDTreeNode(bool leaf): _isLeaf(leaf) {}
+
+    private:
+      KDTreeNode(const KDTreeNode&); // unavailable
+      void operator=(const KDTreeNode&); // unavailable
+
+      class SplitEqualOrLess;
+      const bool _isLeaf;
+    };
+
+    class KDTreeInterior : public KDTreeNode,
+      public mathic::DivMask::HasDivMask<C::UseTreeDivMask> {
+    public:
+      typedef typename C::Exponent Exponent;
+      typedef KDTreeInterior Interior;
+      typedef KDTreeLeaf Leaf;
+      typedef KDTreeNode Node;
+
+      KDTreeInterior
+        (Node& equalOrLess,
+         Node& strictlyGreater,
+         size_t var,
+         Exponent exponent):
+      Node(false),
+        _equalOrLess(&equalOrLess),
+        _strictlyGreater(&strictlyGreater),
+        _var(var),
+        _exponent(exponent) {
+        }
+      KDTreeInterior
+        (size_t var,
+         Exponent exponent):
+      Node(false),
+        _equalOrLess(0),
+        _strictlyGreater(0),
+        _var(var),
+        _exponent(exponent) {
+        }
+      size_t getVar() const {return _var;}
+      Exponent getExponent() const {return _exponent;}
+
+      Node& getEqualOrLess() {return *_equalOrLess;}
+      const Node& getEqualOrLess() const {return *_equalOrLess;}
+      void setEqualOrLess(Node* equalOrLess) {_equalOrLess = equalOrLess;}
+
+      Node& getStrictlyGreater() {return *_strictlyGreater;}
+      const Node& getStrictlyGreater() const {return *_strictlyGreater;}
+      void setStrictlyGreater(Node* strictlyGreater) {
+        _strictlyGreater = strictlyGreater;
+      }
+
+      Node& getChildFor(const ExtEntry& entry, const C& conf) {
+        if (getExponent() < conf.getExponent(entry.get(), getVar()))
+          return getStrictlyGreater();
+        else
+          return getEqualOrLess();
+      }
+
+      using DivMask::HasDivMask<C::UseTreeDivMask>::updateToLowerBound;
+      void updateToLowerBound(Node& node) {
+        if (!C::UseTreeDivMask)
+          return;
+        if (node.isLeaf())
+          DivMask::HasDivMask<C::UseTreeDivMask>::
+            updateToLowerBound(node.asLeaf().entries());
+        else
+          DivMask::HasDivMask<C::UseTreeDivMask>::
+            updateToLowerBound(node.asInterior());
+      }
+
+    private:
+      Node* _equalOrLess;
+      Node* _strictlyGreater;
+      size_t _var;
+      Exponent _exponent;
+    };
+
+    
+    class KDTreeLeaf : public KDTreeNode {
+      typedef KDTreeInterior Interior;
+      typedef KDTreeLeaf Leaf;
+      typedef KDTreeNode Node;
+    public:
+      typedef typename C::Monomial Monomial;
+      typedef ExtEntry* iterator;
+      typedef const ExtEntry* const_iterator;
+      typedef const ExtEntry& const_reference;
+      typedef ExtEntry value_type;
+      typedef DivMask::Calculator<C> DivMaskCalculator;
+
+      KDTreeLeaf(memt::Arena& arena, const C& conf);
+
+      /** Copies Entry's in [begin, end) into the new leaf after
+       calculating div mask if using those. */
+      template<class Iter>
+      KDTreeLeaf(Iter begin, Iter end, memt::Arena& arena,
+        const DivMaskCalculator& calc, const C& conf);
+
+      /** Copies ExtEntry's [begin, end) into the new leaf. */
+      template<class Iter>
+      KDTreeLeaf(Iter begin, Iter end, memt::Arena& arena, const C& conf);
+
+      mathic::KDEntryArray<C, ExtEntry>& entries() {return _entries;}
+      const KDEntryArray<C, ExtEntry>& entries() const {return _entries;}
+
+      /** When this node is full, call this to insert an element. It
+       splits the elements in this noe into two leaves and returns
+       a new interior node that is the parent of them. */
+      Interior& splitInsert(const ExtEntry& entry, Interior* parent,
+        memt::Arena& arena, const C& conf);
+
+    private:
+      KDEntryArray<C, ExtEntry> _entries;
+    };
+
+  public:
+    typedef typename Leaf::iterator LeafIt;
+
+  public:
+    BinaryKDTree(const C& configuration);
+    ~BinaryKDTree();
+
+    template<class MultipleOutput>
+    size_t removeMultiples(const ExtMonoRef& monomial, MultipleOutput& out);
+
+    bool removeElement(const Monomial& monomial);
+
+    void insert(const ExtEntry& entry);
+
+    template<class Iter>
+    void reset(Iter begin, Iter end, const DivMaskCalculator& calc);
+
+    inline Entry* findDivisor(const ExtMonoRef& monomial);
+
+    template<class DivisorOutput>
+    inline void findAllDivisors
+      (const ExtMonoRef& monomial, DivisorOutput& out);
+
+    template<class Output>
+    inline void findAllMultiples
+      (const ExtMonoRef& monomial, Output& out);
+
+    template<class EntryOutput>
+    void forAll(EntryOutput& out);
+
+    void clear();
+
+    size_t getMemoryUse() const;
+
+    C& getConfiguration() {return _conf;}
+
+    void print(std::ostream& out) const;
+
+#ifdef MATHIC_DEBUG
+    bool debugIsValid() const;
+#endif
+
+  private:
+    BinaryKDTree(const BinaryKDTree<C>&); // unavailable
+    void operator=(const BinaryKDTree<C>&); // unavailable
+  
+    template<class Iter>
+    struct InsertTodo {
+      Iter begin;
+      Iter end;
+      Interior* parent;
+    };
+
+    memt::Arena _arena; // Everything permanent allocated from here.
+    C _conf; // User supplied configuration.
+    mutable std::vector<Node*> _tmp; // For navigating the tree.
+    Node* _root; // Root of the tree. Can be null!
+  };
+
+  template<class C>
+  BinaryKDTree<C>::BinaryKDTree(const C& configuration):
+  _conf(configuration), _root(0) {
+    MATHIC_ASSERT(C::LeafSize > 0);
+    MATHIC_ASSERT(debugIsValid());
+  }
+
+  template<class C>
+  BinaryKDTree<C>::~BinaryKDTree() {
+    clear();
+  }
+
+  template<class C>
+  template<class MO>
+  size_t BinaryKDTree<C>::removeMultiples(const ExtMonoRef& extMonomial, MO& out) {
+    MATHIC_ASSERT(_tmp.empty());
+    if (_root == 0)
+      return 0;
+    size_t removedCount = 0;
+    Node* node = _root;
+    while (true) {
+      while (node->isInterior()) {
+        Interior& interior = node->asInterior();
+        if (!(interior.getExponent() <
+              _conf.getExponent(extMonomial.get(), interior.getVar())))
+          _tmp.push_back(&interior.getEqualOrLess());
+        node = &interior.getStrictlyGreater();
+      }
+      MATHIC_ASSERT(node->isLeaf());
+      removedCount += node->asLeaf().entries().removeMultiples(extMonomial, out, _conf);
+      if (_tmp.empty())
+        break;
+      node = _tmp.back();
+      _tmp.pop_back();
+    }
+    MATHIC_ASSERT(_tmp.empty());
+    MATHIC_ASSERT(debugIsValid());
+    return removedCount;
+  }
+
+  template<class C>
+  bool BinaryKDTree<C>::removeElement(const Monomial& monomial) {
+    MATHIC_ASSERT(_tmp.empty());
+    if (_root == 0)
+      return 0;
+    Node* node = _root;
+
+    while (node->isInterior())
+      node = node->asInterior().getChildFor(monomial, _conf);
+    const bool value = node->asLeaf().removeElement(monomial);
+    MATHIC_ASSERT(debugIsValid());
+    return value;
+  }
+
+  template<class C>
+  void BinaryKDTree<C>::insert(const ExtEntry& extEntry) {
+    Interior* parent = 0;
+    if (_root == 0)
+      _root = new (_arena.allocObjectNoCon<Leaf>()) Leaf(_arena, _conf);
+    Node* node = _root;
+    while (node->isInterior()) {
+      parent = &node->asInterior();
+      if (C::UseTreeDivMask)
+        parent->updateToLowerBound(extEntry);
+      node = &parent->getChildFor(extEntry, _conf);
+    }
+    Leaf* leaf = &node->asLeaf();
+
+    MATHIC_ASSERT(leaf->entries().size() <= C::LeafSize);
+    if (leaf->entries().size() == C::LeafSize) {
+      Interior& interior = leaf->splitInsert(extEntry, parent, _arena, _conf);
+      if (parent == 0) {
+        ASSERT(leaf == _root);
+        _root = &interior;
+      }
+    } else {
+      MATHIC_ASSERT(leaf->entries().size() < C::LeafSize);
+      leaf->entries().insert(extEntry, _conf);
+      MATHIC_ASSERT(debugIsValid());
+    }
+  }
+
+  template<class C>
+  template<class Iter>
+  void BinaryKDTree<C>::reset(Iter insertBegin, Iter insertEnd, const DivMaskCalculator& calc) {
+    clear();
+    if (insertBegin == insertEnd)
+      return;
+
+    typedef InsertTodo<Iter> Task;
+    typedef std::vector<Task> TaskCont;
+    TaskCont todo;
+
+    Interior* parent = 0;
+    bool isEqualOrLessChild = false;
+    while (true) {
+      Node* node = 0;
+      const size_t insertCount = std::distance(insertBegin, insertEnd);
+      const bool isLeaf = (insertCount <= C::LeafSize);
+      if (isLeaf)
+        node = new (_arena.allocObjectNoCon<Leaf>())
+          Leaf(insertBegin, insertEnd, _arena, calc, _conf);
+      else {
+        size_t var =
+          (parent == 0 ? static_cast<size_t>(-1) : parent->getVar());
+
+        Exponent exp;
+        Iter middle = KDEntryArray<C, ExtEntry>::
+          split(insertBegin, insertEnd, var, exp, _conf);
+        Interior* interior = new (_arena.allocObjectNoCon<Interior>())
+          Interior(var, exp);
+
+        MATHIC_ASSERT(middle != insertBegin && middle != insertEnd);
+        // push strictly-greater on todo
+        Task task;
+        task.begin = middle;
+        task.end = insertEnd;
+        task.parent = interior;
+        todo.push_back(task);
+        // set up equal-or-less
+        insertEnd = middle;
+        node = interior;
+      }
+
+      if (parent == 0) {
+        ASSERT(_root == 0);
+        _root = node;
+      } else if (isEqualOrLessChild)
+        parent->setEqualOrLess(node);
+      else
+        parent->setStrictlyGreater(node);
+
+      if (isLeaf) {
+        // grab next item from todo
+        if (todo.empty())
+          break;
+        Task task = todo.back();
+        todo.pop_back();
+        insertBegin = task.begin;
+        insertEnd = task.end;
+        parent = task.parent;
+        // only strictlyGreater goes on todo
+        isEqualOrLessChild = false;
+      } else {
+        isEqualOrLessChild = true;
+        parent = &node->asInterior();
+        // continue with equal-or-less as next item      
+      }
+    }
+    ASSERT(_root != 0);
+
+    if (C::UseTreeDivMask) {
+      // record nodes in tree using breadth first search
+      typedef std::vector<Interior*> NodeCont;
+      NodeCont nodes;
+      if (_root->isInterior())
+        nodes.push_back(&_root->asInterior());
+      for (size_t i = 0; i < nodes.size(); ++i) {
+        Interior* node = nodes[i];
+        if (node->getEqualOrLess().isInterior())
+          nodes.push_back(&node->getEqualOrLess().asInterior());
+        if (node->getStrictlyGreater().isInterior())
+          nodes.push_back(&node->getStrictlyGreater().asInterior());
+      }
+      // compute div masks in reverse order of breath first search
+      typename NodeCont::reverse_iterator it = nodes.rbegin();
+      typename NodeCont::reverse_iterator end = nodes.rend();
+      for (; it != end; ++it) {
+        Interior* node = *it;
+        node->updateToLowerBound(node->getEqualOrLess());
+        node->updateToLowerBound(node->getStrictlyGreater());
+      }
+    }
+    MATHIC_ASSERT(debugIsValid());
+  }
+
+  template<class C>
+  typename BinaryKDTree<C>::Entry* BinaryKDTree<C>::findDivisor
+    (const ExtMonoRef& extMonomial) {
+
+    MATHIC_ASSERT(debugIsValid());
+    MATHIC_ASSERT(_tmp.empty());
+    if (_root == 0)
+      return 0;
+    Node* node = _root;
+    while (true) {
+      while (node->isInterior()) {
+        Interior& interior = node->asInterior();
+        if (C::UseTreeDivMask &&
+            !interior.getDivMask().canDivide(extMonomial.getDivMask()))
+          goto next;
+
+        if (interior.getExponent() <
+            _conf.getExponent(extMonomial.get(), interior.getVar()))
+          _tmp.push_back(&interior.getStrictlyGreater());
+        node = &interior.getEqualOrLess();
+      }
+
+      {
+        MATHIC_ASSERT(node->isLeaf());
+        Leaf& leaf = node->asLeaf();
+        LeafIt leafIt = leaf.entries().findDivisor(extMonomial, _conf);
+        if (leafIt != leaf.entries().end()) {
+          MATHIC_ASSERT(_conf.divides(leafIt->get(), extMonomial.get()));
+          _tmp.clear();
+          return &leafIt->get();
+        }
+      }
+    next:
+      if (_tmp.empty())
+        break;
+      node = _tmp.back();
+      _tmp.pop_back();
+    }
+    MATHIC_ASSERT(_tmp.empty());
+    return 0;
+  }
+
+  template<class C>
+  template<class DO>
+  void BinaryKDTree<C>::findAllDivisors(const ExtMonoRef& extMonomial, DO& output) {
+    MATHIC_ASSERT(_tmp.empty());
+    if (_root == 0)
+      return;
+    Node* node = _root;
+    while (true) {
+      while (node->isInterior()) {
+        Interior& interior = node->asInterior();
+        if (C::UseTreeDivMask &&
+            !interior.getDivMask().canDivide(extMonomial.getDivMask()))
+          goto next;
+        if (interior.getExponent() <
+            _conf.getExponent(extMonomial.get(), interior.getVar()))
+          _tmp.push_back(&interior.getStrictlyGreater());
+        node = &interior.getEqualOrLess();
+      }
+      MATHIC_ASSERT(node->isLeaf());
+      {
+        Leaf& leaf = node->asLeaf();
+        if (!leaf.entries().findAllDivisors(extMonomial, output, _conf)) {
+          _tmp.clear();
+          break;
+        }
+      }
+next:
+      if (_tmp.empty())
+        break;
+      node = _tmp.back();
+      _tmp.pop_back();
+    }
+    MATHIC_ASSERT(_tmp.empty());
+  }
+
+  template<class C>
+  template<class DO>
+  void BinaryKDTree<C>::findAllMultiples(const ExtMonoRef& extMonomial, DO& output) {
+    MATHIC_ASSERT(_tmp.empty());
+    if (_root == 0)
+      return;
+    Node* node = _root;
+    while (true) {
+      while (node->isInterior()) {
+        Interior& interior = node->asInterior();
+        if (!(interior.getExponent() <
+            _conf.getExponent(extMonomial.get(), interior.getVar())))
+          _tmp.push_back(&interior.getEqualOrLess());
+        node = &interior.getStrictlyGreater();
+      }
+      MATHIC_ASSERT(node->isLeaf());
+      {
+        Leaf& leaf = node->asLeaf();
+        if (!leaf.entries().findAllMultiples(extMonomial, output, _conf)) {
+          _tmp.clear();
+          break;
+        }
+      }
+next:
+      if (_tmp.empty())
+        break;
+      node = _tmp.back();
+      _tmp.pop_back();
+    }
+    MATHIC_ASSERT(_tmp.empty());
+  }
+
+  template<class C>
+  template<class EO>
+  void BinaryKDTree<C>::forAll(EO& output) {
+    MATHIC_ASSERT(_tmp.empty());
+    if (_root == 0)
+      return;
+    Node* node = _root;
+    while (true) {
+      while (node->isInterior()) {
+        Interior& interior = node->asInterior();
+        _tmp.push_back(&interior.getStrictlyGreater());
+        node = &interior.getEqualOrLess();
+      }
+      MATHIC_ASSERT(node->isLeaf());
+      Leaf& leaf = node->asLeaf();
+      if (!leaf.entries().forAll(output)) {
+        _tmp.clear();
+        break;
+      }
+      if (_tmp.empty())
+        break;
+      node = _tmp.back();
+      _tmp.pop_back();
+    }
+    MATHIC_ASSERT(_tmp.empty());
+  }
+
+  template<class C>
+  void BinaryKDTree<C>::clear() {
+    MATHIC_ASSERT(_tmp.empty());
+    // Call Entry destructors
+    if (_root != 0)
+      _tmp.push_back(_root);
+    while (!_tmp.empty()) {
+      Node* node = _tmp.back();
+      _tmp.pop_back();
+      while (node->isInterior()) {
+        _tmp.push_back(&node->asInterior().getStrictlyGreater());
+        node = &node->asInterior().getEqualOrLess();
+      }
+      MATHIC_ASSERT(node->isLeaf());
+      node->asLeaf().entries().clear();
+    }
+    _arena.freeAllAllocs();
+    _root = 0;
+  }
+
+  template<class C>
+  size_t BinaryKDTree<C>::getMemoryUse() const {
+	size_t sum = _arena.getMemoryUse();
+	sum += _tmp.capacity() * sizeof(_tmp.front());
+	return sum;
+  }
+
+  template<class C>
+  void BinaryKDTree<C>::print(std::ostream& out) const {
+    out << "<<<<<<<< BinaryKDTree >>>>>>>>\n";
+    MATHIC_ASSERT(_tmp.empty());
+    if (_root != 0) {
+      Node* node = _root;
+      while (true) {
+        if (node->isInterior()) {
+          Interior& interior = node->asInterior();
+          out << "**** Interior Node " << &interior << '\n';
+          out << "Split on " << interior.getVar() <<
+            '^' << interior.getExponent() << '\n';
+          out << "Child <=: " << &interior.getEqualOrLess() << '\n';
+          out << "Child > : " << &interior.getStrictlyGreater() << '\n';
+          out << '\n';
+          _tmp.push_back(&interior.getEqualOrLess());
+          _tmp.push_back(&interior.getStrictlyGreater());
+        } else {
+          Leaf& leaf = node->asLeaf();
+          out << "**** Leaf Node " << &leaf << '\n';
+          for (size_t i = 0; i < leaf.entries().size(); ++i) {
+            out << "Entry " << (i + 1) << ": "
+              << leaf.entries().begin()[i].get() << '\n';
+          }
+          out << '\n';
+        }
+        if (_tmp.empty())
+          break;
+        node = _tmp.back();
+        _tmp.pop_back();
+      }
+      MATHIC_ASSERT(_tmp.empty());
+    }
+  }
+
+#ifdef MATHIC_DEBUG
+  template<class C>
+  bool BinaryKDTree<C>::debugIsValid() const {
+    MATHIC_ASSERT(_tmp.empty());
+    MATHIC_ASSERT(!_conf.getDoAutomaticRebuilds() || _conf.getRebuildRatio() > 0);
+
+    if (_root == 0)
+      return true;
+
+    // record all nodes
+    std::vector<Node*> nodes;
+    nodes.push_back(_root);
+    size_t sizeSum = 0;
+    for (size_t i = 0; i < nodes.size(); ++i) {
+      Node* node = nodes[i];
+      if (node->isInterior()) {
+        MATHIC_ASSERT(node->asInterior().getVar() < _conf.getVarCount());
+        nodes.push_back(&node->asInterior().getStrictlyGreater());
+        nodes.push_back(&node->asInterior().getEqualOrLess());
+      } else
+        sizeSum += node->asLeaf().entries().size();
+    }
+
+    // check the recorded nodes
+    MATHIC_ASSERT(_tmp.empty());
+    for (size_t i = 0; i < nodes.size(); ++i) {
+      Node* nodei = nodes[i];
+      if (nodei->isLeaf()) {
+        ASSERT(nodei->asLeaf().entries().debugIsValid());
+        continue;
+      }
+      Interior& interior = nodei->asInterior();
+      size_t var = interior.getVar();
+      Exponent exp = interior.getExponent();
+
+      ASSERT(_tmp.empty());
+      // check equal or less than sub tree
+      _tmp.push_back(&interior.getEqualOrLess());
+      while (!_tmp.empty()) {
+        Node* node = _tmp.back();
+        _tmp.pop_back();
+        if (C::UseTreeDivMask) {
+          if (node->isInterior())
+            MATHIC_ASSERT(interior.getDivMask().canDivide(node->asInterior().getDivMask()));
+          else
+            MATHIC_ASSERT(interior.getDivMask().canDivide(node->asLeaf().entries().getDivMask()));
+        }
+        if (node->isInterior()) {
+          _tmp.push_back(&node->asInterior().getStrictlyGreater());
+          _tmp.push_back(&node->asInterior().getEqualOrLess());
+        } else {
+          MATHIC_ASSERT(node->asLeaf().entries().allLessThanOrEqualTo(var, exp, _conf));
+        }
+      }
+
+      // check strictly greater
+      _tmp.push_back(&interior.getStrictlyGreater());
+      while (!_tmp.empty()) {
+        Node* node = _tmp.back();
+        _tmp.pop_back();
+        if (C::UseTreeDivMask) {
+          if (node->isInterior())
+            MATHIC_ASSERT(interior.getDivMask().canDivide(node->asInterior().getDivMask()));
+          else
+            MATHIC_ASSERT(interior.getDivMask().canDivide(node->asLeaf().entries().getDivMask()));
+        }
+        if (node->isInterior()) {
+          _tmp.push_back(&node->asInterior().getStrictlyGreater());
+          _tmp.push_back(&node->asInterior().getEqualOrLess());
+        } else {
+          MATHIC_ASSERT(node->asLeaf().entries().allStrictlyGreaterThan(var, exp, _conf));
+        }
+      }
+    }
+    return true;
+  }
+#endif
+
+  template<class C>
+  BinaryKDTree<C>::KDTreeLeaf::KDTreeLeaf(memt::Arena& arena, const C& conf):
+  Node(true), _entries(arena, conf) {}
+
+  template<class C>  
+  template<class Iter>
+  BinaryKDTree<C>::KDTreeLeaf::KDTreeLeaf(
+    Iter begin,
+    Iter end,
+    memt::Arena& arena,
+    const DivMaskCalculator& calc,
+    const C& conf):
+    Node(true), _entries(begin, end, arena, calc, conf) {}
+
+  template<class C>  
+  template<class Iter>
+  BinaryKDTree<C>::KDTreeLeaf::KDTreeLeaf(
+    Iter begin,
+    Iter end,
+    memt::Arena& arena,
+    const C& conf):
+    Node(true), _entries(begin, end, arena, conf) {}
+
+  template<class C>
+  class BinaryKDTree<C>::KDTreeNode::SplitEqualOrLess {
+  public:
+    typedef typename C::Exponent Exponent;
+    typedef typename C::Entry Entry;
+  SplitEqualOrLess(size_t var, const Exponent& exp, const C& conf):
+    _var(var), _exp(exp), _conf(conf) {}
+    bool operator()(const Entry& entry) const {
+      return !(_exp < _conf.getExponent(entry, _var));
+    }
+  private:
+    size_t _var;
+    const Exponent& _exp;
+    const C& _conf;
+  };
+
+  template<class C>
+  typename BinaryKDTree<C>::KDTreeInterior&
+  BinaryKDTree<C>::KDTreeLeaf::splitInsert(const ExtEntry& extEntry, Interior* parent, memt::Arena& arena, const C& conf) {
+    MATHIC_ASSERT(conf.getVarCount() > 0);
+    MATHIC_ASSERT(entries().size() > 0);
+    size_t var = (parent == 0 ? static_cast<size_t>(-1) : parent->getVar());
+    typename C::Exponent exp;
+
+    iterator middle = KDEntryArray<C, ExtEntry>::split
+      (entries().begin(), entries().end(), var, exp, conf, &extEntry);
+    Leaf& other = *new (arena.allocObjectNoCon<Leaf>()) Leaf(middle, entries().end(), arena, conf);
+    while (middle != entries().end())
+      entries().pop_back();
+    if (conf.getSortOnInsert())
+      std::sort(entries().begin(), entries().end(), Comparer<C>(conf));
+
+    Interior& interior = *new (arena.allocObjectNoCon<Interior>())
+      Interior(*this, other, var, exp);
+    if (C::UseTreeDivMask) {
+      entries().recalculateTreeDivMask();
+      interior.updateToLowerBound(entries());
+      interior.updateToLowerBound(other.entries());
+    }
+    if (parent != 0) {
+      if (&parent->getEqualOrLess() == this)
+        parent->setEqualOrLess(&interior);
+      else {
+        MATHIC_ASSERT(&parent->getStrictlyGreater() == this);
+        parent->setStrictlyGreater(&interior);
+      }
+    }
+
+    interior.updateToLowerBound(extEntry);
+    Leaf* insertLeaf = &interior.getChildFor(extEntry, conf).asLeaf();
+    ASSERT(insertLeaf->entries().size() < C::LeafSize);
+    insertLeaf->entries().insert(extEntry, conf);
+
+    return interior;
+  }
+}
+
+#endif
diff --git a/src/mathic/BoolParameter.cpp b/src/mathic/BoolParameter.cpp
new file mode 100755
index 0000000..9e64ad5
--- /dev/null
+++ b/src/mathic/BoolParameter.cpp
@@ -0,0 +1,31 @@
+#include "BoolParameter.h"
+
+#include "error.h"
+
+namespace mathic {
+  BoolParameter::BoolParameter(const std::string& name,
+                               const std::string& description,
+                               bool defaultValue):
+    CliParameter(name, description),
+    _value(defaultValue) {
+  }
+
+  std::string BoolParameter::argumentType() const {
+    return "[BOOL]";
+  }
+
+  std::string BoolParameter::valueAsString() const {
+    return _value ? "on" : "off";
+  }
+
+  void BoolParameter::processArgument(const std::string& argument) {
+    if (argument.empty() || argument == "on")
+      _value = true;
+    else if (argument == "off")
+      _value = false;
+    else {
+      reportError("Option -" + name() + " was given the argument \"" +
+        argument + "\". The only valid arguments are \"on\" and \"off\".");
+    }
+  }
+}
diff --git a/src/mathic/BoolParameter.h b/src/mathic/BoolParameter.h
new file mode 100755
index 0000000..c10aea8
--- /dev/null
+++ b/src/mathic/BoolParameter.h
@@ -0,0 +1,31 @@
+#ifndef MATHIC_BOOL_PARAMETER_GUARD
+#define MATHIC_BOOL_PARAMETER_GUARD
+
+#include "stdinc.h"
+#include "CliParameter.h"
+#include <utility>
+#include <string>
+
+namespace mathic {
+  class BoolParameter : public CliParameter {
+  public:
+    BoolParameter(const std::string& name,
+                  const std::string& description,
+                  bool defaultValue);
+
+    bool value() const {return _value;}
+    void setValue(bool value) {_value = value;}
+
+    operator bool() const {return value();}
+    void operator=(bool value) {setValue(value);}
+
+    virtual std::string argumentType() const;
+    virtual std::string valueAsString() const;
+    virtual void processArgument(const std::string& argument);
+
+  private:
+    bool _value;
+  };
+}
+
+#endif
diff --git a/src/mathic/CliParameter.cpp b/src/mathic/CliParameter.cpp
new file mode 100755
index 0000000..2c15f5d
--- /dev/null
+++ b/src/mathic/CliParameter.cpp
@@ -0,0 +1,19 @@
+#include "CliParameter.h"
+#include "error.h"
+
+namespace mathic {
+  CliParameter::CliParameter(
+    const std::string& name,
+    const std::string& description
+  ):
+    _name(name),
+    _description(description) {
+  }
+
+  CliParameter::~CliParameter() {
+  }
+
+  void CliParameter::appendToDescription(const std::string& str) {
+    _description += str;
+  }
+}
diff --git a/src/mathic/CliParameter.h b/src/mathic/CliParameter.h
new file mode 100755
index 0000000..db89835
--- /dev/null
+++ b/src/mathic/CliParameter.h
@@ -0,0 +1,29 @@
+#ifndef MATHIC_PARAMETER_GUARD
+#define MATHIC_PARAMETER_GUARD
+
+#include "stdinc.h"
+#include <string>
+
+namespace mathic {
+  class CliParameter {
+  public:
+    virtual ~CliParameter();
+
+    const std::string& name() const {return _name;}
+    const std::string& description() const {return _description;}
+    void appendToDescription(const std::string& str);
+
+    virtual std::string argumentType() const = 0;
+    virtual std::string valueAsString() const = 0;
+    virtual void processArgument(const std::string& argument) = 0;
+
+  protected:
+    CliParameter(const std::string& name, const std::string& description);
+
+  private:
+    std::string _name;
+    std::string _description;
+  };
+}
+
+#endif
diff --git a/src/mathic/CliParser.cpp b/src/mathic/CliParser.cpp
new file mode 100644
index 0000000..6e6af75
--- /dev/null
+++ b/src/mathic/CliParser.cpp
@@ -0,0 +1,101 @@
+#include "CliParser.h"
+
+#include "error.h"
+#include "CliParameter.h"
+
+namespace mathic {
+  namespace {
+    // We are using a NameFactory just for its prefix-finding functionality, so
+    // we set the thing being created to be just void pointers that are null.
+    typedef void* Dummy;
+    typedef NameFactory<Dummy> ParamNames;
+    ParamNames makeParamNames(std::vector<CliParameter*> params) {
+      struct HoldsFunction { // work around for no local functions in old C++
+        static std::auto_ptr<Dummy> dummyCreate() {
+          return std::auto_ptr<Dummy>(0);
+        }
+      };
+
+      ParamNames names("option");
+      for (size_t i = 0; i < params.size(); ++i)
+        names.registerProduct(params[i]->name(), HoldsFunction::dummyCreate);
+      return names;
+    }
+  }
+
+  void CliParser::pushBackRegisteredActionNames(
+    std::vector<std::string>& names
+  ) const {
+    _actions.namesWithPrefix("", names);
+  }
+
+
+  CliParser::CliParser(): _actions("action") {}
+
+  std::auto_ptr<Action> CliParser::createActionWithPrefix(
+    const std::string& prefix
+  ) {
+    return createWithPrefix(_actions, prefix);
+  }
+
+  std::auto_ptr<Action> CliParser::parse(int argc, char** argv) {
+    std::vector<std::string> commandLine(argv, argv + argc);
+    return parse(commandLine);
+  }
+
+  std::auto_ptr<Action> CliParser::parse
+    (const std::vector<std::string>& commandLine) {
+    if (commandLine.empty())
+      throwError<UnknownNameException>("No action specified.");
+    std::auto_ptr<Action> action = createActionWithPrefix(commandLine[0]);
+
+    std::vector<CliParameter*> params;
+    action->pushBackParameters(params);
+    ParamNames paramNames = makeParamNames(params);
+
+    std::vector<std::string> options;
+    std::vector<std::string> directOptions;
+    bool sawDash = false;
+    for (size_t i = 1; i < commandLine.size(); ++i) {
+      if (commandLine[i].empty())
+        continue;
+      if (commandLine[i][0] == '-')
+        sawDash = true;
+      if (sawDash)
+        options.push_back(commandLine[i]);
+      else
+        directOptions.push_back(commandLine[i]);
+    }
+
+    action->directOptions(directOptions, *this);
+
+    size_t i = 1;
+    for (size_t i = 0; i < options.size(); ++i) {
+      std::string const& token = options[i];
+      if (token[0] != '-')
+        reportError("Expected an option when reading \"" +
+                    token + "\", but options start with a dash (-).\n");
+      std::string noDash(token.begin() + 1, token.end());
+      std::string name = uniqueNameWithPrefix(paramNames, noDash);
+
+      std::string optionArgument;
+      if (i + 1 < options.size() && options[i + 1][0] != '-') {
+        optionArgument = options[i + 1];
+        ++i;
+      }
+
+      for (std::vector<CliParameter*>::iterator it = params.begin();; ++it) {
+        if (it == params.end()) {
+          // shouldn't get here as name was recognized above
+          reportInternalError("Processing non-existent option \""
+            + name + "\".");
+        }
+        if ((*it)->name() == name) {
+          (*it)->processArgument(optionArgument);
+          break;
+        }
+      }
+    }
+    return action;
+  }
+}
diff --git a/src/mathic/CliParser.h b/src/mathic/CliParser.h
new file mode 100644
index 0000000..22fcb42
--- /dev/null
+++ b/src/mathic/CliParser.h
@@ -0,0 +1,50 @@
+#ifndef MATHIC_CLI_PARSER_GUARD
+#define MATHIC_CLI_PARSER_GUARD
+
+#include "NameFactory.h"
+#include "Action.h"
+
+namespace mathic {
+  class CliParser {
+  public:
+    CliParser();
+
+    template<class ConcreteAction>
+    void registerAction(const std::string& name);
+
+    // picks the name up from ConcreteAction::staticName().
+    template<class ConcreteAction>
+    void registerAction();
+
+    void registerHelpAction
+      (const std::string& preMessage, const std::string& postMessage);
+
+    void pushBackRegisteredActionNames(
+      std::vector<std::string>& names
+    ) const;
+
+    const std::string& helpPreMessage() const {return _helpPreMessage;}
+    const std::string& helpPostMessage() const {return _helpPostMessage;}
+
+    std::auto_ptr<Action> parse(int argc, char** argv);
+    std::auto_ptr<Action> parse(const std::vector<std::string>& commandLine);
+    std::auto_ptr<Action> createActionWithPrefix(const std::string& prefix);
+
+  private:
+    NameFactory<Action> _actions;
+    std::string _helpPreMessage;
+    std::string _helpPostMessage;
+  };
+
+  template<class ConcreteAction>
+  void CliParser::registerAction(const std::string& name) {
+    nameFactoryRegister<ConcreteAction>(_actions, name);
+  };
+
+  template<class ConcreteAction>
+  void CliParser::registerAction() {
+    nameFactoryRegister<ConcreteAction>(_actions);
+  };
+}
+
+#endif
diff --git a/src/mathic/ColumnPrinter.cpp b/src/mathic/ColumnPrinter.cpp
new file mode 100755
index 0000000..92a760b
--- /dev/null
+++ b/src/mathic/ColumnPrinter.cpp
@@ -0,0 +1,185 @@
+#include "ColumnPrinter.h"
+
+namespace mathic {
+  namespace {
+	size_t getLineWidth(const std::string& str, size_t pos) {
+	  size_t startPos = pos;
+	  while (pos < str.size() && str[pos] != '\n')
+		++pos;
+	  return pos - startPos;
+	}
+
+	void printSpaces(std::ostream& out, size_t howMany) {
+	  while (howMany > 0) {
+		out << ' ';
+		--howMany;
+	  }
+	}
+  }
+
+  ColumnPrinter::ColumnPrinter(size_t columnCount):
+	_cols() {
+	while (columnCount > 0) {
+	  addColumn();
+	  --columnCount;
+	}
+  }
+
+  ColumnPrinter::~ColumnPrinter() {
+	for (std::vector<Col*>::iterator it = _cols.begin();
+		 it != _cols.end(); ++it)
+	  delete *it;
+  }
+
+  void ColumnPrinter::setPrefix(const std::string& prefix) {
+	_prefix = prefix;
+  }
+
+  void ColumnPrinter::addColumn(bool flushLeft,
+								const std::string& prefix,
+								const std::string& suffix) {
+	std::auto_ptr<Col> col(new Col());
+	col->prefix = prefix;
+	col->suffix = suffix;
+	col->flushLeft = flushLeft;
+
+	_cols.push_back(0);
+	_cols.back() = col.release(); // push_back didn't throw, so safe to release
+  }
+
+  size_t ColumnPrinter::getColumnCount() const {
+	return _cols.size();
+  }
+
+  std::ostream& ColumnPrinter::operator[](size_t col) {
+	MATHIC_ASSERT(col < getColumnCount());
+	return _cols[col]->text;
+  }
+
+  void ColumnPrinter::print(std::ostream& out) const {
+	// Calculate the width of each column.
+	std::vector<size_t> widths(getColumnCount());
+	for (size_t col = 0; col < getColumnCount(); ++col) {
+	  const std::string& text = _cols[col]->text.str();
+	  size_t maxWidth = 0;
+
+	  size_t pos = 0;
+	  while (pos < text.size()) {
+		size_t width = getLineWidth(text, pos);
+		if (width > maxWidth)
+		  maxWidth = width;
+
+		// We can't just increment pos unconditionally by width + 1, as
+		// that could result in an overflow.
+		pos += width;
+		if (text[pos] == '\n')
+		  ++pos;
+	  }
+	  widths[col] = maxWidth;
+	}
+
+	// Print each row
+	std::vector<size_t> poses(getColumnCount());
+	while (true) {
+	  bool done = true;
+	  for (size_t col = 0; col < getColumnCount(); ++col) {
+		if (poses[col] < _cols[col]->text.str().size()) {
+		  done = false;
+		  break;
+		}
+	  }
+	  if (done)
+		break;
+
+	  out << _prefix;
+	  for (size_t col = 0; col < getColumnCount(); ++col) {
+		out << _cols[col]->prefix;
+
+		const std::string& text = _cols[col]->text.str();
+		size_t& pos = poses[col];
+		size_t width = getLineWidth(text, pos);
+
+		if (!_cols[col]->flushLeft)
+		  printSpaces(out, widths[col] - width);
+
+		while (pos < text.size()) {
+		  if (text[pos] == '\n') {
+			++pos;
+			break;
+		  }
+		  out << text[pos];
+		  ++pos;
+		}
+
+		if (_cols[col]->flushLeft)
+		  printSpaces(out, widths[col] - width);
+
+		out << _cols[col]->suffix;
+	  }
+	  out << '\n';
+	}
+  }
+
+  std::string ColumnPrinter::commafy(unsigned long long l) {
+    std::stringstream out;
+    out << l;
+    std::string str;
+    for (size_t i = 0; i < out.str().size(); ++i) {
+      str += out.str()[i];
+      if (i != out.str().size() - 1 && ((out.str().size() - i) % 3) == 1)
+        str += ',';
+    }
+    return str;
+  }
+
+  std::string ColumnPrinter::percent(
+      unsigned long long numerator,
+      unsigned long long denominator) {
+    return percent(static_cast<double>(numerator) / denominator);
+  }
+
+  std::string ColumnPrinter::percent(double ratio) {
+    return oneDecimal(ratio * 100) + '%';
+  }
+
+  std::string ColumnPrinter::ratio(
+    unsigned long long numerator,
+    unsigned long long denominator) {
+    return oneDecimal(static_cast<double>(numerator) / denominator);
+  }
+
+  std::string ColumnPrinter::oneDecimal(double d) {
+    std::ostringstream out;
+    unsigned long long l = static_cast<unsigned long long>(d * 10 + 0.5);
+    out << l / 10 << '.' << l % 10;
+	return out.str();
+  }
+
+  std::string ColumnPrinter::bytesInUnit(unsigned long long bytes) {
+	std::ostringstream out;
+	if (bytes < 1024) {
+	  out << bytes << 'b';
+    } else {
+	  const char* units[] = {"kb", "mb", "gb", "tb"};
+	  const size_t unitCount = sizeof(units) / sizeof(*units);
+	  double amount = static_cast<double>(bytes) / 1024.0;
+	  size_t i = 0;
+	  for (i = 0; i < unitCount && amount >= 1024; ++i)
+        amount /= 1024.0;
+	  out << oneDecimal(amount) << units[i];
+    }
+    return out.str();
+  }
+
+
+  std::ostream& operator<<(std::ostream& out, const ColumnPrinter& printer) {
+	printer.print(out);
+	return out;
+  }
+
+  void print(FILE* out, const ColumnPrinter& pr) {
+	std::ostringstream str;
+	str << pr;
+	fputs(str.str().c_str(), out);
+  }
+}
diff --git a/src/mathic/ColumnPrinter.h b/src/mathic/ColumnPrinter.h
new file mode 100755
index 0000000..96ede3a
--- /dev/null
+++ b/src/mathic/ColumnPrinter.h
@@ -0,0 +1,64 @@
+#ifndef MATHIC_COLUMN_PRINTER_GUARD
+#define MATHIC_COLUMN_PRINTER_GUARD
+
+#include "stdinc.h"
+#include <sstream>
+#include <vector>
+#include <cstdio>
+#include <memory>
+#include <string>
+
+namespace mathic {
+  class ColumnPrinter {
+  public:
+	ColumnPrinter(size_t columnCount = 0);
+	~ColumnPrinter();
+
+	void setPrefix(const std::string& prefix);
+	void addColumn(bool flushLeft = true,
+				   const std::string& prefix = "  ",
+				   const std::string& suffix = "");
+	size_t getColumnCount() const;
+
+	std::ostream& operator[](size_t col);
+
+	void print(std::ostream& out) const;
+
+    /** returns 123456789 as "123,456,789". */
+    static std::string commafy(unsigned long long l);
+
+    /** returns (3,4) as "75.0%". */
+    static std::string percent(
+      unsigned long long numerator,
+      unsigned long long denominator);
+
+    /** returns 0.7565 as "75.7%". */
+    static std::string percent(double ratio);
+
+    /** Returns (7,4) as "1.8" */
+    static std::string ratio(
+      unsigned long long numerator,
+      unsigned long long denominator);
+
+	/** Returns d as a string printed to 1 decimal place, rounding up at 0.5 */
+    static std::string oneDecimal(double d);
+
+	/** Prints as X bytes, X kilobytes, X megabytes etc. */
+    static std::string bytesInUnit(unsigned long long bytes);
+
+  private:
+	struct Col {
+	  std::string prefix;
+	  std::stringstream text;
+	  std::string suffix;
+	  bool flushLeft;
+	};
+	std::vector<Col*> _cols;
+	std::string _prefix;
+  };
+
+  std::ostream& operator<<(std::ostream& out, const ColumnPrinter& printer);
+  void print(FILE* out, const ColumnPrinter& pr);
+}
+
+#endif
diff --git a/src/mathic/ComTree.h b/src/mathic/ComTree.h
new file mode 100644
index 0000000..dcc5d60
--- /dev/null
+++ b/src/mathic/ComTree.h
@@ -0,0 +1,273 @@
+#ifndef MATHIC_COM_TREE_GUARD
+#define MATHIC_COM_TREE_GUARD
+
+#include "stdinc.h"
+#include <ostream>
+
+namespace mathic {
+  /** This class packs a complete binary tree in a vector.
+
+	  The idea is to have the root at index 1, and then the left child of node n
+	  will be at index 2n and the right child will be at index 2n + 1. The
+	  corresponding formulas when indexes start at 0 take more computation, so
+	  we need a 1-based array so we can't use std::vector.
+
+	  Also, when sizeof(Entry) is a power of 2 it is faster to keep track of
+	  i * sizeof(Entry) than directly keeping track of an index i. This doesn't
+	  work well when sizeof(Entry) is not a power of two. So we need both
+	  possibilities. That is why this class never exposes indexes. Instead
+	  you interact with Node objects that serve the role of an index, but the
+	  precise value it stores is encapsulated. This way you can't do something
+	  like _array[i * sizeof(Entry)] by accident. Client code also does not
+	  need to (indeed, can't) be aware of how indexes are calculated, stored and
+	  looked up.
+
+	  If FastIndex is false, then Nodes contain an index i. If FastIndex is
+	  true, then Nodes contain the byte offset i * sizeof(Entry). FastIndex must
+	  be false if sizeof(Entry) is not a power of two.
+  */
+  template<class Entry, bool FastIndex>
+	class ComTree {
+  public:
+	class Node;
+	ComTree(size_t initialCapacity = 0);
+	ComTree(const ComTree& tree, size_t minCapacity = 0);
+	~ComTree() {delete[](_array + 1);}
+
+	Entry& operator[](Node n);
+	const Entry& operator[](Node n) const;
+
+	bool empty() const {return _lastLeaf == Node(0);}
+	size_t size() const {return _lastLeaf.getNormalIndex();}
+	size_t capacity() const {return _capacityEnd.getNormalIndex();}
+	Node lastLeaf() const {return _lastLeaf;}
+
+	void pushBack(const Entry& value);
+	void pushBackWithCapacity(const Entry& value);
+	void popBack();
+
+	bool hasFreeCapacity(size_t extraCapacity) const;
+	void increaseCapacity();
+	void swap(ComTree& tree);
+
+	struct Node {
+      Node(): _index(fi ? S : 1) {} // the root node is the default
+
+	  Node parent() const;
+	  Node left() const;
+	  Node right() const;
+	  Node sibling() const;
+	  Node leftSibling() const;
+	  Node next() const;
+	  Node next(size_t count) const;
+	  Node prev() const;
+	  Node& operator++() {*this = next(); return *this;}
+
+	  bool isRoot() const {return *this == Node();}
+	  bool isLeft() const {return fi ? !(_index & S) : !(_index & 1);}
+	  bool isRight() const {return fi ? _index & S : _index & 1;}
+
+	  bool operator<(Node node) const {return _index < node._index;}
+	  bool operator<=(Node node) const {return _index <= node._index;}
+	  bool operator>(Node node) const {return _index > node._index;}
+	  bool operator>=(Node node) const {return _index >= node._index;}
+	  bool operator==(Node node) const {return _index == node._index;}
+	  bool operator!=(Node node) const {return _index != node._index;}
+
+	  //private:
+	  friend class ComTree<Entry, FastIndex>;
+	  static const bool fi = FastIndex;
+	  static const size_t S = sizeof(Entry);
+	  explicit Node(size_t i): _index(i) {}
+	  size_t getNormalIndex() const {return fi ? _index / S : _index;}
+	  size_t _index;
+	};
+
+	void print(std::ostream& out) const;
+
+    void clear();
+
+    size_t getMemoryUse() const;
+
+#ifdef MATHIC_DEBUG
+	bool isValid() const;
+#endif
+
+  private:
+	ComTree& operator=(const ComTree& tree) const; // not available
+
+	Entry* _array;
+	Node _lastLeaf;
+	Node _capacityEnd;
+  };
+
+  template<class E, bool FI>
+  void ComTree<E, FI>::clear() {
+    _lastLeaf = Node(0);
+  }
+
+  template<class E, bool FI>
+  size_t ComTree<E, FI>::getMemoryUse() const {
+    return capacity() * sizeof(E);
+  }
+
+  template<class E, bool FI>
+	std::ostream& operator<<(std::ostream& out, const ComTree<E, FI>& tree) {
+	tree.print(out);
+	return out;
+  }
+
+  template<class E, bool FI>
+	ComTree<E, FI>::ComTree(size_t initialCapacity):
+  _array(static_cast<E*>(0) - 1),
+	_lastLeaf(0),
+	_capacityEnd(Node(0).next(initialCapacity)) {
+	if (initialCapacity > 0)
+	  _array = new E[initialCapacity] - 1;
+	MATHIC_ASSERT(isValid());
+  }
+
+  template<class E, bool FI>
+	ComTree<E, FI>::ComTree(const ComTree& tree, size_t minCapacity):
+  _array(static_cast<E*>(0) - 1),
+	_lastLeaf(tree._lastLeaf) {
+	if (tree.size() > minCapacity)
+	  minCapacity = tree.size();
+	_capacityEnd = Node(0).next(minCapacity);
+	if (minCapacity == 0)
+	  return;
+	_array = new E[minCapacity] - 1;
+	for (Node i; i <= tree.lastLeaf(); ++i)
+	  (*this)[i] = tree[i];
+  }
+
+  template<class E, bool FI>
+	E& ComTree<E, FI>::operator[](Node n) {
+	if (!FI)
+	  return _array[n._index];
+	char* base = reinterpret_cast<char*>(_array);
+	E* element = reinterpret_cast<E*>(base + n._index);
+	MATHIC_ASSERT(element == &(_array[n._index / sizeof(E)]));
+	return *element;
+  }
+
+  template<class E, bool FI>
+	const E& ComTree<E, FI>::operator[](Node n) const {
+	return const_cast<ComTree<E, FI>*>(this)->operator[](n);
+  }
+
+  template<class E, bool FI>
+	void ComTree<E, FI>::pushBack(const E& value) {
+	if (_lastLeaf == _capacityEnd)
+	  increaseCapacity();
+	_lastLeaf = _lastLeaf.next();
+	(*this)[lastLeaf()] = value;
+  }
+
+  template<class E, bool FI>
+	void ComTree<E, FI>::pushBackWithCapacity(const E& value) {
+	MATHIC_ASSERT(_lastLeaf != _capacityEnd);
+	_lastLeaf = _lastLeaf.next();
+	(*this)[lastLeaf()] = value;
+  }
+
+  template<class E, bool FI>
+	void ComTree<E, FI>::popBack() {
+	MATHIC_ASSERT(_lastLeaf >= Node());
+	_lastLeaf = _lastLeaf.prev();
+  }
+
+  template<class E, bool FI>
+	void ComTree<E, FI>::swap(ComTree& tree) {
+	std::swap(_array, tree._array);
+	std::swap(_lastLeaf, tree._lastLeaf);
+	std::swap(_capacityEnd, tree._capacityEnd);
+  }
+
+  template<class E, bool FI>
+	typename ComTree<E, FI>::Node ComTree<E, FI>::Node::parent() const {
+	return fi ? Node((_index / (2 * S)) * S) : Node(_index / 2);
+  }
+
+  template<class E, bool FI>
+	typename ComTree<E, FI>::Node ComTree<E, FI>::Node::left() const {
+	return Node(2 * _index);
+  }
+
+  template<class E, bool FI>
+	typename ComTree<E, FI>::Node ComTree<E, FI>::Node::right() const {
+	return fi ? Node(2 * _index + S) : Node(2 * _index + 1);
+  }
+
+  template<class E, bool FI>
+	typename ComTree<E, FI>::Node ComTree<E, FI>::Node::sibling() const {
+	return fi ? Node(_index ^ S) : Node(_index ^ 1);
+  }
+
+  template<class E, bool FI>
+	typename ComTree<E, FI>::Node ComTree<E, FI>::Node::leftSibling() const {
+	return fi ? Node(_index & ~S) : Node(_index & ~1);
+  }
+
+  template<class E, bool FI>
+	typename ComTree<E, FI>::Node ComTree<E, FI>::Node::next() const {
+	return fi ? Node(_index + S) : Node(_index + 1);
+  }
+
+  template<class E, bool FI>
+	typename ComTree<E, FI>::Node ComTree<E, FI>::Node::next(size_t count) const {
+	return fi ? Node(_index + S * count) : Node(_index + count);
+  }
+
+  template<class E, bool FI>
+	typename ComTree<E, FI>::Node ComTree<E, FI>::Node::prev() const {
+	return fi ? Node(_index - S) : Node(_index - 1);
+  }
+
+  template<class E, bool FI>
+	void ComTree<E, FI>::print(std::ostream& out) const {
+	Node last = lastLeaf();
+	for (Node i; i <= last; i = i.next()) {
+	  if ((i._index & (i._index - 1)) == 0) // if i._index is a power of 2
+		out << "\n " << i._index << ':';
+	  out << ' ' << (*this)[i];
+	}
+	out << "}\n";
+  }
+
+#ifdef MATHIC_DEBUG
+  template<class E, bool FI>
+	bool ComTree<E, FI>::isValid() const {
+	// sizeof(Entry) must be a power of two if FastIndex is true.
+	MATHIC_ASSERT(!FI || (sizeof(E) & (sizeof(E) - 1)) == 0);
+	if (capacity() == 0) {
+	  MATHIC_ASSERT(_array == static_cast<E*>(0) - 1);
+	  MATHIC_ASSERT(_capacityEnd == Node(0));
+	  MATHIC_ASSERT(_lastLeaf == Node(0));
+	} else {
+	  MATHIC_ASSERT(_array != static_cast<E*>(0) - 1);
+	  MATHIC_ASSERT(_capacityEnd > Node(0));
+	  MATHIC_ASSERT(_lastLeaf <= _capacityEnd);
+	}
+	return true;
+  }
+#endif
+
+  template<class E, bool FI>
+	bool ComTree<E, FI>::hasFreeCapacity(size_t extraCapacity) const {
+	return Node(_capacityEnd._index - _lastLeaf._index) >=
+	  Node(0).next(extraCapacity);
+  }
+
+  template<class E, bool FI>
+	void ComTree<E, FI>::increaseCapacity() {
+	ComTree<E, FI> newTree(capacity() == 0 ? 16 : capacity() * 2);
+	for (Node i; i <= lastLeaf(); i = i.next())
+	  newTree.pushBack((*this)[i]);
+	std::swap(_array, newTree._array);
+	std::swap(_capacityEnd, newTree._capacityEnd);
+	MATHIC_ASSERT(isValid());
+  }
+}
+
+#endif
diff --git a/src/mathic/Comparer.h b/src/mathic/Comparer.h
new file mode 100644
index 0000000..6f60bac
--- /dev/null
+++ b/src/mathic/Comparer.h
@@ -0,0 +1,18 @@
+#ifndef MATHIC_COMPARER_GUARD
+#define MATHIC_COMPARER_GUARD
+
+namespace mathic {
+  template<class C>
+    class Comparer {
+  public:
+  Comparer(const C& conf): _conf(conf) {}
+  template<class A, class B>
+  bool operator()(const A& a, const B& b) const {
+    return _conf.isLessThan(a.get(), b.get());
+  }
+  private:
+    const C& _conf;
+  };
+}
+
+#endif
diff --git a/src/mathic/DivFinder.h b/src/mathic/DivFinder.h
new file mode 100755
index 0000000..7fbb933
--- /dev/null
+++ b/src/mathic/DivFinder.h
@@ -0,0 +1,74 @@
+#ifndef MATHIC_DIV_FINDER_GUARD
+#define MATHIC_DIV_FINDER_GUARD
+
+/** An object that supports queries for divisors of a monomial.
+
+ This is an object for documentation purposes. Use the concrete
+ implementations of this interface to get an actual DivFinder-like
+ object.
+
+ DivFinder stores configurable Entry objects that represent a monomial
+ together with any required additional information.
+
+ The class is parameterized on a Configuration. The Configuration class
+ must have the following members.
+
+ * A type Monomial
+  Represents a monomial.
+
+ * A type Entry
+  These are the things added to the finder. Entry represents a monomial
+  along with any additional required information that client code needs
+  to associate with monomials in the finder.
+
+ * A type Exponent
+  These are exponents of the monomials. Exponent must have a copy constructor,
+  an operator= and an operator< for comparision with other exponents.
+
+ * A function Exponent getExponent(Monomial m, size_t var) const
+  Returns the exponent of the variable var in m. m can be a const reference.
+
+ * A function bool divides(Entry a, Monomial b) const
+ * A function bool divides(Monomial a, Entry b) const
+ * A function bool divides(Entry a, Entry b) const
+  Returns whether a divides b. a and b can be const references. If Entry
+  and Monomial are the same type then only one function is needed.
+
+ * A function size_t getVarCount() const
+  Returns the number of variables. Variables are indexed from 0 to
+  getVarCount() - 1. Must be a positive number.
+
+ * static const bool UseDivMask
+  Set to true to use div masks to speed up queries. This must be a
+  static const data member.
+
+ * size_t getUseAutomaticRebuild() const
+ * double getRebuildRatio() const
+ * size_t getRebuildMin() const
+  If getUseAutomaticRebuild() returns true, the tree will call rebuild
+  after a total of max(size() * getRebuildRatio(), getRebuildMin())
+  entry insertions and removals have occurred. A rebuild ratio of 0.5
+  and a minimum of 500 has worked well for random vectors.
+
+ * A method bool isLessThan(Entry a, Monomial b) const
+ * A method bool isLessThan(Monomial a, Entry b) const
+ * A method bool isLessThan(Entry a, Entry b) const
+  isLessThan must define a total order < on entries/monomials. a and b can
+  be const references. If Entry and Monomial are the same type then only
+  one function is needed.
+
+ It is possible to obtain non-const Entries from a DivFinder. It is allowed
+ to change these, but the monomial they represent must not change. When the
+ DivFinder calls some method X on the Configuration, the Configuration must
+ not in return cause a method to be called on the DivFinder until the method
+ X has returned. This is because the DivFinder may not be in a valid state
+ at the time it is calling X.
+
+ @todo: put these docs somewhere else.
+*/
+namespace {
+  template<class Configuration>
+  class DivFinder; // no implementation
+}
+
+#endif
diff --git a/src/mathic/DivList.h b/src/mathic/DivList.h
new file mode 100755
index 0000000..1f5928a
--- /dev/null
+++ b/src/mathic/DivList.h
@@ -0,0 +1,616 @@
+#ifndef MATHIC_DIV_ARRAY_GUARD
+#define MATHIC_DIV_ARRAY_GUARD
+
+#include "stdinc.h"
+#include "DivMask.h"
+#include "Comparer.h"
+#include <memtailor.h>
+#include <vector>
+#include <string>
+#include <list>
+#include <algorithm>
+#include <sstream>
+
+namespace mathic {
+  /** An object that supports queries for divisors of a monomial using
+      an array of monomials. See DivFinder for more documentation.
+
+      Extra fields for Configuration:
+
+      * static const bool UseLinkedList
+      Use a linked list if true, otherwise use an array.
+
+      * static const bool UseDivMask
+      Use div masks if true.
+
+      * bool getSortOnInsert() const
+      Keep the monomials sorted to speed up queries.
+  */
+  template<class Configuration>
+    class DivList;
+
+  namespace DivListHelper {
+    // Implementation details for DivList.
+
+    template<bool B, class E>
+      struct ListImpl;
+
+    template<class Entry>
+      struct ListImpl<false, Entry> {
+      typedef std::vector<Entry> Impl;
+    };
+    template<class Entry>
+      struct ListImpl<true, Entry> {
+      typedef std::list<Entry> Impl;
+    };
+  }
+
+  template<class C>
+    class DivList {
+  public:
+    typedef C Configuration;
+    typedef typename C::Entry Entry;
+    typedef typename C::Monomial Monomial;
+    typedef typename C::Exponent Exponent;
+
+    static const bool UseLinkedList = C::UseLinkedList;
+    static const bool UseDivMask = C::UseDivMask;
+
+  private:
+    typedef typename DivMask::Extender<Entry, C::UseDivMask> ExtEntry;
+    typedef typename DivMask::Extender<const Monomial&,C::UseDivMask> ExtMonoRef;
+    typedef typename DivMask::Calculator<C> DivMaskCalculator;
+
+    typedef typename DivListHelper::ListImpl<C::UseLinkedList, ExtEntry>::Impl
+      List;
+    typedef typename List::iterator ListIter;
+    typedef typename List::const_iterator CListIter;
+
+  public:
+    class iterator;
+    class const_iterator;
+
+    DivList(const C& configuration);
+
+    template<class Iter>
+      void insert(Iter begin, Iter end);
+    void insert(const Entry& entry);
+
+    bool removeMultiples(const Monomial& monomial);
+    template<class MultipleOutput>
+      bool removeMultiples
+      (const Monomial& monomial, MultipleOutput& out);
+
+    bool removeElement(const Monomial& monomial);
+
+    iterator findDivisorIterator(const Monomial& monomial);
+
+    Entry* findDivisor(const Monomial& monomial);
+    const Entry* findDivisor(const Monomial& monomial) const;
+
+    template<class DO>
+    void findAllDivisors(const Monomial& monomial, DO& out);
+    template<class DO>
+    void findAllDivisors(const Monomial& monomial, DO& out) const;
+
+    template<class DO>
+    void findAllMultiples(const Monomial& monomial, DO& out);
+
+    template<class Output>
+    void findAllMultiples(const Monomial& monomial, Output& output) const {
+      ConstEntryOutput<Output> constOutput(output);
+      const_cast<DivList<C>&>(*this).findAllMultiples(monomial, constOutput);
+    }
+
+    template<class EntryOutput>
+    void forAll(EntryOutput& output);
+    template<class EntryOutput>
+    void forAll(EntryOutput& output) const;
+
+    iterator begin() {return iterator(_list.begin());}
+    const_iterator begin() const {return const_iterator(_list.begin());}
+    iterator end() {return iterator(_list.end());}
+    const_iterator end() const {return const_iterator(_list.end());}
+
+    bool empty() const {return _list.empty();}
+    size_t size() const {return _list.size();}
+
+    std::string getName() const;
+
+    C& getConfiguration() {return _conf;}
+    const C& getConfiguration() const {return _conf;}
+
+    void moveToFront(iterator pos);
+
+    void rebuild();
+
+	/** Returns the number of bytes allocated by this object. Does not
+		include sizeof(*this), does not include any additional memory
+		that the configuration may have allocated and does not include
+		any memory that an Entry may point to. Does include
+		sizeof(Entry) as well as unused memory that is being kept to
+		avoid frequent allocations. */
+    size_t getMemoryUse() const;
+
+  private:
+    DivList(const DivList<C>&); // unavailable
+    void operator=(const DivList<C>&); // unavailable
+
+    void resetNumberOfChangesTillRebuild();
+    void reportChanges(size_t changesMadeCount);
+
+    template<class DO>
+    class ConstEntryOutput {
+    public:
+    ConstEntryOutput(DO& out): _out(out) {}
+      bool proceed(const Entry& entry) {return _out.proceed(entry);}
+    private:
+      DO& _out;
+    };
+    class DummyMultipleOutput {
+    public:
+      void push_back(Entry& e) {}
+    };
+
+    List _list;
+    C _conf;
+    DivMaskCalculator _divMaskCalculator;
+    size_t _changesTillRebuild; /// Update using reportChanges().
+  };
+
+  template<class C>
+    class DivList<C>::const_iterator :
+  public std::iterator<std::bidirectional_iterator_tag, const Entry> {
+  public:
+    friend class DivList<C>;
+    explicit const_iterator(CListIter it): _it(it) {}
+    bool operator==(const_iterator it) {return _it == it._it;}
+    bool operator!=(const_iterator it) {return _it != it._it;}
+    bool operator==(iterator it) {return *this == const_iterator(it);}
+    bool operator!=(iterator it) {return *this != const_iterator(it);}
+
+    const Entry& operator*() const {return _it->get();}
+    const Entry* operator->() const {return &_it->get();}
+
+    const_iterator& operator++() {++_it; return *this;}
+    const_iterator operator++(int) {
+      const_iterator tmp = *this;
+      operator++();
+      return tmp;
+    }
+    const_iterator& operator--() {--_it; return *this;}
+    const_iterator operator--(int) {
+      const_iterator tmp = *this;
+      operator--();
+      return tmp;
+    }
+
+  protected:
+    ListIter getInternal() {return _it;}
+
+  private:
+    CListIter _it;
+  };
+
+  template<class C>
+    class DivList<C>::iterator :
+  public std::iterator<std::bidirectional_iterator_tag, Entry> {
+  public:
+    friend class DivList<C>;
+    explicit iterator(ListIter it): _it(it) {}
+    operator const_iterator() const {return const_iterator(_it);}
+
+    bool operator==(iterator it) {return _it == it._it;}
+    bool operator!=(iterator it) {return _it != it._it;}
+    bool operator==(const_iterator it) {return it == const_iterator(*this);}
+    bool operator!=(const_iterator it) {return it != const_iterator(*this);}
+
+    iterator& operator++() {++_it; return *this;}
+    iterator operator++(int) {iterator tmp = *this; operator++(); return tmp;}
+    iterator& operator--() {--_it; return *this;}
+    iterator operator--(int) {iterator tmp = *this; operator--(); return tmp;}
+
+    Entry& operator*() const {return _it->get();}
+    Entry* operator->() const {return &_it->get();}
+
+  protected:
+    ListIter getInternal() {return _it;}
+
+  private:
+    ListIter _it;
+  };
+
+  namespace DivListHelper {
+    template<class C, class E, class M, class MO>
+      size_t removeMultiples
+      (C& conf, std::vector<E>& list, const M& monomial, MO& out) {
+      typedef typename std::vector<E>::iterator iterator;
+      iterator it = list.begin();
+      iterator oldEnd = list.end();
+      for (; it != oldEnd; ++it) {
+        if (monomial.divides(*it, conf)) {
+          out.push_back(it->get());
+          break;
+        }
+      }
+      if (it == oldEnd)
+        return 0;
+      iterator newEnd = it;
+      for (++it; it != oldEnd; ++it) {
+        if (!monomial.divides(*it, conf)) {
+          *newEnd = *it;
+          ++newEnd;
+        } else
+          out.push_back(it->get());
+      }
+      const size_t origSize = list.size();
+      const size_t newSize = std::distance(list.begin(), newEnd);
+      MATHIC_ASSERT(newSize < list.size());
+      list.resize(newSize);
+      return origSize - newSize;
+    }
+
+    template<class C, class E, class M, class MO>
+    size_t removeMultiples(C& conf,
+                           std::list<E>& list,
+                           const M& monomial,
+                           MO& out) {
+#ifdef MATHIC_DEBUG
+      const size_t origSize = list.size();
+#endif
+      typedef typename std::list<E>::iterator iterator;
+      iterator it = list.begin();
+      iterator oldEnd = list.end();
+      size_t removedCount = 0;
+      while (it != oldEnd) {
+        if (monomial.divides(*it, conf)) {
+          out.push_back(it->get());
+          ++removedCount;
+          it = list.erase(it);
+        } else
+          ++it;
+      }
+      MATHIC_ASSERT(list.size() + removedCount == origSize);
+      return removedCount;
+    }
+
+    template<class E, class It>
+      void moveToFront(std::vector<E>& list, It pos) {
+      E valueToMove = *pos;
+      It begin = list.begin();
+      while (pos != begin) {
+        It prev = pos;
+        --pos;
+        *prev = *pos;
+      }
+      list.front() = valueToMove;
+    }
+
+    template<class E, class It>
+      void moveToFront(std::list<E>& list, It pos) {
+      list.splice(list.begin(), list, pos);
+    }
+
+    template<class C, class E>
+      typename std::list<E>::iterator
+      insertSort(C& conf, std::list<E>& list, const E& entry) {
+      typedef typename std::list<E>::iterator iterator;
+      iterator end = list.end();
+      iterator it = list.begin();
+      for (; it != end; ++it)
+        if (conf.isLessThan(entry.get(), it->get()))
+          break;
+      return list.insert(it, entry);
+    }
+
+    template<class C, class E>
+      typename std::vector<E>::iterator
+      insertSort(C& conf, std::vector<E>& list, const E& entry) {
+      typedef typename std::vector<E>::iterator iterator;
+      iterator it = std::upper_bound(list.begin(), list.end(), entry,
+                                     Comparer<C>(conf));
+      return list.insert(it, entry);
+    }
+
+    template<class C, class E>
+      void sortAll(C& conf, std::list<E>& list) {
+      list.sort(Comparer<C>(conf));
+    }
+
+    template<class C, class E>
+      void sortAll(C& conf, std::vector<E>& list) {
+      std::sort(list.begin(), list.end(), Comparer<C>(conf));
+    }
+
+    template<class C, class E, class M>
+      typename std::vector<E>::iterator
+      findDivisorSorted(C& conf, std::vector<E>& list, const M& monomial) {
+      typedef typename std::vector<E>::iterator iterator;
+      iterator rangeEnd =
+        std::upper_bound(list.begin(), list.end(), monomial, Comparer<C>(conf));
+      iterator it = list.begin();
+      for (; it != rangeEnd; ++it)
+        if (it->divides(monomial, conf))
+          return it;
+      return list.end();
+    }
+
+    template<class C, class E, class M>
+      typename std::list<E>::iterator
+      findDivisorSorted(C& conf, std::list<E>& list, const M& monomial) {
+      typedef typename std::list<E>::iterator iterator;
+      iterator end = list.end();
+      iterator it = list.begin();
+      size_t count = 0;
+      for (; it != end; ++it) {
+        ++count;
+        if (count == 35) {
+          count = 0;
+          if (conf.isLessThan(monomial.get(), it->get()))
+            break;
+        }
+        if (it->divides(monomial, conf))
+          return it;
+      }
+      return end;
+    }
+
+    template<class C, class E, class M, class DO>
+      void findAllDivisorsSorted
+      (C& conf, std::vector<E>& list, const M& monomial, DO& out) {
+      typedef typename std::vector<E>::iterator iterator;
+      iterator rangeEnd =
+        std::upper_bound(list.begin(), list.end(), monomial, Comparer<C>(conf));
+      iterator it = list.begin();
+      for (; it != rangeEnd; ++it)
+        if (it->divides(monomial, conf))
+          if (!out.proceed(it->get()))
+            break;
+    }
+
+    template<class C, class E, class M, class O>
+      void findAllDivisorsSorted
+      (C& conf, std::list<E>& list, const M& monomial, O& out) {
+      typedef typename std::list<E>::iterator iterator;
+      iterator end = list.end();
+      iterator it = list.begin();
+      size_t count = 0;
+      for (; it != end; ++it) {
+        ++count;
+        if (count == 35) {
+          count = 0;
+          if (conf.isLessThan(monomial.get(), it->get()))
+            break;
+        }
+        if (it->divides(monomial, conf))
+          if (!out.proceed(it->get()))
+            break;
+      }
+    }
+  }
+
+  template<class C>
+    DivList<C>::DivList(const C& configuration):
+  _conf(configuration),
+    _divMaskCalculator(configuration) {
+      resetNumberOfChangesTillRebuild();
+    }
+
+  template<class C>
+    void DivList<C>::insert(const Entry& entry) {
+    ExtEntry extEntry(entry, _divMaskCalculator, _conf);
+
+    if (!_conf.getSortOnInsert())
+      _list.push_back(extEntry);
+    else
+      DivListHelper::insertSort(_conf, _list, extEntry);
+    reportChanges(1);
+  }
+
+  template<class C>
+    template<class Iter>
+    void DivList<C>::insert(Iter rangeBegin, Iter rangeEnd) {
+    if (!empty()) {
+      for (; rangeBegin != rangeEnd; ++rangeBegin)
+        insert(*rangeBegin);
+      return;
+    }
+    if (rangeBegin == rangeEnd)
+      return;
+
+    _divMaskCalculator.rebuild(rangeBegin, rangeEnd, _conf);
+    for (; rangeBegin != rangeEnd; ++rangeBegin)
+      _list.push_back(ExtEntry(*rangeBegin, _divMaskCalculator, _conf));
+    if (_conf.getSortOnInsert())
+      DivListHelper::sortAll(_conf, _list);
+    resetNumberOfChangesTillRebuild();
+  }
+
+  template<class C>
+  template<class MO>
+  bool DivList<C>::removeMultiples(const Monomial& monomial, MO& out) {
+    ExtMonoRef extMonomial(monomial, _divMaskCalculator, _conf);
+#ifdef MATHIC_DEBUG
+    const size_t origSize = size();
+#endif
+    const size_t removedCount =
+      DivListHelper::removeMultiples(_conf, _list, extMonomial, out);
+    MATHIC_ASSERT(size() + removedCount == origSize);
+    reportChanges(removedCount);
+    return removedCount > 0;
+  }
+
+  template<class C>
+  bool DivList<C>::removeMultiples(const Monomial& monomial) {
+    DummyMultipleOutput out;
+    return removeMultiples(monomial, out);
+  }
+
+  template<class C>
+  bool DivList<C>::removeElement(const Monomial& monomial) {
+    const size_t varCount = _conf.getVarCount();
+    for (ListIter it = _list.begin(); it != _list.end(); ++it) {
+      for (size_t var = 0; var < varCount; ++var) {
+        if (_conf.getExponent(monomial, var) !=
+          _conf.getExponent(it->get(), var)) {
+          goto skip;
+        }
+      }
+      _list.erase(it);
+      return true;
+    skip:;
+    }
+    return false;
+  }
+
+  template<class C>
+  typename DivList<C>::iterator
+  DivList<C>::findDivisorIterator(const Monomial& monomial) {
+    ExtMonoRef extMonomial(monomial, _divMaskCalculator, _conf);
+
+    if (!_conf.getSortOnInsert()) {
+      ListIter listEnd = _list.end();
+      for (ListIter it = _list.begin(); it != listEnd; ++it) {
+        if (it->divides(extMonomial, _conf))
+          return iterator(it);
+      }
+      return iterator(listEnd);
+    } else
+      return iterator(DivListHelper::findDivisorSorted(_conf, _list, extMonomial));
+  }
+
+  template<class C>
+  typename DivList<C>::Entry*
+  DivList<C>::findDivisor(const Monomial& monomial) {
+    ExtMonoRef extMonomial(monomial, _divMaskCalculator, _conf);
+
+    if (!_conf.getSortOnInsert()) {
+      const ListIter listEnd = _list.end();
+      for (ListIter it = _list.begin(); it != listEnd; ++it) {
+        if (it->divides(extMonomial, _conf))
+          return &it->get();
+      }
+      return 0;
+    } else {
+      ListIter it = DivListHelper::findDivisorSorted(_conf, _list, extMonomial);
+      return it == _list.end() ? 0 : &it->get();
+    }
+  }
+
+  template<class C>
+  const typename DivList<C>::Entry*
+  DivList<C>::findDivisor(const Monomial& monomial) const {
+    return const_cast<DivList<C>&>(*this).findDivisor(monomial);
+  }
+
+  template<class C>
+  template<class DO>
+  void DivList<C>::findAllDivisors(const Monomial& monomial, DO& out) {
+    ExtMonoRef extMonomial(monomial, _divMaskCalculator, _conf);
+    if (!_conf.getSortOnInsert()) {
+      const ListIter listEnd = _list.end();
+      for (ListIter it = _list.begin(); it != listEnd; ++it)
+        if (it->divides(extMonomial, _conf))
+          if (!out.proceed(it->get()))
+            break;
+    } else
+      DivListHelper::findAllDivisorsSorted(_conf, _list, extMonomial, out);
+  }
+
+  template<class C>
+  template<class DO>
+  void DivList<C>::findAllMultiples(const Monomial& monomial, DO& out) {
+    // todo: consider doing sorted version
+    ExtMonoRef extMonomial(monomial, _divMaskCalculator, _conf);
+    const ListIter listEnd = _list.end();
+    for (ListIter it = _list.begin(); it != listEnd; ++it)
+      if (extMonomial.divides(*it, _conf))
+        if (!out.proceed(it->get()))
+          break;
+  }
+
+  template<class C>
+  template<class DO>
+  void DivList<C>::findAllDivisors(const Monomial& monomial,
+                                     DO& output) const {
+    ConstEntryOutput<DO> constOutput(output);
+    const_cast<DivList<C>&>(*this).findAllDivisors(monomial, constOutput);
+  }
+
+  template<class C>
+  template<class EntryOutput>
+  void DivList<C>::forAll(EntryOutput& output) {
+    iterator stop = end();
+    for (iterator it = begin(); it != stop; ++it)
+      if (!output.proceed(*it))
+        return;
+  }
+
+  template<class C>
+  template<class EntryOutput>
+  void DivList<C>::forAll(EntryOutput& output) const {
+    ConstEntryOutput<EntryOutput> constOutput(output);
+    const_cast<DivList<C>&>(*this).forAll(constOutput);
+  }
+
+  template<class C>
+  std::string DivList<C>::getName() const {
+    std::ostringstream out;
+    out <<"DivList"
+        << (UseLinkedList ? " linked" : " array");
+    if (UseDivMask && _conf.getDoAutomaticRebuilds()) {
+      out << " autob:" << _conf.getRebuildRatio()
+          << '/' << _conf.getRebuildMin();
+    }
+    out << (_conf.getSortOnInsert() ? " sort" : "")
+        << (UseDivMask ? " dmask" : "");
+    return out.str();
+  }
+
+  template<class C>
+    void DivList<C>::moveToFront(iterator pos) {
+    DivListHelper::moveToFront(_list, pos.getInternal());
+  }
+
+  template<class C>
+    void DivList<C>::rebuild() {
+    const size_t totalSize = size();
+    typedef memt::ArenaVector<Entry, true> TmpContainer;
+    TmpContainer tmpCopy(memt::Arena::getArena(), totalSize);
+    std::copy(begin(), end(), std::back_inserter<TmpContainer>(tmpCopy));
+    _divMaskCalculator.rebuild(tmpCopy.begin(), tmpCopy.end(), _conf);
+    ListIter listEnd = _list.end();
+    for (ListIter it = _list.begin(); it != listEnd; ++it)
+      it->recalculateDivMask(_divMaskCalculator, _conf);
+    resetNumberOfChangesTillRebuild();
+  }
+
+  template<class C>
+    void DivList<C>::resetNumberOfChangesTillRebuild() {
+    if (!_conf.getDoAutomaticRebuilds())
+      return;
+    MATHIC_ASSERT(_conf.getRebuildRatio() > 0);
+    _changesTillRebuild = std::max
+      (static_cast<size_t>(size() * _conf.getRebuildRatio()),
+       _conf.getRebuildMin());
+  }
+
+  template<class C>
+    void DivList<C>::reportChanges(size_t changesMadeCount) {
+    // note how negative value/overflow of _changesTillRebuild cannot
+    // happen this way.
+    if (!_conf.getDoAutomaticRebuilds())
+      return;
+    if (_changesTillRebuild > changesMadeCount)
+      _changesTillRebuild -= changesMadeCount;
+    else
+      rebuild();
+  }
+
+  template<class C>
+  size_t DivList<C>::getMemoryUse() const {
+	return _list.capacity() * sizeof(_list.front());
+  }
+}
+
+#endif
diff --git a/src/mathic/DivMask.cpp b/src/mathic/DivMask.cpp
new file mode 100644
index 0000000..bc4b1fa
--- /dev/null
+++ b/src/mathic/DivMask.cpp
@@ -0,0 +1,14 @@
+#include "DivMask.h"
+
+#ifdef MATHIC_TRACK_DIV_MASK_HIT_RATIO
+namespace mathic {
+  namespace DivMaskStats {
+    unsigned long maskComputes = 0;
+    unsigned long maskChecks = 0;
+    unsigned long maskHits = 0;
+    unsigned long divChecks = 0;
+    unsigned long divDivides = 0;
+    unsigned long divHits = 0;
+  }
+}
+#endif
diff --git a/src/mathic/DivMask.h b/src/mathic/DivMask.h
new file mode 100644
index 0000000..96f4bb9
--- /dev/null
+++ b/src/mathic/DivMask.h
@@ -0,0 +1,463 @@
+#ifndef MATHIC_BIT_MASK_GUARD
+#define MATHIC_BIT_MASK_GUARD
+
+#include "stdinc.h"
+#include <vector>
+#include <utility>
+#include <algorithm>
+
+// Value x means do 2^x mask checks before printing stats
+//#define MATHIC_TRACK_DIV_MASK_HIT_RATIO 25
+//#define MATHIC_TRACK_DIV_MASK_HIT_RATIO 30
+#ifdef MATHIC_TRACK_DIV_MASK_HIT_RATIO
+#include <iostream>
+#include "ColumnPrinter.h"
+#endif
+
+namespace mathic {
+#ifdef MATHIC_TRACK_DIV_MASK_HIT_RATIO
+  namespace DivMaskStats {
+    extern unsigned long maskComputes; // div masks computed
+    extern unsigned long maskChecks; // how many times mask is checked
+    extern unsigned long maskHits; // times canDivide returns false
+    extern unsigned long divChecks; // times divisibility is checked with mask
+    extern unsigned long divDivides; // mask can't hit as there is divisibility
+    extern unsigned long divHits; // times mask rules out divisibility
+  }
+#endif
+
+  /** Class representing a div mask. This is a set of bits that can
+      be used to determine that one monomial cannot divide another
+      monomial. */
+  class DivMask {
+  public:
+    /** Calculates div masks. Don't change NullCalculator
+        from its default value. The actual code are in partial specializations
+        selecting the right version based on NullCalculator. */
+    template<class Configuration,
+      bool NullCalculator = Configuration::UseDivMask>
+      class Calculator;
+
+  DivMask(): _mask(0) {}
+    static DivMask getMaxMask() {return ~static_cast<MaskType>(0);}
+
+    template<class T, class Configuration>
+      DivMask(const T& t,
+              const Calculator<Configuration>& calc, const Configuration& conf):
+    _mask(calc.compute(t, conf)) {}
+
+    template<class T, class Configuration>
+    void recalculate(const T& t,
+                     const Calculator<Configuration>& calc,
+                     const Configuration& conf) {
+      _mask = calc.compute(t, conf);
+    }
+
+    bool canDivide(const DivMask& mask) const {
+      const bool canDiv = ((_mask & ~mask._mask) == 0);
+#ifdef MATHIC_TRACK_DIV_MASK_HIT_RATIO
+      ++DivMaskStats::maskChecks;
+      if (!canDiv)
+        ++DivMaskStats::maskHits;
+
+      // print stats every 2^MATHIC_TRACK_DIV_MASK_HIT_RATIO time
+      const unsigned long mod = (1 << MATHIC_TRACK_DIV_MASK_HIT_RATIO) - 1;
+      if ((DivMaskStats::maskChecks & mod) == 0) {
+        std::cerr << "**** DivMask stats (turn off by not defining macro) ****\n";
+        ColumnPrinter pr;
+        pr.addColumn(true, "* ");
+        pr.addColumn(false, " ");
+        pr.addColumn(false, "  ");
+        pr.addColumn(true, " ");
+        pr[0] << "masks computed:\n";
+        pr[1] << ColumnPrinter::commafy(DivMaskStats::maskComputes) << '\n';
+        pr[2] << ColumnPrinter::percent
+          (DivMaskStats::maskComputes, DivMaskStats::maskChecks) << '\n';
+        pr[3] << "of mask checks\n";
+
+        pr[0] << "mask checks:\n";
+        pr[1] << ColumnPrinter::commafy(DivMaskStats::maskChecks) << '\n';
+        pr[2] << '\n';
+        pr[3] << '\n';
+
+        pr[0] << "mask hits:\n";
+        pr[1] << ColumnPrinter::commafy(DivMaskStats::maskHits) << '\n';
+        pr[2] << ColumnPrinter::percent
+          (DivMaskStats::maskHits, DivMaskStats::maskChecks) << '\n';
+        pr[3] << "of mask checks\n";
+
+        pr[0] << "mask div checks:\n";
+        pr[1] << ColumnPrinter::commafy(DivMaskStats::divChecks) << '\n';
+        pr[2] << ColumnPrinter::percent
+          (DivMaskStats::divChecks, DivMaskStats::maskChecks) << '\n';
+        pr[3] << "of mask checks\n";
+
+        pr[0] << "actually divide:\n";
+        pr[1] << ColumnPrinter::commafy(DivMaskStats::divDivides) << '\n';
+        pr[2] << ColumnPrinter::percent
+          (DivMaskStats::divDivides, DivMaskStats::divChecks) << '\n';
+        pr[3] << "of div checks\n";
+
+        pr[0] << "mask div hits:\n";
+        pr[1] << ColumnPrinter::commafy(DivMaskStats::divHits) << '\n';
+        pr[2] << ColumnPrinter::percent
+          (DivMaskStats::divHits, DivMaskStats::divChecks) << '\n';
+        pr[3] << "of div checks, " << ColumnPrinter::percent
+          (DivMaskStats::divHits,
+           DivMaskStats::divChecks - DivMaskStats::divDivides)
+           << " adjusted.\n";          
+        std::cerr << pr << "****\n";
+      }
+#endif
+
+      return canDiv;
+    }
+
+    void combineAnd(const DivMask& mask) {_mask &= mask._mask;}
+
+    bool operator==(DivMask& mask) const {return _mask == mask._mask;}
+    bool operator!=(DivMask& mask) const {return _mask != mask._mask;}
+
+    /** Extender extends T with a div mask if UseDivMask is true. It is
+        allowed for T to be a reference type or const. */
+    template<class T, bool UseDivMask>
+    class Extender;
+
+    /** Base class to include a DivMask into a class at compile time
+        based on the template parameter UseDivMask. The class offers
+        the same methods either way, but they are replaced by do-nothing
+        or asserting versions if UseDivMask is false. */
+    template<bool UseDivMask>
+    class HasDivMask;
+
+  protected:
+    template<class C>
+    class ExponentComparer {
+    public:
+      ExponentComparer(size_t var, const C& conf): _var(var), _conf(conf) {}
+      template<class E>
+      bool operator()(const E& a, const E& b) const {
+        return _conf.getExponent(a, _var) < _conf.getExponent(b, _var);
+      }
+    private:
+      size_t _var;
+      const C& _conf;
+    };
+
+    struct VarData {
+      size_t var; // the variable in question
+
+      // let e be the average of the minimum and maximum exponent of var.
+      // then split is the number of elements whose exponent of var is
+      // <= average, or it is the number of elements whose exponent of var
+      // is > average, whichever is those two numbers is smaller.
+      size_t split;
+
+      // How many bits of the DivMask to dedicate to this variable.
+      size_t bitsForVar;
+
+      bool operator<(const VarData& data) const {
+        return split > data.split; // larger split first in order
+      }
+    };
+
+    typedef unsigned int MaskType;
+    DivMask(MaskType mask): _mask(mask) {}
+
+  private:
+    /** To eliminate warnings about T& if T is already a reference type. */
+    template<class T> struct Ref {typedef T& RefType;};
+    template<class T> struct Ref<T&> {typedef T& RefType;};
+    MaskType _mask;
+  };
+
+  template<class C>
+    class DivMask::Calculator<C, true> {
+  public:
+    Calculator(const C& conf) {rebuildDefault(conf);}
+
+    /** Change the meaning of the bits in the div masks produced by this
+        object to something that will likely work well for entries
+        in [begin, end). All div masks will have to be recomputed
+        after this. Mixing div masks computed before a call to
+        rebuild() with ones after has unpredictable results. */
+    template<class Iter>
+    void rebuild(Iter begin, Iter end, const C& conf);
+
+    /** Rebuilds without the benefit of knowing a range of entries
+        that the div masks are supposed to work well for. */
+    void rebuildDefault(const C& conf);
+
+    /** Computes a div mask for t. */
+    template<class T>
+    DivMask::MaskType compute(const T& t, const C& conf) const;
+
+  private:
+    typedef typename C::Exponent Exponent;
+    /** If entry at index i is the pair (var,exp) then the bit at
+        index var in a bit mask is 1 if the exponent of var in the
+        monomial is strictly greater than exp. */
+    typedef std::vector<std::pair<size_t, Exponent> > BitContainer;
+    BitContainer _bits;
+  };
+
+  template<class C>
+  template<class Iter>
+  void DivMask::Calculator<C, true>::
+  rebuild(Iter begin, Iter end, const C& conf) {
+    const size_t size = std::distance(begin, end);
+    if (size == 0) {
+      rebuildDefault(conf);
+      return;
+    }
+
+    _bits.clear();
+    const size_t varCount = conf.getVarCount();
+    const size_t TotalBits = sizeof(MaskType) * BitsPerByte;
+
+    // ** Determine information about each variable
+    std::vector<VarData> datas;
+    for (size_t var = 0; var < varCount; ++var) {
+      Exponent min = conf.getExponent(*begin, 0);
+      Exponent max = min;
+      for (Iter it = begin; it != end; ++it) {
+        Exponent exp = conf.getExponent(*it, var);
+        if (max < exp)
+          max = exp;
+        if (exp < min)
+          min = exp;
+      }
+      Exponent average = min + (max - min) / 2; // this formula avoids overflow
+      size_t split = 0;
+      for (Iter it = begin; it != end; ++it)
+        if (conf.getExponent(*it, var) < average)
+          ++split;
+      if (split > size / 2)
+        split = size - split;
+      VarData data;
+      data.var = var;
+      data.split = split;
+      datas.push_back(data);
+    }
+    std::sort(datas.begin(), datas.end());
+    MATHIC_ASSERT(datas.size() == varCount);
+
+    // distribute bits to variables according to the data collected
+    std::vector<size_t> bitsForVars(varCount);
+    for (size_t i = 0; i < varCount; ++i) {
+      const size_t var = datas[i].var;
+      bitsForVars[var] = TotalBits / varCount;
+      if (i < TotalBits % varCount)
+        ++bitsForVars[var];
+    }
+
+    // calculate the meaning of each bit and put it in _bits
+    for (size_t var = 0; var < varCount; ++var) {
+      const size_t bitsForVar = bitsForVars[var];
+      if (bitsForVar == 0)
+        continue;
+
+      const bool useRank = false;
+      if (useRank) {
+        std::sort(begin, end, ExponentComparer<C>(var, conf));
+        size_t size = std::distance(begin, end);
+        size_t offset = size / (bitsForVar + 1);
+        if (offset== 0)
+          offset = 1;
+        Exponent lastExp;
+        size_t lastJ = 0;
+        for (size_t i = 1; i <= bitsForVar; ++i) {
+          size_t j = i * offset;
+          if (i > 1 && j < lastJ)
+            j = lastJ + 1;
+          if (j >= size)
+            j = size - 1;
+          if (i > 1) {
+            while (j < size && conf.getExponent(begin[j], var) == lastExp)
+              ++j;
+            if (j == size)
+              break;
+          }
+          _bits.push_back(
+            std::make_pair(var, conf.getExponent(begin[j], var)));
+          lastJ = j;
+          lastExp = conf.getExponent(begin[j], var);
+          if (j == size - 1)
+            break;
+        }
+      } else {
+        Exponent min = conf.getExponent(*begin, 0);
+        Exponent max = min;
+        for (Iter it = begin; it != end; ++it) {
+          Exponent exp = conf.getExponent(*it, var);
+          if (max < exp)
+            max = exp;
+          if (exp < min)
+            min = exp;
+        }
+
+        // divide the range [a,b] into bitsForVar equal pieces
+        // and use the left end points of those ranges
+        // as the points for the bits.
+        Exponent increment = (max - min) / static_cast<Exponent>(bitsForVar); // todo: can avoid cast?
+        if (increment == 0)
+          increment = 1;
+        for (size_t i = 0; i < bitsForVar; ++i)
+          _bits.push_back(std::make_pair(var, min + increment * static_cast<Exponent>(i)));
+           // todo: can avoid cast?
+      }
+    }
+  }
+
+  template<class C>
+    void DivMask::Calculator<C, true>::
+    rebuildDefault(const C& conf) {
+    _bits.clear();
+    const size_t varCount = conf.getVarCount();
+    const size_t TotalBits = sizeof(MaskType) * BitsPerByte;
+    for (size_t var = 0; var < varCount; ++var) {
+      const size_t bitsForVar =
+        TotalBits / varCount + (var < TotalBits % varCount);
+      Exponent exp = 0;
+      for (size_t i = 0; i < bitsForVar; ++i) {
+        _bits.push_back(std::make_pair(var, exp));
+        exp = (i == 0 ? 1 : exp * 2);
+      }
+    }
+  }
+
+  template<class C>
+  template<class T>
+  DivMask::MaskType DivMask::Calculator<C, true>::
+    compute(const T& t, const C& conf) const {
+#ifdef MATHIC_TRACK_DIV_MASK_HIT_RATIO
+      ++DivMaskStats::maskComputes;
+#endif
+    typedef typename BitContainer::const_iterator const_iterator;
+    const const_iterator end = _bits.end();
+    DivMask::MaskType mask = 0;
+    for (const_iterator it = _bits.begin(); it != end; ++it)
+      mask = (mask << 1) | (conf.getExponent(t, it->first) > it->second);   
+    return mask;
+  }
+
+  template<class C>
+    class DivMask::Calculator<C, false> {
+  public:
+    Calculator(const C& conf) {}
+
+    template<class Iter>
+    void rebuild(Iter begin, Iter end, const C& conf) {}
+    void rebuildDefault(const C& conf) {}
+  };
+
+  template<>
+  class DivMask::HasDivMask<true> {
+  public:
+    template<class T, class C>
+      HasDivMask(const T& t, const Calculator<C>& calc, const C& conf):
+    _mask(t, calc, conf) {}
+    HasDivMask() {resetDivMask();}
+
+    DivMask& getDivMask() {return _mask;}
+    const DivMask& getDivMask() const {return _mask;}
+    void resetDivMask() {_mask = DivMask::getMaxMask();}
+    bool canDivide(const HasDivMask<true>& t) const {
+      return getDivMask().canDivide(t.getDivMask());
+    }
+
+    void updateToLowerBound(const HasDivMask<true>& t) {
+      _mask.combineAnd(t.getDivMask());
+    }
+
+  protected:
+    template<class T, class C>
+      void recalculateDivMask
+      (const T& t, const Calculator<C>& calc, const C& conf) {
+      _mask.recalculate(t, calc, conf);
+    }
+
+  private:
+    DivMask _mask;
+  };
+
+  template<>
+  class DivMask::HasDivMask<false> {
+  public:
+    void resetDivMask() {MATHIC_ASSERT(false);}
+    DivMask getDivMask() const {MATHIC_ASSERT(false); return DivMask();}
+    bool canDivide(const HasDivMask<false>& t) const {return true;}
+    template<bool B>
+    void updateToLowerBound(const HasDivMask<B>& entry) {}
+  };
+
+  template<class T>
+  class DivMask::Extender<T, true> : public HasDivMask<true> {
+  private:
+    typedef typename Ref<T>::RefType Reference;
+    typedef typename Ref<const T>::RefType ConstReference;
+  public:
+  Extender(): HasDivMask<true>(), _t() {}
+    template<class C>
+    Extender(ConstReference t, const Calculator<C>& calc, const C& conf):
+    HasDivMask<true>(t, calc, conf), _t(t) {}
+
+    template<class S, class C>
+    bool divides(const Extender<S, true>& t, const C& conf) const {
+      bool canDiv = this->canDivide(t);
+#ifdef MATHIC_TRACK_DIV_MASK_HIT_RATIO
+      ++DivMaskStats::divChecks;
+      if (!canDiv)
+        ++DivMaskStats::divHits;
+#endif
+      if (!canDiv)
+        return false;
+
+      bool actuallyDivides = conf.divides(get(), t.get());
+#ifdef MATHIC_TRACK_DIV_MASK_HIT_RATIO
+      if (actuallyDivides)
+        ++DivMaskStats::divDivides;
+#endif
+      return actuallyDivides;
+    }
+
+    template<class C>
+      void recalculateDivMask(const Calculator<C>& calc, const C& conf) {
+      this->HasDivMask<true>::recalculateDivMask(get(), calc, conf);
+    }
+
+    Reference get() {return _t;}
+    ConstReference get() const {return _t;}
+
+  private:
+    T _t;
+  };
+
+  template<class T>
+    class DivMask::Extender<T, false> : public HasDivMask<false> {
+  private:
+    typedef typename Ref<T>::RefType Reference;
+    typedef typename Ref<const T>::RefType ConstReference;
+  public:
+  Extender(): HasDivMask<false>(), _t() {}
+    template<class C>
+      Extender(ConstReference t, const Calculator<C>& calc, const C& conf):
+    HasDivMask<false>(), _t(t) {}
+
+    template<class S, class C>
+      bool divides(const Extender<S, false>& t, const C& conf) const {
+      return conf.divides(get(), t.get());
+    }
+
+    template<class C>
+      void recalculateDivMask(const Calculator<C>& calc, const C& conf) {}
+
+    Reference get() {return _t;}
+    ConstReference get() const {return _t;}
+
+  private:
+    T _t;
+  };
+}
+
+#endif
diff --git a/src/mathic/ElementDeleter.cpp b/src/mathic/ElementDeleter.cpp
new file mode 100755
index 0000000..fe8d951
--- /dev/null
+++ b/src/mathic/ElementDeleter.cpp
@@ -0,0 +1 @@
+#include "ElementDeleter.h"
diff --git a/src/mathic/ElementDeleter.h b/src/mathic/ElementDeleter.h
new file mode 100755
index 0000000..9de80ab
--- /dev/null
+++ b/src/mathic/ElementDeleter.h
@@ -0,0 +1,138 @@
+#ifndef MATHIC_ELEMENT_DELETER_GUARD
+#define MATHIC_ELEMENT_DELETER_GUARD
+
+#include "stdinc.h"
+#include <memory>
+
+namespace mathic {
+  // The purpose of this class is to call delete on the elements of a
+  // standard library container which holds pointers. It removes the
+  // elements from the container as they are being deleted, but it does
+  // not delete the container itself. Do not use this class to
+  // deallocate a vector of built-in arrays, since those require
+  // deallocation using delete[] rather than delete.
+  //
+  // This can be a convenience when coding, but the real purpose is to
+  // avoid memory leaks in the face of an exception being thrown. When a
+  // standard library container goes out of scope, its destructor is
+  // called, but the destructor does not deallocate pointer elements, so
+  // they will leak unless special care is taken to avoid that, such as
+  // using this class.
+  //
+  // The most straight-forward solution may seem to use
+  // e.g. vector<auto_ptr<T>> in place of vector<T*>, but this does not
+  // work because storing auto_ptr<T> in a standard library container is
+  // never safe (look this up on the internet to get the details).
+  //
+  // The reference counting smart pointer class shared_ptr from Boost or
+  // TR1 would solve this issue even better by using
+  // vector<shared_ptr<T>> instead of vector<T*>, but that would require
+  // a dependency on Boost or on having a very recent compiler which
+  // incorporates TR1.
+  //
+  // TODO: make an AutoVector that wraps std::vector instead of or as a
+  // supplement to this class.
+  //
+  // Container::value_type is required to be a pointer type.
+  template<class Container>
+  class ElementDeleter {
+   public:
+    // Only the constructor can attach an ElementDeleter to a container,
+    // and this helps ensure (but does not guarantee) the precondition
+    // of the destructor of ElementDeleter.
+    ElementDeleter(Container& container): _container(&container) {
+    }
+
+    // Calls deleteElements() and shares its precondition.
+    ~ElementDeleter() {
+      deleteElements();
+    }
+
+    // Call release() to prevent this ElementDeleter from manipulating
+    // the container in any way.
+    void release() {
+      _container = 0;
+    }
+
+    // If release has been called, this method does nothing. Otherwise
+    // the container must still be valid, and then delete is called on
+    // each element of the array and clear is called on the container.
+    void deleteElements() {
+      if (_container == 0)
+        return;
+
+      // The code below may seem obviously correct, but it is a
+      // non-trivial fact that it works in the face of exceptions.
+      //
+      // First of all, we are allowed to assume that destructors do not
+      // throw exceptions, so the loop will run to completion.
+      //
+      // Normally clear() *can* throw an exception according to the
+      // standard (which is weird), but if the copy constructor and
+      // assignment operator do not throw exceptions, then it does
+      // not. In our case, we require the element type to be a pointer
+      // type, so for this reason only do we know that clear will not
+      // throw an exception. Thus we do not have to worry about leaving
+      // around a container full of invalid pointers if clear() should
+      // throw an exception.
+
+      typename Container::iterator end = _container->end();
+      typename Container::iterator it = _container->begin();
+      for (; it != end; ++it)
+        delete *it;
+      _container->clear();
+    }
+
+   private:
+    Container* _container;
+  };
+
+  // exceptionSafePushBack is designed to work around the fact that this
+  // code can leak memory:
+  //
+  //   vector<int*> vec;
+  //   ElementDeleter<vector<int*> > elementDeleter(vec);
+  //   auto_ptr<int> p(new int());
+  //   vec.push_back(p.release())
+  //
+  // This is because push_back can fail by throwing a bad_alloc, and at
+  // that point the pointer in p has already been released, so that
+  // pointer is now lost and hence the memory is leaked.
+  //
+  // This can be fixed by replacing
+  //
+  //   vec.push_back(p.release())
+  //
+  // by
+  //
+  //   vec.push_back(0);
+  //   vec.back() = p.release();
+  //
+  // but this is annoying and looks quite strange. It is much clearer to
+  // write
+  //
+  //   exceptionSafePushBack(vec, p);
+  //
+  template<class Container, class Element>
+  void exceptionSafePushBack(Container& container, std::auto_ptr<Element> pointer) {
+    container.push_back(0);
+    container.back() = pointer.release();
+  }
+
+  // Serves the same purpose as exceptionSafePushBack, except that this
+  // overload will simply ignore an exception without propagating it.
+  // Thus if there is not enough memory to add the element to the container,
+  // the element will simply get deleted and the container will remain
+  // unchanged. This works well if e.g. adding an element to a cache, where
+  // it is no great problem if the element gets deleted rather than added.
+  template<class Container, class Element>
+  void noThrowPushBack(Container& container, std::auto_ptr<Element> pointer) throw () {
+    try {
+      exceptionSafePushBack(container, pointer);
+    } catch (const std::bad_alloc&) {
+      // Ignore the exception.
+    }
+  }
+}
+
+#endif
diff --git a/src/mathic/GeoFront.h b/src/mathic/GeoFront.h
new file mode 100644
index 0000000..9fc145a
--- /dev/null
+++ b/src/mathic/GeoFront.h
@@ -0,0 +1,375 @@
+#ifndef MATHIC_GEO_FRONT_GUARD
+#define MATHIC_GEO_FRONT_GUARD
+
+#include "stdinc.h"
+#include <vector>
+#include <utility>
+
+namespace mathic {
+  /**
+	 To be used by Geobucket class.
+
+	 Configuration is the Configuration from the owning Geobucket.
+
+	 Bucket is the Bucket class from the owning Geobucket. Having Bucket be a
+	 parameter allows it to be used before it is declared so that this header
+	 need not include Geobucket's header, which would otherwise be a cyclic
+	 dependency. This also grants access to Geobucket<C>::Bucket which is
+	 otherwise private.
+
+	 Why not make this an inner template class of Geobucket? Because inner
+	 template classes cannot be specialized without also specializing the
+	 outer class.
+  */
+
+  template<class Configuration>
+	class Geobucket;
+
+  template<class Configuration,
+	class Bucket = typename Geobucket<Configuration>::Bucket,
+	bool Order = Configuration::trackFront>
+	class GeoFront;
+
+  // ********************************************************************
+  // GeoFront maintaining no special order
+  template<class C, class Bucket>
+	class GeoFront<C, Bucket, false> {
+  public:
+	/** A reference is kept to entryCountRef so that it can be updated
+		in the event of a deduplication. */
+  GeoFront(const C& conf, size_t& entryCountRef):
+	_cachedMaxBucket(0), _entryCountRef(entryCountRef), _conf(conf) {
+	  MATHIC_ASSERT(!C::trackFront);
+	}
+
+    void clear() {
+      _cachedMaxBucket = 0;
+    }
+
+	void reserveCapacity(size_t newCapacity) {}
+	void bucketsInvalidated(Bucket* oldBegin, Bucket* newBegin) {
+	  _cachedMaxBucket = 0;
+	}
+	bool empty() const {return _entryCountRef == 0;}
+
+	void insert(Bucket* bucket) {_cachedMaxBucket = 0;}
+	void remove(Bucket* bucket) {_cachedMaxBucket = 0;}
+	void keyIncreased(Bucket* bucket) {_cachedMaxBucket = 0;}
+	void keyDecreased(Bucket* bucket) {_cachedMaxBucket = 0;}
+	void swapKeys(Bucket* a, Bucket* b) {}
+	bool larger(const Bucket* a, const Bucket* b) const {
+	  MATHIC_ASSERT(false);
+	  return false;
+	}
+	const Bucket* getMax(Bucket* bucketBegin, Bucket* bucketEnd) const;
+
+#ifdef MATHIC_DEBUG
+	bool debugIsValid(Bucket* bucketBegin, Bucket* bucketEnd) const;
+#endif
+
+    size_t getMemoryUse() const;
+
+  private:
+	const Bucket* computeMax(Bucket* bucketBegin, Bucket* bucketEnd) const;
+
+	mutable const Bucket* _cachedMaxBucket;
+	mutable size_t& _entryCountRef;
+	const C& _conf;
+  };
+
+  template<class C, class B>
+  size_t GeoFront<C, B, false>::getMemoryUse() const {
+    return 0;
+  }
+
+  template<class C, class B>
+  const B* GeoFront<C, B, false>::getMax(B* bucketBegin, B* bucketEnd) const {
+	// the point is that the compiler is more likely to compile this
+	// pre-calculation so that computeMax won't get called in cases
+	// where the maximum has already been computed.
+	if (_cachedMaxBucket != 0)
+	  return _cachedMaxBucket;
+	return computeMax(bucketBegin, bucketEnd);
+  }
+
+  template<class C, class B>
+	const B* GeoFront<C, B, false>::computeMax
+	(B* bucketBegin, B* bucketEnd) const {
+	MATHIC_ASSERT(_cachedMaxBucket == 0);
+	const B* maxBucket = bucketBegin;
+	while (maxBucket->empty()) {
+	  ++maxBucket;
+	  MATHIC_ASSERT(maxBucket != bucketEnd);
+	}
+	for (const B* it = maxBucket + 1; it != bucketEnd; ++it) {
+	  if (it->empty())
+		continue;
+	  typename C::CompareResult cmp =
+		_conf.compare(it->back(), maxBucket->back());
+	  if (_conf.cmpLessThan(cmp))
+		continue;
+	  if (C::supportDeduplication && _conf.cmpEqual(cmp)) {
+		B* mb = const_cast<B*>(maxBucket);
+		mb->setEntry(mb->end() - 1,
+					 _conf.deduplicate(mb->back(), it->back()));
+		const_cast<B*>(it)->pop_back();
+		--_entryCountRef;
+		continue;
+	  }
+	  maxBucket = it;
+	}
+	MATHIC_ASSERT(maxBucket != bucketEnd);
+	return _cachedMaxBucket = maxBucket;
+  }
+
+#ifdef MATHIC_DEBUG
+  template<class C, class B>
+	bool GeoFront<C, B, false>::debugIsValid(B* bucketBegin, B* bucketEnd) const {
+	if (_cachedMaxBucket == 0)
+	  return true;
+	MATHIC_ASSERT(!_cachedMaxBucket->empty());
+	for (B* bucket = bucketBegin; bucket != bucketEnd; ++bucket) {
+	  if (!bucket->empty()) {
+		MATHIC_ASSERT(!_conf.cmpLessThan
+			   (_conf.compare(_cachedMaxBucket->back(), bucket->back())));
+	  }
+	}
+	return true;
+  }
+#endif
+
+  // ********************************************************************
+  // GeoFront maintaining an ordered list
+  template<class C, class Bucket>
+	class GeoFront<C, Bucket, true> {
+  public:
+	GeoFront(const C& conf, size_t& entryCountRef);
+
+	Bucket** begin() {return _bucketBegin;}
+	Bucket*const* begin() const {return _bucketBegin;}
+	Bucket** end() {return _bucketEnd;}
+	Bucket*const* end() const {return _bucketEnd;}
+
+	/** Can contain this many   */
+	void reserveCapacity(size_t newCapacity);
+	void bucketsInvalidated(Bucket* oldBegin, Bucket* newBegin);
+	bool empty() const {return _bucketBegin == _bucketEnd;}
+
+    void clear();
+	void insert(Bucket* bucket);
+	void remove(Bucket* bucket);
+	void keyIncreased(Bucket* bucket);
+	void keyDecreased(Bucket* bucket);
+	void swapKeys(Bucket* a, Bucket* b);
+	bool larger(const Bucket* a, const Bucket* b) const;
+	const Bucket* getMax(Bucket* bucketBegin, Bucket* bucketEnd) const;
+
+#ifdef MATHIC_DEBUG
+	bool debugIsValid(Bucket* bucketBegin, Bucket* bucketEnd) const;
+#endif
+
+    size_t getMemoryUse() const;
+
+  private:
+    size_t size() const {return _bucketEnd - _bucketBegin;}
+    size_t capacity() const {return _bucketCapacityEnd - _bucketBegin;}
+
+	Bucket** _bucketBegin;
+	Bucket** _bucketEnd;
+    Bucket** _bucketCapacityEnd;
+	mutable size_t& _entryCountRef;
+	const C& _conf;
+  };
+
+  template<class C, class B>
+  void GeoFront<C, B, true>::clear() {
+    _bucketEnd = _bucketBegin;
+  }
+
+  template<class C, class B>
+  size_t GeoFront<C, B, true>::getMemoryUse() const {
+    return capacity() * sizeof(*_bucketBegin);
+  }
+
+  template<class C, class B>
+  GeoFront<C, B, true>::GeoFront(const C& conf, size_t& entryCountRef):
+	_bucketBegin(0),
+	_bucketEnd(0),
+    _bucketCapacityEnd(0),
+	_entryCountRef(entryCountRef),
+	_conf(conf) {
+    MATHIC_ASSERT(C::trackFront);
+  }
+
+  template<class C, class B>
+  void GeoFront<C, B, true>::reserveCapacity(size_t newCapacity) {
+    ASSERT(newCapacity >= size());
+	if (newCapacity == 0)
+	  newCapacity = 1;
+    size_t const oldSize = size();
+	B** const oldBegin = _bucketBegin;  
+    B** const oldEnd = _bucketEnd;
+    _bucketBegin = new B*[newCapacity];
+	_bucketEnd = _bucketBegin + oldSize;
+    _bucketCapacityEnd = _bucketBegin + newCapacity;
+    std::copy(oldBegin, oldEnd, _bucketBegin);
+
+	// the tokens point into the old space, so map them to an index
+	// and then back to a pointer into the newly allocated memory.
+	for (B** bucket = _bucketBegin; bucket != _bucketEnd; ++bucket) {
+	  B** token = (*bucket)->getFrontToken();
+	  token = (token - oldBegin) + _bucketBegin;
+	  (*bucket)->setFrontToken(token);
+	}
+    delete[] oldBegin;
+  }
+
+  template<class C, class B>
+	void GeoFront<C, B, true>::bucketsInvalidated
+	(B* oldBegin, B* newBegin) {
+	// _buckets points into an array of buckets that has been reallocated,
+	// so we need to go to an index and back to update the pointers
+	// to point into the new memory area.
+	if (empty())
+	  return;
+	for (B** bucket = begin(); bucket != end(); ++bucket)
+	  *bucket = (*bucket - oldBegin) + newBegin;
+  }
+
+  template<class C, class B>
+	void GeoFront<C, B, true>::insert(B* bucket) {
+	if (!C::trackFront)
+	  return;
+	MATHIC_ASSERT(bucket != 0);
+	MATHIC_ASSERT(bucket->_frontPos == 0);
+	MATHIC_ASSERT(!bucket->empty());
+    if (_bucketEnd == _bucketCapacityEnd)
+      reserveCapacity(size() + 1);
+    *_bucketEnd = bucket;
+    ++_bucketEnd;
+	bucket->_frontPos = end() - 1;
+	keyIncreased(bucket);
+  }
+
+  template<class C, class B>
+	void GeoFront<C, B, true>::keyIncreased(B* bucket) {
+	B** pos = bucket->_frontPos;
+	B** begin = this->begin();
+	for (; pos != begin; --pos) { // move bucket to lower index
+	  B& shouldBeGreater = **(pos - 1);
+	  typename C::CompareResult cmp =
+		_conf.compare(shouldBeGreater.back(), bucket->back());
+	  if (!_conf.cmpLessThan(cmp))
+		break;
+	  // todo: if equal
+	  *pos = *(pos - 1);
+	  shouldBeGreater._frontPos = pos;
+	}
+	// We don't have to adjust bucket's position if it never moved, but
+	// detecting that without extra branches makes the code too complex
+	// for it to be worth it.
+	*pos = bucket;
+	bucket->_frontPos = pos;
+  }
+
+  template<class C, class B>
+	void GeoFront<C, B, true>::keyDecreased(B* bucket) {
+	if (bucket->empty()) {
+	  remove(bucket);
+	  return;
+	}
+	B** pos = bucket->_frontPos;
+	B** end = this->end();
+	for (; pos + 1 != end; ++pos) { // move bucket to higher index
+	  B& otherBucket = **(pos + 1);
+	  typename C::CompareResult cmp =
+		_conf.compare(bucket->back(), otherBucket.back());
+	  if (!_conf.cmpLessThan(cmp)) {
+		if (!C::supportDeduplication || !_conf.cmpEqual(cmp))
+		  break; // greater than, found correct position
+		otherBucket.setEntry(otherBucket.end() - 1,
+							 _conf.deduplicate(bucket->back(), otherBucket.back()));
+		bucket->pop_back();
+		--_entryCountRef;
+		if (bucket->empty()) {
+		  bucket->_frontPos = pos;
+		  remove(bucket);
+		  return;
+		}
+	  }
+	  *pos = *(pos + 1);
+	  otherBucket._frontPos = pos;
+	}
+	// We don't have to adjust bucket's position if it never moved, but
+	// detecting that without extra branches makes the code too complex
+	// for it to be worth it.
+	*pos = bucket;
+	bucket->_frontPos = pos;
+  }
+
+  template<class C, class B>
+	void GeoFront<C, B, true>::remove(B* bucket) {
+	MATHIC_ASSERT(bucket->_frontPos != 0);
+	MATHIC_ASSERT(bucket->empty());
+	B** end = this->end(); // can't dereference end
+	for (B** i = bucket->_frontPos + 1; i != end; ++i) {
+	  *(i - 1) = *i;
+	  (*i)->_frontPos = i - 1;
+	}
+    --_bucketEnd;
+	bucket->_frontPos = 0;
+  }
+
+  template<class C, class B>
+	void GeoFront<C, B, true>::swapKeys(B* a, B* b) {
+	MATHIC_ASSERT(a != 0);
+	MATHIC_ASSERT(b != 0);
+	std::swap(a->_frontPos, b->_frontPos);
+	if (a->_frontPos != 0)
+	  *a->_frontPos = a;
+	if (b->_frontPos != 0)
+	  *b->_frontPos = b;
+  }
+
+  template<class C, class B>
+	bool GeoFront<C, B, true>::larger(const B* a, const B* b) const {
+	MATHIC_ASSERT(a != 0);
+	MATHIC_ASSERT(b != 0);
+	return a->_frontPos < b->_frontPos;
+  }
+
+  template<class C, class B>
+	const B* GeoFront<C, B, true>::getMax(B* bucketBegin, B* bucketEnd) const {
+	MATHIC_ASSERT(!empty());
+	return *begin();  
+  }
+
+#ifdef MATHIC_DEBUG
+  template<class C, class B>
+	bool GeoFront<C, B, true>::debugIsValid(B* bucketBegin, B* bucketEnd) const {
+	std::vector<const B*> nonEmpty;
+	size_t size = bucketEnd - bucketBegin;
+	for (size_t b = 0; b < size; ++b) {
+	  if (bucketBegin[b].empty()) {
+		MATHIC_ASSERT(bucketBegin[b]._frontPos == 0);
+	  } else {
+		MATHIC_ASSERT(bucketBegin[b]._frontPos != 0);
+		MATHIC_ASSERT(*(bucketBegin[b]._frontPos) == &(bucketBegin[b]));
+		nonEmpty.push_back(&(bucketBegin[b]));
+	  }
+	}
+	std::vector<B*> frontCopy(_bucketBegin, _bucketEnd);
+	std::sort(nonEmpty.begin(), nonEmpty.end());
+	std::sort(frontCopy.begin(), frontCopy.end());
+	MATHIC_ASSERT(std::equal(frontCopy.begin(), frontCopy.end(), nonEmpty.begin()));
+    if (!empty()) {
+      for (B** it = _bucketBegin + 1; it != _bucketEnd; ++it)
+        MATHIC_ASSERT(!_conf.cmpLessThan
+          (_conf.compare((*(it - 1))->back(), (*it)->back())));
+    }
+	return true;
+  }
+#endif
+}
+
+#endif
diff --git a/src/mathic/Geobucket.h b/src/mathic/Geobucket.h
new file mode 100755
index 0000000..c14ea9c
--- /dev/null
+++ b/src/mathic/Geobucket.h
@@ -0,0 +1,805 @@
+#ifndef MATHIC_GEOBUCKET_GUARD
+#define MATHIC_GEOBUCKET_GUARD
+
+#include "stdinc.h"
+#include <string>
+#include <sstream>
+#include <vector>
+#include <algorithm>
+#include "GeoFront.h"
+
+namespace mathic {
+  enum GeobucketBucketStorage {
+	GeoStorePlain = 0,
+	GeoStoreDoubleBuffer = 1,
+	GeoStoreSameSizeBuffer = 2,
+
+	GeobucketBucketStorageBegin = 0,
+	GeobucketStorageEnd = 3
+  };
+
+  /** A geobucket priority queue.
+
+	  The Configuration template parameter specifies properties of the geobucket.
+	  A configuration object is passed to the constructor of geobucket which
+	  makes a copy. After the initial copy no further copies are made.
+
+	  Configuration must have these fields:
+
+	  * A type Entry
+	  The elements of the geobucket will have this type. Entry must have a copy
+	  constructor.
+
+	  * A type CompareResult
+	  Intended to be a bool for "less than" or some other type that can encode
+	  "less than", "equal" and "greater than". As the Configuration itself
+	  interprets what the values of this type mean, the type can be anything.
+	  CompareResult must have a copy constructor.
+
+	  * A const or static method: CompareResult compare(Entry, Entry)
+	  It is OK for the two parameters to be const Entry&, but compare must not
+	  retain a reference to the Entry. The return value is intended to
+	  encode the ordering of the two elements.
+
+	  * A const or static method: bool cmpLessThan(CompareResult)
+	  The geobucket calls this on a CompareResult returned from compare(a,b).
+	  The return value should be true if and only if a is strictly less than b.
+
+	  * A size_t minBucketSize
+	  This is the size of the smallest bucket. Must be at least 1.
+
+	  * A size_t geoBase
+	  When a new bucket is added, its capacity is geoBase multiplied by the
+	  largest capacity among the buckets in the geobucket. Must be at least
+	  two.
+
+	  * A static const size_t insertFactor
+	  An insert of size S will be done into the smallest bucket whose total
+	  capacity (not free capacity) is at least S * insertFactor. 
+
+	  * A static const bool supportDeduplication
+	  If this is true, then the geobucket will remove entries that are compared
+	  and found to be equal. This requires the use of a method cmpEqual and
+	  deduplicate.
+
+	  * A static or const method: bool cmpEqual(CompareResult)
+	  The method is only called if supportDeduplication is true.
+	  The geobucket calls this on a CompareResult returned from compare(a,b).
+	  If the return value is true, then a and b must be equivalent in the ordering
+	  imposed by compare and cmpLessThan. When the return value is true,
+	  the two elements will be replaced by the return value of deduplicate.
+
+	  * A static or const method: Entry deduplicate(Entry a, Entry b)
+	  This method is only called if supportDeduplication is true and
+	  cmpEqual(compare(a,b)) is true. The two elements a and b in the geobucket
+	  will be replaced by the return value of deduplicate. So the number of
+	  elements in the geobucket will decrease by one every time deduplicate
+	  is called.
+
+	  * A static const bool minBucketBinarySearch
+	  If this field is true, insertions of single elements is done using binary
+	  search. Otherwise a linear search is done.
+
+	  * A static const bool trackFront
+	  If this field is true, then a sorted list of buckets will be maintained
+	  to aid in determining the largest element in the queue. Otherwise a
+	  linear search is done through the buckets to find the largest element.
+
+	  * A static const bool premerge
+	  Let A be a list of elements and let B be the elements in a bucket. Suppose
+	  we are about to merge A and B and put them into the same bucket. If 
+	  the combined size of A and B is larger than the capacity of the bucket,
+	  and premerge is true, then B will be preemptively merged into the next
+	  bucket after which A can be copied into the now empty bucket that B
+	  previously occupied. If premerge is false, then A and B will be merged,
+	  and the overflow will force a merge of the combined A and B into the
+	  next bucket.
+
+	  * A static const bool collectMax
+	  The meta data of a bucket is kept in a separate memory area from the
+	  elements of the bucket. If collectMax is true, then the maximum element
+	  of each bucket is copied into the meta data area. The idea is to
+	  minimize cache misses caused when pop does a linear scan through
+	  the maximum elements.
+
+	  * A static const GeobucketBucketStorage bucketStorage
+	  GeoStorePlain = 0,
+	  GeoStoreDoubleBuffer = 1,
+	  GeoStoreSameSizeBuffer = 2,
+
+	  If this field is GeoStorePlain, then a bucket of capacity S has a memory
+	  area of size S.
+
+	  If this field is GeoStoreDoubleBuffer, then every bucket will have two
+	  same-size memory areas. Only one of the two memory areas is in use at
+	  any one time. That way a merge into the bucket can store its
+	  result into the other memory area so that a merge does not require a copy.
+
+	  If this field is GeoStoreSameSizeBuffer, then all buckets use a
+	  memory area of the same size as the maximum bucket. A bucket's noted
+	  capacity does not change. This way any memory area can be used in place
+	  of any other memory area, which makes it possible to do merges with no
+	  copies and also the content of two buckets can be swapped with no copies.
+	  Cannot be combined with useDoubleBucket.
+  */
+  template<class C>
+	class Geobucket {
+  public:
+	typedef C Configuration;
+	typedef typename Configuration::Entry Entry;
+
+	Geobucket(const Configuration& configuration);
+
+	Configuration& getConfiguration() {return _conf;}
+	const Configuration& getConfiguration() const {return _conf;}
+
+	std::string getName() const;
+	void push(Entry entries);
+
+	// [begin, end) must be sorted in decreasing order.
+	// If Configuration::supportDeduplication is true, then no value must
+	// be present twice in [begin, end).
+	template<class It>
+    void push(It begin, It end);
+    void clear();
+	Entry pop();
+	Entry top() const;
+	bool empty() const;
+	void print(std::ostream& out) const;
+
+    template<class T>
+    void forAll(T& t) const {
+      for (Bucket* bucket = _bucketBegin; bucket != _bucketEnd; ++bucket) {
+        const Entry* stop = bucket->end();
+        for (const Entry* entry = bucket->begin(); entry != stop; ++entry) {
+          if (!t.proceed(*entry)) {
+            MATHIC_ASSERT(isValid());
+            return;
+          }
+        }
+      }
+	  MATHIC_ASSERT(isValid());
+    }
+
+    size_t getMemoryUse() const;
+
+  private:
+	Geobucket(const Geobucket&); // unavailable
+	Geobucket& operator=(const Geobucket&); // unavailable
+
+	struct Bucket {
+	  Bucket(size_t capacity, Entry* buffer, Entry* otherBuffer);
+	  size_t size() const {return _size;}
+	  size_t capacity() const {return _capacity;}
+	  Entry* begin() {return _begin;}
+	  Entry* end() {return begin() + size();}
+	  const Entry* begin() const {return _begin;}
+	  const Entry* end() const {return begin() + size();}
+	  bool empty() const {return size() == 0;}
+	  const Entry& back() const {
+		MATHIC_ASSERT(!empty());
+		return Configuration::collectMax ? _back : *(end() - 1);
+	  }
+	  const Entry& operator[](size_t i) const {
+		MATHIC_ASSERT(i < size());
+		return *(begin() + i);
+	  }
+	  void pop_back() {
+		MATHIC_ASSERT(size() > 0);
+		--_size;
+		if (Configuration::collectMax && _size > 0)
+		  _back = *(end() - 1);
+	  }
+	  void setEntry(Entry* pos, const Entry& entry) {
+		MATHIC_ASSERT(begin() <= pos && pos < end());
+		*pos = entry;
+		if (Configuration::collectMax && pos == end() - 1)
+		  _back = entry;
+	  }
+	  void insertAtNotEnd(Entry* pos, const Entry& entry) {
+		MATHIC_ASSERT(begin() <= pos && pos < end());
+		for (Entry* it = end(); it != pos; --it)
+		  *it = *(it - 1);
+		*pos = entry;
+		++_size;
+	  }
+	  void setBuffer(Entry* buffer) {
+		std::copy(begin(), end(), buffer);
+		_begin = buffer;
+	  }
+	  void setBufferWithNewEntries(Entry* buffer, size_t size) {
+		_begin = buffer;
+		_size = size;
+		if (size > 0)
+		  _back = *(end() - 1);        
+	  }
+	  void setOtherBuffer(Entry* otherBuffer) {
+		MATHIC_ASSERT(Configuration::bucketStorage == GeoStoreDoubleBuffer);
+		_otherBuffer = otherBuffer;
+	  }
+	  Entry* getOtherBuffer() {
+		MATHIC_ASSERT(Configuration::bucketStorage == GeoStoreDoubleBuffer);
+		return _otherBuffer;
+	  }
+	  void switchToOtherBuffer(size_t size) {
+		MATHIC_ASSERT(Configuration::bucketStorage == GeoStoreDoubleBuffer);
+		std::swap(_begin, _otherBuffer);
+		_size = size;
+		if (size > 0)
+		  _back = *(end() - 1);
+	  }
+	  void clear() {
+		_size = 0;
+	  }
+	  template<class It>
+	  void assign(It begin, It end, size_t size) {
+		MATHIC_ASSERT(static_cast<size_t>(end - begin) == size);
+		std::copy(begin, end, _begin);
+		_size = size;
+		if (size > 0)
+		  _back = *(end - 1);
+	  }
+	  template<class It1, class It2>
+		void merge(Geobucket<Configuration>& gb, It1 begin1, It1 end1, It2 begin2, It2 end2) {
+		Entry* end = gb.merge(begin1, end1, begin2, end2, _begin);
+		_size = end - _begin;
+		if (_size > 0)
+		  _back = *(end - 1);
+	  }
+	  void push_back(const Entry& e) {
+		MATHIC_ASSERT(size() < capacity());
+		*(_begin + _size) = e;
+		++_size;
+		if (Configuration::collectMax)
+		  _back = e;
+	  }
+	  Bucket** getFrontToken() {return _frontPos;}
+	  const Bucket** getFrontToken() const {return _frontPos;}
+	  void setFrontToken(Bucket** token) {_frontPos = token;}
+
+	  Bucket** _frontPos;
+
+	private:
+	  Entry* _otherBuffer;
+	  Entry _back;
+	  Entry* _begin;
+	  size_t _size;
+	  size_t _capacity;
+	};
+	void addBucket();
+
+	template<bool value> struct Premerge {};
+	template<class It>
+	  void insert(Bucket* bucket, It begin, It end, size_t size, Premerge<true>);
+	template<class It>
+	  void insert(Bucket* bucket, It begin, It end, size_t size, Premerge<false>);
+
+	template<class It1, class It2, class ResIt>
+	  ResIt merge(It1 begin1, It1 end1, It2 begin2, It2 end2, ResIt res);
+	template<class It>
+	  size_t singleInsert(It begin, size_t size, const Entry& value) const;
+
+	void moveToEmpty(Bucket& to, Bucket& from);
+	template<class It>
+	  void mergeToEmpty(Bucket& to, Bucket& from, It begin, It end);
+	void mergeToNonEmpty(Bucket& into, Bucket& from);
+	template<class It>
+	  void mergeToNonEmpty(Bucket& into, It begin, It end);
+
+	size_t _geoBase;
+	std::vector<Bucket> _buckets;
+	Bucket* _bucketBegin;
+	Bucket* _bucketEnd;
+	std::vector<Entry> _mem;
+	Entry* _tmp; // has capacity equal to the largest bucket
+	size_t _entryCount;
+
+	// Has capacity equal to the largest bucket. Only used when
+	// C::premerge is false.
+	Entry* _tmpForNoPremerge;
+	Configuration _conf;
+	GeoFront<Configuration> _front;
+
+#ifdef MATHIC_DEBUG
+	bool isValid() const;
+#endif
+  };
+
+  template<class C>
+	Geobucket<C>::Geobucket(const C& configuration):
+  _bucketBegin(0),
+	_bucketEnd(0),
+	_tmp(0),
+	_entryCount(0),
+	_tmpForNoPremerge(0),
+	_conf(configuration),
+	_front(_conf, _entryCount) {
+	MATHIC_ASSERT(_conf.geoBase > 1);
+	addBucket(); // this avoids the special case of no buckets.
+    ASSERT(_front.debugIsValid(_bucketBegin, _bucketEnd));
+  }
+
+  template<class C>
+	std::string Geobucket<C>::getName() const {
+	std::ostringstream out;
+	out << "Geobucket("
+		<< 'b' << _conf.geoBase
+		<< 'm' << _conf.minBucketSize
+		<< 'i' << C::insertFactor
+		<< (C::minBucketBinarySearch ? " mbin" : "")
+		<< (C::trackFront ? " tf" : "")
+		<< (C::supportDeduplication ? " dedup" : "")
+		<< (C::premerge ? " prem" : "")
+		<< (C::collectMax ? " col" : "")
+		<< (C::bucketStorage == GeoStoreDoubleBuffer ? " db" : "")
+		<< (C::bucketStorage == GeoStoreSameSizeBuffer ? " ss" : "")
+		<< ')';
+	return out.str();
+  }
+
+  template<class C>
+	void Geobucket<C>::push(Entry entry) {
+	++_entryCount;
+	Bucket& bucket = *_bucketBegin;
+	if (bucket.size() == bucket.capacity()) {
+	  const Entry* p = &entry;
+	  insert(_bucketBegin, p, p + 1, 1, Premerge<C::premerge>());
+	  return;
+	}
+	if (bucket.empty()) {
+	  bucket.push_back(entry);
+	  _front.insert(&bucket);
+	} else if (C::minBucketBinarySearch) {
+	  size_t range = bucket.size();
+	  Entry* begin = bucket.begin();
+	  while (true) {
+		// invariant: the position is in the range [begin, begin + range].
+		if (range == 0) {
+		  if (begin == bucket.end()) {
+			bucket.push_back(entry);
+			_front.keyIncreased(&bucket);
+		  } else
+			bucket.insertAtNotEnd(begin, entry);
+		  break;
+		}
+		Entry* mid = begin + range / 2;
+		typename C::CompareResult cmp = _conf.compare(entry, *mid);
+		if (_conf.cmpLessThan(cmp))
+		  range /= 2;
+		else if (!C::supportDeduplication || !_conf.cmpEqual(cmp)) {
+		  begin = mid;
+		  ++begin;
+		  range -= range / 2 + 1;
+		} else {
+		  --_entryCount;
+		  bucket.setEntry(mid, _conf.deduplicate(*mid, entry));
+		  break;
+		}
+	  }
+	} else {
+	  Entry* end = bucket.end();
+	  for (Entry* pos = bucket.begin(); pos != end; ++pos) {
+		typename C::CompareResult cmp = _conf.compare(entry, *pos);
+		if (_conf.cmpLessThan(cmp)) {
+		  bucket.insertAtNotEnd(pos, entry);
+		  return;
+		}
+		if (C::supportDeduplication && _conf.cmpEqual(cmp)) {
+		  bucket.setEntry(pos, _conf.deduplicate(*pos, entry));
+		  --_entryCount;
+		  return;
+		}
+	  }
+	  bucket.push_back(entry);
+	  _front.keyIncreased(&bucket);
+	}
+  }
+
+  template<class C>
+	template<class It>
+	void Geobucket<C>::push(It begin, It end) {
+#ifdef MATHIC_DEBUG
+	if (begin != end) {
+	  for (It it = begin; it + 1 != end; ++it) {
+		// deduplication assumes that [begin, end) does not contain
+		// duplicates for efficiency, so support for deduplication implies
+		// that no element can be duplicated within a pushed range.
+		if (C::supportDeduplication) {
+		  MATHIC_ASSERT(_conf.cmpLessThan(_conf.compare(*(it + 1), *it)));
+		} else {
+		  MATHIC_ASSERT(!_conf.cmpLessThan(_conf.compare(*it, *(it + 1))));
+		}
+	  }
+	}
+#endif
+	const size_t entryCount = end - begin;
+	const size_t adjCount = entryCount * C::insertFactor;
+	_entryCount += entryCount;
+	while (adjCount > (_bucketEnd - 1)->capacity())
+	  addBucket();
+	for (Bucket* bucket = _bucketBegin; ; ++bucket) {
+	  MATHIC_ASSERT(bucket != _bucketEnd);
+	  if (adjCount <= bucket->capacity()) {
+		std::reverse_iterator<It> rBegin(end);
+		std::reverse_iterator<It> rEnd(begin);
+		insert(bucket, rBegin, rEnd, entryCount, Premerge<C::premerge>());
+		break;
+	  }
+	}
+	MATHIC_ASSERT(isValid());
+  }
+
+  template<class C>
+  void Geobucket<C>::clear() {
+    _entryCount = 0;
+    _front.clear();
+    for (Bucket* bucket = _bucketBegin; bucket != _bucketEnd; ++bucket)
+      bucket->clear();
+	MATHIC_ASSERT(isValid());
+  }
+
+  template<class C>
+  typename Geobucket<C>::Entry Geobucket<C>::pop() {
+	Bucket* maxBucket =
+	  const_cast<Bucket*>(_front.getMax(_bucketBegin, _bucketEnd));
+	Entry top = maxBucket->back();
+	maxBucket->pop_back();
+	--_entryCount;
+	_front.keyDecreased(maxBucket);
+	MATHIC_ASSERT(isValid());
+	return top;
+  }
+
+  template<class C>
+	typename Geobucket<C>::Entry Geobucket<C>::top() const {
+	MATHIC_ASSERT(!empty());
+	return _front.getMax(_bucketBegin, _bucketEnd)->back();
+  }
+
+  template<class C>
+	bool Geobucket<C>::empty() const {
+#ifdef MATHIC_DEBUG
+	bool empty = true;
+	for (size_t b = 0; b < _buckets.size(); ++b) {
+	  if (!_buckets[b].empty()) {
+		empty = false;
+		break;
+	  }
+	}
+	MATHIC_ASSERT(empty == !_entryCount);
+#endif
+	return _entryCount == 0;
+  }
+
+  template<class C>
+	void Geobucket<C>::print(std::ostream& out) const {
+	out << getName() << ": {\n";
+	for (const Bucket* bucket = _bucketBegin; bucket != _bucketEnd; ++bucket) {
+	  out << ' ' << (bucket - _bucketBegin) << ":";
+	  if (bucket->size() > 4) {
+		out << ' ' << (*bucket)[0] << ' ' << (*bucket)[1] << " ... "
+			<< (*bucket)[bucket->size() - 2] << ' '
+			<< (*bucket)[bucket->size() - 1];
+	  } else
+		for (size_t i = 0; i < bucket->size(); ++i)
+		  out << ' ' << (*bucket)[i];
+	  out << " [" << bucket->size() << '/' << bucket->capacity() << "]\n";
+	}
+	out << "}\n";
+  }
+
+  template<class C>
+	void Geobucket<C>::addBucket() {
+	// calculate required amount of memory
+	const size_t newBucketSize = _bucketBegin == _bucketEnd ?
+	  _conf.minBucketSize : (_bucketEnd - 1)->capacity() * _conf.geoBase;
+	size_t required = 0;
+	typedef typename std::vector<Bucket>::iterator It;
+	for (Bucket* it = _bucketBegin; it != _bucketEnd; ++it) {
+	  required += C::bucketStorage == GeoStoreSameSizeBuffer ?
+		newBucketSize : it->capacity();
+	  if (C::bucketStorage == GeoStoreDoubleBuffer)
+		required += it->capacity(); // for other buffer
+	}
+	required += newBucketSize; // for new bucket
+	if (C::bucketStorage == GeoStoreDoubleBuffer)
+	  required += newBucketSize; // for other buffer
+
+	required += newBucketSize; // for _tmp
+	if (!C::premerge)
+	  required += newBucketSize; // for _tmpForNoPremerge
+
+	// allocate new memory
+	std::vector<Entry> newMem(required);
+	std::copy(_mem.begin(), _mem.end(), newMem.begin());
+
+	// move to new memory buffer
+	size_t offset = 0;
+	for (Bucket* it = _bucketBegin; it != _bucketEnd; ++it) {
+	  it->setBuffer(&(newMem[offset]));
+	  offset += C::bucketStorage == GeoStoreSameSizeBuffer ?
+		newBucketSize : it->capacity();
+	  if (C::bucketStorage == GeoStoreDoubleBuffer) {
+		it->setOtherBuffer(&(newMem[offset]));
+		offset += it->capacity();
+	  }
+	}
+	Entry* buffer = &(newMem[offset]);
+	offset += newBucketSize;
+	Entry* otherBuffer = 0;
+	if (C::bucketStorage == GeoStoreDoubleBuffer) {
+	  otherBuffer = &(newMem[offset]);
+	  offset += newBucketSize;
+	}
+	// redirect pointers in _front to point to new memory for _buckets
+	Bucket* oldBucketBegin = _bucketBegin;
+	_buckets.push_back(Bucket(newBucketSize, buffer, otherBuffer));
+	_bucketBegin = &_buckets.front();
+	_bucketEnd = _bucketBegin + _buckets.size();
+	_front.bucketsInvalidated(oldBucketBegin, _bucketBegin);
+	_front.reserveCapacity(_bucketEnd - _bucketBegin);
+
+	_tmp = &(newMem[offset]);
+	offset += newBucketSize;
+	if (!C::premerge) {
+	  _tmpForNoPremerge = &(newMem[offset]);
+	  offset += newBucketSize;
+	}
+
+	MATHIC_ASSERT(offset == required);
+	_mem.swap(newMem);
+  }
+
+  template<class C>
+	void Geobucket<C>::mergeToNonEmpty(Bucket& to, Bucket& from) {
+	MATHIC_ASSERT(!to.empty());
+	MATHIC_ASSERT(!from.empty());
+	MATHIC_ASSERT(&to != &from);
+	MATHIC_ASSERT(to.size() + from.size() <= to.capacity());
+	if (C::trackFront && _front.larger(&from, &to))
+	  _front.swapKeys(&to, &from);
+	mergeToNonEmpty(to, from.begin(), from.end());
+	from.clear();
+	_front.remove(&from);
+  }
+
+  template<class C>
+	template<class It>
+	void Geobucket<C>::mergeToNonEmpty(Bucket& into, It begin, It end) {
+	// todo: template select instead of if
+	// todo: into => to
+	MATHIC_ASSERT(!into.empty());
+	MATHIC_ASSERT(begin != end);
+	MATHIC_ASSERT(static_cast<size_t>(end - begin) <= into.capacity());
+	if (C::bucketStorage == GeoStoreDoubleBuffer) {
+	  Entry* other = into.getOtherBuffer();
+	  Entry* otherEnd = merge(into.begin(), into.end(), begin, end, other);
+	  into.switchToOtherBuffer(otherEnd - other);
+	} else if (C::bucketStorage == GeoStoreSameSizeBuffer) {
+	  Entry* tmpEnd = merge(into.begin(), into.end(), begin, end, _tmp);
+	  Entry* previousBufferOfInto = into.begin();
+	  into.setBufferWithNewEntries(_tmp, tmpEnd - _tmp);
+	  _tmp = previousBufferOfInto;
+	} else {
+	  Entry* tmpEnd = std::copy(into.begin(), into.end(), _tmp);
+	  into.merge(*this, begin, end, _tmp, tmpEnd);
+	}
+	_front.keyIncreased(&into);
+  }
+
+  template<class C>
+	template<class It>
+	void Geobucket<C>::mergeToEmpty(Bucket& to, Bucket& from, It begin, It end) {
+	MATHIC_ASSERT(to.empty());
+	MATHIC_ASSERT(!from.empty()); // so has place in front
+	MATHIC_ASSERT(&to != &from);
+	MATHIC_ASSERT(begin != end);
+	MATHIC_ASSERT(static_cast<size_t>(end - begin) + from.size() <= to.capacity());
+	to.merge(*this, begin, end, from.begin(), from.end());
+	from.clear();
+	_front.swapKeys(&from, &to);
+	_front.keyIncreased(&to);
+  }
+
+  template<class C>
+	void Geobucket<C>::moveToEmpty(Bucket& to, Bucket& from) {
+	MATHIC_ASSERT(&to != &from);
+	MATHIC_ASSERT(to.empty());
+	MATHIC_ASSERT(!from.empty());
+	MATHIC_ASSERT(from.size() <= to.capacity());
+
+	if (C::bucketStorage == GeoStoreSameSizeBuffer) {
+	  Entry* previousBufferOfTo = to.begin();
+	  to.setBufferWithNewEntries(from.begin(), from.size());
+	  from.setBufferWithNewEntries(previousBufferOfTo, 0);
+	} else {
+	  to.assign(from.begin(), from.end(), from.size());
+	  from.clear();
+	}
+	_front.swapKeys(&from, &to);
+  }
+
+  template<class C>
+	template<class It>
+	void Geobucket<C>::insert
+	(Bucket* p, It begin, It end, size_t incomingSize, Premerge<false>) {
+	MATHIC_ASSERT(!C::premerge);
+	MATHIC_ASSERT(incomingSize == static_cast<size_t>(end - begin));
+	MATHIC_ASSERT(0 < incomingSize);
+	MATHIC_ASSERT(begin != end);
+
+	size_t b = p - _bucketBegin;
+	Bucket& bucket = _buckets[b];
+
+	if (bucket.empty()) {
+	  bucket.assign(begin, end, incomingSize);
+	  _front.insert(&bucket);
+	  return;
+	}
+	if (bucket.size() + incomingSize <= bucket.capacity()) {
+	  mergeToNonEmpty(bucket, begin, end);
+	  return;
+	}
+
+	size_t accumulatedSize = bucket.size() + incomingSize;
+	for (size_t i = b + 1; ; ++i) {
+	  if (i == _buckets.size())
+		addBucket(); // can invalidate bucket reference variable
+	  accumulatedSize += _buckets[i].size();
+	  if (accumulatedSize <= _buckets[i].capacity())
+		break;
+	}
+
+	// deal with first step separately as the iterator can have
+	// different type (grrrrr)
+	Bucket& current = _buckets[b];
+	MATHIC_ASSERT(b + 1 < _buckets.size());
+	Bucket& next = _buckets[b + 1];
+	if (next.empty()) {
+	  mergeToEmpty(next, current, begin, end);
+	  return;
+	}
+	Entry* tmpForNoPremergeEnd = merge(
+									   begin, end, current.begin(), current.end(), _tmpForNoPremerge);
+	current.clear();
+	_front.remove(&current);
+	++b;
+
+	while (true) {
+	  Bucket& current = _buckets[b];
+	  const size_t predictedSize =
+		(tmpForNoPremergeEnd - _tmpForNoPremerge) + current.size();
+	  if (predictedSize <= current.capacity()) {
+		mergeToNonEmpty(current, _tmpForNoPremerge, tmpForNoPremergeEnd);
+		return;
+	  }
+	  MATHIC_ASSERT(b + 1 < _buckets.size());
+	  Bucket& next = _buckets[b + 1];
+	  if (next.empty()) {
+		mergeToEmpty(next, current, _tmpForNoPremerge, tmpForNoPremergeEnd);
+		return;
+	  }
+	  tmpForNoPremergeEnd = merge(_tmpForNoPremerge, tmpForNoPremergeEnd,
+								  current.begin(), current.end(), _tmp);
+	  std::swap(_tmp, _tmpForNoPremerge);
+	  current.clear();
+	  _front.remove(&current);
+	  ++b;
+	}
+  }
+
+  template<class C>
+	template<class It>
+	void Geobucket<C>::insert
+	(Bucket* bucket, It begin, It end, size_t size, Premerge<true>) {
+	MATHIC_ASSERT(C::premerge);
+	// ** determine premerge range (bucket, rbegin]
+	Bucket* rbegin = bucket;
+	size_t incomingSize = size;
+	while (true) {
+	  if (rbegin->size() + incomingSize <= rbegin->capacity())
+		break;
+	  incomingSize = rbegin->size(); // this will be incoming for next bucket
+	  ++rbegin;
+	  if (rbegin == _bucketEnd) {
+		Bucket* oldBucketBegin = _bucketBegin;
+		addBucket();
+		bucket = (bucket - oldBucketBegin) + _bucketBegin;
+		rbegin = (rbegin - oldBucketBegin) + _bucketBegin;
+		break;
+	  }
+	}
+	// ** perform premerges
+	if (bucket != rbegin) {
+	  if (!rbegin->empty()) {
+		mergeToNonEmpty(*rbegin, *(rbegin - 1));
+		--rbegin;
+	  }
+	  for (Bucket* rit = rbegin; rit != bucket; --rit)
+		moveToEmpty(*rit, *(rit - 1));
+	}
+	// ** perform insertion
+	if (bucket->empty()) {
+	  bucket->assign(begin, end, size);
+      _front.insert(bucket);
+	} else
+	  mergeToNonEmpty(*bucket, begin, end);
+  }
+
+  template<class C>
+	template<class It1, class It2, class ResIt>
+	ResIt Geobucket<C>::merge
+	(It1 begin1, It1 end1, It2 begin2, It2 end2, ResIt res) {
+	if (begin1 == end1) goto range1Done;
+	if (begin2 == end2) goto range2Done;
+	while (true) {
+	  typename C::CompareResult cmp = _conf.compare(*begin1, *begin2);
+	  if (_conf.cmpLessThan(cmp)) {
+		*res = *begin1;
+		++res;
+		++begin1;
+		if (begin1 == end1) goto range1Done;
+	  } else if (!C::supportDeduplication || !_conf.cmpEqual(cmp)) {
+		*res = *begin2;
+		++res;
+		++begin2;
+		if (begin2 == end2) goto range2Done;
+	  } else {
+		*res = _conf.deduplicate(*begin1, *begin2);
+		++res;
+		++begin1;
+		++begin2;
+		--_entryCount;
+		if (begin1 == end1) goto range1Done;
+		if (begin2 == end2) goto range2Done;
+	  }
+	}
+  range1Done: return std::copy(begin2, end2, res);
+  range2Done: return std::copy(begin1, end1, res);
+  }
+
+  template<class C>
+	Geobucket<C>::Bucket::Bucket
+	(size_t capacity, Entry* buffer, Entry* otherBuffer):
+  _frontPos(0),
+	_otherBuffer(otherBuffer),
+	_begin(buffer),
+	_size(0),
+	_capacity(capacity) {
+	  MATHIC_ASSERT(C::bucketStorage == GeoStoreDoubleBuffer ?
+			 otherBuffer != 0 : otherBuffer == 0);
+	}
+
+  template<class C>
+  size_t Geobucket<C>::getMemoryUse() const {
+    return _mem.capacity() * sizeof(_mem.front()) +
+      _buckets.capacity() * sizeof(_buckets.front()) +
+      _front.getMemoryUse();
+  }
+
+#ifdef MATHIC_DEBUG
+  template<class C>
+	bool Geobucket<C>::isValid() const {
+	MATHIC_ASSERT(_conf.geoBase >= 2);
+	MATHIC_ASSERT(!_buckets.empty());
+	MATHIC_ASSERT(_bucketBegin == &_buckets.front());
+	MATHIC_ASSERT(_bucketEnd == _bucketBegin + _buckets.size());
+	MATHIC_ASSERT(_buckets.front().capacity() >= 1);
+
+	size_t entryCount = 0;
+	for (size_t b = 0; b < _buckets.size(); ++b) {
+	  const Bucket& bucket = _buckets[b];
+	  entryCount += bucket.size();
+	  if (bucket.empty())
+		continue;
+	  for (const Entry* it = bucket.begin(); it != bucket.end() - 1; ++it) {
+		MATHIC_ASSERT(!_conf.cmpLessThan(_conf.compare(*(it + 1), *it)));
+	  }
+	}
+	MATHIC_ASSERT(entryCount == _entryCount);
+	return _front.debugIsValid(_bucketBegin, _bucketEnd);
+  }
+#endif
+}
+
+#endif
diff --git a/src/mathic/Heap.h b/src/mathic/Heap.h
new file mode 100755
index 0000000..a3f7978
--- /dev/null
+++ b/src/mathic/Heap.h
@@ -0,0 +1,200 @@
+#ifndef MATHIC_HEAP_GUARD
+#define MATHIC_HEAP_GUARD
+
+#include "stdinc.h"
+#include "ComTree.h"
+#include <vector>
+#include <ostream>
+#include <string>
+
+namespace mathic {
+  /** A heap priority queue.
+
+  Configuration serves the same role as for Geobucket. It must have these
+  fields that work as for Geobucket.
+
+  * A type Entry
+  * A type CompareResult
+  * A const or static method: CompareResult compare(Entry, Entry)
+  * A const or static method: bool cmpLessThan(CompareResult)
+  * A static const bool supportDeduplication
+  * A static or const method: bool cmpEqual(CompareResult)
+
+  It also has these additional fields:
+
+  * A static const bool fastIndex
+  If this field is true, then a faster way of calculating indexes is used.
+  This requires sizeof(Entry) to be a power of two! This can be achieved
+  by adding padding to Entry, but this class does not do that for you.
+  */
+  template<class C>
+	class Heap {
+  public:
+	typedef C Configuration;
+	typedef typename Configuration::Entry Entry;
+
+    Heap(const Configuration& configuration): _conf(configuration) {}
+	Configuration& getConfiguration() {return _conf;}
+	const Configuration& getConfiguration() const {return _conf;}
+
+    template<class T>
+    void forAll(T& t) const {
+      Node stop = _tree.lastLeaf().next();
+      for (Node it = Node(); it != stop; ++it)
+        if (!t.proceed(_tree[it]))
+          return;
+    }
+
+	std::string getName() const;
+	void push(Entry entry);
+    template<class It>
+	void push(It begin, It end);
+    void clear();
+	Entry pop();
+	Entry top() const {return _tree[Node()];}
+	bool empty() const {return _tree.empty();}
+	size_t size() const {return _tree.size();}
+
+	void print(std::ostream& out) const;
+
+	void decreaseTop(Entry newEntry);
+
+    size_t getMemoryUse() const;
+
+  private:
+	typedef ComTree<Entry, Configuration::fastIndex> Tree;
+	typedef typename Tree::Node Node;
+
+	Node moveHoleDown(Node hole);
+	void moveValueUp(Node pos, Entry value);
+
+#ifdef MATHIC_DEBUG
+	bool isValid() const;
+#endif
+
+	Tree _tree;
+	Configuration _conf;
+  };
+
+  template<class C>
+  size_t Heap<C>::getMemoryUse() const {
+    return _tree.getMemoryUse();
+  }
+
+  template<class C>
+  std::string Heap<C>::getName() const {
+	return std::string("heap(") +
+	  (C::fastIndex ?  "fi" : "si") +
+	  (C::supportDeduplication ? " dedup" : "") +
+	  ')';
+  }
+
+  template<class C>
+	void Heap<C>::push(Entry entry) {
+	_tree.pushBack(entry);
+	moveValueUp(_tree.lastLeaf(), entry);
+	MATHIC_ASSERT(isValid());
+  }
+
+  template<class C>
+  template<class It>
+  void Heap<C>::push(It begin, It end) {
+	for (; begin != end; ++begin)
+	  push(*begin);
+  }
+
+  template<class C>
+	void Heap<C>::decreaseTop(Entry newEntry) {
+	moveValueUp(moveHoleDown(Node()), newEntry);
+	MATHIC_ASSERT(isValid());
+  }
+
+  template<class C>
+  void Heap<C>::clear() {
+    _tree.clear();
+	MATHIC_ASSERT(isValid());
+  }
+
+  template<class C>
+  typename Heap<C>::Entry Heap<C>::pop() {
+	Entry top = _tree[Node()];
+	Entry movedValue = _tree[_tree.lastLeaf()];
+	_tree.popBack();
+	if (!_tree.empty())
+	  moveValueUp(moveHoleDown(Node()), movedValue);
+	return top;
+	MATHIC_ASSERT(isValid());
+  }
+
+  template<class C>
+	void Heap<C>::print(std::ostream& out) const {
+	out << getName() << ": {" << _tree << "}\n";
+  }
+
+  template<class C>
+	typename Heap<C>::Node Heap<C>::moveHoleDown(Node hole) {
+	const Node firstWithout2Children = _tree.lastLeaf().next().parent();
+	while (hole < firstWithout2Children) {
+	  // can assume hole has two children here
+	  Node child = hole.left();
+	  Node sibling = child.next();
+	  if (_conf.cmpLessThan(_conf.compare(_tree[child], _tree[sibling])))
+		child = sibling;
+	  _tree[hole] = _tree[child];
+	  hole = child;
+	}
+	// if we are at a node that has a single left child
+	if (hole == firstWithout2Children && _tree.lastLeaf().isLeft()) {
+	  Node child = hole.left();
+	  _tree[hole] = _tree[child];
+	  hole = child;
+	}
+	return hole;
+  }
+
+  template<class C>
+	void Heap<C>::moveValueUp(Node pos, Entry value) {
+	const Node origPos = pos;
+  again:
+	while (!pos.isRoot()) {
+	  const Node up = pos.parent();
+	  typename C::CompareResult cmp = _conf.compare(_tree[up], value);
+	  if (_conf.cmpLessThan(cmp)) {
+		_tree[pos] = _tree[up];
+		pos = up;
+	  } else if (C::supportDeduplication && _conf.cmpEqual(cmp)) {
+		_tree[up] = _conf.deduplicate(_tree[up], value);
+		if (pos != origPos) {
+		  // move elements back
+		  Entry tmp = _tree[origPos];
+		  for (Node p = origPos.parent(); p != pos; p = p.parent())
+			std::swap(tmp, _tree[p]);
+		}
+		pos = origPos;
+		value = _tree[_tree.lastLeaf()];
+		_tree.popBack();
+		if (origPos == _tree.lastLeaf().next()) {
+		  MATHIC_ASSERT(isValid());
+		  return;
+		}
+		goto again;
+	  } else
+		break;
+	}
+	_tree[pos] = value;
+	MATHIC_ASSERT(isValid());
+  }
+
+#ifdef MATHIC_DEBUG
+  template<class C>
+	bool Heap<C>::isValid() const {
+	MATHIC_ASSERT(_tree.isValid());
+	for (Node i = Node().next(); i <= _tree.lastLeaf(); ++i) {
+	  MATHIC_ASSERT(!_conf.cmpLessThan(_conf.compare(_tree[i.parent()], _tree[i])));
+	}
+	return true;
+  }
+#endif
+}
+
+#endif
diff --git a/src/mathic/HelpAction.cpp b/src/mathic/HelpAction.cpp
new file mode 100755
index 0000000..32c7b9d
--- /dev/null
+++ b/src/mathic/HelpAction.cpp
@@ -0,0 +1,113 @@
+#include "HelpAction.h"
+
+#include "CliParameter.h"
+#include "error.h"
+#include "display.h"
+#include "ColumnPrinter.h"
+#include "CliParser.h"
+
+#include <iostream>
+#include <algorithm>
+
+namespace mathic {
+  HelpAction::HelpAction() {}
+
+  const char* HelpAction::name() const {
+    return staticName();
+  }
+
+  const char* HelpAction::description() const {
+    return 
+    "Typing `frobby help' displays a list of the available actions.\n"
+    "Typing `frobby help ACTION' displays a detailed description of that "
+    "action.\n\n"
+    "As an example, typing `frobby help irrdecom' will yield detailed "
+    "information about the irrdecom action.";
+  }
+
+  const char* HelpAction::shortDescription() const {
+    return "Return information about the command line interface.";
+  }
+
+
+  void HelpAction::directOptions(
+    std::vector<std::string> tokens,
+    CliParser& parser
+  ) {
+    _parser = &parser;
+    if (tokens.size() == 1)
+      _topic = tokens.front();
+    else if (tokens.size() > 1)
+      reportError("Did not expect second option \"" + tokens[1] + "\".");
+  }
+
+  void HelpAction::pushBackParameters(std::vector<CliParameter*>& parameters) {
+  }
+
+  namespace {
+    // Helper function for displayActionHelp().
+    bool paramCmp(CliParameter* a, CliParameter* b) {
+      MATHIC_ASSERT(a != 0);
+      MATHIC_ASSERT(b != 0);
+      return std::string(a->name()) < b->name();
+    }
+  }
+
+  void HelpAction::displayActionHelp(Action& action) {
+    std::ostringstream out;
+    out << "Displaying information on action: " << action.name() << "\n\n";
+    out << action.description() << "\n";
+
+    std::vector<CliParameter*> parameters;
+    action.pushBackParameters(parameters);
+    sort(parameters.begin(), parameters.end(), paramCmp);
+
+    display(out.str());
+
+    if (!parameters.empty()) {
+      fprintf(stderr, "\nThe parameters accepted by %s are as follows.\n",
+              action.name());
+
+      typedef std::vector<CliParameter*>::const_iterator cit;
+      for (cit it = parameters.begin(); it != parameters.end(); ++it) {
+        std::string defaultValue = (*it)->valueAsString();
+        fprintf(stderr, "\n -%s %s   (default is %s)\n",
+                (*it)->name().c_str(),
+                (*it)->argumentType().c_str(),
+                (*it)->valueAsString().c_str());
+        display((*it)->description(), "   ");
+      }
+    }
+  }
+
+  void HelpAction::performAction() {
+    if (_topic != "") {
+      displayActionHelp(*_parser->createActionWithPrefix(_topic));
+      return;
+    }
+
+    std::ostringstream out;
+
+    out << _parser->helpPreMessage() << '\n';
+
+    ColumnPrinter printer;
+    printer.addColumn(false, " ");
+    printer.addColumn(true, " - ");
+
+    std::vector<std::string> names;
+    _parser->pushBackRegisteredActionNames(names);
+    for (std::vector<std::string>::const_iterator it = names.begin();
+         it != names.end(); ++it) {
+      std::auto_ptr<Action> action(_parser->createActionWithPrefix(*it));
+      printer[0] << action->name() << '\n';
+	  printer[1] << action->shortDescription() << '\n';
+    }
+    printer.print(out);
+    out << '\n' << _parser->helpPostMessage() << '\n';
+    display(out.str());
+  }
+
+  const char* HelpAction::staticName() {
+    return "help";
+  }
+}
diff --git a/src/mathic/HelpAction.h b/src/mathic/HelpAction.h
new file mode 100755
index 0000000..e724afd
--- /dev/null
+++ b/src/mathic/HelpAction.h
@@ -0,0 +1,34 @@
+#ifndef MATHIC_HELP_ACTION_GUARD
+#define MATHIC_HELP_ACTION_GUARD
+
+#include "stdinc.h"
+#include "Action.h"
+#include <string>
+
+namespace mathic {
+  class HelpAction : public Action {
+   public:
+    HelpAction();
+
+    virtual void directOptions
+      (std::vector<std::string> tokens, CliParser& parser);
+    virtual void performAction();
+
+    virtual const char* name() const;
+    virtual const char* description() const;
+    virtual const char* shortDescription() const;
+    virtual void pushBackParameters(std::vector<CliParameter*>& parameters);
+
+    virtual bool isHelpAction() const {return true;}
+
+    static const char* staticName();
+
+  private:
+    void displayActionHelp(Action& action);
+
+    CliParser* _parser;
+    std::string _topic;
+  };
+}
+
+#endif
diff --git a/src/mathic/IntegerParameter.cpp b/src/mathic/IntegerParameter.cpp
new file mode 100755
index 0000000..f17cf32
--- /dev/null
+++ b/src/mathic/IntegerParameter.cpp
@@ -0,0 +1,36 @@
+#include "IntegerParameter.h"
+
+#include "error.h"
+#include <sstream>
+#include <cctype>
+
+namespace mathic {
+  IntegerParameter::IntegerParameter(const std::string& name,
+                                     const std::string& description,
+                                     unsigned int defaultValue):
+    CliParameter(name, description),
+    _value(defaultValue) {
+  }
+
+  std::string IntegerParameter::argumentType() const {
+    return "INTEGER";
+  }
+
+  std::string IntegerParameter::valueAsString() const {
+    std::ostringstream out;
+    out << value();
+    return out.str();
+  }
+
+  void IntegerParameter::processArgument(const std::string& argument) {
+    std::istringstream in(argument);
+    in >> _value;
+    std::ostringstream out;
+    out << _value;
+    if (out.str() != argument) {
+      reportError("The value given to option -" + name() + " was not "
+        "as expected. It must be a non-negative integer in the range "
+        "[0, 2^31-1].");
+    }
+  }
+}
diff --git a/src/mathic/IntegerParameter.h b/src/mathic/IntegerParameter.h
new file mode 100755
index 0000000..e16f096
--- /dev/null
+++ b/src/mathic/IntegerParameter.h
@@ -0,0 +1,31 @@
+#ifndef MATHIC_INTEGER_PARAMETER_GUARD
+#define MATHIC_INTEGER_PARAMETER_GUARD
+
+#include "stdinc.h"
+#include "CliParameter.h"
+#include <utility>
+#include <string>
+
+namespace mathic {
+  class IntegerParameter : public CliParameter {
+  public:
+    IntegerParameter(const std::string& name,
+                     const std::string& description,
+                     unsigned int defaultValue);
+
+    unsigned int value() const {return _value;}
+    void setValue(unsigned int value) {_value = value;}
+
+    operator unsigned int() const {return value();}
+    void operator=(unsigned int value) {setValue(value);}
+
+    virtual std::string argumentType() const;
+    virtual std::string valueAsString() const;
+    virtual void processArgument(const std::string& argument);
+
+  private:
+    unsigned int _value;
+  };
+}
+
+#endif
diff --git a/src/mathic/KDEntryArray.h b/src/mathic/KDEntryArray.h
new file mode 100755
index 0000000..92e3eea
--- /dev/null
+++ b/src/mathic/KDEntryArray.h
@@ -0,0 +1,493 @@
+#ifndef MATHIC_K_D_ENTRY_ARRAY_GUARD
+#define MATHIC_K_D_ENTRY_ARRAY_GUARD
+
+#include "stdinc.h"
+
+#include "DivMask.h"
+#include "Comparer.h"
+
+#include <stdexcept>
+#include <memtailor.h>
+
+namespace mathic {
+  template<class C, class EE>
+  class KDEntryArray : public DivMask::HasDivMask<C::UseTreeDivMask> {
+  public:
+    typedef typename C::Entry Entry;
+    typedef typename C::Exponent Exponent;
+    typedef EE ExtEntry;
+    typedef EE* iterator;
+    typedef const EE* const_iterator;
+    typedef const EE& const_reference;
+    typedef EE value_type;
+    typedef DivMask::Calculator<C> DivMaskCalculator;
+
+    KDEntryArray(memt::Arena& arena, const C& conf);
+
+    template<class Iter>
+    KDEntryArray(Iter begin, Iter end, memt::Arena& arena,
+      const DivMaskCalculator& calc, const C& conf);
+    template<class Iter>
+    KDEntryArray(Iter begin, Iter end, memt::Arena& arena, const C& conf);
+
+    void clear();
+
+    void recalculateTreeDivMask();
+#ifdef DEBUG
+    bool debugIsValid() const;
+#endif
+
+    iterator begin() {return reinterpret_cast<ExtEntry*>(_beginMemory);}
+    const_iterator begin() const {
+      return reinterpret_cast<const ExtEntry*>(_beginMemory);
+    }
+    iterator end() {return _end;}
+    const_iterator end() const {return _end;}
+
+    bool empty() const {return begin() == end();}
+    size_t size() const {return std::distance(begin(), end());}
+    EE& front() {MATHIC_ASSERT(!empty()); return *begin();}
+    const EE& front() const {MATHIC_ASSERT(!empty()); return *begin();}
+    EE& back() {MATHIC_ASSERT(!empty()); return *(_end - 1);}
+    const EE& back() const {MATHIC_ASSERT(!empty()); return *(_end - 1);}
+
+    void push_back(const EE& entry);
+    void pop_back();
+    void insert(iterator it, const EE& entry);
+    void insert(const EE& entry, const C& conf);
+
+    /** Returns how many were removed. */
+    template<class EM, class MO>
+    size_t removeMultiples(const EM& monomial, MO& out, const C& conf);
+
+    template<class M>
+    bool removeElement(const M& monomial, const C& conf);
+
+    template<class EM>
+    inline iterator findDivisor(const EM& extMonomial, const C& conf);
+
+    template<class EM, class DO>
+    inline bool findAllDivisors(const EM& extMonomial, DO& out, const C& conf);
+
+    template<class EM, class Output>
+    inline bool findAllMultiples
+      (const EM& extMonomial, Output& out, const C& conf);
+
+    template<class EO>
+    bool forAll(EO& eo);
+
+    bool allStrictlyGreaterThan(size_t var, Exponent exp, const C& conf);
+    bool allLessThanOrEqualTo(size_t var, Exponent exp, const C& conf);
+
+    /** Reorders [begin, iter) and chooses a var and an exp such that
+     if mid is the returned value, then [begin, mid) has less than or
+     equal to exp exponent of var and [mid,end) has strictly greater
+     exponent. The initial value of var is a hint that var + 1 could
+     be a good place to start the search for a suitable value of var.
+     begin must not equal end.
+     
+     If not null, the entry os taken into account when deciding which
+     split to perform. The Entry is NOT inserted   into [begin, end). */
+    template<class Iter>
+    static Iter split(
+      Iter begin,
+      Iter end,
+      size_t& var,
+      Exponent& exp,
+      const C& conf,
+      const ExtEntry* extEntry = 0
+    );
+
+    using DivMask::HasDivMask<C::UseTreeDivMask>::resetDivMask;
+    using DivMask::HasDivMask<C::UseTreeDivMask>::getDivMask;
+
+  private:
+    static Entry& getEntry(Entry& e) {return e;}
+    static const Entry& getEntry(const Entry& e) {return e;}
+    static Entry& getEntry(ExtEntry& e) {return e.get();}
+    static const Entry& getEntry(const ExtEntry& e) {return e.get();}
+
+    KDEntryArray(const KDEntryArray&); // unavailable
+    void operator=(const KDEntryArray&); // unavailable
+
+    class SplitEqualOrLess;
+
+
+    /** This is the memory for the entries. It is kept as a raw char*
+     to avoid constructing all the entries right away. */
+    char _beginMemory[C::LeafSize * sizeof(ExtEntry)];
+    iterator _end; // points into _beginMemory
+#ifdef MATHIC_DEBUG
+    const bool _sortOnInsertDebug;
+#endif
+  };
+
+  template<class C, class EE>
+  class KDEntryArray<C, EE>::SplitEqualOrLess {
+  public:
+    typedef typename C::Exponent Exponent;
+    typedef typename C::Entry Entry;
+  SplitEqualOrLess(size_t var, const Exponent& exp, const C& conf):
+    _var(var), _exp(exp), _conf(conf) {}
+    bool operator()(const Entry& entry) const {
+      return !(_exp < _conf.getExponent(entry, _var));
+    }
+    bool operator()(const ExtEntry& entry) const {
+      return !(_exp < _conf.getExponent(entry.get(), _var));
+    }
+  private:
+    size_t _var;
+    const Exponent& _exp;
+    const C& _conf;
+  };
+
+  template<class C, class EE>
+  template<class Iter>
+  Iter KDEntryArray<C, EE>::split(
+    Iter begin,
+    Iter end,
+    size_t& var,
+    Exponent& exp,
+    const C& conf,
+    const ExtEntry* extEntry
+  ) {
+    MATHIC_ASSERT(begin != end);
+    const size_t varCount = conf.getVarCount();
+    for (size_t i = 0; i < varCount; ++i) {
+      var = (var + 1) % conf.getVarCount();
+
+      typename C::Exponent min;
+      typename C::Exponent max;
+      if (extEntry == 0) {
+        min = conf.getExponent(getEntry(*begin), var);
+        max = conf.getExponent(getEntry(*begin), var);
+      }  else {
+        min = conf.getExponent(getEntry(*extEntry), var);
+        max = conf.getExponent(getEntry(*extEntry), var);
+      }
+      for (Iter it = begin; it != end; ++it) {
+        min = std::min(min, conf.getExponent(getEntry(*it), var));
+        max = std::max(max, conf.getExponent(getEntry(*it), var));
+      }
+      if (min == max)
+        continue;
+      // this formula for the average avoids overflow
+      exp = min + (max - min) / 2;
+      SplitEqualOrLess cmp(var, exp, conf);
+      return std::partition(begin, end, cmp);
+    }
+    MATHIC_ASSERT(false);
+    throw std::logic_error("ERROR: Inserted duplicate entry into a KD tree.");
+  }
+
+  template<class C, class EE>
+  KDEntryArray<C, EE>::KDEntryArray(memt::Arena& arena, const C& conf)
+#ifdef MATHIC_DEBUG
+    :_sortOnInsertDebug(conf.getSortOnInsert())
+#endif
+  {
+    _end = begin();
+  }
+
+  template<class C, class EE>
+  template<class Iter>
+  KDEntryArray<C, EE>::KDEntryArray(
+    Iter begin,
+    Iter end,
+    memt::Arena& arena,
+    const DivMaskCalculator& calc,
+    const C& conf) 
+#ifdef MATHIC_DEBUG
+  :_sortOnInsertDebug(conf.getSortOnInsert())
+#endif
+  {
+    MATHIC_ASSERT(static_cast<size_t>(std::distance(begin, end)) <=
+                  C::LeafSize);
+    _end = this->begin();
+    // cannot directly copy as memory is not constructed.
+    for (; begin != end; ++begin)
+      push_back(EE(*begin, calc, conf));
+    if (conf.getSortOnInsert())
+      std::sort(this->begin(), this->end(), Comparer<C>(conf));
+  }
+
+  template<class C, class EE>
+  template<class Iter>
+  KDEntryArray<C, EE>::KDEntryArray(
+    Iter begin,
+    Iter end,
+    memt::Arena& arena,
+    const C& conf) 
+#ifdef MATHIC_DEBUG
+  :_sortOnInsertDebug(conf.getSortOnInsert())
+#endif
+  {
+    MATHIC_ASSERT(static_cast<size_t>(std::distance(begin, end)) <=
+                  C::LeafSize);
+    _end = this->begin();
+    // cannot directly copy as memory is not constructed.
+    for (; begin != end; ++begin)
+      push_back(*begin);
+    if (conf.getSortOnInsert())
+      std::sort(this->begin(), this->end(), Comparer<C>(conf));
+  }
+
+  template<class C, class EE>
+    void KDEntryArray<C, EE>::push_back(const EE& entry) {
+    MATHIC_ASSERT(size() < C::LeafSize);
+    new (_end) EE(entry);
+    updateToLowerBound(entry);
+    ++_end;
+  }
+
+  template<class C, class EE>
+    void KDEntryArray<C, EE>::pop_back() {
+    MATHIC_ASSERT(!empty());
+    --_end;
+    _end->~EE();
+  }
+
+  template<class C, class EE>
+    void KDEntryArray<C, EE>::insert(iterator it, const EE& entry) {
+    MATHIC_ASSERT(size() < C::LeafSize);
+    if (it == end()) {
+      push_back(entry);
+      return;
+    }
+    push_back(back());
+    iterator moveTo = end();
+    for (--moveTo; moveTo != it; --moveTo)
+      *moveTo = *(moveTo - 1);
+    updateToLowerBound(entry);
+    *it = entry;
+  }
+
+  template<class C, class EE>
+    void KDEntryArray<C, EE>::insert(const EE& entry, const C& conf) {
+    MATHIC_ASSERT(size() < C::LeafSize);
+    if (!conf.getSortOnInsert())
+      push_back(entry);
+    else {
+      iterator it = std::upper_bound(begin(), end(), entry, Comparer<C>(conf));
+      insert(it, entry);
+    }
+  }
+
+  template<class C, class EE>
+    void KDEntryArray<C, EE>::clear() {
+      while (!empty())
+        pop_back();
+  }
+
+  template<class C, class EE>
+  template<class EM, class MO>
+  size_t KDEntryArray<C, EE>::removeMultiples
+    (const EM& monomial, MO& out, const C& conf) {
+    MATHIC_ASSERT(C::AllowRemovals);
+    if (C::LeafSize == 1) { // special case for performance
+      if (empty() || !monomial.divides(*begin(), conf))
+        return 0;
+      out.push_back(begin()->get());
+      pop_back();
+      return 1;
+    }
+
+    iterator it = begin();
+    iterator oldEnd = end();
+    for (; it != oldEnd; ++it) {
+      if (monomial.divides(*it, conf)) {
+        out.push_back(it->get());
+        break;
+      }
+    }
+    if (it == oldEnd)
+      return 0;
+    iterator newEnd = it;
+    for (++it; it != oldEnd; ++it) {
+      if (!monomial.divides(*it, conf)) {
+        *newEnd = *it;
+        ++newEnd;
+      } else
+        out.push_back(it->get());
+    }
+    // cannot just set _end directly as the superfluous
+    // entries at the end need to be destructed.
+    const size_t newSize = std::distance(begin(), newEnd);
+    const size_t removedCount = size() - newSize;
+    MATHIC_ASSERT(newSize < size());
+    do {
+      pop_back();
+    } while (newSize < size());
+    MATHIC_ASSERT(size() == newSize);
+    return removedCount;
+  }
+
+  template<class C, class EE>
+  template<class M>
+  bool KDEntryArray<C, EE>::removeElement(const M& monomial, const C& conf) {
+    const size_t varCount = conf.getVarCount();
+    const_iterator stop = end();
+    for (iterator it = begin(); it != stop; ++it) {
+      for (size_t var = 0; var < varCount; ++var)
+        if (conf.getExponent(monomial, var) != conf.getExponent(it->get(), var))
+          goto skip;
+      if (it != end()) {
+        const_iterator next = it;
+        for (++next; next != end(); ++it, ++next)
+          *it = *next;
+      }
+      pop_back();
+      return true;
+    skip:;
+    }
+    return false;
+  }
+
+  template<class C, class EE>
+  template<class EM>
+  typename KDEntryArray<C, EE>::iterator
+  KDEntryArray<C, EE>::findDivisor(const EM& extMonomial, const C& conf) {
+    if (C::UseTreeDivMask &&
+      C::LeafSize > 1 && // no reason to do it for just 1 leaf
+      !getDivMask().canDivide(extMonomial.getDivMask()))
+      return end();
+
+    if (C::LeafSize == 1) { // special case for performance
+      ASSERT(C::AllowRemovals || !empty());
+      if ((!C::AllowRemovals || !empty()) &&
+        begin()->divides(extMonomial, conf))
+        return begin();
+      else
+        return end();
+    }
+    else if (!conf.getSortOnInsert()) {
+      const iterator stop = end();
+      for (iterator it = begin(); it != stop; ++it)
+        if (it->divides(extMonomial, conf))
+          return it;
+      return stop;
+    } else {
+      iterator rangeEnd =
+        std::upper_bound(begin(), end(), extMonomial, Comparer<C>(conf));
+      iterator it = begin();
+      for (; it != rangeEnd; ++it)
+        if (it->divides(extMonomial, conf))
+          return it;
+      return end();
+    }
+  }
+
+  template<class C, class EE>
+  template<class EM, class DO>
+  bool KDEntryArray<C, EE>::
+    findAllDivisors(const EM& extMonomial, DO& out, const C& conf) {
+    if (C::UseTreeDivMask &&
+      C::LeafSize > 1 && // no reason to do it for just 1 leaf
+      !getDivMask().canDivide(extMonomial.getDivMask()))
+      return end();
+
+    if (C::LeafSize == 1) { // special case for performance
+      ASSERT(C::AllowRemovals || !empty());
+      return (C::AllowRemovals && empty()) ||
+        !begin()->divides(extMonomial, conf) ||
+        out.proceed(begin()->get());
+    } else  if (!conf.getSortOnInsert()) {
+      const iterator stop = end();
+      for (iterator it = begin(); it != stop; ++it)
+        if (it->divides(extMonomial, conf))
+          if (!out.proceed(it->get()))
+            return false;
+    } else {
+      iterator rangeEnd =
+        std::upper_bound(begin(), end(), extMonomial, Comparer<C>(conf));
+      iterator it = begin();
+      for (; it != rangeEnd; ++it)
+        if (it->divides(extMonomial, conf))
+          if (!out.proceed(it->get()))
+            return false;
+    }
+    return true;
+  }
+
+  template<class C, class EE>
+  template<class EM, class DO>
+  bool KDEntryArray<C, EE>::
+  findAllMultiples(const EM& extMonomial, DO& out, const C& conf) {
+    if (C::LeafSize == 1) { // special case for performance
+      ASSERT(C::AllowRemovals || !empty());
+      return (C::AllowRemovals && empty()) ||
+        !extMonomial.divides(*begin(), conf) ||
+        out.proceed(begin()->get());
+    }
+
+    // todo: consider making sorted version
+    const iterator stop = end();
+    for (iterator it = begin(); it != stop; ++it)
+      if (extMonomial.divides(*it, conf))
+        if (!out.proceed(it->get()))
+          return false;
+    return true;
+  }
+
+  template<class C, class EE>
+  template<class EO>
+  bool KDEntryArray<C, EE>::forAll(EO& output) {
+    if (C::LeafSize == 1) { // special case for performance
+      ASSERT(C::AllowRemovals || !empty());
+      return (C::AllowRemovals && empty()) || output.proceed(begin()->get());
+    }
+    const iterator stop = end();
+    for (iterator it = begin(); it != stop; ++it)
+      if (!output.proceed(it->get()))
+        return false;
+    return true;
+  }
+
+  template<class C, class EE>
+  bool KDEntryArray<C, EE>::allStrictlyGreaterThan(
+    size_t var,
+    Exponent exp,
+    const C& conf
+  ) {
+    for (const_iterator it = begin(); it != end(); ++it)
+      if (!(exp < conf.getExponent(it->get(), var)))
+        return false;
+    return true;
+  }
+
+  template<class C, class EE>
+  bool KDEntryArray<C, EE>::allLessThanOrEqualTo(
+    size_t var,
+    Exponent exp,
+    const C& conf
+  ) {
+    for (const_iterator it = begin(); it != end(); ++it)
+      if (exp < conf.getExponent(it->get(), var))
+        return false;
+    return true;
+  }
+
+  template<class C, class EE>
+  void KDEntryArray<C, EE>::recalculateTreeDivMask() {
+    if (!C::UseTreeDivMask)
+      return;
+    resetDivMask();
+    for (const_iterator it = begin(); it != end(); ++it)
+      updateToLowerBound(*it);
+  }
+#ifdef DEBUG
+  template<class C, class EE>
+  bool KDEntryArray<C, EE>::debugIsValid() const {
+    MATHIC_ASSERT(C::AllowRemovals || !empty());
+    MATHIC_ASSERT(static_cast<size_t>(end() - begin()) <= C::LeafSize);
+    if (C::UseTreeDivMask && C::LeafSize > 1) {
+      for (const_iterator it = begin(); it != end(); ++it) {
+        MATHIC_ASSERT(getDivMask().canDivide(it->getDivMask()));
+      }
+    }
+    return true;
+  }
+#endif
+}
+
+#endif
diff --git a/src/mathic/KDTree.h b/src/mathic/KDTree.h
new file mode 100755
index 0000000..8290bb2
--- /dev/null
+++ b/src/mathic/KDTree.h
@@ -0,0 +1,366 @@
+#ifndef MATHIC_K_D_TREE_GUARD
+#define MATHIC_K_D_TREE_GUARD
+
+#include "stdinc.h"
+#include "DivMask.h"
+#include "BinaryKDTree.h"
+#include "PackedKDTree.h"
+#include <memtailor.h>
+#include <list>
+#include <string>
+#include <algorithm>
+#include <iterator>
+#include <sstream>
+#include <vector>
+
+namespace mathic {
+  /** An object that supports queries for divisors of a monomial using
+      a KD Tree (K Dimensional Tree). See DivFinder.h for more documentation.
+
+      Extra fields for Configuration:
+
+      * bool getSortOnInsert() const
+      Return true to keep the monomials in leaves sorted to speed up queries.
+
+      * size_t getLeafSize() const
+      Return the fixed maximal size of a leaf.
+
+      * static const bool AllowRemovals
+      If false, it is an error to call methods that remove elements from
+      the data structure. This can be a slight speed up in some cases.
+      Clear and rebuild is still allowed even if this field is false.
+  */
+  template<class Configuration>
+  class KDTree;
+
+  namespace KDTreeInternal {
+    // cannot do this inside KDTree as template partial specializations
+    // cannot be done inside a class.
+    template<class C, bool Pack>
+    struct SelectTree {
+      typedef BinaryKDTree<C> Tree;
+    };
+    template<class C>
+    struct SelectTree<C, true> {
+      typedef PackedKDTree<C> Tree;
+    };
+  }
+
+  template<class C>
+  class KDTree {
+  private:
+    // for figuring out which kd tree implementation to use
+    typedef typename KDTreeInternal::SelectTree<C, C::PackedTree>::Tree Tree;
+    typedef typename Tree::ExtEntry ExtEntry;
+    typedef typename Tree::ExtMonoRef ExtMonoRef;
+  public:
+    typedef C Configuration;
+
+    /** Constructs an object with the given configuration. The configuration
+        is copied into the object, so a reference to the passed-in object is
+        not kept. The configuration is not copied other than the initial copy. */
+    KDTree(const C& configuration):
+      _divMaskCalculator(configuration),
+      _tree(configuration),
+      _size(0) {
+      resetNumberOfChangesTillRebuild();
+      if (getConfiguration().getUseDivisorCache())
+        _divisorCache = 0;
+    }
+
+    static const bool UseDivMask = C::UseDivMask;
+    typedef typename C::Monomial Monomial;
+    typedef typename C::Entry Entry;
+    typedef typename C::Exponent Exponent;
+
+    /** Returns whether there are any entries. */
+    bool empty() const {return size() == 0;}
+
+    /** Returns the number of entries. */
+    size_t size() const {return _size;}
+
+    /** Returns a string that describes the data structure. */
+    std::string getName() const;
+
+    /** Returns a reference to this object's configuration object. */
+    C& getConfiguration() {
+      return _tree.getConfiguration();
+    }
+
+    /** Returns a reference to this object's configuration object. */
+    const C& getConfiguration() const {
+      return const_cast<Tree&>(_tree).getConfiguration();
+    }
+
+    /** Removes all multiples of monomial. A duplicate counts
+        as a multiple. Returns true if any multiples were removed. */
+    bool removeMultiples(const Monomial& monomial) {
+      MATHIC_ASSERT(C::AllowRemovals);
+      if (!C::AllowRemovals)
+        throw std::logic_error("Removal request while removals disabled.");
+      DummyMultipleOutput out;
+      return removeMultiples(monomial, out);
+    }
+
+    /** Removes all multiples of monomial. A duplicate counts
+        as a multiple. Returns true if any multiples were removed.
+        Calls out.push_back(entry) for each entry that is removed. */
+    template<class MultipleOutput>
+    bool removeMultiples(const Monomial& monomial, MultipleOutput& out) {
+      MATHIC_ASSERT(C::AllowRemovals);
+      if (!C::AllowRemovals)
+        throw std::logic_error("Removal request while removals disabled.");
+      ExtMonoRef extMonomial(monomial, _divMaskCalculator, getConfiguration());
+      size_t removedCount = _tree.removeMultiples(extMonomial, out);
+      reportChanges(0, removedCount);
+      return removedCount > 0;
+    }
+
+    /** Calls out.proceed(entry) for each entry that monomial divides.
+        The method returns if proceed returns false, otherwise the
+        search for divisors proceeds. */
+    template<class Output>
+    void findAllMultiples(const Monomial& monomial, Output& out) {
+      ExtMonoRef extMonomial(monomial, _divMaskCalculator, getConfiguration());
+      _tree.findAllMultiples(extMonomial, out);
+    }
+
+    /** Calls out.proceed(entry) for each entry that monomial divides.
+        The method returns if proceed returns false, otherwise the
+        search for divisors proceeds. */
+    template<class Output>
+    void findAllMultiples(const Monomial& monomial, Output& output) const {
+      ConstEntryOutput<Output> constOutput(output);
+      const_cast<KDTree<C>&>(*this).findAllMultiples(monomial, constOutput);
+    }
+
+    /** Inserts entry into the data structure. Does NOT remove multiples
+        of entry and entry is inserted even if it is a multiple of another
+        entry. */
+    void insert(const Entry& entry) {
+      ExtEntry extEntry(entry, _divMaskCalculator, getConfiguration());
+      _tree.insert(extEntry);
+      reportChanges(1, 0);
+    }
+
+    /** Inserts the entries in the range [begin, end) into the data
+        structure. Does NOT remove multiples of entry and entry is inserted
+        even if it is a multiple of another entry.
+
+        The elements in the range [begin, end) may be rearranged by this
+        function, so the range must be mutable. If that is not acceptable,
+        call the one element insert method for each element. */
+    template<class Iter>
+    void insert(Iter begin, Iter end) {
+      if (begin == end)
+        return;
+      const size_t inserted = std::distance(begin, end); 
+      if (!empty()) {
+        for (; begin != end; ++begin)
+          _tree.insert(*begin);
+      } else {
+        _tree.insert(begin, end);
+        // insert into empty container is equivalent to rebuild
+        resetNumberOfChangesTillRebuild();
+      }
+      reportChanges(inserted, 0);
+    }
+
+    /** Removes an element whose exponents are equal to monomial's. Returns
+      if there are no such monomials in the data structure. */
+    bool removeElement(const Monomial& monomial) {
+      MATHIC_ASSERT(C::AllowRemovals);
+      if (!C::AllowRemovals)
+        throw std::logic_error("Removal request while removals disabled.");
+      return _tree.removeElement(monomial);
+    }
+
+    /** Returns a pointer to an entry that divides monomial. Returns null if no
+        entries divide monomial. */
+    inline Entry* findDivisor(const Monomial& monomial) {
+      // todo: do this on extended monomials. requires cache to be extended.
+      const C& conf = getConfiguration();
+      if (conf.getUseDivisorCache() &&
+        _divisorCache != 0 &&
+        conf.divides(*_divisorCache, monomial))
+        return _divisorCache;
+
+      ExtMonoRef extMonomial(monomial, _divMaskCalculator, getConfiguration());
+      Entry* divisor = _tree.findDivisor(extMonomial);
+      if (conf.getUseDivisorCache() && divisor != 0)
+        _divisorCache = divisor;
+      return divisor;
+    }
+
+    /** Returns the position of a divisor of monomial. Returns null if no
+        entries divide monomial. */
+    inline const Entry* findDivisor(const Monomial& monomial) const {
+      return const_cast<KDTree<C>&>(*this).findDivisor(monomial);
+    }
+
+    /** Calls out.proceed(entry) for each entry that divides monomial.
+        The method returns if proceed returns false, otherwise the
+        search for divisors proceeds. */
+    template<class DivisorOutput>
+    void findAllDivisors(const Monomial& monomial, DivisorOutput& out) {
+      ExtMonoRef extMonomial(monomial, _divMaskCalculator, getConfiguration());
+      _tree.findAllDivisors(extMonomial, out);
+    }
+
+    /** Calls output.proceed(entry) for each entry that divides monomial.
+        The method returns if proceed returns false, otherwise the
+        search for divisors proceeds. */
+    template<class DivisorOutput>
+    void findAllDivisors(const Monomial& monomial, DivisorOutput& output) const {
+      ConstEntryOutput<DivisorOutput> constOutput(output);
+      const_cast<KDTree<C>&>(*this).findAllDivisors(monomial, constOutput);
+    }
+
+    /** Calls output.proceed(entry) for each entry.
+        The method returns if proceed returns false, otherwise the
+        search for divisors proceeds. */
+    template<class EntryOutput>
+    void forAll(EntryOutput& out) {
+      _tree.forAll(out);
+    }
+
+    /** Calls out.proceed(entry) for each entry.
+        The method returns if proceed returns false, otherwise the
+        search for divisors proceeds. */
+    template<class EntryOutput>
+    void forAll(EntryOutput& output) const {
+      ConstEntryOutput<EntryOutput> constOutput(output);
+      const_cast<KDTree<C>&>(*this).forAll(constOutput);
+    }
+
+    /** Removes all entries. Does not reset the configuration object. */
+    void clear() {
+      _tree.clear();
+      resetNumberOfChangesTillRebuild();
+      _tree.calc().rebuildDefault(getConfiguration());
+    }
+
+    /** Rebuilds the data structure. */
+    void rebuild() {
+      EntryRecorder recorder(memt::Arena::getArena(), size());
+      _tree.forAll(recorder);
+      _divMaskCalculator.rebuild
+        (recorder.begin(), recorder.end(), getConfiguration());
+      _tree.reset(recorder.begin(), recorder.end(), _divMaskCalculator);
+      resetNumberOfChangesTillRebuild();
+    }
+
+	/** Returns the number of bytes allocated by this object. Does not
+		include sizeof(*this), does not include any additional memory
+		that the configuration may have allocated and does not include
+		any memory that an Entry may point to. Does include
+		sizeof(Entry) as well as unused memory that is being kept to
+		avoid frequent allocations. */
+    size_t getMemoryUse() const {return _tree.getMemoryUse();}
+
+  private:
+    KDTree(const KDTree<C>&); // unavailable
+    void operator=(const KDTree<C>&); // unavailable
+
+    // For recording all entries in the tree using forAll.
+    class EntryRecorder {
+    public:
+      EntryRecorder(memt::Arena& arena, size_t capacity):
+        _entries(arena, capacity) {}
+      bool proceed(const Entry& entry) {
+        _entries.push_back(entry);
+       return true;
+      }
+      Entry* begin() {return _entries.begin();}
+      Entry* end() {return _entries.end();}
+
+    private:
+      memt::ArenaVector<Entry, true> _entries;
+    };
+
+    /// makes the parameter given to proceed be const.
+    template<class EntryOutput>
+    class ConstEntryOutput {
+    public:
+    ConstEntryOutput(EntryOutput& out): _out(out) {}
+      bool proceed(const Entry& entry) {return _out.proceed(entry);}
+    private:
+      EntryOutput& _out;
+    };
+
+    /// Ignores everything passed to it. */
+    class DummyMultipleOutput {
+    public:
+      void push_back(Entry& e) {}
+    };
+
+    void reportChanges(size_t additions, size_t removals);
+    void resetNumberOfChangesTillRebuild();
+    bool reportChangesRebuild(size_t additions, size_t removals);
+    size_t _changesTillRebuild; /// Update using reportChanges().
+
+    Entry* _divisorCache; /// The divisor in the previous query. Can be null.
+
+    // All DivMasks calculated using this.
+    typename Tree::DivMaskCalculator _divMaskCalculator;
+    Tree _tree;
+    size_t _size;
+  };
+
+  template<class C>
+  std::string KDTree<C>::getName() const {
+    std::stringstream out;
+    const C& conf = getConfiguration();
+    out << "KDTree(" << (C::PackedTree ? "packed" : "binary") << ')';
+    out << " leaf:" << C::LeafSize;
+    if (UseDivMask && conf.getDoAutomaticRebuilds()) {
+      out << " autob:" << conf.getRebuildRatio()
+          << '/' << conf.getRebuildMin();
+    }
+    out << (C::UseDivMask && !C::UseTreeDivMask ? " dmask" : "")
+        << (C::UseTreeDivMask ? " tree-dmask" : "")
+        << (conf.getSortOnInsert() ? " sort" : "")
+        << (conf.getUseDivisorCache() ? " cache" : "")
+        << (C::AllowRemovals ? "" : " no-removals");
+    return out.str();
+  }
+
+  template<class C>
+  void KDTree<C>::resetNumberOfChangesTillRebuild() {
+    const C& conf = getConfiguration();
+    if (conf.getUseDivisorCache())
+      _divisorCache = 0;
+    if (!conf.getDoAutomaticRebuilds())
+      return;
+    MATHIC_ASSERT(conf.getRebuildRatio() > 0);
+    _changesTillRebuild = std::max
+      (static_cast<size_t>(size() * conf.getRebuildRatio()),
+       conf.getRebuildMin());
+  }
+
+  template<class C>
+  void KDTree<C>::reportChanges(size_t additions, size_t removals) {
+    if (getConfiguration().getUseDivisorCache() && (additions | removals) != 0)
+      _divisorCache = 0;
+    if (reportChangesRebuild(additions, removals))
+      rebuild();
+  }
+
+  template<class C>
+  bool KDTree<C>::reportChangesRebuild(size_t additions, size_t removals) {
+    // note how negative value/overflow of _changesTillRebuild cannot
+    // happen this way.
+    MATHIC_ASSERT(removals <= size() + additions);
+    _size = (size() + additions) - removals;
+    if (!getConfiguration().getDoAutomaticRebuilds())
+      return false;
+    const size_t changesMadeCount = additions + removals;
+    if (_changesTillRebuild > changesMadeCount) {
+      _changesTillRebuild -= changesMadeCount;
+      return false;
+    } else
+      return true;
+  }
+}
+
+#endif
diff --git a/src/mathic/NameFactory.cpp b/src/mathic/NameFactory.cpp
new file mode 100755
index 0000000..74a2b00
--- /dev/null
+++ b/src/mathic/NameFactory.cpp
@@ -0,0 +1 @@
+#include "NameFactory.h"
diff --git a/src/mathic/NameFactory.h b/src/mathic/NameFactory.h
new file mode 100755
index 0000000..0eb210b
--- /dev/null
+++ b/src/mathic/NameFactory.h
@@ -0,0 +1,201 @@
+#ifndef MATHIC_NAME_FACTORY_GUARD
+#define MATHIC_NAME_FACTORY_GUARD
+
+#include "stdinc.h"
+#include <vector>
+#include <string>
+#include <algorithm>
+#include <memory>
+#include "error.h"
+
+namespace mathic {
+  /** A NameFactory takes a name and then creates an instance of a class
+   that has been previously registered under that name. This is done
+   in a general way using templates.
+
+   None of this is very efficient currently. However, the interface can be
+   implemented much more efficiently if that becomes necessary.
+  */
+  template<class AbstractProduct>
+  class NameFactory {
+   public:
+    /** @param abstractName The name for those things that are being
+     generated in general. Used for error messages. */
+    NameFactory(const char* abstractName): _abstractName(abstractName) {}
+
+    typedef std::auto_ptr<AbstractProduct> (*FactoryFunction)();
+    void registerProduct(const std::string& name, FactoryFunction function);
+
+    /** Calls the function registered to the parameter name and returns
+     the result. Returns null if name has not been registered. */
+    std::auto_ptr<AbstractProduct>
+      createNullOnUnknown(const std::string& name) const;
+
+    /** Calls the function registered to the parameter name and returns
+     the result. Throws an exception if name has not been registered. */
+    std::auto_ptr<AbstractProduct> create(const std::string& name) const;
+
+    /** Inserts into names all registered names that have the indicated
+     prefix in lexicographic increasing order. */
+    void namesWithPrefix
+      (const std::string& prefix, std::vector<std::string>& names) const;
+
+    /** Returns the name of the kinds of things being created. */
+    std::string abstractProductName() const;
+
+    /** Returns true if no names have been registered. */
+    bool empty() const;
+
+   private:
+    typedef std::pair<std::string, FactoryFunction> Pair;
+    typedef typename std::vector<Pair>::const_iterator const_iterator;
+    std::vector<Pair> _pairs;
+    const std::string _abstractName;
+  };
+
+  /** Registers the given name to a function that
+    default-constructs a ConcreteProduct. */
+  template<class ConcreteProduct, class AbstractProduct>
+  void nameFactoryRegister
+    (NameFactory<AbstractProduct>& factory, const std::string& name);
+
+  /** Registers the name ConcreteProduct::staticName() to a function that
+    default-constructs a ConcreteProduct. */
+  template<class ConcreteProduct, class AbstractProduct>
+  void nameFactoryRegister
+    (NameFactory<AbstractProduct>& factory);
+
+  /** Registers the string returned by ConcreteProduct::staticName()
+   to a function that default-constructs a ConcreteProduct. */
+  template<class ConcreteProduct, class AbstractProduct>
+  void nameFactoryRegister(NameFactory<AbstractProduct>& factory);
+
+  /** Creates the unique product that has the indicated prefix, or
+   creates the actual product that has name equal to the indicated
+   prefix. Exceptions thrown are as for uniqueNamesWithPrefix(). */
+  template<class AbstractProduct>
+  std::auto_ptr<AbstractProduct> createWithPrefix
+  (const NameFactory<AbstractProduct>& factory, const std::string& prefix);
+
+  /** Returns the unique product name that has the indicated prefix, or
+   return prefix itself if it is the actual name of a product.
+
+   @exception UnknownNameException If no product has the indicated
+   prefix.
+
+   @exception AmbiguousNameException If more than one product has the
+   indicated prefix and the prefix is not the actual name of any
+   product. */
+  template<class AbstractProduct>
+  std::string uniqueNameWithPrefix
+  (const NameFactory<AbstractProduct>& factory, const std::string& prefix);
+
+
+  // **************************************************************
+  // These implementations have to be included here due
+  // to being templates.
+
+  template<class AbstractProduct>
+  std::auto_ptr<AbstractProduct> NameFactory<AbstractProduct>::
+  createNullOnUnknown(const std::string& name) const {
+    for (const_iterator it = _pairs.begin(); it != _pairs.end(); ++it)
+      if (it->first == name)
+        return it->second();
+    return std::auto_ptr<AbstractProduct>();
+  }
+
+  template<class AbstractProduct>
+  std::auto_ptr<AbstractProduct> NameFactory<AbstractProduct>::
+  create(const std::string& name) const {
+    std::auto_ptr<AbstractProduct> product = createNullOnUnknown(name);
+    if (product.get() == 0)
+      throwError<UnknownNameException>(
+        "Unknown " + abstractProductName() + " \"" + name + "\".");
+    return product;
+  }
+
+  template<class AbstractProduct>
+  void NameFactory<AbstractProduct>::
+  registerProduct(const std::string& name, FactoryFunction function) {
+    MATHIC_ASSERT(createNullOnUnknown(name).get() == 0); // no duplicate names
+    _pairs.push_back(Pair(name, function));
+  }
+
+  template<class AbstractProduct>
+  void NameFactory<AbstractProduct>::namesWithPrefix(
+    const std::string& prefix,
+    std::vector<std::string>& names
+  ) const {
+    for (const_iterator it = _pairs.begin(); it != _pairs.end(); ++it)
+      if (it->first.compare(0, prefix.size(), prefix) == 0)
+        names.push_back(it->first);
+    std::sort(names.begin(), names.end());
+  }
+
+  template<class AbstractProduct>
+  bool NameFactory<AbstractProduct>::empty() const {
+    return _pairs.empty();
+  }
+
+  template<class AbstractProduct>
+  std::string NameFactory<AbstractProduct>::abstractProductName() const {
+    return _abstractName;
+  }
+
+  template<class ConcreteProduct, class AbstractProduct>
+  void nameFactoryRegister(NameFactory<AbstractProduct>& factory) {
+    nameFactoryRegister<ConcreteProduct, AbstractProduct>
+      (factory, ConcreteProduct::staticName());
+  }
+
+  template<class ConcreteProduct, class AbstractProduct>
+  void nameFactoryRegister
+    (NameFactory<AbstractProduct>& factory, const std::string& name) {
+    // work-around for no local functions in old C++
+    struct HoldsFunction {
+      static std::auto_ptr<AbstractProduct> createConcreteProduct() {
+        return std::auto_ptr<AbstractProduct>(new ConcreteProduct());
+      }
+    };
+    factory.registerProduct(name, HoldsFunction::createConcreteProduct);
+  }
+
+  template<class AbstractProduct>
+  std::auto_ptr<AbstractProduct> createWithPrefix
+  (const NameFactory<AbstractProduct>& factory, const std::string& prefix) {
+    return factory.createNullOnUnknown(uniqueNameWithPrefix(factory, prefix));
+  }
+
+  template<class AbstractProduct>
+  std::string uniqueNameWithPrefix
+  (const NameFactory<AbstractProduct>& factory, const std::string& prefix) {
+    std::vector<std::string> names;
+    factory.namesWithPrefix(prefix, names);
+
+    // if exact string found, then use that one even if there are other
+    // prefix matches.
+    if (std::find(names.begin(), names.end(), prefix) != names.end()) {
+      names.clear();
+      names.push_back(prefix);
+    }
+
+    if (names.empty()) {
+      throwError<UnknownNameException>
+        ("No " + factory.abstractProductName() +
+         " has the prefix \"" + prefix + "\".");
+    }
+
+    if (names.size() >= 2) {
+      std::string errorMsg = "More than one " + factory.abstractProductName() +
+        " has prefix \"" + prefix + "\":\n ";
+      for (size_t name = 0; name < names.size(); ++name)
+        errorMsg += ' ' + names[name];
+      throwError<AmbiguousNameException>(errorMsg);
+    }
+
+    MATHIC_ASSERT(names.size() == 1);
+    return names.back();
+  }
+}
+
+#endif
diff --git a/src/mathic/PackedKDTree.h b/src/mathic/PackedKDTree.h
new file mode 100755
index 0000000..374807b
--- /dev/null
+++ b/src/mathic/PackedKDTree.h
@@ -0,0 +1,760 @@
+#ifndef MATHIC_PACKED_K_D_TREE_GUARD
+#define MATHIC_PACKED_K_D_TREE_GUARD
+
+#include "stdinc.h"
+#include "DivMask.h"
+#include "KDEntryArray.h"
+#include <memtailor.h>
+#include <ostream>
+
+namespace mathic {
+  template<class C>
+  class PackedKDTree {
+  public:
+    typedef typename C::Monomial Monomial;
+    typedef typename C::Entry Entry;
+    typedef typename C::Exponent Exponent;
+    typedef typename DivMask::Extender<Entry, C::UseDivMask> ExtEntry;
+    typedef typename DivMask::Extender<const Monomial&,C::UseDivMask> ExtMonoRef;
+    typedef typename DivMask::Calculator<C> DivMaskCalculator;
+
+    struct ExpOrder {
+    ExpOrder(size_t var, const C& conf): _var(var), _conf(conf) {}
+      bool operator()(const ExtEntry& a, const ExtEntry& b) const {
+        return _conf.getExponent(a.get(), _var) < _conf.getExponent(b.get(), _var);
+      }
+    private:
+      const size_t _var;
+      const C& _conf;
+    };
+
+    private:
+    typedef C Configuration;
+    static const bool UseDivMask = C::UseDivMask;
+
+    class Node {
+    public:
+      static Node* makeNode(memt::Arena& arena, const C& conf) {
+        return new (arena.alloc(sizeOf(0)))
+          Node(arena, conf);
+      }
+
+      template<class Iter>
+      static Node* makeNode(Iter begin, Iter end, memt::Arena& arena,
+        const C& conf, size_t childCount) {
+        return new (arena.alloc(sizeOf(childCount)))
+          Node(begin, end, arena, conf, childCount);
+      }
+
+      template<class Iter>
+      static Node* makeNode(Iter begin, Iter end, memt::Arena& arena,
+        const DivMaskCalculator& calc, const C& conf, size_t childCount) {
+        return new (arena.alloc(sizeOf(childCount)))
+          Node(begin, end, arena, calc, conf, childCount);
+      }
+
+      static size_t sizeOf(size_t childCount) {
+        if (childCount > 0)
+          --childCount; // array has size 1, so one element already there
+        return sizeof(Node) + childCount * sizeof(Child);
+      }
+
+      struct Child : public mathic::DivMask::HasDivMask<C::UseTreeDivMask> {
+        size_t var;
+        Exponent exponent;
+        Node* node;
+      };
+      typedef Child* iterator;
+      typedef Child const* const_iterator;
+      iterator childBegin() {return _childrenMemoryBegin;}
+      const_iterator childBegin() const {return _childrenMemoryBegin;}
+      iterator childEnd() {return _childrenEnd;}
+      const_iterator childEnd() const {return _childrenEnd;}
+
+      bool hasChildren() const {return childBegin() != childEnd();}
+      template<class ME> // ME is MonomialOrEntry
+      bool inChild(const_iterator child, const ME me, const C& conf) const {
+        return child->exponent < conf.getExponent(me, child->var);
+      }
+
+      mathic::KDEntryArray<C, ExtEntry>& entries() {return _entries;}
+      const KDEntryArray<C, ExtEntry>& entries() const {return _entries;}
+
+      Node* splitInsert(
+        const ExtEntry& extEntry,
+        Child* childFromParent,
+        memt::Arena& arena,
+        const C& conf);
+
+#ifdef MATHIC_DEBUG
+      bool debugIsValid() const;
+#endif
+
+    private:
+      Node(const Node&); // unavailable
+      void operator=(const Node&); // unavailable
+
+      Node(memt::Arena& arena, const C& conf);
+      
+      template<class Iter>
+      Node(Iter begin, Iter end, memt::Arena& arena,
+        const C& conf, size_t childCount);
+
+      template<class Iter>
+      Node(Iter begin, Iter end, memt::Arena& arena,
+        const DivMaskCalculator& calc, const C& conf, size_t childCount);
+
+      class SplitEqualOrLess;
+
+      KDEntryArray<C, ExtEntry> _entries;
+      // Array has size 1 to appease compiler since size 0 produces warnings
+      // or errors. Actual size can be greater if more memory has been
+      // allocated for the node than sizeof(Node).
+      Child* _childrenEnd; // points into _childrenMemoryBegin
+      Child _childrenMemoryBegin[1];
+    };
+
+  public:
+    PackedKDTree(const C& configuration);
+    ~PackedKDTree();
+
+    template<class MultipleOutput>
+    size_t removeMultiples(const ExtMonoRef& monomial, MultipleOutput& out);
+
+    bool removeElement(const Monomial& monomial);
+
+    void insert(const ExtEntry& entry);
+
+    template<class Iter>
+    void reset(Iter begin, Iter end, const DivMaskCalculator& calc);
+
+    inline Entry* findDivisor(const ExtMonoRef& monomial);
+
+    template<class DivisorOutput>
+    inline void findAllDivisors
+      (const ExtMonoRef& monomial, DivisorOutput& out);
+
+    template<class DivisorOutput>
+    inline void findAllMultiples
+      (const ExtMonoRef& monomial, DivisorOutput& out);
+
+    template<class EntryOutput>
+    void forAll(EntryOutput& out);
+
+    void clear();
+
+    size_t getMemoryUse() const;
+
+    void print(std::ostream& out) const;
+
+    C& getConfiguration() {return _conf;}
+
+#ifdef MATHIC_DEBUG
+    bool debugIsValid() const;
+#endif
+
+  private:
+    PackedKDTree(const PackedKDTree<C>&); // unavailable
+    void operator=(const PackedKDTree<C>&); // unavailable
+  
+    template<class Iter>
+    struct InsertTodo {
+      Iter begin;
+      Iter end;
+      Exponent exp;
+      size_t var;
+      typename Node::Child* fromParent;
+    };
+
+    memt::Arena _arena; // Everything permanent allocated from here.
+    C _conf; // User supplied configuration.
+    mutable std::vector<Node*> _tmp; // For navigating the tree.
+    Node* _root; // Root of the tree. Can be null!
+  };
+
+  template<class C>
+  PackedKDTree<C>::PackedKDTree(const C& configuration):
+  _conf(configuration), _root(0) {
+    MATHIC_ASSERT(C::LeafSize > 0);
+    MATHIC_ASSERT(debugIsValid());
+  }
+
+  template<class C>
+  PackedKDTree<C>::~PackedKDTree() {
+    clear();
+  }
+
+  template<class C>
+  PackedKDTree<C>::Node::Node(memt::Arena& arena, const C& conf):
+  _entries(arena, conf) {
+    _childrenEnd = childBegin();
+  }
+
+  template<class C>
+  template<class Iter>
+  PackedKDTree<C>::Node::Node(
+    Iter begin,
+    Iter end,
+    memt::Arena& arena,
+    const C& conf,
+    size_t childCount):
+    _entries(begin, end, arena, conf) {
+    _childrenEnd = childBegin() + childCount;
+  }
+
+  template<class C>
+  template<class Iter>
+  PackedKDTree<C>::Node::Node(
+    Iter begin,
+    Iter end,
+    memt::Arena& arena,
+    const DivMaskCalculator& calc,
+    const C& conf,
+    size_t childCount):
+    _entries(begin, end, arena, calc, conf) {
+    _childrenEnd = childBegin() + childCount;
+  }
+
+  template<class C>
+  template<class MO>
+  size_t PackedKDTree<C>::removeMultiples(
+    const ExtMonoRef& extMonomial,
+    MO& out
+  ) {
+    MATHIC_ASSERT(_tmp.empty());
+    if (_root == 0)
+      return 0;
+    size_t removedCount = 0;
+    Node* node = _root;
+    while (true) {
+      for (typename Node::const_iterator it = node->childBegin();
+        it != node->childEnd(); ++it) {
+        _tmp.push_back(it->node);
+        if (node->inChild(it, extMonomial.get(), _conf))
+          goto stopped;
+      }
+      removedCount += node->entries().removeMultiples(extMonomial, out, _conf);
+stopped:;
+      if (_tmp.empty())
+        break;
+      node = _tmp.back();
+      _tmp.pop_back();
+    }
+    MATHIC_ASSERT(_tmp.empty());
+    MATHIC_ASSERT(debugIsValid());
+    return removedCount;
+  }
+
+  template<class C>
+  bool PackedKDTree<C>::removeElement(const Monomial& monomial) {
+    MATHIC_ASSERT(_tmp.empty());
+    if (_root == 0)
+      return false;
+    Node* node = _root;
+ 
+    typename Node::iterator child = node->childBegin();
+    while (child != node->childEnd()) {
+      if (node->inChild(child, monomial, _conf)) {
+        node = child->node;
+        child = node->childBegin();
+      } else
+        ++child;
+    }
+    const bool value = node->entries().removeElement(monomial, _conf);
+    MATHIC_ASSERT(debugIsValid());
+    return value;
+  }
+
+  template<class C>
+  void PackedKDTree<C>::insert(const ExtEntry& extEntry) {
+    MATHIC_ASSERT(debugIsValid());
+    // find node in which to insert extEntry
+    typename Node::Child* parentChild = 0;
+    if (_root == 0)
+      _root = Node::makeNode(_arena, _conf);
+    Node* node = _root;
+    typename Node::iterator child = node->childBegin();
+    while (true) {
+      if (child == node->childEnd()) {
+        MATHIC_ASSERT(node->entries().size() <= C::LeafSize);
+        if (node->entries().size() < C::LeafSize)
+          node->entries().insert(extEntry, _conf);
+        else { // split full node
+          node = node->splitInsert(extEntry, parentChild, _arena, _conf);
+          if (parentChild == 0)
+            _root = node;
+        }
+        break;
+      }
+      if (C::UseTreeDivMask)
+        child->updateToLowerBound(extEntry);
+      if (node->inChild(child, extEntry.get(), _conf)) {
+        parentChild = &*child;
+        node = child->node;
+        child = node->childBegin();
+      } else
+        ++child;
+    }
+    MATHIC_ASSERT(debugIsValid());
+  }
+
+  template<class C>
+  template<class Iter>
+  void PackedKDTree<C>::reset(Iter insertBegin, Iter insertEnd, const DivMaskCalculator& calc) {
+    clear();
+    if (insertBegin == insertEnd)
+      return;
+
+    typedef InsertTodo<Iter> Task;
+    typedef std::vector<Task> TaskCont;
+    TaskCont todo;
+    TaskCont children;
+
+    {
+      Task initialTask;
+      initialTask.begin = insertBegin;
+      initialTask.end = insertEnd;
+      initialTask.var = static_cast<size_t>(-1);
+      initialTask.fromParent = 0;
+      todo.push_back(initialTask);
+    }
+    while (!todo.empty()) {
+      Iter begin = todo.back().begin;
+      Iter end = todo.back().end;
+      size_t var = todo.back().var;
+      typename Node::Child* fromParent = todo.back().fromParent;
+      if (fromParent != 0) {
+        fromParent->var = var;
+        fromParent->exponent = todo.back().exp;
+      }
+      todo.pop_back();
+
+      // split off children until reaching few enough entries
+      while (C::LeafSize < static_cast<size_t>(std::distance(begin, end))) {
+        Task child;
+        Iter middle = KDEntryArray<C, ExtEntry>::
+          split(begin, end, var, child.exp, _conf);
+        MATHIC_ASSERT(begin < middle && middle < end);
+        MATHIC_ASSERT(var < _conf.getVarCount());
+        child.begin = middle;
+        child.end = end;
+        child.var = var;
+        children.push_back(child);
+        // now operate on the equal-or-less part of the range
+        end = middle;
+      }
+      Node* node = Node::makeNode
+        (begin, end, _arena, calc, _conf, children.size());
+      if (_root == 0)
+        _root = node;
+      if (fromParent != 0)
+        fromParent->node = node;
+      for (size_t child = 0; child < children.size(); ++child) {
+        children[child].fromParent = &*(node->childBegin() + child);
+        todo.push_back(children[child]);
+      }
+      children.clear();
+    }
+    MATHIC_ASSERT(_root != 0);
+
+    if (C::UseTreeDivMask) {
+      // record nodes in tree using breadth first search
+      typedef std::vector<Node*> NodeCont;
+      NodeCont nodes;
+      nodes.push_back(_root);
+      for (size_t i = 0; i < nodes.size(); ++i) {
+        Node* node = nodes[i];
+        for (typename Node::iterator child = node->childBegin();
+          child != node->childEnd(); ++child)
+          nodes.push_back(child->node);
+      }
+      // compute div masks in reverse order of breath first search
+      typename NodeCont::reverse_iterator it = nodes.rbegin();
+      typename NodeCont::reverse_iterator end = nodes.rend();
+      for (; it != end; ++it) {
+        Node* node = *it;
+        typedef std::reverse_iterator<typename Node::iterator> riter;
+        riter rbegin = riter(node->childEnd());
+        riter rend = riter(node->childBegin());
+        for (riter child = rbegin; child != rend; ++child) {
+          child->resetDivMask();
+          if (child == rbegin)
+            child->updateToLowerBound(node->entries());
+          else {
+            riter prev = child;
+            --prev;
+            child->updateToLowerBound(*prev);
+          }
+          if (child->node->hasChildren())
+            child->updateToLowerBound(*child->node->childBegin());
+          else
+            child->updateToLowerBound(child->node->entries());
+        }
+        ASSERT(node->debugIsValid());
+      }
+    }
+    MATHIC_ASSERT(debugIsValid());
+  }
+
+  template<class C>
+  typename PackedKDTree<C>::Entry* PackedKDTree<C>::findDivisor
+    (const ExtMonoRef& extMonomial) {
+    MATHIC_ASSERT(_tmp.empty());
+    if (_root == 0)
+      return 0;
+    Node* node = _root;
+    while (true) {
+      // record relevant children for later processing
+      for (typename Node::const_iterator it = node->childBegin();
+        it != node->childEnd(); ++it) {
+        if (C::UseTreeDivMask &&
+          !it->getDivMask().canDivide(extMonomial.getDivMask()))
+          goto next;
+        if (node->inChild(it, extMonomial.get(), _conf))
+          _tmp.push_back(it->node);
+      }
+
+      // look for divisor in entries of node
+      {
+        typename KDEntryArray<C, ExtEntry>::iterator it =
+          node->entries().findDivisor(extMonomial, _conf);
+        if (it != node->entries().end()) {
+          MATHIC_ASSERT(_conf.divides(it->get(), extMonomial.get()));
+          _tmp.clear();
+          return &it->get();
+        }
+      }
+
+next:
+      // grab next node to process
+      if (_tmp.empty())
+        break;
+      node = _tmp.back();
+      _tmp.pop_back();
+    }
+    MATHIC_ASSERT(_tmp.empty());
+    return 0;
+  }
+
+  template<class C>
+  template<class DO>
+  void PackedKDTree<C>::findAllDivisors(
+    const ExtMonoRef& extMonomial,
+    DO& output
+  ) {
+    MATHIC_ASSERT(_tmp.empty());
+    if (_root == 0)
+      return;
+    Node* node = _root;
+    while (true) {
+      for (typename Node::const_iterator it = node->childBegin();
+        it != node->childEnd(); ++it) {
+        if (C::UseTreeDivMask &&
+          !it->getDivMask().canDivide(extMonomial.getDivMask()))
+          goto next; // div mask rules this sub tree out
+        if (node->inChild(it, extMonomial.get(), _conf))
+          _tmp.push_back(it->node);
+      }
+      if (!node->entries().findAllDivisors(extMonomial, output, _conf)) {
+        _tmp.clear();
+        break;
+      }
+next:
+      if (_tmp.empty())
+        break;
+      node = _tmp.back();
+      _tmp.pop_back();
+    }
+    MATHIC_ASSERT(_tmp.empty());
+  }
+
+  template<class C>
+  template<class DO>
+  void PackedKDTree<C>::findAllMultiples(
+    const ExtMonoRef& extMonomial,
+    DO& output
+  ) {
+    MATHIC_ASSERT(_tmp.empty());
+    if (_root == 0)
+      return;
+    Node* node = _root;
+    while (true) {
+      for (typename Node::const_iterator it = node->childBegin();
+        it != node->childEnd(); ++it) {
+          _tmp.push_back(it->node);
+          if (node->inChild(it, extMonomial.get(), _conf))
+            goto next;
+      }
+      if (!node->entries().findAllMultiples(extMonomial, output, _conf)) {
+        _tmp.clear();
+        break;
+      }
+next:
+      if (_tmp.empty())
+        break;
+      node = _tmp.back();
+      _tmp.pop_back();
+    }
+    MATHIC_ASSERT(_tmp.empty());
+  }
+
+  template<class C>
+  template<class EO>
+  void PackedKDTree<C>::forAll(EO& output) {
+    MATHIC_ASSERT(_tmp.empty());
+    if (_root == 0)
+      return;
+    Node* node = _root;
+    while (true) {
+      if (!node->entries().forAll(output)) {
+        _tmp.clear();
+        break;
+      }
+      for (typename Node::iterator it = node->childBegin();
+        it != node->childEnd(); ++it)
+        _tmp.push_back(it->node);
+      if (_tmp.empty())
+        break;
+      node = _tmp.back();
+      _tmp.pop_back();
+    }
+    MATHIC_ASSERT(_tmp.empty());
+  }
+
+  template<class C>
+  void PackedKDTree<C>::clear() {
+    MATHIC_ASSERT(_tmp.empty());
+    // Call Entry destructors
+    if (_root != 0)
+      _tmp.push_back(_root);
+    while (!_tmp.empty()) {
+      Node* node = _tmp.back();
+      _tmp.pop_back();
+      node->entries().clear(); // calls destructors
+      for (typename Node::iterator it = node->childBegin();
+        it != node->childEnd(); ++it)
+        _tmp.push_back(it->node);
+    }
+    _arena.freeAllAllocs();
+    _root = 0;
+  }
+
+  template<class C>
+  size_t PackedKDTree<C>::getMemoryUse() const {
+    // todo: not accurate
+	size_t sum = _arena.getMemoryUse();
+	sum += _tmp.capacity() * sizeof(_tmp.front());
+	return sum;
+  }
+
+  template<class C>
+  void PackedKDTree<C>::print(std::ostream& out) const {
+    out << "<<<<<<<< PackedKDTree >>>>>>>>\n";
+    MATHIC_ASSERT(_tmp.empty());
+    if (_root == 0)
+      return;
+    Node* node = _root;
+    while (true) {
+      out << "**** Node " << node << "\nchildren:\n";
+      for (typename Node::iterator it = node->childBegin();
+        it != node->childEnd(); ++it) {
+        _tmp.push_back(it->node);
+        out << "Child " << ((it - node->childBegin()) + 1) << ": "
+          << '>' << (it->var + 1) << '^' << it->exponent
+          << ' ' << it->node << '\n';
+      }
+      for (size_t i = 0; i < node->entries().size(); ++i) {
+        out << "Entry " << (i + 1) << ": "
+          << node->entries().begin()[i].get() << '\n';
+      }
+      out << '\n';
+      if (_tmp.empty())
+        break;
+      node = _tmp.back();
+      _tmp.pop_back();
+    }
+    MATHIC_ASSERT(_tmp.empty());
+  }
+
+#ifdef MATHIC_DEBUG
+  template<class C>
+  bool PackedKDTree<C>::debugIsValid() const {
+    //print(std::cerr); std::cerr << std::flush;
+    MATHIC_ASSERT(_tmp.empty());
+    MATHIC_ASSERT(!_conf.getDoAutomaticRebuilds() || _conf.getRebuildRatio() > 0);
+    if (_root == 0)
+      return true;
+
+    // record all nodes
+    std::vector<Node*> nodes;
+    nodes.push_back(_root);
+    for (size_t i = 0; i < nodes.size(); ++i) {
+      Node* node = nodes[i];
+      ASSERT(node->entries().debugIsValid());
+      for (typename Node::iterator it = node->childBegin();
+        it != node->childEnd(); ++it) {
+        MATHIC_ASSERT(it->var < _conf.getVarCount());
+        MATHIC_ASSERT(!C::UseTreeDivMask ||
+          it->canDivide(node->entries()));
+        nodes.push_back(it->node);
+      }
+    }
+
+    // check the recorded nodes
+    MATHIC_ASSERT(_tmp.empty());
+    for (size_t i = 0; i < nodes.size(); ++i) {
+      Node* ancestor = nodes[i];
+
+      for (typename Node::iterator ancestorIt = ancestor->childBegin();
+        ancestorIt != ancestor->childEnd(); ++ancestorIt) {
+        MATHIC_ASSERT(_tmp.empty());
+        size_t var = ancestorIt->var;
+        Exponent exp = ancestorIt->exponent;
+        // check strictly greater than subtree
+        _tmp.push_back(ancestorIt->node);
+        while (!_tmp.empty()) {
+          Node* node = _tmp.back();
+          _tmp.pop_back();
+          for (typename Node::iterator it = node->childBegin();
+            it != node->childEnd(); ++it) {
+            MATHIC_ASSERT(!C::UseTreeDivMask || ancestorIt->canDivide(*it));
+            _tmp.push_back(it->node);
+          }
+          MATHIC_ASSERT(node->entries().
+            allStrictlyGreaterThan(var, exp, _conf));
+          MATHIC_ASSERT(!C::UseTreeDivMask ||
+            ancestorIt->canDivide(node->entries()));
+        }
+        // check less than or equal to sub tree.
+        MATHIC_ASSERT(ancestor->entries().
+          allLessThanOrEqualTo(var, exp, _conf));
+        // go through the rest of the children
+        typename Node::iterator restIt = ancestorIt;
+        for (++restIt; restIt != ancestor->childEnd(); ++restIt) {
+          MATHIC_ASSERT(!C::UseTreeDivMask || ancestorIt->canDivide(*restIt));
+          _tmp.push_back(restIt->node);
+        }
+        while (!_tmp.empty()) {
+          Node* node = _tmp.back();
+          _tmp.pop_back();
+          for (typename Node::iterator it = node->childBegin();
+            it != node->childEnd(); ++it) {
+            MATHIC_ASSERT(!C::UseTreeDivMask || ancestorIt->canDivide(*it));
+            _tmp.push_back(it->node);
+          }
+          MATHIC_ASSERT(node->entries().
+            allLessThanOrEqualTo(var, exp, _conf));
+          MATHIC_ASSERT(!C::UseTreeDivMask ||
+            ancestorIt->canDivide(node->entries()));
+        }
+      }
+    }
+    return true;
+  }
+#endif
+
+  template<class C>
+  class PackedKDTree<C>::Node::SplitEqualOrLess {
+  public:
+    typedef typename C::Exponent Exponent;
+    typedef typename C::Entry Entry;
+  SplitEqualOrLess(size_t var, const Exponent& exp, const C& conf):
+    _var(var), _exp(exp), _conf(conf) {}
+    bool operator()(const Entry& entry) const {
+      return !(_exp < _conf.getExponent(entry, _var));
+    }
+  private:
+    size_t _var;
+    const Exponent& _exp;
+    const C& _conf;
+  };
+
+  template<class C>
+  typename PackedKDTree<C>::Node* PackedKDTree<C>::Node::splitInsert(
+    const ExtEntry& extEntry,
+    Child* childFromParent,
+    memt::Arena& arena,
+    const C& conf
+  ) {
+    MATHIC_ASSERT(conf.getVarCount() > 0);
+    MATHIC_ASSERT(entries().size() > 0);
+    size_t var;
+    if (hasChildren())
+      var = (childEnd() - 1)->var;
+    else if (childFromParent != 0)
+      var = childFromParent->var;
+    else
+      var = static_cast<size_t>(-1);
+    typename C::Exponent exp;
+
+    // there is not room to add another child, so make a
+    // new Node with more space and put the Node we are splitting
+    // off into the vacated space. It will fit as it has no
+    // children at all.
+
+    typename KDEntryArray<C, ExtEntry>::iterator middle =
+      KDEntryArray<C, ExtEntry>::split
+      (entries().begin(), entries().end(), var, exp, conf, &extEntry);
+
+    // ** copy relevant part of *this into new space
+    Node* copied = makeNode(entries().begin(), middle, arena, conf,
+      std::distance(childBegin(), childEnd()) + 1);
+    std::copy(childBegin(), childEnd(), copied->childBegin());
+    Child& newChild = *(copied->childEnd() - 1);
+    newChild.var = var;
+    newChild.exponent = exp;
+    newChild.node = this;
+    if (childFromParent != 0)
+      childFromParent->node = copied;
+    if (C::UseTreeDivMask) {
+      newChild.resetDivMask();
+      newChild.updateToLowerBound(entries());
+      newChild.updateToLowerBound(extEntry);
+    }
+
+    // ** fix up remaining part of *this to be the child of copied
+    // OK to call std::copy as begin is not in the range [middle, end).
+    std::copy(middle, entries().end(), entries().begin());
+    const size_t targetSize = std::distance(middle, entries().end());
+    while (entries().size() > targetSize)
+      entries().pop_back();
+    if (conf.getSortOnInsert())
+      std::sort(entries().begin(), entries().end(), Comparer<C>(conf));
+    if (C::UseTreeDivMask)
+      entries().recalculateTreeDivMask();
+    _childrenEnd = childBegin();
+
+    if (copied->inChild(copied->childEnd() - 1, extEntry.get(), conf))
+      entries().insert(extEntry, conf);
+    else
+      copied->entries().insert(extEntry, conf);
+
+    MATHIC_ASSERT(debugIsValid());
+    MATHIC_ASSERT(copied->debugIsValid());
+
+    return copied;
+  }
+
+#ifdef MATHIC_DEBUG
+  template<class C>
+  bool PackedKDTree<C>::Node::debugIsValid() const {
+    ASSERT(entries().debugIsValid());
+    ASSERT(childBegin() <= childEnd());
+    if (C::UseTreeDivMask) {
+      for (const_iterator child = childBegin(); child != childEnd(); ++child) {
+        if (child != childEnd() - 1)
+          MATHIC_ASSERT(child->canDivide(*(child + 1)));
+        else
+          MATHIC_ASSERT(child->canDivide(entries()));
+        if (child->node->hasChildren())
+          MATHIC_ASSERT(child->canDivide(*child->node->childBegin()));
+        else
+          MATHIC_ASSERT(child->canDivide(child->node->entries()));
+      }
+    }
+    return true;
+  }
+#endif
+}
+
+#endif
diff --git a/src/mathic/StlSet.h b/src/mathic/StlSet.h
new file mode 100755
index 0000000..9f1609f
--- /dev/null
+++ b/src/mathic/StlSet.h
@@ -0,0 +1,68 @@
+#ifndef MATHIC_STL_SET_GUARD
+#define MATHIC_STL_SET_GUARD
+
+#include "stdinc.h"
+#include <set>
+#include <string>
+#include <ostream>
+
+namespace mathic {
+  template<class C>
+	class StlSet {
+  public:
+	typedef C Configuration;
+	typedef typename Configuration::Entry Entry;
+
+  StlSet(const Configuration& configuration):
+    _conf(configuration), _set(Cmp(&_conf)) {}
+	Configuration& getConfiguration() {return _conf;}
+	const Configuration& getConfiguration() const {return _conf;}
+
+	std::string getName() const {return "stlset";}
+	void push(Entry entry) {_set.insert(entry);}
+	void push(const Entry* begin, const Entry* end) {
+	  for (; begin != end; ++begin)
+		push(*begin);
+	}
+	Entry pop() {
+	  Entry top = *_set.begin();
+	  _set.erase(_set.begin());
+	  return top;
+	}
+	Entry top() {
+	  return *_set.begin();
+	}
+	bool empty() const {return _set.empty();}
+	void print(std::ostream& out) const {
+	  out << getName() << ":\n";
+	  for (typename std::multiset<Entry, Cmp>::const_iterator it = _set.begin();
+		   it != _set.end(); ++it)
+		out << ' ' << *it;
+	  out << '\n';
+	}
+
+    /** This is necessarily an estimate since there is no
+     way to tell how much memory a std::multiset is using. */
+    size_t getMemoryUse() const {
+      const size_t bytesPerItemEstimate =
+        2 * sizeof(void*) + // assume binary tree with left and right pointers
+        sizeof(void*) + // assume minimal overhead in the allocator behind new
+        sizeof(int) + // assume some overhead to maintain balance in tree
+        sizeof(Entry); // assume data payload        
+      return _set.size() * bytesPerItemEstimate;
+    }
+
+  private:
+	Configuration _conf;
+	struct Cmp {
+    Cmp(const Configuration* conf): _conf(conf) {}
+	  bool operator()(const Entry& a, const Entry& b) {
+		return _conf->cmpLessThan(_conf->compare(b, a));
+	  }
+	  const Configuration* _conf; // should be &, but gcc complains
+	};
+	std::multiset<Entry, Cmp> _set;
+  };
+}
+
+#endif
diff --git a/src/mathic/StringParameter.cpp b/src/mathic/StringParameter.cpp
new file mode 100755
index 0000000..84f35e7
--- /dev/null
+++ b/src/mathic/StringParameter.cpp
@@ -0,0 +1,22 @@
+#include "StringParameter.h"
+
+namespace mathic {
+  StringParameter::StringParameter(const std::string& name,
+                                   const std::string& description,
+                                   const std::string& defaultValue):
+    CliParameter(name, description),
+    _value(defaultValue) {
+  }
+
+  std::string StringParameter::argumentType() const {
+    return "STRING";
+  }
+
+  std::string StringParameter::valueAsString() const {
+    return _value;
+  }
+
+  void StringParameter::processArgument(const std::string& argument) {
+    _value = argument;
+  }
+}
diff --git a/src/mathic/StringParameter.h b/src/mathic/StringParameter.h
new file mode 100755
index 0000000..f94f6f1
--- /dev/null
+++ b/src/mathic/StringParameter.h
@@ -0,0 +1,32 @@
+#ifndef MATHIC_STRING_PARAMETER_GUARD
+#define MATHIC_STRING_PARAMETER_GUARD
+
+#include "stdinc.h"
+#include "CliParameter.h"
+#include <utility>
+#include <string>
+
+namespace mathic {
+  class StringParameter : public CliParameter {
+  public:
+    StringParameter(const std::string& name,
+                    const std::string& description,
+                    const std::string& defaultValue);
+
+    const std::string& value() const {return _value;}
+    void setValue(const std::string& value) {_value = value;}
+
+    operator const std::string&() const {return value();}
+    void operator=(const std::string& value) {setValue(value);}
+    bool operator==(const std::string& str) const {return value() == str;}
+
+    virtual std::string argumentType() const;
+    virtual std::string valueAsString() const;
+    virtual void processArgument(const std::string& argument);
+
+  private:
+    std::string _value;
+  };
+}
+
+#endif
diff --git a/src/mathic/Timer.cpp b/src/mathic/Timer.cpp
new file mode 100644
index 0000000..9e221c9
--- /dev/null
+++ b/src/mathic/Timer.cpp
@@ -0,0 +1,51 @@
+#include "Timer.h"
+
+namespace mathic {
+  unsigned long Timer::getMilliseconds() const {
+    const double floatSpan = clock() - _clocksAtReset;
+    const double floatMilliseconds = 1000 * (floatSpan / CLOCKS_PER_SEC);
+    unsigned long milliseconds = static_cast<unsigned long>(floatMilliseconds);
+    if (floatMilliseconds - milliseconds >= 0.5)
+      ++milliseconds;
+    return milliseconds;
+  }
+
+  void Timer::print(FILE* out) const {
+    unsigned long milliseconds = getMilliseconds();
+    unsigned long seconds = milliseconds / 1000;
+    unsigned long minutes = seconds / 60;
+    unsigned long hours = minutes / 60;
+
+    milliseconds %= 1000;
+    seconds %= 60;
+    minutes %= 60;
+
+    fputc('(', out);
+    if (hours != 0)
+      fprintf(out, "%luh", hours);
+    if (minutes != 0 || hours != 0)
+      fprintf(out, "%lum", minutes);
+    fprintf(out, "%lu.%03lus)", seconds, milliseconds);
+  }
+
+  void Timer::print(std::ostream& out) const {
+    unsigned long milliseconds = getMilliseconds();
+    unsigned long seconds = milliseconds / 1000;
+    unsigned long minutes = seconds / 60;
+    unsigned long hours = minutes / 60;
+
+    milliseconds %= 1000;
+    seconds %= 60;
+    minutes %= 60;
+
+    if (hours != 0)
+      out << hours << 'h';
+    if (minutes != 0 || hours != 0)
+      out << minutes << 'm';
+    out << seconds << '.';
+    out << (milliseconds / 100);
+    out << ((milliseconds / 10) % 10);
+    out << (milliseconds % 10);
+    out << "s";
+  }
+}
diff --git a/src/mathic/Timer.h b/src/mathic/Timer.h
new file mode 100644
index 0000000..d00e325
--- /dev/null
+++ b/src/mathic/Timer.h
@@ -0,0 +1,44 @@
+#ifndef MATHIC_TIMER_GUARD
+#define MATHIC_TIMER_GUARD
+
+#include "stdinc.h"
+#include <ctime>
+#include <cstdio>
+#include <ostream>
+
+namespace mathic {
+  /** Measures spans of CPU time.
+
+      The internal record of time can overflow quickly. If
+      clock_t is 32 bits unsigned and CLOCKS_PER_TIC is one million
+      then overflow will occur after 71 minutes. */
+  class Timer {
+  public:
+    Timer() {reset();}
+
+    /** Resets the amount of elapsed CPU time to zero. */
+    void reset() {_clocksAtReset = std::clock();}
+
+    /** Returns the number of CPU milliseconds since the last reset.
+        See class description for time span overflow limitations. */
+    unsigned long getMilliseconds() const;
+
+    /** Prints the elapsed time in a human readable format. See
+        class description for time span overflow limitations. */
+    void print(FILE* out) const;
+
+    /** Prints the elapsed time in a human readable format. See
+        class description for time span overflow limitations. */
+    void print(std::ostream& out) const;
+
+  private:
+    std::clock_t _clocksAtReset;
+  };
+
+  inline std::ostream& operator<<(std::ostream& out, const Timer& timer) {
+    timer.print(out);
+    return out;
+  }
+}
+
+#endif
diff --git a/src/mathic/TourTree.h b/src/mathic/TourTree.h
new file mode 100755
index 0000000..9256c12
--- /dev/null
+++ b/src/mathic/TourTree.h
@@ -0,0 +1,261 @@
+#ifndef MATHIC_TOUR_TREE_GUARD
+#define MATHIC_TOUR_TREE_GUARD
+
+#include "stdinc.h"
+#include "ComTree.h"
+#include <string>
+#include <vector>
+
+namespace mathic {
+  template<class C>
+	class TourTree {
+  public:
+	typedef C Configuration;
+	typedef typename Configuration::Entry Entry;
+
+	TourTree(const Configuration& configuration);
+	Configuration& getConfiguration() {return _conf;}
+	const Configuration& getConfiguration() const {return _conf;}
+
+    std::string getName() const;
+	void push(Entry entry);
+    template<class It>
+	void push(It begin, It end);
+	Entry pop();
+	Entry top() const;
+	bool empty() const {return _tree.empty();}
+	void print(std::ostream& out) const;
+
+	void decreaseTop(Entry newEntry);
+
+    template<class T>
+    void forAll(T& t) const {
+      typedef typename std::vector<Player>::const_iterator Iter;
+      Iter end = _players.end();
+      for (Iter it = _players.begin(); it != end; ++it)
+        if (!t.proceed(it->entry))
+          return;
+    }
+
+    template<class T>
+    void forAll(T& t) {
+      typedef typename std::vector<Player>::iterator Iter;
+      Iter end = _players.end();
+      for (Iter it = _players.begin(); it != end; ++it)
+        if (!t.proceed(it->entry))
+          return;
+    }
+
+    void clear();
+
+    size_t getMemoryUse() const;
+
+  private:
+	class Player;
+	typedef ComTree<Player*, C::fastIndex> Tree;
+	typedef typename Tree::Node Node;
+	struct Player { 
+      Player(const Entry& entry, Node leaf): entry(entry), leaf(leaf) {}
+	  Entry entry;
+	  Node leaf;
+	};
+
+	void reallocate();
+
+#ifdef MATHIC_DEBUG
+	bool isValid() const;
+#endif
+
+	Tree _tree;
+	std::vector<Player> _players;
+	Configuration _conf;
+  };
+
+  template<class C>
+  void TourTree<C>::clear() {
+    _tree.clear();
+    _players.clear();
+  }
+
+  template<class C>
+  size_t TourTree<C>::getMemoryUse() const {
+    return _tree.getMemoryUse() +
+      _players.capacity() * sizeof(_players.front());
+  }
+
+  template<class C>
+  TourTree<C>::TourTree(const C& configuration): _conf(configuration) {
+	reallocate();
+  }
+
+  template<class C>
+	std::string TourTree<C>::getName() const {
+	return std::string("t-tree (") +
+	  (C::fastIndex ? "fi" : "si") +
+	  ')';
+  }
+
+  template<class C>
+	void TourTree<C>::push(Entry entry) {
+	MATHIC_ASSERT(isValid());
+	if (!_tree.hasFreeCapacity(2))
+	  reallocate();
+	if (empty()) {
+	  _players.push_back(Player(entry, Node()));
+	  _tree.pushBackWithCapacity(&_players.back());
+	  MATHIC_ASSERT(isValid());
+	  return;
+	}
+	// move leaf down as left child
+	Node posParent = _tree.lastLeaf().next().parent();
+	Player* moveDown = _tree[posParent];
+	_tree.pushBackWithCapacity(moveDown);
+	moveDown->leaf = _tree.lastLeaf();
+	MATHIC_ASSERT(_tree.lastLeaf().isLeft());
+
+	// insert entry as right child
+	_players.push_back(Player(entry, _tree.lastLeaf().next()));
+	_tree.pushBackWithCapacity(&_players.back());
+	MATHIC_ASSERT(_tree.lastLeaf().isRight());
+
+	Node pos = _tree.lastLeaf();
+	do {
+	  MATHIC_ASSERT(!pos.isRoot());
+	  MATHIC_ASSERT(posParent == pos.parent());
+	  typename C::CompareResult cmp = _conf.compare
+		(_tree[posParent]->entry, _tree[pos]->entry);
+	  if (!_conf.cmpLessThan(cmp))
+		break;
+	  _tree[posParent] = _tree[pos];
+	  pos = posParent;
+	  posParent = pos.parent();
+	} while (!pos.isRoot());
+	MATHIC_ASSERT(isValid());
+  }
+
+  template<class C>
+  template<class It>
+  void TourTree<C>::push(It begin, It end) {
+	for (; begin != end; ++begin)
+	  push(*begin);
+  }
+
+  template<class C>
+	void TourTree<C>::decreaseTop(Entry newEntry) {
+	MATHIC_ASSERT(!empty());
+	Player* player = _tree[Node()];
+	player->entry = newEntry;
+	for (Node pos = player->leaf; !pos.isRoot(); pos = pos.parent()) {
+	  Player* opponent = _tree[pos.sibling()];
+	  if (_conf.cmpLessThan(_conf.compare(player->entry, opponent->entry)))
+		player = opponent;
+	  _tree[pos.parent()] = player;
+	}
+	MATHIC_ASSERT(isValid());
+  }
+
+  template<class C>
+	typename TourTree<C>::Entry TourTree<C>::pop() {
+	MATHIC_ASSERT(!empty());
+	Entry top = _tree[Node()]->entry;
+	if (_tree.lastLeaf().isRoot()) {
+	  _tree.popBack();
+	  _players.pop_back();
+	  MATHIC_ASSERT(isValid());
+	  return top;
+	}
+	Node parentPos = _tree.lastLeaf().parent();
+	Player* left = _tree[_tree.lastLeaf().prev()];
+	Player* right = _tree[_tree.lastLeaf()];
+
+	if (right == _tree[parentPos]) {
+	  // we want right to be the smaller entry so that it can be
+	  // removed without that having an impact further up the tree.
+	  std::swap(left->entry, right->entry);
+	  for (Node pos = parentPos; _tree[pos] == right; pos = pos.parent()) {
+		_tree[pos] = left;
+		if (pos.isRoot())
+		  break;
+	  }
+	}
+	Player* player = _tree[Node()];
+	player->entry = right->entry; // let right take the winner's place
+	MATHIC_ASSERT(right == &_players.back());
+	_players.pop_back(); // remove right
+	left->leaf = parentPos; // move up left
+	_tree.popBack();
+	_tree.popBack();
+	for (Node pos = player->leaf; !pos.isRoot();) {
+	  Player* opponent = _tree[pos.sibling()];
+	  typename C::CompareResult cmp =
+		_conf.compare(player->entry, opponent->entry);
+	  if (_conf.cmpLessThan(cmp))
+		player = opponent;
+	  pos = pos.parent();
+	  _tree[pos] = player;
+	}
+	MATHIC_ASSERT(isValid());
+	return top;
+  }
+
+  template<class C>
+	typename TourTree<C>::Entry TourTree<C>::top() const {
+	MATHIC_ASSERT(!empty());
+	return _tree[Node()]->entry;
+  }
+
+  template<class C>
+	void TourTree<C>::print(std::ostream& out) const {
+	out << getName() << ": {\n" << _tree << "}\n";
+  }
+
+  template<class C>
+	void TourTree<C>::reallocate() {
+	_tree.increaseCapacity();
+	const size_t newCapacity = _tree.capacity();
+	if (_players.empty())
+	  _players.reserve(newCapacity / 2 + 2);
+	else {
+	  Player* oldBegin = &_players.front();
+	  _players.reserve(newCapacity / 2 + 2);
+	  Player* newBegin = &_players.front();
+	  for (Node pos; pos <= _tree.lastLeaf(); ++pos)
+		_tree[pos] = newBegin + (_tree[pos] - oldBegin);
+	}
+	MATHIC_ASSERT(isValid());
+  }
+
+#ifdef MATHIC_DEBUG
+  template<class C>
+	bool TourTree<C>::isValid() const {
+	MATHIC_ASSERT(_tree.capacity() + 1 <= 2 * _players.capacity());
+	MATHIC_ASSERT((empty() && _players.empty()) ||
+		   (_tree.size() + 1 == 2 * _players.size()));
+	// _tree points into _players
+	for (Node pos; pos <= _tree.lastLeaf(); ++pos) {
+	  size_t index = _tree[pos] - &(_players.front());
+	  MATHIC_ASSERT(index < _players.size());
+	}
+
+	for (Node pos; pos <= _tree.lastLeaf(); ++pos) {
+	  if (pos.left() >= _tree.lastLeaf()) { // leaf or two children
+		MATHIC_ASSERT(pos.right() > _tree.lastLeaf()); // pos is a leaf
+		MATHIC_ASSERT(_tree[pos]->leaf == pos);
+	  } else {
+		MATHIC_ASSERT(pos.right() <= _tree.lastLeaf()); // pos has two children
+		// exactly one child wins
+		MATHIC_ASSERT(_tree[pos.left()] != _tree[pos.right()]);
+		MATHIC_ASSERT(_tree[pos] == _tree[pos.left()] ||
+			   _tree[pos] == _tree[pos.right()]);
+		MATHIC_ASSERT(!_conf.cmpLessThan(
+          _conf.compare(_tree[pos]->entry, _tree[pos.left()]->entry)));
+		MATHIC_ASSERT(!_conf.cmpLessThan(
+          _conf.compare(_tree[pos]->entry, _tree[pos.right()]->entry)));
+	  }
+	}
+	return true;
+  }
+#endif
+}
+
+#endif
diff --git a/src/mathic/display.cpp b/src/mathic/display.cpp
new file mode 100755
index 0000000..a149a40
--- /dev/null
+++ b/src/mathic/display.cpp
@@ -0,0 +1,145 @@
+#include "display.h"
+
+#include <cctype>
+#include <cstdio>
+
+namespace mathic {
+  namespace {
+    /** Automatically break lines at this width. */
+    static const size_t ConsoleWidth = 79;
+
+    /** Helper class for display(). */
+    class Printer {
+    public:
+      Printer(const std::string& msg, const std::string& prepend):
+        _pos(0), _lineSize(0), _msg(msg), _prefix(prepend) {
+
+	    std::string wordSpacePrefix;
+
+        while (_pos < _msg.size()) {
+          // We are always at the start of a line at this point.
+		  MATHIC_ASSERT(_lineSize == 0);
+          readIndentation();
+		  printRaw(_prefix);
+		  printRaw(_indentation);
+
+          if (_pos == _msg.size())
+            break;
+          if (_msg[_pos] == '\n') {
+            newLine();
+            ++_pos;
+            continue;
+          }
+
+		  wordSpacePrefix.clear();
+          while (_pos < _msg.size()) {
+            if (_msg[_pos] == '\n') {
+              ++_pos;
+              break;
+            }
+            if (isspace(_msg[_pos])) {
+			  wordSpacePrefix += _msg[_pos];
+			  ++_pos;
+              continue;
+            }
+            MATHIC_ASSERT(!isspace(_msg[_pos]));
+            MATHIC_ASSERT(_msg[_pos] != '\n');
+            MATHIC_ASSERT(_pos < _msg.size());
+
+            std::string word;
+            while (_pos < _msg.size() &&
+				   _msg[_pos] != '\n' &&
+				   !isspace(_msg[_pos])) {
+              word += _msg[_pos];
+              ++_pos;
+            }
+            MATHIC_ASSERT(!word.empty());
+            printWord(wordSpacePrefix, word);
+		    wordSpacePrefix.clear();
+          }
+
+		  newLine();
+        }
+      }
+
+    private:
+      void newLine() {
+        printRaw('\n');
+        _lineSize = 0;
+      }
+
+      void readIndentation() {
+        // Read whitespace at beginning of line.
+        _indentation.clear();
+        while (_pos < _msg.size() && _msg[_pos] != '\n' && isspace(_msg[_pos])) {
+          _indentation += _msg[_pos];
+          ++_pos;
+        }
+      }
+
+      void printWord(const std::string& wordSpacePrefix, const std::string& word) {
+        MATHIC_ASSERT(!word.empty());
+
+        // Note that this will print beyond the console width if word is
+        // the first thing we are printing on this line. That is because
+        // there then is no way to fit the word on one line.
+	    size_t wordAndPrefixSize = word.size() + wordSpacePrefix.size();
+	    if (_lineSize != 0 && _lineSize + wordAndPrefixSize  > ConsoleWidth) {
+		  // we skip space before word if inserting newline
+		  newLine();
+		  printRaw(_prefix);
+		  printRaw(_indentation);
+	    } else
+		  printRaw(wordSpacePrefix);
+        printRaw(word);
+      }
+
+      void printRaw(const std::string& word) {
+        fputs(word.c_str(), stderr);
+        _lineSize += word.size();
+      }
+
+      void printRaw(char c) {
+        fputc(c, stderr);
+        ++_lineSize;
+      }
+
+      size_t _pos;
+      size_t _lineSize;
+      const std::string& _msg;
+      const std::string& _prefix;
+      std::string _indentation;
+    };
+  }
+
+  void display(const std::string& msg, const std::string& prepend) {
+    Printer(msg, prepend);
+  }
+
+  void displayNote(const std::string& msg) {
+    display("NOTE: " + msg + "\n");
+  }
+
+  void displayError(const std::string& msg) {
+    display("ERROR: " + msg + "\n");
+  }
+
+  void displayInternalError(const std::string& msg) {
+    display("INTERNAL ERROR: " + msg + "\n");
+  }
+
+  void displayException(const std::exception& exception) {
+    try {
+      display(exception.what());
+    } catch (...) {
+      fputs("\n\n*** Error while printing error! ***\n", stderr);
+      fflush(stderr);
+      fputs("*** Retrying display of error using simpler display method. ***\n",
+            stderr);
+      fflush(stderr);
+      fputs(exception.what(), stderr);
+      fflush(stderr);
+      throw;
+    }
+  }
+}
diff --git a/src/mathic/display.h b/src/mathic/display.h
new file mode 100755
index 0000000..f086f4a
--- /dev/null
+++ b/src/mathic/display.h
@@ -0,0 +1,41 @@
+#ifndef MATHIC_DISPLAY_GUARD
+#define MATHIC_DISPLAY_GUARD
+
+#include <string>
+#include "stdinc.h"
+
+/** @file display.h
+
+ This file contains functions for printing strings to standard
+ error. They all perform automatic line breaking suitable for printing
+ to a console.
+*/
+
+namespace mathic {
+  /** Display msg to standard error with automatic line breaking. If a
+   automatically broken line begins with whitespace, that whitespace is
+   repeated in front of every line that is generated from breaking
+   it.
+
+   @param prepend Print this in front of every line that is printed.
+  */
+  void display(const std::string& msg, const std::string& prepend = "");
+
+  /** Display msg to standard error in a way that indicates that this is
+   something that the user should take note of but that is not an
+   error. */
+  void displayNote(const std::string& msg);
+
+  /** Display msg to standard error in a way that indicates that it is
+   an error. */
+  void displayError(const std::string& msg);
+
+  /** Display msg to standard in a way that indicates that it is an
+   internal error. */
+  void displayInternalError(const std::string& errorMsg);
+
+  /** Display the message of exception. */
+  void displayException(const std::exception& exception);
+}
+
+#endif
diff --git a/src/mathic/error.cpp b/src/mathic/error.cpp
new file mode 100755
index 0000000..3f388a8
--- /dev/null
+++ b/src/mathic/error.cpp
@@ -0,0 +1,22 @@
+#include "error.h"
+#include <sstream>
+
+namespace mathic {
+  void reportError(const std::string& errorMsg) {
+    throw MathicException("ERROR: " + errorMsg);
+  }
+
+  void reportInternalError(const std::string& errorMsg) {
+    throw InternalMathicException("INTERNAL ERROR: " + errorMsg);
+  }
+
+  void reportInternalError
+  (const std::string& errorMsg, const char* file, unsigned int lineNumber) {
+
+    std::ostringstream err;
+    err << errorMsg << '\n'
+        << "The internal error occured in file " << file
+        << " on line " << lineNumber << '.';
+    reportInternalError(err.str());
+  }
+}
diff --git a/src/mathic/error.h b/src/mathic/error.h
new file mode 100755
index 0000000..6c9353b
--- /dev/null
+++ b/src/mathic/error.h
@@ -0,0 +1,56 @@
+#ifndef MATHIC_ERROR_GUARD
+#define MATHIC_ERROR_GUARD
+
+#include <stdexcept>
+#include <string>
+
+namespace mathic {
+  /** This is the base of the Mathic exception hierarchy for exceptions
+   that can occur due to expected error conditions. */
+  class MathicException : public std::runtime_error {
+  public:
+    MathicException(const std::string& str): runtime_error(str) {}
+  };
+
+  /** This exception signals that a bug in Mathic has been detected. */
+  class InternalMathicException : public std::logic_error {
+   public:
+    InternalMathicException(const std::string& str): logic_error(str) {}
+  };
+
+  // The do {...} while (0) is to collect everything into a single
+  // statement that still requires a semicolon after it. The throw is to
+  // prevent spurious compiler warnings about a missing return
+  // statement.
+  #define MATHIC_INTERNAL_ERROR(msg) \
+    do { \
+      reportInternalError(msg, __FILE__, __LINE__); \
+      throw; \
+    } while (false)
+  #define INTERNAL_ERROR_UNIMPLEMENTED() \
+    INTERNAL_ERROR("Called function that has not been implemented.")
+
+  // These methods throw exceptions.
+  void reportError(const std::string& errorMsg);
+  void reportInternalError(const std::string& errorMsg);
+  void reportInternalError
+  (const std::string& errorMsg, const char* file, unsigned int lineNumber);
+
+  template<class Exception>
+  void throwError(const std::string& errorMsg) {
+    throw Exception("ERROR: " + errorMsg + '\n');
+  }
+
+
+  #define MATHIC_DEFINE_EXCEPTION(NAME) \
+    class NAME##Exception : public MathicException { \
+    public: \
+      NAME##Exception(const std::string& str): MathicException(str) {} \
+    }
+
+  MATHIC_DEFINE_EXCEPTION(UnknownName);
+  MATHIC_DEFINE_EXCEPTION(AmbiguousName);
+  MATHIC_DEFINE_EXCEPTION(Unsupported);
+}
+
+#endif
diff --git a/src/mathic/main.cpp b/src/mathic/main.cpp
new file mode 100755
index 0000000..dce1663
--- /dev/null
+++ b/src/mathic/main.cpp
@@ -0,0 +1,17 @@
+#include "divsim/divMain.h"
+#include "pqsim/pqMain.h"
+#include <string>
+#include <iostream>
+
+int main(int argc, const char** args) {
+  std::string name = args[0];
+  const size_t offset = name.find_last_of("/\\");
+  if (offset != std::string::npos)
+	name = name.substr(offset + 1);
+  if (name == "div")
+	return divMain();
+  else if (name == "pq")
+	return pqMain(argc, args);
+  std::cout << "Name of executable must be div or pq.\n";
+  return 1;
+}
diff --git a/src/mathic/stdinc.h b/src/mathic/stdinc.h
new file mode 100755
index 0000000..3311b15
--- /dev/null
+++ b/src/mathic/stdinc.h
@@ -0,0 +1,26 @@
+#ifndef MATHIC_STDINC_GUARD
+#define MATHIC_STDINC_GUARD
+
+#if (defined DEBUG || defined _DEBUG) && (!(defined MATCHIC_NDEBUG))
+#ifndef MATHIC_DEBUG
+#define MATHIC_DEBUG
+#endif
+#include <cassert>
+#define MATHIC_ASSERT(X) assert(X)
+#endif
+
+#ifndef MATHIC_ASSERT
+#define MATHIC_ASSERT(X)
+#endif
+
+namespace mathic {
+  static const unsigned long BitsPerByte = 8;
+}
+
+#ifndef MATHIC_NO_MIC_NAMESPACE
+namespace mic {
+  using namespace mathic;
+}
+#endif
+
+#endif
diff --git a/src/pqsim/GeobucketModel.h b/src/pqsim/GeobucketModel.h
new file mode 100755
index 0000000..fef45f7
--- /dev/null
+++ b/src/pqsim/GeobucketModel.h
@@ -0,0 +1,68 @@
+#ifndef GEOBUCKET_MODEL_GUARD
+#define GEOBUCKET_MODEL_GUARD
+
+#include "Model.h"
+#include "mathic/Geobucket.h"
+
+template<
+  bool TrackFront,
+  bool MinBucketBinarySearch,
+  bool Premerge,
+  bool CollectMax,
+  int BucketStorage,
+  size_t InsertFactor>
+class GeobucketModelBase {
+public:
+  GeobucketModelBase(size_t geoBase, size_t minBucketSize):
+    geoBase(geoBase), minBucketSize(minBucketSize) {}
+  size_t geoBase;
+  size_t minBucketSize;
+
+  static const bool trackFront = TrackFront;
+  static const bool minBucketBinarySearch = MinBucketBinarySearch;
+  static const bool premerge = Premerge;
+  static const bool collectMax = CollectMax;
+  static const mathic::GeobucketBucketStorage bucketStorage =
+    (mathic::GeobucketBucketStorage)BucketStorage;
+  static const size_t insertFactor = InsertFactor;
+};
+
+template<
+  bool OnSpans,
+  bool TrackFront,
+  bool MinBucketBinarySearch,
+  bool Deduplicate,
+  bool Premerge,
+  bool CollectMax,
+  int BucketStorage,
+  size_t InsertFactor = 1>
+class GeobucketModel :
+  public Model<
+    OnSpans,
+    Deduplicate,
+    false,
+    mathic::Geobucket,
+    GeobucketModelBase<
+      TrackFront,
+      MinBucketBinarySearch,
+      Premerge,
+      CollectMax,
+      BucketStorage,
+      InsertFactor> > {
+public:
+  GeobucketModel(size_t geoBase, size_t minBucketSize):
+    Model<
+    OnSpans,
+    Deduplicate,
+    false,
+    mathic::Geobucket,
+    GeobucketModelBase<
+      TrackFront,
+      MinBucketBinarySearch,
+      Premerge,
+      CollectMax,
+      BucketStorage,
+      InsertFactor> >(geoBase, minBucketSize) {}
+};
+
+#endif
diff --git a/src/pqsim/HeapModel.h b/src/pqsim/HeapModel.h
new file mode 100755
index 0000000..ad39299
--- /dev/null
+++ b/src/pqsim/HeapModel.h
@@ -0,0 +1,16 @@
+#ifndef HEAP_MODEL_GUARD
+#define HEAP_MODEL_GUARD
+
+#include "Model.h"
+#include "mathic/Heap.h"
+
+template<bool FastIndex>
+struct HeapModelBase {
+  static const bool fastIndex = FastIndex;
+};
+
+template<bool OnSpans, bool Deduplicate, bool FastIndex>
+class HeapModel : public Model<
+  OnSpans, Deduplicate, true, mathic::Heap, HeapModelBase<FastIndex> > {};
+
+#endif
diff --git a/src/pqsim/Item.cpp b/src/pqsim/Item.cpp
new file mode 100755
index 0000000..3ab11f3
--- /dev/null
+++ b/src/pqsim/Item.cpp
@@ -0,0 +1,9 @@
+#include "stdinc.h"
+#include "Item.h"
+
+void Item::print(std::ostream& out) const {
+  if (atEnd())
+	out << "invalid";
+  else
+	out << getValue();
+}
diff --git a/src/pqsim/Item.h b/src/pqsim/Item.h
new file mode 100755
index 0000000..1792ad7
--- /dev/null
+++ b/src/pqsim/Item.h
@@ -0,0 +1,110 @@
+#ifndef ITEM_GUARD
+#define ITEM_GUARD
+
+#include <ostream>
+#include <vector>
+
+typedef unsigned long Value;
+
+class Item;
+enum CompareResult {Less, Equal, Greater};
+CompareResult compare(Value a, Value b);
+CompareResult compare(const Item& a, const Item& b);
+
+class Item {
+ public:
+  Item(); // creates Item which is at end.
+  explicit Item(Value value);
+  Item(const Value* begin, const Value* end);
+
+  bool atEnd() const;
+  void toNext();
+  Item getNext() const;
+  size_t getLength() const;
+
+  const Value* begin() const {return _current;}
+  const Value* end() const {return _end;}
+
+  Value getValue() const;
+
+  void print(std::ostream& out) const;
+
+  bool operator==(const Item& item);
+
+ private:
+  Value _value;
+  const Value* _current;
+  const Value* _end;
+  Value dummy; // to make sizeof(Item) a power of two
+};
+
+template<bool> struct ItemOrValue{};
+template<> struct ItemOrValue<true> {typedef Item Entry;};
+template<> struct ItemOrValue<false> {typedef Value Entry;};
+
+inline CompareResult compare(Value a, Value b) {
+  if (a < b)
+    return Less;
+  if (b < a)
+    return Greater;
+  return Equal;
+}
+
+inline CompareResult compare(const Item& a, const Item& b) {
+  if (a.getValue() < b.getValue())
+    return Less;
+  if (b.getValue() < a.getValue())
+    return Greater;
+  return Equal;
+}
+
+
+inline std::ostream& operator<<(std::ostream& out, const Item& item) {
+  item.print(out);
+  return out;
+}
+
+inline bool Item::atEnd() const {
+  return _current == _end;
+}
+
+inline Value Item::getValue() const {
+  ASSERT(!atEnd());
+  return _value;
+}
+
+inline void Item::toNext() {
+  ASSERT(!atEnd());
+  ++_current;
+  if (!atEnd()) {
+	ASSERT(_value >= *_current);
+	_value = *_current;
+  }
+}
+
+inline Item Item::getNext() const {
+  ASSERT(!atEnd());
+  Item next(*this);
+  next.toNext();
+  return next;
+}
+
+inline bool Item::operator==(const Item& item) {
+  return getValue() == item.getValue();
+}
+
+inline Item::Item(): _value(-1), _current(0), _end(0) {}
+
+inline Item::Item(Value value): _value(value), _current(0), _end(0) {
+  ++_end;
+}
+
+inline Item::Item(const Value* begin, const Value* end):
+  _value(begin != end ? *begin : 0), _current(begin), _end(end) {}
+
+inline size_t Item::getLength() const {
+  return _end - _current;
+}
+
+
+#endif
diff --git a/src/pqsim/Model.cpp b/src/pqsim/Model.cpp
new file mode 100644
index 0000000..f9d51f0
--- /dev/null
+++ b/src/pqsim/Model.cpp
@@ -0,0 +1,2 @@
+#include "stdinc.h"
+#include "Model.h"
diff --git a/src/pqsim/Model.h b/src/pqsim/Model.h
new file mode 100644
index 0000000..12767d5
--- /dev/null
+++ b/src/pqsim/Model.h
@@ -0,0 +1,202 @@
+#ifndef MODEL_GUARD
+#define MODEL_GUARD
+
+#include "Item.h"
+#include <vector>
+
+namespace ModelHelper {
+  class NullConfigurationBase {};
+  template<bool> struct OnSpans {};
+  template<bool> struct UseDecreaseTop {};
+
+  template<class DS>
+  inline void push(DS& ds, const Value* begin, const Value* end, OnSpans<0>);
+  template<class DS>
+  inline void push(DS& ds, const Value* begin, const Value* end, OnSpans<1>);
+  template<class DS, bool DT>
+  inline Value pop(DS& ds, OnSpans<0>, UseDecreaseTop<DT>);
+
+  template<class DS>
+  inline Value pop(DS& ds, OnSpans<1>, UseDecreaseTop<0>);
+  template<class DS>
+  inline Value pop(DS& ds, OnSpans<1>, UseDecreaseTop<1>);
+
+  inline Value deduplicate
+   (std::vector<Value>& pending, const Value& a, const Value& b);
+  inline Item deduplicate
+   (std::vector<Item>& pending, const Item& a, const Item& b);
+}
+
+template<
+  bool OnSpans,
+  bool Deduplicate,
+  bool UseDecreaseTop,
+  template<class> class DataStructure,
+  class ConfigurationBase = ModelHelper::NullConfigurationBase>
+class Model {
+public:
+  Model(): _ds(Configuration()) {}
+  template<class A>
+  Model(const A& a): _ds(Configuration(a)) {}
+  template<class A, class B>
+  Model(const A& a, const B& b): _ds(Configuration(a, b)) {}
+
+  std::string getName() const {
+    return _ds.getName() +
+      (UseDecreaseTop ? " dectop" : "") +
+      (OnSpans ? " on spans" : " on elements");
+  }
+
+  void push(const Value* begin, const Value* end) {
+    ModelHelper::push(_ds, begin, end, ModelHelper::OnSpans<OnSpans>());
+  }
+
+  Value pop() {
+    return ModelHelper::pop(_ds,
+      ModelHelper::OnSpans<OnSpans>(),
+      ModelHelper::UseDecreaseTop<UseDecreaseTop>());
+  }
+
+  bool empty() const {return _ds.empty();}
+  void print(std::ostream& out) const {_ds.print(out);}
+
+  size_t getComparisons() const {
+    return _ds.getConfiguration().getComparisons();
+  }
+
+  size_t getMemoryUse() const {
+    return _ds.getMemoryUse();
+  }
+
+private:
+  class Configuration : public ConfigurationBase {
+  public:
+    typedef typename ItemOrValue<OnSpans>::Entry Entry;
+
+    Configuration(): _comparisons(0) {}
+    template<class A, class B>
+    Configuration(const A& a, const B& b):
+      ConfigurationBase(a, b), _comparisons(0) {}
+
+    typedef ::CompareResult CompareResult;
+    CompareResult compare(const Entry& a, const Entry& b) const {
+      ++_comparisons;
+      return ::compare(a, b);
+    }
+    bool cmpLessThan(CompareResult r) const {return r == Less;}
+    bool cmpEqual(CompareResult r) const {
+      ASSERT(supportDeduplication);
+      return r == Equal;
+    }
+    Entry deduplicate(const Entry& a, const Entry& b) const {
+      ASSERT(supportDeduplication);
+      return ModelHelper::deduplicate(_pending, a, b);
+    }
+
+    std::vector<Entry>& getPending() {return _pending;}
+    size_t getComparisons() const {return _comparisons;}
+
+    static const bool supportDeduplication = Deduplicate;
+
+  private:
+    mutable size_t _comparisons;
+    mutable std::vector<Entry> _pending;
+  };
+
+  DataStructure<Configuration> _ds;
+};
+
+namespace ModelHelper {
+  template<class DS>
+  inline void push(DS& ds, const Value* begin, const Value* end, OnSpans<0>) {
+    ds.push(begin, end);
+  }
+  template<class DS>
+  inline void push(DS& ds, const Value* begin, const Value* end, OnSpans<1>) {
+    ds.push(Item(begin, end));
+  }
+
+  template<class DS, bool DT>
+  inline Value pop(DS& ds, OnSpans<0>, UseDecreaseTop<DT>) {
+    Value topValue = ds.top();
+    do {
+      ds.pop();
+    } while (!ds.empty() && ds.top() == topValue);
+    return topValue;
+  }
+
+  template<class DS>
+  inline Value pop(DS& ds, OnSpans<1>, UseDecreaseTop<0>) {
+    ASSERT(DS::Configuration::supportDeduplication ||
+      ds.getConfiguration().getPending().empty());
+    Value topValue = ds.top().getValue();
+    do {
+      Item top = ds.pop();
+      top.toNext();
+      if (!top.atEnd())
+        ds.push(top);
+
+      if (DS::Configuration::supportDeduplication) {
+        std::vector<Item>& pending = ds.getConfiguration().getPending();
+        while (!pending.empty()) {
+          // this has to work even if push changes pending, which is
+          // why the loop is done like this.
+          Item item = pending.back();
+          pending.pop_back();
+          ds.push(item);
+        }
+      } else {
+        ASSERT(ds.getConfiguration().getPending().empty());
+      }
+    } while (!ds.empty() && ds.top().getValue() == topValue);
+    ASSERT(DS::Configuration::supportDeduplication ||
+      ds.getConfiguration().getPending().empty());
+    return topValue;
+  }
+
+  template<class DS>
+  inline Value pop(DS& ds, OnSpans<1>, UseDecreaseTop<1>) {
+    ASSERT(DS::Configuration::supportDeduplication ||
+      ds.getConfiguration().getPending().empty());
+    Value topValue = ds.top().getValue();
+    do {
+      Item top = ds.top();
+      top.toNext();
+      if (!top.atEnd())
+        ds.decreaseTop(top);
+      else
+        ds.pop();
+
+      ASSERT(DS::Configuration::supportDeduplication ||
+        ds.getConfiguration().getPending().empty());
+      if (DS::Configuration::supportDeduplication) {
+        std::vector<Item>& pending = ds.getConfiguration().getPending();
+        while (!pending.empty()) {
+          // this has to work even if push changes pending, which is
+          // why the loop is done like this.
+          Item item = pending.back();
+          pending.pop_back();
+          ds.push(item);
+        }
+      }
+    } while (!ds.empty() && ds.top().getValue() == topValue);
+    ASSERT(DS::Configuration::supportDeduplication ||
+      ds.getConfiguration().getPending().empty());
+    return topValue;
+  }
+
+  inline Value deduplicate
+   (std::vector<Value>& pending, const Value& a, const Value& b) {
+    return a;
+  }
+  inline Item deduplicate
+   (std::vector<Item>& pending, const Item& a, const Item& b) {
+    Item next = b;
+    next.toNext();
+    if (!next.atEnd())
+      pending.push_back(next);
+    return a;
+  }
+}
+
+#endif
diff --git a/src/pqsim/Simulator.cpp b/src/pqsim/Simulator.cpp
new file mode 100755
index 0000000..8ff8c10
--- /dev/null
+++ b/src/pqsim/Simulator.cpp
@@ -0,0 +1,326 @@
+#include "stdinc.h"
+#include "Simulator.h"
+
+#include "mathic/ColumnPrinter.h"
+#include <queue>
+#include <iterator>
+#include <algorithm>
+#include <set>
+
+namespace {
+  std::string commafy(unsigned long l) {
+    std::stringstream out;
+    out << l;
+    std::string str;
+    for (size_t i = 0; i < out.str().size(); ++i) {
+      str += out.str()[i];
+      if (i != out.str().size() - 1 && ((out.str().size() - i) % 3) == 1)
+        str += ',';
+    }
+    return str;
+  }
+
+  struct SimBuilder {
+    typedef Simulator::Event Event;
+    SimBuilder(bool popDuplicates,
+     std::vector<Value>& mem,
+     std::vector<Event>& events):
+     _popDuplicates(popDuplicates),
+     _mem(mem),
+     _events(events),
+     _pushCount(0),
+     _popCount(0),
+     _liveCountSum(0),
+     _pushSum(0),
+     _duplicateCount(0) {
+      _events.clear();
+      _mem.clear();
+    }
+
+    size_t getLiveCount() const {return _queue.size();}
+    size_t getPushCount() const {return _pushCount;}
+    size_t getPushSum() const {return _pushSum;}
+    size_t getPopCount() const {return _popCount;}
+    size_t getAvgLiveCount() const {
+      return _events.empty() ? 0 : _liveCountSum / _events.size();
+    }
+    size_t getDupliateCount() const {return _duplicateCount;}
+
+    // call nothing but addToPush and isInPush
+    // after calling beginPush until you call endPush.
+    void beginPush() {
+      ASSERT(_push.empty());
+      _liveCountSum += getLiveCount();
+      _events.push_back(Event());
+      _events.back().begin = _mem.size();
+    }
+    void addToPush(Value v) {
+      if (isLive(v))
+        ++_duplicateCount;
+      _push.insert(v); // for faster isInPush
+      _mem.push_back(v);
+      _queue.insert(v);
+    }
+    bool isInPush(Value v) {
+      return _push.find(v) != _push.end();
+    }
+    void endPush() {
+      Event& e = _events.back();
+      e.size = _mem.size() - e.begin;
+      std::vector<Value>::iterator begin = _mem.begin() + e.begin;
+      std::sort(begin, begin + e.size, std::greater<Value>());
+      ++_pushCount;
+      _pushSum += e.size;
+      _push.clear();
+    }
+
+    // todo: move clients to use begin...endpush
+    template<class It>
+    void push(It begin, It end) {
+      beginPush();
+      for (It it = begin; it != end; ++it)
+        addToPush(*it);
+      endPush();
+    }
+
+    Value pop() {
+      _liveCountSum += getLiveCount();
+      ++_popCount;
+      Value top = *_queue.rbegin();
+      do {
+        std::multiset<Value>::iterator last = _queue.end();
+        --last;
+        _queue.erase(last);
+      } while (_popDuplicates && !_queue.empty() && *_queue.rbegin() == top);
+      Event e;
+      e.popValue = top;
+      _events.push_back(e);
+      return top;
+    }
+
+    bool noLive() const {return _queue.empty();}
+
+    Value getRandomLive() const {
+      ASSERT(!noLive());
+      const size_t randomIndex = rand() % _queue.size();
+      std::multiset<Value>::const_iterator it = _queue.begin();
+      std::advance(it, randomIndex);
+      return *it;
+    }
+
+    bool isLive(Value v) const {
+      return _queue.find(v) != _queue.end();
+    }
+
+  private:
+    bool _popDuplicates;
+    std::multiset<Value> _queue;
+    std::multiset<Value> _push;
+    std::vector<Value>& _mem;
+    std::vector<Event>& _events;
+    size_t _pushCount;
+    size_t _popCount;
+    size_t _liveCountSum;
+    size_t _pushSum;
+    size_t _duplicateCount;
+  };
+
+  std::string makeDescription(SimBuilder& sim, size_t repeats,
+    std::string name) {
+    std::ostringstream out;
+    const size_t traffic = sim.getPushSum();
+    out << "*** Simulation \"" << name << "\"\n ";
+    out << sim.getPushCount() << " spans\n ";
+    out << (traffic / sim.getPushCount()) << " per span on average\n ";
+    out << sim.getAvgLiveCount() << " elements in queue on average\n ";
+    out << traffic << " entries popped in total.\n ";
+    out << (sim.getDupliateCount() * 100 / traffic) << "% duplicates\n ";
+    out << repeats << " repeats.\n";
+    return out.str();
+  }
+}
+
+void Simulator::dupSpans
+ (size_t pushSumGoal, size_t avgSpan, size_t avgLiveGoal,
+ size_t dupPercentage) {
+  SimBuilder sim(true, _mem, _events);
+  //size_t liveDeviation = 30;
+  size_t spanDeviation = 10;
+  ASSERT(avgSpan > 0);
+  if (avgSpan <= spanDeviation)
+    spanDeviation = avgSpan - 1;
+
+  while (sim.getPushSum() < pushSumGoal || !sim.noLive()) {
+    bool doPush = (sim.getAvgLiveCount() < avgLiveGoal);
+    if (sim.getPushSum() == pushSumGoal)
+      doPush = false;
+    else if (sim.noLive())
+      doPush = true;
+
+    if (doPush) {
+      const size_t size =
+        avgSpan - spanDeviation + rand() % (2 * spanDeviation);
+      sim.beginPush();
+      for (size_t i = 0; i < size; ++i) {
+        if (!sim.noLive() &&
+          static_cast<size_t>(rand() % 100) <= dupPercentage) {
+          Value v;
+          size_t tries = 0;
+          // if there are only fewer elements to duplicate than there
+          // are elements in the push, then this will never succeed.
+          // It will also take a long time to succeed even in some situations
+          // where it is possible. So we only try it for so long.
+          do {
+            v = (tries < 20 ? sim.getRandomLive() : rand());
+            ++tries;
+          } while (sim.isInPush(v));
+          sim.addToPush(v);
+        } else {
+          Value v;
+          do {
+            v = rand();
+          } while (sim.isInPush(v) || sim.isLive(v));
+          sim.addToPush(v);
+        }
+      }
+      sim.endPush();
+    } else
+      sim.pop();
+  }
+  _description = makeDescription(sim, _repeats, "dup spans");
+}
+
+void Simulator::orderSpans
+(size_t spanCount, size_t spanSize, size_t avgSize) {
+  SimBuilder sim(true, _mem, _events);
+  size_t insNum = (spanSize + spanCount * avgSize) * 3;
+  size_t deviation = (spanSize) / 2;
+  if (deviation == 0)
+    deviation = 1;
+  if (deviation > avgSize)
+    deviation = avgSize - 1;
+
+  while (sim.getLiveCount() > 0 || sim.getPushCount() < spanCount) {
+    const size_t live = sim.getLiveCount();
+    const size_t minLive = avgSize - deviation;
+    const size_t pushes = sim.getPushCount();
+    if (live == 0 || (pushes < spanCount && live < minLive)) {
+      sim.beginPush();
+      for (size_t i = 0; i < spanSize; ++i) {
+        Value v;
+        do {
+          v = insNum + rand() % (2*avgSize);
+        } while (sim.isInPush(v));
+        --insNum;
+        sim.addToPush(v);
+      }
+      sim.endPush();
+    } else
+      sim.pop();
+  }
+
+  _description = makeDescription(sim, _repeats, "ordered spans");
+}
+
+void Simulator::randomSpans(size_t spanCount, size_t spanSize, size_t initialSize) {
+  SimBuilder sim(false, _mem, _events);
+  while (sim.getLiveCount() || sim.getPushCount() < spanCount) {
+    bool doPop = rand() % (spanSize + 1) != 0;
+    if (sim.getLiveCount() == 0)
+      doPop = false;
+    if (sim.getPushCount() == spanCount)
+      doPop = true;
+
+    if (doPop)
+      sim.pop();
+    else {
+      size_t size = (sim.getPushCount() == 0 ? initialSize : spanSize);
+      sim.beginPush();
+      for (size_t i = 0; i < size; ++i) {
+        Value v;
+        do {
+          v = rand();
+        } while (sim.isInPush(v));
+        sim.addToPush(v);
+      }
+      sim.endPush();
+    }
+  }
+  _description = makeDescription(sim, _repeats, "random spans");
+}
+
+void Simulator::printEventSummary(std::ostream& out) const {
+  out << _description << std::endl;
+}
+
+void Simulator::printEvents(std::ostream& out) const {
+  out << "*** The " << _events.size() << " events are\n";
+  for (size_t i = 0; i < _events.size(); ++i)
+    print(_events[i], out);
+}
+
+void Simulator::print(const Event& e, std::ostream& out) const {
+  if (e.size == 0)
+    out << "Pop " << e.popValue << '\n';
+  else {
+    out << "Insert";
+    std::vector<Value>::const_iterator it = _mem.begin() + e.begin;
+    std::vector<Value>::const_iterator end = it + e.size;
+    for (; it != end; ++it)
+      out << ' ' << *it;
+    out << '\n';
+  }
+}
+
+void Simulator::printData(std::ostream& out) const {
+  std::vector<SimData> sorted(_data);
+  sort(sorted.begin(), sorted.end());
+  out << "*** Simulation outcome ***" << std::endl;
+  mic::ColumnPrinter pr;
+  pr.addColumn(true);
+  pr.addColumn(false, " ", "ms");
+  pr.addColumn(false, " ", "cmps");
+  pr.addColumn(false, " ", "kb");
+  for (std::vector<SimData>::const_iterator it = sorted.begin();
+    it != sorted.end(); ++it) {
+    pr[0] << it->name << '\n';
+    pr[1] << commafy(it->mseconds) << '\n';
+    pr[2] << commafy(it->comparisons) << '\n';
+    pr[3] << commafy(it->memoryUse / 1024) << '\n';
+  }
+  pr.print(out);
+}
+
+void Simulator::setupEvents() {
+  size_t activeSum = 0;
+  std::priority_queue<int> queue;
+  typedef std::vector<Event>::iterator Iterator;
+  Iterator end = _events.end();
+  for (Iterator it = _events.begin(); it != end; ++it) {
+    Event& e = *it;
+    activeSum += queue.size();
+    if (e.size == 0) {
+      e.popValue = queue.top();
+      queue.pop();
+    } else {
+      Value* begin = &(_mem[e.begin]);
+      Value* end = begin + e.size;
+      sort(begin, end, std::greater<Value>());
+      for (const Value* v = begin; v != end; ++v)
+        queue.push(*v);
+    }
+  }
+  _avgSize = activeSum / _events.size();
+}
+
+void Simulator::SimData::print(std::ostream& out) {
+  out << name
+    << " " << commafy(mseconds) << " ms"
+    << " " << commafy(comparisons) << " cmps"
+    << " " << commafy(memoryUse / 1024) << " kb"
+    << '\n';
+}
+
+bool Simulator::SimData::operator<(const SimData& sd) const {
+  return mseconds < sd.mseconds;
+}
diff --git a/src/pqsim/Simulator.h b/src/pqsim/Simulator.h
new file mode 100755
index 0000000..e11a610
--- /dev/null
+++ b/src/pqsim/Simulator.h
@@ -0,0 +1,103 @@
+#ifndef SIMULATOR_GUARD
+#define SIMULATOR_GUARD
+
+#include "Item.h"
+#include <queue>
+#include <vector>
+#include <ctime>
+#include <algorithm>
+#include <sstream>
+#include <iostream>
+#include <string>
+
+class Simulator {
+public:
+  Simulator(size_t repeats): _repeats(repeats), _simType("none") {}
+
+  void dupSpans(size_t pushSumGoal, size_t avgSpan, size_t avgLiveGoal,
+    size_t dupPercentage);
+  void orderSpans(size_t spanCount, size_t spanSize, size_t avgSize);
+  void randomSpans(size_t spanCount, size_t spanSize, size_t initialSize);
+
+  template<class PQueue>
+  void run(PQueue& pq, bool printData = true, bool printStates = false);
+
+  void printEventSummary(std::ostream& out) const;
+  void printEvents(std::ostream& out) const;
+  void printData(std::ostream& out) const;
+
+  struct Event {
+    Event(): size(0) {}
+    size_t begin;
+    size_t size; // insert _mem( [begin, begin + size) ) if size > 0.
+	Value popValue; // pop this value if size == 0
+  };
+
+private:
+  struct SimData {
+    std::string name;
+    unsigned long comparisons;
+    unsigned long mseconds;
+    size_t memoryUse;
+    bool operator<(const SimData& sd) const;
+    void print(std::ostream& out);
+  };
+
+  void setupEvents();
+  void print(const Event& e, std::ostream& out) const;
+
+  std::vector<Event> _events;
+  std::vector<SimData> _data;
+  std::vector<Value> _mem;
+  size_t _spanCount;
+  size_t _spanSize;
+  size_t _avgSize;
+  size_t _repeats;
+  std::string _simType;
+  std::string _description;
+};
+
+template<class PQueue>
+void Simulator::run(PQueue& pqueue, bool printData, bool printStates) {
+  clock_t timeBegin = clock();
+  std::vector<Event>::const_iterator end = _events.end();
+  for (size_t turn = 0; turn < _repeats; ++turn) {
+    typedef std::vector<Event>::const_iterator CIterator;
+    CIterator end = _events.end();
+    for (CIterator it = _events.begin(); it != end; ++it) {
+      const Event& e = *it;
+      if (printStates) {
+        std::cerr << "*** The next event is\n";
+        print(e, std::cerr);
+        std::cerr << "*** The state of " << pqueue.getName()
+          << " (" << pqueue.getComparisons() << " comparisons) is\n";
+        pqueue.print(std::cerr);
+        std::cerr << '\n';
+      }
+      if (e.size == 0) {
+        Value item = pqueue.pop();
+        if (!(item == e.popValue)) {
+          std::cerr << "ERROR: queue " << pqueue.getName()
+            << " gave incorrect value " << item << std::endl;
+          exit(1);
+        }
+      } else {
+        const Value* begin = &_mem[e.begin];
+        pqueue.push(begin, begin + e.size);
+      }
+    }
+  }
+  clock_t timeEnd = clock();
+
+  SimData data;
+  data.name = pqueue.getName();
+  data.memoryUse = pqueue.getMemoryUse();
+  data.comparisons = pqueue.getComparisons();
+  data.mseconds = (unsigned long)
+    ((double(timeEnd) - timeBegin) * 1000) / CLOCKS_PER_SEC;
+  _data.push_back(data);
+  if (printData)
+    data.print(std::cerr);
+}
+
+#endif
diff --git a/src/pqsim/StlSetModel.h b/src/pqsim/StlSetModel.h
new file mode 100755
index 0000000..24fbdc2
--- /dev/null
+++ b/src/pqsim/StlSetModel.h
@@ -0,0 +1,10 @@
+#ifndef STL_SET_MODEL_GUARD
+#define STL_SET_MODEL_GUARD
+
+#include "Model.h"
+#include "mathic/StlSet.h"
+
+template<bool OnSpans>
+class StlSetModel : public Model<OnSpans, false, false, mathic::StlSet> {};
+
+#endif
diff --git a/src/pqsim/TourTreeModel.h b/src/pqsim/TourTreeModel.h
new file mode 100755
index 0000000..109a913
--- /dev/null
+++ b/src/pqsim/TourTreeModel.h
@@ -0,0 +1,16 @@
+#ifndef TOUR_TREE_MODEL_GUARD
+#define TOUR_TREE_MODEL_GUARD
+
+#include "mathic/TourTree.h"
+#include "Model.h"
+
+template<bool FastIndex>
+struct TourTreeModelBase {
+  static const bool fastIndex = FastIndex;
+};
+
+template<bool OnSpans, bool FastIndex>
+class TourTreeModel : public Model<
+  OnSpans, false, true, mathic::TourTree, TourTreeModelBase<FastIndex> > {};
+
+#endif
diff --git a/src/pqsim/pqMain.cpp b/src/pqsim/pqMain.cpp
new file mode 100755
index 0000000..a211ddd
--- /dev/null
+++ b/src/pqsim/pqMain.cpp
@@ -0,0 +1,65 @@
+#include "stdinc.h"
+
+#include "StlSetModel.h"
+#include "HeapModel.h"
+#include "GeobucketModel.h"
+#include "TourTreeModel.h"
+#include "Simulator.h"
+#include <iostream>
+#include <ctime>
+
+namespace {
+  size_t toInt(const char* str) {
+	std::istringstream in(str);
+	size_t i;
+	in >> i;
+	return i;
+  }
+}
+
+int main(int argc, const char** args) {
+  srand(static_cast<unsigned int>(time(0)));
+  srand(0);
+  if (argc < 4) {
+	std::cerr << "usage: elements span-length target-avg-size\n";
+	return 0;
+  }
+  size_t elements = toInt(args[1]);
+  size_t spanSize = toInt(args[2]);
+  size_t avgOrInitialSize = toInt(args[3]);
+  size_t dups = 30;
+  if (argc >= 5)
+    dups = toInt(args[4]);
+
+  size_t repeats = 500;
+  IF_DEBUG(repeats = 2;);
+
+  std::cerr << "Generating simulation..." << std::endl;
+  Simulator sim(repeats);
+  //sim.orderSpans(elements / spanSize, spanSize, avgOrInitialSize);
+  //sim.randomSpans(elements / spanSize, spanSize, avgOrInitialSize);
+  sim.dupSpans(elements, spanSize, avgOrInitialSize, dups);
+  sim.printEventSummary(std::cerr);
+  //sim.printEvents(std::cerr);
+  std::cerr << '\n' << std::endl;
+
+#ifdef DEBUG
+  {TourTreeModel<0,0> x; sim.run(x);}
+  {HeapModel<0,0,0> x; sim.run(x);}
+#else
+  {TourTreeModel<1,0> x; sim.run(x);}
+  {TourTreeModel<0,0> x; sim.run(x);}
+  {GeobucketModel<0,0,0,0,0,0,0> x(4, 32); sim.run(x);}
+  {GeobucketModel<0,0,0,0,0,0,0> x(2, 32); sim.run(x);}
+  {GeobucketModel<0,0,0,1,0,0,0> x(4, 32); sim.run(x);}
+  {StlSetModel<1> x; sim.run(x);}
+  {StlSetModel<0> x; sim.run(x);}
+  {HeapModel<0,0,0> x; sim.run(x);}
+  {HeapModel<1,0,0> x; sim.run(x);}
+  {HeapModel<0,1,0> x; sim.run(x);}
+  {HeapModel<1,1,0> x; sim.run(x);}
+#endif
+
+  sim.printData(std::cout);
+  return 0;
+}
diff --git a/src/pqsim/pqMain.h b/src/pqsim/pqMain.h
new file mode 100755
index 0000000..57ec9e8
--- /dev/null
+++ b/src/pqsim/pqMain.h
@@ -0,0 +1,6 @@
+#ifndef PQ_MAIN
+#define PQ_MAIN
+
+int main(int argc, const char** args);
+
+#endif
diff --git a/src/pqsim/stdinc.h b/src/pqsim/stdinc.h
new file mode 100755
index 0000000..da6f62a
--- /dev/null
+++ b/src/pqsim/stdinc.h
@@ -0,0 +1,48 @@
+#ifdef STDINC_GUARD
+#error stdinc.h included twice
+#endif
+#define STDINC_GUARD
+
+#ifdef _MSC_VER // For Microsoft Compiler in Visual Studio C++.
+#pragma warning (push, 1) // Reduce warning level for GMP headers.
+#endif
+
+#ifndef _MSC_VER
+#define NO_INLINE
+#endif
+
+#ifdef _MSC_VER // For Microsoft Compiler in Visual Studio C++.
+#define NO_INLINE __declspec(noinline)
+#pragma warning (pop) // Go back to previous warning level.
+#pragma warning (disable: 4996) // std::copy is flagged as dangerous.
+#pragma warning (disable: 4290) // VC++ ignores throw () specification.
+#pragma warning (disable: 4127) // Warns about using "while (true)".
+#pragma warning (disable: 4100) // Warns about unused parameters.
+#pragma warning (disable: 4800) // Warns on int to bool conversion.
+#pragma warning (disable: 4146) // Warns on unary minus on unsigned (bit trick)
+
+// This warning warns about using the this pointer in base member
+// initializer lists. This is a pretty good warning as that can
+// obviously easily go wrong, but it is pretty useful to do as well,
+// so the warning is turned off.
+#pragma warning (disable: 4355)
+
+#ifdef _DEBUG
+#define DEBUG
+#endif
+
+#endif
+
+#include <cstddef>
+#include <memory>
+
+#ifdef DEBUG
+#include <iostream> // Useful for debugging.
+#define PRINT
+#include <cassert>
+#define ASSERT(X) assert(X);
+#define IF_DEBUG(X) X
+#else
+#define ASSERT(X)
+#define IF_DEBUG(X)
+#endif
diff --git a/src/test/DivFinder.cpp b/src/test/DivFinder.cpp
new file mode 100755
index 0000000..ca920ae
--- /dev/null
+++ b/src/test/DivFinder.cpp
@@ -0,0 +1,10 @@
+#include "divsim/stdinc.h"
+#include "mathic/KDTree.h"
+#include <gtest/gtest.h>
+
+#include "mathic/DivList.h"
+#include "divsim/KDTreeModel.h"
+
+TEST(DivFinder, NoOp) {
+  KDTreeModel<1,1,1,1,1> model(1, 1, 0, 0, 1.0, 1000);
+};
diff --git a/src/test/gtestInclude.cpp b/src/test/gtestInclude.cpp
new file mode 100755
index 0000000..a14f48f
--- /dev/null
+++ b/src/test/gtestInclude.cpp
@@ -0,0 +1,10 @@
+// Includes a file from gtest that pulls in all of the implementation
+// of gtest. The gtest docs recommend building gtest individually for
+// each program rather than using an installed gtest and this is as
+// easy a way of doing it as any. Especially because it guarantees that
+// the compiler flags are the same, which is the whole point of the
+// recommendation to build gtest for each program.
+
+// the .. goes back from the include/ directory of gtest so we can
+// enter the src directory.
+#include <../src/gtest-all.cc>
diff --git a/src/test/testMain.cpp b/src/test/testMain.cpp
new file mode 100755
index 0000000..4d820af
--- /dev/null
+++ b/src/test/testMain.cpp
@@ -0,0 +1,6 @@
+#include <gtest/gtest.h>
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/mathic.git



More information about the debian-science-commits mailing list