double qsearch_fulltree_sum_distance_org(FullTree *tree, int a, int b) { FullNode *map = get_nodes(tree); int branch2b = map[a].node_branch[b]; int branch2a = map[b].node_branch[a]; return npairs( map[a].leaf_count[branch2b] ) * map[a].dist[branch2b] + npairs( map[b].leaf_count[branch2a] ) * map[b].dist[branch2a]; }
static void set_score(FullTree *tree) { // calculate the score tree->raw_score = 0; FullNode *map = get_nodes(tree); int i; for (i = (tree->node_count + 2)/2; i < tree->node_count; ++i) { tree->raw_score += npairs(map[i].leaf_count[0]) * map[i].dist[0]; tree->raw_score += npairs(map[i].leaf_count[1]) * map[i].dist[1]; tree->raw_score += npairs(map[i].leaf_count[2]) * map[i].dist[2]; } }
int dict_find(const ref * pdref, const ref * pkey, ref ** ppvalue) { dict *pdict = pdref->value.pdict; int code = real_dict_find(pdref, pkey, ppvalue); stats_dict.lookups++; if (r_has_type(pkey, t_name) && dict_is_packed(pdict)) { uint nidx = name_index(dict_mem(pdict), pkey); uint hash = dict_hash_mod(dict_name_index_hash(nidx), npairs(pdict)) + 1; if (pdict->keys.value.packed[hash] == pt_tag(pt_literal_name) + nidx ) stats_dict.probe1++; else if (pdict->keys.value.packed[hash - 1] == pt_tag(pt_literal_name) + nidx ) stats_dict.probe2++; } /* Do the cheap flag test before the expensive remainder test. */ if (gs_debug_c('d') && !(stats_dict.lookups % 1000)) dlprintf3("[d]lookups=%ld probe1=%ld probe2=%ld\n", stats_dict.lookups, stats_dict.probe1, stats_dict.probe2); return code; }
ref * dstack_find_name_by_index(dict_stack_t * pds, uint nidx) { ref *pvalue = real_dstack_find_name_by_index(pds, nidx); dict *pdict = pds->stack.p->value.pdict; INCR(lookups); if (dict_is_packed(pdict)) { uint hash = dict_hash_mod(dict_name_index_hash(nidx), npairs(pdict)) + 1; if (pdict->keys.value.packed[hash] == pt_tag(pt_literal_name) + nidx ) INCR(probes[0]); else if (pdict->keys.value.packed[hash - 1] == pt_tag(pt_literal_name) + nidx ) INCR(probes[1]); } if (gs_debug_c('d') && !(stats_dstack.lookups % 1000)) dlprintf3("[d]lookups=%ld probe1=%ld probe2=%ld\n", stats_dstack.lookups, stats_dstack.probes[0], stats_dstack.probes[1]); return pvalue; }
double qsearch_fulltree_sum_distance(FullTree *tree, int a, int b) { FullNode *map = get_nodes(tree); double sum = 0.0; int node = map[a].connections[ map[a].node_branch[b] ]; int n = 0; while (node != b) { int toa = map[node].node_branch[a]; int tob = map[node].node_branch[b]; sum += npairs( map[node].leaf_count[ toa ] ) * map[node].dist[toa]; sum += npairs( map[node].leaf_count[ tob ] ) * map[node].dist[tob]; n++; node = map[node].connections[ tob ]; } return sum / n; }
/* Grow a dictionary for dict_put. */ int dict_grow(ref * pdref, dict_stack_t *pds) { dict *pdict = pdref->value.pdict; /* We might have maxlength < npairs, if */ /* dict_round_size increased the size. */ ulong new_size = (ulong) d_maxlength(pdict); /* Adobe does this */ if (new_size < 20) new_size += 10; else if (new_size < 200) new_size *= 2; else new_size += new_size / 2; #if ARCH_SIZEOF_INT < ARCH_SIZEOF_LONG if (new_size > max_uint) new_size = max_uint; #endif if (new_size > npairs(pdict)) { int code = dict_resize(pdref, (uint) new_size, pds); if (code >= 0) return code; /* new_size was too big. */ if (npairs(pdict) < dict_max_size) { code = dict_resize(pdref, dict_max_size, pds); if (code >= 0) return code; } if (npairs(pdict) == d_maxlength(pdict)) { /* Can't do it. */ return code; } /* We can't grow to new_size, but we can grow to npairs. */ new_size = npairs(pdict); } /* maxlength < npairs, we can grow in place */ ref_save_in(dict_memory(pdict), pdref, &pdict->maxlength, "dict_put(maxlength)"); d_set_maxlength(pdict, new_size); return 0; }
/* Return the maximum index of a slot within a dictionary. */ uint dict_max_index(const ref * pdref /* t_dictionary */ ) { return npairs(pdref->value.pdict) - 1; }
/* * Look up a key in a dictionary. Store a pointer to the value slot * where found, or to the (value) slot for inserting. * See idict.h for the possible return values. */ int dict_find(const ref * pdref, const ref * pkey, ref ** ppvalue /* result is stored here */ ) { dict *pdict = pdref->value.pdict; uint size = npairs(pdict); register int etype; uint nidx; ref_packed kpack; uint hash; int ktype; const gs_memory_t *mem = dict_mem(pdict); /* Compute hash. The only types we bother with are strings, */ /* names, and (unlikely, but worth checking for) integers. */ switch (r_type(pkey)) { case t_name: nidx = name_index(mem, pkey); nh: hash = dict_name_index_hash(nidx); kpack = packed_name_key(nidx); ktype = t_name; break; case t_string: /* convert to a name first */ { ref nref; int code; if (!r_has_attr(pkey, a_read)) return_error(gs_error_invalidaccess); code = name_ref(mem, pkey->value.bytes, r_size(pkey), &nref, 1); if (code < 0) return code; nidx = name_index(mem, &nref); } goto nh; case t_real: /* * Make sure that equal reals and integers hash the same. */ { int expt, i; double mant = frexp(pkey->value.realval, &expt); /* * The value is mant * 2^expt, where 0.5 <= mant < 1, * or else expt == mant == 0. */ if (expt < sizeof(long) * 8 || pkey->value.realval == min_long) i = (int)pkey->value.realval; else i = (int)(mant * min_long); /* MSVC 6.00.8168.0 cannot compile this */ hash = (uint)i * 30503; /* with -O2 as a single expression */ } goto ih; case t_integer: hash = (uint)pkey->value.intval * 30503; ih: kpack = packed_key_impossible; ktype = -1; nidx = 0; /* only to pacify gcc */ break; case t_null: /* not allowed as a key */ return_error(gs_error_typecheck); default: hash = r_btype(pkey) * 99; /* yech */ kpack = packed_key_impossible; ktype = -1; nidx = 0; /* only to pacify gcc */ } /* Search the dictionary */ if (dict_is_packed(pdict)) { const ref_packed *pslot = 0; # define found *ppvalue = packed_search_value_pointer; return 1 # define deleted if (pslot == 0) pslot = kp # define missing goto miss # include "idicttpl.h" # undef missing # undef deleted # undef found /* * Double wraparound, dict is full. * Note that even if there was an empty slot (pslot != 0), * we must return dictfull if length = maxlength. */ if (pslot == 0 || d_length(pdict) == d_maxlength(pdict)) return_error(gs_error_dictfull); *ppvalue = pdict->values.value.refs + (pslot - kbot); return 0; miss: /* Key is missing, not double wrap. See above re dictfull. */ if (d_length(pdict) == d_maxlength(pdict)) return_error(gs_error_dictfull); if (pslot == 0) pslot = kp; *ppvalue = pdict->values.value.refs + (pslot - kbot); return 0; } else { ref *kbot = pdict->keys.value.refs; register ref *kp; ref *pslot = 0; int wrap = 0; for (kp = kbot + dict_hash_mod(hash, size) + 2;;) { --kp; if ((etype = r_type(kp)) == ktype) { /* Fast comparison if both keys are names */ if (name_index(mem, kp) == nidx) { *ppvalue = pdict->values.value.refs + (kp - kbot); return 1; } } else if (etype == t_null) { /* Empty, deleted, or wraparound. */ /* Figure out which. */ if (kp == kbot) { /* wrap */ if (wrap++) { /* wrapped twice */ if (pslot == 0) return_error(gs_error_dictfull); break; } kp += size + 1; } else if (r_has_attr(kp, a_executable)) { /* Deleted entry, save the slot. */ if (pslot == 0) pslot = kp; } else /* key not found */ break; } else { if (obj_eq(mem, kp, pkey)) { *ppvalue = pdict->values.value.refs + (kp - kbot); return 1; } } } if (d_length(pdict) == d_maxlength(pdict)) return_error(gs_error_dictfull); *ppvalue = pdict->values.value.refs + ((pslot != 0 ? pslot : kp) - kbot); return 0; } }
/* * Look up a name on the dictionary stack. * Return the pointer to the value if found, 0 if not. */ ref * dstack_find_name_by_index(dict_stack_t * pds, uint nidx) { ds_ptr pdref = pds->stack.p; /* Since we know the hash function is the identity function, */ /* there's no point in allocating a separate variable for it. */ #define hash dict_name_index_hash(nidx) ref_packed kpack = packed_name_key(nidx); do { dict *pdict = pdref->value.pdict; uint size = npairs(pdict); const gs_memory_t *mem = dict_mem(pdict); #ifdef DEBUG if (gs_debug_c('D')) { ref dnref; name_index_ref(mem, nidx, &dnref); dlputs("[D]lookup "); debug_print_name(mem, &dnref); dprintf3(" in 0x%lx(%u/%u)\n", (ulong) pdict, dict_length(pdref), dict_maxlength(pdref)); } #endif #define INCR_DEPTH(pdref)\ INCR(depth[min(MAX_STATS_DEPTH, pds->stack.p - pdref)]) if (dict_is_packed(pdict)) { packed_search_1(INCR_DEPTH(pdref), return packed_search_value_pointer, DO_NOTHING, goto miss); packed_search_2(INCR_DEPTH(pdref), return packed_search_value_pointer, DO_NOTHING, break); miss:; } else { ref *kbot = pdict->keys.value.refs; register ref *kp; int wrap = 0; /* Search the dictionary */ for (kp = kbot + dict_hash_mod(hash, size) + 2;;) { --kp; if (r_has_type(kp, t_name)) { if (name_index(mem, kp) == nidx) { INCR_DEPTH(pdref); return pdict->values.value.refs + (kp - kbot); } } else if (r_has_type(kp, t_null)) { /* Empty, deleted, or wraparound. */ /* Figure out which. */ if (!r_has_attr(kp, a_executable)) break; if (kp == kbot) { /* wrap */ if (wrap++) break; /* 2 wraps */ kp += size + 1; } } } } #undef INCR_DEPTH }
void qsearch_fulltree_swap_nodes(FullTree *tree, int A, int B, const gsl_matrix *dm) { FullNode *ctm = get_nodes(tree); if (A == B) return; // no point in doing anything int interiorA = ctm[A].connections[ ctm[A].node_branch[B] ]; int interiorB = ctm[B].connections[ (int) ctm[B].node_branch[A] ]; if (interiorA == interiorB || interiorA == B) return; // swap does not change score int node_count = tree->node_count; int leaf_count = (node_count + 2)/2; int aToInteriorBranch = ctm[A].node_branch[interiorA]; int bToInteriorBranch = ctm[B].node_branch[interiorB]; int countA = leaf_count - ctm[A].leaf_count[aToInteriorBranch]; int countB = leaf_count - ctm[B].leaf_count[bToInteriorBranch]; int interiorToABranch = ctm[interiorA].node_branch[A]; int interiorToBBranch = ctm[interiorB].node_branch[B]; // loop over internal nodes, swap node_branches from A <-> B int node = interiorA; //printf("Score before %f\n", tree->raw_score); // store the nodes that need to be updated GArray *aNodes = get_tmpA(tree); //g_array_sized_new(FALSE, FALSE, sizeof(guint32), countA*2 - 1); GArray *bNodes = get_tmpB(tree); //g_array_sized_new(FALSE, FALSE, sizeof(guint32), countB*2 - 1); g_array_set_size(aNodes, 0); g_array_set_size(bNodes, 0); int i,j; for (i = 0; i < node_count; ++i) { if (i == A || ctm[A].node_branch[i] != aToInteriorBranch) { g_array_append_val(aNodes, i); } if (i == B || ctm[B].node_branch[i] != bToInteriorBranch) { g_array_append_val(bNodes, i); } } // move towards B while (node != B) { int aBranch = ctm[node].node_branch[A]; int bBranch = ctm[node].node_branch[B]; int cBranch = 3 - aBranch - bBranch; tree->raw_score -= npairs(ctm[node].leaf_count[0]) * ctm[node].dist[0]; tree->raw_score -= npairs(ctm[node].leaf_count[1]) * ctm[node].dist[1]; tree->raw_score -= npairs(ctm[node].leaf_count[2]) * ctm[node].dist[2]; //printf("Node %d\n", node); //printf("Score now %f, distances %f %f %f\n", tree->raw_score, ctm[node].dist[0], ctm[node].dist[1], ctm[node].dist[2]); ctm[node].leaf_count[aBranch] += countB - countA; ctm[node].leaf_count[bBranch] += countA - countB; // update the branches that point to elements from A for (i = 0; i < aNodes->len; ++i) { guint32 aNode = g_array_index(aNodes, guint32, i); g_assert(ctm[node].node_branch[aNode] == aBranch); ctm[node].node_branch[aNode] = bBranch; // update distances if (aNode < leaf_count) { // it's a leaf for (j = 0; j < leaf_count; ++j) { if (aNode==j) continue; double d = gsl_matrix_get(dm, aNode, j); if (ctm[node].node_branch[j] == cBranch) { ctm[node].dist[aBranch] += d; ctm[node].dist[bBranch] -= d; } else if (ctm[node].node_branch[j] == aBranch) { ctm[node].dist[cBranch] += d; } else { ctm[node].dist[cBranch] -= d; } } } } // update the branches that point to elements from B for (i = 0; i < bNodes->len; ++i) { guint32 bNode = g_array_index(bNodes, guint32, i); g_assert(ctm[node].node_branch[bNode] == bBranch); ctm[node].node_branch[bNode] = aBranch; if (bNode < leaf_count) { // it's a leaf for (j = 0; j < leaf_count; ++j) { if (bNode==j) continue; double d = gsl_matrix_get(dm, bNode, j); if (ctm[node].node_branch[j] == cBranch) { ctm[node].dist[bBranch] += d; ctm[node].dist[aBranch] -= d; } else if (ctm[node].node_branch[j] == bBranch) { ctm[node].dist[cBranch] += d; } else { ctm[node].dist[cBranch] -= d; } } } } tree->raw_score += npairs(ctm[node].leaf_count[0]) * ctm[node].dist[0]; tree->raw_score += npairs(ctm[node].leaf_count[1]) * ctm[node].dist[1]; tree->raw_score += npairs(ctm[node].leaf_count[2]) * ctm[node].dist[2]; //printf("Score now2 %f, distances %f %f %f\n", tree->raw_score, ctm[node].dist[0], ctm[node].dist[1], ctm[node].dist[2]); node = ctm[node].connections[ bBranch ]; } // swap directions for A and B ctm[interiorA].connections[ interiorToABranch ] = B; ctm[interiorB].connections[ interiorToBBranch ] = A; // swap connections for A and b ctm[A].connections[ aToInteriorBranch ] = interiorB; ctm[B].connections[ bToInteriorBranch ] = interiorA; }