extern struct SyncTreeWorkerHead * SyncTreeWorkerCreate(struct SyncHashCacheHead *cache, struct SyncHashCacheEntry *ent) { struct SyncTreeWorkerHead * head = NEW_STRUCT(1, SyncTreeWorkerHead); int lim = 4; struct SyncTreeWorkerEntry * stack = NEW_STRUCT(lim, SyncTreeWorkerEntry); head->stack = stack; head->lim = lim; head->cache = cache; SyncTreeWorkerInit(head, ent); return head; }
struct neighbour_list * neighbour_list_create() { NEW_STRUCT(ret,neighbour_list); ret->array = assoc_array_create(neighbour_list_get_router_id,assoc_array_key_comp_int); ret->mutex = mutex_create(); return ret; }
static void __combine_arrays(uint32_t subnet, uint32_t mask, uint32_t next_hop, char * interface, void * userdata, int * finished) { struct assoc_array * array = (struct assoc_array *)userdata; struct forwarding_table_subnet_list * ftsl; struct forwarding_table_entry * fte; NEW_STRUCT(entry,forwarding_table_entry); struct ip_address ip = {subnet,mask}; entry->ip.subnet = subnet; entry->ip.mask = mask; entry->next_hop = next_hop; strcpy(entry->interface,interface); if(__forwarding_table_get_entry(NULL, array, &ip, &ftsl, &fte)) { free(assoc_array_delete(ftsl->list,&fte->ip.subnet)); } if(ftsl == NULL) { ftsl = (struct forwarding_table_subnet_list *) malloc(sizeof(struct forwarding_table_subnet_list)); ftsl->mask = mask; ftsl->list = assoc_array_create(__forwarding_table_get_key_dest, assoc_array_key_comp_int); assoc_array_insert(array,ftsl); } assoc_array_insert(ftsl->list,entry); }
static void set_up_perimeter( Tetrahedron *base_tet, VertexIndex base_vertex, PerimeterPiece **perimeter_anchor) { int i; PerimeterPiece *pp[3]; base_tet->extra[base_vertex].visited = TRUE; base_tet->extra[base_vertex].parent_tet = NULL; base_tet->extra[base_vertex].orientation = right_handed; for (i = 0; i < 3; i++) pp[i] = NEW_STRUCT(PerimeterPiece); for (i = 0; i < 3; i++) { pp[i]->tet = base_tet; pp[i]->vertex = base_vertex; pp[i]->face = vt_side[base_vertex][i]; pp[i]->orientation = right_handed; pp[i]->checked = FALSE; pp[i]->next = pp[(i+1)%3]; pp[i]->prev = pp[(i+2)%3]; } *perimeter_anchor = pp[0]; }
extern struct SyncHashCacheHead * SyncHashCacheCreate(struct SyncRootStruct *root, uint32_t mod) { struct SyncHashCacheHead *head = NEW_STRUCT(1, SyncHashCacheHead); if (mod < 4) mod = 4; head->mod = mod; head->ents = NEW_ANY(mod, struct SyncHashCacheEntry *); head->root = root; return head; }
void forwarding_table_create(struct sr_instance * sr) { NEW_STRUCT(ret,forwarding_table); ROUTER(sr)->fwd_table = ret; ret->array_s = assoc_array_create(__forwarding_table_get_key_mask,assoc_array_key_comp_int); ret->array_d = assoc_array_create(__forwarding_table_get_key_mask,assoc_array_key_comp_int); ret->array_nat = assoc_array_create(__forwarding_table_get_key_mask,assoc_array_key_comp_int); ret->mutex = mutex_create(); ret->running_dijkstra = 0; }
static void copy_isometry( Triangulation *manifold0, Triangulation *manifold1, Isometry **new_isometry) { Tetrahedron *tet0; int i; /* * Allocate the Isometry. */ *new_isometry = NEW_STRUCT(Isometry); (*new_isometry)->tet_image = NEW_ARRAY(manifold0->num_tetrahedra, int); (*new_isometry)->tet_map = NEW_ARRAY(manifold0->num_tetrahedra, Permutation); (*new_isometry)->cusp_image = NEW_ARRAY(manifold0->num_cusps, int); (*new_isometry)->cusp_map = NEW_ARRAY(manifold0->num_cusps, MatrixInt22); (*new_isometry)->singular_image = NEW_ARRAY(manifold0->num_singular_arcs, int); /* * Set the num_tetrahedra and num_cusps fields. */ (*new_isometry)->num_tetrahedra = manifold0->num_tetrahedra; (*new_isometry)->num_cusps = manifold0->num_cusps; (*new_isometry)->num_singular_arcs = manifold0->num_singular_arcs; /* * Copy the isometry from the Triangulation * to the Isometry data structure. */ for (tet0 = manifold0->tet_list_begin.next, i = 0; tet0 != &manifold0->tet_list_end; tet0 = tet0->next, i++) { (*new_isometry)->tet_image[i] = tet0->image->index; (*new_isometry)->tet_map[i] = tet0->map; } /* * How does this Isometry act on the Cusps? */ compute_cusp_action(manifold0, manifold1, *new_isometry); compute_singular_action(manifold0, *new_isometry); /* * We don't use the "next" field. */ (*new_isometry)->next = NULL; }
extern struct SyncTreeWorkerEntry * SyncTreeWorkerPush(struct SyncTreeWorkerHead *head) { struct SyncNodeElem *ref = SyncTreeWorkerGetElem(head); if (ref == NULL || (ref->kind & SyncElemKind_leaf)) return NULL; struct SyncTreeWorkerEntry *ent = SyncTreeWorkerTop(head); struct SyncHashCacheEntry *ce = ent->cacheEntry; if (ce == NULL) return NULL; struct SyncNodeComposite *nc = ce->ncL; if (nc == NULL) nc = ce->ncR; if (nc == NULL) return NULL; struct ccn_buf_decoder cbd; struct ccn_buf_decoder *cb = SyncInitDecoderFromOffset(&cbd, nc, ref->start, ref->stop); const unsigned char *xp = NULL; ssize_t xs = 0; SyncGetHashPtr(cb, &xp, &xs); ce = SyncHashLookup(head->cache, xp, xs); if (ce == NULL) // no entry? this is not so good return NULL; struct SyncTreeWorkerEntry *stack = head->stack; int level = head->level; int oLim = head->lim; if (level > oLim) { // something bad has happened return NULL; } if (level == oLim) { // first, expand the stack to get enough room int nLim = oLim + oLim / 2 + 4; struct SyncTreeWorkerEntry *nStack = NEW_STRUCT(nLim, SyncTreeWorkerEntry); memcpy(nStack, stack, level*sizeof(struct SyncTreeWorkerEntry)); free(stack); stack = nStack; head->stack = nStack; head->lim = nLim; } // now we can push the node head->level = level+1; ent = &stack[level]; ent->pos = 0; ent->count = 0; ent->cacheEntry = ce; ce->busy++; head->visits++; return ent; }
extern struct SyncBaseStruct * SyncNewBase(struct ccnr_handle *ccnr, struct ccn *ccn, struct ccn_schedule *sched) { sync_time now = SyncCurrentTime(); struct SyncBaseStruct *base = NEW_STRUCT(1, SyncBaseStruct); base->ccnr = ccnr; base->ccn = ccn; base->sched = sched; struct SyncPrivate *priv = NEW_STRUCT(1, SyncPrivate); base->priv = priv; priv->topoAccum = SyncAllocNameAccum(4); priv->prefixAccum = SyncAllocNameAccum(4); priv->sliceCmdPrefix = ccn_charbuf_create(); priv->localHostPrefix = ccn_charbuf_create(); priv->comps = ccn_indexbuf_create(); priv->stableTarget = CCNR_NULL_HWM; priv->stableStored = CCNR_NULL_HWM; priv->lastStable = now; priv->lastCacheClean = now; ccn_name_from_uri(priv->localHostPrefix, "/%C1.M.S.localhost"); ccn_name_from_uri(priv->sliceCmdPrefix, "/%C1.M.S.localhost/%C1.S.cs"); return base; }
extern void SyncSetErrInner(struct SyncBaseStruct *base, enum SyncErrCode code, char * file, int line) { struct SyncErrStruct *err = NEW_STRUCT(1, SyncErrStruct); err->code = code; err->file = file; err->line = line; struct SyncErrStruct *lag = base->errList; while (lag != NULL) { struct SyncErrStruct *next = lag->next; if (next == NULL) break; lag = next; } if (lag != NULL) lag->next = err; else base->errList = err; }
void forwarding_table_add(struct sr_instance * sr, struct ip_address * ip, uint32_t nh, char * interface, int isDynamic, int nat) { struct forwarding_table * ft = FORWARDING_TABLE(sr); struct forwarding_table_subnet_list * ftsl; struct forwarding_table_entry * fte; NEW_STRUCT(entry,forwarding_table_entry); uint32_t next_hop = nh; struct assoc_array * array; if(interface_list_ip_in_network_on_interface(sr,ip,interface)) { next_hop = 0; } entry->ip = *ip; entry->ip.subnet &= ip->mask; entry->next_hop = next_hop; strcpy(entry->interface,interface); mutex_lock(ft->mutex); array = isDynamic ? (nat ? ft->array_nat : ft->array_d) : ft->array_s; if(__forwarding_table_get_entry(ft, array, ip, &ftsl, &fte)) { free(assoc_array_delete(ftsl->list,&fte->ip.subnet)); } if(ftsl == NULL) { ftsl = (struct forwarding_table_subnet_list *) malloc(sizeof(struct forwarding_table_subnet_list)); ftsl->mask = ip->mask; ftsl->list = assoc_array_create(__forwarding_table_get_key_dest, assoc_array_key_comp_int); assoc_array_insert(array,ftsl); } assoc_array_insert(ftsl->list,entry); if(ft->running_dijkstra == 0 && nat == 0) { forwarding_table_hw_write(sr); router_notify(sr, isDynamic ? ROUTER_UPDATE_FWD_TABLE : ROUTER_UPDATE_FWD_TABLE_S); } mutex_unlock(ft->mutex); }
cifs_dir_p cifs_mask(cifs_connect_p c, const char *path, const char *mask) { cifs_dir_p d; NEW_STRUCT(d); if (d == NULL) return NULL; d->t = cifs_trans_new(); if (d->t == NULL) { FREE_STRUCT(d); return NULL; } d->c = c; cifs_find_first_req(c, path, mask); if (cifs_trans_request(c, d->t)) { cifs_trans_free(d->t); FREE_STRUCT(d); return NULL; } cifs_log_trans("findfirst", d->t); struct cifs_find_first_res_s *ff = cifs_buf_cur(d->t->param); d->end = ff->end_of_search; d->sid = ff->sid; d->buf = d->t->data; d->count = ff->search_count; d->path = cifs_buf_new(PATH_MAX + NAME_MAX + 2); d->de.path = cifs_buf_cur(d->path); cifs_write_str(d->path, path); cifs_write_str(d->path, "/"); d->de.name = cifs_buf_cur(d->path); return d; }
extern struct SyncHashCacheEntry * SyncHashEnter(struct SyncHashCacheHead *head, const unsigned char *xp, ssize_t xs, enum SyncHashState set) { if (xp == NULL || xs <= 0) return NULL; uint32_t h = SyncSmallHash(xp, xs); uint32_t hx = h % head->mod; struct SyncHashCacheEntry *old = head->ents[hx]; struct SyncHashCacheEntry *ent = old; head->probes = head->probes + 1; while (ent != NULL) { if (h == ent->small) { // probably equal, but we have to check ssize_t cmp = SyncCmpHashesRaw(xp, xs, ent->hash->buf, ent->hash->length); if (cmp == 0) { ent->state |= set; return ent; } } ent = ent->next; } head->misses = head->misses + 1; if (ent == NULL) { uintmax_t index = head->lastIndex + 1; head->lastIndex = index; head->probes = head->probes + 1; head->misses = head->misses + 1; ent = NEW_STRUCT(1, SyncHashCacheEntry); ent->lastUsed = SyncCurrentTime(); ent->head = head; ent->next = old; ent->small = h; ent->hash = ccn_charbuf_create(); ent->index = index; ccn_charbuf_append(ent->hash, xp, xs); head->ents[hx] = ent; head->len++; } ent->state |= set; return ent; }
void create_one_cusp( Triangulation *manifold, Tetrahedron *tet, Boolean is_finite, VertexIndex v, int cusp_index) { Cusp *cusp; IdealVertex *queue; int queue_first, queue_last; Tetrahedron *tet1, *nbr; VertexIndex v1, nbr_v; FaceIndex f; /* * Create the cusp, add it to the list, and set * the is_finite and index fields. */ cusp = NEW_STRUCT(Cusp); initialize_cusp(cusp); INSERT_BEFORE(cusp, &manifold->cusp_list_end); cusp->is_finite = is_finite; cusp->index = cusp_index; /* * We don't set the topology, is_complete, m, l, holonomy, * cusp_shape or shape_precision fields. * * For "real" cusps the calling routine may * * (1) call peripheral_curves() to set the cusp->topology, * * (2) keep the default values of cusp->is_complete, * cusp->m and cusp->l as set by initialize_cusp(), and * * (3) let the holonomy and cusp_shape be computed automatically * when hyperbolic structure is computed. * * Alternatively, the calling routine may set these fields in other * ways, as it sees fit. * * If we were called by create_fake_cusps(), then the above fields * are all irrelevant and ignored. */ /* * Set the tet->cusp field at all vertices incident to the new cusp. */ /* * Allocate space for a queue of pointers to the IdealVertices. * Each IdealVertex will appear on the queue at most once, so an * array of length 4 * manifold->num_tetrahedra will suffice. */ queue = NEW_ARRAY(4 * manifold->num_tetrahedra, IdealVertex); /* * Set the cusp of the given IdealVertex... */ tet->cusp[v] = cusp; /* * ...and put it on the queue. */ queue_first = 0; queue_last = 0; queue[0].tet = tet; queue[0].v = v; /* * Start processing the queue. */ do { /* * Pull an IdealVertex off the front of the queue. */ tet1 = queue[queue_first].tet; v1 = queue[queue_first].v; queue_first++; /* * Look at the three neighboring IdealVertices. */ for (f = 0; f < 4; f++) { if (f == v1) continue; nbr = tet1->neighbor[f]; nbr_v = EVALUATE(tet1->gluing[f], v1); /* * If the neighbor's cusp hasn't been set... */ if (nbr->cusp[nbr_v] == NULL) { /* * ...set it... */ nbr->cusp[nbr_v] = cusp; /* * ...and add it to the end of the queue. */ ++queue_last; queue[queue_last].tet = nbr; queue[queue_last].v = nbr_v; } } } while (queue_first <= queue_last); /* * Free the memory used for the queue. */ my_free(queue); }
static void expand_perimeter( PerimeterPiece *perimeter_anchor) { int num_unchecked_pieces; PerimeterPiece *pp, *new_piece; Permutation gluing; Tetrahedron *nbr_tet; VertexIndex nbr_vertex; FaceIndex nbr_back_face, nbr_left_face, nbr_right_face; Orientation nbr_orientation; for (num_unchecked_pieces = 3, pp = perimeter_anchor; num_unchecked_pieces; pp = pp->next) if (pp->checked == FALSE) { gluing = pp->tet->gluing[pp->face]; nbr_tet = pp->tet->neighbor[pp->face]; nbr_vertex = EVALUATE(gluing, pp->vertex); if (nbr_tet->extra[nbr_vertex].visited) { pp->checked = TRUE; num_unchecked_pieces--; } else { /* * Extend the tree to the neighboring vertex. */ nbr_back_face = EVALUATE(gluing, pp->face); if (parity[gluing] == orientation_preserving) nbr_orientation = pp->orientation; else nbr_orientation = ! pp->orientation; if (nbr_orientation == right_handed) { nbr_left_face = remaining_face[nbr_vertex][nbr_back_face]; nbr_right_face = remaining_face[nbr_back_face][nbr_vertex]; } else { nbr_left_face = remaining_face[nbr_back_face][nbr_vertex]; nbr_right_face = remaining_face[nbr_vertex][nbr_back_face]; } nbr_tet->extra[nbr_vertex].visited = TRUE; nbr_tet->extra[nbr_vertex].parent_tet = pp->tet; nbr_tet->extra[nbr_vertex].parent_vertex = pp->vertex; nbr_tet->extra[nbr_vertex].this_faces_parent = nbr_back_face; nbr_tet->extra[nbr_vertex].parent_faces_this = pp->face; nbr_tet->extra[nbr_vertex].orientation = nbr_orientation; /* * Extend the perimeter across the neighboring * vertex. The new PerimeterPiece is added on * the right side of the old one, so that the * pp = pp->next step in the loop moves us past * both the old and new perimeter pieces. This * causes the perimeter to expand uniformly in * all directions. */ new_piece = NEW_STRUCT(PerimeterPiece); new_piece->tet = nbr_tet; new_piece->vertex = nbr_vertex; new_piece->face = nbr_right_face; new_piece->orientation = nbr_orientation; new_piece->checked = FALSE; new_piece->next = pp; new_piece->prev = pp->prev; pp->prev->next = new_piece; pp->tet = nbr_tet; pp->vertex = nbr_vertex; pp->face = nbr_left_face; pp->orientation = nbr_orientation; pp->checked = FALSE; /* unchanged */ pp->next = pp->next; /* unchanged */ pp->prev = new_piece; /* * Increment the count of unchecked pieces. */ num_unchecked_pieces++; } } }
cifs_uri_p cifs_uri_parse(const char *str) { char *buf, *a, *b; cifs_uri_p uri; NEW_STRUCT(uri); buf = strdup(str); cifs_uri_unescape(buf); a = buf; if (a[0] == '\\' && a[1] == '\\') { /* UNC */ uri->scheme = URI_CIFS; b = a; while ((b = strchr(b, '\\'))) { *b++ = '/'; } a += 2; } else { b = strstr(a, "://"); if (b) { if (!strncmp(a, "file", b-a)) { uri->scheme = URI_FILE; } else if (!strncmp(a, "cifs", b-a) || !strncmp(a, "smb", b-a)) { uri->scheme = URI_CIFS; } else { goto err; } a = b+3; } else { uri->scheme = URI_FILE; } } if (uri->scheme != URI_FILE) { /* [user[:password]@]host[:[addr:]port] */ char *at, *co; b = strchr(a, '/'); if (b) *b = 0; at = strchr(a, '@'); if (at) { *at = 0; co = strchr(a, ':'); if (co) { uri->user = strndup(a, co-a); uri->password = strdup(co+1); } else { uri->user = strdup(a); } *at = '@'; a=at+1; } co = strchr(a, ':'); if (co) { uri->host = strndup(a, co-a); at = strrchr(a, ':'); if (co != at) { uri->addr = strndup(co+1, at-co-1); } uri->port = atoi(at+1); } else { uri->host = strdup(a); } if (b) { *b = '/'; a = b+1; } else { a += strlen(a); } } if (a[0] && uri->scheme == URI_CIFS) { b = strchr(a, '/'); if (b) { uri->tree = strndup(a, b-a); a = b+1; } else { uri->tree = strdup(a); a += strlen(a); } } uri->path = strdup(a); b = strrchr(a, '/'); if (b) { uri->file = strdup(b+1); uri->dir = strndup(a, b-a); } else { uri->file = strdup(a); uri->dir = strdup(""); } free(buf); return uri; err: free(buf); free(uri); return NULL; }
void data_to_triangulation( TriangulationData *data, Triangulation **manifold_ptr) { /* * We assume the UI has done some basic error checking * on the data, so we don't repeat it here. */ Triangulation *manifold; Tetrahedron **tet_array; Cusp **cusp_array; Boolean cusps_are_given; int i, j, k, l, m; Boolean all_peripheral_curves_are_zero, finite_vertices_are_present; /* * Initialize *manifold_ptr to NULL. * We'll do all our work with manifold, and then copy * manifold to *manifold_ptr at the very end. */ *manifold_ptr = NULL; /* * Allocate and initialize the Triangulation structure. */ manifold = NEW_STRUCT(Triangulation); initialize_triangulation(manifold); /* * Allocate and copy the name. */ manifold->name = NEW_ARRAY(strlen(data->name) + 1, char); strcpy(manifold->name, data->name); /* * Set up the global information. * * The hyperbolic structure is included in the file only for * human readers; here we recompute it from scratch. */ manifold->num_tetrahedra = data->num_tetrahedra; manifold->solution_type[complete] = not_attempted; manifold->solution_type[ filled ] = not_attempted; manifold->orientability = data->orientability; manifold->num_or_cusps = data->num_or_cusps; manifold->num_nonor_cusps = data->num_nonor_cusps; manifold->num_cusps = manifold->num_or_cusps + manifold->num_nonor_cusps; /* * Allocate the Tetrahedra. * Keep pointers to them on a temporary array, so we can * find them by their indices. */ tet_array = NEW_ARRAY(manifold->num_tetrahedra, Tetrahedron *); for (i = 0; i < manifold->num_tetrahedra; i++) { tet_array[i] = NEW_STRUCT(Tetrahedron); initialize_tetrahedron(tet_array[i]); INSERT_BEFORE(tet_array[i], &manifold->tet_list_end); } /* * If num_or_cusps or num_nonor_cusps is nonzero, allocate the Cusps. * Keep pointers to them on temporary arrays, so we can find them * by their indices. * Otherwise we will create arbitrary Cusps later. */ cusps_are_given = (data->num_or_cusps != 0) || (data->num_nonor_cusps != 0); if (cusps_are_given == TRUE) { cusp_array = NEW_ARRAY(manifold->num_cusps, Cusp *); for (i = 0; i < manifold->num_cusps; i++) { cusp_array[i] = NEW_STRUCT(Cusp); initialize_cusp(cusp_array[i]); INSERT_BEFORE(cusp_array[i], &manifold->cusp_list_end); } }
static void drill_tube( Triangulation *manifold, Tetrahedron *tet, EdgeIndex e, Boolean creating_new_cusp) { /* * Insert a triangular-pillow-with-tunnel (as described at the top * of this file) so as to connect the boundary component at one * end of the given edge to the boundary component at the other end. * The orientation on the triangular pillow will match the * orientation on tet, so that the orientation on the manifold * (if there is one) will be preserved. Edge orientations are also * respected. */ VertexIndex v0, v1, v2, vv0, vv1, vv2; FaceIndex f, ff; Tetrahedron *nbr_tet, *new_tet0, *new_tet1; Permutation gluing; EdgeClass *edge0, *edge1, *edge2, *new_edge; Orientation edge_orientation0, edge_orientation1, edge_orientation2; PeripheralCurve c; Orientation h; int num_strands, intersection_number[2], the_gcd; Cusp *unique_cusp; MatrixInt22 basis_change[1]; /* * Relative to the orientation of tet, the vertices v0, v1 and v2 * are arranged in counterclockwise order around the face f. */ v0 = one_vertex_at_edge[e]; v1 = other_vertex_at_edge[e]; v2 = remaining_face[v1][v0]; f = remaining_face[v0][v1]; /* * Note the matching face and its vertices. */ nbr_tet = tet->neighbor[f]; gluing = tet->gluing[f]; ff = EVALUATE(gluing, f); vv0 = EVALUATE(gluing, v0); vv1 = EVALUATE(gluing, v1); vv2 = EVALUATE(gluing, v2); /* * Note the incident EdgeClasses (which may or may not be distinct). */ edge0 = tet->edge_class[e]; edge1 = tet->edge_class[edge_between_vertices[v1][v2]]; edge2 = tet->edge_class[edge_between_vertices[v2][v0]]; /* * Construct the triangular-pillow-with-tunnel, as described * at the top of this file. */ new_tet0 = NEW_STRUCT(Tetrahedron); new_tet1 = NEW_STRUCT(Tetrahedron); initialize_tetrahedron(new_tet0); initialize_tetrahedron(new_tet1); INSERT_BEFORE(new_tet0, &manifold->tet_list_end); INSERT_BEFORE(new_tet1, &manifold->tet_list_end); manifold->num_tetrahedra += 2; new_edge = NEW_STRUCT(EdgeClass); initialize_edge_class(new_edge); INSERT_BEFORE(new_edge, &manifold->edge_list_end); new_tet0->neighbor[0] = new_tet1; new_tet0->neighbor[1] = NULL; /* assigned below */ new_tet0->neighbor[2] = NULL; /* assigned below */ new_tet0->neighbor[3] = new_tet1; new_tet1->neighbor[0] = new_tet0; new_tet1->neighbor[1] = new_tet1; new_tet1->neighbor[2] = new_tet1; new_tet1->neighbor[3] = new_tet0; new_tet0->gluing[0] = CREATE_PERMUTATION(0, 0, 1, 2, 2, 1, 3, 3); new_tet0->gluing[1] = 0x00; /* assigned below */ new_tet0->gluing[2] = 0x00; /* assigned below */ new_tet0->gluing[3] = CREATE_PERMUTATION(0, 1, 1, 0, 2, 2, 3, 3); new_tet1->gluing[0] = CREATE_PERMUTATION(0, 0, 1, 2, 2, 1, 3, 3); new_tet1->gluing[1] = CREATE_PERMUTATION(0, 0, 1, 2, 2, 1, 3, 3); new_tet1->gluing[2] = CREATE_PERMUTATION(0, 0, 1, 2, 2, 1, 3, 3); new_tet1->gluing[3] = CREATE_PERMUTATION(0, 1, 1, 0, 2, 2, 3, 3); new_tet0->edge_class[0] = edge1; new_tet0->edge_class[1] = edge1; new_tet0->edge_class[2] = edge0; new_tet0->edge_class[3] = edge2; new_tet0->edge_class[4] = edge0; new_tet0->edge_class[5] = edge0; new_tet1->edge_class[0] = edge1; new_tet1->edge_class[1] = edge1; new_tet1->edge_class[2] = edge0; new_tet1->edge_class[3] = new_edge; new_tet1->edge_class[4] = edge0; new_tet1->edge_class[5] = edge0; edge0->order += 6; edge1->order += 4; edge2->order += 1; new_edge->order = 1; new_edge->incident_tet = new_tet1; new_edge->incident_edge_index = 3; edge_orientation0 = tet->edge_orientation[e]; edge_orientation1 = tet->edge_orientation[edge_between_vertices[v1][v2]]; edge_orientation2 = tet->edge_orientation[edge_between_vertices[v2][v0]]; new_tet0->edge_orientation[0] = edge_orientation1; new_tet0->edge_orientation[1] = edge_orientation1; new_tet0->edge_orientation[2] = edge_orientation0; new_tet0->edge_orientation[3] = edge_orientation2; new_tet0->edge_orientation[4] = edge_orientation0; new_tet0->edge_orientation[5] = edge_orientation0; new_tet1->edge_orientation[0] = edge_orientation1; new_tet1->edge_orientation[1] = edge_orientation1; new_tet1->edge_orientation[2] = edge_orientation0; new_tet1->edge_orientation[3] = right_handed; new_tet1->edge_orientation[4] = edge_orientation0; new_tet1->edge_orientation[5] = edge_orientation0; new_tet0->cusp[0] = tet->cusp[v0]; new_tet0->cusp[1] = tet->cusp[v0]; new_tet0->cusp[2] = tet->cusp[v0]; new_tet0->cusp[3] = tet->cusp[v2]; new_tet1->cusp[0] = tet->cusp[v0]; new_tet1->cusp[1] = tet->cusp[v0]; new_tet1->cusp[2] = tet->cusp[v0]; new_tet1->cusp[3] = tet->cusp[v2]; /* * Install the triangular-pillow-with-tunnel. */ tet->neighbor[f] = new_tet0; tet->gluing[f] = CREATE_PERMUTATION(f, 2, v0, 0, v1, 1, v2, 3); new_tet0->neighbor[2] = tet; new_tet0->gluing[2] = inverse_permutation[tet->gluing[f]]; nbr_tet->neighbor[ff] = new_tet0; nbr_tet->gluing[ff] = CREATE_PERMUTATION(ff, 1, vv0, 0, vv1, 2, vv2, 3); new_tet0->neighbor[1] = nbr_tet; new_tet0->gluing[1] = inverse_permutation[nbr_tet->gluing[ff]]; /* * Typically creating_new_cusp is FALSE, meaning that we are * connecting a spherical boundary component to a torus or * Klein bottle boundary component, and we simply extend the * existing peripheral curves across the new tetrahedra. * * In the exceptional case that creating_new_cusp is TRUE, * meaning that the manifold has no real cusps and we are * connecting the "special fake cusp" to itself, we must * install a meridian and longitude, and set up the Dehn filling. */ if (creating_new_cusp == FALSE) { /* * Extend the peripheral curves across the boundary of the * triangular-pillow-with-tunnel. * * Note: The orientations of new_tet0 and new_tet1 match that * of tet, so the right_handed and left_handed sheets match up * in the obvious way. */ for (c = 0; c < 2; c++) /* c = M, L */ for (h = 0; h < 2; h++) /* h = right_handed, left_handed */ { num_strands = tet->curve[c][h][v0][f]; new_tet0->curve[c][h][0][2] = -num_strands; new_tet0->curve[c][h][0][1] = +num_strands; num_strands = tet->curve[c][h][v1][f]; new_tet0->curve[c][h][1][2] = -num_strands; new_tet0->curve[c][h][1][0] = +num_strands; new_tet1->curve[c][h][2][0] = -num_strands; new_tet1->curve[c][h][2][1] = +num_strands; new_tet1->curve[c][h][1][2] = -num_strands; new_tet1->curve[c][h][1][0] = +num_strands; new_tet0->curve[c][h][2][0] = -num_strands; new_tet0->curve[c][h][2][1] = +num_strands; num_strands = tet->curve[c][h][v2][f]; new_tet0->curve[c][h][3][2] = -num_strands; new_tet0->curve[c][h][3][1] = +num_strands; } } else /* creating_new_cusp == TRUE */ { /* * We have just installed a tube connecting the (unique) * spherical "cusp" to itself, to convert it to a torus or * Klein bottle. */ unique_cusp = tet->cusp[v0]->matching_cusp; unique_cusp->is_complete = TRUE; /* to be filled below */ unique_cusp->index = 0; unique_cusp->is_finite = FALSE; manifold->num_cusps = 1; /* * Install an arbitrary meridian and longitude. */ peripheral_curves(manifold); count_cusps(manifold); /* * Two sides of the (truncated) vertex 0 of new_tet0 * (namely the sides incident to faces 1 and 2 of new_tet0) * define the Dehn filling curve by which we can recover * the closed manifold. Count how many times the newly * installed meridian and longitude cross this Dehn filling curve. * To avoid messy questions about which sheet of the cusp's * double cover we're on, use two (parallel) copies of the * Dehn filling curve, one on each sheet of the cover. * Ultimately we're looking for a linear combination of the * meridian and longitude whose intersection number with * the Dehn filling curve is zero, so it won't matter if * we're off by a factor of two. */ for (c = 0; c < 2; c++) /* c = M, L */ { intersection_number[c] = 0; for (h = 0; h < 2; h++) /* h = right_handed, left_handed */ { intersection_number[c] += new_tet0->curve[c][h][0][1]; intersection_number[c] += new_tet0->curve[c][h][0][2]; } } /* * Use the intersection numbers to deduce * the desired Dehn filling coefficients. */ the_gcd = gcd(intersection_number[M], intersection_number[L]); unique_cusp->is_complete = FALSE; unique_cusp->m = -intersection_number[L] / the_gcd; unique_cusp->l = +intersection_number[M] / the_gcd; /* * Switch to a basis in which the Dehn filling curve is a meridian. */ unique_cusp->cusp_shape[initial] = Zero; /* force current_curve_basis() to ignore the cusp shape */ current_curve_basis(manifold, unique_cusp->index, basis_change[0]); if (change_peripheral_curves(manifold, basis_change) != func_OK) uFatalError("drill_tube", "finite_vertices"); } }
/* DJH */ void my_drill_tube( Triangulation *manifold, int singular_index ) { /* * Insert a triangular-pillow-with-tunnel (as described at the top * of this file) so as to connect the boundary component at one * end of the given edge to the boundary component at the other end. * The orientation on the triangular pillow will match the * orientation on tet, so that the orientation on the manifold * (if there is one) will be preserved. Edge orientations are also * respected. */ EdgeIndex e; VertexIndex v0, v1, v2, vv0, vv1, vv2; FaceIndex f, ff; Tetrahedron *nbr_tet, *tet, *tet0, *new_tet0, *new_tet1; Permutation gluing; EdgeClass *edge0, *edge1, *edge2, *edge, *new_edge, *edge3; Orientation edge_orientation0, edge_orientation1, edge_orientation2; PeripheralCurve c; Orientation h; int num_strands, i, intersection_number[2], the_gcd; Cusp *unique_cusp, *merged_cusp, *dead_cusp, *cusp; MatrixInt22 *basis_change = NULL; Boolean creating_new_cusp, same_cusp; int *cone_points, num_cone_points, dead_index; for( edge = manifold->edge_list_begin.next; edge!=&manifold->edge_list_end; edge = edge->next ) if (edge->is_singular) if (edge->singular_index == singular_index) break; if (edge == &manifold->edge_list_end) uFatalError("my_drill_tube", "finite_vertices"); tet = edge->incident_tet; e = edge->incident_edge_index; /* * Relative to the orientation of tet, the vertices v0, v1 and v2 * are arranged in counterclockwise order around the face f. */ v0 = one_vertex_at_edge[e]; v1 = other_vertex_at_edge[e]; if ( tet->cusp[v0] == tet->cusp[v1] && tet->cusp[v1]->num_cone_points ==2 /* if it's a $\S^2(n,n) orbifold then we are creating a torus cusp */ && tet->cusp[v1]->euler_characteristic==2) creating_new_cusp = TRUE; else creating_new_cusp = FALSE; v2 = remaining_face[v1][v0]; f = remaining_face[v0][v1]; /* * Note the matching face and its vertices. */ nbr_tet = tet->neighbor[f]; gluing = tet->gluing[f]; ff = EVALUATE(gluing, f); vv0 = EVALUATE(gluing, v0); vv1 = EVALUATE(gluing, v1); vv2 = EVALUATE(gluing, v2); /* * Note the incident EdgeClasses (which may or may not be distinct). */ edge0 = tet->edge_class[e]; edge1 = tet->edge_class[edge_between_vertices[v1][v2]]; edge2 = tet->edge_class[edge_between_vertices[v2][v0]]; /* * Construct the triangular-pillow-with-tunnel, as described * at the top of this file. */ new_tet0 = NEW_STRUCT(Tetrahedron); new_tet1 = NEW_STRUCT(Tetrahedron); initialize_tetrahedron(new_tet0); initialize_tetrahedron(new_tet1); INSERT_BEFORE(new_tet0, &manifold->tet_list_end); INSERT_BEFORE(new_tet1, &manifold->tet_list_end); manifold->num_tetrahedra += 2; new_edge = NEW_STRUCT(EdgeClass); initialize_edge_class(new_edge); INSERT_BEFORE(new_edge, &manifold->edge_list_end); new_tet0->neighbor[0] = new_tet1; new_tet0->neighbor[1] = NULL; /* assigned below */ new_tet0->neighbor[2] = NULL; /* assigned below */ new_tet0->neighbor[3] = new_tet1; new_tet1->neighbor[0] = new_tet0; new_tet1->neighbor[1] = new_tet1; new_tet1->neighbor[2] = new_tet1; new_tet1->neighbor[3] = new_tet0; new_tet0->gluing[0] = CREATE_PERMUTATION(0, 0, 1, 2, 2, 1, 3, 3); new_tet0->gluing[1] = 0x00; /* assigned below */ new_tet0->gluing[2] = 0x00; /* assigned below */ new_tet0->gluing[3] = CREATE_PERMUTATION(0, 1, 1, 0, 2, 2, 3, 3); new_tet1->gluing[0] = CREATE_PERMUTATION(0, 0, 1, 2, 2, 1, 3, 3); new_tet1->gluing[1] = CREATE_PERMUTATION(0, 0, 1, 2, 2, 1, 3, 3); new_tet1->gluing[2] = CREATE_PERMUTATION(0, 0, 1, 2, 2, 1, 3, 3); new_tet1->gluing[3] = CREATE_PERMUTATION(0, 1, 1, 0, 2, 2, 3, 3); new_tet0->edge_class[0] = edge1; new_tet0->edge_class[1] = edge1; new_tet0->edge_class[2] = edge0; new_tet0->edge_class[3] = edge2; new_tet0->edge_class[4] = edge0; new_tet0->edge_class[5] = edge0; new_tet1->edge_class[0] = edge1; new_tet1->edge_class[1] = edge1; new_tet1->edge_class[2] = edge0; new_tet1->edge_class[3] = new_edge; new_tet1->edge_class[4] = edge0; new_tet1->edge_class[5] = edge0; edge0->order += 6; edge1->order += 4; edge2->order += 1; new_edge->order = 1; new_edge->incident_tet = new_tet1; new_edge->incident_edge_index = 3; edge_orientation0 = tet->edge_orientation[e]; edge_orientation1 = tet->edge_orientation[edge_between_vertices[v1][v2]]; edge_orientation2 = tet->edge_orientation[edge_between_vertices[v2][v0]]; new_tet0->edge_orientation[0] = edge_orientation1; new_tet0->edge_orientation[1] = edge_orientation1; new_tet0->edge_orientation[2] = edge_orientation0; new_tet0->edge_orientation[3] = edge_orientation2; new_tet0->edge_orientation[4] = edge_orientation0; new_tet0->edge_orientation[5] = edge_orientation0; new_tet1->edge_orientation[0] = edge_orientation1; new_tet1->edge_orientation[1] = edge_orientation1; new_tet1->edge_orientation[2] = edge_orientation0; new_tet1->edge_orientation[3] = right_handed; new_tet1->edge_orientation[4] = edge_orientation0; new_tet1->edge_orientation[5] = edge_orientation0; new_tet0->cusp[0] = tet->cusp[v0]; new_tet0->cusp[1] = tet->cusp[v0]; new_tet0->cusp[2] = tet->cusp[v0]; new_tet0->cusp[3] = tet->cusp[v2]; new_tet1->cusp[0] = tet->cusp[v0]; new_tet1->cusp[1] = tet->cusp[v0]; new_tet1->cusp[2] = tet->cusp[v0]; new_tet1->cusp[3] = tet->cusp[v2]; /* * Install the triangular-pillow-with-tunnel. */ tet->neighbor[f] = new_tet0; tet->gluing[f] = CREATE_PERMUTATION(f, 2, v0, 0, v1, 1, v2, 3); new_tet0->neighbor[2] = tet; new_tet0->gluing[2] = inverse_permutation[tet->gluing[f]]; nbr_tet->neighbor[ff] = new_tet0; nbr_tet->gluing[ff] = CREATE_PERMUTATION(ff, 1, vv0, 0, vv1, 2, vv2, 3); new_tet0->neighbor[1] = nbr_tet; new_tet0->gluing[1] = inverse_permutation[nbr_tet->gluing[ff]]; for(c=0;c<2;c++) for(h=0;h<2;h++) { new_tet0->curve[c][h][3][2] = -nbr_tet->curve[c][h][v2][f]; new_tet0->curve[c][h][3][1] = -nbr_tet->curve[c][h][vv2][ff]; } /* * Typically creating_new_cusp is FALSE, meaning that we are * connecting a spherical boundary component to a torus or * Klein bottle boundary component, and we simply extend the * existing peripheral curves across the new tetrahedra. * * In the exceptional case that creating_new_cusp is TRUE, * meaning that the manifold has no real cusps and we are * connecting the "special fake cusp" to itself, we must * install a meridian and longitude, and set up the Dehn filling. */ if (creating_new_cusp == FALSE) { if (tet->cusp[v0]->index<tet->cusp[v1]->index) { merged_cusp = tet->cusp[v0]; dead_cusp = tet->cusp[v1]; } else { merged_cusp = tet->cusp[v1]; dead_cusp = tet->cusp[v0]; } if (merged_cusp==dead_cusp) same_cusp = TRUE; else same_cusp = FALSE; if (same_cusp) merged_cusp->euler_characteristic = merged_cusp->euler_characteristic - 2; else if (merged_cusp->euler_characteristic==2 || dead_cusp->euler_characteristic==2) merged_cusp->euler_characteristic = merged_cusp->euler_characteristic +dead_cusp->euler_characteristic - 2; else merged_cusp->euler_characteristic = merged_cusp->euler_characteristic +dead_cusp->euler_characteristic; merged_cusp->topology = unknown_topology; if (same_cusp) num_cone_points = merged_cusp->num_cone_points - 2; else num_cone_points = merged_cusp->num_cone_points + dead_cusp->num_cone_points -2; cone_points = NEW_ARRAY( num_cone_points, int ); num_cone_points = 0; for(i=0;i<merged_cusp->num_cone_points;i++) if (merged_cusp->cone_points[i]!=edge->singular_index) cone_points[num_cone_points++] = merged_cusp->cone_points[i]; my_free(merged_cusp->cone_points); if (!same_cusp) { dead_index = dead_cusp->index; /* fix cusp fields */ for( tet0 = manifold->tet_list_begin.next; tet0!=&manifold->tet_list_end; tet0 = tet0->next ) for( i = 0; i < 4; i++ ) if (tet0->cusp[i] == dead_cusp) tet0->cusp[i] = merged_cusp; for(i=0;i<dead_cusp->num_cone_points;i++) if (dead_cusp->cone_points[i]!=edge->singular_index) cone_points[num_cone_points++] = dead_cusp->cone_points[i]; my_free(dead_cusp->cone_points); REMOVE_NODE(dead_cusp); my_free(dead_cusp); } /* install new cone points */ merged_cusp->cone_points = cone_points; merged_cusp->num_cone_points = num_cone_points; for( cusp = manifold->cusp_list_begin.next; cusp!=&manifold->cusp_list_end; cusp = cusp->next ) { for (i=0;i < cusp->num_cone_points;i++) if (cusp->cone_points[i] > edge->singular_index) cusp->cone_points[i] = cusp->cone_points[i] - 1; if (!same_cusp && cusp->index > dead_index) cusp->index--; } for( edge3 = manifold->edge_list_begin.next; edge3!=&manifold->edge_list_end; edge3 = edge3->next ) if (edge3->is_singular && edge3->singular_index > edge->singular_index) edge3->singular_index--; edge->singular_index = -1; edge->is_singular = FALSE; edge->singular_order = 1; manifold->num_singular_arcs--; if (!same_cusp) { manifold->num_cusps--; manifold->num_or_cusps--; } } else /* creating_new_cusp == TRUE */ {
FuncResult compute_cusped_isometries( Triangulation *manifold0, Triangulation *manifold1, IsometryList **isometry_list, IsometryList **isometry_list_of_links) { Triangulation *copy_of_manifold0, *copy_of_manifold1; Isometry *partial_isometry_list, *new_isometry; Tetrahedron *tet0, *tet1; int i; /* * If manifold0 != manifold1 we are computing the isometries from one * manifold to another. We begin by making a copy of each manifold * and converting it to the canonical retriangulation of the * canonical cell decomposition. */ if (manifold0 != manifold1) { /* * Make copies of the manifolds. */ copy_triangulation(manifold0, ©_of_manifold0); copy_triangulation(manifold1, ©_of_manifold1); /* * Find the canonical triangulations of the copies. */ if (canonize(copy_of_manifold0) == func_failed || canonize(copy_of_manifold1) == func_failed) { free_triangulation(copy_of_manifold0); free_triangulation(copy_of_manifold1); *isometry_list = NULL; *isometry_list_of_links = NULL; return func_failed; } } /* * If manifold0 == manifold1 we are computing the symmetries from * a manifold to itself. In this case we find the canonical * retriangulation of the canonical cell decomposition before making * the second copy. This serves two purposes: * * (1) It reduces the run time, because we avoid a redundant call * to canonize(). * * (2) It insures that the Tetrahedra will be listed in the same * order in the two manifolds. This makes it easy for the * symmetry group program to recognize the identity symmetry. * (Perhaps you are curious as to how the Tetrahedra could * possibly fail to be listed in the same order. In rare * cases canonize() must do some random retriangulation. * If this is done to two identical copies of a Triangulation * the final canonical retriangulations will of course be * combinatorially the same, but the Tetrahedra might be listed * in different orders and numbered differently.) */ else { /* manifold0 == manifold1 */ /* * Make one copy of the manifold. */ copy_triangulation(manifold0, ©_of_manifold0); /* * Find the canonical retriangulation. */ if (canonize(copy_of_manifold0) == func_failed) { free_triangulation(copy_of_manifold0); *isometry_list = NULL; *isometry_list_of_links = NULL; return func_failed; } /* * Make a second copy of the canonical retriangulation. */ copy_triangulation(copy_of_manifold0, ©_of_manifold1); } /* * Allocate space for the IsometryList and initialize it. */ *isometry_list = NEW_STRUCT(IsometryList); (*isometry_list)->num_isometries = 0; (*isometry_list)->isometry = NULL; /* * If isometry_list_of_links is not NULL, allocate and * initialize *isometry_list_of_links as well. */ if (isometry_list_of_links != NULL) { *isometry_list_of_links = NEW_STRUCT(IsometryList); (*isometry_list_of_links)->num_isometries = 0; (*isometry_list_of_links)->isometry = NULL; } /* * If the two manifolds don't have the same number of * Tetrahedra, then there can't possibly be any isometries * between the two. We just initialized the IsometryList(s) * to be empty, so if there aren't any isometries, we're * ready free the copies of the manifolds and return. */ if (copy_of_manifold0->num_tetrahedra != copy_of_manifold1->num_tetrahedra) { free_triangulation(copy_of_manifold0); free_triangulation(copy_of_manifold1); return func_OK; } /* * partial_isometry_list will keep a linked list of the * Isometries we discover. When we're done we'll allocate * the array (*isometry_list)->isometry and copy the * addresses of the Isometries into it. For now, we * initialize partial_isometry_list to NULL to show that * the linked list is empty. */ partial_isometry_list = NULL; /* * Assign indices to the Tetrahedra in each manifold. */ number_the_tetrahedra(copy_of_manifold0); number_the_tetrahedra(copy_of_manifold1); /* * Try mapping an arbitrary but fixed Tetrahedron of * manifold0 ("tet0") to each Tetrahedron of manifold1 * in turn, with each possible Permutation. See which * of these maps extends to a global isometry. We're * guaranteed to find all possible isometries this way * (and typically quite a lot of other garbage as well). */ /* * Let tet0 be the first Tetrahedron on manifold0's list. */ tet0 = copy_of_manifold0->tet_list_begin.next; /* * Consider each Tetrahedron in manifold1. */ for (tet1 = copy_of_manifold1->tet_list_begin.next; tet1 != ©_of_manifold1->tet_list_end; tet1 = tet1->next) /* * Consider each of the 24 possible ways to map tet0 to tet1. */ for (i = 0; i < 24; i++) /* * Does mapping tet0 to tet1 via permutation_by_index[i] * define an isometry? */ if (attempt_isometry(copy_of_manifold0, tet0, tet1, permutation_by_index[i], NULL ) == func_OK) { /* * Copy the isometry to an Isometry data structure . . . */ copy_isometry(copy_of_manifold0, copy_of_manifold1, &new_isometry); /* * . . . add it to the partial_isometry_list . . . */ new_isometry->next = partial_isometry_list; partial_isometry_list = new_isometry; /* * . . . and increment the count. */ (*isometry_list)->num_isometries++; } /* * If some Isometries were found, allocate space for the * array (*isometry_list)->isometry and write the addresses * of the Isometries into it. */ make_isometry_array(*isometry_list, partial_isometry_list); /* * If isometry_list_of_links is not NULL, make a copy of * those Isometries which extend to the associated link * (i.e. those which take meridians to meridians). */ find_isometries_which_extend(*isometry_list, isometry_list_of_links); /* * Discard the copies of the manifolds. */ free_triangulation(copy_of_manifold0); free_triangulation(copy_of_manifold1); return func_OK; }
static Triangulation *try_Dirichlet_to_triangulation( WEPolyhedron *polyhedron) { /* * Implement Plan A as described above. */ Triangulation *triangulation; WEEdge *edge, *nbr_edge, *mate_edge; WEEdgeEnd end; WEEdgeSide side; Tetrahedron *new_tet; FaceIndex f; /* * Don't attempt to triangulate an orbifold. */ if (singular_set_is_empty(polyhedron) == FALSE) return NULL; /* * Set up the Triangulation. */ triangulation = NEW_STRUCT(Triangulation); initialize_triangulation(triangulation); /* * Allocate and copy the name. */ triangulation->name = NEW_ARRAY(strlen(DEFAULT_NAME) + 1, char); strcpy(triangulation->name, DEFAULT_NAME); /* * Allocate the Tetrahedra. */ triangulation->num_tetrahedra = 4 * polyhedron->num_edges; for (edge = polyhedron->edge_list_begin.next; edge != &polyhedron->edge_list_end; edge = edge->next) for (end = 0; end < 2; end++) /* = tail, tip */ for (side = 0; side < 2; side++) /* = left, right */ { new_tet = NEW_STRUCT(Tetrahedron); initialize_tetrahedron(new_tet); INSERT_BEFORE(new_tet, &triangulation->tet_list_end); edge->tet[end][side] = new_tet; } /* * Initialize neighbors. */ for (edge = polyhedron->edge_list_begin.next; edge != &polyhedron->edge_list_end; edge = edge->next) for (end = 0; end < 2; end++) /* = tail, tip */ for (side = 0; side < 2; side++) /* = left, right */ { /* * Neighbor[0] is associated to this same WEEdge. * It lies on the same side (left or right), but * at the opposite end (tail or tip). */ edge->tet[end][side]->neighbor[0] = edge->tet[!end][side]; /* * Neighbor[1] lies on the same face of the Dirichlet * domain, but at the "next side" of that face. */ nbr_edge = edge->e[end][side]; if (nbr_edge->v[!end] == edge->v[end]) /* edge and nbr_edge point in the same direction */ edge->tet[end][side]->neighbor[1] = nbr_edge->tet[!end][side]; else if (nbr_edge->v[end] == edge->v[end]) /* edge and nbr_edge point in opposite directions */ edge->tet[end][side]->neighbor[1] = nbr_edge->tet[end][!side]; else uFatalError("Dirichlet_to_triangulation", "Dirichlet_conversion"); /* * Neighbor[2] is associated to this same WEEdge. * It lies at the same end (tail or tip), but * on the opposite side (left or right). */ edge->tet[end][side]->neighbor[2] = edge->tet[end][!side]; /* * Neighbor[3] lies on this face's "mate" elsewhere * on the Dirichlet domain. */ mate_edge = edge->neighbor[side]; edge->tet[end][side]->neighbor[3] = mate_edge->tet [edge->preserves_direction[side] ? end : !end ] [edge->preserves_sides[side] ? side : !side]; } /* * Initialize all gluings to the identity. */ for (edge = polyhedron->edge_list_begin.next; edge != &polyhedron->edge_list_end; edge = edge->next) for (end = 0; end < 2; end++) /* = tail, tip */ for (side = 0; side < 2; side++) /* = left, right */ for (f = 0; f < 4; f++) edge->tet[end][side]->gluing[f] = IDENTITY_PERMUTATION; /* * Set up the EdgeClasses. */ create_edge_classes(triangulation); orient_edge_classes(triangulation); /* * Attempt to orient the manifold. */ orient(triangulation); /* * Set up the Cusps, including "fake cusps" for the finite vertices. * Then locate and remove the fake cusps. If the manifold is closed, * drill out an arbitrary curve to express it as a Dehn filling. * Finally, determine the topology of each cusp (torus or Klein bottle) * and count them. */ create_cusps(triangulation); mark_fake_cusps(triangulation); peripheral_curves(triangulation); remove_finite_vertices(triangulation); count_cusps(triangulation); /* * Try to compute a hyperbolic structure, first for the unfilled * manifold, and then for the closed manifold if appropriate. */ find_complete_hyperbolic_structure(triangulation); do_Dehn_filling(triangulation); /* * If the manifold is hyperbolic, install a shortest basis on each cusp. */ if ( triangulation->solution_type[complete] == geometric_solution || triangulation->solution_type[complete] == nongeometric_solution) install_shortest_bases(triangulation); /* * All done! */ return triangulation; }
static void find_isometries_which_extend( IsometryList *isometry_list, IsometryList **isometry_list_of_links) { Isometry *original, *copy; int i, j, k, l, count; /* * If the isometry_list_of_links isn't needed, don't compute it. */ if (isometry_list_of_links == NULL) return; /* * The function compute_cusped_isometries() (which calls this function) * has already allocated space for the new IsometryList. * (It has also intialized the num_isometries and isometry fields, * but we reinitialize them here just for good form.) */ /* * How many Isometries extend to the link? */ (*isometry_list_of_links)->num_isometries = 0; /* intentionally redundant */ for (i = 0; i < isometry_list->num_isometries; i++) if (isometry_list->isometry[i]->extends_to_link == TRUE) (*isometry_list_of_links)->num_isometries++; /* * If there are no Isometries which extend, set * (*isometry_list_of_links)->isometry to NULL and return. */ if ((*isometry_list_of_links)->num_isometries == 0) { (*isometry_list_of_links)->isometry = NULL; /* intentionally redundant */ return; } /* * Allocate space for the Isometries which extend to * Isometries of the associated links, and copy them in. */ (*isometry_list_of_links)->isometry = NEW_ARRAY((*isometry_list_of_links)->num_isometries, Isometry *); for (i = 0, count = 0; i < isometry_list->num_isometries; i++) if (isometry_list->isometry[i]->extends_to_link == TRUE) { (*isometry_list_of_links)->isometry[count] = NEW_STRUCT(Isometry); original = isometry_list->isometry[i]; copy = (*isometry_list_of_links)->isometry[count]; copy->num_tetrahedra = original->num_tetrahedra; copy->num_cusps = original->num_cusps; copy->num_singular_arcs = original->num_singular_arcs; copy->tet_image = NEW_ARRAY(copy->num_tetrahedra, int); copy->tet_map = NEW_ARRAY(copy->num_tetrahedra, Permutation); for (j = 0; j < copy->num_tetrahedra; j++) { copy->tet_image[j] = original->tet_image[j]; copy->tet_map [j] = original->tet_map [j]; } copy->cusp_image = NEW_ARRAY(copy->num_cusps, int); copy->cusp_map = NEW_ARRAY(copy->num_cusps, MatrixInt22); for (j = 0; j < copy->num_cusps; j++) { copy->cusp_image[j] = original->cusp_image[j]; for (k = 0; k < 2; k++) for (l = 0; l < 2; l++) copy->cusp_map[j][k][l] = original->cusp_map[j][k][l]; } copy->singular_image = NEW_ARRAY(copy->num_singular_arcs, int); for (j=0;j<copy->num_singular_arcs;j++) copy->singular_image[j] = original->singular_image[j]; copy->extends_to_link = original->extends_to_link; count++; }
RepresentationList *find_representations( Triangulation *manifold, int n, PermutationSubgroup range) { RepresentationList *representation_list; int i,j, n_factorial, range_size, num_simplified_generators, num_simplified_relations, num_original_generators, **simplified_group_relations, **original_generators, **meridians, **longitudes, digit, **Sn, *representation_by_index, **candidateSn, *candidateZn; GroupPresentation *simplified_group; RepresentationIntoSn *new_representation; /* * Begin with a quick error check */ if (manifold == NULL ) uFatalError("find_representations","representations"); /* * Make sure the manifold has a set of generators. */ new_choose_generators(manifold, FALSE); /* * Allocate the RepresentationList. */ representation_list = NEW_STRUCT(RepresentationList); representation_list->num_generators = manifold->num_generators; representation_list->num_sheets = n; representation_list->num_cusps = manifold->num_cusps; representation_list->list = NULL; /* * The cusps must be unfilled or have integer Dehn filling * coefficients (non relatively prime integers are OK -- they * define orbifolds). Otherwise we can't define a representation * into S(n) in any meaningful way, so we return an empty list. */ if (all_Dehn_coefficients_are_integers(manifold) == FALSE) return representation_list; /* * If n is less than 1, return an empty list. */ if (n < 1) return representation_list; /* * Get a simplified presentation for the fundamental group. * Use minimize_number_of_generators == TRUE, because the number * of (potential) representations is an exponential function * of the number of generators. At the end we'll convert * the final representations to the standard generators defined in * choose_generators(). * * 97/4/7 If the group is trivial, return an empty list. */ simplified_group = fundamental_group(manifold, TRUE, TRUE, TRUE); num_simplified_generators = fg_get_num_generators(simplified_group); if (num_simplified_generators == 0) { free_group_presentation(simplified_group); return representation_list; } num_simplified_relations = fg_get_num_relations(simplified_group); simplified_group_relations = NEW_ARRAY(num_simplified_relations, int *); for (i = 0, j = 0; i < fg_get_num_relations(simplified_group); i++) { simplified_group_relations[j] = fg_get_relation(simplified_group, i); j++; } num_original_generators = manifold->num_generators; original_generators = NEW_ARRAY(num_original_generators, int *); for (i = 0; i < num_original_generators; i++) original_generators[i] = fg_get_original_generator(simplified_group, i); free_group_presentation(simplified_group); /* * If the range is all of S(n), it will be convenient to precompute * an array containing all its elements. */ if (range == permutation_subgroup_Sn) { n_factorial = factorial(n); Sn = compute_Sn(n); } else { n_factorial = 0; Sn = NULL; } /* * If the range is all of S(n), then each "candidate" representation * in the loop below will be expressed as an array of pointers * to rows of the array Sn, one pointer for each generator. */ if (range == permutation_subgroup_Sn) candidateSn = NEW_ARRAY(num_simplified_generators, int *); else