1use crate::error::{Error, Result};
2use crate::layout::TokenSpan;
3use serde::{Deserialize, Serialize};
4
5#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
7pub struct ScreeningGridConfig {
8 #[serde(alias = "rows")]
11 pub layer_count: usize,
12 #[serde(alias = "columns")]
14 pub head_count: usize,
15}
16
17impl Default for ScreeningGridConfig {
18 fn default() -> Self {
19 Self {
20 layer_count: 2,
21 head_count: 2,
22 }
23 }
24}
25
26impl ScreeningGridConfig {
27 pub fn validate(&self) -> Result<()> {
28 if self.layer_count == 0 {
29 return Err(Error::Config(
30 "screening_grid layer_count must be greater than zero".into(),
31 ));
32 }
33 if self.head_count == 0 {
34 return Err(Error::Config(
35 "screening_grid head_count must be greater than zero".into(),
36 ));
37 }
38 Ok(())
39 }
40
41 pub fn tile_slots(&self) -> usize {
42 self.layer_count * self.head_count
43 }
44
45 #[deprecated(note = "use tile_slots for paper-aligned naming")]
46 pub fn cells(&self) -> usize {
47 self.tile_slots()
48 }
49}
50
51#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
53pub struct TileConfig {
54 #[serde(alias = "tile_size")]
55 pub tokens_per_tile: usize,
56 #[serde(alias = "tile_stride")]
57 pub tile_stride_tokens: usize,
58 #[serde(alias = "grid")]
59 pub screening_grid: ScreeningGridConfig,
60}
61
62impl Default for TileConfig {
63 fn default() -> Self {
64 Self {
65 tokens_per_tile: 32,
66 tile_stride_tokens: 16,
67 screening_grid: ScreeningGridConfig::default(),
68 }
69 }
70}
71
72impl TileConfig {
73 pub fn validate(&self) -> Result<()> {
74 if self.tokens_per_tile == 0 {
75 return Err(Error::Config(
76 "tokens_per_tile must be greater than zero".into(),
77 ));
78 }
79 if self.tile_stride_tokens == 0 {
80 return Err(Error::Config(
81 "tile_stride_tokens must be greater than zero".into(),
82 ));
83 }
84 self.screening_grid.validate()
85 }
86}
87
88#[derive(Clone, Debug, PartialEq, Eq)]
90pub struct Tile {
91 pub index: usize,
92 pub screen_index: usize,
93 pub layer_index: usize,
94 pub head_index: usize,
95 pub span: TokenSpan,
96}
97
98impl Tile {
99 pub fn new(
100 index: usize,
101 screen_index: usize,
102 layer_index: usize,
103 head_index: usize,
104 span: TokenSpan,
105 ) -> Self {
106 Self {
107 index,
108 screen_index,
109 layer_index,
110 head_index,
111 span,
112 }
113 }
114
115 pub fn len(&self) -> usize {
116 self.span.len()
117 }
118
119 pub fn is_empty(&self) -> bool {
120 self.span.is_empty()
121 }
122}