├── .gitignore
├── Makefile.am
├── README.md
├── autogen.sh
├── build
├── autotools
│ ├── .gitignore
│ ├── m4
│ │ └── .gitignore
│ └── mathic.pc.in
└── vs12
│ ├── mathic-lib
│ ├── mathic-lib.vcxproj
│ └── mathic-lib.vcxproj.filters
│ ├── mathic-test
│ ├── mathic-test.vcxproj
│ └── mathic-test.vcxproj.filters
│ └── mathic.sln
├── configure.ac
├── fixspace
├── include
└── mathic
│ ├── mathic.cpp
│ └── mathic.h
├── libs
└── .gitignore
├── replace
└── src
├── divsim
├── DivListModel.h
├── KDTreeModel.h
├── Monomial.h
├── Simulation.cpp
├── Simulation.h
├── divMain.cpp
├── divMain.h
└── stdinc.h
├── mathic.cpp
├── mathic.h
├── mathic
├── Action.cpp
├── Action.h
├── BinaryKDTree.h
├── BitTriangle.cpp
├── BitTriangle.h
├── BoolParameter.cpp
├── BoolParameter.h
├── CliParameter.cpp
├── CliParameter.h
├── CliParser.cpp
├── CliParser.h
├── ColumnPrinter.cpp
├── ColumnPrinter.h
├── ComTree.h
├── Comparer.h
├── DivFinder.h
├── DivList.h
├── DivMask.cpp
├── DivMask.h
├── GeoFront.h
├── Geobucket.h
├── HashTable.h
├── Heap.h
├── HelpAction.cpp
├── HelpAction.h
├── IntegerParameter.cpp
├── IntegerParameter.h
├── KDEntryArray.h
├── KDTree.h
├── NameFactory.h
├── PackedKDTree.h
├── PairQueue.h
├── StlSet.h
├── StringParameter.cpp
├── StringParameter.h
├── Timer.cpp
├── Timer.h
├── TourTree.h
├── display.cpp
├── display.h
├── error.cpp
├── error.h
├── main.cpp
└── stdinc.h
├── pqsim
├── GeobucketModel.h
├── HeapModel.h
├── Item.cpp
├── Item.h
├── Model.cpp
├── Model.h
├── Simulator.cpp
├── Simulator.h
├── StlSetModel.h
├── TourTreeModel.h
├── pqMain.cpp
├── pqMain.h
└── stdinc.h
└── test
├── BitTriangle.cpp
├── DivFinder.cpp
├── HashTable.cpp
├── PairQueue.cpp
├── gtestInclude.cpp
└── testMain.cpp
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 |
6 | # Compiled Dynamic libraries
7 | *.so
8 |
9 | # Compiled Static libraries
10 | *.lai
11 | *.la
12 | *.a
13 |
14 | # Emacs backup files
15 | \#*\#
16 | *~
17 |
18 | # Autotools generated files
19 | config.log
20 | config.status
21 | libtool
22 | .deps/
23 | .dirstamp
24 | aclocal.m4
25 | autom4te.cache/
26 | Makefile.in
27 | Makefile
28 | configure
29 | .libs/
30 |
31 | # Visual studio generated files
32 | *.suo
33 | *.sdf
34 | *.opensdf
35 | *.vcxproj.user
36 | output/
37 |
38 | # Configure build targets
39 | deb/
40 | debnoass/
41 | pro/
42 | rel/
43 | relass/
44 |
45 |
--------------------------------------------------------------------------------
/Makefile.am:
--------------------------------------------------------------------------------
1 | # options passed to aclocal, which is a tool for making macroes visible to
2 | # autoconf. We use -I to tell aclocal where we put the local macros.
3 | ACLOCAL_AMFLAGS = -I build/autotools/m4
4 |
5 | # Options passed to the C and C++ PreProcessor (CPP) and compiler
6 | AM_CPPFLAGS = -I${top_srcdir}/
7 | libmathic_la_CPPFLAGS = $(DEPS_CFLAGS)
8 |
9 | # tell Libtool what the name of the library is.
10 | lib_LTLIBRARIES = libmathic.la
11 |
12 | # set the C++ compiler to include src/
13 | AM_CXXFLAGS=-I$(top_srcdir)/src/ -std=gnu++0x
14 |
15 | # libraries that are needed by this library
16 | libmathic_la_LIBADD= $(DEPS_LIBS)
17 |
18 | # the sources that are built to make libmathic.
19 | libmathic_la_SOURCES = src/mathic/Timer.cpp \
20 | src/mathic/ColumnPrinter.cpp src/mathic/DivMask.cpp \
21 | src/mathic/Action.cpp src/mathic/BoolParameter.cpp \
22 | src/mathic/CliParameter.cpp src/mathic/CliParser.cpp \
23 | src/mathic/error.cpp src/mathic/HelpAction.cpp \
24 | src/mathic/IntegerParameter.cpp src/mathic/StringParameter.cpp \
25 | src/mathic/display.cpp src/mathic/BitTriangle.cpp src/mathic.cpp
26 |
27 | # The headers that libmathic installs.
28 | # Normally, automake strips the path from the files when installing them,
29 | # so src/mathic/x.h gets installed as just x.h.
30 | mathicA_include_HEADERS = src/mathic.h
31 | mathicA_includedir = $(includedir)
32 | # install remaining headers into subdirectory of the include dir
33 | mathicB_includedir = \
34 | $(includedir)/mathic
35 | mathicB_include_HEADERS = src/mathic/Action.h src/mathic/Geobucket.h \
36 | src/mathic/BinaryKDTree.h src/mathic/GeoFront.h \
37 | src/mathic/BoolParameter.h src/mathic/Heap.h \
38 | src/mathic/CliParameter.h src/mathic/HelpAction.h \
39 | src/mathic/CliParser.h src/mathic/IntegerParameter.h \
40 | src/mathic/ColumnPrinter.h src/mathic/KDEntryArray.h \
41 | src/mathic/Comparer.h src/mathic/KDTree.h src/mathic/ComTree.h \
42 | src/mathic/NameFactory.h src/mathic/display.h \
43 | src/mathic/PackedKDTree.h src/mathic/DivFinder.h src/mathic/stdinc.h \
44 | src/mathic/DivList.h src/mathic/StlSet.h src/mathic/DivMask.h \
45 | src/mathic/StringParameter.h \
46 | src/mathic/Timer.h src/mathic/error.h src/mathic/TourTree.h \
47 | src/mathic/BitTriangle.h \
48 | src/mathic/PairQueue.h \
49 | src/mathic/HashTable.h
50 |
51 | pkgconfigdir = $(libdir)/pkgconfig
52 | pkgconfig_DATA = build/autotools/mathic.pc
53 |
54 | # When making a distribution file, Automake knows to include all files
55 | # that are necessary to build the project. EXTRA_DIST specifies files
56 | # to include beyond those used in the build process.
57 | EXTRA_DIST = autogen.sh
58 |
59 | # tell automake what programs are there that are not built automatically
60 | EXTRA_PROGRAMS = pqsim divsim
61 |
62 | # set up the divisor query simulation. Listing the headers in sources
63 | # ensure that those files are included in distributions.
64 | divsim_CPPFLAGS = $(DEPS_CFLAGS)
65 | divsim_SOURCES = src/divsim/divMain.cpp src/divsim/Simulation.cpp \
66 | src/divsim/DivListModel.h src/divsim/KDTreeModel.h \
67 | src/divsim/Simulation.h src/divsim/divMain.h src/divsim/Monomial.h \
68 | src/divsim/stdinc.h
69 | divsim_LDADD = $(top_builddir)/libmathic.la
70 |
71 | # set up the priority queue simulation. Listing the headers in sources
72 | # ensure that those files are included in distributions.
73 | pqsim_CPPFLAGS = $(DEPS_CFLAGS)
74 | pqsim_SOURCES = src/pqsim/Item.cpp src/pqsim/Model.cpp \
75 | src/pqsim/pqMain.cpp src/pqsim/Simulator.cpp \
76 | src/pqsim/GeobucketModel.h src/pqsim/Model.h src/pqsim/stdinc.h \
77 | src/pqsim/HeapModel.h src/pqsim/pqMain.h src/pqsim/StlSetModel.h \
78 | src/pqsim/Item.h src/pqsim/Simulator.h src/pqsim/TourTreeModel.h
79 | pqsim_LDADD = $(top_builddir)/libmathic.la
80 |
81 |
82 | # set up tests to run on "make check"
83 | if with_gtest
84 |
85 | TESTS=unittest
86 | check_PROGRAMS=$(TESTS)
87 |
88 | unittest_CPPFLAGS = $(DEPS_CFLAGS)
89 | unittest_CXXFLAGS = -I$(top_srcdir)/src/ -std=gnu++0x
90 | unittest_LDADD = $(DEPS_LIBS)
91 | unittest_LDFLAGS= $(top_builddir)/libmathic.la
92 |
93 | test_LIBS=
94 | unittest_SOURCES=src/test/DivFinder.cpp src/test/gtestInclude.cpp \
95 | src/test/testMain.cpp src/test/BitTriangle.cpp \
96 | src/test/PairQueue.cpp \
97 | src/test/HashTable.cpp
98 |
99 | else
100 |
101 | check:
102 | @echo
103 | @echo "Configure did not locate gtest, so unittests cannot be run."
104 |
105 | endif
106 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | mathic
2 | ======
3 |
4 | Mathic is a C++ library of fast data structures designed for use in
5 | Groebner basis computation. This includes data structures for ordering
6 | S-pairs, performing divisor queries and ordering polynomial terms
7 | during polynomial reduction.
8 |
9 | With Mathic you get to use highly optimized code with little effort so
10 | that you can focus more of your time on whatever part of your Groebner
11 | basis implementation that you are interested in. The data structures
12 | use templates to allow you to use them with whatever representation of
13 | monomials/terms and coefficients that your code uses. In fact the only
14 | places where Mathic defines its own monomials/terms is in the test
15 | code and example code. Currently only dense representations of
16 | terms/monomials are suitable since Mathic will frequently ask "what is
17 | the exponent of variable number x in this term/monomial?".
18 |
19 | The paper "Practical Grobner Basis Computation" describes the data
20 | structures from a high level. It was presented at ISSAC 2012 and is
21 | available at http://arxiv.org/abs/1206.6940
22 |
--------------------------------------------------------------------------------
/autogen.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | srcdir="`dirname '$0'`"
3 |
4 | autoreconf --verbose --install --force $srcdir
5 |
--------------------------------------------------------------------------------
/build/autotools/.gitignore:
--------------------------------------------------------------------------------
1 | # Autotools generated files
2 | ar-lib
3 | config.guess
4 | config.sub
5 | depcomp
6 | install-sh
7 | ltmain.sh
8 | mathic-*.pc
9 | missing
10 |
--------------------------------------------------------------------------------
/build/autotools/m4/.gitignore:
--------------------------------------------------------------------------------
1 | # Autotools generated files
2 | libtool.m4
3 | ltoptions.m4
4 | ltsugar.m4
5 | ltversion.m4
6 | lt~obsolete.m4
7 |
--------------------------------------------------------------------------------
/build/autotools/mathic.pc.in:
--------------------------------------------------------------------------------
1 | prefix=@prefix@
2 | exec_prefix=@exec_prefix@
3 | libdir=@libdir@
4 | includedir=@includedir@
5 |
6 | Name: mathic
7 | Description: C++ library of symbolic algebra data structures for use in Groebner basis computation.
8 | URL: https://github.com/broune/mathic
9 | Requires: memtailor
10 | Version: @PACKAGE_VERSION@
11 | Libs: -L${libdir} -lmathic
12 | Cflags: -I${includedir}/
13 |
--------------------------------------------------------------------------------
/build/vs12/mathic-lib/mathic-lib.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 | Source Files
23 |
24 |
25 | Source Files
26 |
27 |
28 | Source Files
29 |
30 |
31 | Source Files
32 |
33 |
34 | Source Files
35 |
36 |
37 | Source Files
38 |
39 |
40 | Source Files
41 |
42 |
43 | Source Files
44 |
45 |
46 | Source Files
47 |
48 |
49 | Source Files
50 |
51 |
52 | Source Files
53 |
54 |
55 | Source Files
56 |
57 |
58 |
59 |
60 | Header Files
61 |
62 |
63 | Header Files
64 |
65 |
66 | Header Files
67 |
68 |
69 | Header Files
70 |
71 |
72 | Header Files
73 |
74 |
75 | Header Files
76 |
77 |
78 | Header Files
79 |
80 |
81 | Header Files
82 |
83 |
84 | Header Files
85 |
86 |
87 | Header Files
88 |
89 |
90 | Header Files
91 |
92 |
93 | Header Files
94 |
95 |
96 | Header Files
97 |
98 |
99 | Header Files
100 |
101 |
102 | Header Files
103 |
104 |
105 | Header Files
106 |
107 |
108 | Header Files
109 |
110 |
111 | Header Files
112 |
113 |
114 | Header Files
115 |
116 |
117 | Header Files
118 |
119 |
120 | Header Files
121 |
122 |
123 | Header Files
124 |
125 |
126 | Header Files
127 |
128 |
129 | Header Files
130 |
131 |
132 | Header Files
133 |
134 |
135 | Header Files
136 |
137 |
138 | Header Files
139 |
140 |
141 | Header Files
142 |
143 |
144 | Header Files
145 |
146 |
147 | Header Files
148 |
149 |
150 |
--------------------------------------------------------------------------------
/build/vs12/mathic-test/mathic-test.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 | Source Files
23 |
24 |
25 | Source Files
26 |
27 |
28 | Source Files
29 |
30 |
31 | Source Files
32 |
33 |
34 | Source Files
35 |
36 |
37 |
--------------------------------------------------------------------------------
/build/vs12/mathic.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2012
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mathic-lib", "mathic-lib\mathic-lib.vcxproj", "{BEBD36F1-A124-4C01-8E67-3208D4472661}"
5 | EndProject
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mathic-test", "mathic-test\mathic-test.vcxproj", "{9B09A868-B169-43E8-AFF9-D2F12657ABCF}"
7 | ProjectSection(ProjectDependencies) = postProject
8 | {BEBD36F1-A124-4C01-8E67-3208D4472661} = {BEBD36F1-A124-4C01-8E67-3208D4472661}
9 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551} = {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}
10 | EndProjectSection
11 | EndProject
12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "memtailor-lib", "..\..\..\memtailor\build\vs12\memtailor-lib\memtailor-lib.vcxproj", "{534C44F8-BA0A-4AF0-95F1-260CA8EF3551}"
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Win32 = Debug|Win32
17 | Debug|x64 = Debug|x64
18 | Debug-NoAssert|Win32 = Debug-NoAssert|Win32
19 | Debug-NoAssert|x64 = Debug-NoAssert|x64
20 | Release|Win32 = Release|Win32
21 | Release|x64 = Release|x64
22 | Release-Assert|Win32 = Release-Assert|Win32
23 | Release-Assert|x64 = Release-Assert|x64
24 | WarningAsError|Win32 = WarningAsError|Win32
25 | WarningAsError|x64 = WarningAsError|x64
26 | EndGlobalSection
27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
28 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.Debug|Win32.ActiveCfg = Debug|Win32
29 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.Debug|Win32.Build.0 = Debug|Win32
30 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.Debug|x64.ActiveCfg = Debug|x64
31 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.Debug|x64.Build.0 = Debug|x64
32 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.Debug-NoAssert|Win32.ActiveCfg = Debug-NoAssert|Win32
33 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.Debug-NoAssert|Win32.Build.0 = Debug-NoAssert|Win32
34 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.Debug-NoAssert|x64.ActiveCfg = Debug-NoAssert|x64
35 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.Debug-NoAssert|x64.Build.0 = Debug-NoAssert|x64
36 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.Release|Win32.ActiveCfg = Release|Win32
37 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.Release|Win32.Build.0 = Release|Win32
38 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.Release|x64.ActiveCfg = Release|x64
39 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.Release|x64.Build.0 = Release|x64
40 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.Release-Assert|Win32.ActiveCfg = Release-Assert|Win32
41 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.Release-Assert|Win32.Build.0 = Release-Assert|Win32
42 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.Release-Assert|x64.ActiveCfg = Release-Assert|x64
43 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.Release-Assert|x64.Build.0 = Release-Assert|x64
44 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.WarningAsError|Win32.ActiveCfg = WarningAsError|Win32
45 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.WarningAsError|Win32.Build.0 = WarningAsError|Win32
46 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.WarningAsError|x64.ActiveCfg = WarningAsError|x64
47 | {BEBD36F1-A124-4C01-8E67-3208D4472661}.WarningAsError|x64.Build.0 = WarningAsError|x64
48 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.Debug|Win32.ActiveCfg = Debug|Win32
49 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.Debug|Win32.Build.0 = Debug|Win32
50 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.Debug|x64.ActiveCfg = Debug|x64
51 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.Debug|x64.Build.0 = Debug|x64
52 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.Debug-NoAssert|Win32.ActiveCfg = Debug-NoAssert|Win32
53 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.Debug-NoAssert|Win32.Build.0 = Debug-NoAssert|Win32
54 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.Debug-NoAssert|x64.ActiveCfg = Debug-NoAssert|x64
55 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.Debug-NoAssert|x64.Build.0 = Debug-NoAssert|x64
56 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.Release|Win32.ActiveCfg = Release|Win32
57 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.Release|Win32.Build.0 = Release|Win32
58 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.Release|x64.ActiveCfg = Release|x64
59 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.Release|x64.Build.0 = Release|x64
60 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.Release-Assert|Win32.ActiveCfg = Release-Assert|Win32
61 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.Release-Assert|Win32.Build.0 = Release-Assert|Win32
62 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.Release-Assert|x64.ActiveCfg = Release-Assert|x64
63 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.Release-Assert|x64.Build.0 = Release-Assert|x64
64 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.WarningAsError|Win32.ActiveCfg = WarningAsError|Win32
65 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.WarningAsError|Win32.Build.0 = WarningAsError|Win32
66 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.WarningAsError|x64.ActiveCfg = WarningAsError|x64
67 | {9B09A868-B169-43E8-AFF9-D2F12657ABCF}.WarningAsError|x64.Build.0 = WarningAsError|x64
68 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug|Win32.ActiveCfg = Debug|Win32
69 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug|Win32.Build.0 = Debug|Win32
70 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug|x64.ActiveCfg = Debug|x64
71 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug|x64.Build.0 = Debug|x64
72 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug-NoAssert|Win32.ActiveCfg = Debug-NoAssert|Win32
73 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug-NoAssert|Win32.Build.0 = Debug-NoAssert|Win32
74 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug-NoAssert|x64.ActiveCfg = Debug-NoAssert|x64
75 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug-NoAssert|x64.Build.0 = Debug-NoAssert|x64
76 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release|Win32.ActiveCfg = Release|Win32
77 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release|Win32.Build.0 = Release|Win32
78 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release|x64.ActiveCfg = Release|x64
79 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release|x64.Build.0 = Release|x64
80 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release-Assert|Win32.ActiveCfg = Release-Assert|Win32
81 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release-Assert|Win32.Build.0 = Release-Assert|Win32
82 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release-Assert|x64.ActiveCfg = Release-Assert|x64
83 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release-Assert|x64.Build.0 = Release-Assert|x64
84 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.WarningAsError|Win32.ActiveCfg = WarningAsError|Win32
85 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.WarningAsError|Win32.Build.0 = WarningAsError|Win32
86 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.WarningAsError|x64.ActiveCfg = WarningAsError|x64
87 | {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.WarningAsError|x64.Build.0 = WarningAsError|x64
88 | EndGlobalSection
89 | GlobalSection(SolutionProperties) = preSolution
90 | HideSolutionNode = FALSE
91 | EndGlobalSection
92 | EndGlobal
93 |
--------------------------------------------------------------------------------
/configure.ac:
--------------------------------------------------------------------------------
1 | dnl AC_INIT sets up autoconf and must be first macro.
2 | AC_INIT([mathic], [1.0]) # package, version, bug-report-email
3 |
4 | # Check that memtailor is installed and locate it
5 | PKG_CHECK_MODULES([MEMTAILOR], [memtailor])
6 |
7 | dnl ----- The gtest dependency
8 |
9 | AC_ARG_WITH([gtest], AS_HELP_STRING(
10 | [--with-gtest], [use gtest, which is required for running the unit tests
11 | with make check. The value download, which is the default, downloads
12 | gtest if a gtest source directory cannot be found. Per the recommendation
13 | of the gtest documentation, gtest is compiled with the tests, so an
14 | installed gtest is not usable - you need the gtest source. GTEST_PATH
15 | indicates where to look for gtest and it is also where gtest
16 | will be downloaded to if not found. The default path is srcdir/libs so
17 | that gtest needs to be at srcdir/libs/gtest/ where srcdir is the
18 | base of the directory being configured from.]
19 | ))
20 |
21 | AC_MSG_CHECKING([for gtest])
22 | AS_IF([test "x$GTEST_PATH" == "x"], [GTEST_PATH="$srcdir/libs"])
23 | AS_IF([test "x$GTEST_VERSION" == "x"], [GTEST_VERSION="1.6.0"])
24 | AS_IF([test "x$with_gtest" == "x"], [with_gtest="download"])
25 |
26 | AS_IF([test "x$with_gtest" == "xdownload"],
27 | [with_gtest="yes"; AC_CHECK_FILE([$GTEST_PATH/gtest/src/gtest-all.cc], [], [
28 | mkdir -p "$GTEST_PATH";
29 | (
30 | cd $GTEST_PATH;
31 | rm -rf gtest-$GTEST_VERSION.zip
32 | wget http://googletest.googlecode.com/files/gtest-$GTEST_VERSION.zip;
33 | unzip gtest-$GTEST_VERSION.zip;
34 | rm gtest-$GTEST_VERSION.zip
35 | rm -rf gtest/
36 | mv gtest-$GTEST_VERSION/ gtest/
37 | );
38 | if test ! -e "$GTEST_PATH/gtest/src/gtest-all.cc"; then
39 | AC_MSG_WARN([Failed to download or extract gtest.]);
40 | with_gtest="no";
41 | else
42 | with_gtest="yes";
43 | fi
44 | ])],
45 | [test "x$with_gtest" == "xyes"], [
46 | AC_CHECK_FILE([$GTEST_PATH/gtest/src/gtest-all.cc], [], [
47 | AC_MSG_ERROR([could not find gtest source at path $GTEST_PATH.])
48 | ])
49 | ],
50 | [test "x$with_gtest" == "xno"], [],
51 | [AC_MSG_ERROR([invalid value $with_gtest for with_gtest.])]
52 | )
53 | AS_IF([test "x$with_gtest" == "xyes"],
54 | [GTEST_CFLAGS="-I`cd $GTEST_PATH/gtest/include; echo $PWD` -I`cd $GTEST_PATH/gtest/; echo $PWD`"]);
55 | AM_CONDITIONAL(with_gtest, test "x$with_gtest" == "xyes")
56 |
57 | DEPS_CFLAGS="$MEMTAILOR_CFLAGS $GTEST_CFLAGS"
58 | DEPS_LIBS="$MEMTAILOR_LIBS $GTEST_LIBS"
59 | AC_SUBST(DEPS_CFLAGS)
60 | AC_SUBST(DEPS_LIBS)
61 |
62 | # set up information about directories
63 | AC_CONFIG_MACRO_DIR([build/autotools/m4]) # directory of extra autoconf macroes
64 | AC_CONFIG_AUX_DIR([build/autotools]) # directory for auxiliary build tools (install-sh etc)
65 |
66 | # check that source directory is correct
67 | dnl if autoconf is told the source code is in a directory that does not
68 | dnl contain this file then it knows that the directory is wrong.
69 | AC_CONFIG_SRCDIR([src/mathic.h])
70 |
71 | # Enable optional maintainer mode (off by default)
72 | dnl AM_MAINTAINER_MODE turns off automatic reconstruction of the build
73 | dnl files if the source build files have changed. A developer will want
74 | dnl those automatic reconstructions to happen so that changes to the
75 | dnl build system are actually carried out. However, a user might not
76 | dnl have the tools required to reconfigure and the need for
77 | dnl reconstruction might be spurious if the last-modified date is set
78 | dnl incorrectly on the build files.
79 | dnl
80 | dnl Passing the option [enable] to AM_MAINTAINER_MODE makes the
81 | dnl non-reconstruction feature available, but only when turned on by
82 | dnl passing the option –disable-maintainer-mode. This option is
83 | dnl apparently useful to some package distributors.
84 | AM_MAINTAINER_MODE([enable])
85 |
86 | # Set up Automake
87 | dnl foreign: do not create the GNU-specific file COPYING and do not complain
88 | dnl that GNU-specific files like NEWS, README, AUTHORS and ChangeLog are
89 | dnl missing.
90 | dnl -Wall: set Automake to emit all warnings it can. Is NOT RELATED to setting
91 | dnl warnings for other tools. For example, it wil not make the compiler
92 | dnl get a -Wall option.
93 | dnl subdir-objects: Put object files in a directory structure based on
94 | dnl the directory structure of the source files. This way, two source
95 | dnl files with the same name in different directories do not conflict.
96 | AM_INIT_AUTOMAKE([foreign subdir-objects -Wall])
97 |
98 | # if --enable-silent-rules is passed to ./configure or if V=0 is passed
99 | # to make, then the compilation output will be much less verbose making
100 | # it possible to spot warnings and errors as they go by.
101 | AM_SILENT_RULES()
102 |
103 | # Set up the $(LN_S) macro, which creates symbolic links
104 | AC_PROG_LN_S
105 |
106 | # set output variable INSTALL to the name of a BSD-compatible install program.
107 | # Requires install-sh to be present as a fallback, even on systems where
108 | # the fallback is not used.
109 | AC_PROG_INSTALL
110 |
111 | # Locate the C++ compiler.
112 | AC_PROG_CXX
113 |
114 | # Set up LibTool
115 | LT_INIT
116 |
117 | dnl Set the version for the library -- this concerns compatibility of the
118 | dnl source and binary interface of the library and is not the same as the
119 | dnl version of the project.
120 | AC_SUBST([MATHIC_SO_VERSION], [0:0:0])
121 |
122 | dnl Set up AC_OUTPUT to create each file by copying an input file
123 | dnl while substituting the output variable values.
124 | AC_CONFIG_FILES([Makefile
125 | build/autotools/mathic.pc:build/autotools/mathic.pc.in])
126 |
127 | dnl Macro that is required to be at the end of any Autoconf script.
128 | dnl Creates config.status and launches it.
129 | AC_OUTPUT
130 |
--------------------------------------------------------------------------------
/fixspace:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Does the following operations on the files passed as arguments:
4 | # - Remove trailing space from lines
5 | # - Remove trailing blank lines
6 | # - Remove/convert DOS-style line breaks
7 | # - Expand tabs to spaces with a tabspace of 8
8 |
9 | # I once had an error where the conversion had an error (the computer
10 | # didn't have dos2unix), resulting in the converted files being empty.
11 | # The result was that every file got replaced by an empty file! That
12 | # was not so nice, so this script stops operation as soon as any error
13 | # occurs, and it also checks that only space has been changed before
14 | # it overwrites the original file with a space-fixed version.
15 |
16 | for f in $*; do echo $f;
17 |
18 | tr -d '\r' < $f > __spaceTmp0;
19 | if [ $? != 0 ]; then echo "There was an error removing DOS-style line breaks."; exit 1; fi;
20 |
21 | expand -4 < __spaceTmp0 > __spaceTmp1;
22 | if [ $? != 0 ]; then echo "There was an error expanding tabs."; exit 1; fi;
23 |
24 | sed 's/[[:blank:]]*$//g' < __spaceTmp1 > __spaceTmp2;
25 | if [ $? != 0 ]; then echo "There was an error eliminating trailing space from lines."; exit 1; fi;
26 |
27 | # Make completely sure that we only changed the spaces
28 | diff -EbwB -q $f __spaceTmp2;
29 | if [ $? != 0 ]; then echo "There was an error. Conversion not confirmed correct."; exit 1; fi;
30 |
31 | sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' < __spaceTmp2 > __spaceTmp3;
32 | if [ $? != 0 ]; then echo "There was an error eliminating trailing blank lines."; exit 1; fi;
33 |
34 | # We have to do diff twice, because diff will not ignore trailing
35 | # lines that consist only of spaces. It will ignore changes to space and removal of
36 | # completely empty lines, so if we do it twice we get the right thing.
37 |
38 | # Make completely sure that we only changed the spaces
39 | diff -EbwB -q __spaceTmp2 __spaceTmp3;
40 | if [ $? != 0 ]; then echo "There was an error. Conversion not confirmed correct."; exit 1; fi;
41 |
42 | diff -q $f __spaceTmp3 1>/dev/null;
43 | if [ $? != 0 ]; then
44 | mv -f __spaceTmp3 $f;
45 | if [ $? != 0 ]; then echo "There was an error moving fixed file into place."; exit 1; fi;
46 | echo "Fixed space issue for $f."
47 | fi
48 |
49 | rm -f __spaceTmp0 __spaceTmp1 __spaceTmp2 __spaceTmp3;
50 | if [ $? != 0 ]; then echo "There was an error removing temporary files."; exit 1; fi;
51 | done;
52 |
--------------------------------------------------------------------------------
/include/mathic/mathic.cpp:
--------------------------------------------------------------------------------
1 | // This implementation file includes all the implementation files needed
2 | // to get MemTailor working.
3 | #include "mathic.h"
4 | #include "../../src/Timer.cpp"
5 | #include "../../src/ColumnPrinter.cpp"
6 | #include "../../src/DivMask.cpp"
7 | #include "../../src/Action.cpp"
8 | #include "../../src/BoolParameter.cpp"
9 | #include "../../src/CliParameter.cpp"
10 | #include "../../src/CliParser.cpp"
11 | #include "../../src/NameFactory.cpp"
12 | #include "../../src/error.cpp"
13 | #include "../../src/HelpAction.cpp"
14 | #include "../../src/IntegerParameter.cpp"
15 | #include "../../src/StringParameter.cpp"
16 | #include "../../src/display.cpp"
17 |
--------------------------------------------------------------------------------
/include/mathic/mathic.h:
--------------------------------------------------------------------------------
1 | // Include this file to pull in all external MemTailor files
2 |
3 | // utilities
4 | #include "../../src/Timer.h"
5 | #include "../../src/ColumnPrinter.h"
6 | #include "../../src/error.h"
7 |
8 | // divisor query data structures
9 | #include "../../src/DivList.h"
10 | #include "../../src/KDTree.h"
11 |
12 | // priority queue data structures
13 | #include "../../src/TourTree.h"
14 | #include "../../src/StlSet.h"
15 | #include "../../src/Heap.h"
16 | #include "../../src/Geobucket.h"
17 |
18 | // CLI package
19 | #include "../../src/Action.h"
20 | #include "../../src/BoolParameter.h"
21 | #include "../../src/CliParameter.h"
22 | #include "../../src/CliParser.h"
23 | #include "../../src/HelpAction.h"
24 | #include "../../src/IntegerParameter.h"
25 | #include "../../src/StringParameter.h"
26 | #include "../../src/display.h"
27 |
--------------------------------------------------------------------------------
/libs/.gitignore:
--------------------------------------------------------------------------------
1 | gtest/
2 |
--------------------------------------------------------------------------------
/replace:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | echo "Running script \"sed s/$1/$2/\""
3 | for i in 1 2 3; do
4 | /usr/bin/sleep 1; echo -n .;
5 | done
6 |
7 | for f in `ls src/*.cpp src/*.h`; do
8 | echo "Processing $f";
9 | sed "s/$1/$2/" < $f > $f.tmp
10 | mv $f.tmp $f
11 | done
12 |
--------------------------------------------------------------------------------
/src/divsim/DivListModel.h:
--------------------------------------------------------------------------------
1 | #ifndef DIV_ARRAY_MODEL_GUARD
2 | #define DIV_ARRAY_MODEL_GUARD
3 |
4 | #include "Monomial.h"
5 | #include "mathic/DivList.h"
6 | #include
7 | #include
8 |
9 | /** Helper class for DivListModel. */
10 | template
11 | class DivListModelConfiguration;
12 |
13 | template
14 | class DivListModelConfiguration {
15 | public:
16 | typedef int Exponent;
17 | typedef ::Monomial Monomial;
18 | typedef Monomial Entry;
19 |
20 | DivListModelConfiguration
21 | (size_t varCount,
22 | bool sortOnInsert,
23 | double rebuildRatio,
24 | size_t minRebuild):
25 | _varCount(varCount),
26 | _sortOnInsert(sortOnInsert),
27 | _useAutomaticRebuild((rebuildRatio > 0.0 || minRebuild > 0) && UDM),
28 | _rebuildRatio(rebuildRatio),
29 | _minRebuild(minRebuild),
30 | _expQueryCount(0) {}
31 |
32 | static const bool UseLinkedList = ULL;
33 | static const bool UseDivMask = UDM;
34 |
35 | bool getDoAutomaticRebuilds() const {return _useAutomaticRebuild;}
36 | double getRebuildRatio() const {return _rebuildRatio;}
37 | size_t getRebuildMin() const {return _minRebuild;}
38 | bool getSortOnInsert() const {return _sortOnInsert;}
39 |
40 |
41 | size_t getVarCount() const {return _varCount;}
42 |
43 | Exponent getExponent(const Monomial& monomial, size_t var) const {
44 | ++_expQueryCount;
45 | ASSERT(var < monomial.size());
46 | return monomial[var];
47 | }
48 |
49 | bool divides(const Monomial& a, const Monomial& b) const {
50 | for (size_t var = 0; var < getVarCount(); ++var)
51 | if (getExponent(b, var) < getExponent(a, var))
52 | return false;
53 | return true;
54 | }
55 |
56 | bool isLessThan(const Monomial& a, const Monomial& b) const {
57 | for (size_t var = 0; var < getVarCount(); ++var) {
58 | if (getExponent(a, var) < getExponent(b, var))
59 | return true;
60 | if (getExponent(b, var) < getExponent(a, var))
61 | return false;
62 | }
63 | return false;
64 | }
65 |
66 | unsigned long long getExpQueryCount() const {return _expQueryCount;}
67 |
68 | private:
69 | const size_t _varCount;
70 | const bool _sortOnInsert;
71 | const bool _useAutomaticRebuild;
72 | const double _rebuildRatio;
73 | const size_t _minRebuild;
74 | mutable unsigned long long _expQueryCount;
75 | };
76 |
77 | template
78 | class DivListModel;
79 |
80 | /** An instantiation of the capabilities of DivList. */
81 | template
82 | class DivListModel {
83 | private:
84 | typedef DivListModelConfiguration C;
85 | typedef mathic::DivList Finder;
86 | public:
87 | typedef typename Finder::iterator iterator;
88 | typedef typename Finder::const_iterator const_iterator;
89 | typedef typename Finder::Monomial Monomial;
90 | typedef typename Finder::Entry Entry;
91 |
92 | DivListModel(size_t varCount,
93 | bool minimizeOnInsert,
94 | bool moveDivisorToFront,
95 | bool sortOnInsert,
96 | double rebuildRatio,
97 | size_t minRebuild):
98 | _finder(C(varCount, sortOnInsert, rebuildRatio, minRebuild)),
99 | _minimizeOnInsert(minimizeOnInsert),
100 | _moveDivisorToFront(moveDivisorToFront) {
101 | ASSERT(!sortOnInsert || !moveDivisorToFront);
102 | }
103 |
104 | void insert(const Entry& entry);
105 | template
106 | void insert(const Entry& entry, MultipleOutput& removed);
107 |
108 | Entry* findDivisor(const Monomial& monomial) {
109 | iterator it = _finder.findDivisorIterator(monomial);
110 | if (_moveDivisorToFront && it != _finder.end()) {
111 | _finder.moveToFront(it);
112 | it = _finder.begin();
113 | }
114 | return it == end() ? 0 : &*it;
115 | }
116 | const Entry* findDivisor(const Monomial& monomial) const {
117 | return const_cast&>(*this).findDivisor(monomial);
118 | }
119 |
120 | template
121 | void findAllDivisors(const Monomial& monomial, DO& out) {
122 | _finder.findAllDivisors(monomial, out);
123 | }
124 | template
125 | void findAllDivisors(const Monomial& monomial, DO& out) const {
126 | _finder.findAllDivisors(monomial, out);
127 | }
128 | template
129 | void forAll(EO& out) {
130 | _finder.forAll(out);
131 | }
132 | template
133 | void forAll(EO& out) const {
134 | _finder.forAll(out);
135 | }
136 |
137 | std::string getName() const;
138 |
139 | iterator begin() {return _finder.begin();}
140 | const_iterator begin() const {return _finder.begin();}
141 | iterator end() {return _finder.end();}
142 | const_iterator end() const {return _finder.end();}
143 | size_t size() const {return _finder.size();}
144 |
145 | unsigned long long getExpQueryCount() const {
146 | return _finder.getConfiguration().getExpQueryCount();
147 | }
148 |
149 | private:
150 | Finder _finder;
151 | const bool _minimizeOnInsert;
152 | const bool _moveDivisorToFront;
153 | };
154 |
155 | template
156 | inline void DivListModel::insert(const Entry& entry) {
157 | if (!_minimizeOnInsert) {
158 | _finder.insert(entry);
159 | return;
160 | }
161 | if (findDivisor(entry) != 0)
162 | return;
163 | bool hasMultiples = _finder.removeMultiples(entry);
164 | _finder.insert(entry);
165 | if (_moveDivisorToFront && hasMultiples) {
166 | iterator it = _finder.end();
167 | _finder.moveToFront(--it);
168 | }
169 | }
170 |
171 | template
172 | template
173 | inline void DivListModel::insert(const Entry& entry, MO& out) {
174 | if (!_minimizeOnInsert) {
175 | _finder.insert(entry);
176 | return;
177 | }
178 | if (findDivisor(entry) != 0)
179 | return;
180 | bool hasMultiples = _finder.removeMultiples(entry, out);
181 | _finder.insert(entry);
182 | if (_moveDivisorToFront && hasMultiples) {
183 | iterator it = _finder.end();
184 | _finder.moveToFront(--it);
185 | }
186 | }
187 |
188 | template
189 | inline std::string DivListModel::getName() const {
190 | return _finder.getName() +
191 | (_minimizeOnInsert ? " remin" : " nomin") +
192 | (_moveDivisorToFront ? " toFront" : "");
193 | }
194 |
195 | #endif
196 |
--------------------------------------------------------------------------------
/src/divsim/KDTreeModel.h:
--------------------------------------------------------------------------------
1 | #ifndef K_D_TREE_MODEL_GUARD
2 | #define K_D_TREE_MODEL_GUARD
3 |
4 | #include "Monomial.h"
5 | #include "mathic/KDTree.h"
6 | #include
7 | #include
8 |
9 | template<
10 | bool UseDivMask,
11 | bool UseTreeDivMask,
12 | bool PackedTree,
13 | size_t LeafSize,
14 | bool AllowRemovals>
15 | class KDTreeModelConfiguration;
16 |
17 | /** Helper class for KDTreeModel. */
18 | template
19 | class KDTreeModelConfiguration {
20 | public:
21 | typedef int Exponent;
22 | typedef ::Monomial Monomial;
23 | typedef Monomial Entry;
24 |
25 | KDTreeModelConfiguration
26 | (size_t varCount,
27 | bool sortOnInsert,
28 | bool useDivisorCache,
29 | double rebuildRatio,
30 | size_t minRebuild):
31 | _varCount(varCount),
32 | _sortOnInsert(sortOnInsert),
33 | _useDivisorCache(useDivisorCache),
34 | _useAutomaticRebuild((rebuildRatio > 0.0 || minRebuild > 0) && UDM),
35 | _rebuildRatio(rebuildRatio),
36 | _minRebuild(minRebuild),
37 | _expQueryCount(0) {
38 | ASSERT(rebuildRatio >= 0);
39 | }
40 |
41 | size_t getVarCount() const {return _varCount;}
42 | bool getSortOnInsert() const {return _sortOnInsert;}
43 |
44 | Exponent getExponent(const Monomial& monomial, size_t var) const {
45 | ++_expQueryCount;
46 | ASSERT(var < monomial.size());
47 | return monomial[var];
48 | }
49 |
50 | NO_PINLINE bool divides(const Monomial& a, const Monomial& b) const {
51 | for (size_t var = 0; var < getVarCount(); ++var)
52 | if (getExponent(b, var) < getExponent(a, var))
53 | return false;
54 | return true;
55 | }
56 |
57 | bool isLessThan(const Monomial& a, const Monomial& b) const {
58 | for (size_t var = 0; var < getVarCount(); ++var) {
59 | if (getExponent(a, var) < getExponent(b, var))
60 | return true;
61 | if (getExponent(b, var) < getExponent(a, var))
62 | return false;
63 | }
64 | return false;
65 | }
66 |
67 | size_t getLeafSize() const {return LeafSize;}
68 | bool getUseDivisorCache() const {return _useDivisorCache;}
69 | bool getDoAutomaticRebuilds() const {return _useAutomaticRebuild;}
70 | double getRebuildRatio() const {return _rebuildRatio;}
71 | size_t getRebuildMin() const {return _minRebuild;}
72 |
73 | static const bool UseDivMask = UDM;
74 | static const bool UseTreeDivMask = UTDM;
75 | static const bool PackedTree = PT;
76 | static const size_t LeafSize = LS;
77 | static const bool AllowRemovals = AR;
78 |
79 | unsigned long long getExpQueryCount() const {return _expQueryCount;}
80 |
81 | private:
82 | const size_t _varCount;
83 | const bool _sortOnInsert;
84 | const bool _useDivisorCache;
85 | const bool _useAutomaticRebuild;
86 | const double _rebuildRatio;
87 | const size_t _minRebuild;
88 | mutable unsigned long long _expQueryCount;
89 | };
90 |
91 | /** An instantiation of the capabilities of KDTree. */
92 | template<
93 | bool UseDivMask,
94 | bool UseTreeDivMask,
95 | bool PackedTree,
96 | size_t LeafSize,
97 | bool AllowRemovals
98 | >
99 | class KDTreeModel {
100 | private:
101 | typedef KDTreeModelConfiguration
102 | C;
103 | typedef mathic::KDTree Finder;
104 | public:
105 | typedef typename Finder::Monomial Monomial;
106 | typedef typename Finder::Entry Entry;
107 |
108 | KDTreeModel(size_t varCount,
109 | bool minimizeOnInsert,
110 | bool sortOnInsert,
111 | bool useDivisorCache,
112 | double rebuildRatio,
113 | size_t minRebuild):
114 | _finder(C(varCount, sortOnInsert, useDivisorCache, rebuildRatio, minRebuild)),
115 | _minimizeOnInsert(minimizeOnInsert) {
116 | ASSERT(!UseTreeDivMask || UseDivMask);
117 | }
118 |
119 |
120 | void insert(const Entry& entry);
121 | template
122 | void insert(const Entry& entry, MultipleOutput& removed);
123 |
124 | Entry* findDivisor(const Monomial& monomial) {
125 | return _finder.findDivisor(monomial);
126 | }
127 | const Entry* findDivisor(const Monomial& monomial) const {
128 | return _finder.findDivisor(monomial);
129 | }
130 | std::string getName() const;
131 |
132 | template
133 | void findAllDivisors(const Monomial& monomial, DO& out) {
134 | _finder.findAllDivisors(monomial, out);
135 | }
136 | template
137 | void findAllDivisors(const Monomial& monomial, DO& out) const {
138 | _finder.findAllDivisors(monomial, out);
139 | }
140 | template
141 | void forAll(EO& out) {
142 | _finder.forAll(out);
143 | }
144 | template
145 | void forAll(EO& out) const {
146 | _finder.forAll(out);
147 | }
148 | size_t size() const {return _finder.size();}
149 |
150 | unsigned long long getExpQueryCount() const {
151 | return _finder.getConfiguration().getExpQueryCount();
152 | }
153 |
154 | class Comparer;
155 |
156 | private:
157 | Finder _finder;
158 | bool _minimizeOnInsert;
159 | };
160 |
161 | template
162 | inline void KDTreeModel::insert(const Entry& entry) {
163 | if (!_minimizeOnInsert) {
164 | _finder.insert(entry);
165 | return;
166 | }
167 | if (findDivisor(entry) != 0)
168 | return;
169 | _finder.removeMultiples(entry);
170 | _finder.insert(entry);
171 | }
172 |
173 | template
174 | template
175 | inline void KDTreeModel::
176 | insert(const Entry& entry, MultipleOutput& removed) {
177 | if (!_minimizeOnInsert) {
178 | _finder.insert(entry);
179 | return;
180 | }
181 | if (findDivisor(entry) != 0)
182 | return;
183 | _finder.removeMultiples(entry, removed);
184 | _finder.insert(entry);
185 | }
186 |
187 | template
188 | inline std::string KDTreeModel::getName() const {
189 | return _finder.getName() +
190 | (_minimizeOnInsert ? " remin" : " nomin");
191 | }
192 |
193 | #endif
194 |
--------------------------------------------------------------------------------
/src/divsim/Monomial.h:
--------------------------------------------------------------------------------
1 | #ifndef MONOMIAL_GUARD
2 | #define MONOMIAL_GUARD
3 |
4 | #include
5 | #include
6 |
7 | class Monomial {
8 | public:
9 | typedef int Exponent;
10 |
11 | Monomial(): _exponents(0) {IF_DEBUG(_size = 0);}
12 | Monomial(std::vector& v): _exponents(&v[0]) {
13 | IF_DEBUG(_size = v.size());
14 | }
15 |
16 | inline Exponent& operator[](size_t index) {
17 | ASSERT(index < _size);
18 | return _exponents[index];
19 | }
20 | inline const Exponent& operator[](size_t index) const {
21 | ASSERT(index < _size);
22 | return _exponents[index];
23 | }
24 |
25 | const Exponent* getPointer() const {return _exponents;}
26 |
27 | #ifdef DEBUG
28 | size_t size() const {return _size;}
29 | bool operator==(const Monomial& m) const {return _exponents == m._exponents;}
30 | bool operator<(const Monomial& m) const {return _exponents < m._exponents;}
31 | #endif
32 |
33 | private:
34 | #ifdef DEBUG
35 | size_t _size;
36 | #endif
37 | Exponent* _exponents;
38 | };
39 |
40 | inline std::ostream& operator<<(std::ostream& out, const Monomial& monomial) {
41 | #ifdef DEBUG
42 | out << "(Monomial:";
43 | for (size_t i = 0; i < monomial.size(); ++i)
44 | out << ' ' << monomial[i];
45 | out << ')';
46 | #else
47 | out << "(Monomial)";
48 | #endif
49 | return out;
50 | }
51 |
52 | #endif
53 |
--------------------------------------------------------------------------------
/src/divsim/Simulation.cpp:
--------------------------------------------------------------------------------
1 | #include "stdinc.h"
2 | #include "Simulation.h"
3 |
4 | #include "mathic/ColumnPrinter.h"
5 | #include
6 | #include
7 |
8 | namespace {
9 | void makeRandom(std::vector& monomial) {
10 | for (size_t var = 0; var < monomial.size(); ++var)
11 | monomial[var] = rand() % 1000;
12 | }
13 | }
14 |
15 | void Simulation::makeStandard
16 | (size_t varCount, size_t inserts, size_t queries, bool findAll) {
17 | srand(0);
18 |
19 | _findAll = findAll;
20 | _varCount = varCount;
21 | _events.clear();
22 | for (size_t i = 0; i < inserts + queries; ++i) {
23 | /*Event event2;
24 | event2._type = StateUnknown;
25 | _events.push_back(event2);*/
26 |
27 | Event event;
28 | event._monomial.resize(varCount);
29 | makeRandom(event._monomial);
30 | event._type = (i <= inserts ? InsertUnknown : QueryUnknown);
31 | _events.push_back(event);
32 | }
33 | }
34 |
35 | void Simulation::printData(std::ostream& out) const {
36 | std::vector sorted(_data);
37 | std::sort(sorted.begin(), sorted.end());
38 | out << "*** Simulation outcome for "
39 | << _repeats << " repeats ***" << std::endl;
40 | mic::ColumnPrinter pr;
41 | pr.addColumn(true);
42 | pr.addColumn(false, " ", "ms");
43 | pr.addColumn(false, " ", "eqs");
44 | for (std::vector::const_iterator it = sorted.begin();
45 | it != sorted.end(); ++it) {
46 | pr[0] << it->_name << '\n';
47 | pr[1] << mic::ColumnPrinter::commafy(it->_mseconds) << '\n';
48 | pr[2] << mic::ColumnPrinter::commafy(it->_expQueryCount) << '\n';
49 | }
50 | pr.print(out);
51 | }
52 |
53 | void Simulation::SimData::print(std::ostream& out) {
54 | out << _name
55 | << " " << mic::ColumnPrinter::commafy(_mseconds) << " ms"
56 | << " " << mic::ColumnPrinter::commafy(_expQueryCount) << " eqs"
57 | << '\n';
58 | }
59 |
60 | bool Simulation::SimData::operator<(const SimData& sd) const {
61 | return _mseconds < sd._mseconds;
62 | }
63 |
--------------------------------------------------------------------------------
/src/divsim/Simulation.h:
--------------------------------------------------------------------------------
1 | #ifndef SIMULATION_GUARD
2 | #define SIMULATION_GUARD
3 |
4 | #include "Monomial.h"
5 | #include "mathic/Timer.h"
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | class Simulation {
12 | public:
13 | Simulation(size_t repeats, bool printPartialData):
14 | _repeats(repeats), _printPartialData(printPartialData), _simType("none") {}
15 |
16 | void makeStandard(size_t varCount, size_t inserts, size_t queries, bool findAll);
17 |
18 | template
19 | void run();
20 | template
21 | void run(const Param1& param1);
22 | template
23 | void run(const Param1& param1, const Param2& param2);
24 | template
25 | void run(const Param1& param1, const Param2& param2, const Param3& param3);
26 | template
27 | void run(const P1& p1, const P2& p2, const P3& param3, const P4& param4);
28 | template
29 | void run(const P1& p1, const P2& p2, const P3& param3, const P4& param4,
30 | const P5& p5);
31 | template
33 | void run(const P1& p1, const P2& p2, const P3& param3, const P4& param4,
34 | const P5& p5, const P6& p6);
35 |
36 | void printData(std::ostream& out) const;
37 |
38 | private:
39 | struct SimData {
40 | bool operator<(const SimData& sd) const;
41 | void print(std::ostream& out);
42 |
43 | std::string _name;
44 | unsigned long _mseconds;
45 | unsigned long long _expQueryCount;
46 | };
47 |
48 | template
49 | void run(DivFinder& finder);
50 |
51 | enum EventType {
52 | InsertUnknown,
53 | InsertKnown,
54 | QueryNoDivisor,
55 | QueryHasDivisor,
56 | QueryUnknown,
57 | StateUnknown,
58 | StateKnown
59 | };
60 | struct Event {
61 | EventType _type;
62 | std::vector _monomial;
63 | std::vector _state;
64 | #ifdef DEBUG
65 | std::vector _allMonomials;
66 | #else
67 | size_t _monomialCount;
68 | #endif
69 | };
70 | class MonomialStore;
71 |
72 | bool _findAll;
73 | std::vector _events;
74 | std::vector _data;
75 | size_t _varCount;
76 | size_t _repeats;
77 | bool _printPartialData;
78 | std::string _simType;
79 | };
80 |
81 | template
82 | void Simulation::run() {
83 | DivFinder finder(_varCount);
84 | run(finder);
85 | }
86 |
87 | template
88 | void Simulation::run(const Param1& param1) {
89 | DivFinder finder(_varCount, param1);
90 | run(finder);
91 | }
92 |
93 | template
94 | void Simulation::run(const Param1& param1, const Param2& param2) {
95 | DivFinder finder(_varCount, param1, param2);
96 | run(finder);
97 | }
98 |
99 | template
100 | void Simulation::run
101 | (const Param1& param1, const Param2& param2, const Param3& param3) {
102 | DivFinder finder(_varCount, param1, param2, param3);
103 | run(finder);
104 | }
105 |
106 | template
107 | void Simulation::run
108 | (const P1& param1, const P2& param2, const P3& param3, const P4& param4) {
109 | DivFinder finder(_varCount, param1, param2, param3, param4);
110 | run(finder);
111 | }
112 |
113 | template
114 | void Simulation::run
115 | (const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5) {
116 | DivFinder finder(_varCount, p1, p2, p3, p4, p5);
117 | run(finder);
118 | }
119 |
120 | template
122 | void Simulation::run
123 | (const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5,
124 | const P6& p6) {
125 | DivFinder finder(_varCount, p1, p2, p3, p4, p5, p6);
126 | run(finder);
127 | }
128 |
129 | class Simulation::MonomialStore {
130 | public:
131 | MonomialStore() {clear();}
132 | void clear() {
133 | #ifdef DEBUG
134 | _monomials.clear();
135 | #else
136 | _monomialCount = 0;
137 | #endif
138 | }
139 |
140 | void push_back(const Monomial& monomial) {
141 | proceed(monomial);
142 | }
143 | bool proceed(const Monomial& monomial) {
144 | #ifdef DEBUG
145 | _monomials.push_back(monomial);
146 | #else
147 | ++_monomialCount;
148 | #endif
149 | return true;
150 | }
151 |
152 | template
153 | void checkInsert(Event& e, const Finder& finder) {
154 | #ifdef DEBUG
155 | std::sort(_monomials.begin(), _monomials.end());
156 | #endif
157 |
158 | if (e._type == InsertUnknown) {
159 | #ifdef DEBUG
160 | e._allMonomials.clear();
161 | for (size_t i = 0; i < _monomials.size(); ++i)
162 | e._allMonomials.push_back(_monomials[i]);
163 | #else
164 | e._monomialCount = _monomialCount;
165 | #endif
166 | e._type = InsertKnown;
167 | } else {
168 | #ifdef DEBUG
169 | ASSERT(_monomials == e._allMonomials);
170 | #else
171 | if (_monomialCount != e._monomialCount) {
172 | std::cerr << "Finder \"" << finder.getName() <<
173 | "\" found incorrect number of monomials." << std::endl;
174 | std::exit(1);
175 | }
176 | #endif
177 | }
178 | }
179 |
180 | template
181 | void checkQuery(Event& e, const Finder& finder) {
182 | #ifdef DEBUG
183 | for (size_t d = 0; d < _monomials.size(); ++d) {
184 | for (size_t var = 0; var < e._monomial.size(); ++var) {
185 | ASSERT(_monomials[d][var] <= e._monomial[var]);
186 | }
187 | }
188 | std::sort(_monomials.begin(), _monomials.end());
189 | #endif
190 |
191 | if (e._type == QueryUnknown) {
192 | bool noMonomials;
193 | #ifdef DEBUG
194 | e._allMonomials.clear();
195 | for (size_t i = 0; i < _monomials.size(); ++i)
196 | e._allMonomials.push_back(_monomials[i]);
197 | noMonomials = _monomials.empty();
198 | #else
199 | e._monomialCount = _monomialCount;
200 | noMonomials = _monomialCount == 0;
201 | #endif
202 | e._type = noMonomials ? QueryNoDivisor : QueryHasDivisor;
203 | } else {
204 | #ifdef DEBUG
205 | for (size_t i = 0; i < _monomials.size(); ++i)
206 | ASSERT(_monomials[i] == e._allMonomials[i]);
207 | #else
208 | if (_monomialCount != e._monomialCount) {
209 | std::cerr << "Finder \"" << finder.getName() <<
210 | "\" found incorrect number of monomials." << std::endl;
211 | std::exit(1);
212 | }
213 | #endif
214 | }
215 | }
216 |
217 | private:
218 | #ifdef DEBUG
219 | std::vector _monomials;
220 | #else
221 | size_t _monomialCount;
222 | #endif
223 | };
224 |
225 | struct ForAll {
226 | public:
227 | ForAll(std::vector& entries): _entries(entries) {}
228 | bool proceed(const Monomial& m) {
229 | _entries.push_back(m.getPointer());
230 | return true;
231 | }
232 |
233 | private:
234 | std::vector& _entries;
235 | };
236 |
237 | template
238 | void Simulation::run(DivFinder& finder) {
239 | mic::Timer timer;
240 | std::vector divisors;
241 | std::vector tmp;
242 | for (size_t step = 0; step < _repeats; ++step) {
243 | for (size_t i = 0; i < _events.size(); ++i) {
244 | Event& e = _events[i];
245 | if (e._type == InsertKnown || e._type == InsertUnknown) {
246 | divisors.clear();
247 | MonomialStore store;
248 | if (0) {
249 | // here to make sure it compiles, also easy to switch to checking this instead.
250 | finder.insert(e._monomial);
251 | } else
252 | finder.insert(e._monomial, store);
253 | store.checkInsert(e, finder);
254 | } else if (e._type == StateUnknown || e._type == StateKnown) {
255 | tmp.clear();
256 | ForAll forAll(tmp);
257 | finder.forAll(forAll);
258 | if (e._type == StateUnknown) {
259 | e._type = StateKnown;
260 | e._state.swap(tmp);
261 | } else {
262 | if (e._state != tmp) {
263 | std::cerr << "states differ." << std::endl;
264 | std::exit(1);
265 | }
266 | }
267 | } else if (!_findAll) {
268 | typename DivFinder::Entry* entry = finder.findDivisor(e._monomial);
269 | if (entry == 0) {
270 | if (e._type == QueryHasDivisor) {
271 | std::cerr << "Divisor finder \"" << finder.getName()
272 | << "\" failed to find divisor." << std::endl;
273 | std::exit(1);
274 | }
275 | e._type = QueryNoDivisor;
276 | } else {
277 | #ifdef DEBUG
278 | for (size_t var = 0; var < _varCount; ++var) {
279 | ASSERT((*entry)[var] <= e._monomial[var]);
280 | }
281 | #endif
282 | if (e._type == QueryNoDivisor) {
283 | std::cerr << "Divisor finder \"" << finder.getName() <<
284 | "\" found incorrect divisor." << std::endl;
285 | std::exit(1);
286 | }
287 | e._type = QueryHasDivisor;
288 | }
289 | } else {
290 | ASSERT(_findAll);
291 | divisors.clear();
292 | MonomialStore store;
293 | const_cast(finder) // to test const interface
294 | .findAllDivisors(e._monomial, store);
295 | store.checkQuery(e, finder);
296 | }
297 | }
298 | }
299 |
300 | SimData data;
301 | data._mseconds = (unsigned long)timer.getMilliseconds();
302 | data._name = finder.getName();
303 | data._expQueryCount = finder.getExpQueryCount();
304 | _data.push_back(data);
305 | if (_printPartialData)
306 | data.print(std::cerr);
307 | std::cout << finder.size() << std::endl;
308 | }
309 |
310 | #endif
311 |
--------------------------------------------------------------------------------
/src/divsim/divMain.cpp:
--------------------------------------------------------------------------------
1 | #include "stdinc.h"
2 |
3 | #include "DivListModel.h"
4 | #include "KDTreeModel.h"
5 | #include "Simulation.h"
6 | #include "mathic/Timer.h"
7 | #include
8 |
9 | int main() {
10 | const size_t repeats = IF_DEBUG(true ? 1 :) 1;
11 | Simulation sim(repeats, true);
12 | mic::Timer timer;
13 | std::cout << "Generating simulation. ";
14 |
15 |
16 | #ifdef DEBUG
17 | sim.makeStandard(10, 400, 1000, true);
18 | #else
19 | sim.makeStandard(10, 5000, 2000000, true);
20 | #endif
21 | timer.print(std::cout);
22 | std::cout << std::endl;
23 |
24 | #ifndef DEBUG
25 | sim.run >(0, 0, 0, 1.0, 1000);
26 | sim.run >(0, 0, 0, 1.0, 1000);
27 | return 0;
28 |
29 | sim.run >(1, 0, 0, 0.0, 0); // best tree, no mask
30 | sim.run >(1, 0, 0, 0.0, 0); // best tree, no mask
31 |
32 | sim.run >(1, 0, 0, 1.0, 1000); // best tree, mask
33 | sim.run >(1, 0, 0, 1.0, 1000); // best tree, mask
34 |
35 | sim.run >(1, 1, 0, 0.5, 500);
36 | return 0;
37 | #endif
38 |
39 |
40 | /*
41 | for (int minimizeOnInsert = 1; minimizeOnInsert <= 1; ++minimizeOnInsert) {
42 | for (int order = 0; order <= 2; ++order) {
43 | bool moveDivisorToFront = (order == 1);
44 | bool sortOnInsert = (order == 2);
45 | sim.run >
46 | (minimizeOnInsert, moveDivisorToFront, sortOnInsert);
47 | sim.run >
48 | (minimizeOnInsert, moveDivisorToFront, sortOnInsert);
49 | }
50 | }
51 | //*/
52 |
53 | //sim.run >(1, 0, 1, 0.0, 0); // best array, no mask
54 | /*
55 | sim.run >(1, 0, 0)
56 | sim.run >(1, 1, 0);
57 | sim.run >(1, 0, 1);
58 | sim.run >(1, 0, 0);
59 | sim.run >(1, 1, 0);
60 | sim.run >(1, 0, 1);
61 | //*/
62 |
63 | sim.run >(0, 0, 0, 0.0, 0);
64 | sim.run >(0, 1, 0, 0.5, 500);
65 | for (int mini = 0; mini <= 0; ++mini) {
66 | for (int sortOnInsert = 0; sortOnInsert <= 1; ++sortOnInsert) {
67 | for (int useDivCache = 0; useDivCache <= 1; ++useDivCache) {
68 | sim.run >(mini,sortOnInsert,useDivCache, 0.5, 10);
69 | sim.run >(mini,sortOnInsert,useDivCache, 0.5, 10);
70 | sim.run >(mini,sortOnInsert,useDivCache, 0.5, 10);
71 |
72 | sim.run >(mini,sortOnInsert,useDivCache, 0.5, 10);
73 | sim.run >(mini,sortOnInsert,useDivCache, 0.5, 10);
74 | sim.run >(mini,sortOnInsert,useDivCache, 0.5, 10);
75 |
76 | sim.run >(mini,sortOnInsert,useDivCache, 0.5, 10);
77 | sim.run >(mini,sortOnInsert,useDivCache, 0.5, 10);
78 | sim.run >(mini,sortOnInsert,useDivCache, 0.5, 10);
79 |
80 | sim.run >(mini,sortOnInsert,useDivCache, 0.5, 10);
81 |
82 | sim.run >(mini,sortOnInsert,useDivCache, 0.5, 10);
83 | sim.run >(mini,sortOnInsert,useDivCache, 0.5, 10);
84 | sim.run >(mini,sortOnInsert,useDivCache, 0.5, 10);
85 |
86 | /*
87 | for (size_t leafSize = 5; leafSize <= 15; leafSize += 5)
88 | for (size_t start = 0; start <= 0; start += 200)
89 | for (double ratio = 0; ratio < 0.1; ratio += 0.2)
90 | sim.run >(leafSize, mini,sortOnInsert,useDivisorCache, ratio, start);
91 |
92 | //*/
93 | /*sim.run >(8, mini,sortOnInsert,useDivisorCache, 0, 0);
94 | sim.run >(8, mini,sortOnInsert,useDivisorCache, 0, 0);
95 | sim.run >(20, mini,sortOnInsert,useDivisorCache, 0, 0);
96 | sim.run >(20, mini,sortOnInsert,useDivisorCache, 0, 0);
97 | sim.run >(40, mini,sortOnInsert,useDivisorCache, 0, 0);
98 | sim.run >(40, mini,sortOnInsert,useDivisorCache, 0, 0);
99 | sim.run >(60, mini,sortOnInsert,useDivisorCache, 0, 0);
100 | sim.run >(60, mini,sortOnInsert,useDivisorCache, 0, 0);*/
101 |
102 | /*
103 | sim.run >(10, mini,sortOnInsert,useDivisorCache, 0.001, 2000);
104 | sim.run >(10, mini,sortOnInsert,useDivisorCache, 0.001, 4000);
105 |
106 | sim.run >(10, mini,sortOnInsert,useDivisorCache, 0.001, 6000);
107 | sim.run >(10, mini,sortOnInsert,useDivisorCache, 0.001, 6000);
108 |
109 | sim.run >(10, mini,sortOnInsert,useDivisorCache, 0.001, 8000);
110 | sim.run >(10, mini,sortOnInsert,useDivisorCache, 0.001, 10000);*/
111 | //sim.run(10, mini,sortOnInsert,useDivisorCache, 4, 2000);
112 | //sim.run(20, mini,sortOnInsert,useDivisorCache, 0.75, 2000);
113 | //sim.run(8, mini,sortOnInsert,useDivisorCache, 0.75, 2000);
114 | }
115 | }
116 | }
117 | //*/
118 | /*
119 | for (int mini = 1; mini <= 1; ++mini) {
120 | for (int noneFrontSort = 0; noneFrontSort <= 2; ++noneFrontSort) {
121 | bool tof = (noneFrontSort == 1);
122 | bool sort = (noneFrontSort == 2);
123 |
124 | for (double ratio = 0.5; ratio < 0.51; ratio += 0.1)
125 | for (size_t start = 500; start <= 500; start += 100)
126 | sim.run >(mini, tof, sort, ratio, start);
127 | }
128 | }
129 | //*/
130 |
131 | /* best for single query from best to worst
132 | sim.run >(40, 1, 0, 0, 1.0, 1000); // best tree, mask
133 | sim.run >(15, 1, 0, 0, 0.0, 0); // best tree, no mask
134 | sim.run >(1, 1, 0, 0.5, 500); // best array, mask
135 | sim.run >(1, 1, 0, 0.5, 500); // should be best linked, mask
136 | sim.run >(1, 0, 1, 0.0, 0); // best array, no mask
137 | sim.run >(1, 0, 1, 0.0, 0); // best linked, no mask
138 | //*/
139 |
140 | /* base div lists
141 | sim.run >(1, 0, 0, 0.0, 0); // base array
142 | sim.run >(1, 0, 0, 0.0, 0); // base linked
143 | //*/
144 |
145 | std::cout << "\n\n";
146 | sim.printData(std::cout);
147 | return 0;
148 | }
149 |
--------------------------------------------------------------------------------
/src/divsim/divMain.h:
--------------------------------------------------------------------------------
1 | #ifndef MATHIC_DIV_MAIN_GUARD
2 | #define MATHIC_DIV_MAIN_GUARD
3 |
4 | int main();
5 |
6 | #endif
7 |
--------------------------------------------------------------------------------
/src/divsim/stdinc.h:
--------------------------------------------------------------------------------
1 | #ifdef STDINC_GUARD
2 | #error stdinc.h included twice
3 | #endif
4 | #define STDINC_GUARD
5 |
6 | #ifdef _MSC_VER // For Microsoft Compiler in Visual Studio C++.
7 | #pragma warning (push, 1) // Reduce warning level for GMP headers.
8 | #endif
9 |
10 | #ifdef PROFILE
11 | #define NO_PINLINE NO_INLINE
12 | #else
13 | #define NO_PINLINE
14 | #endif
15 |
16 | #ifndef _MSC_VER
17 | #define NO_INLINE __attribute__ ((noinline))
18 | #endif
19 |
20 | #ifdef _MSC_VER // For Microsoft Compiler in Visual Studio C++.
21 | #define NO_INLINE __declspec(noinline)
22 | #pragma warning (pop) // Go back to previous warning level.
23 | #pragma warning (disable: 4996) // std::copy is flagged as dangerous.
24 | #pragma warning (disable: 4290) // VC++ ignores throw () specification.
25 | #pragma warning (disable: 4127) // Warns about using "while (true)".
26 | #pragma warning (disable: 4100) // Warns about unused parameters.
27 | #pragma warning (disable: 4800) // Warns on int to bool conversion.
28 | #pragma warning (disable: 4146) // Warns on unary minus on unsigned (bit trick)
29 |
30 | // This warning warns about using the this pointer in base member
31 | // initializer lists. This is a pretty good warning as that can
32 | // obviously easily go wrong, but it is pretty useful to do as well,
33 | // so the warning is turned off.
34 | #pragma warning (disable: 4355)
35 |
36 | #ifdef _DEBUG
37 | #define DEBUG
38 | #endif
39 |
40 | #endif
41 |
42 | #include
43 | #include
44 |
45 | #ifdef DEBUG
46 | #include // Useful for debugging.
47 | #define PRINT
48 | #include
49 | #define ASSERT(X) assert(X);
50 | #define IF_DEBUG(X) X
51 | #else
52 | #define ASSERT(X)
53 | #define IF_DEBUG(X)
54 | #endif
55 |
56 | static const size_t BitsPerByte = 8;
57 | static const size_t MemoryAlignment = sizeof(void*);
58 |
--------------------------------------------------------------------------------
/src/mathic.cpp:
--------------------------------------------------------------------------------
1 | #include "mathic.h"
2 |
3 | extern "C" {
4 | void libmathicIsPresent(void) {}
5 | }
6 |
--------------------------------------------------------------------------------
/src/mathic.h:
--------------------------------------------------------------------------------
1 | // Include this file to pull in all external Mathic files
2 |
3 | // utilities
4 | #include "mathic/Timer.h"
5 | #include "mathic/ColumnPrinter.h"
6 | #include "mathic/error.h"
7 |
8 | // other data structures
9 | #include "mathic/BitTriangle.h"
10 | #include "mathic/HashTable.h"
11 |
12 | // divisor query data structures
13 | #include "mathic/DivList.h"
14 | #include "mathic/KDTree.h"
15 |
16 | // priority queue data structures
17 | #include "mathic/TourTree.h"
18 | #include "mathic/StlSet.h"
19 | #include "mathic/Heap.h"
20 | #include "mathic/Geobucket.h"
21 | #include "mathic/PairQueue.h"
22 |
23 | // CLI package
24 | #include "mathic/Action.h"
25 | #include "mathic/BoolParameter.h"
26 | #include "mathic/CliParameter.h"
27 | #include "mathic/CliParser.h"
28 | #include "mathic/HelpAction.h"
29 | #include "mathic/IntegerParameter.h"
30 | #include "mathic/StringParameter.h"
31 | #include "mathic/display.h"
32 |
33 | extern "C" {
34 | // Put a C function in the library so that it can be detected by the autoconf
35 | // macro AC_CHECK_LIB. That macro can only check for libraries that contain
36 | // at least one C function.
37 | void libmathicIsPresent(void); // This function does nothing.
38 | }
39 |
--------------------------------------------------------------------------------
/src/mathic/Action.cpp:
--------------------------------------------------------------------------------
1 | #include "Action.h"
2 | #include "error.h"
3 |
4 | namespace mathic {
5 | Action::~Action() {
6 | }
7 |
8 | void Action::directOptions(
9 | std::vector tokens,
10 | CliParser& parser
11 | ) {
12 | if (!tokens.empty()) {
13 | reportError("Expected a dash (-) to indicate an option when reading \"" +
14 | tokens.front() + "\".");
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/mathic/Action.h:
--------------------------------------------------------------------------------
1 | #ifndef MATHIC_ACTION_GUARD
2 | #define MATHIC_ACTION_GUARD
3 |
4 | #include "stdinc.h"
5 | #include
6 | #include
7 |
8 | namespace mathic {
9 | class CliParameter;
10 | class CliParser;
11 |
12 | class Action {
13 | public:
14 | virtual ~Action();
15 |
16 | // Called with tokens that precede any option of the
17 | // form -option. The default is to give an error saying
18 | // that a dash was expected if tokens is not empty.
19 | virtual void directOptions
20 | (std::vector tokens, CliParser& parser);
21 |
22 | // Do what it is this action does.
23 | virtual void performAction() = 0;
24 |
25 | // ***************************************
26 | // **** Information provided by each Action
27 |
28 | // The name of the action.
29 | virtual const char* name() const = 0;
30 |
31 | // More detailed explanation of what the action does.
32 | virtual const char* description() const = 0;
33 |
34 | // One-line summary of the description.
35 | virtual const char* shortDescription() const = 0;
36 |
37 | // Append the parameters for this action to the passed-in container.
38 | // Do not clear the passed-in container.
39 | virtual void pushBackParameters(std::vector& parameters) = 0;
40 |
41 | // Return true if this class is HelpAction.
42 | virtual bool isHelpAction() const {return false;}
43 | };
44 | }
45 |
46 | #endif
47 |
--------------------------------------------------------------------------------
/src/mathic/BitTriangle.cpp:
--------------------------------------------------------------------------------
1 | #include "stdinc.h"
2 | #include "BitTriangle.h"
3 |
4 | namespace mathic {
5 | size_t BitTriangle::getMemoryUse() const
6 | {
7 | size_t sum = mColumns.capacity() * sizeof(mColumns.front());
8 | const size_t stop = mColumns.size();
9 | for (size_t i = 0; i != stop; ++i) {
10 | size_t const capacity = mColumns[i].capacity();
11 | sum += (capacity + 7) / 8; // 8 bits per byte rounded up
12 | }
13 | return sum;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/mathic/BitTriangle.h:
--------------------------------------------------------------------------------
1 | #ifndef MATHIC_BIT_TRIANGLE_GUARD
2 | #define MATHIC_BIT_TRIANGLE_GUARD
3 |
4 | #include "stdinc.h"
5 | #include
6 | #include
7 |
8 | namespace mathic {
9 | // Object that stores a triangular 2-dimensional array of bits. For example:
10 | //
11 | // row
12 | // 3|
13 | // 2| 1
14 | // 1| 0 1
15 | // 0| 0 0 0
16 | // -------
17 | // 0 1 2 3 column
18 | //
19 | // A bit is addressed by a pair (column, row) where the column goes first.
20 | // All valid address pairs have 0 <= row < column < columnCount().
21 | // Columns can be added dynamically.
22 | class BitTriangle {
23 | public:
24 | // Returns how many columns the triangle has
25 | size_t columnCount() const {return mColumns.size();}
26 |
27 | // Returns true if there are no columns in the triangle
28 | bool empty() const {return mColumns.empty();}
29 |
30 | // Adds a new column of the triangle. This increases columnCount() by
31 | // one, and the index of the new column is the previous value of
32 | // columnCount(). The new bits are all set to false initially.
33 | void addColumn() {
34 | size_t const oldSize = mColumns.size();
35 | mColumns.resize(oldSize + 1);
36 | mColumns[oldSize].resize(oldSize);
37 | }
38 |
39 | // Returns the bit in the given column and row. As this is a triangle it
40 | // must be true that row < column.
41 | MATHIC_INLINE bool bit(size_t column, size_t row) const {
42 | MATHIC_ASSERT(column < columnCount());
43 | MATHIC_ASSERT(row < column);
44 | return mColumns[column][row];
45 | }
46 |
47 | // As bit(), but uses max(x,y) as the column and min(x,y) as the
48 | // row.
49 | bool bitUnordered(size_t x, size_t y) const {
50 | MATHIC_ASSERT(x < columnCount());
51 | MATHIC_ASSERT(y < columnCount());
52 | MATHIC_ASSERT(x != y);
53 | if (x < y)
54 | std::swap(x, y);
55 | return bit(x, y);
56 | }
57 |
58 | // Sets the bit in the given column and row. As this is a triangle
59 | // it must be true that column >= row.
60 | MATHIC_INLINE void setBit(size_t column, size_t row, bool value) {
61 | MATHIC_ASSERT(column < columnCount());
62 | MATHIC_ASSERT(row < column);
63 | mColumns[column][row] = value;
64 | }
65 |
66 | // As setBit, but uses max(x,y) as the column and min(x,y) as the
67 | // row.
68 | void setBitUnordered(size_t x, size_t y, bool value) {
69 | MATHIC_ASSERT(x < columnCount());
70 | MATHIC_ASSERT(y < columnCount());
71 | MATHIC_ASSERT(x != y);
72 | if (x < y)
73 | std::swap(x, y);
74 | setBit(x, y, value);
75 | }
76 |
77 | size_t getMemoryUse() const;
78 |
79 | private:
80 | // @todo: use one big array instead of an array of arrays.
81 | std::vector > mColumns;
82 | };
83 | }
84 |
85 | #endif
86 |
--------------------------------------------------------------------------------
/src/mathic/BoolParameter.cpp:
--------------------------------------------------------------------------------
1 | #include "BoolParameter.h"
2 |
3 | #include "error.h"
4 |
5 | namespace mathic {
6 | BoolParameter::BoolParameter(const std::string& name,
7 | const std::string& description,
8 | bool defaultValue):
9 | CliParameter(name, description),
10 | _value(defaultValue) {
11 | }
12 |
13 | std::string BoolParameter::argumentType() const {
14 | return "[BOOL]";
15 | }
16 |
17 | std::string BoolParameter::valueAsString() const {
18 | return _value ? "on" : "off";
19 | }
20 |
21 | void BoolParameter::processArgument(const std::string& argument) {
22 | if (argument.empty() || argument == "on")
23 | _value = true;
24 | else if (argument == "off")
25 | _value = false;
26 | else {
27 | reportError("Option -" + name() + " was given the argument \"" +
28 | argument + "\". The only valid arguments are \"on\" and \"off\".");
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/mathic/BoolParameter.h:
--------------------------------------------------------------------------------
1 | #ifndef MATHIC_BOOL_PARAMETER_GUARD
2 | #define MATHIC_BOOL_PARAMETER_GUARD
3 |
4 | #include "stdinc.h"
5 | #include "CliParameter.h"
6 | #include
7 | #include
8 |
9 | namespace mathic {
10 | class BoolParameter : public CliParameter {
11 | public:
12 | BoolParameter(const std::string& name,
13 | const std::string& description,
14 | bool defaultValue);
15 |
16 | bool value() const {return _value;}
17 | void setValue(bool value) {_value = value;}
18 |
19 | operator bool() const {return value();}
20 | void operator=(bool value) {setValue(value);}
21 |
22 | virtual std::string argumentType() const;
23 | virtual std::string valueAsString() const;
24 | virtual void processArgument(const std::string& argument);
25 |
26 | private:
27 | bool _value;
28 | };
29 | }
30 |
31 | #endif
32 |
--------------------------------------------------------------------------------
/src/mathic/CliParameter.cpp:
--------------------------------------------------------------------------------
1 | #include "CliParameter.h"
2 | #include "error.h"
3 |
4 | namespace mathic {
5 | CliParameter::CliParameter(
6 | const std::string& name,
7 | const std::string& description
8 | ):
9 | _name(name),
10 | _description(description) {
11 | }
12 |
13 | CliParameter::~CliParameter() {
14 | }
15 |
16 | void CliParameter::appendToDescription(const std::string& str) {
17 | _description += str;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/mathic/CliParameter.h:
--------------------------------------------------------------------------------
1 | #ifndef MATHIC_PARAMETER_GUARD
2 | #define MATHIC_PARAMETER_GUARD
3 |
4 | #include "stdinc.h"
5 | #include
6 |
7 | namespace mathic {
8 | class CliParameter {
9 | public:
10 | virtual ~CliParameter();
11 |
12 | const std::string& name() const {return _name;}
13 | const std::string& description() const {return _description;}
14 | void appendToDescription(const std::string& str);
15 |
16 | virtual std::string argumentType() const = 0;
17 | virtual std::string valueAsString() const = 0;
18 | virtual void processArgument(const std::string& argument) = 0;
19 |
20 | protected:
21 | CliParameter(const std::string& name, const std::string& description);
22 |
23 | private:
24 | std::string _name;
25 | std::string _description;
26 | };
27 | }
28 |
29 | #endif
30 |
--------------------------------------------------------------------------------
/src/mathic/CliParser.cpp:
--------------------------------------------------------------------------------
1 | #include "CliParser.h"
2 |
3 | #include "error.h"
4 | #include "CliParameter.h"
5 |
6 | namespace mathic {
7 | namespace {
8 | // We are using a NameFactory just for its prefix-finding functionality, so
9 | // we set the thing being created to be just void pointers that are null.
10 | typedef void* Dummy;
11 | typedef NameFactory ParamNames;
12 | ParamNames makeParamNames(std::vector params) {
13 | ParamNames names("option");
14 | for (size_t i = 0; i < params.size(); ++i) {
15 | const auto makeNull = [](){return std::unique_ptr();};
16 | names.registerProduct(params[i]->name(), makeNull);
17 | }
18 | return names;
19 | }
20 | }
21 |
22 | void CliParser::pushBackRegisteredActionNames(
23 | std::vector& names
24 | ) const {
25 | _actions.namesWithPrefix("", names);
26 | }
27 |
28 |
29 | CliParser::CliParser(): _actions("action") {}
30 |
31 | std::unique_ptr CliParser::createActionWithPrefix(
32 | const std::string& prefix
33 | ) {
34 | return createWithPrefix(_actions, prefix);
35 | }
36 |
37 | std::unique_ptr CliParser::parse(int argc, char** argv) {
38 | std::vector commandLine(argv, argv + argc);
39 | return parse(commandLine);
40 | }
41 |
42 | std::unique_ptr CliParser::parse
43 | (const std::vector& commandLine) {
44 | if (commandLine.empty())
45 | throwError("No action specified.");
46 | std::unique_ptr action = createActionWithPrefix(commandLine[0]);
47 |
48 | std::vector params;
49 | action->pushBackParameters(params);
50 | ParamNames paramNames = makeParamNames(params);
51 |
52 | std::vector options;
53 | std::vector directOptions;
54 | bool sawDash = false;
55 | for (size_t i = 1; i < commandLine.size(); ++i) {
56 | if (commandLine[i].empty())
57 | continue;
58 | if (commandLine[i][0] == '-')
59 | sawDash = true;
60 | if (sawDash)
61 | options.push_back(commandLine[i]);
62 | else
63 | directOptions.push_back(commandLine[i]);
64 | }
65 |
66 | action->directOptions(directOptions, *this);
67 |
68 | size_t i = 1;
69 | for (size_t i = 0; i < options.size(); ++i) {
70 | std::string const& token = options[i];
71 | if (token[0] != '-')
72 | reportError("Expected an option when reading \"" +
73 | token + "\", but options start with a dash (-).\n");
74 | std::string noDash(token.begin() + 1, token.end());
75 | std::string name = uniqueNameWithPrefix(paramNames, noDash);
76 |
77 | std::string optionArgument;
78 | if (i + 1 < options.size() && options[i + 1][0] != '-') {
79 | optionArgument = options[i + 1];
80 | ++i;
81 | }
82 |
83 | for (std::vector::iterator it = params.begin();; ++it) {
84 | if (it == params.end()) {
85 | // shouldn't get here as name was recognized above
86 | reportInternalError("Processing non-existent option \""
87 | + name + "\".");
88 | }
89 | if ((*it)->name() == name) {
90 | (*it)->processArgument(optionArgument);
91 | break;
92 | }
93 | }
94 | }
95 | return action;
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/mathic/CliParser.h:
--------------------------------------------------------------------------------
1 | #ifndef MATHIC_CLI_PARSER_GUARD
2 | #define MATHIC_CLI_PARSER_GUARD
3 |
4 | #include "NameFactory.h"
5 | #include "Action.h"
6 |
7 | namespace mathic {
8 | class CliParser {
9 | public:
10 | CliParser();
11 |
12 | template
13 | void registerAction(const std::string& name);
14 |
15 | // picks the name up from ConcreteAction::staticName().
16 | template
17 | void registerAction();
18 |
19 | void registerHelpAction
20 | (const std::string& preMessage, const std::string& postMessage);
21 |
22 | void pushBackRegisteredActionNames(
23 | std::vector& names
24 | ) const;
25 |
26 | const std::string& helpPreMessage() const {return _helpPreMessage;}
27 | const std::string& helpPostMessage() const {return _helpPostMessage;}
28 |
29 | std::unique_ptr parse(int argc, char** argv);
30 | std::unique_ptr parse(const std::vector& commandLine);
31 | std::unique_ptr createActionWithPrefix(const std::string& prefix);
32 |
33 | private:
34 | NameFactory _actions;
35 | std::string _helpPreMessage;
36 | std::string _helpPostMessage;
37 | };
38 |
39 | template
40 | void CliParser::registerAction(const std::string& name) {
41 | nameFactoryRegister(_actions, name);
42 | };
43 |
44 | template
45 | void CliParser::registerAction() {
46 | nameFactoryRegister(_actions);
47 | };
48 | }
49 |
50 | #endif
51 |
--------------------------------------------------------------------------------
/src/mathic/ColumnPrinter.cpp:
--------------------------------------------------------------------------------
1 | #include "ColumnPrinter.h"
2 |
3 | namespace mathic {
4 | namespace {
5 | size_t getLineWidth(const std::string& str, size_t pos) {
6 | size_t startPos = pos;
7 | while (pos < str.size() && str[pos] != '\n' && str[pos] != '\0')
8 | ++pos;
9 | return pos - startPos;
10 | }
11 |
12 | void printChars(std::ostream& out, size_t howMany, const char c) {
13 | while (howMany > 0) {
14 | out << c;
15 | --howMany;
16 | }
17 | }
18 | }
19 |
20 | ColumnPrinter::ColumnPrinter(size_t columnCount):
21 | _cols() {
22 | while (columnCount > 0) {
23 | addColumn();
24 | --columnCount;
25 | }
26 | }
27 |
28 | void ColumnPrinter::setPrefix(const std::string& prefix) {
29 | _prefix = prefix;
30 | }
31 |
32 | std::ostream& ColumnPrinter::addColumn(bool flushLeft,
33 | const std::string& prefix,
34 | const std::string& suffix) {
35 | std::unique_ptr col(new Col());
36 | col->prefix = prefix;
37 | col->suffix = suffix;
38 | col->flushLeft = flushLeft;
39 |
40 | _cols.emplace_back(std::move(col));
41 |
42 | return _cols.back()->text;
43 | }
44 |
45 | size_t ColumnPrinter::getColumnCount() const {
46 | return _cols.size();
47 | }
48 |
49 | std::ostream& ColumnPrinter::operator[](size_t col) {
50 | MATHIC_ASSERT(col < getColumnCount());
51 | return _cols[col]->text;
52 | }
53 |
54 | void ColumnPrinter::repeatToEndOfLine(const char repeatThis, size_t col) {
55 | MATHIC_ASSERT(col < getColumnCount());
56 | (*this)[col] << '\0' << repeatThis;
57 | }
58 |
59 | void ColumnPrinter::repeatToEndOfLine(const char repeatThis) {
60 | MATHIC_ASSERT(repeatThis != '\n');
61 | for (size_t col = 0; col < getColumnCount(); ++col)
62 | repeatToEndOfLine(repeatThis, col);
63 | }
64 |
65 | void ColumnPrinter::print(std::ostream& out) const {
66 | // stringstream::str() copies the string, so we need
67 | // to extract all the strings and store them to avoid copying
68 | // at every access.
69 | std::vector texts(getColumnCount());
70 | for (size_t col = 0; col < getColumnCount(); ++col)
71 | texts[col] = _cols[col]->text.str();
72 |
73 | // Calculate the width of each column.
74 | std::vector widths(getColumnCount());
75 | for (size_t col = 0; col < getColumnCount(); ++col) {
76 | const auto& text = texts[col];
77 | size_t maxWidth = 0;
78 |
79 | size_t pos = 0;
80 | while (pos < text.size()) {
81 | size_t width = getLineWidth(text, pos);
82 | if (width > maxWidth)
83 | maxWidth = width;
84 |
85 | // We can't just increment pos unconditionally by width + 1, as
86 | // that could result in an overflow.
87 | pos += width;
88 | if (pos == text.size())
89 | break;
90 | if (text[pos] == '\0') {
91 | ++pos;
92 | if (pos == text.size())
93 | break;
94 | ++pos;
95 | } else if (text[pos] == '\n')
96 | ++pos;
97 | }
98 | widths[col] = maxWidth;
99 | }
100 |
101 | // Print each row
102 | std::vector poses(getColumnCount());
103 | while (true) {
104 | bool done = true;
105 | for (size_t col = 0; col < getColumnCount(); ++col) {
106 | if (poses[col] < texts[col].size()) {
107 | done = false;
108 | break;
109 | }
110 | }
111 | if (done)
112 | break;
113 |
114 | out << _prefix;
115 | for (size_t col = 0; col < getColumnCount(); ++col) {
116 | out << _cols[col]->prefix;
117 |
118 | const std::string& text = texts[col];
119 | size_t& pos = poses[col];
120 | size_t width = getLineWidth(text, pos);
121 |
122 | char padChar = ' ';
123 | if (
124 | pos + width < text.size() &&
125 | text[pos + width] == '\0' &&
126 | pos + width + 1 < text.size()
127 | ) {
128 | padChar = text[pos + width + 1];
129 | }
130 |
131 | if (!_cols[col]->flushLeft)
132 | printChars(out, widths[col] - width, padChar);
133 |
134 | while (pos < text.size()) {
135 | if (text[pos] == '\n') {
136 | ++pos;
137 | break;
138 | }
139 | if (text[pos] == '\0') {
140 | ++pos;
141 | if (pos < text.size()) {
142 | MATHIC_ASSERT(text[pos] == padChar);
143 | ++pos;
144 | }
145 | break;
146 | }
147 | out << text[pos];
148 | ++pos;
149 | }
150 |
151 | if (_cols[col]->flushLeft)
152 | printChars(out, widths[col] - width, padChar);
153 |
154 | out << _cols[col]->suffix;
155 | }
156 | out << '\n';
157 | }
158 | }
159 |
160 | std::string ColumnPrinter::commafy(const unsigned long long l) {
161 | std::stringstream out;
162 | out << l;
163 | const auto uncomma = out.str();
164 | std::string str;
165 | for (size_t i = 0; i < uncomma.size(); ++i) {
166 | str += uncomma[i];
167 | if (i != uncomma.size() - 1 && ((uncomma.size() - i) % 3) == 1)
168 | str += ',';
169 | }
170 | return str;
171 | }
172 |
173 | std::string ColumnPrinter::percentInteger(
174 | const unsigned long long numerator,
175 | const unsigned long long denominator
176 | ) {
177 | return ratioInteger(numerator * 100, denominator) + '%';
178 | }
179 |
180 | std::string ColumnPrinter::percentDouble(
181 | const double numerator,
182 | const double denominator
183 | ) {
184 | return ratioDouble(numerator * 100, denominator) + '%';
185 | }
186 |
187 | std::string ColumnPrinter::percentIntegerFixed(
188 | const unsigned long long numerator,
189 | const unsigned long long denominator
190 | ) {
191 | auto str = percentInteger(numerator, denominator);
192 | const size_t maxSize = 6;
193 | MATHIC_ASSERT(maxSize == std::string("100.0%").size());
194 | const auto size = str.size();
195 | if (size > maxSize)
196 | return std::move(str);
197 | return std::string(maxSize - str.size(), ' ') + std::move(str);
198 | }
199 |
200 | std::string ColumnPrinter::percentDouble(const double ratio) {
201 | return oneDecimal(ratio * 100) + '%';
202 | }
203 |
204 | std::string ColumnPrinter::ratioInteger(
205 | const unsigned long long numerator,
206 | const unsigned long long denominator
207 | ) {
208 | if (denominator == 0)
209 | return std::string(numerator == 0 ? "0/0" : "?/0");
210 | return oneDecimal(static_cast(numerator) / denominator);
211 | }
212 |
213 | std::string ColumnPrinter::ratioDouble(
214 | const double numerator,
215 | const double denominator
216 | ) {
217 | const auto epsilon = 0.000000001;
218 | if (-epsilon < denominator && denominator < epsilon) {
219 | if (-epsilon < numerator && numerator < epsilon)
220 | return "0/0";
221 | else
222 | return "?/0";
223 | }
224 | return oneDecimal(static_cast(numerator) / denominator);
225 | }
226 |
227 | std::string ColumnPrinter::oneDecimal(const double d) {
228 | std::ostringstream out;
229 | unsigned long long l = static_cast(d * 10 + 0.5);
230 | out << l / 10 << '.' << l % 10;
231 | return out.str();
232 | }
233 |
234 | std::string ColumnPrinter::withSIPrefix(unsigned long long l) {
235 | std::ostringstream out;
236 | if (l < 1000)
237 | out << l;
238 | else {
239 | const char* const units[] = {"k", "M", "G", "T"};
240 | const size_t unitCount = sizeof(units) / sizeof(*units);
241 | double amount = static_cast(l) / 1000.0;
242 | size_t i = 0;
243 | // the stop condition is at 999.5 because that value will get
244 | // rounded to 1000.0.
245 | for (i = 0; i < unitCount && amount >= 999.95; ++i)
246 | amount /= 1000.0;
247 | out << oneDecimal(amount) << units[i];
248 | }
249 | return out.str();
250 | }
251 |
252 | std::string ColumnPrinter::bytesInUnit(const unsigned long long bytes) {
253 | std::ostringstream out;
254 | if (bytes < 1024)
255 | out << bytes << 'B';
256 | else {
257 | const char* const units[] = {"kB", "MB", "GB", "TB"};
258 | const size_t unitCount = sizeof(units) / sizeof(*units);
259 | double amount = static_cast(bytes) / 1024.0;
260 | size_t i = 0;
261 | // the stop condition is 1023.95 because that value will get
262 | // rounded to 1024.0.
263 | for (i = 0; i < unitCount && amount >= 1023.95; ++i)
264 | amount /= 1024.0;
265 | out << oneDecimal(amount) << units[i];
266 | }
267 | return out.str();
268 | }
269 |
270 |
271 | std::ostream& operator<<(
272 | std::ostream& out,
273 | const ColumnPrinter& printer
274 | ) {
275 | printer.print(out);
276 | return out;
277 | }
278 |
279 | void print(FILE* out, const ColumnPrinter& pr) {
280 | std::ostringstream str;
281 | str << pr;
282 | fputs(str.str().c_str(), out);
283 | }
284 | }
285 |
--------------------------------------------------------------------------------
/src/mathic/ColumnPrinter.h:
--------------------------------------------------------------------------------
1 | #ifndef MATHIC_COLUMN_PRINTER_GUARD
2 | #define MATHIC_COLUMN_PRINTER_GUARD
3 |
4 | #include "stdinc.h"
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | namespace mathic {
12 | class ColumnPrinter {
13 | public:
14 | ColumnPrinter(size_t columnCount = 0);
15 |
16 | void setPrefix(const std::string& prefix);
17 | std::ostream& addColumn(
18 | bool flushLeft = true,
19 | const std::string& prefix = " ",
20 | const std::string& suffix = ""
21 | );
22 | size_t getColumnCount() const;
23 |
24 | std::ostream& operator[](size_t col);
25 |
26 | /// Inserts a newline after padding the current line with repeatThis
27 | /// chars until it fills the column width.
28 | void repeatToEndOfLine(const char repeatThis, size_t col);
29 |
30 | /// Works on all columns.
31 | void repeatToEndOfLine(const char repeatThis);
32 |
33 | void print(std::ostream& out) const;
34 |
35 | /// Returns "123,456,789" for parameter value 123456789.
36 | static std::string commafy(unsigned long long l);
37 |
38 | /// Returns "123.4G" for parameter value 123456789. So the SI prefix is a
39 | /// suffix of the returned string, yet it is still called an SI *prefix*
40 | /// because these are usually used as prefixes to units such as in Km.
41 | static std::string withSIPrefix(unsigned long long l);
42 |
43 | /** returns (3,100) as "3.0%". */
44 | static std::string percentInteger(
45 | unsigned long long numerator,
46 | unsigned long long denominator
47 | );
48 | static std::string percentDouble(double numerator, double denominator);
49 |
50 | /** returns (3,100) as " 3.0%". The string always has the same length for
51 | ratios equal to or less than 999.9%. */
52 | static std::string percentIntegerFixed(
53 | unsigned long long numerator,
54 | unsigned long long denominator);
55 |
56 | /** returns 0.7565 as "75.7%". */
57 | static std::string percentDouble(double ratio);
58 |
59 | /** Returns (7,4) as "1.8" */
60 | static std::string ratioInteger(
61 | unsigned long long numerator,
62 | unsigned long long denominator
63 | );
64 | static std::string ratioDouble(double numerator, double denominator);
65 |
66 | /** Returns d as a string printed to 1 decimal place, rounding up at 0.5 */
67 | static std::string oneDecimal(double d);
68 |
69 | /** Prints as X bytes, X kilobytes, X megabytes etc. */
70 | static std::string bytesInUnit(unsigned long long bytes);
71 |
72 | private:
73 | struct Col {
74 | std::string prefix;
75 | std::stringstream text;
76 | std::string suffix;
77 | bool flushLeft;
78 | std::vector > repeatToEndOfLine;
79 | };
80 | std::vector> _cols;
81 | std::string _prefix;
82 | };
83 |
84 | std::ostream& operator<<(std::ostream& out, const ColumnPrinter& printer);
85 | void print(FILE* out, const ColumnPrinter& pr);
86 | }
87 |
88 | #endif
89 |
--------------------------------------------------------------------------------
/src/mathic/ComTree.h:
--------------------------------------------------------------------------------
1 | #ifndef MATHIC_COM_TREE_GUARD
2 | #define MATHIC_COM_TREE_GUARD
3 |
4 | #include "stdinc.h"
5 | #include
6 |
7 | namespace mathic {
8 | /** This class packs a complete binary tree in a vector.
9 |
10 | The idea is to have the root at index 1, and then the left child of node n
11 | will be at index 2n and the right child will be at index 2n + 1. The
12 | corresponding formulas when indexes start at 0 take more computation, so
13 | we need a 1-based array so we can't use std::vector.
14 |
15 | Also, when sizeof(Entry) is a power of 2 it is faster to keep track of
16 | i * sizeof(Entry) than directly keeping track of an index i. This doesn't
17 | work well when sizeof(Entry) is not a power of two. So we need both
18 | possibilities. That is why this class never exposes indexes. Instead
19 | you interact with Node objects that serve the role of an index, but the
20 | precise value it stores is encapsulated. This way you can't do something
21 | like _array[i * sizeof(Entry)] by accident. Client code also does not
22 | need to (indeed, can't) be aware of how indexes are calculated, stored and
23 | looked up.
24 |
25 | If FastIndex is false, then Nodes contain an index i. If FastIndex is
26 | true, then Nodes contain the byte offset i * sizeof(Entry). FastIndex must
27 | be false if sizeof(Entry) is not a power of two.
28 | */
29 | template
30 | class ComTree {
31 | public:
32 | class Node;
33 | ComTree(size_t initialCapacity = 0);
34 | ComTree(const ComTree& tree, size_t minCapacity = 0);
35 | ComTree(ComTree&& tree);
36 |
37 | ~ComTree() {
38 | MATHIC_ASSERT(isValid());
39 | delete[](_arrayKeepAlive);
40 | }
41 |
42 | Entry& operator[](Node n);
43 | const Entry& operator[](Node n) const;
44 |
45 | bool empty() const {return _lastLeaf == Node(0);}
46 | size_t size() const {return _lastLeaf.getNormalIndex();}
47 | size_t capacity() const {return _capacityEnd.getNormalIndex();}
48 | Node lastLeaf() const {return _lastLeaf;}
49 |
50 | void pushBack(const Entry& value);
51 | void pushBackWithCapacity(const Entry& value);
52 | void popBack();
53 |
54 | bool hasFreeCapacity(size_t extraCapacity) const;
55 | void increaseCapacity();
56 | void swap(ComTree& tree);
57 |
58 | class Node {
59 | public:
60 | Node(): _index(fi ? S : 1) {} // the root node is the default
61 |
62 | Node parent() const;
63 | Node left() const;
64 | Node right() const;
65 | Node sibling() const;
66 | Node leftSibling() const;
67 | Node next() const;
68 | Node next(size_t count) const;
69 | Node prev() const;
70 | Node& operator++() {*this = next(); return *this;}
71 |
72 | bool isRoot() const {return *this == Node();}
73 |
74 | // Returns a size_t instead of a bool so that the compiler does not
75 | // have to convert to bool (this silences a MSVC performance warning).
76 | size_t isLeft() const {return fi ? !(_index & S) : !(_index & 1);}
77 |
78 | // Returns a size_t instead of a bool so that the compiler does not
79 | // have to convert to bool (this silences a MSVC performance warning).
80 | size_t isRight() const {return fi ? _index & S : _index & 1;}
81 |
82 | bool operator<(Node node) const {return _index < node._index;}
83 | bool operator<=(Node node) const {return _index <= node._index;}
84 | bool operator>(Node node) const {return _index > node._index;}
85 | bool operator>=(Node node) const {return _index >= node._index;}
86 | bool operator==(Node node) const {return _index == node._index;}
87 | bool operator!=(Node node) const {return _index != node._index;}
88 |
89 | //private:
90 | friend class ComTree;
91 | static const bool fi = FastIndex;
92 | static const size_t S = sizeof(Entry);
93 | explicit Node(size_t i): _index(i) {}
94 | size_t getNormalIndex() const {return fi ? _index / S : _index;}
95 | size_t _index;
96 | };
97 |
98 | void print(std::ostream& out) const;
99 |
100 | void clear();
101 |
102 | size_t getMemoryUse() const;
103 |
104 | /// Asserts internal invariants if asserts are turned on.
105 | bool isValid() const;
106 |
107 | private:
108 | ComTree& operator=(const ComTree& tree) const; // not available
109 |
110 | Entry* _array;
111 |
112 | /// Macaulay 2 uses Mathic and Macaulay 2 also uses the Boehm garbage
113 | /// collector. Since _array points to a place before the array we
114 | /// are using, that array will be garbage collected if we do not
115 | /// keep around a second pointer that does point into the array.
116 | /// That is the purpose of _arrayKeepAlive.
117 | Entry* _arrayKeepAlive;
118 |
119 | Node _lastLeaf;
120 | Node _capacityEnd;
121 | };
122 |
123 | template
124 | void ComTree::clear() {
125 | _lastLeaf = Node(0);
126 | }
127 |
128 | template
129 | size_t ComTree::getMemoryUse() const {
130 | return capacity() * sizeof(E);
131 | }
132 |
133 | template
134 | std::ostream& operator<<(std::ostream& out, const ComTree& tree) {
135 | tree.print(out);
136 | return out;
137 | }
138 |
139 | template
140 | ComTree::ComTree(size_t initialCapacity):
141 | _array(static_cast(0) - 1),
142 | _arrayKeepAlive(0),
143 | _lastLeaf(0),
144 | _capacityEnd(Node(0).next(initialCapacity))
145 | {
146 | if (initialCapacity > 0) {
147 | _arrayKeepAlive = new E[initialCapacity];
148 | _array = _arrayKeepAlive - 1;
149 | }
150 | MATHIC_ASSERT(isValid());
151 | }
152 |
153 | template
154 | ComTree::ComTree(const ComTree& tree, size_t minCapacity):
155 | _array(static_cast(0) - 1),
156 | _arrayKeepAlive(0),
157 | _lastLeaf(tree._lastLeaf)
158 | {
159 | if (tree.size() > minCapacity)
160 | minCapacity = tree.size();
161 | _capacityEnd = Node(0).next(minCapacity);
162 | if (minCapacity != 0) {
163 | _arrayKeepAlive = new E[minCapacity];
164 | _array = _arrayKeepAlive - 1;
165 | for (Node i; i <= tree.lastLeaf(); ++i)
166 | (*this)[i] = tree[i];
167 | }
168 |
169 | MATHIC_ASSERT(isValid());
170 | }
171 |
172 | template
173 | ComTree::ComTree(ComTree&& tree):
174 | _array(tree._array),
175 | _arrayKeepAlive(tree._arrayKeepAlive),
176 | _lastLeaf(tree._lastLeaf),
177 | _capacityEnd(tree._capacityEnd)
178 | {
179 | tree._array = static_cast(0) - 1;
180 | tree._arrayKeepAlive = 0;
181 | _lastLeaf = Node(0);
182 | _capacityEnd = Node(0);
183 | }
184 |
185 | template
186 | inline E& ComTree::operator[](Node n) {
187 | MATHIC_ASSERT(_array == _arrayKeepAlive - 1);
188 | if (!FI)
189 | return _array[n._index];
190 | char* base = reinterpret_cast(_array);
191 | E* element = reinterpret_cast(base + n._index);
192 | MATHIC_ASSERT(element == &(_array[n._index / sizeof(E)]));
193 | return *element;
194 | }
195 |
196 | template
197 | inline const E& ComTree::operator[](Node n) const {
198 | return const_cast*>(this)->operator[](n);
199 | }
200 |
201 | template
202 | void ComTree::pushBack(const E& value) {
203 | if (_lastLeaf == _capacityEnd)
204 | increaseCapacity();
205 | _lastLeaf = _lastLeaf.next();
206 | (*this)[lastLeaf()] = value;
207 | }
208 |
209 | template
210 | void ComTree::pushBackWithCapacity(const E& value) {
211 | MATHIC_ASSERT(_lastLeaf != _capacityEnd);
212 | _lastLeaf = _lastLeaf.next();
213 | (*this)[lastLeaf()] = value;
214 | }
215 |
216 | template
217 | void ComTree::popBack() {
218 | MATHIC_ASSERT(_lastLeaf >= Node());
219 | _lastLeaf = _lastLeaf.prev();
220 | }
221 |
222 | template
223 | void ComTree::swap(ComTree& tree) {
224 | MATHIC_ASSERT(isValid());
225 | MATHIC_ASSERT(tree.isValid());
226 |
227 | std::swap(_array, tree._array);
228 | std::swap(_arrayKeepAlive, tree._arrayKeepAlive);
229 | std::swap(_lastLeaf, tree._lastLeaf);
230 | std::swap(_capacityEnd, tree._capacityEnd);
231 |
232 | MATHIC_ASSERT(isValid());
233 | MATHIC_ASSERT(tree.isValid());
234 | }
235 |
236 | template
237 | typename ComTree::Node ComTree::Node::parent() const {
238 | return fi ? Node((_index / (2 * S)) * S) : Node(_index / 2);
239 | }
240 |
241 | template
242 | typename ComTree::Node ComTree::Node::left() const {
243 | return Node(2 * _index);
244 | }
245 |
246 | template
247 | typename ComTree::Node ComTree::Node::right() const {
248 | return fi ? Node(2 * _index + S) : Node(2 * _index + 1);
249 | }
250 |
251 | template
252 | typename ComTree::Node ComTree::Node::sibling() const {
253 | return fi ? Node(_index ^ S) : Node(_index ^ 1);
254 | }
255 |
256 | template
257 | typename ComTree::Node ComTree::Node::leftSibling() const {
258 | return fi ? Node(_index & ~S) : Node(_index & ~1);
259 | }
260 |
261 | template
262 | typename ComTree::Node ComTree::Node::next() const {
263 | return fi ? Node(_index + S) : Node(_index + 1);
264 | }
265 |
266 | template
267 | typename ComTree::Node ComTree::Node::next(size_t count) const {
268 | return fi ? Node(_index + S * count) : Node(_index + count);
269 | }
270 |
271 | template
272 | typename ComTree::Node ComTree::Node::prev() const {
273 | return fi ? Node(_index - S) : Node(_index - 1);
274 | }
275 |
276 | template
277 | void ComTree::print(std::ostream& out) const {
278 | Node last = lastLeaf();
279 | for (Node i; i <= last; i = i.next()) {
280 | if ((i._index & (i._index - 1)) == 0) // if i._index is a power of 2
281 | out << "\n " << i._index << ':';
282 | out << ' ' << (*this)[i];
283 | }
284 | out << "}\n";
285 | }
286 |
287 | template