@@ -250,3 +250,183 @@ impl<T: Clone + Eq> MeetSemiLattice for FlatSet<T> {
250250 true
251251 }
252252}
253+
254+ macro_rules! packed_int_join_semi_lattice {
255+ ( $name: ident, $base: ty) => {
256+ #[ derive( Debug , PartialEq , Eq , Copy , Clone , PartialOrd , Ord ) ]
257+ pub struct $name( $base) ;
258+ impl $name {
259+ pub const TOP : Self = Self ( <$base>:: MAX ) ;
260+ // If the value is too large it will be top, which is more conservative and thus
261+ // alright. It is only unsafe to make items bot.
262+ #[ inline]
263+ pub const fn new( v: $base) -> Self {
264+ Self ( v)
265+ }
266+
267+ #[ inline]
268+ pub fn saturating_new( v: impl TryInto <$base>) -> Self {
269+ v. try_into( ) . map( |v| Self ( v) ) . unwrap_or( Self :: TOP )
270+ }
271+
272+ pub const fn inner( self ) -> $base {
273+ self . 0
274+ }
275+ }
276+
277+ impl JoinSemiLattice for $name {
278+ #[ inline]
279+ fn join( & mut self , other: & Self ) -> bool {
280+ match ( * self , * other) {
281+ ( Self :: TOP , _) => false ,
282+ ( a, b) if a == b => false ,
283+ _ => {
284+ * self = Self :: TOP ;
285+ true
286+ }
287+ }
288+ }
289+ }
290+
291+ impl <C > crate :: fmt:: DebugWithContext <C > for $name {
292+ fn fmt_with( & self , _: & C , f: & mut std:: fmt:: Formatter <' _>) -> std:: fmt:: Result {
293+ if * self == Self :: TOP { write!( f, "TOP" ) } else { write!( f, "{}" , self . inner( ) ) }
294+ }
295+ }
296+ } ;
297+ }
298+
299+ packed_int_join_semi_lattice ! ( PackedU8JoinSemiLattice , u8 ) ;
300+
301+ #[ derive( Eq , PartialEq , Copy , Clone , Debug ) ]
302+ pub struct FactArray < T , const N : usize > {
303+ // FIXME(julianknodt): maybe map Idxs to each N element?
304+ pub arr : [ T ; N ] ,
305+ }
306+
307+ impl < T , const N : usize > FactArray < T , N > {
308+ #[ inline]
309+ pub fn insert ( & mut self , i : impl Idx , fact : T ) {
310+ let Some ( v) = self . arr . get_mut ( i. index ( ) ) else { return } ;
311+ * v = fact;
312+ }
313+ #[ inline]
314+ pub fn get ( & self , i : & impl Idx ) -> Option < & T > {
315+ self . arr . get ( i. index ( ) )
316+ }
317+ }
318+
319+ impl < T : JoinSemiLattice , const N : usize > JoinSemiLattice for FactArray < T , N > {
320+ fn join ( & mut self , other : & Self ) -> bool {
321+ let mut changed = false ;
322+ for ( a, b) in self . arr . iter_mut ( ) . zip ( other. arr . iter ( ) ) {
323+ changed |= a. join ( b) ;
324+ }
325+ changed
326+ }
327+ }
328+
329+ impl < T : MeetSemiLattice , const N : usize > MeetSemiLattice for FactArray < T , N > {
330+ fn meet ( & mut self , other : & Self ) -> bool {
331+ let mut changed = false ;
332+ for ( a, b) in self . arr . iter_mut ( ) . zip ( other. arr . iter ( ) ) {
333+ changed |= a. meet ( b) ;
334+ }
335+ changed
336+ }
337+ }
338+
339+ #[ derive( Eq , PartialEq , Copy , Clone , Debug ) ]
340+ pub struct FactCache < I , L , F , const N : usize > {
341+ facts : [ F ; N ] ,
342+ ord : [ ( I , L ) ; N ] ,
343+ len : usize ,
344+ }
345+
346+ impl < I : Idx , L : Ord + Eq + Copy , F , const N : usize > FactCache < I , L , F , N > {
347+ pub fn new ( empty_i : I , empty_l : L , empty_f : F ) -> Self
348+ where
349+ F : Copy ,
350+ {
351+ Self { facts : [ empty_f; N ] , ord : [ ( empty_i, empty_l) ; N ] , len : 0 }
352+ }
353+ /// inserts a fact into the cache, evicting the oldest one,
354+ /// Or updating it if there is information on one already. If the new fact being
355+ /// inserted is older than the previous fact, it will not be inserted.
356+ pub fn insert ( & mut self , i : I , l : L , fact : F ) {
357+ let mut idx = None ;
358+ for ( j, ( ci, cl) ) in self . ord [ ..self . len ] . iter_mut ( ) . enumerate ( ) {
359+ if * ci == i {
360+ assert ! ( * cl <= l) ;
361+ idx = Some ( j) ;
362+ break ;
363+ }
364+ }
365+ if idx. is_none ( ) && self . len < N {
366+ let new_len = self . len + 1 ;
367+ idx = Some ( std:: mem:: replace ( & mut self . len , new_len) ) ;
368+ } ;
369+ if let Some ( idx) = idx {
370+ self . facts [ idx] = fact;
371+ self . ord [ idx] = ( i, l) ;
372+ return ;
373+ } ;
374+ let ( p, ( _, old_l) ) = self . ord . iter ( ) . enumerate ( ) . min_by_key ( |k| k. 1 . 1 ) . unwrap ( ) ;
375+ // FIXME(julianknodt) maybe don't make this an assert but just don't update?
376+ assert ! ( * old_l <= l) ;
377+ self . ord [ p] = ( i, l) ;
378+ self . facts [ p] = fact;
379+ }
380+ pub fn get ( & self , i : I ) -> Option < ( & L , & F ) > {
381+ let ( p, ( _, loc) ) =
382+ self . ord [ ..self . len ] . iter ( ) . enumerate ( ) . find ( |( _, iloc) | iloc. 0 == i) ?;
383+ Some ( ( loc, & self . facts [ p] ) )
384+ }
385+ pub fn remove ( & mut self , i : I ) -> bool {
386+ let Some ( pos) = self . ord [ ..self . len ] . iter ( ) . position ( |( ci, _) | * ci == i)
387+ else { return false } ;
388+
389+ self . remove_idx ( pos) ;
390+ return true ;
391+ }
392+ #[ inline]
393+ fn remove_idx ( & mut self , i : usize ) {
394+ assert ! ( i < self . len) ;
395+ self . ord . swap ( i, self . len ) ;
396+ self . facts . swap ( i, self . len ) ;
397+ self . len -= 1 ;
398+ }
399+
400+ fn drain_filter ( & mut self , mut should_rm : impl FnMut ( & I , & mut L , & mut F ) -> bool ) {
401+ let mut i = 0 ;
402+ while i < self . len {
403+ let ( idx, l) = & mut self . ord [ i] ;
404+ let f = & mut self . facts [ i] ;
405+ if should_rm ( idx, l, f) {
406+ self . remove_idx ( i) ;
407+ continue ;
408+ }
409+ i += 1 ;
410+ }
411+ }
412+ }
413+
414+ impl < I : Idx , L : Ord + Eq + Copy , F : Eq , const N : usize > JoinSemiLattice for FactCache < I , L , F , N > {
415+ fn join ( & mut self , other : & Self ) -> bool {
416+ let mut changed = false ;
417+ self . drain_filter ( |i, l, f| {
418+ let Some ( ( other_loc, other_fact) ) = other. get ( * i) else {
419+ changed = true ;
420+ return true ;
421+ } ;
422+ if other_fact == f {
423+ * l = ( * l) . max ( * other_loc) ;
424+ return false ;
425+ }
426+ changed = true ;
427+ return true ;
428+ } ) ;
429+
430+ changed
431+ }
432+ }
0 commit comments