chiark / gitweb /
Comment the examples.
authorSimon Tatham <anakin@pobox.com>
Thu, 17 Apr 2025 07:16:30 +0000 (08:16 +0100)
committerSimon Tatham <anakin@pobox.com>
Thu, 17 Apr 2025 07:21:48 +0000 (08:21 +0100)
examples/minpoly.rs
examples/tables.rs

index 2c5b7bf02fd4f2807d65fa4996ee0bd790bc23c8..625df3f247b96f16c47e5202fb0ef63aa0856b2f 100644 (file)
@@ -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!();
index 1e24c8c1ed632079d7b61226654efb9efc9fb997..6244d59e7c44b2b88dc586e31c91f4ba8230538b 100644 (file)
@@ -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!();
     }