|
768 | 768 |
|
769 | 769 | local __list_new |
770 | 770 | local __list_dup |
| 771 | +local __list_lwr |
771 | 772 |
|
772 | 773 | ---@param reserve? integer |
773 | 774 | ---@return any[] |
@@ -796,6 +797,42 @@ function __list_dup(list) |
796 | 797 | return dup_list |
797 | 798 | end |
798 | 799 |
|
| 800 | +---@generic V |
| 801 | +---@param list V[] |
| 802 | +---@param item V |
| 803 | +---@param comp? fun(a: V, b: V): boolean |
| 804 | +---@return integer lower_bound_index |
| 805 | +---@nodiscard |
| 806 | +function __list_lwr(list, item, comp) |
| 807 | + local lower, upper = 1, #list |
| 808 | + |
| 809 | + if comp then |
| 810 | + while lower <= upper do |
| 811 | + local middle = lower + (upper - lower) / 2 |
| 812 | + middle = middle - middle % 1 -- fast math.floor |
| 813 | + |
| 814 | + if comp(item, list[middle]) then |
| 815 | + upper = middle - 1 |
| 816 | + else |
| 817 | + lower = middle + 1 |
| 818 | + end |
| 819 | + end |
| 820 | + else |
| 821 | + while lower <= upper do |
| 822 | + local middle = lower + (upper - lower) / 2 |
| 823 | + middle = middle - middle % 1 -- fast math.floor |
| 824 | + |
| 825 | + if item < list[middle] then |
| 826 | + upper = middle - 1 |
| 827 | + else |
| 828 | + lower = middle + 1 |
| 829 | + end |
| 830 | + end |
| 831 | + end |
| 832 | + |
| 833 | + return lower |
| 834 | +end |
| 835 | + |
799 | 836 | --- |
800 | 837 | --- |
801 | 838 | --- |
@@ -1111,6 +1148,11 @@ local __new_chunk |
1111 | 1148 | local __default_realloc |
1112 | 1149 | local __default_compmove |
1113 | 1150 |
|
| 1151 | +local __add_root_chunk |
| 1152 | +local __remove_root_chunk |
| 1153 | +local __add_child_chunk |
| 1154 | +local __remove_child_chunk |
| 1155 | + |
1114 | 1156 | local __update_chunk_caches |
1115 | 1157 | local __update_chunk_queries |
1116 | 1158 | local __update_chunk_storages |
@@ -1272,29 +1314,10 @@ function __new_chunk(chunk_parent, chunk_fragment) |
1272 | 1314 | __has_required_fragments = false, |
1273 | 1315 | }, __chunk_mt) |
1274 | 1316 |
|
1275 | | - if chunk_parent then |
1276 | | - chunk.__parent = chunk_parent |
1277 | | - |
1278 | | - chunk_parent.__child_count = __assoc_list_insert_ex( |
1279 | | - chunk_parent.__child_set, chunk_parent.__child_list, chunk_parent.__child_count, |
1280 | | - chunk) |
1281 | | - |
1282 | | - chunk_parent.__with_fragment_edges[chunk_fragment] = chunk |
1283 | | - chunk.__without_fragment_edges[chunk_fragment] = chunk_parent |
1284 | | - end |
1285 | | - |
1286 | 1317 | if not chunk_parent then |
1287 | | - local existing_root_index = __root_set[chunk_fragment] |
1288 | | - local existing_root_chunk = __root_list[existing_root_index] |
1289 | | - |
1290 | | - if existing_root_chunk ~= nil then |
1291 | | - __error_fmt('unexpected root chunk (%s)', |
1292 | | - __lua_tostring(existing_root_chunk)) |
1293 | | - end |
1294 | | - |
1295 | | - __root_count = __root_count + 1 |
1296 | | - __root_set[chunk_fragment] = __root_count |
1297 | | - __root_list[__root_count] = chunk |
| 1318 | + __add_root_chunk(chunk) |
| 1319 | + else |
| 1320 | + __add_child_chunk(chunk, chunk_parent) |
1298 | 1321 | end |
1299 | 1322 |
|
1300 | 1323 | do |
@@ -1361,6 +1384,107 @@ function __default_compmove(src, f, e, t, dst) |
1361 | 1384 | __lua_table_move(src, f, e, t, dst) |
1362 | 1385 | end |
1363 | 1386 |
|
| 1387 | +---@param root evolved.chunk |
| 1388 | +function __add_root_chunk(root) |
| 1389 | + local root_index = __list_lwr(__root_list, root, function(a, b) |
| 1390 | + return a.__fragment < b.__fragment |
| 1391 | + end) |
| 1392 | + |
| 1393 | + for sib_root_index = __root_count, root_index, -1 do |
| 1394 | + local sib_root = __root_list[sib_root_index] |
| 1395 | + __root_set[sib_root.__fragment] = sib_root_index + 1 |
| 1396 | + __root_list[sib_root_index + 1] = sib_root |
| 1397 | + end |
| 1398 | + |
| 1399 | + __root_set[root.__fragment] = root_index |
| 1400 | + __root_list[root_index] = root |
| 1401 | + __root_count = __root_count + 1 |
| 1402 | +end |
| 1403 | + |
| 1404 | +---@param root evolved.chunk |
| 1405 | +function __remove_root_chunk(root) |
| 1406 | + if root.__parent then |
| 1407 | + __error_fmt('unexpected root chunk: (%s)', |
| 1408 | + __lua_tostring(root)) |
| 1409 | + return |
| 1410 | + end |
| 1411 | + |
| 1412 | + local root_index = __root_set[root.__fragment] |
| 1413 | + |
| 1414 | + if not root_index or __root_list[root_index] ~= root then |
| 1415 | + __error_fmt('unexpected root chunk: (%s)', |
| 1416 | + __lua_tostring(root)) |
| 1417 | + return |
| 1418 | + end |
| 1419 | + |
| 1420 | + for sib_root_index = root_index, __root_count - 1 do |
| 1421 | + local sib_root = __root_list[sib_root_index + 1] |
| 1422 | + __root_set[sib_root.__fragment] = sib_root_index |
| 1423 | + __root_list[sib_root_index] = sib_root |
| 1424 | + end |
| 1425 | + |
| 1426 | + __root_set[root.__fragment] = nil |
| 1427 | + __root_list[__root_count] = nil |
| 1428 | + __root_count = __root_count - 1 |
| 1429 | +end |
| 1430 | + |
| 1431 | +---@param child evolved.chunk |
| 1432 | +---@param parent evolved.chunk |
| 1433 | +function __add_child_chunk(child, parent) |
| 1434 | + local child_index = __list_lwr(parent.__child_list, child, function(a, b) |
| 1435 | + return a.__fragment < b.__fragment |
| 1436 | + end) |
| 1437 | + |
| 1438 | + for sib_child_index = parent.__child_count, child_index, -1 do |
| 1439 | + local sib_child = parent.__child_list[sib_child_index] |
| 1440 | + parent.__child_set[sib_child] = sib_child_index + 1 |
| 1441 | + parent.__child_list[sib_child_index + 1] = sib_child |
| 1442 | + end |
| 1443 | + |
| 1444 | + parent.__child_set[child] = child_index |
| 1445 | + parent.__child_list[child_index] = child |
| 1446 | + parent.__child_count = parent.__child_count + 1 |
| 1447 | + |
| 1448 | + parent.__with_fragment_edges[child.__fragment] = child |
| 1449 | + child.__without_fragment_edges[child.__fragment] = parent |
| 1450 | + |
| 1451 | + child.__parent = parent |
| 1452 | +end |
| 1453 | + |
| 1454 | +---@param child evolved.chunk |
| 1455 | +function __remove_child_chunk(child) |
| 1456 | + local parent = child.__parent |
| 1457 | + |
| 1458 | + if not parent then |
| 1459 | + __error_fmt('unexpected child chunk: (%s)', |
| 1460 | + __lua_tostring(child)) |
| 1461 | + return |
| 1462 | + end |
| 1463 | + |
| 1464 | + local child_index = parent.__child_set[child] |
| 1465 | + |
| 1466 | + if not child_index or parent.__child_list[child_index] ~= child then |
| 1467 | + __error_fmt('unexpected child chunk: (%s)', |
| 1468 | + __lua_tostring(child)) |
| 1469 | + return |
| 1470 | + end |
| 1471 | + |
| 1472 | + for sib_child_index = child_index, parent.__child_count - 1 do |
| 1473 | + local next_sib_child = parent.__child_list[sib_child_index + 1] |
| 1474 | + parent.__child_set[next_sib_child] = sib_child_index |
| 1475 | + parent.__child_list[sib_child_index] = next_sib_child |
| 1476 | + end |
| 1477 | + |
| 1478 | + parent.__child_set[child] = nil |
| 1479 | + parent.__child_list[parent.__child_count] = nil |
| 1480 | + parent.__child_count = parent.__child_count - 1 |
| 1481 | + |
| 1482 | + parent.__with_fragment_edges[child.__fragment] = nil |
| 1483 | + child.__without_fragment_edges[child.__fragment] = nil |
| 1484 | + |
| 1485 | + child.__parent = nil |
| 1486 | +end |
| 1487 | + |
1364 | 1488 | ---@param chunk evolved.chunk |
1365 | 1489 | function __update_chunk_caches(chunk) |
1366 | 1490 | local chunk_parent = chunk.__parent |
@@ -2945,66 +3069,37 @@ function __purge_chunk(chunk) |
2945 | 3069 | __shrink_chunk(chunk, 0) |
2946 | 3070 | end |
2947 | 3071 |
|
2948 | | - local chunk_parent = chunk.__parent |
2949 | | - local chunk_fragment = chunk.__fragment |
2950 | | - |
2951 | | - local chunk_fragment_list = chunk.__fragment_list |
2952 | | - local chunk_fragment_count = chunk.__fragment_count |
2953 | | - |
2954 | | - local with_fragment_edges = chunk.__with_fragment_edges |
2955 | | - local without_fragment_edges = chunk.__without_fragment_edges |
2956 | | - |
2957 | | - if not chunk_parent then |
2958 | | - local existing_root_index = __root_set[chunk_fragment] |
2959 | | - local existing_root_chunk = __root_list[existing_root_index] |
2960 | | - |
2961 | | - if existing_root_chunk ~= chunk then |
2962 | | - __error_fmt('unexpected root chunk (%s)', |
2963 | | - __lua_tostring(existing_root_chunk)) |
2964 | | - end |
2965 | | - |
2966 | | - for root_index = existing_root_index, __root_count - 1 do |
2967 | | - local next_root = __root_list[root_index + 1] |
2968 | | - __root_set[next_root.__fragment] = root_index |
2969 | | - __root_list[root_index] = next_root |
2970 | | - end |
2971 | | - |
2972 | | - __root_set[chunk_fragment] = nil |
2973 | | - __root_list[__root_count] = nil |
2974 | | - __root_count = __root_count - 1 |
| 3072 | + if not chunk.__parent then |
| 3073 | + __remove_root_chunk(chunk) |
| 3074 | + else |
| 3075 | + __remove_child_chunk(chunk) |
2975 | 3076 | end |
2976 | 3077 |
|
2977 | 3078 | do |
2978 | | - local major = chunk_fragment |
| 3079 | + local major = chunk.__fragment |
2979 | 3080 | local major_chunks = __major_chunks[major] |
2980 | 3081 |
|
2981 | 3082 | if major_chunks and __assoc_list_remove(major_chunks, chunk) == 0 then |
2982 | 3083 | __major_chunks[major] = nil |
2983 | 3084 | end |
2984 | 3085 | end |
2985 | 3086 |
|
2986 | | - for chunk_fragment_index = 1, chunk_fragment_count do |
2987 | | - local minor = chunk_fragment_list[chunk_fragment_index] |
| 3087 | + for chunk_fragment_index = 1, chunk.__fragment_count do |
| 3088 | + local minor = chunk.__fragment_list[chunk_fragment_index] |
2988 | 3089 | local minor_chunks = __minor_chunks[minor] |
2989 | 3090 |
|
2990 | 3091 | if minor_chunks and __assoc_list_remove(minor_chunks, chunk) == 0 then |
2991 | 3092 | __minor_chunks[minor] = nil |
2992 | 3093 | end |
2993 | 3094 | end |
2994 | 3095 |
|
2995 | | - if chunk_parent then |
2996 | | - chunk.__parent, chunk_parent.__child_count = nil, __assoc_list_remove_ex( |
2997 | | - chunk_parent.__child_set, chunk_parent.__child_list, chunk_parent.__child_count, |
2998 | | - chunk) |
2999 | | - end |
3000 | | - |
3001 | | - for with_fragment, with_fragment_edge in __lua_next, with_fragment_edges do |
3002 | | - with_fragment_edges[with_fragment] = nil |
| 3096 | + for with_fragment, with_fragment_edge in __lua_next, chunk.__with_fragment_edges do |
| 3097 | + chunk.__with_fragment_edges[with_fragment] = nil |
3003 | 3098 | with_fragment_edge.__without_fragment_edges[with_fragment] = nil |
3004 | 3099 | end |
3005 | 3100 |
|
3006 | | - for without_fragment, without_fragment_edge in __lua_next, without_fragment_edges do |
3007 | | - without_fragment_edges[without_fragment] = nil |
| 3101 | + for without_fragment, without_fragment_edge in __lua_next, chunk.__without_fragment_edges do |
| 3102 | + chunk.__without_fragment_edges[without_fragment] = nil |
3008 | 3103 | without_fragment_edge.__with_fragment_edges[without_fragment] = nil |
3009 | 3104 | end |
3010 | 3105 |
|
|
0 commit comments