press.rs

25.5 kB · rust · 765 lines

1use crate::core::error::{overflow_error, value_error, Result};2use crate::math::bang::factory::{code_to_corners, MagicLayer};3use crate::math::bang::Code;4use serde::{Deserialize, Serialize};56/// The largest corner count the tally press accepts, keeping its table a million rows.7pub const CORNERS: usize = 20;89fn corner_count(dimension: usize, base: usize) -> Result<usize> {10    let count = base.pow(dimension as u32);11    if count >= 128 {12        return overflow_error(format!(13            "dimension {dimension} base {base} has {count} corners, past the 127 a u128 code holds."14        ));15    }16    Ok(count)17}1819/// Returns the corner-usage mask of a number, one bit per digit vector its expansion uses.20///21/// A number is read in base `base` to the power of the dimension, so each digit is one22/// residue corner of the design cube, and zero uses exactly the zero corner.23///24/// ```25/// assert_eq!(mrlyrs::math::press::usage(0, 2, 2).unwrap().get(), 1);26/// assert_eq!(mrlyrs::math::press::usage(6, 2, 2).unwrap().get(), 0b0110);27/// ```28///29/// # Errors30///31/// Errors when the dimension and base reach a hundred and twenty-eight corners.32pub fn usage(number: u128, dimension: usize, base: usize) -> Result<Code> {33    Ok(mask(number, corner_count(dimension, base)? as u128))34}3536fn mask(number: u128, radix: u128) -> Code {37    if number == 0 {38        return Code(1);39    }40    let mut out: u128 = 0;41    let mut rest = number;42    while rest > 0 {43        out |= 1 << (rest % radix);44        rest /= radix;45    }46    Code(out)47}4849/// Returns whether every digit vector of the number lies in the design.50///51/// This is the scalar membership rule of the sequence press: the number's base52/// `base` to the dimension digits, read as residue corners, must all be filled.53/// At dimension one it is the classic restricted-digit set.54///55/// ```56/// use mrlyrs::math::bang::Code;57/// let members: Vec<u128> = (0..30).filter(|&n| mrlyrs::math::press::member(Code::from(0b0111u64), n, 2, 2).unwrap()).collect();58/// assert_eq!(members, vec![0, 1, 2, 4, 5, 6, 8, 9, 10, 16, 17, 18, 20, 21, 22, 24, 25, 26]);59/// ```60///61/// # Errors62///63/// Errors when the dimension and base reach a hundred and twenty-eight corners.64pub fn member(code: Code, number: u128, dimension: usize, base: usize) -> Result<bool> {65    Ok(usage(number, dimension, base)?.get() & !code.get() == 0)66}6768/// Returns the count of distinct digit vectors the number uses.69///70/// # Errors71///72/// Errors when the dimension and base reach a hundred and twenty-eight corners.73pub fn distinct(number: u128, dimension: usize, base: usize) -> Result<u32> {74    Ok(usage(number, dimension, base)?.get().count_ones())75}7677/// Returns the number of designs of the dimension and base that contain the number.78///79/// A design contains the number exactly when it fills every used corner, so the count80/// is two to the free corners, and the average membership over all designs is one over81/// two to the distinct-vector count.82///83/// ```84/// assert_eq!(mrlyrs::math::press::containing(6, 2, 2).unwrap(), 4);85/// ```86///87/// # Errors88///89/// Errors when the dimension and base reach a hundred and twenty-eight corners.90pub fn containing(number: u128, dimension: usize, base: usize) -> Result<u128> {91    Ok(1 << (corner_count(dimension, base)? as u32 - distinct(number, dimension, base)?))92}9394/// Splits a number into its dimension coordinates, one base digit peeled per axis in parallel.95///96/// ```97/// assert_eq!(mrlyrs::math::press::coordinates(6, 2, 2).unwrap(), vec![1, 2]);98/// ```99///100/// # Errors101///102/// Errors when the dimension and base reach a hundred and twenty-eight corners.103pub fn coordinates(number: u128, dimension: usize, base: usize) -> Result<Vec<u128>> {104    let radix = corner_count(dimension, base)? as u128;105    let mut out = vec![0u128; dimension];106    let mut rest = number;107    let mut place: u128 = 1;108    while rest > 0 {109        let mut corner = rest % radix;110        for axis in (0..dimension).rev() {111            out[axis] += (corner % base as u128) * place;112            corner /= base as u128;113        }114        rest /= radix;115        place *= base as u128;116    }117    Ok(out)118}119120/// Weaves dimension coordinates back into their single interleaved number.121///122/// # Errors123///124/// Errors on an empty coordinate list, past a hundred and twenty-seven corners, or when the woven number passes a u128.125pub fn interleave(coords: &[u128], base: usize) -> Result<u128> {126    if coords.is_empty() {127        return value_error("interleave needs at least one coordinate.");128    }129    let dimension = coords.len();130    let radix = corner_count(dimension, base)? as u128;131    let mut digits = Vec::new();132    let mut rest: Vec<u128> = coords.to_vec();133    while rest.iter().any(|&c| c > 0) {134        let mut corner: u128 = 0;135        for value in rest.iter_mut() {136            corner = corner * base as u128 + *value % base as u128;137            *value /= base as u128;138        }139        digits.push(corner);140    }141    let mut out: u128 = 0;142    for &corner in digits.iter().rev() {143        out = match out.checked_mul(radix).and_then(|v| v.checked_add(corner)) {144            Some(value) => value,145            None => {146                return overflow_error("the woven number passes a hundred and twenty-eight bits.")147            }148        };149    }150    Ok(out)151}152153/// Returns the first members of a design in ascending order.154///155/// Stops early where the next member would pass a hundred and twenty-eight bits.156///157/// ```158/// use mrlyrs::math::bang::Code;159/// assert_eq!(mrlyrs::math::press::members(Code::from(0b10u64), 1, 2, 5).unwrap(), vec![1, 3, 7, 15, 31]);160/// ```161///162/// # Errors163///164/// Errors when the dimension and base reach a hundred and twenty-eight corners.165pub fn members(code: Code, dimension: usize, base: usize, count: usize) -> Result<Vec<u128>> {166    let radix = corner_count(dimension, base)? as u128;167    let allowed: Vec<u128> = (0..radix).filter(|&i| (code.get() >> i) & 1 == 1).collect();168    let mut out = Vec::with_capacity(count);169    if count == 0 || allowed.is_empty() {170        return Ok(out);171    }172    if allowed[0] == 0 {173        out.push(0);174    }175    let mut length = 1usize;176    while out.len() < count {177        let mut slots = vec![0usize; length];178        if allowed[0] == 0 {179            slots[0] = 1;180            if allowed.len() == 1 {181                return Ok(out);182            }183        }184        'level: loop {185            let mut value: u128 = 0;186            let mut fits = true;187            for &slot in &slots {188                match value189                    .checked_mul(radix)190                    .and_then(|v| v.checked_add(allowed[slot]))191                {192                    Some(next) => value = next,193                    None => {194                        fits = false;195                        break;196                    }197                }198            }199            if !fits {200                return Ok(out);201            }202            out.push(value);203            if out.len() == count {204                return Ok(out);205            }206            for place in (0..length).rev() {207                slots[place] += 1;208                if slots[place] < allowed.len() {209                    continue 'level;210                }211                slots[place] = usize::from(place == 0 && allowed[0] == 0);212            }213            break;214        }215        length += 1;216        if radix.checked_pow(length as u32 - 1).is_none() {217            return Ok(out);218        }219    }220    Ok(out)221}222223/// Counts the members of a design below the limit.224///225/// ```226/// use mrlyrs::math::bang::Code;227/// assert_eq!(mrlyrs::math::press::count_below(Code::from(0b0111u64), 2, 2, 27).unwrap(), 18);228/// ```229///230/// # Errors231///232/// Errors when the dimension and base reach a hundred and twenty-eight corners.233pub fn count_below(code: Code, dimension: usize, base: usize, limit: u128) -> Result<u128> {234    let radix = corner_count(dimension, base)? as u128;235    let allowed: Vec<u128> = (0..radix).filter(|&i| (code.get() >> i) & 1 == 1).collect();236    if limit == 0 || allowed.is_empty() {237        return Ok(0);238    }239    let mut digits = Vec::new();240    let mut rest = limit;241    while rest > 0 {242        digits.push(rest % radix);243        rest /= radix;244    }245    digits.reverse();246    let k = allowed.len() as u128;247    let lead = allowed.iter().filter(|&&v| v != 0).count() as u128;248    let mut total: u128 = if allowed[0] == 0 { 1 } else { 0 };249    let mut power: u128 = 1;250    for _ in 1..digits.len() {251        total += lead * power;252        power *= k;253    }254    for (place, &digit) in digits.iter().enumerate() {255        let below = allowed256            .iter()257            .filter(|&&v| v < digit && (place > 0 || v != 0))258            .count() as u128;259        let tail = digits.len() - place - 1;260        total += below * k.pow(tail as u32);261        if !allowed.contains(&digit) {262            break;263        }264    }265    Ok(total)266}267268/// The tally press: one pass over the integers weighs every design of a universe at once.269///270/// Each added number lands its weight in the bucket of its corner-usage mask, and a271/// design's total is the sum over the submasks of its code, so a single sweep prices272/// a Mertens sum, a member count or a prime count for all two to the corners designs.273#[derive(Serialize, Deserialize)]274pub struct Press {275    /// The design dimension of the universe.276    pub dimension: usize,277    /// The numeral base of the universe.278    pub base: usize,279    corners: usize,280    tallies: Vec<i128>,281}282283impl Press {284    /// Builds an empty press over every design of the dimension and base.285    ///286    /// ```287    /// use mrlyrs::math::bang::Code;288    /// let mut press = mrlyrs::math::press::Press::new(2, 2).unwrap();289    /// press.add(6, 1);290    /// assert_eq!((press.total(Code::from(6u64)), press.total(Code::from(1u64))), (1, 0));291    /// ```292    ///293    /// # Errors294    ///295    /// Errors past twenty corners, where the bucket table would leave a million rows.296    pub fn new(dimension: usize, base: usize) -> Result<Press> {297        let corners = corner_count(dimension, base)?;298        if corners > CORNERS {299            return value_error(format!(300                "the tally press holds at most {CORNERS} corners, not {corners}."301            ));302        }303        Ok(Press {304            dimension,305            base,306            corners,307            tallies: vec![0; 1 << corners],308        })309    }310    /// Adds a weighted number to its usage bucket.311    pub fn add(&mut self, number: u128, weight: i128) {312        self.tallies[mask(number, self.corners as u128).get() as usize] += weight;313    }314    /// Returns the total weight the design at a code has collected.315    pub fn total(&self, code: Code) -> i128 {316        let code = code.get();317        let mut sum = self.tallies[0];318        let mut sub = code;319        while sub != 0 {320            sum += self.tallies[sub as usize];321            sub = (sub - 1) & code;322        }323        sum324    }325    /// Returns every design's total in code order by one subset-sum transform.326    pub fn totals(&self) -> Vec<i128> {327        let mut out = self.tallies.clone();328        for bit in 0..self.corners {329            for mask in 0..out.len() {330                if mask >> bit & 1 == 1 {331                    out[mask] += out[mask ^ (1 << bit)];332                }333            }334        }335        out336    }337}338339fn layer_radix(layer: &MagicLayer) -> u128 {340    (layer.number as u128).pow(layer.design.dim as u32)341}342343/// Returns the allowed digit table of one magic layer, one flag per cell of its tile.344///345/// A cell is allowed when its coordinate residues form a filled corner, which is the346/// tile the layer renders read as a digit alphabet.347///348/// # Errors349///350/// Errors when a layer's code is out of range.351pub fn layer_table(layer: &MagicLayer) -> Result<Vec<bool>> {352    let corners = code_to_corners(353        Code::from(layer.design.code),354        layer.design.dim,355        layer.design.base,356    )?;357    let dimension = layer.design.dim;358    let base = layer.design.base;359    let side = layer.number;360    let mut out = Vec::with_capacity(side.pow(dimension as u32));361    for cell in 0..side.pow(dimension as u32) {362        let mut rest = cell;363        let mut residue = vec![0u8; dimension];364        for axis in (0..dimension).rev() {365            residue[axis] = ((rest % side) % base) as u8;366            rest /= side;367        }368        out.push(corners.contains(&residue));369    }370    Ok(out)371}372373fn word_tables(layers: &[MagicLayer]) -> Result<Vec<Vec<bool>>> {374    if layers.is_empty() {375        return value_error("a word needs at least one layer.");376    }377    let dimension = layers[0].design.dim;378    if layers.iter().any(|l| l.design.dim != dimension) {379        return value_error("all word layers must have the same dimension.");380    }381    layers.iter().map(layer_table).collect()382}383384/// Counts the members of a magic word from its layer fills, without enumeration.385///386/// # Errors387///388/// Errors when a layer's code is out of range.389pub fn word_count(layers: &[MagicLayer]) -> Result<u128> {390    let tables = word_tables(layers)?;391    Ok(tables392        .iter()393        .map(|t| t.iter().filter(|&&b| b).count() as u128)394        .product())395}396397/// Returns whether the number lies in the magic word's composed design.398///399/// The number is read in the word's mixed radix, one digit per layer with the first400/// layer most significant, and every digit must land on an allowed cell of its tile.401/// A number past the word's domain is an error.402///403/// # Errors404///405/// Errors on a code out of range, or a number past the word's domain.406pub fn word_member(layers: &[MagicLayer], number: u128) -> Result<bool> {407    let tables = word_tables(layers)?;408    let mut rest = number;409    let mut ok = true;410    for (layer, table) in layers.iter().zip(&tables).rev() {411        let radix = layer_radix(layer);412        ok &= table[(rest % radix) as usize];413        rest /= radix;414    }415    if rest > 0 {416        return value_error(format!("number {number} lies past the word's domain."));417    }418    Ok(ok)419}420421/// Enumerates every member of the magic word in ascending order.422///423/// The member count is the product of the layer fills, so measure with `word_count`424/// before pressing a word too rich to hold.425///426/// # Errors427///428/// Errors when a layer's code is out of range.429pub fn word_members(layers: &[MagicLayer]) -> Result<Vec<u128>> {430    let tables = word_tables(layers)?;431    let alphabets: Vec<Vec<u128>> = tables432        .iter()433        .map(|t| {434            t.iter()435                .enumerate()436                .filter(|(_, &b)| b)437                .map(|(i, _)| i as u128)438                .collect()439        })440        .collect();441    if alphabets.iter().any(|a| a.is_empty()) {442        return Ok(Vec::new());443    }444    let radixes: Vec<u128> = layers.iter().map(layer_radix).collect();445    let mut out = Vec::new();446    let mut slots = vec![0usize; layers.len()];447    loop {448        let mut value: u128 = 0;449        for (place, &slot) in slots.iter().enumerate() {450            value = value * radixes[place] + alphabets[place][slot];451        }452        out.push(value);453        let mut place = layers.len();454        loop {455            if place == 0 {456                return Ok(out);457            }458            place -= 1;459            slots[place] += 1;460            if slots[place] < alphabets[place].len() {461                break;462            }463            slots[place] = 0;464        }465    }466}467468/// Returns the diagonal slice profile of a magic word by the substitution product.469///470/// The profile of a tile lists, per coordinate sum, its filled cells, and the profile471/// of a Kronecker word is the product of its layer profiles with strides, so no cell472/// of the composed design is ever enumerated.473///474/// # Errors475///476/// Errors when a layer's code is out of range.477pub fn word_profile(layers: &[MagicLayer]) -> Result<Vec<u128>> {478    let tables = word_tables(layers)?;479    let dimension = layers[0].design.dim;480    let mut out = vec![1u128];481    let mut stride: usize = 1;482    for (layer, table) in layers.iter().zip(&tables).rev() {483        let side = layer.number;484        let mut profile = vec![0u128; dimension * (side - 1) + 1];485        for (cell, &filled) in table.iter().enumerate() {486            if filled {487                let mut rest = cell;488                let mut total = 0usize;489                for _ in 0..dimension {490                    total += rest % side;491                    rest /= side;492                }493                profile[total] += 1;494            }495        }496        let mut next = vec![0u128; (profile.len() - 1) * stride + out.len()];497        for (i, &a) in profile.iter().enumerate() {498            if a == 0 {499                continue;500            }501            for (j, &b) in out.iter().enumerate() {502                next[i * stride + j] += a * b;503            }504        }505        out = next;506        stride *= side;507    }508    Ok(out)509}510511/// Returns the diagonal slice profile of one design pressed to a fractal level.512///513/// # Errors514///515/// Errors below level one, or on a code out of range.516pub fn profile(code: Code, dimension: usize, base: usize, level: usize) -> Result<Vec<u128>> {517    if level < 1 {518        return value_error("level must be at least 1.");519    }520    let layer = MagicLayer::new(521        crate::math::name::Bang::new(code.get(), dimension, base),522        base,523    );524    word_profile(&vec![layer; level])525}526527#[cfg(test)]528mod tests {529    use super::*;530    use crate::math::bang::factory::create;531    use crate::math::name::Bang;532533    #[test]534    fn usage_of_zero_is_the_zero_corner() {535        assert_eq!(usage(0, 2, 2).unwrap().get(), 1);536        assert_eq!(usage(0, 1, 10).unwrap().get(), 1);537        assert_eq!(distinct(0, 2, 2).unwrap(), 1);538    }539540    #[test]541    fn membership_matches_a_digit_check_at_base_ten() {542        let no_seven = Code(!(1u128 << 7) & ((1u128 << 10) - 1));543        for n in 0..10_000u128 {544            let digits_clean = !n.to_string().contains('7');545            assert_eq!(member(no_seven, n, 1, 10).unwrap(), digits_clean, "{n}");546        }547    }548549    #[test]550    fn members_of_the_repunit_design_are_the_mersenne_numbers() {551        assert_eq!(552            members(Code(0b10), 1, 2, 6).unwrap(),553            vec![1, 3, 7, 15, 31, 63]554        );555    }556557    #[test]558    fn members_walk_ascending_and_agree_with_membership() {559        for code in [Code(0b0111), Code(0b0110), Code(0b1001), Code(0b1111)] {560            let list = members(code, 2, 2, 40).unwrap();561            for pair in list.windows(2) {562                assert!(pair[0] < pair[1]);563            }564            let scanned: Vec<u128> = (0..200)565                .filter(|&n| member(code, n, 2, 2).unwrap())566                .collect();567            let shared = list.len().min(scanned.len());568            assert_eq!(list[..shared], scanned[..shared], "{code}");569        }570    }571572    #[test]573    fn count_below_agrees_with_the_member_walk() {574        for code in [575            Code(0b0111),576            Code(0b0110),577            Code(0b1011),578            Code(0b0001),579            Code(0b0000),580        ] {581            let list = members(code, 2, 2, 60).unwrap();582            for limit in 0..300u128 {583                let walked = list.iter().filter(|&&m| m < limit).count() as u128;584                if list.len() < 60 || walked < 60 {585                    assert_eq!(586                        count_below(code, 2, 2, limit).unwrap(),587                        walked,588                        "{code} {limit}"589                    );590                }591            }592        }593    }594595    #[test]596    fn the_member_count_at_a_level_boundary_is_the_geometric_sum() {597        let code = Code(0b0111);598        let k: u128 = 3;599        for level in 1..6u32 {600            let boundary = 4u128.pow(level);601            let full: u128 = 1 + (k - 1) * (k.pow(level) - 1) / (k - 1);602            assert_eq!(count_below(code, 2, 2, boundary).unwrap(), full);603        }604    }605606    #[test]607    fn membership_matches_the_rendered_fractal() {608        for code in [Code(7), Code(6), Code(9), Code(11)] {609            let level = 3;610            let tile = create(code, 2, 2, 2, level).unwrap();611            let side = 1u128 << level;612            for n in 0..4u128.pow(level as u32) {613                let coords = coordinates(n, 2, 2).unwrap();614                let flat = (coords[0] * side + coords[1]) as usize;615                let filled = tile.bytes().unwrap()[flat] == 1;616                let padded = member(code, n, 2, 2).unwrap()617                    && (code.get() & 1 == 1 || n >= 4u128.pow(level as u32 - 1));618                assert_eq!(padded, filled, "{code} {n}");619            }620        }621    }622623    #[test]624    fn coordinates_and_interleave_round_trip() {625        for n in 0..5_000u128 {626            assert_eq!(interleave(&coordinates(n, 2, 2).unwrap(), 2).unwrap(), n);627            assert_eq!(interleave(&coordinates(n, 3, 2).unwrap(), 2).unwrap(), n);628            assert_eq!(interleave(&coordinates(n, 2, 3).unwrap(), 3).unwrap(), n);629        }630    }631632    #[test]633    fn containing_counts_the_designs_that_hold_the_number() {634        for n in 0..500u128 {635            let direct = (0..16u128)636                .filter(|&code| member(Code(code), n, 2, 2).unwrap())637                .count();638            assert_eq!(containing(n, 2, 2).unwrap(), direct as u128, "{n}");639        }640    }641642    #[test]643    fn the_membership_average_over_all_designs_is_two_to_minus_distinct() {644        for n in 0..2_000u128 {645            assert_eq!(646                containing(n, 2, 2).unwrap(),647                1 << (4 - distinct(n, 2, 2).unwrap())648            );649            assert_eq!(650                containing(n, 3, 2).unwrap(),651                1 << (8 - distinct(n, 3, 2).unwrap())652            );653        }654    }655656    #[test]657    fn the_press_totals_agree_with_direct_member_sums() {658        let mut press = Press::new(2, 2).unwrap();659        let weights: Vec<i128> = (0..600).map(|n| (n as i128 % 7) - 3).collect();660        for (n, &w) in weights.iter().enumerate() {661            press.add(n as u128, w);662        }663        let totals = press.totals();664        for code in 0..16u128 {665            let direct: i128 = weights666                .iter()667                .enumerate()668                .filter(|(n, _)| member(Code(code), *n as u128, 2, 2).unwrap())669                .map(|(_, &w)| w)670                .sum();671            assert_eq!(press.total(Code(code)), direct, "{code}");672            assert_eq!(totals[code as usize], direct, "{code}");673        }674    }675676    #[test]677    fn a_native_word_is_the_stationary_press() {678        let layer = MagicLayer::new(Bang::new(7, 2, 2), 2);679        let word = vec![layer; 3];680        for n in 0..64u128 {681            let padded = member(Code(7), n, 2, 2).unwrap();682            assert_eq!(word_member(&word, n).unwrap(), padded, "{n}");683        }684        assert_eq!(word_count(&word).unwrap(), 27);685    }686687    #[test]688    fn word_members_match_the_magic_tensor() {689        let word = [690            MagicLayer::new(Bang::new(7, 2, 2), 3),691            MagicLayer::new(Bang::new(14, 2, 2), 5),692        ];693        let tensor = crate::math::bang::factory::magic(&word).unwrap();694        let side = 15u128;695        let list = word_members(&word).unwrap();696        assert_eq!(list.len() as u128, word_count(&word).unwrap());697        for n in 0..word.iter().map(layer_radix).product::<u128>() {698            let mut rest = n;699            let mut x = 0u128;700            let mut y = 0u128;701            let mut place = 1u128;702            for layer in word.iter().rev() {703                let cell = rest % layer_radix(layer);704                rest /= layer_radix(layer);705                let s = layer.number as u128;706                x += (cell / s) * place;707                y += (cell % s) * place;708                place *= s;709            }710            let filled = tensor.bytes().unwrap()[(x * side + y) as usize] == 1;711            assert_eq!(word_member(&word, n).unwrap(), filled, "{n}");712            assert_eq!(list.contains(&n), filled, "{n}");713        }714    }715716    #[test]717    fn word_profiles_match_the_rendered_diagonal_sums() {718        let word = [719            MagicLayer::new(Bang::new(7, 2, 2), 3),720            MagicLayer::new(Bang::new(14, 2, 2), 5),721        ];722        let tensor = crate::math::bang::factory::magic(&word).unwrap();723        let side = 15usize;724        let mut direct = vec![0u128; 2 * side - 1];725        for (flat, &b) in tensor.bytes().unwrap().iter().enumerate() {726            if b == 1 {727                direct[flat / side + flat % side] += 1;728            }729        }730        assert_eq!(word_profile(&word).unwrap(), direct);731    }732733    #[test]734    fn profile_totals_are_the_fill_powers() {735        let native = profile(Code(7), 2, 2, 4).unwrap();736        assert_eq!(native.iter().sum::<u128>(), 3u128.pow(4));737        let sponge = vec![MagicLayer::new(Bang::new(23, 3, 2), 3); 3];738        let classic = word_profile(&sponge).unwrap();739        assert_eq!(classic.iter().sum::<u128>(), 20u128.pow(3));740    }741742    #[test]743    fn refuses_a_universe_past_its_corners_and_an_empty_weave() {744        assert!(Press::new(5, 2).is_err());745        assert!(Press::new(7, 2).is_err());746        assert!(usage(1, 7, 2).is_err());747        assert!(member(Code(1), 1, 7, 2).is_err());748        assert!(distinct(1, 7, 2).is_err());749        assert!(containing(1, 7, 2).is_err());750        assert!(coordinates(1, 7, 2).is_err());751        assert!(members(Code(1), 7, 2, 1).is_err());752        assert!(count_below(Code(1), 7, 2, 4).is_err());753        assert!(interleave(&[], 2).is_err());754        assert!(interleave(&[u128::MAX, u128::MAX], 2).is_err());755    }756757    #[test]758    fn refuses_a_word_of_mismatched_dimensions_or_a_number_past_its_domain() {759        let plane = MagicLayer::new(Bang::new(7, 2, 2), 3);760        let cube = MagicLayer::new(Bang::new(23, 3, 2), 3);761        assert!(word_member(&[plane.clone(), cube], 0).is_err());762        assert!(word_member(&[plane], 9).is_err());763        assert!(word_member(&[], 0).is_err());764    }765}