Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
remove basic acces to bitsets
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonathan Kliem committed Sep 9, 2020
1 parent cba37e8 commit 0b41c77
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 38 deletions.
63 changes: 62 additions & 1 deletion src/sage/geometry/polyhedron/combinatorial_polyhedron/bitsets.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
*/

#include "gmp.h"
#include <cstring>
using namespace std;

const size_t index_shift = 6;
const size_t LIMB_BITS = 64;
Expand All @@ -15,7 +17,6 @@ const size_t LIMB_BITS = 64;
#############################################################################
*/


inline uint64_t limb_one_set_bit(size_t n){
/*
Return a limb with only bit n set.
Expand All @@ -38,6 +39,52 @@ inline uint64_t limb_lower_bits_down(size_t n){
return ((uint64_t) 1 << (n % LIMB_BITS)) - 1;
}

/*
#############################################################################
# Bitset Initalization
#############################################################################
*/

inline void bitset_clear(uint64_t* bits, size_t face_length){
/*
Remove all elements from the set.
*/
memset(bits, 0, face_length*8);
}

inline void bitset_copy(uint64_t* dst, uint64_t* src, size_t face_length){
/*
Copy the bitset src over to the bitset dst, overwriting dst.
We assume ``dst.limbs == src.limbs``.
*/
memcpy(dst, src, face_length*8);
}

inline void bitset_copy(uint64_t* dst, uint64_t* src, size_t face_length_dst, size_t face_length_src){
/*
Copy the bitset src over to the bitset dst, overwriting dst.
If ``dst`` is longer, then additional bits are set to zero.
*/
if (face_length_src > face_length_dst)
face_length_src = face_length_dst;

memcpy(dst, src, face_length_src*8);
memset(dst+face_length_src, 0, (face_length_dst-face_length_src)*8);
}

inline int bitset_cmp(uint64_t* a, uint64_t* b, size_t face_length){
/*
Compare bitsets a and b. Return 0 if the two sets are
identical, and consistently return -1 or 1 for two sets that are
not equal.
We assume ``a.limbs >= b.limbs``.
*/
return memcmp(a, b, face_length*8);
}

/*
#############################################################################
# Bitset Bit Manipulation
Expand Down Expand Up @@ -66,6 +113,20 @@ inline void bitset_add(uint64_t* bits, size_t n){
bits[n >> index_shift] |= limb_one_set_bit(n);
}

inline void bitset_set_first_n(uint64_t* bits, size_t face_length, size_t n){
/*
Set exactly the first n bits.
*/
size_t i;
size_t index = n >> index_shift;
for(i = 0; i < index; i++)
bits[i] = -1;
if (index < face_length)
bits[index] = limb_lower_bits_down(n);
for(i=index+1; i < face_length; i++)
bits[i] = 0;
}

/*
#############################################################################
# Bitset Searching
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# distutils: depends = sage/geometry/polyhedron/combinatorial_polyhedron/bitset_operations.cc
# distutils: depends = sage/geometry/polyhedron/combinatorial_polyhedron/bitset_operations.cc sage/geometry/polyhedron/combinatorial_polyhedron/bitsets.cc
# distutils: language = c++
# distutils: extra_compile_args = -std=c++11
# distutils: libraries = gmp

r"""
Combinatorial face of a polyhedron
Expand Down Expand Up @@ -76,7 +77,6 @@ from .conversions cimport bit_rep_to_Vrep_list
from .base cimport CombinatorialPolyhedron
from .face_iterator cimport FaceIterator_base
from .polyhedron_face_lattice cimport PolyhedronFaceLattice
from libc.string cimport memcpy

cdef extern from "bitset_operations.cc":
cdef size_t count_atoms(uint64_t *A, size_t face_length)
Expand All @@ -92,6 +92,9 @@ cdef extern from "bitset_operations.cc":
# in terms of uint64_t.
# ``n_coatoms`` length of ``coatoms``.

cdef extern from "bitsets.cc":
cdef void bitset_copy(uint64_t* dst, uint64_t* src, size_t face_length)

cdef extern from "Python.h":
int unlikely(int) nogil # Defined by Cython

Expand All @@ -113,7 +116,7 @@ cdef class CombinatorialFace(SageObject):
sage: F = C.face_lattice()
sage: F._elements[3]
29
17
sage: C.face_by_face_lattice_index(29)
A 1-dimensional face of a 5-dimensional combinatorial polyhedron
Expand Down Expand Up @@ -186,7 +189,7 @@ cdef class CombinatorialFace(SageObject):
self._dual = it.dual
self.face_mem = ListOfFaces(1, it.structure.face_length*64)
self.face = self.face_mem.data[0]
memcpy(self.face, it.structure.face, it.structure.face_length*8)
bitset_copy(self.face, it.structure.face, it.structure.face_length)
self._mem = MemoryAllocator()
self._dimension = it.structure.current_dimension
self._ambient_dimension = it.structure.dimension
Expand All @@ -211,7 +214,7 @@ cdef class CombinatorialFace(SageObject):
self._dual = all_faces.dual
self.face_mem = ListOfFaces(1, all_faces.face_length*64)
self.face = self.face_mem.data[0]
memcpy(self.face, all_faces.faces[dimension+1][index], all_faces.face_length*8)
bitset_copy(self.face, all_faces.faces[dimension+1][index], all_faces.face_length)
self._mem = MemoryAllocator()
self._dimension = dimension
self._ambient_dimension = all_faces.dimension
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ AUTHOR:

from sage.structure.element import is_Matrix

from libc.string cimport memset
from .list_of_faces cimport ListOfFaces
from sage.misc.superseded import deprecated_function_alias
from sage.matrix.matrix_integer_dense cimport Matrix_integer_dense
Expand All @@ -87,6 +86,7 @@ cdef extern from "Python.h":
cdef extern from "bitsets.cc":
cdef void bitset_add(uint64_t* bits, size_t n)
cdef size_t bitset_next(uint64_t* bits, size_t face_length, size_t n)
cdef void bitset_clear(uint64_t* bits, size_t face_length)

def _Vrep_list_to_bit_rep_wrapper(tup, size_t face_length=-1):
r"""
Expand All @@ -96,7 +96,7 @@ def _Vrep_list_to_bit_rep_wrapper(tup, size_t face_length=-1):
sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \
....: import _Vrep_list_to_bit_rep_wrapper
sage: _Vrep_list_to_bit_rep_wrapper((60, 63))
sage: _Vrep_list_to_bit_rep_wrapper((0, 3))
(9,)
"""
if face_length == -1:
Expand Down Expand Up @@ -129,9 +129,9 @@ cdef int Vrep_list_to_bit_rep(tuple Vrep_list, uint64_t *output,
sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \
....: import _Vrep_list_to_bit_rep_wrapper
sage: _Vrep_list_to_bit_rep_wrapper((62, 63))
sage: _Vrep_list_to_bit_rep_wrapper((0, 1))
(3,)
sage: _Vrep_list_to_bit_rep_wrapper((61, 63, 125))
sage: _Vrep_list_to_bit_rep_wrapper((0, 2, 64+2))
(5, 4)
sage: _Vrep_list_to_bit_rep_wrapper((62, 70), face_length=1)
Traceback (most recent call last):
Expand All @@ -150,7 +150,7 @@ cdef int Vrep_list_to_bit_rep(tuple Vrep_list, uint64_t *output,
cdef size_t position # determines the position in output of entry
cdef size_t value # determines which bit will be set in output[position]

memset(output, 0, face_length*8) # initialize output
bitset_clear(output, face_length)
if unlikely(len(Vrep_list) != len(set(Vrep_list))):
raise ValueError("entries of ``tup`` are not distinct")
for entry in Vrep_list:
Expand All @@ -166,7 +166,7 @@ def _incidences_to_bit_rep_wrapper(tup, size_t face_length=-1):
sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \
....: import _incidences_to_bit_rep_wrapper
sage: _incidences_to_bit_rep_wrapper((0,) * 60 + (1,0,0,1))
sage: _incidences_to_bit_rep_wrapper((1,0,0,1))
(9,)
"""
if face_length == -1:
Expand Down Expand Up @@ -201,10 +201,10 @@ cdef int incidences_to_bit_rep(tuple incidences, uint64_t *output,
sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \
....: import _incidences_to_bit_rep_wrapper
sage: _incidences_to_bit_rep_wrapper((0,) * 62 + (1,1))
sage: _incidences_to_bit_rep_wrapper((1,1))
(3,)
sage: _incidences_to_bit_rep_wrapper((0,) * 61 + (1,0,1) +
....: (0,) * 61 + (1,))
sage: _incidences_to_bit_rep_wrapper((1,0,1) + 61*(0,) +
....: (0,0,1,))
(5, 4)
sage: _incidences_to_bit_rep_wrapper((1,) * 64) == (2**64-1,)
True
Expand All @@ -216,7 +216,7 @@ cdef int incidences_to_bit_rep(tuple incidences, uint64_t *output,
cdef size_t entry # index for the entries in tup
cdef size_t length = len(incidences)

memset(output, 0, face_length*8) #initialize
bitset_clear(output, face_length)
if unlikely(length > 64*face_length):
raise IndexError("output too small to represent all incidences")
for entry in range(length):
Expand Down Expand Up @@ -282,7 +282,7 @@ def incidence_matrix_to_bit_rep_of_facets(Matrix_integer_dense matrix):
cdef size_t i
for i in range(ncols):
output = facets_data[i]
memset(output, 0, face_length*8) #initialize
bitset_clear(output, face_length)

# Filling each facet with its Vrep-incidences, which "is" the
# "i-th column" of the original matrix (but we have transposed).
Expand Down Expand Up @@ -444,7 +444,7 @@ def facets_tuple_to_bit_rep_of_Vrep(tuple facets_input, size_t n_Vrep):
cdef size_t face_length = Vrep.face_length
cdef size_t i
for i in range(n_Vrep):
memset(Vrep_data[i], 0, face_length*8)
bitset_clear(Vrep_data[i], face_length)

cdef size_t input_facet # will iterate over indices of facets_input
cdef size_t position # determines the position in output of entry
Expand Down Expand Up @@ -484,7 +484,7 @@ def _bit_rep_to_Vrep_list_wrapper(data, index=0):
....: import facets_tuple_to_bit_rep_of_facets, \
....: _bit_rep_to_Vrep_list_wrapper
sage: _bit_rep_to_Vrep_list_wrapper((1, 1))
(63, 127)
(0, 64)
sage: faces = facets_tuple_to_bit_rep_of_facets(((1,5,123,1054),), 1055)
sage: _bit_rep_to_Vrep_list_wrapper(faces, 0)
(1, 5, 123, 1054)
Expand Down Expand Up @@ -531,11 +531,11 @@ cdef inline size_t bit_rep_to_Vrep_list(uint64_t *face, size_t *output,
sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \
....: import _bit_rep_to_Vrep_list_wrapper
sage: _bit_rep_to_Vrep_list_wrapper((17, 31))
(59, 63, 123, 124, 125, 126, 127)
(0, 4, 64, 65, 66, 67, 68)
sage: _bit_rep_to_Vrep_list_wrapper((13,))
(60, 61, 63)
(0, 2, 3)
sage: _bit_rep_to_Vrep_list_wrapper((0, 61))
(122, 123, 124, 125, 127)
(64, 66, 67, 68, 69)
TESTS:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ AUTHOR:
from sage.structure.element import is_Matrix

from cysignals.signals cimport sig_on, sig_off
from libc.string cimport memcpy
from sage.matrix.matrix_integer_dense cimport Matrix_integer_dense

cdef extern from "bitset_operations.cc":
Expand Down Expand Up @@ -146,6 +145,10 @@ cdef extern from "bitset_operations.cc":
cdef extern from "bitsets.cc":
cdef void bitset_add(uint64_t* bits, size_t n)
cdef int bitset_in(uint64_t* bits, size_t n)
cdef void bitset_copy(uint64_t* dst, uint64_t* src, size_t face_length)
cdef void bitset_copy_flex "bitset_copy" (uint64_t* dst, uint64_t* src, size_t face_length_dst, size_t face_length_src)
cdef void bitset_clear(uint64_t* bits, size_t face_length)
cdef void bitset_set_first_n(uint64_t* bits, size_t face_length, size_t n)

cdef extern from "Python.h":
int unlikely(int) nogil # Defined by Cython
Expand Down Expand Up @@ -267,7 +270,7 @@ cdef class ListOfFaces:
cdef ListOfFaces copy = ListOfFaces(self.n_faces, self.n_atoms)
cdef size_t i
for i in range(self.n_faces):
memcpy(copy.data[i], self.data[i], self.face_length*8)
bitset_copy(copy.data[i], self.data[i], self.face_length)
return copy

cpdef int compute_dimension(self) except -2:
Expand Down Expand Up @@ -356,7 +359,7 @@ cdef class ListOfFaces:
cdef size_t new_n_faces
sig_on()
new_n_faces = get_next_level(faces, n_faces,
newfaces.data, NULL, 0, face_length)
newfaces.data, NULL, 0, face_length)
sig_off()

newfaces.n_faces = new_n_faces
Expand Down Expand Up @@ -420,25 +423,20 @@ cdef class ListOfFaces:
[1 1 1 1 0]
"""
cdef ListOfFaces copy
cdef size_t i, j
cdef size_t i

# ``copy`` has a new atom and a new coatom.
copy = ListOfFaces(self.n_faces + 1, self.n_atoms + 1)

for i in range(self.n_faces):
for j in range(self.face_length, copy.face_length):
copy.data[i][j] = 0

# All old coatoms contain their respective old atoms.
# Also all of them contain the new atom.
memcpy(copy.data[i], self.data[i], self.face_length*8)
bitset_copy_flex(copy.data[i], self.data[i], copy.face_length, self.face_length)
bitset_add(copy.data[i], self.n_atoms)

# The new coatom contains all atoms, but the new atom.
for i in range(copy.face_length):
copy.data[self.n_faces][i] = 0
for i in range(self.n_atoms):
bitset_add(copy.data[self.n_faces], i)
bitset_set_first_n(copy.data[self.n_faces], copy.face_length, self.n_atoms)

return copy

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# distutils: depends = sage/geometry/polyhedron/combinatorial_polyhedron/bitset_operations.cc
# distutils: depends = sage/geometry/polyhedron/combinatorial_polyhedron/bitset_operations.cc sage/geometry/polyhedron/combinatorial_polyhedron/bitsets.cc
# distutils: language = c++
# distutils: extra_compile_args = -std=c++11
# distutils: libraries = gmp

r"""
PolyhedronFaceLattice
Expand Down Expand Up @@ -68,7 +69,6 @@ from .conversions \
facets_tuple_to_bit_rep_of_Vrep

from sage.rings.integer cimport smallInteger
from libc.string cimport memcmp, memcpy, memset
from .conversions cimport Vrep_list_to_bit_rep, bit_rep_to_Vrep_list
from .base cimport CombinatorialPolyhedron
from .face_iterator cimport FaceIterator
Expand All @@ -87,6 +87,10 @@ cdef extern from "bitset_operations.cc":
# in terms of uint64_t.
# ``n_coatoms`` length of ``coatoms``.

cdef extern from "bitsets.cc":
cdef int bitset_cmp(uint64_t* a, uint64_t* b, size_t face_length)
cdef void bitset_copy(uint64_t* dst, uint64_t* src, size_t face_length)

cdef extern from "Python.h":
int unlikely(int) nogil # Defined by Cython

Expand Down Expand Up @@ -245,7 +249,7 @@ cdef class PolyhedronFaceLattice:
raise IOError("trying to add too many faces to ``PolyhedronFaceLattice``")

# Actually add the face by copying its data.
memcpy(self.faces[face_dim + 1][counter], face, self.face_length*8)
bitset_copy(self.faces[face_dim + 1][counter], face, self.face_length)
self.face_counter[face_dim + 1] += 1

cdef int _sort(self) except -1:
Expand Down Expand Up @@ -413,7 +417,7 @@ cdef class PolyhedronFaceLattice:
r"""
Return `1` if ``one`` is smaller than ``two``, otherwise `0`.
"""
return memcmp(one, two, self.face_length*8) < 0
return bitset_cmp(one, two, self.face_length) < 0

cdef inline int is_equal(self, int dimension, size_t index, uint64_t *face) except -1:
r"""
Expand All @@ -426,7 +430,7 @@ cdef class PolyhedronFaceLattice:
raise IndexError()
cdef uint64_t *face2 = self.faces[dimension+1][index]
cdef size_t i
return (0 == memcmp(face, face2, self.face_length*8))
return (0 == bitset_cmp(face, face2, self.face_length))

cpdef CombinatorialFace get_face(self, int dimension, size_t index):
r"""
Expand Down

0 comments on commit 0b41c77

Please sign in to comment.