// Obtain a sorted move list. static int get_sortable_move_list(searchNode *node, sortable_move_t * move_list, int hash_table_move) { // number of moves in list int num_of_moves = generate_all_opt(&(node->position), move_list, false); color_t fake_color_to_move = color_to_move_of(&(node->position)); move_t killer_a = killer[KMT(node->ply, 0)]; move_t killer_b = killer[KMT(node->ply, 1)]; // sort special moves to the front for (int mv_index = 0; mv_index < num_of_moves; mv_index++) { move_t mv = get_move(move_list[mv_index]); if (mv == hash_table_move) { set_sort_key(&move_list[mv_index], SORT_MASK); } else if (mv == killer_a) { set_sort_key(&move_list[mv_index], SORT_MASK - 1); } else if (mv == killer_b) { set_sort_key(&move_list[mv_index], SORT_MASK - 2); } else { ptype_t pce = ptype_mv_of(mv); rot_t ro = rot_of(mv); // rotation square_t fs = from_square(mv); int ot = ORI_MASK & (ori_of(node->position.board[fs]) + ro); square_t ts = to_square(mv); set_sort_key(&move_list[mv_index], best_move_history[BMH(fake_color_to_move, pce, ts, ot)]); } } return num_of_moves; }
static void sort_secondary(struct tracing_map *map, const struct tracing_map_sort_entry **entries, unsigned int n_entries, struct tracing_map_sort_key *primary_key, struct tracing_map_sort_key *secondary_key) { int (*primary_fn)(const struct tracing_map_sort_entry **, const struct tracing_map_sort_entry **); int (*secondary_fn)(const struct tracing_map_sort_entry **, const struct tracing_map_sort_entry **); unsigned i, start = 0, n_sub = 1; if (is_key(map, primary_key->field_idx)) primary_fn = cmp_entries_key; else primary_fn = cmp_entries_sum; if (is_key(map, secondary_key->field_idx)) secondary_fn = cmp_entries_key; else secondary_fn = cmp_entries_sum; for (i = 0; i < n_entries - 1; i++) { const struct tracing_map_sort_entry **a = &entries[i]; const struct tracing_map_sort_entry **b = &entries[i + 1]; if (primary_fn(a, b) == 0) { n_sub++; if (i < n_entries - 2) continue; } if (n_sub < 2) { start = i + 1; n_sub = 1; continue; } set_sort_key(map, secondary_key); sort(&entries[start], n_sub, sizeof(struct tracing_map_sort_entry *), (int (*)(const void *, const void *))secondary_fn, NULL); set_sort_key(map, primary_key); start = i + 1; n_sub = 1; } }
// Obtain a sorted move list. static int get_sortable_move_list(searchNode *node, sortable_move_t * move_list, int hash_table_move) { // number of moves in list int num_of_moves = generate_all(&(node->position), move_list, false); color_t fake_color_to_move = color_to_move_of(&(node->position)); move_t killer_a = killer[KMT(node->ply, 0)]; move_t killer_b = killer[KMT(node->ply, 1)]; for (int mv_index = 0; mv_index < num_of_moves; mv_index++) { move_t mv = move_list[mv_index]; // don't use get_move. assumes generate_all doesn't bungle up high bits if (mv == hash_table_move) { set_sort_key(&move_list[mv_index], SORT_MASK); } else if (mv == killer_a) { set_sort_key(&move_list[mv_index], SORT_MASK - 1); } else if (mv == killer_b) { set_sort_key(&move_list[mv_index], SORT_MASK - 2); } else { ptype_t pce = ptype_mv_of(mv); rot_t ro = rot_of(mv); // rotation square_t fs = from_square(mv); int ot = ORI_MASK & (ori_of(node->position.board[fs]) + ro); square_t ts = to_square(mv); set_sort_key(&move_list[mv_index], best_move_history[BMH(fake_color_to_move, pce, ts, ot)]); } sortable_move_t insert = move_list[mv_index]; // TODO: enable this optimization for final since node counts change // if (insert > SORT_MASK) { int hole = mv_index; while (hole > 0 && insert > move_list[hole-1]) { move_list[hole] = move_list[hole-1]; hole--; } move_list[hole] = insert; // } } return num_of_moves; }
/** * tracing_map_sort_entries - Sort the current set of tracing_map_elts in a map * @map: The tracing_map * @sort_key: The sort key to use for sorting * @sort_entries: outval: pointer to allocated and sorted array of entries * * tracing_map_sort_entries() sorts the current set of entries in the * map and returns the list of tracing_map_sort_entries containing * them to the client in the sort_entries param. The client can * access the struct tracing_map_elt element of interest directly as * the 'elt' field of a returned struct tracing_map_sort_entry object. * * The sort_key has only two fields: idx and descending. 'idx' refers * to the index of the field added via tracing_map_add_sum_field() or * tracing_map_add_key_field() when the tracing_map was initialized. * 'descending' is a flag that if set reverses the sort order, which * by default is ascending. * * The client should not hold on to the returned array but should use * it and call tracing_map_destroy_sort_entries() when done. * * Return: the number of sort_entries in the struct tracing_map_sort_entry * array, negative on error */ int tracing_map_sort_entries(struct tracing_map *map, struct tracing_map_sort_key *sort_keys, unsigned int n_sort_keys, struct tracing_map_sort_entry ***sort_entries) { int (*cmp_entries_fn)(const struct tracing_map_sort_entry **, const struct tracing_map_sort_entry **); struct tracing_map_sort_entry *sort_entry, **entries; int i, n_entries, ret; entries = vmalloc(map->max_elts * sizeof(sort_entry)); if (!entries) return -ENOMEM; for (i = 0, n_entries = 0; i < map->map_size; i++) { struct tracing_map_entry *entry; entry = TRACING_MAP_ENTRY(map->map, i); if (!entry->key || !entry->val) continue; entries[n_entries] = create_sort_entry(entry->val->key, entry->val); if (!entries[n_entries++]) { ret = -ENOMEM; goto free; } } if (n_entries == 0) { ret = 0; goto free; } if (n_entries == 1) { *sort_entries = entries; return 1; } ret = merge_dups(entries, n_entries, map->key_size); if (ret < 0) goto free; n_entries -= ret; if (is_key(map, sort_keys[0].field_idx)) cmp_entries_fn = cmp_entries_key; else cmp_entries_fn = cmp_entries_sum; set_sort_key(map, &sort_keys[0]); sort(entries, n_entries, sizeof(struct tracing_map_sort_entry *), (int (*)(const void *, const void *))cmp_entries_fn, NULL); if (n_sort_keys > 1) sort_secondary(map, (const struct tracing_map_sort_entry **)entries, n_entries, &sort_keys[0], &sort_keys[1]); *sort_entries = entries; return n_entries; free: tracing_map_destroy_sort_entries(entries, n_entries); return ret; }