From: Samual Lenks Date: Fri, 11 Oct 2013 01:08:27 +0000 (-0400) Subject: Use binary search to find first item for each category X-Git-Tag: xonotic-v0.8.0~256^2~25 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=a81db04aebd319f659fbde9c6776a7fed2e74b24;p=xonotic%2Fxonotic-data.pk3dir.git Use binary search to find first item for each category --- diff --git a/qcsrc/menu/xonotic/serverlist.c b/qcsrc/menu/xonotic/serverlist.c index 51e70f045..f36a1229c 100644 --- a/qcsrc/menu/xonotic/serverlist.c +++ b/qcsrc/menu/xonotic/serverlist.c @@ -670,40 +670,77 @@ void XonoticServerList_draw(entity me) // ^ unfortunately no such optimization can be made-- we must process through the // entire list, otherwise there is no way to know which item is first in its category. - float cat, x; - for(i = 0; i < itemcount; ++i) // FIXME this loop is TOTALLY unacceptable (O(servers)). Make it O(categories * log(servers)). Yes, that is possible. + if(itemcount) { - cat = gethostcachenumber(SLIST_FIELD_CATEGORY, i); - if(cat) + float cat = 0, x; + float first, middle, last; + float newfirst = 0; + for(x = 1; x <= category_ent_count; ++x) { - if(category_draw_count == 0) + first = newfirst; + last = (itemcount - 1); + middle = floor((first + last) / 2); + + while(first <= last) { - category_name[category_draw_count] = cat; - category_item[category_draw_count] = i; - ++category_draw_count; - ++me.nItems; + cat = gethostcachenumber(SLIST_FIELD_CATEGORY, middle); + if(cat > x) { last = middle - 1; } + else if(cat == x) + { + if(middle == 0 || (gethostcachenumber(SLIST_FIELD_CATEGORY, middle - 1) != x)) // check if middle is the first of its category + { + //print(sprintf("hit: x='%d', dc='%d', first='%d', middle='%d', last='%d', cat='%d'.\n", x, category_draw_count, first, middle, last, cat)); + category_name[category_draw_count] = cat; + category_item[category_draw_count] = middle; + ++category_draw_count; + ++me.nItems; + newfirst = middle + 1; // already scanned through these, skip 'em + break; + } + else { last = middle - 1; } // nope, try again + } + else { first = middle + 1; } + middle = floor((first + last) / 2); } - else + } + + /*float cat = 0, i = 0, x = 0; + for(i = 0; i < itemcount; ++i) // FIXME this loop is TOTALLY unacceptable (O(servers)). Make it O(categories * log(servers)). Yes, that is possible. + { + cat = gethostcachenumber(SLIST_FIELD_CATEGORY, i); + if(cat) { - found = 0; - for(x = 0; x < category_draw_count; ++x) { if(cat == category_name[x]) { found = 1; } } - if not(found) + if(category_draw_count == 0) { + print(sprintf("hit: i='%d', dc='%d', cat='%d'.\n", i, category_draw_count, cat)); category_name[category_draw_count] = cat; category_item[category_draw_count] = i; ++category_draw_count; ++me.nItems; } + else + { + found = 0; + for(x = 0; x < category_draw_count; ++x) { if(cat == category_name[x]) { found = 1; } } + if not(found) + { + print(sprintf("hit: i='%d', dc='%d', cat='%d'.\n", i, category_draw_count, cat)); + category_name[category_draw_count] = cat; + category_item[category_draw_count] = i; + ++category_draw_count; + ++me.nItems; + } + } } + }*/ + if(autocvar_menu_slist_categories_onlyifmultiple && (category_draw_count == 1)) + { + category_name[0] = -1; + category_item[0] = -1; + category_draw_count = 0; + me.nItems = itemcount; } } - if(autocvar_menu_slist_categories_onlyifmultiple && (category_draw_count == 1)) - { - category_name[0] = -1; - category_item[0] = -1; - category_draw_count = 0; - me.nItems = itemcount; - } } else { me.nItems = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT); }