Changeset - 3fdb178e94b2
[Not reviewed]
0 1 0
Christopher Esterhuyse - 5 years ago 2020-02-14 14:55:43
christopher.esterhuyse@gmail.com
matrices seem very promising
1 file changed with 5 insertions and 76 deletions:
0 comments (0 inline, 0 general)
src/runtime/ecs.rs
Show inline comments
 
@@ -590,122 +590,118 @@ impl Debug for FlagMatrix {
 
                        true => '1',
 
                    }
 
                )?;
 
            }
 
            write!(f, "|\n")?;
 
        }
 
        Ok(())
 
    }
 
}
 

	
 
struct FlagMatrix {
 
    bytes: *mut u32,
 
    u32s_total: usize,
 
    u32s_per_row: usize,
 
    dims: [usize; 2],
 
}
 
#[inline(always)]
 
fn ceiling_to_mul_32(value: usize) -> usize {
 
    (value + 31) & !31
 
}
 
impl Drop for FlagMatrix {
 
    fn drop(&mut self) {
 
        let layout = Self::layout_for(self.u32s_total);
 
        unsafe {
 
            //?
 
            // ?
 
            std::alloc::dealloc(self.bytes as *mut u8, layout);
 
        }
 
    }
 
}
 
impl FlagMatrix {
 
    fn get_dims(&self) -> &[usize; 2] {
 
        &self.dims
 
    }
 

	
 
    fn reshape(&mut self, new_dims: [usize; 2]) {
 
        dbg!(self.u32s_total, self.u32s_per_row);
 

	
 
        // 1. calc new u32s_per_row
 
        let new_u32s_per_row = match ceiling_to_mul_32(new_dims[1]) / 32 {
 
            min if min > self.u32s_per_row => Some(min * 2),
 
            _ => None,
 
        };
 

	
 
        // 2. calc new u32s_total
 
        let new_u32s_total = match new_u32s_per_row.unwrap_or(self.u32s_per_row) * new_dims[0] {
 
            min if min > self.u32s_total => Some(min * 2),
 
            _ => None,
 
        };
 

	
 
        dbg!(new_u32s_per_row, new_u32s_total);
 
        match [new_u32s_per_row, new_u32s_total] {
 
            [None, None] => { /* do nothing */ }
 
            [None, Some(new_u32s_total)] => {
 
                assert!(new_u32s_total > self.u32s_total);
 
                // realloc only!
 
                dbg!("REALLOC ONLY");
 
                println!("BEFORE {:?}", self.bytes);
 
                // assert!(new_u32s_total > self.u32s_total);
 
                let old_layout = Self::layout_for(self.u32s_total);
 
                let new_layout = Self::layout_for(new_u32s_total);
 
                let new_bytes = unsafe {
 
                    let new_bytes = std::alloc::alloc(new_layout) as *mut u32;
 
                    // copy the previous total
 
                    self.bytes.copy_to_nonoverlapping(new_bytes, self.u32s_total);
 
                    // and zero the remainder
 
                    new_bytes
 
                        .add(self.u32s_total)
 
                        .write_bytes(0u8, new_u32s_total - self.u32s_total);
 
                    // drop the previous buffer
 
                    std::alloc::dealloc(self.bytes as *mut u8, old_layout);
 
                    new_bytes
 
                };
 
                self.bytes = new_bytes;
 
                println!("AFTER {:?}", self.bytes);
 
                self.u32s_total = new_u32s_total;
 
            }
 
            [Some(new_u32s_per_row), None] => {
 
                assert!(new_u32s_per_row > self.u32s_per_row);
 
                // shift only!
 
                dbg!("SHIFT ONLY");
 
                // assert!(new_u32s_per_row > self.u32s_per_row);
 
                for r in (0..self.dims[0]).rev() {
 
                    // iterate in REVERSE order because new row[n] may overwrite old row[n+m]
 
                    unsafe {
 
                        let src = self.bytes.add(r * self.u32s_per_row);
 
                        let dest = self.bytes.add(r * new_u32s_per_row);
 
                        // copy the used prefix
 
                        src.copy_to(dest, self.u32s_per_row);
 
                        // and zero the remainder
 
                        dest.add(self.u32s_per_row)
 
                            .write_bytes(0u8, new_u32s_per_row - self.u32s_per_row);
 
                    }
 
                }
 
                self.u32s_per_row = new_u32s_per_row;
 
            }
 
            [Some(new_u32s_per_row), Some(new_u32s_total)] => {
 
                assert!(new_u32s_total > self.u32s_total);
 
                assert!(new_u32s_per_row > self.u32s_per_row);
 
                // alloc AND shift!
 
                dbg!("BOTH");
 
                // assert!(new_u32s_total > self.u32s_total);
 
                // assert!(new_u32s_per_row > self.u32s_per_row);
 
                let old_layout = Self::layout_for(self.u32s_total);
 
                let new_layout = Self::layout_for(new_u32s_total);
 
                let new_bytes = unsafe { std::alloc::alloc(new_layout) as *mut u32 };
 
                for r in 0..self.dims[0] {
 
                    // iterate forwards over rows!
 
                    unsafe {
 
                        let src = self.bytes.add(r * self.u32s_per_row);
 
                        let dest = new_bytes.add(r * new_u32s_per_row);
 
                        // copy the used prefix
 
                        src.copy_to_nonoverlapping(dest, self.u32s_per_row);
 
                        // and zero the remainder
 
                        dest.add(self.u32s_per_row)
 
                            .write_bytes(0u8, new_u32s_per_row - self.u32s_per_row);
 
                    }
 
                }
 
                let fresh_rows_at = self.dims[0] * new_u32s_per_row;
 
                unsafe {
 
                    new_bytes.add(fresh_rows_at).write_bytes(0u8, new_u32s_total - fresh_rows_at);
 
                }
 
                unsafe { std::alloc::dealloc(self.bytes as *mut u8, old_layout) };
 
                self.u32s_per_row = new_u32s_per_row;
 
                self.bytes = new_bytes;
 
                self.u32s_total = new_u32s_total;
 
            }
 
@@ -773,106 +769,39 @@ impl FlagMatrix {
 
    fn col_iter_t1fn<'a, 'b: 'a>(
 
        &'a self,
 
        t_row: usize,
 
        f_rows: &'b [usize],
 
    ) -> impl Iterator<Item = usize> + 'a {
 
        // 1. do all bounds checks
 
        assert!(t_row < self.dims[0]);
 
        for &row in f_rows.iter() {
 
            assert!(row < self.dims[0]);
 
        }
 

	
 
        // 2. construct an unsafe iterator over chunks
 
        let chunk_iter = (0..self.u32s_per_row).map(move |col_chunk_index| {
 
            let t_chunk = unsafe { self.copy_chunk_unchecked(t_row, col_chunk_index) };
 
            f_rows.iter().fold(t_chunk, |chunk, &f_row| {
 
                let f_chunk = unsafe { self.copy_chunk_unchecked(f_row, col_chunk_index) };
 
                chunk & !f_chunk
 
            })
 
        });
 
        // 3. return an unsafe iterator over column indices
 
        BitChunkIter::new(chunk_iter).filter(move |&x| x < self.dims[1])
 
    }
 
}
 

	
 
#[derive(Debug, Copy, Clone)]
 
enum ColumnCombinator<'a> {
 
    Row(usize),
 
    True,
 
    False,
 
    And(&'a ColumnCombinator<'a>, &'a ColumnCombinator<'a>),
 
    Or(&'a ColumnCombinator<'a>, &'a ColumnCombinator<'a>),
 
    Not(&'a ColumnCombinator<'a>),
 
}
 
struct FlaggedColumnIter<'a> {
 
    flag_matrix: &'a FlagMatrix,
 
    next_column_chunk: usize,
 
    combinator: &'a ColumnCombinator<'a>,
 
}
 
impl<'a> FlaggedColumnIter<'a> {
 
    fn new(flag_matrix: &'a FlagMatrix, combinator: &'a ColumnCombinator<'a>) -> Self {
 
        Self { flag_matrix, combinator, next_column_chunk: 0 }
 
    }
 
    /// #Safety: bounds on self.next_column_chunk have been checked with self.flag_matrix
 
    /// retrieves the column chunk at self.next_column_chunk
 
    unsafe fn combine(&self, c: &ColumnCombinator) -> u32 {
 
        use ColumnCombinator as Cc;
 
        match c {
 
            Cc::Row(row) => self.flag_matrix.copy_chunk_unchecked(*row, self.next_column_chunk),
 
            Cc::False => 0u32,
 
            Cc::True => !0u32,
 
            Cc::And(a, b) => self.combine(a) & self.combine(b),
 
            Cc::Or(a, b) => self.combine(a) | self.combine(b),
 
            Cc::Not(a) => !self.combine(a),
 
        }
 
    }
 
}
 
impl<'a> Iterator for FlaggedColumnIter<'a> {
 
    type Item = u32;
 
    fn next(&mut self) -> Option<Self::Item> {
 
        struct CombineCtx<'a> {
 
            flag_matrix: &'a FlagMatrix,
 
            nth_col_chunk: usize,
 
        }
 
        if self.next_column_chunk >= self.flag_matrix.u32s_per_row {
 
            None
 
        } else {
 
            let x = unsafe { self.combine(self.combinator) };
 
            self.next_column_chunk += 1;
 
            Some(x)
 
        }
 
    }
 
}
 

	
 
struct ColumnIter<'a> {
 
    bit_chunk_iter: BitChunkIter<FlaggedColumnIter<'a>>,
 
}
 
impl<'a> ColumnIter<'a> {
 
    fn new(m: &'a FlagMatrix, combinator: &'a ColumnCombinator) -> Self {
 
        let iter = FlaggedColumnIter::new(m, combinator);
 
        let bit_chunk_iter = BitChunkIter::new(iter);
 
        Self { bit_chunk_iter }
 
    }
 
}
 
impl<'a> Iterator for ColumnIter<'a> {
 
    type Item = usize;
 
    fn next(&mut self) -> Option<Self::Item> {
 
        let v: Option<usize> = self.bit_chunk_iter.next();
 
        v.filter(|&x| x < self.bit_chunk_iter.chunk_iter.flag_matrix.dims[1])
 
    }
 
}
 

	
 
#[test]
 
fn matrix() {
 
    let mut m = FlagMatrix::new([5, 5], [0, 0]);
 
    for i in 0..5 {
 
        m.set([0, i]);
 
        m.set([i, i]);
 
    }
 
    println!("{:?}", &m);
 
    m.reshape([6, 40]);
 
    let iter = m.col_iter_t1fn(0, &[1, 2, 3]);
 
    for c in iter {
 
        println!("{:?}", c);
 
    }
 
    println!("{:?}", &m);
 
}
0 comments (0 inline, 0 general)