designs.rs
6.7 kB · rust · 197 lines
1use super::Cell2d;2use crate::core::atoms;3use crate::core::errors::{value_error, Result};4use crate::core::tensor::Tensor;5use crate::core::tile::Design;6use crate::math::bang::factory;7use crate::math::bang::universe::Code;89pub use crate::math::bang::factory::levels_code;1011fn build(pattern: Tensor, level: usize, rotation: usize) -> Result<Cell2d> {12 let mut cell = crate::math::dim::grow::<2>(pattern, level)?;13 if rotation != 0 {14 cell = cell.rotate(rotation);15 }16 Ok(cell)17}1819/// Builds the design a universe code names, deepened to the level and rotated by quarter-turns.20pub fn create(21 code: Code,22 number: usize,23 level: usize,24 rotation: usize,25 base: usize,26) -> Result<Cell2d> {27 build(factory::create(code, number, 2, base, 1)?, level, rotation)28}2930/// Builds the design straight from its filled residue corners, deepened to the level and rotated by quarter-turns.31pub fn from_corners(32 corners: &[Vec<u8>],33 number: usize,34 level: usize,35 rotation: usize,36 base: usize,37) -> Result<Cell2d> {38 build(39 factory::create_from_corners(corners, number, 2, base, 1)?,40 level,41 rotation,42 )43}4445/// Builds the level-set design, filling every residue corner whose digits sum to a named level.46///47/// ```48/// let n = 5;49/// assert_eq!(50/// mrlyrs::math::two::level_set(n, &[0, 1], 1, 0, 2).unwrap(),51/// mrlyrs::math::two::carpet(n, 1).unwrap()52/// );53/// ```54pub fn level_set(55 number: usize,56 levels: &[usize],57 level: usize,58 rotation: usize,59 base: usize,60) -> Result<Cell2d> {61 create(levels_code(2, base, levels), number, level, rotation, base)62}6364/// Builds the design the name picks, deepened to the level and rotated by quarter-turns.65pub fn named(design: Design, number: usize, level: usize, rotation: usize) -> Result<Cell2d> {66 let pattern = match design {67 Design::Carpet => atoms::carpet_2d(number),68 Design::Net => atoms::net_2d(number),69 Design::Htree => atoms::htree_2d(number),70 Design::Vtree => atoms::vtree_2d(number),71 Design::Void => atoms::void_2d(number),72 Design::Point => atoms::point_2d(number),73 Design::Dust => atoms::dust_2d(number),74 Design::Hline => atoms::hline_2d(number),75 Design::Vline => atoms::vline_2d(number),76 Design::Star => atoms::star_2d(number),77 other => return value_error(format!("design {} is not 2d.", other.name())),78 };79 build(pattern, level, rotation)80}8182/// Builds an all-empty cell of the given size and level.83pub fn zeros(number: usize, level: usize) -> Result<Cell2d> {84 build(atoms::zeros_2d(number), level, 0)85}8687/// Builds an all-filled cell of the given size and level.88pub fn ones(number: usize, level: usize) -> Result<Cell2d> {89 build(atoms::ones_2d(number), level, 0)90}9192/// Builds the carpet fractal, its seed pierced at every odd-odd site, deepened to the level.93pub fn carpet(number: usize, level: usize) -> Result<Cell2d> {94 build(atoms::carpet_2d(number), level, 0)95}9697/// Builds the net fractal, its seed on wherever a coordinate is odd, deepened to the level.98pub fn net(number: usize, level: usize) -> Result<Cell2d> {99 build(atoms::net_2d(number), level, 0)100}101102/// Builds the htree fractal, its seed striped along even rows, deepened to the level.103pub fn htree(number: usize, level: usize) -> Result<Cell2d> {104 build(atoms::htree_2d(number), level, 0)105}106107/// Builds the vtree fractal, its seed striped along even columns, deepened to the level.108pub fn vtree(number: usize, level: usize) -> Result<Cell2d> {109 build(atoms::vtree_2d(number), level, 0)110}111112/// Builds the void fractal, its seed a checkerboard on even parity, deepened to the level.113pub fn void(number: usize, level: usize) -> Result<Cell2d> {114 build(atoms::void_2d(number), level, 0)115}116117/// Builds the point fractal, its seed on at every odd-odd site, deepened to the level.118pub fn point(number: usize, level: usize) -> Result<Cell2d> {119 build(atoms::point_2d(number), level, 0)120}121122/// Builds the dust fractal, its seed on at every even-even site, deepened to the level.123pub fn dust(number: usize, level: usize) -> Result<Cell2d> {124 build(atoms::dust_2d(number), level, 0)125}126127/// Builds the hline fractal, its seed striped along odd rows, deepened to the level.128pub fn hline(number: usize, level: usize) -> Result<Cell2d> {129 build(atoms::hline_2d(number), level, 0)130}131132/// Builds the vline fractal, its seed striped along odd columns, deepened to the level.133pub fn vline(number: usize, level: usize) -> Result<Cell2d> {134 build(atoms::vline_2d(number), level, 0)135}136137/// Builds the star fractal, its seed on where exactly one coordinate is odd, deepened to the level.138pub fn star(number: usize, level: usize) -> Result<Cell2d> {139 build(atoms::star_2d(number), level, 0)140}141142#[cfg(test)]143mod tests {144 use super::*;145 #[test]146 fn carpet_fractal_growth() {147 let c = carpet(3, 3).unwrap();148 assert_eq!(c.width(), 27);149 assert_eq!(c.types().sum(), carpet(3, 1).unwrap().types().sum().pow(3));150 }151 #[test]152 fn create_matches_carpet() {153 let by_name = carpet(5, 2).unwrap();154 let by_code = create(7, 5, 2, 0, 2).unwrap();155 assert_eq!(by_name, by_code);156 }157 #[test]158 fn level_sets_reproduce_the_symmetric_designs() {159 for n in 1..8 {160 assert_eq!(161 level_set(n, &[0, 1], 1, 0, 2).unwrap(),162 carpet(n, 1).unwrap()163 );164 assert_eq!(level_set(n, &[1, 2], 1, 0, 2).unwrap(), net(n, 1).unwrap());165 assert_eq!(level_set(n, &[0, 2], 1, 0, 2).unwrap(), void(n, 1).unwrap());166 }167 assert_eq!(level_set(4, &[], 1, 0, 2).unwrap(), zeros(4, 1).unwrap());168 assert_eq!(169 level_set(4, &[0, 1, 2], 1, 0, 2).unwrap(),170 ones(4, 1).unwrap()171 );172 }173 #[test]174 fn level_sets_carry_level_and_rotation() {175 let deep = level_set(3, &[0, 1], 2, 0, 2).unwrap();176 assert_eq!(deep, carpet(3, 2).unwrap());177 let turned = level_set(5, &[1, 2], 1, 1, 2).unwrap();178 assert_eq!(turned, net(5, 1).unwrap().rotate(1));179 }180 #[test]181 fn named_builders_take_a_rotation() {182 for (design, plain) in [183 (Design::Carpet, carpet(5, 1).unwrap()),184 (Design::Net, net(5, 1).unwrap()),185 (Design::Htree, htree(5, 1).unwrap()),186 (Design::Vtree, vtree(5, 1).unwrap()),187 (Design::Void, void(5, 1).unwrap()),188 ] {189 assert_eq!(named(design, 5, 1, 0).unwrap(), plain);190 for k in 1..4 {191 assert_eq!(named(design, 5, 1, k).unwrap(), plain.clone().rotate(k));192 }193 }194 assert_eq!(named(Design::Vtree, 5, 1, 1).unwrap(), htree(5, 1).unwrap());195 assert!(named(Design::Ztree, 5, 1, 0).is_err());196 }197}