+//! 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;
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!();
+//! 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);
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!();
}