## Coverage Report

#### Created: 2026-01-25 15:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /home/noah/src/trueno/src/tiling/calculator.rs

    Line
    Count
    Source
    1
    //! TCB index calculation utilities.
    2
    3
    use super::config::TilingConfig;
    4
    5
    /// Index calculator for hierarchical tiling
    6
    ///
    7
    /// Converts between linear indices and (row, col) coordinates at each tiling level.
    8
    #[derive(Debug, Clone)]
    9
    pub struct TcbIndexCalculator {
    10
        /// Tiling configuration
    11
        pub config: TilingConfig,
    12
        /// Problem dimensions
    13
        problem_m: u32,
    14
        problem_n: u32,
    15
        problem_k: u32,
    16
    }
    17
    18
    impl TcbIndexCalculator {
    19
        /// Create a new index calculator for the given problem size
    20
        #[must_use]
    21
    0
        pub fn new(config: TilingConfig, m: u32, n: u32, k: u32) -> Self {
    22
    0
            Self {
    23
    0
                config,
    24
    0
                problem_m: m,
    25
    0
                problem_n: n,
    26
    0
                problem_k: k,
    27
    0
            }
    28
    0
        }
    29
    30
        /// Get macro-tile offset for a given block index
    31
        ///
    32
        /// Returns (row_offset, col_offset) in the output matrix.
    33
        #[must_use]
    34
    0
        pub fn macro_tile_offset(&self, block_idx: u32) -> (u32, u32) {
    35
    0
            let tiles_per_row = (self.problem_n + self.config.macro_tile.n - 1) / self.config.macro_tile.n;
    36
    0
            let row = (block_idx / tiles_per_row) * self.config.macro_tile.m;
    37
    0
            let col = (block_idx % tiles_per_row) * self.config.macro_tile.n;
    38
    0
            (row, col)
    39
    0
        }
    40
    41
        /// Get midi-tile offset within a macro-tile
    42
        #[must_use]
    43
    0
        pub fn midi_tile_offset(&self, midi_idx: u32) -> (u32, u32) {
    44
    0
            let tiles_per_row = self.config.macro_tile.n / self.config.midi_tile.n;
    45
    0
            let row = (midi_idx / tiles_per_row) * self.config.midi_tile.m;
    46
    0
            let col = (midi_idx % tiles_per_row) * self.config.midi_tile.n;
    47
    0
            (row, col)
    48
    0
        }
    49
    50
        /// Get micro-tile offset within a midi-tile
    51
        #[must_use]
    52
    0
        pub fn micro_tile_offset(&self, micro_idx: u32) -> (u32, u32) {
    53
    0
            let tiles_per_row = self.config.midi_tile.n / self.config.micro_tile.n;
    54
    0
            let row = (micro_idx / tiles_per_row) * self.config.micro_tile.m;
    55
    0
            let col = (micro_idx % tiles_per_row) * self.config.micro_tile.n;
    56
    0
            (row, col)
    57
    0
        }
    58
    59
        /// Convert block index to linear memory offset
    60
        ///
    61
        /// For row-major C matrix with given stride.
    62
        #[must_use]
    63
        #[inline]
    64
    0
        pub fn block_to_linear_offset(&self, block_idx: u32, stride: u32) -> usize {
    65
    0
            let (row, col) = self.macro_tile_offset(block_idx);
    66
    0
            (row * stride + col) as usize
    67
    0
        }
    68
    69
        /// Calculate A matrix offset for K-dimension blocking
    70
        #[must_use]
    71
        #[inline]
    72
    0
        pub fn a_offset(&self, macro_row: u32, k_block: u32) -> usize {
    73
    0
            let row = macro_row * self.config.macro_tile.m;
    74
    0
            let col = k_block * self.config.macro_tile.k;
    75
    0
            (row * self.problem_k + col) as usize
    76
    0
        }
    77
    78
        /// Calculate B matrix offset for K-dimension blocking
    79
        #[must_use]
    80
        #[inline]
    81
    0
        pub fn b_offset(&self, k_block: u32, macro_col: u32) -> usize {
    82
    0
            let row = k_block * self.config.macro_tile.k;
    83
    0
            let col = macro_col * self.config.macro_tile.n;
    84
    0
            (row * self.problem_n + col) as usize
    85
    0
        }
    86
    87
        /// Get number of K blocks needed
    88
        #[must_use]
    89
    0
        pub fn num_k_blocks(&self) -> u32 {
    90
    0
            (self.problem_k + self.config.macro_tile.k - 1) / self.config.macro_tile.k
    91
    0
        }
    92
    93
        /// Check if this is a boundary tile (may need masking)
    94
        #[must_use]
    95
    0
        pub fn is_boundary_tile(&self, block_idx: u32) -> bool {
    96
    0
            let (row, col) = self.macro_tile_offset(block_idx);
    97
    0
            row + self.config.macro_tile.m > self.problem_m
    98
    0
                || col + self.config.macro_tile.n > self.problem_n
    99
    0
        }
    100
    101
        /// Get actual tile dimensions (may be smaller at boundaries)
    102
        #[must_use]
    103
    0
        pub fn actual_tile_dims(&self, block_idx: u32) -> (u32, u32) {
    104
    0
            let (row, col) = self.macro_tile_offset(block_idx);
    105
    0
            let actual_m = (self.problem_m - row).min(self.config.macro_tile.m);
    106
    0
            let actual_n = (self.problem_n - col).min(self.config.macro_tile.n);
    107
    0
            (actual_m, actual_n)
    108
    0
        }
    109
    }