diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd index a318ad4c383..010865f66a1 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd @@ -62,9 +62,16 @@ cdef class CombinatorialPolyhedron(SageObject): cdef tuple _mem_tuple cdef FaceIterator _face_iter(self, bint dual, int dimension) - cdef int _compute_f_vector(self, bint compute_edges=*) except -1 - cdef int _compute_edges(self, dual) except -1 - cdef int _compute_ridges(self, dual) except -1 + cdef int _compute_f_vector(self, bint compute_edges=*, given_dual=*) except -1 + + cdef inline int _compute_edges(self, dual) except -1: + return self._compute_edges_or_ridges(dual, True) + + cdef inline int _compute_ridges(self, dual) except -1: + return self._compute_edges_or_ridges(dual, False) + + cdef int _compute_edges_or_ridges(self, bint dual, bint do_edges) except -1 + cdef size_t _compute_edges_or_ridges_with_iterator(self, FaceIterator face_iter, bint do_atom_rep, size_t ***edges_pt, size_t *counter_pt, size_t *current_length_pt, MemoryAllocator mem) except -1 cdef int _compute_face_lattice_incidences(self) except -1 cdef inline int _set_edge(self, size_t a, size_t b, size_t ***edges_pt, size_t *counter_pt, size_t *current_length_pt, MemoryAllocator mem) except -1 diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx index 166579dbb04..def4cd842ca 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx @@ -1171,7 +1171,7 @@ cdef class CombinatorialPolyhedron(SageObject): self._compute_edges(dual=False) else: # In most bounded cases, one should use the dual. - self._compute_ridges(dual=True) + self._compute_edges(dual=True) if self._edges is NULL: raise ValueError('could not determine edges') @@ -1340,7 +1340,7 @@ cdef class CombinatorialPolyhedron(SageObject): elif self.n_Vrepresentation()*self.n_Vrepresentation() < self.n_facets(): # This is a wild estimate # that in this case it is better to use the dual. - self._compute_edges(dual=True) + self._compute_ridges(dual=True) else: # In most bounded cases, one should not use the dual. self._compute_ridges(dual=False) @@ -2769,7 +2769,7 @@ cdef class CombinatorialPolyhedron(SageObject): # Internal methods. - cdef int _compute_f_vector(self, bint compute_edges=False) except -1: + cdef int _compute_f_vector(self, bint compute_edges=False, given_dual=None) except -1: r""" Compute the ``f_vector`` of the polyhedron. @@ -2788,6 +2788,10 @@ cdef class CombinatorialPolyhedron(SageObject): else: # In this case the dual approach is faster. dual = True + if given_dual is not None: + dual = given_dual + + cdef FaceIterator face_iter = self._face_iter(dual, -2) cdef int dim = self.dimension() @@ -2862,16 +2866,18 @@ cdef class CombinatorialPolyhedron(SageObject): self._mem_tuple += (mem,) sig_unblock() - cdef int _compute_edges(self, dual) except -1: + cdef int _compute_edges_or_ridges(self, bint dual, bint do_edges) except -1: r""" - Compute the edges of the polyhedron. + Compute the edges of the polyhedron if ``edges`` else the ridges. + + If ``dual``, use the face iterator in dual mode, else in non-dual. - If ``dual`` is ``True``, compute the edges of the dual. In this case, - this will also compute the ``f_vector``, if unknown. + If the ``f_vector`` is unkown computes it as well if computing the edges + in non-dual mode or the ridges in dual-mode. See :meth:`CombinatorialPolyhedron.edges` and :meth:`CombinatorialPolyhedron.ridges`. """ - if (self._edges is not NULL and not dual) or (self._ridges is not NULL and dual): + if (self._edges is not NULL and do_edges) or (self._ridges is not NULL and not do_edges): return 0 # There is no need to recompute. cdef MemoryAllocator mem = MemoryAllocator() @@ -2881,187 +2887,66 @@ cdef class CombinatorialPolyhedron(SageObject): cdef size_t **edges = mem.malloc(sizeof(size_t**)) cdef size_t counter = 0 # the number of edges so far cdef size_t current_length = 1 # dynamically enlarge **edges + cdef int output_dim_init = 1 if do_edges else dim - 2 - cdef size_t a,b # vertices of an edge - - if dim == 1: - # In this case there is an edge, but its not a proper face. + if dim == 1 and (do_edges or self.n_facets() > 1): + # In this case there is an edge/ridge, but its not a proper face. self._set_edge(0, 1, &edges, &counter, ¤t_length, mem) - # Success, copy the data to ``CombinatorialPolyhedron``. - if dual: - # We have actually computed the ridges. - sig_block() - self._n_ridges = counter - self._ridges = edges - self._mem_tuple += (mem,) - sig_unblock() - else: - sig_block() - self._n_edges = counter - self._edges = edges - self._mem_tuple += (mem,) - sig_unblock() - return 0 - - if dim == 0: - # There is no edge. - # Prevent calling the face iterator with an improper dimension. - counter = 0 - - # Success, copy the data to ``CombinatorialPolyhedron``. - if dual: - # We have actually computed the ridges. - sig_block() - self._n_ridges = counter - self._ridges = edges - self._mem_tuple += (mem,) - sig_unblock() - else: - sig_block() - self._n_edges = counter - self._edges = edges - self._mem_tuple += (mem,) - sig_unblock() - return 0 - - if not self._f_vector: - # While doing the edges one might as well do the f-vector. - return self._compute_f_vector(compute_edges=True) + elif dim <= 1 or self.n_facets() == 0: + # There is no edge/ridge. + # Prevent an error when calling the face iterator. + pass - # Only compute the edges. + elif not self._f_vector and ((dual ^ do_edges)): + # While doing edges in non-dual mode or ridges in dual-mode + # one might as well do the f-vector. + return self._compute_f_vector(compute_edges=True, given_dual=dual) - if not dual: - face_iter = self._face_iter(dual, 1) else: - # ``output_dimension`` in - # :meth:`~sage.geometry.polyhedron.combinatorial_polyhedron.face_iterator.FaceIterator.__init__` - # requires the dimension of the original polyhedron - face_iter = self._face_iter(dual, dim - 2) + # Only compute the edges/ridges. + face_iter = self._face_iter(dual, output_dim_init) - if self.n_facets() > 0 and dim > 0: - # If not, there won't even be any edges. Prevent error message. - - while (face_iter.next_dimension() == 1): - # Set up face_iter.atom_rep - face_iter.set_atom_rep() - - # Copy the information. - a = face_iter.structure.atom_rep[0] - b = face_iter.structure.atom_rep[1] - self._set_edge(a, b, &edges, &counter, ¤t_length, mem) + self._compute_edges_or_ridges_with_iterator(face_iter, (dual ^ do_edges), &edges, &counter, ¤t_length, mem) # Success, copy the data to ``CombinatorialPolyhedron``. - if dual: + if do_edges: sig_block() - self._n_ridges = counter - self._ridges = edges + self._n_edges = counter + self._edges = edges self._mem_tuple += (mem,) sig_unblock() else: sig_block() - self._n_edges = counter - self._edges = edges + self._n_ridges = counter + self._ridges = edges self._mem_tuple += (mem,) sig_unblock() - cdef int _compute_ridges(self, dual) except -1: + cdef size_t _compute_edges_or_ridges_with_iterator(self, FaceIterator face_iter, bint do_atom_rep, size_t ***edges_pt, size_t *counter_pt, size_t *current_length_pt, MemoryAllocator mem) except -1: r""" - Compute the ridges of the polyhedron. - - If ``dual`` is ``True``, compute the ridges of the dual. - - See :meth:`edges` and :meth:`ridges`. + See :meth:`CombinatorialPolyhedron._compute_edges`. """ - if (self._edges is not NULL and dual) or (self._ridges is not NULL and not dual): - return 0 # There is no need to recompute. - - cdef MemoryAllocator mem = MemoryAllocator() - cdef FaceIterator face_iter + cdef size_t a,b # facets of an edge cdef int dim = self.dimension() + cdef output_dimension = 1 if do_atom_rep else dim - 2 - # For each ridge we determine its location in ``ridges`` - # by ``ridges[one][two]``. - cdef size_t **ridges = mem.malloc(sizeof(size_t**)) - - cdef size_t counter = 0 # the number of ridges so far - cdef size_t current_length = 1 # dynamically enlarge **ridges - - cdef size_t a,b # facets of a ridge - - if dim == 1 and self.n_facets() > 1: - # In this case there is a ridge, but its not a proper face. - self._set_edge(0, 1, &ridges, &counter, ¤t_length, mem) - - # Success, copy the data to ``CombinatorialPolyhedron``. - if not dual: - sig_block() - self._n_ridges = counter - self._ridges = ridges - self._mem_tuple += (mem,) - sig_unblock() - else: - sig_block() - self._n_edges = counter - self._edges = ridges - self._mem_tuple += (mem,) - sig_unblock() - return 0 - - if dim <= 1: - # There is no ridge, but face iterator expects a proper face dimension as input. - counter = 0 + while (face_iter.next_dimension() == output_dimension): + if do_atom_rep: + # Set up face_iter.atom_rep + face_iter.set_atom_rep() - # Success, copy the data to ``CombinatorialPolyhedron``. - if not dual: - sig_block() - self._n_ridges = counter - self._ridges = ridges - self._mem_tuple += (mem,) - sig_unblock() + # Copy the information. + a = face_iter.structure.atom_rep[0] + b = face_iter.structure.atom_rep[1] else: - sig_block() - self._n_edges = counter - self._edges = ridges - self._mem_tuple += (mem,) - sig_unblock() - return 0 - - if dual: - # ``output_dimension`` in - # :meth:`FaceIterator.__init` - # requires the dimension of the original polyhedron - face_iter = self._face_iter(dual, 1) - else: - face_iter = self._face_iter(dual, dim -2) - - if self.n_facets() > 1 and dim > 0: - # If not, there won't even be any ridges - # as intersection of two distinct facets. - # Prevent error message. - - while (face_iter.next_dimension() == dim - 2): # Set up face_iter.coatom_rep face_iter.set_coatom_rep() # Copy the information. a = face_iter.structure.coatom_rep[0] b = face_iter.structure.coatom_rep[1] - self._set_edge(a, b, &ridges, &counter, ¤t_length, mem) - - # Success, copy the data to ``CombinatorialPolyhedron``. - if not dual: - sig_block() - self._n_ridges = counter - self._ridges = ridges - self._mem_tuple += (mem,) - sig_unblock() - else: - sig_block() - self._n_edges = counter - self._edges = ridges - self._mem_tuple += (mem,) - sig_unblock() + self._set_edge(a, b, edges_pt, counter_pt, current_length_pt, mem) cdef int _compute_face_lattice_incidences(self) except -1: r"""