summaryrefslogtreecommitdiff
path: root/src/Bitmap_cubical_complex
diff options
context:
space:
mode:
Diffstat (limited to 'src/Bitmap_cubical_complex')
-rw-r--r--src/Bitmap_cubical_complex/doc/COPYRIGHT12
-rw-r--r--src/Bitmap_cubical_complex/doc/Cubical_complex_representation.ipe732
-rw-r--r--src/Bitmap_cubical_complex/doc/Cubical_complex_representation.pngbin0 -> 19167 bytes
-rw-r--r--src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h110
-rw-r--r--src/Bitmap_cubical_complex/doc/bitmapAllCubes.pngbin0 -> 38944 bytes
-rw-r--r--src/Bitmap_cubical_complex/doc/exampleBitmap.pngbin0 -> 2549 bytes
-rw-r--r--src/Bitmap_cubical_complex/example/CMakeLists.txt10
-rw-r--r--src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp70
-rw-r--r--src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h570
-rw-r--r--src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h133
-rw-r--r--src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h857
-rw-r--r--src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h384
-rw-r--r--src/Bitmap_cubical_complex/test/Bitmap_test.cpp1581
-rw-r--r--src/Bitmap_cubical_complex/test/CMakeLists.txt14
-rw-r--r--src/Bitmap_cubical_complex/utilities/CMakeLists.txt28
-rw-r--r--src/Bitmap_cubical_complex/utilities/cubical_complex_persistence.cpp68
-rw-r--r--src/Bitmap_cubical_complex/utilities/cubicalcomplex.md37
-rw-r--r--src/Bitmap_cubical_complex/utilities/periodic_cubical_complex_persistence.cpp70
18 files changed, 4676 insertions, 0 deletions
diff --git a/src/Bitmap_cubical_complex/doc/COPYRIGHT b/src/Bitmap_cubical_complex/doc/COPYRIGHT
new file mode 100644
index 00000000..61f17f6d
--- /dev/null
+++ b/src/Bitmap_cubical_complex/doc/COPYRIGHT
@@ -0,0 +1,12 @@
+The files of this directory are part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+
+Author(s): Vincent Rouvreau
+
+Copyright (C) 2015 Inria
+
+This gives everyone the freedoms to use openFrameworks in any context:
+commercial or non-commercial, public or private, open or closed source.
+
+You should have received a copy of the MIT License along with this program.
+If not, see https://opensource.org/licenses/MIT. \ No newline at end of file
diff --git a/src/Bitmap_cubical_complex/doc/Cubical_complex_representation.ipe b/src/Bitmap_cubical_complex/doc/Cubical_complex_representation.ipe
new file mode 100644
index 00000000..bec245e7
--- /dev/null
+++ b/src/Bitmap_cubical_complex/doc/Cubical_complex_representation.ipe
@@ -0,0 +1,732 @@
+<?xml version="1.0"?>
+<!DOCTYPE ipe SYSTEM "ipe.dtd">
+<ipe version="70107" creator="Ipe 7.1.10">
+<info created="D:20160330102945" modified="D:20160330104654"/>
+<ipestyle name="basic">
+<symbol name="arrow/arc(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/farc(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/ptarc(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-0.8 0 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/fptarc(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-0.8 0 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="mark/circle(sx)" transformations="translations">
+<path fill="sym-stroke">
+0.6 0 0 0.6 0 0 e
+0.4 0 0 0.4 0 0 e
+</path>
+</symbol>
+<symbol name="mark/disk(sx)" transformations="translations">
+<path fill="sym-stroke">
+0.6 0 0 0.6 0 0 e
+</path>
+</symbol>
+<symbol name="mark/fdisk(sfx)" transformations="translations">
+<group>
+<path fill="sym-fill">
+0.5 0 0 0.5 0 0 e
+</path>
+<path fill="sym-stroke" fillrule="eofill">
+0.6 0 0 0.6 0 0 e
+0.4 0 0 0.4 0 0 e
+</path>
+</group>
+</symbol>
+<symbol name="mark/box(sx)" transformations="translations">
+<path fill="sym-stroke" fillrule="eofill">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+-0.4 -0.4 m
+0.4 -0.4 l
+0.4 0.4 l
+-0.4 0.4 l
+h
+</path>
+</symbol>
+<symbol name="mark/square(sx)" transformations="translations">
+<path fill="sym-stroke">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+</path>
+</symbol>
+<symbol name="mark/fsquare(sfx)" transformations="translations">
+<group>
+<path fill="sym-fill">
+-0.5 -0.5 m
+0.5 -0.5 l
+0.5 0.5 l
+-0.5 0.5 l
+h
+</path>
+<path fill="sym-stroke" fillrule="eofill">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+-0.4 -0.4 m
+0.4 -0.4 l
+0.4 0.4 l
+-0.4 0.4 l
+h
+</path>
+</group>
+</symbol>
+<symbol name="mark/cross(sx)" transformations="translations">
+<group>
+<path fill="sym-stroke">
+-0.43 -0.57 m
+0.57 0.43 l
+0.43 0.57 l
+-0.57 -0.43 l
+h
+</path>
+<path fill="sym-stroke">
+-0.43 0.57 m
+0.57 -0.43 l
+0.43 -0.57 l
+-0.57 0.43 l
+h
+</path>
+</group>
+</symbol>
+<symbol name="arrow/fnormal(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/pointed(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-0.8 0 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/fpointed(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-0.8 0 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/linear(spx)">
+<path stroke="sym-stroke" pen="sym-pen">
+-1 0.333 m
+0 0 l
+-1 -0.333 l
+</path>
+</symbol>
+<symbol name="arrow/fdouble(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+-1 0 m
+-2 0.333 l
+-2 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/double(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+-1 0 m
+-2 0.333 l
+-2 -0.333 l
+h
+</path>
+</symbol>
+<pen name="heavier" value="0.8"/>
+<pen name="fat" value="1.2"/>
+<pen name="ultrafat" value="2"/>
+<symbolsize name="large" value="5"/>
+<symbolsize name="small" value="2"/>
+<symbolsize name="tiny" value="1.1"/>
+<arrowsize name="large" value="10"/>
+<arrowsize name="small" value="5"/>
+<arrowsize name="tiny" value="3"/>
+<color name="red" value="1 0 0"/>
+<color name="green" value="0 1 0"/>
+<color name="blue" value="0 0 1"/>
+<color name="yellow" value="1 1 0"/>
+<color name="orange" value="1 0.647 0"/>
+<color name="gold" value="1 0.843 0"/>
+<color name="purple" value="0.627 0.125 0.941"/>
+<color name="gray" value="0.745"/>
+<color name="brown" value="0.647 0.165 0.165"/>
+<color name="navy" value="0 0 0.502"/>
+<color name="pink" value="1 0.753 0.796"/>
+<color name="seagreen" value="0.18 0.545 0.341"/>
+<color name="turquoise" value="0.251 0.878 0.816"/>
+<color name="violet" value="0.933 0.51 0.933"/>
+<color name="darkblue" value="0 0 0.545"/>
+<color name="darkcyan" value="0 0.545 0.545"/>
+<color name="darkgray" value="0.663"/>
+<color name="darkgreen" value="0 0.392 0"/>
+<color name="darkmagenta" value="0.545 0 0.545"/>
+<color name="darkorange" value="1 0.549 0"/>
+<color name="darkred" value="0.545 0 0"/>
+<color name="lightblue" value="0.678 0.847 0.902"/>
+<color name="lightcyan" value="0.878 1 1"/>
+<color name="lightgray" value="0.827"/>
+<color name="lightgreen" value="0.565 0.933 0.565"/>
+<color name="lightyellow" value="1 1 0.878"/>
+<dashstyle name="dashed" value="[4] 0"/>
+<dashstyle name="dotted" value="[1 3] 0"/>
+<dashstyle name="dash dotted" value="[4 2 1 2] 0"/>
+<dashstyle name="dash dot dotted" value="[4 2 1 2 1 2] 0"/>
+<textsize name="large" value="\large"/>
+<textsize name="Large" value="\Large"/>
+<textsize name="LARGE" value="\LARGE"/>
+<textsize name="huge" value="\huge"/>
+<textsize name="Huge" value="\Huge"/>
+<textsize name="small" value="\small"/>
+<textsize name="footnote" value="\footnotesize"/>
+<textsize name="tiny" value="\tiny"/>
+<textstyle name="center" begin="\begin{center}" end="\end{center}"/>
+<textstyle name="itemize" begin="\begin{itemize}" end="\end{itemize}"/>
+<textstyle name="item" begin="\begin{itemize}\item{}" end="\end{itemize}"/>
+<gridsize name="4 pts" value="4"/>
+<gridsize name="8 pts (~3 mm)" value="8"/>
+<gridsize name="16 pts (~6 mm)" value="16"/>
+<gridsize name="32 pts (~12 mm)" value="32"/>
+<gridsize name="10 pts (~3.5 mm)" value="10"/>
+<gridsize name="20 pts (~7 mm)" value="20"/>
+<gridsize name="14 pts (~5 mm)" value="14"/>
+<gridsize name="28 pts (~10 mm)" value="28"/>
+<gridsize name="56 pts (~20 mm)" value="56"/>
+<anglesize name="90 deg" value="90"/>
+<anglesize name="60 deg" value="60"/>
+<anglesize name="45 deg" value="45"/>
+<anglesize name="30 deg" value="30"/>
+<anglesize name="22.5 deg" value="22.5"/>
+<opacity name="10%" value="0.1"/>
+<opacity name="30%" value="0.3"/>
+<opacity name="50%" value="0.5"/>
+<opacity name="75%" value="0.75"/>
+<tiling name="falling" angle="-60" step="4" width="1"/>
+<tiling name="rising" angle="30" step="4" width="1"/>
+</ipestyle>
+<page>
+<layer name="alpha"/>
+<view layers="alpha" active="alpha"/>
+<path layer="alpha" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<text transformations="translations" pos="180 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">0</text>
+<path stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<text transformations="translations" pos="212 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">1</text>
+<path matrix="1 0 0 1 64 0" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<text matrix="1 0 0 1 64 0" transformations="translations" pos="180 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">2</text>
+<path matrix="1 0 0 1 64 0" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<text matrix="1 0 0 1 64 0" transformations="translations" pos="212 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">3</text>
+<path matrix="1 0 0 1 128 0" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<text matrix="1 0 0 1 128 0" transformations="translations" pos="180 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">4</text>
+<path matrix="1 0 0 1 128 0" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<text matrix="1 0 0 1 128 0" transformations="translations" pos="212 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">5</text>
+<path matrix="1 0 0 1 192 0" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<text matrix="1 0 0 1 192 0" transformations="translations" pos="180 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">6</text>
+<path matrix="1 0 0 1 192 0" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<text matrix="1 0 0 1 192 0" transformations="translations" pos="212 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">7</text>
+<path matrix="1 0 0 1 256 0" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<text matrix="1 0 0 1 256 0" transformations="translations" pos="180 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">8</text>
+<path matrix="1 0 0 1 0 -32" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<text matrix="1 0 0 1 0 -48" transformations="translations" pos="180 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">1</text>
+<path matrix="1 0 0 1 0 -32" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 64 -32" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<text matrix="1 0 0 1 64 -48" transformations="translations" pos="180 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">2</text>
+<path matrix="1 0 0 1 64 -32" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<text matrix="1 0 0 1 96 -48" transformations="translations" pos="212 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">3</text>
+<path matrix="1 0 0 1 128 -32" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<text matrix="1 0 0 1 192 -48" transformations="translations" pos="180 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">4</text>
+<path matrix="1 0 0 1 128 -32" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<text matrix="1 0 0 1 224 -48" transformations="translations" pos="212 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">5</text>
+<path matrix="1 0 0 1 192 -32" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 192 -32" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 256 -32" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 -32 0" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path matrix="1 0 0 1 -32 64" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 0 64" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path matrix="1 0 0 1 -32 128" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<text transformations="translations" pos="132 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">1</text>
+<text transformations="translations" pos="132 548" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">2</text>
+<text transformations="translations" pos="132 612" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">3</text>
+<path matrix="1 0 0 1 32 0" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<text transformations="translations" pos="180 516" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">9</text>
+<path matrix="1 0 0 1 96 0" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<text transformations="translations" pos="244 516" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">11</text>
+<path matrix="1 0 0 1 160 0" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path matrix="1 0 0 1 224 0" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path matrix="1 0 0 1 288 0" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path matrix="1 0 0 1 0 64" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 0 64" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 64 64" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 64 64" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 128 64" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 128 64" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 192 64" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 192 64" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 256 64" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 0 128" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 0 128" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 64 128" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 64 128" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 128 128" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 128 128" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 192 128" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 192 128" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 256 128" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 32 64" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path matrix="1 0 0 1 96 64" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path matrix="1 0 0 1 160 64" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path matrix="1 0 0 1 224 64" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path matrix="1 0 0 1 288 64" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path stroke="black" fill="lightgray">
+192 544 m
+192 496 l
+240 496 l
+240 544 l
+h
+</path>
+<path matrix="1 0 0 1 64 0" stroke="black" fill="lightgray">
+192 544 m
+192 496 l
+240 496 l
+240 544 l
+h
+</path>
+<path matrix="1 0 0 1 128 0" stroke="black" fill="lightgray">
+192 544 m
+192 496 l
+240 496 l
+240 544 l
+h
+</path>
+<path matrix="1 0 0 1 192 0" stroke="black" fill="lightgray">
+192 544 m
+192 496 l
+240 496 l
+240 544 l
+h
+</path>
+<path matrix="1 0 0 1 0 64" stroke="black" fill="lightgray">
+192 544 m
+192 496 l
+240 496 l
+240 544 l
+h
+</path>
+<path matrix="1 0 0 1 64 64" stroke="black" fill="lightgray">
+192 544 m
+192 496 l
+240 496 l
+240 544 l
+h
+</path>
+<path matrix="1 0 0 1 128 64" stroke="black" fill="lightgray">
+192 544 m
+192 496 l
+240 496 l
+240 544 l
+h
+</path>
+<path matrix="1 0 0 1 192 64" stroke="black" fill="lightgray">
+192 544 m
+192 496 l
+240 496 l
+240 544 l
+h
+</path>
+<text transformations="translations" pos="212 516" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">10</text>
+<text transformations="translations" pos="276 516" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">12</text>
+<text transformations="translations" pos="308 516" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">13</text>
+<text transformations="translations" pos="340 516" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">14</text>
+<text transformations="translations" pos="372 516" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">15</text>
+<text transformations="translations" pos="404 516" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">16</text>
+<text transformations="translations" pos="436 516" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">17</text>
+<text transformations="translations" pos="180 548" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">18</text>
+<text transformations="translations" pos="212 548" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">19</text>
+<text transformations="translations" pos="244 548" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">20</text>
+<text transformations="translations" pos="276 548" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">21</text>
+<text transformations="translations" pos="308 548" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">22</text>
+<text transformations="translations" pos="340 548" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">23</text>
+<text transformations="translations" pos="372 548" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">24</text>
+<text transformations="translations" pos="404 548" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">25</text>
+<text transformations="translations" pos="436 548" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">26</text>
+<text transformations="translations" pos="180 580" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">27</text>
+<text transformations="translations" pos="212 580" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">28</text>
+<text transformations="translations" pos="244 580" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">29</text>
+<text transformations="translations" pos="276 580" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">30</text>
+<text transformations="translations" pos="308 580" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">31</text>
+<text transformations="translations" pos="340 580" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">32</text>
+<text transformations="translations" pos="372 580" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">33</text>
+<text transformations="translations" pos="404 580" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">34</text>
+<text transformations="translations" pos="436 580" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">35</text>
+<text transformations="translations" pos="180 612" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">36</text>
+<text transformations="translations" pos="212 612" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">37</text>
+<text transformations="translations" pos="244 612" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">38</text>
+<text transformations="translations" pos="276 612" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">39</text>
+<text transformations="translations" pos="308 612" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">40</text>
+<text transformations="translations" pos="340 612" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">41</text>
+<text transformations="translations" pos="372 612" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">42</text>
+<text transformations="translations" pos="404 612" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">43</text>
+<text transformations="translations" pos="436 612" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">44</text>
+<path stroke="black" arrow="normal/normal">
+152 456 m
+472 456 l
+</path>
+<path stroke="black" arrow="normal/normal">
+152 456 m
+152 648 l
+</path>
+</page>
+</ipe>
diff --git a/src/Bitmap_cubical_complex/doc/Cubical_complex_representation.png b/src/Bitmap_cubical_complex/doc/Cubical_complex_representation.png
new file mode 100644
index 00000000..afb2a75e
--- /dev/null
+++ b/src/Bitmap_cubical_complex/doc/Cubical_complex_representation.png
Binary files differ
diff --git a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h
new file mode 100644
index 00000000..d2b9ccd6
--- /dev/null
+++ b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h
@@ -0,0 +1,110 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Pawel Dlotko
+ *
+ * Copyright (C) 2015 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+
+#ifndef DOC_GUDHI_CUBICAL_COMPLEX_COMPLEX_H_
+#define DOC_GUDHI_CUBICAL_COMPLEX_COMPLEX_H_
+
+namespace Gudhi {
+
+namespace cubical_complex {
+
+/** \defgroup cubical_complex Cubical complex
+ *
+ * \author Pawel Dlotko
+ *
+ * @{
+ *
+
+ * Bitmap_cubical_complex is an example of a structured complex useful in computational mathematics (specially rigorous
+ * numerics) and image analysis. The presented implementation of cubical complexes is based on the following
+ * definition.
+ *
+ * An <em>elementary interval</em> is an interval of a form \f$ [n,n+1] \f$, or \f$[n,n]\f$, for \f$ n \in \mathcal{Z}
+ * \f$. The first one is called <em>non-degenerate</em>, while the second one is \a degenerate interval. A
+ * <em>boundary of a elementary interval</em> is a chain \f$\partial [n,n+1] = [n+1,n+1]-[n,n] \f$ in case of
+ * non-degenerated elementary interval and \f$\partial [n,n] = 0 \f$ in case of degenerate elementary interval. An
+ * <em>elementary cube</em> \f$ C \f$ is a product of elementary intervals, \f$C=I_1 \times \ldots \times I_n\f$.
+ * <em>Embedding dimension</em> of a cube is n, the number of elementary intervals (degenerate or not) in the product.
+ * A <em>dimension of a cube</em> \f$C=I_1 \times ... \times I_n\f$ is the number of non degenerate elementary
+ * intervals in the product. A <em>boundary of a cube</em> \f$C=I_1 \times \ldots \times I_n\f$ is a chain obtained
+ * in the following way:
+ * \f[\partial C = (\partial I_1 \times \ldots \times I_n) + (I_1 \times \partial I_2 \times \ldots \times I_n) +
+ * \ldots + (I_1 \times I_2 \times \ldots \times \partial I_n).\f]
+ * A <em>cubical complex</em> \f$\mathcal{K}\f$ is a collection of cubes closed under operation of taking boundary
+ * (i.e. boundary of every cube from the collection is in the collection). A cube \f$C\f$ in cubical complex
+ * \f$\mathcal{K}\f$ is <em>maximal</em> if it is not in a boundary of any other cube in \f$\mathcal{K}\f$. A \a
+ * support of a cube \f$C\f$ is the set in \f$\mathbb{R}^n\f$ occupied by \f$C\f$ (\f$n\f$ is the embedding dimension
+ * of \f$C\f$).
+ *
+ * Cubes may be equipped with a filtration values in which case we have filtered cubical complex. All the cubical
+ * complexes considered in this implementation are filtered cubical complexes (although, the range of a filtration may
+ * be a set of two elements).
+ *
+ * For further details and theory of cubical complexes, please consult \cite kaczynski2004computational as well as the
+ * following paper \cite peikert2012topological .
+ *
+ * \section cubicalcomplexdatastructure Data structure
+ *
+ * The implementation of Cubical complex provides a representation of complexes that occupy a rectangular region in
+ * \f$\mathbb{R}^n\f$. This extra assumption allows for a memory efficient way of storing cubical complexes in a form
+ * of so called bitmaps. Let \f$R = [b_1,e_1] \times \ldots \times [b_n,e_n]\f$, for \f$b_1,...b_n,e_1,...,e_n \in
+ * \mathbb{Z}\f$, \f$b_i \leq d_i\f$ be the considered rectangular region and let \f$\mathcal{K}\f$ be a filtered
+ * cubical complex having the rectangle \f$R\f$ as its support. Note that the structure of the coordinate system gives
+ * a way a lexicographical ordering of cells of \f$\mathcal{K}\f$. This ordering is a base of the presented
+ * bitmap-based implementation. In this implementation, the whole cubical complex is stored as a vector of the values
+ * of filtration. This, together with dimension of \f$\mathcal{K}\f$ and the sizes of \f$\mathcal{K}\f$ in all
+ * directions, allows to determine, dimension, neighborhood, boundary and coboundary of every cube \f$C \in
+ * \mathcal{K}\f$.
+ *
+ * \image html "Cubical_complex_representation.png" Cubical complex.
+ *
+ * Note that the cubical complex in the figure above is, in a natural way, a product of one dimensional cubical
+ * complexes in \f$\mathbb{R}\f$. The number of all cubes in each direction is equal \f$2n+1\f$, where \f$n\f$ is the
+ * number of maximal cubes in the considered direction. Let us consider a cube at the position \f$k\f$ in the bitmap.
+ * Knowing the sizes of the bitmap, by a series of modulo operation, we can determine which elementary intervals are
+ * present in the product that gives the cube \f$C\f$. In a similar way, we can compute boundary and the coboundary of
+ * each cube. Further details can be found in the literature.
+ *
+ * \section inputformat Input Format
+ *
+ * In the current implementation, filtration is given at the maximal cubes, and it is then extended by the lower star
+ * filtration to all cubes. There are a number of constructors that can be used to construct cubical complex by users
+ * who want to use the code directly. They can be found in the \a Bitmap_cubical_complex class.
+ * Currently one input from a text file is used. It uses a format inspired from the Perseus software
+ * (http://www.sas.upenn.edu/~vnanda/perseus/) by Vidit Nanda.
+ * \note While Perseus assume the filtration of all maximal cubes to be non-negative, over here we do not enforce this
+ * and we allow any filtration values. As a consequence one cannot use `-1`'s to indicate missing cubes. If you have
+ * missing cubes in your complex, please set their filtration to \f$+\infty\f$ (aka. `inf` in the file).
+ *
+ * The file format is described in details in \ref FileFormatsPerseus file format section.
+ *
+ * \section PeriodicBoundaryConditions Periodic boundary conditions
+ * Often one would like to impose periodic boundary conditions to the cubical complex. Let \f$ I_1\times ... \times
+ * I_n \f$ be a box that is decomposed with a cubical complex \f$ \mathcal{K} \f$. Imposing periodic boundary
+ * conditions in the direction i, means that the left and the right side of a complex \f$ \mathcal{K} \f$ are
+ * considered the same. In particular, if for a bitmap \f$ \mathcal{K} \f$ periodic boundary conditions are imposed
+ * in all directions, then complex \f$ \mathcal{K} \f$ became n-dimensional torus. One can use various constructors
+ * from the file Bitmap_cubical_complex_periodic_boundary_conditions_base.h to construct cubical complex with periodic
+ * boundary conditions. One can also use Perseus style input files (see \ref FileFormatsPerseus).
+ *
+ * \section BitmapExamples Examples
+ * End user programs are available in example/Bitmap_cubical_complex and utilities/Bitmap_cubical_complex folders.
+ *
+ */
+/** @} */ // end defgroup cubical_complex
+
+} // namespace cubical_complex
+
+namespace Cubical_complex = cubical_complex;
+
+} // namespace Gudhi
+
+#endif // DOC_GUDHI_CUBICAL_COMPLEX_COMPLEX_H_
diff --git a/src/Bitmap_cubical_complex/doc/bitmapAllCubes.png b/src/Bitmap_cubical_complex/doc/bitmapAllCubes.png
new file mode 100644
index 00000000..77167b13
--- /dev/null
+++ b/src/Bitmap_cubical_complex/doc/bitmapAllCubes.png
Binary files differ
diff --git a/src/Bitmap_cubical_complex/doc/exampleBitmap.png b/src/Bitmap_cubical_complex/doc/exampleBitmap.png
new file mode 100644
index 00000000..069c6eb2
--- /dev/null
+++ b/src/Bitmap_cubical_complex/doc/exampleBitmap.png
Binary files differ
diff --git a/src/Bitmap_cubical_complex/example/CMakeLists.txt b/src/Bitmap_cubical_complex/example/CMakeLists.txt
new file mode 100644
index 00000000..dc659f2d
--- /dev/null
+++ b/src/Bitmap_cubical_complex/example/CMakeLists.txt
@@ -0,0 +1,10 @@
+project(Bitmap_cubical_complex_examples)
+
+add_executable ( Random_bitmap_cubical_complex Random_bitmap_cubical_complex.cpp )
+if (TBB_FOUND)
+ target_link_libraries(Random_bitmap_cubical_complex ${TBB_LIBRARIES})
+endif()
+add_test(NAME Bitmap_cubical_complex_example_random COMMAND $<TARGET_FILE:Random_bitmap_cubical_complex>
+ "2" "100" "100")
+
+install(TARGETS Random_bitmap_cubical_complex DESTINATION bin)
diff --git a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp
new file mode 100644
index 00000000..46ea8f2e
--- /dev/null
+++ b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp
@@ -0,0 +1,70 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Pawel Dlotko
+ *
+ * Copyright (C) 2015 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+// for persistence algorithm
+#include <gudhi/reader_utils.h>
+#include <gudhi/Bitmap_cubical_complex.h>
+#include <gudhi/Persistent_cohomology.h>
+
+// standard stuff
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+int main(int argc, char** argv) {
+ srand(time(0));
+
+ std::cout
+ << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical "
+ << "complexes. The first parameter of the program is the dimension D of the bitmap. The next D parameters are "
+ << "number of top dimensional cubes in each dimension of the bitmap. The program will create random cubical "
+ << "complex of that sizes and compute persistent homology of it." << std::endl;
+
+ int p = 2;
+ double min_persistence = 0;
+
+ if (argc < 3) {
+ std::cerr << "Wrong number of parameters, the program will now terminate\n";
+ return 1;
+ }
+
+ size_t dimensionOfBitmap = (size_t)atoi(argv[1]);
+ std::vector<unsigned> sizes;
+ size_t multipliers = 1;
+ for (size_t dim = 0; dim != dimensionOfBitmap; ++dim) {
+ unsigned sizeInThisDimension = (unsigned)atoi(argv[2 + dim]);
+ sizes.push_back(sizeInThisDimension);
+ multipliers *= sizeInThisDimension;
+ }
+
+ std::vector<double> data;
+ for (size_t i = 0; i != multipliers; ++i) {
+ data.push_back(rand() / static_cast<double>(RAND_MAX));
+ }
+
+ typedef Gudhi::cubical_complex::Bitmap_cubical_complex_base<double> Bitmap_cubical_complex_base;
+ typedef Gudhi::cubical_complex::Bitmap_cubical_complex<Bitmap_cubical_complex_base> Bitmap_cubical_complex;
+ Bitmap_cubical_complex b(sizes, data);
+
+ // Compute the persistence diagram of the complex
+ typedef Gudhi::persistent_cohomology::Field_Zp Field_Zp;
+ typedef Gudhi::persistent_cohomology::Persistent_cohomology<Bitmap_cubical_complex, Field_Zp> Persistent_cohomology;
+ Persistent_cohomology pcoh(b);
+ pcoh.init_coefficients(p); // initializes the coefficient field for homology
+ pcoh.compute_persistent_cohomology(min_persistence);
+
+ std::stringstream ss;
+ ss << "randomComplex_persistence";
+ std::ofstream out(ss.str().c_str());
+ pcoh.output_diagram(out);
+ out.close();
+
+ return 0;
+}
diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h
new file mode 100644
index 00000000..37514dee
--- /dev/null
+++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h
@@ -0,0 +1,570 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Pawel Dlotko
+ *
+ * Copyright (C) 2015 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#ifndef BITMAP_CUBICAL_COMPLEX_H_
+#define BITMAP_CUBICAL_COMPLEX_H_
+
+#include <gudhi/Bitmap_cubical_complex_base.h>
+#include <gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h>
+
+#ifdef GUDHI_USE_TBB
+#include <tbb/parallel_sort.h>
+#endif
+
+#include <limits>
+#include <utility> // for pair<>
+#include <algorithm> // for sort
+#include <vector>
+#include <numeric> // for iota
+#include <cstddef>
+
+namespace Gudhi {
+
+namespace cubical_complex {
+
+// global variable, was used just for debugging.
+const bool globalDbg = false;
+
+template <typename T>
+class is_before_in_filtration;
+
+/**
+ * @brief Cubical complex represented as a bitmap.
+ * @ingroup cubical_complex
+ * @details This is a Bitmap_cubical_complex class. It joints a functionalities of Bitmap_cubical_complex_base and
+ * Bitmap_cubical_complex_periodic_boundary_conditions_base classes into
+ * Gudhi persistent homology engine. It is a template class that inherit from its template parameter. The template
+ * parameter is supposed to be either Bitmap_cubical_complex_base or
+ * Bitmap_cubical_complex_periodic_boundary_conditions_base class.
+ **/
+template <typename T>
+class Bitmap_cubical_complex : public T {
+ public:
+ //*********************************************//
+ // Typedefs and typenames
+ //*********************************************//
+ typedef std::size_t Simplex_key;
+ typedef typename T::filtration_type Filtration_value;
+ typedef Simplex_key Simplex_handle;
+
+ //*********************************************//
+ // Constructors
+ //*********************************************//
+ // Over here we need to define various input types. I am proposing the following ones:
+ // Perseus style
+ // TODO(PD) H5 files?
+ // TODO(PD) binary files with little endiangs / big endians ?
+ // TODO(PD) constructor from a vector of elements of a type T. ?
+
+ /**
+ * Constructor form a Perseus-style file.
+ **/
+ Bitmap_cubical_complex(const char* perseus_style_file)
+ : T(perseus_style_file), key_associated_to_simplex(this->total_number_of_cells + 1) {
+ if (globalDbg) {
+ std::cerr << "Bitmap_cubical_complex( const char* perseus_style_file )\n";
+ }
+ for (std::size_t i = 0; i != this->total_number_of_cells; ++i) {
+ this->key_associated_to_simplex[i] = i;
+ }
+ // we initialize this only once, in each constructor, when the bitmap is constructed.
+ // If the user decide to change some elements of the bitmap, then this procedure need
+ // to be called again.
+ this->initialize_simplex_associated_to_key();
+ }
+
+ /**
+ * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells
+ * in the following directions and vector of element of a type T
+ * with filtration on top dimensional cells.
+ **/
+ Bitmap_cubical_complex(const std::vector<unsigned>& dimensions,
+ const std::vector<Filtration_value>& top_dimensional_cells)
+ : T(dimensions, top_dimensional_cells), key_associated_to_simplex(this->total_number_of_cells + 1) {
+ for (std::size_t i = 0; i != this->total_number_of_cells; ++i) {
+ this->key_associated_to_simplex[i] = i;
+ }
+ // we initialize this only once, in each constructor, when the bitmap is constructed.
+ // If the user decide to change some elements of the bitmap, then this procedure need
+ // to be called again.
+ this->initialize_simplex_associated_to_key();
+ }
+
+ /**
+ * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells
+ * in the following directions and vector of element of a type Filtration_value
+ * with filtration on top dimensional cells. The last parameter of the constructor is a vector of boolean of a length
+ * equal to the dimension of cubical complex.
+ * If the position i on this vector is true, then we impose periodic boundary conditions in this direction.
+ **/
+ Bitmap_cubical_complex(const std::vector<unsigned>& dimensions,
+ const std::vector<Filtration_value>& top_dimensional_cells,
+ std::vector<bool> directions_in_which_periodic_b_cond_are_to_be_imposed)
+ : T(dimensions, top_dimensional_cells, directions_in_which_periodic_b_cond_are_to_be_imposed),
+ key_associated_to_simplex(this->total_number_of_cells + 1) {
+ for (std::size_t i = 0; i != this->total_number_of_cells; ++i) {
+ this->key_associated_to_simplex[i] = i;
+ }
+ // we initialize this only once, in each constructor, when the bitmap is constructed.
+ // If the user decide to change some elements of the bitmap, then this procedure need
+ // to be called again.
+ this->initialize_simplex_associated_to_key();
+ }
+
+ /**
+ * Destructor of the Bitmap_cubical_complex class.
+ **/
+ virtual ~Bitmap_cubical_complex() {}
+
+ //*********************************************//
+ // Other 'easy' functions
+ //*********************************************//
+
+ /**
+ * Returns number of all cubes in the complex.
+ **/
+ std::size_t num_simplices() const { return this->total_number_of_cells; }
+
+ /**
+ * Returns a Simplex_handle to a cube that do not exist in this complex.
+ **/
+ static Simplex_handle null_simplex() {
+ if (globalDbg) {
+ std::cerr << "Simplex_handle null_simplex()\n";
+ }
+ return std::numeric_limits<Simplex_handle>::max();
+ }
+
+ /**
+ * Returns dimension of the complex.
+ **/
+ inline std::size_t dimension() const { return this->sizes.size(); }
+
+ /**
+ * Return dimension of a cell pointed by the Simplex_handle.
+ **/
+ inline unsigned dimension(Simplex_handle sh) const {
+ if (globalDbg) {
+ std::cerr << "unsigned dimension(const Simplex_handle& sh)\n";
+ }
+ if (sh != null_simplex()) return this->get_dimension_of_a_cell(sh);
+ return -1;
+ }
+
+ /**
+ * Return the filtration of a cell pointed by the Simplex_handle.
+ **/
+ Filtration_value filtration(Simplex_handle sh) {
+ if (globalDbg) {
+ std::cerr << "Filtration_value filtration(const Simplex_handle& sh)\n";
+ }
+ // Returns the filtration value of a simplex.
+ if (sh != null_simplex()) return this->data[sh];
+ return std::numeric_limits<Filtration_value>::infinity();
+ }
+
+ /**
+ * Return a key which is not a key of any cube in the considered data structure.
+ **/
+ static Simplex_key null_key() {
+ if (globalDbg) {
+ std::cerr << "Simplex_key null_key()\n";
+ }
+ return std::numeric_limits<Simplex_handle>::max();
+ }
+
+ /**
+ * Return the key of a cube pointed by the Simplex_handle.
+ **/
+ Simplex_key key(Simplex_handle sh) const {
+ if (globalDbg) {
+ std::cerr << "Simplex_key key(const Simplex_handle& sh)\n";
+ }
+ if (sh != null_simplex()) {
+ return this->key_associated_to_simplex[sh];
+ }
+ return this->null_key();
+ }
+
+ /**
+ * Return the Simplex_handle given the key of the cube.
+ **/
+ Simplex_handle simplex(Simplex_key key) {
+ if (globalDbg) {
+ std::cerr << "Simplex_handle simplex(Simplex_key key)\n";
+ }
+ if (key != null_key()) {
+ return this->simplex_associated_to_key[key];
+ }
+ return null_simplex();
+ }
+
+ /**
+ * Assign key to a cube pointed by the Simplex_handle
+ **/
+ void assign_key(Simplex_handle sh, Simplex_key key) {
+ if (globalDbg) {
+ std::cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n";
+ }
+ if (key == null_key()) return;
+ this->key_associated_to_simplex[sh] = key;
+ this->simplex_associated_to_key[key] = sh;
+ }
+
+ /**
+ * Function called from a constructor. It is needed for Filtration_simplex_iterator to work.
+ **/
+ void initialize_simplex_associated_to_key();
+
+ //*********************************************//
+ // Iterators
+ //*********************************************//
+
+ /**
+ * Boundary_simplex_range class provides ranges for boundary iterators.
+ **/
+ typedef typename std::vector<Simplex_handle>::iterator Boundary_simplex_iterator;
+ typedef typename std::vector<Simplex_handle> Boundary_simplex_range;
+
+ /**
+ * Filtration_simplex_iterator class provides an iterator though the whole structure in the order of filtration.
+ * Secondary criteria for filtration are:
+ * (1) Dimension of a cube (lower dimensional comes first).
+ * (2) Position in the data structure (the ones that are earlies in the data structure comes first).
+ **/
+ class Filtration_simplex_range;
+
+ class Filtration_simplex_iterator : std::iterator<std::input_iterator_tag, Simplex_handle> {
+ // Iterator over all simplices of the complex in the order of the indexing scheme.
+ // 'value_type' must be 'Simplex_handle'.
+ public:
+ Filtration_simplex_iterator(Bitmap_cubical_complex* b) : b(b), position(0) {}
+
+ Filtration_simplex_iterator() : b(NULL), position(0) {}
+
+ Filtration_simplex_iterator operator++() {
+ if (globalDbg) {
+ std::cerr << "Filtration_simplex_iterator operator++\n";
+ }
+ ++this->position;
+ return (*this);
+ }
+
+ Filtration_simplex_iterator operator++(int) {
+ Filtration_simplex_iterator result = *this;
+ ++(*this);
+ return result;
+ }
+
+ Filtration_simplex_iterator& operator=(const Filtration_simplex_iterator& rhs) {
+ if (globalDbg) {
+ std::cerr << "Filtration_simplex_iterator operator =\n";
+ }
+ this->b = rhs.b;
+ this->position = rhs.position;
+ return (*this);
+ }
+
+ bool operator==(const Filtration_simplex_iterator& rhs) const {
+ if (globalDbg) {
+ std::cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n";
+ }
+ return (this->position == rhs.position);
+ }
+
+ bool operator!=(const Filtration_simplex_iterator& rhs) const {
+ if (globalDbg) {
+ std::cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n";
+ }
+ return !(*this == rhs);
+ }
+
+ Simplex_handle operator*() {
+ if (globalDbg) {
+ std::cerr << "Simplex_handle operator*()\n";
+ }
+ return this->b->simplex_associated_to_key[this->position];
+ }
+
+ friend class Filtration_simplex_range;
+
+ private:
+ Bitmap_cubical_complex<T>* b;
+ std::size_t position;
+ };
+
+ /**
+ * @brief Filtration_simplex_range provides the ranges for Filtration_simplex_iterator.
+ **/
+ class Filtration_simplex_range {
+ // Range over the simplices of the complex in the order of the filtration.
+ // .begin() and .end() return type Filtration_simplex_iterator.
+ public:
+ typedef Filtration_simplex_iterator const_iterator;
+ typedef Filtration_simplex_iterator iterator;
+
+ Filtration_simplex_range(Bitmap_cubical_complex<T>* b) : b(b) {}
+
+ Filtration_simplex_iterator begin() {
+ if (globalDbg) {
+ std::cerr << "Filtration_simplex_iterator begin() \n";
+ }
+ return Filtration_simplex_iterator(this->b);
+ }
+
+ Filtration_simplex_iterator end() {
+ if (globalDbg) {
+ std::cerr << "Filtration_simplex_iterator end()\n";
+ }
+ Filtration_simplex_iterator it(this->b);
+ it.position = this->b->simplex_associated_to_key.size();
+ return it;
+ }
+
+ private:
+ Bitmap_cubical_complex<T>* b;
+ };
+
+ //*********************************************//
+ // Methods to access iterators from the container:
+
+ /**
+ * boundary_simplex_range creates an object of a Boundary_simplex_range class
+ * that provides ranges for the Boundary_simplex_iterator.
+ **/
+ Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) { return this->get_boundary_of_a_cell(sh); }
+
+ /**
+ * filtration_simplex_range creates an object of a Filtration_simplex_range class
+ * that provides ranges for the Filtration_simplex_iterator.
+ **/
+ Filtration_simplex_range filtration_simplex_range() {
+ if (globalDbg) {
+ std::cerr << "Filtration_simplex_range filtration_simplex_range()\n";
+ }
+ // Returns a range over the simplices of the complex in the order of the filtration
+ return Filtration_simplex_range(this);
+ }
+ //*********************************************//
+
+ //*********************************************//
+ // Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are
+ // there.
+ // TODO(PD) the file IndexingTag.h in the Gudhi library contains an empty structure, so
+ // I understand that this is something that was planned (for simplicial maps?)
+ // but was never finished. The only idea I have here is to use the same empty structure from
+ // IndexingTag.h file, but only if the compiler needs it. If the compiler
+ // do not need it, then I would rather not add here elements which I do not understand.
+ // typedef Indexing_tag
+
+ /**
+ * Function needed for compatibility with Gudhi. Not useful for other purposes.
+ **/
+ std::pair<Simplex_handle, Simplex_handle> endpoints(Simplex_handle sh) {
+ std::vector<std::size_t> bdry = this->get_boundary_of_a_cell(sh);
+ if (globalDbg) {
+ std::cerr << "std::pair<Simplex_handle, Simplex_handle> endpoints( Simplex_handle sh )\n";
+ std::cerr << "bdry.size() : " << bdry.size() << "\n";
+ }
+ // this method returns two first elements from the boundary of sh.
+ if (bdry.size() < 2)
+ throw(
+ "Error in endpoints in Bitmap_cubical_complex class. The cell have less than two elements in the "
+ "boundary.");
+ return std::make_pair(bdry[0], bdry[1]);
+ }
+
+ /**
+ * Class needed for compatibility with Gudhi. Not useful for other purposes.
+ **/
+ class Skeleton_simplex_range;
+
+ class Skeleton_simplex_iterator : std::iterator<std::input_iterator_tag, Simplex_handle> {
+ // Iterator over all simplices of the complex in the order of the indexing scheme.
+ // 'value_type' must be 'Simplex_handle'.
+ public:
+ Skeleton_simplex_iterator(Bitmap_cubical_complex* b, std::size_t d) : b(b), dimension(d) {
+ if (globalDbg) {
+ std::cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , std::size_t d )\n";
+ }
+ // find the position of the first simplex of a dimension d
+ this->position = 0;
+ while ((this->position != b->data.size()) &&
+ (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) {
+ ++this->position;
+ }
+ }
+
+ Skeleton_simplex_iterator() : b(NULL), position(0), dimension(0) {}
+
+ Skeleton_simplex_iterator operator++() {
+ if (globalDbg) {
+ std::cerr << "Skeleton_simplex_iterator operator++()\n";
+ }
+ // increment the position as long as you did not get to the next element of the dimension dimension.
+ ++this->position;
+ while ((this->position != this->b->data.size()) &&
+ (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) {
+ ++this->position;
+ }
+ return (*this);
+ }
+
+ Skeleton_simplex_iterator operator++(int) {
+ Skeleton_simplex_iterator result = *this;
+ ++(*this);
+ return result;
+ }
+
+ Skeleton_simplex_iterator& operator=(const Skeleton_simplex_iterator& rhs) {
+ if (globalDbg) {
+ std::cerr << "Skeleton_simplex_iterator operator =\n";
+ }
+ this->b = rhs.b;
+ this->position = rhs.position;
+ this->dimension = rhs.dimension;
+ return (*this);
+ }
+
+ bool operator==(const Skeleton_simplex_iterator& rhs) const {
+ if (globalDbg) {
+ std::cerr << "bool operator ==\n";
+ }
+ return (this->position == rhs.position);
+ }
+
+ bool operator!=(const Skeleton_simplex_iterator& rhs) const {
+ if (globalDbg) {
+ std::cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n";
+ }
+ return !(*this == rhs);
+ }
+
+ Simplex_handle operator*() {
+ if (globalDbg) {
+ std::cerr << "Simplex_handle operator*() \n";
+ }
+ return this->position;
+ }
+
+ friend class Skeleton_simplex_range;
+
+ private:
+ Bitmap_cubical_complex<T>* b;
+ std::size_t position;
+ unsigned dimension;
+ };
+
+ /**
+ * @brief Class needed for compatibility with Gudhi. Not useful for other purposes.
+ **/
+ class Skeleton_simplex_range {
+ // Range over the simplices of the complex in the order of the filtration.
+ // .begin() and .end() return type Filtration_simplex_iterator.
+ public:
+ typedef Skeleton_simplex_iterator const_iterator;
+ typedef Skeleton_simplex_iterator iterator;
+
+ Skeleton_simplex_range(Bitmap_cubical_complex<T>* b, unsigned dimension) : b(b), dimension(dimension) {}
+
+ Skeleton_simplex_iterator begin() {
+ if (globalDbg) {
+ std::cerr << "Skeleton_simplex_iterator begin()\n";
+ }
+ return Skeleton_simplex_iterator(this->b, this->dimension);
+ }
+
+ Skeleton_simplex_iterator end() {
+ if (globalDbg) {
+ std::cerr << "Skeleton_simplex_iterator end()\n";
+ }
+ Skeleton_simplex_iterator it(this->b, this->dimension);
+ it.position = this->b->data.size();
+ return it;
+ }
+
+ private:
+ Bitmap_cubical_complex<T>* b;
+ unsigned dimension;
+ };
+
+ /**
+ * Function needed for compatibility with Gudhi. Not useful for other purposes.
+ **/
+ Skeleton_simplex_range skeleton_simplex_range(unsigned dimension) {
+ if (globalDbg) {
+ std::cerr << "Skeleton_simplex_range skeleton_simplex_range( unsigned dimension )\n";
+ }
+ return Skeleton_simplex_range(this, dimension);
+ }
+
+ friend class is_before_in_filtration<T>;
+
+ protected:
+ std::vector<std::size_t> key_associated_to_simplex;
+ std::vector<std::size_t> simplex_associated_to_key;
+}; // Bitmap_cubical_complex
+
+template <typename T>
+void Bitmap_cubical_complex<T>::initialize_simplex_associated_to_key() {
+ if (globalDbg) {
+ std::cerr << "void Bitmap_cubical_complex<T>::initialize_elements_ordered_according_to_filtration() \n";
+ }
+ this->simplex_associated_to_key = std::vector<std::size_t>(this->data.size());
+ std::iota(std::begin(simplex_associated_to_key), std::end(simplex_associated_to_key), 0);
+#ifdef GUDHI_USE_TBB
+ tbb::parallel_sort(simplex_associated_to_key.begin(), simplex_associated_to_key.end(),
+ is_before_in_filtration<T>(this));
+#else
+ std::sort(simplex_associated_to_key.begin(), simplex_associated_to_key.end(), is_before_in_filtration<T>(this));
+#endif
+
+ // we still need to deal here with a key_associated_to_simplex:
+ for (std::size_t i = 0; i != simplex_associated_to_key.size(); ++i) {
+ this->key_associated_to_simplex[simplex_associated_to_key[i]] = i;
+ }
+}
+
+template <typename T>
+class is_before_in_filtration {
+ public:
+ explicit is_before_in_filtration(Bitmap_cubical_complex<T>* CC) : CC_(CC) {}
+
+ bool operator()(const typename Bitmap_cubical_complex<T>::Simplex_handle& sh1,
+ const typename Bitmap_cubical_complex<T>::Simplex_handle& sh2) const {
+ // Not using st_->filtration(sh1) because it uselessly tests for null_simplex.
+ typedef typename T::filtration_type Filtration_value;
+ Filtration_value fil1 = CC_->data[sh1];
+ Filtration_value fil2 = CC_->data[sh2];
+ if (fil1 != fil2) {
+ return fil1 < fil2;
+ }
+ // in this case they are on the same filtration level, so the dimension decide.
+ std::size_t dim1 = CC_->get_dimension_of_a_cell(sh1);
+ std::size_t dim2 = CC_->get_dimension_of_a_cell(sh2);
+ if (dim1 != dim2) {
+ return dim1 < dim2;
+ }
+ // in this case both filtration and dimensions of the considered cubes are the same. To have stable sort, we simply
+ // compare their positions in the bitmap:
+ return sh1 < sh2;
+ }
+
+ protected:
+ Bitmap_cubical_complex<T>* CC_;
+};
+
+} // namespace cubical_complex
+
+namespace Cubical_complex = cubical_complex;
+
+} // namespace Gudhi
+
+#endif // BITMAP_CUBICAL_COMPLEX_H_
diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h
new file mode 100644
index 00000000..fdcea230
--- /dev/null
+++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h
@@ -0,0 +1,133 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Pawel Dlotko
+ *
+ * Copyright (C) 2015 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#ifndef BITMAP_CUBICAL_COMPLEX_COUNTER_H_
+#define BITMAP_CUBICAL_COMPLEX_COUNTER_H_
+
+#include <iostream>
+#include <vector>
+#include <cstddef>
+
+namespace Gudhi {
+
+namespace cubical_complex {
+
+/**
+ * @brief This is an implementation of a counter being a vector of integers.
+ * @details The constructor of the class takes as an input two vectors W and V.
+ * It assumes that W < V coordinatewise.
+ * If the initial counter W is not specified, it is assumed to be vector of zeros.
+ * The class allows to iterate between W and V by using increment() function.
+ * The increment() function returns a bool value.
+ * The current counter reach the end counter V if the value returned by the increment function is FALSE.
+ * This class is needed for the implementation of a bitmapCubicalComplex.
+ **/
+class counter {
+ public:
+ /**
+ * Constructor of a counter class. It takes only the parameter which is the end value of the counter.
+ * The default beginning value is a vector of the same length as the endd, filled-in with zeros.
+ **/
+ counter(const std::vector<unsigned>& endd) : begin(endd.size(), 0), end(endd), current(endd.size(), 0) { }
+
+ /**
+ * Constructor of a counter class. It takes as the input beginn and end vector.
+ * It assumes that begin vector is lexicographically below the end vector.
+ **/
+ counter(const std::vector< unsigned >& beginn, const std::vector< unsigned >& endd) : begin(beginn), end(endd), current(endd.size(), 0) {
+ if (beginn.size() != endd.size())
+ throw "In constructor of a counter, begin and end vectors do not have the same size. Program terminate";
+ }
+
+ /**
+ * Function to increment the counter. If the value returned by the function is true,
+ * then the incrementation process was successful.
+ * If the value of the function is false, that means, that the counter have reached its end-value.
+ **/
+ bool increment() {
+ std::size_t i = 0;
+ while ((i != this->end.size()) && (this->current[i] == this->end[i])) {
+ ++i;
+ }
+
+ if (i == this->end.size())return false;
+ ++this->current[i];
+ for (std::size_t j = 0; j != i; ++j) {
+ this->current[j] = this->begin[j];
+ }
+ return true;
+ }
+
+ /**
+ * Function to check if we are at the end of counter.
+ **/
+ bool isFinal() {
+ for (std::size_t i = 0; i != this->current.size(); ++i) {
+ if (this->current[i] == this->end[i])return true;
+ }
+ return false;
+ }
+
+ /**
+ * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition.
+ * Its aim is to find an counter corresponding to the element the following
+ * boundary element is identified with when periodic boundary conditions are imposed.
+ **/
+ std::vector< unsigned > find_opposite(const std::vector< bool >& directionsForPeriodicBCond) {
+ std::vector< unsigned > result;
+ for (std::size_t i = 0; i != this->current.size(); ++i) {
+ if ((this->current[i] == this->end[i]) && (directionsForPeriodicBCond[i] == true)) {
+ result.push_back(this->begin[i]);
+ } else {
+ result.push_back(this->current[i]);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Function checking at which positions the current value of a counter is the final value of the counter.
+ **/
+ std::vector< bool > directions_of_finals() {
+ std::vector< bool > result;
+ for (std::size_t i = 0; i != this->current.size(); ++i) {
+ if (this->current[i] == this->end[i]) {
+ result.push_back(true);
+ } else {
+ result.push_back(false);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Function to write counter to the stream.
+ **/
+ friend std::ostream& operator<<(std::ostream& out, const counter& c) {
+ // std::cerr << "c.current.size() : " << c.current.size() << endl;
+ for (std::size_t i = 0; i != c.current.size(); ++i) {
+ out << c.current[i] << " ";
+ }
+ return out;
+ }
+
+ private:
+ std::vector< unsigned > begin;
+ std::vector< unsigned > end;
+ std::vector< unsigned > current;
+};
+
+} // namespace cubical_complex
+
+namespace Cubical_complex = cubical_complex;
+
+} // namespace Gudhi
+
+#endif // BITMAP_CUBICAL_COMPLEX_COUNTER_H_
diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h
new file mode 100644
index 00000000..0d6299d2
--- /dev/null
+++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h
@@ -0,0 +1,857 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Pawel Dlotko
+ *
+ * Copyright (C) 2015 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#ifndef BITMAP_CUBICAL_COMPLEX_BASE_H_
+#define BITMAP_CUBICAL_COMPLEX_BASE_H_
+
+#include <gudhi/Bitmap_cubical_complex/counter.h>
+
+#include <iostream>
+#include <vector>
+#include <string>
+#include <fstream>
+#include <algorithm>
+#include <iterator>
+#include <limits>
+#include <utility>
+#include <stdexcept>
+#include <cstddef>
+
+namespace Gudhi {
+
+namespace cubical_complex {
+
+/**
+ * @brief Cubical complex represented as a bitmap, class with basic implementation.
+ * @ingroup cubical_complex
+ * @details This is a class implementing a basic bitmap data structure to store cubical complexes.
+ * It implements only the most basic subroutines.
+ * The idea of the bitmap is the following. Our aim is to have a memory efficient
+ * data structure to store d-dimensional cubical complex
+ * C being a cubical decomposition
+ * of a rectangular region of a space. This is achieved by storing C as a
+ * vector of bits (this is where the name 'bitmap' came from).
+ * Each cell is represented by a single
+ * bit (in case of black and white bitmaps, or by a single element of a type T
+ * (here T is a filtration type of a bitmap, typically a double).
+ * All the informations needed for homology and
+ * persistent homology computations (like dimension of a cell, boundary and
+ * coboundary elements of a cell, are then obtained from the
+ * position of the element in C.
+ * The default filtration used in this implementation is the lower star filtration.
+ */
+template <typename T>
+class Bitmap_cubical_complex_base {
+ public:
+ typedef T filtration_type;
+
+ /**
+ *Default constructor
+ **/
+ Bitmap_cubical_complex_base() : total_number_of_cells(0) {}
+ /**
+ * There are a few constructors of a Bitmap_cubical_complex_base class.
+ * First one, that takes vector<unsigned>, creates an empty bitmap of a dimension equal
+ * the number of elements in the
+ * input vector and size in the i-th dimension equal the number in the position i-of the input vector.
+ */
+ Bitmap_cubical_complex_base(const std::vector<unsigned>& sizes);
+ /**
+ * The second constructor takes as a input a Perseus style file. For more details,
+ * please consult the documentations of
+ * Perseus software as well as examples attached to this
+ * implementation.
+ **/
+ Bitmap_cubical_complex_base(const char* perseus_style_file);
+ /**
+ * The last constructor of a Bitmap_cubical_complex_base class accepts vector of dimensions (as the first one)
+ * together with vector of filtration values of top dimensional cells.
+ **/
+ Bitmap_cubical_complex_base(const std::vector<unsigned>& dimensions, const std::vector<T>& top_dimensional_cells);
+
+ /**
+ * Destructor of the Bitmap_cubical_complex_base class.
+ **/
+ virtual ~Bitmap_cubical_complex_base() {}
+
+ /**
+ * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell
+ * and get_cell_data are the basic
+ * functions that compute boundary / coboundary / dimension and the filtration
+ * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a
+ * non-negative integer, indicating a position of a cube in the data structure.
+ * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to
+ * the positions of (co)boundary element of the input cell.
+ * The boundary elements are guaranteed to be returned so that the
+ * incidence coefficients of boundary elements are alternating.
+ */
+ virtual inline std::vector<std::size_t> get_boundary_of_a_cell(std::size_t cell) const;
+ /**
+ * The functions get_coboundary_of_a_cell, get_coboundary_of_a_cell,
+ * get_dimension_of_a_cell and get_cell_data are the basic
+ * functions that compute boundary / coboundary / dimension and the filtration
+ * value form a position of a cell in the structure of a bitmap.
+ * The input parameter of all of those function is a non-negative integer,
+ * indicating a position of a cube in the data structure.
+ * In the case of functions that compute (co)boundary, the output is a vector if
+ * non-negative integers pointing to the
+ * positions of (co)boundary element of the input cell.
+ * Note that unlike in the case of boundary, over here the elements are
+ * not guaranteed to be returned with alternating incidence numbers.
+ *
+ **/
+ virtual inline std::vector<std::size_t> get_coboundary_of_a_cell(std::size_t cell) const;
+
+ /**
+ * This procedure compute incidence numbers between cubes. For a cube \f$A\f$ of
+ * dimension n and a cube \f$B \subset A\f$ of dimension n-1, an incidence
+ * between \f$A\f$ and \f$B\f$ is the integer with which \f$B\f$ appears in the boundary of \f$A\f$.
+ * Note that first parameter is a cube of dimension n,
+ * and the second parameter is an adjusted cube in dimension n-1.
+ * Given \f$A = [b_1,e_1] \times \ldots \ [b_{j-1},e_{j-1}] \times [b_{j},e_{j}] \times [b_{j+1},e_{j+1}] \times \ldots
+ *\times [b_{n},e_{n}] \f$
+ * such that \f$ b_{j} \neq e_{j} \f$
+ * and \f$B = [b_1,e_1] \times \ldots \ [b_{j-1},e_{j-1}] \times [a,a] \times [b_{j+1},e_{j+1}] \times \ldots \times
+ *[b_{n},e_{n}] \f$
+ * where \f$ a = b_{j}\f$ or \f$ a = e_{j}\f$, the incidence between \f$A\f$ and \f$B\f$
+ * computed by this procedure is given by formula:
+ * \f$ c\ (-1)^{\sum_{i=1}^{j-1} dim [b_{i},e_{i}]} \f$
+ * Where \f$ dim [b_{i},e_{i}] = 0 \f$ if \f$ b_{i}=e_{i} \f$ and 1 in other case.
+ * c is -1 if \f$ a = b_{j}\f$ and 1 if \f$ a = e_{j}\f$.
+ * @exception std::logic_error In case when the cube \f$B\f$ is not n-1
+ * dimensional face of a cube \f$A\f$.
+ **/
+ virtual int compute_incidence_between_cells(std::size_t coface, std::size_t face) const {
+ // first get the counters for coface and face:
+ std::vector<unsigned> coface_counter = this->compute_counter_for_given_cell(coface);
+ std::vector<unsigned> face_counter = this->compute_counter_for_given_cell(face);
+
+ // coface_counter and face_counter should agree at all positions except from one:
+ int number_of_position_in_which_counters_do_not_agree = -1;
+ std::size_t number_of_full_faces_that_comes_before = 0;
+ for (std::size_t i = 0; i != coface_counter.size(); ++i) {
+ if ((coface_counter[i] % 2 == 1) && (number_of_position_in_which_counters_do_not_agree == -1)) {
+ ++number_of_full_faces_that_comes_before;
+ }
+ if (coface_counter[i] != face_counter[i]) {
+ if (number_of_position_in_which_counters_do_not_agree != -1) {
+ std::cout << "Cells given to compute_incidence_between_cells procedure do not form a pair of coface-face.\n";
+ throw std::logic_error(
+ "Cells given to compute_incidence_between_cells procedure do not form a pair of coface-face.");
+ }
+ number_of_position_in_which_counters_do_not_agree = i;
+ }
+ }
+
+ int incidence = 1;
+ if (number_of_full_faces_that_comes_before % 2) incidence = -1;
+ // if the face cell is on the right from coface cell:
+ if (coface_counter[number_of_position_in_which_counters_do_not_agree] + 1 ==
+ face_counter[number_of_position_in_which_counters_do_not_agree]) {
+ incidence *= -1;
+ }
+
+ return incidence;
+ }
+
+ /**
+* In the case of get_dimension_of_a_cell function, the output is a non-negative integer
+* indicating the dimension of a cell.
+* Note that unlike in the case of boundary, over here the elements are
+* not guaranteed to be returned with alternating incidence numbers.
+* To compute incidence between cells use compute_incidence_between_cells
+* procedure
+**/
+ inline unsigned get_dimension_of_a_cell(std::size_t cell) const;
+
+ /**
+ * In the case of get_cell_data, the output parameter is a reference to the value of a cube in a given position.
+ * This allows reading and changing the value of filtration. Note that if the value of a filtration is changed, the
+ * code do not check if we have a filtration or not. i.e. it do not check if the value of a filtration of a cell is
+ * not smaller than the value of a filtration of its boundary and not greater than the value of its coboundary.
+ **/
+ inline T& get_cell_data(std::size_t cell);
+
+ /**
+ * Typical input used to construct a baseBitmap class is a filtration given at the top dimensional cells.
+ * Then, there are a few ways one can pick the filtration of lower dimensional
+ * cells. The most typical one is by so called lower star filtration. This function is always called by any
+ * constructor which takes the top dimensional cells. If you use such a constructor,
+ * then there is no need to call this function. Call it only if you are putting the filtration
+ * of the cells by your own (for instance by using Top_dimensional_cells_iterator).
+ **/
+ void impose_lower_star_filtration(); // assume that top dimensional cells are already set.
+
+ /**
+ * Returns dimension of a complex.
+ **/
+ inline unsigned dimension() const { return sizes.size(); }
+
+ /**
+ * Returns number of all cubes in the data structure.
+ **/
+ inline unsigned size() const { return this->data.size(); }
+
+ /**
+ * Writing to stream operator. By using it we get the values T of cells in order in which they are stored in the
+ * structure. This procedure is used for debugging purposes.
+ **/
+ template <typename K>
+ friend std::ostream& operator<<(std::ostream& os, const Bitmap_cubical_complex_base<K>& b);
+
+ /**
+ * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values
+ * equally distributed in the range of data.
+ * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute
+ * persistence gets worst. When dealing with this type of data, one may want to put different values on cells to
+ * some number of bins. The function put_data_to_bins( std::size_t number_of_bins ) is designed for that purpose.
+ * The parameter of the function is the number of bins (distinct values) we want to have in the cubical complex.
+ **/
+ void put_data_to_bins(std::size_t number_of_bins);
+
+ /**
+ * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values
+ * equally distributed in the range of data.
+ * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute
+ * persistence gets worst. When dealing with this type of data, one may want to put different values on cells to
+ * some number of bins. The function put_data_to_bins( T diameter_of_bin ) is designed for that purpose.
+ * The parameter of it is the diameter of each bin. Note that the bottleneck distance between the persistence
+ * diagram of the cubical complex before and after using such a function will be bounded by the parameter
+ * diameter_of_bin.
+ **/
+ void put_data_to_bins(T diameter_of_bin);
+
+ /**
+ * Functions to find min and max values of filtration.
+ **/
+ std::pair<T, T> min_max_filtration();
+
+ // ITERATORS
+
+ /**
+ * @brief Iterator through all cells in the complex (in order they appear in the structure -- i.e.
+ * in lexicographical order).
+ **/
+ class All_cells_iterator : std::iterator<std::input_iterator_tag, T> {
+ public:
+ All_cells_iterator() { this->counter = 0; }
+
+ All_cells_iterator operator++() {
+ // first find first element of the counter that can be increased:
+ ++this->counter;
+ return *this;
+ }
+
+ All_cells_iterator operator++(int) {
+ All_cells_iterator result = *this;
+ ++(*this);
+ return result;
+ }
+
+ All_cells_iterator& operator=(const All_cells_iterator& rhs) {
+ this->counter = rhs.counter;
+ return *this;
+ }
+
+ bool operator==(const All_cells_iterator& rhs) const {
+ if (this->counter != rhs.counter) return false;
+ return true;
+ }
+
+ bool operator!=(const All_cells_iterator& rhs) const { return !(*this == rhs); }
+
+ /*
+ * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as
+ * an argument of the following functions:
+ * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell
+ * boundary and coboundary and dimension
+ * and in function get_cell_data to get a filtration of a cell.
+ */
+ std::size_t operator*() { return this->counter; }
+ friend class Bitmap_cubical_complex_base;
+
+ protected:
+ std::size_t counter;
+ };
+
+ /**
+ * Function returning a All_cells_iterator to the first cell of the bitmap.
+ **/
+ All_cells_iterator all_cells_iterator_begin() {
+ All_cells_iterator a;
+ return a;
+ }
+
+ /**
+ * Function returning a All_cells_iterator to the last cell of the bitmap.
+ **/
+ All_cells_iterator all_cells_iterator_end() {
+ All_cells_iterator a;
+ a.counter = this->data.size();
+ return a;
+ }
+
+ /**
+ * @brief All_cells_range class provides ranges for All_cells_iterator
+ **/
+ class All_cells_range {
+ public:
+ All_cells_range(Bitmap_cubical_complex_base* b) : b(b) {}
+
+ All_cells_iterator begin() { return b->all_cells_iterator_begin(); }
+
+ All_cells_iterator end() { return b->all_cells_iterator_end(); }
+
+ private:
+ Bitmap_cubical_complex_base<T>* b;
+ };
+
+ All_cells_range all_cells_range() { return All_cells_range(this); }
+
+ /**
+ * Boundary_range class provides ranges for boundary iterators.
+ **/
+ typedef typename std::vector<std::size_t>::const_iterator Boundary_iterator;
+ typedef typename std::vector<std::size_t> Boundary_range;
+
+ /**
+ * boundary_simplex_range creates an object of a Boundary_simplex_range class
+ * that provides ranges for the Boundary_simplex_iterator.
+ **/
+ Boundary_range boundary_range(std::size_t sh) { return this->get_boundary_of_a_cell(sh); }
+
+ /**
+ * Coboundary_range class provides ranges for boundary iterators.
+ **/
+ typedef typename std::vector<std::size_t>::const_iterator Coboundary_iterator;
+ typedef typename std::vector<std::size_t> Coboundary_range;
+
+ /**
+ * boundary_simplex_range creates an object of a Boundary_simplex_range class
+ * that provides ranges for the Boundary_simplex_iterator.
+ **/
+ Coboundary_range coboundary_range(std::size_t sh) { return this->get_coboundary_of_a_cell(sh); }
+
+ /**
+ * @brief Iterator through top dimensional cells of the complex. The cells appear in order they are stored
+ * in the structure (i.e. in lexicographical order)
+ **/
+ class Top_dimensional_cells_iterator : std::iterator<std::input_iterator_tag, T> {
+ public:
+ Top_dimensional_cells_iterator(Bitmap_cubical_complex_base& b) : b(b) {
+ this->counter = std::vector<std::size_t>(b.dimension());
+ // std::fill( this->counter.begin() , this->counter.end() , 0 );
+ }
+
+ Top_dimensional_cells_iterator operator++() {
+ // first find first element of the counter that can be increased:
+ std::size_t dim = 0;
+ while ((dim != this->b.dimension()) && (this->counter[dim] == this->b.sizes[dim] - 1)) ++dim;
+
+ if (dim != this->b.dimension()) {
+ ++this->counter[dim];
+ for (std::size_t i = 0; i != dim; ++i) {
+ this->counter[i] = 0;
+ }
+ } else {
+ ++this->counter[0];
+ }
+ return *this;
+ }
+
+ Top_dimensional_cells_iterator operator++(int) {
+ Top_dimensional_cells_iterator result = *this;
+ ++(*this);
+ return result;
+ }
+
+ Top_dimensional_cells_iterator& operator=(const Top_dimensional_cells_iterator& rhs) {
+ this->counter = rhs.counter;
+ this->b = rhs.b;
+ return *this;
+ }
+
+ bool operator==(const Top_dimensional_cells_iterator& rhs) const {
+ if (&this->b != &rhs.b) return false;
+ if (this->counter.size() != rhs.counter.size()) return false;
+ for (std::size_t i = 0; i != this->counter.size(); ++i) {
+ if (this->counter[i] != rhs.counter[i]) return false;
+ }
+ return true;
+ }
+
+ bool operator!=(const Top_dimensional_cells_iterator& rhs) const { return !(*this == rhs); }
+
+ /*
+ * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as
+ * an argument of the following functions:
+ * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell
+ * boundary and coboundary and dimension
+ * and in function get_cell_data to get a filtration of a cell.
+ */
+ std::size_t operator*() { return this->compute_index_in_bitmap(); }
+
+ std::size_t compute_index_in_bitmap() const {
+ std::size_t index = 0;
+ for (std::size_t i = 0; i != this->counter.size(); ++i) {
+ index += (2 * this->counter[i] + 1) * this->b.multipliers[i];
+ }
+ return index;
+ }
+
+ void print_counter() const {
+ for (std::size_t i = 0; i != this->counter.size(); ++i) {
+ std::cout << this->counter[i] << " ";
+ }
+ }
+ friend class Bitmap_cubical_complex_base;
+
+ protected:
+ std::vector<std::size_t> counter;
+ Bitmap_cubical_complex_base& b;
+ };
+
+ /**
+ * Function returning a Top_dimensional_cells_iterator to the first top dimensional cell of the bitmap.
+ **/
+ Top_dimensional_cells_iterator top_dimensional_cells_iterator_begin() {
+ Top_dimensional_cells_iterator a(*this);
+ return a;
+ }
+
+ /**
+ * Function returning a Top_dimensional_cells_iterator to the last top dimensional cell of the bitmap.
+ **/
+ Top_dimensional_cells_iterator top_dimensional_cells_iterator_end() {
+ Top_dimensional_cells_iterator a(*this);
+ for (std::size_t i = 0; i != this->dimension(); ++i) {
+ a.counter[i] = this->sizes[i] - 1;
+ }
+ a.counter[0]++;
+ return a;
+ }
+
+ /**
+ * @brief Top_dimensional_cells_iterator_range class provides ranges for Top_dimensional_cells_iterator_range
+ **/
+ class Top_dimensional_cells_range {
+ public:
+ Top_dimensional_cells_range(Bitmap_cubical_complex_base* b) : b(b) {}
+
+ Top_dimensional_cells_iterator begin() { return b->top_dimensional_cells_iterator_begin(); }
+
+ Top_dimensional_cells_iterator end() { return b->top_dimensional_cells_iterator_end(); }
+
+ private:
+ Bitmap_cubical_complex_base<T>* b;
+ };
+
+ Top_dimensional_cells_range top_dimensional_cells_range() { return Top_dimensional_cells_range(this); }
+
+ //****************************************************************************************************************//
+ //****************************************************************************************************************//
+ //****************************************************************************************************************//
+ //****************************************************************************************************************//
+
+ inline std::size_t number_cells() const { return this->total_number_of_cells; }
+
+ //****************************************************************************************************************//
+ //****************************************************************************************************************//
+ //****************************************************************************************************************//
+ //****************************************************************************************************************//
+
+ protected:
+ std::vector<unsigned> sizes;
+ std::vector<unsigned> multipliers;
+ std::vector<T> data;
+ std::size_t total_number_of_cells;
+
+ void set_up_containers(const std::vector<unsigned>& sizes) {
+ unsigned multiplier = 1;
+ for (std::size_t i = 0; i != sizes.size(); ++i) {
+ this->sizes.push_back(sizes[i]);
+ this->multipliers.push_back(multiplier);
+ multiplier *= 2 * sizes[i] + 1;
+ }
+ this->data = std::vector<T>(multiplier, std::numeric_limits<T>::infinity());
+ this->total_number_of_cells = multiplier;
+ }
+
+ std::size_t compute_position_in_bitmap(const std::vector<unsigned>& counter) {
+ std::size_t position = 0;
+ for (std::size_t i = 0; i != this->multipliers.size(); ++i) {
+ position += this->multipliers[i] * counter[i];
+ }
+ return position;
+ }
+
+ std::vector<unsigned> compute_counter_for_given_cell(std::size_t cell) const {
+ std::vector<unsigned> counter;
+ counter.reserve(this->sizes.size());
+ for (std::size_t dim = this->sizes.size(); dim != 0; --dim) {
+ counter.push_back(cell / this->multipliers[dim - 1]);
+ cell = cell % this->multipliers[dim - 1];
+ }
+ std::reverse(counter.begin(), counter.end());
+ return counter;
+ }
+ void read_perseus_style_file(const char* perseus_style_file);
+ void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector<unsigned>& sizes_in_following_directions,
+ const std::vector<T>& top_dimensional_cells);
+ Bitmap_cubical_complex_base(const char* perseus_style_file, std::vector<bool> directions);
+ Bitmap_cubical_complex_base(const std::vector<unsigned>& sizes, std::vector<bool> directions);
+ Bitmap_cubical_complex_base(const std::vector<unsigned>& dimensions, const std::vector<T>& top_dimensional_cells,
+ std::vector<bool> directions);
+};
+
+template <typename T>
+void Bitmap_cubical_complex_base<T>::put_data_to_bins(std::size_t number_of_bins) {
+ bool dbg = false;
+
+ std::pair<T, T> min_max = this->min_max_filtration();
+ T dx = (min_max.second - min_max.first) / (T)number_of_bins;
+
+ // now put the data into the appropriate bins:
+ for (std::size_t i = 0; i != this->data.size(); ++i) {
+ if (dbg) {
+ std::cerr << "Before binning : " << this->data[i] << std::endl;
+ }
+ this->data[i] = min_max.first + dx * (this->data[i] - min_max.first) / number_of_bins;
+ if (dbg) {
+ std::cerr << "After binning : " << this->data[i] << std::endl;
+ }
+ }
+}
+
+template <typename T>
+void Bitmap_cubical_complex_base<T>::put_data_to_bins(T diameter_of_bin) {
+ bool dbg = false;
+ std::pair<T, T> min_max = this->min_max_filtration();
+
+ std::size_t number_of_bins = (min_max.second - min_max.first) / diameter_of_bin;
+ // now put the data into the appropriate bins:
+ for (std::size_t i = 0; i != this->data.size(); ++i) {
+ if (dbg) {
+ std::cerr << "Before binning : " << this->data[i] << std::endl;
+ }
+ this->data[i] = min_max.first + diameter_of_bin * (this->data[i] - min_max.first) / number_of_bins;
+ if (dbg) {
+ std::cerr << "After binning : " << this->data[i] << std::endl;
+ }
+ }
+}
+
+template <typename T>
+std::pair<T, T> Bitmap_cubical_complex_base<T>::min_max_filtration() {
+ std::pair<T, T> min_max(std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity());
+ for (std::size_t i = 0; i != this->data.size(); ++i) {
+ if (this->data[i] < min_max.first) min_max.first = this->data[i];
+ if (this->data[i] > min_max.second) min_max.second = this->data[i];
+ }
+ return min_max;
+}
+
+template <typename K>
+std::ostream& operator<<(std::ostream& out, const Bitmap_cubical_complex_base<K>& b) {
+ for (typename Bitmap_cubical_complex_base<K>::all_cells_const_iterator it = b.all_cells_const_begin();
+ it != b.all_cells_const_end(); ++it) {
+ out << *it << " ";
+ }
+ return out;
+}
+
+template <typename T>
+Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base(const std::vector<unsigned>& sizes) {
+ this->set_up_containers(sizes);
+}
+
+template <typename T>
+void Bitmap_cubical_complex_base<T>::setup_bitmap_based_on_top_dimensional_cells_list(
+ const std::vector<unsigned>& sizes_in_following_directions, const std::vector<T>& top_dimensional_cells) {
+ this->set_up_containers(sizes_in_following_directions);
+
+ std::size_t number_of_top_dimensional_elements = 1;
+ for (std::size_t i = 0; i != sizes_in_following_directions.size(); ++i) {
+ number_of_top_dimensional_elements *= sizes_in_following_directions[i];
+ }
+ if (number_of_top_dimensional_elements != top_dimensional_cells.size()) {
+ std::cerr << "Error in constructor Bitmap_cubical_complex_base ( std::vector<std::size_t> "
+ << "sizes_in_following_directions, std::vector<T> top_dimensional_cells ). Number of top dimensional "
+ << "elements that follow from sizes_in_following_directions vector is different than the size of "
+ << "top_dimensional_cells vector."
+ << std::endl;
+ throw(
+ "Error in constructor Bitmap_cubical_complex_base( std::vector<std::size_t> sizes_in_following_directions,"
+ "std::vector<T> top_dimensional_cells ). Number of top dimensional elements that follow from "
+ "sizes_in_following_directions vector is different than the size of top_dimensional_cells vector.");
+ }
+
+ Bitmap_cubical_complex_base<T>::Top_dimensional_cells_iterator it(*this);
+ std::size_t index = 0;
+ for (it = this->top_dimensional_cells_iterator_begin(); it != this->top_dimensional_cells_iterator_end(); ++it) {
+ this->get_cell_data(*it) = top_dimensional_cells[index];
+ ++index;
+ }
+ this->impose_lower_star_filtration();
+}
+
+template <typename T>
+Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base(const std::vector<unsigned>& sizes_in_following_directions,
+ const std::vector<T>& top_dimensional_cells) {
+ this->setup_bitmap_based_on_top_dimensional_cells_list(sizes_in_following_directions, top_dimensional_cells);
+}
+
+template <typename T>
+void Bitmap_cubical_complex_base<T>::read_perseus_style_file(const char* perseus_style_file) {
+ bool dbg = false;
+ std::ifstream inFiltration;
+ inFiltration.open(perseus_style_file);
+ unsigned dimensionOfData;
+ inFiltration >> dimensionOfData;
+
+ if (dbg) {
+ std::cerr << "dimensionOfData : " << dimensionOfData << std::endl;
+ }
+
+ std::vector<unsigned> sizes;
+ sizes.reserve(dimensionOfData);
+ // all dimensions multiplied
+ std::size_t dimensions = 1;
+ for (std::size_t i = 0; i != dimensionOfData; ++i) {
+ unsigned size_in_this_dimension;
+ inFiltration >> size_in_this_dimension;
+ sizes.push_back(size_in_this_dimension);
+ dimensions *= size_in_this_dimension;
+ if (dbg) {
+ std::cerr << "size_in_this_dimension : " << size_in_this_dimension << std::endl;
+ }
+ }
+ this->set_up_containers(sizes);
+
+ Bitmap_cubical_complex_base<T>::Top_dimensional_cells_iterator it(*this);
+ it = this->top_dimensional_cells_iterator_begin();
+
+ T filtrationLevel = 0.;
+ std::size_t filtration_counter = 0;
+ while (!inFiltration.eof()) {
+ std::string line;
+ getline(inFiltration, line);
+ if (line.length() != 0) {
+ int n = sscanf(line.c_str(), "%lf", &filtrationLevel);
+ if (n != 1) {
+ std::string perseus_error("Bad Perseus file format. This line is incorrect : " + line);
+ throw std::ios_base::failure(perseus_error.c_str());
+ }
+
+ if (dbg) {
+ std::cerr << "Cell of an index : " << it.compute_index_in_bitmap()
+ << " and dimension: " << this->get_dimension_of_a_cell(it.compute_index_in_bitmap())
+ << " get the value : " << filtrationLevel << std::endl;
+ }
+ this->get_cell_data(*it) = filtrationLevel;
+ ++it;
+ ++filtration_counter;
+ }
+ }
+
+ if (filtration_counter != dimensions) {
+ std::string perseus_error("Bad Perseus file format. Read " + std::to_string(filtration_counter) + " expected " + \
+ std::to_string(dimensions) + " values");
+ throw std::ios_base::failure(perseus_error.c_str());
+ }
+
+ inFiltration.close();
+ this->impose_lower_star_filtration();
+}
+
+template <typename T>
+Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base(const char* perseus_style_file,
+ std::vector<bool> directions) {
+ // this constructor is here just for compatibility with a class that creates cubical complexes with periodic boundary
+ // conditions.
+ // It ignores the last parameter of the function.
+ this->read_perseus_style_file(perseus_style_file);
+}
+
+template <typename T>
+Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base(const std::vector<unsigned>& sizes,
+ std::vector<bool> directions) {
+ // this constructor is here just for compatibility with a class that creates cubical complexes with periodic boundary
+ // conditions.
+ // It ignores the last parameter of the function.
+ this->set_up_containers(sizes);
+}
+
+template <typename T>
+Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base(const std::vector<unsigned>& dimensions,
+ const std::vector<T>& top_dimensional_cells,
+ std::vector<bool> directions) {
+ // this constructor is here just for compatibility with a class that creates cubical complexes with periodic boundary
+ // conditions.
+ // It ignores the last parameter of the function.
+ this->setup_bitmap_based_on_top_dimensional_cells_list(dimensions, top_dimensional_cells);
+}
+
+template <typename T>
+Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base(const char* perseus_style_file) {
+ this->read_perseus_style_file(perseus_style_file);
+}
+
+template <typename T>
+std::vector<std::size_t> Bitmap_cubical_complex_base<T>::get_boundary_of_a_cell(std::size_t cell) const {
+ std::vector<std::size_t> boundary_elements;
+
+ // Speed traded of for memory. Check if it is better in practice.
+ boundary_elements.reserve(this->dimension() * 2);
+
+ std::size_t sum_of_dimensions = 0;
+ std::size_t cell1 = cell;
+ for (std::size_t i = this->multipliers.size(); i != 0; --i) {
+ unsigned position = cell1 / this->multipliers[i - 1];
+ if (position % 2 == 1) {
+ if (sum_of_dimensions % 2) {
+ boundary_elements.push_back(cell + this->multipliers[i - 1]);
+ boundary_elements.push_back(cell - this->multipliers[i - 1]);
+ } else {
+ boundary_elements.push_back(cell - this->multipliers[i - 1]);
+ boundary_elements.push_back(cell + this->multipliers[i - 1]);
+ }
+ ++sum_of_dimensions;
+ }
+ cell1 = cell1 % this->multipliers[i - 1];
+ }
+
+ return boundary_elements;
+}
+
+template <typename T>
+std::vector<std::size_t> Bitmap_cubical_complex_base<T>::get_coboundary_of_a_cell(std::size_t cell) const {
+ std::vector<unsigned> counter = this->compute_counter_for_given_cell(cell);
+ std::vector<std::size_t> coboundary_elements;
+ std::size_t cell1 = cell;
+ for (std::size_t i = this->multipliers.size(); i != 0; --i) {
+ unsigned position = cell1 / this->multipliers[i - 1];
+ if (position % 2 == 0) {
+ if ((cell > this->multipliers[i - 1]) && (counter[i - 1] != 0)) {
+ coboundary_elements.push_back(cell - this->multipliers[i - 1]);
+ }
+ if ((cell + this->multipliers[i - 1] < this->data.size()) && (counter[i - 1] != 2 * this->sizes[i - 1])) {
+ coboundary_elements.push_back(cell + this->multipliers[i - 1]);
+ }
+ }
+ cell1 = cell1 % this->multipliers[i - 1];
+ }
+ return coboundary_elements;
+}
+
+template <typename T>
+unsigned Bitmap_cubical_complex_base<T>::get_dimension_of_a_cell(std::size_t cell) const {
+ bool dbg = false;
+ if (dbg) std::cerr << "\n\n\n Computing position o a cell of an index : " << cell << std::endl;
+ unsigned dimension = 0;
+ for (std::size_t i = this->multipliers.size(); i != 0; --i) {
+ unsigned position = cell / this->multipliers[i - 1];
+
+ if (dbg) {
+ std::cerr << "i-1 :" << i - 1 << std::endl;
+ std::cerr << "cell : " << cell << std::endl;
+ std::cerr << "position : " << position << std::endl;
+ std::cerr << "multipliers[" << i - 1 << "] = " << this->multipliers[i - 1] << std::endl;
+ }
+
+ if (position % 2 == 1) {
+ if (dbg) std::cerr << "Nonzero length in this direction \n";
+ dimension++;
+ }
+ cell = cell % this->multipliers[i - 1];
+ }
+ return dimension;
+}
+
+template <typename T>
+inline T& Bitmap_cubical_complex_base<T>::get_cell_data(std::size_t cell) {
+ return this->data[cell];
+}
+
+template <typename T>
+void Bitmap_cubical_complex_base<T>::impose_lower_star_filtration() {
+ bool dbg = false;
+
+ // this vector will be used to check which elements have already been taken care of in imposing lower star filtration
+ std::vector<bool> is_this_cell_considered(this->data.size(), false);
+
+ std::size_t size_to_reserve = 1;
+ for (std::size_t i = 0; i != this->multipliers.size(); ++i) {
+ size_to_reserve *= (std::size_t)((this->multipliers[i] - 1) / 2);
+ }
+
+ std::vector<std::size_t> indices_to_consider;
+ indices_to_consider.reserve(size_to_reserve);
+ // we assume here that we already have a filtration on the top dimensional cells and
+ // we have to extend it to lower ones.
+ typename Bitmap_cubical_complex_base<T>::Top_dimensional_cells_iterator it(*this);
+ for (it = this->top_dimensional_cells_iterator_begin(); it != this->top_dimensional_cells_iterator_end(); ++it) {
+ indices_to_consider.push_back(it.compute_index_in_bitmap());
+ }
+
+ while (indices_to_consider.size()) {
+ if (dbg) {
+ std::cerr << "indices_to_consider in this iteration \n";
+ for (std::size_t i = 0; i != indices_to_consider.size(); ++i) {
+ std::cout << indices_to_consider[i] << " ";
+ }
+ }
+ std::vector<std::size_t> new_indices_to_consider;
+ for (std::size_t i = 0; i != indices_to_consider.size(); ++i) {
+ std::vector<std::size_t> bd = this->get_boundary_of_a_cell(indices_to_consider[i]);
+ for (std::size_t boundaryIt = 0; boundaryIt != bd.size(); ++boundaryIt) {
+ if (dbg) {
+ std::cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[bd[boundaryIt]]
+ << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[indices_to_consider[i]]
+ << std::endl;
+ }
+ if (this->data[bd[boundaryIt]] > this->data[indices_to_consider[i]]) {
+ this->data[bd[boundaryIt]] = this->data[indices_to_consider[i]];
+ if (dbg) {
+ std::cerr << "Setting the value of a cell : " << bd[boundaryIt]
+ << " to : " << this->data[indices_to_consider[i]] << std::endl;
+ }
+ }
+ if (is_this_cell_considered[bd[boundaryIt]] == false) {
+ new_indices_to_consider.push_back(bd[boundaryIt]);
+ is_this_cell_considered[bd[boundaryIt]] = true;
+ }
+ }
+ }
+ indices_to_consider.swap(new_indices_to_consider);
+ }
+}
+
+template <typename T>
+bool compareFirstElementsOfTuples(const std::pair<std::pair<T, std::size_t>, char>& first,
+ const std::pair<std::pair<T, std::size_t>, char>& second) {
+ if (first.first.first < second.first.first) {
+ return true;
+ } else {
+ if (first.first.first > second.first.first) {
+ return false;
+ }
+ // in this case first.first.first == second.first.first, so we need to compare dimensions
+ return first.second < second.second;
+ }
+}
+
+} // namespace cubical_complex
+
+namespace Cubical_complex = cubical_complex;
+
+} // namespace Gudhi
+
+#endif // BITMAP_CUBICAL_COMPLEX_BASE_H_
diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h
new file mode 100644
index 00000000..edd794fe
--- /dev/null
+++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h
@@ -0,0 +1,384 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Pawel Dlotko
+ *
+ * Copyright (C) 2015 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#ifndef BITMAP_CUBICAL_COMPLEX_PERIODIC_BOUNDARY_CONDITIONS_BASE_H_
+#define BITMAP_CUBICAL_COMPLEX_PERIODIC_BOUNDARY_CONDITIONS_BASE_H_
+
+#include <gudhi/Bitmap_cubical_complex_base.h>
+
+#include <cmath>
+#include <limits> // for numeric_limits<>
+#include <vector>
+#include <stdexcept>
+#include <cstddef>
+
+namespace Gudhi {
+
+namespace cubical_complex {
+
+// in this class, we are storing all the elements which are in normal bitmap (i.e. the bitmap without the periodic
+// boundary conditions). But, we set up the iterators and the procedures to compute boundary and coboundary in the way
+// that it is all right. We assume here that all the cells that are on the left / bottom and so on remains, while all
+// the cells on the right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base
+
+/**
+ * @brief Cubical complex with periodic boundary conditions represented as a bitmap.
+ * @ingroup cubical_complex
+ * @details This is a class implementing a bitmap data structure with periodic boundary conditions. Most of the
+ * functions are
+ * identical to the functions from Bitmap_cubical_complex_base.
+ * The ones that needed to be updated are the constructors and get_boundary_of_a_cell and get_coboundary_of_a_cell.
+ */
+template <typename T>
+class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_cubical_complex_base<T> {
+ public:
+ // constructors that take an extra parameter:
+
+ /**
+ * Default constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class.
+ */
+ Bitmap_cubical_complex_periodic_boundary_conditions_base() {}
+ /**
+ * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the following
+ * parameters: (1) vector with numbers of top dimensional cells in all dimensions and (2) vector of booleans. If
+ * at i-th position of this vector there is true value, that means that periodic boundary conditions are to be
+ * imposed in this direction. In case of false, the periodic boundary conditions will not be imposed in the direction
+ * i.
+ */
+ Bitmap_cubical_complex_periodic_boundary_conditions_base(
+ const std::vector<unsigned>& sizes,
+ const std::vector<bool>& directions_in_which_periodic_b_cond_are_to_be_imposed);
+ /**
+ * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the name of Perseus
+ * style file as an input. Please consult the documentation about the specification of the file.
+ */
+ Bitmap_cubical_complex_periodic_boundary_conditions_base(const char* perseusStyleFile);
+ /**
+ * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the following
+ * parameters: (1) vector with numbers of top dimensional cells in all dimensions and (2) vector of top dimensional
+ * cells (ordered lexicographically) and (3) vector of booleans. If at i-th position of this vector there is true
+ * value, that means that periodic boundary conditions are to be imposed in this direction. In case of false, the
+ * periodic boundary conditions will not be imposed in the direction i.
+ */
+ Bitmap_cubical_complex_periodic_boundary_conditions_base(
+ const std::vector<unsigned>& dimensions, const std::vector<T>& topDimensionalCells,
+ const std::vector<bool>& directions_in_which_periodic_b_cond_are_to_be_imposed);
+
+ /**
+ * Destructor of the Bitmap_cubical_complex_periodic_boundary_conditions_base class.
+ **/
+ virtual ~Bitmap_cubical_complex_periodic_boundary_conditions_base() {}
+
+ // overwritten methods co compute boundary and coboundary
+ /**
+ * A version of a function that return boundary of a given cell for an object of
+ * Bitmap_cubical_complex_periodic_boundary_conditions_base class.
+ * The boundary elements are guaranteed to be returned so that the
+ * incidence coefficients are alternating.
+ */
+ virtual std::vector<std::size_t> get_boundary_of_a_cell(std::size_t cell) const;
+
+ /**
+ * A version of a function that return coboundary of a given cell for an object of
+ * Bitmap_cubical_complex_periodic_boundary_conditions_base class.
+ * Note that unlike in the case of boundary, over here the elements are
+ * not guaranteed to be returned with alternating incidence numbers.
+ * To compute incidence between cells use compute_incidence_between_cells
+ * procedure
+ */
+ virtual std::vector<std::size_t> get_coboundary_of_a_cell(std::size_t cell) const;
+
+ /**
+ * This procedure compute incidence numbers between cubes. For a cube \f$A\f$ of
+ * dimension n and a cube \f$B \subset A\f$ of dimension n-1, an incidence
+ * between \f$A\f$ and \f$B\f$ is the integer with which \f$B\f$ appears in the boundary of \f$A\f$.
+ * Note that first parameter is a cube of dimension n,
+ * and the second parameter is an adjusted cube in dimension n-1.
+ * Given \f$A = [b_1,e_1] \times \ldots \ [b_{j-1},e_{j-1}] \times [b_{j},e_{j}] \times [b_{j+1},e_{j+1}] \times \ldots
+ *\times [b_{n},e_{n}] \f$
+ * such that \f$ b_{j} \neq e_{j} \f$
+ * and \f$B = [b_1,e_1] \times \ldots \ [b_{j-1},e_{j-1}] \times [a,a] \times [b_{j+1},e_{j+1}] \times \ldots \times
+ *[b_{n},e_{n}]s \f$
+ * where \f$ a = b_{j}\f$ or \f$ a = e_{j}\f$, the incidence between \f$A\f$ and \f$B\f$
+ * computed by this procedure is given by formula:
+ * \f$ c\ (-1)^{\sum_{i=1}^{j-1} dim [b_{i},e_{i}]} \f$
+ * Where \f$ dim [b_{i},e_{i}] = 0 \f$ if \f$ b_{i}=e_{i} \f$ and 1 in other case.
+ * c is -1 if \f$ a = b_{j}\f$ and 1 if \f$ a = e_{j}\f$.
+ * @exception std::logic_error In case when the cube \f$B\f$ is not n-1
+ * dimensional face of a cube \f$A\f$.
+ **/
+ virtual int compute_incidence_between_cells(std::size_t coface, std::size_t face) {
+ // first get the counters for coface and face:
+ std::vector<unsigned> coface_counter = this->compute_counter_for_given_cell(coface);
+ std::vector<unsigned> face_counter = this->compute_counter_for_given_cell(face);
+
+ // coface_counter and face_counter should agree at all positions except from one:
+ int number_of_position_in_which_counters_do_not_agree = -1;
+ std::size_t number_of_full_faces_that_comes_before = 0;
+ for (std::size_t i = 0; i != coface_counter.size(); ++i) {
+ if ((coface_counter[i] % 2 == 1) && (number_of_position_in_which_counters_do_not_agree == -1)) {
+ ++number_of_full_faces_that_comes_before;
+ }
+ if (coface_counter[i] != face_counter[i]) {
+ if (number_of_position_in_which_counters_do_not_agree != -1) {
+ std::cout << "Cells given to compute_incidence_between_cells procedure do not form a pair of coface-face.\n";
+ throw std::logic_error(
+ "Cells given to compute_incidence_between_cells procedure do not form a pair of coface-face.");
+ }
+ number_of_position_in_which_counters_do_not_agree = i;
+ }
+ }
+
+ int incidence = 1;
+ if (number_of_full_faces_that_comes_before % 2) incidence = -1;
+ // if the face cell is on the right from coface cell:
+ if ((coface_counter[number_of_position_in_which_counters_do_not_agree] + 1 ==
+ face_counter[number_of_position_in_which_counters_do_not_agree]) ||
+ ((coface_counter[number_of_position_in_which_counters_do_not_agree] != 1) &&
+ (face_counter[number_of_position_in_which_counters_do_not_agree] == 0))) {
+ incidence *= -1;
+ }
+
+ return incidence;
+ }
+
+ protected:
+ std::vector<bool> directions_in_which_periodic_b_cond_are_to_be_imposed;
+
+ void set_up_containers(const std::vector<unsigned>& sizes) {
+ unsigned multiplier = 1;
+ for (std::size_t i = 0; i != sizes.size(); ++i) {
+ this->sizes.push_back(sizes[i]);
+ this->multipliers.push_back(multiplier);
+
+ if (directions_in_which_periodic_b_cond_are_to_be_imposed[i]) {
+ multiplier *= 2 * sizes[i];
+ } else {
+ multiplier *= 2 * sizes[i] + 1;
+ }
+ }
+ // std::reverse( this->sizes.begin() , this->sizes.end() );
+ this->data = std::vector<T>(multiplier, std::numeric_limits<T>::infinity());
+ this->total_number_of_cells = multiplier;
+ }
+ Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector<unsigned>& sizes);
+ Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector<unsigned>& dimensions,
+ const std::vector<T>& topDimensionalCells);
+
+ /**
+ * A procedure used to construct the data structures in the class.
+ **/
+ void construct_complex_based_on_top_dimensional_cells(
+ const std::vector<unsigned>& dimensions, const std::vector<T>& topDimensionalCells,
+ const std::vector<bool>& directions_in_which_periodic_b_cond_are_to_be_imposed);
+};
+
+template <typename T>
+void Bitmap_cubical_complex_periodic_boundary_conditions_base<T>::construct_complex_based_on_top_dimensional_cells(
+ const std::vector<unsigned>& dimensions, const std::vector<T>& topDimensionalCells,
+ const std::vector<bool>& directions_in_which_periodic_b_cond_are_to_be_imposed) {
+ this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed;
+ this->set_up_containers(dimensions);
+
+ std::size_t i = 0;
+ for (auto it = this->top_dimensional_cells_iterator_begin(); it != this->top_dimensional_cells_iterator_end(); ++it) {
+ this->get_cell_data(*it) = topDimensionalCells[i];
+ ++i;
+ }
+ this->impose_lower_star_filtration();
+}
+
+template <typename T>
+Bitmap_cubical_complex_periodic_boundary_conditions_base<T>::Bitmap_cubical_complex_periodic_boundary_conditions_base(
+ const std::vector<unsigned>& sizes,
+ const std::vector<bool>& directions_in_which_periodic_b_cond_are_to_be_imposed) {
+ this->directions_in_which_periodic_b_cond_are_to_be_imposed(directions_in_which_periodic_b_cond_are_to_be_imposed);
+ this->set_up_containers(sizes);
+}
+
+template <typename T>
+Bitmap_cubical_complex_periodic_boundary_conditions_base<T>::Bitmap_cubical_complex_periodic_boundary_conditions_base(
+ const char* perseus_style_file) {
+ // for Perseus style files:
+ bool dbg = false;
+
+ std::ifstream inFiltration;
+ inFiltration.open(perseus_style_file);
+ unsigned dimensionOfData;
+ inFiltration >> dimensionOfData;
+
+ this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector<bool>(dimensionOfData, false);
+
+ std::vector<unsigned> sizes;
+ sizes.reserve(dimensionOfData);
+ for (std::size_t i = 0; i != dimensionOfData; ++i) {
+ int size_in_this_dimension;
+ inFiltration >> size_in_this_dimension;
+ if (size_in_this_dimension < 0) {
+ this->directions_in_which_periodic_b_cond_are_to_be_imposed[i] = true;
+ }
+ sizes.push_back(abs(size_in_this_dimension));
+ }
+ this->set_up_containers(sizes);
+
+ typename Bitmap_cubical_complex_periodic_boundary_conditions_base<T>::Top_dimensional_cells_iterator it(*this);
+ it = this->top_dimensional_cells_iterator_begin();
+
+ while (!inFiltration.eof()) {
+ double filtrationLevel;
+ inFiltration >> filtrationLevel;
+ if (inFiltration.eof()) break;
+
+ if (dbg) {
+ std::cerr << "Cell of an index : " << it.compute_index_in_bitmap()
+ << " and dimension: " << this->get_dimension_of_a_cell(it.compute_index_in_bitmap())
+ << " get the value : " << filtrationLevel << std::endl;
+ }
+ this->get_cell_data(*it) = filtrationLevel;
+ ++it;
+ }
+ inFiltration.close();
+ this->impose_lower_star_filtration();
+}
+
+template <typename T>
+Bitmap_cubical_complex_periodic_boundary_conditions_base<T>::Bitmap_cubical_complex_periodic_boundary_conditions_base(
+ const std::vector<unsigned>& sizes) {
+ this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector<bool>(sizes.size(), false);
+ this->set_up_containers(sizes);
+}
+
+template <typename T>
+Bitmap_cubical_complex_periodic_boundary_conditions_base<T>::Bitmap_cubical_complex_periodic_boundary_conditions_base(
+ const std::vector<unsigned>& dimensions, const std::vector<T>& topDimensionalCells) {
+ std::vector<bool> directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector<bool>(dimensions.size(), false);
+ this->construct_complex_based_on_top_dimensional_cells(dimensions, topDimensionalCells,
+ directions_in_which_periodic_b_cond_are_to_be_imposed);
+}
+
+template <typename T>
+Bitmap_cubical_complex_periodic_boundary_conditions_base<T>::Bitmap_cubical_complex_periodic_boundary_conditions_base(
+ const std::vector<unsigned>& dimensions, const std::vector<T>& topDimensionalCells,
+ const std::vector<bool>& directions_in_which_periodic_b_cond_are_to_be_imposed) {
+ this->construct_complex_based_on_top_dimensional_cells(dimensions, topDimensionalCells,
+ directions_in_which_periodic_b_cond_are_to_be_imposed);
+}
+
+// ***********************Methods************************ //
+
+template <typename T>
+std::vector<std::size_t> Bitmap_cubical_complex_periodic_boundary_conditions_base<T>::get_boundary_of_a_cell(
+ std::size_t cell) const {
+ bool dbg = false;
+ if (dbg) {
+ std::cerr << "Computations of boundary of a cell : " << cell << std::endl;
+ }
+
+ std::vector<std::size_t> boundary_elements;
+ boundary_elements.reserve(this->dimension() * 2);
+ std::size_t cell1 = cell;
+ std::size_t sum_of_dimensions = 0;
+
+ for (std::size_t i = this->multipliers.size(); i != 0; --i) {
+ unsigned position = cell1 / this->multipliers[i - 1];
+ // this cell have a nonzero length in this direction, therefore we can compute its boundary in this direction.
+ if (position % 2 == 1) {
+ // if there are no periodic boundary conditions in this direction, we do not have to do anything.
+ if (!directions_in_which_periodic_b_cond_are_to_be_imposed[i - 1]) {
+ // std::cerr << "A\n";
+ if (sum_of_dimensions % 2) {
+ boundary_elements.push_back(cell - this->multipliers[i - 1]);
+ boundary_elements.push_back(cell + this->multipliers[i - 1]);
+ } else {
+ boundary_elements.push_back(cell + this->multipliers[i - 1]);
+ boundary_elements.push_back(cell - this->multipliers[i - 1]);
+ }
+ if (dbg) {
+ std::cerr << cell - this->multipliers[i - 1] << " " << cell + this->multipliers[i - 1] << " ";
+ }
+ } else {
+ // in this direction we have to do boundary conditions. Therefore, we need to check if we are not at the end.
+ if (position != 2 * this->sizes[i - 1] - 1) {
+ // std::cerr << "B\n";
+ if (sum_of_dimensions % 2) {
+ boundary_elements.push_back(cell - this->multipliers[i - 1]);
+ boundary_elements.push_back(cell + this->multipliers[i - 1]);
+ } else {
+ boundary_elements.push_back(cell + this->multipliers[i - 1]);
+ boundary_elements.push_back(cell - this->multipliers[i - 1]);
+ }
+ if (dbg) {
+ std::cerr << cell - this->multipliers[i - 1] << " " << cell + this->multipliers[i - 1] << " ";
+ }
+ } else {
+ // std::cerr << "C\n";
+ if (sum_of_dimensions % 2) {
+ boundary_elements.push_back(cell - this->multipliers[i - 1]);
+ boundary_elements.push_back(cell - (2 * this->sizes[i - 1] - 1) * this->multipliers[i - 1]);
+ } else {
+ boundary_elements.push_back(cell - (2 * this->sizes[i - 1] - 1) * this->multipliers[i - 1]);
+ boundary_elements.push_back(cell - this->multipliers[i - 1]);
+ }
+ if (dbg) {
+ std::cerr << cell - this->multipliers[i - 1] << " "
+ << cell - (2 * this->sizes[i - 1] - 1) * this->multipliers[i - 1] << " ";
+ }
+ }
+ }
+ ++sum_of_dimensions;
+ }
+ cell1 = cell1 % this->multipliers[i - 1];
+ }
+ return boundary_elements;
+}
+
+template <typename T>
+std::vector<std::size_t> Bitmap_cubical_complex_periodic_boundary_conditions_base<T>::get_coboundary_of_a_cell(
+ std::size_t cell) const {
+ std::vector<unsigned> counter = this->compute_counter_for_given_cell(cell);
+ std::vector<std::size_t> coboundary_elements;
+ std::size_t cell1 = cell;
+ for (std::size_t i = this->multipliers.size(); i != 0; --i) {
+ unsigned position = cell1 / this->multipliers[i - 1];
+ // if the cell has zero length in this direction, then it will have cbd in this direction.
+ if (position % 2 == 0) {
+ if (!this->directions_in_which_periodic_b_cond_are_to_be_imposed[i - 1]) {
+ // no periodic boundary conditions in this direction
+ if ((counter[i - 1] != 0) && (cell > this->multipliers[i - 1])) {
+ coboundary_elements.push_back(cell - this->multipliers[i - 1]);
+ }
+ if ((counter[i - 1] != 2 * this->sizes[i - 1]) && (cell + this->multipliers[i - 1] < this->data.size())) {
+ coboundary_elements.push_back(cell + this->multipliers[i - 1]);
+ }
+ } else {
+ // we want to have periodic boundary conditions in this direction
+ if (counter[i - 1] != 0) {
+ coboundary_elements.push_back(cell - this->multipliers[i - 1]);
+ coboundary_elements.push_back(cell + this->multipliers[i - 1]);
+ } else {
+ // in this case counter[i-1] == 0.
+ coboundary_elements.push_back(cell + this->multipliers[i - 1]);
+ coboundary_elements.push_back(cell + (2 * this->sizes[i - 1] - 1) * this->multipliers[i - 1]);
+ }
+ }
+ }
+
+ cell1 = cell1 % this->multipliers[i - 1];
+ }
+ return coboundary_elements;
+}
+
+} // namespace cubical_complex
+
+namespace Cubical_complex = cubical_complex;
+
+} // namespace Gudhi
+
+#endif // BITMAP_CUBICAL_COMPLEX_PERIODIC_BOUNDARY_CONDITIONS_BASE_H_
diff --git a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp
new file mode 100644
index 00000000..f18adb36
--- /dev/null
+++ b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp
@@ -0,0 +1,1581 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Pawel Dlotko
+ *
+ * Copyright (C) 2015 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "cubical_complex"
+#include <boost/test/unit_test.hpp>
+
+#include <gudhi/reader_utils.h>
+#include <gudhi/Bitmap_cubical_complex.h>
+#include <gudhi/Persistent_cohomology.h>
+
+// standard stuff
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <limits>
+
+typedef Gudhi::cubical_complex::Bitmap_cubical_complex_base<double> Bitmap_cubical_complex_base;
+typedef Gudhi::cubical_complex::Bitmap_cubical_complex<Bitmap_cubical_complex_base> Bitmap_cubical_complex;
+
+typedef Gudhi::cubical_complex::Bitmap_cubical_complex_periodic_boundary_conditions_base<double>
+ Bitmap_cubical_complex_periodic_boundary_conditions_base;
+typedef Gudhi::cubical_complex::Bitmap_cubical_complex<Bitmap_cubical_complex_periodic_boundary_conditions_base>
+ Bitmap_cubical_complex_periodic_boundary_conditions;
+
+BOOST_AUTO_TEST_CASE(check_dimension) {
+ std::vector<double> increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9});
+
+ std::vector<unsigned> dimensions({3, 3});
+
+ Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells);
+ BOOST_CHECK(increasing.dimension() == 2);
+}
+
+BOOST_AUTO_TEST_CASE(topDimensionalCellsIterator_test) {
+ std::vector<double> expectedFiltrationValues1({0, 0, 0, 0, 100, 0, 0, 0, 0});
+
+ std::vector<double> expectedFiltrationValues2({1, 2, 3, 4, 5, 6, 7, 8, 9});
+
+ std::vector<double> increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9});
+
+ std::vector<double> oneDimensionalCycle({0, 0, 0, 0, 100, 0, 0, 0, 0});
+
+ std::vector<unsigned> dimensions({3, 3});
+
+ Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells);
+ Bitmap_cubical_complex hole(dimensions, oneDimensionalCycle);
+
+ int i = 0;
+ for (Bitmap_cubical_complex::Top_dimensional_cells_iterator it = increasing.top_dimensional_cells_iterator_begin();
+ it != increasing.top_dimensional_cells_iterator_end(); ++it) {
+ BOOST_CHECK(increasing.get_cell_data(*it) == expectedFiltrationValues2[i]);
+ ++i;
+ }
+ i = 0;
+ for (Bitmap_cubical_complex::Top_dimensional_cells_iterator it = hole.top_dimensional_cells_iterator_begin();
+ it != hole.top_dimensional_cells_iterator_end(); ++it) {
+ BOOST_CHECK(hole.get_cell_data(*it) == expectedFiltrationValues1[i]);
+ ++i;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(compute_boundary_test_1) {
+ std::vector<double> boundary0;
+ std::vector<double> boundary1;
+ boundary1.push_back(0);
+ boundary1.push_back(2);
+ std::vector<double> boundary2;
+ std::vector<double> boundary3;
+ boundary3.push_back(2);
+ boundary3.push_back(4);
+ std::vector<double> boundary4;
+ std::vector<double> boundary5;
+ boundary5.push_back(4);
+ boundary5.push_back(6);
+ std::vector<double> boundary6;
+ std::vector<double> boundary7;
+ boundary7.push_back(0);
+ boundary7.push_back(14);
+ std::vector<double> boundary8;
+ boundary8.push_back(1);
+ boundary8.push_back(15);
+ boundary8.push_back(9);
+ boundary8.push_back(7);
+ std::vector<double> boundary9;
+ boundary9.push_back(2);
+ boundary9.push_back(16);
+ std::vector<double> boundary10;
+ boundary10.push_back(3);
+ boundary10.push_back(17);
+ boundary10.push_back(11);
+ boundary10.push_back(9);
+ std::vector<double> boundary11;
+ boundary11.push_back(4);
+ boundary11.push_back(18);
+ std::vector<double> boundary12;
+ boundary12.push_back(5);
+ boundary12.push_back(19);
+ boundary12.push_back(13);
+ boundary12.push_back(11);
+ std::vector<double> boundary13;
+ boundary13.push_back(6);
+ boundary13.push_back(20);
+ std::vector<double> boundary14;
+ std::vector<double> boundary15;
+ boundary15.push_back(14);
+ boundary15.push_back(16);
+ std::vector<double> boundary16;
+ std::vector<double> boundary17;
+ boundary17.push_back(16);
+ boundary17.push_back(18);
+ std::vector<double> boundary18;
+ std::vector<double> boundary19;
+ boundary19.push_back(18);
+ boundary19.push_back(20);
+ std::vector<double> boundary20;
+ std::vector<double> boundary21;
+ boundary21.push_back(14);
+ boundary21.push_back(28);
+ std::vector<double> boundary22;
+ boundary22.push_back(15);
+ boundary22.push_back(29);
+ boundary22.push_back(23);
+ boundary22.push_back(21);
+ std::vector<double> boundary23;
+ boundary23.push_back(16);
+ boundary23.push_back(30);
+ std::vector<double> boundary24;
+ boundary24.push_back(17);
+ boundary24.push_back(31);
+ boundary24.push_back(25);
+ boundary24.push_back(23);
+ std::vector<double> boundary25;
+ boundary25.push_back(18);
+ boundary25.push_back(32);
+ std::vector<double> boundary26;
+ boundary26.push_back(19);
+ boundary26.push_back(33);
+ boundary26.push_back(27);
+ boundary26.push_back(25);
+ std::vector<double> boundary27;
+ boundary27.push_back(20);
+ boundary27.push_back(34);
+ std::vector<double> boundary28;
+ std::vector<double> boundary29;
+ boundary29.push_back(28);
+ boundary29.push_back(30);
+ std::vector<double> boundary30;
+ std::vector<double> boundary31;
+ boundary31.push_back(30);
+ boundary31.push_back(32);
+ std::vector<double> boundary32;
+ std::vector<double> boundary33;
+ boundary33.push_back(32);
+ boundary33.push_back(34);
+ std::vector<double> boundary34;
+ std::vector<double> boundary35;
+ boundary35.push_back(28);
+ boundary35.push_back(42);
+ std::vector<double> boundary36;
+ boundary36.push_back(29);
+ boundary36.push_back(43);
+ boundary36.push_back(37);
+ boundary36.push_back(35);
+ std::vector<double> boundary37;
+ boundary37.push_back(30);
+ boundary37.push_back(44);
+ std::vector<double> boundary38;
+ boundary38.push_back(31);
+ boundary38.push_back(45);
+ boundary38.push_back(39);
+ boundary38.push_back(37);
+ std::vector<double> boundary39;
+ boundary39.push_back(32);
+ boundary39.push_back(46);
+ std::vector<double> boundary40;
+ boundary40.push_back(33);
+ boundary40.push_back(47);
+ boundary40.push_back(41);
+ boundary40.push_back(39);
+ std::vector<double> boundary41;
+ boundary41.push_back(34);
+ boundary41.push_back(48);
+ std::vector<double> boundary42;
+ std::vector<double> boundary43;
+ boundary43.push_back(42);
+ boundary43.push_back(44);
+ std::vector<double> boundary44;
+ std::vector<double> boundary45;
+ boundary45.push_back(44);
+ boundary45.push_back(46);
+ std::vector<double> boundary46;
+ std::vector<double> boundary47;
+ boundary47.push_back(46);
+ boundary47.push_back(48);
+ std::vector<double> boundary48;
+ std::vector<std::vector<double> > boundaries;
+ boundaries.push_back(boundary0);
+ boundaries.push_back(boundary1);
+ boundaries.push_back(boundary2);
+ boundaries.push_back(boundary3);
+ boundaries.push_back(boundary4);
+ boundaries.push_back(boundary5);
+ boundaries.push_back(boundary6);
+ boundaries.push_back(boundary7);
+ boundaries.push_back(boundary8);
+ boundaries.push_back(boundary9);
+ boundaries.push_back(boundary10);
+ boundaries.push_back(boundary11);
+ boundaries.push_back(boundary12);
+ boundaries.push_back(boundary13);
+ boundaries.push_back(boundary14);
+ boundaries.push_back(boundary15);
+ boundaries.push_back(boundary16);
+ boundaries.push_back(boundary17);
+ boundaries.push_back(boundary18);
+ boundaries.push_back(boundary19);
+ boundaries.push_back(boundary20);
+ boundaries.push_back(boundary21);
+ boundaries.push_back(boundary22);
+ boundaries.push_back(boundary23);
+ boundaries.push_back(boundary24);
+ boundaries.push_back(boundary25);
+ boundaries.push_back(boundary26);
+ boundaries.push_back(boundary27);
+ boundaries.push_back(boundary28);
+ boundaries.push_back(boundary29);
+ boundaries.push_back(boundary30);
+ boundaries.push_back(boundary31);
+ boundaries.push_back(boundary32);
+ boundaries.push_back(boundary33);
+ boundaries.push_back(boundary34);
+ boundaries.push_back(boundary35);
+ boundaries.push_back(boundary36);
+ boundaries.push_back(boundary37);
+ boundaries.push_back(boundary38);
+ boundaries.push_back(boundary39);
+ boundaries.push_back(boundary40);
+ boundaries.push_back(boundary41);
+ boundaries.push_back(boundary42);
+ boundaries.push_back(boundary43);
+ boundaries.push_back(boundary44);
+ boundaries.push_back(boundary45);
+ boundaries.push_back(boundary46);
+ boundaries.push_back(boundary47);
+ boundaries.push_back(boundary48);
+
+ std::vector<double> increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9});
+
+ std::vector<unsigned> dimensions({3, 3});
+
+ Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells);
+ for (size_t i = 0; i != increasing.size(); ++i) {
+ std::vector<size_t> bd = increasing.get_boundary_of_a_cell(i);
+ for (size_t j = 0; j != bd.size(); ++j) {
+ BOOST_CHECK(boundaries[i][j] == bd[j]);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(compute_boundary_test_2) {
+ std::vector<double> increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9});
+
+ std::vector<unsigned> dimensions({3, 3});
+
+ Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells);
+
+ std::vector<double> coboundaryElements;
+ coboundaryElements.push_back(7);
+ coboundaryElements.push_back(1);
+ coboundaryElements.push_back(8);
+ coboundaryElements.push_back(9);
+ coboundaryElements.push_back(1);
+ coboundaryElements.push_back(3);
+ coboundaryElements.push_back(10);
+ coboundaryElements.push_back(11);
+ coboundaryElements.push_back(3);
+ coboundaryElements.push_back(5);
+ coboundaryElements.push_back(12);
+ coboundaryElements.push_back(13);
+ coboundaryElements.push_back(5);
+ coboundaryElements.push_back(8);
+ coboundaryElements.push_back(8);
+ coboundaryElements.push_back(10);
+ coboundaryElements.push_back(10);
+ coboundaryElements.push_back(12);
+ coboundaryElements.push_back(12);
+ coboundaryElements.push_back(7);
+ coboundaryElements.push_back(21);
+ coboundaryElements.push_back(15);
+ coboundaryElements.push_back(8);
+ coboundaryElements.push_back(22);
+ coboundaryElements.push_back(9);
+ coboundaryElements.push_back(23);
+ coboundaryElements.push_back(15);
+ coboundaryElements.push_back(17);
+ coboundaryElements.push_back(10);
+ coboundaryElements.push_back(24);
+ coboundaryElements.push_back(11);
+ coboundaryElements.push_back(25);
+ coboundaryElements.push_back(17);
+ coboundaryElements.push_back(19);
+ coboundaryElements.push_back(12);
+ coboundaryElements.push_back(26);
+ coboundaryElements.push_back(13);
+ coboundaryElements.push_back(27);
+ coboundaryElements.push_back(19);
+ coboundaryElements.push_back(22);
+ coboundaryElements.push_back(22);
+ coboundaryElements.push_back(24);
+ coboundaryElements.push_back(24);
+ coboundaryElements.push_back(26);
+ coboundaryElements.push_back(26);
+ coboundaryElements.push_back(21);
+ coboundaryElements.push_back(35);
+ coboundaryElements.push_back(29);
+ coboundaryElements.push_back(22);
+ coboundaryElements.push_back(36);
+ coboundaryElements.push_back(23);
+ coboundaryElements.push_back(37);
+ coboundaryElements.push_back(29);
+ coboundaryElements.push_back(31);
+ coboundaryElements.push_back(24);
+ coboundaryElements.push_back(38);
+ coboundaryElements.push_back(25);
+ coboundaryElements.push_back(39);
+ coboundaryElements.push_back(31);
+ coboundaryElements.push_back(33);
+ coboundaryElements.push_back(26);
+ coboundaryElements.push_back(40);
+ coboundaryElements.push_back(27);
+ coboundaryElements.push_back(41);
+ coboundaryElements.push_back(33);
+ coboundaryElements.push_back(36);
+ coboundaryElements.push_back(36);
+ coboundaryElements.push_back(38);
+ coboundaryElements.push_back(38);
+ coboundaryElements.push_back(40);
+ coboundaryElements.push_back(40);
+ coboundaryElements.push_back(35);
+ coboundaryElements.push_back(43);
+ coboundaryElements.push_back(36);
+ coboundaryElements.push_back(37);
+ coboundaryElements.push_back(43);
+ coboundaryElements.push_back(45);
+ coboundaryElements.push_back(38);
+ coboundaryElements.push_back(39);
+ coboundaryElements.push_back(45);
+ coboundaryElements.push_back(47);
+ coboundaryElements.push_back(40);
+ coboundaryElements.push_back(41);
+ coboundaryElements.push_back(47);
+
+ size_t number = 0;
+ for (size_t i = 0; i != increasing.size(); ++i) {
+ std::vector<size_t> bd = increasing.get_coboundary_of_a_cell(i);
+ for (size_t j = 0; j != bd.size(); ++j) {
+ BOOST_CHECK(coboundaryElements[number] == bd[j]);
+ ++number;
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(compute_boundary_test_3) {
+ std::vector<double> increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9});
+
+ std::vector<unsigned> dimensions({3, 3});
+
+ Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells);
+
+ std::vector<unsigned> dim;
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+
+ for (size_t i = 0; i != increasing.size(); ++i) {
+ BOOST_CHECK(increasing.get_dimension_of_a_cell(i) == dim[i]);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(Filtration_simplex_iterator_test) {
+ std::vector<double> increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9});
+
+ std::vector<unsigned> dimensions({3, 3});
+
+ Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells);
+
+ std::vector<unsigned> dim;
+ dim.push_back(0);
+ dim.push_back(0);
+ dim.push_back(0);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(0);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(0);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(0);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(0);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(2);
+
+ std::vector<double> fil;
+ fil.push_back(1);
+ fil.push_back(1);
+ fil.push_back(1);
+ fil.push_back(1);
+ fil.push_back(1);
+ fil.push_back(1);
+ fil.push_back(1);
+ fil.push_back(1);
+ fil.push_back(1);
+ fil.push_back(2);
+ fil.push_back(2);
+ fil.push_back(2);
+ fil.push_back(2);
+ fil.push_back(2);
+ fil.push_back(2);
+ fil.push_back(3);
+ fil.push_back(3);
+ fil.push_back(3);
+ fil.push_back(3);
+ fil.push_back(3);
+ fil.push_back(3);
+ fil.push_back(4);
+ fil.push_back(4);
+ fil.push_back(4);
+ fil.push_back(4);
+ fil.push_back(4);
+ fil.push_back(4);
+ fil.push_back(5);
+ fil.push_back(5);
+ fil.push_back(5);
+ fil.push_back(5);
+ fil.push_back(6);
+ fil.push_back(6);
+ fil.push_back(6);
+ fil.push_back(6);
+ fil.push_back(7);
+ fil.push_back(7);
+ fil.push_back(7);
+ fil.push_back(7);
+ fil.push_back(7);
+ fil.push_back(7);
+ fil.push_back(8);
+ fil.push_back(8);
+ fil.push_back(8);
+ fil.push_back(8);
+ fil.push_back(9);
+ fil.push_back(9);
+ fil.push_back(9);
+ fil.push_back(9);
+
+ Bitmap_cubical_complex::Filtration_simplex_range range = increasing.filtration_simplex_range();
+ size_t position = 0;
+ for (Bitmap_cubical_complex::Filtration_simplex_iterator it = range.begin(); it != range.end(); ++it) {
+ BOOST_CHECK(increasing.dimension(*it) == dim[position]);
+ BOOST_CHECK(increasing.filtration(*it) == fil[position]);
+ ++position;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(boudary_operator_2d_bitmap_with_periodic_bcond) {
+ std::vector<double> filtration({0, 0, 0, 0});
+
+ std::vector<unsigned> dimensions({2, 2});
+
+ std::vector<bool> periodic_directions({true, true});
+
+ Bitmap_cubical_complex_periodic_boundary_conditions cmplx(dimensions, filtration, periodic_directions);
+ BOOST_CHECK(cmplx.dimension() == 2);
+
+ std::vector<double> boundary0;
+ std::vector<double> boundary1;
+ boundary1.push_back(2);
+ boundary1.push_back(0);
+ std::vector<double> boundary2;
+ std::vector<double> boundary3;
+ boundary3.push_back(0);
+ boundary3.push_back(2);
+ std::vector<double> boundary4;
+ boundary4.push_back(8);
+ boundary4.push_back(0);
+ std::vector<double> boundary5;
+ boundary5.push_back(9);
+ boundary5.push_back(1);
+ boundary5.push_back(4);
+ boundary5.push_back(6);
+ std::vector<double> boundary6;
+ boundary6.push_back(10);
+ boundary6.push_back(2);
+ std::vector<double> boundary7;
+ boundary7.push_back(11);
+ boundary7.push_back(3);
+ boundary7.push_back(6);
+ boundary7.push_back(4);
+ std::vector<double> boundary8;
+ std::vector<double> boundary9;
+ boundary9.push_back(10);
+ boundary9.push_back(8);
+ std::vector<double> boundary10;
+ std::vector<double> boundary11;
+ boundary11.push_back(8);
+ boundary11.push_back(10);
+ std::vector<double> boundary12;
+ boundary12.push_back(0);
+ boundary12.push_back(8);
+ std::vector<double> boundary13;
+ boundary13.push_back(1);
+ boundary13.push_back(9);
+ boundary13.push_back(12);
+ boundary13.push_back(14);
+ std::vector<double> boundary14;
+ boundary14.push_back(2);
+ boundary14.push_back(10);
+ std::vector<double> boundary15;
+ boundary15.push_back(3);
+ boundary15.push_back(11);
+ boundary15.push_back(14);
+ boundary15.push_back(12);
+
+ std::vector<std::vector<double> > boundaries;
+ boundaries.push_back(boundary0);
+ boundaries.push_back(boundary1);
+ boundaries.push_back(boundary2);
+ boundaries.push_back(boundary3);
+ boundaries.push_back(boundary4);
+ boundaries.push_back(boundary5);
+ boundaries.push_back(boundary6);
+ boundaries.push_back(boundary7);
+ boundaries.push_back(boundary8);
+ boundaries.push_back(boundary9);
+ boundaries.push_back(boundary10);
+ boundaries.push_back(boundary11);
+ boundaries.push_back(boundary12);
+ boundaries.push_back(boundary13);
+ boundaries.push_back(boundary14);
+ boundaries.push_back(boundary15);
+
+ for (size_t i = 0; i != cmplx.size(); ++i) {
+ std::vector<size_t> bd = cmplx.get_boundary_of_a_cell(i);
+ for (size_t j = 0; j != bd.size(); ++j) {
+ BOOST_CHECK(boundaries[i][j] == bd[j]);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(coboudary_operator_2d_bitmap_with_periodic_bcond) {
+ std::vector<double> filtration({0, 0, 0, 0});
+
+ std::vector<unsigned> dimensions({2, 2});
+
+ std::vector<bool> periodic_directions({true, true});
+
+ Bitmap_cubical_complex_periodic_boundary_conditions cmplx(dimensions, filtration, periodic_directions);
+ BOOST_CHECK(cmplx.dimension() == 2);
+
+ std::vector<double> coboundary0;
+ coboundary0.push_back(4);
+ coboundary0.push_back(12);
+ coboundary0.push_back(1);
+ coboundary0.push_back(3);
+ std::vector<double> coboundary1;
+ coboundary1.push_back(5);
+ coboundary1.push_back(13);
+ std::vector<double> coboundary2;
+ coboundary2.push_back(6);
+ coboundary2.push_back(14);
+ coboundary2.push_back(1);
+ coboundary2.push_back(3);
+ std::vector<double> coboundary3;
+ coboundary3.push_back(7);
+ coboundary3.push_back(15);
+ std::vector<double> coboundary4;
+ coboundary4.push_back(5);
+ coboundary4.push_back(7);
+ std::vector<double> coboundary5;
+ std::vector<double> coboundary6;
+ coboundary6.push_back(5);
+ coboundary6.push_back(7);
+ std::vector<double> coboundary7;
+ std::vector<double> coboundary8;
+ coboundary8.push_back(4);
+ coboundary8.push_back(12);
+ coboundary8.push_back(9);
+ coboundary8.push_back(11);
+ std::vector<double> coboundary9;
+ coboundary9.push_back(5);
+ coboundary9.push_back(13);
+ std::vector<double> coboundary10;
+ coboundary10.push_back(6);
+ coboundary10.push_back(14);
+ coboundary10.push_back(9);
+ coboundary10.push_back(11);
+ std::vector<double> coboundary11;
+ coboundary11.push_back(7);
+ coboundary11.push_back(15);
+ std::vector<double> coboundary12;
+ coboundary12.push_back(13);
+ coboundary12.push_back(15);
+ std::vector<double> coboundary13;
+ std::vector<double> coboundary14;
+ coboundary14.push_back(13);
+ coboundary14.push_back(15);
+ std::vector<double> coboundary15;
+
+ std::vector<std::vector<double> > coboundaries;
+ coboundaries.push_back(coboundary0);
+ coboundaries.push_back(coboundary1);
+ coboundaries.push_back(coboundary2);
+ coboundaries.push_back(coboundary3);
+ coboundaries.push_back(coboundary4);
+ coboundaries.push_back(coboundary5);
+ coboundaries.push_back(coboundary6);
+ coboundaries.push_back(coboundary7);
+ coboundaries.push_back(coboundary8);
+ coboundaries.push_back(coboundary9);
+ coboundaries.push_back(coboundary10);
+ coboundaries.push_back(coboundary11);
+ coboundaries.push_back(coboundary12);
+ coboundaries.push_back(coboundary13);
+ coboundaries.push_back(coboundary14);
+ coboundaries.push_back(coboundary15);
+
+ for (size_t i = 0; i != cmplx.size(); ++i) {
+ std::vector<size_t> cbd = cmplx.get_coboundary_of_a_cell(i);
+ for (size_t j = 0; j != cbd.size(); ++j) {
+ BOOST_CHECK(coboundaries[i][j] == cbd[j]);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(bitmap_2d_with_periodic_bcond_filtration) {
+ std::vector<double> filtrationOrg({0, 1, 2, 3});
+
+ std::vector<unsigned> dimensions({2, 2});
+
+ std::vector<bool> periodic_directions({true, true});
+
+ Bitmap_cubical_complex_periodic_boundary_conditions cmplx(dimensions, filtrationOrg, periodic_directions);
+ BOOST_CHECK(cmplx.dimension() == 2);
+
+ std::vector<double> filtration;
+ filtration.push_back(0); // 0
+ filtration.push_back(0); // 1
+ filtration.push_back(0); // 2
+ filtration.push_back(1); // 3
+ filtration.push_back(0); // 4
+ filtration.push_back(0); // 5
+ filtration.push_back(0); // 6
+ filtration.push_back(1); // 7
+ filtration.push_back(0); // 8
+ filtration.push_back(0); // 9
+ filtration.push_back(0); // 10
+ filtration.push_back(1); // 11
+ filtration.push_back(2); // 12
+ filtration.push_back(2); // 13
+ filtration.push_back(2); // 14
+ filtration.push_back(3); // 15
+
+ for (size_t i = 0; i != cmplx.size(); ++i) {
+ BOOST_CHECK(filtration[i] == cmplx.get_cell_data(i));
+ }
+}
+
+BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check) {
+ std::vector<double> expected_filtration;
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(3);
+
+ std::vector<unsigned> expected_dimension;
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+
+ std::vector<size_t> expected_boundary;
+ expected_boundary.push_back(0);
+ expected_boundary.push_back(2);
+ expected_boundary.push_back(2);
+ expected_boundary.push_back(4);
+ expected_boundary.push_back(0);
+ expected_boundary.push_back(10);
+ expected_boundary.push_back(1);
+ expected_boundary.push_back(11);
+ expected_boundary.push_back(7);
+ expected_boundary.push_back(5);
+ expected_boundary.push_back(2);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(3);
+ expected_boundary.push_back(13);
+ expected_boundary.push_back(9);
+ expected_boundary.push_back(7);
+ expected_boundary.push_back(4);
+ expected_boundary.push_back(14);
+ expected_boundary.push_back(10);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(14);
+ expected_boundary.push_back(10);
+ expected_boundary.push_back(20);
+ expected_boundary.push_back(11);
+ expected_boundary.push_back(21);
+ expected_boundary.push_back(17);
+ expected_boundary.push_back(15);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(22);
+ expected_boundary.push_back(13);
+ expected_boundary.push_back(23);
+ expected_boundary.push_back(19);
+ expected_boundary.push_back(17);
+ expected_boundary.push_back(14);
+ expected_boundary.push_back(24);
+ expected_boundary.push_back(20);
+ expected_boundary.push_back(22);
+ expected_boundary.push_back(22);
+ expected_boundary.push_back(24);
+
+ std::vector<size_t> expected_coboundary;
+ expected_coboundary.push_back(5);
+ expected_coboundary.push_back(1);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(7);
+ expected_coboundary.push_back(1);
+ expected_coboundary.push_back(3);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(9);
+ expected_coboundary.push_back(3);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(5);
+ expected_coboundary.push_back(15);
+ expected_coboundary.push_back(11);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(7);
+ expected_coboundary.push_back(17);
+ expected_coboundary.push_back(11);
+ expected_coboundary.push_back(13);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(9);
+ expected_coboundary.push_back(19);
+ expected_coboundary.push_back(13);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(15);
+ expected_coboundary.push_back(21);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(17);
+ expected_coboundary.push_back(21);
+ expected_coboundary.push_back(23);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(19);
+ expected_coboundary.push_back(23);
+
+ std::vector<unsigned> sizes(2);
+ sizes[0] = 2;
+ sizes[1] = 2;
+
+ std::vector<double> data(4);
+ data[0] = 0;
+ data[1] = 1;
+ data[2] = 2;
+ data[3] = 3;
+
+ Bitmap_cubical_complex_base ba(sizes, data);
+ int i = 0;
+ int bd_it = 0;
+ int cbd_it = 0;
+ for (Bitmap_cubical_complex_base::All_cells_iterator it = ba.all_cells_iterator_begin();
+ it != ba.all_cells_iterator_end(); ++it) {
+ BOOST_CHECK(expected_filtration[i] == ba.get_cell_data(*it));
+ BOOST_CHECK(expected_dimension[i] == ba.get_dimension_of_a_cell(*it));
+
+ Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it);
+ for (Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin(); bd != bdrange.end(); ++bd) {
+ BOOST_CHECK(expected_boundary[bd_it] == *bd);
+ ++bd_it;
+ }
+
+ Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it);
+ for (Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin(); cbd != cbdrange.end(); ++cbd) {
+ BOOST_CHECK(expected_coboundary[cbd_it] == *cbd);
+ ++cbd_it;
+ }
+ ++i;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check_range_check_2) {
+ std::vector<double> expected_filtration;
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(3);
+
+ std::vector<unsigned> expected_dimension;
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+
+ std::vector<size_t> expected_boundary;
+ expected_boundary.push_back(0);
+ expected_boundary.push_back(2);
+ expected_boundary.push_back(2);
+ expected_boundary.push_back(4);
+ expected_boundary.push_back(0);
+ expected_boundary.push_back(10);
+ expected_boundary.push_back(1);
+ expected_boundary.push_back(11);
+ expected_boundary.push_back(7);
+ expected_boundary.push_back(5);
+ expected_boundary.push_back(2);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(3);
+ expected_boundary.push_back(13);
+ expected_boundary.push_back(9);
+ expected_boundary.push_back(7);
+ expected_boundary.push_back(4);
+ expected_boundary.push_back(14);
+ expected_boundary.push_back(10);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(14);
+ expected_boundary.push_back(10);
+ expected_boundary.push_back(20);
+ expected_boundary.push_back(11);
+ expected_boundary.push_back(21);
+ expected_boundary.push_back(17);
+ expected_boundary.push_back(15);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(22);
+ expected_boundary.push_back(13);
+ expected_boundary.push_back(23);
+ expected_boundary.push_back(19);
+ expected_boundary.push_back(17);
+ expected_boundary.push_back(14);
+ expected_boundary.push_back(24);
+ expected_boundary.push_back(20);
+ expected_boundary.push_back(22);
+ expected_boundary.push_back(22);
+ expected_boundary.push_back(24);
+
+ std::vector<size_t> expected_coboundary;
+ expected_coboundary.push_back(5);
+ expected_coboundary.push_back(1);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(7);
+ expected_coboundary.push_back(1);
+ expected_coboundary.push_back(3);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(9);
+ expected_coboundary.push_back(3);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(5);
+ expected_coboundary.push_back(15);
+ expected_coboundary.push_back(11);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(7);
+ expected_coboundary.push_back(17);
+ expected_coboundary.push_back(11);
+ expected_coboundary.push_back(13);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(9);
+ expected_coboundary.push_back(19);
+ expected_coboundary.push_back(13);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(15);
+ expected_coboundary.push_back(21);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(17);
+ expected_coboundary.push_back(21);
+ expected_coboundary.push_back(23);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(19);
+ expected_coboundary.push_back(23);
+
+ std::vector<unsigned> sizes(2);
+ sizes[0] = 2;
+ sizes[1] = 2;
+
+ std::vector<double> data(4);
+ data[0] = 0;
+ data[1] = 1;
+ data[2] = 2;
+ data[3] = 3;
+
+ Bitmap_cubical_complex_base ba(sizes, data);
+ int i = 0;
+ int bd_it = 0;
+ int cbd_it = 0;
+
+ Bitmap_cubical_complex_base::All_cells_range range(&ba);
+ for (Bitmap_cubical_complex_base::All_cells_iterator it = range.begin(); it != range.end(); ++it) {
+ BOOST_CHECK(expected_filtration[i] == ba.get_cell_data(*it));
+ BOOST_CHECK(expected_dimension[i] == ba.get_dimension_of_a_cell(*it));
+
+ Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it);
+ for (Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin(); bd != bdrange.end(); ++bd) {
+ BOOST_CHECK(expected_boundary[bd_it] == *bd);
+ ++bd_it;
+ }
+
+ Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it);
+ for (Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin(); cbd != cbdrange.end(); ++cbd) {
+ BOOST_CHECK(expected_coboundary[cbd_it] == *cbd);
+ ++cbd_it;
+ }
+ ++i;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check_range_check) {
+ std::vector<double> expected_filtration;
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(3);
+
+ std::vector<unsigned> expected_dimension;
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+
+ std::vector<size_t> expected_boundary;
+ expected_boundary.push_back(0);
+ expected_boundary.push_back(2);
+ expected_boundary.push_back(2);
+ expected_boundary.push_back(4);
+ expected_boundary.push_back(0);
+ expected_boundary.push_back(10);
+ expected_boundary.push_back(1);
+ expected_boundary.push_back(11);
+ expected_boundary.push_back(7);
+ expected_boundary.push_back(5);
+ expected_boundary.push_back(2);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(3);
+ expected_boundary.push_back(13);
+ expected_boundary.push_back(9);
+ expected_boundary.push_back(7);
+ expected_boundary.push_back(4);
+ expected_boundary.push_back(14);
+ expected_boundary.push_back(10);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(14);
+ expected_boundary.push_back(10);
+ expected_boundary.push_back(20);
+ expected_boundary.push_back(11);
+ expected_boundary.push_back(21);
+ expected_boundary.push_back(17);
+ expected_boundary.push_back(15);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(22);
+ expected_boundary.push_back(13);
+ expected_boundary.push_back(23);
+ expected_boundary.push_back(19);
+ expected_boundary.push_back(17);
+ expected_boundary.push_back(14);
+ expected_boundary.push_back(24);
+ expected_boundary.push_back(20);
+ expected_boundary.push_back(22);
+ expected_boundary.push_back(22);
+ expected_boundary.push_back(24);
+
+ std::vector<size_t> expected_coboundary;
+ expected_coboundary.push_back(5);
+ expected_coboundary.push_back(1);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(7);
+ expected_coboundary.push_back(1);
+ expected_coboundary.push_back(3);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(9);
+ expected_coboundary.push_back(3);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(5);
+ expected_coboundary.push_back(15);
+ expected_coboundary.push_back(11);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(7);
+ expected_coboundary.push_back(17);
+ expected_coboundary.push_back(11);
+ expected_coboundary.push_back(13);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(9);
+ expected_coboundary.push_back(19);
+ expected_coboundary.push_back(13);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(15);
+ expected_coboundary.push_back(21);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(17);
+ expected_coboundary.push_back(21);
+ expected_coboundary.push_back(23);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(19);
+ expected_coboundary.push_back(23);
+
+ std::vector<unsigned> sizes(2);
+ sizes[0] = 2;
+ sizes[1] = 2;
+
+ std::vector<double> data(4);
+ data[0] = 0;
+ data[1] = 1;
+ data[2] = 2;
+ data[3] = 3;
+
+ Bitmap_cubical_complex_base ba(sizes, data);
+ int i = 0;
+ int bd_it = 0;
+ int cbd_it = 0;
+
+ Bitmap_cubical_complex_base::All_cells_range range = ba.all_cells_range();
+ for (Bitmap_cubical_complex_base::All_cells_iterator it = range.begin(); it != range.end(); ++it) {
+ BOOST_CHECK(expected_filtration[i] == ba.get_cell_data(*it));
+ BOOST_CHECK(expected_dimension[i] == ba.get_dimension_of_a_cell(*it));
+
+ Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it);
+ for (Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin(); bd != bdrange.end(); ++bd) {
+ BOOST_CHECK(expected_boundary[bd_it] == *bd);
+ ++bd_it;
+ }
+
+ Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it);
+ for (Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin(); cbd != cbdrange.end(); ++cbd) {
+ BOOST_CHECK(expected_coboundary[cbd_it] == *cbd);
+ ++cbd_it;
+ }
+ ++i;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(Top_dimensional_cells_iterator_range_check) {
+ std::vector<double> expected_filtration;
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(3);
+
+ std::vector<unsigned> sizes(2);
+ sizes[0] = 2;
+ sizes[1] = 2;
+
+ std::vector<double> data(4);
+ data[0] = 0;
+ data[1] = 1;
+ data[2] = 2;
+ data[3] = 3;
+
+ Bitmap_cubical_complex_base ba(sizes, data);
+ int i = 0;
+
+ Bitmap_cubical_complex_base::Top_dimensional_cells_range range = ba.top_dimensional_cells_range();
+ for (Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it = range.begin(); it != range.end(); ++it) {
+ BOOST_CHECK(data[i] == ba.get_cell_data(*it));
+ BOOST_CHECK(ba.get_dimension_of_a_cell(*it) == 2);
+ ++i;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(check_if_boundary_of_boundary_is_zero_non_periodic_case_3_d) {
+ std::vector<unsigned> sizes(3);
+ sizes[0] = 3;
+ sizes[1] = 3;
+ sizes[2] = 3;
+
+ std::vector<double> data(27, 0);
+
+ int number_of_all_elements = (2 * sizes[0] + 1) * (2 * sizes[1] + 1) * (2 * sizes[2] + 1);
+ std::vector<int> elems_in_boundary(number_of_all_elements, 0);
+ Bitmap_cubical_complex_base ba(sizes, data);
+ for (Bitmap_cubical_complex_base::All_cells_iterator it = ba.all_cells_iterator_begin();
+ it != ba.all_cells_iterator_end(); ++it) {
+ int i = 1;
+ Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it);
+ for (Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin(); bd != bdrange.end(); ++bd) {
+ Bitmap_cubical_complex_base::Boundary_range second_bdrange = ba.boundary_range(*bd);
+ int j = 1;
+ for (Bitmap_cubical_complex_base::Boundary_iterator bd2 = second_bdrange.begin(); bd2 != second_bdrange.end();
+ ++bd2) {
+ elems_in_boundary[*bd2] += i * j;
+ j *= -1;
+ }
+ i *= -1;
+ }
+ // check if there is anything nonzero in elems_in_boundary
+ for (size_t i = 0; i != elems_in_boundary.size(); ++i) {
+ BOOST_CHECK(elems_in_boundary[i] == 0);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(check_if_boundary_of_boundary_is_zero_non_periodic_case_4_d) {
+ std::vector<unsigned> sizes(4);
+ sizes[0] = 3;
+ sizes[1] = 3;
+ sizes[2] = 3;
+ sizes[3] = 3;
+
+ std::vector<double> data(81, 0);
+
+ int number_of_all_elements = (2 * sizes[0] + 1) * (2 * sizes[1] + 1) * (2 * sizes[2] + 1) * (2 * sizes[3] + 1);
+ std::vector<int> elems_in_boundary(number_of_all_elements, 0);
+ Bitmap_cubical_complex_base ba(sizes, data);
+ for (Bitmap_cubical_complex_base::All_cells_iterator it = ba.all_cells_iterator_begin();
+ it != ba.all_cells_iterator_end(); ++it) {
+ int i = 1;
+ Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it);
+ for (Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin(); bd != bdrange.end(); ++bd) {
+ Bitmap_cubical_complex_base::Boundary_range second_bdrange = ba.boundary_range(*bd);
+ int j = 1;
+ for (Bitmap_cubical_complex_base::Boundary_iterator bd2 = second_bdrange.begin(); bd2 != second_bdrange.end();
+ ++bd2) {
+ elems_in_boundary[*bd2] += i * j;
+ j *= -1;
+ }
+ i *= -1;
+ }
+ // check if there is anything nonzero in elems_in_boundary
+ for (size_t i = 0; i != elems_in_boundary.size(); ++i) {
+ BOOST_CHECK(elems_in_boundary[i] == 0);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(check_if_boundary_of_boundary_is_zero_periodic_case_2d) {
+ std::vector<unsigned> sizes(2);
+ sizes[0] = 3;
+ sizes[1] = 3;
+
+ std::vector<bool> directions_of_periodicity(2, true);
+ std::vector<double> data(9, 0);
+
+ int number_of_all_elements = (2 * sizes[0]) * (2 * sizes[1]); // *(2*sizes[2]);
+ std::vector<int> elems_in_boundary(number_of_all_elements, 0);
+ Bitmap_cubical_complex_periodic_boundary_conditions ba(sizes, data, directions_of_periodicity);
+ for (Bitmap_cubical_complex_periodic_boundary_conditions::All_cells_iterator it = ba.all_cells_iterator_begin();
+ it != ba.all_cells_iterator_end(); ++it) {
+ int i = 1;
+
+ // std::cout << "Element : " << *it << std::endl;
+
+ Bitmap_cubical_complex_periodic_boundary_conditions_base::Boundary_range bdrange = ba.boundary_range(*it);
+ for (Bitmap_cubical_complex_periodic_boundary_conditions::Boundary_iterator bd = bdrange.begin();
+ bd != bdrange.end(); ++bd) {
+ // std::cout << *bd << " ";
+ Bitmap_cubical_complex_periodic_boundary_conditions::Boundary_range second_bdrange = ba.boundary_range(*bd);
+ int j = 1;
+ for (Bitmap_cubical_complex_periodic_boundary_conditions::Boundary_iterator bd2 = second_bdrange.begin();
+ bd2 != second_bdrange.end(); ++bd2) {
+ elems_in_boundary[*bd2] += i * j;
+ j *= -1;
+ }
+ i *= -1;
+ }
+ // getchar();
+
+ // check if there is anything nonzero in elems_in_boundary
+ for (size_t i = 0; i != elems_in_boundary.size(); ++i) {
+ BOOST_CHECK(elems_in_boundary[i] == 0);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(check_if_boundary_of_boundary_is_zero_periodic_case_3d) {
+ std::vector<unsigned> sizes(3);
+ sizes[0] = 3;
+ sizes[1] = 3;
+ sizes[2] = 3;
+
+ std::vector<bool> directions_of_periodicity(3, true);
+
+ std::vector<double> data(27, 0);
+
+ int number_of_all_elements = (2 * sizes[0]) * (2 * sizes[1]) * (2 * sizes[2]);
+ Bitmap_cubical_complex_periodic_boundary_conditions ba(sizes, data, directions_of_periodicity);
+ std::vector<int> elems_in_boundary(number_of_all_elements, 0);
+ for (Bitmap_cubical_complex_periodic_boundary_conditions::All_cells_iterator it = ba.all_cells_iterator_begin();
+ it != ba.all_cells_iterator_end(); ++it) {
+ // std::cout << "Element : " << *it << std::endl;
+
+ int i = 1;
+
+ Bitmap_cubical_complex_periodic_boundary_conditions_base::Boundary_range bdrange = ba.boundary_range(*it);
+ for (Bitmap_cubical_complex_periodic_boundary_conditions::Boundary_iterator bd = bdrange.begin();
+ bd != bdrange.end(); ++bd) {
+ Bitmap_cubical_complex_periodic_boundary_conditions::Boundary_range second_bdrange = ba.boundary_range(*bd);
+ // std::cout << *bd << " ";
+ int j = 1;
+ for (Bitmap_cubical_complex_periodic_boundary_conditions::Boundary_iterator bd2 = second_bdrange.begin();
+ bd2 != second_bdrange.end(); ++bd2) {
+ elems_in_boundary[*bd2] += i * j;
+ j *= -1;
+ }
+ i *= -1;
+ }
+
+ // check if there is anything nonzero in elems_in_boundary
+ for (size_t i = 0; i != elems_in_boundary.size(); ++i) {
+ BOOST_CHECK(elems_in_boundary[i] == 0);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(check_if_boundary_of_boundary_is_zero_periodic_case_4d) {
+ std::vector<unsigned> sizes(4);
+ sizes[0] = 3;
+ sizes[1] = 3;
+ sizes[2] = 3;
+ sizes[3] = 3;
+
+ std::vector<bool> directions_of_periodicity(4, true);
+
+ std::vector<double> data(81, 0);
+
+ int number_of_all_elements = (2 * sizes[0]) * (2 * sizes[1]) * (2 * sizes[2]) * (2 * sizes[3]);
+ std::vector<int> elems_in_boundary(number_of_all_elements, 0);
+ Bitmap_cubical_complex_periodic_boundary_conditions ba(sizes, data, directions_of_periodicity);
+ for (Bitmap_cubical_complex_periodic_boundary_conditions::All_cells_iterator it = ba.all_cells_iterator_begin();
+ it != ba.all_cells_iterator_end(); ++it) {
+ int i = 1;
+
+ Bitmap_cubical_complex_periodic_boundary_conditions_base::Boundary_range bdrange = ba.boundary_range(*it);
+ for (Bitmap_cubical_complex_periodic_boundary_conditions::Boundary_iterator bd = bdrange.begin();
+ bd != bdrange.end(); ++bd) {
+ Bitmap_cubical_complex_periodic_boundary_conditions::Boundary_range second_bdrange = ba.boundary_range(*bd);
+ int j = 1;
+ for (Bitmap_cubical_complex_periodic_boundary_conditions::Boundary_iterator bd2 = second_bdrange.begin();
+ bd2 != second_bdrange.end(); ++bd2) {
+ elems_in_boundary[*bd2] += i * j;
+ j *= -1;
+ }
+ i *= -1;
+ }
+
+ // check if there is anything nonzero in elems_in_boundary
+ for (size_t i = 0; i != elems_in_boundary.size(); ++i) {
+ BOOST_CHECK(elems_in_boundary[i] == 0);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(compute_incidence_between_cells_test) {
+ std::vector<unsigned> sizes(3);
+ sizes[0] = 3;
+ sizes[1] = 3;
+ sizes[2] = 3;
+
+ std::vector<double> data(27, 0);
+
+ int number_of_all_elements = (2 * sizes[0] + 1) * (2 * sizes[1] + 1) * (2 * sizes[1] + 1);
+ Bitmap_cubical_complex_base ba(sizes, data);
+ std::vector<int> elems_in_boundary(number_of_all_elements, 0);
+ for (Bitmap_cubical_complex_base::All_cells_iterator it = ba.all_cells_iterator_begin();
+ it != ba.all_cells_iterator_end(); ++it) {
+ Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it);
+ for (Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin(); bd != bdrange.end(); ++bd) {
+ Bitmap_cubical_complex_base::Boundary_range second_bdrange = ba.boundary_range(*bd);
+ for (Bitmap_cubical_complex_base::Boundary_iterator bd2 = second_bdrange.begin(); bd2 != second_bdrange.end();
+ ++bd2) {
+ elems_in_boundary[*bd2] +=
+ ba.compute_incidence_between_cells(*it, *bd) * ba.compute_incidence_between_cells(*bd, *bd2);
+ }
+ }
+ // check if there is anything nonzero in elems_in_boundary
+ for (size_t i = 0; i != elems_in_boundary.size(); ++i) {
+ BOOST_CHECK(elems_in_boundary[i] == 0);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(compute_incidence_between_cells_test_periodic_boundary_conditions) {
+ std::vector<unsigned> sizes(3);
+ sizes[0] = 3;
+ sizes[1] = 3;
+ sizes[2] = 3;
+
+ std::vector<bool> directions_of_periodicity(3, true);
+ std::vector<double> data(27, 0);
+
+ int number_of_all_elements = (2 * sizes[0]) * (2 * sizes[1]) * (2 * sizes[2]);
+ Bitmap_cubical_complex_periodic_boundary_conditions ba(sizes, data, directions_of_periodicity);
+
+ std::vector<int> elems_in_boundary(number_of_all_elements, 0);
+ for (Bitmap_cubical_complex_periodic_boundary_conditions::All_cells_iterator it = ba.all_cells_iterator_begin();
+ it != ba.all_cells_iterator_end(); ++it) {
+ Bitmap_cubical_complex_periodic_boundary_conditions_base::Boundary_range bdrange = ba.boundary_range(*it);
+ for (Bitmap_cubical_complex_periodic_boundary_conditions::Boundary_iterator bd = bdrange.begin();
+ bd != bdrange.end(); ++bd) {
+ // std::cout << *bd << " ";
+ Bitmap_cubical_complex_periodic_boundary_conditions::Boundary_range second_bdrange = ba.boundary_range(*bd);
+ for (Bitmap_cubical_complex_periodic_boundary_conditions::Boundary_iterator bd2 = second_bdrange.begin();
+ bd2 != second_bdrange.end(); ++bd2) {
+ elems_in_boundary[*bd2] +=
+ ba.compute_incidence_between_cells(*it, *bd) * ba.compute_incidence_between_cells(*bd, *bd2);
+ }
+ }
+ // check if there is anything nonzero in elems_in_boundary
+ for (size_t i = 0; i != elems_in_boundary.size(); ++i) {
+ BOOST_CHECK(elems_in_boundary[i] == 0);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(perseus_file_read) {
+ Bitmap_cubical_complex increasing("sinusoid.txt");
+
+ auto it = increasing.top_dimensional_cells_iterator_begin();
+ double value = increasing.get_cell_data(*it);
+ std::cout << "First value of sinusoid.txt is " << value << std::endl;
+ BOOST_CHECK(value == 10.);
+ // Next value
+ ++it;
+ value = increasing.get_cell_data(*it);
+ std::cout << "Second value of sinusoid.txt is " << value << std::endl;
+ BOOST_CHECK(value == std::numeric_limits<double>::infinity());
+}
diff --git a/src/Bitmap_cubical_complex/test/CMakeLists.txt b/src/Bitmap_cubical_complex/test/CMakeLists.txt
new file mode 100644
index 00000000..d2f002a6
--- /dev/null
+++ b/src/Bitmap_cubical_complex/test/CMakeLists.txt
@@ -0,0 +1,14 @@
+project(Bitmap_cubical_complex_tests)
+
+include(GUDHI_test_coverage)
+
+# Do not forget to copy test files in current binary dir
+file(COPY "${CMAKE_SOURCE_DIR}/data/bitmap/sinusoid.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+
+add_executable ( Bitmap_cubical_complex_test_unit Bitmap_test.cpp )
+target_link_libraries(Bitmap_cubical_complex_test_unit ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+if (TBB_FOUND)
+ target_link_libraries(Bitmap_cubical_complex_test_unit ${TBB_LIBRARIES})
+endif()
+
+gudhi_add_coverage_test(Bitmap_cubical_complex_test_unit)
diff --git a/src/Bitmap_cubical_complex/utilities/CMakeLists.txt b/src/Bitmap_cubical_complex/utilities/CMakeLists.txt
new file mode 100644
index 00000000..416db67f
--- /dev/null
+++ b/src/Bitmap_cubical_complex/utilities/CMakeLists.txt
@@ -0,0 +1,28 @@
+project(Bitmap_cubical_complex_utilities)
+
+add_executable ( cubical_complex_persistence cubical_complex_persistence.cpp )
+if (TBB_FOUND)
+ target_link_libraries(cubical_complex_persistence ${TBB_LIBRARIES})
+endif()
+
+add_test(NAME Bitmap_cubical_complex_utility_persistence_one_sphere COMMAND $<TARGET_FILE:cubical_complex_persistence>
+ "${CMAKE_SOURCE_DIR}/data/bitmap/CubicalOneSphere.txt")
+
+add_test(NAME Bitmap_cubical_complex_utility_persistence_two_sphere COMMAND $<TARGET_FILE:cubical_complex_persistence>
+ "${CMAKE_SOURCE_DIR}/data/bitmap/CubicalTwoSphere.txt")
+
+add_executable ( periodic_cubical_complex_persistence periodic_cubical_complex_persistence.cpp )
+if (TBB_FOUND)
+ target_link_libraries(periodic_cubical_complex_persistence ${TBB_LIBRARIES})
+endif()
+
+add_test(NAME Bitmap_cubical_complex_utility_periodic_boundary_conditions_2d_torus
+ COMMAND $<TARGET_FILE:periodic_cubical_complex_persistence>
+ "${CMAKE_SOURCE_DIR}/data/bitmap/2d_torus.txt")
+
+add_test(NAME Bitmap_cubical_complex_utility_periodic_boundary_conditions_3d_torus
+ COMMAND $<TARGET_FILE:periodic_cubical_complex_persistence>
+ "${CMAKE_SOURCE_DIR}/data/bitmap/3d_torus.txt")
+
+install(TARGETS cubical_complex_persistence DESTINATION bin)
+install(TARGETS periodic_cubical_complex_persistence DESTINATION bin)
diff --git a/src/Bitmap_cubical_complex/utilities/cubical_complex_persistence.cpp b/src/Bitmap_cubical_complex/utilities/cubical_complex_persistence.cpp
new file mode 100644
index 00000000..a9792c2d
--- /dev/null
+++ b/src/Bitmap_cubical_complex/utilities/cubical_complex_persistence.cpp
@@ -0,0 +1,68 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Pawel Dlotko
+ *
+ * Copyright (C) 2015 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#include <gudhi/reader_utils.h>
+#include <gudhi/Bitmap_cubical_complex.h>
+#include <gudhi/Persistent_cohomology.h>
+
+// standard stuff
+#include <iostream>
+#include <string>
+#include <vector>
+#include <cstddef>
+
+int main(int argc, char** argv) {
+ std::cout
+ << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical "
+ << "complexes provided in text files in Perseus style (the only numbered in the first line is a dimension D of a"
+ << "bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let "
+ << "N denote product of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are "
+ << "filtrations of top dimensional cells. We assume that the cells are in the lexicographical order. See "
+ << "CubicalOneSphere.txt or CubicalTwoSphere.txt for example.\n"
+ << std::endl;
+
+ if (argc != 2) {
+ std::cerr << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at "
+ << "the input. The program will now terminate.\n";
+ return 1;
+ }
+
+ typedef Gudhi::cubical_complex::Bitmap_cubical_complex_base<double> Bitmap_cubical_complex_base;
+ typedef Gudhi::cubical_complex::Bitmap_cubical_complex<Bitmap_cubical_complex_base> Bitmap_cubical_complex;
+ typedef Gudhi::persistent_cohomology::Field_Zp Field_Zp;
+ typedef Gudhi::persistent_cohomology::Persistent_cohomology<Bitmap_cubical_complex, Field_Zp> Persistent_cohomology;
+
+ Bitmap_cubical_complex b(argv[1]);
+
+ // Compute the persistence diagram of the complex
+ Persistent_cohomology pcoh(b);
+ int p = 11;
+ double min_persistence = 0;
+
+ pcoh.init_coefficients(p); // initializes the coefficient field for homology
+ pcoh.compute_persistent_cohomology(min_persistence);
+
+ std::string output_file_name(argv[1]);
+ output_file_name += "_persistence";
+
+ std::size_t last_in_path = output_file_name.find_last_of("/\\");
+
+ if (last_in_path != std::string::npos) {
+ output_file_name = output_file_name.substr(last_in_path + 1);
+ }
+
+ std::ofstream out(output_file_name.c_str());
+ pcoh.output_diagram(out);
+ out.close();
+
+ std::cout << "Result in file: " << output_file_name << "\n";
+
+ return 0;
+}
diff --git a/src/Bitmap_cubical_complex/utilities/cubicalcomplex.md b/src/Bitmap_cubical_complex/utilities/cubicalcomplex.md
new file mode 100644
index 00000000..5b0404c3
--- /dev/null
+++ b/src/Bitmap_cubical_complex/utilities/cubicalcomplex.md
@@ -0,0 +1,37 @@
+---
+layout: page
+title: "Cubical complex"
+meta_title: "Cubical complex"
+teaser: ""
+permalink: /cubicalcomplex/
+---
+{::comment}
+Leave the lines above as it is required by the web site generator 'Jekyll'
+{:/comment}
+
+
+## cubical_complex_persistence ##
+This program computes persistent homology, by using the Bitmap_cubical_complex class, of cubical complexes provided in text files in Perseus style.
+See [here](/doc/latest/fileformats.html#FileFormatsPerseus) for a description of the file format.
+
+**Example**
+
+```
+ cubical_complex_persistence data/bitmap/CubicalTwoSphere.txt
+```
+
+* Creates a Cubical Complex from the Perseus style file `CubicalTwoSphere.txt`,
+computes Persistence cohomology from it and writes the results in a persistence file `CubicalTwoSphere.txt_persistence`.
+
+## periodic_cubical_complex_persistence ##
+
+Same as above, but with periodic boundary conditions.
+
+**Example**
+
+```
+ periodic_cubical_complex_persistence data/bitmap/3d_torus.txt
+```
+
+* Creates a Periodical Cubical Complex from the Perseus style file `3d_torus.txt`,
+computes Persistence cohomology from it and writes the results in a persistence file `3d_torus.txt_persistence`.
diff --git a/src/Bitmap_cubical_complex/utilities/periodic_cubical_complex_persistence.cpp b/src/Bitmap_cubical_complex/utilities/periodic_cubical_complex_persistence.cpp
new file mode 100644
index 00000000..fa97bac0
--- /dev/null
+++ b/src/Bitmap_cubical_complex/utilities/periodic_cubical_complex_persistence.cpp
@@ -0,0 +1,70 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Pawel Dlotko
+ *
+ * Copyright (C) 2015 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#include <gudhi/reader_utils.h>
+#include <gudhi/Bitmap_cubical_complex.h>
+#include <gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h>
+#include <gudhi/Persistent_cohomology.h>
+
+// standard stuff
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <string>
+
+int main(int argc, char** argv) {
+ std::cout
+ << "This program computes persistent homology, by using "
+ << "Bitmap_cubical_complex_periodic_boundary_conditions class, of cubical complexes provided in text files in "
+ << "Perseus style (the only numbered in the first line is a dimension D of a bitmap. In the lines I between 2 "
+ << "and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product of the numbers "
+ << "in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We "
+ << "assume that the cells are in the lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for"
+ << " example.\n"
+ << std::endl;
+
+ if (argc != 2) {
+ std::cerr << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at "
+ << "the input. The program will now terminate.\n";
+ return 1;
+ }
+
+ typedef Gudhi::cubical_complex::Bitmap_cubical_complex_periodic_boundary_conditions_base<double> Bitmap_base;
+ typedef Gudhi::cubical_complex::Bitmap_cubical_complex<Bitmap_base> Bitmap_cubical_complex;
+
+ Bitmap_cubical_complex b(argv[1]);
+
+ typedef Gudhi::persistent_cohomology::Field_Zp Field_Zp;
+ typedef Gudhi::persistent_cohomology::Persistent_cohomology<Bitmap_cubical_complex, Field_Zp> Persistent_cohomology;
+ // Compute the persistence diagram of the complex
+ Persistent_cohomology pcoh(b, true);
+
+ int p = 11;
+ double min_persistence = 0;
+ pcoh.init_coefficients(p); // initializes the coefficient field for homology
+ pcoh.compute_persistent_cohomology(min_persistence);
+
+ std::string output_file_name(argv[1]);
+ output_file_name += "_persistence";
+
+ std::size_t last_in_path = output_file_name.find_last_of("/\\");
+
+ if (last_in_path != std::string::npos) {
+ output_file_name = output_file_name.substr(last_in_path + 1);
+ }
+
+ std::ofstream out(output_file_name.c_str());
+ pcoh.output_diagram(out);
+ out.close();
+
+ std::cout << "Result in file: " << output_file_name << "\n";
+
+ return 0;
+}