Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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);
}
Пример #4
0
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];
}
Пример #5
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;
}
Пример #6
0
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;
}
Пример #7
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;
}
Пример #8
0
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;
}
Пример #9
0
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;
}
Пример #10
0
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;
}
Пример #11
0
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);
}
Пример #12
0
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;
}
Пример #13
0
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;
}
Пример #14
0
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);
}
Пример #15
0
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++;

            }
        }
}
Пример #16
0
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;
}
Пример #17
0
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);
		}
	}
Пример #18
0
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");
	}
}
Пример #19
0
/* 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 */
	{
Пример #20
0
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, &copy_of_manifold0);
		copy_triangulation(manifold1, &copy_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, &copy_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, &copy_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 != &copy_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;
}
Пример #21
0
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;
}
Пример #22
0
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++;
		}
Пример #23
0
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