static const char *genimg_get_short_name(const table_entry_t *table, int val) { table = get_table_entry(table, val); if (!table) return "unknown"; #if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC) return table->sname; #else return table->sname + gd->reloc_off; #endif }
/** * get_table_entry_name - translate entry id to long name * @table: pointer to a translation table for entries of a specific type * @msg: message to be returned when translation fails * @id: entry id to be translated * * get_table_entry_name() will go over translation table trying to find * entry that matches given id. If matching entry is found, its long * name is returned to the caller. * * returns: * long entry name if translation succeeds * msg otherwise */ char *get_table_entry_name(const table_entry_t *table, char *msg, int id) { table = get_table_entry(table, id); if (!table) return msg; #if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC) return table->lname; #else return table->lname + gd->reloc_off; #endif }
/** * get_cat_table_entry_short_name - translate entry id to short name * @category: category to look up (enum ih_category) * @id: entry id to be translated * * This will scan the translation table trying to find the entry that matches * the given id. * * @retur short entry name if translation succeeds; error string on failure */ const char *genimg_get_cat_short_name(enum ih_category category, uint id) { const table_entry_t *entry; entry = get_table_entry(table_info[category].table, id); if (!entry) return unknown_msg(category); #if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC) return entry->sname; #else return entry->sname + gd->reloc_off; #endif }
const char *genimg_get_type_short_name(uint8_t type) { const table_entry_t *table; table = get_table_entry(uimage_type, type); if (!table) return "unknown"; #if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC) return table->sname; #else return table->sname + gd->reloc_off; #endif }
void get_or_create_table_entry(HSQUIRRELVM vm, const std::string& name) { sq_pushstring(vm, name.c_str(), -1); if(SQ_FAILED(sq_get(vm, -2))) { sq_pushstring(vm, name.c_str(), -1); sq_newtable(vm); if(SQ_FAILED(sq_createslot(vm, -3))) { std::ostringstream msg; msg << "failed to create '" << name << "' table entry"; throw scripting::SquirrelError(vm, msg.str()); } else { get_table_entry(vm, name); } } else { // successfully placed result on stack } }
void qs_filter_relations(sieve_conf_t *conf) { /* Perform all of the postprocessing on the list of relations from the sieving phase. There are two main jobs, reading in all the relations that will be used and then determining the list of cycles in which partial relations appear. Care should be taken to avoid wasting huge amounts of memory */ msieve_obj *obj = conf->obj; uint32 *hashtable = conf->cycle_hashtable; cycle_t *table = conf->cycle_table; uint32 num_poly_factors = conf->num_poly_factors; uint32 num_derived_poly = 1 << (num_poly_factors - 1); uint32 *final_poly_index; uint32 num_relations, num_cycles, num_poly; la_col_t *cycle_list; relation_t *relation_list; uint32 i, passes, start; uint32 curr_a_idx, curr_poly_idx, curr_rel; uint32 curr_expected, curr_saved, curr_cycle; uint32 total_poly_a; uint32 poly_saved; uint32 cycle_bins[NUM_CYCLE_BINS+1] = {0}; char buf[LINE_BUF_SIZE]; /* Rather than reading all the relations in and then removing singletons, read only the large primes of each relation into an initial list, remove the singletons, and then only read in the relations that survive. This avoids reading in useless relations (and usually the polynomials they would need) */ savefile_open(&obj->savefile, SAVEFILE_READ); relation_list = (relation_t *)xmalloc(10000 * sizeof(relation_t)); curr_rel = 10000; i = 0; total_poly_a = 0; /* skip over the first line */ savefile_read_line(buf, sizeof(buf), &obj->savefile); while (!savefile_eof(&obj->savefile)) { char *start; switch (buf[0]) { case 'A': total_poly_a++; break; case 'R': start = strchr(buf, 'L'); if (start != NULL) { uint32 prime1, prime2; read_large_primes(start, &prime1, &prime2); if (i == curr_rel) { curr_rel = 3 * curr_rel / 2; relation_list = (relation_t *)xrealloc( relation_list, curr_rel * sizeof(relation_t)); } relation_list[i].poly_idx = i; relation_list[i].large_prime[0] = prime1; relation_list[i].large_prime[1] = prime2; i++; } break; } savefile_read_line(buf, sizeof(buf), &obj->savefile); } num_relations = i; num_relations = purge_singletons(obj, relation_list, num_relations, table, hashtable); relation_list = (relation_t *)xrealloc(relation_list, num_relations * sizeof(relation_t)); /* Now we know how many relations to expect. Also initialize the lists of polynomial 'a' and 'b' values */ num_poly = 10000; conf->poly_list = (poly_t *)xmalloc(num_poly * sizeof(poly_t)); conf->poly_a_list = (mp_t *)xmalloc(total_poly_a * sizeof(mp_t)); final_poly_index = (uint32 *)xmalloc(num_derived_poly * sizeof(uint32)); /* initialize the running counts of relations and polynomials */ i = 0; curr_expected = 0; curr_saved = 0; curr_rel = (uint32)(-1); curr_poly_idx = (uint32)(-1); curr_a_idx = (uint32)(-1); poly_saved = 0; logprintf(obj, "attempting to read %u relations\n", num_relations); /* Read in the relations and the polynomials they use at the same time. */ savefile_rewind(&obj->savefile); while (curr_expected < num_relations) { char *tmp; relation_t *r; /* read in the next entity */ if (savefile_eof(&obj->savefile)) break; savefile_read_line(buf, sizeof(buf), &obj->savefile); switch (buf[0]) { case 'A': /* Read in a new 'a' value */ curr_a_idx++; read_poly_a(conf, buf); mp_copy(&conf->curr_a, conf->poly_a_list+curr_a_idx); /* build all of the 'b' values associated with it */ build_derived_poly(conf); /* all 'b' values start off unused */ memset(final_poly_index, -1, num_derived_poly * sizeof(uint32)); break; case 'R': /* handle a new relation. First find the large primes; these will determine if a relation is full or partial */ tmp = strchr(buf, 'L'); if (tmp == NULL) break; /* Check if this relation is needed. If it survived singleton removal then its ordinal ID will be in the next entry of relation_list. First move up the index of relation_list until the relation index to check is >= the one we have (it may have gotten behind because relations were corrupted) */ curr_rel++; while (curr_expected < num_relations && relation_list[curr_expected].poly_idx < curr_rel) { curr_expected++; } /* now check if the relation should be saved */ if (curr_expected >= num_relations || relation_list[curr_expected].poly_idx != curr_rel) break; curr_expected++; /* convert the ASCII text of the relation to a relation_t, verifying correctness in the process */ r = relation_list + curr_saved; if (read_relation(conf, buf, r) != 0) { logprintf(obj, "failed to read relation %d\n", curr_expected - 1); break; } curr_saved++; /* if necessary, save the b value corresponding to this relation */ if (final_poly_index[r->poly_idx] == (uint32)(-1)) { if (i == num_poly) { num_poly *= 2; conf->poly_list = (poly_t *)xrealloc( conf->poly_list, num_poly * sizeof(poly_t)); } conf->poly_list[i].a_idx = curr_a_idx; signed_mp_copy(&(conf->curr_b[r->poly_idx]), &(conf->poly_list[i].b)); final_poly_index[r->poly_idx] = i; r->poly_idx = i++; } else { r->poly_idx = final_poly_index[r->poly_idx]; } break; /* done with this relation */ } } /* update the structures with the counts of relations and polynomials actually recovered */ num_relations = curr_saved; logprintf(obj, "recovered %u relations\n", num_relations); logprintf(obj, "recovered %u polynomials\n", i); savefile_close(&obj->savefile); free(final_poly_index); conf->poly_list = (poly_t *)xrealloc(conf->poly_list, i * sizeof(poly_t)); /* begin the cycle generation process by purging duplicate relations. For the sake of consistency, always rebuild the graph afterwards */ num_relations = purge_duplicate_relations(obj, relation_list, num_relations); memset(hashtable, 0, sizeof(uint32) << LOG2_CYCLE_HASH); conf->vertices = 0; conf->components = 0; conf->cycle_table_size = 1; for (i = 0; i < num_relations; i++) { relation_t *r = relation_list + i; if (r->large_prime[0] != r->large_prime[1]) { add_to_cycles(conf, r->large_prime[0], r->large_prime[1]); } } /* compute the number of cycles to expect. Note that this number includes cycles from both full and partial relations (the cycle for a full relation is trivial) */ num_cycles = num_relations + conf->components - conf->vertices; /* The idea behind the cycle-finding code is this: the graph is composed of a bunch of connected components, and each component contains one or more cycles. To find the cycles, you build the 'spanning tree' for each component. Think of the spanning tree as a binary tree; there are no cycles in it because leaves are only connected to a common root and not to each other. Any time you connect together two leaves of the tree, though, a cycle is formed. So, for a spanning tree like this: 1 o / \ 2 o o 3 / \ \ o o o 4 5 6 if you connect leaves 4 and 5 you get a cycle (4-2-5). If you connect leaves 4 and 6 you get another cycle (4-2-1-3-6) that will reuse two of the nodes in the first cycle. It's this reuse that makes double large primes so powerful. For our purposes, every edge in the tree above represents a partial relation. Every edge that would create a cycle comes from another partial relation. So to find all the cycles, you begin with the roots of all of the connected components, and then iterate through the list of partial relations until all have been 'processed'. A partial relation is considered processed when one or both of its primes is in the tree. If one prime is present then the relation gets added to the tree; if both primes are present then the relation creates one cycle but is *not* added to the tree. It's really great to see such simple ideas do something so complicated as finding cycles (and doing it very quickly) */ /* First traverse the entire graph and remove any vertices that are not the roots of connected components (i.e. remove any primes whose cycle_t entry does not point to itself */ for (i = 0; i < (1 << LOG2_CYCLE_HASH); i++) { uint32 offset = hashtable[i]; while (offset != 0) { cycle_t *entry = table + offset; if (offset != entry->data) entry->data = 0; offset = entry->next; } } logprintf(obj, "attempting to build %u cycles\n", num_cycles); cycle_list = (la_col_t *)xmalloc(num_cycles * sizeof(la_col_t)); /* keep going until either all cycles are found, all relations are processed, or cycles stop arriving. Normally these conditions all occur at the same time */ for (start = passes = curr_cycle = 0; start < num_relations && curr_cycle < num_cycles; passes++) { /* The list of relations up to index 'start' is con- sidered processed. For all relations past that... */ uint32 start_cycles = curr_cycle; for (i = start; i < num_relations && curr_cycle < num_cycles; i++) { cycle_t *entry1, *entry2; relation_t rtmp = relation_list[i]; if (rtmp.large_prime[0] == rtmp.large_prime[1]) { /* this is a full relation, and forms a cycle just by itself. Move it to position 'start' of the relation list and increment 'start'. The relation is now frozen at that position */ la_col_t *c = cycle_list + curr_cycle++; relation_list[i] = relation_list[start]; relation_list[start] = rtmp; /* build a trivial cycle for the relation */ c->cycle.num_relations = 1; c->cycle.list = (uint32 *) xmalloc(sizeof(uint32)); c->cycle.list[0] = start++; continue; } /* retrieve the cycle_t entries associated with the large primes in relation r. */ entry1 = get_table_entry(table, hashtable, rtmp.large_prime[0], 0); entry2 = get_table_entry(table, hashtable, rtmp.large_prime[1], 0); /* if both vertices do not point to other vertices, then neither prime has been added to the graph yet, and r must remain unprocessed */ if (entry1->data == 0 && entry2->data == 0) continue; /* if one or the other prime is part of the graph, add r to the graph. The vertex not in the graph points to the vertex that is, and this entry also points to the relation that is associated with rtmp. If both primes are in the graph, recover the cycle this generates */ if (entry1->data == 0) { entry1->data = entry2 - table; entry1->count = start; } else if (entry2->data == 0) { entry2->data = entry1 - table; entry2->count = start; } else { la_col_t *c = cycle_list + curr_cycle; c->cycle.list = NULL; enumerate_cycle(obj, c, table, entry1, entry2, start); if (c->cycle.list) curr_cycle++; } /* whatever happened above, the relation is processed now; move it to position 'start' of the relation list and increment 'start'. The relation is now frozen at that position */ relation_list[i] = relation_list[start]; relation_list[start++] = rtmp; } /* If this pass did not find any new cycles, then we've reached steady state and are finished */ if (curr_cycle == start_cycles) break; } num_cycles = curr_cycle; logprintf(obj, "found %u cycles in %u passes\n", num_cycles, passes); /* sort the list of cycles so that the cycles with the largest number of relations will come last. If the linear algebra code skips any cycles it can easily skip the most dense cycles */ qsort(cycle_list, (size_t)num_cycles, sizeof(la_col_t), sort_cycles); conf->relation_list = relation_list; conf->num_relations = num_relations; conf->cycle_list = cycle_list; conf->num_cycles = num_cycles; /* print out a histogram of cycle lengths for infor- mational purposes */ for (i = 0; i < num_cycles; i++) { num_relations = cycle_list[i].cycle.num_relations; if (num_relations >= NUM_CYCLE_BINS) cycle_bins[NUM_CYCLE_BINS]++; else cycle_bins[num_relations - 1]++; } logprintf(obj, "distribution of cycle lengths:\n"); for (i = 0; i < NUM_CYCLE_BINS; i++) { if (cycle_bins[i]) { logprintf(obj, " length %d : %d\n", i + 1, cycle_bins[i]); } } if (cycle_bins[i]) logprintf(obj, " length %u+: %u\n", i + 1, cycle_bins[i]); logprintf(obj, "largest cycle: %u relations\n", cycle_list[num_cycles-1].cycle.num_relations); }
/*--------------------------------------------------------------------*/ static uint32 purge_singletons(msieve_obj *obj, relation_t *list, uint32 num_relations, cycle_t *table, uint32 *hashtable) { /* given a list of relations and the graph from the sieving stage, remove any relation that contains a prime that only occurs once in the graph. Because removing a relation removes a second prime as well, this process must be iterated until no more relations are removed */ uint32 num_left; uint32 i, j, k; uint32 passes = 0; logprintf(obj, "begin with %u relations\n", num_relations); do { num_left = num_relations; /* for each relation */ for (i = j = 0; i < num_relations; i++) { relation_t *r = list + i; uint32 prime; cycle_t *entry; /* full relations always survive */ if (r->large_prime[0] == r->large_prime[1]) { list[j++] = list[i]; continue; } /* for each prime in that relation */ for (k = 0; k < 2; k++) { prime = r->large_prime[k]; entry = get_table_entry(table, hashtable, prime, 0); /* if the relation is due to be removed, decrement the count of its other primes in the graph. The following is specialized for two primes */ if (entry->count < 2) { prime = r->large_prime[k ^ 1]; entry = get_table_entry(table, hashtable, prime, 0); entry->count--; break; } } if (k == 2) list[j++] = list[i]; } num_relations = j; passes++; } while (num_left != num_relations); logprintf(obj, "reduce to %u relations in %u passes\n", num_left, passes); return num_left; }
/*--------------------------------------------------------------------*/ static uint32 add_to_hashtable(cycle_t *table, uint32 *hashtable, uint32 prime1, uint32 prime2, uint32 default_table_entry, uint32 *components, uint32 *vertices) { /* update the list of cycles to reflect the presence of a partial relation with large primes 'prime1' and 'prime2'. There are three quantities to track, the number of edges, components and vertices. The number of cycles in the graph is then e + c - v. There is one edge for each partial relation, and one vertex for each prime that appears in the graph (these are easy to count). A connected component is a group of primes that are all reachable from each other via edges in the graph. All of the vertices that are in a cycle must belong to the same connected component. Think of a component as a tree of vertices; one prime is chosen arbitrarily as the 'root' of that tree. The number of new primes added to the graph (0, 1, or 2) is returned */ uint32 root[2]; uint32 root1, root2; uint32 i; uint32 num_new_entries = 0; /* for each prime */ for (i = 0; i < 2; i++) { uint32 prime = ((i == 0) ? prime1 : prime2); uint32 offset; cycle_t *entry; /* retrieve the cycle_t corresponding to that prime from the graph (or allocate a new one) */ entry = get_table_entry(table, hashtable, prime, default_table_entry); entry->count++; if (entry->data == 0) { /* if this prime has not occurred in the graph before, increment the number of vertices and the number of components, then make the table entry point to itself. */ num_new_entries++; default_table_entry++; offset = entry - table; entry->data = offset; (*components)++; (*vertices)++; } else { /* the prime is already in the table, which means we can follow a linked list of pointers to other primes until we reach a cycle_t that points to itself. This last cycle_t is the 'root' of the connected component that contains 'prime'. Save its value */ cycle_t *first_entry, *next_entry; first_entry = entry; next_entry = table + entry->data; while (entry != next_entry) { entry = next_entry; next_entry = table + next_entry->data; } /* Also perform path compression: now that we know the value of the root for this prime, make all of the pointers in the primes we visited along the way point back to this root. This will speed up future root lookups */ offset = entry->data; entry = first_entry; next_entry = table + entry->data; while (entry != next_entry) { entry->data = offset; entry = next_entry; next_entry = table + next_entry->data; } } root[i] = offset; } /* If the roots for prime1 and prime2 are different, then they lie within separate connected components. We're about to connect this edge to one of these components, and the presence of the other prime means that these two components are about to be merged together. Hence the total number of components in the graph goes down by one. */ root1 = root[0]; root2 = root[1]; if (root1 != root2) (*components)--; /* This partial relation represents an edge in the graph; we have to attach this edge to one or the other of the connected components. Attach it to the component whose representative prime is smallest; since small primes are more common, this will give the smaller root more edges, and will potentially increase the number of cycles the graph contains */ if (table[root1].prime < table[root2].prime) table[root2].data = root1; else table[root1].data = root2; return num_new_entries; }