From: Simon Tatham Date: Thu, 17 Apr 2025 07:16:30 +0000 (+0100) Subject: Comment the examples. X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=eb9023dc30c3dd70677eadf5b57e482f99093686;p=nimber.git Comment the examples. --- diff --git a/examples/minpoly.rs b/examples/minpoly.rs index 2c5b7bf..625df3f 100644 --- a/examples/minpoly.rs +++ b/examples/minpoly.rs @@ -1,3 +1,29 @@ +//! Use the nimber multiplication in this crate to compute the minimal +//! polynomials of nimbers over GF(2): that is, the smallest (measured +//! by degree) polynomial P with coefficients 0 and 1 such that P(x), +//! evaluated in nimber arithmetic, is zero. +//! +//! The polynomials are printed as integers, by the usual convention +//! in which 2^n stands in for x^n. For example, the number 0x13 +//! breaks down in binary as 2^4+2^1+1, and therefore represents the +//! polynomial x^4+x^1+1. (For very large polynomials this notation +//! saves a lot of space!) +//! +//! The program calculates the minimal polynomials of the first 256 +//! nimbers, and also the minimal polynomials of nimbers of the form +//! 2^(2^n)-1, i.e. 3, 15, 255, 65535, ..., up to 2^4096-1. +//! +//! It's not checked in this program, but the second sequence of +//! polynomials is interesting because the ones computed here are all +//! _primitive_: that is, if you calculate the powers of x mod P, they +//! cover every possible nonzero polynomial of degree smaller than P +//! before cycling back to 1. I don't know if that property continues +//! forever, only that it continues as far as 2^4096-1. (Beyond that, +//! to check the order of x you'd need to know the factorisation of a +//! large Fermat number, and as of 2025-04, nobody knows that.) This +//! sequence of polynomials is in [OEIS](https://oeis.org/A382121); +//! this example code serves as a means of recalculating them. + use itertools::Itertools; use std::collections::hash_map::Entry; use std::collections::HashMap; @@ -111,11 +137,7 @@ fn largest_nimber_in_subfield(level: usize) -> FiniteNimber { fn main() { println!("Min poly of nimbers up to 2^8:"); for n in (0..256).map(FiniteNimber::from) { - println!( - "{} has minimal polynomial {}", - &n, - minimal_polynomial(&n) - ); + println!("{} has minimal polynomial {}", &n, minimal_polynomial(&n)); } println!(); diff --git a/examples/tables.rs b/examples/tables.rs index 1e24c8c..6244d59 100644 --- a/examples/tables.rs +++ b/examples/tables.rs @@ -1,29 +1,63 @@ +//! Basic demonstration of some nimber arithmetic operations, by +//! printing multiplication tables and similar. +//! +//! All these tables correspond to a sequence in OEIS (links in the +//! output). The addition and multiplication tables can also be +//! checked visually against [the ones on +//! Wikipedia](https://en.wikipedia.org/wiki/Nimber#Addition_and_multiplication_tables). + use nimber::FiniteNimber; fn main() { - println!("Multiplication table for nimbers less than 16:"); + println!( + "Addition table for nimbers less than 16 (https://oeis.org/A003987):" + ); + for y in (0..16).map(|y| FiniteNimber::from(y)) { + for (xi, x) in (0..16).map(|x| FiniteNimber::from(x)).enumerate() { + let product = x + &y; + print!( + "{}{:x}", + if xi == 0 { "" } else { " " }, + product.as_slice()[0] + ); + } + println!(); + } + + println!(); + + println!("Multiplication table for nimbers less than 16 (https://oeis.org/A051775):"); for y in (0..16).map(|y| FiniteNimber::from(y)) { for (xi, x) in (0..16).map(|x| FiniteNimber::from(x)).enumerate() { let product = x * &y; - print!("{}{:x}", if xi==0 { "" } else { " " }, product.as_slice()[0]); + print!( + "{}{:x}", + if xi == 0 { "" } else { " " }, + product.as_slice()[0] + ); } println!(); } println!(); - println!("Multiplication table for powers of 2 less than 2^16:"); + println!("Multiplication table for powers of 2 less than 2^16 (https://oeis.org/A223541):"); for y in (0..16).map(|y| FiniteNimber::from(1 << y)) { - for (xi, x) in (0..16).map(|x| FiniteNimber::from(1 << x)).enumerate() { + for (xi, x) in (0..16).map(|x| FiniteNimber::from(1 << x)).enumerate() + { let product = x * &y; - print!("{}{:04x}", if xi==0 { "" } else { " " }, product.as_slice()[0]); + print!( + "{}{:04x}", + if xi == 0 { "" } else { " " }, + product.as_slice()[0] + ); } println!(); } println!(); - println!("Multiplicative inverses of nimbers up to 2^8:"); + println!("Multiplicative inverses of nimbers up to 2^8 (https://oeis.org/A051917):"); for y in 0..16 { for (xi, x) in (0..16).enumerate() { let n = FiniteNimber::from(y * 16 + x); @@ -31,19 +65,23 @@ fn main() { None => "--".into(), Some(inv) => format!("{:02x}", inv.as_slice()[0]), }; - print!("{}{}", if xi==0 { "" } else { " " }, invstr); + print!("{}{}", if xi == 0 { "" } else { " " }, invstr); } println!(); } println!(); - println!("Square roots of nimbers up to 2^8:"); + println!("Square roots of nimbers up to 2^8 (https://oeis.org/A160679):"); for y in 0..16 { for (xi, x) in (0..16).enumerate() { let n = FiniteNimber::from(y * 16 + x); let sqrt = n.sqrt(); - print!("{}{:02x}", if xi==0 { "" } else { " " }, sqrt.as_slice()[0]); + print!( + "{}{:02x}", + if xi == 0 { "" } else { " " }, + sqrt.as_slice()[0] + ); } println!(); }