@@ -19,6 +19,32 @@ fn useMovedDeltaPath(block_len: usize, moved_count: usize) bool {
1919 return affected_pairs * 2 < total_pairs ;
2020}
2121
22+ fn useGroupedExactPath (block_len : usize , distinct_count : usize ) bool {
23+ return distinct_count <= 8 and distinct_count * 4 <= block_len ;
24+ }
25+
26+ fn cheapDistinctCount (comptime T : type , keys : []const key .KeyType (T )) usize {
27+ const table_len = Config .max_block_size * 2 ;
28+ var used : [table_len ]bool = [_ ]bool {false } ** table_len ;
29+ var table : [table_len ]key .KeyType (T ) = undefined ;
30+ var count : usize = 0 ;
31+
32+ for (keys ) | value | {
33+ var hash : usize = @intCast (value ^ (value >> @min (@bitSizeOf (key .KeyType (T )) / 2 , 16 )));
34+ hash %= table_len ;
35+ while (used [hash ]) : (hash = (hash + 1 ) % table_len ) {
36+ if (table [hash ] == value ) break ;
37+ }
38+ if (! used [hash ]) {
39+ used [hash ] = true ;
40+ table [hash ] = value ;
41+ count += 1 ;
42+ }
43+ }
44+
45+ return count ;
46+ }
47+
2248fn isPermutation (mapping : []const usize ) bool {
2349 var seen : [Config .max_block_size ]bool = [_ ]bool {false } ** Config .max_block_size ;
2450 for (mapping ) | value | {
@@ -76,8 +102,26 @@ pub fn tryTransportBlock(comptime T: type, block: []T, cfg: Config, stats: ?*Sta
76102 var desired : [Config .max_block_size ]usize = undefined ;
77103 var source_to_final : [Config .max_block_size ]usize = undefined ;
78104 var moved_indices : [Config .max_block_size ]usize = undefined ;
105+ var group_ids : [Config .max_block_size ]u8 = undefined ;
106+ var final_group_ids : [Config .max_block_size ]u8 = undefined ;
107+ var distinct_keys : [Config .max_block_size ]key .KeyType (T ) = undefined ;
108+ var weight_matrix : [Config .max_block_size * Config .max_block_size ]u16 = undefined ;
109+
110+ const estimated_distinct = cheapDistinctCount (T , keys [0.. block .len ]);
111+ const grouped_path = useGroupedExactPath (block .len , estimated_distinct );
112+ const distinct_count = if (grouped_path )
113+ energy .collectDistinctGroups (T , keys [0.. block .len ], distinct_keys [0.. block .len ], group_ids [0.. block .len ])
114+ else
115+ 0 ;
79116
80- const before_energy = pressure .computeFromKeysWithEnergy (T , keys [0.. block .len ], cfg , pressures [0.. block .len ]);
117+ const before_energy = if (grouped_path )
118+ blk : {
119+ energy .buildGroupWeightMatrix (T , distinct_keys [0.. distinct_count ], cfg , weight_matrix [0 .. distinct_count * distinct_count ]);
120+ pressure .computeFromKeys (T , keys [0.. block .len ], cfg , pressures [0.. block .len ]);
121+ break :blk energy .blockEnergyFromGroupIds (group_ids [0.. block .len ], distinct_count , weight_matrix [0 .. distinct_count * distinct_count ]);
122+ }
123+ else
124+ pressure .computeFromKeysWithEnergy (T , keys [0.. block .len ], cfg , pressures [0.. block .len ]);
81125 if (before_energy == 0 ) {
82126 if (stats ) | s | s .transport_blocks_rejected += 1 ;
83127 return .{ .accepted = false , .before_energy = before_energy , .after_energy = before_energy };
@@ -116,7 +160,14 @@ pub fn tryTransportBlock(comptime T: type, block: []T, cfg: Config, stats: ?*Sta
116160 return .{ .accepted = false , .before_energy = before_energy , .after_energy = before_energy };
117161 }
118162
119- const after_energy = if (useMovedDeltaPath (block .len , moved_count ))
163+ const after_energy = if (grouped_path )
164+ blk : {
165+ for (group_ids [0.. block .len ], 0.. ) | group , source_index | {
166+ final_group_ids [source_to_final [source_index ]] = group ;
167+ }
168+ break :blk energy .blockEnergyFromGroupIds (final_group_ids [0.. block .len ], distinct_count , weight_matrix [0 .. distinct_count * distinct_count ]);
169+ }
170+ else if (useMovedDeltaPath (block .len , moved_count ))
120171 energy .energyAfterPermutationFromMovedKeys (
121172 T ,
122173 keys [0.. block .len ],
0 commit comments